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"
46 /* XXX Set this to 1 after the next binutils release. */
47 #define WARN_DEPRECATED 0
50 /* Must be at least the size of the largest unwind opcode (currently two). */
51 #define ARM_OPCODE_CHUNK_SIZE 8
53 /* This structure holds the unwinding state. */
58 symbolS
* table_entry
;
59 symbolS
* personality_routine
;
60 int personality_index
;
61 /* The segment containing the function. */
64 /* Opcodes generated from this function. */
65 unsigned char * opcodes
;
68 /* The number of bytes pushed to the stack. */
70 /* We don't add stack adjustment opcodes immediately so that we can merge
71 multiple adjustments. We can also omit the final adjustment
72 when using a frame pointer. */
73 offsetT pending_offset
;
74 /* These two fields are set by both unwind_movsp and unwind_setfp. They
75 hold the reg+offset to use when restoring sp from a frame pointer. */
78 /* Nonzero if an unwind_setfp directive has been seen. */
80 /* Nonzero if the last opcode restores sp from fp_reg. */
81 unsigned sp_restored
:1;
93 /* Types of processor to assemble for. */
94 #define ARM_1 ARM_ARCH_V1
95 #define ARM_2 ARM_ARCH_V2
96 #define ARM_3 ARM_ARCH_V2S
97 #define ARM_250 ARM_ARCH_V2S
98 #define ARM_6 ARM_ARCH_V3
99 #define ARM_7 ARM_ARCH_V3
100 #define ARM_8 ARM_ARCH_V4
101 #define ARM_9 ARM_ARCH_V4T
102 #define ARM_STRONG ARM_ARCH_V4
103 #define ARM_CPU_MASK 0x0000000f /* XXX? */
106 #if defined __XSCALE__
107 #define CPU_DEFAULT (ARM_ARCH_XSCALE)
109 #if defined __thumb__
110 #define CPU_DEFAULT (ARM_ARCH_V5T)
112 #define CPU_DEFAULT ARM_ANY
118 #define FPU_DEFAULT FPU_ARCH_FPA
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. */
130 /* For backwards compatibility we default to the FPA. */
132 #define FPU_DEFAULT FPU_ARCH_FPA
135 #define streq(a, b) (strcmp (a, b) == 0)
136 #define skip_whitespace(str) while (*(str) == ' ') ++(str)
138 static unsigned long cpu_variant
;
139 static int target_oabi
= 0;
141 /* Flags stored in private area of BFD structure. */
142 static int uses_apcs_26
= FALSE
;
143 static int atpcs
= FALSE
;
144 static int support_interwork
= FALSE
;
145 static int uses_apcs_float
= FALSE
;
146 static int pic_code
= FALSE
;
148 /* Variables that we set while parsing command-line options. Once all
149 options have been read we re-process these values to set the real
151 static int legacy_cpu
= -1;
152 static int legacy_fpu
= -1;
154 static int mcpu_cpu_opt
= -1;
155 static int mcpu_fpu_opt
= -1;
156 static int march_cpu_opt
= -1;
157 static int march_fpu_opt
= -1;
158 static int mfpu_opt
= -1;
159 static int mfloat_abi_opt
= -1;
161 static int meabi_flags
= EF_ARM_EABI_UNKNOWN
;
164 /* This array holds the chars that always start a comment. If the
165 pre-processor is disabled, these aren't very useful. */
166 const char comment_chars
[] = "@";
168 /* This array holds the chars that only start a comment at the beginning of
169 a line. If the line seems to have the form '# 123 filename'
170 .line and .file directives will appear in the pre-processed output. */
171 /* Note that input_file.c hand checks for '#' at the beginning of the
172 first line of the input file. This is because the compiler outputs
173 #NO_APP at the beginning of its output. */
174 /* Also note that comments like this one will always work. */
175 const char line_comment_chars
[] = "#";
177 const char line_separator_chars
[] = ";";
179 /* Chars that can be used to separate mant
180 from exp in floating point numbers. */
181 const char EXP_CHARS
[] = "eE";
183 /* Chars that mean this number is a floating point constant. */
187 const char FLT_CHARS
[] = "rRsSfFdDxXeEpP";
189 /* Prefix characters that indicate the start of an immediate
191 #define is_immediate_prefix(C) ((C) == '#' || (C) == '$')
194 /* Pre-defined "_GLOBAL_OFFSET_TABLE_" */
195 symbolS
* GOT_symbol
;
198 /* Size of relocation record. */
199 const int md_reloc_size
= 8;
201 /* 0: assemble for ARM,
202 1: assemble for Thumb,
203 2: assemble for Thumb even though target CPU does not support thumb
205 static int thumb_mode
= 0;
207 typedef struct arm_fix
215 unsigned long instruction
;
219 bfd_reloc_code_real_type type
;
236 struct asm_shift_properties
238 enum asm_shift_index index
;
239 unsigned long bit_field
;
240 unsigned int allows_0
: 1;
241 unsigned int allows_32
: 1;
244 static const struct asm_shift_properties shift_properties
[] =
246 { SHIFT_LSL
, 0, 1, 0},
247 { SHIFT_LSR
, 0x20, 0, 1},
248 { SHIFT_ASR
, 0x40, 0, 1},
249 { SHIFT_ROR
, 0x60, 0, 0},
250 { SHIFT_RRX
, 0x60, 0, 0}
253 struct asm_shift_name
256 const struct asm_shift_properties
* properties
;
259 static const struct asm_shift_name shift_names
[] =
261 { "asl", shift_properties
+ SHIFT_LSL
},
262 { "lsl", shift_properties
+ SHIFT_LSL
},
263 { "lsr", shift_properties
+ SHIFT_LSR
},
264 { "asr", shift_properties
+ SHIFT_ASR
},
265 { "ror", shift_properties
+ SHIFT_ROR
},
266 { "rrx", shift_properties
+ SHIFT_RRX
},
267 { "ASL", shift_properties
+ SHIFT_LSL
},
268 { "LSL", shift_properties
+ SHIFT_LSL
},
269 { "LSR", shift_properties
+ SHIFT_LSR
},
270 { "ASR", shift_properties
+ SHIFT_ASR
},
271 { "ROR", shift_properties
+ SHIFT_ROR
},
272 { "RRX", shift_properties
+ SHIFT_RRX
}
275 /* Any kind of shift is accepted. */
276 #define NO_SHIFT_RESTRICT 1
277 /* The shift operand must be an immediate value, not a register. */
278 #define SHIFT_IMMEDIATE 0
279 /* The shift must be LSL or ASR and the operand must be an immediate. */
280 #define SHIFT_LSL_OR_ASR_IMMEDIATE 2
281 /* The shift must be ASR and the operand must be an immediate. */
282 #define SHIFT_ASR_IMMEDIATE 3
283 /* The shift must be LSL and the operand must be an immediate. */
284 #define SHIFT_LSL_IMMEDIATE 4
286 #define NUM_FLOAT_VALS 8
288 const char * fp_const
[] =
290 "0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0", 0
293 /* Number of littlenums required to hold an extended precision number. */
294 #define MAX_LITTLENUMS 6
296 LITTLENUM_TYPE fp_values
[NUM_FLOAT_VALS
][MAX_LITTLENUMS
];
301 /* Whether a Co-processor load/store operation accepts write-back forms. */
310 #define CP_T_X 0x00008000
311 #define CP_T_Y 0x00400000
312 #define CP_T_Pre 0x01000000
313 #define CP_T_UD 0x00800000
314 #define CP_T_WB 0x00200000
316 #define CONDS_BIT 0x00100000
317 #define LOAD_BIT 0x00100000
319 #define DOUBLE_LOAD_FLAG 0x00000001
323 const char * template;
327 #define COND_ALWAYS 0xe0000000
328 #define COND_MASK 0xf0000000
330 static const struct asm_cond conds
[] =
334 {"cs", 0x20000000}, {"hs", 0x20000000},
335 {"cc", 0x30000000}, {"ul", 0x30000000}, {"lo", 0x30000000},
352 const char *template;
357 /* The bit that distinguishes CPSR and SPSR. */
358 #define SPSR_BIT (1 << 22)
360 /* How many bits to shift the PSR_xxx bits up by. */
363 #define PSR_c (1 << 0)
364 #define PSR_x (1 << 1)
365 #define PSR_s (1 << 2)
366 #define PSR_f (1 << 3)
368 static const struct asm_psr psrs
[] =
370 {"CPSR", TRUE
, PSR_c
| PSR_f
},
371 {"CPSR_all", TRUE
, PSR_c
| PSR_f
},
372 {"SPSR", FALSE
, PSR_c
| PSR_f
},
373 {"SPSR_all", FALSE
, PSR_c
| PSR_f
},
374 {"CPSR_flg", TRUE
, PSR_f
},
375 {"CPSR_f", TRUE
, PSR_f
},
376 {"SPSR_flg", FALSE
, PSR_f
},
377 {"SPSR_f", FALSE
, PSR_f
},
378 {"CPSR_c", TRUE
, PSR_c
},
379 {"CPSR_ctl", TRUE
, PSR_c
},
380 {"SPSR_c", FALSE
, PSR_c
},
381 {"SPSR_ctl", FALSE
, PSR_c
},
382 {"CPSR_x", TRUE
, PSR_x
},
383 {"CPSR_s", TRUE
, PSR_s
},
384 {"SPSR_x", FALSE
, PSR_x
},
385 {"SPSR_s", FALSE
, PSR_s
},
386 /* Combinations of flags. */
387 {"CPSR_fs", TRUE
, PSR_f
| PSR_s
},
388 {"CPSR_fx", TRUE
, PSR_f
| PSR_x
},
389 {"CPSR_fc", TRUE
, PSR_f
| PSR_c
},
390 {"CPSR_sf", TRUE
, PSR_s
| PSR_f
},
391 {"CPSR_sx", TRUE
, PSR_s
| PSR_x
},
392 {"CPSR_sc", TRUE
, PSR_s
| PSR_c
},
393 {"CPSR_xf", TRUE
, PSR_x
| PSR_f
},
394 {"CPSR_xs", TRUE
, PSR_x
| PSR_s
},
395 {"CPSR_xc", TRUE
, PSR_x
| PSR_c
},
396 {"CPSR_cf", TRUE
, PSR_c
| PSR_f
},
397 {"CPSR_cs", TRUE
, PSR_c
| PSR_s
},
398 {"CPSR_cx", TRUE
, PSR_c
| PSR_x
},
399 {"CPSR_fsx", TRUE
, PSR_f
| PSR_s
| PSR_x
},
400 {"CPSR_fsc", TRUE
, PSR_f
| PSR_s
| PSR_c
},
401 {"CPSR_fxs", TRUE
, PSR_f
| PSR_x
| PSR_s
},
402 {"CPSR_fxc", TRUE
, PSR_f
| PSR_x
| PSR_c
},
403 {"CPSR_fcs", TRUE
, PSR_f
| PSR_c
| PSR_s
},
404 {"CPSR_fcx", TRUE
, PSR_f
| PSR_c
| PSR_x
},
405 {"CPSR_sfx", TRUE
, PSR_s
| PSR_f
| PSR_x
},
406 {"CPSR_sfc", TRUE
, PSR_s
| PSR_f
| PSR_c
},
407 {"CPSR_sxf", TRUE
, PSR_s
| PSR_x
| PSR_f
},
408 {"CPSR_sxc", TRUE
, PSR_s
| PSR_x
| PSR_c
},
409 {"CPSR_scf", TRUE
, PSR_s
| PSR_c
| PSR_f
},
410 {"CPSR_scx", TRUE
, PSR_s
| PSR_c
| PSR_x
},
411 {"CPSR_xfs", TRUE
, PSR_x
| PSR_f
| PSR_s
},
412 {"CPSR_xfc", TRUE
, PSR_x
| PSR_f
| PSR_c
},
413 {"CPSR_xsf", TRUE
, PSR_x
| PSR_s
| PSR_f
},
414 {"CPSR_xsc", TRUE
, PSR_x
| PSR_s
| PSR_c
},
415 {"CPSR_xcf", TRUE
, PSR_x
| PSR_c
| PSR_f
},
416 {"CPSR_xcs", TRUE
, PSR_x
| PSR_c
| PSR_s
},
417 {"CPSR_cfs", TRUE
, PSR_c
| PSR_f
| PSR_s
},
418 {"CPSR_cfx", TRUE
, PSR_c
| PSR_f
| PSR_x
},
419 {"CPSR_csf", TRUE
, PSR_c
| PSR_s
| PSR_f
},
420 {"CPSR_csx", TRUE
, PSR_c
| PSR_s
| PSR_x
},
421 {"CPSR_cxf", TRUE
, PSR_c
| PSR_x
| PSR_f
},
422 {"CPSR_cxs", TRUE
, PSR_c
| PSR_x
| PSR_s
},
423 {"CPSR_fsxc", TRUE
, PSR_f
| PSR_s
| PSR_x
| PSR_c
},
424 {"CPSR_fscx", TRUE
, PSR_f
| PSR_s
| PSR_c
| PSR_x
},
425 {"CPSR_fxsc", TRUE
, PSR_f
| PSR_x
| PSR_s
| PSR_c
},
426 {"CPSR_fxcs", TRUE
, PSR_f
| PSR_x
| PSR_c
| PSR_s
},
427 {"CPSR_fcsx", TRUE
, PSR_f
| PSR_c
| PSR_s
| PSR_x
},
428 {"CPSR_fcxs", TRUE
, PSR_f
| PSR_c
| PSR_x
| PSR_s
},
429 {"CPSR_sfxc", TRUE
, PSR_s
| PSR_f
| PSR_x
| PSR_c
},
430 {"CPSR_sfcx", TRUE
, PSR_s
| PSR_f
| PSR_c
| PSR_x
},
431 {"CPSR_sxfc", TRUE
, PSR_s
| PSR_x
| PSR_f
| PSR_c
},
432 {"CPSR_sxcf", TRUE
, PSR_s
| PSR_x
| PSR_c
| PSR_f
},
433 {"CPSR_scfx", TRUE
, PSR_s
| PSR_c
| PSR_f
| PSR_x
},
434 {"CPSR_scxf", TRUE
, PSR_s
| PSR_c
| PSR_x
| PSR_f
},
435 {"CPSR_xfsc", TRUE
, PSR_x
| PSR_f
| PSR_s
| PSR_c
},
436 {"CPSR_xfcs", TRUE
, PSR_x
| PSR_f
| PSR_c
| PSR_s
},
437 {"CPSR_xsfc", TRUE
, PSR_x
| PSR_s
| PSR_f
| PSR_c
},
438 {"CPSR_xscf", TRUE
, PSR_x
| PSR_s
| PSR_c
| PSR_f
},
439 {"CPSR_xcfs", TRUE
, PSR_x
| PSR_c
| PSR_f
| PSR_s
},
440 {"CPSR_xcsf", TRUE
, PSR_x
| PSR_c
| PSR_s
| PSR_f
},
441 {"CPSR_cfsx", TRUE
, PSR_c
| PSR_f
| PSR_s
| PSR_x
},
442 {"CPSR_cfxs", TRUE
, PSR_c
| PSR_f
| PSR_x
| PSR_s
},
443 {"CPSR_csfx", TRUE
, PSR_c
| PSR_s
| PSR_f
| PSR_x
},
444 {"CPSR_csxf", TRUE
, PSR_c
| PSR_s
| PSR_x
| PSR_f
},
445 {"CPSR_cxfs", TRUE
, PSR_c
| PSR_x
| PSR_f
| PSR_s
},
446 {"CPSR_cxsf", TRUE
, PSR_c
| PSR_x
| PSR_s
| PSR_f
},
447 {"SPSR_fs", FALSE
, PSR_f
| PSR_s
},
448 {"SPSR_fx", FALSE
, PSR_f
| PSR_x
},
449 {"SPSR_fc", FALSE
, PSR_f
| PSR_c
},
450 {"SPSR_sf", FALSE
, PSR_s
| PSR_f
},
451 {"SPSR_sx", FALSE
, PSR_s
| PSR_x
},
452 {"SPSR_sc", FALSE
, PSR_s
| PSR_c
},
453 {"SPSR_xf", FALSE
, PSR_x
| PSR_f
},
454 {"SPSR_xs", FALSE
, PSR_x
| PSR_s
},
455 {"SPSR_xc", FALSE
, PSR_x
| PSR_c
},
456 {"SPSR_cf", FALSE
, PSR_c
| PSR_f
},
457 {"SPSR_cs", FALSE
, PSR_c
| PSR_s
},
458 {"SPSR_cx", FALSE
, PSR_c
| PSR_x
},
459 {"SPSR_fsx", FALSE
, PSR_f
| PSR_s
| PSR_x
},
460 {"SPSR_fsc", FALSE
, PSR_f
| PSR_s
| PSR_c
},
461 {"SPSR_fxs", FALSE
, PSR_f
| PSR_x
| PSR_s
},
462 {"SPSR_fxc", FALSE
, PSR_f
| PSR_x
| PSR_c
},
463 {"SPSR_fcs", FALSE
, PSR_f
| PSR_c
| PSR_s
},
464 {"SPSR_fcx", FALSE
, PSR_f
| PSR_c
| PSR_x
},
465 {"SPSR_sfx", FALSE
, PSR_s
| PSR_f
| PSR_x
},
466 {"SPSR_sfc", FALSE
, PSR_s
| PSR_f
| PSR_c
},
467 {"SPSR_sxf", FALSE
, PSR_s
| PSR_x
| PSR_f
},
468 {"SPSR_sxc", FALSE
, PSR_s
| PSR_x
| PSR_c
},
469 {"SPSR_scf", FALSE
, PSR_s
| PSR_c
| PSR_f
},
470 {"SPSR_scx", FALSE
, PSR_s
| PSR_c
| PSR_x
},
471 {"SPSR_xfs", FALSE
, PSR_x
| PSR_f
| PSR_s
},
472 {"SPSR_xfc", FALSE
, PSR_x
| PSR_f
| PSR_c
},
473 {"SPSR_xsf", FALSE
, PSR_x
| PSR_s
| PSR_f
},
474 {"SPSR_xsc", FALSE
, PSR_x
| PSR_s
| PSR_c
},
475 {"SPSR_xcf", FALSE
, PSR_x
| PSR_c
| PSR_f
},
476 {"SPSR_xcs", FALSE
, PSR_x
| PSR_c
| PSR_s
},
477 {"SPSR_cfs", FALSE
, PSR_c
| PSR_f
| PSR_s
},
478 {"SPSR_cfx", FALSE
, PSR_c
| PSR_f
| PSR_x
},
479 {"SPSR_csf", FALSE
, PSR_c
| PSR_s
| PSR_f
},
480 {"SPSR_csx", FALSE
, PSR_c
| PSR_s
| PSR_x
},
481 {"SPSR_cxf", FALSE
, PSR_c
| PSR_x
| PSR_f
},
482 {"SPSR_cxs", FALSE
, PSR_c
| PSR_x
| PSR_s
},
483 {"SPSR_fsxc", FALSE
, PSR_f
| PSR_s
| PSR_x
| PSR_c
},
484 {"SPSR_fscx", FALSE
, PSR_f
| PSR_s
| PSR_c
| PSR_x
},
485 {"SPSR_fxsc", FALSE
, PSR_f
| PSR_x
| PSR_s
| PSR_c
},
486 {"SPSR_fxcs", FALSE
, PSR_f
| PSR_x
| PSR_c
| PSR_s
},
487 {"SPSR_fcsx", FALSE
, PSR_f
| PSR_c
| PSR_s
| PSR_x
},
488 {"SPSR_fcxs", FALSE
, PSR_f
| PSR_c
| PSR_x
| PSR_s
},
489 {"SPSR_sfxc", FALSE
, PSR_s
| PSR_f
| PSR_x
| PSR_c
},
490 {"SPSR_sfcx", FALSE
, PSR_s
| PSR_f
| PSR_c
| PSR_x
},
491 {"SPSR_sxfc", FALSE
, PSR_s
| PSR_x
| PSR_f
| PSR_c
},
492 {"SPSR_sxcf", FALSE
, PSR_s
| PSR_x
| PSR_c
| PSR_f
},
493 {"SPSR_scfx", FALSE
, PSR_s
| PSR_c
| PSR_f
| PSR_x
},
494 {"SPSR_scxf", FALSE
, PSR_s
| PSR_c
| PSR_x
| PSR_f
},
495 {"SPSR_xfsc", FALSE
, PSR_x
| PSR_f
| PSR_s
| PSR_c
},
496 {"SPSR_xfcs", FALSE
, PSR_x
| PSR_f
| PSR_c
| PSR_s
},
497 {"SPSR_xsfc", FALSE
, PSR_x
| PSR_s
| PSR_f
| PSR_c
},
498 {"SPSR_xscf", FALSE
, PSR_x
| PSR_s
| PSR_c
| PSR_f
},
499 {"SPSR_xcfs", FALSE
, PSR_x
| PSR_c
| PSR_f
| PSR_s
},
500 {"SPSR_xcsf", FALSE
, PSR_x
| PSR_c
| PSR_s
| PSR_f
},
501 {"SPSR_cfsx", FALSE
, PSR_c
| PSR_f
| PSR_s
| PSR_x
},
502 {"SPSR_cfxs", FALSE
, PSR_c
| PSR_f
| PSR_x
| PSR_s
},
503 {"SPSR_csfx", FALSE
, PSR_c
| PSR_s
| PSR_f
| PSR_x
},
504 {"SPSR_csxf", FALSE
, PSR_c
| PSR_s
| PSR_x
| PSR_f
},
505 {"SPSR_cxfs", FALSE
, PSR_c
| PSR_x
| PSR_f
| PSR_s
},
506 {"SPSR_cxsf", FALSE
, PSR_c
| PSR_x
| PSR_s
| PSR_f
},
513 IWMMXT_REG_WR_OR_WC
= 2,
517 enum iwmmxt_insn_type
540 VFP_REG_Dd
, VFP_REG_Dm
, VFP_REG_Dn
545 VFP_REG_Sd
, VFP_REG_Sm
, VFP_REG_Sn
550 VFP_LDSTMIA
, VFP_LDSTMDB
, VFP_LDSTMIAX
, VFP_LDSTMDBX
553 /* VFP system registers. */
560 static const struct vfp_reg vfp_regs
[] =
562 {"fpsid", 0x00000000},
563 {"FPSID", 0x00000000},
564 {"fpscr", 0x00010000},
565 {"FPSCR", 0x00010000},
566 {"fpexc", 0x00080000},
567 {"FPEXC", 0x00080000}
570 /* Structure for a hash table entry for a register. */
578 /* Some well known registers that we refer to directly elsewhere. */
583 #define wr_register(reg) ((reg ^ WR_PREFIX) >= 0 && (reg ^ WR_PREFIX) <= 15)
584 #define wc_register(reg) ((reg ^ WC_PREFIX) >= 0 && (reg ^ WC_PREFIX) <= 15)
585 #define wcg_register(reg) ((reg ^ WC_PREFIX) >= 8 && (reg ^ WC_PREFIX) <= 11)
587 /* These are the standard names. Users can add aliases with .req.
588 and delete them with .unreq. */
590 /* Integer Register Numbers. */
591 static const struct reg_entry rn_table
[] =
593 {"r0", 0, TRUE
}, {"r1", 1, TRUE
}, {"r2", 2, TRUE
}, {"r3", 3, TRUE
},
594 {"r4", 4, TRUE
}, {"r5", 5, TRUE
}, {"r6", 6, TRUE
}, {"r7", 7, TRUE
},
595 {"r8", 8, TRUE
}, {"r9", 9, TRUE
}, {"r10", 10, TRUE
}, {"r11", 11, TRUE
},
596 {"r12", 12, TRUE
}, {"r13", REG_SP
, TRUE
}, {"r14", REG_LR
, TRUE
}, {"r15", REG_PC
, TRUE
},
597 /* ATPCS Synonyms. */
598 {"a1", 0, TRUE
}, {"a2", 1, TRUE
}, {"a3", 2, TRUE
}, {"a4", 3, TRUE
},
599 {"v1", 4, TRUE
}, {"v2", 5, TRUE
}, {"v3", 6, TRUE
}, {"v4", 7, TRUE
},
600 {"v5", 8, TRUE
}, {"v6", 9, TRUE
}, {"v7", 10, TRUE
}, {"v8", 11, TRUE
},
601 /* Well-known aliases. */
602 {"wr", 7, TRUE
}, {"sb", 9, TRUE
}, {"sl", 10, TRUE
}, {"fp", 11, TRUE
},
603 {"ip", 12, TRUE
}, {"sp", REG_SP
, TRUE
}, {"lr", REG_LR
, TRUE
}, {"pc", REG_PC
, TRUE
},
607 #define WR_PREFIX 0x200
608 #define WC_PREFIX 0x400
610 static const struct reg_entry iwmmxt_table
[] =
612 /* Intel Wireless MMX technology register names. */
613 { "wr0", 0x0 | WR_PREFIX
, TRUE
}, {"wr1", 0x1 | WR_PREFIX
, TRUE
},
614 { "wr2", 0x2 | WR_PREFIX
, TRUE
}, {"wr3", 0x3 | WR_PREFIX
, TRUE
},
615 { "wr4", 0x4 | WR_PREFIX
, TRUE
}, {"wr5", 0x5 | WR_PREFIX
, TRUE
},
616 { "wr6", 0x6 | WR_PREFIX
, TRUE
}, {"wr7", 0x7 | WR_PREFIX
, TRUE
},
617 { "wr8", 0x8 | WR_PREFIX
, TRUE
}, {"wr9", 0x9 | WR_PREFIX
, TRUE
},
618 { "wr10", 0xa | WR_PREFIX
, TRUE
}, {"wr11", 0xb | WR_PREFIX
, TRUE
},
619 { "wr12", 0xc | WR_PREFIX
, TRUE
}, {"wr13", 0xd | WR_PREFIX
, TRUE
},
620 { "wr14", 0xe | WR_PREFIX
, TRUE
}, {"wr15", 0xf | WR_PREFIX
, TRUE
},
621 { "wcid", 0x0 | WC_PREFIX
, TRUE
}, {"wcon", 0x1 | WC_PREFIX
, TRUE
},
622 {"wcssf", 0x2 | WC_PREFIX
, TRUE
}, {"wcasf", 0x3 | WC_PREFIX
, TRUE
},
623 {"wcgr0", 0x8 | WC_PREFIX
, TRUE
}, {"wcgr1", 0x9 | WC_PREFIX
, TRUE
},
624 {"wcgr2", 0xa | WC_PREFIX
, TRUE
}, {"wcgr3", 0xb | WC_PREFIX
, TRUE
},
626 { "wR0", 0x0 | WR_PREFIX
, TRUE
}, {"wR1", 0x1 | WR_PREFIX
, TRUE
},
627 { "wR2", 0x2 | WR_PREFIX
, TRUE
}, {"wR3", 0x3 | WR_PREFIX
, TRUE
},
628 { "wR4", 0x4 | WR_PREFIX
, TRUE
}, {"wR5", 0x5 | WR_PREFIX
, TRUE
},
629 { "wR6", 0x6 | WR_PREFIX
, TRUE
}, {"wR7", 0x7 | WR_PREFIX
, TRUE
},
630 { "wR8", 0x8 | WR_PREFIX
, TRUE
}, {"wR9", 0x9 | WR_PREFIX
, TRUE
},
631 { "wR10", 0xa | WR_PREFIX
, TRUE
}, {"wR11", 0xb | WR_PREFIX
, TRUE
},
632 { "wR12", 0xc | WR_PREFIX
, TRUE
}, {"wR13", 0xd | WR_PREFIX
, TRUE
},
633 { "wR14", 0xe | WR_PREFIX
, TRUE
}, {"wR15", 0xf | WR_PREFIX
, TRUE
},
634 { "wCID", 0x0 | WC_PREFIX
, TRUE
}, {"wCon", 0x1 | WC_PREFIX
, TRUE
},
635 {"wCSSF", 0x2 | WC_PREFIX
, TRUE
}, {"wCASF", 0x3 | WC_PREFIX
, TRUE
},
636 {"wCGR0", 0x8 | WC_PREFIX
, TRUE
}, {"wCGR1", 0x9 | WC_PREFIX
, TRUE
},
637 {"wCGR2", 0xa | WC_PREFIX
, TRUE
}, {"wCGR3", 0xb | WC_PREFIX
, TRUE
},
641 /* Co-processor Numbers. */
642 static const struct reg_entry cp_table
[] =
644 {"p0", 0, TRUE
}, {"p1", 1, TRUE
}, {"p2", 2, TRUE
}, {"p3", 3, TRUE
},
645 {"p4", 4, TRUE
}, {"p5", 5, TRUE
}, {"p6", 6, TRUE
}, {"p7", 7, TRUE
},
646 {"p8", 8, TRUE
}, {"p9", 9, TRUE
}, {"p10", 10, TRUE
}, {"p11", 11, TRUE
},
647 {"p12", 12, TRUE
}, {"p13", 13, TRUE
}, {"p14", 14, TRUE
}, {"p15", 15, TRUE
},
651 /* Co-processor Register Numbers. */
652 static const struct reg_entry cn_table
[] =
654 {"c0", 0, TRUE
}, {"c1", 1, TRUE
}, {"c2", 2, TRUE
}, {"c3", 3, TRUE
},
655 {"c4", 4, TRUE
}, {"c5", 5, TRUE
}, {"c6", 6, TRUE
}, {"c7", 7, TRUE
},
656 {"c8", 8, TRUE
}, {"c9", 9, TRUE
}, {"c10", 10, TRUE
}, {"c11", 11, TRUE
},
657 {"c12", 12, TRUE
}, {"c13", 13, TRUE
}, {"c14", 14, TRUE
}, {"c15", 15, TRUE
},
658 /* Not really valid, but kept for back-wards compatibility. */
659 {"cr0", 0, TRUE
}, {"cr1", 1, TRUE
}, {"cr2", 2, TRUE
}, {"cr3", 3, TRUE
},
660 {"cr4", 4, TRUE
}, {"cr5", 5, TRUE
}, {"cr6", 6, TRUE
}, {"cr7", 7, TRUE
},
661 {"cr8", 8, TRUE
}, {"cr9", 9, TRUE
}, {"cr10", 10, TRUE
}, {"cr11", 11, TRUE
},
662 {"cr12", 12, TRUE
}, {"cr13", 13, TRUE
}, {"cr14", 14, TRUE
}, {"cr15", 15, TRUE
},
667 static const struct reg_entry fn_table
[] =
669 {"f0", 0, TRUE
}, {"f1", 1, TRUE
}, {"f2", 2, TRUE
}, {"f3", 3, TRUE
},
670 {"f4", 4, TRUE
}, {"f5", 5, TRUE
}, {"f6", 6, TRUE
}, {"f7", 7, TRUE
},
674 /* VFP SP Registers. */
675 static const struct reg_entry sn_table
[] =
677 {"s0", 0, TRUE
}, {"s1", 1, TRUE
}, {"s2", 2, TRUE
}, {"s3", 3, TRUE
},
678 {"s4", 4, TRUE
}, {"s5", 5, TRUE
}, {"s6", 6, TRUE
}, {"s7", 7, TRUE
},
679 {"s8", 8, TRUE
}, {"s9", 9, TRUE
}, {"s10", 10, TRUE
}, {"s11", 11, TRUE
},
680 {"s12", 12, TRUE
}, {"s13", 13, TRUE
}, {"s14", 14, TRUE
}, {"s15", 15, TRUE
},
681 {"s16", 16, TRUE
}, {"s17", 17, TRUE
}, {"s18", 18, TRUE
}, {"s19", 19, TRUE
},
682 {"s20", 20, TRUE
}, {"s21", 21, TRUE
}, {"s22", 22, TRUE
}, {"s23", 23, TRUE
},
683 {"s24", 24, TRUE
}, {"s25", 25, TRUE
}, {"s26", 26, TRUE
}, {"s27", 27, TRUE
},
684 {"s28", 28, TRUE
}, {"s29", 29, TRUE
}, {"s30", 30, TRUE
}, {"s31", 31, TRUE
},
688 /* VFP DP Registers. */
689 static const struct reg_entry dn_table
[] =
691 {"d0", 0, TRUE
}, {"d1", 1, TRUE
}, {"d2", 2, TRUE
}, {"d3", 3, TRUE
},
692 {"d4", 4, TRUE
}, {"d5", 5, TRUE
}, {"d6", 6, TRUE
}, {"d7", 7, TRUE
},
693 {"d8", 8, TRUE
}, {"d9", 9, TRUE
}, {"d10", 10, TRUE
}, {"d11", 11, TRUE
},
694 {"d12", 12, TRUE
}, {"d13", 13, TRUE
}, {"d14", 14, TRUE
}, {"d15", 15, TRUE
},
698 /* Maverick DSP coprocessor registers. */
699 static const struct reg_entry mav_mvf_table
[] =
701 {"mvf0", 0, TRUE
}, {"mvf1", 1, TRUE
}, {"mvf2", 2, TRUE
}, {"mvf3", 3, TRUE
},
702 {"mvf4", 4, TRUE
}, {"mvf5", 5, TRUE
}, {"mvf6", 6, TRUE
}, {"mvf7", 7, TRUE
},
703 {"mvf8", 8, TRUE
}, {"mvf9", 9, TRUE
}, {"mvf10", 10, TRUE
}, {"mvf11", 11, TRUE
},
704 {"mvf12", 12, TRUE
}, {"mvf13", 13, TRUE
}, {"mvf14", 14, TRUE
}, {"mvf15", 15, TRUE
},
708 static const struct reg_entry mav_mvd_table
[] =
710 {"mvd0", 0, TRUE
}, {"mvd1", 1, TRUE
}, {"mvd2", 2, TRUE
}, {"mvd3", 3, TRUE
},
711 {"mvd4", 4, TRUE
}, {"mvd5", 5, TRUE
}, {"mvd6", 6, TRUE
}, {"mvd7", 7, TRUE
},
712 {"mvd8", 8, TRUE
}, {"mvd9", 9, TRUE
}, {"mvd10", 10, TRUE
}, {"mvd11", 11, TRUE
},
713 {"mvd12", 12, TRUE
}, {"mvd13", 13, TRUE
}, {"mvd14", 14, TRUE
}, {"mvd15", 15, TRUE
},
717 static const struct reg_entry mav_mvfx_table
[] =
719 {"mvfx0", 0, TRUE
}, {"mvfx1", 1, TRUE
}, {"mvfx2", 2, TRUE
}, {"mvfx3", 3, TRUE
},
720 {"mvfx4", 4, TRUE
}, {"mvfx5", 5, TRUE
}, {"mvfx6", 6, TRUE
}, {"mvfx7", 7, TRUE
},
721 {"mvfx8", 8, TRUE
}, {"mvfx9", 9, TRUE
}, {"mvfx10", 10, TRUE
}, {"mvfx11", 11, TRUE
},
722 {"mvfx12", 12, TRUE
}, {"mvfx13", 13, TRUE
}, {"mvfx14", 14, TRUE
}, {"mvfx15", 15, TRUE
},
726 static const struct reg_entry mav_mvdx_table
[] =
728 {"mvdx0", 0, TRUE
}, {"mvdx1", 1, TRUE
}, {"mvdx2", 2, TRUE
}, {"mvdx3", 3, TRUE
},
729 {"mvdx4", 4, TRUE
}, {"mvdx5", 5, TRUE
}, {"mvdx6", 6, TRUE
}, {"mvdx7", 7, TRUE
},
730 {"mvdx8", 8, TRUE
}, {"mvdx9", 9, TRUE
}, {"mvdx10", 10, TRUE
}, {"mvdx11", 11, TRUE
},
731 {"mvdx12", 12, TRUE
}, {"mvdx13", 13, TRUE
}, {"mvdx14", 14, TRUE
}, {"mvdx15", 15, TRUE
},
735 static const struct reg_entry mav_mvax_table
[] =
737 {"mvax0", 0, TRUE
}, {"mvax1", 1, TRUE
}, {"mvax2", 2, TRUE
}, {"mvax3", 3, TRUE
},
741 static const struct reg_entry mav_dspsc_table
[] =
749 const struct reg_entry
* names
;
751 struct hash_control
* htab
;
752 const char * expected
;
755 struct reg_map all_reg_maps
[] =
757 {rn_table
, 15, NULL
, N_("ARM register expected")},
758 {cp_table
, 15, NULL
, N_("bad or missing co-processor number")},
759 {cn_table
, 15, NULL
, N_("co-processor register expected")},
760 {fn_table
, 7, NULL
, N_("FPA register expected")},
761 {sn_table
, 31, NULL
, N_("VFP single precision register expected")},
762 {dn_table
, 15, NULL
, N_("VFP double precision register expected")},
763 {mav_mvf_table
, 15, NULL
, N_("Maverick MVF register expected")},
764 {mav_mvd_table
, 15, NULL
, N_("Maverick MVD register expected")},
765 {mav_mvfx_table
, 15, NULL
, N_("Maverick MVFX register expected")},
766 {mav_mvdx_table
, 15, NULL
, N_("Maverick MVDX register expected")},
767 {mav_mvax_table
, 3, NULL
, N_("Maverick MVAX register expected")},
768 {mav_dspsc_table
, 0, NULL
, N_("Maverick DSPSC register expected")},
769 {iwmmxt_table
, 23, NULL
, N_("Intel Wireless MMX technology register expected")},
772 /* Enumeration matching entries in table above. */
776 #define REG_TYPE_FIRST REG_TYPE_RN
788 REG_TYPE_IWMMXT
= 12,
793 /* ARM instructions take 4bytes in the object file, Thumb instructions
797 /* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
798 #define MAV_MODE1 0x100c
800 /* "INSN<cond> X,Y" where X:bit16, Y:bit12. */
801 #define MAV_MODE2 0x0c10
803 /* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
804 #define MAV_MODE3 0x100c
806 /* "INSN<cond> X,Y,Z" where X:16, Y:0, Z:12. */
807 #define MAV_MODE4 0x0c0010
809 /* "INSN<cond> X,Y,Z" where X:12, Y:16, Z:0. */
810 #define MAV_MODE5 0x00100c
812 /* "INSN<cond> W,X,Y,Z" where W:5, X:12, Y:16, Z:0. */
813 #define MAV_MODE6 0x00100c05
817 /* Basic string to match. */
818 const char * template;
820 /* Basic instruction code. */
823 /* Offset into the template where the condition code (if any) will be.
824 If zero, then the instruction is never conditional. */
825 unsigned cond_offset
;
827 /* Which architecture variant provides this instruction. */
828 unsigned long variant
;
830 /* Function to call to parse args. */
831 void (* parms
) (char *);
834 /* Defines for various bits that we will want to toggle. */
835 #define INST_IMMEDIATE 0x02000000
836 #define OFFSET_REG 0x02000000
837 #define HWOFFSET_IMM 0x00400000
838 #define SHIFT_BY_REG 0x00000010
839 #define PRE_INDEX 0x01000000
840 #define INDEX_UP 0x00800000
841 #define WRITE_BACK 0x00200000
842 #define LDM_TYPE_2_OR_3 0x00400000
844 #define LITERAL_MASK 0xf000f000
845 #define OPCODE_MASK 0xfe1fffff
846 #define V4_STR_BIT 0x00000020
848 #define DATA_OP_SHIFT 21
850 /* Codes to distinguish the arithmetic instructions. */
861 #define OPCODE_CMP 10
862 #define OPCODE_CMN 11
863 #define OPCODE_ORR 12
864 #define OPCODE_MOV 13
865 #define OPCODE_BIC 14
866 #define OPCODE_MVN 15
868 #define T_OPCODE_MUL 0x4340
869 #define T_OPCODE_TST 0x4200
870 #define T_OPCODE_CMN 0x42c0
871 #define T_OPCODE_NEG 0x4240
872 #define T_OPCODE_MVN 0x43c0
874 #define T_OPCODE_ADD_R3 0x1800
875 #define T_OPCODE_SUB_R3 0x1a00
876 #define T_OPCODE_ADD_HI 0x4400
877 #define T_OPCODE_ADD_ST 0xb000
878 #define T_OPCODE_SUB_ST 0xb080
879 #define T_OPCODE_ADD_SP 0xa800
880 #define T_OPCODE_ADD_PC 0xa000
881 #define T_OPCODE_ADD_I8 0x3000
882 #define T_OPCODE_SUB_I8 0x3800
883 #define T_OPCODE_ADD_I3 0x1c00
884 #define T_OPCODE_SUB_I3 0x1e00
886 #define T_OPCODE_ASR_R 0x4100
887 #define T_OPCODE_LSL_R 0x4080
888 #define T_OPCODE_LSR_R 0x40c0
889 #define T_OPCODE_ASR_I 0x1000
890 #define T_OPCODE_LSL_I 0x0000
891 #define T_OPCODE_LSR_I 0x0800
893 #define T_OPCODE_MOV_I8 0x2000
894 #define T_OPCODE_CMP_I8 0x2800
895 #define T_OPCODE_CMP_LR 0x4280
896 #define T_OPCODE_MOV_HR 0x4600
897 #define T_OPCODE_CMP_HR 0x4500
899 #define T_OPCODE_LDR_PC 0x4800
900 #define T_OPCODE_LDR_SP 0x9800
901 #define T_OPCODE_STR_SP 0x9000
902 #define T_OPCODE_LDR_IW 0x6800
903 #define T_OPCODE_STR_IW 0x6000
904 #define T_OPCODE_LDR_IH 0x8800
905 #define T_OPCODE_STR_IH 0x8000
906 #define T_OPCODE_LDR_IB 0x7800
907 #define T_OPCODE_STR_IB 0x7000
908 #define T_OPCODE_LDR_RW 0x5800
909 #define T_OPCODE_STR_RW 0x5000
910 #define T_OPCODE_LDR_RH 0x5a00
911 #define T_OPCODE_STR_RH 0x5200
912 #define T_OPCODE_LDR_RB 0x5c00
913 #define T_OPCODE_STR_RB 0x5400
915 #define T_OPCODE_PUSH 0xb400
916 #define T_OPCODE_POP 0xbc00
918 #define T_OPCODE_BRANCH 0xe7fe
920 #define THUMB_SIZE 2 /* Size of thumb instruction. */
921 #define THUMB_REG_LO 0x1
922 #define THUMB_REG_HI 0x2
923 #define THUMB_REG_ANY 0x3
925 #define THUMB_H1 0x0080
926 #define THUMB_H2 0x0040
933 #define THUMB_COMPARE 1
937 #define THUMB_STORE 1
939 #define THUMB_PP_PC_LR 0x0100
941 /* These three are used for immediate shifts, do not alter. */
943 #define THUMB_HALFWORD 1
948 /* Basic string to match. */
949 const char * template;
951 /* Basic instruction code. */
956 /* Which CPU variants this exists for. */
957 unsigned long variant
;
959 /* Function to call to parse args. */
960 void (* parms
) (char *);
963 #define BAD_ARGS _("bad arguments to instruction")
964 #define BAD_PC _("r15 not allowed here")
965 #define BAD_COND _("instruction is not conditional")
966 #define ERR_NO_ACCUM _("acc0 expected")
968 static struct hash_control
* arm_ops_hsh
= NULL
;
969 static struct hash_control
* arm_tops_hsh
= NULL
;
970 static struct hash_control
* arm_cond_hsh
= NULL
;
971 static struct hash_control
* arm_shift_hsh
= NULL
;
972 static struct hash_control
* arm_psr_hsh
= NULL
;
974 /* Stuff needed to resolve the label ambiguity
984 symbolS
* last_label_seen
;
985 static int label_is_thumb_function_name
= FALSE
;
987 /* Literal Pool stuff. */
989 #define MAX_LITERAL_POOL_SIZE 1024
991 /* Literal pool structure. Held on a per-section
992 and per-sub-section basis. */
994 typedef struct literal_pool
996 expressionS literals
[MAX_LITERAL_POOL_SIZE
];
997 unsigned int next_free_entry
;
1001 subsegT sub_section
;
1002 struct literal_pool
* next
;
1005 /* Pointer to a linked list of literal pools. */
1006 literal_pool
* list_of_pools
= NULL
;
1008 static literal_pool
*
1009 find_literal_pool (void)
1011 literal_pool
* pool
;
1013 for (pool
= list_of_pools
; pool
!= NULL
; pool
= pool
->next
)
1015 if (pool
->section
== now_seg
1016 && pool
->sub_section
== now_subseg
)
1023 static literal_pool
*
1024 find_or_make_literal_pool (void)
1026 /* Next literal pool ID number. */
1027 static unsigned int latest_pool_num
= 1;
1028 literal_pool
* pool
;
1030 pool
= find_literal_pool ();
1034 /* Create a new pool. */
1035 pool
= xmalloc (sizeof (* pool
));
1039 pool
->next_free_entry
= 0;
1040 pool
->section
= now_seg
;
1041 pool
->sub_section
= now_subseg
;
1042 pool
->next
= list_of_pools
;
1043 pool
->symbol
= NULL
;
1045 /* Add it to the list. */
1046 list_of_pools
= pool
;
1049 /* New pools, and emptied pools, will have a NULL symbol. */
1050 if (pool
->symbol
== NULL
)
1052 pool
->symbol
= symbol_create (FAKE_LABEL_NAME
, undefined_section
,
1053 (valueT
) 0, &zero_address_frag
);
1054 pool
->id
= latest_pool_num
++;
1061 /* Add the literal in the global 'inst'
1062 structure to the relevent literal pool. */
1065 add_to_lit_pool (void)
1067 literal_pool
* pool
;
1070 pool
= find_or_make_literal_pool ();
1072 /* Check if this literal value is already in the pool. */
1073 for (entry
= 0; entry
< pool
->next_free_entry
; entry
++)
1075 if ((pool
->literals
[entry
].X_op
== inst
.reloc
.exp
.X_op
)
1076 && (inst
.reloc
.exp
.X_op
== O_constant
)
1077 && (pool
->literals
[entry
].X_add_number
1078 == inst
.reloc
.exp
.X_add_number
)
1079 && (pool
->literals
[entry
].X_unsigned
1080 == inst
.reloc
.exp
.X_unsigned
))
1083 if ((pool
->literals
[entry
].X_op
== inst
.reloc
.exp
.X_op
)
1084 && (inst
.reloc
.exp
.X_op
== O_symbol
)
1085 && (pool
->literals
[entry
].X_add_number
1086 == inst
.reloc
.exp
.X_add_number
)
1087 && (pool
->literals
[entry
].X_add_symbol
1088 == inst
.reloc
.exp
.X_add_symbol
)
1089 && (pool
->literals
[entry
].X_op_symbol
1090 == inst
.reloc
.exp
.X_op_symbol
))
1094 /* Do we need to create a new entry? */
1095 if (entry
== pool
->next_free_entry
)
1097 if (entry
>= MAX_LITERAL_POOL_SIZE
)
1099 inst
.error
= _("literal pool overflow");
1103 pool
->literals
[entry
] = inst
.reloc
.exp
;
1104 pool
->next_free_entry
+= 1;
1107 inst
.reloc
.exp
.X_op
= O_symbol
;
1108 inst
.reloc
.exp
.X_add_number
= ((int) entry
) * 4 - 8;
1109 inst
.reloc
.exp
.X_add_symbol
= pool
->symbol
;
1114 /* Can't use symbol_new here, so have to create a symbol and then at
1115 a later date assign it a value. Thats what these functions do. */
1118 symbol_locate (symbolS
* symbolP
,
1119 const char * name
, /* It is copied, the caller can modify. */
1120 segT segment
, /* Segment identifier (SEG_<something>). */
1121 valueT valu
, /* Symbol value. */
1122 fragS
* frag
) /* Associated fragment. */
1124 unsigned int name_length
;
1125 char * preserved_copy_of_name
;
1127 name_length
= strlen (name
) + 1; /* +1 for \0. */
1128 obstack_grow (¬es
, name
, name_length
);
1129 preserved_copy_of_name
= obstack_finish (¬es
);
1130 #ifdef STRIP_UNDERSCORE
1131 if (preserved_copy_of_name
[0] == '_')
1132 preserved_copy_of_name
++;
1135 #ifdef tc_canonicalize_symbol_name
1136 preserved_copy_of_name
=
1137 tc_canonicalize_symbol_name (preserved_copy_of_name
);
1140 S_SET_NAME (symbolP
, preserved_copy_of_name
);
1142 S_SET_SEGMENT (symbolP
, segment
);
1143 S_SET_VALUE (symbolP
, valu
);
1144 symbol_clear_list_pointers (symbolP
);
1146 symbol_set_frag (symbolP
, frag
);
1148 /* Link to end of symbol chain. */
1150 extern int symbol_table_frozen
;
1152 if (symbol_table_frozen
)
1156 symbol_append (symbolP
, symbol_lastP
, & symbol_rootP
, & symbol_lastP
);
1158 obj_symbol_new_hook (symbolP
);
1160 #ifdef tc_symbol_new_hook
1161 tc_symbol_new_hook (symbolP
);
1165 verify_symbol_chain (symbol_rootP
, symbol_lastP
);
1166 #endif /* DEBUG_SYMS */
1169 /* Check that an immediate is valid.
1170 If so, convert it to the right format. */
1173 validate_immediate (unsigned int val
)
1178 #define rotate_left(v, n) (v << n | v >> (32 - n))
1180 for (i
= 0; i
< 32; i
+= 2)
1181 if ((a
= rotate_left (val
, i
)) <= 0xff)
1182 return a
| (i
<< 7); /* 12-bit pack: [shift-cnt,const]. */
1187 /* Check to see if an immediate can be computed as two separate immediate
1188 values, added together. We already know that this value cannot be
1189 computed by just one ARM instruction. */
1192 validate_immediate_twopart (unsigned int val
,
1193 unsigned int * highpart
)
1198 for (i
= 0; i
< 32; i
+= 2)
1199 if (((a
= rotate_left (val
, i
)) & 0xff) != 0)
1205 * highpart
= (a
>> 8) | ((i
+ 24) << 7);
1207 else if (a
& 0xff0000)
1211 * highpart
= (a
>> 16) | ((i
+ 16) << 7);
1215 assert (a
& 0xff000000);
1216 * highpart
= (a
>> 24) | ((i
+ 8) << 7);
1219 return (a
& 0xff) | (i
<< 7);
1226 validate_offset_imm (unsigned int val
, int hwse
)
1228 if ((hwse
&& val
> 255) || val
> 4095)
1235 /* This code is to handle mapping symbols as defined in the ARM ELF spec.
1236 (This text is taken from version B-02 of the spec):
1238 4.4.7 Mapping and tagging symbols
1240 A section of an ARM ELF file can contain a mixture of ARM code,
1241 Thumb code, and data. There are inline transitions between code
1242 and data at literal pool boundaries. There can also be inline
1243 transitions between ARM code and Thumb code, for example in
1244 ARM-Thumb inter-working veneers. Linkers, machine-level
1245 debuggers, profiling tools, and disassembly tools need to map
1246 images accurately. For example, setting an ARM breakpoint on a
1247 Thumb location, or in a literal pool, can crash the program
1248 being debugged, ruining the debugging session.
1250 ARM ELF entities are mapped (see section 4.4.7.1 below) and
1251 tagged (see section 4.4.7.2 below) using local symbols (with
1252 binding STB_LOCAL). To assist consumers, mapping and tagging
1253 symbols should be collated first in the symbol table, before
1254 other symbols with binding STB_LOCAL.
1256 To allow properly collated mapping and tagging symbols to be
1257 skipped by consumers that have no interest in them, the first
1258 such symbol should have the name $m and its st_value field equal
1259 to the total number of mapping and tagging symbols (including
1260 the $m) in the symbol table.
1262 4.4.7.1 Mapping symbols
1264 $a Labels the first byte of a sequence of ARM instructions.
1265 Its type is STT_FUNC.
1267 $d Labels the first byte of a sequence of data items.
1268 Its type is STT_OBJECT.
1270 $t Labels the first byte of a sequence of Thumb instructions.
1271 Its type is STT_FUNC.
1273 This list of mapping symbols may be extended in the future.
1275 Section-relative mapping symbols
1277 Mapping symbols defined in a section define a sequence of
1278 half-open address intervals that cover the address range of the
1279 section. Each interval starts at the address defined by a
1280 mapping symbol, and continues up to, but not including, the
1281 address defined by the next (in address order) mapping symbol or
1282 the end of the section. A corollary is that there must be a
1283 mapping symbol defined at the beginning of each section.
1284 Consumers can ignore the size of a section-relative mapping
1285 symbol. Producers can set it to 0.
1287 Absolute mapping symbols
1289 Because of the need to crystallize a Thumb address with the
1290 Thumb-bit set, absolute symbol of type STT_FUNC (symbols of type
1291 STT_FUNC defined in section SHN_ABS) need to be mapped with $a
1294 The extent of a mapping symbol defined in SHN_ABS is [st_value,
1295 st_value + st_size), or [st_value, st_value + 1) if st_size = 0,
1296 where [x, y) denotes the half-open address range from x,
1297 inclusive, to y, exclusive.
1299 In the absence of a mapping symbol, a consumer can interpret a
1300 function symbol with an odd value as the Thumb code address
1301 obtained by clearing the least significant bit of the
1302 value. This interpretation is deprecated, and it may not work in
1305 Note - the Tagging symbols ($b, $f, $p $m) have been dropped from
1306 the EABI (which is still under development), so they are not
1307 implemented here. */
1309 static enum mstate mapstate
= MAP_UNDEFINED
;
1312 mapping_state (enum mstate state
)
1315 const char * symname
;
1318 if (mapstate
== state
)
1319 /* The mapping symbol has already been emitted.
1320 There is nothing else to do. */
1333 type
= BSF_FUNCTION
;
1337 type
= BSF_FUNCTION
;
1345 seg_info (now_seg
)->tc_segment_info_data
= state
;
1347 symbolP
= symbol_new (symname
, now_seg
, (valueT
) frag_now_fix (), frag_now
);
1348 symbol_table_insert (symbolP
);
1349 symbol_get_bfdsym (symbolP
)->flags
|= type
| BSF_LOCAL
;
1354 THUMB_SET_FUNC (symbolP
, 0);
1355 ARM_SET_THUMB (symbolP
, 0);
1356 ARM_SET_INTERWORK (symbolP
, support_interwork
);
1360 THUMB_SET_FUNC (symbolP
, 1);
1361 ARM_SET_THUMB (symbolP
, 1);
1362 ARM_SET_INTERWORK (symbolP
, support_interwork
);
1371 /* When we change sections we need to issue a new mapping symbol. */
1374 arm_elf_change_section (void)
1378 /* Link an unlinked unwind index table section to the .text section. */
1379 if (elf_section_type (now_seg
) == SHT_ARM_EXIDX
1380 && elf_linked_to_section (now_seg
) == NULL
)
1381 elf_linked_to_section (now_seg
) = text_section
;
1383 if (!SEG_NORMAL (now_seg
))
1386 flags
= bfd_get_section_flags (stdoutput
, now_seg
);
1388 /* We can ignore sections that only contain debug info. */
1389 if ((flags
& SEC_ALLOC
) == 0)
1392 mapstate
= seg_info (now_seg
)->tc_segment_info_data
;
1396 arm_elf_section_type (const char * str
, size_t len
)
1398 if (len
== 5 && strncmp (str
, "exidx", 5) == 0)
1399 return SHT_ARM_EXIDX
;
1404 #define mapping_state(a)
1405 #endif /* OBJ_ELF */
1407 /* arm_reg_parse () := if it looks like a register, return its token and
1408 advance the pointer. */
1411 arm_reg_parse (char ** ccp
, struct hash_control
* htab
)
1413 char * start
= * ccp
;
1416 struct reg_entry
* reg
;
1418 #ifdef REGISTER_PREFIX
1419 if (*start
!= REGISTER_PREFIX
)
1424 #ifdef OPTIONAL_REGISTER_PREFIX
1425 if (*p
== OPTIONAL_REGISTER_PREFIX
)
1429 if (!ISALPHA (*p
) || !is_name_beginner (*p
))
1433 while (ISALPHA (c
) || ISDIGIT (c
) || c
== '_')
1437 reg
= (struct reg_entry
*) hash_find (htab
, start
);
1449 /* Search for the following register name in each of the possible reg name
1450 tables. Return the classification if found, or REG_TYPE_MAX if not
1453 static enum arm_reg_type
1454 arm_reg_parse_any (char *cp
)
1458 for (i
= (int) REG_TYPE_FIRST
; i
< (int) REG_TYPE_MAX
; i
++)
1459 if (arm_reg_parse (&cp
, all_reg_maps
[i
].htab
) != FAIL
)
1460 return (enum arm_reg_type
) i
;
1462 return REG_TYPE_MAX
;
1466 opcode_select (int width
)
1473 if (! (cpu_variant
& ARM_EXT_V4T
))
1474 as_bad (_("selected processor does not support THUMB opcodes"));
1477 /* No need to force the alignment, since we will have been
1478 coming from ARM mode, which is word-aligned. */
1479 record_alignment (now_seg
, 1);
1481 mapping_state (MAP_THUMB
);
1487 if ((cpu_variant
& ARM_ALL
) == ARM_EXT_V4T
)
1488 as_bad (_("selected processor does not support ARM opcodes"));
1493 frag_align (2, 0, 0);
1495 record_alignment (now_seg
, 1);
1497 mapping_state (MAP_ARM
);
1501 as_bad (_("invalid instruction size selected (%d)"), width
);
1506 s_req (int a ATTRIBUTE_UNUSED
)
1508 as_bad (_("invalid syntax for .req directive"));
1511 /* The .unreq directive deletes an alias which was previously defined
1512 by .req. For example:
1518 s_unreq (int a ATTRIBUTE_UNUSED
)
1523 skip_whitespace (input_line_pointer
);
1524 name
= input_line_pointer
;
1526 while (*input_line_pointer
!= 0
1527 && *input_line_pointer
!= ' '
1528 && *input_line_pointer
!= '\n')
1529 ++input_line_pointer
;
1531 saved_char
= *input_line_pointer
;
1532 *input_line_pointer
= 0;
1536 enum arm_reg_type req_type
= arm_reg_parse_any (name
);
1538 if (req_type
!= REG_TYPE_MAX
)
1540 char *temp_name
= name
;
1541 int req_no
= arm_reg_parse (&temp_name
, all_reg_maps
[req_type
].htab
);
1545 struct reg_entry
*req_entry
;
1547 /* Check to see if this alias is a builtin one. */
1548 req_entry
= hash_delete (all_reg_maps
[req_type
].htab
, name
);
1551 as_bad (_("unreq: missing hash entry for \"%s\""), name
);
1552 else if (req_entry
->builtin
)
1553 /* FIXME: We are deleting a built in register alias which
1554 points to a const data structure, so we only need to
1555 free up the memory used by the key in the hash table.
1556 Unfortunately we have not recorded this value, so this
1557 is a memory leak. */
1558 /* FIXME: Should we issue a warning message ? */
1562 /* Deleting a user defined alias. We need to free the
1563 key and the value, but fortunately the key is the same
1564 as the value->name field. */
1565 free ((char *) req_entry
->name
);
1570 as_bad (_(".unreq: unrecognized symbol \"%s\""), name
);
1573 as_bad (_(".unreq: unrecognized symbol \"%s\""), name
);
1576 as_bad (_("invalid syntax for .unreq directive"));
1578 *input_line_pointer
= saved_char
;
1579 demand_empty_rest_of_line ();
1583 s_bss (int ignore ATTRIBUTE_UNUSED
)
1585 /* We don't support putting frags in the BSS segment, we fake it by
1586 marking in_bss, then looking at s_skip for clues. */
1587 subseg_set (bss_section
, 0);
1588 demand_empty_rest_of_line ();
1589 mapping_state (MAP_DATA
);
1593 s_even (int ignore ATTRIBUTE_UNUSED
)
1595 /* Never make frag if expect extra pass. */
1597 frag_align (1, 0, 0);
1599 record_alignment (now_seg
, 1);
1601 demand_empty_rest_of_line ();
1605 s_ltorg (int ignored ATTRIBUTE_UNUSED
)
1608 literal_pool
* pool
;
1611 pool
= find_literal_pool ();
1613 || pool
->symbol
== NULL
1614 || pool
->next_free_entry
== 0)
1617 mapping_state (MAP_DATA
);
1619 /* Align pool as you have word accesses.
1620 Only make a frag if we have to. */
1622 frag_align (2, 0, 0);
1624 record_alignment (now_seg
, 2);
1626 sprintf (sym_name
, "$$lit_\002%x", pool
->id
);
1628 symbol_locate (pool
->symbol
, sym_name
, now_seg
,
1629 (valueT
) frag_now_fix (), frag_now
);
1630 symbol_table_insert (pool
->symbol
);
1632 ARM_SET_THUMB (pool
->symbol
, thumb_mode
);
1634 #if defined OBJ_COFF || defined OBJ_ELF
1635 ARM_SET_INTERWORK (pool
->symbol
, support_interwork
);
1638 for (entry
= 0; entry
< pool
->next_free_entry
; entry
++)
1639 /* First output the expression in the instruction to the pool. */
1640 emit_expr (&(pool
->literals
[entry
]), 4); /* .word */
1642 /* Mark the pool as empty. */
1643 pool
->next_free_entry
= 0;
1644 pool
->symbol
= NULL
;
1647 /* Same as s_align_ptwo but align 0 => align 2. */
1650 s_align (int unused ATTRIBUTE_UNUSED
)
1654 long max_alignment
= 15;
1656 temp
= get_absolute_expression ();
1657 if (temp
> max_alignment
)
1658 as_bad (_("alignment too large: %d assumed"), temp
= max_alignment
);
1661 as_bad (_("alignment negative. 0 assumed."));
1665 if (*input_line_pointer
== ',')
1667 input_line_pointer
++;
1668 temp_fill
= get_absolute_expression ();
1676 /* Only make a frag if we HAVE to. */
1677 if (temp
&& !need_pass_2
)
1678 frag_align (temp
, (int) temp_fill
, 0);
1679 demand_empty_rest_of_line ();
1681 record_alignment (now_seg
, temp
);
1685 s_force_thumb (int ignore ATTRIBUTE_UNUSED
)
1687 /* If we are not already in thumb mode go into it, EVEN if
1688 the target processor does not support thumb instructions.
1689 This is used by gcc/config/arm/lib1funcs.asm for example
1690 to compile interworking support functions even if the
1691 target processor should not support interworking. */
1696 record_alignment (now_seg
, 1);
1699 demand_empty_rest_of_line ();
1703 s_thumb_func (int ignore ATTRIBUTE_UNUSED
)
1708 /* The following label is the name/address of the start of a Thumb function.
1709 We need to know this for the interworking support. */
1710 label_is_thumb_function_name
= TRUE
;
1712 demand_empty_rest_of_line ();
1715 /* Perform a .set directive, but also mark the alias as
1716 being a thumb function. */
1719 s_thumb_set (int equiv
)
1721 /* XXX the following is a duplicate of the code for s_set() in read.c
1722 We cannot just call that code as we need to get at the symbol that
1729 /* Especial apologies for the random logic:
1730 This just grew, and could be parsed much more simply!
1732 name
= input_line_pointer
;
1733 delim
= get_symbol_end ();
1734 end_name
= input_line_pointer
;
1739 if (*input_line_pointer
!= ',')
1742 as_bad (_("expected comma after name \"%s\""), name
);
1744 ignore_rest_of_line ();
1748 input_line_pointer
++;
1751 if (name
[0] == '.' && name
[1] == '\0')
1753 /* XXX - this should not happen to .thumb_set. */
1757 if ((symbolP
= symbol_find (name
)) == NULL
1758 && (symbolP
= md_undefined_symbol (name
)) == NULL
)
1761 /* When doing symbol listings, play games with dummy fragments living
1762 outside the normal fragment chain to record the file and line info
1764 if (listing
& LISTING_SYMBOLS
)
1766 extern struct list_info_struct
* listing_tail
;
1767 fragS
* dummy_frag
= xmalloc (sizeof (fragS
));
1769 memset (dummy_frag
, 0, sizeof (fragS
));
1770 dummy_frag
->fr_type
= rs_fill
;
1771 dummy_frag
->line
= listing_tail
;
1772 symbolP
= symbol_new (name
, undefined_section
, 0, dummy_frag
);
1773 dummy_frag
->fr_symbol
= symbolP
;
1777 symbolP
= symbol_new (name
, undefined_section
, 0, &zero_address_frag
);
1780 /* "set" symbols are local unless otherwise specified. */
1781 SF_SET_LOCAL (symbolP
);
1782 #endif /* OBJ_COFF */
1783 } /* Make a new symbol. */
1785 symbol_table_insert (symbolP
);
1790 && S_IS_DEFINED (symbolP
)
1791 && S_GET_SEGMENT (symbolP
) != reg_section
)
1792 as_bad (_("symbol `%s' already defined"), S_GET_NAME (symbolP
));
1794 pseudo_set (symbolP
);
1796 demand_empty_rest_of_line ();
1798 /* XXX Now we come to the Thumb specific bit of code. */
1800 THUMB_SET_FUNC (symbolP
, 1);
1801 ARM_SET_THUMB (symbolP
, 1);
1802 #if defined OBJ_ELF || defined OBJ_COFF
1803 ARM_SET_INTERWORK (symbolP
, support_interwork
);
1808 s_arm (int ignore ATTRIBUTE_UNUSED
)
1811 demand_empty_rest_of_line ();
1815 s_thumb (int ignore ATTRIBUTE_UNUSED
)
1818 demand_empty_rest_of_line ();
1822 s_code (int unused ATTRIBUTE_UNUSED
)
1826 temp
= get_absolute_expression ();
1831 opcode_select (temp
);
1835 as_bad (_("invalid operand to .code directive (%d) (expecting 16 or 32)"), temp
);
1840 end_of_line (char * str
)
1842 skip_whitespace (str
);
1844 if (*str
!= '\0' && !inst
.error
)
1845 inst
.error
= _("garbage following instruction");
1849 skip_past_comma (char ** str
)
1851 char * p
= * str
, c
;
1854 while ((c
= *p
) == ' ' || c
== ',')
1857 if (c
== ',' && comma
++)
1865 return comma
? SUCCESS
: FAIL
;
1868 /* Return TRUE if anything in the expression is a bignum. */
1871 walk_no_bignums (symbolS
* sp
)
1873 if (symbol_get_value_expression (sp
)->X_op
== O_big
)
1876 if (symbol_get_value_expression (sp
)->X_add_symbol
)
1878 return (walk_no_bignums (symbol_get_value_expression (sp
)->X_add_symbol
)
1879 || (symbol_get_value_expression (sp
)->X_op_symbol
1880 && walk_no_bignums (symbol_get_value_expression (sp
)->X_op_symbol
)));
1886 static int in_my_get_expression
= 0;
1889 my_get_expression (expressionS
* ep
, char ** str
)
1894 save_in
= input_line_pointer
;
1895 input_line_pointer
= *str
;
1896 in_my_get_expression
= 1;
1897 seg
= expression (ep
);
1898 in_my_get_expression
= 0;
1900 if (ep
->X_op
== O_illegal
)
1902 /* We found a bad expression in md_operand(). */
1903 *str
= input_line_pointer
;
1904 input_line_pointer
= save_in
;
1909 if (seg
!= absolute_section
1910 && seg
!= text_section
1911 && seg
!= data_section
1912 && seg
!= bss_section
1913 && seg
!= undefined_section
)
1915 inst
.error
= _("bad_segment");
1916 *str
= input_line_pointer
;
1917 input_line_pointer
= save_in
;
1922 /* Get rid of any bignums now, so that we don't generate an error for which
1923 we can't establish a line number later on. Big numbers are never valid
1924 in instructions, which is where this routine is always called. */
1925 if (ep
->X_op
== O_big
1926 || (ep
->X_add_symbol
1927 && (walk_no_bignums (ep
->X_add_symbol
)
1929 && walk_no_bignums (ep
->X_op_symbol
)))))
1931 inst
.error
= _("invalid constant");
1932 *str
= input_line_pointer
;
1933 input_line_pointer
= save_in
;
1937 *str
= input_line_pointer
;
1938 input_line_pointer
= save_in
;
1942 /* A standard register must be given at this point.
1943 SHIFT is the place to put it in inst.instruction.
1944 Restores input start point on error.
1945 Returns the reg#, or FAIL. */
1948 reg_required_here (char ** str
, int shift
)
1950 static char buff
[128]; /* XXX */
1952 char * start
= * str
;
1954 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_RN
].htab
)) != FAIL
)
1957 inst
.instruction
|= reg
<< shift
;
1961 /* Restore the start point, we may have got a reg of the wrong class. */
1964 /* In the few cases where we might be able to accept something else
1965 this error can be overridden. */
1966 sprintf (buff
, _("register expected, not '%.100s'"), start
);
1972 /* A Intel Wireless MMX technology register
1973 must be given at this point.
1974 Shift is the place to put it in inst.instruction.
1975 Restores input start point on err.
1976 Returns the reg#, or FAIL. */
1979 wreg_required_here (char ** str
,
1981 enum wreg_type reg_type
)
1983 static char buff
[128];
1985 char * start
= *str
;
1987 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_IWMMXT
].htab
)) != FAIL
)
1989 if (wr_register (reg
)
1990 && (reg_type
== IWMMXT_REG_WR
|| reg_type
== IWMMXT_REG_WR_OR_WC
))
1993 inst
.instruction
|= (reg
^ WR_PREFIX
) << shift
;
1996 else if (wc_register (reg
)
1997 && (reg_type
== IWMMXT_REG_WC
|| reg_type
== IWMMXT_REG_WR_OR_WC
))
2000 inst
.instruction
|= (reg
^ WC_PREFIX
) << shift
;
2003 else if ((wcg_register (reg
) && reg_type
== IWMMXT_REG_WCG
))
2006 inst
.instruction
|= ((reg
^ WC_PREFIX
) - 8) << shift
;
2011 /* Restore the start point, we may have got a reg of the wrong class. */
2014 /* In the few cases where we might be able to accept
2015 something else this error can be overridden. */
2016 sprintf (buff
, _("Intel Wireless MMX technology register expected, not '%.100s'"), start
);
2022 static const struct asm_psr
*
2023 arm_psr_parse (char ** ccp
)
2025 char * start
= * ccp
;
2028 const struct asm_psr
* psr
;
2032 /* Skip to the end of the next word in the input stream. */
2037 while (ISALPHA (c
) || c
== '_');
2039 /* Terminate the word. */
2042 /* CPSR's and SPSR's can now be lowercase. This is just a convenience
2043 feature for ease of use and backwards compatibility. */
2044 if (!strncmp (start
, "cpsr", 4))
2045 strncpy (start
, "CPSR", 4);
2046 else if (!strncmp (start
, "spsr", 4))
2047 strncpy (start
, "SPSR", 4);
2049 /* Now locate the word in the psr hash table. */
2050 psr
= (const struct asm_psr
*) hash_find (arm_psr_hsh
, start
);
2052 /* Restore the input stream. */
2055 /* If we found a valid match, advance the
2056 stream pointer past the end of the word. */
2062 /* Parse the input looking for a PSR flag. */
2065 psr_required_here (char ** str
)
2067 char * start
= * str
;
2068 const struct asm_psr
* psr
;
2070 psr
= arm_psr_parse (str
);
2074 /* If this is the SPSR that is being modified, set the R bit. */
2076 inst
.instruction
|= SPSR_BIT
;
2078 /* Set the psr flags in the MSR instruction. */
2079 inst
.instruction
|= psr
->field
<< PSR_SHIFT
;
2084 /* In the few cases where we might be able to accept
2085 something else this error can be overridden. */
2086 inst
.error
= _("flag for {c}psr instruction expected");
2088 /* Restore the start point. */
2094 co_proc_number (char ** str
)
2096 int processor
, pchar
;
2099 skip_whitespace (*str
);
2102 /* The data sheet seems to imply that just a number on its own is valid
2103 here, but the RISC iX assembler seems to accept a prefix 'p'. We will
2105 if ((processor
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_CP
].htab
))
2111 if (pchar
>= '0' && pchar
<= '9')
2113 processor
= pchar
- '0';
2114 if (**str
>= '0' && **str
<= '9')
2116 processor
= processor
* 10 + *(*str
)++ - '0';
2119 inst
.error
= _("illegal co-processor number");
2126 inst
.error
= all_reg_maps
[REG_TYPE_CP
].expected
;
2131 inst
.instruction
|= processor
<< 8;
2136 cp_opc_expr (char ** str
, int where
, int length
)
2140 skip_whitespace (* str
);
2142 memset (&expr
, '\0', sizeof (expr
));
2144 if (my_get_expression (&expr
, str
))
2146 if (expr
.X_op
!= O_constant
)
2148 inst
.error
= _("bad or missing expression");
2152 if ((expr
.X_add_number
& ((1 << length
) - 1)) != expr
.X_add_number
)
2154 inst
.error
= _("immediate co-processor expression too large");
2158 inst
.instruction
|= expr
.X_add_number
<< where
;
2163 cp_reg_required_here (char ** str
, int where
)
2166 char * start
= *str
;
2168 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_CN
].htab
)) != FAIL
)
2170 inst
.instruction
|= reg
<< where
;
2174 /* In the few cases where we might be able to accept something else
2175 this error can be overridden. */
2176 inst
.error
= all_reg_maps
[REG_TYPE_CN
].expected
;
2178 /* Restore the start point. */
2184 fp_reg_required_here (char ** str
, int where
)
2187 char * start
= * str
;
2189 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_FN
].htab
)) != FAIL
)
2191 inst
.instruction
|= reg
<< where
;
2195 /* In the few cases where we might be able to accept something else
2196 this error can be overridden. */
2197 inst
.error
= all_reg_maps
[REG_TYPE_FN
].expected
;
2199 /* Restore the start point. */
2205 cp_address_offset (char ** str
)
2209 skip_whitespace (* str
);
2211 if (! is_immediate_prefix (**str
))
2213 inst
.error
= _("immediate expression expected");
2219 if (my_get_expression (& inst
.reloc
.exp
, str
))
2222 if (inst
.reloc
.exp
.X_op
== O_constant
)
2224 offset
= inst
.reloc
.exp
.X_add_number
;
2228 inst
.error
= _("co-processor address must be word aligned");
2232 if (offset
> 1023 || offset
< -1023)
2234 inst
.error
= _("offset too large");
2239 inst
.instruction
|= INDEX_UP
;
2243 inst
.instruction
|= offset
>> 2;
2246 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM
;
2252 cp_address_required_here (char ** str
, int wb_ok
)
2263 skip_whitespace (p
);
2265 if ((reg
= reg_required_here (& p
, 16)) == FAIL
)
2268 skip_whitespace (p
);
2274 skip_whitespace (p
);
2278 /* As an extension to the official ARM syntax we allow:
2280 as a short hand for:
2282 inst
.instruction
|= PRE_INDEX
| INDEX_UP
;
2287 if (skip_past_comma (& p
) == FAIL
)
2289 inst
.error
= _("comma expected after closing square bracket");
2293 skip_whitespace (p
);
2300 write_back
= WRITE_BACK
;
2304 inst
.error
= _("pc may not be used in post-increment");
2308 if (cp_address_offset (& p
) == FAIL
)
2312 pre_inc
= PRE_INDEX
| INDEX_UP
;
2318 /* [Rn], {<expr>} */
2321 skip_whitespace (p
);
2323 if (my_get_expression (& inst
.reloc
.exp
, & p
))
2326 if (inst
.reloc
.exp
.X_op
== O_constant
)
2328 option
= inst
.reloc
.exp
.X_add_number
;
2330 if (option
> 255 || option
< 0)
2332 inst
.error
= _("'option' field too large");
2336 skip_whitespace (p
);
2340 inst
.error
= _("'}' expected at end of 'option' field");
2346 inst
.instruction
|= option
;
2347 inst
.instruction
|= INDEX_UP
;
2352 inst
.error
= _("non-constant expressions for 'option' field not supported");
2358 inst
.error
= _("# or { expected after comma");
2364 /* '['Rn, #expr']'[!] */
2366 if (skip_past_comma (& p
) == FAIL
)
2368 inst
.error
= _("pre-indexed expression expected");
2372 pre_inc
= PRE_INDEX
;
2374 if (cp_address_offset (& p
) == FAIL
)
2377 skip_whitespace (p
);
2381 inst
.error
= _("missing ]");
2385 skip_whitespace (p
);
2387 if (wb_ok
&& *p
== '!')
2391 inst
.error
= _("pc may not be used with write-back");
2396 write_back
= WRITE_BACK
;
2402 if (my_get_expression (&inst
.reloc
.exp
, &p
))
2405 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM
;
2406 inst
.reloc
.exp
.X_add_number
-= 8; /* PC rel adjust. */
2407 inst
.reloc
.pc_rel
= 1;
2408 inst
.instruction
|= (REG_PC
<< 16);
2409 pre_inc
= PRE_INDEX
;
2412 inst
.instruction
|= write_back
| pre_inc
;
2418 cp_byte_address_offset (char ** str
)
2422 skip_whitespace (* str
);
2424 if (! is_immediate_prefix (**str
))
2426 inst
.error
= _("immediate expression expected");
2432 if (my_get_expression (& inst
.reloc
.exp
, str
))
2435 if (inst
.reloc
.exp
.X_op
== O_constant
)
2437 offset
= inst
.reloc
.exp
.X_add_number
;
2439 if (offset
> 255 || offset
< -255)
2441 inst
.error
= _("offset too large");
2446 inst
.instruction
|= INDEX_UP
;
2450 inst
.instruction
|= offset
;
2453 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM_S2
;
2459 cp_byte_address_required_here (char ** str
)
2470 skip_whitespace (p
);
2472 if ((reg
= reg_required_here (& p
, 16)) == FAIL
)
2475 skip_whitespace (p
);
2481 if (skip_past_comma (& p
) == SUCCESS
)
2484 write_back
= WRITE_BACK
;
2488 inst
.error
= _("pc may not be used in post-increment");
2492 if (cp_byte_address_offset (& p
) == FAIL
)
2496 pre_inc
= PRE_INDEX
| INDEX_UP
;
2500 /* '['Rn, #expr']'[!] */
2502 if (skip_past_comma (& p
) == FAIL
)
2504 inst
.error
= _("pre-indexed expression expected");
2508 pre_inc
= PRE_INDEX
;
2510 if (cp_byte_address_offset (& p
) == FAIL
)
2513 skip_whitespace (p
);
2517 inst
.error
= _("missing ]");
2521 skip_whitespace (p
);
2527 inst
.error
= _("pc may not be used with write-back");
2532 write_back
= WRITE_BACK
;
2538 if (my_get_expression (&inst
.reloc
.exp
, &p
))
2541 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM_S2
;
2542 inst
.reloc
.exp
.X_add_number
-= 8; /* PC rel adjust. */
2543 inst
.reloc
.pc_rel
= 1;
2544 inst
.instruction
|= (REG_PC
<< 16);
2545 pre_inc
= PRE_INDEX
;
2548 inst
.instruction
|= write_back
| pre_inc
;
2556 skip_whitespace (str
);
2561 if (my_get_expression (&inst
.reloc
.exp
, &str
))
2562 inst
.reloc
.exp
.X_op
= O_illegal
;
2565 skip_whitespace (str
);
2569 inst
.reloc
.exp
.X_op
= O_illegal
;
2572 if (inst
.reloc
.exp
.X_op
!= O_constant
2573 || inst
.reloc
.exp
.X_add_number
> 255
2574 || inst
.reloc
.exp
.X_add_number
< 0)
2576 inst
.error
= _("Invalid NOP hint");
2580 /* Arcitectural NOP hints are CPSR sets with no bits selected. */
2581 inst
.instruction
&= 0xf0000000;
2582 inst
.instruction
|= 0x0320f000 + inst
.reloc
.exp
.X_add_number
;
2589 do_empty (char * str
)
2591 /* Do nothing really. */
2600 /* Only one syntax. */
2601 skip_whitespace (str
);
2603 if (reg_required_here (&str
, 12) == FAIL
)
2605 inst
.error
= BAD_ARGS
;
2609 if (skip_past_comma (&str
) == FAIL
)
2611 inst
.error
= _("comma expected after register name");
2615 skip_whitespace (str
);
2617 if ( streq (str
, "CPSR")
2618 || streq (str
, "SPSR")
2619 /* Lower case versions for backwards compatibility. */
2620 || streq (str
, "cpsr")
2621 || streq (str
, "spsr"))
2624 /* This is for backwards compatibility with older toolchains. */
2625 else if ( streq (str
, "cpsr_all")
2626 || streq (str
, "spsr_all"))
2630 inst
.error
= _("CPSR or SPSR expected");
2634 if (* str
== 's' || * str
== 'S')
2635 inst
.instruction
|= SPSR_BIT
;
2641 /* Two possible forms:
2642 "{C|S}PSR_<field>, Rm",
2643 "{C|S}PSR_f, #expression". */
2648 skip_whitespace (str
);
2650 if (psr_required_here (& str
) == FAIL
)
2653 if (skip_past_comma (& str
) == FAIL
)
2655 inst
.error
= _("comma missing after psr flags");
2659 skip_whitespace (str
);
2661 if (reg_required_here (& str
, 0) != FAIL
)
2668 if (! is_immediate_prefix (* str
))
2671 _("only a register or immediate value can follow a psr flag");
2678 if (my_get_expression (& inst
.reloc
.exp
, & str
))
2681 _("only a register or immediate value can follow a psr flag");
2685 #if 0 /* The first edition of the ARM architecture manual stated that
2686 writing anything other than the flags with an immediate operation
2687 had UNPREDICTABLE effects. This constraint was removed in the
2688 second edition of the specification. */
2689 if ((cpu_variant
& ARM_EXT_V5
) != ARM_EXT_V5
2690 && inst
.instruction
& ((PSR_c
| PSR_x
| PSR_s
) << PSR_SHIFT
))
2692 inst
.error
= _("immediate value cannot be used to set this field");
2697 inst
.instruction
|= INST_IMMEDIATE
;
2699 if (inst
.reloc
.exp
.X_add_symbol
)
2701 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
2702 inst
.reloc
.pc_rel
= 0;
2706 unsigned value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
2708 if (value
== (unsigned) FAIL
)
2710 inst
.error
= _("invalid constant");
2714 inst
.instruction
|= value
;
2721 /* Long Multiply Parser
2722 UMULL RdLo, RdHi, Rm, Rs
2723 SMULL RdLo, RdHi, Rm, Rs
2724 UMLAL RdLo, RdHi, Rm, Rs
2725 SMLAL RdLo, RdHi, Rm, Rs. */
2728 do_mull (char * str
)
2730 int rdlo
, rdhi
, rm
, rs
;
2732 /* Only one format "rdlo, rdhi, rm, rs". */
2733 skip_whitespace (str
);
2735 if ((rdlo
= reg_required_here (&str
, 12)) == FAIL
)
2737 inst
.error
= BAD_ARGS
;
2741 if (skip_past_comma (&str
) == FAIL
2742 || (rdhi
= reg_required_here (&str
, 16)) == FAIL
)
2744 inst
.error
= BAD_ARGS
;
2748 if (skip_past_comma (&str
) == FAIL
2749 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
2751 inst
.error
= BAD_ARGS
;
2755 /* rdhi, rdlo and rm must all be different. */
2756 if (rdlo
== rdhi
|| rdlo
== rm
|| rdhi
== rm
)
2757 as_tsktsk (_("rdhi, rdlo and rm must all be different"));
2759 if (skip_past_comma (&str
) == FAIL
2760 || (rs
= reg_required_here (&str
, 8)) == FAIL
)
2762 inst
.error
= BAD_ARGS
;
2766 if (rdhi
== REG_PC
|| rdhi
== REG_PC
|| rdhi
== REG_PC
|| rdhi
== REG_PC
)
2768 inst
.error
= BAD_PC
;
2780 /* Only one format "rd, rm, rs". */
2781 skip_whitespace (str
);
2783 if ((rd
= reg_required_here (&str
, 16)) == FAIL
)
2785 inst
.error
= BAD_ARGS
;
2791 inst
.error
= BAD_PC
;
2795 if (skip_past_comma (&str
) == FAIL
2796 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
2798 inst
.error
= BAD_ARGS
;
2804 inst
.error
= BAD_PC
;
2809 as_tsktsk (_("rd and rm should be different in mul"));
2811 if (skip_past_comma (&str
) == FAIL
2812 || (rm
= reg_required_here (&str
, 8)) == FAIL
)
2814 inst
.error
= BAD_ARGS
;
2820 inst
.error
= BAD_PC
;
2832 /* Only one format "rd, rm, rs, rn". */
2833 skip_whitespace (str
);
2835 if ((rd
= reg_required_here (&str
, 16)) == FAIL
)
2837 inst
.error
= BAD_ARGS
;
2843 inst
.error
= BAD_PC
;
2847 if (skip_past_comma (&str
) == FAIL
2848 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
2850 inst
.error
= BAD_ARGS
;
2856 inst
.error
= BAD_PC
;
2861 as_tsktsk (_("rd and rm should be different in mla"));
2863 if (skip_past_comma (&str
) == FAIL
2864 || (rd
= reg_required_here (&str
, 8)) == FAIL
2865 || skip_past_comma (&str
) == FAIL
2866 || (rm
= reg_required_here (&str
, 12)) == FAIL
)
2868 inst
.error
= BAD_ARGS
;
2872 if (rd
== REG_PC
|| rm
== REG_PC
)
2874 inst
.error
= BAD_PC
;
2881 /* Expects *str -> the characters "acc0", possibly with leading blanks.
2882 Advances *str to the next non-alphanumeric.
2883 Returns 0, or else FAIL (in which case sets inst.error).
2885 (In a future XScale, there may be accumulators other than zero.
2886 At that time this routine and its callers can be upgraded to suit.) */
2889 accum0_required_here (char ** str
)
2891 static char buff
[128]; /* Note the address is taken. Hence, static. */
2894 int result
= 0; /* The accum number. */
2896 skip_whitespace (p
);
2898 *str
= p
; /* Advance caller's string pointer too. */
2903 *--p
= 0; /* Aap nul into input buffer at non-alnum. */
2905 if (! ( streq (*str
, "acc0") || streq (*str
, "ACC0")))
2907 sprintf (buff
, _("acc0 expected, not '%.100s'"), *str
);
2912 *p
= c
; /* Unzap. */
2913 *str
= p
; /* Caller's string pointer to after match. */
2918 ldst_extend_v4 (char ** str
)
2927 if (my_get_expression (& inst
.reloc
.exp
, str
))
2930 if (inst
.reloc
.exp
.X_op
== O_constant
)
2932 int value
= inst
.reloc
.exp
.X_add_number
;
2934 if (value
< -255 || value
> 255)
2936 inst
.error
= _("address offset too large");
2946 /* Halfword and signextension instructions have the
2947 immediate value split across bits 11..8 and bits 3..0. */
2948 inst
.instruction
|= (add
| HWOFFSET_IMM
2949 | ((value
>> 4) << 8) | (value
& 0xF));
2953 inst
.instruction
|= HWOFFSET_IMM
;
2954 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
2955 inst
.reloc
.pc_rel
= 0;
2968 if (reg_required_here (str
, 0) == FAIL
)
2971 inst
.instruction
|= add
;
2976 /* Expects **str -> after a comma. May be leading blanks.
2977 Advances *str, recognizing a load mode, and setting inst.instruction.
2978 Returns rn, or else FAIL (in which case may set inst.error
2979 and not advance str)
2981 Note: doesn't know Rd, so no err checks that require such knowledge. */
2984 ld_mode_required_here (char ** string
)
2986 char * str
= * string
;
2990 skip_whitespace (str
);
2996 skip_whitespace (str
);
2998 if ((rn
= reg_required_here (& str
, 16)) == FAIL
)
3001 skip_whitespace (str
);
3007 if (skip_past_comma (& str
) == SUCCESS
)
3009 /* [Rn],... (post inc) */
3010 if (ldst_extend_v4 (&str
) == FAIL
)
3015 skip_whitespace (str
);
3020 inst
.instruction
|= WRITE_BACK
;
3023 inst
.instruction
|= INDEX_UP
| HWOFFSET_IMM
;
3029 if (skip_past_comma (& str
) == FAIL
)
3031 inst
.error
= _("pre-indexed expression expected");
3037 if (ldst_extend_v4 (&str
) == FAIL
)
3040 skip_whitespace (str
);
3042 if (* str
++ != ']')
3044 inst
.error
= _("missing ]");
3048 skip_whitespace (str
);
3053 inst
.instruction
|= WRITE_BACK
;
3057 else if (* str
== '=') /* ldr's "r,=label" syntax */
3058 /* We should never reach here, because <text> = <expression> is
3059 caught gas/read.c read_a_source_file() as a .set operation. */
3061 else /* PC +- 8 bit immediate offset. */
3063 if (my_get_expression (& inst
.reloc
.exp
, & str
))
3066 inst
.instruction
|= HWOFFSET_IMM
; /* The I bit. */
3067 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
3068 inst
.reloc
.exp
.X_add_number
-= 8; /* PC rel adjust. */
3069 inst
.reloc
.pc_rel
= 1;
3070 inst
.instruction
|= (REG_PC
<< 16);
3076 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
3082 /* ARM V5E (El Segundo) signed-multiply-accumulate (argument parse)
3083 SMLAxy{cond} Rd,Rm,Rs,Rn
3084 SMLAWy{cond} Rd,Rm,Rs,Rn
3085 Error if any register is R15. */
3088 do_smla (char * str
)
3092 skip_whitespace (str
);
3094 if ((rd
= reg_required_here (& str
, 16)) == FAIL
3095 || skip_past_comma (& str
) == FAIL
3096 || (rm
= reg_required_here (& str
, 0)) == FAIL
3097 || skip_past_comma (& str
) == FAIL
3098 || (rs
= reg_required_here (& str
, 8)) == FAIL
3099 || skip_past_comma (& str
) == FAIL
3100 || (rn
= reg_required_here (& str
, 12)) == FAIL
)
3101 inst
.error
= BAD_ARGS
;
3103 else if (rd
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
|| rn
== REG_PC
)
3104 inst
.error
= BAD_PC
;
3110 /* ARM V5E (El Segundo) signed-multiply-accumulate-long (argument parse)
3111 SMLALxy{cond} Rdlo,Rdhi,Rm,Rs
3112 Error if any register is R15.
3113 Warning if Rdlo == Rdhi. */
3116 do_smlal (char * str
)
3118 int rdlo
, rdhi
, rm
, rs
;
3120 skip_whitespace (str
);
3122 if ((rdlo
= reg_required_here (& str
, 12)) == FAIL
3123 || skip_past_comma (& str
) == FAIL
3124 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
3125 || skip_past_comma (& str
) == FAIL
3126 || (rm
= reg_required_here (& str
, 0)) == FAIL
3127 || skip_past_comma (& str
) == FAIL
3128 || (rs
= reg_required_here (& str
, 8)) == FAIL
)
3130 inst
.error
= BAD_ARGS
;
3134 if (rdlo
== REG_PC
|| rdhi
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
)
3136 inst
.error
= BAD_PC
;
3141 as_tsktsk (_("rdhi and rdlo must be different"));
3146 /* ARM V5E (El Segundo) signed-multiply (argument parse)
3147 SMULxy{cond} Rd,Rm,Rs
3148 Error if any register is R15. */
3151 do_smul (char * str
)
3155 skip_whitespace (str
);
3157 if ((rd
= reg_required_here (& str
, 16)) == FAIL
3158 || skip_past_comma (& str
) == FAIL
3159 || (rm
= reg_required_here (& str
, 0)) == FAIL
3160 || skip_past_comma (& str
) == FAIL
3161 || (rs
= reg_required_here (& str
, 8)) == FAIL
)
3162 inst
.error
= BAD_ARGS
;
3164 else if (rd
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
)
3165 inst
.error
= BAD_PC
;
3171 /* ARM V5E (El Segundo) saturating-add/subtract (argument parse)
3172 Q[D]{ADD,SUB}{cond} Rd,Rm,Rn
3173 Error if any register is R15. */
3176 do_qadd (char * str
)
3180 skip_whitespace (str
);
3182 if ((rd
= reg_required_here (& str
, 12)) == FAIL
3183 || skip_past_comma (& str
) == FAIL
3184 || (rm
= reg_required_here (& str
, 0)) == FAIL
3185 || skip_past_comma (& str
) == FAIL
3186 || (rn
= reg_required_here (& str
, 16)) == FAIL
)
3187 inst
.error
= BAD_ARGS
;
3189 else if (rd
== REG_PC
|| rm
== REG_PC
|| rn
== REG_PC
)
3190 inst
.error
= BAD_PC
;
3196 /* ARM V5E (el Segundo)
3197 MCRRcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
3198 MRRCcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
3200 These are equivalent to the XScale instructions MAR and MRA,
3201 respectively, when coproc == 0, opcode == 0, and CRm == 0.
3203 Result unpredicatable if Rd or Rn is R15. */
3206 do_co_reg2c (char * str
)
3210 skip_whitespace (str
);
3212 if (co_proc_number (& str
) == FAIL
)
3215 inst
.error
= BAD_ARGS
;
3219 if (skip_past_comma (& str
) == FAIL
3220 || cp_opc_expr (& str
, 4, 4) == FAIL
)
3223 inst
.error
= BAD_ARGS
;
3227 if (skip_past_comma (& str
) == FAIL
3228 || (rd
= reg_required_here (& str
, 12)) == FAIL
)
3231 inst
.error
= BAD_ARGS
;
3235 if (skip_past_comma (& str
) == FAIL
3236 || (rn
= reg_required_here (& str
, 16)) == FAIL
)
3239 inst
.error
= BAD_ARGS
;
3243 /* Unpredictable result if rd or rn is R15. */
3244 if (rd
== REG_PC
|| rn
== REG_PC
)
3246 (_("Warning: instruction unpredictable when using r15"));
3248 if (skip_past_comma (& str
) == FAIL
3249 || cp_reg_required_here (& str
, 0) == FAIL
)
3252 inst
.error
= BAD_ARGS
;
3259 /* ARM V5 count-leading-zeroes instruction (argument parse)
3260 CLZ{<cond>} <Rd>, <Rm>
3261 Condition defaults to COND_ALWAYS.
3262 Error if Rd or Rm are R15. */
3269 skip_whitespace (str
);
3271 if (((rd
= reg_required_here (& str
, 12)) == FAIL
)
3272 || (skip_past_comma (& str
) == FAIL
)
3273 || ((rm
= reg_required_here (& str
, 0)) == FAIL
))
3274 inst
.error
= BAD_ARGS
;
3276 else if (rd
== REG_PC
|| rm
== REG_PC
)
3277 inst
.error
= BAD_PC
;
3283 /* ARM V5 (argument parse)
3284 LDC2{L} <coproc>, <CRd>, <addressing mode>
3285 STC2{L} <coproc>, <CRd>, <addressing mode>
3286 Instruction is not conditional, and has 0xf in the condition field.
3287 Otherwise, it's the same as LDC/STC. */
3290 do_lstc2 (char * str
)
3292 skip_whitespace (str
);
3294 if (co_proc_number (& str
) == FAIL
)
3297 inst
.error
= BAD_ARGS
;
3299 else if (skip_past_comma (& str
) == FAIL
3300 || cp_reg_required_here (& str
, 12) == FAIL
)
3303 inst
.error
= BAD_ARGS
;
3305 else if (skip_past_comma (& str
) == FAIL
3306 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
3309 inst
.error
= BAD_ARGS
;
3315 /* ARM V5 (argument parse)
3316 CDP2 <coproc>, <opcode_1>, <CRd>, <CRn>, <CRm>, <opcode_2>
3317 Instruction is not conditional, and has 0xf in the condition field.
3318 Otherwise, it's the same as CDP. */
3321 do_cdp2 (char * str
)
3323 skip_whitespace (str
);
3325 if (co_proc_number (& str
) == FAIL
)
3328 inst
.error
= BAD_ARGS
;
3332 if (skip_past_comma (& str
) == FAIL
3333 || cp_opc_expr (& str
, 20,4) == FAIL
)
3336 inst
.error
= BAD_ARGS
;
3340 if (skip_past_comma (& str
) == FAIL
3341 || cp_reg_required_here (& str
, 12) == FAIL
)
3344 inst
.error
= BAD_ARGS
;
3348 if (skip_past_comma (& str
) == FAIL
3349 || cp_reg_required_here (& str
, 16) == FAIL
)
3352 inst
.error
= BAD_ARGS
;
3356 if (skip_past_comma (& str
) == FAIL
3357 || cp_reg_required_here (& str
, 0) == FAIL
)
3360 inst
.error
= BAD_ARGS
;
3364 if (skip_past_comma (& str
) == SUCCESS
)
3366 if (cp_opc_expr (& str
, 5, 3) == FAIL
)
3369 inst
.error
= BAD_ARGS
;
3377 /* ARM V5 (argument parse)
3378 MCR2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
3379 MRC2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
3380 Instruction is not conditional, and has 0xf in the condition field.
3381 Otherwise, it's the same as MCR/MRC. */
3384 do_co_reg2 (char * str
)
3386 skip_whitespace (str
);
3388 if (co_proc_number (& str
) == FAIL
)
3391 inst
.error
= BAD_ARGS
;
3395 if (skip_past_comma (& str
) == FAIL
3396 || cp_opc_expr (& str
, 21, 3) == FAIL
)
3399 inst
.error
= BAD_ARGS
;
3403 if (skip_past_comma (& str
) == FAIL
3404 || reg_required_here (& str
, 12) == FAIL
)
3407 inst
.error
= BAD_ARGS
;
3411 if (skip_past_comma (& str
) == FAIL
3412 || cp_reg_required_here (& str
, 16) == FAIL
)
3415 inst
.error
= BAD_ARGS
;
3419 if (skip_past_comma (& str
) == FAIL
3420 || cp_reg_required_here (& str
, 0) == FAIL
)
3423 inst
.error
= BAD_ARGS
;
3427 if (skip_past_comma (& str
) == SUCCESS
)
3429 if (cp_opc_expr (& str
, 5, 3) == FAIL
)
3432 inst
.error
= BAD_ARGS
;
3445 skip_whitespace (str
);
3447 if ((reg
= reg_required_here (&str
, 0)) == FAIL
)
3449 inst
.error
= BAD_ARGS
;
3453 /* Note - it is not illegal to do a "bx pc". Useless, but not illegal. */
3455 as_tsktsk (_("use of r15 in bx in ARM mode is not really useful"));
3460 /* ARM v5TEJ. Jump to Jazelle code. */
3467 skip_whitespace (str
);
3469 if ((reg
= reg_required_here (&str
, 0)) == FAIL
)
3471 inst
.error
= BAD_ARGS
;
3475 /* Note - it is not illegal to do a "bxj pc". Useless, but not illegal. */
3477 as_tsktsk (_("use of r15 in bxj is not really useful"));
3482 /* ARM V6 umaal (argument parse). */
3485 do_umaal (char * str
)
3487 int rdlo
, rdhi
, rm
, rs
;
3489 skip_whitespace (str
);
3490 if ((rdlo
= reg_required_here (& str
, 12)) == FAIL
3491 || skip_past_comma (& str
) == FAIL
3492 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
3493 || skip_past_comma (& str
) == FAIL
3494 || (rm
= reg_required_here (& str
, 0)) == FAIL
3495 || skip_past_comma (& str
) == FAIL
3496 || (rs
= reg_required_here (& str
, 8)) == FAIL
)
3498 inst
.error
= BAD_ARGS
;
3502 if (rdlo
== REG_PC
|| rdhi
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
)
3504 inst
.error
= BAD_PC
;
3511 /* ARM V6 strex (argument parse). */
3514 do_strex (char * str
)
3518 /* Parse Rd, Rm,. */
3519 skip_whitespace (str
);
3520 if ((rd
= reg_required_here (& str
, 12)) == FAIL
3521 || skip_past_comma (& str
) == FAIL
3522 || (rm
= reg_required_here (& str
, 0)) == FAIL
3523 || skip_past_comma (& str
) == FAIL
)
3525 inst
.error
= BAD_ARGS
;
3528 if (rd
== REG_PC
|| rm
== REG_PC
)
3530 inst
.error
= BAD_PC
;
3535 inst
.error
= _("Rd equal to Rm or Rn yields unpredictable results");
3539 /* Skip past '['. */
3540 if ((strlen (str
) >= 1)
3541 && strncmp (str
, "[", 1) == 0)
3544 skip_whitespace (str
);
3547 if ((rn
= reg_required_here (& str
, 16)) == FAIL
)
3549 inst
.error
= BAD_ARGS
;
3552 else if (rn
== REG_PC
)
3554 inst
.error
= BAD_PC
;
3559 inst
.error
= _("Rd equal to Rm or Rn yields unpredictable results");
3562 skip_whitespace (str
);
3564 /* Skip past ']'. */
3565 if ((strlen (str
) >= 1)
3566 && strncmp (str
, "]", 1) == 0)
3572 /* KIND indicates what kind of shifts are accepted. */
3575 decode_shift (char ** str
, int kind
)
3577 const struct asm_shift_name
* shift
;
3581 skip_whitespace (* str
);
3583 for (p
= * str
; ISALPHA (* p
); p
++)
3588 inst
.error
= _("shift expression expected");
3594 shift
= (const struct asm_shift_name
*) hash_find (arm_shift_hsh
, * str
);
3599 inst
.error
= _("shift expression expected");
3603 assert (shift
->properties
->index
== shift_properties
[shift
->properties
->index
].index
);
3605 if (kind
== SHIFT_LSL_OR_ASR_IMMEDIATE
3606 && shift
->properties
->index
!= SHIFT_LSL
3607 && shift
->properties
->index
!= SHIFT_ASR
)
3609 inst
.error
= _("'LSL' or 'ASR' required");
3612 else if (kind
== SHIFT_LSL_IMMEDIATE
3613 && shift
->properties
->index
!= SHIFT_LSL
)
3615 inst
.error
= _("'LSL' required");
3618 else if (kind
== SHIFT_ASR_IMMEDIATE
3619 && shift
->properties
->index
!= SHIFT_ASR
)
3621 inst
.error
= _("'ASR' required");
3625 if (shift
->properties
->index
== SHIFT_RRX
)
3628 inst
.instruction
|= shift
->properties
->bit_field
;
3632 skip_whitespace (p
);
3634 if (kind
== NO_SHIFT_RESTRICT
&& reg_required_here (& p
, 8) != FAIL
)
3636 inst
.instruction
|= shift
->properties
->bit_field
| SHIFT_BY_REG
;
3640 else if (! is_immediate_prefix (* p
))
3642 inst
.error
= (NO_SHIFT_RESTRICT
3643 ? _("shift requires register or #expression")
3644 : _("shift requires #expression"));
3652 if (my_get_expression (& inst
.reloc
.exp
, & p
))
3655 /* Validate some simple #expressions. */
3656 if (inst
.reloc
.exp
.X_op
== O_constant
)
3658 unsigned num
= inst
.reloc
.exp
.X_add_number
;
3660 /* Reject operations greater than 32. */
3662 /* Reject a shift of 0 unless the mode allows it. */
3663 || (num
== 0 && shift
->properties
->allows_0
== 0)
3664 /* Reject a shift of 32 unless the mode allows it. */
3665 || (num
== 32 && shift
->properties
->allows_32
== 0)
3668 /* As a special case we allow a shift of zero for
3669 modes that do not support it to be recoded as an
3670 logical shift left of zero (ie nothing). We warn
3671 about this though. */
3674 as_warn (_("shift of 0 ignored."));
3675 shift
= & shift_names
[0];
3676 assert (shift
->properties
->index
== SHIFT_LSL
);
3680 inst
.error
= _("invalid immediate shift");
3685 /* Shifts of 32 are encoded as 0, for those shifts that
3690 inst
.instruction
|= (num
<< 7) | shift
->properties
->bit_field
;
3694 inst
.reloc
.type
= BFD_RELOC_ARM_SHIFT_IMM
;
3695 inst
.reloc
.pc_rel
= 0;
3696 inst
.instruction
|= shift
->properties
->bit_field
;
3704 do_sat (char ** str
, int bias
)
3709 skip_whitespace (*str
);
3711 /* Parse <Rd>, field. */
3712 if ((rd
= reg_required_here (str
, 12)) == FAIL
3713 || skip_past_comma (str
) == FAIL
)
3715 inst
.error
= BAD_ARGS
;
3720 inst
.error
= BAD_PC
;
3724 /* Parse #<immed>, field. */
3725 if (is_immediate_prefix (**str
))
3729 inst
.error
= _("immediate expression expected");
3732 if (my_get_expression (&expr
, str
))
3734 inst
.error
= _("bad expression");
3737 if (expr
.X_op
!= O_constant
)
3739 inst
.error
= _("constant expression expected");
3742 if (expr
.X_add_number
+ bias
< 0
3743 || expr
.X_add_number
+ bias
> 31)
3745 inst
.error
= _("immediate value out of range");
3748 inst
.instruction
|= (expr
.X_add_number
+ bias
) << 16;
3749 if (skip_past_comma (str
) == FAIL
)
3751 inst
.error
= BAD_ARGS
;
3755 /* Parse <Rm> field. */
3756 if ((rm
= reg_required_here (str
, 0)) == FAIL
)
3758 inst
.error
= BAD_ARGS
;
3763 inst
.error
= BAD_PC
;
3767 if (skip_past_comma (str
) == SUCCESS
)
3768 decode_shift (str
, SHIFT_LSL_OR_ASR_IMMEDIATE
);
3771 /* ARM V6 ssat (argument parse). */
3774 do_ssat (char * str
)
3776 do_sat (&str
, /*bias=*/-1);
3780 /* ARM V6 usat (argument parse). */
3783 do_usat (char * str
)
3785 do_sat (&str
, /*bias=*/0);
3790 do_sat16 (char ** str
, int bias
)
3795 skip_whitespace (*str
);
3797 /* Parse the <Rd> field. */
3798 if ((rd
= reg_required_here (str
, 12)) == FAIL
3799 || skip_past_comma (str
) == FAIL
)
3801 inst
.error
= BAD_ARGS
;
3806 inst
.error
= BAD_PC
;
3810 /* Parse #<immed>, field. */
3811 if (is_immediate_prefix (**str
))
3815 inst
.error
= _("immediate expression expected");
3818 if (my_get_expression (&expr
, str
))
3820 inst
.error
= _("bad expression");
3823 if (expr
.X_op
!= O_constant
)
3825 inst
.error
= _("constant expression expected");
3828 if (expr
.X_add_number
+ bias
< 0
3829 || expr
.X_add_number
+ bias
> 15)
3831 inst
.error
= _("immediate value out of range");
3834 inst
.instruction
|= (expr
.X_add_number
+ bias
) << 16;
3835 if (skip_past_comma (str
) == FAIL
)
3837 inst
.error
= BAD_ARGS
;
3841 /* Parse <Rm> field. */
3842 if ((rm
= reg_required_here (str
, 0)) == FAIL
)
3844 inst
.error
= BAD_ARGS
;
3849 inst
.error
= BAD_PC
;
3854 /* ARM V6 ssat16 (argument parse). */
3857 do_ssat16 (char * str
)
3859 do_sat16 (&str
, /*bias=*/-1);
3864 do_usat16 (char * str
)
3866 do_sat16 (&str
, /*bias=*/0);
3871 do_cps_mode (char ** str
)
3875 skip_whitespace (*str
);
3877 if (! is_immediate_prefix (**str
))
3879 inst
.error
= _("immediate expression expected");
3883 (*str
)++; /* Strip off the immediate signifier. */
3884 if (my_get_expression (&expr
, str
))
3886 inst
.error
= _("bad expression");
3890 if (expr
.X_op
!= O_constant
)
3892 inst
.error
= _("constant expression expected");
3896 /* The mode is a 5 bit field. Valid values are 0-31. */
3897 if (((unsigned) expr
.X_add_number
) > 31
3898 || (inst
.reloc
.exp
.X_add_number
) < 0)
3900 inst
.error
= _("invalid constant");
3904 inst
.instruction
|= expr
.X_add_number
;
3907 /* ARM V6 srs (argument parse). */
3913 skip_whitespace (str
);
3914 exclam
= strchr (str
, '!');
3922 inst
.instruction
|= WRITE_BACK
;
3928 /* ARM V6 SMMUL (argument parse). */
3931 do_smmul (char * str
)
3935 skip_whitespace (str
);
3936 if ((rd
= reg_required_here (&str
, 16)) == FAIL
3937 || skip_past_comma (&str
) == FAIL
3938 || (rm
= reg_required_here (&str
, 0)) == FAIL
3939 || skip_past_comma (&str
) == FAIL
3940 || (rs
= reg_required_here (&str
, 8)) == FAIL
)
3942 inst
.error
= BAD_ARGS
;
3950 inst
.error
= BAD_PC
;
3957 /* ARM V6 SMLALD (argument parse). */
3960 do_smlald (char * str
)
3962 int rdlo
, rdhi
, rm
, rs
;
3964 skip_whitespace (str
);
3965 if ((rdlo
= reg_required_here (&str
, 12)) == FAIL
3966 || skip_past_comma (&str
) == FAIL
3967 || (rdhi
= reg_required_here (&str
, 16)) == FAIL
3968 || skip_past_comma (&str
) == FAIL
3969 || (rm
= reg_required_here (&str
, 0)) == FAIL
3970 || skip_past_comma (&str
) == FAIL
3971 || (rs
= reg_required_here (&str
, 8)) == FAIL
)
3973 inst
.error
= BAD_ARGS
;
3982 inst
.error
= BAD_PC
;
3989 /* ARM V6 SMLAD (argument parse). Signed multiply accumulate dual.
3990 smlad{x}{<cond>} Rd, Rm, Rs, Rn */
3993 do_smlad (char * str
)
3997 skip_whitespace (str
);
3998 if ((rd
= reg_required_here (&str
, 16)) == FAIL
3999 || skip_past_comma (&str
) == FAIL
4000 || (rm
= reg_required_here (&str
, 0)) == FAIL
4001 || skip_past_comma (&str
) == FAIL
4002 || (rs
= reg_required_here (&str
, 8)) == FAIL
4003 || skip_past_comma (&str
) == FAIL
4004 || (rn
= reg_required_here (&str
, 12)) == FAIL
)
4006 inst
.error
= BAD_ARGS
;
4015 inst
.error
= BAD_PC
;
4022 /* Returns true if the endian-specifier indicates big-endianness. */
4025 do_endian_specifier (char * str
)
4029 skip_whitespace (str
);
4030 if (strlen (str
) < 2)
4031 inst
.error
= _("missing endian specifier");
4032 else if (strncasecmp (str
, "BE", 2) == 0)
4037 else if (strncasecmp (str
, "LE", 2) == 0)
4040 inst
.error
= _("valid endian specifiers are be or le");
4047 /* ARM V6 SETEND (argument parse). Sets the E bit in the CPSR while
4048 preserving the other bits.
4050 setend <endian_specifier>, where <endian_specifier> is either
4054 do_setend (char * str
)
4056 if (do_endian_specifier (str
))
4057 inst
.instruction
|= 0x200;
4062 SXTH {<cond>} <Rd>, <Rm>{, <rotation>}
4063 Condition defaults to COND_ALWAYS.
4064 Error if any register uses R15. */
4067 do_sxth (char * str
)
4071 int rotation_clear_mask
= 0xfffff3ff;
4072 int rotation_eight_mask
= 0x00000400;
4073 int rotation_sixteen_mask
= 0x00000800;
4074 int rotation_twenty_four_mask
= 0x00000c00;
4076 skip_whitespace (str
);
4077 if ((rd
= reg_required_here (&str
, 12)) == FAIL
4078 || skip_past_comma (&str
) == FAIL
4079 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
4081 inst
.error
= BAD_ARGS
;
4085 else if (rd
== REG_PC
|| rm
== REG_PC
)
4087 inst
.error
= BAD_PC
;
4091 /* Zero out the rotation field. */
4092 inst
.instruction
&= rotation_clear_mask
;
4094 /* Check for lack of optional rotation field. */
4095 if (skip_past_comma (&str
) == FAIL
)
4101 /* Move past 'ROR'. */
4102 skip_whitespace (str
);
4103 if (strncasecmp (str
, "ROR", 3) == 0)
4107 inst
.error
= _("missing rotation field after comma");
4111 /* Get the immediate constant. */
4112 skip_whitespace (str
);
4113 if (is_immediate_prefix (* str
))
4117 inst
.error
= _("immediate expression expected");
4121 if (my_get_expression (&expr
, &str
))
4123 inst
.error
= _("bad expression");
4127 if (expr
.X_op
!= O_constant
)
4129 inst
.error
= _("constant expression expected");
4133 switch (expr
.X_add_number
)
4136 /* Rotation field has already been zeroed. */
4139 inst
.instruction
|= rotation_eight_mask
;
4143 inst
.instruction
|= rotation_sixteen_mask
;
4147 inst
.instruction
|= rotation_twenty_four_mask
;
4151 inst
.error
= _("rotation can be 8, 16, 24 or 0 when field is ommited");
4158 /* ARM V6 SXTAH extracts a 16-bit value from a register, sign
4159 extends it to 32-bits, and adds the result to a value in another
4160 register. You can specify a rotation by 0, 8, 16, or 24 bits
4161 before extracting the 16-bit value.
4162 SXTAH{<cond>} <Rd>, <Rn>, <Rm>{, <rotation>}
4163 Condition defaults to COND_ALWAYS.
4164 Error if any register uses R15. */
4167 do_sxtah (char * str
)
4171 int rotation_clear_mask
= 0xfffff3ff;
4172 int rotation_eight_mask
= 0x00000400;
4173 int rotation_sixteen_mask
= 0x00000800;
4174 int rotation_twenty_four_mask
= 0x00000c00;
4176 skip_whitespace (str
);
4177 if ((rd
= reg_required_here (&str
, 12)) == FAIL
4178 || skip_past_comma (&str
) == FAIL
4179 || (rn
= reg_required_here (&str
, 16)) == FAIL
4180 || skip_past_comma (&str
) == FAIL
4181 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
4183 inst
.error
= BAD_ARGS
;
4187 else if (rd
== REG_PC
|| rn
== REG_PC
|| rm
== REG_PC
)
4189 inst
.error
= BAD_PC
;
4193 /* Zero out the rotation field. */
4194 inst
.instruction
&= rotation_clear_mask
;
4196 /* Check for lack of optional rotation field. */
4197 if (skip_past_comma (&str
) == FAIL
)
4203 /* Move past 'ROR'. */
4204 skip_whitespace (str
);
4205 if (strncasecmp (str
, "ROR", 3) == 0)
4209 inst
.error
= _("missing rotation field after comma");
4213 /* Get the immediate constant. */
4214 skip_whitespace (str
);
4215 if (is_immediate_prefix (* str
))
4219 inst
.error
= _("immediate expression expected");
4223 if (my_get_expression (&expr
, &str
))
4225 inst
.error
= _("bad expression");
4229 if (expr
.X_op
!= O_constant
)
4231 inst
.error
= _("constant expression expected");
4235 switch (expr
.X_add_number
)
4238 /* Rotation field has already been zeroed. */
4242 inst
.instruction
|= rotation_eight_mask
;
4246 inst
.instruction
|= rotation_sixteen_mask
;
4250 inst
.instruction
|= rotation_twenty_four_mask
;
4254 inst
.error
= _("rotation can be 8, 16, 24 or 0 when field is ommited");
4262 /* ARM V6 RFE (Return from Exception) loads the PC and CPSR from the
4263 word at the specified address and the following word
4265 Unconditionally executed.
4266 Error if Rn is R15. */
4273 skip_whitespace (str
);
4275 if ((rn
= reg_required_here (&str
, 16)) == FAIL
)
4280 inst
.error
= BAD_PC
;
4284 skip_whitespace (str
);
4288 inst
.instruction
|= WRITE_BACK
;
4294 /* ARM V6 REV (Byte Reverse Word) reverses the byte order in a 32-bit
4295 register (argument parse).
4297 Condition defaults to COND_ALWAYS.
4298 Error if Rd or Rm are R15. */
4305 skip_whitespace (str
);
4307 if ((rd
= reg_required_here (&str
, 12)) == FAIL
4308 || skip_past_comma (&str
) == FAIL
4309 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
4310 inst
.error
= BAD_ARGS
;
4312 else if (rd
== REG_PC
|| rm
== REG_PC
)
4313 inst
.error
= BAD_PC
;
4319 /* ARM V6 Perform Two Sixteen Bit Integer Additions. (argument parse).
4320 QADD16{<cond>} <Rd>, <Rn>, <Rm>
4321 Condition defaults to COND_ALWAYS.
4322 Error if Rd, Rn or Rm are R15. */
4325 do_qadd16 (char * str
)
4329 skip_whitespace (str
);
4331 if ((rd
= reg_required_here (&str
, 12)) == FAIL
4332 || skip_past_comma (&str
) == FAIL
4333 || (rn
= reg_required_here (&str
, 16)) == FAIL
4334 || skip_past_comma (&str
) == FAIL
4335 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
4336 inst
.error
= BAD_ARGS
;
4338 else if (rd
== REG_PC
|| rm
== REG_PC
|| rn
== REG_PC
)
4339 inst
.error
= BAD_PC
;
4346 do_pkh_core (char * str
, int shift
)
4350 skip_whitespace (str
);
4351 if (((rd
= reg_required_here (&str
, 12)) == FAIL
)
4352 || (skip_past_comma (&str
) == FAIL
)
4353 || ((rn
= reg_required_here (&str
, 16)) == FAIL
)
4354 || (skip_past_comma (&str
) == FAIL
)
4355 || ((rm
= reg_required_here (&str
, 0)) == FAIL
))
4357 inst
.error
= BAD_ARGS
;
4361 else if (rd
== REG_PC
|| rn
== REG_PC
|| rm
== REG_PC
)
4363 inst
.error
= BAD_PC
;
4367 /* Check for optional shift immediate constant. */
4368 if (skip_past_comma (&str
) == FAIL
)
4370 if (shift
== SHIFT_ASR_IMMEDIATE
)
4372 /* If the shift specifier is ommited, turn the instruction
4373 into pkhbt rd, rm, rn. First, switch the instruction
4374 code, and clear the rn and rm fields. */
4375 inst
.instruction
&= 0xfff0f010;
4376 /* Now, re-encode the registers. */
4377 inst
.instruction
|= (rm
<< 16) | rn
;
4382 decode_shift (&str
, shift
);
4385 /* ARM V6 Pack Halfword Bottom Top instruction (argument parse).
4386 PKHBT {<cond>} <Rd>, <Rn>, <Rm> {, LSL #<shift_imm>}
4387 Condition defaults to COND_ALWAYS.
4388 Error if Rd, Rn or Rm are R15. */
4391 do_pkhbt (char * str
)
4393 do_pkh_core (str
, SHIFT_LSL_IMMEDIATE
);
4396 /* ARM V6 PKHTB (Argument Parse). */
4399 do_pkhtb (char * str
)
4401 do_pkh_core (str
, SHIFT_ASR_IMMEDIATE
);
4404 /* ARM V6 Load Register Exclusive instruction (argument parse).
4405 LDREX{,B,D,H}{<cond>} <Rd, [<Rn>]
4406 Condition defaults to COND_ALWAYS.
4407 Error if Rd or Rn are R15.
4408 See ARMARMv6 A4.1.27: LDREX. */
4411 do_ldrex (char * str
)
4415 skip_whitespace (str
);
4418 if (((rd
= reg_required_here (&str
, 12)) == FAIL
)
4419 || (skip_past_comma (&str
) == FAIL
))
4421 inst
.error
= BAD_ARGS
;
4424 else if (rd
== REG_PC
)
4426 inst
.error
= BAD_PC
;
4429 skip_whitespace (str
);
4431 /* Skip past '['. */
4432 if ((strlen (str
) >= 1)
4433 &&strncmp (str
, "[", 1) == 0)
4435 skip_whitespace (str
);
4438 if ((rn
= reg_required_here (&str
, 16)) == FAIL
)
4440 inst
.error
= BAD_ARGS
;
4443 else if (rn
== REG_PC
)
4445 inst
.error
= BAD_PC
;
4448 skip_whitespace (str
);
4450 /* Skip past ']'. */
4451 if ((strlen (str
) >= 1)
4452 && strncmp (str
, "]", 1) == 0)
4458 /* ARM V6 change processor state instruction (argument parse)
4459 CPS, CPSIE, CSPID . */
4469 do_cps_flags (char ** str
, int thumb_p
)
4474 unsigned long arm_value
;
4475 unsigned long thumb_value
;
4477 static struct cps_flag flag_table
[] =
4486 skip_whitespace (*str
);
4488 /* Get the a, f and i flags. */
4489 while (**str
&& **str
!= ',')
4492 struct cps_flag
*q
= flag_table
+ sizeof (flag_table
)/sizeof (*p
);
4494 for (p
= flag_table
; p
< q
; ++p
)
4495 if (strncasecmp (*str
, &p
->character
, 1) == 0)
4497 inst
.instruction
|= (thumb_p
? p
->thumb_value
: p
->arm_value
);
4503 inst
.error
= _("unrecognized flag");
4510 inst
.error
= _("no 'a', 'i', or 'f' flags for 'cps'");
4514 do_cpsi (char * str
)
4516 do_cps_flags (&str
, /*thumb_p=*/0);
4518 if (skip_past_comma (&str
) == SUCCESS
)
4520 skip_whitespace (str
);
4526 /* THUMB V5 breakpoint instruction (argument parse)
4530 do_t_bkpt (char * str
)
4533 unsigned long number
;
4535 skip_whitespace (str
);
4537 /* Allow optional leading '#'. */
4538 if (is_immediate_prefix (*str
))
4541 memset (& expr
, '\0', sizeof (expr
));
4542 if (my_get_expression (& expr
, & str
)
4543 || (expr
.X_op
!= O_constant
4544 /* As a convenience we allow 'bkpt' without an operand. */
4545 && expr
.X_op
!= O_absent
))
4547 inst
.error
= _("bad expression");
4551 number
= expr
.X_add_number
;
4553 /* Check it fits an 8 bit unsigned. */
4554 if (number
!= (number
& 0xff))
4556 inst
.error
= _("immediate value out of range");
4560 inst
.instruction
|= number
;
4565 static bfd_reloc_code_real_type
4566 arm_parse_reloc (void)
4575 bfd_reloc_code_real_type reloc
;
4579 #define MAP(str,reloc) { str, sizeof (str) - 1, reloc }
4580 MAP ("(got)", BFD_RELOC_ARM_GOT32
),
4581 MAP ("(gotoff)", BFD_RELOC_ARM_GOTOFF
),
4582 /* ScottB: Jan 30, 1998 - Added support for parsing "var(PLT)"
4583 branch instructions generated by GCC for PLT relocs. */
4584 MAP ("(plt)", BFD_RELOC_ARM_PLT32
),
4585 MAP ("(target1)", BFD_RELOC_ARM_TARGET1
),
4586 MAP ("(sbrel)", BFD_RELOC_ARM_SBREL32
),
4587 MAP ("(target2)", BFD_RELOC_ARM_TARGET2
),
4588 { NULL
, 0, BFD_RELOC_UNUSED
}
4592 for (i
= 0, ip
= input_line_pointer
;
4593 i
< sizeof (id
) && (ISALNUM (*ip
) || ISPUNCT (*ip
));
4595 id
[i
] = TOLOWER (*ip
);
4597 for (i
= 0; reloc_map
[i
].str
; i
++)
4598 if (strncmp (id
, reloc_map
[i
].str
, reloc_map
[i
].len
) == 0)
4601 input_line_pointer
+= reloc_map
[i
].len
;
4603 return reloc_map
[i
].reloc
;
4606 /* ARM V5 branch-link-exchange (argument parse) for BLX(1) only.
4607 Expects inst.instruction is set for BLX(1).
4608 Note: this is cloned from do_branch, and the reloc changed to be a
4609 new one that can cope with setting one extra bit (the H bit). */
4612 do_branch25 (char * str
)
4614 if (my_get_expression (& inst
.reloc
.exp
, & str
))
4621 /* ScottB: February 5, 1998 */
4622 /* Check to see of PLT32 reloc required for the instruction. */
4624 /* arm_parse_reloc() works on input_line_pointer.
4625 We actually want to parse the operands to the branch instruction
4626 passed in 'str'. Save the input pointer and restore it later. */
4627 save_in
= input_line_pointer
;
4628 input_line_pointer
= str
;
4630 if (inst
.reloc
.exp
.X_op
== O_symbol
4632 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32
)
4634 inst
.reloc
.type
= BFD_RELOC_ARM_PLT32
;
4635 inst
.reloc
.pc_rel
= 0;
4636 /* Modify str to point to after parsed operands, otherwise
4637 end_of_line() will complain about the (PLT) left in str. */
4638 str
= input_line_pointer
;
4642 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BLX
;
4643 inst
.reloc
.pc_rel
= 1;
4646 input_line_pointer
= save_in
;
4649 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BLX
;
4650 inst
.reloc
.pc_rel
= 1;
4651 #endif /* OBJ_ELF */
4656 /* ARM V5 branch-link-exchange instruction (argument parse)
4657 BLX <target_addr> ie BLX(1)
4658 BLX{<condition>} <Rm> ie BLX(2)
4659 Unfortunately, there are two different opcodes for this mnemonic.
4660 So, the insns[].value is not used, and the code here zaps values
4661 into inst.instruction.
4662 Also, the <target_addr> can be 25 bits, hence has its own reloc. */
4670 skip_whitespace (mystr
);
4671 rm
= reg_required_here (& mystr
, 0);
4673 /* The above may set inst.error. Ignore his opinion. */
4678 /* Arg is a register.
4679 Use the condition code our caller put in inst.instruction.
4680 Pass ourselves off as a BX with a funny opcode. */
4681 inst
.instruction
|= 0x012fff30;
4686 /* This must be is BLX <target address>, no condition allowed. */
4687 if (inst
.instruction
!= COND_ALWAYS
)
4689 inst
.error
= BAD_COND
;
4693 inst
.instruction
= 0xfafffffe;
4695 /* Process like a B/BL, but with a different reloc.
4696 Note that B/BL expecte fffffe, not 0, offset in the opcode table. */
4701 /* ARM V5 Thumb BLX (argument parse)
4702 BLX <target_addr> which is BLX(1)
4703 BLX <Rm> which is BLX(2)
4704 Unfortunately, there are two different opcodes for this mnemonic.
4705 So, the tinsns[].value is not used, and the code here zaps values
4706 into inst.instruction. */
4709 do_t_blx (char * str
)
4714 skip_whitespace (mystr
);
4715 inst
.instruction
= 0x4780;
4717 /* Note that this call is to the ARM register recognizer. BLX(2)
4718 uses the ARM register space, not the Thumb one, so a call to
4719 thumb_reg() would be wrong. */
4720 rm
= reg_required_here (& mystr
, 3);
4725 /* It's BLX(2). The .instruction was zapped with rm & is final. */
4730 /* No ARM register. This must be BLX(1). Change the .instruction. */
4731 inst
.instruction
= 0xf7ffeffe;
4734 if (my_get_expression (& inst
.reloc
.exp
, & mystr
))
4737 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BLX
;
4738 inst
.reloc
.pc_rel
= 1;
4741 end_of_line (mystr
);
4744 /* ARM V5 breakpoint instruction (argument parse)
4745 BKPT <16 bit unsigned immediate>
4746 Instruction is not conditional.
4747 The bit pattern given in insns[] has the COND_ALWAYS condition,
4748 and it is an error if the caller tried to override that. */
4751 do_bkpt (char * str
)
4754 unsigned long number
;
4756 skip_whitespace (str
);
4758 /* Allow optional leading '#'. */
4759 if (is_immediate_prefix (* str
))
4762 memset (& expr
, '\0', sizeof (expr
));
4764 if (my_get_expression (& expr
, & str
)
4765 || (expr
.X_op
!= O_constant
4766 /* As a convenience we allow 'bkpt' without an operand. */
4767 && expr
.X_op
!= O_absent
))
4769 inst
.error
= _("bad expression");
4773 number
= expr
.X_add_number
;
4775 /* Check it fits a 16 bit unsigned. */
4776 if (number
!= (number
& 0xffff))
4778 inst
.error
= _("immediate value out of range");
4782 /* Top 12 of 16 bits to bits 19:8. */
4783 inst
.instruction
|= (number
& 0xfff0) << 4;
4785 /* Bottom 4 of 16 bits to bits 3:0. */
4786 inst
.instruction
|= number
& 0xf;
4791 /* THUMB CPS instruction (argument parse). */
4794 do_t_cps (char * str
)
4796 do_cps_flags (&str
, /*thumb_p=*/1);
4800 /* Parse and validate that a register is of the right form, this saves
4801 repeated checking of this information in many similar cases.
4802 Unlike the 32-bit case we do not insert the register into the opcode
4803 here, since the position is often unknown until the full instruction
4807 thumb_reg (char ** strp
, int hi_lo
)
4811 if ((reg
= reg_required_here (strp
, -1)) == FAIL
)
4819 inst
.error
= _("lo register required");
4827 inst
.error
= _("hi register required");
4840 thumb_mov_compare (char * str
, int move
)
4844 skip_whitespace (str
);
4846 if ((Rd
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
4847 || skip_past_comma (&str
) == FAIL
)
4850 inst
.error
= BAD_ARGS
;
4854 if (move
!= THUMB_CPY
&& is_immediate_prefix (*str
))
4857 if (my_get_expression (&inst
.reloc
.exp
, &str
))
4860 else if ((Rs
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
4865 if (move
!= THUMB_CPY
&& Rs
< 8 && Rd
< 8)
4867 if (move
== THUMB_MOVE
)
4868 /* A move of two lowregs is encoded as ADD Rd, Rs, #0
4869 since a MOV instruction produces unpredictable results. */
4870 inst
.instruction
= T_OPCODE_ADD_I3
;
4872 inst
.instruction
= T_OPCODE_CMP_LR
;
4873 inst
.instruction
|= Rd
| (Rs
<< 3);
4877 if (move
== THUMB_MOVE
)
4878 inst
.instruction
= T_OPCODE_MOV_HR
;
4879 else if (move
!= THUMB_CPY
)
4880 inst
.instruction
= T_OPCODE_CMP_HR
;
4883 inst
.instruction
|= THUMB_H1
;
4886 inst
.instruction
|= THUMB_H2
;
4888 inst
.instruction
|= (Rd
& 7) | ((Rs
& 7) << 3);
4895 inst
.error
= _("only lo regs allowed with immediate");
4899 if (move
== THUMB_MOVE
)
4900 inst
.instruction
= T_OPCODE_MOV_I8
;
4902 inst
.instruction
= T_OPCODE_CMP_I8
;
4904 inst
.instruction
|= Rd
<< 8;
4906 if (inst
.reloc
.exp
.X_op
!= O_constant
)
4907 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_IMM
;
4910 unsigned value
= inst
.reloc
.exp
.X_add_number
;
4914 inst
.error
= _("invalid immediate");
4918 inst
.instruction
|= value
;
4925 /* THUMB CPY instruction (argument parse). */
4928 do_t_cpy (char * str
)
4930 thumb_mov_compare (str
, THUMB_CPY
);
4933 /* THUMB SETEND instruction (argument parse). */
4936 do_t_setend (char * str
)
4938 if (do_endian_specifier (str
))
4939 inst
.instruction
|= 0x8;
4942 /* Parse INSN_TYPE insn STR having a possible IMMEDIATE_SIZE immediate. */
4944 static unsigned long
4945 check_iwmmxt_insn (char * str
,
4946 enum iwmmxt_insn_type insn_type
,
4950 const char * inst_error
;
4952 unsigned long number
;
4954 inst_error
= inst
.error
;
4956 inst
.error
= BAD_ARGS
;
4957 skip_whitespace (str
);
4962 if ((reg
= reg_required_here (&str
, 12)) == FAIL
)
4967 if ((wreg_required_here (&str
, 0, IWMMXT_REG_WR
)) == FAIL
)
4972 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
4973 || skip_past_comma (&str
) == FAIL
4974 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
))
4979 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
4980 || skip_past_comma (&str
) == FAIL
4981 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
4982 || skip_past_comma (&str
) == FAIL
4983 || wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
))
4988 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
4989 || skip_past_comma (&str
) == FAIL
4990 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
4991 || skip_past_comma (&str
) == FAIL
4992 || wreg_required_here (&str
, 0, IWMMXT_REG_WCG
) == FAIL
))
4997 if ((wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
4998 || skip_past_comma (&str
) == FAIL
4999 || reg_required_here (&str
, 12) == FAIL
))
5004 if ((reg_required_here (&str
, 12) == FAIL
5005 || skip_past_comma (&str
) == FAIL
5006 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
))
5011 if ((wreg_required_here (&str
, 5, IWMMXT_REG_WR
) == FAIL
5012 || skip_past_comma (&str
) == FAIL
5013 || reg_required_here (&str
, 0) == FAIL
5014 || skip_past_comma (&str
) == FAIL
5015 || reg_required_here (&str
, 12) == FAIL
))
5020 if ((wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
5021 || skip_past_comma (&str
) == FAIL
5022 || reg_required_here (&str
, 12) == FAIL
5023 || skip_past_comma (&str
) == FAIL
5024 || reg_required_here (&str
, 16) == FAIL
))
5029 if ((reg_required_here (&str
, 12) == FAIL
5030 || skip_past_comma (&str
) == FAIL
5031 || reg_required_here (&str
, 16) == FAIL
5032 || skip_past_comma (&str
) == FAIL
5033 || wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
))
5038 if ((wreg_required_here (&str
, 16, IWMMXT_REG_WC
) == FAIL
5039 || skip_past_comma (&str
) == FAIL
5040 || reg_required_here (&str
, 12) == FAIL
))
5045 if ((reg_required_here (&str
, 12) == FAIL
5046 || skip_past_comma (&str
) == FAIL
5047 || wreg_required_here (&str
, 16, IWMMXT_REG_WC
) == FAIL
))
5052 if ((wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
5053 || skip_past_comma (&str
) == FAIL
5054 || reg_required_here (&str
, 12) == FAIL
5055 || skip_past_comma (&str
) == FAIL
))
5060 if ((reg_required_here (&str
, 12) == FAIL
5061 || skip_past_comma (&str
) == FAIL
))
5066 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
5067 || skip_past_comma (&str
) == FAIL
5068 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
5069 || skip_past_comma (&str
) == FAIL
5070 || wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
5071 || skip_past_comma (&str
) == FAIL
))
5076 if ((reg_required_here (&str
, 12) == FAIL
5077 || skip_past_comma (&str
) == FAIL
5078 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
5079 || skip_past_comma (&str
) == FAIL
))
5084 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
5085 || skip_past_comma (&str
) == FAIL
5086 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
5087 || skip_past_comma (&str
) == FAIL
))
5092 if (immediate_size
== 0)
5095 inst
.error
= inst_error
;
5100 skip_whitespace (str
);
5102 /* Allow optional leading '#'. */
5103 if (is_immediate_prefix (* str
))
5106 memset (& expr
, '\0', sizeof (expr
));
5108 if (my_get_expression (& expr
, & str
) || (expr
.X_op
!= O_constant
))
5110 inst
.error
= _("bad or missing expression");
5114 number
= expr
.X_add_number
;
5116 if (number
!= (number
& immediate_size
))
5118 inst
.error
= _("immediate value out of range");
5122 inst
.error
= inst_error
;
5128 do_iwmmxt_byte_addr (char * str
)
5130 int op
= (inst
.instruction
& 0x300) >> 8;
5133 inst
.instruction
&= ~0x300;
5134 inst
.instruction
|= (op
& 1) << 22 | (op
& 2) << 7;
5136 skip_whitespace (str
);
5138 if ((reg
= wreg_required_here (&str
, 12, IWMMXT_REG_WR_OR_WC
)) == FAIL
5139 || skip_past_comma (& str
) == FAIL
5140 || cp_byte_address_required_here (&str
) == FAIL
)
5143 inst
.error
= BAD_ARGS
;
5148 if (wc_register (reg
))
5150 as_bad (_("non-word size not supported with control register"));
5151 inst
.instruction
|= 0xf0000100;
5152 inst
.instruction
&= ~0x00400000;
5157 do_iwmmxt_tandc (char * str
)
5161 reg
= check_iwmmxt_insn (str
, check_rd
, 0);
5163 if (reg
!= REG_PC
&& !inst
.error
)
5164 inst
.error
= _("only r15 allowed here");
5168 do_iwmmxt_tbcst (char * str
)
5170 check_iwmmxt_insn (str
, check_tbcst
, 0);
5174 do_iwmmxt_textrc (char * str
)
5176 unsigned long number
;
5178 if ((number
= check_iwmmxt_insn (str
, check_textrc
, 7)) == (unsigned long) FAIL
)
5181 inst
.instruction
|= number
& 0x7;
5185 do_iwmmxt_textrm (char * str
)
5187 unsigned long number
;
5189 if ((number
= check_iwmmxt_insn (str
, check_textrm
, 7)) == (unsigned long) FAIL
)
5192 inst
.instruction
|= number
& 0x7;
5196 do_iwmmxt_tinsr (char * str
)
5198 unsigned long number
;
5200 if ((number
= check_iwmmxt_insn (str
, check_tinsr
, 7)) == (unsigned long) FAIL
)
5203 inst
.instruction
|= number
& 0x7;
5207 do_iwmmxt_tmcr (char * str
)
5209 check_iwmmxt_insn (str
, check_tmcr
, 0);
5213 do_iwmmxt_tmcrr (char * str
)
5215 check_iwmmxt_insn (str
, check_tmcrr
, 0);
5219 do_iwmmxt_tmia (char * str
)
5221 check_iwmmxt_insn (str
, check_tmia
, 0);
5225 do_iwmmxt_tmovmsk (char * str
)
5227 check_iwmmxt_insn (str
, check_tmovmsk
, 0);
5231 do_iwmmxt_tmrc (char * str
)
5233 check_iwmmxt_insn (str
, check_tmrc
, 0);
5237 do_iwmmxt_tmrrc (char * str
)
5239 check_iwmmxt_insn (str
, check_tmrrc
, 0);
5243 do_iwmmxt_torc (char * str
)
5245 check_iwmmxt_insn (str
, check_rd
, 0);
5249 do_iwmmxt_waligni (char * str
)
5251 unsigned long number
;
5253 if ((number
= check_iwmmxt_insn (str
, check_waligni
, 7)) == (unsigned long) FAIL
)
5256 inst
.instruction
|= ((number
& 0x7) << 20);
5260 do_iwmmxt_wmov (char * str
)
5262 if (check_iwmmxt_insn (str
, check_wrwr
, 0) == (unsigned long) FAIL
)
5265 inst
.instruction
|= ((inst
.instruction
>> 16) & 0xf);
5269 do_iwmmxt_word_addr (char * str
)
5271 int op
= (inst
.instruction
& 0x300) >> 8;
5274 inst
.instruction
&= ~0x300;
5275 inst
.instruction
|= (op
& 1) << 22 | (op
& 2) << 7;
5277 skip_whitespace (str
);
5279 if ((reg
= wreg_required_here (&str
, 12, IWMMXT_REG_WR_OR_WC
)) == FAIL
5280 || skip_past_comma (& str
) == FAIL
5281 || cp_address_required_here (& str
, CP_WB_OK
) == FAIL
)
5284 inst
.error
= BAD_ARGS
;
5289 if (wc_register (reg
))
5291 if ((inst
.instruction
& COND_MASK
) != COND_ALWAYS
)
5292 as_bad (_("conditional execution not supported with control register"));
5294 as_bad (_("non-word size not supported with control register"));
5295 inst
.instruction
|= 0xf0000100;
5296 inst
.instruction
&= ~0x00400000;
5301 do_iwmmxt_wrwr (char * str
)
5303 check_iwmmxt_insn (str
, check_wrwr
, 0);
5307 do_iwmmxt_wrwrwcg (char * str
)
5309 check_iwmmxt_insn (str
, check_wrwrwcg
, 0);
5313 do_iwmmxt_wrwrwr (char * str
)
5315 check_iwmmxt_insn (str
, check_wrwrwr
, 0);
5319 do_iwmmxt_wshufh (char * str
)
5321 unsigned long number
;
5323 if ((number
= check_iwmmxt_insn (str
, check_wshufh
, 0xff)) == (unsigned long) FAIL
)
5326 inst
.instruction
|= ((number
& 0xf0) << 16) | (number
& 0xf);
5330 do_iwmmxt_wzero (char * str
)
5332 if (check_iwmmxt_insn (str
, check_wr
, 0) == (unsigned long) FAIL
)
5335 inst
.instruction
|= ((inst
.instruction
& 0xf) << 12) | ((inst
.instruction
& 0xf) << 16);
5338 /* Xscale multiply-accumulate (argument parse)
5341 MIAxycc acc0,Rm,Rs. */
5344 do_xsc_mia (char * str
)
5349 if (accum0_required_here (& str
) == FAIL
)
5350 inst
.error
= ERR_NO_ACCUM
;
5352 else if (skip_past_comma (& str
) == FAIL
5353 || (rm
= reg_required_here (& str
, 0)) == FAIL
)
5354 inst
.error
= BAD_ARGS
;
5356 else if (skip_past_comma (& str
) == FAIL
5357 || (rs
= reg_required_here (& str
, 12)) == FAIL
)
5358 inst
.error
= BAD_ARGS
;
5360 /* inst.instruction has now been zapped with both rm and rs. */
5361 else if (rm
== REG_PC
|| rs
== REG_PC
)
5362 inst
.error
= BAD_PC
; /* Undefined result if rm or rs is R15. */
5368 /* Xscale move-accumulator-register (argument parse)
5370 MARcc acc0,RdLo,RdHi. */
5373 do_xsc_mar (char * str
)
5377 if (accum0_required_here (& str
) == FAIL
)
5378 inst
.error
= ERR_NO_ACCUM
;
5380 else if (skip_past_comma (& str
) == FAIL
5381 || (rdlo
= reg_required_here (& str
, 12)) == FAIL
)
5382 inst
.error
= BAD_ARGS
;
5384 else if (skip_past_comma (& str
) == FAIL
5385 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
)
5386 inst
.error
= BAD_ARGS
;
5388 /* inst.instruction has now been zapped with both rdlo and rdhi. */
5389 else if (rdlo
== REG_PC
|| rdhi
== REG_PC
)
5390 inst
.error
= BAD_PC
; /* Undefined result if rdlo or rdhi is R15. */
5396 /* Xscale move-register-accumulator (argument parse)
5398 MRAcc RdLo,RdHi,acc0. */
5401 do_xsc_mra (char * str
)
5406 skip_whitespace (str
);
5408 if ((rdlo
= reg_required_here (& str
, 12)) == FAIL
)
5409 inst
.error
= BAD_ARGS
;
5411 else if (skip_past_comma (& str
) == FAIL
5412 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
)
5413 inst
.error
= BAD_ARGS
;
5415 else if (skip_past_comma (& str
) == FAIL
5416 || accum0_required_here (& str
) == FAIL
)
5417 inst
.error
= ERR_NO_ACCUM
;
5419 /* inst.instruction has now been zapped with both rdlo and rdhi. */
5420 else if (rdlo
== rdhi
)
5421 inst
.error
= BAD_ARGS
; /* Undefined result if 2 writes to same reg. */
5423 else if (rdlo
== REG_PC
|| rdhi
== REG_PC
)
5424 inst
.error
= BAD_PC
; /* Undefined result if rdlo or rdhi is R15. */
5430 ldst_extend (char ** str
)
5439 if (my_get_expression (& inst
.reloc
.exp
, str
))
5442 if (inst
.reloc
.exp
.X_op
== O_constant
)
5444 int value
= inst
.reloc
.exp
.X_add_number
;
5446 if (value
< -4095 || value
> 4095)
5448 inst
.error
= _("address offset too large");
5458 inst
.instruction
|= add
| value
;
5462 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM
;
5463 inst
.reloc
.pc_rel
= 0;
5476 if (reg_required_here (str
, 0) == FAIL
)
5479 inst
.instruction
|= add
| OFFSET_REG
;
5480 if (skip_past_comma (str
) == SUCCESS
)
5481 return decode_shift (str
, SHIFT_IMMEDIATE
);
5487 /* ARMv5TE: Preload-Cache
5491 Syntactically, like LDR with B=1, W=0, L=1. */
5498 skip_whitespace (str
);
5502 inst
.error
= _("'[' expected after PLD mnemonic");
5507 skip_whitespace (str
);
5509 if ((rd
= reg_required_here (& str
, 16)) == FAIL
)
5512 skip_whitespace (str
);
5518 skip_whitespace (str
);
5520 /* Post-indexed addressing is not allowed with PLD. */
5521 if (skip_past_comma (&str
) == SUCCESS
)
5524 = _("post-indexed expression used in preload instruction");
5527 else if (*str
== '!') /* [Rn]! */
5529 inst
.error
= _("writeback used in preload instruction");
5533 inst
.instruction
|= INDEX_UP
| PRE_INDEX
;
5535 else /* [Rn, ...] */
5537 if (skip_past_comma (& str
) == FAIL
)
5539 inst
.error
= _("pre-indexed expression expected");
5543 if (ldst_extend (&str
) == FAIL
)
5546 skip_whitespace (str
);
5550 inst
.error
= _("missing ]");
5555 skip_whitespace (str
);
5557 if (* str
== '!') /* [Rn]! */
5559 inst
.error
= _("writeback used in preload instruction");
5563 inst
.instruction
|= PRE_INDEX
;
5569 /* ARMv5TE load-consecutive (argument parse)
5576 do_ldrd (char * str
)
5581 skip_whitespace (str
);
5583 if ((rd
= reg_required_here (& str
, 12)) == FAIL
)
5585 inst
.error
= BAD_ARGS
;
5589 if (skip_past_comma (& str
) == FAIL
5590 || (rn
= ld_mode_required_here (& str
)) == FAIL
)
5593 inst
.error
= BAD_ARGS
;
5597 /* inst.instruction has now been zapped with Rd and the addressing mode. */
5598 if (rd
& 1) /* Unpredictable result if Rd is odd. */
5600 inst
.error
= _("destination register must be even");
5606 inst
.error
= _("r14 not allowed here");
5610 if (((rd
== rn
) || (rd
+ 1 == rn
))
5611 && ((inst
.instruction
& WRITE_BACK
)
5612 || (!(inst
.instruction
& PRE_INDEX
))))
5613 as_warn (_("pre/post-indexing used when modified address register is destination"));
5615 /* For an index-register load, the index register must not overlap the
5616 destination (even if not write-back). */
5617 if ((inst
.instruction
& V4_STR_BIT
) == 0
5618 && (inst
.instruction
& HWOFFSET_IMM
) == 0)
5620 int rm
= inst
.instruction
& 0x0000000f;
5622 if (rm
== rd
|| (rm
== rd
+ 1))
5623 as_warn (_("ldrd destination registers must not overlap index register"));
5629 /* Returns the index into fp_values of a floating point number,
5630 or -1 if not in the table. */
5633 my_get_float_expression (char ** str
)
5635 LITTLENUM_TYPE words
[MAX_LITTLENUMS
];
5641 memset (words
, 0, MAX_LITTLENUMS
* sizeof (LITTLENUM_TYPE
));
5643 /* Look for a raw floating point number. */
5644 if ((save_in
= atof_ieee (*str
, 'x', words
)) != NULL
5645 && is_end_of_line
[(unsigned char) *save_in
])
5647 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
5649 for (j
= 0; j
< MAX_LITTLENUMS
; j
++)
5651 if (words
[j
] != fp_values
[i
][j
])
5655 if (j
== MAX_LITTLENUMS
)
5663 /* Try and parse a more complex expression, this will probably fail
5664 unless the code uses a floating point prefix (eg "0f"). */
5665 save_in
= input_line_pointer
;
5666 input_line_pointer
= *str
;
5667 if (expression (&exp
) == absolute_section
5668 && exp
.X_op
== O_big
5669 && exp
.X_add_number
< 0)
5671 /* FIXME: 5 = X_PRECISION, should be #define'd where we can use it.
5673 if (gen_to_words (words
, 5, (long) 15) == 0)
5675 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
5677 for (j
= 0; j
< MAX_LITTLENUMS
; j
++)
5679 if (words
[j
] != fp_values
[i
][j
])
5683 if (j
== MAX_LITTLENUMS
)
5685 *str
= input_line_pointer
;
5686 input_line_pointer
= save_in
;
5693 *str
= input_line_pointer
;
5694 input_line_pointer
= save_in
;
5698 /* We handle all bad expressions here, so that we can report the faulty
5699 instruction in the error message. */
5701 md_operand (expressionS
* expr
)
5703 if (in_my_get_expression
)
5705 expr
->X_op
= O_illegal
;
5706 if (inst
.error
== NULL
)
5707 inst
.error
= _("bad expression");
5711 /* Do those data_ops which can take a negative immediate constant
5712 by altering the instruction. A bit of a hack really.
5716 by inverting the second operand, and
5719 by negating the second operand. */
5722 negate_data_op (unsigned long * instruction
,
5723 unsigned long value
)
5726 unsigned long negated
, inverted
;
5728 negated
= validate_immediate (-value
);
5729 inverted
= validate_immediate (~value
);
5731 op
= (*instruction
>> DATA_OP_SHIFT
) & 0xf;
5734 /* First negates. */
5735 case OPCODE_SUB
: /* ADD <-> SUB */
5736 new_inst
= OPCODE_ADD
;
5741 new_inst
= OPCODE_SUB
;
5745 case OPCODE_CMP
: /* CMP <-> CMN */
5746 new_inst
= OPCODE_CMN
;
5751 new_inst
= OPCODE_CMP
;
5755 /* Now Inverted ops. */
5756 case OPCODE_MOV
: /* MOV <-> MVN */
5757 new_inst
= OPCODE_MVN
;
5762 new_inst
= OPCODE_MOV
;
5766 case OPCODE_AND
: /* AND <-> BIC */
5767 new_inst
= OPCODE_BIC
;
5772 new_inst
= OPCODE_AND
;
5776 case OPCODE_ADC
: /* ADC <-> SBC */
5777 new_inst
= OPCODE_SBC
;
5782 new_inst
= OPCODE_ADC
;
5786 /* We cannot do anything. */
5791 if (value
== (unsigned) FAIL
)
5794 *instruction
&= OPCODE_MASK
;
5795 *instruction
|= new_inst
<< DATA_OP_SHIFT
;
5800 data_op2 (char ** str
)
5805 skip_whitespace (* str
);
5807 if (reg_required_here (str
, 0) != FAIL
)
5809 if (skip_past_comma (str
) == SUCCESS
)
5810 /* Shift operation on register. */
5811 return decode_shift (str
, NO_SHIFT_RESTRICT
);
5817 /* Immediate expression. */
5818 if (is_immediate_prefix (**str
))
5823 if (my_get_expression (&inst
.reloc
.exp
, str
))
5826 if (inst
.reloc
.exp
.X_add_symbol
)
5828 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
5829 inst
.reloc
.pc_rel
= 0;
5833 if (skip_past_comma (str
) == SUCCESS
)
5835 /* #x, y -- ie explicit rotation by Y. */
5836 if (my_get_expression (&expr
, str
))
5839 if (expr
.X_op
!= O_constant
)
5841 inst
.error
= _("constant expression expected");
5845 /* Rotate must be a multiple of 2. */
5846 if (((unsigned) expr
.X_add_number
) > 30
5847 || (expr
.X_add_number
& 1) != 0
5848 || ((unsigned) inst
.reloc
.exp
.X_add_number
) > 255)
5850 inst
.error
= _("invalid constant");
5853 inst
.instruction
|= INST_IMMEDIATE
;
5854 inst
.instruction
|= inst
.reloc
.exp
.X_add_number
;
5855 inst
.instruction
|= expr
.X_add_number
<< 7;
5859 /* Implicit rotation, select a suitable one. */
5860 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
5864 /* Can't be done. Perhaps the code reads something like
5865 "add Rd, Rn, #-n", where "sub Rd, Rn, #n" would be OK. */
5866 if ((value
= negate_data_op (&inst
.instruction
,
5867 inst
.reloc
.exp
.X_add_number
))
5870 inst
.error
= _("invalid constant");
5875 inst
.instruction
|= value
;
5878 inst
.instruction
|= INST_IMMEDIATE
;
5883 inst
.error
= _("register or shift expression expected");
5889 fp_op2 (char ** str
)
5891 skip_whitespace (* str
);
5893 if (fp_reg_required_here (str
, 0) != FAIL
)
5897 /* Immediate expression. */
5898 if (*((*str
)++) == '#')
5904 skip_whitespace (* str
);
5906 /* First try and match exact strings, this is to guarantee
5907 that some formats will work even for cross assembly. */
5909 for (i
= 0; fp_const
[i
]; i
++)
5911 if (strncmp (*str
, fp_const
[i
], strlen (fp_const
[i
])) == 0)
5915 *str
+= strlen (fp_const
[i
]);
5916 if (is_end_of_line
[(unsigned char) **str
])
5918 inst
.instruction
|= i
+ 8;
5925 /* Just because we didn't get a match doesn't mean that the
5926 constant isn't valid, just that it is in a format that we
5927 don't automatically recognize. Try parsing it with
5928 the standard expression routines. */
5929 if ((i
= my_get_float_expression (str
)) >= 0)
5931 inst
.instruction
|= i
+ 8;
5935 inst
.error
= _("invalid floating point immediate expression");
5939 _("floating point register or immediate expression expected");
5945 do_arit (char * str
)
5947 skip_whitespace (str
);
5949 if (reg_required_here (&str
, 12) == FAIL
5950 || skip_past_comma (&str
) == FAIL
5951 || reg_required_here (&str
, 16) == FAIL
5952 || skip_past_comma (&str
) == FAIL
5953 || data_op2 (&str
) == FAIL
)
5956 inst
.error
= BAD_ARGS
;
5966 /* This is a pseudo-op of the form "adr rd, label" to be converted
5967 into a relative address of the form "add rd, pc, #label-.-8". */
5968 skip_whitespace (str
);
5970 if (reg_required_here (&str
, 12) == FAIL
5971 || skip_past_comma (&str
) == FAIL
5972 || my_get_expression (&inst
.reloc
.exp
, &str
))
5975 inst
.error
= BAD_ARGS
;
5979 /* Frag hacking will turn this into a sub instruction if the offset turns
5980 out to be negative. */
5981 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
5983 inst
.reloc
.exp
.X_add_number
-= 8; /* PC relative adjust. */
5985 inst
.reloc
.pc_rel
= 1;
5991 do_adrl (char * str
)
5993 /* This is a pseudo-op of the form "adrl rd, label" to be converted
5994 into a relative address of the form:
5995 add rd, pc, #low(label-.-8)"
5996 add rd, rd, #high(label-.-8)" */
5998 skip_whitespace (str
);
6000 if (reg_required_here (&str
, 12) == FAIL
6001 || skip_past_comma (&str
) == FAIL
6002 || my_get_expression (&inst
.reloc
.exp
, &str
))
6005 inst
.error
= BAD_ARGS
;
6011 /* Frag hacking will turn this into a sub instruction if the offset turns
6012 out to be negative. */
6013 inst
.reloc
.type
= BFD_RELOC_ARM_ADRL_IMMEDIATE
;
6015 inst
.reloc
.exp
.X_add_number
-= 8; /* PC relative adjust */
6017 inst
.reloc
.pc_rel
= 1;
6018 inst
.size
= INSN_SIZE
* 2;
6024 skip_whitespace (str
);
6026 if (reg_required_here (&str
, 16) == FAIL
)
6029 inst
.error
= BAD_ARGS
;
6033 if (skip_past_comma (&str
) == FAIL
6034 || data_op2 (&str
) == FAIL
)
6037 inst
.error
= BAD_ARGS
;
6047 skip_whitespace (str
);
6049 if (reg_required_here (&str
, 12) == FAIL
)
6052 inst
.error
= BAD_ARGS
;
6056 if (skip_past_comma (&str
) == FAIL
6057 || data_op2 (&str
) == FAIL
)
6060 inst
.error
= BAD_ARGS
;
6068 do_ldst (char * str
)
6074 skip_whitespace (str
);
6076 if ((conflict_reg
= reg_required_here (&str
, 12)) == FAIL
)
6079 inst
.error
= BAD_ARGS
;
6083 if (skip_past_comma (&str
) == FAIL
)
6085 inst
.error
= _("address expected");
6095 skip_whitespace (str
);
6097 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
6100 /* Conflicts can occur on stores as well as loads. */
6101 conflict_reg
= (conflict_reg
== reg
);
6103 skip_whitespace (str
);
6109 if (skip_past_comma (&str
) == SUCCESS
)
6111 /* [Rn],... (post inc) */
6112 if (ldst_extend (&str
) == FAIL
)
6115 as_warn (_("%s register same as write-back base"),
6116 ((inst
.instruction
& LOAD_BIT
)
6117 ? _("destination") : _("source")));
6122 skip_whitespace (str
);
6127 as_warn (_("%s register same as write-back base"),
6128 ((inst
.instruction
& LOAD_BIT
)
6129 ? _("destination") : _("source")));
6131 inst
.instruction
|= WRITE_BACK
;
6134 inst
.instruction
|= INDEX_UP
;
6141 if (skip_past_comma (&str
) == FAIL
)
6143 inst
.error
= _("pre-indexed expression expected");
6148 if (ldst_extend (&str
) == FAIL
)
6151 skip_whitespace (str
);
6155 inst
.error
= _("missing ]");
6159 skip_whitespace (str
);
6164 as_warn (_("%s register same as write-back base"),
6165 ((inst
.instruction
& LOAD_BIT
)
6166 ? _("destination") : _("source")));
6168 inst
.instruction
|= WRITE_BACK
;
6172 else if (*str
== '=')
6174 if ((inst
.instruction
& LOAD_BIT
) == 0)
6176 inst
.error
= _("invalid pseudo operation");
6180 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
6183 skip_whitespace (str
);
6185 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6188 if (inst
.reloc
.exp
.X_op
!= O_constant
6189 && inst
.reloc
.exp
.X_op
!= O_symbol
)
6191 inst
.error
= _("constant expression expected");
6195 if (inst
.reloc
.exp
.X_op
== O_constant
)
6197 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
6201 /* This can be done with a mov instruction. */
6202 inst
.instruction
&= LITERAL_MASK
;
6203 inst
.instruction
|= (INST_IMMEDIATE
6204 | (OPCODE_MOV
<< DATA_OP_SHIFT
));
6205 inst
.instruction
|= value
& 0xfff;
6210 value
= validate_immediate (~inst
.reloc
.exp
.X_add_number
);
6214 /* This can be done with a mvn instruction. */
6215 inst
.instruction
&= LITERAL_MASK
;
6216 inst
.instruction
|= (INST_IMMEDIATE
6217 | (OPCODE_MVN
<< DATA_OP_SHIFT
));
6218 inst
.instruction
|= value
& 0xfff;
6224 /* Insert into literal pool. */
6225 if (add_to_lit_pool () == FAIL
)
6228 inst
.error
= _("literal pool insertion failed");
6232 /* Change the instruction exp to point to the pool. */
6233 inst
.reloc
.type
= BFD_RELOC_ARM_LITERAL
;
6234 inst
.reloc
.pc_rel
= 1;
6235 inst
.instruction
|= (REG_PC
<< 16);
6240 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6243 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM
;
6245 /* PC rel adjust. */
6246 inst
.reloc
.exp
.X_add_number
-= 8;
6248 inst
.reloc
.pc_rel
= 1;
6249 inst
.instruction
|= (REG_PC
<< 16);
6253 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
6258 do_ldstt (char * str
)
6262 skip_whitespace (str
);
6264 if ((conflict_reg
= reg_required_here (& str
, 12)) == FAIL
)
6267 inst
.error
= BAD_ARGS
;
6271 if (skip_past_comma (& str
) == FAIL
)
6273 inst
.error
= _("address expected");
6283 skip_whitespace (str
);
6285 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
6288 /* ldrt/strt always use post-indexed addressing, so if the base is
6289 the same as Rd, we warn. */
6290 if (conflict_reg
== reg
)
6291 as_warn (_("%s register same as write-back base"),
6292 ((inst
.instruction
& LOAD_BIT
)
6293 ? _("destination") : _("source")));
6295 skip_whitespace (str
);
6301 if (skip_past_comma (&str
) == SUCCESS
)
6303 /* [Rn],... (post inc) */
6304 if (ldst_extend (&str
) == FAIL
)
6310 skip_whitespace (str
);
6312 /* Skip a write-back '!'. */
6316 inst
.instruction
|= INDEX_UP
;
6321 inst
.error
= _("post-indexed expression expected");
6327 inst
.error
= _("post-indexed expression expected");
6334 /* Halfword and signed-byte load/store operations. */
6337 do_ldstv4 (char * str
)
6343 skip_whitespace (str
);
6345 if ((conflict_reg
= reg_required_here (& str
, 12)) == FAIL
)
6348 inst
.error
= BAD_ARGS
;
6352 if (skip_past_comma (& str
) == FAIL
)
6354 inst
.error
= _("address expected");
6364 skip_whitespace (str
);
6366 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
6369 /* Conflicts can occur on stores as well as loads. */
6370 conflict_reg
= (conflict_reg
== reg
);
6372 skip_whitespace (str
);
6378 if (skip_past_comma (&str
) == SUCCESS
)
6380 /* [Rn],... (post inc) */
6381 if (ldst_extend_v4 (&str
) == FAIL
)
6384 as_warn (_("%s register same as write-back base"),
6385 ((inst
.instruction
& LOAD_BIT
)
6386 ? _("destination") : _("source")));
6391 inst
.instruction
|= HWOFFSET_IMM
;
6393 skip_whitespace (str
);
6398 as_warn (_("%s register same as write-back base"),
6399 ((inst
.instruction
& LOAD_BIT
)
6400 ? _("destination") : _("source")));
6402 inst
.instruction
|= WRITE_BACK
;
6405 inst
.instruction
|= INDEX_UP
;
6412 if (skip_past_comma (&str
) == FAIL
)
6414 inst
.error
= _("pre-indexed expression expected");
6419 if (ldst_extend_v4 (&str
) == FAIL
)
6422 skip_whitespace (str
);
6426 inst
.error
= _("missing ]");
6430 skip_whitespace (str
);
6435 as_warn (_("%s register same as write-back base"),
6436 ((inst
.instruction
& LOAD_BIT
)
6437 ? _("destination") : _("source")));
6439 inst
.instruction
|= WRITE_BACK
;
6443 else if (*str
== '=')
6445 if ((inst
.instruction
& LOAD_BIT
) == 0)
6447 inst
.error
= _("invalid pseudo operation");
6451 /* XXX Does this work correctly for half-word/byte ops? */
6452 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
6455 skip_whitespace (str
);
6457 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6460 if (inst
.reloc
.exp
.X_op
!= O_constant
6461 && inst
.reloc
.exp
.X_op
!= O_symbol
)
6463 inst
.error
= _("constant expression expected");
6467 if (inst
.reloc
.exp
.X_op
== O_constant
)
6469 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
6473 /* This can be done with a mov instruction. */
6474 inst
.instruction
&= LITERAL_MASK
;
6475 inst
.instruction
|= INST_IMMEDIATE
| (OPCODE_MOV
<< DATA_OP_SHIFT
);
6476 inst
.instruction
|= value
& 0xfff;
6481 value
= validate_immediate (~ inst
.reloc
.exp
.X_add_number
);
6485 /* This can be done with a mvn instruction. */
6486 inst
.instruction
&= LITERAL_MASK
;
6487 inst
.instruction
|= INST_IMMEDIATE
| (OPCODE_MVN
<< DATA_OP_SHIFT
);
6488 inst
.instruction
|= value
& 0xfff;
6494 /* Insert into literal pool. */
6495 if (add_to_lit_pool () == FAIL
)
6498 inst
.error
= _("literal pool insertion failed");
6502 /* Change the instruction exp to point to the pool. */
6503 inst
.instruction
|= HWOFFSET_IMM
;
6504 inst
.reloc
.type
= BFD_RELOC_ARM_HWLITERAL
;
6505 inst
.reloc
.pc_rel
= 1;
6506 inst
.instruction
|= (REG_PC
<< 16);
6511 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6514 inst
.instruction
|= HWOFFSET_IMM
;
6515 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
6517 /* PC rel adjust. */
6518 inst
.reloc
.exp
.X_add_number
-= 8;
6520 inst
.reloc
.pc_rel
= 1;
6521 inst
.instruction
|= (REG_PC
<< 16);
6525 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
6530 reg_list (char ** strp
)
6532 char * str
= * strp
;
6536 /* We come back here if we get ranges concatenated by '+' or '|'. */
6551 skip_whitespace (str
);
6553 if ((reg
= reg_required_here (& str
, -1)) == FAIL
)
6562 inst
.error
= _("bad range in register list");
6566 for (i
= cur_reg
+ 1; i
< reg
; i
++)
6568 if (range
& (1 << i
))
6570 (_("Warning: duplicated register (r%d) in register list"),
6578 if (range
& (1 << reg
))
6579 as_tsktsk (_("Warning: duplicated register (r%d) in register list"),
6581 else if (reg
<= cur_reg
)
6582 as_tsktsk (_("Warning: register range not in ascending order"));
6587 while (skip_past_comma (&str
) != FAIL
6588 || (in_range
= 1, *str
++ == '-'));
6590 skip_whitespace (str
);
6594 inst
.error
= _("missing `}'");
6602 if (my_get_expression (&expr
, &str
))
6605 if (expr
.X_op
== O_constant
)
6607 if (expr
.X_add_number
6608 != (expr
.X_add_number
& 0x0000ffff))
6610 inst
.error
= _("invalid register mask");
6614 if ((range
& expr
.X_add_number
) != 0)
6616 int regno
= range
& expr
.X_add_number
;
6619 regno
= (1 << regno
) - 1;
6621 (_("Warning: duplicated register (r%d) in register list"),
6625 range
|= expr
.X_add_number
;
6629 if (inst
.reloc
.type
!= 0)
6631 inst
.error
= _("expression too complex");
6635 memcpy (&inst
.reloc
.exp
, &expr
, sizeof (expressionS
));
6636 inst
.reloc
.type
= BFD_RELOC_ARM_MULTI
;
6637 inst
.reloc
.pc_rel
= 0;
6641 skip_whitespace (str
);
6643 if (*str
== '|' || *str
== '+')
6649 while (another_range
);
6656 do_ldmstm (char * str
)
6661 skip_whitespace (str
);
6663 if ((base_reg
= reg_required_here (&str
, 16)) == FAIL
)
6666 if (base_reg
== REG_PC
)
6668 inst
.error
= _("r15 not allowed as base register");
6672 skip_whitespace (str
);
6676 inst
.instruction
|= WRITE_BACK
;
6680 if (skip_past_comma (&str
) == FAIL
6681 || (range
= reg_list (&str
)) == FAIL
)
6684 inst
.error
= BAD_ARGS
;
6691 inst
.instruction
|= LDM_TYPE_2_OR_3
;
6694 if (inst
.instruction
& WRITE_BACK
)
6696 /* Check for unpredictable uses of writeback. */
6697 if (inst
.instruction
& LOAD_BIT
)
6699 /* Not allowed in LDM type 2. */
6700 if ((inst
.instruction
& LDM_TYPE_2_OR_3
)
6701 && ((range
& (1 << REG_PC
)) == 0))
6702 as_warn (_("writeback of base register is UNPREDICTABLE"));
6703 /* Only allowed if base reg not in list for other types. */
6704 else if (range
& (1 << base_reg
))
6705 as_warn (_("writeback of base register when in register list is UNPREDICTABLE"));
6709 /* Not allowed for type 2. */
6710 if (inst
.instruction
& LDM_TYPE_2_OR_3
)
6711 as_warn (_("writeback of base register is UNPREDICTABLE"));
6712 /* Only allowed if base reg not in list, or first in list. */
6713 else if ((range
& (1 << base_reg
))
6714 && (range
& ((1 << base_reg
) - 1)))
6715 as_warn (_("if writeback register is in list, it must be the lowest reg in the list"));
6719 inst
.instruction
|= range
;
6726 skip_whitespace (str
);
6728 /* Allow optional leading '#'. */
6729 if (is_immediate_prefix (*str
))
6732 if (my_get_expression (& inst
.reloc
.exp
, & str
))
6735 inst
.reloc
.type
= BFD_RELOC_ARM_SMI
;
6736 inst
.reloc
.pc_rel
= 0;
6743 skip_whitespace (str
);
6745 /* Allow optional leading '#'. */
6746 if (is_immediate_prefix (*str
))
6749 if (my_get_expression (& inst
.reloc
.exp
, & str
))
6752 inst
.reloc
.type
= BFD_RELOC_ARM_SWI
;
6753 inst
.reloc
.pc_rel
= 0;
6758 do_swap (char * str
)
6762 skip_whitespace (str
);
6764 if ((reg
= reg_required_here (&str
, 12)) == FAIL
)
6769 inst
.error
= _("r15 not allowed in swap");
6773 if (skip_past_comma (&str
) == FAIL
6774 || (reg
= reg_required_here (&str
, 0)) == FAIL
)
6777 inst
.error
= BAD_ARGS
;
6783 inst
.error
= _("r15 not allowed in swap");
6787 if (skip_past_comma (&str
) == FAIL
6790 inst
.error
= BAD_ARGS
;
6794 skip_whitespace (str
);
6796 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
6801 inst
.error
= BAD_PC
;
6805 skip_whitespace (str
);
6809 inst
.error
= _("missing ]");
6817 do_branch (char * str
)
6819 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6826 /* ScottB: February 5, 1998 - Check to see of PLT32 reloc
6827 required for the instruction. */
6829 /* arm_parse_reloc () works on input_line_pointer.
6830 We actually want to parse the operands to the branch instruction
6831 passed in 'str'. Save the input pointer and restore it later. */
6832 save_in
= input_line_pointer
;
6833 input_line_pointer
= str
;
6834 if (inst
.reloc
.exp
.X_op
== O_symbol
6836 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32
)
6838 inst
.reloc
.type
= BFD_RELOC_ARM_PLT32
;
6839 inst
.reloc
.pc_rel
= 0;
6840 /* Modify str to point to after parsed operands, otherwise
6841 end_of_line() will complain about the (PLT) left in str. */
6842 str
= input_line_pointer
;
6846 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BRANCH
;
6847 inst
.reloc
.pc_rel
= 1;
6849 input_line_pointer
= save_in
;
6852 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BRANCH
;
6853 inst
.reloc
.pc_rel
= 1;
6854 #endif /* OBJ_ELF */
6862 /* Co-processor data operation.
6863 Format: CDP{cond} CP#,<expr>,CRd,CRn,CRm{,<expr>} */
6864 skip_whitespace (str
);
6866 if (co_proc_number (&str
) == FAIL
)
6869 inst
.error
= BAD_ARGS
;
6873 if (skip_past_comma (&str
) == FAIL
6874 || cp_opc_expr (&str
, 20,4) == FAIL
)
6877 inst
.error
= BAD_ARGS
;
6881 if (skip_past_comma (&str
) == FAIL
6882 || cp_reg_required_here (&str
, 12) == FAIL
)
6885 inst
.error
= BAD_ARGS
;
6889 if (skip_past_comma (&str
) == FAIL
6890 || cp_reg_required_here (&str
, 16) == FAIL
)
6893 inst
.error
= BAD_ARGS
;
6897 if (skip_past_comma (&str
) == FAIL
6898 || cp_reg_required_here (&str
, 0) == FAIL
)
6901 inst
.error
= BAD_ARGS
;
6905 if (skip_past_comma (&str
) == SUCCESS
)
6907 if (cp_opc_expr (&str
, 5, 3) == FAIL
)
6910 inst
.error
= BAD_ARGS
;
6919 do_lstc (char * str
)
6921 /* Co-processor register load/store.
6922 Format: <LDC|STC{cond}[L] CP#,CRd,<address> */
6924 skip_whitespace (str
);
6926 if (co_proc_number (&str
) == FAIL
)
6929 inst
.error
= BAD_ARGS
;
6933 if (skip_past_comma (&str
) == FAIL
6934 || cp_reg_required_here (&str
, 12) == FAIL
)
6937 inst
.error
= BAD_ARGS
;
6941 if (skip_past_comma (&str
) == FAIL
6942 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
6945 inst
.error
= BAD_ARGS
;
6953 do_co_reg (char * str
)
6955 /* Co-processor register transfer.
6956 Format: <MCR|MRC>{cond} CP#,<expr1>,Rd,CRn,CRm{,<expr2>} */
6958 skip_whitespace (str
);
6960 if (co_proc_number (&str
) == FAIL
)
6963 inst
.error
= BAD_ARGS
;
6967 if (skip_past_comma (&str
) == FAIL
6968 || cp_opc_expr (&str
, 21, 3) == FAIL
)
6971 inst
.error
= BAD_ARGS
;
6975 if (skip_past_comma (&str
) == FAIL
6976 || reg_required_here (&str
, 12) == FAIL
)
6979 inst
.error
= BAD_ARGS
;
6983 if (skip_past_comma (&str
) == FAIL
6984 || cp_reg_required_here (&str
, 16) == FAIL
)
6987 inst
.error
= BAD_ARGS
;
6991 if (skip_past_comma (&str
) == FAIL
6992 || cp_reg_required_here (&str
, 0) == FAIL
)
6995 inst
.error
= BAD_ARGS
;
6999 if (skip_past_comma (&str
) == SUCCESS
)
7001 if (cp_opc_expr (&str
, 5, 3) == FAIL
)
7004 inst
.error
= BAD_ARGS
;
7013 do_fpa_ctrl (char * str
)
7015 /* FP control registers.
7016 Format: <WFS|RFS|WFC|RFC>{cond} Rn */
7018 skip_whitespace (str
);
7020 if (reg_required_here (&str
, 12) == FAIL
)
7023 inst
.error
= BAD_ARGS
;
7031 do_fpa_ldst (char * str
)
7033 skip_whitespace (str
);
7035 if (fp_reg_required_here (&str
, 12) == FAIL
)
7038 inst
.error
= BAD_ARGS
;
7042 if (skip_past_comma (&str
) == FAIL
7043 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
7046 inst
.error
= BAD_ARGS
;
7054 do_fpa_ldmstm (char * str
)
7058 skip_whitespace (str
);
7060 if (fp_reg_required_here (&str
, 12) == FAIL
)
7063 inst
.error
= BAD_ARGS
;
7067 /* Get Number of registers to transfer. */
7068 if (skip_past_comma (&str
) == FAIL
7069 || my_get_expression (&inst
.reloc
.exp
, &str
))
7072 inst
.error
= _("constant expression expected");
7076 if (inst
.reloc
.exp
.X_op
!= O_constant
)
7078 inst
.error
= _("constant value required for number of registers");
7082 num_regs
= inst
.reloc
.exp
.X_add_number
;
7084 if (num_regs
< 1 || num_regs
> 4)
7086 inst
.error
= _("number of registers must be in the range [1:4]");
7093 inst
.instruction
|= CP_T_X
;
7096 inst
.instruction
|= CP_T_Y
;
7099 inst
.instruction
|= CP_T_Y
| CP_T_X
;
7107 if (inst
.instruction
& (CP_T_Pre
| CP_T_UD
)) /* ea/fd format. */
7113 /* The instruction specified "ea" or "fd", so we can only accept
7114 [Rn]{!}. The instruction does not really support stacking or
7115 unstacking, so we have to emulate these by setting appropriate
7116 bits and offsets. */
7117 if (skip_past_comma (&str
) == FAIL
7121 inst
.error
= BAD_ARGS
;
7126 skip_whitespace (str
);
7128 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
7131 skip_whitespace (str
);
7135 inst
.error
= BAD_ARGS
;
7147 _("r15 not allowed as base register with write-back");
7154 if (inst
.instruction
& CP_T_Pre
)
7156 /* Pre-decrement. */
7157 offset
= 3 * num_regs
;
7159 inst
.instruction
|= CP_T_WB
;
7163 /* Post-increment. */
7166 inst
.instruction
|= CP_T_WB
;
7167 offset
= 3 * num_regs
;
7171 /* No write-back, so convert this into a standard pre-increment
7172 instruction -- aesthetically more pleasing. */
7173 inst
.instruction
|= CP_T_Pre
| CP_T_UD
;
7178 inst
.instruction
|= offset
;
7180 else if (skip_past_comma (&str
) == FAIL
7181 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
7184 inst
.error
= BAD_ARGS
;
7192 do_fpa_dyadic (char * str
)
7194 skip_whitespace (str
);
7196 if (fp_reg_required_here (&str
, 12) == FAIL
)
7199 inst
.error
= BAD_ARGS
;
7203 if (skip_past_comma (&str
) == FAIL
7204 || fp_reg_required_here (&str
, 16) == FAIL
)
7207 inst
.error
= BAD_ARGS
;
7211 if (skip_past_comma (&str
) == FAIL
7212 || fp_op2 (&str
) == FAIL
)
7215 inst
.error
= BAD_ARGS
;
7223 do_fpa_monadic (char * str
)
7225 skip_whitespace (str
);
7227 if (fp_reg_required_here (&str
, 12) == FAIL
)
7230 inst
.error
= BAD_ARGS
;
7234 if (skip_past_comma (&str
) == FAIL
7235 || fp_op2 (&str
) == FAIL
)
7238 inst
.error
= BAD_ARGS
;
7246 do_fpa_cmp (char * str
)
7248 skip_whitespace (str
);
7250 if (fp_reg_required_here (&str
, 16) == FAIL
)
7253 inst
.error
= BAD_ARGS
;
7257 if (skip_past_comma (&str
) == FAIL
7258 || fp_op2 (&str
) == FAIL
)
7261 inst
.error
= BAD_ARGS
;
7269 do_fpa_from_reg (char * str
)
7271 skip_whitespace (str
);
7273 if (fp_reg_required_here (&str
, 16) == FAIL
)
7276 inst
.error
= BAD_ARGS
;
7280 if (skip_past_comma (&str
) == FAIL
7281 || reg_required_here (&str
, 12) == FAIL
)
7284 inst
.error
= BAD_ARGS
;
7292 do_fpa_to_reg (char * str
)
7294 skip_whitespace (str
);
7296 if (reg_required_here (&str
, 12) == FAIL
)
7299 if (skip_past_comma (&str
) == FAIL
7300 || fp_reg_required_here (&str
, 0) == FAIL
)
7303 inst
.error
= BAD_ARGS
;
7310 /* Encode a VFP SP register number. */
7313 vfp_sp_encode_reg (int reg
, enum vfp_sp_reg_pos pos
)
7318 inst
.instruction
|= ((reg
>> 1) << 12) | ((reg
& 1) << 22);
7322 inst
.instruction
|= ((reg
>> 1) << 16) | ((reg
& 1) << 7);
7326 inst
.instruction
|= ((reg
>> 1) << 0) | ((reg
& 1) << 5);
7335 vfp_sp_reg_required_here (char ** str
,
7336 enum vfp_sp_reg_pos pos
)
7339 char * start
= *str
;
7341 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_SN
].htab
)) != FAIL
)
7343 vfp_sp_encode_reg (reg
, pos
);
7347 /* In the few cases where we might be able to accept something else
7348 this error can be overridden. */
7349 inst
.error
= _(all_reg_maps
[REG_TYPE_SN
].expected
);
7351 /* Restore the start point. */
7357 vfp_dp_reg_required_here (char ** str
,
7358 enum vfp_dp_reg_pos pos
)
7361 char * start
= *str
;
7363 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_DN
].htab
)) != FAIL
)
7368 inst
.instruction
|= reg
<< 12;
7372 inst
.instruction
|= reg
<< 16;
7376 inst
.instruction
|= reg
<< 0;
7385 /* In the few cases where we might be able to accept something else
7386 this error can be overridden. */
7387 inst
.error
= _(all_reg_maps
[REG_TYPE_DN
].expected
);
7389 /* Restore the start point. */
7395 do_vfp_sp_monadic (char * str
)
7397 skip_whitespace (str
);
7399 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
7402 if (skip_past_comma (&str
) == FAIL
7403 || vfp_sp_reg_required_here (&str
, VFP_REG_Sm
) == FAIL
)
7406 inst
.error
= BAD_ARGS
;
7414 do_vfp_dp_monadic (char * str
)
7416 skip_whitespace (str
);
7418 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
7421 if (skip_past_comma (&str
) == FAIL
7422 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
7425 inst
.error
= BAD_ARGS
;
7433 do_vfp_sp_dyadic (char * str
)
7435 skip_whitespace (str
);
7437 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
7440 if (skip_past_comma (&str
) == FAIL
7441 || vfp_sp_reg_required_here (&str
, VFP_REG_Sn
) == FAIL
7442 || skip_past_comma (&str
) == FAIL
7443 || vfp_sp_reg_required_here (&str
, VFP_REG_Sm
) == FAIL
)
7446 inst
.error
= BAD_ARGS
;
7454 do_vfp_dp_dyadic (char * str
)
7456 skip_whitespace (str
);
7458 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
7461 if (skip_past_comma (&str
) == FAIL
7462 || vfp_dp_reg_required_here (&str
, VFP_REG_Dn
) == FAIL
7463 || skip_past_comma (&str
) == FAIL
7464 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
7467 inst
.error
= BAD_ARGS
;
7475 do_vfp_reg_from_sp (char * str
)
7477 skip_whitespace (str
);
7479 if (reg_required_here (&str
, 12) == FAIL
)
7482 if (skip_past_comma (&str
) == FAIL
7483 || vfp_sp_reg_required_here (&str
, VFP_REG_Sn
) == FAIL
)
7486 inst
.error
= BAD_ARGS
;
7493 /* Parse a VFP register list. If the string is invalid return FAIL.
7494 Otherwise return the number of registers, and set PBASE to the first
7495 register. Double precision registers are matched if DP is nonzero. */
7498 vfp_parse_reg_list (char **str
, int *pbase
, int dp
)
7506 unsigned long mask
= 0;
7513 skip_whitespace (*str
);
7517 regtype
= REG_TYPE_DN
;
7522 regtype
= REG_TYPE_SN
;
7526 base_reg
= max_regs
;
7530 new_base
= arm_reg_parse (str
, all_reg_maps
[regtype
].htab
);
7531 if (new_base
== FAIL
)
7533 inst
.error
= _(all_reg_maps
[regtype
].expected
);
7537 if (new_base
< base_reg
)
7538 base_reg
= new_base
;
7540 if (mask
& (1 << new_base
))
7542 inst
.error
= _("invalid register list");
7546 if ((mask
>> new_base
) != 0 && ! warned
)
7548 as_tsktsk (_("register list not in ascending order"));
7552 mask
|= 1 << new_base
;
7555 skip_whitespace (*str
);
7557 if (**str
== '-') /* We have the start of a range expression */
7564 = arm_reg_parse (str
, all_reg_maps
[regtype
].htab
))
7567 inst
.error
= _(all_reg_maps
[regtype
].expected
);
7571 if (high_range
<= new_base
)
7573 inst
.error
= _("register range not in ascending order");
7577 for (new_base
++; new_base
<= high_range
; new_base
++)
7579 if (mask
& (1 << new_base
))
7581 inst
.error
= _("invalid register list");
7585 mask
|= 1 << new_base
;
7590 while (skip_past_comma (str
) != FAIL
);
7594 /* Sanity check -- should have raised a parse error above. */
7595 if (count
== 0 || count
> max_regs
)
7600 /* Final test -- the registers must be consecutive. */
7602 for (i
= 0; i
< count
; i
++)
7604 if ((mask
& (1u << i
)) == 0)
7606 inst
.error
= _("non-contiguous register range");
7615 do_vfp_reg2_from_sp2 (char * str
)
7619 skip_whitespace (str
);
7621 if (reg_required_here (&str
, 12) == FAIL
7622 || skip_past_comma (&str
) == FAIL
7623 || reg_required_here (&str
, 16) == FAIL
7624 || skip_past_comma (&str
) == FAIL
)
7627 inst
.error
= BAD_ARGS
;
7631 /* We require exactly two consecutive SP registers. */
7632 if (vfp_parse_reg_list (&str
, ®
, 0) != 2)
7635 inst
.error
= _("only two consecutive VFP SP registers allowed here");
7637 vfp_sp_encode_reg (reg
, VFP_REG_Sm
);
7643 do_vfp_sp_from_reg (char * str
)
7645 skip_whitespace (str
);
7647 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sn
) == FAIL
)
7650 if (skip_past_comma (&str
) == FAIL
7651 || reg_required_here (&str
, 12) == FAIL
)
7654 inst
.error
= BAD_ARGS
;
7662 do_vfp_sp2_from_reg2 (char * str
)
7666 skip_whitespace (str
);
7668 /* We require exactly two consecutive SP registers. */
7669 if (vfp_parse_reg_list (&str
, ®
, 0) != 2)
7672 inst
.error
= _("only two consecutive VFP SP registers allowed here");
7674 vfp_sp_encode_reg (reg
, VFP_REG_Sm
);
7676 if (skip_past_comma (&str
) == FAIL
7677 || reg_required_here (&str
, 12) == FAIL
7678 || skip_past_comma (&str
) == FAIL
7679 || reg_required_here (&str
, 16) == FAIL
)
7682 inst
.error
= BAD_ARGS
;
7690 do_vfp_reg_from_dp (char * str
)
7692 skip_whitespace (str
);
7694 if (reg_required_here (&str
, 12) == FAIL
)
7697 if (skip_past_comma (&str
) == FAIL
7698 || vfp_dp_reg_required_here (&str
, VFP_REG_Dn
) == FAIL
)
7701 inst
.error
= BAD_ARGS
;
7709 do_vfp_reg2_from_dp (char * str
)
7711 skip_whitespace (str
);
7713 if (reg_required_here (&str
, 12) == FAIL
)
7716 if (skip_past_comma (&str
) == FAIL
7717 || reg_required_here (&str
, 16) == FAIL
7718 || skip_past_comma (&str
) == FAIL
7719 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
7722 inst
.error
= BAD_ARGS
;
7730 do_vfp_dp_from_reg (char * str
)
7732 skip_whitespace (str
);
7734 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dn
) == FAIL
)
7737 if (skip_past_comma (&str
) == FAIL
7738 || reg_required_here (&str
, 12) == FAIL
)
7741 inst
.error
= BAD_ARGS
;
7749 do_vfp_dp_from_reg2 (char * str
)
7751 skip_whitespace (str
);
7753 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
7756 if (skip_past_comma (&str
) == FAIL
7757 || reg_required_here (&str
, 12) == FAIL
7758 || skip_past_comma (&str
) == FAIL
7759 || reg_required_here (&str
, 16) == FAIL
)
7762 inst
.error
= BAD_ARGS
;
7769 static const struct vfp_reg
*
7770 vfp_psr_parse (char ** str
)
7775 const struct vfp_reg
*vreg
;
7779 /* Find the end of the current token. */
7784 while (ISALPHA (c
));
7789 for (vreg
= vfp_regs
+ 0;
7790 vreg
< vfp_regs
+ sizeof (vfp_regs
) / sizeof (struct vfp_reg
);
7793 if (streq (start
, vreg
->name
))
7806 vfp_psr_required_here (char ** str
)
7809 const struct vfp_reg
*vreg
;
7811 vreg
= vfp_psr_parse (str
);
7815 inst
.instruction
|= vreg
->regno
;
7819 inst
.error
= _("VFP system register expected");
7826 do_vfp_reg_from_ctrl (char * str
)
7828 skip_whitespace (str
);
7830 if (reg_required_here (&str
, 12) == FAIL
)
7833 if (skip_past_comma (&str
) == FAIL
7834 || vfp_psr_required_here (&str
) == FAIL
)
7837 inst
.error
= BAD_ARGS
;
7845 do_vfp_ctrl_from_reg (char * str
)
7847 skip_whitespace (str
);
7849 if (vfp_psr_required_here (&str
) == FAIL
)
7852 if (skip_past_comma (&str
) == FAIL
7853 || reg_required_here (&str
, 12) == FAIL
)
7856 inst
.error
= BAD_ARGS
;
7864 do_vfp_sp_ldst (char * str
)
7866 skip_whitespace (str
);
7868 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
7871 inst
.error
= BAD_ARGS
;
7875 if (skip_past_comma (&str
) == FAIL
7876 || cp_address_required_here (&str
, CP_NO_WB
) == FAIL
)
7879 inst
.error
= BAD_ARGS
;
7887 do_vfp_dp_ldst (char * str
)
7889 skip_whitespace (str
);
7891 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
7894 inst
.error
= BAD_ARGS
;
7898 if (skip_past_comma (&str
) == FAIL
7899 || cp_address_required_here (&str
, CP_NO_WB
) == FAIL
)
7902 inst
.error
= BAD_ARGS
;
7911 vfp_sp_ldstm (char * str
, enum vfp_ldstm_type ldstm_type
)
7916 skip_whitespace (str
);
7918 if (reg_required_here (&str
, 16) == FAIL
)
7921 skip_whitespace (str
);
7925 inst
.instruction
|= WRITE_BACK
;
7928 else if (ldstm_type
!= VFP_LDSTMIA
)
7930 inst
.error
= _("this addressing mode requires base-register writeback");
7934 if (skip_past_comma (&str
) == FAIL
7935 || (count
= vfp_parse_reg_list (&str
, ®
, 0)) == FAIL
)
7938 inst
.error
= BAD_ARGS
;
7941 vfp_sp_encode_reg (reg
, VFP_REG_Sd
);
7943 inst
.instruction
|= count
;
7948 vfp_dp_ldstm (char * str
, enum vfp_ldstm_type ldstm_type
)
7953 skip_whitespace (str
);
7955 if (reg_required_here (&str
, 16) == FAIL
)
7958 skip_whitespace (str
);
7962 inst
.instruction
|= WRITE_BACK
;
7965 else if (ldstm_type
!= VFP_LDSTMIA
&& ldstm_type
!= VFP_LDSTMIAX
)
7967 inst
.error
= _("this addressing mode requires base-register writeback");
7971 if (skip_past_comma (&str
) == FAIL
7972 || (count
= vfp_parse_reg_list (&str
, ®
, 1)) == FAIL
)
7975 inst
.error
= BAD_ARGS
;
7980 if (ldstm_type
== VFP_LDSTMIAX
|| ldstm_type
== VFP_LDSTMDBX
)
7983 inst
.instruction
|= (reg
<< 12) | count
;
7988 do_vfp_sp_ldstmia (char * str
)
7990 vfp_sp_ldstm (str
, VFP_LDSTMIA
);
7994 do_vfp_sp_ldstmdb (char * str
)
7996 vfp_sp_ldstm (str
, VFP_LDSTMDB
);
8000 do_vfp_dp_ldstmia (char * str
)
8002 vfp_dp_ldstm (str
, VFP_LDSTMIA
);
8006 do_vfp_dp_ldstmdb (char * str
)
8008 vfp_dp_ldstm (str
, VFP_LDSTMDB
);
8012 do_vfp_xp_ldstmia (char *str
)
8014 vfp_dp_ldstm (str
, VFP_LDSTMIAX
);
8018 do_vfp_xp_ldstmdb (char * str
)
8020 vfp_dp_ldstm (str
, VFP_LDSTMDBX
);
8024 do_vfp_sp_compare_z (char * str
)
8026 skip_whitespace (str
);
8028 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
8031 inst
.error
= BAD_ARGS
;
8039 do_vfp_dp_compare_z (char * str
)
8041 skip_whitespace (str
);
8043 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
8046 inst
.error
= BAD_ARGS
;
8054 do_vfp_dp_sp_cvt (char * str
)
8056 skip_whitespace (str
);
8058 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
8061 if (skip_past_comma (&str
) == FAIL
8062 || vfp_sp_reg_required_here (&str
, VFP_REG_Sm
) == FAIL
)
8065 inst
.error
= BAD_ARGS
;
8073 do_vfp_sp_dp_cvt (char * str
)
8075 skip_whitespace (str
);
8077 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
8080 if (skip_past_comma (&str
) == FAIL
8081 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
8084 inst
.error
= BAD_ARGS
;
8091 /* Thumb specific routines. */
8093 /* Parse an add or subtract instruction, SUBTRACT is non-zero if the opcode
8097 thumb_add_sub (char * str
, int subtract
)
8099 int Rd
, Rs
, Rn
= FAIL
;
8101 skip_whitespace (str
);
8103 if ((Rd
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
8104 || skip_past_comma (&str
) == FAIL
)
8107 inst
.error
= BAD_ARGS
;
8111 if (is_immediate_prefix (*str
))
8115 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8120 if ((Rs
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
8123 if (skip_past_comma (&str
) == FAIL
)
8125 /* Two operand format, shuffle the registers
8126 and pretend there are 3. */
8130 else if (is_immediate_prefix (*str
))
8133 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8136 else if ((Rn
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
8140 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
8141 for the latter case, EXPR contains the immediate that was found. */
8144 /* All register format. */
8145 if (Rd
> 7 || Rs
> 7 || Rn
> 7)
8149 inst
.error
= _("dest and source1 must be the same register");
8153 /* Can't do this for SUB. */
8156 inst
.error
= _("subtract valid only on lo regs");
8160 inst
.instruction
= (T_OPCODE_ADD_HI
8161 | (Rd
> 7 ? THUMB_H1
: 0)
8162 | (Rn
> 7 ? THUMB_H2
: 0));
8163 inst
.instruction
|= (Rd
& 7) | ((Rn
& 7) << 3);
8167 inst
.instruction
= subtract
? T_OPCODE_SUB_R3
: T_OPCODE_ADD_R3
;
8168 inst
.instruction
|= Rd
| (Rs
<< 3) | (Rn
<< 6);
8173 /* Immediate expression, now things start to get nasty. */
8175 /* First deal with HI regs, only very restricted cases allowed:
8176 Adjusting SP, and using PC or SP to get an address. */
8177 if ((Rd
> 7 && (Rd
!= REG_SP
|| Rs
!= REG_SP
))
8178 || (Rs
> 7 && Rs
!= REG_SP
&& Rs
!= REG_PC
))
8180 inst
.error
= _("invalid Hi register with immediate");
8184 if (inst
.reloc
.exp
.X_op
!= O_constant
)
8186 /* Value isn't known yet, all we can do is store all the fragments
8187 we know about in the instruction and let the reloc hacking
8189 inst
.instruction
= (subtract
? 0x8000 : 0) | (Rd
<< 4) | Rs
;
8190 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_ADD
;
8194 int offset
= inst
.reloc
.exp
.X_add_number
;
8204 /* Quick check, in case offset is MIN_INT. */
8207 inst
.error
= _("immediate value out of range");
8211 /* Note - you cannot convert a subtract of 0 into an
8212 add of 0 because the carry flag is set differently. */
8213 else if (offset
> 0)
8218 if (offset
& ~0x1fc)
8220 inst
.error
= _("invalid immediate value for stack adjust");
8223 inst
.instruction
= subtract
? T_OPCODE_SUB_ST
: T_OPCODE_ADD_ST
;
8224 inst
.instruction
|= offset
>> 2;
8226 else if (Rs
== REG_PC
|| Rs
== REG_SP
)
8229 || (offset
& ~0x3fc))
8231 inst
.error
= _("invalid immediate for address calculation");
8234 inst
.instruction
= (Rs
== REG_PC
? T_OPCODE_ADD_PC
8236 inst
.instruction
|= (Rd
<< 8) | (offset
>> 2);
8242 inst
.error
= _("immediate value out of range");
8245 inst
.instruction
= subtract
? T_OPCODE_SUB_I8
: T_OPCODE_ADD_I8
;
8246 inst
.instruction
|= (Rd
<< 8) | offset
;
8252 inst
.error
= _("immediate value out of range");
8255 inst
.instruction
= subtract
? T_OPCODE_SUB_I3
: T_OPCODE_ADD_I3
;
8256 inst
.instruction
|= Rd
| (Rs
<< 3) | (offset
<< 6);
8265 thumb_shift (char * str
, int shift
)
8267 int Rd
, Rs
, Rn
= FAIL
;
8269 skip_whitespace (str
);
8271 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
8272 || skip_past_comma (&str
) == FAIL
)
8275 inst
.error
= BAD_ARGS
;
8279 if (is_immediate_prefix (*str
))
8281 /* Two operand immediate format, set Rs to Rd. */
8284 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8289 if ((Rs
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
8292 if (skip_past_comma (&str
) == FAIL
)
8294 /* Two operand format, shuffle the registers
8295 and pretend there are 3. */
8299 else if (is_immediate_prefix (*str
))
8302 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8305 else if ((Rn
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
8309 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
8310 for the latter case, EXPR contains the immediate that was found. */
8316 inst
.error
= _("source1 and dest must be same register");
8322 case THUMB_ASR
: inst
.instruction
= T_OPCODE_ASR_R
; break;
8323 case THUMB_LSL
: inst
.instruction
= T_OPCODE_LSL_R
; break;
8324 case THUMB_LSR
: inst
.instruction
= T_OPCODE_LSR_R
; break;
8327 inst
.instruction
|= Rd
| (Rn
<< 3);
8333 case THUMB_ASR
: inst
.instruction
= T_OPCODE_ASR_I
; break;
8334 case THUMB_LSL
: inst
.instruction
= T_OPCODE_LSL_I
; break;
8335 case THUMB_LSR
: inst
.instruction
= T_OPCODE_LSR_I
; break;
8338 if (inst
.reloc
.exp
.X_op
!= O_constant
)
8340 /* Value isn't known yet, create a dummy reloc and let reloc
8341 hacking fix it up. */
8342 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_SHIFT
;
8346 unsigned shift_value
= inst
.reloc
.exp
.X_add_number
;
8348 if (shift_value
> 32 || (shift_value
== 32 && shift
== THUMB_LSL
))
8350 inst
.error
= _("invalid immediate for shift");
8354 /* Shifts of zero are handled by converting to LSL. */
8355 if (shift_value
== 0)
8356 inst
.instruction
= T_OPCODE_LSL_I
;
8358 /* Shifts of 32 are encoded as a shift of zero. */
8359 if (shift_value
== 32)
8362 inst
.instruction
|= shift_value
<< 6;
8365 inst
.instruction
|= Rd
| (Rs
<< 3);
8372 thumb_load_store (char * str
, int load_store
, int size
)
8374 int Rd
, Rb
, Ro
= FAIL
;
8376 skip_whitespace (str
);
8378 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
8379 || skip_past_comma (&str
) == FAIL
)
8382 inst
.error
= BAD_ARGS
;
8389 if ((Rb
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
8392 if (skip_past_comma (&str
) != FAIL
)
8394 if (is_immediate_prefix (*str
))
8397 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8400 else if ((Ro
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
8405 inst
.reloc
.exp
.X_op
= O_constant
;
8406 inst
.reloc
.exp
.X_add_number
= 0;
8411 inst
.error
= _("expected ']'");
8416 else if (*str
== '=')
8418 if (load_store
!= THUMB_LOAD
)
8420 inst
.error
= _("invalid pseudo operation");
8424 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
8427 skip_whitespace (str
);
8429 if (my_get_expression (& inst
.reloc
.exp
, & str
))
8434 if ( inst
.reloc
.exp
.X_op
!= O_constant
8435 && inst
.reloc
.exp
.X_op
!= O_symbol
)
8437 inst
.error
= "Constant expression expected";
8441 if (inst
.reloc
.exp
.X_op
== O_constant
8442 && ((inst
.reloc
.exp
.X_add_number
& ~0xFF) == 0))
8444 /* This can be done with a mov instruction. */
8446 inst
.instruction
= T_OPCODE_MOV_I8
| (Rd
<< 8);
8447 inst
.instruction
|= inst
.reloc
.exp
.X_add_number
;
8451 /* Insert into literal pool. */
8452 if (add_to_lit_pool () == FAIL
)
8455 inst
.error
= "literal pool insertion failed";
8459 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
8460 inst
.reloc
.pc_rel
= 1;
8461 inst
.instruction
= T_OPCODE_LDR_PC
| (Rd
<< 8);
8462 /* Adjust ARM pipeline offset to Thumb. */
8463 inst
.reloc
.exp
.X_add_number
+= 4;
8469 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8472 inst
.instruction
= T_OPCODE_LDR_PC
| (Rd
<< 8);
8473 inst
.reloc
.pc_rel
= 1;
8474 inst
.reloc
.exp
.X_add_number
-= 4; /* Pipeline offset. */
8475 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
8480 if (Rb
== REG_PC
|| Rb
== REG_SP
)
8482 if (size
!= THUMB_WORD
)
8484 inst
.error
= _("byte or halfword not valid for base register");
8487 else if (Rb
== REG_PC
&& load_store
!= THUMB_LOAD
)
8489 inst
.error
= _("r15 based store not allowed");
8492 else if (Ro
!= FAIL
)
8494 inst
.error
= _("invalid base register for register offset");
8499 inst
.instruction
= T_OPCODE_LDR_PC
;
8500 else if (load_store
== THUMB_LOAD
)
8501 inst
.instruction
= T_OPCODE_LDR_SP
;
8503 inst
.instruction
= T_OPCODE_STR_SP
;
8505 inst
.instruction
|= Rd
<< 8;
8506 if (inst
.reloc
.exp
.X_op
== O_constant
)
8508 unsigned offset
= inst
.reloc
.exp
.X_add_number
;
8510 if (offset
& ~0x3fc)
8512 inst
.error
= _("invalid offset");
8516 inst
.instruction
|= offset
>> 2;
8519 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
8523 inst
.error
= _("invalid base register in load/store");
8526 else if (Ro
== FAIL
)
8528 /* Immediate offset. */
8529 if (size
== THUMB_WORD
)
8530 inst
.instruction
= (load_store
== THUMB_LOAD
8531 ? T_OPCODE_LDR_IW
: T_OPCODE_STR_IW
);
8532 else if (size
== THUMB_HALFWORD
)
8533 inst
.instruction
= (load_store
== THUMB_LOAD
8534 ? T_OPCODE_LDR_IH
: T_OPCODE_STR_IH
);
8536 inst
.instruction
= (load_store
== THUMB_LOAD
8537 ? T_OPCODE_LDR_IB
: T_OPCODE_STR_IB
);
8539 inst
.instruction
|= Rd
| (Rb
<< 3);
8541 if (inst
.reloc
.exp
.X_op
== O_constant
)
8543 unsigned offset
= inst
.reloc
.exp
.X_add_number
;
8545 if (offset
& ~(0x1f << size
))
8547 inst
.error
= _("invalid offset");
8550 inst
.instruction
|= (offset
>> size
) << 6;
8553 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
8557 /* Register offset. */
8558 if (size
== THUMB_WORD
)
8559 inst
.instruction
= (load_store
== THUMB_LOAD
8560 ? T_OPCODE_LDR_RW
: T_OPCODE_STR_RW
);
8561 else if (size
== THUMB_HALFWORD
)
8562 inst
.instruction
= (load_store
== THUMB_LOAD
8563 ? T_OPCODE_LDR_RH
: T_OPCODE_STR_RH
);
8565 inst
.instruction
= (load_store
== THUMB_LOAD
8566 ? T_OPCODE_LDR_RB
: T_OPCODE_STR_RB
);
8568 inst
.instruction
|= Rd
| (Rb
<< 3) | (Ro
<< 6);
8574 /* A register must be given at this point.
8576 Shift is the place to put it in inst.instruction.
8578 Restores input start point on err.
8579 Returns the reg#, or FAIL. */
8582 mav_reg_required_here (char ** str
, int shift
, enum arm_reg_type regtype
)
8587 if ((reg
= arm_reg_parse (str
, all_reg_maps
[regtype
].htab
)) != FAIL
)
8590 inst
.instruction
|= reg
<< shift
;
8595 /* Restore the start point. */
8598 /* Try generic coprocessor name if applicable. */
8599 if (regtype
== REG_TYPE_MVF
||
8600 regtype
== REG_TYPE_MVD
||
8601 regtype
== REG_TYPE_MVFX
||
8602 regtype
== REG_TYPE_MVDX
)
8604 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_CN
].htab
)) != FAIL
)
8607 inst
.instruction
|= reg
<< shift
;
8612 /* Restore the start point. */
8616 /* In the few cases where we might be able to accept something else
8617 this error can be overridden. */
8618 inst
.error
= _(all_reg_maps
[regtype
].expected
);
8623 /* Cirrus Maverick Instructions. */
8625 /* Isnsn like "foo X,Y". */
8628 do_mav_binops (char * str
,
8630 enum arm_reg_type reg0
,
8631 enum arm_reg_type reg1
)
8635 shift0
= mode
& 0xff;
8636 shift1
= (mode
>> 8) & 0xff;
8638 skip_whitespace (str
);
8640 if (mav_reg_required_here (&str
, shift0
, reg0
) == FAIL
8641 || skip_past_comma (&str
) == FAIL
8642 || mav_reg_required_here (&str
, shift1
, reg1
) == FAIL
)
8645 inst
.error
= BAD_ARGS
;
8651 /* Isnsn like "foo X,Y,Z". */
8654 do_mav_triple (char * str
,
8656 enum arm_reg_type reg0
,
8657 enum arm_reg_type reg1
,
8658 enum arm_reg_type reg2
)
8660 int shift0
, shift1
, shift2
;
8662 shift0
= mode
& 0xff;
8663 shift1
= (mode
>> 8) & 0xff;
8664 shift2
= (mode
>> 16) & 0xff;
8666 skip_whitespace (str
);
8668 if (mav_reg_required_here (&str
, shift0
, reg0
) == FAIL
8669 || skip_past_comma (&str
) == FAIL
8670 || mav_reg_required_here (&str
, shift1
, reg1
) == FAIL
8671 || skip_past_comma (&str
) == FAIL
8672 || mav_reg_required_here (&str
, shift2
, reg2
) == FAIL
)
8675 inst
.error
= BAD_ARGS
;
8681 /* Wrapper functions. */
8684 do_mav_binops_1a (char * str
)
8686 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_RN
, REG_TYPE_MVF
);
8690 do_mav_binops_1b (char * str
)
8692 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_RN
, REG_TYPE_MVD
);
8696 do_mav_binops_1c (char * str
)
8698 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_RN
, REG_TYPE_MVDX
);
8702 do_mav_binops_1d (char * str
)
8704 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVF
);
8708 do_mav_binops_1e (char * str
)
8710 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVD
);
8714 do_mav_binops_1f (char * str
)
8716 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVF
);
8720 do_mav_binops_1g (char * str
)
8722 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVD
);
8726 do_mav_binops_1h (char * str
)
8728 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVFX
);
8732 do_mav_binops_1i (char * str
)
8734 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVFX
);
8738 do_mav_binops_1j (char * str
)
8740 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVDX
);
8744 do_mav_binops_1k (char * str
)
8746 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVDX
);
8750 do_mav_binops_1l (char * str
)
8752 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVFX
, REG_TYPE_MVF
);
8756 do_mav_binops_1m (char * str
)
8758 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVFX
, REG_TYPE_MVD
);
8762 do_mav_binops_1n (char * str
)
8764 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
8768 do_mav_binops_1o (char * str
)
8770 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
8774 do_mav_binops_2a (char * str
)
8776 do_mav_binops (str
, MAV_MODE2
, REG_TYPE_MVF
, REG_TYPE_RN
);
8780 do_mav_binops_2b (char * str
)
8782 do_mav_binops (str
, MAV_MODE2
, REG_TYPE_MVD
, REG_TYPE_RN
);
8786 do_mav_binops_2c (char * str
)
8788 do_mav_binops (str
, MAV_MODE2
, REG_TYPE_MVDX
, REG_TYPE_RN
);
8792 do_mav_binops_3a (char * str
)
8794 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVAX
, REG_TYPE_MVFX
);
8798 do_mav_binops_3b (char * str
)
8800 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVFX
, REG_TYPE_MVAX
);
8804 do_mav_binops_3c (char * str
)
8806 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVAX
, REG_TYPE_MVDX
);
8810 do_mav_binops_3d (char * str
)
8812 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVDX
, REG_TYPE_MVAX
);
8816 do_mav_triple_4a (char * str
)
8818 do_mav_triple (str
, MAV_MODE4
, REG_TYPE_MVFX
, REG_TYPE_MVFX
, REG_TYPE_RN
);
8822 do_mav_triple_4b (char * str
)
8824 do_mav_triple (str
, MAV_MODE4
, REG_TYPE_MVDX
, REG_TYPE_MVDX
, REG_TYPE_RN
);
8828 do_mav_triple_5a (char * str
)
8830 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVF
, REG_TYPE_MVF
);
8834 do_mav_triple_5b (char * str
)
8836 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVD
, REG_TYPE_MVD
);
8840 do_mav_triple_5c (char * str
)
8842 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
8846 do_mav_triple_5d (char * str
)
8848 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
8852 do_mav_triple_5e (char * str
)
8854 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVF
, REG_TYPE_MVF
, REG_TYPE_MVF
);
8858 do_mav_triple_5f (char * str
)
8860 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVD
, REG_TYPE_MVD
, REG_TYPE_MVD
);
8864 do_mav_triple_5g (char * str
)
8866 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVFX
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
8870 do_mav_triple_5h (char * str
)
8872 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVDX
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
8875 /* Isnsn like "foo W,X,Y,Z".
8876 where W=MVAX[0:3] and X,Y,Z=MVFX[0:15]. */
8879 do_mav_quad (char * str
,
8881 enum arm_reg_type reg0
,
8882 enum arm_reg_type reg1
,
8883 enum arm_reg_type reg2
,
8884 enum arm_reg_type reg3
)
8886 int shift0
, shift1
, shift2
, shift3
;
8888 shift0
= mode
& 0xff;
8889 shift1
= (mode
>> 8) & 0xff;
8890 shift2
= (mode
>> 16) & 0xff;
8891 shift3
= (mode
>> 24) & 0xff;
8893 skip_whitespace (str
);
8895 if (mav_reg_required_here (&str
, shift0
, reg0
) == FAIL
8896 || skip_past_comma (&str
) == FAIL
8897 || mav_reg_required_here (&str
, shift1
, reg1
) == FAIL
8898 || skip_past_comma (&str
) == FAIL
8899 || mav_reg_required_here (&str
, shift2
, reg2
) == FAIL
8900 || skip_past_comma (&str
) == FAIL
8901 || mav_reg_required_here (&str
, shift3
, reg3
) == FAIL
)
8904 inst
.error
= BAD_ARGS
;
8911 do_mav_quad_6a (char * str
)
8913 do_mav_quad (str
, MAV_MODE6
, REG_TYPE_MVAX
, REG_TYPE_MVFX
, REG_TYPE_MVFX
,
8918 do_mav_quad_6b (char * str
)
8920 do_mav_quad (str
, MAV_MODE6
, REG_TYPE_MVAX
, REG_TYPE_MVAX
, REG_TYPE_MVFX
,
8924 /* cfmvsc32<cond> DSPSC,MVDX[15:0]. */
8926 do_mav_dspsc_1 (char * str
)
8928 skip_whitespace (str
);
8931 if (mav_reg_required_here (&str
, -1, REG_TYPE_DSPSC
) == FAIL
8932 || skip_past_comma (&str
) == FAIL
8933 || mav_reg_required_here (&str
, 12, REG_TYPE_MVDX
) == FAIL
)
8936 inst
.error
= BAD_ARGS
;
8944 /* cfmv32sc<cond> MVDX[15:0],DSPSC. */
8946 do_mav_dspsc_2 (char * str
)
8948 skip_whitespace (str
);
8951 if (mav_reg_required_here (&str
, 12, REG_TYPE_MVDX
) == FAIL
8952 || skip_past_comma (&str
) == FAIL
8953 || mav_reg_required_here (&str
, -1, REG_TYPE_DSPSC
) == FAIL
)
8956 inst
.error
= BAD_ARGS
;
8964 /* Maverick shift immediate instructions.
8965 cfsh32<cond> MVFX[15:0],MVFX[15:0],Shift[6:0].
8966 cfsh64<cond> MVDX[15:0],MVDX[15:0],Shift[6:0]. */
8969 do_mav_shift (char * str
,
8970 enum arm_reg_type reg0
,
8971 enum arm_reg_type reg1
)
8976 skip_whitespace (str
);
8980 if (mav_reg_required_here (&str
, 12, reg0
) == FAIL
8981 || skip_past_comma (&str
) == FAIL
8982 || mav_reg_required_here (&str
, 16, reg1
) == FAIL
8983 || skip_past_comma (&str
) == FAIL
)
8986 inst
.error
= BAD_ARGS
;
8990 /* Calculate the immediate operand.
8991 The operand is a 7bit signed number. */
8992 skip_whitespace (str
);
8997 if (!ISDIGIT (*str
) && *str
!= '-')
8999 inst
.error
= _("expecting immediate, 7bit operand");
9009 for (imm
= 0; *str
&& ISDIGIT (*str
); ++str
)
9010 imm
= imm
* 10 + *str
- '0';
9014 inst
.error
= _("immediate out of range");
9018 /* Make negative imm's into 7bit signed numbers. */
9025 /* Bits 0-3 of the insn should have bits 0-3 of the immediate.
9026 Bits 5-7 of the insn should have bits 4-6 of the immediate.
9027 Bit 4 should be 0. */
9028 imm
= (imm
& 0xf) | ((imm
& 0x70) << 1);
9030 inst
.instruction
|= imm
;
9035 do_mav_shift_1 (char * str
)
9037 do_mav_shift (str
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
9041 do_mav_shift_2 (char * str
)
9043 do_mav_shift (str
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
9047 mav_parse_offset (char ** str
, int * negative
)
9054 skip_whitespace (p
);
9067 inst
.error
= _("offset expected");
9071 for (offset
= 0; *p
&& ISDIGIT (*p
); ++p
)
9072 offset
= offset
* 10 + *p
- '0';
9076 inst
.error
= _("offset out of range");
9081 inst
.error
= _("offset not a multiple of 4");
9087 return *negative
? -offset
: offset
;
9090 /* Maverick load/store instructions.
9091 <insn><cond> CRd,[Rn,<offset>]{!}.
9092 <insn><cond> CRd,[Rn],<offset>. */
9095 do_mav_ldst (char * str
, enum arm_reg_type reg0
)
9097 int offset
, negative
;
9099 skip_whitespace (str
);
9101 if (mav_reg_required_here (&str
, 12, reg0
) == FAIL
9102 || skip_past_comma (&str
) == FAIL
9104 || reg_required_here (&str
, 16) == FAIL
)
9107 if (skip_past_comma (&str
) == SUCCESS
)
9109 /* You are here: "<offset>]{!}". */
9110 inst
.instruction
|= PRE_INDEX
;
9112 offset
= mav_parse_offset (&str
, &negative
);
9119 inst
.error
= _("missing ]");
9125 inst
.instruction
|= WRITE_BACK
;
9131 /* You are here: "], <offset>". */
9134 inst
.error
= _("missing ]");
9138 if (skip_past_comma (&str
) == FAIL
9139 || (offset
= mav_parse_offset (&str
, &negative
), inst
.error
))
9142 inst
.instruction
|= CP_T_WB
; /* Post indexed, set bit W. */
9148 inst
.instruction
|= CP_T_UD
; /* Positive, so set bit U. */
9150 inst
.instruction
|= offset
>> 2;
9156 inst
.error
= BAD_ARGS
;
9160 do_mav_ldst_1 (char * str
)
9162 do_mav_ldst (str
, REG_TYPE_MVF
);
9166 do_mav_ldst_2 (char * str
)
9168 do_mav_ldst (str
, REG_TYPE_MVD
);
9172 do_mav_ldst_3 (char * str
)
9174 do_mav_ldst (str
, REG_TYPE_MVFX
);
9178 do_mav_ldst_4 (char * str
)
9180 do_mav_ldst (str
, REG_TYPE_MVDX
);
9184 do_t_nop (char * str
)
9190 /* Handle the Format 4 instructions that do not have equivalents in other
9191 formats. That is, ADC, AND, EOR, SBC, ROR, TST, NEG, CMN, ORR, MUL,
9195 do_t_arit (char * str
)
9199 skip_whitespace (str
);
9201 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
9202 || skip_past_comma (&str
) == FAIL
9203 || (Rs
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
9205 inst
.error
= BAD_ARGS
;
9209 if (skip_past_comma (&str
) != FAIL
)
9211 /* Three operand format not allowed for TST, CMN, NEG and MVN.
9212 (It isn't allowed for CMP either, but that isn't handled by this
9214 if (inst
.instruction
== T_OPCODE_TST
9215 || inst
.instruction
== T_OPCODE_CMN
9216 || inst
.instruction
== T_OPCODE_NEG
9217 || inst
.instruction
== T_OPCODE_MVN
)
9219 inst
.error
= BAD_ARGS
;
9223 if ((Rn
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
9228 inst
.error
= _("dest and source1 must be the same register");
9234 if (inst
.instruction
== T_OPCODE_MUL
9236 as_tsktsk (_("Rs and Rd must be different in MUL"));
9238 inst
.instruction
|= Rd
| (Rs
<< 3);
9243 do_t_add (char * str
)
9245 thumb_add_sub (str
, 0);
9249 do_t_asr (char * str
)
9251 thumb_shift (str
, THUMB_ASR
);
9255 do_t_branch9 (char * str
)
9257 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9259 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH9
;
9260 inst
.reloc
.pc_rel
= 1;
9265 do_t_branch12 (char * str
)
9267 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9269 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH12
;
9270 inst
.reloc
.pc_rel
= 1;
9274 /* Find the real, Thumb encoded start of a Thumb function. */
9277 find_real_start (symbolS
* symbolP
)
9280 const char * name
= S_GET_NAME (symbolP
);
9281 symbolS
* new_target
;
9283 /* This definition must agree with the one in gcc/config/arm/thumb.c. */
9284 #define STUB_NAME ".real_start_of"
9289 /* Names that start with '.' are local labels, not function entry points.
9290 The compiler may generate BL instructions to these labels because it
9291 needs to perform a branch to a far away location. */
9295 real_start
= malloc (strlen (name
) + strlen (STUB_NAME
) + 1);
9296 sprintf (real_start
, "%s%s", STUB_NAME
, name
);
9298 new_target
= symbol_find (real_start
);
9300 if (new_target
== NULL
)
9302 as_warn ("Failed to find real start of function: %s\n", name
);
9303 new_target
= symbolP
;
9312 do_t_branch23 (char * str
)
9314 if (my_get_expression (& inst
.reloc
.exp
, & str
))
9317 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH23
;
9318 inst
.reloc
.pc_rel
= 1;
9321 /* If the destination of the branch is a defined symbol which does not have
9322 the THUMB_FUNC attribute, then we must be calling a function which has
9323 the (interfacearm) attribute. We look for the Thumb entry point to that
9324 function and change the branch to refer to that function instead. */
9325 if ( inst
.reloc
.exp
.X_op
== O_symbol
9326 && inst
.reloc
.exp
.X_add_symbol
!= NULL
9327 && S_IS_DEFINED (inst
.reloc
.exp
.X_add_symbol
)
9328 && ! THUMB_IS_FUNC (inst
.reloc
.exp
.X_add_symbol
))
9329 inst
.reloc
.exp
.X_add_symbol
=
9330 find_real_start (inst
.reloc
.exp
.X_add_symbol
);
9334 do_t_bx (char * str
)
9338 skip_whitespace (str
);
9340 if ((reg
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
9343 /* This sets THUMB_H2 from the top bit of reg. */
9344 inst
.instruction
|= reg
<< 3;
9346 /* ??? FIXME: Should add a hacky reloc here if reg is REG_PC. The reloc
9347 should cause the alignment to be checked once it is known. This is
9348 because BX PC only works if the instruction is word aligned. */
9354 do_t_compare (char * str
)
9356 thumb_mov_compare (str
, THUMB_COMPARE
);
9360 do_t_ldmstm (char * str
)
9365 skip_whitespace (str
);
9367 if ((Rb
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
9371 as_warn (_("inserted missing '!': load/store multiple always writes back base register"));
9375 if (skip_past_comma (&str
) == FAIL
9376 || (range
= reg_list (&str
)) == FAIL
)
9379 inst
.error
= BAD_ARGS
;
9383 if (inst
.reloc
.type
!= BFD_RELOC_NONE
)
9385 /* This really doesn't seem worth it. */
9386 inst
.reloc
.type
= BFD_RELOC_NONE
;
9387 inst
.error
= _("expression too complex");
9393 inst
.error
= _("only lo-regs valid in load/store multiple");
9397 inst
.instruction
|= (Rb
<< 8) | range
;
9402 do_t_ldr (char * str
)
9404 thumb_load_store (str
, THUMB_LOAD
, THUMB_WORD
);
9408 do_t_ldrb (char * str
)
9410 thumb_load_store (str
, THUMB_LOAD
, THUMB_BYTE
);
9414 do_t_ldrh (char * str
)
9416 thumb_load_store (str
, THUMB_LOAD
, THUMB_HALFWORD
);
9420 do_t_lds (char * str
)
9424 skip_whitespace (str
);
9426 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
9427 || skip_past_comma (&str
) == FAIL
9429 || (Rb
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
9430 || skip_past_comma (&str
) == FAIL
9431 || (Ro
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
9435 inst
.error
= _("syntax: ldrs[b] Rd, [Rb, Ro]");
9439 inst
.instruction
|= Rd
| (Rb
<< 3) | (Ro
<< 6);
9444 do_t_lsl (char * str
)
9446 thumb_shift (str
, THUMB_LSL
);
9450 do_t_lsr (char * str
)
9452 thumb_shift (str
, THUMB_LSR
);
9456 do_t_mov (char * str
)
9458 thumb_mov_compare (str
, THUMB_MOVE
);
9462 do_t_push_pop (char * str
)
9466 skip_whitespace (str
);
9468 if ((range
= reg_list (&str
)) == FAIL
)
9471 inst
.error
= BAD_ARGS
;
9475 if (inst
.reloc
.type
!= BFD_RELOC_NONE
)
9477 /* This really doesn't seem worth it. */
9478 inst
.reloc
.type
= BFD_RELOC_NONE
;
9479 inst
.error
= _("expression too complex");
9485 if ((inst
.instruction
== T_OPCODE_PUSH
9486 && (range
& ~0xff) == 1 << REG_LR
)
9487 || (inst
.instruction
== T_OPCODE_POP
9488 && (range
& ~0xff) == 1 << REG_PC
))
9490 inst
.instruction
|= THUMB_PP_PC_LR
;
9495 inst
.error
= _("invalid register list to push/pop instruction");
9500 inst
.instruction
|= range
;
9505 do_t_str (char * str
)
9507 thumb_load_store (str
, THUMB_STORE
, THUMB_WORD
);
9511 do_t_strb (char * str
)
9513 thumb_load_store (str
, THUMB_STORE
, THUMB_BYTE
);
9517 do_t_strh (char * str
)
9519 thumb_load_store (str
, THUMB_STORE
, THUMB_HALFWORD
);
9523 do_t_sub (char * str
)
9525 thumb_add_sub (str
, 1);
9529 do_t_swi (char * str
)
9531 skip_whitespace (str
);
9533 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9536 inst
.reloc
.type
= BFD_RELOC_ARM_SWI
;
9541 do_t_adr (char * str
)
9545 /* This is a pseudo-op of the form "adr rd, label" to be converted
9546 into a relative address of the form "add rd, pc, #label-.-4". */
9547 skip_whitespace (str
);
9549 /* Store Rd in temporary location inside instruction. */
9550 if ((reg
= reg_required_here (&str
, 4)) == FAIL
9551 || (reg
> 7) /* For Thumb reg must be r0..r7. */
9552 || skip_past_comma (&str
) == FAIL
9553 || my_get_expression (&inst
.reloc
.exp
, &str
))
9556 inst
.error
= BAD_ARGS
;
9560 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_ADD
;
9561 inst
.reloc
.exp
.X_add_number
-= 4; /* PC relative adjust. */
9562 inst
.reloc
.pc_rel
= 1;
9563 inst
.instruction
|= REG_PC
; /* Rd is already placed into the instruction. */
9569 insert_reg (const struct reg_entry
* r
,
9570 struct hash_control
* htab
)
9572 int len
= strlen (r
->name
) + 2;
9573 char * buf
= xmalloc (len
);
9574 char * buf2
= xmalloc (len
);
9577 #ifdef REGISTER_PREFIX
9578 buf
[i
++] = REGISTER_PREFIX
;
9581 strcpy (buf
+ i
, r
->name
);
9583 for (i
= 0; buf
[i
]; i
++)
9584 buf2
[i
] = TOUPPER (buf
[i
]);
9588 hash_insert (htab
, buf
, (PTR
) r
);
9589 hash_insert (htab
, buf2
, (PTR
) r
);
9593 build_reg_hsh (struct reg_map
* map
)
9595 const struct reg_entry
*r
;
9597 if ((map
->htab
= hash_new ()) == NULL
)
9598 as_fatal (_("virtual memory exhausted"));
9600 for (r
= map
->names
; r
->name
!= NULL
; r
++)
9601 insert_reg (r
, map
->htab
);
9605 insert_reg_alias (char * str
,
9607 struct hash_control
*htab
)
9610 struct reg_entry
* new = xmalloc (sizeof (struct reg_entry
));
9611 const char * name
= xmalloc (strlen (str
) + 1);
9613 strcpy ((char *) name
, str
);
9616 new->number
= regnum
;
9617 new->builtin
= FALSE
;
9619 error
= hash_insert (htab
, name
, (PTR
) new);
9622 as_bad (_("failed to create an alias for %s, reason: %s"),
9624 free ((char *) name
);
9629 /* Look for the .req directive. This is of the form:
9631 new_register_name .req existing_register_name
9633 If we find one, or if it looks sufficiently like one that we want to
9634 handle any error here, return non-zero. Otherwise return zero. */
9637 create_register_alias (char * newname
, char * p
)
9643 skip_whitespace (q
);
9648 if (*q
&& !strncmp (q
, ".req ", 5))
9653 #ifndef IGNORE_OPCODE_CASE
9654 newname
= original_case_string
;
9656 copy_of_str
= newname
;
9659 skip_whitespace (q
);
9661 for (r
= q
; *r
!= '\0'; r
++)
9667 enum arm_reg_type new_type
, old_type
;
9672 old_type
= arm_reg_parse_any (q
);
9675 new_type
= arm_reg_parse_any (newname
);
9677 if (new_type
== REG_TYPE_MAX
)
9679 if (old_type
!= REG_TYPE_MAX
)
9681 old_regno
= arm_reg_parse (&q
, all_reg_maps
[old_type
].htab
);
9682 insert_reg_alias (newname
, old_regno
,
9683 all_reg_maps
[old_type
].htab
);
9686 as_warn (_("register '%s' does not exist\n"), q
);
9688 else if (old_type
== REG_TYPE_MAX
)
9690 as_warn (_("ignoring redefinition of register alias '%s' to non-existant register '%s'"),
9695 /* Do not warn about redefinitions to the same alias. */
9696 if (new_type
!= old_type
9697 || (arm_reg_parse (&q
, all_reg_maps
[old_type
].htab
)
9698 != arm_reg_parse (&q
, all_reg_maps
[new_type
].htab
)))
9699 as_warn (_("ignoring redefinition of register alias '%s'"),
9705 as_warn (_("ignoring incomplete .req pseuso op"));
9716 set_constant_flonums (void)
9720 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
9721 if (atof_ieee ((char *) fp_const
[i
], 'x', fp_values
[i
]) == NULL
)
9726 static const struct asm_opcode insns
[] =
9728 /* Core ARM Instructions. */
9729 {"and", 0xe0000000, 3, ARM_EXT_V1
, do_arit
},
9730 {"ands", 0xe0100000, 3, ARM_EXT_V1
, do_arit
},
9731 {"eor", 0xe0200000, 3, ARM_EXT_V1
, do_arit
},
9732 {"eors", 0xe0300000, 3, ARM_EXT_V1
, do_arit
},
9733 {"sub", 0xe0400000, 3, ARM_EXT_V1
, do_arit
},
9734 {"subs", 0xe0500000, 3, ARM_EXT_V1
, do_arit
},
9735 {"rsb", 0xe0600000, 3, ARM_EXT_V1
, do_arit
},
9736 {"rsbs", 0xe0700000, 3, ARM_EXT_V1
, do_arit
},
9737 {"add", 0xe0800000, 3, ARM_EXT_V1
, do_arit
},
9738 {"adds", 0xe0900000, 3, ARM_EXT_V1
, do_arit
},
9739 {"adc", 0xe0a00000, 3, ARM_EXT_V1
, do_arit
},
9740 {"adcs", 0xe0b00000, 3, ARM_EXT_V1
, do_arit
},
9741 {"sbc", 0xe0c00000, 3, ARM_EXT_V1
, do_arit
},
9742 {"sbcs", 0xe0d00000, 3, ARM_EXT_V1
, do_arit
},
9743 {"rsc", 0xe0e00000, 3, ARM_EXT_V1
, do_arit
},
9744 {"rscs", 0xe0f00000, 3, ARM_EXT_V1
, do_arit
},
9745 {"orr", 0xe1800000, 3, ARM_EXT_V1
, do_arit
},
9746 {"orrs", 0xe1900000, 3, ARM_EXT_V1
, do_arit
},
9747 {"bic", 0xe1c00000, 3, ARM_EXT_V1
, do_arit
},
9748 {"bics", 0xe1d00000, 3, ARM_EXT_V1
, do_arit
},
9750 {"tst", 0xe1100000, 3, ARM_EXT_V1
, do_cmp
},
9751 {"tsts", 0xe1100000, 3, ARM_EXT_V1
, do_cmp
},
9752 {"tstp", 0xe110f000, 3, ARM_EXT_V1
, do_cmp
},
9753 {"teq", 0xe1300000, 3, ARM_EXT_V1
, do_cmp
},
9754 {"teqs", 0xe1300000, 3, ARM_EXT_V1
, do_cmp
},
9755 {"teqp", 0xe130f000, 3, ARM_EXT_V1
, do_cmp
},
9756 {"cmp", 0xe1500000, 3, ARM_EXT_V1
, do_cmp
},
9757 {"cmps", 0xe1500000, 3, ARM_EXT_V1
, do_cmp
},
9758 {"cmpp", 0xe150f000, 3, ARM_EXT_V1
, do_cmp
},
9759 {"cmn", 0xe1700000, 3, ARM_EXT_V1
, do_cmp
},
9760 {"cmns", 0xe1700000, 3, ARM_EXT_V1
, do_cmp
},
9761 {"cmnp", 0xe170f000, 3, ARM_EXT_V1
, do_cmp
},
9763 {"mov", 0xe1a00000, 3, ARM_EXT_V1
, do_mov
},
9764 {"movs", 0xe1b00000, 3, ARM_EXT_V1
, do_mov
},
9765 {"mvn", 0xe1e00000, 3, ARM_EXT_V1
, do_mov
},
9766 {"mvns", 0xe1f00000, 3, ARM_EXT_V1
, do_mov
},
9768 {"ldr", 0xe4100000, 3, ARM_EXT_V1
, do_ldst
},
9769 {"ldrb", 0xe4500000, 3, ARM_EXT_V1
, do_ldst
},
9770 {"ldrt", 0xe4300000, 3, ARM_EXT_V1
, do_ldstt
},
9771 {"ldrbt", 0xe4700000, 3, ARM_EXT_V1
, do_ldstt
},
9772 {"str", 0xe4000000, 3, ARM_EXT_V1
, do_ldst
},
9773 {"strb", 0xe4400000, 3, ARM_EXT_V1
, do_ldst
},
9774 {"strt", 0xe4200000, 3, ARM_EXT_V1
, do_ldstt
},
9775 {"strbt", 0xe4600000, 3, ARM_EXT_V1
, do_ldstt
},
9777 {"stmia", 0xe8800000, 3, ARM_EXT_V1
, do_ldmstm
},
9778 {"stmib", 0xe9800000, 3, ARM_EXT_V1
, do_ldmstm
},
9779 {"stmda", 0xe8000000, 3, ARM_EXT_V1
, do_ldmstm
},
9780 {"stmdb", 0xe9000000, 3, ARM_EXT_V1
, do_ldmstm
},
9781 {"stmfd", 0xe9000000, 3, ARM_EXT_V1
, do_ldmstm
},
9782 {"stmfa", 0xe9800000, 3, ARM_EXT_V1
, do_ldmstm
},
9783 {"stmea", 0xe8800000, 3, ARM_EXT_V1
, do_ldmstm
},
9784 {"stmed", 0xe8000000, 3, ARM_EXT_V1
, do_ldmstm
},
9786 {"ldmia", 0xe8900000, 3, ARM_EXT_V1
, do_ldmstm
},
9787 {"ldmib", 0xe9900000, 3, ARM_EXT_V1
, do_ldmstm
},
9788 {"ldmda", 0xe8100000, 3, ARM_EXT_V1
, do_ldmstm
},
9789 {"ldmdb", 0xe9100000, 3, ARM_EXT_V1
, do_ldmstm
},
9790 {"ldmfd", 0xe8900000, 3, ARM_EXT_V1
, do_ldmstm
},
9791 {"ldmfa", 0xe8100000, 3, ARM_EXT_V1
, do_ldmstm
},
9792 {"ldmea", 0xe9100000, 3, ARM_EXT_V1
, do_ldmstm
},
9793 {"ldmed", 0xe9900000, 3, ARM_EXT_V1
, do_ldmstm
},
9795 {"swi", 0xef000000, 3, ARM_EXT_V1
, do_swi
},
9797 /* XXX This is the wrong place to do this. Think multi-arch. */
9798 {"bl", 0xeb000000, 2, ARM_EXT_V1
, do_branch
},
9799 {"b", 0xea000000, 1, ARM_EXT_V1
, do_branch
},
9801 {"bl", 0xebfffffe, 2, ARM_EXT_V1
, do_branch
},
9802 {"b", 0xeafffffe, 1, ARM_EXT_V1
, do_branch
},
9806 {"adr", 0xe28f0000, 3, ARM_EXT_V1
, do_adr
},
9807 {"adrl", 0xe28f0000, 3, ARM_EXT_V1
, do_adrl
},
9808 {"nop", 0xe1a00000, 3, ARM_EXT_V1
, do_nop
},
9810 /* ARM 2 multiplies. */
9811 {"mul", 0xe0000090, 3, ARM_EXT_V2
, do_mul
},
9812 {"muls", 0xe0100090, 3, ARM_EXT_V2
, do_mul
},
9813 {"mla", 0xe0200090, 3, ARM_EXT_V2
, do_mla
},
9814 {"mlas", 0xe0300090, 3, ARM_EXT_V2
, do_mla
},
9816 /* Generic coprocessor instructions. */
9817 {"cdp", 0xee000000, 3, ARM_EXT_V2
, do_cdp
},
9818 {"ldc", 0xec100000, 3, ARM_EXT_V2
, do_lstc
},
9819 {"ldcl", 0xec500000, 3, ARM_EXT_V2
, do_lstc
},
9820 {"stc", 0xec000000, 3, ARM_EXT_V2
, do_lstc
},
9821 {"stcl", 0xec400000, 3, ARM_EXT_V2
, do_lstc
},
9822 {"mcr", 0xee000010, 3, ARM_EXT_V2
, do_co_reg
},
9823 {"mrc", 0xee100010, 3, ARM_EXT_V2
, do_co_reg
},
9825 /* ARM 3 - swp instructions. */
9826 {"swp", 0xe1000090, 3, ARM_EXT_V2S
, do_swap
},
9827 {"swpb", 0xe1400090, 3, ARM_EXT_V2S
, do_swap
},
9829 /* ARM 6 Status register instructions. */
9830 {"mrs", 0xe10f0000, 3, ARM_EXT_V3
, do_mrs
},
9831 {"msr", 0xe120f000, 3, ARM_EXT_V3
, do_msr
},
9832 /* ScottB: our code uses 0xe128f000 for msr.
9833 NickC: but this is wrong because the bits 16 through 19 are
9834 handled by the PSR_xxx defines above. */
9836 /* ARM 7M long multiplies. */
9837 {"smull", 0xe0c00090, 5, ARM_EXT_V3M
, do_mull
},
9838 {"smulls", 0xe0d00090, 5, ARM_EXT_V3M
, do_mull
},
9839 {"umull", 0xe0800090, 5, ARM_EXT_V3M
, do_mull
},
9840 {"umulls", 0xe0900090, 5, ARM_EXT_V3M
, do_mull
},
9841 {"smlal", 0xe0e00090, 5, ARM_EXT_V3M
, do_mull
},
9842 {"smlals", 0xe0f00090, 5, ARM_EXT_V3M
, do_mull
},
9843 {"umlal", 0xe0a00090, 5, ARM_EXT_V3M
, do_mull
},
9844 {"umlals", 0xe0b00090, 5, ARM_EXT_V3M
, do_mull
},
9846 /* ARM Architecture 4. */
9847 {"ldrh", 0xe01000b0, 3, ARM_EXT_V4
, do_ldstv4
},
9848 {"ldrsh", 0xe01000f0, 3, ARM_EXT_V4
, do_ldstv4
},
9849 {"ldrsb", 0xe01000d0, 3, ARM_EXT_V4
, do_ldstv4
},
9850 {"strh", 0xe00000b0, 3, ARM_EXT_V4
, do_ldstv4
},
9852 /* ARM Architecture 4T. */
9853 /* Note: bx (and blx) are required on V5, even if the processor does
9854 not support Thumb. */
9855 {"bx", 0xe12fff10, 2, ARM_EXT_V4T
| ARM_EXT_V5
, do_bx
},
9857 /* ARM Architecture 5T. */
9858 /* Note: blx has 2 variants, so the .value is set dynamically.
9859 Only one of the variants has conditional execution. */
9860 {"blx", 0xe0000000, 3, ARM_EXT_V5
, do_blx
},
9861 {"clz", 0xe16f0f10, 3, ARM_EXT_V5
, do_clz
},
9862 {"bkpt", 0xe1200070, 0, ARM_EXT_V5
, do_bkpt
},
9863 {"ldc2", 0xfc100000, 0, ARM_EXT_V5
, do_lstc2
},
9864 {"ldc2l", 0xfc500000, 0, ARM_EXT_V5
, do_lstc2
},
9865 {"stc2", 0xfc000000, 0, ARM_EXT_V5
, do_lstc2
},
9866 {"stc2l", 0xfc400000, 0, ARM_EXT_V5
, do_lstc2
},
9867 {"cdp2", 0xfe000000, 0, ARM_EXT_V5
, do_cdp2
},
9868 {"mcr2", 0xfe000010, 0, ARM_EXT_V5
, do_co_reg2
},
9869 {"mrc2", 0xfe100010, 0, ARM_EXT_V5
, do_co_reg2
},
9871 /* ARM Architecture 5TExP. */
9872 {"smlabb", 0xe1000080, 6, ARM_EXT_V5ExP
, do_smla
},
9873 {"smlatb", 0xe10000a0, 6, ARM_EXT_V5ExP
, do_smla
},
9874 {"smlabt", 0xe10000c0, 6, ARM_EXT_V5ExP
, do_smla
},
9875 {"smlatt", 0xe10000e0, 6, ARM_EXT_V5ExP
, do_smla
},
9877 {"smlawb", 0xe1200080, 6, ARM_EXT_V5ExP
, do_smla
},
9878 {"smlawt", 0xe12000c0, 6, ARM_EXT_V5ExP
, do_smla
},
9880 {"smlalbb", 0xe1400080, 7, ARM_EXT_V5ExP
, do_smlal
},
9881 {"smlaltb", 0xe14000a0, 7, ARM_EXT_V5ExP
, do_smlal
},
9882 {"smlalbt", 0xe14000c0, 7, ARM_EXT_V5ExP
, do_smlal
},
9883 {"smlaltt", 0xe14000e0, 7, ARM_EXT_V5ExP
, do_smlal
},
9885 {"smulbb", 0xe1600080, 6, ARM_EXT_V5ExP
, do_smul
},
9886 {"smultb", 0xe16000a0, 6, ARM_EXT_V5ExP
, do_smul
},
9887 {"smulbt", 0xe16000c0, 6, ARM_EXT_V5ExP
, do_smul
},
9888 {"smultt", 0xe16000e0, 6, ARM_EXT_V5ExP
, do_smul
},
9890 {"smulwb", 0xe12000a0, 6, ARM_EXT_V5ExP
, do_smul
},
9891 {"smulwt", 0xe12000e0, 6, ARM_EXT_V5ExP
, do_smul
},
9893 {"qadd", 0xe1000050, 4, ARM_EXT_V5ExP
, do_qadd
},
9894 {"qdadd", 0xe1400050, 5, ARM_EXT_V5ExP
, do_qadd
},
9895 {"qsub", 0xe1200050, 4, ARM_EXT_V5ExP
, do_qadd
},
9896 {"qdsub", 0xe1600050, 5, ARM_EXT_V5ExP
, do_qadd
},
9898 /* ARM Architecture 5TE. */
9899 {"pld", 0xf450f000, 0, ARM_EXT_V5E
, do_pld
},
9900 {"ldrd", 0xe00000d0, 3, ARM_EXT_V5E
, do_ldrd
},
9901 {"strd", 0xe00000f0, 3, ARM_EXT_V5E
, do_ldrd
},
9903 {"mcrr", 0xec400000, 4, ARM_EXT_V5E
, do_co_reg2c
},
9904 {"mrrc", 0xec500000, 4, ARM_EXT_V5E
, do_co_reg2c
},
9906 /* ARM Architecture 5TEJ. */
9907 {"bxj", 0xe12fff20, 3, ARM_EXT_V5J
, do_bxj
},
9910 { "cps", 0xf1020000, 0, ARM_EXT_V6
, do_cps
},
9911 { "cpsie", 0xf1080000, 0, ARM_EXT_V6
, do_cpsi
},
9912 { "cpsid", 0xf10C0000, 0, ARM_EXT_V6
, do_cpsi
},
9913 { "ldrex", 0xe1900f9f, 5, ARM_EXT_V6
, do_ldrex
},
9914 { "mcrr2", 0xfc400000, 0, ARM_EXT_V6
, do_co_reg2c
},
9915 { "mrrc2", 0xfc500000, 0, ARM_EXT_V6
, do_co_reg2c
},
9916 { "pkhbt", 0xe6800010, 5, ARM_EXT_V6
, do_pkhbt
},
9917 { "pkhtb", 0xe6800050, 5, ARM_EXT_V6
, do_pkhtb
},
9918 { "qadd16", 0xe6200f10, 6, ARM_EXT_V6
, do_qadd16
},
9919 { "qadd8", 0xe6200f90, 5, ARM_EXT_V6
, do_qadd16
},
9920 { "qaddsubx", 0xe6200f30, 8, ARM_EXT_V6
, do_qadd16
},
9921 { "qsub16", 0xe6200f70, 6, ARM_EXT_V6
, do_qadd16
},
9922 { "qsub8", 0xe6200ff0, 5, ARM_EXT_V6
, do_qadd16
},
9923 { "qsubaddx", 0xe6200f50, 8, ARM_EXT_V6
, do_qadd16
},
9924 { "sadd16", 0xe6100f10, 6, ARM_EXT_V6
, do_qadd16
},
9925 { "sadd8", 0xe6100f90, 5, ARM_EXT_V6
, do_qadd16
},
9926 { "saddsubx", 0xe6100f30, 8, ARM_EXT_V6
, do_qadd16
},
9927 { "shadd16", 0xe6300f10, 7, ARM_EXT_V6
, do_qadd16
},
9928 { "shadd8", 0xe6300f90, 6, ARM_EXT_V6
, do_qadd16
},
9929 { "shaddsubx", 0xe6300f30, 9, ARM_EXT_V6
, do_qadd16
},
9930 { "shsub16", 0xe6300f70, 7, ARM_EXT_V6
, do_qadd16
},
9931 { "shsub8", 0xe6300ff0, 6, ARM_EXT_V6
, do_qadd16
},
9932 { "shsubaddx", 0xe6300f50, 9, ARM_EXT_V6
, do_qadd16
},
9933 { "ssub16", 0xe6100f70, 6, ARM_EXT_V6
, do_qadd16
},
9934 { "ssub8", 0xe6100ff0, 5, ARM_EXT_V6
, do_qadd16
},
9935 { "ssubaddx", 0xe6100f50, 8, ARM_EXT_V6
, do_qadd16
},
9936 { "uadd16", 0xe6500f10, 6, ARM_EXT_V6
, do_qadd16
},
9937 { "uadd8", 0xe6500f90, 5, ARM_EXT_V6
, do_qadd16
},
9938 { "uaddsubx", 0xe6500f30, 8, ARM_EXT_V6
, do_qadd16
},
9939 { "uhadd16", 0xe6700f10, 7, ARM_EXT_V6
, do_qadd16
},
9940 { "uhadd8", 0xe6700f90, 6, ARM_EXT_V6
, do_qadd16
},
9941 { "uhaddsubx", 0xe6700f30, 9, ARM_EXT_V6
, do_qadd16
},
9942 { "uhsub16", 0xe6700f70, 7, ARM_EXT_V6
, do_qadd16
},
9943 { "uhsub8", 0xe6700ff0, 6, ARM_EXT_V6
, do_qadd16
},
9944 { "uhsubaddx", 0xe6700f50, 9, ARM_EXT_V6
, do_qadd16
},
9945 { "uqadd16", 0xe6600f10, 7, ARM_EXT_V6
, do_qadd16
},
9946 { "uqadd8", 0xe6600f90, 6, ARM_EXT_V6
, do_qadd16
},
9947 { "uqaddsubx", 0xe6600f30, 9, ARM_EXT_V6
, do_qadd16
},
9948 { "uqsub16", 0xe6600f70, 7, ARM_EXT_V6
, do_qadd16
},
9949 { "uqsub8", 0xe6600ff0, 6, ARM_EXT_V6
, do_qadd16
},
9950 { "uqsubaddx", 0xe6600f50, 9, ARM_EXT_V6
, do_qadd16
},
9951 { "usub16", 0xe6500f70, 6, ARM_EXT_V6
, do_qadd16
},
9952 { "usub8", 0xe6500ff0, 5, ARM_EXT_V6
, do_qadd16
},
9953 { "usubaddx", 0xe6500f50, 8, ARM_EXT_V6
, do_qadd16
},
9954 { "rev", 0xe6bf0f30, 3, ARM_EXT_V6
, do_rev
},
9955 { "rev16", 0xe6bf0fb0, 5, ARM_EXT_V6
, do_rev
},
9956 { "revsh", 0xe6ff0fb0, 5, ARM_EXT_V6
, do_rev
},
9957 { "rfeia", 0xf8900a00, 0, ARM_EXT_V6
, do_rfe
},
9958 { "rfeib", 0xf9900a00, 0, ARM_EXT_V6
, do_rfe
},
9959 { "rfeda", 0xf8100a00, 0, ARM_EXT_V6
, do_rfe
},
9960 { "rfedb", 0xf9100a00, 0, ARM_EXT_V6
, do_rfe
},
9961 { "rfefd", 0xf8900a00, 0, ARM_EXT_V6
, do_rfe
},
9962 { "rfefa", 0xf9900a00, 0, ARM_EXT_V6
, do_rfe
},
9963 { "rfeea", 0xf8100a00, 0, ARM_EXT_V6
, do_rfe
},
9964 { "rfeed", 0xf9100a00, 0, ARM_EXT_V6
, do_rfe
},
9965 { "sxtah", 0xe6b00070, 5, ARM_EXT_V6
, do_sxtah
},
9966 { "sxtab16", 0xe6800070, 7, ARM_EXT_V6
, do_sxtah
},
9967 { "sxtab", 0xe6a00070, 5, ARM_EXT_V6
, do_sxtah
},
9968 { "sxth", 0xe6bf0070, 4, ARM_EXT_V6
, do_sxth
},
9969 { "sxtb16", 0xe68f0070, 6, ARM_EXT_V6
, do_sxth
},
9970 { "sxtb", 0xe6af0070, 4, ARM_EXT_V6
, do_sxth
},
9971 { "uxtah", 0xe6f00070, 5, ARM_EXT_V6
, do_sxtah
},
9972 { "uxtab16", 0xe6c00070, 7, ARM_EXT_V6
, do_sxtah
},
9973 { "uxtab", 0xe6e00070, 5, ARM_EXT_V6
, do_sxtah
},
9974 { "uxth", 0xe6ff0070, 4, ARM_EXT_V6
, do_sxth
},
9975 { "uxtb16", 0xe6cf0070, 6, ARM_EXT_V6
, do_sxth
},
9976 { "uxtb", 0xe6ef0070, 4, ARM_EXT_V6
, do_sxth
},
9977 { "sel", 0xe68000b0, 3, ARM_EXT_V6
, do_qadd16
},
9978 { "setend", 0xf1010000, 0, ARM_EXT_V6
, do_setend
},
9979 { "smlad", 0xe7000010, 5, ARM_EXT_V6
, do_smlad
},
9980 { "smladx", 0xe7000030, 6, ARM_EXT_V6
, do_smlad
},
9981 { "smlald", 0xe7400010, 6, ARM_EXT_V6
, do_smlald
},
9982 { "smlaldx", 0xe7400030, 7, ARM_EXT_V6
, do_smlald
},
9983 { "smlsd", 0xe7000050, 5, ARM_EXT_V6
, do_smlad
},
9984 { "smlsdx", 0xe7000070, 6, ARM_EXT_V6
, do_smlad
},
9985 { "smlsld", 0xe7400050, 6, ARM_EXT_V6
, do_smlald
},
9986 { "smlsldx", 0xe7400070, 7, ARM_EXT_V6
, do_smlald
},
9987 { "smmla", 0xe7500010, 5, ARM_EXT_V6
, do_smlad
},
9988 { "smmlar", 0xe7500030, 6, ARM_EXT_V6
, do_smlad
},
9989 { "smmls", 0xe75000d0, 5, ARM_EXT_V6
, do_smlad
},
9990 { "smmlsr", 0xe75000f0, 6, ARM_EXT_V6
, do_smlad
},
9991 { "smmul", 0xe750f010, 5, ARM_EXT_V6
, do_smmul
},
9992 { "smmulr", 0xe750f030, 6, ARM_EXT_V6
, do_smmul
},
9993 { "smuad", 0xe700f010, 5, ARM_EXT_V6
, do_smmul
},
9994 { "smuadx", 0xe700f030, 6, ARM_EXT_V6
, do_smmul
},
9995 { "smusd", 0xe700f050, 5, ARM_EXT_V6
, do_smmul
},
9996 { "smusdx", 0xe700f070, 6, ARM_EXT_V6
, do_smmul
},
9997 { "srsia", 0xf8cd0500, 0, ARM_EXT_V6
, do_srs
},
9998 { "srsib", 0xf9cd0500, 0, ARM_EXT_V6
, do_srs
},
9999 { "srsda", 0xf84d0500, 0, ARM_EXT_V6
, do_srs
},
10000 { "srsdb", 0xf94d0500, 0, ARM_EXT_V6
, do_srs
},
10001 { "ssat", 0xe6a00010, 4, ARM_EXT_V6
, do_ssat
},
10002 { "ssat16", 0xe6a00f30, 6, ARM_EXT_V6
, do_ssat16
},
10003 { "strex", 0xe1800f90, 5, ARM_EXT_V6
, do_strex
},
10004 { "umaal", 0xe0400090, 5, ARM_EXT_V6
, do_umaal
},
10005 { "usad8", 0xe780f010, 5, ARM_EXT_V6
, do_smmul
},
10006 { "usada8", 0xe7800010, 6, ARM_EXT_V6
, do_smlad
},
10007 { "usat", 0xe6e00010, 4, ARM_EXT_V6
, do_usat
},
10008 { "usat16", 0xe6e00f30, 6, ARM_EXT_V6
, do_usat16
},
10011 { "clrex", 0xf57ff01f, 0, ARM_EXT_V6K
, do_empty
},
10012 { "ldrexb", 0xe1d00f9f, 6, ARM_EXT_V6K
, do_ldrex
},
10013 { "ldrexd", 0xe1b00f9f, 6, ARM_EXT_V6K
, do_ldrex
},
10014 { "ldrexh", 0xe1f00f9f, 6, ARM_EXT_V6K
, do_ldrex
},
10015 { "sev", 0xe320f004, 3, ARM_EXT_V6K
, do_empty
},
10016 { "strexb", 0xe1c00f90, 6, ARM_EXT_V6K
, do_strex
},
10017 { "strexd", 0xe1a00f90, 6, ARM_EXT_V6K
, do_strex
},
10018 { "strexh", 0xe1e00f90, 6, ARM_EXT_V6K
, do_strex
},
10019 { "wfe", 0xe320f002, 3, ARM_EXT_V6K
, do_empty
},
10020 { "wfi", 0xe320f003, 3, ARM_EXT_V6K
, do_empty
},
10021 { "yield", 0xe320f001, 5, ARM_EXT_V6K
, do_empty
},
10024 { "smi", 0xe1600070, 3, ARM_EXT_V6Z
, do_smi
},
10026 /* Core FPA instruction set (V1). */
10027 {"wfs", 0xee200110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
10028 {"rfs", 0xee300110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
10029 {"wfc", 0xee400110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
10030 {"rfc", 0xee500110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
10032 {"ldfs", 0xec100100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10033 {"ldfd", 0xec108100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10034 {"ldfe", 0xec500100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10035 {"ldfp", 0xec508100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10037 {"stfs", 0xec000100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10038 {"stfd", 0xec008100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10039 {"stfe", 0xec400100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10040 {"stfp", 0xec408100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
10042 {"mvfs", 0xee008100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10043 {"mvfsp", 0xee008120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10044 {"mvfsm", 0xee008140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10045 {"mvfsz", 0xee008160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10046 {"mvfd", 0xee008180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10047 {"mvfdp", 0xee0081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10048 {"mvfdm", 0xee0081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10049 {"mvfdz", 0xee0081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10050 {"mvfe", 0xee088100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10051 {"mvfep", 0xee088120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10052 {"mvfem", 0xee088140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10053 {"mvfez", 0xee088160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10055 {"mnfs", 0xee108100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10056 {"mnfsp", 0xee108120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10057 {"mnfsm", 0xee108140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10058 {"mnfsz", 0xee108160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10059 {"mnfd", 0xee108180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10060 {"mnfdp", 0xee1081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10061 {"mnfdm", 0xee1081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10062 {"mnfdz", 0xee1081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10063 {"mnfe", 0xee188100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10064 {"mnfep", 0xee188120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10065 {"mnfem", 0xee188140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10066 {"mnfez", 0xee188160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10068 {"abss", 0xee208100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10069 {"abssp", 0xee208120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10070 {"abssm", 0xee208140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10071 {"abssz", 0xee208160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10072 {"absd", 0xee208180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10073 {"absdp", 0xee2081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10074 {"absdm", 0xee2081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10075 {"absdz", 0xee2081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10076 {"abse", 0xee288100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10077 {"absep", 0xee288120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10078 {"absem", 0xee288140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10079 {"absez", 0xee288160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10081 {"rnds", 0xee308100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10082 {"rndsp", 0xee308120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10083 {"rndsm", 0xee308140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10084 {"rndsz", 0xee308160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10085 {"rndd", 0xee308180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10086 {"rnddp", 0xee3081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10087 {"rnddm", 0xee3081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10088 {"rnddz", 0xee3081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10089 {"rnde", 0xee388100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10090 {"rndep", 0xee388120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10091 {"rndem", 0xee388140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10092 {"rndez", 0xee388160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10094 {"sqts", 0xee408100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10095 {"sqtsp", 0xee408120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10096 {"sqtsm", 0xee408140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10097 {"sqtsz", 0xee408160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10098 {"sqtd", 0xee408180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10099 {"sqtdp", 0xee4081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10100 {"sqtdm", 0xee4081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10101 {"sqtdz", 0xee4081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10102 {"sqte", 0xee488100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10103 {"sqtep", 0xee488120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10104 {"sqtem", 0xee488140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10105 {"sqtez", 0xee488160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10107 {"logs", 0xee508100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10108 {"logsp", 0xee508120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10109 {"logsm", 0xee508140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10110 {"logsz", 0xee508160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10111 {"logd", 0xee508180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10112 {"logdp", 0xee5081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10113 {"logdm", 0xee5081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10114 {"logdz", 0xee5081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10115 {"loge", 0xee588100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10116 {"logep", 0xee588120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10117 {"logem", 0xee588140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10118 {"logez", 0xee588160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10120 {"lgns", 0xee608100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10121 {"lgnsp", 0xee608120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10122 {"lgnsm", 0xee608140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10123 {"lgnsz", 0xee608160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10124 {"lgnd", 0xee608180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10125 {"lgndp", 0xee6081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10126 {"lgndm", 0xee6081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10127 {"lgndz", 0xee6081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10128 {"lgne", 0xee688100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10129 {"lgnep", 0xee688120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10130 {"lgnem", 0xee688140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10131 {"lgnez", 0xee688160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10133 {"exps", 0xee708100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10134 {"expsp", 0xee708120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10135 {"expsm", 0xee708140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10136 {"expsz", 0xee708160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10137 {"expd", 0xee708180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10138 {"expdp", 0xee7081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10139 {"expdm", 0xee7081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10140 {"expdz", 0xee7081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10141 {"expe", 0xee788100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10142 {"expep", 0xee788120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10143 {"expem", 0xee788140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10144 {"expdz", 0xee788160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10146 {"sins", 0xee808100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10147 {"sinsp", 0xee808120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10148 {"sinsm", 0xee808140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10149 {"sinsz", 0xee808160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10150 {"sind", 0xee808180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10151 {"sindp", 0xee8081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10152 {"sindm", 0xee8081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10153 {"sindz", 0xee8081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10154 {"sine", 0xee888100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10155 {"sinep", 0xee888120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10156 {"sinem", 0xee888140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10157 {"sinez", 0xee888160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10159 {"coss", 0xee908100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10160 {"cossp", 0xee908120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10161 {"cossm", 0xee908140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10162 {"cossz", 0xee908160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10163 {"cosd", 0xee908180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10164 {"cosdp", 0xee9081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10165 {"cosdm", 0xee9081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10166 {"cosdz", 0xee9081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10167 {"cose", 0xee988100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10168 {"cosep", 0xee988120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10169 {"cosem", 0xee988140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10170 {"cosez", 0xee988160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10172 {"tans", 0xeea08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10173 {"tansp", 0xeea08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10174 {"tansm", 0xeea08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10175 {"tansz", 0xeea08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10176 {"tand", 0xeea08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10177 {"tandp", 0xeea081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10178 {"tandm", 0xeea081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10179 {"tandz", 0xeea081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10180 {"tane", 0xeea88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10181 {"tanep", 0xeea88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10182 {"tanem", 0xeea88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10183 {"tanez", 0xeea88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10185 {"asns", 0xeeb08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10186 {"asnsp", 0xeeb08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10187 {"asnsm", 0xeeb08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10188 {"asnsz", 0xeeb08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10189 {"asnd", 0xeeb08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10190 {"asndp", 0xeeb081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10191 {"asndm", 0xeeb081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10192 {"asndz", 0xeeb081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10193 {"asne", 0xeeb88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10194 {"asnep", 0xeeb88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10195 {"asnem", 0xeeb88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10196 {"asnez", 0xeeb88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10198 {"acss", 0xeec08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10199 {"acssp", 0xeec08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10200 {"acssm", 0xeec08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10201 {"acssz", 0xeec08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10202 {"acsd", 0xeec08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10203 {"acsdp", 0xeec081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10204 {"acsdm", 0xeec081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10205 {"acsdz", 0xeec081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10206 {"acse", 0xeec88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10207 {"acsep", 0xeec88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10208 {"acsem", 0xeec88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10209 {"acsez", 0xeec88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10211 {"atns", 0xeed08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10212 {"atnsp", 0xeed08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10213 {"atnsm", 0xeed08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10214 {"atnsz", 0xeed08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10215 {"atnd", 0xeed08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10216 {"atndp", 0xeed081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10217 {"atndm", 0xeed081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10218 {"atndz", 0xeed081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10219 {"atne", 0xeed88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10220 {"atnep", 0xeed88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10221 {"atnem", 0xeed88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10222 {"atnez", 0xeed88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10224 {"urds", 0xeee08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10225 {"urdsp", 0xeee08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10226 {"urdsm", 0xeee08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10227 {"urdsz", 0xeee08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10228 {"urdd", 0xeee08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10229 {"urddp", 0xeee081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10230 {"urddm", 0xeee081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10231 {"urddz", 0xeee081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10232 {"urde", 0xeee88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10233 {"urdep", 0xeee88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10234 {"urdem", 0xeee88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10235 {"urdez", 0xeee88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10237 {"nrms", 0xeef08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10238 {"nrmsp", 0xeef08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10239 {"nrmsm", 0xeef08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10240 {"nrmsz", 0xeef08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10241 {"nrmd", 0xeef08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10242 {"nrmdp", 0xeef081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10243 {"nrmdm", 0xeef081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10244 {"nrmdz", 0xeef081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10245 {"nrme", 0xeef88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10246 {"nrmep", 0xeef88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10247 {"nrmem", 0xeef88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10248 {"nrmez", 0xeef88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
10250 {"adfs", 0xee000100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10251 {"adfsp", 0xee000120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10252 {"adfsm", 0xee000140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10253 {"adfsz", 0xee000160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10254 {"adfd", 0xee000180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10255 {"adfdp", 0xee0001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10256 {"adfdm", 0xee0001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10257 {"adfdz", 0xee0001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10258 {"adfe", 0xee080100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10259 {"adfep", 0xee080120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10260 {"adfem", 0xee080140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10261 {"adfez", 0xee080160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10263 {"sufs", 0xee200100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10264 {"sufsp", 0xee200120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10265 {"sufsm", 0xee200140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10266 {"sufsz", 0xee200160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10267 {"sufd", 0xee200180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10268 {"sufdp", 0xee2001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10269 {"sufdm", 0xee2001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10270 {"sufdz", 0xee2001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10271 {"sufe", 0xee280100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10272 {"sufep", 0xee280120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10273 {"sufem", 0xee280140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10274 {"sufez", 0xee280160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10276 {"rsfs", 0xee300100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10277 {"rsfsp", 0xee300120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10278 {"rsfsm", 0xee300140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10279 {"rsfsz", 0xee300160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10280 {"rsfd", 0xee300180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10281 {"rsfdp", 0xee3001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10282 {"rsfdm", 0xee3001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10283 {"rsfdz", 0xee3001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10284 {"rsfe", 0xee380100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10285 {"rsfep", 0xee380120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10286 {"rsfem", 0xee380140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10287 {"rsfez", 0xee380160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10289 {"mufs", 0xee100100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10290 {"mufsp", 0xee100120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10291 {"mufsm", 0xee100140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10292 {"mufsz", 0xee100160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10293 {"mufd", 0xee100180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10294 {"mufdp", 0xee1001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10295 {"mufdm", 0xee1001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10296 {"mufdz", 0xee1001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10297 {"mufe", 0xee180100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10298 {"mufep", 0xee180120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10299 {"mufem", 0xee180140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10300 {"mufez", 0xee180160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10302 {"dvfs", 0xee400100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10303 {"dvfsp", 0xee400120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10304 {"dvfsm", 0xee400140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10305 {"dvfsz", 0xee400160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10306 {"dvfd", 0xee400180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10307 {"dvfdp", 0xee4001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10308 {"dvfdm", 0xee4001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10309 {"dvfdz", 0xee4001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10310 {"dvfe", 0xee480100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10311 {"dvfep", 0xee480120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10312 {"dvfem", 0xee480140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10313 {"dvfez", 0xee480160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10315 {"rdfs", 0xee500100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10316 {"rdfsp", 0xee500120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10317 {"rdfsm", 0xee500140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10318 {"rdfsz", 0xee500160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10319 {"rdfd", 0xee500180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10320 {"rdfdp", 0xee5001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10321 {"rdfdm", 0xee5001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10322 {"rdfdz", 0xee5001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10323 {"rdfe", 0xee580100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10324 {"rdfep", 0xee580120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10325 {"rdfem", 0xee580140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10326 {"rdfez", 0xee580160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10328 {"pows", 0xee600100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10329 {"powsp", 0xee600120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10330 {"powsm", 0xee600140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10331 {"powsz", 0xee600160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10332 {"powd", 0xee600180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10333 {"powdp", 0xee6001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10334 {"powdm", 0xee6001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10335 {"powdz", 0xee6001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10336 {"powe", 0xee680100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10337 {"powep", 0xee680120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10338 {"powem", 0xee680140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10339 {"powez", 0xee680160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10341 {"rpws", 0xee700100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10342 {"rpwsp", 0xee700120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10343 {"rpwsm", 0xee700140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10344 {"rpwsz", 0xee700160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10345 {"rpwd", 0xee700180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10346 {"rpwdp", 0xee7001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10347 {"rpwdm", 0xee7001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10348 {"rpwdz", 0xee7001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10349 {"rpwe", 0xee780100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10350 {"rpwep", 0xee780120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10351 {"rpwem", 0xee780140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10352 {"rpwez", 0xee780160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10354 {"rmfs", 0xee800100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10355 {"rmfsp", 0xee800120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10356 {"rmfsm", 0xee800140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10357 {"rmfsz", 0xee800160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10358 {"rmfd", 0xee800180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10359 {"rmfdp", 0xee8001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10360 {"rmfdm", 0xee8001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10361 {"rmfdz", 0xee8001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10362 {"rmfe", 0xee880100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10363 {"rmfep", 0xee880120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10364 {"rmfem", 0xee880140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10365 {"rmfez", 0xee880160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10367 {"fmls", 0xee900100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10368 {"fmlsp", 0xee900120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10369 {"fmlsm", 0xee900140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10370 {"fmlsz", 0xee900160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10371 {"fmld", 0xee900180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10372 {"fmldp", 0xee9001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10373 {"fmldm", 0xee9001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10374 {"fmldz", 0xee9001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10375 {"fmle", 0xee980100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10376 {"fmlep", 0xee980120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10377 {"fmlem", 0xee980140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10378 {"fmlez", 0xee980160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10380 {"fdvs", 0xeea00100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10381 {"fdvsp", 0xeea00120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10382 {"fdvsm", 0xeea00140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10383 {"fdvsz", 0xeea00160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10384 {"fdvd", 0xeea00180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10385 {"fdvdp", 0xeea001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10386 {"fdvdm", 0xeea001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10387 {"fdvdz", 0xeea001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10388 {"fdve", 0xeea80100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10389 {"fdvep", 0xeea80120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10390 {"fdvem", 0xeea80140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10391 {"fdvez", 0xeea80160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10393 {"frds", 0xeeb00100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10394 {"frdsp", 0xeeb00120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10395 {"frdsm", 0xeeb00140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10396 {"frdsz", 0xeeb00160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10397 {"frdd", 0xeeb00180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10398 {"frddp", 0xeeb001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10399 {"frddm", 0xeeb001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10400 {"frddz", 0xeeb001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10401 {"frde", 0xeeb80100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10402 {"frdep", 0xeeb80120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10403 {"frdem", 0xeeb80140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10404 {"frdez", 0xeeb80160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10406 {"pols", 0xeec00100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10407 {"polsp", 0xeec00120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10408 {"polsm", 0xeec00140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10409 {"polsz", 0xeec00160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10410 {"pold", 0xeec00180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10411 {"poldp", 0xeec001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10412 {"poldm", 0xeec001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10413 {"poldz", 0xeec001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10414 {"pole", 0xeec80100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10415 {"polep", 0xeec80120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10416 {"polem", 0xeec80140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10417 {"polez", 0xeec80160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
10419 {"cmf", 0xee90f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
10420 {"cmfe", 0xeed0f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
10421 {"cnf", 0xeeb0f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
10422 {"cnfe", 0xeef0f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
10423 /* The FPA10 data sheet suggests that the 'E' of cmfe/cnfe should
10424 not be an optional suffix, but part of the instruction. To be
10425 compatible, we accept either. */
10426 {"cmfe", 0xeed0f110, 4, FPU_FPA_EXT_V1
, do_fpa_cmp
},
10427 {"cnfe", 0xeef0f110, 4, FPU_FPA_EXT_V1
, do_fpa_cmp
},
10429 {"flts", 0xee000110, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10430 {"fltsp", 0xee000130, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10431 {"fltsm", 0xee000150, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10432 {"fltsz", 0xee000170, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10433 {"fltd", 0xee000190, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10434 {"fltdp", 0xee0001b0, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10435 {"fltdm", 0xee0001d0, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10436 {"fltdz", 0xee0001f0, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10437 {"flte", 0xee080110, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10438 {"fltep", 0xee080130, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10439 {"fltem", 0xee080150, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10440 {"fltez", 0xee080170, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
10442 /* The implementation of the FIX instruction is broken on some
10443 assemblers, in that it accepts a precision specifier as well as a
10444 rounding specifier, despite the fact that this is meaningless.
10445 To be more compatible, we accept it as well, though of course it
10446 does not set any bits. */
10447 {"fix", 0xee100110, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10448 {"fixp", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10449 {"fixm", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10450 {"fixz", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10451 {"fixsp", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10452 {"fixsm", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10453 {"fixsz", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10454 {"fixdp", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10455 {"fixdm", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10456 {"fixdz", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10457 {"fixep", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10458 {"fixem", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10459 {"fixez", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
10461 /* Instructions that were new with the real FPA, call them V2. */
10462 {"lfm", 0xec100200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
10463 {"lfmfd", 0xec900200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
10464 {"lfmea", 0xed100200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
10465 {"sfm", 0xec000200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
10466 {"sfmfd", 0xed000200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
10467 {"sfmea", 0xec800200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
10469 /* VFP V1xD (single precision). */
10470 /* Moves and type conversions. */
10471 {"fcpys", 0xeeb00a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10472 {"fmrs", 0xee100a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_reg_from_sp
},
10473 {"fmsr", 0xee000a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_sp_from_reg
},
10474 {"fmstat", 0xeef1fa10, 6, FPU_VFP_EXT_V1xD
, do_empty
},
10475 {"fsitos", 0xeeb80ac0, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10476 {"fuitos", 0xeeb80a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10477 {"ftosis", 0xeebd0a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10478 {"ftosizs", 0xeebd0ac0, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10479 {"ftouis", 0xeebc0a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10480 {"ftouizs", 0xeebc0ac0, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10481 {"fmrx", 0xeef00a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_reg_from_ctrl
},
10482 {"fmxr", 0xeee00a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_ctrl_from_reg
},
10484 /* Memory operations. */
10485 {"flds", 0xed100a00, 4, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldst
},
10486 {"fsts", 0xed000a00, 4, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldst
},
10487 {"fldmias", 0xec900a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
10488 {"fldmfds", 0xec900a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
10489 {"fldmdbs", 0xed300a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
10490 {"fldmeas", 0xed300a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
10491 {"fldmiax", 0xec900b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
10492 {"fldmfdx", 0xec900b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
10493 {"fldmdbx", 0xed300b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
10494 {"fldmeax", 0xed300b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
10495 {"fstmias", 0xec800a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
10496 {"fstmeas", 0xec800a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
10497 {"fstmdbs", 0xed200a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
10498 {"fstmfds", 0xed200a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
10499 {"fstmiax", 0xec800b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
10500 {"fstmeax", 0xec800b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
10501 {"fstmdbx", 0xed200b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
10502 {"fstmfdx", 0xed200b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
10504 /* Monadic operations. */
10505 {"fabss", 0xeeb00ac0, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10506 {"fnegs", 0xeeb10a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10507 {"fsqrts", 0xeeb10ac0, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10509 /* Dyadic operations. */
10510 {"fadds", 0xee300a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10511 {"fsubs", 0xee300a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10512 {"fmuls", 0xee200a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10513 {"fdivs", 0xee800a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10514 {"fmacs", 0xee000a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10515 {"fmscs", 0xee100a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10516 {"fnmuls", 0xee200a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10517 {"fnmacs", 0xee000a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10518 {"fnmscs", 0xee100a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
10521 {"fcmps", 0xeeb40a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10522 {"fcmpzs", 0xeeb50a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_compare_z
},
10523 {"fcmpes", 0xeeb40ac0, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
10524 {"fcmpezs", 0xeeb50ac0, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_compare_z
},
10526 /* VFP V1 (Double precision). */
10527 /* Moves and type conversions. */
10528 {"fcpyd", 0xeeb00b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
10529 {"fcvtds", 0xeeb70ac0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_sp_cvt
},
10530 {"fcvtsd", 0xeeb70bc0, 6, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
10531 {"fmdhr", 0xee200b10, 5, FPU_VFP_EXT_V1
, do_vfp_dp_from_reg
},
10532 {"fmdlr", 0xee000b10, 5, FPU_VFP_EXT_V1
, do_vfp_dp_from_reg
},
10533 {"fmrdh", 0xee300b10, 5, FPU_VFP_EXT_V1
, do_vfp_reg_from_dp
},
10534 {"fmrdl", 0xee100b10, 5, FPU_VFP_EXT_V1
, do_vfp_reg_from_dp
},
10535 {"fsitod", 0xeeb80bc0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_sp_cvt
},
10536 {"fuitod", 0xeeb80b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_sp_cvt
},
10537 {"ftosid", 0xeebd0b40, 6, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
10538 {"ftosizd", 0xeebd0bc0, 7, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
10539 {"ftouid", 0xeebc0b40, 6, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
10540 {"ftouizd", 0xeebc0bc0, 7, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
10542 /* Memory operations. */
10543 {"fldd", 0xed100b00, 4, FPU_VFP_EXT_V1
, do_vfp_dp_ldst
},
10544 {"fstd", 0xed000b00, 4, FPU_VFP_EXT_V1
, do_vfp_dp_ldst
},
10545 {"fldmiad", 0xec900b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
10546 {"fldmfdd", 0xec900b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
10547 {"fldmdbd", 0xed300b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
10548 {"fldmead", 0xed300b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
10549 {"fstmiad", 0xec800b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
10550 {"fstmead", 0xec800b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
10551 {"fstmdbd", 0xed200b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
10552 {"fstmfdd", 0xed200b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
10554 /* Monadic operations. */
10555 {"fabsd", 0xeeb00bc0, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
10556 {"fnegd", 0xeeb10b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
10557 {"fsqrtd", 0xeeb10bc0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
10559 /* Dyadic operations. */
10560 {"faddd", 0xee300b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10561 {"fsubd", 0xee300b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10562 {"fmuld", 0xee200b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10563 {"fdivd", 0xee800b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10564 {"fmacd", 0xee000b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10565 {"fmscd", 0xee100b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10566 {"fnmuld", 0xee200b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10567 {"fnmacd", 0xee000b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10568 {"fnmscd", 0xee100b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
10571 {"fcmpd", 0xeeb40b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
10572 {"fcmpzd", 0xeeb50b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_compare_z
},
10573 {"fcmped", 0xeeb40bc0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
10574 {"fcmpezd", 0xeeb50bc0, 7, FPU_VFP_EXT_V1
, do_vfp_dp_compare_z
},
10577 {"fmsrr", 0xec400a10, 5, FPU_VFP_EXT_V2
, do_vfp_sp2_from_reg2
},
10578 {"fmrrs", 0xec500a10, 5, FPU_VFP_EXT_V2
, do_vfp_reg2_from_sp2
},
10579 {"fmdrr", 0xec400b10, 5, FPU_VFP_EXT_V2
, do_vfp_dp_from_reg2
},
10580 {"fmrrd", 0xec500b10, 5, FPU_VFP_EXT_V2
, do_vfp_reg2_from_dp
},
10582 /* Intel XScale extensions to ARM V5 ISA. (All use CP0). */
10583 {"mia", 0xee200010, 3, ARM_CEXT_XSCALE
, do_xsc_mia
},
10584 {"miaph", 0xee280010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
10585 {"miabb", 0xee2c0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
10586 {"miabt", 0xee2d0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
10587 {"miatb", 0xee2e0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
10588 {"miatt", 0xee2f0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
10589 {"mar", 0xec400000, 3, ARM_CEXT_XSCALE
, do_xsc_mar
},
10590 {"mra", 0xec500000, 3, ARM_CEXT_XSCALE
, do_xsc_mra
},
10592 /* Intel Wireless MMX technology instructions. */
10593 {"tandcb", 0xee130130, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tandc
},
10594 {"tandch", 0xee530130, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tandc
},
10595 {"tandcw", 0xee930130, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tandc
},
10596 {"tbcstb", 0xee400010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tbcst
},
10597 {"tbcsth", 0xee400050, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tbcst
},
10598 {"tbcstw", 0xee400090, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tbcst
},
10599 {"textrcb", 0xee130170, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_textrc
},
10600 {"textrch", 0xee530170, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_textrc
},
10601 {"textrcw", 0xee930170, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_textrc
},
10602 {"textrmub", 0xee100070, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
10603 {"textrmuh", 0xee500070, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
10604 {"textrmuw", 0xee900070, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
10605 {"textrmsb", 0xee100078, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
10606 {"textrmsh", 0xee500078, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
10607 {"textrmsw", 0xee900078, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
10608 {"tinsrb", 0xee600010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tinsr
},
10609 {"tinsrh", 0xee600050, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tinsr
},
10610 {"tinsrw", 0xee600090, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tinsr
},
10611 {"tmcr", 0xee000110, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_tmcr
},
10612 {"tmcrr", 0xec400000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_tmcrr
},
10613 {"tmia", 0xee200010, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
10614 {"tmiaph", 0xee280010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
10615 {"tmiabb", 0xee2c0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
10616 {"tmiabt", 0xee2d0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
10617 {"tmiatb", 0xee2e0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
10618 {"tmiatt", 0xee2f0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
10619 {"tmovmskb", 0xee100030, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_tmovmsk
},
10620 {"tmovmskh", 0xee500030, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_tmovmsk
},
10621 {"tmovmskw", 0xee900030, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_tmovmsk
},
10622 {"tmrc", 0xee100110, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_tmrc
},
10623 {"tmrrc", 0xec500000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_tmrrc
},
10624 {"torcb", 0xee130150, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_torc
},
10625 {"torch", 0xee530150, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_torc
},
10626 {"torcw", 0xee930150, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_torc
},
10627 {"waccb", 0xee0001c0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10628 {"wacch", 0xee4001c0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10629 {"waccw", 0xee8001c0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10630 {"waddbss", 0xee300180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10631 {"waddb", 0xee000180, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10632 {"waddbus", 0xee100180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10633 {"waddhss", 0xee700180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10634 {"waddh", 0xee400180, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10635 {"waddhus", 0xee500180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10636 {"waddwss", 0xeeb00180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10637 {"waddw", 0xee800180, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10638 {"waddwus", 0xee900180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10639 {"waligni", 0xee000020, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_waligni
},
10640 {"walignr0", 0xee800020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10641 {"walignr1", 0xee900020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10642 {"walignr2", 0xeea00020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10643 {"walignr3", 0xeeb00020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10644 {"wand", 0xee200000, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10645 {"wandn", 0xee300000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10646 {"wavg2b", 0xee800000, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10647 {"wavg2br", 0xee900000, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10648 {"wavg2h", 0xeec00000, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10649 {"wavg2hr", 0xeed00000, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10650 {"wcmpeqb", 0xee000060, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10651 {"wcmpeqh", 0xee400060, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10652 {"wcmpeqw", 0xee800060, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10653 {"wcmpgtub", 0xee100060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10654 {"wcmpgtuh", 0xee500060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10655 {"wcmpgtuw", 0xee900060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10656 {"wcmpgtsb", 0xee300060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10657 {"wcmpgtsh", 0xee700060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10658 {"wcmpgtsw", 0xeeb00060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10659 {"wldrb", 0xec100000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
10660 {"wldrh", 0xec100100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
10661 {"wldrw", 0xec100200, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
10662 {"wldrd", 0xec100300, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
10663 {"wmacs", 0xee600100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10664 {"wmacsz", 0xee700100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10665 {"wmacu", 0xee400100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10666 {"wmacuz", 0xee500100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10667 {"wmadds", 0xeea00100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10668 {"wmaddu", 0xee800100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10669 {"wmaxsb", 0xee200160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10670 {"wmaxsh", 0xee600160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10671 {"wmaxsw", 0xeea00160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10672 {"wmaxub", 0xee000160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10673 {"wmaxuh", 0xee400160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10674 {"wmaxuw", 0xee800160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10675 {"wminsb", 0xee300160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10676 {"wminsh", 0xee700160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10677 {"wminsw", 0xeeb00160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10678 {"wminub", 0xee100160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10679 {"wminuh", 0xee500160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10680 {"wminuw", 0xee900160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10681 {"wmov", 0xee000000, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_wmov
},
10682 {"wmulsm", 0xee300100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10683 {"wmulsl", 0xee200100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10684 {"wmulum", 0xee100100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10685 {"wmulul", 0xee000100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10686 {"wor", 0xee000000, 3, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10687 {"wpackhss", 0xee700080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10688 {"wpackhus", 0xee500080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10689 {"wpackwss", 0xeeb00080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10690 {"wpackwus", 0xee900080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10691 {"wpackdss", 0xeef00080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10692 {"wpackdus", 0xeed00080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10693 {"wrorh", 0xee700040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10694 {"wrorhg", 0xee700148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10695 {"wrorw", 0xeeb00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10696 {"wrorwg", 0xeeb00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10697 {"wrord", 0xeef00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10698 {"wrordg", 0xeef00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10699 {"wsadb", 0xee000120, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10700 {"wsadbz", 0xee100120, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10701 {"wsadh", 0xee400120, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10702 {"wsadhz", 0xee500120, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10703 {"wshufh", 0xee0001e0, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wshufh
},
10704 {"wsllh", 0xee500040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10705 {"wsllhg", 0xee500148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10706 {"wsllw", 0xee900040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10707 {"wsllwg", 0xee900148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10708 {"wslld", 0xeed00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10709 {"wslldg", 0xeed00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10710 {"wsrah", 0xee400040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10711 {"wsrahg", 0xee400148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10712 {"wsraw", 0xee800040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10713 {"wsrawg", 0xee800148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10714 {"wsrad", 0xeec00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10715 {"wsradg", 0xeec00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10716 {"wsrlh", 0xee600040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10717 {"wsrlhg", 0xee600148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10718 {"wsrlw", 0xeea00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10719 {"wsrlwg", 0xeea00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10720 {"wsrld", 0xeee00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10721 {"wsrldg", 0xeee00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
10722 {"wstrb", 0xec000000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
10723 {"wstrh", 0xec000100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
10724 {"wstrw", 0xec000200, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
10725 {"wstrd", 0xec000300, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
10726 {"wsubbss", 0xee3001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10727 {"wsubb", 0xee0001a0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10728 {"wsubbus", 0xee1001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10729 {"wsubhss", 0xee7001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10730 {"wsubh", 0xee4001a0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10731 {"wsubhus", 0xee5001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10732 {"wsubwss", 0xeeb001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10733 {"wsubw", 0xee8001a0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10734 {"wsubwus", 0xee9001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10735 {"wunpckehub", 0xee0000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10736 {"wunpckehuh", 0xee4000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10737 {"wunpckehuw", 0xee8000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10738 {"wunpckehsb", 0xee2000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10739 {"wunpckehsh", 0xee6000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10740 {"wunpckehsw", 0xeea000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10741 {"wunpckihb", 0xee1000c0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10742 {"wunpckihh", 0xee5000c0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10743 {"wunpckihw", 0xee9000c0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10744 {"wunpckelub", 0xee0000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10745 {"wunpckeluh", 0xee4000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10746 {"wunpckeluw", 0xee8000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10747 {"wunpckelsb", 0xee2000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10748 {"wunpckelsh", 0xee6000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10749 {"wunpckelsw", 0xeea000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
10750 {"wunpckilb", 0xee1000e0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10751 {"wunpckilh", 0xee5000e0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10752 {"wunpckilw", 0xee9000e0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10753 {"wxor", 0xee100000, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
10754 {"wzero", 0xee300000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wzero
},
10756 /* Cirrus Maverick instructions. */
10757 {"cfldrs", 0xec100400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_1
},
10758 {"cfldrd", 0xec500400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_2
},
10759 {"cfldr32", 0xec100500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_3
},
10760 {"cfldr64", 0xec500500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_4
},
10761 {"cfstrs", 0xec000400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_1
},
10762 {"cfstrd", 0xec400400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_2
},
10763 {"cfstr32", 0xec000500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_3
},
10764 {"cfstr64", 0xec400500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_4
},
10765 {"cfmvsr", 0xee000450, 6, ARM_CEXT_MAVERICK
, do_mav_binops_2a
},
10766 {"cfmvrs", 0xee100450, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1a
},
10767 {"cfmvdlr", 0xee000410, 7, ARM_CEXT_MAVERICK
, do_mav_binops_2b
},
10768 {"cfmvrdl", 0xee100410, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1b
},
10769 {"cfmvdhr", 0xee000430, 7, ARM_CEXT_MAVERICK
, do_mav_binops_2b
},
10770 {"cfmvrdh", 0xee100430, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1b
},
10771 {"cfmv64lr", 0xee000510, 8, ARM_CEXT_MAVERICK
, do_mav_binops_2c
},
10772 {"cfmvr64l", 0xee100510, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1c
},
10773 {"cfmv64hr", 0xee000530, 8, ARM_CEXT_MAVERICK
, do_mav_binops_2c
},
10774 {"cfmvr64h", 0xee100530, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1c
},
10775 {"cfmval32", 0xee200440, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
10776 {"cfmv32al", 0xee100440, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
10777 {"cfmvam32", 0xee200460, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
10778 {"cfmv32am", 0xee100460, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
10779 {"cfmvah32", 0xee200480, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
10780 {"cfmv32ah", 0xee100480, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
10781 {"cfmva32", 0xee2004a0, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
10782 {"cfmv32a", 0xee1004a0, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
10783 {"cfmva64", 0xee2004c0, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3c
},
10784 {"cfmv64a", 0xee1004c0, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3d
},
10785 {"cfmvsc32", 0xee2004e0, 8, ARM_CEXT_MAVERICK
, do_mav_dspsc_1
},
10786 {"cfmv32sc", 0xee1004e0, 8, ARM_CEXT_MAVERICK
, do_mav_dspsc_2
},
10787 {"cfcpys", 0xee000400, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1d
},
10788 {"cfcpyd", 0xee000420, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1e
},
10789 {"cfcvtsd", 0xee000460, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1f
},
10790 {"cfcvtds", 0xee000440, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1g
},
10791 {"cfcvt32s", 0xee000480, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1h
},
10792 {"cfcvt32d", 0xee0004a0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1i
},
10793 {"cfcvt64s", 0xee0004c0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1j
},
10794 {"cfcvt64d", 0xee0004e0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1k
},
10795 {"cfcvts32", 0xee100580, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1l
},
10796 {"cfcvtd32", 0xee1005a0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1m
},
10797 {"cftruncs32", 0xee1005c0, 10, ARM_CEXT_MAVERICK
, do_mav_binops_1l
},
10798 {"cftruncd32", 0xee1005e0, 10, ARM_CEXT_MAVERICK
, do_mav_binops_1m
},
10799 {"cfrshl32", 0xee000550, 8, ARM_CEXT_MAVERICK
, do_mav_triple_4a
},
10800 {"cfrshl64", 0xee000570, 8, ARM_CEXT_MAVERICK
, do_mav_triple_4b
},
10801 {"cfsh32", 0xee000500, 6, ARM_CEXT_MAVERICK
, do_mav_shift_1
},
10802 {"cfsh64", 0xee200500, 6, ARM_CEXT_MAVERICK
, do_mav_shift_2
},
10803 {"cfcmps", 0xee100490, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5a
},
10804 {"cfcmpd", 0xee1004b0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5b
},
10805 {"cfcmp32", 0xee100590, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5c
},
10806 {"cfcmp64", 0xee1005b0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5d
},
10807 {"cfabss", 0xee300400, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1d
},
10808 {"cfabsd", 0xee300420, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1e
},
10809 {"cfnegs", 0xee300440, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1d
},
10810 {"cfnegd", 0xee300460, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1e
},
10811 {"cfadds", 0xee300480, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5e
},
10812 {"cfaddd", 0xee3004a0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5f
},
10813 {"cfsubs", 0xee3004c0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5e
},
10814 {"cfsubd", 0xee3004e0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5f
},
10815 {"cfmuls", 0xee100400, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5e
},
10816 {"cfmuld", 0xee100420, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5f
},
10817 {"cfabs32", 0xee300500, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1n
},
10818 {"cfabs64", 0xee300520, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1o
},
10819 {"cfneg32", 0xee300540, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1n
},
10820 {"cfneg64", 0xee300560, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1o
},
10821 {"cfadd32", 0xee300580, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
10822 {"cfadd64", 0xee3005a0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5h
},
10823 {"cfsub32", 0xee3005c0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
10824 {"cfsub64", 0xee3005e0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5h
},
10825 {"cfmul32", 0xee100500, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
10826 {"cfmul64", 0xee100520, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5h
},
10827 {"cfmac32", 0xee100540, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
10828 {"cfmsc32", 0xee100560, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
10829 {"cfmadd32", 0xee000600, 8, ARM_CEXT_MAVERICK
, do_mav_quad_6a
},
10830 {"cfmsub32", 0xee100600, 8, ARM_CEXT_MAVERICK
, do_mav_quad_6a
},
10831 {"cfmadda32", 0xee200600, 9, ARM_CEXT_MAVERICK
, do_mav_quad_6b
},
10832 {"cfmsuba32", 0xee300600, 9, ARM_CEXT_MAVERICK
, do_mav_quad_6b
},
10835 /* Iterate over the base tables to create the instruction patterns. */
10838 build_arm_ops_hsh (void)
10842 static struct obstack insn_obstack
;
10844 obstack_begin (&insn_obstack
, 4000);
10846 for (i
= 0; i
< sizeof (insns
) / sizeof (struct asm_opcode
); i
++)
10848 const struct asm_opcode
*insn
= insns
+ i
;
10850 if (insn
->cond_offset
!= 0)
10852 /* Insn supports conditional execution. Build the varaints
10853 and insert them in the hash table. */
10854 for (j
= 0; j
< sizeof (conds
) / sizeof (struct asm_cond
); j
++)
10856 unsigned len
= strlen (insn
->template);
10857 struct asm_opcode
*new;
10860 new = obstack_alloc (&insn_obstack
, sizeof (struct asm_opcode
));
10861 /* All condition codes are two characters. */
10862 template = obstack_alloc (&insn_obstack
, len
+ 3);
10864 strncpy (template, insn
->template, insn
->cond_offset
);
10865 strcpy (template + insn
->cond_offset
, conds
[j
].template);
10866 if (len
> insn
->cond_offset
)
10867 strcpy (template + insn
->cond_offset
+ 2,
10868 insn
->template + insn
->cond_offset
);
10869 new->template = template;
10870 new->cond_offset
= 0;
10871 new->variant
= insn
->variant
;
10872 new->parms
= insn
->parms
;
10873 new->value
= (insn
->value
& ~COND_MASK
) | conds
[j
].value
;
10875 hash_insert (arm_ops_hsh
, new->template, (PTR
) new);
10878 /* Finally, insert the unconditional insn in the table directly;
10879 no need to build a copy. */
10880 hash_insert (arm_ops_hsh
, insn
->template, (PTR
) insn
);
10884 #if 0 /* Suppressed - for now. */
10885 #if defined OBJ_ELF || defined OBJ_COFF
10888 #define arm_Note Elf_External_Note
10892 unsigned char namesz
[4]; /* Size of entry's owner string. */
10893 unsigned char descsz
[4]; /* Size of the note descriptor. */
10894 unsigned char type
[4]; /* Interpretation of the descriptor. */
10895 char name
[1]; /* Start of the name+desc data. */
10899 /* The description is kept to a fix sized in order to make updating
10900 it and merging it easier. */
10901 #define ARM_NOTE_DESCRIPTION_LENGTH 8
10904 arm_add_note (const char * name
,
10905 const char * description
,
10908 arm_Note note ATTRIBUTE_UNUSED
;
10910 unsigned int name_len
;
10912 name_len
= (strlen (name
) + 1 + 3) & ~3;
10914 p
= frag_more (sizeof (note
.namesz
));
10915 md_number_to_chars (p
, (valueT
) name_len
, sizeof (note
.namesz
));
10917 p
= frag_more (sizeof (note
.descsz
));
10918 md_number_to_chars (p
, (valueT
) ARM_NOTE_DESCRIPTION_LENGTH
, sizeof (note
.descsz
));
10920 p
= frag_more (sizeof (note
.type
));
10921 md_number_to_chars (p
, (valueT
) type
, sizeof (note
.type
));
10923 p
= frag_more (name_len
);
10926 p
= frag_more (ARM_NOTE_DESCRIPTION_LENGTH
);
10927 strncpy (p
, description
, ARM_NOTE_DESCRIPTION_LENGTH
);
10928 frag_align (2, 0, 0);
10934 static const struct thumb_opcode tinsns
[] =
10936 /* Thumb v1 (ARMv4T). */
10937 {"adc", 0x4140, 2, ARM_EXT_V4T
, do_t_arit
},
10938 {"add", 0x0000, 2, ARM_EXT_V4T
, do_t_add
},
10939 {"and", 0x4000, 2, ARM_EXT_V4T
, do_t_arit
},
10940 {"asr", 0x0000, 2, ARM_EXT_V4T
, do_t_asr
},
10941 {"b", T_OPCODE_BRANCH
, 2, ARM_EXT_V4T
, do_t_branch12
},
10942 {"beq", 0xd0fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10943 {"bne", 0xd1fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10944 {"bcs", 0xd2fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10945 {"bhs", 0xd2fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10946 {"bcc", 0xd3fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10947 {"bul", 0xd3fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10948 {"blo", 0xd3fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10949 {"bmi", 0xd4fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10950 {"bpl", 0xd5fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10951 {"bvs", 0xd6fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10952 {"bvc", 0xd7fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10953 {"bhi", 0xd8fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10954 {"bls", 0xd9fe, 2, ARM_EXT_V4T
, do_t_branch9
},
10955 {"bge", 0xdafe, 2, ARM_EXT_V4T
, do_t_branch9
},
10956 {"blt", 0xdbfe, 2, ARM_EXT_V4T
, do_t_branch9
},
10957 {"bgt", 0xdcfe, 2, ARM_EXT_V4T
, do_t_branch9
},
10958 {"ble", 0xddfe, 2, ARM_EXT_V4T
, do_t_branch9
},
10959 {"bal", 0xdefe, 2, ARM_EXT_V4T
, do_t_branch9
},
10960 {"bic", 0x4380, 2, ARM_EXT_V4T
, do_t_arit
},
10961 {"bl", 0xf7fffffe, 4, ARM_EXT_V4T
, do_t_branch23
},
10962 {"bx", 0x4700, 2, ARM_EXT_V4T
, do_t_bx
},
10963 {"cmn", T_OPCODE_CMN
, 2, ARM_EXT_V4T
, do_t_arit
},
10964 {"cmp", 0x0000, 2, ARM_EXT_V4T
, do_t_compare
},
10965 {"eor", 0x4040, 2, ARM_EXT_V4T
, do_t_arit
},
10966 {"ldmia", 0xc800, 2, ARM_EXT_V4T
, do_t_ldmstm
},
10967 {"ldr", 0x0000, 2, ARM_EXT_V4T
, do_t_ldr
},
10968 {"ldrb", 0x0000, 2, ARM_EXT_V4T
, do_t_ldrb
},
10969 {"ldrh", 0x0000, 2, ARM_EXT_V4T
, do_t_ldrh
},
10970 {"ldrsb", 0x5600, 2, ARM_EXT_V4T
, do_t_lds
},
10971 {"ldrsh", 0x5e00, 2, ARM_EXT_V4T
, do_t_lds
},
10972 {"ldsb", 0x5600, 2, ARM_EXT_V4T
, do_t_lds
},
10973 {"ldsh", 0x5e00, 2, ARM_EXT_V4T
, do_t_lds
},
10974 {"lsl", 0x0000, 2, ARM_EXT_V4T
, do_t_lsl
},
10975 {"lsr", 0x0000, 2, ARM_EXT_V4T
, do_t_lsr
},
10976 {"mov", 0x0000, 2, ARM_EXT_V4T
, do_t_mov
},
10977 {"mul", T_OPCODE_MUL
, 2, ARM_EXT_V4T
, do_t_arit
},
10978 {"mvn", T_OPCODE_MVN
, 2, ARM_EXT_V4T
, do_t_arit
},
10979 {"neg", T_OPCODE_NEG
, 2, ARM_EXT_V4T
, do_t_arit
},
10980 {"orr", 0x4300, 2, ARM_EXT_V4T
, do_t_arit
},
10981 {"pop", 0xbc00, 2, ARM_EXT_V4T
, do_t_push_pop
},
10982 {"push", 0xb400, 2, ARM_EXT_V4T
, do_t_push_pop
},
10983 {"ror", 0x41c0, 2, ARM_EXT_V4T
, do_t_arit
},
10984 {"sbc", 0x4180, 2, ARM_EXT_V4T
, do_t_arit
},
10985 {"stmia", 0xc000, 2, ARM_EXT_V4T
, do_t_ldmstm
},
10986 {"str", 0x0000, 2, ARM_EXT_V4T
, do_t_str
},
10987 {"strb", 0x0000, 2, ARM_EXT_V4T
, do_t_strb
},
10988 {"strh", 0x0000, 2, ARM_EXT_V4T
, do_t_strh
},
10989 {"swi", 0xdf00, 2, ARM_EXT_V4T
, do_t_swi
},
10990 {"sub", 0x0000, 2, ARM_EXT_V4T
, do_t_sub
},
10991 {"tst", T_OPCODE_TST
, 2, ARM_EXT_V4T
, do_t_arit
},
10993 {"adr", 0x0000, 2, ARM_EXT_V4T
, do_t_adr
},
10994 {"nop", 0x46C0, 2, ARM_EXT_V4T
, do_t_nop
}, /* mov r8,r8 */
10995 /* Thumb v2 (ARMv5T). */
10996 {"blx", 0, 0, ARM_EXT_V5T
, do_t_blx
},
10997 {"bkpt", 0xbe00, 2, ARM_EXT_V5T
, do_t_bkpt
},
11000 {"cpsie", 0xb660, 2, ARM_EXT_V6
, do_t_cps
},
11001 {"cpsid", 0xb670, 2, ARM_EXT_V6
, do_t_cps
},
11002 {"cpy", 0x4600, 2, ARM_EXT_V6
, do_t_cpy
},
11003 {"rev", 0xba00, 2, ARM_EXT_V6
, do_t_arit
},
11004 {"rev16", 0xba40, 2, ARM_EXT_V6
, do_t_arit
},
11005 {"revsh", 0xbac0, 2, ARM_EXT_V6
, do_t_arit
},
11006 {"setend", 0xb650, 2, ARM_EXT_V6
, do_t_setend
},
11007 {"sxth", 0xb200, 2, ARM_EXT_V6
, do_t_arit
},
11008 {"sxtb", 0xb240, 2, ARM_EXT_V6
, do_t_arit
},
11009 {"uxth", 0xb280, 2, ARM_EXT_V6
, do_t_arit
},
11010 {"uxtb", 0xb2c0, 2, ARM_EXT_V6
, do_t_arit
},
11019 if ( (arm_ops_hsh
= hash_new ()) == NULL
11020 || (arm_tops_hsh
= hash_new ()) == NULL
11021 || (arm_cond_hsh
= hash_new ()) == NULL
11022 || (arm_shift_hsh
= hash_new ()) == NULL
11023 || (arm_psr_hsh
= hash_new ()) == NULL
)
11024 as_fatal (_("virtual memory exhausted"));
11026 build_arm_ops_hsh ();
11027 for (i
= 0; i
< sizeof (tinsns
) / sizeof (struct thumb_opcode
); i
++)
11028 hash_insert (arm_tops_hsh
, tinsns
[i
].template, (PTR
) (tinsns
+ i
));
11029 for (i
= 0; i
< sizeof (conds
) / sizeof (struct asm_cond
); i
++)
11030 hash_insert (arm_cond_hsh
, conds
[i
].template, (PTR
) (conds
+ i
));
11031 for (i
= 0; i
< sizeof (shift_names
) / sizeof (struct asm_shift_name
); i
++)
11032 hash_insert (arm_shift_hsh
, shift_names
[i
].name
, (PTR
) (shift_names
+ i
));
11033 for (i
= 0; i
< sizeof (psrs
) / sizeof (struct asm_psr
); i
++)
11034 hash_insert (arm_psr_hsh
, psrs
[i
].template, (PTR
) (psrs
+ i
));
11036 for (i
= (int) REG_TYPE_FIRST
; i
< (int) REG_TYPE_MAX
; i
++)
11037 build_reg_hsh (all_reg_maps
+ i
);
11039 set_constant_flonums ();
11041 /* Set the cpu variant based on the command-line options. We prefer
11042 -mcpu= over -march= if both are set (as for GCC); and we prefer
11043 -mfpu= over any other way of setting the floating point unit.
11044 Use of legacy options with new options are faulted. */
11045 if (legacy_cpu
!= -1)
11047 if (mcpu_cpu_opt
!= -1 || march_cpu_opt
!= -1)
11048 as_bad (_("use of old and new-style options to set CPU type"));
11050 mcpu_cpu_opt
= legacy_cpu
;
11052 else if (mcpu_cpu_opt
== -1)
11053 mcpu_cpu_opt
= march_cpu_opt
;
11055 if (legacy_fpu
!= -1)
11057 if (mfpu_opt
!= -1)
11058 as_bad (_("use of old and new-style options to set FPU type"));
11060 mfpu_opt
= legacy_fpu
;
11062 else if (mfpu_opt
== -1)
11064 #if !(defined (TE_LINUX) || defined (TE_NetBSD))
11065 /* Some environments specify a default FPU. If they don't, infer it
11066 from the processor. */
11067 if (mcpu_fpu_opt
!= -1)
11068 mfpu_opt
= mcpu_fpu_opt
;
11070 mfpu_opt
= march_fpu_opt
;
11072 mfpu_opt
= FPU_DEFAULT
;
11076 if (mfpu_opt
== -1)
11078 if (mcpu_cpu_opt
== -1)
11079 mfpu_opt
= FPU_DEFAULT
;
11080 else if (mcpu_cpu_opt
& ARM_EXT_V5
)
11081 mfpu_opt
= FPU_ARCH_VFP_V2
;
11083 mfpu_opt
= FPU_ARCH_FPA
;
11086 if (mcpu_cpu_opt
== -1)
11087 mcpu_cpu_opt
= CPU_DEFAULT
;
11089 cpu_variant
= mcpu_cpu_opt
| mfpu_opt
;
11092 unsigned int flags
= 0;
11094 #if defined OBJ_ELF
11095 flags
= meabi_flags
;
11097 switch (meabi_flags
)
11099 case EF_ARM_EABI_UNKNOWN
:
11101 #if defined OBJ_COFF || defined OBJ_ELF
11102 /* Set the flags in the private structure. */
11103 if (uses_apcs_26
) flags
|= F_APCS26
;
11104 if (support_interwork
) flags
|= F_INTERWORK
;
11105 if (uses_apcs_float
) flags
|= F_APCS_FLOAT
;
11106 if (pic_code
) flags
|= F_PIC
;
11107 if ((cpu_variant
& FPU_ANY
) == FPU_NONE
11108 || (cpu_variant
& FPU_ANY
) == FPU_ARCH_VFP
) /* VFP layout only. */
11109 flags
|= F_SOFT_FLOAT
;
11111 switch (mfloat_abi_opt
)
11113 case ARM_FLOAT_ABI_SOFT
:
11114 case ARM_FLOAT_ABI_SOFTFP
:
11115 flags
|= F_SOFT_FLOAT
;
11118 case ARM_FLOAT_ABI_HARD
:
11119 if (flags
& F_SOFT_FLOAT
)
11120 as_bad (_("hard-float conflicts with specified fpu"));
11124 /* Using VFP conventions (even if soft-float). */
11125 if (cpu_variant
& FPU_VFP_EXT_NONE
)
11126 flags
|= F_VFP_FLOAT
;
11128 #if defined OBJ_ELF
11129 if (cpu_variant
& FPU_ARCH_MAVERICK
)
11130 flags
|= EF_ARM_MAVERICK_FLOAT
;
11133 case EF_ARM_EABI_VER3
:
11134 /* No additional flags to set. */
11141 #if defined OBJ_COFF || defined OBJ_ELF
11142 bfd_set_private_flags (stdoutput
, flags
);
11144 /* We have run out flags in the COFF header to encode the
11145 status of ATPCS support, so instead we create a dummy,
11146 empty, debug section called .arm.atpcs. */
11151 sec
= bfd_make_section (stdoutput
, ".arm.atpcs");
11155 bfd_set_section_flags
11156 (stdoutput
, sec
, SEC_READONLY
| SEC_DEBUGGING
/* | SEC_HAS_CONTENTS */);
11157 bfd_set_section_size (stdoutput
, sec
, 0);
11158 bfd_set_section_contents (stdoutput
, sec
, NULL
, 0, 0);
11164 /* Record the CPU type as well. */
11165 switch (cpu_variant
& ARM_CPU_MASK
)
11168 mach
= bfd_mach_arm_2
;
11171 case ARM_3
: /* Also ARM_250. */
11172 mach
= bfd_mach_arm_2a
;
11175 case ARM_6
: /* Also ARM_7. */
11176 mach
= bfd_mach_arm_3
;
11180 mach
= bfd_mach_arm_unknown
;
11184 /* Catch special cases. */
11185 if (cpu_variant
& ARM_CEXT_IWMMXT
)
11186 mach
= bfd_mach_arm_iWMMXt
;
11187 else if (cpu_variant
& ARM_CEXT_XSCALE
)
11188 mach
= bfd_mach_arm_XScale
;
11189 else if (cpu_variant
& ARM_CEXT_MAVERICK
)
11190 mach
= bfd_mach_arm_ep9312
;
11191 else if (cpu_variant
& ARM_EXT_V5E
)
11192 mach
= bfd_mach_arm_5TE
;
11193 else if (cpu_variant
& ARM_EXT_V5
)
11195 if (cpu_variant
& ARM_EXT_V4T
)
11196 mach
= bfd_mach_arm_5T
;
11198 mach
= bfd_mach_arm_5
;
11200 else if (cpu_variant
& ARM_EXT_V4
)
11202 if (cpu_variant
& ARM_EXT_V4T
)
11203 mach
= bfd_mach_arm_4T
;
11205 mach
= bfd_mach_arm_4
;
11207 else if (cpu_variant
& ARM_EXT_V3M
)
11208 mach
= bfd_mach_arm_3M
;
11210 #if 0 /* Suppressed - for now. */
11211 #if defined (OBJ_ELF) || defined (OBJ_COFF)
11213 /* Create a .note section to fully identify this arm binary. */
11215 #define NOTE_ARCH_STRING "arch: "
11217 #if defined OBJ_COFF && ! defined NT_VERSION
11218 #define NT_VERSION 1
11223 segT current_seg
= now_seg
;
11224 subsegT current_subseg
= now_subseg
;
11225 asection
* arm_arch
;
11226 const char * arch_string
;
11228 arm_arch
= bfd_make_section_old_way (stdoutput
, ARM_NOTE_SECTION
);
11231 bfd_set_section_flags (stdoutput
, arm_arch
,
11232 SEC_DATA
| SEC_ALLOC
| SEC_LOAD
| SEC_LINK_ONCE \
11233 | SEC_HAS_CONTENTS
);
11235 bfd_set_section_flags (stdoutput
, arm_arch
,
11236 SEC_READONLY
| SEC_HAS_CONTENTS
);
11238 arm_arch
->output_section
= arm_arch
;
11239 subseg_set (arm_arch
, 0);
11244 case bfd_mach_arm_unknown
: arch_string
= "unknown"; break;
11245 case bfd_mach_arm_2
: arch_string
= "armv2"; break;
11246 case bfd_mach_arm_2a
: arch_string
= "armv2a"; break;
11247 case bfd_mach_arm_3
: arch_string
= "armv3"; break;
11248 case bfd_mach_arm_3M
: arch_string
= "armv3M"; break;
11249 case bfd_mach_arm_4
: arch_string
= "armv4"; break;
11250 case bfd_mach_arm_4T
: arch_string
= "armv4t"; break;
11251 case bfd_mach_arm_5
: arch_string
= "armv5"; break;
11252 case bfd_mach_arm_5T
: arch_string
= "armv5t"; break;
11253 case bfd_mach_arm_5TE
: arch_string
= "armv5te"; break;
11254 case bfd_mach_arm_XScale
: arch_string
= "XScale"; break;
11255 case bfd_mach_arm_ep9312
: arch_string
= "ep9312"; break;
11256 case bfd_mach_arm_iWMMXt
: arch_string
= "iWMMXt"; break;
11259 arm_add_note (NOTE_ARCH_STRING
, arch_string
, NT_ARCH
);
11261 subseg_set (current_seg
, current_subseg
);
11264 #endif /* Suppressed code. */
11266 bfd_set_arch_mach (stdoutput
, TARGET_ARCH
, mach
);
11269 /* Turn an integer of n bytes (in val) into a stream of bytes appropriate
11270 for use in the a.out file, and stores them in the array pointed to by buf.
11271 This knows about the endian-ness of the target machine and does
11272 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
11273 2 (short) and 4 (long) Floating numbers are put out as a series of
11274 LITTLENUMS (shorts, here at least). */
11277 md_number_to_chars (char * buf
, valueT val
, int n
)
11279 if (target_big_endian
)
11280 number_to_chars_bigendian (buf
, val
, n
);
11282 number_to_chars_littleendian (buf
, val
, n
);
11286 md_chars_to_number (char * buf
, int n
)
11289 unsigned char * where
= (unsigned char *) buf
;
11291 if (target_big_endian
)
11296 result
|= (*where
++ & 255);
11304 result
|= (where
[n
] & 255);
11311 /* Turn a string in input_line_pointer into a floating point constant
11312 of type TYPE, and store the appropriate bytes in *LITP. The number
11313 of LITTLENUMS emitted is stored in *SIZEP. An error message is
11314 returned, or NULL on OK.
11316 Note that fp constants aren't represent in the normal way on the ARM.
11317 In big endian mode, things are as expected. However, in little endian
11318 mode fp constants are big-endian word-wise, and little-endian byte-wise
11319 within the words. For example, (double) 1.1 in big endian mode is
11320 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
11321 the byte sequence 99 99 f1 3f 9a 99 99 99.
11323 ??? The format of 12 byte floats is uncertain according to gcc's arm.h. */
11326 md_atof (int type
, char * litP
, int * sizeP
)
11329 LITTLENUM_TYPE words
[MAX_LITTLENUMS
];
11361 return _("bad call to MD_ATOF()");
11364 t
= atof_ieee (input_line_pointer
, type
, words
);
11366 input_line_pointer
= t
;
11369 if (target_big_endian
)
11371 for (i
= 0; i
< prec
; i
++)
11373 md_number_to_chars (litP
, (valueT
) words
[i
], 2);
11379 if (cpu_variant
& FPU_ARCH_VFP
)
11380 for (i
= prec
- 1; i
>= 0; i
--)
11382 md_number_to_chars (litP
, (valueT
) words
[i
], 2);
11386 /* For a 4 byte float the order of elements in `words' is 1 0.
11387 For an 8 byte float the order is 1 0 3 2. */
11388 for (i
= 0; i
< prec
; i
+= 2)
11390 md_number_to_chars (litP
, (valueT
) words
[i
+ 1], 2);
11391 md_number_to_chars (litP
+ 2, (valueT
) words
[i
], 2);
11399 /* The knowledge of the PC's pipeline offset is built into the insns
11403 md_pcrel_from (fixS
* fixP
)
11406 && S_GET_SEGMENT (fixP
->fx_addsy
) == undefined_section
11407 && fixP
->fx_subsy
== NULL
)
11410 if (fixP
->fx_pcrel
&& (fixP
->fx_r_type
== BFD_RELOC_ARM_THUMB_ADD
))
11412 /* PC relative addressing on the Thumb is slightly odd
11413 as the bottom two bits of the PC are forced to zero
11414 for the calculation. */
11415 return (fixP
->fx_where
+ fixP
->fx_frag
->fr_address
) & ~3;
11419 /* The pattern was adjusted to accommodate CE's off-by-one fixups,
11420 so we un-adjust here to compensate for the accommodation. */
11421 return fixP
->fx_where
+ fixP
->fx_frag
->fr_address
+ 8;
11423 return fixP
->fx_where
+ fixP
->fx_frag
->fr_address
;
11427 /* Round up a section size to the appropriate boundary. */
11430 md_section_align (segT segment ATTRIBUTE_UNUSED
,
11436 /* Round all sects to multiple of 4. */
11437 return (size
+ 3) & ~3;
11441 /* Under ELF we need to default _GLOBAL_OFFSET_TABLE.
11442 Otherwise we have no need to default values of symbols. */
11445 md_undefined_symbol (char * name ATTRIBUTE_UNUSED
)
11448 if (name
[0] == '_' && name
[1] == 'G'
11449 && streq (name
, GLOBAL_OFFSET_TABLE_NAME
))
11453 if (symbol_find (name
))
11454 as_bad ("GOT already in the symbol table");
11456 GOT_symbol
= symbol_new (name
, undefined_section
,
11457 (valueT
) 0, & zero_address_frag
);
11468 md_apply_fix3 (fixS
* fixP
,
11472 offsetT value
= * valP
;
11474 unsigned int newimm
;
11475 unsigned long temp
;
11477 char * buf
= fixP
->fx_where
+ fixP
->fx_frag
->fr_literal
;
11478 arm_fix_data
* arm_data
= (arm_fix_data
*) fixP
->tc_fix_data
;
11480 assert (fixP
->fx_r_type
< BFD_RELOC_UNUSED
);
11482 /* Note whether this will delete the relocation. */
11484 /* Patch from REarnshaw to JDavis (disabled for the moment, since it
11485 doesn't work fully.) */
11486 if ((fixP
->fx_addsy
== 0 || symbol_constant_p (fixP
->fx_addsy
))
11487 && !fixP
->fx_pcrel
)
11489 if (fixP
->fx_addsy
== 0 && !fixP
->fx_pcrel
)
11493 /* If this symbol is in a different section then we need to leave it for
11494 the linker to deal with. Unfortunately, md_pcrel_from can't tell,
11495 so we have to undo it's effects here. */
11496 if (fixP
->fx_pcrel
)
11498 if (fixP
->fx_addsy
!= NULL
11499 && S_IS_DEFINED (fixP
->fx_addsy
)
11500 && S_GET_SEGMENT (fixP
->fx_addsy
) != seg
)
11503 && (fixP
->fx_r_type
== BFD_RELOC_ARM_PCREL_BRANCH
11504 || fixP
->fx_r_type
== BFD_RELOC_ARM_PCREL_BLX
11508 value
+= md_pcrel_from (fixP
);
11512 /* Remember value for emit_reloc. */
11513 fixP
->fx_addnumber
= value
;
11515 switch (fixP
->fx_r_type
)
11517 case BFD_RELOC_ARM_IMMEDIATE
:
11518 /* We claim that this fixup has been processed here,
11519 even if in fact we generate an error because we do
11520 not have a reloc for it, so tc_gen_reloc will reject it. */
11524 && ! S_IS_DEFINED (fixP
->fx_addsy
))
11526 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11527 _("undefined symbol %s used as an immediate value"),
11528 S_GET_NAME (fixP
->fx_addsy
));
11532 newimm
= validate_immediate (value
);
11533 temp
= md_chars_to_number (buf
, INSN_SIZE
);
11535 /* If the instruction will fail, see if we can fix things up by
11536 changing the opcode. */
11537 if (newimm
== (unsigned int) FAIL
11538 && (newimm
= negate_data_op (&temp
, value
)) == (unsigned int) FAIL
)
11540 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11541 _("invalid constant (%lx) after fixup"),
11542 (unsigned long) value
);
11546 newimm
|= (temp
& 0xfffff000);
11547 md_number_to_chars (buf
, (valueT
) newimm
, INSN_SIZE
);
11550 case BFD_RELOC_ARM_ADRL_IMMEDIATE
:
11552 unsigned int highpart
= 0;
11553 unsigned int newinsn
= 0xe1a00000; /* nop. */
11555 newimm
= validate_immediate (value
);
11556 temp
= md_chars_to_number (buf
, INSN_SIZE
);
11558 /* If the instruction will fail, see if we can fix things up by
11559 changing the opcode. */
11560 if (newimm
== (unsigned int) FAIL
11561 && (newimm
= negate_data_op (& temp
, value
)) == (unsigned int) FAIL
)
11563 /* No ? OK - try using two ADD instructions to generate
11565 newimm
= validate_immediate_twopart (value
, & highpart
);
11567 /* Yes - then make sure that the second instruction is
11569 if (newimm
!= (unsigned int) FAIL
)
11571 /* Still No ? Try using a negated value. */
11572 else if ((newimm
= validate_immediate_twopart (- value
, & highpart
)) != (unsigned int) FAIL
)
11573 temp
= newinsn
= (temp
& OPCODE_MASK
) | OPCODE_SUB
<< DATA_OP_SHIFT
;
11574 /* Otherwise - give up. */
11577 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11578 _("unable to compute ADRL instructions for PC offset of 0x%lx"),
11583 /* Replace the first operand in the 2nd instruction (which
11584 is the PC) with the destination register. We have
11585 already added in the PC in the first instruction and we
11586 do not want to do it again. */
11587 newinsn
&= ~ 0xf0000;
11588 newinsn
|= ((newinsn
& 0x0f000) << 4);
11591 newimm
|= (temp
& 0xfffff000);
11592 md_number_to_chars (buf
, (valueT
) newimm
, INSN_SIZE
);
11594 highpart
|= (newinsn
& 0xfffff000);
11595 md_number_to_chars (buf
+ INSN_SIZE
, (valueT
) highpart
, INSN_SIZE
);
11599 case BFD_RELOC_ARM_OFFSET_IMM
:
11605 if (validate_offset_imm (value
, 0) == FAIL
)
11607 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11608 _("bad immediate value for offset (%ld)"),
11613 newval
= md_chars_to_number (buf
, INSN_SIZE
);
11614 newval
&= 0xff7ff000;
11615 newval
|= value
| (sign
? INDEX_UP
: 0);
11616 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11619 case BFD_RELOC_ARM_OFFSET_IMM8
:
11620 case BFD_RELOC_ARM_HWLITERAL
:
11626 if (validate_offset_imm (value
, 1) == FAIL
)
11628 if (fixP
->fx_r_type
== BFD_RELOC_ARM_HWLITERAL
)
11629 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11630 _("invalid literal constant: pool needs to be closer"));
11632 as_bad (_("bad immediate value for half-word offset (%ld)"),
11637 newval
= md_chars_to_number (buf
, INSN_SIZE
);
11638 newval
&= 0xff7ff0f0;
11639 newval
|= ((value
>> 4) << 8) | (value
& 0xf) | (sign
? INDEX_UP
: 0);
11640 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11643 case BFD_RELOC_ARM_LITERAL
:
11649 if (validate_offset_imm (value
, 0) == FAIL
)
11651 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11652 _("invalid literal constant: pool needs to be closer"));
11656 newval
= md_chars_to_number (buf
, INSN_SIZE
);
11657 newval
&= 0xff7ff000;
11658 newval
|= value
| (sign
? INDEX_UP
: 0);
11659 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11662 case BFD_RELOC_ARM_SHIFT_IMM
:
11663 newval
= md_chars_to_number (buf
, INSN_SIZE
);
11664 if (((unsigned long) value
) > 32
11666 && (((newval
& 0x60) == 0) || (newval
& 0x60) == 0x60)))
11668 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11669 _("shift expression is too large"));
11674 /* Shifts of zero must be done as lsl. */
11676 else if (value
== 32)
11678 newval
&= 0xfffff07f;
11679 newval
|= (value
& 0x1f) << 7;
11680 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11683 case BFD_RELOC_ARM_SMI
:
11684 if (((unsigned long) value
) > 0xffff)
11685 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11686 _("invalid smi expression"));
11687 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xfff000f0;
11688 newval
|= (value
& 0xf) | ((value
& 0xfff0) << 4);
11689 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11692 case BFD_RELOC_ARM_SWI
:
11693 if (arm_data
->thumb_mode
)
11695 if (((unsigned long) value
) > 0xff)
11696 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11697 _("invalid swi expression"));
11698 newval
= md_chars_to_number (buf
, THUMB_SIZE
) & 0xff00;
11700 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
11704 if (((unsigned long) value
) > 0x00ffffff)
11705 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11706 _("invalid swi expression"));
11707 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff000000;
11709 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11713 case BFD_RELOC_ARM_MULTI
:
11714 if (((unsigned long) value
) > 0xffff)
11715 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11716 _("invalid expression in load/store multiple"));
11717 newval
= value
| md_chars_to_number (buf
, INSN_SIZE
);
11718 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11721 case BFD_RELOC_ARM_PCREL_BRANCH
:
11722 newval
= md_chars_to_number (buf
, INSN_SIZE
);
11724 /* Sign-extend a 24-bit number. */
11725 #define SEXT24(x) ((((x) & 0xffffff) ^ (~ 0x7fffff)) + 0x800000)
11729 value
= fixP
->fx_offset
;
11732 /* We are going to store value (shifted right by two) in the
11733 instruction, in a 24 bit, signed field. Thus we need to check
11734 that none of the top 8 bits of the shifted value (top 7 bits of
11735 the unshifted, unsigned value) are set, or that they are all set. */
11736 if ((value
& ~ ((offsetT
) 0x1ffffff)) != 0
11737 && ((value
& ~ ((offsetT
) 0x1ffffff)) != ~ ((offsetT
) 0x1ffffff)))
11740 /* Normally we would be stuck at this point, since we cannot store
11741 the absolute address that is the destination of the branch in the
11742 24 bits of the branch instruction. If however, we happen to know
11743 that the destination of the branch is in the same section as the
11744 branch instruction itself, then we can compute the relocation for
11745 ourselves and not have to bother the linker with it.
11747 FIXME: The tests for OBJ_ELF and ! target_oabi are only here
11748 because I have not worked out how to do this for OBJ_COFF or
11751 && fixP
->fx_addsy
!= NULL
11752 && S_IS_DEFINED (fixP
->fx_addsy
)
11753 && S_GET_SEGMENT (fixP
->fx_addsy
) == seg
)
11755 /* Get pc relative value to go into the branch. */
11758 /* Permit a backward branch provided that enough bits
11759 are set. Allow a forwards branch, provided that
11760 enough bits are clear. */
11761 if ( (value
& ~ ((offsetT
) 0x1ffffff)) == ~ ((offsetT
) 0x1ffffff)
11762 || (value
& ~ ((offsetT
) 0x1ffffff)) == 0)
11766 if (! fixP
->fx_done
)
11768 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11769 _("GAS can't handle same-section branch dest >= 0x04000000"));
11773 value
+= SEXT24 (newval
);
11775 if ( (value
& ~ ((offsetT
) 0xffffff)) != 0
11776 && ((value
& ~ ((offsetT
) 0xffffff)) != ~ ((offsetT
) 0xffffff)))
11777 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11778 _("out of range branch"));
11780 newval
= (value
& 0x00ffffff) | (newval
& 0xff000000);
11781 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11784 case BFD_RELOC_ARM_PCREL_BLX
:
11787 newval
= md_chars_to_number (buf
, INSN_SIZE
);
11791 value
= fixP
->fx_offset
;
11793 hbit
= (value
>> 1) & 1;
11794 value
= (value
>> 2) & 0x00ffffff;
11795 value
= (value
+ (newval
& 0x00ffffff)) & 0x00ffffff;
11796 newval
= value
| (newval
& 0xfe000000) | (hbit
<< 24);
11797 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11801 case BFD_RELOC_THUMB_PCREL_BRANCH9
: /* Conditional branch. */
11802 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
11804 addressT diff
= (newval
& 0xff) << 1;
11809 if ((value
& ~0xff) && ((value
& ~0xff) != ~0xff))
11810 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11811 _("branch out of range"));
11812 newval
= (newval
& 0xff00) | ((value
& 0x1ff) >> 1);
11814 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
11817 case BFD_RELOC_THUMB_PCREL_BRANCH12
: /* Unconditional branch. */
11818 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
11820 addressT diff
= (newval
& 0x7ff) << 1;
11825 if ((value
& ~0x7ff) && ((value
& ~0x7ff) != ~0x7ff))
11826 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11827 _("branch out of range"));
11828 newval
= (newval
& 0xf800) | ((value
& 0xfff) >> 1);
11830 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
11833 case BFD_RELOC_THUMB_PCREL_BLX
:
11834 case BFD_RELOC_THUMB_PCREL_BRANCH23
:
11839 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
11840 newval2
= md_chars_to_number (buf
+ THUMB_SIZE
, THUMB_SIZE
);
11841 diff
= ((newval
& 0x7ff) << 12) | ((newval2
& 0x7ff) << 1);
11842 if (diff
& 0x400000)
11845 value
= fixP
->fx_offset
;
11849 if ((value
& ~0x3fffff) && ((value
& ~0x3fffff) != ~0x3fffff))
11850 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11851 _("branch with link out of range"));
11853 newval
= (newval
& 0xf800) | ((value
& 0x7fffff) >> 12);
11854 newval2
= (newval2
& 0xf800) | ((value
& 0xfff) >> 1);
11855 if (fixP
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BLX
)
11856 /* For a BLX instruction, make sure that the relocation is rounded up
11857 to a word boundary. This follows the semantics of the instruction
11858 which specifies that bit 1 of the target address will come from bit
11859 1 of the base address. */
11860 newval2
= (newval2
+ 1) & ~ 1;
11861 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
11862 md_number_to_chars (buf
+ THUMB_SIZE
, newval2
, THUMB_SIZE
);
11867 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
11868 md_number_to_chars (buf
, value
, 1);
11870 else if (!target_oabi
)
11872 value
= fixP
->fx_offset
;
11873 md_number_to_chars (buf
, value
, 1);
11879 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
11880 md_number_to_chars (buf
, value
, 2);
11882 else if (!target_oabi
)
11884 value
= fixP
->fx_offset
;
11885 md_number_to_chars (buf
, value
, 2);
11891 case BFD_RELOC_ARM_GOT32
:
11892 case BFD_RELOC_ARM_GOTOFF
:
11893 case BFD_RELOC_ARM_TARGET2
:
11894 md_number_to_chars (buf
, 0, 4);
11898 case BFD_RELOC_RVA
:
11900 case BFD_RELOC_ARM_TARGET1
:
11901 case BFD_RELOC_ARM_ROSEGREL32
:
11902 case BFD_RELOC_ARM_SBREL32
:
11903 case BFD_RELOC_32_PCREL
:
11904 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
11905 md_number_to_chars (buf
, value
, 4);
11907 else if (!target_oabi
)
11909 value
= fixP
->fx_offset
;
11910 md_number_to_chars (buf
, value
, 4);
11916 case BFD_RELOC_ARM_PREL31
:
11917 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
11919 newval
= md_chars_to_number (buf
, 4) & 0x80000000;
11920 if ((value
^ (value
>> 1)) & 0x40000000)
11922 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11923 _("rel31 relocation overflow"));
11925 newval
|= value
& 0x7fffffff;
11926 md_number_to_chars (buf
, newval
, 4);
11930 case BFD_RELOC_ARM_PLT32
:
11931 /* It appears the instruction is fully prepared at this point. */
11935 case BFD_RELOC_ARM_CP_OFF_IMM
:
11937 if (value
< -1023 || value
> 1023 || (value
& 3))
11938 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11939 _("illegal value for co-processor offset"));
11942 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff7fff00;
11943 newval
|= (value
>> 2) | (sign
? INDEX_UP
: 0);
11944 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11947 case BFD_RELOC_ARM_CP_OFF_IMM_S2
:
11949 if (value
< -255 || value
> 255)
11950 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11951 _("Illegal value for co-processor offset"));
11954 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff7fff00;
11955 newval
|= value
| (sign
? INDEX_UP
: 0);
11956 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11959 case BFD_RELOC_ARM_THUMB_OFFSET
:
11960 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
11961 /* Exactly what ranges, and where the offset is inserted depends
11962 on the type of instruction, we can establish this from the
11964 switch (newval
>> 12)
11966 case 4: /* PC load. */
11967 /* Thumb PC loads are somewhat odd, bit 1 of the PC is
11968 forced to zero for these loads, so we will need to round
11969 up the offset if the instruction address is not word
11970 aligned (since the final address produced must be, and
11971 we can only describe word-aligned immediate offsets). */
11973 if ((fixP
->fx_frag
->fr_address
+ fixP
->fx_where
+ value
) & 3)
11974 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11975 _("invalid offset, target not word aligned (0x%08X)"),
11976 (unsigned int) (fixP
->fx_frag
->fr_address
11977 + fixP
->fx_where
+ value
));
11979 if ((value
+ 2) & ~0x3fe)
11980 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11981 _("invalid offset, value too big (0x%08lX)"),
11984 /* Round up, since pc will be rounded down. */
11985 newval
|= (value
+ 2) >> 2;
11988 case 9: /* SP load/store. */
11989 if (value
& ~0x3fc)
11990 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11991 _("invalid offset, value too big (0x%08lX)"),
11993 newval
|= value
>> 2;
11996 case 6: /* Word load/store. */
11998 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11999 _("invalid offset, value too big (0x%08lX)"),
12001 newval
|= value
<< 4; /* 6 - 2. */
12004 case 7: /* Byte load/store. */
12006 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12007 _("invalid offset, value too big (0x%08lX)"),
12009 newval
|= value
<< 6;
12012 case 8: /* Halfword load/store. */
12014 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12015 _("invalid offset, value too big (0x%08lX)"),
12017 newval
|= value
<< 5; /* 6 - 1. */
12021 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12022 "Unable to process relocation for thumb opcode: %lx",
12023 (unsigned long) newval
);
12026 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12029 case BFD_RELOC_ARM_THUMB_ADD
:
12030 /* This is a complicated relocation, since we use it for all of
12031 the following immediate relocations:
12035 9bit ADD/SUB SP word-aligned
12036 10bit ADD PC/SP word-aligned
12038 The type of instruction being processed is encoded in the
12045 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12047 int rd
= (newval
>> 4) & 0xf;
12048 int rs
= newval
& 0xf;
12049 int subtract
= newval
& 0x8000;
12053 if (value
& ~0x1fc)
12054 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12055 _("invalid immediate for stack address calculation"));
12056 newval
= subtract
? T_OPCODE_SUB_ST
: T_OPCODE_ADD_ST
;
12057 newval
|= value
>> 2;
12059 else if (rs
== REG_PC
|| rs
== REG_SP
)
12063 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12064 _("invalid immediate for address calculation (value = 0x%08lX)"),
12065 (unsigned long) value
);
12066 newval
= (rs
== REG_PC
? T_OPCODE_ADD_PC
: T_OPCODE_ADD_SP
);
12068 newval
|= value
>> 2;
12073 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12074 _("invalid 8bit immediate"));
12075 newval
= subtract
? T_OPCODE_SUB_I8
: T_OPCODE_ADD_I8
;
12076 newval
|= (rd
<< 8) | value
;
12081 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12082 _("invalid 3bit immediate"));
12083 newval
= subtract
? T_OPCODE_SUB_I3
: T_OPCODE_ADD_I3
;
12084 newval
|= rd
| (rs
<< 3) | (value
<< 6);
12087 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12090 case BFD_RELOC_ARM_THUMB_IMM
:
12091 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12092 switch (newval
>> 11)
12094 case 0x04: /* 8bit immediate MOV. */
12095 case 0x05: /* 8bit immediate CMP. */
12096 if (value
< 0 || value
> 255)
12097 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12098 _("invalid immediate: %ld is too large"),
12106 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12109 case BFD_RELOC_ARM_THUMB_SHIFT
:
12110 /* 5bit shift value (0..31). */
12111 if (value
< 0 || value
> 31)
12112 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12113 _("illegal Thumb shift value: %ld"), (long) value
);
12114 newval
= md_chars_to_number (buf
, THUMB_SIZE
) & 0xf03f;
12115 newval
|= value
<< 6;
12116 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12119 case BFD_RELOC_VTABLE_INHERIT
:
12120 case BFD_RELOC_VTABLE_ENTRY
:
12124 case BFD_RELOC_NONE
:
12126 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12127 _("bad relocation fixup type (%d)"), fixP
->fx_r_type
);
12131 /* Translate internal representation of relocation info to BFD target
12135 tc_gen_reloc (asection
* section ATTRIBUTE_UNUSED
,
12139 bfd_reloc_code_real_type code
;
12141 reloc
= xmalloc (sizeof (arelent
));
12143 reloc
->sym_ptr_ptr
= xmalloc (sizeof (asymbol
*));
12144 *reloc
->sym_ptr_ptr
= symbol_get_bfdsym (fixp
->fx_addsy
);
12145 reloc
->address
= fixp
->fx_frag
->fr_address
+ fixp
->fx_where
;
12147 /* @@ Why fx_addnumber sometimes and fx_offset other times? */
12149 if (fixp
->fx_pcrel
== 0)
12150 reloc
->addend
= fixp
->fx_offset
;
12152 reloc
->addend
= fixp
->fx_offset
= reloc
->address
;
12153 #else /* OBJ_ELF */
12154 reloc
->addend
= fixp
->fx_offset
;
12157 switch (fixp
->fx_r_type
)
12160 if (fixp
->fx_pcrel
)
12162 code
= BFD_RELOC_8_PCREL
;
12167 if (fixp
->fx_pcrel
)
12169 code
= BFD_RELOC_16_PCREL
;
12174 if (fixp
->fx_pcrel
)
12176 code
= BFD_RELOC_32_PCREL
;
12180 case BFD_RELOC_ARM_PCREL_BRANCH
:
12181 case BFD_RELOC_ARM_PCREL_BLX
:
12182 case BFD_RELOC_RVA
:
12183 case BFD_RELOC_THUMB_PCREL_BRANCH9
:
12184 case BFD_RELOC_THUMB_PCREL_BRANCH12
:
12185 case BFD_RELOC_THUMB_PCREL_BRANCH23
:
12186 case BFD_RELOC_THUMB_PCREL_BLX
:
12187 case BFD_RELOC_VTABLE_ENTRY
:
12188 case BFD_RELOC_VTABLE_INHERIT
:
12189 code
= fixp
->fx_r_type
;
12192 case BFD_RELOC_ARM_LITERAL
:
12193 case BFD_RELOC_ARM_HWLITERAL
:
12194 /* If this is called then the a literal has
12195 been referenced across a section boundary. */
12196 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12197 _("literal referenced across section boundary"));
12201 case BFD_RELOC_ARM_GOT32
:
12202 case BFD_RELOC_ARM_GOTOFF
:
12203 case BFD_RELOC_ARM_PLT32
:
12204 case BFD_RELOC_ARM_TARGET1
:
12205 case BFD_RELOC_ARM_ROSEGREL32
:
12206 case BFD_RELOC_ARM_SBREL32
:
12207 case BFD_RELOC_ARM_PREL31
:
12208 case BFD_RELOC_ARM_TARGET2
:
12209 code
= fixp
->fx_r_type
;
12213 case BFD_RELOC_ARM_IMMEDIATE
:
12214 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12215 _("internal relocation (type: IMMEDIATE) not fixed up"));
12218 case BFD_RELOC_ARM_ADRL_IMMEDIATE
:
12219 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12220 _("ADRL used for a symbol not defined in the same file"));
12223 case BFD_RELOC_ARM_OFFSET_IMM
:
12224 if (fixp
->fx_addsy
!= NULL
12225 && !S_IS_DEFINED (fixp
->fx_addsy
)
12226 && S_IS_LOCAL (fixp
->fx_addsy
))
12228 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12229 _("undefined local label `%s'"),
12230 S_GET_NAME (fixp
->fx_addsy
));
12234 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12235 _("internal_relocation (type: OFFSET_IMM) not fixed up"));
12242 switch (fixp
->fx_r_type
)
12244 case BFD_RELOC_ARM_OFFSET_IMM8
: type
= "OFFSET_IMM8"; break;
12245 case BFD_RELOC_ARM_SHIFT_IMM
: type
= "SHIFT_IMM"; break;
12246 case BFD_RELOC_ARM_SMI
: type
= "SMI"; break;
12247 case BFD_RELOC_ARM_SWI
: type
= "SWI"; break;
12248 case BFD_RELOC_ARM_MULTI
: type
= "MULTI"; break;
12249 case BFD_RELOC_ARM_CP_OFF_IMM
: type
= "CP_OFF_IMM"; break;
12250 case BFD_RELOC_ARM_THUMB_ADD
: type
= "THUMB_ADD"; break;
12251 case BFD_RELOC_ARM_THUMB_SHIFT
: type
= "THUMB_SHIFT"; break;
12252 case BFD_RELOC_ARM_THUMB_IMM
: type
= "THUMB_IMM"; break;
12253 case BFD_RELOC_ARM_THUMB_OFFSET
: type
= "THUMB_OFFSET"; break;
12254 default: type
= _("<unknown>"); break;
12256 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12257 _("cannot represent %s relocation in this object file format"),
12264 if ((code
== BFD_RELOC_32_PCREL
|| code
== BFD_RELOC_32
)
12266 && fixp
->fx_addsy
== GOT_symbol
)
12268 code
= BFD_RELOC_ARM_GOTPC
;
12269 reloc
->addend
= fixp
->fx_offset
= reloc
->address
;
12273 reloc
->howto
= bfd_reloc_type_lookup (stdoutput
, code
);
12275 if (reloc
->howto
== NULL
)
12277 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12278 _("cannot represent %s relocation in this object file format"),
12279 bfd_get_reloc_code_name (code
));
12283 /* HACK: Since arm ELF uses Rel instead of Rela, encode the
12284 vtable entry to be used in the relocation's section offset. */
12285 if (fixp
->fx_r_type
== BFD_RELOC_VTABLE_ENTRY
)
12286 reloc
->address
= fixp
->fx_offset
;
12292 md_estimate_size_before_relax (fragS
* fragP ATTRIBUTE_UNUSED
,
12293 segT segtype ATTRIBUTE_UNUSED
)
12295 as_fatal (_("md_estimate_size_before_relax\n"));
12299 /* We need to be able to fix up arbitrary expressions in some statements.
12300 This is so that we can handle symbols that are an arbitrary distance from
12301 the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
12302 which returns part of an address in a form which will be valid for
12303 a data instruction. We do this by pushing the expression into a symbol
12304 in the expr_section, and creating a fix for that. */
12307 fix_new_arm (fragS
* frag
,
12315 arm_fix_data
* arm_data
;
12323 new_fix
= fix_new_exp (frag
, where
, size
, exp
, pc_rel
, reloc
);
12327 new_fix
= fix_new (frag
, where
, size
, make_expr_symbol (exp
), 0,
12332 /* Mark whether the fix is to a THUMB instruction, or an ARM
12334 arm_data
= obstack_alloc (& notes
, sizeof (arm_fix_data
));
12335 new_fix
->tc_fix_data
= (PTR
) arm_data
;
12336 arm_data
->thumb_mode
= thumb_mode
;
12340 output_inst (const char * str
)
12346 as_bad ("%s -- `%s'", inst
.error
, str
);
12350 to
= frag_more (inst
.size
);
12352 if (thumb_mode
&& (inst
.size
> THUMB_SIZE
))
12354 assert (inst
.size
== (2 * THUMB_SIZE
));
12355 md_number_to_chars (to
, inst
.instruction
>> 16, THUMB_SIZE
);
12356 md_number_to_chars (to
+ THUMB_SIZE
, inst
.instruction
, THUMB_SIZE
);
12358 else if (inst
.size
> INSN_SIZE
)
12360 assert (inst
.size
== (2 * INSN_SIZE
));
12361 md_number_to_chars (to
, inst
.instruction
, INSN_SIZE
);
12362 md_number_to_chars (to
+ INSN_SIZE
, inst
.instruction
, INSN_SIZE
);
12365 md_number_to_chars (to
, inst
.instruction
, inst
.size
);
12367 if (inst
.reloc
.type
!= BFD_RELOC_NONE
)
12368 fix_new_arm (frag_now
, to
- frag_now
->fr_literal
,
12369 inst
.size
, & inst
.reloc
.exp
, inst
.reloc
.pc_rel
,
12373 dwarf2_emit_insn (inst
.size
);
12378 md_assemble (char * str
)
12384 /* Align the instruction.
12385 This may not be the right thing to do but ... */
12390 /* Align the previous label if needed. */
12391 if (last_label_seen
!= NULL
)
12393 symbol_set_frag (last_label_seen
, frag_now
);
12394 S_SET_VALUE (last_label_seen
, (valueT
) frag_now_fix ());
12395 S_SET_SEGMENT (last_label_seen
, now_seg
);
12398 memset (&inst
, '\0', sizeof (inst
));
12399 inst
.reloc
.type
= BFD_RELOC_NONE
;
12401 skip_whitespace (str
);
12403 /* Scan up to the end of the op-code, which must end in white space or
12405 for (start
= p
= str
; *p
!= '\0'; p
++)
12411 as_bad (_("no operator -- statement `%s'\n"), str
);
12417 const struct thumb_opcode
* opcode
;
12421 opcode
= (const struct thumb_opcode
*) hash_find (arm_tops_hsh
, str
);
12426 /* Check that this instruction is supported for this CPU. */
12427 if (thumb_mode
== 1 && (opcode
->variant
& cpu_variant
) == 0)
12429 as_bad (_("selected processor does not support `%s'"), str
);
12433 mapping_state (MAP_THUMB
);
12434 inst
.instruction
= opcode
->value
;
12435 inst
.size
= opcode
->size
;
12443 const struct asm_opcode
* opcode
;
12447 opcode
= (const struct asm_opcode
*) hash_find (arm_ops_hsh
, str
);
12452 /* Check that this instruction is supported for this CPU. */
12453 if ((opcode
->variant
& cpu_variant
) == 0)
12455 as_bad (_("selected processor does not support `%s'"), str
);
12459 mapping_state (MAP_ARM
);
12460 inst
.instruction
= opcode
->value
;
12461 inst
.size
= INSN_SIZE
;
12468 /* It wasn't an instruction, but it might be a register alias of the form
12470 if (create_register_alias (str
, p
))
12473 as_bad (_("bad instruction `%s'"), start
);
12477 Invocation line includes a switch not recognized by the base assembler.
12478 See if it's a processor-specific option.
12480 This routine is somewhat complicated by the need for backwards
12481 compatibility (since older releases of gcc can't be changed).
12482 The new options try to make the interface as compatible as
12485 New options (supported) are:
12487 -mcpu=<cpu name> Assemble for selected processor
12488 -march=<architecture name> Assemble for selected architecture
12489 -mfpu=<fpu architecture> Assemble for selected FPU.
12490 -EB/-mbig-endian Big-endian
12491 -EL/-mlittle-endian Little-endian
12492 -k Generate PIC code
12493 -mthumb Start in Thumb mode
12494 -mthumb-interwork Code supports ARM/Thumb interworking
12496 For now we will also provide support for:
12498 -mapcs-32 32-bit Program counter
12499 -mapcs-26 26-bit Program counter
12500 -macps-float Floats passed in FP registers
12501 -mapcs-reentrant Reentrant code
12503 (sometime these will probably be replaced with -mapcs=<list of options>
12504 and -matpcs=<list of options>)
12506 The remaining options are only supported for back-wards compatibility.
12507 Cpu variants, the arm part is optional:
12508 -m[arm]1 Currently not supported.
12509 -m[arm]2, -m[arm]250 Arm 2 and Arm 250 processor
12510 -m[arm]3 Arm 3 processor
12511 -m[arm]6[xx], Arm 6 processors
12512 -m[arm]7[xx][t][[d]m] Arm 7 processors
12513 -m[arm]8[10] Arm 8 processors
12514 -m[arm]9[20][tdmi] Arm 9 processors
12515 -mstrongarm[110[0]] StrongARM processors
12516 -mxscale XScale processors
12517 -m[arm]v[2345[t[e]]] Arm architectures
12518 -mall All (except the ARM1)
12520 -mfpa10, -mfpa11 FPA10 and 11 co-processor instructions
12521 -mfpe-old (No float load/store multiples)
12522 -mvfpxd VFP Single precision
12524 -mno-fpu Disable all floating point instructions
12526 The following CPU names are recognized:
12527 arm1, arm2, arm250, arm3, arm6, arm600, arm610, arm620,
12528 arm7, arm7m, arm7d, arm7dm, arm7di, arm7dmi, arm70, arm700,
12529 arm700i, arm710 arm710t, arm720, arm720t, arm740t, arm710c,
12530 arm7100, arm7500, arm7500fe, arm7tdmi, arm8, arm810, arm9,
12531 arm920, arm920t, arm940t, arm946, arm966, arm9tdmi, arm9e,
12532 arm10t arm10e, arm1020t, arm1020e, arm10200e,
12533 strongarm, strongarm110, strongarm1100, strongarm1110, xscale.
12537 const char * md_shortopts
= "m:k";
12539 #ifdef ARM_BI_ENDIAN
12540 #define OPTION_EB (OPTION_MD_BASE + 0)
12541 #define OPTION_EL (OPTION_MD_BASE + 1)
12543 #if TARGET_BYTES_BIG_ENDIAN
12544 #define OPTION_EB (OPTION_MD_BASE + 0)
12546 #define OPTION_EL (OPTION_MD_BASE + 1)
12550 struct option md_longopts
[] =
12553 {"EB", no_argument
, NULL
, OPTION_EB
},
12556 {"EL", no_argument
, NULL
, OPTION_EL
},
12558 {NULL
, no_argument
, NULL
, 0}
12561 size_t md_longopts_size
= sizeof (md_longopts
);
12563 struct arm_option_table
12565 char *option
; /* Option name to match. */
12566 char *help
; /* Help information. */
12567 int *var
; /* Variable to change. */
12568 int value
; /* What to change it to. */
12569 char *deprecated
; /* If non-null, print this message. */
12572 struct arm_option_table arm_opts
[] =
12574 {"k", N_("generate PIC code"), &pic_code
, 1, NULL
},
12575 {"mthumb", N_("assemble Thumb code"), &thumb_mode
, 1, NULL
},
12576 {"mthumb-interwork", N_("support ARM/Thumb interworking"),
12577 &support_interwork
, 1, NULL
},
12578 {"moabi", N_("use old ABI (ELF only)"), &target_oabi
, 1, NULL
},
12579 {"mapcs-32", N_("code uses 32-bit program counter"), &uses_apcs_26
, 0, NULL
},
12580 {"mapcs-26", N_("code uses 26-bit program counter"), &uses_apcs_26
, 1, NULL
},
12581 {"mapcs-float", N_("floating point args are in fp regs"), &uses_apcs_float
,
12583 {"mapcs-reentrant", N_("re-entrant code"), &pic_code
, 1, NULL
},
12584 {"matpcs", N_("code is ATPCS conformant"), &atpcs
, 1, NULL
},
12585 {"mbig-endian", N_("assemble for big-endian"), &target_big_endian
, 1, NULL
},
12586 {"mlittle-endian", N_("assemble for little-endian"), &target_big_endian
, 1,
12589 /* These are recognized by the assembler, but have no affect on code. */
12590 {"mapcs-frame", N_("use frame pointer"), NULL
, 0, NULL
},
12591 {"mapcs-stack-check", N_("use stack size checking"), NULL
, 0, NULL
},
12593 /* DON'T add any new processors to this list -- we want the whole list
12594 to go away... Add them to the processors table instead. */
12595 {"marm1", NULL
, &legacy_cpu
, ARM_ARCH_V1
, N_("use -mcpu=arm1")},
12596 {"m1", NULL
, &legacy_cpu
, ARM_ARCH_V1
, N_("use -mcpu=arm1")},
12597 {"marm2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -mcpu=arm2")},
12598 {"m2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -mcpu=arm2")},
12599 {"marm250", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm250")},
12600 {"m250", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm250")},
12601 {"marm3", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm3")},
12602 {"m3", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm3")},
12603 {"marm6", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm6")},
12604 {"m6", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm6")},
12605 {"marm600", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm600")},
12606 {"m600", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm600")},
12607 {"marm610", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm610")},
12608 {"m610", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm610")},
12609 {"marm620", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm620")},
12610 {"m620", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm620")},
12611 {"marm7", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7")},
12612 {"m7", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7")},
12613 {"marm70", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm70")},
12614 {"m70", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm70")},
12615 {"marm700", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700")},
12616 {"m700", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700")},
12617 {"marm700i", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700i")},
12618 {"m700i", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700i")},
12619 {"marm710", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710")},
12620 {"m710", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710")},
12621 {"marm710c", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710c")},
12622 {"m710c", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710c")},
12623 {"marm720", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm720")},
12624 {"m720", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm720")},
12625 {"marm7d", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7d")},
12626 {"m7d", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7d")},
12627 {"marm7di", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7di")},
12628 {"m7di", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7di")},
12629 {"marm7m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7m")},
12630 {"m7m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7m")},
12631 {"marm7dm", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dm")},
12632 {"m7dm", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dm")},
12633 {"marm7dmi", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dmi")},
12634 {"m7dmi", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dmi")},
12635 {"marm7100", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7100")},
12636 {"m7100", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7100")},
12637 {"marm7500", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500")},
12638 {"m7500", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500")},
12639 {"marm7500fe", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500fe")},
12640 {"m7500fe", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500fe")},
12641 {"marm7t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
12642 {"m7t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
12643 {"marm7tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
12644 {"m7tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
12645 {"marm710t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm710t")},
12646 {"m710t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm710t")},
12647 {"marm720t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm720t")},
12648 {"m720t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm720t")},
12649 {"marm740t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm740t")},
12650 {"m740t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm740t")},
12651 {"marm8", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm8")},
12652 {"m8", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm8")},
12653 {"marm810", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm810")},
12654 {"m810", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm810")},
12655 {"marm9", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9")},
12656 {"m9", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9")},
12657 {"marm9tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9tdmi")},
12658 {"m9tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9tdmi")},
12659 {"marm920", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm920")},
12660 {"m920", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm920")},
12661 {"marm940", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm940")},
12662 {"m940", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm940")},
12663 {"mstrongarm", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=strongarm")},
12664 {"mstrongarm110", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
12665 N_("use -mcpu=strongarm110")},
12666 {"mstrongarm1100", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
12667 N_("use -mcpu=strongarm1100")},
12668 {"mstrongarm1110", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
12669 N_("use -mcpu=strongarm1110")},
12670 {"mxscale", NULL
, &legacy_cpu
, ARM_ARCH_XSCALE
, N_("use -mcpu=xscale")},
12671 {"miwmmxt", NULL
, &legacy_cpu
, ARM_ARCH_IWMMXT
, N_("use -mcpu=iwmmxt")},
12672 {"mall", NULL
, &legacy_cpu
, ARM_ANY
, N_("use -mcpu=all")},
12674 /* Architecture variants -- don't add any more to this list either. */
12675 {"mv2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -march=armv2")},
12676 {"marmv2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -march=armv2")},
12677 {"mv2a", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -march=armv2a")},
12678 {"marmv2a", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -march=armv2a")},
12679 {"mv3", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -march=armv3")},
12680 {"marmv3", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -march=armv3")},
12681 {"mv3m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -march=armv3m")},
12682 {"marmv3m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -march=armv3m")},
12683 {"mv4", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -march=armv4")},
12684 {"marmv4", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -march=armv4")},
12685 {"mv4t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -march=armv4t")},
12686 {"marmv4t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -march=armv4t")},
12687 {"mv5", NULL
, &legacy_cpu
, ARM_ARCH_V5
, N_("use -march=armv5")},
12688 {"marmv5", NULL
, &legacy_cpu
, ARM_ARCH_V5
, N_("use -march=armv5")},
12689 {"mv5t", NULL
, &legacy_cpu
, ARM_ARCH_V5T
, N_("use -march=armv5t")},
12690 {"marmv5t", NULL
, &legacy_cpu
, ARM_ARCH_V5T
, N_("use -march=armv5t")},
12691 {"mv5e", NULL
, &legacy_cpu
, ARM_ARCH_V5TE
, N_("use -march=armv5te")},
12692 {"marmv5e", NULL
, &legacy_cpu
, ARM_ARCH_V5TE
, N_("use -march=armv5te")},
12694 /* Floating point variants -- don't add any more to this list either. */
12695 {"mfpe-old", NULL
, &legacy_fpu
, FPU_ARCH_FPE
, N_("use -mfpu=fpe")},
12696 {"mfpa10", NULL
, &legacy_fpu
, FPU_ARCH_FPA
, N_("use -mfpu=fpa10")},
12697 {"mfpa11", NULL
, &legacy_fpu
, FPU_ARCH_FPA
, N_("use -mfpu=fpa11")},
12698 {"mno-fpu", NULL
, &legacy_fpu
, 0,
12699 N_("use either -mfpu=softfpa or -mfpu=softvfp")},
12701 {NULL
, NULL
, NULL
, 0, NULL
}
12704 struct arm_cpu_option_table
12708 /* For some CPUs we assume an FPU unless the user explicitly sets
12713 /* This list should, at a minimum, contain all the cpu names
12714 recognized by GCC. */
12715 static struct arm_cpu_option_table arm_cpus
[] =
12717 {"all", ARM_ANY
, FPU_ARCH_FPA
},
12718 {"arm1", ARM_ARCH_V1
, FPU_ARCH_FPA
},
12719 {"arm2", ARM_ARCH_V2
, FPU_ARCH_FPA
},
12720 {"arm250", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
12721 {"arm3", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
12722 {"arm6", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12723 {"arm60", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12724 {"arm600", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12725 {"arm610", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12726 {"arm620", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12727 {"arm7", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12728 {"arm7m", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
12729 {"arm7d", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12730 {"arm7dm", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
12731 {"arm7di", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12732 {"arm7dmi", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
12733 {"arm70", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12734 {"arm700", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12735 {"arm700i", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12736 {"arm710", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12737 {"arm710t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12738 {"arm720", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12739 {"arm720t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12740 {"arm740t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12741 {"arm710c", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12742 {"arm7100", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12743 {"arm7500", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12744 {"arm7500fe", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12745 {"arm7t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12746 {"arm7tdmi", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12747 {"arm7tdmi-s", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12748 {"arm8", ARM_ARCH_V4
, FPU_ARCH_FPA
},
12749 {"arm810", ARM_ARCH_V4
, FPU_ARCH_FPA
},
12750 {"strongarm", ARM_ARCH_V4
, FPU_ARCH_FPA
},
12751 {"strongarm1", ARM_ARCH_V4
, FPU_ARCH_FPA
},
12752 {"strongarm110", ARM_ARCH_V4
, FPU_ARCH_FPA
},
12753 {"strongarm1100", ARM_ARCH_V4
, FPU_ARCH_FPA
},
12754 {"strongarm1110", ARM_ARCH_V4
, FPU_ARCH_FPA
},
12755 {"arm9", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12756 {"arm920", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12757 {"arm920t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12758 {"arm922t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12759 {"arm940t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12760 {"arm9tdmi", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12761 /* For V5 or later processors we default to using VFP; but the user
12762 should really set the FPU type explicitly. */
12763 {"arm9e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
12764 {"arm9e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
12765 {"arm926ej", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP_V2
},
12766 {"arm926ejs", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP_V2
},
12767 {"arm926ej-s", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP_V2
},
12768 {"arm946e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
12769 {"arm946e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
12770 {"arm966e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
12771 {"arm966e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
12772 {"arm10t", ARM_ARCH_V5T
, FPU_ARCH_VFP_V1
},
12773 {"arm10e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
12774 {"arm1020", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
12775 {"arm1020t", ARM_ARCH_V5T
, FPU_ARCH_VFP_V1
},
12776 {"arm1020e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
12777 {"arm1026ejs", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
12778 {"arm1026ej-s", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
12779 {"arm1136js", ARM_ARCH_V6
, FPU_NONE
},
12780 {"arm1136j-s", ARM_ARCH_V6
, FPU_NONE
},
12781 {"arm1136jfs", ARM_ARCH_V6
, FPU_ARCH_VFP_V2
},
12782 {"arm1136jf-s", ARM_ARCH_V6
, FPU_ARCH_VFP_V2
},
12783 {"mpcore", ARM_ARCH_V6K
, FPU_ARCH_VFP_V2
},
12784 {"mpcorenovfp", ARM_ARCH_V6K
, FPU_NONE
},
12785 {"arm1176jz-s", ARM_ARCH_V6ZK
, FPU_NONE
},
12786 {"arm1176jzf-s", ARM_ARCH_V6ZK
, FPU_ARCH_VFP_V2
},
12787 /* ??? XSCALE is really an architecture. */
12788 {"xscale", ARM_ARCH_XSCALE
, FPU_ARCH_VFP_V2
},
12789 /* ??? iwmmxt is not a processor. */
12790 {"iwmmxt", ARM_ARCH_IWMMXT
, FPU_ARCH_VFP_V2
},
12791 {"i80200", ARM_ARCH_XSCALE
, FPU_ARCH_VFP_V2
},
12793 {"ep9312", ARM_ARCH_V4T
| ARM_CEXT_MAVERICK
, FPU_ARCH_MAVERICK
},
12797 struct arm_arch_option_table
12804 /* This list should, at a minimum, contain all the architecture names
12805 recognized by GCC. */
12806 static struct arm_arch_option_table arm_archs
[] =
12808 {"all", ARM_ANY
, FPU_ARCH_FPA
},
12809 {"armv1", ARM_ARCH_V1
, FPU_ARCH_FPA
},
12810 {"armv2", ARM_ARCH_V2
, FPU_ARCH_FPA
},
12811 {"armv2a", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
12812 {"armv2s", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
12813 {"armv3", ARM_ARCH_V3
, FPU_ARCH_FPA
},
12814 {"armv3m", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
12815 {"armv4", ARM_ARCH_V4
, FPU_ARCH_FPA
},
12816 {"armv4xm", ARM_ARCH_V4xM
, FPU_ARCH_FPA
},
12817 {"armv4t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
12818 {"armv4txm", ARM_ARCH_V4TxM
, FPU_ARCH_FPA
},
12819 {"armv5", ARM_ARCH_V5
, FPU_ARCH_VFP
},
12820 {"armv5t", ARM_ARCH_V5T
, FPU_ARCH_VFP
},
12821 {"armv5txm", ARM_ARCH_V5TxM
, FPU_ARCH_VFP
},
12822 {"armv5te", ARM_ARCH_V5TE
, FPU_ARCH_VFP
},
12823 {"armv5texp", ARM_ARCH_V5TExP
, FPU_ARCH_VFP
},
12824 {"armv5tej", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP
},
12825 {"armv6", ARM_ARCH_V6
, FPU_ARCH_VFP
},
12826 {"armv6j", ARM_ARCH_V6
, FPU_ARCH_VFP
},
12827 {"armv6k", ARM_ARCH_V6K
, FPU_ARCH_VFP
},
12828 {"armv6z", ARM_ARCH_V6Z
, FPU_ARCH_VFP
},
12829 {"armv6zk", ARM_ARCH_V6ZK
, FPU_ARCH_VFP
},
12830 {"xscale", ARM_ARCH_XSCALE
, FPU_ARCH_VFP
},
12831 {"iwmmxt", ARM_ARCH_IWMMXT
, FPU_ARCH_VFP
},
12835 /* ISA extensions in the co-processor space. */
12836 struct arm_arch_extension_table
12842 static struct arm_arch_extension_table arm_extensions
[] =
12844 {"maverick", ARM_CEXT_MAVERICK
},
12845 {"xscale", ARM_CEXT_XSCALE
},
12846 {"iwmmxt", ARM_CEXT_IWMMXT
},
12850 struct arm_fpu_option_table
12856 /* This list should, at a minimum, contain all the fpu names
12857 recognized by GCC. */
12858 static struct arm_fpu_option_table arm_fpus
[] =
12860 {"softfpa", FPU_NONE
},
12861 {"fpe", FPU_ARCH_FPE
},
12862 {"fpe2", FPU_ARCH_FPE
},
12863 {"fpe3", FPU_ARCH_FPA
}, /* Third release supports LFM/SFM. */
12864 {"fpa", FPU_ARCH_FPA
},
12865 {"fpa10", FPU_ARCH_FPA
},
12866 {"fpa11", FPU_ARCH_FPA
},
12867 {"arm7500fe", FPU_ARCH_FPA
},
12868 {"softvfp", FPU_ARCH_VFP
},
12869 {"softvfp+vfp", FPU_ARCH_VFP_V2
},
12870 {"vfp", FPU_ARCH_VFP_V2
},
12871 {"vfp9", FPU_ARCH_VFP_V2
},
12872 {"vfp10", FPU_ARCH_VFP_V2
},
12873 {"vfp10-r0", FPU_ARCH_VFP_V1
},
12874 {"vfpxd", FPU_ARCH_VFP_V1xD
},
12875 {"arm1020t", FPU_ARCH_VFP_V1
},
12876 {"arm1020e", FPU_ARCH_VFP_V2
},
12877 {"arm1136jfs", FPU_ARCH_VFP_V2
},
12878 {"arm1136jf-s", FPU_ARCH_VFP_V2
},
12879 {"maverick", FPU_ARCH_MAVERICK
},
12883 struct arm_float_abi_option_table
12889 static struct arm_float_abi_option_table arm_float_abis
[] =
12891 {"hard", ARM_FLOAT_ABI_HARD
},
12892 {"softfp", ARM_FLOAT_ABI_SOFTFP
},
12893 {"soft", ARM_FLOAT_ABI_SOFT
},
12897 struct arm_eabi_option_table
12900 unsigned int value
;
12904 /* We only know hot to output GNU and ver 3 (AAELF) formats. */
12905 static struct arm_eabi_option_table arm_eabis
[] =
12907 {"gnu", EF_ARM_EABI_UNKNOWN
},
12908 {"3", EF_ARM_EABI_VER3
},
12913 struct arm_long_option_table
12915 char * option
; /* Substring to match. */
12916 char * help
; /* Help information. */
12917 int (* func
) (char * subopt
); /* Function to decode sub-option. */
12918 char * deprecated
; /* If non-null, print this message. */
12922 arm_parse_extension (char * str
, int * opt_p
)
12924 while (str
!= NULL
&& *str
!= 0)
12926 struct arm_arch_extension_table
* opt
;
12932 as_bad (_("invalid architectural extension"));
12937 ext
= strchr (str
, '+');
12940 optlen
= ext
- str
;
12942 optlen
= strlen (str
);
12946 as_bad (_("missing architectural extension"));
12950 for (opt
= arm_extensions
; opt
->name
!= NULL
; opt
++)
12951 if (strncmp (opt
->name
, str
, optlen
) == 0)
12953 *opt_p
|= opt
->value
;
12957 if (opt
->name
== NULL
)
12959 as_bad (_("unknown architectural extnsion `%s'"), str
);
12970 arm_parse_cpu (char * str
)
12972 struct arm_cpu_option_table
* opt
;
12973 char * ext
= strchr (str
, '+');
12977 optlen
= ext
- str
;
12979 optlen
= strlen (str
);
12983 as_bad (_("missing cpu name `%s'"), str
);
12987 for (opt
= arm_cpus
; opt
->name
!= NULL
; opt
++)
12988 if (strncmp (opt
->name
, str
, optlen
) == 0)
12990 mcpu_cpu_opt
= opt
->value
;
12991 mcpu_fpu_opt
= opt
->default_fpu
;
12994 return arm_parse_extension (ext
, &mcpu_cpu_opt
);
12999 as_bad (_("unknown cpu `%s'"), str
);
13004 arm_parse_arch (char * str
)
13006 struct arm_arch_option_table
*opt
;
13007 char *ext
= strchr (str
, '+');
13011 optlen
= ext
- str
;
13013 optlen
= strlen (str
);
13017 as_bad (_("missing architecture name `%s'"), str
);
13022 for (opt
= arm_archs
; opt
->name
!= NULL
; opt
++)
13023 if (streq (opt
->name
, str
))
13025 march_cpu_opt
= opt
->value
;
13026 march_fpu_opt
= opt
->default_fpu
;
13029 return arm_parse_extension (ext
, &march_cpu_opt
);
13034 as_bad (_("unknown architecture `%s'\n"), str
);
13039 arm_parse_fpu (char * str
)
13041 struct arm_fpu_option_table
* opt
;
13043 for (opt
= arm_fpus
; opt
->name
!= NULL
; opt
++)
13044 if (streq (opt
->name
, str
))
13046 mfpu_opt
= opt
->value
;
13050 as_bad (_("unknown floating point format `%s'\n"), str
);
13055 arm_parse_float_abi (char * str
)
13057 struct arm_float_abi_option_table
* opt
;
13059 for (opt
= arm_float_abis
; opt
->name
!= NULL
; opt
++)
13060 if (streq (opt
->name
, str
))
13062 mfloat_abi_opt
= opt
->value
;
13066 as_bad (_("unknown floating point abi `%s'\n"), str
);
13072 arm_parse_eabi (char * str
)
13074 struct arm_eabi_option_table
*opt
;
13076 for (opt
= arm_eabis
; opt
->name
!= NULL
; opt
++)
13077 if (streq (opt
->name
, str
))
13079 meabi_flags
= opt
->value
;
13082 as_bad (_("unknown EABI `%s'\n"), str
);
13087 struct arm_long_option_table arm_long_opts
[] =
13089 {"mcpu=", N_("<cpu name>\t assemble for CPU <cpu name>"),
13090 arm_parse_cpu
, NULL
},
13091 {"march=", N_("<arch name>\t assemble for architecture <arch name>"),
13092 arm_parse_arch
, NULL
},
13093 {"mfpu=", N_("<fpu name>\t assemble for FPU architecture <fpu name>"),
13094 arm_parse_fpu
, NULL
},
13095 {"mfloat-abi=", N_("<abi>\t assemble for floating point ABI <abi>"),
13096 arm_parse_float_abi
, NULL
},
13098 {"meabi=", N_("<ver>\t assemble for eabi version <ver>"),
13099 arm_parse_eabi
, NULL
},
13101 {NULL
, NULL
, 0, NULL
}
13105 md_parse_option (int c
, char * arg
)
13107 struct arm_option_table
*opt
;
13108 struct arm_long_option_table
*lopt
;
13114 target_big_endian
= 1;
13120 target_big_endian
= 0;
13125 /* Listing option. Just ignore these, we don't support additional
13130 for (opt
= arm_opts
; opt
->option
!= NULL
; opt
++)
13132 if (c
== opt
->option
[0]
13133 && ((arg
== NULL
&& opt
->option
[1] == 0)
13134 || streq (arg
, opt
->option
+ 1)))
13136 #if WARN_DEPRECATED
13137 /* If the option is deprecated, tell the user. */
13138 if (opt
->deprecated
!= NULL
)
13139 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c
,
13140 arg
? arg
: "", _(opt
->deprecated
));
13143 if (opt
->var
!= NULL
)
13144 *opt
->var
= opt
->value
;
13150 for (lopt
= arm_long_opts
; lopt
->option
!= NULL
; lopt
++)
13152 /* These options are expected to have an argument. */
13153 if (c
== lopt
->option
[0]
13155 && strncmp (arg
, lopt
->option
+ 1,
13156 strlen (lopt
->option
+ 1)) == 0)
13158 #if WARN_DEPRECATED
13159 /* If the option is deprecated, tell the user. */
13160 if (lopt
->deprecated
!= NULL
)
13161 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c
, arg
,
13162 _(lopt
->deprecated
));
13165 /* Call the sup-option parser. */
13166 return lopt
->func (arg
+ strlen (lopt
->option
) - 1);
13177 md_show_usage (FILE * fp
)
13179 struct arm_option_table
*opt
;
13180 struct arm_long_option_table
*lopt
;
13182 fprintf (fp
, _(" ARM-specific assembler options:\n"));
13184 for (opt
= arm_opts
; opt
->option
!= NULL
; opt
++)
13185 if (opt
->help
!= NULL
)
13186 fprintf (fp
, " -%-23s%s\n", opt
->option
, _(opt
->help
));
13188 for (lopt
= arm_long_opts
; lopt
->option
!= NULL
; lopt
++)
13189 if (lopt
->help
!= NULL
)
13190 fprintf (fp
, " -%s%s\n", lopt
->option
, _(lopt
->help
));
13194 -EB assemble code for a big-endian cpu\n"));
13199 -EL assemble code for a little-endian cpu\n"));
13203 /* This fix_new is called by cons via TC_CONS_FIX_NEW. */
13206 cons_fix_new_arm (fragS
* frag
,
13211 bfd_reloc_code_real_type type
;
13215 FIXME: @@ Should look at CPU word size. */
13219 type
= BFD_RELOC_8
;
13222 type
= BFD_RELOC_16
;
13226 type
= BFD_RELOC_32
;
13229 type
= BFD_RELOC_64
;
13233 fix_new_exp (frag
, where
, (int) size
, exp
, pcrel
, type
);
13236 /* A good place to do this, although this was probably not intended
13237 for this kind of use. We need to dump the literal pool before
13238 references are made to a null symbol pointer. */
13243 literal_pool
* pool
;
13245 for (pool
= list_of_pools
; pool
; pool
= pool
->next
)
13247 /* Put it at the end of the relevent section. */
13248 subseg_set (pool
->section
, pool
->sub_section
);
13250 arm_elf_change_section ();
13257 arm_start_line_hook (void)
13259 last_label_seen
= NULL
;
13263 arm_frob_label (symbolS
* sym
)
13265 last_label_seen
= sym
;
13267 ARM_SET_THUMB (sym
, thumb_mode
);
13269 #if defined OBJ_COFF || defined OBJ_ELF
13270 ARM_SET_INTERWORK (sym
, support_interwork
);
13273 /* Note - do not allow local symbols (.Lxxx) to be labeled
13274 as Thumb functions. This is because these labels, whilst
13275 they exist inside Thumb code, are not the entry points for
13276 possible ARM->Thumb calls. Also, these labels can be used
13277 as part of a computed goto or switch statement. eg gcc
13278 can generate code that looks like this:
13280 ldr r2, [pc, .Laaa]
13290 The first instruction loads the address of the jump table.
13291 The second instruction converts a table index into a byte offset.
13292 The third instruction gets the jump address out of the table.
13293 The fourth instruction performs the jump.
13295 If the address stored at .Laaa is that of a symbol which has the
13296 Thumb_Func bit set, then the linker will arrange for this address
13297 to have the bottom bit set, which in turn would mean that the
13298 address computation performed by the third instruction would end
13299 up with the bottom bit set. Since the ARM is capable of unaligned
13300 word loads, the instruction would then load the incorrect address
13301 out of the jump table, and chaos would ensue. */
13302 if (label_is_thumb_function_name
13303 && (S_GET_NAME (sym
)[0] != '.' || S_GET_NAME (sym
)[1] != 'L')
13304 && (bfd_get_section_flags (stdoutput
, now_seg
) & SEC_CODE
) != 0)
13306 /* When the address of a Thumb function is taken the bottom
13307 bit of that address should be set. This will allow
13308 interworking between Arm and Thumb functions to work
13311 THUMB_SET_FUNC (sym
, 1);
13313 label_is_thumb_function_name
= FALSE
;
13317 /* Adjust the symbol table. This marks Thumb symbols as distinct from
13321 arm_adjust_symtab (void)
13326 for (sym
= symbol_rootP
; sym
!= NULL
; sym
= symbol_next (sym
))
13328 if (ARM_IS_THUMB (sym
))
13330 if (THUMB_IS_FUNC (sym
))
13332 /* Mark the symbol as a Thumb function. */
13333 if ( S_GET_STORAGE_CLASS (sym
) == C_STAT
13334 || S_GET_STORAGE_CLASS (sym
) == C_LABEL
) /* This can happen! */
13335 S_SET_STORAGE_CLASS (sym
, C_THUMBSTATFUNC
);
13337 else if (S_GET_STORAGE_CLASS (sym
) == C_EXT
)
13338 S_SET_STORAGE_CLASS (sym
, C_THUMBEXTFUNC
);
13340 as_bad (_("%s: unexpected function type: %d"),
13341 S_GET_NAME (sym
), S_GET_STORAGE_CLASS (sym
));
13343 else switch (S_GET_STORAGE_CLASS (sym
))
13346 S_SET_STORAGE_CLASS (sym
, C_THUMBEXT
);
13349 S_SET_STORAGE_CLASS (sym
, C_THUMBSTAT
);
13352 S_SET_STORAGE_CLASS (sym
, C_THUMBLABEL
);
13360 if (ARM_IS_INTERWORK (sym
))
13361 coffsymbol (symbol_get_bfdsym (sym
))->native
->u
.syment
.n_flags
= 0xFF;
13368 for (sym
= symbol_rootP
; sym
!= NULL
; sym
= symbol_next (sym
))
13370 if (ARM_IS_THUMB (sym
))
13372 elf_symbol_type
* elf_sym
;
13374 elf_sym
= elf_symbol (symbol_get_bfdsym (sym
));
13375 bind
= ELF_ST_BIND (elf_sym
);
13377 /* If it's a .thumb_func, declare it as so,
13378 otherwise tag label as .code 16. */
13379 if (THUMB_IS_FUNC (sym
))
13380 elf_sym
->internal_elf_sym
.st_info
=
13381 ELF_ST_INFO (bind
, STT_ARM_TFUNC
);
13383 elf_sym
->internal_elf_sym
.st_info
=
13384 ELF_ST_INFO (bind
, STT_ARM_16BIT
);
13391 arm_data_in_code (void)
13393 if (thumb_mode
&& ! strncmp (input_line_pointer
+ 1, "data:", 5))
13395 *input_line_pointer
= '/';
13396 input_line_pointer
+= 5;
13397 *input_line_pointer
= 0;
13405 arm_canonicalize_symbol_name (char * name
)
13409 if (thumb_mode
&& (len
= strlen (name
)) > 5
13410 && streq (name
+ len
- 5, "/data"))
13411 *(name
+ len
- 5) = 0;
13416 #if defined OBJ_COFF || defined OBJ_ELF
13418 arm_validate_fix (fixS
* fixP
)
13420 /* If the destination of the branch is a defined symbol which does not have
13421 the THUMB_FUNC attribute, then we must be calling a function which has
13422 the (interfacearm) attribute. We look for the Thumb entry point to that
13423 function and change the branch to refer to that function instead. */
13424 if (fixP
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BRANCH23
13425 && fixP
->fx_addsy
!= NULL
13426 && S_IS_DEFINED (fixP
->fx_addsy
)
13427 && ! THUMB_IS_FUNC (fixP
->fx_addsy
))
13429 fixP
->fx_addsy
= find_real_start (fixP
->fx_addsy
);
13435 arm_force_relocation (struct fix
* fixp
)
13437 #if defined (OBJ_COFF) && defined (TE_PE)
13438 if (fixp
->fx_r_type
== BFD_RELOC_RVA
)
13442 if (fixp
->fx_r_type
== BFD_RELOC_ARM_PCREL_BRANCH
13443 || fixp
->fx_r_type
== BFD_RELOC_ARM_PCREL_BLX
13444 || fixp
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BLX
13445 || fixp
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BRANCH23
)
13449 /* Resolve these relocations even if the symbol is extern or weak. */
13450 if (fixp
->fx_r_type
== BFD_RELOC_ARM_IMMEDIATE
13451 || fixp
->fx_r_type
== BFD_RELOC_ARM_OFFSET_IMM
13452 || fixp
->fx_r_type
== BFD_RELOC_ARM_ADRL_IMMEDIATE
)
13455 return generic_force_reloc (fixp
);
13459 /* This is a little hack to help the gas/arm/adrl.s test. It prevents
13460 local labels from being added to the output symbol table when they
13461 are used with the ADRL pseudo op. The ADRL relocation should always
13462 be resolved before the binbary is emitted, so it is safe to say that
13463 it is adjustable. */
13466 arm_fix_adjustable (fixS
* fixP
)
13468 if (fixP
->fx_r_type
== BFD_RELOC_ARM_ADRL_IMMEDIATE
)
13475 /* Relocations against Thumb function names must be left unadjusted,
13476 so that the linker can use this information to correctly set the
13477 bottom bit of their addresses. The MIPS version of this function
13478 also prevents relocations that are mips-16 specific, but I do not
13479 know why it does this.
13482 There is one other problem that ought to be addressed here, but
13483 which currently is not: Taking the address of a label (rather
13484 than a function) and then later jumping to that address. Such
13485 addresses also ought to have their bottom bit set (assuming that
13486 they reside in Thumb code), but at the moment they will not. */
13489 arm_fix_adjustable (fixS
* fixP
)
13491 if (fixP
->fx_addsy
== NULL
)
13494 if (THUMB_IS_FUNC (fixP
->fx_addsy
)
13495 && fixP
->fx_subsy
== NULL
)
13498 /* We need the symbol name for the VTABLE entries. */
13499 if ( fixP
->fx_r_type
== BFD_RELOC_VTABLE_INHERIT
13500 || fixP
->fx_r_type
== BFD_RELOC_VTABLE_ENTRY
)
13503 /* Don't allow symbols to be discarded on GOT related relocs. */
13504 if (fixP
->fx_r_type
== BFD_RELOC_ARM_PLT32
13505 || fixP
->fx_r_type
== BFD_RELOC_ARM_GOT32
13506 || fixP
->fx_r_type
== BFD_RELOC_ARM_GOTOFF
13507 || fixP
->fx_r_type
== BFD_RELOC_ARM_TARGET2
)
13514 elf32_arm_target_format (void)
13517 return (target_big_endian
13518 ? "elf32-bigarm-symbian"
13519 : "elf32-littlearm-symbian");
13521 if (target_big_endian
)
13524 return "elf32-bigarm-oabi";
13526 return "elf32-bigarm";
13531 return "elf32-littlearm-oabi";
13533 return "elf32-littlearm";
13539 armelf_frob_symbol (symbolS
* symp
,
13542 elf_frob_symbol (symp
, puntp
);
13546 s_arm_elf_cons (int nbytes
)
13550 #ifdef md_flush_pending_output
13551 md_flush_pending_output ();
13554 if (is_it_end_of_statement ())
13556 demand_empty_rest_of_line ();
13560 #ifdef md_cons_align
13561 md_cons_align (nbytes
);
13564 mapping_state (MAP_DATA
);
13567 bfd_reloc_code_real_type reloc
;
13569 expression (& exp
);
13571 if (exp
.X_op
== O_symbol
13572 && * input_line_pointer
== '('
13573 && (reloc
= arm_parse_reloc ()) != BFD_RELOC_UNUSED
)
13575 reloc_howto_type
*howto
= bfd_reloc_type_lookup (stdoutput
, reloc
);
13576 int size
= bfd_get_reloc_size (howto
);
13579 as_bad ("%s relocations do not fit in %d bytes",
13580 howto
->name
, nbytes
);
13583 char *p
= frag_more ((int) nbytes
);
13584 int offset
= nbytes
- size
;
13586 fix_new_exp (frag_now
, p
- frag_now
->fr_literal
+ offset
, size
,
13591 emit_expr (&exp
, (unsigned int) nbytes
);
13593 while (*input_line_pointer
++ == ',');
13595 /* Put terminator back into stream. */
13596 input_line_pointer
--;
13597 demand_empty_rest_of_line ();
13601 /* Parse a .rel31 directive. */
13604 s_arm_rel31 (int ignored ATTRIBUTE_UNUSED
)
13610 SKIP_WHITESPACE ();
13613 if (*input_line_pointer
== '1')
13614 highbit
= 0x80000000;
13615 else if (*input_line_pointer
!= '0')
13616 as_bad (_("expected 0 or 1"));
13618 input_line_pointer
++;
13619 SKIP_WHITESPACE ();
13620 if (*input_line_pointer
!= ',')
13621 as_bad (_("missing comma"));
13622 input_line_pointer
++;
13624 #ifdef md_flush_pending_output
13625 md_flush_pending_output ();
13628 #ifdef md_cons_align
13632 mapping_state (MAP_DATA
);
13637 md_number_to_chars (p
, highbit
, 4);
13638 fix_new_arm (frag_now
, p
- frag_now
->fr_literal
, 4, &exp
, 1,
13639 BFD_RELOC_ARM_PREL31
);
13641 demand_empty_rest_of_line ();
13644 /* Code to deal with unwinding tables. */
13646 static void add_unwind_adjustsp (offsetT
);
13648 /* Switch to section NAME and create section if necessary. It's
13649 rather ugly that we have to manipulate input_line_pointer but I
13650 don't see any other way to accomplish the same thing without
13651 changing obj-elf.c (which may be the Right Thing, in the end).
13652 Copied from tc-ia64.c. */
13655 set_section (char *name
)
13657 char *saved_input_line_pointer
;
13659 saved_input_line_pointer
= input_line_pointer
;
13660 input_line_pointer
= name
;
13661 obj_elf_section (0);
13662 input_line_pointer
= saved_input_line_pointer
;
13665 /* Cenerate and deferred unwind frame offset. */
13668 flush_pending_unwind (void)
13672 offset
= unwind
.pending_offset
;
13673 unwind
.pending_offset
= 0;
13675 add_unwind_adjustsp (offset
);
13678 /* Add an opcode to this list for this function. Two-byte opcodes should
13679 be passed as op[0] << 8 | op[1]. The list of opcodes is built in reverse
13683 add_unwind_opcode (valueT op
, int length
)
13685 /* Add any deferred stack adjustment. */
13686 if (unwind
.pending_offset
)
13687 flush_pending_unwind ();
13689 unwind
.sp_restored
= 0;
13691 if (unwind
.opcode_count
+ length
> unwind
.opcode_alloc
)
13693 unwind
.opcode_alloc
+= ARM_OPCODE_CHUNK_SIZE
;
13694 if (unwind
.opcodes
)
13695 unwind
.opcodes
= xrealloc (unwind
.opcodes
,
13696 unwind
.opcode_alloc
);
13698 unwind
.opcodes
= xmalloc (unwind
.opcode_alloc
);
13703 unwind
.opcodes
[unwind
.opcode_count
] = op
& 0xff;
13705 unwind
.opcode_count
++;
13709 /* Add unwind opcodes to adjust the stack pointer. */
13712 add_unwind_adjustsp (offsetT offset
)
13716 if (offset
> 0x200)
13718 /* We need at most 5 bytes to hold a 32-bit value in a uleb128. */
13723 /* Long form: 0xb2, uleb128. */
13724 /* This might not fit in a word so add the individual bytes,
13725 remembering the list is built in reverse order. */
13726 o
= (valueT
) ((offset
- 0x204) >> 2);
13728 add_unwind_opcode (0, 1);
13730 /* Calculate the uleb128 encoding of the offset. */
13734 bytes
[n
] = o
& 0x7f;
13740 /* Add the insn. */
13742 add_unwind_opcode (bytes
[n
- 1], 1);
13743 add_unwind_opcode (0xb2, 1);
13745 else if (offset
> 0x100)
13747 /* Two short opcodes. */
13748 add_unwind_opcode (0x3f, 1);
13749 op
= (offset
- 0x104) >> 2;
13750 add_unwind_opcode (op
, 1);
13752 else if (offset
> 0)
13754 /* Short opcode. */
13755 op
= (offset
- 4) >> 2;
13756 add_unwind_opcode (op
, 1);
13758 else if (offset
< 0)
13761 while (offset
> 0x100)
13763 add_unwind_opcode (0x7f, 1);
13766 op
= ((offset
- 4) >> 2) | 0x40;
13767 add_unwind_opcode (op
, 1);
13771 /* Finish the list of unwind opcodes for this function. */
13773 finish_unwind_opcodes (void)
13777 if (unwind
.fp_used
)
13779 /* Adjust sp as neccessary. */
13780 unwind
.pending_offset
+= unwind
.fp_offset
- unwind
.frame_size
;
13781 flush_pending_unwind ();
13783 /* After restoring sp from the frame pointer. */
13784 op
= 0x90 | unwind
.fp_reg
;
13785 add_unwind_opcode (op
, 1);
13788 flush_pending_unwind ();
13792 /* Start an exception table entry. If idx is nonzero this is an index table
13796 start_unwind_section (const segT text_seg
, int idx
)
13798 const char * text_name
;
13799 const char * prefix
;
13800 const char * prefix_once
;
13804 size_t sec_name_len
;
13808 prefix
= ELF_STRING_ARM_unwind
;
13809 prefix_once
= ELF_STRING_ARM_unwind_once
;
13813 prefix
= ELF_STRING_ARM_unwind_info
;
13814 prefix_once
= ELF_STRING_ARM_unwind_info_once
;
13817 text_name
= segment_name (text_seg
);
13818 if (streq (text_name
, ".text"))
13821 if (strncmp (text_name
, ".gnu.linkonce.t.",
13822 strlen (".gnu.linkonce.t.")) == 0)
13824 prefix
= prefix_once
;
13825 text_name
+= strlen (".gnu.linkonce.t.");
13828 prefix_len
= strlen (prefix
);
13829 text_len
= strlen (text_name
);
13830 sec_name_len
= prefix_len
+ text_len
;
13831 sec_name
= alloca (sec_name_len
+ 1);
13832 memcpy (sec_name
, prefix
, prefix_len
);
13833 memcpy (sec_name
+ prefix_len
, text_name
, text_len
);
13834 sec_name
[prefix_len
+ text_len
] = '\0';
13836 /* Handle COMDAT group. */
13837 if (prefix
!= prefix_once
&& (text_seg
->flags
& SEC_LINK_ONCE
) != 0)
13840 size_t len
, group_name_len
;
13841 const char *group_name
= elf_group_name (text_seg
);
13843 if (group_name
== NULL
)
13845 as_bad ("Group section `%s' has no group signature",
13846 segment_name (text_seg
));
13847 ignore_rest_of_line ();
13850 /* We have to construct a fake section directive. */
13851 group_name_len
= strlen (group_name
);
13857 len
= (sec_name_len
13858 + prefix_len
/* ,"aG",%sectiontype, */
13859 + group_name_len
/* ,group_name */
13860 + 7); /* ,comdat */
13862 section
= alloca (len
+ 1);
13863 memcpy (section
, sec_name
, sec_name_len
);
13865 memcpy (section
+ sec_name_len
, ",\"aG\",%exidx,", 13);
13867 memcpy (section
+ sec_name_len
, ",\"aG\",%progbits,", 16);
13868 memcpy (section
+ sec_name_len
+ prefix_len
, group_name
, group_name_len
);
13869 memcpy (section
+ len
- 7, ",comdat", 7);
13870 section
[len
] = '\0';
13871 set_section (section
);
13875 set_section (sec_name
);
13876 bfd_set_section_flags (stdoutput
, now_seg
,
13877 SEC_LOAD
| SEC_ALLOC
| SEC_READONLY
);
13880 /* Set the setion link for index tables. */
13882 elf_linked_to_section (now_seg
) = text_seg
;
13886 /* Start an unwind table entry. HAVE_DATA is nonzero if we have additional
13887 personality routine data. Returns zero, or the index table value for
13888 and inline entry. */
13891 create_unwind_entry (int have_data
)
13895 unsigned char *ptr
;
13896 /* The current word of data. */
13898 /* The number of bytes left in this word. */
13901 finish_unwind_opcodes ();
13903 /* Remember the current text section. */
13904 unwind
.saved_seg
= now_seg
;
13905 unwind
.saved_subseg
= now_subseg
;
13907 start_unwind_section (now_seg
, 0);
13909 if (unwind
.personality_routine
== NULL
)
13911 if (unwind
.personality_index
== -2)
13914 as_bad (_("handerdata in cantunwind frame"));
13915 return 1; /* EXIDX_CANTUNWIND. */
13918 /* Use a default personality routine if none is specified. */
13919 if (unwind
.personality_index
== -1)
13921 if (unwind
.opcode_count
> 3)
13922 unwind
.personality_index
= 1;
13924 unwind
.personality_index
= 0;
13927 /* Space for the personality routine entry. */
13928 if (unwind
.personality_index
== 0)
13930 if (unwind
.opcode_count
> 3)
13931 as_bad (_("too many unwind opcodes for personality routine 0"));
13935 /* All the data is inline in the index table. */
13938 while (unwind
.opcode_count
> 0)
13940 unwind
.opcode_count
--;
13941 data
= (data
<< 8) | unwind
.opcodes
[unwind
.opcode_count
];
13945 /* Pad with "finish" opcodes. */
13947 data
= (data
<< 8) | 0xb0;
13954 /* We get two opcodes "free" in the first word. */
13955 size
= unwind
.opcode_count
- 2;
13958 /* An extra byte is required for the opcode count. */
13959 size
= unwind
.opcode_count
+ 1;
13961 size
= (size
+ 3) >> 2;
13963 as_bad (_("too many unwind opcodes"));
13965 frag_align (2, 0, 0);
13966 record_alignment (now_seg
, 2);
13967 unwind
.table_entry
= expr_build_dot ();
13969 /* Allocate the table entry. */
13970 ptr
= frag_more ((size
<< 2) + 4);
13971 where
= frag_now_fix () - ((size
<< 2) + 4);
13973 switch (unwind
.personality_index
)
13976 /* ??? Should this be a PLT generating relocation? */
13977 /* Custom personality routine. */
13978 fix_new (frag_now
, where
, 4, unwind
.personality_routine
, 0, 1,
13979 BFD_RELOC_ARM_PREL31
);
13983 /* Set the first byte to the number of additional words. */
13988 /* ABI defined personality routines. */
13989 /* TODO: Emit R_ARM_NONE to the personality routine. */
13991 /* Three opcodes bytes are packed into the first word. */
13998 /* The size and first two opcode bytes go in the first word. */
13999 data
= ((0x80 + unwind
.personality_index
) << 8) | size
;
14004 /* Should never happen. */
14008 /* Pack the opcodes into words (MSB first), reversing the list at the same
14010 while (unwind
.opcode_count
> 0)
14014 md_number_to_chars (ptr
, data
, 4);
14019 unwind
.opcode_count
--;
14021 data
= (data
<< 8) | unwind
.opcodes
[unwind
.opcode_count
];
14024 /* Finish off the last word. */
14027 /* Pad with "finish" opcodes. */
14029 data
= (data
<< 8) | 0xb0;
14031 md_number_to_chars (ptr
, data
, 4);
14036 /* Add an empty descriptor if there is no user-specified data. */
14037 ptr
= frag_more (4);
14038 md_number_to_chars (ptr
, 0, 4);
14045 /* Parse an unwind_fnstart directive. Simply records the current location. */
14048 s_arm_unwind_fnstart (int ignored ATTRIBUTE_UNUSED
)
14050 demand_empty_rest_of_line ();
14051 /* Mark the start of the function. */
14052 unwind
.proc_start
= expr_build_dot ();
14054 /* Reset the rest of the unwind info. */
14055 unwind
.opcode_count
= 0;
14056 unwind
.table_entry
= NULL
;
14057 unwind
.personality_routine
= NULL
;
14058 unwind
.personality_index
= -1;
14059 unwind
.frame_size
= 0;
14060 unwind
.fp_offset
= 0;
14061 unwind
.fp_reg
= 13;
14062 unwind
.fp_used
= 0;
14063 unwind
.sp_restored
= 0;
14067 /* Parse a handlerdata directive. Creates the exception handling table entry
14068 for the function. */
14071 s_arm_unwind_handlerdata (int ignored ATTRIBUTE_UNUSED
)
14073 demand_empty_rest_of_line ();
14074 if (unwind
.table_entry
)
14075 as_bad (_("dupicate .handlerdata directive"));
14077 create_unwind_entry (1);
14080 /* Parse an unwind_fnend directive. Generates the index table entry. */
14083 s_arm_unwind_fnend (int ignored ATTRIBUTE_UNUSED
)
14086 unsigned char *ptr
;
14089 demand_empty_rest_of_line ();
14091 /* Add eh table entry. */
14092 if (unwind
.table_entry
== NULL
)
14093 val
= create_unwind_entry (0);
14097 /* Add index table entry. This is two words. */
14098 start_unwind_section (unwind
.saved_seg
, 1);
14099 frag_align (2, 0, 0);
14100 record_alignment (now_seg
, 2);
14102 ptr
= frag_more (8);
14103 where
= frag_now_fix () - 8;
14105 /* Self relative offset of the function start. */
14106 fix_new (frag_now
, where
, 4, unwind
.proc_start
, 0, 1,
14110 /* Inline exception table entry. */
14111 md_number_to_chars (ptr
+ 4, val
, 4);
14113 /* Self relative offset of the table entry. */
14114 fix_new (frag_now
, where
+ 4, 4, unwind
.table_entry
, 0, 1,
14115 BFD_RELOC_ARM_PREL31
);
14117 /* Restore the original section. */
14118 subseg_set (unwind
.saved_seg
, unwind
.saved_subseg
);
14122 /* Parse an unwind_cantunwind directive. */
14125 s_arm_unwind_cantunwind (int ignored ATTRIBUTE_UNUSED
)
14127 demand_empty_rest_of_line ();
14128 if (unwind
.personality_routine
|| unwind
.personality_index
!= -1)
14129 as_bad (_("personality routine specified for cantunwind frame"));
14131 unwind
.personality_index
= -2;
14135 /* Parse a personalityindex directive. */
14138 s_arm_unwind_personalityindex (int ignored ATTRIBUTE_UNUSED
)
14142 if (unwind
.personality_routine
|| unwind
.personality_index
!= -1)
14143 as_bad (_("duplicate .personalityindex directive"));
14145 SKIP_WHITESPACE ();
14149 if (exp
.X_op
!= O_constant
14150 || exp
.X_add_number
< 0 || exp
.X_add_number
> 15)
14152 as_bad (_("bad personality routine number"));
14153 ignore_rest_of_line ();
14157 unwind
.personality_index
= exp
.X_add_number
;
14159 demand_empty_rest_of_line ();
14163 /* Parse a personality directive. */
14166 s_arm_unwind_personality (int ignored ATTRIBUTE_UNUSED
)
14170 if (unwind
.personality_routine
|| unwind
.personality_index
!= -1)
14171 as_bad (_("duplicate .personality directive"));
14173 SKIP_WHITESPACE ();
14174 name
= input_line_pointer
;
14175 c
= get_symbol_end ();
14176 p
= input_line_pointer
;
14177 unwind
.personality_routine
= symbol_find_or_make (name
);
14179 SKIP_WHITESPACE ();
14180 demand_empty_rest_of_line ();
14184 /* Parse a directive saving core registers. */
14187 s_arm_unwind_save_core (void)
14193 SKIP_WHITESPACE ();
14194 range
= reg_list (&input_line_pointer
);
14197 as_bad (_("expected register list"));
14198 ignore_rest_of_line ();
14202 demand_empty_rest_of_line ();
14204 /* Turn .unwind_movsp ip followed by .unwind_save {..., ip, ...}
14205 into .unwind_save {..., sp...}. We aren't bothered about the value of
14206 ip because it is clobbered by calls. */
14207 if (unwind
.sp_restored
&& unwind
.fp_reg
== 12
14208 && (range
& 0x3000) == 0x1000)
14210 unwind
.opcode_count
--;
14211 unwind
.sp_restored
= 0;
14212 range
= (range
| 0x2000) & ~0x1000;
14213 unwind
.pending_offset
= 0;
14216 /* See if we can use the short opcodes. These pop a block of upto 8
14217 registers starting with r4, plus maybe r14. */
14218 for (n
= 0; n
< 8; n
++)
14220 /* Break at the first non-saved register. */
14221 if ((range
& (1 << (n
+ 4))) == 0)
14224 /* See if there are any other bits set. */
14225 if (n
== 0 || (range
& (0xfff0 << n
) & 0xbff0) != 0)
14227 /* Use the long form. */
14228 op
= 0x8000 | ((range
>> 4) & 0xfff);
14229 add_unwind_opcode (op
, 2);
14233 /* Use the short form. */
14234 if (range
& 0x4000)
14235 op
= 0xa8; /* Pop r14. */
14237 op
= 0xa0; /* Do not pop r14. */
14239 add_unwind_opcode (op
, 1);
14245 op
= 0xb100 | (range
& 0xf);
14246 add_unwind_opcode (op
, 2);
14249 /* Record the number of bytes pushed. */
14250 for (n
= 0; n
< 16; n
++)
14252 if (range
& (1 << n
))
14253 unwind
.frame_size
+= 4;
14258 /* Parse a directive saving FPA registers. */
14261 s_arm_unwind_save_fpa (int reg
)
14267 /* Get Number of registers to transfer. */
14268 if (skip_past_comma (&input_line_pointer
) != FAIL
)
14271 exp
.X_op
= O_illegal
;
14273 if (exp
.X_op
!= O_constant
)
14275 as_bad (_("expected , <constant>"));
14276 ignore_rest_of_line ();
14280 num_regs
= exp
.X_add_number
;
14282 if (num_regs
< 1 || num_regs
> 4)
14284 as_bad (_("number of registers must be in the range [1:4]"));
14285 ignore_rest_of_line ();
14289 demand_empty_rest_of_line ();
14294 op
= 0xb4 | (num_regs
- 1);
14295 add_unwind_opcode (op
, 1);
14300 op
= 0xc800 | (reg
<< 4) | (num_regs
- 1);
14301 add_unwind_opcode (op
, 2);
14303 unwind
.frame_size
+= num_regs
* 12;
14307 /* Parse a directive saving VFP registers. */
14310 s_arm_unwind_save_vfp (void)
14316 count
= vfp_parse_reg_list (&input_line_pointer
, ®
, 1);
14319 as_bad (_("expected register list"));
14320 ignore_rest_of_line ();
14324 demand_empty_rest_of_line ();
14329 op
= 0xb8 | (count
- 1);
14330 add_unwind_opcode (op
, 1);
14335 op
= 0xb300 | (reg
<< 4) | (count
- 1);
14336 add_unwind_opcode (op
, 2);
14338 unwind
.frame_size
+= count
* 8 + 4;
14342 /* Parse a directive saving iWMMXt registers. */
14345 s_arm_unwind_save_wmmx (void)
14354 if (*input_line_pointer
== '{')
14355 input_line_pointer
++;
14361 reg
= arm_reg_parse (&input_line_pointer
,
14362 all_reg_maps
[REG_TYPE_IWMMXT
].htab
);
14364 if (wr_register (reg
))
14366 i
= reg
& ~WR_PREFIX
;
14368 as_tsktsk (_("register list not in ascending order"));
14371 else if (wcg_register (reg
))
14373 i
= (reg
& ~WC_PREFIX
) - 8;
14375 as_tsktsk (_("register list not in ascending order"));
14376 wcg_mask
|= 1 << i
;
14380 as_bad (_("expected wr or wcgr"));
14384 SKIP_WHITESPACE ();
14385 if (*input_line_pointer
== '-')
14387 hi_reg
= arm_reg_parse (&input_line_pointer
,
14388 all_reg_maps
[REG_TYPE_IWMMXT
].htab
);
14389 if (wr_register (reg
) && wr_register (hi_reg
))
14391 for (; reg
< hi_reg
; reg
++)
14392 wr_mask
|= 1 << (reg
& ~WR_PREFIX
);
14394 else if (wcg_register (reg
) && wcg_register (hi_reg
))
14396 for (; reg
< hi_reg
; reg
++)
14397 wcg_mask
|= 1 << ((reg
& ~WC_PREFIX
) - 8);
14401 as_bad (_("bad register range"));
14406 while (skip_past_comma (&input_line_pointer
) != FAIL
);
14408 SKIP_WHITESPACE ();
14409 if (*input_line_pointer
== '}')
14410 input_line_pointer
++;
14412 demand_empty_rest_of_line ();
14414 if (wr_mask
&& wcg_mask
)
14416 as_bad (_("inconsistent register types"));
14420 /* Generate any deferred opcodes becuuse we're going to be looking at
14422 flush_pending_unwind ();
14426 for (i
= 0; i
< 16; i
++)
14428 if (wcg_mask
& (1 << i
))
14429 unwind
.frame_size
+= 4;
14431 op
= 0xc700 | wcg_mask
;
14432 add_unwind_opcode (op
, 2);
14436 for (i
= 0; i
< 16; i
++)
14438 if (wr_mask
& (1 << i
))
14439 unwind
.frame_size
+= 8;
14441 /* Attempt to combine with a previous opcode. We do this because gcc
14442 likes to output separate unwind directives for a single block of
14444 if (unwind
.opcode_count
> 0)
14446 i
= unwind
.opcodes
[unwind
.opcode_count
- 1];
14447 if ((i
& 0xf8) == 0xc0)
14450 /* Only merge if the blocks are contiguous. */
14453 if ((wr_mask
& 0xfe00) == (1 << 9))
14455 wr_mask
|= ((1 << (i
+ 11)) - 1) & 0xfc00;
14456 unwind
.opcode_count
--;
14459 else if (i
== 6 && unwind
.opcode_count
>= 2)
14461 i
= unwind
.opcodes
[unwind
.opcode_count
- 2];
14465 op
= 0xffff << (reg
- 1);
14467 || ((wr_mask
& op
) == (1u << (reg
- 1))))
14469 op
= (1 << (reg
+ i
+ 1)) - 1;
14470 op
&= ~((1 << reg
) - 1);
14472 unwind
.opcode_count
-= 2;
14479 /* We want to generate opcodes in the order the registers have been
14480 saved, ie. descending order. */
14481 for (reg
= 15; reg
>= -1; reg
--)
14483 /* Save registers in blocks. */
14485 || !(wr_mask
& (1 << reg
)))
14487 /* We found an unsaved reg. Generate opcodes to save the
14488 preceeding block. */
14494 op
= 0xc0 | (hi_reg
- 10);
14495 add_unwind_opcode (op
, 1);
14500 op
= 0xc600 | ((reg
+ 1) << 4) | ((hi_reg
- reg
) - 1);
14501 add_unwind_opcode (op
, 2);
14510 ignore_rest_of_line ();
14514 /* Parse an unwind_save directive. */
14517 s_arm_unwind_save (int ignored ATTRIBUTE_UNUSED
)
14522 /* Figure out what sort of save we have. */
14523 SKIP_WHITESPACE ();
14524 saved_ptr
= input_line_pointer
;
14526 reg
= arm_reg_parse (&input_line_pointer
, all_reg_maps
[REG_TYPE_FN
].htab
);
14529 s_arm_unwind_save_fpa (reg
);
14533 if (*input_line_pointer
== '{')
14534 input_line_pointer
++;
14536 SKIP_WHITESPACE ();
14538 reg
= arm_reg_parse (&input_line_pointer
, all_reg_maps
[REG_TYPE_RN
].htab
);
14541 input_line_pointer
= saved_ptr
;
14542 s_arm_unwind_save_core ();
14546 reg
= arm_reg_parse (&input_line_pointer
, all_reg_maps
[REG_TYPE_DN
].htab
);
14549 input_line_pointer
= saved_ptr
;
14550 s_arm_unwind_save_vfp ();
14554 reg
= arm_reg_parse (&input_line_pointer
,
14555 all_reg_maps
[REG_TYPE_IWMMXT
].htab
);
14558 input_line_pointer
= saved_ptr
;
14559 s_arm_unwind_save_wmmx ();
14563 /* TODO: Maverick registers. */
14564 as_bad (_("unrecognised register"));
14568 /* Parse an unwind_movsp directive. */
14571 s_arm_unwind_movsp (int ignored ATTRIBUTE_UNUSED
)
14576 SKIP_WHITESPACE ();
14577 reg
= reg_required_here (&input_line_pointer
, -1);
14580 as_bad (_("ARM register expected"));
14581 ignore_rest_of_line ();
14585 if (reg
== 13 || reg
== 15)
14587 as_bad (_("r%d not permitted in .unwind_movsp directive"), reg
);
14588 ignore_rest_of_line ();
14592 if (unwind
.fp_reg
!= 13)
14593 as_bad (_("unexpected .unwind_movsp directive"));
14595 /* Generate opcode to restore the value. */
14597 add_unwind_opcode (op
, 1);
14599 /* Record the information for later. */
14600 unwind
.fp_reg
= reg
;
14601 unwind
.fp_offset
= unwind
.frame_size
;
14602 unwind
.sp_restored
= 1;
14603 demand_empty_rest_of_line ();
14607 /* Parse #<number>. */
14610 require_hashconst (int * val
)
14614 SKIP_WHITESPACE ();
14615 if (*input_line_pointer
== '#')
14617 input_line_pointer
++;
14621 exp
.X_op
= O_illegal
;
14623 if (exp
.X_op
!= O_constant
)
14625 as_bad (_("expected #constant"));
14626 ignore_rest_of_line ();
14629 *val
= exp
.X_add_number
;
14633 /* Parse an unwind_pad directive. */
14636 s_arm_unwind_pad (int ignored ATTRIBUTE_UNUSED
)
14640 if (require_hashconst (&offset
) == FAIL
)
14645 as_bad (_("stack increment must be multiple of 4"));
14646 ignore_rest_of_line ();
14650 /* Don't generate any opcodes, just record the details for later. */
14651 unwind
.frame_size
+= offset
;
14652 unwind
.pending_offset
+= offset
;
14654 demand_empty_rest_of_line ();
14657 /* Parse an unwind_setfp directive. */
14660 s_arm_unwind_setfp (int ignored ATTRIBUTE_UNUSED
)
14666 fp_reg
= reg_required_here (&input_line_pointer
, -1);
14667 if (skip_past_comma (&input_line_pointer
) == FAIL
)
14670 sp_reg
= reg_required_here (&input_line_pointer
, -1);
14672 if (fp_reg
== FAIL
|| sp_reg
== FAIL
)
14674 as_bad (_("expected <reg>, <reg>"));
14675 ignore_rest_of_line ();
14679 /* Optonal constant. */
14680 if (skip_past_comma (&input_line_pointer
) != FAIL
)
14682 if (require_hashconst (&offset
) == FAIL
)
14688 demand_empty_rest_of_line ();
14690 if (sp_reg
!= 13 && sp_reg
!= unwind
.fp_reg
)
14692 as_bad (_("register must be either sp or set by a previous"
14693 "unwind_movsp directive"));
14697 /* Don't generate any opcodes, just record the information for later. */
14698 unwind
.fp_reg
= fp_reg
;
14699 unwind
.fp_used
= 1;
14701 unwind
.fp_offset
= unwind
.frame_size
- offset
;
14703 unwind
.fp_offset
-= offset
;
14706 /* Parse an unwind_raw directive. */
14709 s_arm_unwind_raw (int ignored ATTRIBUTE_UNUSED
)
14712 /* This is an arbitary limit. */
14713 unsigned char op
[16];
14716 SKIP_WHITESPACE ();
14718 if (exp
.X_op
== O_constant
14719 && skip_past_comma (&input_line_pointer
) != FAIL
)
14721 unwind
.frame_size
+= exp
.X_add_number
;
14725 exp
.X_op
= O_illegal
;
14727 if (exp
.X_op
!= O_constant
)
14729 as_bad (_("expected <offset>, <opcode>"));
14730 ignore_rest_of_line ();
14736 /* Parse the opcode. */
14741 as_bad (_("unwind opcode too long"));
14742 ignore_rest_of_line ();
14744 if (exp
.X_op
!= O_constant
|| exp
.X_add_number
& ~0xff)
14746 as_bad (_("invalid unwind opcode"));
14747 ignore_rest_of_line ();
14750 op
[count
++] = exp
.X_add_number
;
14752 /* Parse the next byte. */
14753 if (skip_past_comma (&input_line_pointer
) == FAIL
)
14759 /* Add the opcode bytes in reverse order. */
14761 add_unwind_opcode (op
[count
], 1);
14763 demand_empty_rest_of_line ();
14766 #endif /* OBJ_ELF */
14768 /* This is called from HANDLE_ALIGN in write.c. Fill in the contents
14769 of an rs_align_code fragment. */
14772 arm_handle_align (fragS
* fragP
)
14774 static char const arm_noop
[4] = { 0x00, 0x00, 0xa0, 0xe1 };
14775 static char const thumb_noop
[2] = { 0xc0, 0x46 };
14776 static char const arm_bigend_noop
[4] = { 0xe1, 0xa0, 0x00, 0x00 };
14777 static char const thumb_bigend_noop
[2] = { 0x46, 0xc0 };
14779 int bytes
, fix
, noop_size
;
14783 if (fragP
->fr_type
!= rs_align_code
)
14786 bytes
= fragP
->fr_next
->fr_address
- fragP
->fr_address
- fragP
->fr_fix
;
14787 p
= fragP
->fr_literal
+ fragP
->fr_fix
;
14790 if (bytes
> MAX_MEM_FOR_RS_ALIGN_CODE
)
14791 bytes
&= MAX_MEM_FOR_RS_ALIGN_CODE
;
14793 if (fragP
->tc_frag_data
)
14795 if (target_big_endian
)
14796 noop
= thumb_bigend_noop
;
14799 noop_size
= sizeof (thumb_noop
);
14803 if (target_big_endian
)
14804 noop
= arm_bigend_noop
;
14807 noop_size
= sizeof (arm_noop
);
14810 if (bytes
& (noop_size
- 1))
14812 fix
= bytes
& (noop_size
- 1);
14813 memset (p
, 0, fix
);
14818 while (bytes
>= noop_size
)
14820 memcpy (p
, noop
, noop_size
);
14822 bytes
-= noop_size
;
14826 fragP
->fr_fix
+= fix
;
14827 fragP
->fr_var
= noop_size
;
14830 /* Called from md_do_align. Used to create an alignment
14831 frag in a code section. */
14834 arm_frag_align_code (int n
, int max
)
14838 /* We assume that there will never be a requirement
14839 to support alignments greater than 32 bytes. */
14840 if (max
> MAX_MEM_FOR_RS_ALIGN_CODE
)
14841 as_fatal (_("alignments greater than 32 bytes not supported in .text sections."));
14843 p
= frag_var (rs_align_code
,
14844 MAX_MEM_FOR_RS_ALIGN_CODE
,
14846 (relax_substateT
) max
,
14853 /* Perform target specific initialisation of a frag. */
14856 arm_init_frag (fragS
* fragP
)
14858 /* Record whether this frag is in an ARM or a THUMB area. */
14859 fragP
->tc_frag_data
= thumb_mode
;
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' },