1 /* tc-arm.c -- Assemble for the ARM
2 Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
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)
8 This file is part of GAS, the GNU Assembler.
10 GAS is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2, or (at your option)
15 GAS is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with GAS; see the file COPYING. If not, write to the Free
22 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
28 #include "safe-ctype.h"
30 /* Need TARGET_CPU. */
39 #include "dwarf2dbg.h"
42 /* The following bitmasks control CPU extensions: */
43 #define ARM_EXT_V1 0x00000001 /* All processors (core set). */
44 #define ARM_EXT_V2 0x00000002 /* Multiply instructions. */
45 #define ARM_EXT_V2S 0x00000004 /* SWP instructions. */
46 #define ARM_EXT_V3 0x00000008 /* MSR MRS. */
47 #define ARM_EXT_V3M 0x00000010 /* Allow long multiplies. */
48 #define ARM_EXT_V4 0x00000020 /* Allow half word loads. */
49 #define ARM_EXT_V4T 0x00000040 /* Thumb v1. */
50 #define ARM_EXT_V5 0x00000080 /* Allow CLZ, etc. */
51 #define ARM_EXT_V5T 0x00000100 /* Thumb v2. */
52 #define ARM_EXT_V5ExP 0x00000200 /* DSP core set. */
53 #define ARM_EXT_V5E 0x00000400 /* DSP Double transfers. */
54 /* Processor specific extensions. */
55 #define ARM_EXT_XSCALE 0x00000800 /* Allow MIA etc. */
56 #define ARM_EXT_MAVERICK 0x00001000 /* Use Cirrus/DSP coprocessor. */
58 /* Architectures are the sum of the base and extensions. The ARM ARM (rev E)
59 defines the following: ARMv3, ARMv3M, ARMv4xM, ARMv4, ARMv4TxM, ARMv4T,
60 ARMv5xM, ARMv5, ARMv5TxM, ARMv5T, ARMv5TExP, ARMv5TE. To these we add
61 three more to cover cores prior to ARM6. Finally, there are cores which
62 implement further extensions in the co-processor space. */
63 #define ARM_ARCH_V1 ARM_EXT_V1
64 #define ARM_ARCH_V2 (ARM_ARCH_V1 | ARM_EXT_V2)
65 #define ARM_ARCH_V2S (ARM_ARCH_V2 | ARM_EXT_V2S)
66 #define ARM_ARCH_V3 (ARM_ARCH_V2S | ARM_EXT_V3)
67 #define ARM_ARCH_V3M (ARM_ARCH_V3 | ARM_EXT_V3M)
68 #define ARM_ARCH_V4xM (ARM_ARCH_V3 | ARM_EXT_V4)
69 #define ARM_ARCH_V4 (ARM_ARCH_V3M | ARM_EXT_V4)
70 #define ARM_ARCH_V4TxM (ARM_ARCH_V4xM | ARM_EXT_V4T)
71 #define ARM_ARCH_V4T (ARM_ARCH_V4 | ARM_EXT_V4T)
72 #define ARM_ARCH_V5xM (ARM_ARCH_V4xM | ARM_EXT_V5)
73 #define ARM_ARCH_V5 (ARM_ARCH_V4 | ARM_EXT_V5)
74 #define ARM_ARCH_V5TxM (ARM_ARCH_V5xM | ARM_EXT_V4T | ARM_EXT_V5T)
75 #define ARM_ARCH_V5T (ARM_ARCH_V5 | ARM_EXT_V4T | ARM_EXT_V5T)
76 #define ARM_ARCH_V5TExP (ARM_ARCH_V5T | ARM_EXT_V5ExP)
77 #define ARM_ARCH_V5TE (ARM_ARCH_V5TExP | ARM_EXT_V5E)
78 /* Processors with specific extensions in the co-processor space. */
79 #define ARM_ARCH_XSCALE (ARM_ARCH_V5TE | ARM_EXT_XSCALE)
81 /* Some useful combinations: */
82 #define ARM_ANY 0x00ffffff
83 #define ARM_ALL ARM_ANY
85 #define FPU_FPA_EXT_V1 0x80000000 /* Base FPA instruction set. */
86 #define FPU_FPA_EXT_V2 0x40000000 /* LFM/SFM. */
89 #define FPU_ARCH_FPE FPU_FPA_EXT_V1
90 #define FPU_ARCH_FPA (FPU_ARCH_FPE | FPU_FPA_EXT_V2)
92 /* Some useful combinations. */
93 #define FPU_ANY 0xff000000 /* Note this is ~ARM_ANY. */
95 /* Types of processor to assemble for. */
96 #define ARM_1 ARM_ARCH_V1
97 #define ARM_2 ARM_ARCH_V2
98 #define ARM_3 ARM_ARCH_V2S
99 #define ARM_250 ARM_ARCH_V2S
100 #define ARM_6 ARM_ARCH_V3
101 #define ARM_7 ARM_ARCH_V3
102 #define ARM_8 ARM_ARCH_V4
103 #define ARM_9 ARM_ARCH_V4T
104 #define ARM_STRONG ARM_ARCH_V4
105 #define ARM_CPU_MASK 0x0000000f /* XXX? */
108 #if defined __XSCALE__
109 #define CPU_DEFAULT (ARM_ARCH_XSCALE)
111 #if defined __thumb__
112 #define CPU_DEFAULT (ARM_ARCH_V5T)
114 #define CPU_DEFAULT ARM_ALL
120 #define FPU_DEFAULT FPU_ARCH_FPA
123 #define streq(a, b) (strcmp (a, b) == 0)
124 #define skip_whitespace(str) while (*(str) == ' ') ++(str)
126 static unsigned long cpu_variant
= CPU_DEFAULT
| FPU_DEFAULT
;
127 static int target_oabi
= 0;
129 #if defined OBJ_COFF || defined OBJ_ELF
130 /* Flags stored in private area of BFD structure. */
131 static boolean uses_apcs_26
= false;
132 static boolean atpcs
= false;
133 static boolean support_interwork
= false;
134 static boolean uses_apcs_float
= false;
135 static boolean pic_code
= false;
138 /* This array holds the chars that always start a comment. If the
139 pre-processor is disabled, these aren't very useful. */
140 const char comment_chars
[] = "@";
142 /* This array holds the chars that only start a comment at the beginning of
143 a line. If the line seems to have the form '# 123 filename'
144 .line and .file directives will appear in the pre-processed output. */
145 /* Note that input_file.c hand checks for '#' at the beginning of the
146 first line of the input file. This is because the compiler outputs
147 #NO_APP at the beginning of its output. */
148 /* Also note that comments like this one will always work. */
149 const char line_comment_chars
[] = "#";
151 const char line_separator_chars
[] = ";";
153 /* Chars that can be used to separate mant
154 from exp in floating point numbers. */
155 const char EXP_CHARS
[] = "eE";
157 /* Chars that mean this number is a floating point constant. */
161 const char FLT_CHARS
[] = "rRsSfFdDxXeEpP";
163 /* Prefix characters that indicate the start of an immediate
165 #define is_immediate_prefix(C) ((C) == '#' || (C) == '$')
168 /* Pre-defined "_GLOBAL_OFFSET_TABLE_" */
169 symbolS
* GOT_symbol
;
172 /* Size of relocation record. */
173 const int md_reloc_size
= 8;
175 /* 0: assemble for ARM,
176 1: assemble for Thumb,
177 2: assemble for Thumb even though target CPU does not support thumb
179 static int thumb_mode
= 0;
181 typedef struct arm_fix
189 unsigned long instruction
;
193 bfd_reloc_code_real_type type
;
210 struct asm_shift_properties
212 enum asm_shift_index index
;
213 unsigned long bit_field
;
214 unsigned int allows_0
: 1;
215 unsigned int allows_32
: 1;
218 static const struct asm_shift_properties shift_properties
[] =
220 { SHIFT_LSL
, 0, 1, 0},
221 { SHIFT_LSR
, 0x20, 0, 1},
222 { SHIFT_ASR
, 0x40, 0, 1},
223 { SHIFT_ROR
, 0x60, 0, 0},
224 { SHIFT_RRX
, 0x60, 0, 0}
227 struct asm_shift_name
230 const struct asm_shift_properties
* properties
;
233 static const struct asm_shift_name shift_names
[] =
235 { "asl", shift_properties
+ SHIFT_LSL
},
236 { "lsl", shift_properties
+ SHIFT_LSL
},
237 { "lsr", shift_properties
+ SHIFT_LSR
},
238 { "asr", shift_properties
+ SHIFT_ASR
},
239 { "ror", shift_properties
+ SHIFT_ROR
},
240 { "rrx", shift_properties
+ SHIFT_RRX
},
241 { "ASL", shift_properties
+ SHIFT_LSL
},
242 { "LSL", shift_properties
+ SHIFT_LSL
},
243 { "LSR", shift_properties
+ SHIFT_LSR
},
244 { "ASR", shift_properties
+ SHIFT_ASR
},
245 { "ROR", shift_properties
+ SHIFT_ROR
},
246 { "RRX", shift_properties
+ SHIFT_RRX
}
249 #define NO_SHIFT_RESTRICT 1
250 #define SHIFT_RESTRICT 0
252 #define NUM_FLOAT_VALS 8
254 const char * fp_const
[] =
256 "0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0", 0
259 /* Number of littlenums required to hold an extended precision number. */
260 #define MAX_LITTLENUMS 6
262 LITTLENUM_TYPE fp_values
[NUM_FLOAT_VALS
][MAX_LITTLENUMS
];
272 #define CP_T_X 0x00008000
273 #define CP_T_Y 0x00400000
274 #define CP_T_Pre 0x01000000
275 #define CP_T_UD 0x00800000
276 #define CP_T_WB 0x00200000
278 #define CONDS_BIT 0x00100000
279 #define LOAD_BIT 0x00100000
281 #define DOUBLE_LOAD_FLAG 0x00000001
285 const char * template;
289 #define COND_ALWAYS 0xe0000000
290 #define COND_MASK 0xf0000000
292 static const struct asm_cond conds
[] =
296 {"cs", 0x20000000}, {"hs", 0x20000000},
297 {"cc", 0x30000000}, {"ul", 0x30000000}, {"lo", 0x30000000},
314 const char * template;
319 /* The bit that distnguishes CPSR and SPSR. */
320 #define SPSR_BIT (1 << 22)
322 /* How many bits to shift the PSR_xxx bits up by. */
325 #define PSR_c (1 << 0)
326 #define PSR_x (1 << 1)
327 #define PSR_s (1 << 2)
328 #define PSR_f (1 << 3)
330 static const struct asm_psr psrs
[] =
332 {"CPSR", true, PSR_c
| PSR_f
},
333 {"CPSR_all", true, PSR_c
| PSR_f
},
334 {"SPSR", false, PSR_c
| PSR_f
},
335 {"SPSR_all", false, PSR_c
| PSR_f
},
336 {"CPSR_flg", true, PSR_f
},
337 {"CPSR_f", true, PSR_f
},
338 {"SPSR_flg", false, PSR_f
},
339 {"SPSR_f", false, PSR_f
},
340 {"CPSR_c", true, PSR_c
},
341 {"CPSR_ctl", true, PSR_c
},
342 {"SPSR_c", false, PSR_c
},
343 {"SPSR_ctl", false, PSR_c
},
344 {"CPSR_x", true, PSR_x
},
345 {"CPSR_s", true, PSR_s
},
346 {"SPSR_x", false, PSR_x
},
347 {"SPSR_s", false, PSR_s
},
348 /* Combinations of flags. */
349 {"CPSR_fs", true, PSR_f
| PSR_s
},
350 {"CPSR_fx", true, PSR_f
| PSR_x
},
351 {"CPSR_fc", true, PSR_f
| PSR_c
},
352 {"CPSR_sf", true, PSR_s
| PSR_f
},
353 {"CPSR_sx", true, PSR_s
| PSR_x
},
354 {"CPSR_sc", true, PSR_s
| PSR_c
},
355 {"CPSR_xf", true, PSR_x
| PSR_f
},
356 {"CPSR_xs", true, PSR_x
| PSR_s
},
357 {"CPSR_xc", true, PSR_x
| PSR_c
},
358 {"CPSR_cf", true, PSR_c
| PSR_f
},
359 {"CPSR_cs", true, PSR_c
| PSR_s
},
360 {"CPSR_cx", true, PSR_c
| PSR_x
},
361 {"CPSR_fsx", true, PSR_f
| PSR_s
| PSR_x
},
362 {"CPSR_fsc", true, PSR_f
| PSR_s
| PSR_c
},
363 {"CPSR_fxs", true, PSR_f
| PSR_x
| PSR_s
},
364 {"CPSR_fxc", true, PSR_f
| PSR_x
| PSR_c
},
365 {"CPSR_fcs", true, PSR_f
| PSR_c
| PSR_s
},
366 {"CPSR_fcx", true, PSR_f
| PSR_c
| PSR_x
},
367 {"CPSR_sfx", true, PSR_s
| PSR_f
| PSR_x
},
368 {"CPSR_sfc", true, PSR_s
| PSR_f
| PSR_c
},
369 {"CPSR_sxf", true, PSR_s
| PSR_x
| PSR_f
},
370 {"CPSR_sxc", true, PSR_s
| PSR_x
| PSR_c
},
371 {"CPSR_scf", true, PSR_s
| PSR_c
| PSR_f
},
372 {"CPSR_scx", true, PSR_s
| PSR_c
| PSR_x
},
373 {"CPSR_xfs", true, PSR_x
| PSR_f
| PSR_s
},
374 {"CPSR_xfc", true, PSR_x
| PSR_f
| PSR_c
},
375 {"CPSR_xsf", true, PSR_x
| PSR_s
| PSR_f
},
376 {"CPSR_xsc", true, PSR_x
| PSR_s
| PSR_c
},
377 {"CPSR_xcf", true, PSR_x
| PSR_c
| PSR_f
},
378 {"CPSR_xcs", true, PSR_x
| PSR_c
| PSR_s
},
379 {"CPSR_cfs", true, PSR_c
| PSR_f
| PSR_s
},
380 {"CPSR_cfx", true, PSR_c
| PSR_f
| PSR_x
},
381 {"CPSR_csf", true, PSR_c
| PSR_s
| PSR_f
},
382 {"CPSR_csx", true, PSR_c
| PSR_s
| PSR_x
},
383 {"CPSR_cxf", true, PSR_c
| PSR_x
| PSR_f
},
384 {"CPSR_cxs", true, PSR_c
| PSR_x
| PSR_s
},
385 {"CPSR_fsxc", true, PSR_f
| PSR_s
| PSR_x
| PSR_c
},
386 {"CPSR_fscx", true, PSR_f
| PSR_s
| PSR_c
| PSR_x
},
387 {"CPSR_fxsc", true, PSR_f
| PSR_x
| PSR_s
| PSR_c
},
388 {"CPSR_fxcs", true, PSR_f
| PSR_x
| PSR_c
| PSR_s
},
389 {"CPSR_fcsx", true, PSR_f
| PSR_c
| PSR_s
| PSR_x
},
390 {"CPSR_fcxs", true, PSR_f
| PSR_c
| PSR_x
| PSR_s
},
391 {"CPSR_sfxc", true, PSR_s
| PSR_f
| PSR_x
| PSR_c
},
392 {"CPSR_sfcx", true, PSR_s
| PSR_f
| PSR_c
| PSR_x
},
393 {"CPSR_sxfc", true, PSR_s
| PSR_x
| PSR_f
| PSR_c
},
394 {"CPSR_sxcf", true, PSR_s
| PSR_x
| PSR_c
| PSR_f
},
395 {"CPSR_scfx", true, PSR_s
| PSR_c
| PSR_f
| PSR_x
},
396 {"CPSR_scxf", true, PSR_s
| PSR_c
| PSR_x
| PSR_f
},
397 {"CPSR_xfsc", true, PSR_x
| PSR_f
| PSR_s
| PSR_c
},
398 {"CPSR_xfcs", true, PSR_x
| PSR_f
| PSR_c
| PSR_s
},
399 {"CPSR_xsfc", true, PSR_x
| PSR_s
| PSR_f
| PSR_c
},
400 {"CPSR_xscf", true, PSR_x
| PSR_s
| PSR_c
| PSR_f
},
401 {"CPSR_xcfs", true, PSR_x
| PSR_c
| PSR_f
| PSR_s
},
402 {"CPSR_xcsf", true, PSR_x
| PSR_c
| PSR_s
| PSR_f
},
403 {"CPSR_cfsx", true, PSR_c
| PSR_f
| PSR_s
| PSR_x
},
404 {"CPSR_cfxs", true, PSR_c
| PSR_f
| PSR_x
| PSR_s
},
405 {"CPSR_csfx", true, PSR_c
| PSR_s
| PSR_f
| PSR_x
},
406 {"CPSR_csxf", true, PSR_c
| PSR_s
| PSR_x
| PSR_f
},
407 {"CPSR_cxfs", true, PSR_c
| PSR_x
| PSR_f
| PSR_s
},
408 {"CPSR_cxsf", true, PSR_c
| PSR_x
| PSR_s
| PSR_f
},
409 {"SPSR_fs", false, PSR_f
| PSR_s
},
410 {"SPSR_fx", false, PSR_f
| PSR_x
},
411 {"SPSR_fc", false, PSR_f
| PSR_c
},
412 {"SPSR_sf", false, PSR_s
| PSR_f
},
413 {"SPSR_sx", false, PSR_s
| PSR_x
},
414 {"SPSR_sc", false, PSR_s
| PSR_c
},
415 {"SPSR_xf", false, PSR_x
| PSR_f
},
416 {"SPSR_xs", false, PSR_x
| PSR_s
},
417 {"SPSR_xc", false, PSR_x
| PSR_c
},
418 {"SPSR_cf", false, PSR_c
| PSR_f
},
419 {"SPSR_cs", false, PSR_c
| PSR_s
},
420 {"SPSR_cx", false, PSR_c
| PSR_x
},
421 {"SPSR_fsx", false, PSR_f
| PSR_s
| PSR_x
},
422 {"SPSR_fsc", false, PSR_f
| PSR_s
| PSR_c
},
423 {"SPSR_fxs", false, PSR_f
| PSR_x
| PSR_s
},
424 {"SPSR_fxc", false, PSR_f
| PSR_x
| PSR_c
},
425 {"SPSR_fcs", false, PSR_f
| PSR_c
| PSR_s
},
426 {"SPSR_fcx", false, PSR_f
| PSR_c
| PSR_x
},
427 {"SPSR_sfx", false, PSR_s
| PSR_f
| PSR_x
},
428 {"SPSR_sfc", false, PSR_s
| PSR_f
| PSR_c
},
429 {"SPSR_sxf", false, PSR_s
| PSR_x
| PSR_f
},
430 {"SPSR_sxc", false, PSR_s
| PSR_x
| PSR_c
},
431 {"SPSR_scf", false, PSR_s
| PSR_c
| PSR_f
},
432 {"SPSR_scx", false, PSR_s
| PSR_c
| PSR_x
},
433 {"SPSR_xfs", false, PSR_x
| PSR_f
| PSR_s
},
434 {"SPSR_xfc", false, PSR_x
| PSR_f
| PSR_c
},
435 {"SPSR_xsf", false, PSR_x
| PSR_s
| PSR_f
},
436 {"SPSR_xsc", false, PSR_x
| PSR_s
| PSR_c
},
437 {"SPSR_xcf", false, PSR_x
| PSR_c
| PSR_f
},
438 {"SPSR_xcs", false, PSR_x
| PSR_c
| PSR_s
},
439 {"SPSR_cfs", false, PSR_c
| PSR_f
| PSR_s
},
440 {"SPSR_cfx", false, PSR_c
| PSR_f
| PSR_x
},
441 {"SPSR_csf", false, PSR_c
| PSR_s
| PSR_f
},
442 {"SPSR_csx", false, PSR_c
| PSR_s
| PSR_x
},
443 {"SPSR_cxf", false, PSR_c
| PSR_x
| PSR_f
},
444 {"SPSR_cxs", false, PSR_c
| PSR_x
| PSR_s
},
445 {"SPSR_fsxc", false, PSR_f
| PSR_s
| PSR_x
| PSR_c
},
446 {"SPSR_fscx", false, PSR_f
| PSR_s
| PSR_c
| PSR_x
},
447 {"SPSR_fxsc", false, PSR_f
| PSR_x
| PSR_s
| PSR_c
},
448 {"SPSR_fxcs", false, PSR_f
| PSR_x
| PSR_c
| PSR_s
},
449 {"SPSR_fcsx", false, PSR_f
| PSR_c
| PSR_s
| PSR_x
},
450 {"SPSR_fcxs", false, PSR_f
| PSR_c
| PSR_x
| PSR_s
},
451 {"SPSR_sfxc", false, PSR_s
| PSR_f
| PSR_x
| PSR_c
},
452 {"SPSR_sfcx", false, PSR_s
| PSR_f
| PSR_c
| PSR_x
},
453 {"SPSR_sxfc", false, PSR_s
| PSR_x
| PSR_f
| PSR_c
},
454 {"SPSR_sxcf", false, PSR_s
| PSR_x
| PSR_c
| PSR_f
},
455 {"SPSR_scfx", false, PSR_s
| PSR_c
| PSR_f
| PSR_x
},
456 {"SPSR_scxf", false, PSR_s
| PSR_c
| PSR_x
| PSR_f
},
457 {"SPSR_xfsc", false, PSR_x
| PSR_f
| PSR_s
| PSR_c
},
458 {"SPSR_xfcs", false, PSR_x
| PSR_f
| PSR_c
| PSR_s
},
459 {"SPSR_xsfc", false, PSR_x
| PSR_s
| PSR_f
| PSR_c
},
460 {"SPSR_xscf", false, PSR_x
| PSR_s
| PSR_c
| PSR_f
},
461 {"SPSR_xcfs", false, PSR_x
| PSR_c
| PSR_f
| PSR_s
},
462 {"SPSR_xcsf", false, PSR_x
| PSR_c
| PSR_s
| PSR_f
},
463 {"SPSR_cfsx", false, PSR_c
| PSR_f
| PSR_s
| PSR_x
},
464 {"SPSR_cfxs", false, PSR_c
| PSR_f
| PSR_x
| PSR_s
},
465 {"SPSR_csfx", false, PSR_c
| PSR_s
| PSR_f
| PSR_x
},
466 {"SPSR_csxf", false, PSR_c
| PSR_s
| PSR_x
| PSR_f
},
467 {"SPSR_cxfs", false, PSR_c
| PSR_x
| PSR_f
| PSR_s
},
468 {"SPSR_cxsf", false, PSR_c
| PSR_x
| PSR_s
| PSR_f
},
473 CIRRUS_REGTYPE_MVF
= 1,
474 CIRRUS_REGTYPE_MVFX
= 2,
475 CIRRUS_REGTYPE_MVD
= 3,
476 CIRRUS_REGTYPE_MVDX
= 4,
477 CIRRUS_REGTYPE_MVAX
= 5,
478 CIRRUS_REGTYPE_DSPSC
= 6,
479 CIRRUS_REGTYPE_ANY
= 7
482 /* Functions called by parser. */
483 /* ARM instructions. */
484 static void do_arit
PARAMS ((char *, unsigned long));
485 static void do_cmp
PARAMS ((char *, unsigned long));
486 static void do_mov
PARAMS ((char *, unsigned long));
487 static void do_ldst
PARAMS ((char *, unsigned long));
488 static void do_ldstt
PARAMS ((char *, unsigned long));
489 static void do_ldmstm
PARAMS ((char *, unsigned long));
490 static void do_branch
PARAMS ((char *, unsigned long));
491 static void do_swi
PARAMS ((char *, unsigned long));
493 /* Pseudo Op codes. */
494 static void do_adr
PARAMS ((char *, unsigned long));
495 static void do_adrl
PARAMS ((char *, unsigned long));
496 static void do_empty
PARAMS ((char *, unsigned long));
499 static void do_mul
PARAMS ((char *, unsigned long));
500 static void do_mla
PARAMS ((char *, unsigned long));
503 static void do_swap
PARAMS ((char *, unsigned long));
506 static void do_msr
PARAMS ((char *, unsigned long));
507 static void do_mrs
PARAMS ((char *, unsigned long));
510 static void do_mull
PARAMS ((char *, unsigned long));
513 static void do_ldstv4
PARAMS ((char *, unsigned long));
516 static void do_bx
PARAMS ((char *, unsigned long));
519 static void do_blx
PARAMS ((char *, unsigned long));
520 static void do_bkpt
PARAMS ((char *, unsigned long));
521 static void do_clz
PARAMS ((char *, unsigned long));
522 static void do_lstc2
PARAMS ((char *, unsigned long));
523 static void do_cdp2
PARAMS ((char *, unsigned long));
524 static void do_co_reg2
PARAMS ((char *, unsigned long));
527 static void do_smla
PARAMS ((char *, unsigned long));
528 static void do_smlal
PARAMS ((char *, unsigned long));
529 static void do_smul
PARAMS ((char *, unsigned long));
530 static void do_qadd
PARAMS ((char *, unsigned long));
533 static void do_pld
PARAMS ((char *, unsigned long));
534 static void do_ldrd
PARAMS ((char *, unsigned long));
535 static void do_co_reg2c
PARAMS ((char *, unsigned long));
537 /* Coprocessor Instructions. */
538 static void do_cdp
PARAMS ((char *, unsigned long));
539 static void do_lstc
PARAMS ((char *, unsigned long));
540 static void do_co_reg
PARAMS ((char *, unsigned long));
542 /* FPA instructions. */
543 static void do_fpa_ctrl
PARAMS ((char *, unsigned long));
544 static void do_fpa_ldst
PARAMS ((char *, unsigned long));
545 static void do_fpa_ldmstm
PARAMS ((char *, unsigned long));
546 static void do_fpa_dyadic
PARAMS ((char *, unsigned long));
547 static void do_fpa_monadic
PARAMS ((char *, unsigned long));
548 static void do_fpa_cmp
PARAMS ((char *, unsigned long));
549 static void do_fpa_from_reg
PARAMS ((char *, unsigned long));
550 static void do_fpa_to_reg
PARAMS ((char *, unsigned long));
553 static void do_mia
PARAMS ((char *, unsigned long));
554 static void do_mar
PARAMS ((char *, unsigned long));
555 static void do_mra
PARAMS ((char *, unsigned long));
557 /* ARM_EXT_MAVERICK. */
558 static void do_c_binops
PARAMS ((char *, unsigned long, int));
559 static void do_c_binops_1
PARAMS ((char *, unsigned long));
560 static void do_c_binops_2
PARAMS ((char *, unsigned long));
561 static void do_c_binops_3
PARAMS ((char *, unsigned long));
562 static void do_c_triple
PARAMS ((char *, unsigned long, int));
563 static void do_c_triple_4
PARAMS ((char *, unsigned long));
564 static void do_c_triple_5
PARAMS ((char *, unsigned long));
565 static void do_c_quad
PARAMS ((char *, unsigned long, int));
566 static void do_c_quad_6
PARAMS ((char *, unsigned long));
567 static void do_c_dspsc
PARAMS ((char *, unsigned long, int));
568 static void do_c_dspsc_1
PARAMS ((char *, unsigned long));
569 static void do_c_dspsc_2
PARAMS ((char *, unsigned long));
570 static void do_c_shift
PARAMS ((char *, unsigned long, int));
571 static void do_c_shift_1
PARAMS ((char *, unsigned long));
572 static void do_c_shift_2
PARAMS ((char *, unsigned long));
573 static void do_c_ldst
PARAMS ((char *, unsigned long, int));
574 static void do_c_ldst_1
PARAMS ((char *, unsigned long));
575 static void do_c_ldst_2
PARAMS ((char *, unsigned long));
576 static void do_c_ldst_3
PARAMS ((char *, unsigned long));
577 static void do_c_ldst_4
PARAMS ((char *, unsigned long));
578 static int cirrus_reg_required_here
PARAMS ((char **, int,
579 enum cirrus_regtype
));
580 static int cirrus_valid_reg
PARAMS ((int, enum cirrus_regtype
));
581 static int cirrus_parse_offset
PARAMS ((char **, int *));
583 static void fix_new_arm
PARAMS ((fragS
*, int, short, expressionS
*,
585 static int arm_reg_parse
PARAMS ((char **));
586 static const struct asm_psr
* arm_psr_parse
PARAMS ((char **));
587 static void symbol_locate
PARAMS ((symbolS
*, const char *, segT
, valueT
,
589 static int add_to_lit_pool
PARAMS ((void));
590 static unsigned validate_immediate
PARAMS ((unsigned));
591 static unsigned validate_immediate_twopart
PARAMS ((unsigned int,
593 static int validate_offset_imm
PARAMS ((unsigned int, int));
594 static void opcode_select
PARAMS ((int));
595 static void end_of_line
PARAMS ((char *));
596 static int reg_required_here
PARAMS ((char **, int));
597 static int psr_required_here
PARAMS ((char **));
598 static int co_proc_number
PARAMS ((char **));
599 static int cp_opc_expr
PARAMS ((char **, int, int));
600 static int cp_reg_required_here
PARAMS ((char **, int));
601 static int fp_reg_required_here
PARAMS ((char **, int));
602 static int cp_address_offset
PARAMS ((char **));
603 static int cp_address_required_here
PARAMS ((char **));
604 static int my_get_float_expression
PARAMS ((char **));
605 static int skip_past_comma
PARAMS ((char **));
606 static int walk_no_bignums
PARAMS ((symbolS
*));
607 static int negate_data_op
PARAMS ((unsigned long *, unsigned long));
608 static int data_op2
PARAMS ((char **));
609 static int fp_op2
PARAMS ((char **));
610 static long reg_list
PARAMS ((char **));
611 static void thumb_load_store
PARAMS ((char *, int, int));
612 static int decode_shift
PARAMS ((char **, int));
613 static int ldst_extend
PARAMS ((char **));
614 static int ldst_extend_v4
PARAMS ((char **));
615 static void thumb_add_sub
PARAMS ((char *, int));
616 static void insert_reg
PARAMS ((int));
617 static void thumb_shift
PARAMS ((char *, int));
618 static void thumb_mov_compare
PARAMS ((char *, int));
619 static void set_constant_flonums
PARAMS ((void));
620 static valueT md_chars_to_number
PARAMS ((char *, int));
621 static void insert_reg_alias
PARAMS ((char *, int));
622 static void output_inst
PARAMS ((void));
623 static int accum0_required_here
PARAMS ((char **));
624 static int ld_mode_required_here
PARAMS ((char **));
625 static void do_branch25
PARAMS ((char *, unsigned long));
626 static symbolS
* find_real_start
PARAMS ((symbolS
*));
628 static bfd_reloc_code_real_type arm_parse_reloc
PARAMS ((void));
631 /* ARM instructions take 4bytes in the object file, Thumb instructions
635 /* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
636 #define CIRRUS_MODE1 0x100c
638 /* "INSN<cond> X,Y" where X:bit16, Y:bit12. */
639 #define CIRRUS_MODE2 0x0c10
641 /* "INSN<cond> X,Y" where X:0, Y:bit16. */
642 #define CIRRUS_MODE3 0x1000
644 /* "INSN<cond> X,Y,Z" where X:16, Y:0, Z:12. */
645 #define CIRRUS_MODE4 0x0c0010
647 /* "INSN<cond> X,Y,Z" where X:12, Y:16, Z:0. */
648 #define CIRRUS_MODE5 0x00100c
650 /* "INSN<cond> W,X,Y,Z" where W:5, X:12, Y:16, Z:0. */
651 #define CIRRUS_MODE6 0x00100c05
655 /* Basic string to match. */
656 const char * template;
658 /* Basic instruction code. */
661 /* Offset into the template where the condition code (if any) will be.
662 If zero, then the instruction is never conditional. */
663 unsigned cond_offset
;
665 /* Which architecture variant provides this instruction. */
666 unsigned long variant
;
668 /* Function to call to parse args. */
669 void (* parms
) PARAMS ((char *, unsigned long));
672 static const struct asm_opcode insns
[] =
674 /* Core ARM Instructions. */
675 {"and", 0xe0000000, 3, ARM_EXT_V1
, do_arit
},
676 {"ands", 0xe0100000, 3, ARM_EXT_V1
, do_arit
},
677 {"eor", 0xe0200000, 3, ARM_EXT_V1
, do_arit
},
678 {"eors", 0xe0300000, 3, ARM_EXT_V1
, do_arit
},
679 {"sub", 0xe0400000, 3, ARM_EXT_V1
, do_arit
},
680 {"subs", 0xe0500000, 3, ARM_EXT_V1
, do_arit
},
681 {"rsb", 0xe0600000, 3, ARM_EXT_V1
, do_arit
},
682 {"rsbs", 0xe0700000, 3, ARM_EXT_V1
, do_arit
},
683 {"add", 0xe0800000, 3, ARM_EXT_V1
, do_arit
},
684 {"adds", 0xe0900000, 3, ARM_EXT_V1
, do_arit
},
685 {"adc", 0xe0a00000, 3, ARM_EXT_V1
, do_arit
},
686 {"adcs", 0xe0b00000, 3, ARM_EXT_V1
, do_arit
},
687 {"sbc", 0xe0c00000, 3, ARM_EXT_V1
, do_arit
},
688 {"sbcs", 0xe0d00000, 3, ARM_EXT_V1
, do_arit
},
689 {"rsc", 0xe0e00000, 3, ARM_EXT_V1
, do_arit
},
690 {"rscs", 0xe0f00000, 3, ARM_EXT_V1
, do_arit
},
691 {"orr", 0xe1800000, 3, ARM_EXT_V1
, do_arit
},
692 {"orrs", 0xe1900000, 3, ARM_EXT_V1
, do_arit
},
693 {"bic", 0xe1c00000, 3, ARM_EXT_V1
, do_arit
},
694 {"bics", 0xe1d00000, 3, ARM_EXT_V1
, do_arit
},
696 {"tst", 0xe1100000, 3, ARM_EXT_V1
, do_cmp
},
697 {"tsts", 0xe1100000, 3, ARM_EXT_V1
, do_cmp
},
698 {"tstp", 0xe110f000, 3, ARM_EXT_V1
, do_cmp
},
699 {"teq", 0xe1300000, 3, ARM_EXT_V1
, do_cmp
},
700 {"teqs", 0xe1300000, 3, ARM_EXT_V1
, do_cmp
},
701 {"teqp", 0xe130f000, 3, ARM_EXT_V1
, do_cmp
},
702 {"cmp", 0xe1500000, 3, ARM_EXT_V1
, do_cmp
},
703 {"cmps", 0xe1500000, 3, ARM_EXT_V1
, do_cmp
},
704 {"cmpp", 0xe150f000, 3, ARM_EXT_V1
, do_cmp
},
705 {"cmn", 0xe1700000, 3, ARM_EXT_V1
, do_cmp
},
706 {"cmns", 0xe1700000, 3, ARM_EXT_V1
, do_cmp
},
707 {"cmnp", 0xe170f000, 3, ARM_EXT_V1
, do_cmp
},
709 {"mov", 0xe1a00000, 3, ARM_EXT_V1
, do_mov
},
710 {"movs", 0xe1b00000, 3, ARM_EXT_V1
, do_mov
},
711 {"mvn", 0xe1e00000, 3, ARM_EXT_V1
, do_mov
},
712 {"mvns", 0xe1f00000, 3, ARM_EXT_V1
, do_mov
},
714 {"ldr", 0xe4100000, 3, ARM_EXT_V1
, do_ldst
},
715 {"ldrb", 0xe4500000, 3, ARM_EXT_V1
, do_ldst
},
716 {"ldrt", 0xe4300000, 3, ARM_EXT_V1
, do_ldstt
},
717 {"ldrbt", 0xe4700000, 3, ARM_EXT_V1
, do_ldstt
},
718 {"str", 0xe4000000, 3, ARM_EXT_V1
, do_ldst
},
719 {"strb", 0xe4400000, 3, ARM_EXT_V1
, do_ldst
},
720 {"strt", 0xe4200000, 3, ARM_EXT_V1
, do_ldstt
},
721 {"strbt", 0xe4600000, 3, ARM_EXT_V1
, do_ldstt
},
723 {"stmia", 0xe8800000, 3, ARM_EXT_V1
, do_ldmstm
},
724 {"stmib", 0xe9800000, 3, ARM_EXT_V1
, do_ldmstm
},
725 {"stmda", 0xe8000000, 3, ARM_EXT_V1
, do_ldmstm
},
726 {"stmdb", 0xe9000000, 3, ARM_EXT_V1
, do_ldmstm
},
727 {"stmfd", 0xe9000000, 3, ARM_EXT_V1
, do_ldmstm
},
728 {"stmfa", 0xe9800000, 3, ARM_EXT_V1
, do_ldmstm
},
729 {"stmea", 0xe8800000, 3, ARM_EXT_V1
, do_ldmstm
},
730 {"stmed", 0xe8000000, 3, ARM_EXT_V1
, do_ldmstm
},
732 {"ldmia", 0xe8900000, 3, ARM_EXT_V1
, do_ldmstm
},
733 {"ldmib", 0xe9900000, 3, ARM_EXT_V1
, do_ldmstm
},
734 {"ldmda", 0xe8100000, 3, ARM_EXT_V1
, do_ldmstm
},
735 {"ldmdb", 0xe9100000, 3, ARM_EXT_V1
, do_ldmstm
},
736 {"ldmfd", 0xe8900000, 3, ARM_EXT_V1
, do_ldmstm
},
737 {"ldmfa", 0xe8100000, 3, ARM_EXT_V1
, do_ldmstm
},
738 {"ldmea", 0xe9100000, 3, ARM_EXT_V1
, do_ldmstm
},
739 {"ldmed", 0xe9900000, 3, ARM_EXT_V1
, do_ldmstm
},
741 {"swi", 0xef000000, 3, ARM_EXT_V1
, do_swi
},
743 /* XXX This is the wrong place to do this. Think multi-arch. */
744 {"bl", 0xeb000000, 2, ARM_EXT_V1
, do_branch
},
745 {"b", 0xea000000, 1, ARM_EXT_V1
, do_branch
},
747 {"bl", 0xebfffffe, 2, ARM_EXT_V1
, do_branch
},
748 {"b", 0xeafffffe, 1, ARM_EXT_V1
, do_branch
},
752 {"adr", 0xe28f0000, 3, ARM_EXT_V1
, do_adr
},
753 {"adrl", 0xe28f0000, 3, ARM_EXT_V1
, do_adrl
},
754 {"nop", 0xe1a00000, 3, ARM_EXT_V1
, do_empty
},
756 /* ARM 2 multiplies. */
757 {"mul", 0xe0000090, 3, ARM_EXT_V2
, do_mul
},
758 {"muls", 0xe0100090, 3, ARM_EXT_V2
, do_mul
},
759 {"mla", 0xe0200090, 3, ARM_EXT_V2
, do_mla
},
760 {"mlas", 0xe0300090, 3, ARM_EXT_V2
, do_mla
},
762 /* Generic copressor instructions. */
763 {"cdp", 0xee000000, 3, ARM_EXT_V2
, do_cdp
},
764 {"ldc", 0xec100000, 3, ARM_EXT_V2
, do_lstc
},
765 {"ldcl", 0xec500000, 3, ARM_EXT_V2
, do_lstc
},
766 {"stc", 0xec000000, 3, ARM_EXT_V2
, do_lstc
},
767 {"stcl", 0xec400000, 3, ARM_EXT_V2
, do_lstc
},
768 {"mcr", 0xee000010, 3, ARM_EXT_V2
, do_co_reg
},
769 {"mrc", 0xee100010, 3, ARM_EXT_V2
, do_co_reg
},
771 /* ARM 3 - swp instructions. */
772 {"swp", 0xe1000090, 3, ARM_EXT_V2S
, do_swap
},
773 {"swpb", 0xe1400090, 3, ARM_EXT_V2S
, do_swap
},
775 /* ARM 6 Status register instructions. */
776 {"mrs", 0xe10f0000, 3, ARM_EXT_V3
, do_mrs
},
777 {"msr", 0xe120f000, 3, ARM_EXT_V3
, do_msr
},
778 /* ScottB: our code uses 0xe128f000 for msr.
779 NickC: but this is wrong because the bits 16 through 19 are
780 handled by the PSR_xxx defines above. */
782 /* ARM 7M long multiplies - need signed/unsigned flags! */
783 {"smull", 0xe0c00090, 5, ARM_EXT_V3M
, do_mull
},
784 {"smulls", 0xe0d00090, 5, ARM_EXT_V3M
, do_mull
},
785 {"umull", 0xe0800090, 5, ARM_EXT_V3M
, do_mull
},
786 {"umulls", 0xe0900090, 5, ARM_EXT_V3M
, do_mull
},
787 {"smlal", 0xe0e00090, 5, ARM_EXT_V3M
, do_mull
},
788 {"smlals", 0xe0f00090, 5, ARM_EXT_V3M
, do_mull
},
789 {"umlal", 0xe0a00090, 5, ARM_EXT_V3M
, do_mull
},
790 {"umlals", 0xe0b00090, 5, ARM_EXT_V3M
, do_mull
},
792 /* ARM Architecture 4. */
793 {"ldrh", 0xe01000b0, 3, ARM_EXT_V4
, do_ldstv4
},
794 {"ldrsh", 0xe01000f0, 3, ARM_EXT_V4
, do_ldstv4
},
795 {"ldrsb", 0xe01000d0, 3, ARM_EXT_V4
, do_ldstv4
},
796 {"strh", 0xe00000b0, 3, ARM_EXT_V4
, do_ldstv4
},
798 /* ARM Architecture 4T. */
799 /* Note: bx (and blx) are required on V5, even if the processor does
800 not support Thumb. */
801 {"bx", 0xe12fff10, 2, ARM_EXT_V4T
| ARM_EXT_V5
, do_bx
},
803 /* ARM Architecture 5. */
804 /* Note: blx has 2 variants, so the .value is set dynamically.
805 Only one of the variants has conditional execution. */
806 {"blx", 0xe0000000, 3, ARM_EXT_V5
, do_blx
},
807 {"clz", 0xe16f0f10, 3, ARM_EXT_V5
, do_clz
},
808 {"bkpt", 0xe1200070, 0, ARM_EXT_V5
, do_bkpt
},
809 {"ldc2", 0xfc100000, 0, ARM_EXT_V5
, do_lstc2
},
810 {"ldc2l", 0xfc500000, 0, ARM_EXT_V5
, do_lstc2
},
811 {"stc2", 0xfc000000, 0, ARM_EXT_V5
, do_lstc2
},
812 {"stc2l", 0xfc400000, 0, ARM_EXT_V5
, do_lstc2
},
813 {"cdp2", 0xfe000000, 0, ARM_EXT_V5
, do_cdp2
},
814 {"mcr2", 0xfe000010, 0, ARM_EXT_V5
, do_co_reg2
},
815 {"mrc2", 0xfe100010, 0, ARM_EXT_V5
, do_co_reg2
},
817 /* ARM Architecture 5ExP. */
818 {"smlabb", 0xe1000080, 6, ARM_EXT_V5ExP
, do_smla
},
819 {"smlatb", 0xe10000a0, 6, ARM_EXT_V5ExP
, do_smla
},
820 {"smlabt", 0xe10000c0, 6, ARM_EXT_V5ExP
, do_smla
},
821 {"smlatt", 0xe10000e0, 6, ARM_EXT_V5ExP
, do_smla
},
823 {"smlawb", 0xe1200080, 6, ARM_EXT_V5ExP
, do_smla
},
824 {"smlawt", 0xe12000c0, 6, ARM_EXT_V5ExP
, do_smla
},
826 {"smlalbb", 0xe1400080, 7, ARM_EXT_V5ExP
, do_smlal
},
827 {"smlaltb", 0xe14000a0, 7, ARM_EXT_V5ExP
, do_smlal
},
828 {"smlalbt", 0xe14000c0, 7, ARM_EXT_V5ExP
, do_smlal
},
829 {"smlaltt", 0xe14000e0, 7, ARM_EXT_V5ExP
, do_smlal
},
831 {"smulbb", 0xe1600080, 6, ARM_EXT_V5ExP
, do_smul
},
832 {"smultb", 0xe16000a0, 6, ARM_EXT_V5ExP
, do_smul
},
833 {"smulbt", 0xe16000c0, 6, ARM_EXT_V5ExP
, do_smul
},
834 {"smultt", 0xe16000e0, 6, ARM_EXT_V5ExP
, do_smul
},
836 {"smulwb", 0xe12000a0, 6, ARM_EXT_V5ExP
, do_smul
},
837 {"smulwt", 0xe12000e0, 6, ARM_EXT_V5ExP
, do_smul
},
839 {"qadd", 0xe1000050, 4, ARM_EXT_V5ExP
, do_qadd
},
840 {"qdadd", 0xe1400050, 5, ARM_EXT_V5ExP
, do_qadd
},
841 {"qsub", 0xe1200050, 4, ARM_EXT_V5ExP
, do_qadd
},
842 {"qdsub", 0xe1600050, 5, ARM_EXT_V5ExP
, do_qadd
},
844 /* ARM Architecture 5E. */
845 {"pld", 0xf450f000, 0, ARM_EXT_V5E
, do_pld
},
846 {"ldrd", 0xe00000d0, 3, ARM_EXT_V5E
, do_ldrd
},
847 {"strd", 0xe00000f0, 3, ARM_EXT_V5E
, do_ldrd
},
849 {"mcrr", 0xec400000, 4, ARM_EXT_V5E
, do_co_reg2c
},
850 {"mrrc", 0xec500000, 4, ARM_EXT_V5E
, do_co_reg2c
},
852 /* Core FPA instruction set (V1). */
853 {"wfs", 0xee200110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
854 {"rfs", 0xee300110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
855 {"wfc", 0xee400110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
856 {"rfc", 0xee500110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
858 {"ldfs", 0xec100100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
859 {"ldfd", 0xec108100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
860 {"ldfe", 0xec500100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
861 {"ldfp", 0xec508100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
863 {"stfs", 0xec000100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
864 {"stfd", 0xec008100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
865 {"stfe", 0xec400100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
866 {"stfp", 0xec408100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
868 {"mvfs", 0xee008100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
869 {"mvfsp", 0xee008120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
870 {"mvfsm", 0xee008140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
871 {"mvfsz", 0xee008160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
872 {"mvfd", 0xee008180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
873 {"mvfdp", 0xee0081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
874 {"mvfdm", 0xee0081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
875 {"mvfdz", 0xee0081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
876 {"mvfe", 0xee088100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
877 {"mvfep", 0xee088120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
878 {"mvfem", 0xee088140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
879 {"mvfez", 0xee088160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
881 {"mnfs", 0xee108100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
882 {"mnfsp", 0xee108120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
883 {"mnfsm", 0xee108140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
884 {"mnfsz", 0xee108160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
885 {"mnfd", 0xee108180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
886 {"mnfdp", 0xee1081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
887 {"mnfdm", 0xee1081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
888 {"mnfdz", 0xee1081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
889 {"mnfe", 0xee188100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
890 {"mnfep", 0xee188120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
891 {"mnfem", 0xee188140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
892 {"mnfez", 0xee188160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
894 {"abss", 0xee208100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
895 {"abssp", 0xee208120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
896 {"abssm", 0xee208140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
897 {"abssz", 0xee208160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
898 {"absd", 0xee208180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
899 {"absdp", 0xee2081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
900 {"absdm", 0xee2081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
901 {"absdz", 0xee2081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
902 {"abse", 0xee288100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
903 {"absep", 0xee288120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
904 {"absem", 0xee288140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
905 {"absez", 0xee288160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
907 {"rnds", 0xee308100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
908 {"rndsp", 0xee308120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
909 {"rndsm", 0xee308140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
910 {"rndsz", 0xee308160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
911 {"rndd", 0xee308180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
912 {"rnddp", 0xee3081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
913 {"rnddm", 0xee3081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
914 {"rnddz", 0xee3081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
915 {"rnde", 0xee388100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
916 {"rndep", 0xee388120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
917 {"rndem", 0xee388140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
918 {"rndez", 0xee388160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
920 {"sqts", 0xee408100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
921 {"sqtsp", 0xee408120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
922 {"sqtsm", 0xee408140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
923 {"sqtsz", 0xee408160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
924 {"sqtd", 0xee408180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
925 {"sqtdp", 0xee4081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
926 {"sqtdm", 0xee4081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
927 {"sqtdz", 0xee4081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
928 {"sqte", 0xee488100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
929 {"sqtep", 0xee488120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
930 {"sqtem", 0xee488140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
931 {"sqtez", 0xee488160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
933 {"logs", 0xee508100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
934 {"logsp", 0xee508120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
935 {"logsm", 0xee508140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
936 {"logsz", 0xee508160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
937 {"logd", 0xee508180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
938 {"logdp", 0xee5081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
939 {"logdm", 0xee5081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
940 {"logdz", 0xee5081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
941 {"loge", 0xee588100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
942 {"logep", 0xee588120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
943 {"logem", 0xee588140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
944 {"logez", 0xee588160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
946 {"lgns", 0xee608100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
947 {"lgnsp", 0xee608120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
948 {"lgnsm", 0xee608140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
949 {"lgnsz", 0xee608160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
950 {"lgnd", 0xee608180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
951 {"lgndp", 0xee6081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
952 {"lgndm", 0xee6081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
953 {"lgndz", 0xee6081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
954 {"lgne", 0xee688100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
955 {"lgnep", 0xee688120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
956 {"lgnem", 0xee688140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
957 {"lgnez", 0xee688160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
959 {"exps", 0xee708100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
960 {"expsp", 0xee708120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
961 {"expsm", 0xee708140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
962 {"expsz", 0xee708160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
963 {"expd", 0xee708180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
964 {"expdp", 0xee7081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
965 {"expdm", 0xee7081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
966 {"expdz", 0xee7081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
967 {"expe", 0xee788100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
968 {"expep", 0xee788120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
969 {"expem", 0xee788140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
970 {"expdz", 0xee788160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
972 {"sins", 0xee808100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
973 {"sinsp", 0xee808120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
974 {"sinsm", 0xee808140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
975 {"sinsz", 0xee808160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
976 {"sind", 0xee808180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
977 {"sindp", 0xee8081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
978 {"sindm", 0xee8081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
979 {"sindz", 0xee8081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
980 {"sine", 0xee888100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
981 {"sinep", 0xee888120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
982 {"sinem", 0xee888140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
983 {"sinez", 0xee888160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
985 {"coss", 0xee908100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
986 {"cossp", 0xee908120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
987 {"cossm", 0xee908140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
988 {"cossz", 0xee908160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
989 {"cosd", 0xee908180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
990 {"cosdp", 0xee9081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
991 {"cosdm", 0xee9081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
992 {"cosdz", 0xee9081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
993 {"cose", 0xee988100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
994 {"cosep", 0xee988120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
995 {"cosem", 0xee988140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
996 {"cosez", 0xee988160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
998 {"tans", 0xeea08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
999 {"tansp", 0xeea08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1000 {"tansm", 0xeea08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1001 {"tansz", 0xeea08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1002 {"tand", 0xeea08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1003 {"tandp", 0xeea081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1004 {"tandm", 0xeea081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1005 {"tandz", 0xeea081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1006 {"tane", 0xeea88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1007 {"tanep", 0xeea88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1008 {"tanem", 0xeea88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1009 {"tanez", 0xeea88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1011 {"asns", 0xeeb08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1012 {"asnsp", 0xeeb08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1013 {"asnsm", 0xeeb08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1014 {"asnsz", 0xeeb08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1015 {"asnd", 0xeeb08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1016 {"asndp", 0xeeb081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1017 {"asndm", 0xeeb081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1018 {"asndz", 0xeeb081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1019 {"asne", 0xeeb88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1020 {"asnep", 0xeeb88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1021 {"asnem", 0xeeb88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1022 {"asnez", 0xeeb88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1024 {"acss", 0xeec08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1025 {"acssp", 0xeec08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1026 {"acssm", 0xeec08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1027 {"acssz", 0xeec08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1028 {"acsd", 0xeec08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1029 {"acsdp", 0xeec081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1030 {"acsdm", 0xeec081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1031 {"acsdz", 0xeec081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1032 {"acse", 0xeec88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1033 {"acsep", 0xeec88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1034 {"acsem", 0xeec88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1035 {"acsez", 0xeec88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1037 {"atns", 0xeed08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1038 {"atnsp", 0xeed08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1039 {"atnsm", 0xeed08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1040 {"atnsz", 0xeed08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1041 {"atnd", 0xeed08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1042 {"atndp", 0xeed081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1043 {"atndm", 0xeed081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1044 {"atndz", 0xeed081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1045 {"atne", 0xeed88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1046 {"atnep", 0xeed88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1047 {"atnem", 0xeed88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1048 {"atnez", 0xeed88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1050 {"urds", 0xeee08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1051 {"urdsp", 0xeee08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1052 {"urdsm", 0xeee08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1053 {"urdsz", 0xeee08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1054 {"urdd", 0xeee08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1055 {"urddp", 0xeee081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1056 {"urddm", 0xeee081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1057 {"urddz", 0xeee081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1058 {"urde", 0xeee88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1059 {"urdep", 0xeee88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1060 {"urdem", 0xeee88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1061 {"urdez", 0xeee88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1063 {"nrms", 0xeef08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1064 {"nrmsp", 0xeef08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1065 {"nrmsm", 0xeef08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1066 {"nrmsz", 0xeef08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1067 {"nrmd", 0xeef08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1068 {"nrmdp", 0xeef081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1069 {"nrmdm", 0xeef081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1070 {"nrmdz", 0xeef081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1071 {"nrme", 0xeef88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1072 {"nrmep", 0xeef88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1073 {"nrmem", 0xeef88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1074 {"nrmez", 0xeef88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1076 {"adfs", 0xee000100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1077 {"adfsp", 0xee000120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1078 {"adfsm", 0xee000140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1079 {"adfsz", 0xee000160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1080 {"adfd", 0xee000180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1081 {"adfdp", 0xee0001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1082 {"adfdm", 0xee0001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1083 {"adfdz", 0xee0001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1084 {"adfe", 0xee080100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1085 {"adfep", 0xee080120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1086 {"adfem", 0xee080140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1087 {"adfez", 0xee080160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1089 {"sufs", 0xee200100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1090 {"sufsp", 0xee200120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1091 {"sufsm", 0xee200140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1092 {"sufsz", 0xee200160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1093 {"sufd", 0xee200180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1094 {"sufdp", 0xee2001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1095 {"sufdm", 0xee2001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1096 {"sufdz", 0xee2001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1097 {"sufe", 0xee280100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1098 {"sufep", 0xee280120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1099 {"sufem", 0xee280140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1100 {"sufez", 0xee280160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1102 {"rsfs", 0xee300100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1103 {"rsfsp", 0xee300120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1104 {"rsfsm", 0xee300140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1105 {"rsfsz", 0xee300160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1106 {"rsfd", 0xee300180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1107 {"rsfdp", 0xee3001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1108 {"rsfdm", 0xee3001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1109 {"rsfdz", 0xee3001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1110 {"rsfe", 0xee380100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1111 {"rsfep", 0xee380120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1112 {"rsfem", 0xee380140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1113 {"rsfez", 0xee380160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1115 {"mufs", 0xee100100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1116 {"mufsp", 0xee100120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1117 {"mufsm", 0xee100140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1118 {"mufsz", 0xee100160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1119 {"mufd", 0xee100180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1120 {"mufdp", 0xee1001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1121 {"mufdm", 0xee1001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1122 {"mufdz", 0xee1001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1123 {"mufe", 0xee180100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1124 {"mufep", 0xee180120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1125 {"mufem", 0xee180140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1126 {"mufez", 0xee180160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1128 {"dvfs", 0xee400100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1129 {"dvfsp", 0xee400120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1130 {"dvfsm", 0xee400140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1131 {"dvfsz", 0xee400160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1132 {"dvfd", 0xee400180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1133 {"dvfdp", 0xee4001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1134 {"dvfdm", 0xee4001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1135 {"dvfdz", 0xee4001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1136 {"dvfe", 0xee480100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1137 {"dvfep", 0xee480120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1138 {"dvfem", 0xee480140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1139 {"dvfez", 0xee480160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1141 {"rdfs", 0xee500100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1142 {"rdfsp", 0xee500120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1143 {"rdfsm", 0xee500140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1144 {"rdfsz", 0xee500160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1145 {"rdfd", 0xee500180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1146 {"rdfdp", 0xee5001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1147 {"rdfdm", 0xee5001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1148 {"rdfdz", 0xee5001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1149 {"rdfe", 0xee580100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1150 {"rdfep", 0xee580120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1151 {"rdfem", 0xee580140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1152 {"rdfez", 0xee580160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1154 {"pows", 0xee600100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1155 {"powsp", 0xee600120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1156 {"powsm", 0xee600140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1157 {"powsz", 0xee600160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1158 {"powd", 0xee600180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1159 {"powdp", 0xee6001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1160 {"powdm", 0xee6001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1161 {"powdz", 0xee6001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1162 {"powe", 0xee680100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1163 {"powep", 0xee680120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1164 {"powem", 0xee680140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1165 {"powez", 0xee680160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1167 {"rpws", 0xee700100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1168 {"rpwsp", 0xee700120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1169 {"rpwsm", 0xee700140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1170 {"rpwsz", 0xee700160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1171 {"rpwd", 0xee700180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1172 {"rpwdp", 0xee7001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1173 {"rpwdm", 0xee7001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1174 {"rpwdz", 0xee7001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1175 {"rpwe", 0xee780100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1176 {"rpwep", 0xee780120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1177 {"rpwem", 0xee780140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1178 {"rpwez", 0xee780160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1180 {"rmfs", 0xee800100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1181 {"rmfsp", 0xee800120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1182 {"rmfsm", 0xee800140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1183 {"rmfsz", 0xee800160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1184 {"rmfd", 0xee800180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1185 {"rmfdp", 0xee8001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1186 {"rmfdm", 0xee8001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1187 {"rmfdz", 0xee8001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1188 {"rmfe", 0xee880100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1189 {"rmfep", 0xee880120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1190 {"rmfem", 0xee880140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1191 {"rmfez", 0xee880160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1193 {"fmls", 0xee900100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1194 {"fmlsp", 0xee900120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1195 {"fmlsm", 0xee900140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1196 {"fmlsz", 0xee900160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1197 {"fmld", 0xee900180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1198 {"fmldp", 0xee9001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1199 {"fmldm", 0xee9001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1200 {"fmldz", 0xee9001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1201 {"fmle", 0xee980100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1202 {"fmlep", 0xee980120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1203 {"fmlem", 0xee980140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1204 {"fmlez", 0xee980160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1206 {"fdvs", 0xeea00100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1207 {"fdvsp", 0xeea00120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1208 {"fdvsm", 0xeea00140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1209 {"fdvsz", 0xeea00160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1210 {"fdvd", 0xeea00180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1211 {"fdvdp", 0xeea001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1212 {"fdvdm", 0xeea001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1213 {"fdvdz", 0xeea001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1214 {"fdve", 0xeea80100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1215 {"fdvep", 0xeea80120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1216 {"fdvem", 0xeea80140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1217 {"fdvez", 0xeea80160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1219 {"frds", 0xeeb00100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1220 {"frdsp", 0xeeb00120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1221 {"frdsm", 0xeeb00140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1222 {"frdsz", 0xeeb00160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1223 {"frdd", 0xeeb00180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1224 {"frddp", 0xeeb001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1225 {"frddm", 0xeeb001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1226 {"frddz", 0xeeb001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1227 {"frde", 0xeeb80100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1228 {"frdep", 0xeeb80120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1229 {"frdem", 0xeeb80140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1230 {"frdez", 0xeeb80160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1232 {"pols", 0xeec00100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1233 {"polsp", 0xeec00120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1234 {"polsm", 0xeec00140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1235 {"polsz", 0xeec00160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1236 {"pold", 0xeec00180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1237 {"poldp", 0xeec001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1238 {"poldm", 0xeec001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1239 {"poldz", 0xeec001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1240 {"pole", 0xeec80100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1241 {"polep", 0xeec80120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1242 {"polem", 0xeec80140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1243 {"polez", 0xeec80160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1245 {"cmf", 0xee90f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
1246 {"cmfe", 0xeed0f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
1247 {"cnf", 0xeeb0f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
1248 {"cnfe", 0xeef0f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
1249 /* The FPA10 data sheet suggests that the 'E' of cmfe/cnfe should
1250 not be an optional suffix, but part of the instruction. To be
1251 compatible, we accept either. */
1252 {"cmfe", 0xeed0f110, 4, FPU_FPA_EXT_V1
, do_fpa_cmp
},
1253 {"cnfe", 0xeef0f110, 4, FPU_FPA_EXT_V1
, do_fpa_cmp
},
1255 {"flts", 0xee000110, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1256 {"fltsp", 0xee000130, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1257 {"fltsm", 0xee000150, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1258 {"fltsz", 0xee000170, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1259 {"fltd", 0xee000190, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1260 {"fltdp", 0xee0001b0, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1261 {"fltdm", 0xee0001d0, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1262 {"fltdz", 0xee0001f0, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1263 {"flte", 0xee080110, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1264 {"fltep", 0xee080130, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1265 {"fltem", 0xee080150, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1266 {"fltez", 0xee080170, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1268 /* The implementation of the FIX instruction is broken on some
1269 assemblers, in that it accepts a precision specifier as well as a
1270 rounding specifier, despite the fact that this is meaningless.
1271 To be more compatible, we accept it as well, though of course it
1272 does not set any bits. */
1273 {"fix", 0xee100110, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1274 {"fixp", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1275 {"fixm", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1276 {"fixz", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1277 {"fixsp", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1278 {"fixsm", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1279 {"fixsz", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1280 {"fixdp", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1281 {"fixdm", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1282 {"fixdz", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1283 {"fixep", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1284 {"fixem", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1285 {"fixez", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1287 /* Instructions that were new with the real FPA, call them V2. */
1288 {"lfm", 0xec100200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
1289 {"lfmfd", 0xec900200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
1290 {"lfmea", 0xed100200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
1291 {"sfm", 0xec000200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
1292 {"sfmfd", 0xed000200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
1293 {"sfmea", 0xec800200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
1295 /* Intel XScale extensions to ARM V5 ISA. (All use CP0). */
1296 {"mia", 0xee200010, 3, ARM_EXT_XSCALE
, do_mia
},
1297 {"miaph", 0xee280010, 5, ARM_EXT_XSCALE
, do_mia
},
1298 {"miabb", 0xee2c0010, 5, ARM_EXT_XSCALE
, do_mia
},
1299 {"miabt", 0xee2d0010, 5, ARM_EXT_XSCALE
, do_mia
},
1300 {"miatb", 0xee2e0010, 5, ARM_EXT_XSCALE
, do_mia
},
1301 {"miatt", 0xee2f0010, 5, ARM_EXT_XSCALE
, do_mia
},
1302 {"mar", 0xec400000, 3, ARM_EXT_XSCALE
, do_mar
},
1303 {"mra", 0xec500000, 3, ARM_EXT_XSCALE
, do_mra
},
1305 /* Cirrus DSP instructions. */
1306 {"cfldrs", 0xec100400, 6, ARM_EXT_MAVERICK
, do_c_ldst_1
},
1307 {"cfldrd", 0xec500400, 6, ARM_EXT_MAVERICK
, do_c_ldst_2
},
1308 {"cfldr32", 0xec100500, 7, ARM_EXT_MAVERICK
, do_c_ldst_3
},
1309 {"cfldr64", 0xec500500, 7, ARM_EXT_MAVERICK
, do_c_ldst_4
},
1310 {"cfstrs", 0xec000400, 6, ARM_EXT_MAVERICK
, do_c_ldst_1
},
1311 {"cfstrd", 0xec400400, 6, ARM_EXT_MAVERICK
, do_c_ldst_2
},
1312 {"cfstr32", 0xec000500, 7, ARM_EXT_MAVERICK
, do_c_ldst_3
},
1313 {"cfstr64", 0xec400500, 7, ARM_EXT_MAVERICK
, do_c_ldst_4
},
1314 {"cfmvsr", 0xee000450, 6, ARM_EXT_MAVERICK
, do_c_binops_2
},
1315 {"cfmvrs", 0xee100450, 6, ARM_EXT_MAVERICK
, do_c_binops_1
},
1316 {"cfmvdlr", 0xee000410, 7, ARM_EXT_MAVERICK
, do_c_binops_2
},
1317 {"cfmvrdl", 0xee100410, 7, ARM_EXT_MAVERICK
, do_c_binops_1
},
1318 {"cfmvdhr", 0xee000430, 7, ARM_EXT_MAVERICK
, do_c_binops_2
},
1319 {"cfmvrdh", 0xee100430, 7, ARM_EXT_MAVERICK
, do_c_binops_1
},
1320 {"cfmv64lr", 0xee000510, 8, ARM_EXT_MAVERICK
, do_c_binops_2
},
1321 {"cfmvr64l", 0xee100510, 8, ARM_EXT_MAVERICK
, do_c_binops_1
},
1322 {"cfmv64hr", 0xee000530, 8, ARM_EXT_MAVERICK
, do_c_binops_2
},
1323 {"cfmvr64h", 0xee100530, 8, ARM_EXT_MAVERICK
, do_c_binops_1
},
1324 {"cfmval32", 0xee100610, 8, ARM_EXT_MAVERICK
, do_c_binops_3
},
1325 {"cfmv32al", 0xee000610, 8, ARM_EXT_MAVERICK
, do_c_binops_3
},
1326 {"cfmvam32", 0xee100630, 8, ARM_EXT_MAVERICK
, do_c_binops_3
},
1327 {"cfmv32am", 0xee000630, 8, ARM_EXT_MAVERICK
, do_c_binops_3
},
1328 {"cfmvah32", 0xee100650, 8, ARM_EXT_MAVERICK
, do_c_binops_3
},
1329 {"cfmv32ah", 0xee000650, 8, ARM_EXT_MAVERICK
, do_c_binops_3
},
1330 {"cfmv32a", 0xee000670, 7, ARM_EXT_MAVERICK
, do_c_binops_3
},
1331 {"cfmva32", 0xee100670, 7, ARM_EXT_MAVERICK
, do_c_binops_3
},
1332 {"cfmv64a", 0xee000690, 7, ARM_EXT_MAVERICK
, do_c_binops_3
},
1333 {"cfmva64", 0xee100690, 7, ARM_EXT_MAVERICK
, do_c_binops_3
},
1334 {"cfmvsc32", 0xee1006b0, 8, ARM_EXT_MAVERICK
, do_c_dspsc_1
},
1335 {"cfmv32sc", 0xee0006b0, 8, ARM_EXT_MAVERICK
, do_c_dspsc_2
},
1336 {"cfcpys", 0xee000400, 6, ARM_EXT_MAVERICK
, do_c_binops_1
},
1337 {"cfcpyd", 0xee000420, 6, ARM_EXT_MAVERICK
, do_c_binops_1
},
1338 {"cfcvtsd", 0xee000460, 7, ARM_EXT_MAVERICK
, do_c_binops_1
},
1339 {"cfcvtds", 0xee000440, 7, ARM_EXT_MAVERICK
, do_c_binops_1
},
1340 {"cfcvt32s", 0xee000480, 8, ARM_EXT_MAVERICK
, do_c_binops_1
},
1341 {"cfcvt32d", 0xee0004a0, 8, ARM_EXT_MAVERICK
, do_c_binops_1
},
1342 {"cfcvt64s", 0xee0004c0, 8, ARM_EXT_MAVERICK
, do_c_binops_1
},
1343 {"cfcvt64d", 0xee0004e0, 8, ARM_EXT_MAVERICK
, do_c_binops_1
},
1344 {"cfcvts32", 0xee100580, 8, ARM_EXT_MAVERICK
, do_c_binops_1
},
1345 {"cfcvtd32", 0xee1005a0, 8, ARM_EXT_MAVERICK
, do_c_binops_1
},
1346 {"cftruncs32", 0xee1005c0, 10, ARM_EXT_MAVERICK
, do_c_binops_1
},
1347 {"cftruncd32", 0xee1005e0, 10, ARM_EXT_MAVERICK
, do_c_binops_1
},
1348 {"cfrshl32", 0xee000550, 8, ARM_EXT_MAVERICK
, do_c_triple_4
},
1349 {"cfrshl64", 0xee000570, 8, ARM_EXT_MAVERICK
, do_c_triple_4
},
1350 {"cfsh32", 0xee000500, 6, ARM_EXT_MAVERICK
, do_c_shift_1
},
1351 {"cfsh64", 0xee200500, 6, ARM_EXT_MAVERICK
, do_c_shift_2
},
1352 {"cfcmps", 0xee100490, 6, ARM_EXT_MAVERICK
, do_c_triple_5
},
1353 {"cfcmpd", 0xee1004b0, 6, ARM_EXT_MAVERICK
, do_c_triple_5
},
1354 {"cfcmp32", 0xee100590, 7, ARM_EXT_MAVERICK
, do_c_triple_5
},
1355 {"cfcmp64", 0xee1005b0, 7, ARM_EXT_MAVERICK
, do_c_triple_5
},
1356 {"cfabss", 0xee300400, 6, ARM_EXT_MAVERICK
, do_c_binops_1
},
1357 {"cfabsd", 0xee300420, 6, ARM_EXT_MAVERICK
, do_c_binops_1
},
1358 {"cfnegs", 0xee300440, 6, ARM_EXT_MAVERICK
, do_c_binops_1
},
1359 {"cfnegd", 0xee300460, 6, ARM_EXT_MAVERICK
, do_c_binops_1
},
1360 {"cfadds", 0xee300480, 6, ARM_EXT_MAVERICK
, do_c_triple_5
},
1361 {"cfaddd", 0xee3004a0, 6, ARM_EXT_MAVERICK
, do_c_triple_5
},
1362 {"cfsubs", 0xee3004c0, 6, ARM_EXT_MAVERICK
, do_c_triple_5
},
1363 {"cfsubd", 0xee3004e0, 6, ARM_EXT_MAVERICK
, do_c_triple_5
},
1364 {"cfmuls", 0xee100400, 6, ARM_EXT_MAVERICK
, do_c_triple_5
},
1365 {"cfmuld", 0xee100420, 6, ARM_EXT_MAVERICK
, do_c_triple_5
},
1366 {"cfabs32", 0xee300500, 7, ARM_EXT_MAVERICK
, do_c_binops_1
},
1367 {"cfabs64", 0xee300520, 7, ARM_EXT_MAVERICK
, do_c_binops_1
},
1368 {"cfneg32", 0xee300540, 7, ARM_EXT_MAVERICK
, do_c_binops_1
},
1369 {"cfneg64", 0xee300560, 7, ARM_EXT_MAVERICK
, do_c_binops_1
},
1370 {"cfadd32", 0xee300580, 7, ARM_EXT_MAVERICK
, do_c_triple_5
},
1371 {"cfadd64", 0xee3005a0, 7, ARM_EXT_MAVERICK
, do_c_triple_5
},
1372 {"cfsub32", 0xee3005c0, 7, ARM_EXT_MAVERICK
, do_c_triple_5
},
1373 {"cfsub64", 0xee3005e0, 7, ARM_EXT_MAVERICK
, do_c_triple_5
},
1374 {"cfmul32", 0xee100500, 7, ARM_EXT_MAVERICK
, do_c_triple_5
},
1375 {"cfmul64", 0xee100520, 7, ARM_EXT_MAVERICK
, do_c_triple_5
},
1376 {"cfmac32", 0xee100540, 7, ARM_EXT_MAVERICK
, do_c_triple_5
},
1377 {"cfmsc32", 0xee100560, 7, ARM_EXT_MAVERICK
, do_c_triple_5
},
1378 {"cfmadd32", 0xee000600, 8, ARM_EXT_MAVERICK
, do_c_quad_6
},
1379 {"cfmsub32", 0xee100600, 8, ARM_EXT_MAVERICK
, do_c_quad_6
},
1380 {"cfmadda32", 0xee200600, 9, ARM_EXT_MAVERICK
, do_c_quad_6
},
1381 {"cfmsuba32", 0xee300600, 9, ARM_EXT_MAVERICK
, do_c_quad_6
},
1384 /* Defines for various bits that we will want to toggle. */
1385 #define INST_IMMEDIATE 0x02000000
1386 #define OFFSET_REG 0x02000000
1387 #define HWOFFSET_IMM 0x00400000
1388 #define SHIFT_BY_REG 0x00000010
1389 #define PRE_INDEX 0x01000000
1390 #define INDEX_UP 0x00800000
1391 #define WRITE_BACK 0x00200000
1392 #define LDM_TYPE_2_OR_3 0x00400000
1394 #define LITERAL_MASK 0xf000f000
1395 #define OPCODE_MASK 0xfe1fffff
1396 #define V4_STR_BIT 0x00000020
1398 #define DATA_OP_SHIFT 21
1400 /* Codes to distinguish the arithmetic instructions. */
1401 #define OPCODE_AND 0
1402 #define OPCODE_EOR 1
1403 #define OPCODE_SUB 2
1404 #define OPCODE_RSB 3
1405 #define OPCODE_ADD 4
1406 #define OPCODE_ADC 5
1407 #define OPCODE_SBC 6
1408 #define OPCODE_RSC 7
1409 #define OPCODE_TST 8
1410 #define OPCODE_TEQ 9
1411 #define OPCODE_CMP 10
1412 #define OPCODE_CMN 11
1413 #define OPCODE_ORR 12
1414 #define OPCODE_MOV 13
1415 #define OPCODE_BIC 14
1416 #define OPCODE_MVN 15
1418 /* Thumb v1 (ARMv4T). */
1419 static void do_t_nop
PARAMS ((char *));
1420 static void do_t_arit
PARAMS ((char *));
1421 static void do_t_add
PARAMS ((char *));
1422 static void do_t_asr
PARAMS ((char *));
1423 static void do_t_branch9
PARAMS ((char *));
1424 static void do_t_branch12
PARAMS ((char *));
1425 static void do_t_branch23
PARAMS ((char *));
1426 static void do_t_bx
PARAMS ((char *));
1427 static void do_t_compare
PARAMS ((char *));
1428 static void do_t_ldmstm
PARAMS ((char *));
1429 static void do_t_ldr
PARAMS ((char *));
1430 static void do_t_ldrb
PARAMS ((char *));
1431 static void do_t_ldrh
PARAMS ((char *));
1432 static void do_t_lds
PARAMS ((char *));
1433 static void do_t_lsl
PARAMS ((char *));
1434 static void do_t_lsr
PARAMS ((char *));
1435 static void do_t_mov
PARAMS ((char *));
1436 static void do_t_push_pop
PARAMS ((char *));
1437 static void do_t_str
PARAMS ((char *));
1438 static void do_t_strb
PARAMS ((char *));
1439 static void do_t_strh
PARAMS ((char *));
1440 static void do_t_sub
PARAMS ((char *));
1441 static void do_t_swi
PARAMS ((char *));
1442 static void do_t_adr
PARAMS ((char *));
1444 /* Thumb v2 (ARMv5T). */
1445 static void do_t_blx
PARAMS ((char *));
1446 static void do_t_bkpt
PARAMS ((char *));
1448 #define T_OPCODE_MUL 0x4340
1449 #define T_OPCODE_TST 0x4200
1450 #define T_OPCODE_CMN 0x42c0
1451 #define T_OPCODE_NEG 0x4240
1452 #define T_OPCODE_MVN 0x43c0
1454 #define T_OPCODE_ADD_R3 0x1800
1455 #define T_OPCODE_SUB_R3 0x1a00
1456 #define T_OPCODE_ADD_HI 0x4400
1457 #define T_OPCODE_ADD_ST 0xb000
1458 #define T_OPCODE_SUB_ST 0xb080
1459 #define T_OPCODE_ADD_SP 0xa800
1460 #define T_OPCODE_ADD_PC 0xa000
1461 #define T_OPCODE_ADD_I8 0x3000
1462 #define T_OPCODE_SUB_I8 0x3800
1463 #define T_OPCODE_ADD_I3 0x1c00
1464 #define T_OPCODE_SUB_I3 0x1e00
1466 #define T_OPCODE_ASR_R 0x4100
1467 #define T_OPCODE_LSL_R 0x4080
1468 #define T_OPCODE_LSR_R 0x40c0
1469 #define T_OPCODE_ASR_I 0x1000
1470 #define T_OPCODE_LSL_I 0x0000
1471 #define T_OPCODE_LSR_I 0x0800
1473 #define T_OPCODE_MOV_I8 0x2000
1474 #define T_OPCODE_CMP_I8 0x2800
1475 #define T_OPCODE_CMP_LR 0x4280
1476 #define T_OPCODE_MOV_HR 0x4600
1477 #define T_OPCODE_CMP_HR 0x4500
1479 #define T_OPCODE_LDR_PC 0x4800
1480 #define T_OPCODE_LDR_SP 0x9800
1481 #define T_OPCODE_STR_SP 0x9000
1482 #define T_OPCODE_LDR_IW 0x6800
1483 #define T_OPCODE_STR_IW 0x6000
1484 #define T_OPCODE_LDR_IH 0x8800
1485 #define T_OPCODE_STR_IH 0x8000
1486 #define T_OPCODE_LDR_IB 0x7800
1487 #define T_OPCODE_STR_IB 0x7000
1488 #define T_OPCODE_LDR_RW 0x5800
1489 #define T_OPCODE_STR_RW 0x5000
1490 #define T_OPCODE_LDR_RH 0x5a00
1491 #define T_OPCODE_STR_RH 0x5200
1492 #define T_OPCODE_LDR_RB 0x5c00
1493 #define T_OPCODE_STR_RB 0x5400
1495 #define T_OPCODE_PUSH 0xb400
1496 #define T_OPCODE_POP 0xbc00
1498 #define T_OPCODE_BRANCH 0xe7fe
1500 static int thumb_reg
PARAMS ((char ** str
, int hi_lo
));
1502 #define THUMB_SIZE 2 /* Size of thumb instruction. */
1503 #define THUMB_REG_LO 0x1
1504 #define THUMB_REG_HI 0x2
1505 #define THUMB_REG_ANY 0x3
1507 #define THUMB_H1 0x0080
1508 #define THUMB_H2 0x0040
1514 #define THUMB_MOVE 0
1515 #define THUMB_COMPARE 1
1517 #define THUMB_LOAD 0
1518 #define THUMB_STORE 1
1520 #define THUMB_PP_PC_LR 0x0100
1522 /* These three are used for immediate shifts, do not alter. */
1523 #define THUMB_WORD 2
1524 #define THUMB_HALFWORD 1
1525 #define THUMB_BYTE 0
1529 /* Basic string to match. */
1530 const char * template;
1532 /* Basic instruction code. */
1533 unsigned long value
;
1537 /* Which CPU variants this exists for. */
1538 unsigned long variant
;
1540 /* Function to call to parse args. */
1541 void (* parms
) PARAMS ((char *));
1544 static const struct thumb_opcode tinsns
[] =
1546 /* Thumb v1 (ARMv4T). */
1547 {"adc", 0x4140, 2, ARM_EXT_V4T
, do_t_arit
},
1548 {"add", 0x0000, 2, ARM_EXT_V4T
, do_t_add
},
1549 {"and", 0x4000, 2, ARM_EXT_V4T
, do_t_arit
},
1550 {"asr", 0x0000, 2, ARM_EXT_V4T
, do_t_asr
},
1551 {"b", T_OPCODE_BRANCH
, 2, ARM_EXT_V4T
, do_t_branch12
},
1552 {"beq", 0xd0fe, 2, ARM_EXT_V4T
, do_t_branch9
},
1553 {"bne", 0xd1fe, 2, ARM_EXT_V4T
, do_t_branch9
},
1554 {"bcs", 0xd2fe, 2, ARM_EXT_V4T
, do_t_branch9
},
1555 {"bhs", 0xd2fe, 2, ARM_EXT_V4T
, do_t_branch9
},
1556 {"bcc", 0xd3fe, 2, ARM_EXT_V4T
, do_t_branch9
},
1557 {"bul", 0xd3fe, 2, ARM_EXT_V4T
, do_t_branch9
},
1558 {"blo", 0xd3fe, 2, ARM_EXT_V4T
, do_t_branch9
},
1559 {"bmi", 0xd4fe, 2, ARM_EXT_V4T
, do_t_branch9
},
1560 {"bpl", 0xd5fe, 2, ARM_EXT_V4T
, do_t_branch9
},
1561 {"bvs", 0xd6fe, 2, ARM_EXT_V4T
, do_t_branch9
},
1562 {"bvc", 0xd7fe, 2, ARM_EXT_V4T
, do_t_branch9
},
1563 {"bhi", 0xd8fe, 2, ARM_EXT_V4T
, do_t_branch9
},
1564 {"bls", 0xd9fe, 2, ARM_EXT_V4T
, do_t_branch9
},
1565 {"bge", 0xdafe, 2, ARM_EXT_V4T
, do_t_branch9
},
1566 {"blt", 0xdbfe, 2, ARM_EXT_V4T
, do_t_branch9
},
1567 {"bgt", 0xdcfe, 2, ARM_EXT_V4T
, do_t_branch9
},
1568 {"ble", 0xddfe, 2, ARM_EXT_V4T
, do_t_branch9
},
1569 {"bal", 0xdefe, 2, ARM_EXT_V4T
, do_t_branch9
},
1570 {"bic", 0x4380, 2, ARM_EXT_V4T
, do_t_arit
},
1571 {"bl", 0xf7fffffe, 4, ARM_EXT_V4T
, do_t_branch23
},
1572 {"bx", 0x4700, 2, ARM_EXT_V4T
, do_t_bx
},
1573 {"cmn", T_OPCODE_CMN
, 2, ARM_EXT_V4T
, do_t_arit
},
1574 {"cmp", 0x0000, 2, ARM_EXT_V4T
, do_t_compare
},
1575 {"eor", 0x4040, 2, ARM_EXT_V4T
, do_t_arit
},
1576 {"ldmia", 0xc800, 2, ARM_EXT_V4T
, do_t_ldmstm
},
1577 {"ldr", 0x0000, 2, ARM_EXT_V4T
, do_t_ldr
},
1578 {"ldrb", 0x0000, 2, ARM_EXT_V4T
, do_t_ldrb
},
1579 {"ldrh", 0x0000, 2, ARM_EXT_V4T
, do_t_ldrh
},
1580 {"ldrsb", 0x5600, 2, ARM_EXT_V4T
, do_t_lds
},
1581 {"ldrsh", 0x5e00, 2, ARM_EXT_V4T
, do_t_lds
},
1582 {"ldsb", 0x5600, 2, ARM_EXT_V4T
, do_t_lds
},
1583 {"ldsh", 0x5e00, 2, ARM_EXT_V4T
, do_t_lds
},
1584 {"lsl", 0x0000, 2, ARM_EXT_V4T
, do_t_lsl
},
1585 {"lsr", 0x0000, 2, ARM_EXT_V4T
, do_t_lsr
},
1586 {"mov", 0x0000, 2, ARM_EXT_V4T
, do_t_mov
},
1587 {"mul", T_OPCODE_MUL
, 2, ARM_EXT_V4T
, do_t_arit
},
1588 {"mvn", T_OPCODE_MVN
, 2, ARM_EXT_V4T
, do_t_arit
},
1589 {"neg", T_OPCODE_NEG
, 2, ARM_EXT_V4T
, do_t_arit
},
1590 {"orr", 0x4300, 2, ARM_EXT_V4T
, do_t_arit
},
1591 {"pop", 0xbc00, 2, ARM_EXT_V4T
, do_t_push_pop
},
1592 {"push", 0xb400, 2, ARM_EXT_V4T
, do_t_push_pop
},
1593 {"ror", 0x41c0, 2, ARM_EXT_V4T
, do_t_arit
},
1594 {"sbc", 0x4180, 2, ARM_EXT_V4T
, do_t_arit
},
1595 {"stmia", 0xc000, 2, ARM_EXT_V4T
, do_t_ldmstm
},
1596 {"str", 0x0000, 2, ARM_EXT_V4T
, do_t_str
},
1597 {"strb", 0x0000, 2, ARM_EXT_V4T
, do_t_strb
},
1598 {"strh", 0x0000, 2, ARM_EXT_V4T
, do_t_strh
},
1599 {"swi", 0xdf00, 2, ARM_EXT_V4T
, do_t_swi
},
1600 {"sub", 0x0000, 2, ARM_EXT_V4T
, do_t_sub
},
1601 {"tst", T_OPCODE_TST
, 2, ARM_EXT_V4T
, do_t_arit
},
1603 {"adr", 0x0000, 2, ARM_EXT_V4T
, do_t_adr
},
1604 {"nop", 0x46C0, 2, ARM_EXT_V4T
, do_t_nop
}, /* mov r8,r8 */
1605 /* Thumb v2 (ARMv5T). */
1606 {"blx", 0, 0, ARM_EXT_V5T
, do_t_blx
},
1607 {"bkpt", 0xbe00, 2, ARM_EXT_V5T
, do_t_bkpt
},
1616 #define int_register(reg) ((reg) >= 0 && (reg) <= 15)
1617 #define cp_register(reg) ((reg) >= 32 && (reg) <= 47)
1618 #define fp_register(reg) ((reg) >= 16 && (reg) <= 23)
1620 #define ARM_EXT_MAVERICKSC_REG 134
1622 #define cirrus_register(reg) ((reg) >= 50 && (reg) <= 134)
1623 #define cirrus_mvf_register(reg) ((reg) >= 50 && (reg) <= 65)
1624 #define cirrus_mvd_register(reg) ((reg) >= 70 && (reg) <= 85)
1625 #define cirrus_mvfx_register(reg) ((reg) >= 90 && (reg) <= 105)
1626 #define cirrus_mvdx_register(reg) ((reg) >= 110 && (reg) <= 125)
1627 #define cirrus_mvax_register(reg) ((reg) >= 130 && (reg) <= 133)
1628 #define ARM_EXT_MAVERICKsc_register(reg) ((reg) == ARM_EXT_MAVERICKSC_REG)
1634 /* These are the standard names. Users can add aliases with .req. */
1635 static const struct reg_entry reg_table
[] =
1637 /* Processor Register Numbers. */
1638 {"r0", 0}, {"r1", 1}, {"r2", 2}, {"r3", 3},
1639 {"r4", 4}, {"r5", 5}, {"r6", 6}, {"r7", 7},
1640 {"r8", 8}, {"r9", 9}, {"r10", 10}, {"r11", 11},
1641 {"r12", 12}, {"r13", REG_SP
},{"r14", REG_LR
},{"r15", REG_PC
},
1642 /* APCS conventions. */
1643 {"a1", 0}, {"a2", 1}, {"a3", 2}, {"a4", 3},
1644 {"v1", 4}, {"v2", 5}, {"v3", 6}, {"v4", 7}, {"v5", 8},
1645 {"v6", 9}, {"sb", 9}, {"v7", 10}, {"sl", 10},
1646 {"fp", 11}, {"ip", 12}, {"sp", REG_SP
},{"lr", REG_LR
},{"pc", REG_PC
},
1647 /* ATPCS additions to APCS conventions. */
1648 {"wr", 7}, {"v8", 11},
1650 {"f0", 16}, {"f1", 17}, {"f2", 18}, {"f3", 19},
1651 {"f4", 20}, {"f5", 21}, {"f6", 22}, {"f7", 23},
1652 {"c0", 32}, {"c1", 33}, {"c2", 34}, {"c3", 35},
1653 {"c4", 36}, {"c5", 37}, {"c6", 38}, {"c7", 39},
1654 {"c8", 40}, {"c9", 41}, {"c10", 42}, {"c11", 43},
1655 {"c12", 44}, {"c13", 45}, {"c14", 46}, {"c15", 47},
1656 {"cr0", 32}, {"cr1", 33}, {"cr2", 34}, {"cr3", 35},
1657 {"cr4", 36}, {"cr5", 37}, {"cr6", 38}, {"cr7", 39},
1658 {"cr8", 40}, {"cr9", 41}, {"cr10", 42}, {"cr11", 43},
1659 {"cr12", 44}, {"cr13", 45}, {"cr14", 46}, {"cr15", 47},
1660 /* ATPCS additions to float register names. */
1661 {"s0",16}, {"s1",17}, {"s2",18}, {"s3",19},
1662 {"s4",20}, {"s5",21}, {"s6",22}, {"s7",23},
1663 {"d0",16}, {"d1",17}, {"d2",18}, {"d3",19},
1664 {"d4",20}, {"d5",21}, {"d6",22}, {"d7",23},
1665 /* Cirrus DSP coprocessor registers. */
1666 {"mvf0", 50}, {"mvf1", 51}, {"mvf2", 52}, {"mvf3", 53},
1667 {"mvf4", 54}, {"mvf5", 55}, {"mvf6", 56}, {"mvf7", 57},
1668 {"mvf8", 58}, {"mvf9", 59}, {"mvf10", 60}, {"mvf11", 61},
1669 {"mvf12", 62},{"mvf13", 63}, {"mvf14", 64}, {"mvf15", 65},
1670 {"mvd0", 70}, {"mvd1", 71}, {"mvd2", 72}, {"mvd3", 73},
1671 {"mvd4", 74}, {"mvd5", 75}, {"mvd6", 76}, {"mvd7", 77},
1672 {"mvd8", 78}, {"mvd9", 79}, {"mvd10", 80}, {"mvd11", 81},
1673 {"mvd12", 82},{"mvd13", 83}, {"mvd14", 84}, {"mvd15", 85},
1674 {"mvfx0", 90},{"mvfx1", 91}, {"mvfx2", 92}, {"mvfx3", 93},
1675 {"mvfx4", 94},{"mvfx5", 95}, {"mvfx6", 96}, {"mvfx7", 97},
1676 {"mvfx8", 98},{"mvfx9", 99}, {"mvfx10", 100},{"mvfx11", 101},
1677 {"mvfx12", 102},{"mvfx13", 103},{"mvfx14", 104},{"mvfx15", 105},
1678 {"mvdx0", 110}, {"mvdx1", 111}, {"mvdx2", 112}, {"mvdx3", 113},
1679 {"mvdx4", 114}, {"mvdx5", 115}, {"mvdx6", 116}, {"mvdx7", 117},
1680 {"mvdx8", 118}, {"mvdx9", 119}, {"mvdx10", 120},{"mvdx11", 121},
1681 {"mvdx12", 122},{"mvdx13", 123},{"mvdx14", 124},{"mvdx15", 125},
1682 {"mvax0", 130}, {"mvax1", 131}, {"mvax2", 132}, {"mvax3", 133},
1683 {"dspsc", ARM_EXT_MAVERICKSC_REG
},
1684 /* FIXME: At some point we need to add VFP register names. */
1685 /* Array terminator. */
1689 #define BAD_ARGS _("Bad arguments to instruction")
1690 #define BAD_PC _("r15 not allowed here")
1691 #define BAD_FLAGS _("Instruction should not have flags")
1692 #define BAD_COND _("Instruction is not conditional")
1693 #define ERR_NO_ACCUM _("acc0 expected")
1695 static struct hash_control
* arm_ops_hsh
= NULL
;
1696 static struct hash_control
* arm_tops_hsh
= NULL
;
1697 static struct hash_control
* arm_cond_hsh
= NULL
;
1698 static struct hash_control
* arm_shift_hsh
= NULL
;
1699 static struct hash_control
* arm_reg_hsh
= NULL
;
1700 static struct hash_control
* arm_psr_hsh
= NULL
;
1702 /* This table describes all the machine specific pseudo-ops the assembler
1703 has to support. The fields are:
1704 pseudo-op name without dot
1705 function to call to execute this pseudo-op
1706 Integer arg to pass to the function. */
1708 static void s_req
PARAMS ((int));
1709 static void s_align
PARAMS ((int));
1710 static void s_bss
PARAMS ((int));
1711 static void s_even
PARAMS ((int));
1712 static void s_ltorg
PARAMS ((int));
1713 static void s_arm
PARAMS ((int));
1714 static void s_thumb
PARAMS ((int));
1715 static void s_code
PARAMS ((int));
1716 static void s_force_thumb
PARAMS ((int));
1717 static void s_thumb_func
PARAMS ((int));
1718 static void s_thumb_set
PARAMS ((int));
1719 static void arm_s_text
PARAMS ((int));
1720 static void arm_s_data
PARAMS ((int));
1722 static void arm_s_section
PARAMS ((int));
1723 static void s_arm_elf_cons
PARAMS ((int));
1726 static int my_get_expression
PARAMS ((expressionS
*, char **));
1728 const pseudo_typeS md_pseudo_table
[] =
1730 /* Never called becasue '.req' does not start line. */
1731 { "req", s_req
, 0 },
1732 { "bss", s_bss
, 0 },
1733 { "align", s_align
, 0 },
1734 { "arm", s_arm
, 0 },
1735 { "thumb", s_thumb
, 0 },
1736 { "code", s_code
, 0 },
1737 { "force_thumb", s_force_thumb
, 0 },
1738 { "thumb_func", s_thumb_func
, 0 },
1739 { "thumb_set", s_thumb_set
, 0 },
1740 { "even", s_even
, 0 },
1741 { "ltorg", s_ltorg
, 0 },
1742 { "pool", s_ltorg
, 0 },
1743 /* Allow for the effect of section changes. */
1744 { "text", arm_s_text
, 0 },
1745 { "data", arm_s_data
, 0 },
1747 { "section", arm_s_section
, 0 },
1748 { "section.s", arm_s_section
, 0 },
1749 { "sect", arm_s_section
, 0 },
1750 { "sect.s", arm_s_section
, 0 },
1751 { "word", s_arm_elf_cons
, 4 },
1752 { "long", s_arm_elf_cons
, 4 },
1753 { "file", dwarf2_directive_file
, 0 },
1754 { "loc", dwarf2_directive_loc
, 0 },
1758 { "extend", float_cons
, 'x' },
1759 { "ldouble", float_cons
, 'x' },
1760 { "packed", float_cons
, 'p' },
1764 /* Stuff needed to resolve the label ambiguity
1774 symbolS
* last_label_seen
;
1775 static int label_is_thumb_function_name
= false;
1777 /* Literal stuff. */
1779 #define MAX_LITERAL_POOL_SIZE 1024
1781 typedef struct literalS
1783 struct expressionS exp
;
1784 struct arm_it
* inst
;
1787 literalT literals
[MAX_LITERAL_POOL_SIZE
];
1789 /* Next free entry in the pool. */
1790 int next_literal_pool_place
= 0;
1792 /* Next literal pool number. */
1793 int lit_pool_num
= 1;
1795 symbolS
* current_poolP
= NULL
;
1802 if (current_poolP
== NULL
)
1803 current_poolP
= symbol_create (FAKE_LABEL_NAME
, undefined_section
,
1804 (valueT
) 0, &zero_address_frag
);
1806 /* Check if this literal value is already in the pool: */
1807 while (lit_count
< next_literal_pool_place
)
1809 if (literals
[lit_count
].exp
.X_op
== inst
.reloc
.exp
.X_op
1810 && inst
.reloc
.exp
.X_op
== O_constant
1811 && (literals
[lit_count
].exp
.X_add_number
1812 == inst
.reloc
.exp
.X_add_number
)
1813 && literals
[lit_count
].exp
.X_unsigned
== inst
.reloc
.exp
.X_unsigned
)
1816 if (literals
[lit_count
].exp
.X_op
== inst
.reloc
.exp
.X_op
1817 && inst
.reloc
.exp
.X_op
== O_symbol
1818 && (literals
[lit_count
].exp
.X_add_number
1819 == inst
.reloc
.exp
.X_add_number
)
1820 && (literals
[lit_count
].exp
.X_add_symbol
1821 == inst
.reloc
.exp
.X_add_symbol
)
1822 && (literals
[lit_count
].exp
.X_op_symbol
1823 == inst
.reloc
.exp
.X_op_symbol
))
1829 if (lit_count
== next_literal_pool_place
) /* New entry. */
1831 if (next_literal_pool_place
>= MAX_LITERAL_POOL_SIZE
)
1833 inst
.error
= _("Literal Pool Overflow");
1837 literals
[next_literal_pool_place
].exp
= inst
.reloc
.exp
;
1838 lit_count
= next_literal_pool_place
++;
1841 inst
.reloc
.exp
.X_op
= O_symbol
;
1842 inst
.reloc
.exp
.X_add_number
= (lit_count
) * 4 - 8;
1843 inst
.reloc
.exp
.X_add_symbol
= current_poolP
;
1848 /* Can't use symbol_new here, so have to create a symbol and then at
1849 a later date assign it a value. Thats what these functions do. */
1852 symbol_locate (symbolP
, name
, segment
, valu
, frag
)
1854 const char * name
; /* It is copied, the caller can modify. */
1855 segT segment
; /* Segment identifier (SEG_<something>). */
1856 valueT valu
; /* Symbol value. */
1857 fragS
* frag
; /* Associated fragment. */
1859 unsigned int name_length
;
1860 char * preserved_copy_of_name
;
1862 name_length
= strlen (name
) + 1; /* +1 for \0. */
1863 obstack_grow (¬es
, name
, name_length
);
1864 preserved_copy_of_name
= obstack_finish (¬es
);
1865 #ifdef STRIP_UNDERSCORE
1866 if (preserved_copy_of_name
[0] == '_')
1867 preserved_copy_of_name
++;
1870 #ifdef tc_canonicalize_symbol_name
1871 preserved_copy_of_name
=
1872 tc_canonicalize_symbol_name (preserved_copy_of_name
);
1875 S_SET_NAME (symbolP
, preserved_copy_of_name
);
1877 S_SET_SEGMENT (symbolP
, segment
);
1878 S_SET_VALUE (symbolP
, valu
);
1879 symbol_clear_list_pointers(symbolP
);
1881 symbol_set_frag (symbolP
, frag
);
1883 /* Link to end of symbol chain. */
1885 extern int symbol_table_frozen
;
1886 if (symbol_table_frozen
)
1890 symbol_append (symbolP
, symbol_lastP
, & symbol_rootP
, & symbol_lastP
);
1892 obj_symbol_new_hook (symbolP
);
1894 #ifdef tc_symbol_new_hook
1895 tc_symbol_new_hook (symbolP
);
1899 verify_symbol_chain (symbol_rootP
, symbol_lastP
);
1900 #endif /* DEBUG_SYMS */
1903 /* Check that an immediate is valid.
1904 If so, convert it to the right format. */
1907 validate_immediate (val
)
1913 #define rotate_left(v, n) (v << n | v >> (32 - n))
1915 for (i
= 0; i
< 32; i
+= 2)
1916 if ((a
= rotate_left (val
, i
)) <= 0xff)
1917 return a
| (i
<< 7); /* 12-bit pack: [shift-cnt,const]. */
1922 /* Check to see if an immediate can be computed as two seperate immediate
1923 values, added together. We already know that this value cannot be
1924 computed by just one ARM instruction. */
1927 validate_immediate_twopart (val
, highpart
)
1929 unsigned int * highpart
;
1934 for (i
= 0; i
< 32; i
+= 2)
1935 if (((a
= rotate_left (val
, i
)) & 0xff) != 0)
1941 * highpart
= (a
>> 8) | ((i
+ 24) << 7);
1943 else if (a
& 0xff0000)
1947 * highpart
= (a
>> 16) | ((i
+ 16) << 7);
1951 assert (a
& 0xff000000);
1952 * highpart
= (a
>> 24) | ((i
+ 8) << 7);
1955 return (a
& 0xff) | (i
<< 7);
1962 validate_offset_imm (val
, hwse
)
1966 if ((hwse
&& val
> 255) || val
> 4095)
1973 int a ATTRIBUTE_UNUSED
;
1975 as_bad (_("Invalid syntax for .req directive."));
1980 int ignore ATTRIBUTE_UNUSED
;
1982 /* We don't support putting frags in the BSS segment, we fake it by
1983 marking in_bss, then looking at s_skip for clues. */
1984 subseg_set (bss_section
, 0);
1985 demand_empty_rest_of_line ();
1990 int ignore ATTRIBUTE_UNUSED
;
1992 /* Never make frag if expect extra pass. */
1994 frag_align (1, 0, 0);
1996 record_alignment (now_seg
, 1);
1998 demand_empty_rest_of_line ();
2003 int ignored ATTRIBUTE_UNUSED
;
2008 if (current_poolP
== NULL
)
2011 /* Align pool as you have word accesses.
2012 Only make a frag if we have to. */
2014 frag_align (2, 0, 0);
2016 record_alignment (now_seg
, 2);
2018 sprintf (sym_name
, "$$lit_\002%x", lit_pool_num
++);
2020 symbol_locate (current_poolP
, sym_name
, now_seg
,
2021 (valueT
) frag_now_fix (), frag_now
);
2022 symbol_table_insert (current_poolP
);
2024 ARM_SET_THUMB (current_poolP
, thumb_mode
);
2026 #if defined OBJ_COFF || defined OBJ_ELF
2027 ARM_SET_INTERWORK (current_poolP
, support_interwork
);
2030 while (lit_count
< next_literal_pool_place
)
2031 /* First output the expression in the instruction to the pool. */
2032 emit_expr (&(literals
[lit_count
++].exp
), 4); /* .word */
2034 next_literal_pool_place
= 0;
2035 current_poolP
= NULL
;
2038 /* Same as s_align_ptwo but align 0 => align 2. */
2042 int unused ATTRIBUTE_UNUSED
;
2045 register long temp_fill
;
2046 long max_alignment
= 15;
2048 temp
= get_absolute_expression ();
2049 if (temp
> max_alignment
)
2050 as_bad (_("Alignment too large: %d. assumed."), temp
= max_alignment
);
2053 as_bad (_("Alignment negative. 0 assumed."));
2057 if (*input_line_pointer
== ',')
2059 input_line_pointer
++;
2060 temp_fill
= get_absolute_expression ();
2068 /* Only make a frag if we HAVE to. */
2069 if (temp
&& !need_pass_2
)
2070 frag_align (temp
, (int) temp_fill
, 0);
2071 demand_empty_rest_of_line ();
2073 record_alignment (now_seg
, temp
);
2077 s_force_thumb (ignore
)
2078 int ignore ATTRIBUTE_UNUSED
;
2080 /* If we are not already in thumb mode go into it, EVEN if
2081 the target processor does not support thumb instructions.
2082 This is used by gcc/config/arm/lib1funcs.asm for example
2083 to compile interworking support functions even if the
2084 target processor should not support interworking. */
2089 record_alignment (now_seg
, 1);
2092 demand_empty_rest_of_line ();
2096 s_thumb_func (ignore
)
2097 int ignore ATTRIBUTE_UNUSED
;
2102 /* The following label is the name/address of the start of a Thumb function.
2103 We need to know this for the interworking support. */
2104 label_is_thumb_function_name
= true;
2106 demand_empty_rest_of_line ();
2109 /* Perform a .set directive, but also mark the alias as
2110 being a thumb function. */
2116 /* XXX the following is a duplicate of the code for s_set() in read.c
2117 We cannot just call that code as we need to get at the symbol that
2119 register char * name
;
2120 register char delim
;
2121 register char * end_name
;
2122 register symbolS
* symbolP
;
2124 /* Especial apologies for the random logic:
2125 This just grew, and could be parsed much more simply!
2127 name
= input_line_pointer
;
2128 delim
= get_symbol_end ();
2129 end_name
= input_line_pointer
;
2134 if (*input_line_pointer
!= ',')
2137 as_bad (_("Expected comma after name \"%s\""), name
);
2139 ignore_rest_of_line ();
2143 input_line_pointer
++;
2146 if (name
[0] == '.' && name
[1] == '\0')
2148 /* XXX - this should not happen to .thumb_set. */
2152 if ((symbolP
= symbol_find (name
)) == NULL
2153 && (symbolP
= md_undefined_symbol (name
)) == NULL
)
2156 /* When doing symbol listings, play games with dummy fragments living
2157 outside the normal fragment chain to record the file and line info
2159 if (listing
& LISTING_SYMBOLS
)
2161 extern struct list_info_struct
* listing_tail
;
2162 fragS
* dummy_frag
= (fragS
*) xmalloc (sizeof (fragS
));
2164 memset (dummy_frag
, 0, sizeof (fragS
));
2165 dummy_frag
->fr_type
= rs_fill
;
2166 dummy_frag
->line
= listing_tail
;
2167 symbolP
= symbol_new (name
, undefined_section
, 0, dummy_frag
);
2168 dummy_frag
->fr_symbol
= symbolP
;
2172 symbolP
= symbol_new (name
, undefined_section
, 0, &zero_address_frag
);
2175 /* "set" symbols are local unless otherwise specified. */
2176 SF_SET_LOCAL (symbolP
);
2177 #endif /* OBJ_COFF */
2178 } /* Make a new symbol. */
2180 symbol_table_insert (symbolP
);
2185 && S_IS_DEFINED (symbolP
)
2186 && S_GET_SEGMENT (symbolP
) != reg_section
)
2187 as_bad (_("symbol `%s' already defined"), S_GET_NAME (symbolP
));
2189 pseudo_set (symbolP
);
2191 demand_empty_rest_of_line ();
2193 /* XXX Now we come to the Thumb specific bit of code. */
2195 THUMB_SET_FUNC (symbolP
, 1);
2196 ARM_SET_THUMB (symbolP
, 1);
2197 #if defined OBJ_ELF || defined OBJ_COFF
2198 ARM_SET_INTERWORK (symbolP
, support_interwork
);
2202 /* If we change section we must dump the literal pool first. */
2208 if (now_seg
!= text_section
)
2212 obj_elf_text (ignore
);
2222 if (flag_readonly_data_in_text
)
2224 if (now_seg
!= text_section
)
2227 else if (now_seg
!= data_section
)
2231 obj_elf_data (ignore
);
2239 arm_s_section (ignore
)
2244 obj_elf_section (ignore
);
2249 opcode_select (width
)
2257 if (! (cpu_variant
& ARM_EXT_V4T
))
2258 as_bad (_("selected processor does not support THUMB opcodes"));
2261 /* No need to force the alignment, since we will have been
2262 coming from ARM mode, which is word-aligned. */
2263 record_alignment (now_seg
, 1);
2270 if ((cpu_variant
& ARM_ANY
) == ARM_EXT_V4T
)
2271 as_bad (_("selected processor does not support ARM opcodes"));
2276 frag_align (2, 0, 0);
2278 record_alignment (now_seg
, 1);
2283 as_bad (_("invalid instruction size selected (%d)"), width
);
2289 int ignore ATTRIBUTE_UNUSED
;
2292 demand_empty_rest_of_line ();
2297 int ignore ATTRIBUTE_UNUSED
;
2300 demand_empty_rest_of_line ();
2305 int unused ATTRIBUTE_UNUSED
;
2309 temp
= get_absolute_expression ();
2314 opcode_select (temp
);
2318 as_bad (_("invalid operand to .code directive (%d) (expecting 16 or 32)"), temp
);
2326 skip_whitespace (str
);
2329 inst
.error
= _("Garbage following instruction");
2333 skip_past_comma (str
)
2336 char * p
= * str
, c
;
2339 while ((c
= *p
) == ' ' || c
== ',')
2342 if (c
== ',' && comma
++)
2350 return comma
? SUCCESS
: FAIL
;
2353 /* A standard register must be given at this point.
2354 SHIFT is the place to put it in inst.instruction.
2355 Restores input start point on error.
2356 Returns the reg#, or FAIL. */
2359 reg_required_here (str
, shift
)
2363 static char buff
[128]; /* XXX */
2365 char * start
= * str
;
2367 if ((reg
= arm_reg_parse (str
)) != FAIL
&& int_register (reg
))
2370 inst
.instruction
|= reg
<< shift
;
2374 /* Restore the start point, we may have got a reg of the wrong class. */
2377 /* In the few cases where we might be able to accept something else
2378 this error can be overridden. */
2379 sprintf (buff
, _("Register expected, not '%.100s'"), start
);
2385 static const struct asm_psr
*
2387 register char ** ccp
;
2389 char * start
= * ccp
;
2392 const struct asm_psr
* psr
;
2396 /* Skip to the end of the next word in the input stream. */
2401 while (ISALPHA (c
) || c
== '_');
2403 /* Terminate the word. */
2406 /* CPSR's and SPSR's can now be lowercase. This is just a convenience
2407 feature for ease of use and backwards compatibility. */
2408 if (!strncmp (start
, "cpsr", 4))
2409 strncpy (start
, "CPSR", 4);
2410 else if (!strncmp (start
, "spsr", 4))
2411 strncpy (start
, "SPSR", 4);
2413 /* Now locate the word in the psr hash table. */
2414 psr
= (const struct asm_psr
*) hash_find (arm_psr_hsh
, start
);
2416 /* Restore the input stream. */
2419 /* If we found a valid match, advance the
2420 stream pointer past the end of the word. */
2426 /* Parse the input looking for a PSR flag. */
2429 psr_required_here (str
)
2432 char * start
= * str
;
2433 const struct asm_psr
* psr
;
2435 psr
= arm_psr_parse (str
);
2439 /* If this is the SPSR that is being modified, set the R bit. */
2441 inst
.instruction
|= SPSR_BIT
;
2443 /* Set the psr flags in the MSR instruction. */
2444 inst
.instruction
|= psr
->field
<< PSR_SHIFT
;
2449 /* In the few cases where we might be able to accept
2450 something else this error can be overridden. */
2451 inst
.error
= _("flag for {c}psr instruction expected");
2453 /* Restore the start point. */
2459 co_proc_number (str
)
2462 int processor
, pchar
;
2464 skip_whitespace (* str
);
2466 /* The data sheet seems to imply that just a number on its own is valid
2467 here, but the RISC iX assembler seems to accept a prefix 'p'. We will
2469 if (**str
== 'p' || **str
== 'P')
2473 if (pchar
>= '0' && pchar
<= '9')
2475 processor
= pchar
- '0';
2476 if (**str
>= '0' && **str
<= '9')
2478 processor
= processor
* 10 + *(*str
)++ - '0';
2481 inst
.error
= _("Illegal co-processor number");
2488 inst
.error
= _("Bad or missing co-processor number");
2492 inst
.instruction
|= processor
<< 8;
2497 cp_opc_expr (str
, where
, length
)
2504 skip_whitespace (* str
);
2506 memset (&expr
, '\0', sizeof (expr
));
2508 if (my_get_expression (&expr
, str
))
2510 if (expr
.X_op
!= O_constant
)
2512 inst
.error
= _("bad or missing expression");
2516 if ((expr
.X_add_number
& ((1 << length
) - 1)) != expr
.X_add_number
)
2518 inst
.error
= _("immediate co-processor expression too large");
2522 inst
.instruction
|= expr
.X_add_number
<< where
;
2527 cp_reg_required_here (str
, where
)
2532 char * start
= *str
;
2534 if ((reg
= arm_reg_parse (str
)) != FAIL
&& cp_register (reg
))
2537 inst
.instruction
|= reg
<< where
;
2541 /* In the few cases where we might be able to accept something else
2542 this error can be overridden. */
2543 inst
.error
= _("Co-processor register expected");
2545 /* Restore the start point. */
2551 fp_reg_required_here (str
, where
)
2556 char * start
= * str
;
2558 if ((reg
= arm_reg_parse (str
)) != FAIL
&& fp_register (reg
))
2561 inst
.instruction
|= reg
<< where
;
2565 /* In the few cases where we might be able to accept something else
2566 this error can be overridden. */
2567 inst
.error
= _("Floating point register expected");
2569 /* Restore the start point. */
2575 cp_address_offset (str
)
2580 skip_whitespace (* str
);
2582 if (! is_immediate_prefix (**str
))
2584 inst
.error
= _("immediate expression expected");
2590 if (my_get_expression (& inst
.reloc
.exp
, str
))
2593 if (inst
.reloc
.exp
.X_op
== O_constant
)
2595 offset
= inst
.reloc
.exp
.X_add_number
;
2599 inst
.error
= _("co-processor address must be word aligned");
2603 if (offset
> 1023 || offset
< -1023)
2605 inst
.error
= _("offset too large");
2610 inst
.instruction
|= INDEX_UP
;
2614 inst
.instruction
|= offset
>> 2;
2617 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM
;
2623 cp_address_required_here (str
)
2635 skip_whitespace (p
);
2637 if ((reg
= reg_required_here (& p
, 16)) == FAIL
)
2640 skip_whitespace (p
);
2646 if (skip_past_comma (& p
) == SUCCESS
)
2649 write_back
= WRITE_BACK
;
2653 inst
.error
= _("pc may not be used in post-increment");
2657 if (cp_address_offset (& p
) == FAIL
)
2661 pre_inc
= PRE_INDEX
| INDEX_UP
;
2665 /* '['Rn, #expr']'[!] */
2667 if (skip_past_comma (& p
) == FAIL
)
2669 inst
.error
= _("pre-indexed expression expected");
2673 pre_inc
= PRE_INDEX
;
2675 if (cp_address_offset (& p
) == FAIL
)
2678 skip_whitespace (p
);
2682 inst
.error
= _("missing ]");
2686 skip_whitespace (p
);
2692 inst
.error
= _("pc may not be used with write-back");
2697 write_back
= WRITE_BACK
;
2703 if (my_get_expression (&inst
.reloc
.exp
, &p
))
2706 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM
;
2707 inst
.reloc
.exp
.X_add_number
-= 8; /* PC rel adjust. */
2708 inst
.reloc
.pc_rel
= 1;
2709 inst
.instruction
|= (REG_PC
<< 16);
2710 pre_inc
= PRE_INDEX
;
2713 inst
.instruction
|= write_back
| pre_inc
;
2719 do_empty (str
, flags
)
2721 unsigned long flags
;
2723 /* Do nothing really. */
2724 inst
.instruction
|= flags
; /* This is pointless. */
2732 unsigned long flags
;
2736 /* Only one syntax. */
2737 skip_whitespace (str
);
2739 if (reg_required_here (&str
, 12) == FAIL
)
2741 inst
.error
= BAD_ARGS
;
2745 if (skip_past_comma (&str
) == FAIL
)
2747 inst
.error
= _("comma expected after register name");
2751 skip_whitespace (str
);
2753 if ( strcmp (str
, "CPSR") == 0
2754 || strcmp (str
, "SPSR") == 0
2755 /* Lower case versions for backwards compatability. */
2756 || strcmp (str
, "cpsr") == 0
2757 || strcmp (str
, "spsr") == 0)
2760 /* This is for backwards compatability with older toolchains. */
2761 else if ( strcmp (str
, "cpsr_all") == 0
2762 || strcmp (str
, "spsr_all") == 0)
2766 inst
.error
= _("{C|S}PSR expected");
2770 if (* str
== 's' || * str
== 'S')
2771 inst
.instruction
|= SPSR_BIT
;
2774 inst
.instruction
|= flags
;
2778 /* Two possible forms:
2779 "{C|S}PSR_<field>, Rm",
2780 "{C|S}PSR_f, #expression". */
2785 unsigned long flags
;
2787 skip_whitespace (str
);
2789 if (psr_required_here (& str
) == FAIL
)
2792 if (skip_past_comma (& str
) == FAIL
)
2794 inst
.error
= _("comma missing after psr flags");
2798 skip_whitespace (str
);
2800 if (reg_required_here (& str
, 0) != FAIL
)
2803 inst
.instruction
|= flags
;
2808 if (! is_immediate_prefix (* str
))
2811 _("only a register or immediate value can follow a psr flag");
2818 if (my_get_expression (& inst
.reloc
.exp
, & str
))
2821 _("only a register or immediate value can follow a psr flag");
2825 #if 0 /* The first edition of the ARM architecture manual stated that
2826 writing anything other than the flags with an immediate operation
2827 had UNPREDICTABLE effects. This constraint was removed in the
2828 second edition of the specification. */
2829 if ((cpu_variant
& ARM_EXT_V5
) != ARM_EXT_V5
2830 && inst
.instruction
& ((PSR_c
| PSR_x
| PSR_s
) << PSR_SHIFT
))
2832 inst
.error
= _("immediate value cannot be used to set this field");
2837 flags
|= INST_IMMEDIATE
;
2839 if (inst
.reloc
.exp
.X_add_symbol
)
2841 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
2842 inst
.reloc
.pc_rel
= 0;
2846 unsigned value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
2848 if (value
== (unsigned) FAIL
)
2850 inst
.error
= _("Invalid constant");
2854 inst
.instruction
|= value
;
2858 inst
.instruction
|= flags
;
2862 /* Long Multiply Parser
2863 UMULL RdLo, RdHi, Rm, Rs
2864 SMULL RdLo, RdHi, Rm, Rs
2865 UMLAL RdLo, RdHi, Rm, Rs
2866 SMLAL RdLo, RdHi, Rm, Rs. */
2869 do_mull (str
, flags
)
2871 unsigned long flags
;
2873 int rdlo
, rdhi
, rm
, rs
;
2875 /* Only one format "rdlo, rdhi, rm, rs". */
2876 skip_whitespace (str
);
2878 if ((rdlo
= reg_required_here (&str
, 12)) == FAIL
)
2880 inst
.error
= BAD_ARGS
;
2884 if (skip_past_comma (&str
) == FAIL
2885 || (rdhi
= reg_required_here (&str
, 16)) == FAIL
)
2887 inst
.error
= BAD_ARGS
;
2891 if (skip_past_comma (&str
) == FAIL
2892 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
2894 inst
.error
= BAD_ARGS
;
2898 /* rdhi, rdlo and rm must all be different. */
2899 if (rdlo
== rdhi
|| rdlo
== rm
|| rdhi
== rm
)
2900 as_tsktsk (_("rdhi, rdlo and rm must all be different"));
2902 if (skip_past_comma (&str
) == FAIL
2903 || (rs
= reg_required_here (&str
, 8)) == FAIL
)
2905 inst
.error
= BAD_ARGS
;
2909 if (rdhi
== REG_PC
|| rdhi
== REG_PC
|| rdhi
== REG_PC
|| rdhi
== REG_PC
)
2911 inst
.error
= BAD_PC
;
2915 inst
.instruction
|= flags
;
2923 unsigned long flags
;
2927 /* Only one format "rd, rm, rs". */
2928 skip_whitespace (str
);
2930 if ((rd
= reg_required_here (&str
, 16)) == FAIL
)
2932 inst
.error
= BAD_ARGS
;
2938 inst
.error
= BAD_PC
;
2942 if (skip_past_comma (&str
) == FAIL
2943 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
2945 inst
.error
= BAD_ARGS
;
2951 inst
.error
= BAD_PC
;
2956 as_tsktsk (_("rd and rm should be different in mul"));
2958 if (skip_past_comma (&str
) == FAIL
2959 || (rm
= reg_required_here (&str
, 8)) == FAIL
)
2961 inst
.error
= BAD_ARGS
;
2967 inst
.error
= BAD_PC
;
2971 inst
.instruction
|= flags
;
2979 unsigned long flags
;
2983 /* Only one format "rd, rm, rs, rn". */
2984 skip_whitespace (str
);
2986 if ((rd
= reg_required_here (&str
, 16)) == FAIL
)
2988 inst
.error
= BAD_ARGS
;
2994 inst
.error
= BAD_PC
;
2998 if (skip_past_comma (&str
) == FAIL
2999 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
3001 inst
.error
= BAD_ARGS
;
3007 inst
.error
= BAD_PC
;
3012 as_tsktsk (_("rd and rm should be different in mla"));
3014 if (skip_past_comma (&str
) == FAIL
3015 || (rd
= reg_required_here (&str
, 8)) == FAIL
3016 || skip_past_comma (&str
) == FAIL
3017 || (rm
= reg_required_here (&str
, 12)) == FAIL
)
3019 inst
.error
= BAD_ARGS
;
3023 if (rd
== REG_PC
|| rm
== REG_PC
)
3025 inst
.error
= BAD_PC
;
3029 inst
.instruction
|= flags
;
3034 /* Expects *str -> the characters "acc0", possibly with leading blanks.
3035 Advances *str to the next non-alphanumeric.
3036 Returns 0, or else FAIL (in which case sets inst.error).
3038 (In a future XScale, there may be accumulators other than zero.
3039 At that time this routine and its callers can be upgraded to suit.) */
3042 accum0_required_here (str
)
3045 static char buff
[128]; /* Note the address is taken. Hence, static. */
3048 int result
= 0; /* The accum number. */
3050 skip_whitespace (p
);
3052 *str
= p
; /* Advance caller's string pointer too. */
3057 *--p
= 0; /* Aap nul into input buffer at non-alnum. */
3059 if (! ( streq (*str
, "acc0") || streq (*str
, "ACC0")))
3061 sprintf (buff
, _("acc0 expected, not '%.100s'"), *str
);
3066 *p
= c
; /* Unzap. */
3067 *str
= p
; /* Caller's string pointer to after match. */
3071 /* Expects **str -> after a comma. May be leading blanks.
3072 Advances *str, recognizing a load mode, and setting inst.instruction.
3073 Returns rn, or else FAIL (in which case may set inst.error
3074 and not advance str)
3076 Note: doesn't know Rd, so no err checks that require such knowledge. */
3079 ld_mode_required_here (string
)
3082 char * str
= * string
;
3086 skip_whitespace (str
);
3092 skip_whitespace (str
);
3094 if ((rn
= reg_required_here (& str
, 16)) == FAIL
)
3097 skip_whitespace (str
);
3103 if (skip_past_comma (& str
) == SUCCESS
)
3105 /* [Rn],... (post inc) */
3106 if (ldst_extend_v4 (&str
) == FAIL
)
3111 skip_whitespace (str
);
3116 inst
.instruction
|= WRITE_BACK
;
3119 inst
.instruction
|= INDEX_UP
| HWOFFSET_IMM
;
3125 if (skip_past_comma (& str
) == FAIL
)
3127 inst
.error
= _("pre-indexed expression expected");
3133 if (ldst_extend_v4 (&str
) == FAIL
)
3136 skip_whitespace (str
);
3138 if (* str
++ != ']')
3140 inst
.error
= _("missing ]");
3144 skip_whitespace (str
);
3149 inst
.instruction
|= WRITE_BACK
;
3153 else if (* str
== '=') /* ldr's "r,=label" syntax */
3154 /* We should never reach here, because <text> = <expression> is
3155 caught gas/read.c read_a_source_file() as a .set operation. */
3157 else /* PC +- 8 bit immediate offset. */
3159 if (my_get_expression (& inst
.reloc
.exp
, & str
))
3162 inst
.instruction
|= HWOFFSET_IMM
; /* The I bit. */
3163 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
3164 inst
.reloc
.exp
.X_add_number
-= 8; /* PC rel adjust. */
3165 inst
.reloc
.pc_rel
= 1;
3166 inst
.instruction
|= (REG_PC
<< 16);
3172 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
3178 /* ARM V5E (El Segundo) signed-multiply-accumulate (argument parse)
3179 SMLAxy{cond} Rd,Rm,Rs,Rn
3180 SMLAWy{cond} Rd,Rm,Rs,Rn
3181 Error if any register is R15. */
3184 do_smla (str
, flags
)
3186 unsigned long flags
;
3190 skip_whitespace (str
);
3192 if ((rd
= reg_required_here (& str
, 16)) == FAIL
3193 || skip_past_comma (& str
) == FAIL
3194 || (rm
= reg_required_here (& str
, 0)) == FAIL
3195 || skip_past_comma (& str
) == FAIL
3196 || (rs
= reg_required_here (& str
, 8)) == FAIL
3197 || skip_past_comma (& str
) == FAIL
3198 || (rn
= reg_required_here (& str
, 12)) == FAIL
)
3199 inst
.error
= BAD_ARGS
;
3201 else if (rd
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
|| rn
== REG_PC
)
3202 inst
.error
= BAD_PC
;
3205 inst
.error
= BAD_FLAGS
;
3211 /* ARM V5E (El Segundo) signed-multiply-accumulate-long (argument parse)
3212 SMLALxy{cond} Rdlo,Rdhi,Rm,Rs
3213 Error if any register is R15.
3214 Warning if Rdlo == Rdhi. */
3217 do_smlal (str
, flags
)
3219 unsigned long flags
;
3221 int rdlo
, rdhi
, rm
, rs
;
3223 skip_whitespace (str
);
3225 if ((rdlo
= reg_required_here (& str
, 12)) == FAIL
3226 || skip_past_comma (& str
) == FAIL
3227 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
3228 || skip_past_comma (& str
) == FAIL
3229 || (rm
= reg_required_here (& str
, 0)) == FAIL
3230 || skip_past_comma (& str
) == FAIL
3231 || (rs
= reg_required_here (& str
, 8)) == FAIL
)
3233 inst
.error
= BAD_ARGS
;
3237 if (rdlo
== REG_PC
|| rdhi
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
)
3239 inst
.error
= BAD_PC
;
3244 as_tsktsk (_("rdhi and rdlo must be different"));
3247 inst
.error
= BAD_FLAGS
;
3252 /* ARM V5E (El Segundo) signed-multiply (argument parse)
3253 SMULxy{cond} Rd,Rm,Rs
3254 Error if any register is R15. */
3257 do_smul (str
, flags
)
3259 unsigned long flags
;
3263 skip_whitespace (str
);
3265 if ((rd
= reg_required_here (& str
, 16)) == FAIL
3266 || skip_past_comma (& str
) == FAIL
3267 || (rm
= reg_required_here (& str
, 0)) == FAIL
3268 || skip_past_comma (& str
) == FAIL
3269 || (rs
= reg_required_here (& str
, 8)) == FAIL
)
3270 inst
.error
= BAD_ARGS
;
3272 else if (rd
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
)
3273 inst
.error
= BAD_PC
;
3276 inst
.error
= BAD_FLAGS
;
3282 /* ARM V5E (El Segundo) saturating-add/subtract (argument parse)
3283 Q[D]{ADD,SUB}{cond} Rd,Rm,Rn
3284 Error if any register is R15. */
3287 do_qadd (str
, flags
)
3289 unsigned long flags
;
3293 skip_whitespace (str
);
3295 if ((rd
= reg_required_here (& str
, 12)) == FAIL
3296 || skip_past_comma (& str
) == FAIL
3297 || (rm
= reg_required_here (& str
, 0)) == FAIL
3298 || skip_past_comma (& str
) == FAIL
3299 || (rn
= reg_required_here (& str
, 16)) == FAIL
)
3300 inst
.error
= BAD_ARGS
;
3302 else if (rd
== REG_PC
|| rm
== REG_PC
|| rn
== REG_PC
)
3303 inst
.error
= BAD_PC
;
3306 inst
.error
= BAD_FLAGS
;
3312 /* ARM V5E (el Segundo)
3313 MCRRcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
3314 MRRCcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
3316 These are equivalent to the XScale instructions MAR and MRA,
3317 respectively, when coproc == 0, opcode == 0, and CRm == 0.
3319 Result unpredicatable if Rd or Rn is R15. */
3322 do_co_reg2c (str
, flags
)
3324 unsigned long flags
;
3328 skip_whitespace (str
);
3330 if (co_proc_number (& str
) == FAIL
)
3333 inst
.error
= BAD_ARGS
;
3337 if (skip_past_comma (& str
) == FAIL
3338 || cp_opc_expr (& str
, 4, 4) == FAIL
)
3341 inst
.error
= BAD_ARGS
;
3345 if (skip_past_comma (& str
) == FAIL
3346 || (rd
= reg_required_here (& str
, 12)) == FAIL
)
3349 inst
.error
= BAD_ARGS
;
3353 if (skip_past_comma (& str
) == FAIL
3354 || (rn
= reg_required_here (& str
, 16)) == FAIL
)
3357 inst
.error
= BAD_ARGS
;
3361 /* Unpredictable result if rd or rn is R15. */
3362 if (rd
== REG_PC
|| rn
== REG_PC
)
3364 (_("Warning: Instruction unpredictable when using r15"));
3366 if (skip_past_comma (& str
) == FAIL
3367 || cp_reg_required_here (& str
, 0) == FAIL
)
3370 inst
.error
= BAD_ARGS
;
3375 inst
.error
= BAD_COND
;
3380 /* ARM V5 count-leading-zeroes instruction (argument parse)
3381 CLZ{<cond>} <Rd>, <Rm>
3382 Condition defaults to COND_ALWAYS.
3383 Error if Rd or Rm are R15. */
3388 unsigned long flags
;
3398 skip_whitespace (str
);
3400 if (((rd
= reg_required_here (& str
, 12)) == FAIL
)
3401 || (skip_past_comma (& str
) == FAIL
)
3402 || ((rm
= reg_required_here (& str
, 0)) == FAIL
))
3403 inst
.error
= BAD_ARGS
;
3405 else if (rd
== REG_PC
|| rm
== REG_PC
)
3406 inst
.error
= BAD_PC
;
3412 /* ARM V5 (argument parse)
3413 LDC2{L} <coproc>, <CRd>, <addressing mode>
3414 STC2{L} <coproc>, <CRd>, <addressing mode>
3415 Instruction is not conditional, and has 0xf in the codition field.
3416 Otherwise, it's the same as LDC/STC. */
3419 do_lstc2 (str
, flags
)
3421 unsigned long flags
;
3424 inst
.error
= BAD_COND
;
3426 skip_whitespace (str
);
3428 if (co_proc_number (& str
) == FAIL
)
3431 inst
.error
= BAD_ARGS
;
3433 else if (skip_past_comma (& str
) == FAIL
3434 || cp_reg_required_here (& str
, 12) == FAIL
)
3437 inst
.error
= BAD_ARGS
;
3439 else if (skip_past_comma (& str
) == FAIL
3440 || cp_address_required_here (& str
) == FAIL
)
3443 inst
.error
= BAD_ARGS
;
3449 /* ARM V5 (argument parse)
3450 CDP2 <coproc>, <opcode_1>, <CRd>, <CRn>, <CRm>, <opcode_2>
3451 Instruction is not conditional, and has 0xf in the condition field.
3452 Otherwise, it's the same as CDP. */
3455 do_cdp2 (str
, flags
)
3457 unsigned long flags
;
3459 skip_whitespace (str
);
3461 if (co_proc_number (& str
) == FAIL
)
3464 inst
.error
= BAD_ARGS
;
3468 if (skip_past_comma (& str
) == FAIL
3469 || cp_opc_expr (& str
, 20,4) == FAIL
)
3472 inst
.error
= BAD_ARGS
;
3476 if (skip_past_comma (& str
) == FAIL
3477 || cp_reg_required_here (& str
, 12) == FAIL
)
3480 inst
.error
= BAD_ARGS
;
3484 if (skip_past_comma (& str
) == FAIL
3485 || cp_reg_required_here (& str
, 16) == FAIL
)
3488 inst
.error
= BAD_ARGS
;
3492 if (skip_past_comma (& str
) == FAIL
3493 || cp_reg_required_here (& str
, 0) == FAIL
)
3496 inst
.error
= BAD_ARGS
;
3500 if (skip_past_comma (& str
) == SUCCESS
)
3502 if (cp_opc_expr (& str
, 5, 3) == FAIL
)
3505 inst
.error
= BAD_ARGS
;
3511 inst
.error
= BAD_FLAGS
;
3516 /* ARM V5 (argument parse)
3517 MCR2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
3518 MRC2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
3519 Instruction is not conditional, and has 0xf in the condition field.
3520 Otherwise, it's the same as MCR/MRC. */
3523 do_co_reg2 (str
, flags
)
3525 unsigned long flags
;
3527 skip_whitespace (str
);
3529 if (co_proc_number (& str
) == FAIL
)
3532 inst
.error
= BAD_ARGS
;
3536 if (skip_past_comma (& str
) == FAIL
3537 || cp_opc_expr (& str
, 21, 3) == FAIL
)
3540 inst
.error
= BAD_ARGS
;
3544 if (skip_past_comma (& str
) == FAIL
3545 || reg_required_here (& str
, 12) == FAIL
)
3548 inst
.error
= BAD_ARGS
;
3552 if (skip_past_comma (& str
) == FAIL
3553 || cp_reg_required_here (& str
, 16) == FAIL
)
3556 inst
.error
= BAD_ARGS
;
3560 if (skip_past_comma (& str
) == FAIL
3561 || cp_reg_required_here (& str
, 0) == FAIL
)
3564 inst
.error
= BAD_ARGS
;
3568 if (skip_past_comma (& str
) == SUCCESS
)
3570 if (cp_opc_expr (& str
, 5, 3) == FAIL
)
3573 inst
.error
= BAD_ARGS
;
3579 inst
.error
= BAD_COND
;
3584 /* THUMB V5 breakpoint instruction (argument parse)
3592 unsigned long number
;
3594 skip_whitespace (str
);
3596 /* Allow optional leading '#'. */
3597 if (is_immediate_prefix (*str
))
3600 memset (& expr
, '\0', sizeof (expr
));
3601 if (my_get_expression (& expr
, & str
) || (expr
.X_op
!= O_constant
))
3603 inst
.error
= _("bad or missing expression");
3607 number
= expr
.X_add_number
;
3609 /* Check it fits an 8 bit unsigned. */
3610 if (number
!= (number
& 0xff))
3612 inst
.error
= _("immediate value out of range");
3616 inst
.instruction
|= number
;
3621 /* ARM V5 branch-link-exchange (argument parse) for BLX(1) only.
3622 Expects inst.instruction is set for BLX(1).
3623 Note: this is cloned from do_branch, and the reloc changed to be a
3624 new one that can cope with setting one extra bit (the H bit). */
3627 do_branch25 (str
, flags
)
3629 unsigned long flags ATTRIBUTE_UNUSED
;
3631 if (my_get_expression (& inst
.reloc
.exp
, & str
))
3638 /* ScottB: February 5, 1998 */
3639 /* Check to see of PLT32 reloc required for the instruction. */
3641 /* arm_parse_reloc() works on input_line_pointer.
3642 We actually want to parse the operands to the branch instruction
3643 passed in 'str'. Save the input pointer and restore it later. */
3644 save_in
= input_line_pointer
;
3645 input_line_pointer
= str
;
3647 if (inst
.reloc
.exp
.X_op
== O_symbol
3649 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32
)
3651 inst
.reloc
.type
= BFD_RELOC_ARM_PLT32
;
3652 inst
.reloc
.pc_rel
= 0;
3653 /* Modify str to point to after parsed operands, otherwise
3654 end_of_line() will complain about the (PLT) left in str. */
3655 str
= input_line_pointer
;
3659 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BLX
;
3660 inst
.reloc
.pc_rel
= 1;
3663 input_line_pointer
= save_in
;
3666 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BLX
;
3667 inst
.reloc
.pc_rel
= 1;
3668 #endif /* OBJ_ELF */
3673 /* ARM V5 branch-link-exchange instruction (argument parse)
3674 BLX <target_addr> ie BLX(1)
3675 BLX{<condition>} <Rm> ie BLX(2)
3676 Unfortunately, there are two different opcodes for this mnemonic.
3677 So, the insns[].value is not used, and the code here zaps values
3678 into inst.instruction.
3679 Also, the <target_addr> can be 25 bits, hence has its own reloc. */
3684 unsigned long flags
;
3695 skip_whitespace (mystr
);
3696 rm
= reg_required_here (& mystr
, 0);
3698 /* The above may set inst.error. Ignore his opinion. */
3703 /* Arg is a register.
3704 Use the condition code our caller put in inst.instruction.
3705 Pass ourselves off as a BX with a funny opcode. */
3706 inst
.instruction
|= 0x012fff30;
3711 /* This must be is BLX <target address>, no condition allowed. */
3712 if (inst
.instruction
!= COND_ALWAYS
)
3714 inst
.error
= BAD_COND
;
3718 inst
.instruction
= 0xfafffffe;
3720 /* Process like a B/BL, but with a different reloc.
3721 Note that B/BL expecte fffffe, not 0, offset in the opcode table. */
3722 do_branch25 (str
, flags
);
3726 /* ARM V5 Thumb BLX (argument parse)
3727 BLX <target_addr> which is BLX(1)
3728 BLX <Rm> which is BLX(2)
3729 Unfortunately, there are two different opcodes for this mnemonic.
3730 So, the tinsns[].value is not used, and the code here zaps values
3731 into inst.instruction. */
3740 skip_whitespace (mystr
);
3741 inst
.instruction
= 0x4780;
3743 /* Note that this call is to the ARM register recognizer. BLX(2)
3744 uses the ARM register space, not the Thumb one, so a call to
3745 thumb_reg() would be wrong. */
3746 rm
= reg_required_here (& mystr
, 3);
3751 /* It's BLX(2). The .instruction was zapped with rm & is final. */
3756 /* No ARM register. This must be BLX(1). Change the .instruction. */
3757 inst
.instruction
= 0xf7ffeffe;
3760 if (my_get_expression (& inst
.reloc
.exp
, & mystr
))
3763 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BLX
;
3764 inst
.reloc
.pc_rel
= 1;
3767 end_of_line (mystr
);
3770 /* ARM V5 breakpoint instruction (argument parse)
3771 BKPT <16 bit unsigned immediate>
3772 Instruction is not conditional.
3773 The bit pattern given in insns[] has the COND_ALWAYS condition,
3774 and it is an error if the caller tried to override that.
3775 Note "flags" is nonzero if a flag was supplied (which is an error). */
3778 do_bkpt (str
, flags
)
3780 unsigned long flags
;
3783 unsigned long number
;
3785 skip_whitespace (str
);
3787 /* Allow optional leading '#'. */
3788 if (is_immediate_prefix (* str
))
3791 memset (& expr
, '\0', sizeof (expr
));
3793 if (my_get_expression (& expr
, & str
) || (expr
.X_op
!= O_constant
))
3795 inst
.error
= _("bad or missing expression");
3799 number
= expr
.X_add_number
;
3801 /* Check it fits a 16 bit unsigned. */
3802 if (number
!= (number
& 0xffff))
3804 inst
.error
= _("immediate value out of range");
3808 /* Top 12 of 16 bits to bits 19:8. */
3809 inst
.instruction
|= (number
& 0xfff0) << 4;
3811 /* Bottom 4 of 16 bits to bits 3:0. */
3812 inst
.instruction
|= number
& 0xf;
3817 inst
.error
= BAD_FLAGS
;
3820 /* Xscale multiply-accumulate (argument parse)
3823 MIAxycc acc0,Rm,Rs. */
3828 unsigned long flags
;
3836 else if (accum0_required_here (& str
) == FAIL
)
3837 inst
.error
= ERR_NO_ACCUM
;
3839 else if (skip_past_comma (& str
) == FAIL
3840 || (rm
= reg_required_here (& str
, 0)) == FAIL
)
3841 inst
.error
= BAD_ARGS
;
3843 else if (skip_past_comma (& str
) == FAIL
3844 || (rs
= reg_required_here (& str
, 12)) == FAIL
)
3845 inst
.error
= BAD_ARGS
;
3847 /* inst.instruction has now been zapped with both rm and rs. */
3848 else if (rm
== REG_PC
|| rs
== REG_PC
)
3849 inst
.error
= BAD_PC
; /* Undefined result if rm or rs is R15. */
3855 /* Xscale move-accumulator-register (argument parse)
3857 MARcc acc0,RdLo,RdHi. */
3862 unsigned long flags
;
3869 else if (accum0_required_here (& str
) == FAIL
)
3870 inst
.error
= ERR_NO_ACCUM
;
3872 else if (skip_past_comma (& str
) == FAIL
3873 || (rdlo
= reg_required_here (& str
, 12)) == FAIL
)
3874 inst
.error
= BAD_ARGS
;
3876 else if (skip_past_comma (& str
) == FAIL
3877 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
)
3878 inst
.error
= BAD_ARGS
;
3880 /* inst.instruction has now been zapped with both rdlo and rdhi. */
3881 else if (rdlo
== REG_PC
|| rdhi
== REG_PC
)
3882 inst
.error
= BAD_PC
; /* Undefined result if rdlo or rdhi is R15. */
3888 /* Xscale move-register-accumulator (argument parse)
3890 MRAcc RdLo,RdHi,acc0. */
3895 unsigned long flags
;
3906 skip_whitespace (str
);
3908 if ((rdlo
= reg_required_here (& str
, 12)) == FAIL
)
3909 inst
.error
= BAD_ARGS
;
3911 else if (skip_past_comma (& str
) == FAIL
3912 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
)
3913 inst
.error
= BAD_ARGS
;
3915 else if (skip_past_comma (& str
) == FAIL
3916 || accum0_required_here (& str
) == FAIL
)
3917 inst
.error
= ERR_NO_ACCUM
;
3919 /* inst.instruction has now been zapped with both rdlo and rdhi. */
3920 else if (rdlo
== rdhi
)
3921 inst
.error
= BAD_ARGS
; /* Undefined result if 2 writes to same reg. */
3923 else if (rdlo
== REG_PC
|| rdhi
== REG_PC
)
3924 inst
.error
= BAD_PC
; /* Undefined result if rdlo or rdhi is R15. */
3929 /* ARMv5TE: Preload-Cache
3933 Syntactically, like LDR with B=1, W=0, L=1. */
3938 unsigned long flags
;
3948 skip_whitespace (str
);
3952 inst
.error
= _("'[' expected after PLD mnemonic");
3957 skip_whitespace (str
);
3959 if ((rd
= reg_required_here (& str
, 16)) == FAIL
)
3962 skip_whitespace (str
);
3968 skip_whitespace (str
);
3970 /* Post-indexed addressing is not allowed with PLD. */
3971 if (skip_past_comma (&str
) == SUCCESS
)
3974 = _("post-indexed expression used in preload instruction");
3977 else if (*str
== '!') /* [Rn]! */
3979 inst
.error
= _("writeback used in preload instruction");
3983 inst
.instruction
|= INDEX_UP
| PRE_INDEX
;
3985 else /* [Rn, ...] */
3987 if (skip_past_comma (& str
) == FAIL
)
3989 inst
.error
= _("pre-indexed expression expected");
3993 if (ldst_extend (&str
) == FAIL
)
3996 skip_whitespace (str
);
4000 inst
.error
= _("missing ]");
4005 skip_whitespace (str
);
4007 if (* str
== '!') /* [Rn]! */
4009 inst
.error
= _("writeback used in preload instruction");
4013 inst
.instruction
|= PRE_INDEX
;
4019 /* ARMv5TE load-consecutive (argument parse)
4026 do_ldrd (str
, flags
)
4028 unsigned long flags
;
4033 skip_whitespace (str
);
4035 if ((rd
= reg_required_here (& str
, 12)) == FAIL
)
4037 inst
.error
= BAD_ARGS
;
4041 if (skip_past_comma (& str
) == FAIL
4042 || (rn
= ld_mode_required_here (& str
)) == FAIL
)
4045 inst
.error
= BAD_ARGS
;
4049 /* inst.instruction has now been zapped with Rd and the addressing mode. */
4050 if (rd
& 1) /* Unpredictable result if Rd is odd. */
4052 inst
.error
= _("Destination register must be even");
4058 inst
.error
= _("r12 or r14 not allowed here");
4062 if (((rd
== rn
) || (rd
+ 1 == rn
))
4063 && ((inst
.instruction
& WRITE_BACK
)
4064 || (!(inst
.instruction
& PRE_INDEX
))))
4065 as_warn (_("pre/post-indexing used when modified address register is destination"));
4067 /* For an index-register load, the index register must not overlap the
4068 destination (even if not write-back). */
4069 if ((inst
.instruction
& V4_STR_BIT
) == 0
4070 && (inst
.instruction
& HWOFFSET_IMM
) == 0)
4072 int rm
= inst
.instruction
& 0x0000000f;
4074 if (rm
== rd
|| (rm
== rd
+ 1))
4075 as_warn (_("ldrd destination registers must not overlap index register"));
4081 /* Returns the index into fp_values of a floating point number,
4082 or -1 if not in the table. */
4085 my_get_float_expression (str
)
4088 LITTLENUM_TYPE words
[MAX_LITTLENUMS
];
4094 memset (words
, 0, MAX_LITTLENUMS
* sizeof (LITTLENUM_TYPE
));
4096 /* Look for a raw floating point number. */
4097 if ((save_in
= atof_ieee (*str
, 'x', words
)) != NULL
4098 && is_end_of_line
[(unsigned char) *save_in
])
4100 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
4102 for (j
= 0; j
< MAX_LITTLENUMS
; j
++)
4104 if (words
[j
] != fp_values
[i
][j
])
4108 if (j
== MAX_LITTLENUMS
)
4116 /* Try and parse a more complex expression, this will probably fail
4117 unless the code uses a floating point prefix (eg "0f"). */
4118 save_in
= input_line_pointer
;
4119 input_line_pointer
= *str
;
4120 if (expression (&exp
) == absolute_section
4121 && exp
.X_op
== O_big
4122 && exp
.X_add_number
< 0)
4124 /* FIXME: 5 = X_PRECISION, should be #define'd where we can use it.
4126 if (gen_to_words (words
, 5, (long) 15) == 0)
4128 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
4130 for (j
= 0; j
< MAX_LITTLENUMS
; j
++)
4132 if (words
[j
] != fp_values
[i
][j
])
4136 if (j
== MAX_LITTLENUMS
)
4138 *str
= input_line_pointer
;
4139 input_line_pointer
= save_in
;
4146 *str
= input_line_pointer
;
4147 input_line_pointer
= save_in
;
4151 /* Return true if anything in the expression is a bignum. */
4154 walk_no_bignums (sp
)
4157 if (symbol_get_value_expression (sp
)->X_op
== O_big
)
4160 if (symbol_get_value_expression (sp
)->X_add_symbol
)
4162 return (walk_no_bignums (symbol_get_value_expression (sp
)->X_add_symbol
)
4163 || (symbol_get_value_expression (sp
)->X_op_symbol
4164 && walk_no_bignums (symbol_get_value_expression (sp
)->X_op_symbol
)));
4171 my_get_expression (ep
, str
)
4178 save_in
= input_line_pointer
;
4179 input_line_pointer
= *str
;
4180 seg
= expression (ep
);
4183 if (seg
!= absolute_section
4184 && seg
!= text_section
4185 && seg
!= data_section
4186 && seg
!= bss_section
4187 && seg
!= undefined_section
)
4189 inst
.error
= _("bad_segment");
4190 *str
= input_line_pointer
;
4191 input_line_pointer
= save_in
;
4196 /* Get rid of any bignums now, so that we don't generate an error for which
4197 we can't establish a line number later on. Big numbers are never valid
4198 in instructions, which is where this routine is always called. */
4199 if (ep
->X_op
== O_big
4200 || (ep
->X_add_symbol
4201 && (walk_no_bignums (ep
->X_add_symbol
)
4203 && walk_no_bignums (ep
->X_op_symbol
)))))
4205 inst
.error
= _("Invalid constant");
4206 *str
= input_line_pointer
;
4207 input_line_pointer
= save_in
;
4211 *str
= input_line_pointer
;
4212 input_line_pointer
= save_in
;
4216 /* UNRESTRICT should be one if <shift> <register> is permitted for this
4220 decode_shift (str
, unrestrict
)
4224 const struct asm_shift_name
* shift
;
4228 skip_whitespace (* str
);
4230 for (p
= * str
; ISALPHA (* p
); p
++)
4235 inst
.error
= _("Shift expression expected");
4241 shift
= (const struct asm_shift_name
*) hash_find (arm_shift_hsh
, * str
);
4246 inst
.error
= _("Shift expression expected");
4250 assert (shift
->properties
->index
== shift_properties
[shift
->properties
->index
].index
);
4252 if (shift
->properties
->index
== SHIFT_RRX
)
4255 inst
.instruction
|= shift
->properties
->bit_field
;
4259 skip_whitespace (p
);
4261 if (unrestrict
&& reg_required_here (& p
, 8) != FAIL
)
4263 inst
.instruction
|= shift
->properties
->bit_field
| SHIFT_BY_REG
;
4267 else if (! is_immediate_prefix (* p
))
4269 inst
.error
= (unrestrict
4270 ? _("shift requires register or #expression")
4271 : _("shift requires #expression"));
4279 if (my_get_expression (& inst
.reloc
.exp
, & p
))
4282 /* Validate some simple #expressions. */
4283 if (inst
.reloc
.exp
.X_op
== O_constant
)
4285 unsigned num
= inst
.reloc
.exp
.X_add_number
;
4287 /* Reject operations greater than 32. */
4289 /* Reject a shift of 0 unless the mode allows it. */
4290 || (num
== 0 && shift
->properties
->allows_0
== 0)
4291 /* Reject a shift of 32 unless the mode allows it. */
4292 || (num
== 32 && shift
->properties
->allows_32
== 0)
4295 /* As a special case we allow a shift of zero for
4296 modes that do not support it to be recoded as an
4297 logical shift left of zero (ie nothing). We warn
4298 about this though. */
4301 as_warn (_("Shift of 0 ignored."));
4302 shift
= & shift_names
[0];
4303 assert (shift
->properties
->index
== SHIFT_LSL
);
4307 inst
.error
= _("Invalid immediate shift");
4312 /* Shifts of 32 are encoded as 0, for those shifts that
4317 inst
.instruction
|= (num
<< 7) | shift
->properties
->bit_field
;
4321 inst
.reloc
.type
= BFD_RELOC_ARM_SHIFT_IMM
;
4322 inst
.reloc
.pc_rel
= 0;
4323 inst
.instruction
|= shift
->properties
->bit_field
;
4330 /* Do those data_ops which can take a negative immediate constant
4331 by altering the instuction. A bit of a hack really.
4335 by inverting the second operand, and
4338 by negating the second operand. */
4341 negate_data_op (instruction
, value
)
4342 unsigned long * instruction
;
4343 unsigned long value
;
4346 unsigned long negated
, inverted
;
4348 negated
= validate_immediate (-value
);
4349 inverted
= validate_immediate (~value
);
4351 op
= (*instruction
>> DATA_OP_SHIFT
) & 0xf;
4354 /* First negates. */
4355 case OPCODE_SUB
: /* ADD <-> SUB */
4356 new_inst
= OPCODE_ADD
;
4361 new_inst
= OPCODE_SUB
;
4365 case OPCODE_CMP
: /* CMP <-> CMN */
4366 new_inst
= OPCODE_CMN
;
4371 new_inst
= OPCODE_CMP
;
4375 /* Now Inverted ops. */
4376 case OPCODE_MOV
: /* MOV <-> MVN */
4377 new_inst
= OPCODE_MVN
;
4382 new_inst
= OPCODE_MOV
;
4386 case OPCODE_AND
: /* AND <-> BIC */
4387 new_inst
= OPCODE_BIC
;
4392 new_inst
= OPCODE_AND
;
4396 case OPCODE_ADC
: /* ADC <-> SBC */
4397 new_inst
= OPCODE_SBC
;
4402 new_inst
= OPCODE_ADC
;
4406 /* We cannot do anything. */
4411 if (value
== (unsigned) FAIL
)
4414 *instruction
&= OPCODE_MASK
;
4415 *instruction
|= new_inst
<< DATA_OP_SHIFT
;
4426 skip_whitespace (* str
);
4428 if (reg_required_here (str
, 0) != FAIL
)
4430 if (skip_past_comma (str
) == SUCCESS
)
4431 /* Shift operation on register. */
4432 return decode_shift (str
, NO_SHIFT_RESTRICT
);
4438 /* Immediate expression. */
4439 if (is_immediate_prefix (**str
))
4444 if (my_get_expression (&inst
.reloc
.exp
, str
))
4447 if (inst
.reloc
.exp
.X_add_symbol
)
4449 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
4450 inst
.reloc
.pc_rel
= 0;
4454 if (skip_past_comma (str
) == SUCCESS
)
4456 /* #x, y -- ie explicit rotation by Y. */
4457 if (my_get_expression (&expr
, str
))
4460 if (expr
.X_op
!= O_constant
)
4462 inst
.error
= _("Constant expression expected");
4466 /* Rotate must be a multiple of 2. */
4467 if (((unsigned) expr
.X_add_number
) > 30
4468 || (expr
.X_add_number
& 1) != 0
4469 || ((unsigned) inst
.reloc
.exp
.X_add_number
) > 255)
4471 inst
.error
= _("Invalid constant");
4474 inst
.instruction
|= INST_IMMEDIATE
;
4475 inst
.instruction
|= inst
.reloc
.exp
.X_add_number
;
4476 inst
.instruction
|= expr
.X_add_number
<< 7;
4480 /* Implicit rotation, select a suitable one. */
4481 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
4485 /* Can't be done. Perhaps the code reads something like
4486 "add Rd, Rn, #-n", where "sub Rd, Rn, #n" would be OK. */
4487 if ((value
= negate_data_op (&inst
.instruction
,
4488 inst
.reloc
.exp
.X_add_number
))
4491 inst
.error
= _("Invalid constant");
4496 inst
.instruction
|= value
;
4499 inst
.instruction
|= INST_IMMEDIATE
;
4504 inst
.error
= _("Register or shift expression expected");
4513 skip_whitespace (* str
);
4515 if (fp_reg_required_here (str
, 0) != FAIL
)
4519 /* Immediate expression. */
4520 if (*((*str
)++) == '#')
4526 skip_whitespace (* str
);
4528 /* First try and match exact strings, this is to guarantee
4529 that some formats will work even for cross assembly. */
4531 for (i
= 0; fp_const
[i
]; i
++)
4533 if (strncmp (*str
, fp_const
[i
], strlen (fp_const
[i
])) == 0)
4537 *str
+= strlen (fp_const
[i
]);
4538 if (is_end_of_line
[(unsigned char) **str
])
4540 inst
.instruction
|= i
+ 8;
4547 /* Just because we didn't get a match doesn't mean that the
4548 constant isn't valid, just that it is in a format that we
4549 don't automatically recognize. Try parsing it with
4550 the standard expression routines. */
4551 if ((i
= my_get_float_expression (str
)) >= 0)
4553 inst
.instruction
|= i
+ 8;
4557 inst
.error
= _("Invalid floating point immediate expression");
4561 _("Floating point register or immediate expression expected");
4567 do_arit (str
, flags
)
4569 unsigned long flags
;
4571 skip_whitespace (str
);
4573 if (reg_required_here (&str
, 12) == FAIL
4574 || skip_past_comma (&str
) == FAIL
4575 || reg_required_here (&str
, 16) == FAIL
4576 || skip_past_comma (&str
) == FAIL
4577 || data_op2 (&str
) == FAIL
)
4580 inst
.error
= BAD_ARGS
;
4584 inst
.instruction
|= flags
;
4592 unsigned long flags
;
4594 /* This is a pseudo-op of the form "adr rd, label" to be converted
4595 into a relative address of the form "add rd, pc, #label-.-8". */
4596 skip_whitespace (str
);
4598 if (reg_required_here (&str
, 12) == FAIL
4599 || skip_past_comma (&str
) == FAIL
4600 || my_get_expression (&inst
.reloc
.exp
, &str
))
4603 inst
.error
= BAD_ARGS
;
4607 /* Frag hacking will turn this into a sub instruction if the offset turns
4608 out to be negative. */
4609 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
4610 inst
.reloc
.exp
.X_add_number
-= 8; /* PC relative adjust. */
4611 inst
.reloc
.pc_rel
= 1;
4617 do_adrl (str
, flags
)
4619 unsigned long flags
;
4621 /* This is a pseudo-op of the form "adrl rd, label" to be converted
4622 into a relative address of the form:
4623 add rd, pc, #low(label-.-8)"
4624 add rd, rd, #high(label-.-8)" */
4626 skip_whitespace (str
);
4628 if (reg_required_here (&str
, 12) == FAIL
4629 || skip_past_comma (&str
) == FAIL
4630 || my_get_expression (&inst
.reloc
.exp
, &str
))
4633 inst
.error
= BAD_ARGS
;
4639 /* Frag hacking will turn this into a sub instruction if the offset turns
4640 out to be negative. */
4641 inst
.reloc
.type
= BFD_RELOC_ARM_ADRL_IMMEDIATE
;
4642 inst
.reloc
.exp
.X_add_number
-= 8; /* PC relative adjust */
4643 inst
.reloc
.pc_rel
= 1;
4644 inst
.size
= INSN_SIZE
* 2;
4652 unsigned long flags
;
4654 skip_whitespace (str
);
4656 if (reg_required_here (&str
, 16) == FAIL
)
4659 inst
.error
= BAD_ARGS
;
4663 if (skip_past_comma (&str
) == FAIL
4664 || data_op2 (&str
) == FAIL
)
4667 inst
.error
= BAD_ARGS
;
4671 inst
.instruction
|= flags
;
4679 unsigned long flags
;
4681 skip_whitespace (str
);
4683 if (reg_required_here (&str
, 12) == FAIL
)
4686 inst
.error
= BAD_ARGS
;
4690 if (skip_past_comma (&str
) == FAIL
4691 || data_op2 (&str
) == FAIL
)
4694 inst
.error
= BAD_ARGS
;
4698 inst
.instruction
|= flags
;
4714 if (my_get_expression (& inst
.reloc
.exp
, str
))
4717 if (inst
.reloc
.exp
.X_op
== O_constant
)
4719 int value
= inst
.reloc
.exp
.X_add_number
;
4721 if (value
< -4095 || value
> 4095)
4723 inst
.error
= _("address offset too large");
4733 inst
.instruction
|= add
| value
;
4737 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM
;
4738 inst
.reloc
.pc_rel
= 0;
4751 if (reg_required_here (str
, 0) == FAIL
)
4754 inst
.instruction
|= add
| OFFSET_REG
;
4755 if (skip_past_comma (str
) == SUCCESS
)
4756 return decode_shift (str
, SHIFT_RESTRICT
);
4763 do_ldst (str
, flags
)
4765 unsigned long flags
;
4771 skip_whitespace (str
);
4773 if ((conflict_reg
= reg_required_here (&str
, 12)) == FAIL
)
4776 inst
.error
= BAD_ARGS
;
4780 if (skip_past_comma (&str
) == FAIL
)
4782 inst
.error
= _("Address expected");
4794 skip_whitespace (str
);
4796 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
4799 /* Conflicts can occur on stores as well as loads. */
4800 conflict_reg
= (conflict_reg
== reg
);
4802 skip_whitespace (str
);
4808 if (skip_past_comma (&str
) == SUCCESS
)
4810 /* [Rn],... (post inc) */
4811 if (ldst_extend (&str
) == FAIL
)
4814 as_warn (_("%s register same as write-back base"),
4815 ((inst
.instruction
& LOAD_BIT
)
4816 ? _("destination") : _("source")));
4821 skip_whitespace (str
);
4826 as_warn (_("%s register same as write-back base"),
4827 ((inst
.instruction
& LOAD_BIT
)
4828 ? _("destination") : _("source")));
4830 inst
.instruction
|= WRITE_BACK
;
4833 inst
.instruction
|= INDEX_UP
;
4840 if (skip_past_comma (&str
) == FAIL
)
4842 inst
.error
= _("pre-indexed expression expected");
4847 if (ldst_extend (&str
) == FAIL
)
4850 skip_whitespace (str
);
4854 inst
.error
= _("missing ]");
4858 skip_whitespace (str
);
4863 as_warn (_("%s register same as write-back base"),
4864 ((inst
.instruction
& LOAD_BIT
)
4865 ? _("destination") : _("source")));
4867 inst
.instruction
|= WRITE_BACK
;
4871 else if (*str
== '=')
4873 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
4876 skip_whitespace (str
);
4878 if (my_get_expression (&inst
.reloc
.exp
, &str
))
4881 if (inst
.reloc
.exp
.X_op
!= O_constant
4882 && inst
.reloc
.exp
.X_op
!= O_symbol
)
4884 inst
.error
= _("Constant expression expected");
4888 if (inst
.reloc
.exp
.X_op
== O_constant
4889 && (value
= validate_immediate (inst
.reloc
.exp
.X_add_number
)) != FAIL
)
4891 /* This can be done with a mov instruction. */
4892 inst
.instruction
&= LITERAL_MASK
;
4893 inst
.instruction
|= INST_IMMEDIATE
| (OPCODE_MOV
<< DATA_OP_SHIFT
);
4894 inst
.instruction
|= (value
& 0xfff);
4900 /* Insert into literal pool. */
4901 if (add_to_lit_pool () == FAIL
)
4904 inst
.error
= _("literal pool insertion failed");
4908 /* Change the instruction exp to point to the pool. */
4909 inst
.reloc
.type
= BFD_RELOC_ARM_LITERAL
;
4910 inst
.reloc
.pc_rel
= 1;
4911 inst
.instruction
|= (REG_PC
<< 16);
4917 if (my_get_expression (&inst
.reloc
.exp
, &str
))
4920 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM
;
4922 /* PC rel adjust. */
4923 inst
.reloc
.exp
.X_add_number
-= 8;
4925 inst
.reloc
.pc_rel
= 1;
4926 inst
.instruction
|= (REG_PC
<< 16);
4930 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
4936 do_ldstt (str
, flags
)
4938 unsigned long flags
;
4942 skip_whitespace (str
);
4944 if ((conflict_reg
= reg_required_here (& str
, 12)) == FAIL
)
4947 inst
.error
= BAD_ARGS
;
4951 if (skip_past_comma (& str
) == FAIL
)
4953 inst
.error
= _("Address expected");
4963 skip_whitespace (str
);
4965 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
4968 /* ldrt/strt always use post-indexed addressing, so if the base is
4969 the same as Rd, we warn. */
4970 if (conflict_reg
== reg
)
4971 as_warn (_("%s register same as write-back base"),
4972 ((inst
.instruction
& LOAD_BIT
)
4973 ? _("destination") : _("source")));
4975 skip_whitespace (str
);
4981 if (skip_past_comma (&str
) == SUCCESS
)
4983 /* [Rn],... (post inc) */
4984 if (ldst_extend (&str
) == FAIL
)
4990 skip_whitespace (str
);
4992 /* Skip a write-back '!'. */
4996 inst
.instruction
|= INDEX_UP
;
5001 inst
.error
= _("post-indexed expression expected");
5007 inst
.error
= _("post-indexed expression expected");
5016 ldst_extend_v4 (str
)
5026 if (my_get_expression (& inst
.reloc
.exp
, str
))
5029 if (inst
.reloc
.exp
.X_op
== O_constant
)
5031 int value
= inst
.reloc
.exp
.X_add_number
;
5033 if (value
< -255 || value
> 255)
5035 inst
.error
= _("address offset too large");
5045 /* Halfword and signextension instructions have the
5046 immediate value split across bits 11..8 and bits 3..0. */
5047 inst
.instruction
|= (add
| HWOFFSET_IMM
5048 | ((value
>> 4) << 8) | (value
& 0xF));
5052 inst
.instruction
|= HWOFFSET_IMM
;
5053 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
5054 inst
.reloc
.pc_rel
= 0;
5067 if (reg_required_here (str
, 0) == FAIL
)
5070 inst
.instruction
|= add
;
5075 /* Halfword and signed-byte load/store operations. */
5077 do_ldstv4 (str
, flags
)
5079 unsigned long flags
;
5085 skip_whitespace (str
);
5087 if ((conflict_reg
= reg_required_here (& str
, 12)) == FAIL
)
5090 inst
.error
= BAD_ARGS
;
5094 if (skip_past_comma (& str
) == FAIL
)
5096 inst
.error
= _("Address expected");
5106 skip_whitespace (str
);
5108 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
5111 /* Conflicts can occur on stores as well as loads. */
5112 conflict_reg
= (conflict_reg
== reg
);
5114 skip_whitespace (str
);
5120 if (skip_past_comma (&str
) == SUCCESS
)
5122 /* [Rn],... (post inc) */
5123 if (ldst_extend_v4 (&str
) == FAIL
)
5126 as_warn (_("%s register same as write-back base"),
5127 ((inst
.instruction
& LOAD_BIT
)
5128 ? _("destination") : _("source")));
5133 inst
.instruction
|= HWOFFSET_IMM
;
5135 skip_whitespace (str
);
5140 as_warn (_("%s register same as write-back base"),
5141 ((inst
.instruction
& LOAD_BIT
)
5142 ? _("destination") : _("source")));
5144 inst
.instruction
|= WRITE_BACK
;
5147 inst
.instruction
|= INDEX_UP
;
5154 if (skip_past_comma (&str
) == FAIL
)
5156 inst
.error
= _("pre-indexed expression expected");
5161 if (ldst_extend_v4 (&str
) == FAIL
)
5164 skip_whitespace (str
);
5168 inst
.error
= _("missing ]");
5172 skip_whitespace (str
);
5177 as_warn (_("%s register same as write-back base"),
5178 ((inst
.instruction
& LOAD_BIT
)
5179 ? _("destination") : _("source")));
5181 inst
.instruction
|= WRITE_BACK
;
5185 else if (*str
== '=')
5187 /* XXX Does this work correctly for half-word/byte ops? */
5188 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
5191 skip_whitespace (str
);
5193 if (my_get_expression (&inst
.reloc
.exp
, &str
))
5196 if (inst
.reloc
.exp
.X_op
!= O_constant
5197 && inst
.reloc
.exp
.X_op
!= O_symbol
)
5199 inst
.error
= _("Constant expression expected");
5203 if (inst
.reloc
.exp
.X_op
== O_constant
)
5205 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
5209 /* This can be done with a mov instruction. */
5210 inst
.instruction
&= LITERAL_MASK
;
5211 inst
.instruction
|= INST_IMMEDIATE
| (OPCODE_MOV
<< DATA_OP_SHIFT
);
5212 inst
.instruction
|= value
& 0xfff;
5217 value
= validate_immediate (~ inst
.reloc
.exp
.X_add_number
);
5221 /* This can be done with a mvn instruction. */
5222 inst
.instruction
&= LITERAL_MASK
;
5223 inst
.instruction
|= INST_IMMEDIATE
| (OPCODE_MVN
<< DATA_OP_SHIFT
);
5224 inst
.instruction
|= value
& 0xfff;
5230 /* Insert into literal pool. */
5231 if (add_to_lit_pool () == FAIL
)
5234 inst
.error
= _("literal pool insertion failed");
5238 /* Change the instruction exp to point to the pool. */
5239 inst
.instruction
|= HWOFFSET_IMM
;
5240 inst
.reloc
.type
= BFD_RELOC_ARM_HWLITERAL
;
5241 inst
.reloc
.pc_rel
= 1;
5242 inst
.instruction
|= (REG_PC
<< 16);
5247 if (my_get_expression (&inst
.reloc
.exp
, &str
))
5250 inst
.instruction
|= HWOFFSET_IMM
;
5251 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
5253 /* PC rel adjust. */
5254 inst
.reloc
.exp
.X_add_number
-= 8;
5256 inst
.reloc
.pc_rel
= 1;
5257 inst
.instruction
|= (REG_PC
<< 16);
5261 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
5270 char * str
= * strp
;
5274 /* We come back here if we get ranges concatenated by '+' or '|'. */
5289 skip_whitespace (str
);
5291 if ((reg
= reg_required_here (& str
, -1)) == FAIL
)
5300 inst
.error
= _("Bad range in register list");
5304 for (i
= cur_reg
+ 1; i
< reg
; i
++)
5306 if (range
& (1 << i
))
5308 (_("Warning: Duplicated register (r%d) in register list"),
5316 if (range
& (1 << reg
))
5317 as_tsktsk (_("Warning: Duplicated register (r%d) in register list"),
5319 else if (reg
<= cur_reg
)
5320 as_tsktsk (_("Warning: Register range not in ascending order"));
5325 while (skip_past_comma (&str
) != FAIL
5326 || (in_range
= 1, *str
++ == '-'));
5328 skip_whitespace (str
);
5332 inst
.error
= _("Missing `}'");
5340 if (my_get_expression (&expr
, &str
))
5343 if (expr
.X_op
== O_constant
)
5345 if (expr
.X_add_number
5346 != (expr
.X_add_number
& 0x0000ffff))
5348 inst
.error
= _("invalid register mask");
5352 if ((range
& expr
.X_add_number
) != 0)
5354 int regno
= range
& expr
.X_add_number
;
5357 regno
= (1 << regno
) - 1;
5359 (_("Warning: Duplicated register (r%d) in register list"),
5363 range
|= expr
.X_add_number
;
5367 if (inst
.reloc
.type
!= 0)
5369 inst
.error
= _("expression too complex");
5373 memcpy (&inst
.reloc
.exp
, &expr
, sizeof (expressionS
));
5374 inst
.reloc
.type
= BFD_RELOC_ARM_MULTI
;
5375 inst
.reloc
.pc_rel
= 0;
5379 skip_whitespace (str
);
5381 if (*str
== '|' || *str
== '+')
5387 while (another_range
);
5394 do_ldmstm (str
, flags
)
5396 unsigned long flags
;
5401 skip_whitespace (str
);
5403 if ((base_reg
= reg_required_here (&str
, 16)) == FAIL
)
5406 if (base_reg
== REG_PC
)
5408 inst
.error
= _("r15 not allowed as base register");
5412 skip_whitespace (str
);
5416 inst
.instruction
|= WRITE_BACK
;
5420 if (skip_past_comma (&str
) == FAIL
5421 || (range
= reg_list (&str
)) == FAIL
)
5424 inst
.error
= BAD_ARGS
;
5431 inst
.instruction
|= LDM_TYPE_2_OR_3
;
5434 inst
.instruction
|= flags
| range
;
5442 unsigned long flags
;
5444 skip_whitespace (str
);
5446 /* Allow optional leading '#'. */
5447 if (is_immediate_prefix (*str
))
5450 if (my_get_expression (& inst
.reloc
.exp
, & str
))
5453 inst
.reloc
.type
= BFD_RELOC_ARM_SWI
;
5454 inst
.reloc
.pc_rel
= 0;
5455 inst
.instruction
|= flags
;
5463 do_swap (str
, flags
)
5465 unsigned long flags
;
5469 skip_whitespace (str
);
5471 if ((reg
= reg_required_here (&str
, 12)) == FAIL
)
5476 inst
.error
= _("r15 not allowed in swap");
5480 if (skip_past_comma (&str
) == FAIL
5481 || (reg
= reg_required_here (&str
, 0)) == FAIL
)
5484 inst
.error
= BAD_ARGS
;
5490 inst
.error
= _("r15 not allowed in swap");
5494 if (skip_past_comma (&str
) == FAIL
5497 inst
.error
= BAD_ARGS
;
5501 skip_whitespace (str
);
5503 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
5508 inst
.error
= BAD_PC
;
5512 skip_whitespace (str
);
5516 inst
.error
= _("missing ]");
5520 inst
.instruction
|= flags
;
5526 do_branch (str
, flags
)
5528 unsigned long flags ATTRIBUTE_UNUSED
;
5530 if (my_get_expression (&inst
.reloc
.exp
, &str
))
5537 /* ScottB: February 5, 1998 - Check to see of PLT32 reloc
5538 required for the instruction. */
5540 /* arm_parse_reloc () works on input_line_pointer.
5541 We actually want to parse the operands to the branch instruction
5542 passed in 'str'. Save the input pointer and restore it later. */
5543 save_in
= input_line_pointer
;
5544 input_line_pointer
= str
;
5545 if (inst
.reloc
.exp
.X_op
== O_symbol
5547 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32
)
5549 inst
.reloc
.type
= BFD_RELOC_ARM_PLT32
;
5550 inst
.reloc
.pc_rel
= 0;
5551 /* Modify str to point to after parsed operands, otherwise
5552 end_of_line() will complain about the (PLT) left in str. */
5553 str
= input_line_pointer
;
5557 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BRANCH
;
5558 inst
.reloc
.pc_rel
= 1;
5560 input_line_pointer
= save_in
;
5563 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BRANCH
;
5564 inst
.reloc
.pc_rel
= 1;
5565 #endif /* OBJ_ELF */
5574 unsigned long flags ATTRIBUTE_UNUSED
;
5578 skip_whitespace (str
);
5580 if ((reg
= reg_required_here (&str
, 0)) == FAIL
)
5582 inst
.error
= BAD_ARGS
;
5586 /* Note - it is not illegal to do a "bx pc". Useless, but not illegal. */
5588 as_tsktsk (_("Use of r15 in bx in ARM mode is not really useful"));
5596 unsigned long flags ATTRIBUTE_UNUSED
;
5598 /* Co-processor data operation.
5599 Format: CDP{cond} CP#,<expr>,CRd,CRn,CRm{,<expr>} */
5600 skip_whitespace (str
);
5602 if (co_proc_number (&str
) == FAIL
)
5605 inst
.error
= BAD_ARGS
;
5609 if (skip_past_comma (&str
) == FAIL
5610 || cp_opc_expr (&str
, 20,4) == FAIL
)
5613 inst
.error
= BAD_ARGS
;
5617 if (skip_past_comma (&str
) == FAIL
5618 || cp_reg_required_here (&str
, 12) == FAIL
)
5621 inst
.error
= BAD_ARGS
;
5625 if (skip_past_comma (&str
) == FAIL
5626 || cp_reg_required_here (&str
, 16) == FAIL
)
5629 inst
.error
= BAD_ARGS
;
5633 if (skip_past_comma (&str
) == FAIL
5634 || cp_reg_required_here (&str
, 0) == FAIL
)
5637 inst
.error
= BAD_ARGS
;
5641 if (skip_past_comma (&str
) == SUCCESS
)
5643 if (cp_opc_expr (&str
, 5, 3) == FAIL
)
5646 inst
.error
= BAD_ARGS
;
5656 do_lstc (str
, flags
)
5658 unsigned long flags
;
5660 /* Co-processor register load/store.
5661 Format: <LDC|STC{cond}[L] CP#,CRd,<address> */
5663 skip_whitespace (str
);
5665 if (co_proc_number (&str
) == FAIL
)
5668 inst
.error
= BAD_ARGS
;
5672 if (skip_past_comma (&str
) == FAIL
5673 || cp_reg_required_here (&str
, 12) == FAIL
)
5676 inst
.error
= BAD_ARGS
;
5680 if (skip_past_comma (&str
) == FAIL
5681 || cp_address_required_here (&str
) == FAIL
)
5684 inst
.error
= BAD_ARGS
;
5688 inst
.instruction
|= flags
;
5694 do_co_reg (str
, flags
)
5696 unsigned long flags
;
5698 /* Co-processor register transfer.
5699 Format: <MCR|MRC>{cond} CP#,<expr1>,Rd,CRn,CRm{,<expr2>} */
5701 skip_whitespace (str
);
5703 if (co_proc_number (&str
) == FAIL
)
5706 inst
.error
= BAD_ARGS
;
5710 if (skip_past_comma (&str
) == FAIL
5711 || cp_opc_expr (&str
, 21, 3) == FAIL
)
5714 inst
.error
= BAD_ARGS
;
5718 if (skip_past_comma (&str
) == FAIL
5719 || reg_required_here (&str
, 12) == FAIL
)
5722 inst
.error
= BAD_ARGS
;
5726 if (skip_past_comma (&str
) == FAIL
5727 || cp_reg_required_here (&str
, 16) == FAIL
)
5730 inst
.error
= BAD_ARGS
;
5734 if (skip_past_comma (&str
) == FAIL
5735 || cp_reg_required_here (&str
, 0) == FAIL
)
5738 inst
.error
= BAD_ARGS
;
5742 if (skip_past_comma (&str
) == SUCCESS
)
5744 if (cp_opc_expr (&str
, 5, 3) == FAIL
)
5747 inst
.error
= BAD_ARGS
;
5753 inst
.error
= BAD_COND
;
5761 do_fpa_ctrl (str
, flags
)
5763 unsigned long flags ATTRIBUTE_UNUSED
;
5765 /* FP control registers.
5766 Format: <WFS|RFS|WFC|RFC>{cond} Rn */
5768 skip_whitespace (str
);
5770 if (reg_required_here (&str
, 12) == FAIL
)
5773 inst
.error
= BAD_ARGS
;
5782 do_fpa_ldst (str
, flags
)
5784 unsigned long flags ATTRIBUTE_UNUSED
;
5786 skip_whitespace (str
);
5788 if (fp_reg_required_here (&str
, 12) == FAIL
)
5791 inst
.error
= BAD_ARGS
;
5795 if (skip_past_comma (&str
) == FAIL
5796 || cp_address_required_here (&str
) == FAIL
)
5799 inst
.error
= BAD_ARGS
;
5807 do_fpa_ldmstm (str
, flags
)
5809 unsigned long flags
;
5813 skip_whitespace (str
);
5815 if (fp_reg_required_here (&str
, 12) == FAIL
)
5818 inst
.error
= BAD_ARGS
;
5822 /* Get Number of registers to transfer. */
5823 if (skip_past_comma (&str
) == FAIL
5824 || my_get_expression (&inst
.reloc
.exp
, &str
))
5827 inst
.error
= _("constant expression expected");
5831 if (inst
.reloc
.exp
.X_op
!= O_constant
)
5833 inst
.error
= _("Constant value required for number of registers");
5837 num_regs
= inst
.reloc
.exp
.X_add_number
;
5839 if (num_regs
< 1 || num_regs
> 4)
5841 inst
.error
= _("number of registers must be in the range [1:4]");
5848 inst
.instruction
|= CP_T_X
;
5851 inst
.instruction
|= CP_T_Y
;
5854 inst
.instruction
|= CP_T_Y
| CP_T_X
;
5862 if (inst
.instruction
& (CP_T_Pre
| CP_T_UD
)) /* ed/fd format. */
5868 /* The instruction specified "ea" or "fd", so we can only accept
5869 [Rn]{!}. The instruction does not really support stacking or
5870 unstacking, so we have to emulate these by setting appropriate
5871 bits and offsets. */
5872 if (skip_past_comma (&str
) == FAIL
5876 inst
.error
= BAD_ARGS
;
5881 skip_whitespace (str
);
5883 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
5886 skip_whitespace (str
);
5890 inst
.error
= BAD_ARGS
;
5902 _("R15 not allowed as base register with write-back");
5909 if (inst
.instruction
& CP_T_Pre
)
5911 /* Pre-decrement. */
5912 offset
= 3 * num_regs
;
5914 inst
.instruction
|= CP_T_WB
;
5918 /* Post-increment. */
5921 inst
.instruction
|= CP_T_WB
;
5922 offset
= 3 * num_regs
;
5926 /* No write-back, so convert this into a standard pre-increment
5927 instruction -- aesthetically more pleasing. */
5928 inst
.instruction
|= CP_T_Pre
| CP_T_UD
;
5933 inst
.instruction
|= flags
| offset
;
5935 else if (skip_past_comma (&str
) == FAIL
5936 || cp_address_required_here (&str
) == FAIL
)
5939 inst
.error
= BAD_ARGS
;
5947 do_fpa_dyadic (str
, flags
)
5949 unsigned long flags
;
5951 skip_whitespace (str
);
5953 if (fp_reg_required_here (&str
, 12) == FAIL
)
5956 inst
.error
= BAD_ARGS
;
5960 if (skip_past_comma (&str
) == FAIL
5961 || fp_reg_required_here (&str
, 16) == FAIL
)
5964 inst
.error
= BAD_ARGS
;
5968 if (skip_past_comma (&str
) == FAIL
5969 || fp_op2 (&str
) == FAIL
)
5972 inst
.error
= BAD_ARGS
;
5976 inst
.instruction
|= flags
;
5982 do_fpa_monadic (str
, flags
)
5984 unsigned long flags
;
5986 skip_whitespace (str
);
5988 if (fp_reg_required_here (&str
, 12) == FAIL
)
5991 inst
.error
= BAD_ARGS
;
5995 if (skip_past_comma (&str
) == FAIL
5996 || fp_op2 (&str
) == FAIL
)
5999 inst
.error
= BAD_ARGS
;
6003 inst
.instruction
|= flags
;
6009 do_fpa_cmp (str
, flags
)
6011 unsigned long flags
;
6013 skip_whitespace (str
);
6015 if (fp_reg_required_here (&str
, 16) == FAIL
)
6018 inst
.error
= BAD_ARGS
;
6022 if (skip_past_comma (&str
) == FAIL
6023 || fp_op2 (&str
) == FAIL
)
6026 inst
.error
= BAD_ARGS
;
6030 inst
.instruction
|= flags
;
6036 do_fpa_from_reg (str
, flags
)
6038 unsigned long flags
;
6040 skip_whitespace (str
);
6042 if (fp_reg_required_here (&str
, 16) == FAIL
)
6045 inst
.error
= BAD_ARGS
;
6049 if (skip_past_comma (&str
) == FAIL
6050 || reg_required_here (&str
, 12) == FAIL
)
6053 inst
.error
= BAD_ARGS
;
6057 inst
.instruction
|= flags
;
6063 do_fpa_to_reg (str
, flags
)
6065 unsigned long flags
;
6067 skip_whitespace (str
);
6069 if (reg_required_here (&str
, 12) == FAIL
)
6072 if (skip_past_comma (&str
) == FAIL
6073 || fp_reg_required_here (&str
, 0) == FAIL
)
6076 inst
.error
= BAD_ARGS
;
6080 inst
.instruction
|= flags
;
6085 /* Thumb specific routines. */
6087 /* Parse and validate that a register is of the right form, this saves
6088 repeated checking of this information in many similar cases.
6089 Unlike the 32-bit case we do not insert the register into the opcode
6090 here, since the position is often unknown until the full instruction
6094 thumb_reg (strp
, hi_lo
)
6100 if ((reg
= reg_required_here (strp
, -1)) == FAIL
)
6108 inst
.error
= _("lo register required");
6116 inst
.error
= _("hi register required");
6128 /* Parse an add or subtract instruction, SUBTRACT is non-zero if the opcode
6132 thumb_add_sub (str
, subtract
)
6136 int Rd
, Rs
, Rn
= FAIL
;
6138 skip_whitespace (str
);
6140 if ((Rd
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
6141 || skip_past_comma (&str
) == FAIL
)
6144 inst
.error
= BAD_ARGS
;
6148 if (is_immediate_prefix (*str
))
6152 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6157 if ((Rs
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
6160 if (skip_past_comma (&str
) == FAIL
)
6162 /* Two operand format, shuffle the registers
6163 and pretend there are 3. */
6167 else if (is_immediate_prefix (*str
))
6170 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6173 else if ((Rn
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
6177 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
6178 for the latter case, EXPR contains the immediate that was found. */
6181 /* All register format. */
6182 if (Rd
> 7 || Rs
> 7 || Rn
> 7)
6186 inst
.error
= _("dest and source1 must be the same register");
6190 /* Can't do this for SUB. */
6193 inst
.error
= _("subtract valid only on lo regs");
6197 inst
.instruction
= (T_OPCODE_ADD_HI
6198 | (Rd
> 7 ? THUMB_H1
: 0)
6199 | (Rn
> 7 ? THUMB_H2
: 0));
6200 inst
.instruction
|= (Rd
& 7) | ((Rn
& 7) << 3);
6204 inst
.instruction
= subtract
? T_OPCODE_SUB_R3
: T_OPCODE_ADD_R3
;
6205 inst
.instruction
|= Rd
| (Rs
<< 3) | (Rn
<< 6);
6210 /* Immediate expression, now things start to get nasty. */
6212 /* First deal with HI regs, only very restricted cases allowed:
6213 Adjusting SP, and using PC or SP to get an address. */
6214 if ((Rd
> 7 && (Rd
!= REG_SP
|| Rs
!= REG_SP
))
6215 || (Rs
> 7 && Rs
!= REG_SP
&& Rs
!= REG_PC
))
6217 inst
.error
= _("invalid Hi register with immediate");
6221 if (inst
.reloc
.exp
.X_op
!= O_constant
)
6223 /* Value isn't known yet, all we can do is store all the fragments
6224 we know about in the instruction and let the reloc hacking
6226 inst
.instruction
= (subtract
? 0x8000 : 0) | (Rd
<< 4) | Rs
;
6227 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_ADD
;
6231 int offset
= inst
.reloc
.exp
.X_add_number
;
6241 /* Quick check, in case offset is MIN_INT. */
6244 inst
.error
= _("immediate value out of range");
6253 if (offset
& ~0x1fc)
6255 inst
.error
= _("invalid immediate value for stack adjust");
6258 inst
.instruction
= subtract
? T_OPCODE_SUB_ST
: T_OPCODE_ADD_ST
;
6259 inst
.instruction
|= offset
>> 2;
6261 else if (Rs
== REG_PC
|| Rs
== REG_SP
)
6264 || (offset
& ~0x3fc))
6266 inst
.error
= _("invalid immediate for address calculation");
6269 inst
.instruction
= (Rs
== REG_PC
? T_OPCODE_ADD_PC
6271 inst
.instruction
|= (Rd
<< 8) | (offset
>> 2);
6277 inst
.error
= _("immediate value out of range");
6280 inst
.instruction
= subtract
? T_OPCODE_SUB_I8
: T_OPCODE_ADD_I8
;
6281 inst
.instruction
|= (Rd
<< 8) | offset
;
6287 inst
.error
= _("immediate value out of range");
6290 inst
.instruction
= subtract
? T_OPCODE_SUB_I3
: T_OPCODE_ADD_I3
;
6291 inst
.instruction
|= Rd
| (Rs
<< 3) | (offset
<< 6);
6300 thumb_shift (str
, shift
)
6304 int Rd
, Rs
, Rn
= FAIL
;
6306 skip_whitespace (str
);
6308 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
6309 || skip_past_comma (&str
) == FAIL
)
6312 inst
.error
= BAD_ARGS
;
6316 if (is_immediate_prefix (*str
))
6318 /* Two operand immediate format, set Rs to Rd. */
6321 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6326 if ((Rs
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
6329 if (skip_past_comma (&str
) == FAIL
)
6331 /* Two operand format, shuffle the registers
6332 and pretend there are 3. */
6336 else if (is_immediate_prefix (*str
))
6339 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6342 else if ((Rn
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
6346 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
6347 for the latter case, EXPR contains the immediate that was found. */
6353 inst
.error
= _("source1 and dest must be same register");
6359 case THUMB_ASR
: inst
.instruction
= T_OPCODE_ASR_R
; break;
6360 case THUMB_LSL
: inst
.instruction
= T_OPCODE_LSL_R
; break;
6361 case THUMB_LSR
: inst
.instruction
= T_OPCODE_LSR_R
; break;
6364 inst
.instruction
|= Rd
| (Rn
<< 3);
6370 case THUMB_ASR
: inst
.instruction
= T_OPCODE_ASR_I
; break;
6371 case THUMB_LSL
: inst
.instruction
= T_OPCODE_LSL_I
; break;
6372 case THUMB_LSR
: inst
.instruction
= T_OPCODE_LSR_I
; break;
6375 if (inst
.reloc
.exp
.X_op
!= O_constant
)
6377 /* Value isn't known yet, create a dummy reloc and let reloc
6378 hacking fix it up. */
6379 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_SHIFT
;
6383 unsigned shift_value
= inst
.reloc
.exp
.X_add_number
;
6385 if (shift_value
> 32 || (shift_value
== 32 && shift
== THUMB_LSL
))
6387 inst
.error
= _("Invalid immediate for shift");
6391 /* Shifts of zero are handled by converting to LSL. */
6392 if (shift_value
== 0)
6393 inst
.instruction
= T_OPCODE_LSL_I
;
6395 /* Shifts of 32 are encoded as a shift of zero. */
6396 if (shift_value
== 32)
6399 inst
.instruction
|= shift_value
<< 6;
6402 inst
.instruction
|= Rd
| (Rs
<< 3);
6409 thumb_mov_compare (str
, move
)
6415 skip_whitespace (str
);
6417 if ((Rd
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
6418 || skip_past_comma (&str
) == FAIL
)
6421 inst
.error
= BAD_ARGS
;
6425 if (is_immediate_prefix (*str
))
6428 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6431 else if ((Rs
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
6436 if (Rs
< 8 && Rd
< 8)
6438 if (move
== THUMB_MOVE
)
6439 /* A move of two lowregs is encoded as ADD Rd, Rs, #0
6440 since a MOV instruction produces unpredictable results. */
6441 inst
.instruction
= T_OPCODE_ADD_I3
;
6443 inst
.instruction
= T_OPCODE_CMP_LR
;
6444 inst
.instruction
|= Rd
| (Rs
<< 3);
6448 if (move
== THUMB_MOVE
)
6449 inst
.instruction
= T_OPCODE_MOV_HR
;
6451 inst
.instruction
= T_OPCODE_CMP_HR
;
6454 inst
.instruction
|= THUMB_H1
;
6457 inst
.instruction
|= THUMB_H2
;
6459 inst
.instruction
|= (Rd
& 7) | ((Rs
& 7) << 3);
6466 inst
.error
= _("only lo regs allowed with immediate");
6470 if (move
== THUMB_MOVE
)
6471 inst
.instruction
= T_OPCODE_MOV_I8
;
6473 inst
.instruction
= T_OPCODE_CMP_I8
;
6475 inst
.instruction
|= Rd
<< 8;
6477 if (inst
.reloc
.exp
.X_op
!= O_constant
)
6478 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_IMM
;
6481 unsigned value
= inst
.reloc
.exp
.X_add_number
;
6485 inst
.error
= _("invalid immediate");
6489 inst
.instruction
|= value
;
6497 thumb_load_store (str
, load_store
, size
)
6502 int Rd
, Rb
, Ro
= FAIL
;
6504 skip_whitespace (str
);
6506 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
6507 || skip_past_comma (&str
) == FAIL
)
6510 inst
.error
= BAD_ARGS
;
6517 if ((Rb
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
6520 if (skip_past_comma (&str
) != FAIL
)
6522 if (is_immediate_prefix (*str
))
6525 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6528 else if ((Ro
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
6533 inst
.reloc
.exp
.X_op
= O_constant
;
6534 inst
.reloc
.exp
.X_add_number
= 0;
6539 inst
.error
= _("expected ']'");
6544 else if (*str
== '=')
6546 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
6549 skip_whitespace (str
);
6551 if (my_get_expression (& inst
.reloc
.exp
, & str
))
6556 if ( inst
.reloc
.exp
.X_op
!= O_constant
6557 && inst
.reloc
.exp
.X_op
!= O_symbol
)
6559 inst
.error
= "Constant expression expected";
6563 if (inst
.reloc
.exp
.X_op
== O_constant
6564 && ((inst
.reloc
.exp
.X_add_number
& ~0xFF) == 0))
6566 /* This can be done with a mov instruction. */
6568 inst
.instruction
= T_OPCODE_MOV_I8
| (Rd
<< 8);
6569 inst
.instruction
|= inst
.reloc
.exp
.X_add_number
;
6573 /* Insert into literal pool. */
6574 if (add_to_lit_pool () == FAIL
)
6577 inst
.error
= "literal pool insertion failed";
6581 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
6582 inst
.reloc
.pc_rel
= 1;
6583 inst
.instruction
= T_OPCODE_LDR_PC
| (Rd
<< 8);
6584 /* Adjust ARM pipeline offset to Thumb. */
6585 inst
.reloc
.exp
.X_add_number
+= 4;
6591 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6594 inst
.instruction
= T_OPCODE_LDR_PC
| (Rd
<< 8);
6595 inst
.reloc
.pc_rel
= 1;
6596 inst
.reloc
.exp
.X_add_number
-= 4; /* Pipeline offset. */
6597 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
6602 if (Rb
== REG_PC
|| Rb
== REG_SP
)
6604 if (size
!= THUMB_WORD
)
6606 inst
.error
= _("byte or halfword not valid for base register");
6609 else if (Rb
== REG_PC
&& load_store
!= THUMB_LOAD
)
6611 inst
.error
= _("R15 based store not allowed");
6614 else if (Ro
!= FAIL
)
6616 inst
.error
= _("Invalid base register for register offset");
6621 inst
.instruction
= T_OPCODE_LDR_PC
;
6622 else if (load_store
== THUMB_LOAD
)
6623 inst
.instruction
= T_OPCODE_LDR_SP
;
6625 inst
.instruction
= T_OPCODE_STR_SP
;
6627 inst
.instruction
|= Rd
<< 8;
6628 if (inst
.reloc
.exp
.X_op
== O_constant
)
6630 unsigned offset
= inst
.reloc
.exp
.X_add_number
;
6632 if (offset
& ~0x3fc)
6634 inst
.error
= _("invalid offset");
6638 inst
.instruction
|= offset
>> 2;
6641 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
6645 inst
.error
= _("invalid base register in load/store");
6648 else if (Ro
== FAIL
)
6650 /* Immediate offset. */
6651 if (size
== THUMB_WORD
)
6652 inst
.instruction
= (load_store
== THUMB_LOAD
6653 ? T_OPCODE_LDR_IW
: T_OPCODE_STR_IW
);
6654 else if (size
== THUMB_HALFWORD
)
6655 inst
.instruction
= (load_store
== THUMB_LOAD
6656 ? T_OPCODE_LDR_IH
: T_OPCODE_STR_IH
);
6658 inst
.instruction
= (load_store
== THUMB_LOAD
6659 ? T_OPCODE_LDR_IB
: T_OPCODE_STR_IB
);
6661 inst
.instruction
|= Rd
| (Rb
<< 3);
6663 if (inst
.reloc
.exp
.X_op
== O_constant
)
6665 unsigned offset
= inst
.reloc
.exp
.X_add_number
;
6667 if (offset
& ~(0x1f << size
))
6669 inst
.error
= _("Invalid offset");
6672 inst
.instruction
|= (offset
>> size
) << 6;
6675 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
6679 /* Register offset. */
6680 if (size
== THUMB_WORD
)
6681 inst
.instruction
= (load_store
== THUMB_LOAD
6682 ? T_OPCODE_LDR_RW
: T_OPCODE_STR_RW
);
6683 else if (size
== THUMB_HALFWORD
)
6684 inst
.instruction
= (load_store
== THUMB_LOAD
6685 ? T_OPCODE_LDR_RH
: T_OPCODE_STR_RH
);
6687 inst
.instruction
= (load_store
== THUMB_LOAD
6688 ? T_OPCODE_LDR_RB
: T_OPCODE_STR_RB
);
6690 inst
.instruction
|= Rd
| (Rb
<< 3) | (Ro
<< 6);
6696 /* Given a register and a register type, return 1 if
6697 the register is of the given type, else return 0. */
6700 cirrus_valid_reg (reg
, regtype
)
6702 enum cirrus_regtype regtype
;
6706 case CIRRUS_REGTYPE_ANY
:
6709 case CIRRUS_REGTYPE_MVF
:
6710 return cirrus_mvf_register (reg
);
6712 case CIRRUS_REGTYPE_MVFX
:
6713 return cirrus_mvfx_register (reg
);
6715 case CIRRUS_REGTYPE_MVD
:
6716 return cirrus_mvd_register (reg
);
6718 case CIRRUS_REGTYPE_MVDX
:
6719 return cirrus_mvdx_register (reg
);
6721 case CIRRUS_REGTYPE_MVAX
:
6722 return cirrus_mvax_register (reg
);
6724 case CIRRUS_REGTYPE_DSPSC
:
6725 return ARM_EXT_MAVERICKsc_register (reg
);
6731 /* A register must be given at this point.
6733 If the register is a Cirrus register, convert it's reg# appropriately.
6735 Shift is the place to put it in inst.instruction.
6737 regtype is type register type expected, and is:
6743 CIRRUS_REGTYPE_DSPSC
6745 Restores input start point on err.
6746 Returns the reg#, or FAIL. */
6749 cirrus_reg_required_here (str
, shift
, regtype
)
6752 enum cirrus_regtype regtype
;
6754 static char buff
[135]; /* XXX */
6756 char * start
= * str
;
6758 if ((reg
= arm_reg_parse (str
)) != FAIL
6759 && (int_register (reg
)
6760 || cirrus_register (reg
)))
6764 /* Calculate actual register # for opcode. */
6765 if (cirrus_register (reg
)
6766 && !ARM_EXT_MAVERICKsc_register (reg
)) /* Leave this one as is. */
6770 else if (reg
>= 110)
6780 if (!cirrus_valid_reg (orig_reg
, regtype
))
6782 sprintf (buff
, _("invalid register type at '%.100s'"), start
);
6788 inst
.instruction
|= reg
<< shift
;
6793 /* Restore the start point, we may have got a reg of the wrong class. */
6796 /* In the few cases where we might be able to accept something else
6797 this error can be overridden. */
6798 sprintf (buff
, _("Cirrus register expected, not '%.100s'"), start
);
6804 /* Cirrus Instructions. */
6806 /* Wrapper functions. */
6809 do_c_binops_1 (str
, flags
)
6811 unsigned long flags
;
6813 do_c_binops (str
, flags
, CIRRUS_MODE1
);
6817 do_c_binops_2 (str
, flags
)
6819 unsigned long flags
;
6821 do_c_binops (str
, flags
, CIRRUS_MODE2
);
6825 do_c_binops_3 (str
, flags
)
6827 unsigned long flags
;
6829 do_c_binops (str
, flags
, CIRRUS_MODE3
);
6833 do_c_triple_4 (str
, flags
)
6835 unsigned long flags
;
6837 do_c_triple (str
, flags
, CIRRUS_MODE4
);
6841 do_c_triple_5 (str
, flags
)
6843 unsigned long flags
;
6845 do_c_triple (str
, flags
, CIRRUS_MODE5
);
6849 do_c_quad_6 (str
, flags
)
6851 unsigned long flags
;
6853 do_c_quad (str
, flags
, CIRRUS_MODE6
);
6857 do_c_dspsc_1 (str
, flags
)
6859 unsigned long flags
;
6861 do_c_dspsc (str
, flags
, CIRRUS_MODE1
);
6865 do_c_dspsc_2 (str
, flags
)
6867 unsigned long flags
;
6869 do_c_dspsc (str
, flags
, CIRRUS_MODE2
);
6873 do_c_shift_1 (str
, flags
)
6875 unsigned long flags
;
6877 do_c_shift (str
, flags
, CIRRUS_MODE1
);
6881 do_c_shift_2 (str
, flags
)
6883 unsigned long flags
;
6885 do_c_shift (str
, flags
, CIRRUS_MODE2
);
6889 do_c_ldst_1 (str
, flags
)
6891 unsigned long flags
;
6893 do_c_ldst (str
, flags
, CIRRUS_MODE1
);
6897 do_c_ldst_2 (str
, flags
)
6899 unsigned long flags
;
6901 do_c_ldst (str
, flags
, CIRRUS_MODE2
);
6905 do_c_ldst_3 (str
, flags
)
6907 unsigned long flags
;
6909 do_c_ldst (str
, flags
, CIRRUS_MODE3
);
6913 do_c_ldst_4 (str
, flags
)
6915 unsigned long flags
;
6917 do_c_ldst (str
, flags
, CIRRUS_MODE4
);
6920 /* Isnsn like "foo X,Y". */
6923 do_c_binops (str
, flags
, mode
)
6925 unsigned long flags
;
6930 shift1
= mode
& 0xff;
6931 shift2
= (mode
>> 8) & 0xff;
6933 skip_whitespace (str
);
6935 if (cirrus_reg_required_here (&str
, shift1
, CIRRUS_REGTYPE_ANY
) == FAIL
6936 || skip_past_comma (&str
) == FAIL
6937 || cirrus_reg_required_here (&str
, shift2
, CIRRUS_REGTYPE_ANY
) == FAIL
)
6940 inst
.error
= BAD_ARGS
;
6945 inst
.instruction
|= flags
;
6949 /* Isnsn like "foo X,Y,Z". */
6952 do_c_triple (str
, flags
, mode
)
6954 unsigned long flags
;
6957 int shift1
, shift2
, shift3
;
6959 shift1
= mode
& 0xff;
6960 shift2
= (mode
>> 8) & 0xff;
6961 shift3
= (mode
>> 16) & 0xff;
6963 skip_whitespace (str
);
6965 if (cirrus_reg_required_here (&str
, shift1
, CIRRUS_REGTYPE_ANY
) == FAIL
6966 || skip_past_comma (&str
) == FAIL
6967 || cirrus_reg_required_here (&str
, shift2
, CIRRUS_REGTYPE_ANY
) == FAIL
6968 || skip_past_comma (&str
) == FAIL
6969 || cirrus_reg_required_here (&str
, shift3
, CIRRUS_REGTYPE_ANY
) == FAIL
)
6972 inst
.error
= BAD_ARGS
;
6977 inst
.instruction
|= flags
;
6981 /* Isnsn like "foo W,X,Y,Z".
6982 where W=MVAX[0:3] and X,Y,Z=MVFX[0:15]. */
6985 do_c_quad (str
, flags
, mode
)
6987 unsigned long flags
;
6990 int shift1
, shift2
, shift3
, shift4
;
6991 enum cirrus_regtype rt
;
6993 rt
= (inst
.instruction
<< 4 == 0xe2006000
6994 || inst
.instruction
<< 4 == 0xe3006000) ? CIRRUS_REGTYPE_MVAX
6995 : CIRRUS_REGTYPE_MVFX
;
6997 shift1
= mode
& 0xff;
6998 shift2
= (mode
>> 8) & 0xff;
6999 shift3
= (mode
>> 16) & 0xff;
7000 shift4
= (mode
>> 24) & 0xff;
7002 skip_whitespace (str
);
7004 if (cirrus_reg_required_here (&str
, shift1
, CIRRUS_REGTYPE_MVAX
) == FAIL
7005 || skip_past_comma (&str
) == FAIL
7006 || cirrus_reg_required_here (&str
, shift2
, rt
) == FAIL
7007 || skip_past_comma (&str
) == FAIL
7008 || cirrus_reg_required_here (&str
, shift3
, CIRRUS_REGTYPE_MVFX
) == FAIL
7009 || skip_past_comma (&str
) == FAIL
7010 || cirrus_reg_required_here (&str
, shift4
, CIRRUS_REGTYPE_MVFX
) == FAIL
)
7013 inst
.error
= BAD_ARGS
;
7018 inst
.instruction
|= flags
;
7022 /* cfmvsc32<cond> DSPSC,MVFX[15:0].
7023 cfmv32sc<cond> MVFX[15:0],DSPSC. */
7026 do_c_dspsc (str
, flags
, mode
)
7028 unsigned long flags
;
7033 skip_whitespace (str
);
7037 if (mode
== CIRRUS_MODE1
)
7040 if (cirrus_reg_required_here (&str
, -1, CIRRUS_REGTYPE_DSPSC
) == FAIL
7041 || skip_past_comma (&str
) == FAIL
7042 || cirrus_reg_required_here (&str
, 16, CIRRUS_REGTYPE_MVFX
) == FAIL
)
7048 if (cirrus_reg_required_here (&str
, 0, CIRRUS_REGTYPE_MVFX
) == FAIL
7049 || skip_past_comma (&str
) == FAIL
7050 || cirrus_reg_required_here (&str
, -1, CIRRUS_REGTYPE_DSPSC
) == FAIL
)
7057 inst
.error
= BAD_ARGS
;
7061 inst
.instruction
|= flags
;
7068 /* Cirrus shift immediate instructions.
7069 cfsh32<cond> MVFX[15:0],MVFX[15:0],Shift[6:0].
7070 cfsh64<cond> MVDX[15:0],MVDX[15:0],Shift[6:0]. */
7073 do_c_shift (str
, flags
, mode
)
7075 unsigned long flags
;
7081 skip_whitespace (str
);
7085 if (cirrus_reg_required_here (&str
, 12,
7086 (mode
== CIRRUS_MODE1
)
7087 ? CIRRUS_REGTYPE_MVFX
7088 : CIRRUS_REGTYPE_MVDX
) == FAIL
7089 || skip_past_comma (&str
) == FAIL
7090 || cirrus_reg_required_here (&str
, 16,
7091 (mode
== CIRRUS_MODE1
)
7092 ? CIRRUS_REGTYPE_MVFX
7093 : CIRRUS_REGTYPE_MVDX
) == FAIL
7094 || skip_past_comma (&str
) == FAIL
)
7097 inst
.error
= BAD_ARGS
;
7101 /* Calculate the immediate operand.
7102 The operand is a 7bit signed number. */
7103 skip_whitespace (str
);
7108 if (!ISDIGIT (*str
) && *str
!= '-')
7110 inst
.error
= _("expecting immediate, 7bit operand");
7120 for (imm
= 0; *str
&& ISDIGIT (*str
); ++str
)
7121 imm
= imm
* 10 + *str
- '0';
7125 inst
.error
= _("immediate out of range");
7129 /* Make negative imm's into 7bit signed numbers. */
7136 /* Bits 0-3 of the insn should have bits 0-3 of the immediate.
7137 Bits 5-7 of the insn should have bits 4-6 of the immediate.
7138 Bit 4 should be 0. */
7139 imm
= (imm
& 0xf) | ((imm
& 0x70) << 1);
7141 inst
.instruction
|= imm
;
7142 inst
.instruction
|= flags
;
7150 cirrus_parse_offset (str
, negative
)
7159 skip_whitespace (p
);
7172 inst
.error
= _("offset expected");
7176 for (offset
= 0; *p
&& ISDIGIT (*p
); ++p
)
7177 offset
= offset
* 10 + *p
- '0';
7181 inst
.error
= _("offset out of range");
7187 return *negative
? -offset
: offset
;
7190 /* Cirrus load/store instructions.
7191 <insn><cond> CRd,[Rn,<offset>]{!}.
7192 <insn><cond> CRd,[Rn],<offset>. */
7195 do_c_ldst (str
, flags
, mode
)
7197 unsigned long flags
;
7200 int offset
, negative
;
7201 enum cirrus_regtype rt
;
7203 rt
= mode
== CIRRUS_MODE1
? CIRRUS_REGTYPE_MVF
7204 : mode
== CIRRUS_MODE2
? CIRRUS_REGTYPE_MVD
7205 : mode
== CIRRUS_MODE3
? CIRRUS_REGTYPE_MVFX
7206 : mode
== CIRRUS_MODE4
? CIRRUS_REGTYPE_MVDX
: CIRRUS_REGTYPE_MVF
;
7208 skip_whitespace (str
);
7210 if (cirrus_reg_required_here (& str
, 12, rt
) == FAIL
7211 || skip_past_comma (& str
) == FAIL
7213 || reg_required_here (& str
, 16) == FAIL
)
7216 if (skip_past_comma (& str
) == SUCCESS
)
7218 /* You are here: "<offset>]{!}". */
7219 inst
.instruction
|= PRE_INDEX
;
7221 offset
= cirrus_parse_offset (&str
, &negative
);
7228 inst
.error
= _("missing ]");
7234 inst
.instruction
|= WRITE_BACK
;
7240 /* You are here: "], <offset>". */
7243 inst
.error
= _("missing ]");
7247 if (skip_past_comma (&str
) == FAIL
7248 || (offset
= cirrus_parse_offset (&str
, &negative
), inst
.error
))
7251 inst
.instruction
|= CP_T_WB
; /* Post indexed, set bit W. */
7257 inst
.instruction
|= CP_T_UD
; /* Postive, so set bit U. */
7259 inst
.instruction
|= offset
>> 2;
7260 inst
.instruction
|= flags
;
7267 inst
.error
= BAD_ARGS
;
7280 /* Handle the Format 4 instructions that do not have equivalents in other
7281 formats. That is, ADC, AND, EOR, SBC, ROR, TST, NEG, CMN, ORR, MUL,
7290 skip_whitespace (str
);
7292 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
7293 || skip_past_comma (&str
) == FAIL
7294 || (Rs
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
7296 inst
.error
= BAD_ARGS
;
7300 if (skip_past_comma (&str
) != FAIL
)
7302 /* Three operand format not allowed for TST, CMN, NEG and MVN.
7303 (It isn't allowed for CMP either, but that isn't handled by this
7305 if (inst
.instruction
== T_OPCODE_TST
7306 || inst
.instruction
== T_OPCODE_CMN
7307 || inst
.instruction
== T_OPCODE_NEG
7308 || inst
.instruction
== T_OPCODE_MVN
)
7310 inst
.error
= BAD_ARGS
;
7314 if ((Rn
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
7319 inst
.error
= _("dest and source1 must be the same register");
7325 if (inst
.instruction
== T_OPCODE_MUL
7327 as_tsktsk (_("Rs and Rd must be different in MUL"));
7329 inst
.instruction
|= Rd
| (Rs
<< 3);
7337 thumb_add_sub (str
, 0);
7344 thumb_shift (str
, THUMB_ASR
);
7351 if (my_get_expression (&inst
.reloc
.exp
, &str
))
7353 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH9
;
7354 inst
.reloc
.pc_rel
= 1;
7362 if (my_get_expression (&inst
.reloc
.exp
, &str
))
7364 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH12
;
7365 inst
.reloc
.pc_rel
= 1;
7369 /* Find the real, Thumb encoded start of a Thumb function. */
7372 find_real_start (symbolP
)
7376 const char * name
= S_GET_NAME (symbolP
);
7377 symbolS
* new_target
;
7379 /* This definiton must agree with the one in gcc/config/arm/thumb.c. */
7380 #define STUB_NAME ".real_start_of"
7385 /* Names that start with '.' are local labels, not function entry points.
7386 The compiler may generate BL instructions to these labels because it
7387 needs to perform a branch to a far away location. */
7391 real_start
= malloc (strlen (name
) + strlen (STUB_NAME
) + 1);
7392 sprintf (real_start
, "%s%s", STUB_NAME
, name
);
7394 new_target
= symbol_find (real_start
);
7396 if (new_target
== NULL
)
7398 as_warn ("Failed to find real start of function: %s\n", name
);
7399 new_target
= symbolP
;
7411 if (my_get_expression (& inst
.reloc
.exp
, & str
))
7414 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH23
;
7415 inst
.reloc
.pc_rel
= 1;
7418 /* If the destination of the branch is a defined symbol which does not have
7419 the THUMB_FUNC attribute, then we must be calling a function which has
7420 the (interfacearm) attribute. We look for the Thumb entry point to that
7421 function and change the branch to refer to that function instead. */
7422 if ( inst
.reloc
.exp
.X_op
== O_symbol
7423 && inst
.reloc
.exp
.X_add_symbol
!= NULL
7424 && S_IS_DEFINED (inst
.reloc
.exp
.X_add_symbol
)
7425 && ! THUMB_IS_FUNC (inst
.reloc
.exp
.X_add_symbol
))
7426 inst
.reloc
.exp
.X_add_symbol
=
7427 find_real_start (inst
.reloc
.exp
.X_add_symbol
);
7436 skip_whitespace (str
);
7438 if ((reg
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
7441 /* This sets THUMB_H2 from the top bit of reg. */
7442 inst
.instruction
|= reg
<< 3;
7444 /* ??? FIXME: Should add a hacky reloc here if reg is REG_PC. The reloc
7445 should cause the alignment to be checked once it is known. This is
7446 because BX PC only works if the instruction is word aligned. */
7455 thumb_mov_compare (str
, THUMB_COMPARE
);
7465 skip_whitespace (str
);
7467 if ((Rb
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
7471 as_warn (_("Inserted missing '!': load/store multiple always writes back base register"));
7475 if (skip_past_comma (&str
) == FAIL
7476 || (range
= reg_list (&str
)) == FAIL
)
7479 inst
.error
= BAD_ARGS
;
7483 if (inst
.reloc
.type
!= BFD_RELOC_NONE
)
7485 /* This really doesn't seem worth it. */
7486 inst
.reloc
.type
= BFD_RELOC_NONE
;
7487 inst
.error
= _("Expression too complex");
7493 inst
.error
= _("only lo-regs valid in load/store multiple");
7497 inst
.instruction
|= (Rb
<< 8) | range
;
7505 thumb_load_store (str
, THUMB_LOAD
, THUMB_WORD
);
7512 thumb_load_store (str
, THUMB_LOAD
, THUMB_BYTE
);
7519 thumb_load_store (str
, THUMB_LOAD
, THUMB_HALFWORD
);
7528 skip_whitespace (str
);
7530 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
7531 || skip_past_comma (&str
) == FAIL
7533 || (Rb
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
7534 || skip_past_comma (&str
) == FAIL
7535 || (Ro
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
7539 inst
.error
= _("Syntax: ldrs[b] Rd, [Rb, Ro]");
7543 inst
.instruction
|= Rd
| (Rb
<< 3) | (Ro
<< 6);
7551 thumb_shift (str
, THUMB_LSL
);
7558 thumb_shift (str
, THUMB_LSR
);
7565 thumb_mov_compare (str
, THUMB_MOVE
);
7574 skip_whitespace (str
);
7576 if ((range
= reg_list (&str
)) == FAIL
)
7579 inst
.error
= BAD_ARGS
;
7583 if (inst
.reloc
.type
!= BFD_RELOC_NONE
)
7585 /* This really doesn't seem worth it. */
7586 inst
.reloc
.type
= BFD_RELOC_NONE
;
7587 inst
.error
= _("Expression too complex");
7593 if ((inst
.instruction
== T_OPCODE_PUSH
7594 && (range
& ~0xff) == 1 << REG_LR
)
7595 || (inst
.instruction
== T_OPCODE_POP
7596 && (range
& ~0xff) == 1 << REG_PC
))
7598 inst
.instruction
|= THUMB_PP_PC_LR
;
7603 inst
.error
= _("invalid register list to push/pop instruction");
7608 inst
.instruction
|= range
;
7616 thumb_load_store (str
, THUMB_STORE
, THUMB_WORD
);
7623 thumb_load_store (str
, THUMB_STORE
, THUMB_BYTE
);
7630 thumb_load_store (str
, THUMB_STORE
, THUMB_HALFWORD
);
7637 thumb_add_sub (str
, 1);
7644 skip_whitespace (str
);
7646 if (my_get_expression (&inst
.reloc
.exp
, &str
))
7649 inst
.reloc
.type
= BFD_RELOC_ARM_SWI
;
7660 /* This is a pseudo-op of the form "adr rd, label" to be converted
7661 into a relative address of the form "add rd, pc, #label-.-4". */
7662 skip_whitespace (str
);
7664 /* Store Rd in temporary location inside instruction. */
7665 if ((reg
= reg_required_here (&str
, 4)) == FAIL
7666 || (reg
> 7) /* For Thumb reg must be r0..r7. */
7667 || skip_past_comma (&str
) == FAIL
7668 || my_get_expression (&inst
.reloc
.exp
, &str
))
7671 inst
.error
= BAD_ARGS
;
7675 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_ADD
;
7676 inst
.reloc
.exp
.X_add_number
-= 4; /* PC relative adjust. */
7677 inst
.reloc
.pc_rel
= 1;
7678 inst
.instruction
|= REG_PC
; /* Rd is already placed into the instruction. */
7687 int len
= strlen (reg_table
[entry
].name
) + 2;
7688 char * buf
= (char *) xmalloc (len
);
7689 char * buf2
= (char *) xmalloc (len
);
7692 #ifdef REGISTER_PREFIX
7693 buf
[i
++] = REGISTER_PREFIX
;
7696 strcpy (buf
+ i
, reg_table
[entry
].name
);
7698 for (i
= 0; buf
[i
]; i
++)
7699 buf2
[i
] = TOUPPER (buf
[i
]);
7703 hash_insert (arm_reg_hsh
, buf
, (PTR
) & reg_table
[entry
]);
7704 hash_insert (arm_reg_hsh
, buf2
, (PTR
) & reg_table
[entry
]);
7708 insert_reg_alias (str
, regnum
)
7712 struct reg_entry
*new =
7713 (struct reg_entry
*) xmalloc (sizeof (struct reg_entry
));
7714 char *name
= xmalloc (strlen (str
) + 1);
7718 new->number
= regnum
;
7720 hash_insert (arm_reg_hsh
, name
, (PTR
) new);
7724 set_constant_flonums ()
7728 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
7729 if (atof_ieee ((char *) fp_const
[i
], 'x', fp_values
[i
]) == NULL
)
7733 /* Iterate over the base tables to create the instruction patterns. */
7735 build_arm_ops_hsh ()
7739 static struct obstack insn_obstack
;
7741 obstack_begin (&insn_obstack
, 4000);
7743 for (i
= 0; i
< sizeof (insns
) / sizeof (struct asm_opcode
); i
++)
7745 CONST
struct asm_opcode
*insn
= insns
+ i
;
7747 if (insn
->cond_offset
!= 0)
7749 /* Insn supports conditional execution. Build the varaints
7750 and insert them in the hash table. */
7751 for (j
= 0; j
< sizeof (conds
) / sizeof (struct asm_cond
); j
++)
7753 unsigned len
= strlen (insn
->template);
7754 struct asm_opcode
*new;
7757 new = obstack_alloc (&insn_obstack
, sizeof (struct asm_opcode
));
7758 /* All condition codes are two characters. */
7759 template = obstack_alloc (&insn_obstack
, len
+ 3);
7761 strncpy (template, insn
->template, insn
->cond_offset
);
7762 strcpy (template + insn
->cond_offset
, conds
[j
].template);
7763 if (len
> insn
->cond_offset
)
7764 strcpy (template + insn
->cond_offset
+ 2,
7765 insn
->template + insn
->cond_offset
);
7766 new->template = template;
7767 new->cond_offset
= 0;
7768 new->variant
= insn
->variant
;
7769 new->parms
= insn
->parms
;
7770 new->value
= (insn
->value
& ~COND_MASK
) | conds
[j
].value
;
7772 hash_insert (arm_ops_hsh
, new->template, (PTR
) new);
7775 /* Finally, insert the unconditional insn in the table directly;
7776 no need to build a copy. */
7777 hash_insert (arm_ops_hsh
, insn
->template, (PTR
) insn
);
7787 if ( (arm_ops_hsh
= hash_new ()) == NULL
7788 || (arm_tops_hsh
= hash_new ()) == NULL
7789 || (arm_cond_hsh
= hash_new ()) == NULL
7790 || (arm_shift_hsh
= hash_new ()) == NULL
7791 || (arm_reg_hsh
= hash_new ()) == NULL
7792 || (arm_psr_hsh
= hash_new ()) == NULL
)
7793 as_fatal (_("Virtual memory exhausted"));
7795 build_arm_ops_hsh ();
7796 for (i
= 0; i
< sizeof (tinsns
) / sizeof (struct thumb_opcode
); i
++)
7797 hash_insert (arm_tops_hsh
, tinsns
[i
].template, (PTR
) (tinsns
+ i
));
7798 for (i
= 0; i
< sizeof (conds
) / sizeof (struct asm_cond
); i
++)
7799 hash_insert (arm_cond_hsh
, conds
[i
].template, (PTR
) (conds
+ i
));
7800 for (i
= 0; i
< sizeof (shift_names
) / sizeof (struct asm_shift_name
); i
++)
7801 hash_insert (arm_shift_hsh
, shift_names
[i
].name
, (PTR
) (shift_names
+ i
));
7802 for (i
= 0; i
< sizeof (psrs
) / sizeof (struct asm_psr
); i
++)
7803 hash_insert (arm_psr_hsh
, psrs
[i
].template, (PTR
) (psrs
+ i
));
7805 for (i
= 0; reg_table
[i
].name
; i
++)
7808 set_constant_flonums ();
7810 #if defined OBJ_COFF || defined OBJ_ELF
7812 unsigned int flags
= 0;
7814 /* Set the flags in the private structure. */
7815 if (uses_apcs_26
) flags
|= F_APCS26
;
7816 if (support_interwork
) flags
|= F_INTERWORK
;
7817 if (uses_apcs_float
) flags
|= F_APCS_FLOAT
;
7818 if (pic_code
) flags
|= F_PIC
;
7819 if ((cpu_variant
& FPU_ANY
) == FPU_NONE
) flags
|= F_SOFT_FLOAT
;
7821 bfd_set_private_flags (stdoutput
, flags
);
7823 /* We have run out flags in the COFF header to encode the
7824 status of ATPCS support, so instead we create a dummy,
7825 empty, debug section called .arm.atpcs. */
7830 sec
= bfd_make_section (stdoutput
, ".arm.atpcs");
7834 bfd_set_section_flags
7835 (stdoutput
, sec
, SEC_READONLY
| SEC_DEBUGGING
/* | SEC_HAS_CONTENTS */);
7836 bfd_set_section_size (stdoutput
, sec
, 0);
7837 bfd_set_section_contents (stdoutput
, sec
, NULL
, 0, 0);
7843 /* Record the CPU type as well. */
7844 switch (cpu_variant
& ARM_CPU_MASK
)
7847 mach
= bfd_mach_arm_2
;
7850 case ARM_3
: /* Also ARM_250. */
7851 mach
= bfd_mach_arm_2a
;
7854 case ARM_6
: /* Also ARM_7. */
7855 mach
= bfd_mach_arm_3
;
7859 mach
= bfd_mach_arm_4
;
7864 /* Catch special cases. */
7865 if (cpu_variant
& ARM_EXT_XSCALE
)
7866 mach
= bfd_mach_arm_XScale
;
7867 else if (cpu_variant
& ARM_EXT_V5E
)
7868 mach
= bfd_mach_arm_5TE
;
7869 else if (cpu_variant
& ARM_EXT_V5
)
7871 if (cpu_variant
& ARM_EXT_V4T
)
7872 mach
= bfd_mach_arm_5T
;
7874 mach
= bfd_mach_arm_5
;
7876 else if (cpu_variant
& ARM_EXT_V4
)
7878 if (cpu_variant
& ARM_EXT_V4T
)
7879 mach
= bfd_mach_arm_4T
;
7881 mach
= bfd_mach_arm_4
;
7883 else if (cpu_variant
& ARM_EXT_V3M
)
7884 mach
= bfd_mach_arm_3M
;
7886 bfd_set_arch_mach (stdoutput
, TARGET_ARCH
, mach
);
7889 /* Turn an integer of n bytes (in val) into a stream of bytes appropriate
7890 for use in the a.out file, and stores them in the array pointed to by buf.
7891 This knows about the endian-ness of the target machine and does
7892 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
7893 2 (short) and 4 (long) Floating numbers are put out as a series of
7894 LITTLENUMS (shorts, here at least). */
7897 md_number_to_chars (buf
, val
, n
)
7902 if (target_big_endian
)
7903 number_to_chars_bigendian (buf
, val
, n
);
7905 number_to_chars_littleendian (buf
, val
, n
);
7909 md_chars_to_number (buf
, n
)
7914 unsigned char * where
= (unsigned char *) buf
;
7916 if (target_big_endian
)
7921 result
|= (*where
++ & 255);
7929 result
|= (where
[n
] & 255);
7936 /* Turn a string in input_line_pointer into a floating point constant
7937 of type TYPE, and store the appropriate bytes in *LITP. The number
7938 of LITTLENUMS emitted is stored in *SIZEP. An error message is
7939 returned, or NULL on OK.
7941 Note that fp constants aren't represent in the normal way on the ARM.
7942 In big endian mode, things are as expected. However, in little endian
7943 mode fp constants are big-endian word-wise, and little-endian byte-wise
7944 within the words. For example, (double) 1.1 in big endian mode is
7945 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
7946 the byte sequence 99 99 f1 3f 9a 99 99 99.
7948 ??? The format of 12 byte floats is uncertain according to gcc's arm.h. */
7951 md_atof (type
, litP
, sizeP
)
7957 LITTLENUM_TYPE words
[MAX_LITTLENUMS
];
7989 return _("Bad call to MD_ATOF()");
7992 t
= atof_ieee (input_line_pointer
, type
, words
);
7994 input_line_pointer
= t
;
7997 if (target_big_endian
)
7999 for (i
= 0; i
< prec
; i
++)
8001 md_number_to_chars (litP
, (valueT
) words
[i
], 2);
8007 /* For a 4 byte float the order of elements in `words' is 1 0. For an
8008 8 byte float the order is 1 0 3 2. */
8009 for (i
= 0; i
< prec
; i
+= 2)
8011 md_number_to_chars (litP
, (valueT
) words
[i
+ 1], 2);
8012 md_number_to_chars (litP
+ 2, (valueT
) words
[i
], 2);
8020 /* The knowledge of the PC's pipeline offset is built into the insns
8024 md_pcrel_from (fixP
)
8028 && S_GET_SEGMENT (fixP
->fx_addsy
) == undefined_section
8029 && fixP
->fx_subsy
== NULL
)
8032 if (fixP
->fx_pcrel
&& (fixP
->fx_r_type
== BFD_RELOC_ARM_THUMB_ADD
))
8034 /* PC relative addressing on the Thumb is slightly odd
8035 as the bottom two bits of the PC are forced to zero
8036 for the calculation. */
8037 return (fixP
->fx_where
+ fixP
->fx_frag
->fr_address
) & ~3;
8041 /* The pattern was adjusted to accomodate CE's off-by-one fixups,
8042 so we un-adjust here to compensate for the accomodation. */
8043 return fixP
->fx_where
+ fixP
->fx_frag
->fr_address
+ 8;
8045 return fixP
->fx_where
+ fixP
->fx_frag
->fr_address
;
8049 /* Round up a section size to the appropriate boundary. */
8052 md_section_align (segment
, size
)
8053 segT segment ATTRIBUTE_UNUSED
;
8059 /* Round all sects to multiple of 4. */
8060 return (size
+ 3) & ~3;
8064 /* Under ELF we need to default _GLOBAL_OFFSET_TABLE.
8065 Otherwise we have no need to default values of symbols. */
8068 md_undefined_symbol (name
)
8069 char * name ATTRIBUTE_UNUSED
;
8072 if (name
[0] == '_' && name
[1] == 'G'
8073 && streq (name
, GLOBAL_OFFSET_TABLE_NAME
))
8077 if (symbol_find (name
))
8078 as_bad ("GOT already in the symbol table");
8080 GOT_symbol
= symbol_new (name
, undefined_section
,
8081 (valueT
) 0, & zero_address_frag
);
8091 /* arm_reg_parse () := if it looks like a register, return its token and
8092 advance the pointer. */
8096 register char ** ccp
;
8098 char * start
= * ccp
;
8101 struct reg_entry
* reg
;
8103 #ifdef REGISTER_PREFIX
8104 if (*start
!= REGISTER_PREFIX
)
8109 #ifdef OPTIONAL_REGISTER_PREFIX
8110 if (*p
== OPTIONAL_REGISTER_PREFIX
)
8114 if (!ISALPHA (*p
) || !is_name_beginner (*p
))
8118 while (ISALPHA (c
) || ISDIGIT (c
) || c
== '_')
8122 reg
= (struct reg_entry
*) hash_find (arm_reg_hsh
, start
);
8135 md_apply_fix3 (fixP
, valP
, seg
)
8140 offsetT value
= * valP
;
8142 unsigned int newimm
;
8145 char * buf
= fixP
->fx_where
+ fixP
->fx_frag
->fr_literal
;
8146 arm_fix_data
* arm_data
= (arm_fix_data
*) fixP
->tc_fix_data
;
8148 assert (fixP
->fx_r_type
< BFD_RELOC_UNUSED
);
8150 /* Note whether this will delete the relocation. */
8152 /* Patch from REarnshaw to JDavis (disabled for the moment, since it
8153 doesn't work fully.) */
8154 if ((fixP
->fx_addsy
== 0 || symbol_constant_p (fixP
->fx_addsy
))
8157 if (fixP
->fx_addsy
== 0 && !fixP
->fx_pcrel
)
8161 /* If this symbol is in a different section then we need to leave it for
8162 the linker to deal with. Unfortunately, md_pcrel_from can't tell,
8163 so we have to undo it's effects here. */
8166 if (fixP
->fx_addsy
!= NULL
8167 && S_IS_DEFINED (fixP
->fx_addsy
)
8168 && S_GET_SEGMENT (fixP
->fx_addsy
) != seg
)
8171 && (fixP
->fx_r_type
== BFD_RELOC_ARM_PCREL_BRANCH
8172 || fixP
->fx_r_type
== BFD_RELOC_ARM_PCREL_BLX
8176 value
+= md_pcrel_from (fixP
);
8180 /* Remember value for emit_reloc. */
8181 fixP
->fx_addnumber
= value
;
8183 switch (fixP
->fx_r_type
)
8185 case BFD_RELOC_ARM_IMMEDIATE
:
8186 newimm
= validate_immediate (value
);
8187 temp
= md_chars_to_number (buf
, INSN_SIZE
);
8189 /* If the instruction will fail, see if we can fix things up by
8190 changing the opcode. */
8191 if (newimm
== (unsigned int) FAIL
8192 && (newimm
= negate_data_op (&temp
, value
)) == (unsigned int) FAIL
)
8194 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
8195 _("invalid constant (%lx) after fixup"),
8196 (unsigned long) value
);
8200 newimm
|= (temp
& 0xfffff000);
8201 md_number_to_chars (buf
, (valueT
) newimm
, INSN_SIZE
);
8204 case BFD_RELOC_ARM_ADRL_IMMEDIATE
:
8206 unsigned int highpart
= 0;
8207 unsigned int newinsn
= 0xe1a00000; /* nop. */
8208 newimm
= validate_immediate (value
);
8209 temp
= md_chars_to_number (buf
, INSN_SIZE
);
8211 /* If the instruction will fail, see if we can fix things up by
8212 changing the opcode. */
8213 if (newimm
== (unsigned int) FAIL
8214 && (newimm
= negate_data_op (& temp
, value
)) == (unsigned int) FAIL
)
8216 /* No ? OK - try using two ADD instructions to generate
8218 newimm
= validate_immediate_twopart (value
, & highpart
);
8220 /* Yes - then make sure that the second instruction is
8222 if (newimm
!= (unsigned int) FAIL
)
8224 /* Still No ? Try using a negated value. */
8225 else if ((newimm
= validate_immediate_twopart (- value
, & highpart
)) != (unsigned int) FAIL
)
8226 temp
= newinsn
= (temp
& OPCODE_MASK
) | OPCODE_SUB
<< DATA_OP_SHIFT
;
8227 /* Otherwise - give up. */
8230 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
8231 _("Unable to compute ADRL instructions for PC offset of 0x%lx"),
8236 /* Replace the first operand in the 2nd instruction (which
8237 is the PC) with the destination register. We have
8238 already added in the PC in the first instruction and we
8239 do not want to do it again. */
8240 newinsn
&= ~ 0xf0000;
8241 newinsn
|= ((newinsn
& 0x0f000) << 4);
8244 newimm
|= (temp
& 0xfffff000);
8245 md_number_to_chars (buf
, (valueT
) newimm
, INSN_SIZE
);
8247 highpart
|= (newinsn
& 0xfffff000);
8248 md_number_to_chars (buf
+ INSN_SIZE
, (valueT
) highpart
, INSN_SIZE
);
8252 case BFD_RELOC_ARM_OFFSET_IMM
:
8258 if (validate_offset_imm (value
, 0) == FAIL
)
8260 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
8261 _("bad immediate value for offset (%ld)"),
8266 newval
= md_chars_to_number (buf
, INSN_SIZE
);
8267 newval
&= 0xff7ff000;
8268 newval
|= value
| (sign
? INDEX_UP
: 0);
8269 md_number_to_chars (buf
, newval
, INSN_SIZE
);
8272 case BFD_RELOC_ARM_OFFSET_IMM8
:
8273 case BFD_RELOC_ARM_HWLITERAL
:
8279 if (validate_offset_imm (value
, 1) == FAIL
)
8281 if (fixP
->fx_r_type
== BFD_RELOC_ARM_HWLITERAL
)
8282 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
8283 _("invalid literal constant: pool needs to be closer"));
8285 as_bad (_("bad immediate value for half-word offset (%ld)"),
8290 newval
= md_chars_to_number (buf
, INSN_SIZE
);
8291 newval
&= 0xff7ff0f0;
8292 newval
|= ((value
>> 4) << 8) | (value
& 0xf) | (sign
? INDEX_UP
: 0);
8293 md_number_to_chars (buf
, newval
, INSN_SIZE
);
8296 case BFD_RELOC_ARM_LITERAL
:
8302 if (validate_offset_imm (value
, 0) == FAIL
)
8304 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
8305 _("invalid literal constant: pool needs to be closer"));
8309 newval
= md_chars_to_number (buf
, INSN_SIZE
);
8310 newval
&= 0xff7ff000;
8311 newval
|= value
| (sign
? INDEX_UP
: 0);
8312 md_number_to_chars (buf
, newval
, INSN_SIZE
);
8315 case BFD_RELOC_ARM_SHIFT_IMM
:
8316 newval
= md_chars_to_number (buf
, INSN_SIZE
);
8317 if (((unsigned long) value
) > 32
8319 && (((newval
& 0x60) == 0) || (newval
& 0x60) == 0x60)))
8321 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
8322 _("shift expression is too large"));
8327 /* Shifts of zero must be done as lsl. */
8329 else if (value
== 32)
8331 newval
&= 0xfffff07f;
8332 newval
|= (value
& 0x1f) << 7;
8333 md_number_to_chars (buf
, newval
, INSN_SIZE
);
8336 case BFD_RELOC_ARM_SWI
:
8337 if (arm_data
->thumb_mode
)
8339 if (((unsigned long) value
) > 0xff)
8340 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
8341 _("Invalid swi expression"));
8342 newval
= md_chars_to_number (buf
, THUMB_SIZE
) & 0xff00;
8344 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
8348 if (((unsigned long) value
) > 0x00ffffff)
8349 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
8350 _("Invalid swi expression"));
8351 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff000000;
8353 md_number_to_chars (buf
, newval
, INSN_SIZE
);
8357 case BFD_RELOC_ARM_MULTI
:
8358 if (((unsigned long) value
) > 0xffff)
8359 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
8360 _("Invalid expression in load/store multiple"));
8361 newval
= value
| md_chars_to_number (buf
, INSN_SIZE
);
8362 md_number_to_chars (buf
, newval
, INSN_SIZE
);
8365 case BFD_RELOC_ARM_PCREL_BRANCH
:
8366 newval
= md_chars_to_number (buf
, INSN_SIZE
);
8368 /* Sign-extend a 24-bit number. */
8369 #define SEXT24(x) ((((x) & 0xffffff) ^ (~ 0x7fffff)) + 0x800000)
8373 value
= fixP
->fx_offset
;
8376 /* We are going to store value (shifted right by two) in the
8377 instruction, in a 24 bit, signed field. Thus we need to check
8378 that none of the top 8 bits of the shifted value (top 7 bits of
8379 the unshifted, unsigned value) are set, or that they are all set. */
8380 if ((value
& ~ ((offsetT
) 0x1ffffff)) != 0
8381 && ((value
& ~ ((offsetT
) 0x1ffffff)) != ~ ((offsetT
) 0x1ffffff)))
8384 /* Normally we would be stuck at this point, since we cannot store
8385 the absolute address that is the destination of the branch in the
8386 24 bits of the branch instruction. If however, we happen to know
8387 that the destination of the branch is in the same section as the
8388 branch instruciton itself, then we can compute the relocation for
8389 ourselves and not have to bother the linker with it.
8391 FIXME: The tests for OBJ_ELF and ! target_oabi are only here
8392 because I have not worked out how to do this for OBJ_COFF or
8395 && fixP
->fx_addsy
!= NULL
8396 && S_IS_DEFINED (fixP
->fx_addsy
)
8397 && S_GET_SEGMENT (fixP
->fx_addsy
) == seg
)
8399 /* Get pc relative value to go into the branch. */
8402 /* Permit a backward branch provided that enough bits
8403 are set. Allow a forwards branch, provided that
8404 enough bits are clear. */
8405 if ( (value
& ~ ((offsetT
) 0x1ffffff)) == ~ ((offsetT
) 0x1ffffff)
8406 || (value
& ~ ((offsetT
) 0x1ffffff)) == 0)
8410 if (! fixP
->fx_done
)
8412 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
8413 _("gas can't handle same-section branch dest >= 0x04000000"));
8417 value
+= SEXT24 (newval
);
8419 if ( (value
& ~ ((offsetT
) 0xffffff)) != 0
8420 && ((value
& ~ ((offsetT
) 0xffffff)) != ~ ((offsetT
) 0xffffff)))
8421 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
8422 _("out of range branch"));
8424 newval
= (value
& 0x00ffffff) | (newval
& 0xff000000);
8425 md_number_to_chars (buf
, newval
, INSN_SIZE
);
8428 case BFD_RELOC_ARM_PCREL_BLX
:
8431 newval
= md_chars_to_number (buf
, INSN_SIZE
);
8435 value
= fixP
->fx_offset
;
8437 hbit
= (value
>> 1) & 1;
8438 value
= (value
>> 2) & 0x00ffffff;
8439 value
= (value
+ (newval
& 0x00ffffff)) & 0x00ffffff;
8440 newval
= value
| (newval
& 0xfe000000) | (hbit
<< 24);
8441 md_number_to_chars (buf
, newval
, INSN_SIZE
);
8445 case BFD_RELOC_THUMB_PCREL_BRANCH9
: /* Conditional branch. */
8446 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
8448 addressT diff
= (newval
& 0xff) << 1;
8453 if ((value
& ~0xff) && ((value
& ~0xff) != ~0xff))
8454 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
8455 _("Branch out of range"));
8456 newval
= (newval
& 0xff00) | ((value
& 0x1ff) >> 1);
8458 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
8461 case BFD_RELOC_THUMB_PCREL_BRANCH12
: /* Unconditional branch. */
8462 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
8464 addressT diff
= (newval
& 0x7ff) << 1;
8469 if ((value
& ~0x7ff) && ((value
& ~0x7ff) != ~0x7ff))
8470 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
8471 _("Branch out of range"));
8472 newval
= (newval
& 0xf800) | ((value
& 0xfff) >> 1);
8474 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
8477 case BFD_RELOC_THUMB_PCREL_BLX
:
8478 case BFD_RELOC_THUMB_PCREL_BRANCH23
:
8483 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
8484 newval2
= md_chars_to_number (buf
+ THUMB_SIZE
, THUMB_SIZE
);
8485 diff
= ((newval
& 0x7ff) << 12) | ((newval2
& 0x7ff) << 1);
8486 if (diff
& 0x400000)
8489 value
= fixP
->fx_offset
;
8492 if ((value
& ~0x3fffff) && ((value
& ~0x3fffff) != ~0x3fffff))
8493 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
8494 _("Branch with link out of range"));
8496 newval
= (newval
& 0xf800) | ((value
& 0x7fffff) >> 12);
8497 newval2
= (newval2
& 0xf800) | ((value
& 0xfff) >> 1);
8498 if (fixP
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BLX
)
8499 /* Remove bit zero of the adjusted offset. Bit zero can only be
8500 set if the upper insn is at a half-word boundary, since the
8501 destination address, an ARM instruction, must always be on a
8502 word boundary. The semantics of the BLX (1) instruction, however,
8503 are that bit zero in the offset must always be zero, and the
8504 corresponding bit one in the target address will be set from bit
8505 one of the source address. */
8507 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
8508 md_number_to_chars (buf
+ THUMB_SIZE
, newval2
, THUMB_SIZE
);
8513 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
8514 md_number_to_chars (buf
, value
, 1);
8516 else if (!target_oabi
)
8518 value
= fixP
->fx_offset
;
8519 md_number_to_chars (buf
, value
, 1);
8525 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
8526 md_number_to_chars (buf
, value
, 2);
8528 else if (!target_oabi
)
8530 value
= fixP
->fx_offset
;
8531 md_number_to_chars (buf
, value
, 2);
8537 case BFD_RELOC_ARM_GOT32
:
8538 case BFD_RELOC_ARM_GOTOFF
:
8539 md_number_to_chars (buf
, 0, 4);
8545 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
8546 md_number_to_chars (buf
, value
, 4);
8548 else if (!target_oabi
)
8550 value
= fixP
->fx_offset
;
8551 md_number_to_chars (buf
, value
, 4);
8557 case BFD_RELOC_ARM_PLT32
:
8558 /* It appears the instruction is fully prepared at this point. */
8562 case BFD_RELOC_ARM_GOTPC
:
8563 md_number_to_chars (buf
, value
, 4);
8566 case BFD_RELOC_ARM_CP_OFF_IMM
:
8568 if (value
< -1023 || value
> 1023 || (value
& 3))
8569 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
8570 _("Illegal value for co-processor offset"));
8573 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff7fff00;
8574 newval
|= (value
>> 2) | (sign
? INDEX_UP
: 0);
8575 md_number_to_chars (buf
, newval
, INSN_SIZE
);
8578 case BFD_RELOC_ARM_THUMB_OFFSET
:
8579 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
8580 /* Exactly what ranges, and where the offset is inserted depends
8581 on the type of instruction, we can establish this from the
8583 switch (newval
>> 12)
8585 case 4: /* PC load. */
8586 /* Thumb PC loads are somewhat odd, bit 1 of the PC is
8587 forced to zero for these loads, so we will need to round
8588 up the offset if the instruction address is not word
8589 aligned (since the final address produced must be, and
8590 we can only describe word-aligned immediate offsets). */
8592 if ((fixP
->fx_frag
->fr_address
+ fixP
->fx_where
+ value
) & 3)
8593 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
8594 _("Invalid offset, target not word aligned (0x%08X)"),
8595 (unsigned int) (fixP
->fx_frag
->fr_address
8596 + fixP
->fx_where
+ value
));
8598 if ((value
+ 2) & ~0x3fe)
8599 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
8600 _("Invalid offset, value too big (0x%08lX)"), value
);
8602 /* Round up, since pc will be rounded down. */
8603 newval
|= (value
+ 2) >> 2;
8606 case 9: /* SP load/store. */
8608 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
8609 _("Invalid offset, value too big (0x%08lX)"), value
);
8610 newval
|= value
>> 2;
8613 case 6: /* Word load/store. */
8615 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
8616 _("Invalid offset, value too big (0x%08lX)"), value
);
8617 newval
|= value
<< 4; /* 6 - 2. */
8620 case 7: /* Byte load/store. */
8622 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
8623 _("Invalid offset, value too big (0x%08lX)"), value
);
8624 newval
|= value
<< 6;
8627 case 8: /* Halfword load/store. */
8629 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
8630 _("Invalid offset, value too big (0x%08lX)"), value
);
8631 newval
|= value
<< 5; /* 6 - 1. */
8635 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
8636 "Unable to process relocation for thumb opcode: %lx",
8637 (unsigned long) newval
);
8640 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
8643 case BFD_RELOC_ARM_THUMB_ADD
:
8644 /* This is a complicated relocation, since we use it for all of
8645 the following immediate relocations:
8649 9bit ADD/SUB SP word-aligned
8650 10bit ADD PC/SP word-aligned
8652 The type of instruction being processed is encoded in the
8659 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
8661 int rd
= (newval
>> 4) & 0xf;
8662 int rs
= newval
& 0xf;
8663 int subtract
= newval
& 0x8000;
8668 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
8669 _("Invalid immediate for stack address calculation"));
8670 newval
= subtract
? T_OPCODE_SUB_ST
: T_OPCODE_ADD_ST
;
8671 newval
|= value
>> 2;
8673 else if (rs
== REG_PC
|| rs
== REG_SP
)
8677 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
8678 _("Invalid immediate for address calculation (value = 0x%08lX)"),
8679 (unsigned long) value
);
8680 newval
= (rs
== REG_PC
? T_OPCODE_ADD_PC
: T_OPCODE_ADD_SP
);
8682 newval
|= value
>> 2;
8687 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
8688 _("Invalid 8bit immediate"));
8689 newval
= subtract
? T_OPCODE_SUB_I8
: T_OPCODE_ADD_I8
;
8690 newval
|= (rd
<< 8) | value
;
8695 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
8696 _("Invalid 3bit immediate"));
8697 newval
= subtract
? T_OPCODE_SUB_I3
: T_OPCODE_ADD_I3
;
8698 newval
|= rd
| (rs
<< 3) | (value
<< 6);
8701 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
8704 case BFD_RELOC_ARM_THUMB_IMM
:
8705 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
8706 switch (newval
>> 11)
8708 case 0x04: /* 8bit immediate MOV. */
8709 case 0x05: /* 8bit immediate CMP. */
8710 if (value
< 0 || value
> 255)
8711 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
8712 _("Invalid immediate: %ld is too large"),
8720 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
8723 case BFD_RELOC_ARM_THUMB_SHIFT
:
8724 /* 5bit shift value (0..31). */
8725 if (value
< 0 || value
> 31)
8726 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
8727 _("Illegal Thumb shift value: %ld"), (long) value
);
8728 newval
= md_chars_to_number (buf
, THUMB_SIZE
) & 0xf03f;
8729 newval
|= value
<< 6;
8730 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
8733 case BFD_RELOC_VTABLE_INHERIT
:
8734 case BFD_RELOC_VTABLE_ENTRY
:
8738 case BFD_RELOC_NONE
:
8740 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
8741 _("Bad relocation fixup type (%d)"), fixP
->fx_r_type
);
8745 /* Translate internal representation of relocation info to BFD target
8749 tc_gen_reloc (section
, fixp
)
8750 asection
* section ATTRIBUTE_UNUSED
;
8754 bfd_reloc_code_real_type code
;
8756 reloc
= (arelent
*) xmalloc (sizeof (arelent
));
8758 reloc
->sym_ptr_ptr
= (asymbol
**) xmalloc (sizeof (asymbol
*));
8759 *reloc
->sym_ptr_ptr
= symbol_get_bfdsym (fixp
->fx_addsy
);
8760 reloc
->address
= fixp
->fx_frag
->fr_address
+ fixp
->fx_where
;
8762 /* @@ Why fx_addnumber sometimes and fx_offset other times? */
8764 if (fixp
->fx_pcrel
== 0)
8765 reloc
->addend
= fixp
->fx_offset
;
8767 reloc
->addend
= fixp
->fx_offset
= reloc
->address
;
8769 reloc
->addend
= fixp
->fx_offset
;
8772 switch (fixp
->fx_r_type
)
8777 code
= BFD_RELOC_8_PCREL
;
8784 code
= BFD_RELOC_16_PCREL
;
8791 code
= BFD_RELOC_32_PCREL
;
8795 case BFD_RELOC_ARM_PCREL_BRANCH
:
8796 case BFD_RELOC_ARM_PCREL_BLX
:
8798 case BFD_RELOC_THUMB_PCREL_BRANCH9
:
8799 case BFD_RELOC_THUMB_PCREL_BRANCH12
:
8800 case BFD_RELOC_THUMB_PCREL_BRANCH23
:
8801 case BFD_RELOC_THUMB_PCREL_BLX
:
8802 case BFD_RELOC_VTABLE_ENTRY
:
8803 case BFD_RELOC_VTABLE_INHERIT
:
8804 code
= fixp
->fx_r_type
;
8807 case BFD_RELOC_ARM_LITERAL
:
8808 case BFD_RELOC_ARM_HWLITERAL
:
8809 /* If this is called then the a literal has been referenced across
8810 a section boundary - possibly due to an implicit dump. */
8811 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
8812 _("Literal referenced across section boundary (Implicit dump?)"));
8816 case BFD_RELOC_ARM_GOT32
:
8817 case BFD_RELOC_ARM_GOTOFF
:
8818 case BFD_RELOC_ARM_PLT32
:
8819 code
= fixp
->fx_r_type
;
8823 case BFD_RELOC_ARM_IMMEDIATE
:
8824 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
8825 _("Internal_relocation (type %d) not fixed up (IMMEDIATE)"),
8829 case BFD_RELOC_ARM_ADRL_IMMEDIATE
:
8830 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
8831 _("ADRL used for a symbol not defined in the same file"));
8834 case BFD_RELOC_ARM_OFFSET_IMM
:
8835 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
8836 _("Internal_relocation (type %d) not fixed up (OFFSET_IMM)"),
8844 switch (fixp
->fx_r_type
)
8846 case BFD_RELOC_ARM_IMMEDIATE
: type
= "IMMEDIATE"; break;
8847 case BFD_RELOC_ARM_OFFSET_IMM
: type
= "OFFSET_IMM"; break;
8848 case BFD_RELOC_ARM_OFFSET_IMM8
: type
= "OFFSET_IMM8"; break;
8849 case BFD_RELOC_ARM_SHIFT_IMM
: type
= "SHIFT_IMM"; break;
8850 case BFD_RELOC_ARM_SWI
: type
= "SWI"; break;
8851 case BFD_RELOC_ARM_MULTI
: type
= "MULTI"; break;
8852 case BFD_RELOC_ARM_CP_OFF_IMM
: type
= "CP_OFF_IMM"; break;
8853 case BFD_RELOC_ARM_THUMB_ADD
: type
= "THUMB_ADD"; break;
8854 case BFD_RELOC_ARM_THUMB_SHIFT
: type
= "THUMB_SHIFT"; break;
8855 case BFD_RELOC_ARM_THUMB_IMM
: type
= "THUMB_IMM"; break;
8856 case BFD_RELOC_ARM_THUMB_OFFSET
: type
= "THUMB_OFFSET"; break;
8857 default: type
= _("<unknown>"); break;
8859 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
8860 _("Cannot represent %s relocation in this object file format"),
8867 if (code
== BFD_RELOC_32_PCREL
8869 && fixp
->fx_addsy
== GOT_symbol
)
8871 code
= BFD_RELOC_ARM_GOTPC
;
8872 reloc
->addend
= fixp
->fx_offset
= reloc
->address
;
8876 reloc
->howto
= bfd_reloc_type_lookup (stdoutput
, code
);
8878 if (reloc
->howto
== NULL
)
8880 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
8881 _("Can not represent %s relocation in this object file format"),
8882 bfd_get_reloc_code_name (code
));
8886 /* HACK: Since arm ELF uses Rel instead of Rela, encode the
8887 vtable entry to be used in the relocation's section offset. */
8888 if (fixp
->fx_r_type
== BFD_RELOC_VTABLE_ENTRY
)
8889 reloc
->address
= fixp
->fx_offset
;
8895 md_estimate_size_before_relax (fragP
, segtype
)
8896 fragS
* fragP ATTRIBUTE_UNUSED
;
8897 segT segtype ATTRIBUTE_UNUSED
;
8899 as_fatal (_("md_estimate_size_before_relax\n"));
8904 output_inst
PARAMS ((void))
8910 as_bad (inst
.error
);
8914 to
= frag_more (inst
.size
);
8916 if (thumb_mode
&& (inst
.size
> THUMB_SIZE
))
8918 assert (inst
.size
== (2 * THUMB_SIZE
));
8919 md_number_to_chars (to
, inst
.instruction
>> 16, THUMB_SIZE
);
8920 md_number_to_chars (to
+ THUMB_SIZE
, inst
.instruction
, THUMB_SIZE
);
8922 else if (inst
.size
> INSN_SIZE
)
8924 assert (inst
.size
== (2 * INSN_SIZE
));
8925 md_number_to_chars (to
, inst
.instruction
, INSN_SIZE
);
8926 md_number_to_chars (to
+ INSN_SIZE
, inst
.instruction
, INSN_SIZE
);
8929 md_number_to_chars (to
, inst
.instruction
, inst
.size
);
8931 if (inst
.reloc
.type
!= BFD_RELOC_NONE
)
8932 fix_new_arm (frag_now
, to
- frag_now
->fr_literal
,
8933 inst
.size
, & inst
.reloc
.exp
, inst
.reloc
.pc_rel
,
8937 dwarf2_emit_insn (inst
.size
);
8950 /* Align the instruction.
8951 This may not be the right thing to do but ... */
8955 listing_prev_line (); /* Defined in listing.h. */
8957 /* Align the previous label if needed. */
8958 if (last_label_seen
!= NULL
)
8960 symbol_set_frag (last_label_seen
, frag_now
);
8961 S_SET_VALUE (last_label_seen
, (valueT
) frag_now_fix ());
8962 S_SET_SEGMENT (last_label_seen
, now_seg
);
8965 memset (&inst
, '\0', sizeof (inst
));
8966 inst
.reloc
.type
= BFD_RELOC_NONE
;
8968 skip_whitespace (str
);
8970 /* Scan up to the end of the op-code, which must end in white space or
8972 for (start
= p
= str
; *p
!= '\0'; p
++)
8978 as_bad (_("No operator -- statement `%s'\n"), str
);
8984 const struct thumb_opcode
* opcode
;
8988 opcode
= (const struct thumb_opcode
*) hash_find (arm_tops_hsh
, str
);
8993 /* Check that this instruction is supported for this CPU. */
8994 if (thumb_mode
== 1 && (opcode
->variant
& cpu_variant
) == 0)
8996 as_bad (_("selected processor does not support this opcode"));
9000 inst
.instruction
= opcode
->value
;
9001 inst
.size
= opcode
->size
;
9002 (*opcode
->parms
) (p
);
9009 const struct asm_opcode
* opcode
;
9013 opcode
= (CONST
struct asm_opcode
*) hash_find (arm_ops_hsh
, str
);
9018 /* Check that this instruction is supported for this CPU. */
9019 if ((opcode
->variant
& cpu_variant
) == 0)
9021 as_bad (_("selected processor does not support this opcode"));
9025 inst
.instruction
= opcode
->value
;
9026 inst
.size
= INSN_SIZE
;
9027 (*opcode
->parms
) (p
, 0);
9033 /* It wasn't an instruction, but it might be a register alias of the form
9036 skip_whitespace (q
);
9041 if (*q
&& !strncmp (q
, ".req ", 4))
9047 #ifdef IGNORE_OPCODE_CASE
9048 str
= original_case_string
;
9053 skip_whitespace (q
);
9055 for (r
= q
; *r
!= '\0'; r
++)
9065 regnum
= arm_reg_parse (& q
);
9068 reg
= arm_reg_parse (& str
);
9073 insert_reg_alias (str
, regnum
);
9075 as_warn (_("register '%s' does not exist\n"), q
);
9077 else if (regnum
!= FAIL
)
9080 as_warn (_("ignoring redefinition of register alias '%s'"),
9083 /* Do not warn about redefinitions to the same alias. */
9086 as_warn (_("ignoring redefinition of register alias '%s' to non-existant register '%s'"),
9090 as_warn (_("ignoring incomplete .req pseuso op"));
9097 as_bad (_("bad instruction `%s'"), start
);
9101 Invocation line includes a switch not recognized by the base assembler.
9102 See if it's a processor-specific option. These are:
9103 Cpu variants, the arm part is optional:
9104 -m[arm]1 Currently not supported.
9105 -m[arm]2, -m[arm]250 Arm 2 and Arm 250 processor
9106 -m[arm]3 Arm 3 processor
9107 -m[arm]6[xx], Arm 6 processors
9108 -m[arm]7[xx][t][[d]m] Arm 7 processors
9109 -m[arm]8[10] Arm 8 processors
9110 -m[arm]9[20][tdmi] Arm 9 processors
9111 -marm9e Allow Cirrus/DSP instructions
9112 -mstrongarm[110[0]] StrongARM processors
9113 -mxscale XScale processors
9114 -m[arm]v[2345[t[e]]] Arm architectures
9115 -mall All (except the ARM1)
9117 -mfpa10, -mfpa11 FPA10 and 11 co-processor instructions
9118 -mfpe-old (No float load/store multiples)
9119 -mno-fpu Disable all floating point instructions
9120 Run-time endian selection:
9122 -EL little endian cpu
9123 ARM Procedure Calling Standard:
9124 -mapcs-32 32 bit APCS
9125 -mapcs-26 26 bit APCS
9126 -mapcs-float Pass floats in float regs
9127 -mapcs-reentrant Position independent code
9128 -mthumb-interwork Code supports Arm/Thumb interworking
9129 -matpcs ARM/Thumb Procedure Call Standard
9130 -moabi Old ELF ABI */
9132 const char * md_shortopts
= "m:k";
9134 struct option md_longopts
[] =
9136 #ifdef ARM_BI_ENDIAN
9137 #define OPTION_EB (OPTION_MD_BASE + 0)
9138 {"EB", no_argument
, NULL
, OPTION_EB
},
9139 #define OPTION_EL (OPTION_MD_BASE + 1)
9140 {"EL", no_argument
, NULL
, OPTION_EL
},
9142 #define OPTION_OABI (OPTION_MD_BASE +2)
9143 {"oabi", no_argument
, NULL
, OPTION_OABI
},
9146 {NULL
, no_argument
, NULL
, 0}
9149 size_t md_longopts_size
= sizeof (md_longopts
);
9152 md_parse_option (c
, arg
)
9160 #ifdef ARM_BI_ENDIAN
9162 target_big_endian
= 1;
9165 target_big_endian
= 0;
9173 if (streq (str
, "fpa10") || streq (str
, "fpa11"))
9174 cpu_variant
= (cpu_variant
& ~FPU_ANY
) | FPU_ARCH_FPA
;
9175 else if (streq (str
, "fpe-old"))
9176 cpu_variant
= (cpu_variant
& ~FPU_ANY
) | FPU_ARCH_FPE
;
9182 if (streq (str
, "no-fpu"))
9183 cpu_variant
&= ~FPU_ANY
;
9188 if (streq (str
, "oabi"))
9194 /* Limit assembler to generating only Thumb instructions: */
9195 if (streq (str
, "thumb"))
9197 cpu_variant
= (cpu_variant
& ~ARM_ANY
) | ARM_EXT_V4T
;
9198 cpu_variant
= (cpu_variant
& ~FPU_ANY
) | FPU_NONE
;
9201 else if (streq (str
, "thumb-interwork"))
9203 if ((cpu_variant
& ARM_EXT_V4T
) == 0)
9204 cpu_variant
= (cpu_variant
& ~ARM_ANY
) | ARM_ARCH_V4T
;
9205 #if defined OBJ_COFF || defined OBJ_ELF
9206 support_interwork
= true;
9214 if (streq (str
, "all"))
9216 cpu_variant
= ARM_ALL
| FPU_DEFAULT
;
9219 #if defined OBJ_COFF || defined OBJ_ELF
9220 if (! strncmp (str
, "apcs-", 5))
9222 /* GCC passes on all command line options starting "-mapcs-..."
9223 to us, so we must parse them here. */
9227 if (streq (str
, "32"))
9229 uses_apcs_26
= false;
9232 else if (streq (str
, "26"))
9234 uses_apcs_26
= true;
9237 else if (streq (str
, "frame"))
9239 /* Stack frames are being generated - does not affect
9243 else if (streq (str
, "stack-check"))
9245 /* Stack checking is being performed - does not affect
9246 linkage, but does require that the functions
9247 __rt_stkovf_split_small and __rt_stkovf_split_big be
9248 present in the final link. */
9252 else if (streq (str
, "float"))
9254 /* Floating point arguments are being passed in the floating
9255 point registers. This does affect linking, since this
9256 version of the APCS is incompatible with the version that
9257 passes floating points in the integer registers. */
9259 uses_apcs_float
= true;
9262 else if (streq (str
, "reentrant"))
9264 /* Reentrant code has been generated. This does affect
9265 linking, since there is no point in linking reentrant/
9266 position independent code with absolute position code. */
9271 as_bad (_("Unrecognised APCS switch -m%s"), arg
);
9275 if (! strcmp (str
, "atpcs"))
9281 /* Strip off optional "arm". */
9282 if (! strncmp (str
, "arm", 3))
9288 if (streq (str
, "1"))
9289 cpu_variant
= (cpu_variant
& ~ARM_ANY
) | ARM_1
;
9295 if (streq (str
, "2"))
9296 cpu_variant
= (cpu_variant
& ~ARM_ANY
) | ARM_2
;
9297 else if (streq (str
, "250"))
9298 cpu_variant
= (cpu_variant
& ~ARM_ANY
) | ARM_250
;
9304 if (streq (str
, "3"))
9305 cpu_variant
= (cpu_variant
& ~ARM_ANY
) | ARM_3
;
9311 switch (strtol (str
, NULL
, 10))
9318 cpu_variant
= (cpu_variant
& ~ARM_ANY
) | ARM_6
;
9326 /* Eat the processor name. */
9327 switch (strtol (str
, & str
, 10))
9340 cpu_variant
= (cpu_variant
& ~ARM_ANY
) | ARM_7
;
9346 cpu_variant
|= ARM_ARCH_V4T
;
9350 cpu_variant
|= ARM_EXT_V3M
;
9353 case 'f': /* fe => fp enabled cpu. */
9359 case 'c': /* Left over from 710c processor name. */
9360 case 'd': /* Debug. */
9361 case 'i': /* Embedded ICE. */
9362 /* Included for completeness in ARM processor naming. */
9372 if (streq (str
, "8") || streq (str
, "810"))
9373 cpu_variant
= (cpu_variant
& ~ARM_ANY
)
9374 | ARM_8
| ARM_ARCH_V4
;
9380 if (streq (str
, "9"))
9381 cpu_variant
= (cpu_variant
& ~ARM_ANY
)
9382 | ARM_9
| ARM_ARCH_V4T
;
9383 else if (streq (str
, "920"))
9384 cpu_variant
= (cpu_variant
& ~ARM_ANY
)
9385 | ARM_9
| ARM_ARCH_V4
;
9386 else if (streq (str
, "920t"))
9387 cpu_variant
= (cpu_variant
& ~ARM_ANY
)
9388 | ARM_9
| ARM_ARCH_V4T
;
9389 else if (streq (str
, "9tdmi"))
9390 cpu_variant
= (cpu_variant
& ~ARM_ANY
)
9391 | ARM_9
| ARM_ARCH_V4T
;
9392 else if (streq (str
, "9e"))
9393 cpu_variant
= (cpu_variant
& ~ARM_ANY
)
9394 | ARM_9
| ARM_ARCH_V4T
| ARM_EXT_MAVERICK
;
9400 if (streq (str
, "strongarm")
9401 || streq (str
, "strongarm110")
9402 || streq (str
, "strongarm1100"))
9403 cpu_variant
= (cpu_variant
& ~ARM_ANY
)
9404 | ARM_8
| ARM_ARCH_V4
;
9410 if (streq (str
, "xscale"))
9411 cpu_variant
= (cpu_variant
& ~ARM_ANY
)
9412 | ARM_9
| ARM_ARCH_XSCALE
;
9418 /* Select variant based on architecture rather than
9426 cpu_variant
= (cpu_variant
& ~ARM_ANY
) | ARM_3
;
9429 cpu_variant
= (cpu_variant
& ~ARM_ANY
) | ARM_2
;
9432 as_bad (_("Invalid architecture variant -m%s"), arg
);
9438 cpu_variant
= (cpu_variant
& ~ARM_ANY
) | ARM_7
;
9442 case 'm': cpu_variant
|= ARM_EXT_V3M
; break;
9445 as_bad (_("Invalid architecture variant -m%s"), arg
);
9451 cpu_variant
= (cpu_variant
& ~ARM_ANY
) | ARM_7
| ARM_ARCH_V4
;
9455 case 't': cpu_variant
|= ARM_EXT_V4T
; break;
9458 as_bad (_("Invalid architecture variant -m%s"), arg
);
9464 cpu_variant
= (cpu_variant
& ~ARM_ANY
) | ARM_9
| ARM_ARCH_V5
;
9467 case 't': cpu_variant
|= ARM_EXT_V4T
; break;
9468 case 'e': cpu_variant
|= ARM_EXT_V5E
; break;
9471 as_bad (_("Invalid architecture variant -m%s"), arg
);
9477 as_bad (_("Invalid architecture variant -m%s"), arg
);
9484 as_bad (_("Invalid processor variant -m%s"), arg
);
9490 #if defined OBJ_ELF || defined OBJ_COFF
9508 ARM Specific Assembler Options:\n\
9509 -m[arm][<processor name>] select processor variant\n\
9510 -m[arm]v[2|2a|3|3m|4|4t|5[t][e]] select architecture variant\n\
9511 -marm9e allow Cirrus/DSP instructions\n\
9512 -mthumb only allow Thumb instructions\n\
9513 -mthumb-interwork mark the assembled code as supporting interworking\n\
9514 -mall allow any instruction\n\
9515 -mfpa10, -mfpa11 select floating point architecture\n\
9516 -mfpe-old don't allow floating-point multiple instructions\n\
9517 -mno-fpu don't allow any floating-point instructions.\n\
9518 -k generate PIC code.\n"));
9519 #if defined OBJ_COFF || defined OBJ_ELF
9521 -mapcs-32, -mapcs-26 specify which ARM Procedure Calling Standard to use\n\
9522 -matpcs use ARM/Thumb Procedure Calling Standard\n\
9523 -mapcs-float floating point args are passed in FP regs\n\
9524 -mapcs-reentrant the code is position independent/reentrant\n"));
9528 -moabi support the old ELF ABI\n"));
9530 #ifdef ARM_BI_ENDIAN
9532 -EB assemble code for a big endian cpu\n\
9533 -EL assemble code for a little endian cpu\n"));
9537 /* We need to be able to fix up arbitrary expressions in some statements.
9538 This is so that we can handle symbols that are an arbitrary distance from
9539 the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
9540 which returns part of an address in a form which will be valid for
9541 a data instruction. We do this by pushing the expression into a symbol
9542 in the expr_section, and creating a fix for that. */
9545 fix_new_arm (frag
, where
, size
, exp
, pc_rel
, reloc
)
9554 arm_fix_data
* arm_data
;
9562 new_fix
= fix_new_exp (frag
, where
, size
, exp
, pc_rel
, reloc
);
9566 new_fix
= fix_new (frag
, where
, size
, make_expr_symbol (exp
), 0,
9571 /* Mark whether the fix is to a THUMB instruction, or an ARM
9573 arm_data
= (arm_fix_data
*) obstack_alloc (& notes
, sizeof (arm_fix_data
));
9574 new_fix
->tc_fix_data
= (PTR
) arm_data
;
9575 arm_data
->thumb_mode
= thumb_mode
;
9580 /* This fix_new is called by cons via TC_CONS_FIX_NEW. */
9583 cons_fix_new_arm (frag
, where
, size
, exp
)
9589 bfd_reloc_code_real_type type
;
9593 FIXME: @@ Should look at CPU word size. */
9600 type
= BFD_RELOC_16
;
9604 type
= BFD_RELOC_32
;
9607 type
= BFD_RELOC_64
;
9611 fix_new_exp (frag
, where
, (int) size
, exp
, pcrel
, type
);
9614 /* A good place to do this, although this was probably not intended
9615 for this kind of use. We need to dump the literal pool before
9616 references are made to a null symbol pointer. */
9621 if (current_poolP
== NULL
)
9624 /* Put it at the end of text section. */
9625 subseg_set (text_section
, 0);
9627 listing_prev_line ();
9631 arm_start_line_hook ()
9633 last_label_seen
= NULL
;
9637 arm_frob_label (sym
)
9640 last_label_seen
= sym
;
9642 ARM_SET_THUMB (sym
, thumb_mode
);
9644 #if defined OBJ_COFF || defined OBJ_ELF
9645 ARM_SET_INTERWORK (sym
, support_interwork
);
9648 /* Note - do not allow local symbols (.Lxxx) to be labeled
9649 as Thumb functions. This is because these labels, whilst
9650 they exist inside Thumb code, are not the entry points for
9651 possible ARM->Thumb calls. Also, these labels can be used
9652 as part of a computed goto or switch statement. eg gcc
9653 can generate code that looks like this:
9665 The first instruction loads the address of the jump table.
9666 The second instruction converts a table index into a byte offset.
9667 The third instruction gets the jump address out of the table.
9668 The fourth instruction performs the jump.
9670 If the address stored at .Laaa is that of a symbol which has the
9671 Thumb_Func bit set, then the linker will arrange for this address
9672 to have the bottom bit set, which in turn would mean that the
9673 address computation performed by the third instruction would end
9674 up with the bottom bit set. Since the ARM is capable of unaligned
9675 word loads, the instruction would then load the incorrect address
9676 out of the jump table, and chaos would ensue. */
9677 if (label_is_thumb_function_name
9678 && (S_GET_NAME (sym
)[0] != '.' || S_GET_NAME (sym
)[1] != 'L')
9679 && (bfd_get_section_flags (stdoutput
, now_seg
) & SEC_CODE
) != 0)
9681 /* When the address of a Thumb function is taken the bottom
9682 bit of that address should be set. This will allow
9683 interworking between Arm and Thumb functions to work
9686 THUMB_SET_FUNC (sym
, 1);
9688 label_is_thumb_function_name
= false;
9692 /* Adjust the symbol table. This marks Thumb symbols as distinct from
9696 arm_adjust_symtab ()
9701 for (sym
= symbol_rootP
; sym
!= NULL
; sym
= symbol_next (sym
))
9703 if (ARM_IS_THUMB (sym
))
9705 if (THUMB_IS_FUNC (sym
))
9707 /* Mark the symbol as a Thumb function. */
9708 if ( S_GET_STORAGE_CLASS (sym
) == C_STAT
9709 || S_GET_STORAGE_CLASS (sym
) == C_LABEL
) /* This can happen! */
9710 S_SET_STORAGE_CLASS (sym
, C_THUMBSTATFUNC
);
9712 else if (S_GET_STORAGE_CLASS (sym
) == C_EXT
)
9713 S_SET_STORAGE_CLASS (sym
, C_THUMBEXTFUNC
);
9715 as_bad (_("%s: unexpected function type: %d"),
9716 S_GET_NAME (sym
), S_GET_STORAGE_CLASS (sym
));
9718 else switch (S_GET_STORAGE_CLASS (sym
))
9721 S_SET_STORAGE_CLASS (sym
, C_THUMBEXT
);
9724 S_SET_STORAGE_CLASS (sym
, C_THUMBSTAT
);
9727 S_SET_STORAGE_CLASS (sym
, C_THUMBLABEL
);
9735 if (ARM_IS_INTERWORK (sym
))
9736 coffsymbol (symbol_get_bfdsym (sym
))->native
->u
.syment
.n_flags
= 0xFF;
9743 for (sym
= symbol_rootP
; sym
!= NULL
; sym
= symbol_next (sym
))
9745 if (ARM_IS_THUMB (sym
))
9747 elf_symbol_type
* elf_sym
;
9749 elf_sym
= elf_symbol (symbol_get_bfdsym (sym
));
9750 bind
= ELF_ST_BIND (elf_sym
);
9752 /* If it's a .thumb_func, declare it as so,
9753 otherwise tag label as .code 16. */
9754 if (THUMB_IS_FUNC (sym
))
9755 elf_sym
->internal_elf_sym
.st_info
=
9756 ELF_ST_INFO (bind
, STT_ARM_TFUNC
);
9758 elf_sym
->internal_elf_sym
.st_info
=
9759 ELF_ST_INFO (bind
, STT_ARM_16BIT
);
9768 if (thumb_mode
&& ! strncmp (input_line_pointer
+ 1, "data:", 5))
9770 *input_line_pointer
= '/';
9771 input_line_pointer
+= 5;
9772 *input_line_pointer
= 0;
9780 arm_canonicalize_symbol_name (name
)
9785 if (thumb_mode
&& (len
= strlen (name
)) > 5
9786 && streq (name
+ len
- 5, "/data"))
9787 *(name
+ len
- 5) = 0;
9793 arm_validate_fix (fixP
)
9796 /* If the destination of the branch is a defined symbol which does not have
9797 the THUMB_FUNC attribute, then we must be calling a function which has
9798 the (interfacearm) attribute. We look for the Thumb entry point to that
9799 function and change the branch to refer to that function instead. */
9800 if (fixP
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BRANCH23
9801 && fixP
->fx_addsy
!= NULL
9802 && S_IS_DEFINED (fixP
->fx_addsy
)
9803 && ! THUMB_IS_FUNC (fixP
->fx_addsy
))
9805 fixP
->fx_addsy
= find_real_start (fixP
->fx_addsy
);
9813 /* This is a little hack to help the gas/arm/adrl.s test. It prevents
9814 local labels from being added to the output symbol table when they
9815 are used with the ADRL pseudo op. The ADRL relocation should always
9816 be resolved before the binbary is emitted, so it is safe to say that
9817 it is adjustable. */
9820 arm_fix_adjustable (fixP
)
9823 if (fixP
->fx_r_type
== BFD_RELOC_ARM_ADRL_IMMEDIATE
)
9829 /* Relocations against Thumb function names must be left unadjusted,
9830 so that the linker can use this information to correctly set the
9831 bottom bit of their addresses. The MIPS version of this function
9832 also prevents relocations that are mips-16 specific, but I do not
9833 know why it does this.
9836 There is one other problem that ought to be addressed here, but
9837 which currently is not: Taking the address of a label (rather
9838 than a function) and then later jumping to that address. Such
9839 addresses also ought to have their bottom bit set (assuming that
9840 they reside in Thumb code), but at the moment they will not. */
9843 arm_fix_adjustable (fixP
)
9846 if (fixP
->fx_addsy
== NULL
)
9849 /* Prevent all adjustments to global symbols. */
9850 if (S_IS_EXTERN (fixP
->fx_addsy
))
9853 if (S_IS_WEAK (fixP
->fx_addsy
))
9856 if (THUMB_IS_FUNC (fixP
->fx_addsy
)
9857 && fixP
->fx_subsy
== NULL
)
9860 /* We need the symbol name for the VTABLE entries. */
9861 if ( fixP
->fx_r_type
== BFD_RELOC_VTABLE_INHERIT
9862 || fixP
->fx_r_type
== BFD_RELOC_VTABLE_ENTRY
)
9869 elf32_arm_target_format ()
9871 if (target_big_endian
)
9874 return "elf32-bigarm-oabi";
9876 return "elf32-bigarm";
9881 return "elf32-littlearm-oabi";
9883 return "elf32-littlearm";
9888 armelf_frob_symbol (symp
, puntp
)
9892 elf_frob_symbol (symp
, puntp
);
9896 arm_force_relocation (fixp
)
9899 if ( fixp
->fx_r_type
== BFD_RELOC_VTABLE_INHERIT
9900 || fixp
->fx_r_type
== BFD_RELOC_VTABLE_ENTRY
9901 || fixp
->fx_r_type
== BFD_RELOC_ARM_PCREL_BRANCH
9902 || fixp
->fx_r_type
== BFD_RELOC_ARM_PCREL_BLX
9903 || fixp
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BLX
9904 || fixp
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BRANCH23
)
9910 static bfd_reloc_code_real_type
9920 bfd_reloc_code_real_type reloc
;
9924 #define MAP(str,reloc) { str, sizeof (str) - 1, reloc }
9925 MAP ("(got)", BFD_RELOC_ARM_GOT32
),
9926 MAP ("(gotoff)", BFD_RELOC_ARM_GOTOFF
),
9927 /* ScottB: Jan 30, 1998 - Added support for parsing "var(PLT)"
9928 branch instructions generated by GCC for PLT relocs. */
9929 MAP ("(plt)", BFD_RELOC_ARM_PLT32
),
9930 { NULL
, 0, BFD_RELOC_UNUSED
}
9934 for (i
= 0, ip
= input_line_pointer
;
9935 i
< sizeof (id
) && (ISALNUM (*ip
) || ISPUNCT (*ip
));
9937 id
[i
] = TOLOWER (*ip
);
9939 for (i
= 0; reloc_map
[i
].str
; i
++)
9940 if (strncmp (id
, reloc_map
[i
].str
, reloc_map
[i
].len
) == 0)
9943 input_line_pointer
+= reloc_map
[i
].len
;
9945 return reloc_map
[i
].reloc
;
9949 s_arm_elf_cons (nbytes
)
9954 #ifdef md_flush_pending_output
9955 md_flush_pending_output ();
9958 if (is_it_end_of_statement ())
9960 demand_empty_rest_of_line ();
9964 #ifdef md_cons_align
9965 md_cons_align (nbytes
);
9970 bfd_reloc_code_real_type reloc
;
9974 if (exp
.X_op
== O_symbol
9975 && * input_line_pointer
== '('
9976 && (reloc
= arm_parse_reloc ()) != BFD_RELOC_UNUSED
)
9978 reloc_howto_type
*howto
= bfd_reloc_type_lookup (stdoutput
, reloc
);
9979 int size
= bfd_get_reloc_size (howto
);
9982 as_bad ("%s relocations do not fit in %d bytes",
9983 howto
->name
, nbytes
);
9986 register char *p
= frag_more ((int) nbytes
);
9987 int offset
= nbytes
- size
;
9989 fix_new_exp (frag_now
, p
- frag_now
->fr_literal
+ offset
, size
,
9994 emit_expr (&exp
, (unsigned int) nbytes
);
9996 while (*input_line_pointer
++ == ',');
9998 /* Put terminator back into stream. */
9999 input_line_pointer
--;
10000 demand_empty_rest_of_line ();
10003 #endif /* OBJ_ELF */
10005 /* This is called from HANDLE_ALIGN in write.c. Fill in the contents
10006 of an rs_align_code fragment. */
10009 arm_handle_align (fragP
)
10012 static char const arm_noop
[4] = { 0x00, 0x00, 0xa0, 0xe1 };
10013 static char const thumb_noop
[2] = { 0xc0, 0x46 };
10014 static char const arm_bigend_noop
[4] = { 0xe1, 0xa0, 0x00, 0x00 };
10015 static char const thumb_bigend_noop
[2] = { 0x46, 0xc0 };
10017 int bytes
, fix
, noop_size
;
10021 if (fragP
->fr_type
!= rs_align_code
)
10024 bytes
= fragP
->fr_next
->fr_address
- fragP
->fr_address
- fragP
->fr_fix
;
10025 p
= fragP
->fr_literal
+ fragP
->fr_fix
;
10028 if (bytes
> MAX_MEM_FOR_RS_ALIGN_CODE
)
10029 bytes
&= MAX_MEM_FOR_RS_ALIGN_CODE
;
10031 if (fragP
->tc_frag_data
)
10033 if (target_big_endian
)
10034 noop
= thumb_bigend_noop
;
10037 noop_size
= sizeof (thumb_noop
);
10041 if (target_big_endian
)
10042 noop
= arm_bigend_noop
;
10045 noop_size
= sizeof (arm_noop
);
10048 if (bytes
& (noop_size
- 1))
10050 fix
= bytes
& (noop_size
- 1);
10051 memset (p
, 0, fix
);
10056 while (bytes
>= noop_size
)
10058 memcpy (p
, noop
, noop_size
);
10060 bytes
-= noop_size
;
10064 fragP
->fr_fix
+= fix
;
10065 fragP
->fr_var
= noop_size
;
10068 /* Called from md_do_align. Used to create an alignment
10069 frag in a code section. */
10072 arm_frag_align_code (n
, max
)
10078 /* We assume that there will never be a requirment
10079 to support alignments greater than 32 bytes. */
10080 if (max
> MAX_MEM_FOR_RS_ALIGN_CODE
)
10081 as_fatal (_("alignments greater than 32 bytes not supported in .text sections."));
10083 p
= frag_var (rs_align_code
,
10084 MAX_MEM_FOR_RS_ALIGN_CODE
,
10086 (relax_substateT
) max
,
10094 /* Perform target specific initialisation of a frag. */
10097 arm_init_frag (fragP
)
10100 /* Record whether this frag is in an ARM or a THUMB area. */
10101 fragP
->tc_frag_data
= thumb_mode
;