* config/tc-arm.c (s_arm_unwind_fnend): Use R_ARM_PREL31 relocation
[binutils.git] / gas / config / tc-arm.c
blob009be15193a8329665d68796e066c0f6ab592864
1 /* tc-arm.c -- Assemble for the ARM
2 Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
3 Free Software Foundation, Inc.
4 Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org)
5 Modified by David Taylor (dtaylor@armltd.co.uk)
6 Cirrus coprocessor mods by Aldy Hernandez (aldyh@redhat.com)
7 Cirrus coprocessor fixes by Petko Manolov (petkan@nucleusys.com)
8 Cirrus coprocessor fixes by Vladimir Ivanov (vladitx@nucleusys.com)
10 This file is part of GAS, the GNU Assembler.
12 GAS is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2, or (at your option)
15 any later version.
17 GAS is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with GAS; see the file COPYING. If not, write to the Free
24 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
25 02111-1307, USA. */
27 #include <string.h>
28 #define NO_RELOC 0
29 #include "as.h"
30 #include "safe-ctype.h"
32 /* Need TARGET_CPU. */
33 #include "config.h"
34 #include "subsegs.h"
35 #include "obstack.h"
36 #include "symbols.h"
37 #include "listing.h"
39 #include "opcode/arm.h"
41 #ifdef OBJ_ELF
42 #include "elf/arm.h"
43 #include "dwarf2dbg.h"
44 #include "dw2gencfi.h"
45 #endif
47 /* XXX Set this to 1 after the next binutils release. */
48 #define WARN_DEPRECATED 0
50 #ifdef OBJ_ELF
51 /* Must be at least the size of the largest unwind opcode (currently two). */
52 #define ARM_OPCODE_CHUNK_SIZE 8
54 /* This structure holds the unwinding state. */
56 static struct
58 symbolS * proc_start;
59 symbolS * table_entry;
60 symbolS * personality_routine;
61 int personality_index;
62 /* The segment containing the function. */
63 segT saved_seg;
64 subsegT saved_subseg;
65 /* Opcodes generated from this function. */
66 unsigned char * opcodes;
67 int opcode_count;
68 int opcode_alloc;
69 /* The number of bytes pushed to the stack. */
70 offsetT frame_size;
71 /* We don't add stack adjustment opcodes immediately so that we can merge
72 multiple adjustments. We can also omit the final adjustment
73 when using a frame pointer. */
74 offsetT pending_offset;
75 /* These two fields are set by both unwind_movsp and unwind_setfp. They
76 hold the reg+offset to use when restoring sp from a frame pointer. */
77 offsetT fp_offset;
78 int fp_reg;
79 /* Nonzero if an unwind_setfp directive has been seen. */
80 unsigned fp_used:1;
81 /* Nonzero if the last opcode restores sp from fp_reg. */
82 unsigned sp_restored:1;
83 } unwind;
85 #endif /* OBJ_ELF */
87 enum arm_float_abi
89 ARM_FLOAT_ABI_HARD,
90 ARM_FLOAT_ABI_SOFTFP,
91 ARM_FLOAT_ABI_SOFT
94 /* Types of processor to assemble for. */
95 #define ARM_1 ARM_ARCH_V1
96 #define ARM_2 ARM_ARCH_V2
97 #define ARM_3 ARM_ARCH_V2S
98 #define ARM_250 ARM_ARCH_V2S
99 #define ARM_6 ARM_ARCH_V3
100 #define ARM_7 ARM_ARCH_V3
101 #define ARM_8 ARM_ARCH_V4
102 #define ARM_9 ARM_ARCH_V4T
103 #define ARM_STRONG ARM_ARCH_V4
104 #define ARM_CPU_MASK 0x0000000f /* XXX? */
106 #ifndef CPU_DEFAULT
107 #if defined __XSCALE__
108 #define CPU_DEFAULT (ARM_ARCH_XSCALE)
109 #else
110 #if defined __thumb__
111 #define CPU_DEFAULT (ARM_ARCH_V5T)
112 #else
113 #define CPU_DEFAULT ARM_ANY
114 #endif
115 #endif
116 #endif
118 #ifndef FPU_DEFAULT
119 # ifdef TE_LINUX
120 # define FPU_DEFAULT FPU_ARCH_FPA
121 # elif defined (TE_NetBSD)
122 # ifdef OBJ_ELF
123 # define FPU_DEFAULT FPU_ARCH_VFP /* Soft-float, but VFP order. */
124 # else
125 /* Legacy a.out format. */
126 # define FPU_DEFAULT FPU_ARCH_FPA /* Soft-float, but FPA order. */
127 # endif
128 # else
129 /* For backwards compatibility, default to FPA. */
130 # define FPU_DEFAULT FPU_ARCH_FPA
131 # endif
132 #endif /* ifndef FPU_DEFAULT */
134 #define streq(a, b) (strcmp (a, b) == 0)
135 #define skip_whitespace(str) while (*(str) == ' ') ++(str)
137 static unsigned long cpu_variant;
139 /* Flags stored in private area of BFD structure. */
140 static int uses_apcs_26 = FALSE;
141 static int atpcs = FALSE;
142 static int support_interwork = FALSE;
143 static int uses_apcs_float = FALSE;
144 static int pic_code = FALSE;
146 /* Variables that we set while parsing command-line options. Once all
147 options have been read we re-process these values to set the real
148 assembly flags. */
149 static int legacy_cpu = -1;
150 static int legacy_fpu = -1;
152 static int mcpu_cpu_opt = -1;
153 static int mcpu_fpu_opt = -1;
154 static int march_cpu_opt = -1;
155 static int march_fpu_opt = -1;
156 static int mfpu_opt = -1;
157 static int mfloat_abi_opt = -1;
158 #ifdef OBJ_ELF
159 static int meabi_flags = EF_ARM_EABI_UNKNOWN;
160 #endif
162 /* This array holds the chars that always start a comment. If the
163 pre-processor is disabled, these aren't very useful. */
164 const char comment_chars[] = "@";
166 /* This array holds the chars that only start a comment at the beginning of
167 a line. If the line seems to have the form '# 123 filename'
168 .line and .file directives will appear in the pre-processed output. */
169 /* Note that input_file.c hand checks for '#' at the beginning of the
170 first line of the input file. This is because the compiler outputs
171 #NO_APP at the beginning of its output. */
172 /* Also note that comments like this one will always work. */
173 const char line_comment_chars[] = "#";
175 const char line_separator_chars[] = ";";
177 /* Chars that can be used to separate mant
178 from exp in floating point numbers. */
179 const char EXP_CHARS[] = "eE";
181 /* Chars that mean this number is a floating point constant. */
182 /* As in 0f12.456 */
183 /* or 0d1.2345e12 */
185 const char FLT_CHARS[] = "rRsSfFdDxXeEpP";
187 /* Prefix characters that indicate the start of an immediate
188 value. */
189 #define is_immediate_prefix(C) ((C) == '#' || (C) == '$')
191 #ifdef OBJ_ELF
192 /* Pre-defined "_GLOBAL_OFFSET_TABLE_" */
193 symbolS * GOT_symbol;
194 #endif
196 /* Size of relocation record. */
197 const int md_reloc_size = 8;
199 /* 0: assemble for ARM,
200 1: assemble for Thumb,
201 2: assemble for Thumb even though target CPU does not support thumb
202 instructions. */
203 static int thumb_mode = 0;
205 typedef struct arm_fix
207 int thumb_mode;
208 } arm_fix_data;
210 struct arm_it
212 const char * error;
213 unsigned long instruction;
214 int size;
215 struct
217 bfd_reloc_code_real_type type;
218 expressionS exp;
219 int pc_rel;
220 } reloc;
223 struct arm_it inst;
225 enum asm_shift_index
227 SHIFT_LSL = 0,
228 SHIFT_LSR,
229 SHIFT_ASR,
230 SHIFT_ROR,
231 SHIFT_RRX
234 struct asm_shift_properties
236 enum asm_shift_index index;
237 unsigned long bit_field;
238 unsigned int allows_0 : 1;
239 unsigned int allows_32 : 1;
242 static const struct asm_shift_properties shift_properties [] =
244 { SHIFT_LSL, 0, 1, 0},
245 { SHIFT_LSR, 0x20, 0, 1},
246 { SHIFT_ASR, 0x40, 0, 1},
247 { SHIFT_ROR, 0x60, 0, 0},
248 { SHIFT_RRX, 0x60, 0, 0}
251 struct asm_shift_name
253 const char * name;
254 const struct asm_shift_properties * properties;
257 static const struct asm_shift_name shift_names [] =
259 { "asl", shift_properties + SHIFT_LSL },
260 { "lsl", shift_properties + SHIFT_LSL },
261 { "lsr", shift_properties + SHIFT_LSR },
262 { "asr", shift_properties + SHIFT_ASR },
263 { "ror", shift_properties + SHIFT_ROR },
264 { "rrx", shift_properties + SHIFT_RRX },
265 { "ASL", shift_properties + SHIFT_LSL },
266 { "LSL", shift_properties + SHIFT_LSL },
267 { "LSR", shift_properties + SHIFT_LSR },
268 { "ASR", shift_properties + SHIFT_ASR },
269 { "ROR", shift_properties + SHIFT_ROR },
270 { "RRX", shift_properties + SHIFT_RRX }
273 /* Any kind of shift is accepted. */
274 #define NO_SHIFT_RESTRICT 1
275 /* The shift operand must be an immediate value, not a register. */
276 #define SHIFT_IMMEDIATE 0
277 /* The shift must be LSL or ASR and the operand must be an immediate. */
278 #define SHIFT_LSL_OR_ASR_IMMEDIATE 2
279 /* The shift must be ASR and the operand must be an immediate. */
280 #define SHIFT_ASR_IMMEDIATE 3
281 /* The shift must be LSL and the operand must be an immediate. */
282 #define SHIFT_LSL_IMMEDIATE 4
284 #define NUM_FLOAT_VALS 8
286 const char * fp_const[] =
288 "0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0", 0
291 /* Number of littlenums required to hold an extended precision number. */
292 #define MAX_LITTLENUMS 6
294 LITTLENUM_TYPE fp_values[NUM_FLOAT_VALS][MAX_LITTLENUMS];
296 #define FAIL (-1)
297 #define SUCCESS (0)
299 /* Whether a Co-processor load/store operation accepts write-back forms. */
300 #define CP_WB_OK 1
301 #define CP_NO_WB 0
303 #define SUFF_S 1
304 #define SUFF_D 2
305 #define SUFF_E 3
306 #define SUFF_P 4
308 #define CP_T_X 0x00008000
309 #define CP_T_Y 0x00400000
310 #define CP_T_Pre 0x01000000
311 #define CP_T_UD 0x00800000
312 #define CP_T_WB 0x00200000
314 #define CONDS_BIT 0x00100000
315 #define LOAD_BIT 0x00100000
317 #define DOUBLE_LOAD_FLAG 0x00000001
319 struct asm_cond
321 const char * template;
322 unsigned long value;
325 #define COND_ALWAYS 0xe0000000
326 #define COND_MASK 0xf0000000
328 static const struct asm_cond conds[] =
330 {"eq", 0x00000000},
331 {"ne", 0x10000000},
332 {"cs", 0x20000000}, {"hs", 0x20000000},
333 {"cc", 0x30000000}, {"ul", 0x30000000}, {"lo", 0x30000000},
334 {"mi", 0x40000000},
335 {"pl", 0x50000000},
336 {"vs", 0x60000000},
337 {"vc", 0x70000000},
338 {"hi", 0x80000000},
339 {"ls", 0x90000000},
340 {"ge", 0xa0000000},
341 {"lt", 0xb0000000},
342 {"gt", 0xc0000000},
343 {"le", 0xd0000000},
344 {"al", 0xe0000000},
345 {"nv", 0xf0000000}
348 struct asm_psr
350 const char *template;
351 bfd_boolean cpsr;
352 unsigned long field;
355 /* The bit that distinguishes CPSR and SPSR. */
356 #define SPSR_BIT (1 << 22)
358 /* How many bits to shift the PSR_xxx bits up by. */
359 #define PSR_SHIFT 16
361 #define PSR_c (1 << 0)
362 #define PSR_x (1 << 1)
363 #define PSR_s (1 << 2)
364 #define PSR_f (1 << 3)
366 static const struct asm_psr psrs[] =
368 {"CPSR", TRUE, PSR_c | PSR_f},
369 {"CPSR_all", TRUE, PSR_c | PSR_f},
370 {"SPSR", FALSE, PSR_c | PSR_f},
371 {"SPSR_all", FALSE, PSR_c | PSR_f},
372 {"CPSR_flg", TRUE, PSR_f},
373 {"CPSR_f", TRUE, PSR_f},
374 {"SPSR_flg", FALSE, PSR_f},
375 {"SPSR_f", FALSE, PSR_f},
376 {"CPSR_c", TRUE, PSR_c},
377 {"CPSR_ctl", TRUE, PSR_c},
378 {"SPSR_c", FALSE, PSR_c},
379 {"SPSR_ctl", FALSE, PSR_c},
380 {"CPSR_x", TRUE, PSR_x},
381 {"CPSR_s", TRUE, PSR_s},
382 {"SPSR_x", FALSE, PSR_x},
383 {"SPSR_s", FALSE, PSR_s},
384 /* Combinations of flags. */
385 {"CPSR_fs", TRUE, PSR_f | PSR_s},
386 {"CPSR_fx", TRUE, PSR_f | PSR_x},
387 {"CPSR_fc", TRUE, PSR_f | PSR_c},
388 {"CPSR_sf", TRUE, PSR_s | PSR_f},
389 {"CPSR_sx", TRUE, PSR_s | PSR_x},
390 {"CPSR_sc", TRUE, PSR_s | PSR_c},
391 {"CPSR_xf", TRUE, PSR_x | PSR_f},
392 {"CPSR_xs", TRUE, PSR_x | PSR_s},
393 {"CPSR_xc", TRUE, PSR_x | PSR_c},
394 {"CPSR_cf", TRUE, PSR_c | PSR_f},
395 {"CPSR_cs", TRUE, PSR_c | PSR_s},
396 {"CPSR_cx", TRUE, PSR_c | PSR_x},
397 {"CPSR_fsx", TRUE, PSR_f | PSR_s | PSR_x},
398 {"CPSR_fsc", TRUE, PSR_f | PSR_s | PSR_c},
399 {"CPSR_fxs", TRUE, PSR_f | PSR_x | PSR_s},
400 {"CPSR_fxc", TRUE, PSR_f | PSR_x | PSR_c},
401 {"CPSR_fcs", TRUE, PSR_f | PSR_c | PSR_s},
402 {"CPSR_fcx", TRUE, PSR_f | PSR_c | PSR_x},
403 {"CPSR_sfx", TRUE, PSR_s | PSR_f | PSR_x},
404 {"CPSR_sfc", TRUE, PSR_s | PSR_f | PSR_c},
405 {"CPSR_sxf", TRUE, PSR_s | PSR_x | PSR_f},
406 {"CPSR_sxc", TRUE, PSR_s | PSR_x | PSR_c},
407 {"CPSR_scf", TRUE, PSR_s | PSR_c | PSR_f},
408 {"CPSR_scx", TRUE, PSR_s | PSR_c | PSR_x},
409 {"CPSR_xfs", TRUE, PSR_x | PSR_f | PSR_s},
410 {"CPSR_xfc", TRUE, PSR_x | PSR_f | PSR_c},
411 {"CPSR_xsf", TRUE, PSR_x | PSR_s | PSR_f},
412 {"CPSR_xsc", TRUE, PSR_x | PSR_s | PSR_c},
413 {"CPSR_xcf", TRUE, PSR_x | PSR_c | PSR_f},
414 {"CPSR_xcs", TRUE, PSR_x | PSR_c | PSR_s},
415 {"CPSR_cfs", TRUE, PSR_c | PSR_f | PSR_s},
416 {"CPSR_cfx", TRUE, PSR_c | PSR_f | PSR_x},
417 {"CPSR_csf", TRUE, PSR_c | PSR_s | PSR_f},
418 {"CPSR_csx", TRUE, PSR_c | PSR_s | PSR_x},
419 {"CPSR_cxf", TRUE, PSR_c | PSR_x | PSR_f},
420 {"CPSR_cxs", TRUE, PSR_c | PSR_x | PSR_s},
421 {"CPSR_fsxc", TRUE, PSR_f | PSR_s | PSR_x | PSR_c},
422 {"CPSR_fscx", TRUE, PSR_f | PSR_s | PSR_c | PSR_x},
423 {"CPSR_fxsc", TRUE, PSR_f | PSR_x | PSR_s | PSR_c},
424 {"CPSR_fxcs", TRUE, PSR_f | PSR_x | PSR_c | PSR_s},
425 {"CPSR_fcsx", TRUE, PSR_f | PSR_c | PSR_s | PSR_x},
426 {"CPSR_fcxs", TRUE, PSR_f | PSR_c | PSR_x | PSR_s},
427 {"CPSR_sfxc", TRUE, PSR_s | PSR_f | PSR_x | PSR_c},
428 {"CPSR_sfcx", TRUE, PSR_s | PSR_f | PSR_c | PSR_x},
429 {"CPSR_sxfc", TRUE, PSR_s | PSR_x | PSR_f | PSR_c},
430 {"CPSR_sxcf", TRUE, PSR_s | PSR_x | PSR_c | PSR_f},
431 {"CPSR_scfx", TRUE, PSR_s | PSR_c | PSR_f | PSR_x},
432 {"CPSR_scxf", TRUE, PSR_s | PSR_c | PSR_x | PSR_f},
433 {"CPSR_xfsc", TRUE, PSR_x | PSR_f | PSR_s | PSR_c},
434 {"CPSR_xfcs", TRUE, PSR_x | PSR_f | PSR_c | PSR_s},
435 {"CPSR_xsfc", TRUE, PSR_x | PSR_s | PSR_f | PSR_c},
436 {"CPSR_xscf", TRUE, PSR_x | PSR_s | PSR_c | PSR_f},
437 {"CPSR_xcfs", TRUE, PSR_x | PSR_c | PSR_f | PSR_s},
438 {"CPSR_xcsf", TRUE, PSR_x | PSR_c | PSR_s | PSR_f},
439 {"CPSR_cfsx", TRUE, PSR_c | PSR_f | PSR_s | PSR_x},
440 {"CPSR_cfxs", TRUE, PSR_c | PSR_f | PSR_x | PSR_s},
441 {"CPSR_csfx", TRUE, PSR_c | PSR_s | PSR_f | PSR_x},
442 {"CPSR_csxf", TRUE, PSR_c | PSR_s | PSR_x | PSR_f},
443 {"CPSR_cxfs", TRUE, PSR_c | PSR_x | PSR_f | PSR_s},
444 {"CPSR_cxsf", TRUE, PSR_c | PSR_x | PSR_s | PSR_f},
445 {"SPSR_fs", FALSE, PSR_f | PSR_s},
446 {"SPSR_fx", FALSE, PSR_f | PSR_x},
447 {"SPSR_fc", FALSE, PSR_f | PSR_c},
448 {"SPSR_sf", FALSE, PSR_s | PSR_f},
449 {"SPSR_sx", FALSE, PSR_s | PSR_x},
450 {"SPSR_sc", FALSE, PSR_s | PSR_c},
451 {"SPSR_xf", FALSE, PSR_x | PSR_f},
452 {"SPSR_xs", FALSE, PSR_x | PSR_s},
453 {"SPSR_xc", FALSE, PSR_x | PSR_c},
454 {"SPSR_cf", FALSE, PSR_c | PSR_f},
455 {"SPSR_cs", FALSE, PSR_c | PSR_s},
456 {"SPSR_cx", FALSE, PSR_c | PSR_x},
457 {"SPSR_fsx", FALSE, PSR_f | PSR_s | PSR_x},
458 {"SPSR_fsc", FALSE, PSR_f | PSR_s | PSR_c},
459 {"SPSR_fxs", FALSE, PSR_f | PSR_x | PSR_s},
460 {"SPSR_fxc", FALSE, PSR_f | PSR_x | PSR_c},
461 {"SPSR_fcs", FALSE, PSR_f | PSR_c | PSR_s},
462 {"SPSR_fcx", FALSE, PSR_f | PSR_c | PSR_x},
463 {"SPSR_sfx", FALSE, PSR_s | PSR_f | PSR_x},
464 {"SPSR_sfc", FALSE, PSR_s | PSR_f | PSR_c},
465 {"SPSR_sxf", FALSE, PSR_s | PSR_x | PSR_f},
466 {"SPSR_sxc", FALSE, PSR_s | PSR_x | PSR_c},
467 {"SPSR_scf", FALSE, PSR_s | PSR_c | PSR_f},
468 {"SPSR_scx", FALSE, PSR_s | PSR_c | PSR_x},
469 {"SPSR_xfs", FALSE, PSR_x | PSR_f | PSR_s},
470 {"SPSR_xfc", FALSE, PSR_x | PSR_f | PSR_c},
471 {"SPSR_xsf", FALSE, PSR_x | PSR_s | PSR_f},
472 {"SPSR_xsc", FALSE, PSR_x | PSR_s | PSR_c},
473 {"SPSR_xcf", FALSE, PSR_x | PSR_c | PSR_f},
474 {"SPSR_xcs", FALSE, PSR_x | PSR_c | PSR_s},
475 {"SPSR_cfs", FALSE, PSR_c | PSR_f | PSR_s},
476 {"SPSR_cfx", FALSE, PSR_c | PSR_f | PSR_x},
477 {"SPSR_csf", FALSE, PSR_c | PSR_s | PSR_f},
478 {"SPSR_csx", FALSE, PSR_c | PSR_s | PSR_x},
479 {"SPSR_cxf", FALSE, PSR_c | PSR_x | PSR_f},
480 {"SPSR_cxs", FALSE, PSR_c | PSR_x | PSR_s},
481 {"SPSR_fsxc", FALSE, PSR_f | PSR_s | PSR_x | PSR_c},
482 {"SPSR_fscx", FALSE, PSR_f | PSR_s | PSR_c | PSR_x},
483 {"SPSR_fxsc", FALSE, PSR_f | PSR_x | PSR_s | PSR_c},
484 {"SPSR_fxcs", FALSE, PSR_f | PSR_x | PSR_c | PSR_s},
485 {"SPSR_fcsx", FALSE, PSR_f | PSR_c | PSR_s | PSR_x},
486 {"SPSR_fcxs", FALSE, PSR_f | PSR_c | PSR_x | PSR_s},
487 {"SPSR_sfxc", FALSE, PSR_s | PSR_f | PSR_x | PSR_c},
488 {"SPSR_sfcx", FALSE, PSR_s | PSR_f | PSR_c | PSR_x},
489 {"SPSR_sxfc", FALSE, PSR_s | PSR_x | PSR_f | PSR_c},
490 {"SPSR_sxcf", FALSE, PSR_s | PSR_x | PSR_c | PSR_f},
491 {"SPSR_scfx", FALSE, PSR_s | PSR_c | PSR_f | PSR_x},
492 {"SPSR_scxf", FALSE, PSR_s | PSR_c | PSR_x | PSR_f},
493 {"SPSR_xfsc", FALSE, PSR_x | PSR_f | PSR_s | PSR_c},
494 {"SPSR_xfcs", FALSE, PSR_x | PSR_f | PSR_c | PSR_s},
495 {"SPSR_xsfc", FALSE, PSR_x | PSR_s | PSR_f | PSR_c},
496 {"SPSR_xscf", FALSE, PSR_x | PSR_s | PSR_c | PSR_f},
497 {"SPSR_xcfs", FALSE, PSR_x | PSR_c | PSR_f | PSR_s},
498 {"SPSR_xcsf", FALSE, PSR_x | PSR_c | PSR_s | PSR_f},
499 {"SPSR_cfsx", FALSE, PSR_c | PSR_f | PSR_s | PSR_x},
500 {"SPSR_cfxs", FALSE, PSR_c | PSR_f | PSR_x | PSR_s},
501 {"SPSR_csfx", FALSE, PSR_c | PSR_s | PSR_f | PSR_x},
502 {"SPSR_csxf", FALSE, PSR_c | PSR_s | PSR_x | PSR_f},
503 {"SPSR_cxfs", FALSE, PSR_c | PSR_x | PSR_f | PSR_s},
504 {"SPSR_cxsf", FALSE, PSR_c | PSR_x | PSR_s | PSR_f},
507 enum wreg_type
509 IWMMXT_REG_WR = 0,
510 IWMMXT_REG_WC = 1,
511 IWMMXT_REG_WR_OR_WC = 2,
512 IWMMXT_REG_WCG
515 enum iwmmxt_insn_type
517 check_rd,
518 check_wr,
519 check_wrwr,
520 check_wrwrwr,
521 check_wrwrwcg,
522 check_tbcst,
523 check_tmovmsk,
524 check_tmia,
525 check_tmcrr,
526 check_tmrrc,
527 check_tmcr,
528 check_tmrc,
529 check_tinsr,
530 check_textrc,
531 check_waligni,
532 check_textrm,
533 check_wshufh
536 enum vfp_dp_reg_pos
538 VFP_REG_Dd, VFP_REG_Dm, VFP_REG_Dn
541 enum vfp_sp_reg_pos
543 VFP_REG_Sd, VFP_REG_Sm, VFP_REG_Sn
546 enum vfp_ldstm_type
548 VFP_LDSTMIA, VFP_LDSTMDB, VFP_LDSTMIAX, VFP_LDSTMDBX
551 /* VFP system registers. */
552 struct vfp_reg
554 const char *name;
555 unsigned long regno;
558 static const struct vfp_reg vfp_regs[] =
560 {"fpsid", 0x00000000},
561 {"FPSID", 0x00000000},
562 {"fpscr", 0x00010000},
563 {"FPSCR", 0x00010000},
564 {"fpexc", 0x00080000},
565 {"FPEXC", 0x00080000}
568 /* Structure for a hash table entry for a register. */
569 struct reg_entry
571 const char * name;
572 int number;
573 bfd_boolean builtin;
576 /* Some well known registers that we refer to directly elsewhere. */
577 #define REG_SP 13
578 #define REG_LR 14
579 #define REG_PC 15
581 #define wr_register(reg) ((reg ^ WR_PREFIX) >= 0 && (reg ^ WR_PREFIX) <= 15)
582 #define wc_register(reg) ((reg ^ WC_PREFIX) >= 0 && (reg ^ WC_PREFIX) <= 15)
583 #define wcg_register(reg) ((reg ^ WC_PREFIX) >= 8 && (reg ^ WC_PREFIX) <= 11)
585 /* These are the standard names. Users can add aliases with .req.
586 and delete them with .unreq. */
588 /* Integer Register Numbers. */
589 static const struct reg_entry rn_table[] =
591 {"r0", 0, TRUE}, {"r1", 1, TRUE}, {"r2", 2, TRUE}, {"r3", 3, TRUE},
592 {"r4", 4, TRUE}, {"r5", 5, TRUE}, {"r6", 6, TRUE}, {"r7", 7, TRUE},
593 {"r8", 8, TRUE}, {"r9", 9, TRUE}, {"r10", 10, TRUE}, {"r11", 11, TRUE},
594 {"r12", 12, TRUE}, {"r13", REG_SP, TRUE}, {"r14", REG_LR, TRUE}, {"r15", REG_PC, TRUE},
595 /* ATPCS Synonyms. */
596 {"a1", 0, TRUE}, {"a2", 1, TRUE}, {"a3", 2, TRUE}, {"a4", 3, TRUE},
597 {"v1", 4, TRUE}, {"v2", 5, TRUE}, {"v3", 6, TRUE}, {"v4", 7, TRUE},
598 {"v5", 8, TRUE}, {"v6", 9, TRUE}, {"v7", 10, TRUE}, {"v8", 11, TRUE},
599 /* Well-known aliases. */
600 {"wr", 7, TRUE}, {"sb", 9, TRUE}, {"sl", 10, TRUE}, {"fp", 11, TRUE},
601 {"ip", 12, TRUE}, {"sp", REG_SP, TRUE}, {"lr", REG_LR, TRUE}, {"pc", REG_PC, TRUE},
602 {NULL, 0, TRUE}
605 #define WR_PREFIX 0x200
606 #define WC_PREFIX 0x400
608 static const struct reg_entry iwmmxt_table[] =
610 /* Intel Wireless MMX technology register names. */
611 { "wr0", 0x0 | WR_PREFIX, TRUE}, {"wr1", 0x1 | WR_PREFIX, TRUE},
612 { "wr2", 0x2 | WR_PREFIX, TRUE}, {"wr3", 0x3 | WR_PREFIX, TRUE},
613 { "wr4", 0x4 | WR_PREFIX, TRUE}, {"wr5", 0x5 | WR_PREFIX, TRUE},
614 { "wr6", 0x6 | WR_PREFIX, TRUE}, {"wr7", 0x7 | WR_PREFIX, TRUE},
615 { "wr8", 0x8 | WR_PREFIX, TRUE}, {"wr9", 0x9 | WR_PREFIX, TRUE},
616 { "wr10", 0xa | WR_PREFIX, TRUE}, {"wr11", 0xb | WR_PREFIX, TRUE},
617 { "wr12", 0xc | WR_PREFIX, TRUE}, {"wr13", 0xd | WR_PREFIX, TRUE},
618 { "wr14", 0xe | WR_PREFIX, TRUE}, {"wr15", 0xf | WR_PREFIX, TRUE},
619 { "wcid", 0x0 | WC_PREFIX, TRUE}, {"wcon", 0x1 | WC_PREFIX, TRUE},
620 {"wcssf", 0x2 | WC_PREFIX, TRUE}, {"wcasf", 0x3 | WC_PREFIX, TRUE},
621 {"wcgr0", 0x8 | WC_PREFIX, TRUE}, {"wcgr1", 0x9 | WC_PREFIX, TRUE},
622 {"wcgr2", 0xa | WC_PREFIX, TRUE}, {"wcgr3", 0xb | WC_PREFIX, TRUE},
624 { "wR0", 0x0 | WR_PREFIX, TRUE}, {"wR1", 0x1 | WR_PREFIX, TRUE},
625 { "wR2", 0x2 | WR_PREFIX, TRUE}, {"wR3", 0x3 | WR_PREFIX, TRUE},
626 { "wR4", 0x4 | WR_PREFIX, TRUE}, {"wR5", 0x5 | WR_PREFIX, TRUE},
627 { "wR6", 0x6 | WR_PREFIX, TRUE}, {"wR7", 0x7 | WR_PREFIX, TRUE},
628 { "wR8", 0x8 | WR_PREFIX, TRUE}, {"wR9", 0x9 | WR_PREFIX, TRUE},
629 { "wR10", 0xa | WR_PREFIX, TRUE}, {"wR11", 0xb | WR_PREFIX, TRUE},
630 { "wR12", 0xc | WR_PREFIX, TRUE}, {"wR13", 0xd | WR_PREFIX, TRUE},
631 { "wR14", 0xe | WR_PREFIX, TRUE}, {"wR15", 0xf | WR_PREFIX, TRUE},
632 { "wCID", 0x0 | WC_PREFIX, TRUE}, {"wCon", 0x1 | WC_PREFIX, TRUE},
633 {"wCSSF", 0x2 | WC_PREFIX, TRUE}, {"wCASF", 0x3 | WC_PREFIX, TRUE},
634 {"wCGR0", 0x8 | WC_PREFIX, TRUE}, {"wCGR1", 0x9 | WC_PREFIX, TRUE},
635 {"wCGR2", 0xa | WC_PREFIX, TRUE}, {"wCGR3", 0xb | WC_PREFIX, TRUE},
636 {NULL, 0, TRUE}
639 /* Co-processor Numbers. */
640 static const struct reg_entry cp_table[] =
642 {"p0", 0, TRUE}, {"p1", 1, TRUE}, {"p2", 2, TRUE}, {"p3", 3, TRUE},
643 {"p4", 4, TRUE}, {"p5", 5, TRUE}, {"p6", 6, TRUE}, {"p7", 7, TRUE},
644 {"p8", 8, TRUE}, {"p9", 9, TRUE}, {"p10", 10, TRUE}, {"p11", 11, TRUE},
645 {"p12", 12, TRUE}, {"p13", 13, TRUE}, {"p14", 14, TRUE}, {"p15", 15, TRUE},
646 {NULL, 0, TRUE}
649 /* Co-processor Register Numbers. */
650 static const struct reg_entry cn_table[] =
652 {"c0", 0, TRUE}, {"c1", 1, TRUE}, {"c2", 2, TRUE}, {"c3", 3, TRUE},
653 {"c4", 4, TRUE}, {"c5", 5, TRUE}, {"c6", 6, TRUE}, {"c7", 7, TRUE},
654 {"c8", 8, TRUE}, {"c9", 9, TRUE}, {"c10", 10, TRUE}, {"c11", 11, TRUE},
655 {"c12", 12, TRUE}, {"c13", 13, TRUE}, {"c14", 14, TRUE}, {"c15", 15, TRUE},
656 /* Not really valid, but kept for back-wards compatibility. */
657 {"cr0", 0, TRUE}, {"cr1", 1, TRUE}, {"cr2", 2, TRUE}, {"cr3", 3, TRUE},
658 {"cr4", 4, TRUE}, {"cr5", 5, TRUE}, {"cr6", 6, TRUE}, {"cr7", 7, TRUE},
659 {"cr8", 8, TRUE}, {"cr9", 9, TRUE}, {"cr10", 10, TRUE}, {"cr11", 11, TRUE},
660 {"cr12", 12, TRUE}, {"cr13", 13, TRUE}, {"cr14", 14, TRUE}, {"cr15", 15, TRUE},
661 {NULL, 0, TRUE}
664 /* FPA Registers. */
665 static const struct reg_entry fn_table[] =
667 {"f0", 0, TRUE}, {"f1", 1, TRUE}, {"f2", 2, TRUE}, {"f3", 3, TRUE},
668 {"f4", 4, TRUE}, {"f5", 5, TRUE}, {"f6", 6, TRUE}, {"f7", 7, TRUE},
669 {NULL, 0, TRUE}
672 /* VFP SP Registers. */
673 static const struct reg_entry sn_table[] =
675 {"s0", 0, TRUE}, {"s1", 1, TRUE}, {"s2", 2, TRUE}, {"s3", 3, TRUE},
676 {"s4", 4, TRUE}, {"s5", 5, TRUE}, {"s6", 6, TRUE}, {"s7", 7, TRUE},
677 {"s8", 8, TRUE}, {"s9", 9, TRUE}, {"s10", 10, TRUE}, {"s11", 11, TRUE},
678 {"s12", 12, TRUE}, {"s13", 13, TRUE}, {"s14", 14, TRUE}, {"s15", 15, TRUE},
679 {"s16", 16, TRUE}, {"s17", 17, TRUE}, {"s18", 18, TRUE}, {"s19", 19, TRUE},
680 {"s20", 20, TRUE}, {"s21", 21, TRUE}, {"s22", 22, TRUE}, {"s23", 23, TRUE},
681 {"s24", 24, TRUE}, {"s25", 25, TRUE}, {"s26", 26, TRUE}, {"s27", 27, TRUE},
682 {"s28", 28, TRUE}, {"s29", 29, TRUE}, {"s30", 30, TRUE}, {"s31", 31, TRUE},
683 {NULL, 0, TRUE}
686 /* VFP DP Registers. */
687 static const struct reg_entry dn_table[] =
689 {"d0", 0, TRUE}, {"d1", 1, TRUE}, {"d2", 2, TRUE}, {"d3", 3, TRUE},
690 {"d4", 4, TRUE}, {"d5", 5, TRUE}, {"d6", 6, TRUE}, {"d7", 7, TRUE},
691 {"d8", 8, TRUE}, {"d9", 9, TRUE}, {"d10", 10, TRUE}, {"d11", 11, TRUE},
692 {"d12", 12, TRUE}, {"d13", 13, TRUE}, {"d14", 14, TRUE}, {"d15", 15, TRUE},
693 {NULL, 0, TRUE}
696 /* Maverick DSP coprocessor registers. */
697 static const struct reg_entry mav_mvf_table[] =
699 {"mvf0", 0, TRUE}, {"mvf1", 1, TRUE}, {"mvf2", 2, TRUE}, {"mvf3", 3, TRUE},
700 {"mvf4", 4, TRUE}, {"mvf5", 5, TRUE}, {"mvf6", 6, TRUE}, {"mvf7", 7, TRUE},
701 {"mvf8", 8, TRUE}, {"mvf9", 9, TRUE}, {"mvf10", 10, TRUE}, {"mvf11", 11, TRUE},
702 {"mvf12", 12, TRUE}, {"mvf13", 13, TRUE}, {"mvf14", 14, TRUE}, {"mvf15", 15, TRUE},
703 {NULL, 0, TRUE}
706 static const struct reg_entry mav_mvd_table[] =
708 {"mvd0", 0, TRUE}, {"mvd1", 1, TRUE}, {"mvd2", 2, TRUE}, {"mvd3", 3, TRUE},
709 {"mvd4", 4, TRUE}, {"mvd5", 5, TRUE}, {"mvd6", 6, TRUE}, {"mvd7", 7, TRUE},
710 {"mvd8", 8, TRUE}, {"mvd9", 9, TRUE}, {"mvd10", 10, TRUE}, {"mvd11", 11, TRUE},
711 {"mvd12", 12, TRUE}, {"mvd13", 13, TRUE}, {"mvd14", 14, TRUE}, {"mvd15", 15, TRUE},
712 {NULL, 0, TRUE}
715 static const struct reg_entry mav_mvfx_table[] =
717 {"mvfx0", 0, TRUE}, {"mvfx1", 1, TRUE}, {"mvfx2", 2, TRUE}, {"mvfx3", 3, TRUE},
718 {"mvfx4", 4, TRUE}, {"mvfx5", 5, TRUE}, {"mvfx6", 6, TRUE}, {"mvfx7", 7, TRUE},
719 {"mvfx8", 8, TRUE}, {"mvfx9", 9, TRUE}, {"mvfx10", 10, TRUE}, {"mvfx11", 11, TRUE},
720 {"mvfx12", 12, TRUE}, {"mvfx13", 13, TRUE}, {"mvfx14", 14, TRUE}, {"mvfx15", 15, TRUE},
721 {NULL, 0, TRUE}
724 static const struct reg_entry mav_mvdx_table[] =
726 {"mvdx0", 0, TRUE}, {"mvdx1", 1, TRUE}, {"mvdx2", 2, TRUE}, {"mvdx3", 3, TRUE},
727 {"mvdx4", 4, TRUE}, {"mvdx5", 5, TRUE}, {"mvdx6", 6, TRUE}, {"mvdx7", 7, TRUE},
728 {"mvdx8", 8, TRUE}, {"mvdx9", 9, TRUE}, {"mvdx10", 10, TRUE}, {"mvdx11", 11, TRUE},
729 {"mvdx12", 12, TRUE}, {"mvdx13", 13, TRUE}, {"mvdx14", 14, TRUE}, {"mvdx15", 15, TRUE},
730 {NULL, 0, TRUE}
733 static const struct reg_entry mav_mvax_table[] =
735 {"mvax0", 0, TRUE}, {"mvax1", 1, TRUE}, {"mvax2", 2, TRUE}, {"mvax3", 3, TRUE},
736 {NULL, 0, TRUE}
739 static const struct reg_entry mav_dspsc_table[] =
741 {"dspsc", 0, TRUE},
742 {NULL, 0, TRUE}
745 struct reg_map
747 const struct reg_entry * names;
748 int max_regno;
749 struct hash_control * htab;
750 const char * expected;
753 struct reg_map all_reg_maps[] =
755 {rn_table, 15, NULL, N_("ARM register expected")},
756 {cp_table, 15, NULL, N_("bad or missing co-processor number")},
757 {cn_table, 15, NULL, N_("co-processor register expected")},
758 {fn_table, 7, NULL, N_("FPA register expected")},
759 {sn_table, 31, NULL, N_("VFP single precision register expected")},
760 {dn_table, 15, NULL, N_("VFP double precision register expected")},
761 {mav_mvf_table, 15, NULL, N_("Maverick MVF register expected")},
762 {mav_mvd_table, 15, NULL, N_("Maverick MVD register expected")},
763 {mav_mvfx_table, 15, NULL, N_("Maverick MVFX register expected")},
764 {mav_mvdx_table, 15, NULL, N_("Maverick MVDX register expected")},
765 {mav_mvax_table, 3, NULL, N_("Maverick MVAX register expected")},
766 {mav_dspsc_table, 0, NULL, N_("Maverick DSPSC register expected")},
767 {iwmmxt_table, 23, NULL, N_("Intel Wireless MMX technology register expected")},
770 /* Enumeration matching entries in table above. */
771 enum arm_reg_type
773 REG_TYPE_RN = 0,
774 #define REG_TYPE_FIRST REG_TYPE_RN
775 REG_TYPE_CP = 1,
776 REG_TYPE_CN = 2,
777 REG_TYPE_FN = 3,
778 REG_TYPE_SN = 4,
779 REG_TYPE_DN = 5,
780 REG_TYPE_MVF = 6,
781 REG_TYPE_MVD = 7,
782 REG_TYPE_MVFX = 8,
783 REG_TYPE_MVDX = 9,
784 REG_TYPE_MVAX = 10,
785 REG_TYPE_DSPSC = 11,
786 REG_TYPE_IWMMXT = 12,
788 REG_TYPE_MAX = 13
791 /* ARM instructions take 4bytes in the object file, Thumb instructions
792 take 2: */
793 #define INSN_SIZE 4
795 /* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
796 #define MAV_MODE1 0x100c
798 /* "INSN<cond> X,Y" where X:bit16, Y:bit12. */
799 #define MAV_MODE2 0x0c10
801 /* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
802 #define MAV_MODE3 0x100c
804 /* "INSN<cond> X,Y,Z" where X:16, Y:0, Z:12. */
805 #define MAV_MODE4 0x0c0010
807 /* "INSN<cond> X,Y,Z" where X:12, Y:16, Z:0. */
808 #define MAV_MODE5 0x00100c
810 /* "INSN<cond> W,X,Y,Z" where W:5, X:12, Y:16, Z:0. */
811 #define MAV_MODE6 0x00100c05
813 struct asm_opcode
815 /* Basic string to match. */
816 const char * template;
818 /* Basic instruction code. */
819 unsigned long value;
821 /* Offset into the template where the condition code (if any) will be.
822 If zero, then the instruction is never conditional. */
823 unsigned cond_offset;
825 /* Which architecture variant provides this instruction. */
826 unsigned long variant;
828 /* Function to call to parse args. */
829 void (* parms) (char *);
832 /* Defines for various bits that we will want to toggle. */
833 #define INST_IMMEDIATE 0x02000000
834 #define OFFSET_REG 0x02000000
835 #define HWOFFSET_IMM 0x00400000
836 #define SHIFT_BY_REG 0x00000010
837 #define PRE_INDEX 0x01000000
838 #define INDEX_UP 0x00800000
839 #define WRITE_BACK 0x00200000
840 #define LDM_TYPE_2_OR_3 0x00400000
842 #define LITERAL_MASK 0xf000f000
843 #define OPCODE_MASK 0xfe1fffff
844 #define V4_STR_BIT 0x00000020
846 #define DATA_OP_SHIFT 21
848 /* Codes to distinguish the arithmetic instructions. */
849 #define OPCODE_AND 0
850 #define OPCODE_EOR 1
851 #define OPCODE_SUB 2
852 #define OPCODE_RSB 3
853 #define OPCODE_ADD 4
854 #define OPCODE_ADC 5
855 #define OPCODE_SBC 6
856 #define OPCODE_RSC 7
857 #define OPCODE_TST 8
858 #define OPCODE_TEQ 9
859 #define OPCODE_CMP 10
860 #define OPCODE_CMN 11
861 #define OPCODE_ORR 12
862 #define OPCODE_MOV 13
863 #define OPCODE_BIC 14
864 #define OPCODE_MVN 15
866 #define T_OPCODE_MUL 0x4340
867 #define T_OPCODE_TST 0x4200
868 #define T_OPCODE_CMN 0x42c0
869 #define T_OPCODE_NEG 0x4240
870 #define T_OPCODE_MVN 0x43c0
872 #define T_OPCODE_ADD_R3 0x1800
873 #define T_OPCODE_SUB_R3 0x1a00
874 #define T_OPCODE_ADD_HI 0x4400
875 #define T_OPCODE_ADD_ST 0xb000
876 #define T_OPCODE_SUB_ST 0xb080
877 #define T_OPCODE_ADD_SP 0xa800
878 #define T_OPCODE_ADD_PC 0xa000
879 #define T_OPCODE_ADD_I8 0x3000
880 #define T_OPCODE_SUB_I8 0x3800
881 #define T_OPCODE_ADD_I3 0x1c00
882 #define T_OPCODE_SUB_I3 0x1e00
884 #define T_OPCODE_ASR_R 0x4100
885 #define T_OPCODE_LSL_R 0x4080
886 #define T_OPCODE_LSR_R 0x40c0
887 #define T_OPCODE_ASR_I 0x1000
888 #define T_OPCODE_LSL_I 0x0000
889 #define T_OPCODE_LSR_I 0x0800
891 #define T_OPCODE_MOV_I8 0x2000
892 #define T_OPCODE_CMP_I8 0x2800
893 #define T_OPCODE_CMP_LR 0x4280
894 #define T_OPCODE_MOV_HR 0x4600
895 #define T_OPCODE_CMP_HR 0x4500
897 #define T_OPCODE_LDR_PC 0x4800
898 #define T_OPCODE_LDR_SP 0x9800
899 #define T_OPCODE_STR_SP 0x9000
900 #define T_OPCODE_LDR_IW 0x6800
901 #define T_OPCODE_STR_IW 0x6000
902 #define T_OPCODE_LDR_IH 0x8800
903 #define T_OPCODE_STR_IH 0x8000
904 #define T_OPCODE_LDR_IB 0x7800
905 #define T_OPCODE_STR_IB 0x7000
906 #define T_OPCODE_LDR_RW 0x5800
907 #define T_OPCODE_STR_RW 0x5000
908 #define T_OPCODE_LDR_RH 0x5a00
909 #define T_OPCODE_STR_RH 0x5200
910 #define T_OPCODE_LDR_RB 0x5c00
911 #define T_OPCODE_STR_RB 0x5400
913 #define T_OPCODE_PUSH 0xb400
914 #define T_OPCODE_POP 0xbc00
916 #define T_OPCODE_BRANCH 0xe7fe
918 #define THUMB_SIZE 2 /* Size of thumb instruction. */
919 #define THUMB_REG_LO 0x1
920 #define THUMB_REG_HI 0x2
921 #define THUMB_REG_ANY 0x3
923 #define THUMB_H1 0x0080
924 #define THUMB_H2 0x0040
926 #define THUMB_ASR 0
927 #define THUMB_LSL 1
928 #define THUMB_LSR 2
930 #define THUMB_MOVE 0
931 #define THUMB_COMPARE 1
932 #define THUMB_CPY 2
934 #define THUMB_LOAD 0
935 #define THUMB_STORE 1
937 #define THUMB_PP_PC_LR 0x0100
939 /* These three are used for immediate shifts, do not alter. */
940 #define THUMB_WORD 2
941 #define THUMB_HALFWORD 1
942 #define THUMB_BYTE 0
944 struct thumb_opcode
946 /* Basic string to match. */
947 const char * template;
949 /* Basic instruction code. */
950 unsigned long value;
952 int size;
954 /* Which CPU variants this exists for. */
955 unsigned long variant;
957 /* Function to call to parse args. */
958 void (* parms) (char *);
961 #define BAD_ARGS _("bad arguments to instruction")
962 #define BAD_PC _("r15 not allowed here")
963 #define BAD_COND _("instruction is not conditional")
964 #define ERR_NO_ACCUM _("acc0 expected")
966 static struct hash_control * arm_ops_hsh = NULL;
967 static struct hash_control * arm_tops_hsh = NULL;
968 static struct hash_control * arm_cond_hsh = NULL;
969 static struct hash_control * arm_shift_hsh = NULL;
970 static struct hash_control * arm_psr_hsh = NULL;
972 /* Stuff needed to resolve the label ambiguity
975 label: <insn>
976 may differ from:
978 label:
979 <insn>
982 symbolS * last_label_seen;
983 static int label_is_thumb_function_name = FALSE;
985 /* Literal Pool stuff. */
987 #define MAX_LITERAL_POOL_SIZE 1024
989 /* Literal pool structure. Held on a per-section
990 and per-sub-section basis. */
992 typedef struct literal_pool
994 expressionS literals [MAX_LITERAL_POOL_SIZE];
995 unsigned int next_free_entry;
996 unsigned int id;
997 symbolS * symbol;
998 segT section;
999 subsegT sub_section;
1000 struct literal_pool * next;
1001 } literal_pool;
1003 /* Pointer to a linked list of literal pools. */
1004 literal_pool * list_of_pools = NULL;
1006 static literal_pool *
1007 find_literal_pool (void)
1009 literal_pool * pool;
1011 for (pool = list_of_pools; pool != NULL; pool = pool->next)
1013 if (pool->section == now_seg
1014 && pool->sub_section == now_subseg)
1015 break;
1018 return pool;
1021 static literal_pool *
1022 find_or_make_literal_pool (void)
1024 /* Next literal pool ID number. */
1025 static unsigned int latest_pool_num = 1;
1026 literal_pool * pool;
1028 pool = find_literal_pool ();
1030 if (pool == NULL)
1032 /* Create a new pool. */
1033 pool = xmalloc (sizeof (* pool));
1034 if (! pool)
1035 return NULL;
1037 pool->next_free_entry = 0;
1038 pool->section = now_seg;
1039 pool->sub_section = now_subseg;
1040 pool->next = list_of_pools;
1041 pool->symbol = NULL;
1043 /* Add it to the list. */
1044 list_of_pools = pool;
1047 /* New pools, and emptied pools, will have a NULL symbol. */
1048 if (pool->symbol == NULL)
1050 pool->symbol = symbol_create (FAKE_LABEL_NAME, undefined_section,
1051 (valueT) 0, &zero_address_frag);
1052 pool->id = latest_pool_num ++;
1055 /* Done. */
1056 return pool;
1059 /* Add the literal in the global 'inst'
1060 structure to the relevent literal pool. */
1062 static int
1063 add_to_lit_pool (void)
1065 literal_pool * pool;
1066 unsigned int entry;
1068 pool = find_or_make_literal_pool ();
1070 /* Check if this literal value is already in the pool. */
1071 for (entry = 0; entry < pool->next_free_entry; entry ++)
1073 if ((pool->literals[entry].X_op == inst.reloc.exp.X_op)
1074 && (inst.reloc.exp.X_op == O_constant)
1075 && (pool->literals[entry].X_add_number
1076 == inst.reloc.exp.X_add_number)
1077 && (pool->literals[entry].X_unsigned
1078 == inst.reloc.exp.X_unsigned))
1079 break;
1081 if ((pool->literals[entry].X_op == inst.reloc.exp.X_op)
1082 && (inst.reloc.exp.X_op == O_symbol)
1083 && (pool->literals[entry].X_add_number
1084 == inst.reloc.exp.X_add_number)
1085 && (pool->literals[entry].X_add_symbol
1086 == inst.reloc.exp.X_add_symbol)
1087 && (pool->literals[entry].X_op_symbol
1088 == inst.reloc.exp.X_op_symbol))
1089 break;
1092 /* Do we need to create a new entry? */
1093 if (entry == pool->next_free_entry)
1095 if (entry >= MAX_LITERAL_POOL_SIZE)
1097 inst.error = _("literal pool overflow");
1098 return FAIL;
1101 pool->literals[entry] = inst.reloc.exp;
1102 pool->next_free_entry += 1;
1105 inst.reloc.exp.X_op = O_symbol;
1106 inst.reloc.exp.X_add_number = ((int) entry) * 4 - 8;
1107 inst.reloc.exp.X_add_symbol = pool->symbol;
1109 return SUCCESS;
1112 /* Can't use symbol_new here, so have to create a symbol and then at
1113 a later date assign it a value. Thats what these functions do. */
1115 static void
1116 symbol_locate (symbolS * symbolP,
1117 const char * name, /* It is copied, the caller can modify. */
1118 segT segment, /* Segment identifier (SEG_<something>). */
1119 valueT valu, /* Symbol value. */
1120 fragS * frag) /* Associated fragment. */
1122 unsigned int name_length;
1123 char * preserved_copy_of_name;
1125 name_length = strlen (name) + 1; /* +1 for \0. */
1126 obstack_grow (&notes, name, name_length);
1127 preserved_copy_of_name = obstack_finish (&notes);
1128 #ifdef STRIP_UNDERSCORE
1129 if (preserved_copy_of_name[0] == '_')
1130 preserved_copy_of_name++;
1131 #endif
1133 #ifdef tc_canonicalize_symbol_name
1134 preserved_copy_of_name =
1135 tc_canonicalize_symbol_name (preserved_copy_of_name);
1136 #endif
1138 S_SET_NAME (symbolP, preserved_copy_of_name);
1140 S_SET_SEGMENT (symbolP, segment);
1141 S_SET_VALUE (symbolP, valu);
1142 symbol_clear_list_pointers (symbolP);
1144 symbol_set_frag (symbolP, frag);
1146 /* Link to end of symbol chain. */
1148 extern int symbol_table_frozen;
1150 if (symbol_table_frozen)
1151 abort ();
1154 symbol_append (symbolP, symbol_lastP, & symbol_rootP, & symbol_lastP);
1156 obj_symbol_new_hook (symbolP);
1158 #ifdef tc_symbol_new_hook
1159 tc_symbol_new_hook (symbolP);
1160 #endif
1162 #ifdef DEBUG_SYMS
1163 verify_symbol_chain (symbol_rootP, symbol_lastP);
1164 #endif /* DEBUG_SYMS */
1167 /* Check that an immediate is valid.
1168 If so, convert it to the right format. */
1170 static unsigned int
1171 validate_immediate (unsigned int val)
1173 unsigned int a;
1174 unsigned int i;
1176 #define rotate_left(v, n) (v << n | v >> (32 - n))
1178 for (i = 0; i < 32; i += 2)
1179 if ((a = rotate_left (val, i)) <= 0xff)
1180 return a | (i << 7); /* 12-bit pack: [shift-cnt,const]. */
1182 return FAIL;
1185 /* Check to see if an immediate can be computed as two separate immediate
1186 values, added together. We already know that this value cannot be
1187 computed by just one ARM instruction. */
1189 static unsigned int
1190 validate_immediate_twopart (unsigned int val,
1191 unsigned int * highpart)
1193 unsigned int a;
1194 unsigned int i;
1196 for (i = 0; i < 32; i += 2)
1197 if (((a = rotate_left (val, i)) & 0xff) != 0)
1199 if (a & 0xff00)
1201 if (a & ~ 0xffff)
1202 continue;
1203 * highpart = (a >> 8) | ((i + 24) << 7);
1205 else if (a & 0xff0000)
1207 if (a & 0xff000000)
1208 continue;
1209 * highpart = (a >> 16) | ((i + 16) << 7);
1211 else
1213 assert (a & 0xff000000);
1214 * highpart = (a >> 24) | ((i + 8) << 7);
1217 return (a & 0xff) | (i << 7);
1220 return FAIL;
1223 static int
1224 validate_offset_imm (unsigned int val, int hwse)
1226 if ((hwse && val > 255) || val > 4095)
1227 return FAIL;
1228 return val;
1232 #ifdef OBJ_ELF
1233 /* This code is to handle mapping symbols as defined in the ARM ELF spec.
1234 (This text is taken from version B-02 of the spec):
1236 4.4.7 Mapping and tagging symbols
1238 A section of an ARM ELF file can contain a mixture of ARM code,
1239 Thumb code, and data. There are inline transitions between code
1240 and data at literal pool boundaries. There can also be inline
1241 transitions between ARM code and Thumb code, for example in
1242 ARM-Thumb inter-working veneers. Linkers, machine-level
1243 debuggers, profiling tools, and disassembly tools need to map
1244 images accurately. For example, setting an ARM breakpoint on a
1245 Thumb location, or in a literal pool, can crash the program
1246 being debugged, ruining the debugging session.
1248 ARM ELF entities are mapped (see section 4.4.7.1 below) and
1249 tagged (see section 4.4.7.2 below) using local symbols (with
1250 binding STB_LOCAL). To assist consumers, mapping and tagging
1251 symbols should be collated first in the symbol table, before
1252 other symbols with binding STB_LOCAL.
1254 To allow properly collated mapping and tagging symbols to be
1255 skipped by consumers that have no interest in them, the first
1256 such symbol should have the name $m and its st_value field equal
1257 to the total number of mapping and tagging symbols (including
1258 the $m) in the symbol table.
1260 4.4.7.1 Mapping symbols
1262 $a Labels the first byte of a sequence of ARM instructions.
1263 Its type is STT_FUNC.
1265 $d Labels the first byte of a sequence of data items.
1266 Its type is STT_OBJECT.
1268 $t Labels the first byte of a sequence of Thumb instructions.
1269 Its type is STT_FUNC.
1271 This list of mapping symbols may be extended in the future.
1273 Section-relative mapping symbols
1275 Mapping symbols defined in a section define a sequence of
1276 half-open address intervals that cover the address range of the
1277 section. Each interval starts at the address defined by a
1278 mapping symbol, and continues up to, but not including, the
1279 address defined by the next (in address order) mapping symbol or
1280 the end of the section. A corollary is that there must be a
1281 mapping symbol defined at the beginning of each section.
1282 Consumers can ignore the size of a section-relative mapping
1283 symbol. Producers can set it to 0.
1285 Absolute mapping symbols
1287 Because of the need to crystallize a Thumb address with the
1288 Thumb-bit set, absolute symbol of type STT_FUNC (symbols of type
1289 STT_FUNC defined in section SHN_ABS) need to be mapped with $a
1290 or $t.
1292 The extent of a mapping symbol defined in SHN_ABS is [st_value,
1293 st_value + st_size), or [st_value, st_value + 1) if st_size = 0,
1294 where [x, y) denotes the half-open address range from x,
1295 inclusive, to y, exclusive.
1297 In the absence of a mapping symbol, a consumer can interpret a
1298 function symbol with an odd value as the Thumb code address
1299 obtained by clearing the least significant bit of the
1300 value. This interpretation is deprecated, and it may not work in
1301 the future.
1303 Note - the Tagging symbols ($b, $f, $p $m) have been dropped from
1304 the EABI (which is still under development), so they are not
1305 implemented here. */
1307 static enum mstate mapstate = MAP_UNDEFINED;
1309 static void
1310 mapping_state (enum mstate state)
1312 symbolS * symbolP;
1313 const char * symname;
1314 int type;
1316 if (mapstate == state)
1317 /* The mapping symbol has already been emitted.
1318 There is nothing else to do. */
1319 return;
1321 mapstate = state;
1323 switch (state)
1325 case MAP_DATA:
1326 symname = "$d";
1327 type = BSF_OBJECT;
1328 break;
1329 case MAP_ARM:
1330 symname = "$a";
1331 type = BSF_FUNCTION;
1332 break;
1333 case MAP_THUMB:
1334 symname = "$t";
1335 type = BSF_FUNCTION;
1336 break;
1337 case MAP_UNDEFINED:
1338 return;
1339 default:
1340 abort ();
1343 seg_info (now_seg)->tc_segment_info_data = state;
1345 symbolP = symbol_new (symname, now_seg, (valueT) frag_now_fix (), frag_now);
1346 symbol_table_insert (symbolP);
1347 symbol_get_bfdsym (symbolP)->flags |= type | BSF_LOCAL;
1349 switch (state)
1351 case MAP_ARM:
1352 THUMB_SET_FUNC (symbolP, 0);
1353 ARM_SET_THUMB (symbolP, 0);
1354 ARM_SET_INTERWORK (symbolP, support_interwork);
1355 break;
1357 case MAP_THUMB:
1358 THUMB_SET_FUNC (symbolP, 1);
1359 ARM_SET_THUMB (symbolP, 1);
1360 ARM_SET_INTERWORK (symbolP, support_interwork);
1361 break;
1363 case MAP_DATA:
1364 default:
1365 return;
1369 /* When we change sections we need to issue a new mapping symbol. */
1371 void
1372 arm_elf_change_section (void)
1374 flagword flags;
1376 /* Link an unlinked unwind index table section to the .text section. */
1377 if (elf_section_type (now_seg) == SHT_ARM_EXIDX
1378 && elf_linked_to_section (now_seg) == NULL)
1379 elf_linked_to_section (now_seg) = text_section;
1381 if (!SEG_NORMAL (now_seg))
1382 return;
1384 flags = bfd_get_section_flags (stdoutput, now_seg);
1386 /* We can ignore sections that only contain debug info. */
1387 if ((flags & SEC_ALLOC) == 0)
1388 return;
1390 mapstate = seg_info (now_seg)->tc_segment_info_data;
1394 arm_elf_section_type (const char * str, size_t len)
1396 if (len == 5 && strncmp (str, "exidx", 5) == 0)
1397 return SHT_ARM_EXIDX;
1399 return -1;
1401 #else
1402 #define mapping_state(a)
1403 #endif /* OBJ_ELF */
1405 /* arm_reg_parse () := if it looks like a register, return its token and
1406 advance the pointer. */
1408 static int
1409 arm_reg_parse (char ** ccp, struct hash_control * htab)
1411 char * start = * ccp;
1412 char c;
1413 char * p;
1414 struct reg_entry * reg;
1416 #ifdef REGISTER_PREFIX
1417 if (*start != REGISTER_PREFIX)
1418 return FAIL;
1419 p = start + 1;
1420 #else
1421 p = start;
1422 #ifdef OPTIONAL_REGISTER_PREFIX
1423 if (*p == OPTIONAL_REGISTER_PREFIX)
1424 p++, start++;
1425 #endif
1426 #endif
1427 if (!ISALPHA (*p) || !is_name_beginner (*p))
1428 return FAIL;
1430 c = *p++;
1431 while (ISALPHA (c) || ISDIGIT (c) || c == '_')
1432 c = *p++;
1434 *--p = 0;
1435 reg = (struct reg_entry *) hash_find (htab, start);
1436 *p = c;
1438 if (reg)
1440 *ccp = p;
1441 return reg->number;
1444 return FAIL;
1447 /* Search for the following register name in each of the possible reg name
1448 tables. Return the classification if found, or REG_TYPE_MAX if not
1449 present. */
1451 static enum arm_reg_type
1452 arm_reg_parse_any (char *cp)
1454 int i;
1456 for (i = (int) REG_TYPE_FIRST; i < (int) REG_TYPE_MAX; i++)
1457 if (arm_reg_parse (&cp, all_reg_maps[i].htab) != FAIL)
1458 return (enum arm_reg_type) i;
1460 return REG_TYPE_MAX;
1463 static void
1464 opcode_select (int width)
1466 switch (width)
1468 case 16:
1469 if (! thumb_mode)
1471 if (! (cpu_variant & ARM_EXT_V4T))
1472 as_bad (_("selected processor does not support THUMB opcodes"));
1474 thumb_mode = 1;
1475 /* No need to force the alignment, since we will have been
1476 coming from ARM mode, which is word-aligned. */
1477 record_alignment (now_seg, 1);
1479 mapping_state (MAP_THUMB);
1480 break;
1482 case 32:
1483 if (thumb_mode)
1485 if ((cpu_variant & ARM_ALL) == ARM_EXT_V4T)
1486 as_bad (_("selected processor does not support ARM opcodes"));
1488 thumb_mode = 0;
1490 if (!need_pass_2)
1491 frag_align (2, 0, 0);
1493 record_alignment (now_seg, 1);
1495 mapping_state (MAP_ARM);
1496 break;
1498 default:
1499 as_bad (_("invalid instruction size selected (%d)"), width);
1503 static void
1504 s_req (int a ATTRIBUTE_UNUSED)
1506 as_bad (_("invalid syntax for .req directive"));
1509 /* The .unreq directive deletes an alias which was previously defined
1510 by .req. For example:
1512 my_alias .req r11
1513 .unreq my_alias */
1515 static void
1516 s_unreq (int a ATTRIBUTE_UNUSED)
1518 char * name;
1519 char saved_char;
1521 skip_whitespace (input_line_pointer);
1522 name = input_line_pointer;
1524 while (*input_line_pointer != 0
1525 && *input_line_pointer != ' '
1526 && *input_line_pointer != '\n')
1527 ++input_line_pointer;
1529 saved_char = *input_line_pointer;
1530 *input_line_pointer = 0;
1532 if (*name)
1534 enum arm_reg_type req_type = arm_reg_parse_any (name);
1536 if (req_type != REG_TYPE_MAX)
1538 char *temp_name = name;
1539 int req_no = arm_reg_parse (&temp_name, all_reg_maps[req_type].htab);
1541 if (req_no != FAIL)
1543 struct reg_entry *req_entry;
1545 /* Check to see if this alias is a builtin one. */
1546 req_entry = hash_delete (all_reg_maps[req_type].htab, name);
1548 if (!req_entry)
1549 as_bad (_("unreq: missing hash entry for \"%s\""), name);
1550 else if (req_entry->builtin)
1551 /* FIXME: We are deleting a built in register alias which
1552 points to a const data structure, so we only need to
1553 free up the memory used by the key in the hash table.
1554 Unfortunately we have not recorded this value, so this
1555 is a memory leak. */
1556 /* FIXME: Should we issue a warning message ? */
1558 else
1560 /* Deleting a user defined alias. We need to free the
1561 key and the value, but fortunately the key is the same
1562 as the value->name field. */
1563 free ((char *) req_entry->name);
1564 free (req_entry);
1567 else
1568 as_bad (_(".unreq: unrecognized symbol \"%s\""), name);
1570 else
1571 as_bad (_(".unreq: unrecognized symbol \"%s\""), name);
1573 else
1574 as_bad (_("invalid syntax for .unreq directive"));
1576 *input_line_pointer = saved_char;
1577 demand_empty_rest_of_line ();
1580 static void
1581 s_bss (int ignore ATTRIBUTE_UNUSED)
1583 /* We don't support putting frags in the BSS segment, we fake it by
1584 marking in_bss, then looking at s_skip for clues. */
1585 subseg_set (bss_section, 0);
1586 demand_empty_rest_of_line ();
1587 mapping_state (MAP_DATA);
1590 static void
1591 s_even (int ignore ATTRIBUTE_UNUSED)
1593 /* Never make frag if expect extra pass. */
1594 if (!need_pass_2)
1595 frag_align (1, 0, 0);
1597 record_alignment (now_seg, 1);
1599 demand_empty_rest_of_line ();
1602 static void
1603 s_ltorg (int ignored ATTRIBUTE_UNUSED)
1605 unsigned int entry;
1606 literal_pool * pool;
1607 char sym_name[20];
1609 pool = find_literal_pool ();
1610 if (pool == NULL
1611 || pool->symbol == NULL
1612 || pool->next_free_entry == 0)
1613 return;
1615 mapping_state (MAP_DATA);
1617 /* Align pool as you have word accesses.
1618 Only make a frag if we have to. */
1619 if (!need_pass_2)
1620 frag_align (2, 0, 0);
1622 record_alignment (now_seg, 2);
1624 sprintf (sym_name, "$$lit_\002%x", pool->id);
1626 symbol_locate (pool->symbol, sym_name, now_seg,
1627 (valueT) frag_now_fix (), frag_now);
1628 symbol_table_insert (pool->symbol);
1630 ARM_SET_THUMB (pool->symbol, thumb_mode);
1632 #if defined OBJ_COFF || defined OBJ_ELF
1633 ARM_SET_INTERWORK (pool->symbol, support_interwork);
1634 #endif
1636 for (entry = 0; entry < pool->next_free_entry; entry ++)
1637 /* First output the expression in the instruction to the pool. */
1638 emit_expr (&(pool->literals[entry]), 4); /* .word */
1640 /* Mark the pool as empty. */
1641 pool->next_free_entry = 0;
1642 pool->symbol = NULL;
1645 /* Same as s_align_ptwo but align 0 => align 2. */
1647 static void
1648 s_align (int unused ATTRIBUTE_UNUSED)
1650 int temp;
1651 long temp_fill;
1652 long max_alignment = 15;
1654 temp = get_absolute_expression ();
1655 if (temp > max_alignment)
1656 as_bad (_("alignment too large: %d assumed"), temp = max_alignment);
1657 else if (temp < 0)
1659 as_bad (_("alignment negative. 0 assumed."));
1660 temp = 0;
1663 if (*input_line_pointer == ',')
1665 input_line_pointer++;
1666 temp_fill = get_absolute_expression ();
1668 else
1669 temp_fill = 0;
1671 if (!temp)
1672 temp = 2;
1674 /* Only make a frag if we HAVE to. */
1675 if (temp && !need_pass_2)
1676 frag_align (temp, (int) temp_fill, 0);
1677 demand_empty_rest_of_line ();
1679 record_alignment (now_seg, temp);
1682 static void
1683 s_force_thumb (int ignore ATTRIBUTE_UNUSED)
1685 /* If we are not already in thumb mode go into it, EVEN if
1686 the target processor does not support thumb instructions.
1687 This is used by gcc/config/arm/lib1funcs.asm for example
1688 to compile interworking support functions even if the
1689 target processor should not support interworking. */
1690 if (! thumb_mode)
1692 thumb_mode = 2;
1694 record_alignment (now_seg, 1);
1697 demand_empty_rest_of_line ();
1700 static void
1701 s_thumb_func (int ignore ATTRIBUTE_UNUSED)
1703 if (! thumb_mode)
1704 opcode_select (16);
1706 /* The following label is the name/address of the start of a Thumb function.
1707 We need to know this for the interworking support. */
1708 label_is_thumb_function_name = TRUE;
1710 demand_empty_rest_of_line ();
1713 /* Perform a .set directive, but also mark the alias as
1714 being a thumb function. */
1716 static void
1717 s_thumb_set (int equiv)
1719 /* XXX the following is a duplicate of the code for s_set() in read.c
1720 We cannot just call that code as we need to get at the symbol that
1721 is created. */
1722 char * name;
1723 char delim;
1724 char * end_name;
1725 symbolS * symbolP;
1727 /* Especial apologies for the random logic:
1728 This just grew, and could be parsed much more simply!
1729 Dean - in haste. */
1730 name = input_line_pointer;
1731 delim = get_symbol_end ();
1732 end_name = input_line_pointer;
1733 *end_name = delim;
1735 SKIP_WHITESPACE ();
1737 if (*input_line_pointer != ',')
1739 *end_name = 0;
1740 as_bad (_("expected comma after name \"%s\""), name);
1741 *end_name = delim;
1742 ignore_rest_of_line ();
1743 return;
1746 input_line_pointer++;
1747 *end_name = 0;
1749 if (name[0] == '.' && name[1] == '\0')
1751 /* XXX - this should not happen to .thumb_set. */
1752 abort ();
1755 if ((symbolP = symbol_find (name)) == NULL
1756 && (symbolP = md_undefined_symbol (name)) == NULL)
1758 #ifndef NO_LISTING
1759 /* When doing symbol listings, play games with dummy fragments living
1760 outside the normal fragment chain to record the file and line info
1761 for this symbol. */
1762 if (listing & LISTING_SYMBOLS)
1764 extern struct list_info_struct * listing_tail;
1765 fragS * dummy_frag = xmalloc (sizeof (fragS));
1767 memset (dummy_frag, 0, sizeof (fragS));
1768 dummy_frag->fr_type = rs_fill;
1769 dummy_frag->line = listing_tail;
1770 symbolP = symbol_new (name, undefined_section, 0, dummy_frag);
1771 dummy_frag->fr_symbol = symbolP;
1773 else
1774 #endif
1775 symbolP = symbol_new (name, undefined_section, 0, &zero_address_frag);
1777 #ifdef OBJ_COFF
1778 /* "set" symbols are local unless otherwise specified. */
1779 SF_SET_LOCAL (symbolP);
1780 #endif /* OBJ_COFF */
1781 } /* Make a new symbol. */
1783 symbol_table_insert (symbolP);
1785 * end_name = delim;
1787 if (equiv
1788 && S_IS_DEFINED (symbolP)
1789 && S_GET_SEGMENT (symbolP) != reg_section)
1790 as_bad (_("symbol `%s' already defined"), S_GET_NAME (symbolP));
1792 pseudo_set (symbolP);
1794 demand_empty_rest_of_line ();
1796 /* XXX Now we come to the Thumb specific bit of code. */
1798 THUMB_SET_FUNC (symbolP, 1);
1799 ARM_SET_THUMB (symbolP, 1);
1800 #if defined OBJ_ELF || defined OBJ_COFF
1801 ARM_SET_INTERWORK (symbolP, support_interwork);
1802 #endif
1805 static void
1806 s_arm (int ignore ATTRIBUTE_UNUSED)
1808 opcode_select (32);
1809 demand_empty_rest_of_line ();
1812 static void
1813 s_thumb (int ignore ATTRIBUTE_UNUSED)
1815 opcode_select (16);
1816 demand_empty_rest_of_line ();
1819 static void
1820 s_code (int unused ATTRIBUTE_UNUSED)
1822 int temp;
1824 temp = get_absolute_expression ();
1825 switch (temp)
1827 case 16:
1828 case 32:
1829 opcode_select (temp);
1830 break;
1832 default:
1833 as_bad (_("invalid operand to .code directive (%d) (expecting 16 or 32)"), temp);
1837 static void
1838 end_of_line (char * str)
1840 skip_whitespace (str);
1842 if (*str != '\0' && !inst.error)
1843 inst.error = _("garbage following instruction");
1846 static int
1847 skip_past_comma (char ** str)
1849 char * p = * str, c;
1850 int comma = 0;
1852 while ((c = *p) == ' ' || c == ',')
1854 p++;
1855 if (c == ',' && comma++)
1856 return FAIL;
1859 if (c == '\0')
1860 return FAIL;
1862 *str = p;
1863 return comma ? SUCCESS : FAIL;
1866 /* Return TRUE if anything in the expression is a bignum. */
1868 static int
1869 walk_no_bignums (symbolS * sp)
1871 if (symbol_get_value_expression (sp)->X_op == O_big)
1872 return 1;
1874 if (symbol_get_value_expression (sp)->X_add_symbol)
1876 return (walk_no_bignums (symbol_get_value_expression (sp)->X_add_symbol)
1877 || (symbol_get_value_expression (sp)->X_op_symbol
1878 && walk_no_bignums (symbol_get_value_expression (sp)->X_op_symbol)));
1881 return 0;
1884 static int in_my_get_expression = 0;
1886 static int
1887 my_get_expression (expressionS * ep, char ** str)
1889 char * save_in;
1890 segT seg;
1892 save_in = input_line_pointer;
1893 input_line_pointer = *str;
1894 in_my_get_expression = 1;
1895 seg = expression (ep);
1896 in_my_get_expression = 0;
1898 if (ep->X_op == O_illegal)
1900 /* We found a bad expression in md_operand(). */
1901 *str = input_line_pointer;
1902 input_line_pointer = save_in;
1903 return 1;
1906 #ifdef OBJ_AOUT
1907 if (seg != absolute_section
1908 && seg != text_section
1909 && seg != data_section
1910 && seg != bss_section
1911 && seg != undefined_section)
1913 inst.error = _("bad_segment");
1914 *str = input_line_pointer;
1915 input_line_pointer = save_in;
1916 return 1;
1918 #endif
1920 /* Get rid of any bignums now, so that we don't generate an error for which
1921 we can't establish a line number later on. Big numbers are never valid
1922 in instructions, which is where this routine is always called. */
1923 if (ep->X_op == O_big
1924 || (ep->X_add_symbol
1925 && (walk_no_bignums (ep->X_add_symbol)
1926 || (ep->X_op_symbol
1927 && walk_no_bignums (ep->X_op_symbol)))))
1929 inst.error = _("invalid constant");
1930 *str = input_line_pointer;
1931 input_line_pointer = save_in;
1932 return 1;
1935 *str = input_line_pointer;
1936 input_line_pointer = save_in;
1937 return 0;
1940 /* A standard register must be given at this point.
1941 SHIFT is the place to put it in inst.instruction.
1942 Restores input start point on error.
1943 Returns the reg#, or FAIL. */
1945 static int
1946 reg_required_here (char ** str, int shift)
1948 static char buff [128]; /* XXX */
1949 int reg;
1950 char * start = * str;
1952 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_RN].htab)) != FAIL)
1954 if (shift >= 0)
1955 inst.instruction |= reg << shift;
1956 return reg;
1959 /* Restore the start point, we may have got a reg of the wrong class. */
1960 *str = start;
1962 /* In the few cases where we might be able to accept something else
1963 this error can be overridden. */
1964 sprintf (buff, _("register expected, not '%.100s'"), start);
1965 inst.error = buff;
1967 return FAIL;
1970 /* A Intel Wireless MMX technology register
1971 must be given at this point.
1972 Shift is the place to put it in inst.instruction.
1973 Restores input start point on err.
1974 Returns the reg#, or FAIL. */
1976 static int
1977 wreg_required_here (char ** str,
1978 int shift,
1979 enum wreg_type reg_type)
1981 static char buff [128];
1982 int reg;
1983 char * start = *str;
1985 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_IWMMXT].htab)) != FAIL)
1987 if (wr_register (reg)
1988 && (reg_type == IWMMXT_REG_WR || reg_type == IWMMXT_REG_WR_OR_WC))
1990 if (shift >= 0)
1991 inst.instruction |= (reg ^ WR_PREFIX) << shift;
1992 return reg;
1994 else if (wc_register (reg)
1995 && (reg_type == IWMMXT_REG_WC || reg_type == IWMMXT_REG_WR_OR_WC))
1997 if (shift >= 0)
1998 inst.instruction |= (reg ^ WC_PREFIX) << shift;
1999 return reg;
2001 else if ((wcg_register (reg) && reg_type == IWMMXT_REG_WCG))
2003 if (shift >= 0)
2004 inst.instruction |= ((reg ^ WC_PREFIX) - 8) << shift;
2005 return reg;
2009 /* Restore the start point, we may have got a reg of the wrong class. */
2010 *str = start;
2012 /* In the few cases where we might be able to accept
2013 something else this error can be overridden. */
2014 sprintf (buff, _("Intel Wireless MMX technology register expected, not '%.100s'"), start);
2015 inst.error = buff;
2017 return FAIL;
2020 static const struct asm_psr *
2021 arm_psr_parse (char ** ccp)
2023 char * start = * ccp;
2024 char c;
2025 char * p;
2026 const struct asm_psr * psr;
2028 p = start;
2030 /* Skip to the end of the next word in the input stream. */
2033 c = *p++;
2035 while (ISALPHA (c) || c == '_');
2037 /* Terminate the word. */
2038 *--p = 0;
2040 /* CPSR's and SPSR's can now be lowercase. This is just a convenience
2041 feature for ease of use and backwards compatibility. */
2042 if (!strncmp (start, "cpsr", 4))
2043 strncpy (start, "CPSR", 4);
2044 else if (!strncmp (start, "spsr", 4))
2045 strncpy (start, "SPSR", 4);
2047 /* Now locate the word in the psr hash table. */
2048 psr = (const struct asm_psr *) hash_find (arm_psr_hsh, start);
2050 /* Restore the input stream. */
2051 *p = c;
2053 /* If we found a valid match, advance the
2054 stream pointer past the end of the word. */
2055 *ccp = p;
2057 return psr;
2060 /* Parse the input looking for a PSR flag. */
2062 static int
2063 psr_required_here (char ** str)
2065 char * start = * str;
2066 const struct asm_psr * psr;
2068 psr = arm_psr_parse (str);
2070 if (psr)
2072 /* If this is the SPSR that is being modified, set the R bit. */
2073 if (! psr->cpsr)
2074 inst.instruction |= SPSR_BIT;
2076 /* Set the psr flags in the MSR instruction. */
2077 inst.instruction |= psr->field << PSR_SHIFT;
2079 return SUCCESS;
2082 /* In the few cases where we might be able to accept
2083 something else this error can be overridden. */
2084 inst.error = _("flag for {c}psr instruction expected");
2086 /* Restore the start point. */
2087 *str = start;
2088 return FAIL;
2091 static int
2092 co_proc_number (char ** str)
2094 int processor, pchar;
2095 char *start;
2097 skip_whitespace (*str);
2098 start = *str;
2100 /* The data sheet seems to imply that just a number on its own is valid
2101 here, but the RISC iX assembler seems to accept a prefix 'p'. We will
2102 accept either. */
2103 if ((processor = arm_reg_parse (str, all_reg_maps[REG_TYPE_CP].htab))
2104 == FAIL)
2106 *str = start;
2108 pchar = *(*str)++;
2109 if (pchar >= '0' && pchar <= '9')
2111 processor = pchar - '0';
2112 if (**str >= '0' && **str <= '9')
2114 processor = processor * 10 + *(*str)++ - '0';
2115 if (processor > 15)
2117 inst.error = _("illegal co-processor number");
2118 return FAIL;
2122 else
2124 inst.error = all_reg_maps[REG_TYPE_CP].expected;
2125 return FAIL;
2129 inst.instruction |= processor << 8;
2130 return SUCCESS;
2133 static int
2134 cp_opc_expr (char ** str, int where, int length)
2136 expressionS expr;
2138 skip_whitespace (* str);
2140 memset (&expr, '\0', sizeof (expr));
2142 if (my_get_expression (&expr, str))
2143 return FAIL;
2144 if (expr.X_op != O_constant)
2146 inst.error = _("bad or missing expression");
2147 return FAIL;
2150 if ((expr.X_add_number & ((1 << length) - 1)) != expr.X_add_number)
2152 inst.error = _("immediate co-processor expression too large");
2153 return FAIL;
2156 inst.instruction |= expr.X_add_number << where;
2157 return SUCCESS;
2160 static int
2161 cp_reg_required_here (char ** str, int where)
2163 int reg;
2164 char * start = *str;
2166 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_CN].htab)) != FAIL)
2168 inst.instruction |= reg << where;
2169 return reg;
2172 /* In the few cases where we might be able to accept something else
2173 this error can be overridden. */
2174 inst.error = all_reg_maps[REG_TYPE_CN].expected;
2176 /* Restore the start point. */
2177 *str = start;
2178 return FAIL;
2181 static int
2182 fp_reg_required_here (char ** str, int where)
2184 int reg;
2185 char * start = * str;
2187 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_FN].htab)) != FAIL)
2189 inst.instruction |= reg << where;
2190 return reg;
2193 /* In the few cases where we might be able to accept something else
2194 this error can be overridden. */
2195 inst.error = all_reg_maps[REG_TYPE_FN].expected;
2197 /* Restore the start point. */
2198 *str = start;
2199 return FAIL;
2202 static int
2203 cp_address_offset (char ** str)
2205 int offset;
2207 skip_whitespace (* str);
2209 if (! is_immediate_prefix (**str))
2211 inst.error = _("immediate expression expected");
2212 return FAIL;
2215 (*str)++;
2217 if (my_get_expression (& inst.reloc.exp, str))
2218 return FAIL;
2220 if (inst.reloc.exp.X_op == O_constant)
2222 offset = inst.reloc.exp.X_add_number;
2224 if (offset & 3)
2226 inst.error = _("co-processor address must be word aligned");
2227 return FAIL;
2230 if (offset > 1023 || offset < -1023)
2232 inst.error = _("offset too large");
2233 return FAIL;
2236 if (offset >= 0)
2237 inst.instruction |= INDEX_UP;
2238 else
2239 offset = -offset;
2241 inst.instruction |= offset >> 2;
2243 else
2244 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
2246 return SUCCESS;
2249 static int
2250 cp_address_required_here (char ** str, int wb_ok)
2252 char * p = * str;
2253 int pre_inc = 0;
2254 int write_back = 0;
2256 if (*p == '[')
2258 int reg;
2260 p++;
2261 skip_whitespace (p);
2263 if ((reg = reg_required_here (& p, 16)) == FAIL)
2264 return FAIL;
2266 skip_whitespace (p);
2268 if (*p == ']')
2270 p++;
2272 skip_whitespace (p);
2274 if (*p == '\0')
2276 /* As an extension to the official ARM syntax we allow:
2277 [Rn]
2278 as a short hand for:
2279 [Rn,#0] */
2280 inst.instruction |= PRE_INDEX | INDEX_UP;
2281 *str = p;
2282 return SUCCESS;
2285 if (skip_past_comma (& p) == FAIL)
2287 inst.error = _("comma expected after closing square bracket");
2288 return FAIL;
2291 skip_whitespace (p);
2293 if (*p == '#')
2295 if (wb_ok)
2297 /* [Rn], #expr */
2298 write_back = WRITE_BACK;
2300 if (reg == REG_PC)
2302 inst.error = _("pc may not be used in post-increment");
2303 return FAIL;
2306 if (cp_address_offset (& p) == FAIL)
2307 return FAIL;
2309 else
2310 pre_inc = PRE_INDEX | INDEX_UP;
2312 else if (*p == '{')
2314 int option;
2316 /* [Rn], {<expr>} */
2317 p++;
2319 skip_whitespace (p);
2321 if (my_get_expression (& inst.reloc.exp, & p))
2322 return FAIL;
2324 if (inst.reloc.exp.X_op == O_constant)
2326 option = inst.reloc.exp.X_add_number;
2328 if (option > 255 || option < 0)
2330 inst.error = _("'option' field too large");
2331 return FAIL;
2334 skip_whitespace (p);
2336 if (*p != '}')
2338 inst.error = _("'}' expected at end of 'option' field");
2339 return FAIL;
2341 else
2343 p++;
2344 inst.instruction |= option;
2345 inst.instruction |= INDEX_UP;
2348 else
2350 inst.error = _("non-constant expressions for 'option' field not supported");
2351 return FAIL;
2354 else
2356 inst.error = _("# or { expected after comma");
2357 return FAIL;
2360 else
2362 /* '['Rn, #expr']'[!] */
2364 if (skip_past_comma (& p) == FAIL)
2366 inst.error = _("pre-indexed expression expected");
2367 return FAIL;
2370 pre_inc = PRE_INDEX;
2372 if (cp_address_offset (& p) == FAIL)
2373 return FAIL;
2375 skip_whitespace (p);
2377 if (*p++ != ']')
2379 inst.error = _("missing ]");
2380 return FAIL;
2383 skip_whitespace (p);
2385 if (wb_ok && *p == '!')
2387 if (reg == REG_PC)
2389 inst.error = _("pc may not be used with write-back");
2390 return FAIL;
2393 p++;
2394 write_back = WRITE_BACK;
2398 else
2400 if (my_get_expression (&inst.reloc.exp, &p))
2401 return FAIL;
2403 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
2404 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
2405 inst.reloc.pc_rel = 1;
2406 inst.instruction |= (REG_PC << 16);
2407 pre_inc = PRE_INDEX;
2410 inst.instruction |= write_back | pre_inc;
2411 *str = p;
2412 return SUCCESS;
2415 static int
2416 cp_byte_address_offset (char ** str)
2418 int offset;
2420 skip_whitespace (* str);
2422 if (! is_immediate_prefix (**str))
2424 inst.error = _("immediate expression expected");
2425 return FAIL;
2428 (*str)++;
2430 if (my_get_expression (& inst.reloc.exp, str))
2431 return FAIL;
2433 if (inst.reloc.exp.X_op == O_constant)
2435 offset = inst.reloc.exp.X_add_number;
2437 if (offset > 255 || offset < -255)
2439 inst.error = _("offset too large");
2440 return FAIL;
2443 if (offset >= 0)
2444 inst.instruction |= INDEX_UP;
2445 else
2446 offset = -offset;
2448 inst.instruction |= offset;
2450 else
2451 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM_S2;
2453 return SUCCESS;
2456 static int
2457 cp_byte_address_required_here (char ** str)
2459 char * p = * str;
2460 int pre_inc = 0;
2461 int write_back = 0;
2463 if (*p == '[')
2465 int reg;
2467 p++;
2468 skip_whitespace (p);
2470 if ((reg = reg_required_here (& p, 16)) == FAIL)
2471 return FAIL;
2473 skip_whitespace (p);
2475 if (*p == ']')
2477 p++;
2479 if (skip_past_comma (& p) == SUCCESS)
2481 /* [Rn], #expr */
2482 write_back = WRITE_BACK;
2484 if (reg == REG_PC)
2486 inst.error = _("pc may not be used in post-increment");
2487 return FAIL;
2490 if (cp_byte_address_offset (& p) == FAIL)
2491 return FAIL;
2493 else
2494 pre_inc = PRE_INDEX | INDEX_UP;
2496 else
2498 /* '['Rn, #expr']'[!] */
2500 if (skip_past_comma (& p) == FAIL)
2502 inst.error = _("pre-indexed expression expected");
2503 return FAIL;
2506 pre_inc = PRE_INDEX;
2508 if (cp_byte_address_offset (& p) == FAIL)
2509 return FAIL;
2511 skip_whitespace (p);
2513 if (*p++ != ']')
2515 inst.error = _("missing ]");
2516 return FAIL;
2519 skip_whitespace (p);
2521 if (*p == '!')
2523 if (reg == REG_PC)
2525 inst.error = _("pc may not be used with write-back");
2526 return FAIL;
2529 p++;
2530 write_back = WRITE_BACK;
2534 else
2536 if (my_get_expression (&inst.reloc.exp, &p))
2537 return FAIL;
2539 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM_S2;
2540 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
2541 inst.reloc.pc_rel = 1;
2542 inst.instruction |= (REG_PC << 16);
2543 pre_inc = PRE_INDEX;
2546 inst.instruction |= write_back | pre_inc;
2547 *str = p;
2548 return SUCCESS;
2551 static void
2552 do_nop (char * str)
2554 skip_whitespace (str);
2555 if (*str == '{')
2557 str++;
2559 if (my_get_expression (&inst.reloc.exp, &str))
2560 inst.reloc.exp.X_op = O_illegal;
2561 else
2563 skip_whitespace (str);
2564 if (*str == '}')
2565 str++;
2566 else
2567 inst.reloc.exp.X_op = O_illegal;
2570 if (inst.reloc.exp.X_op != O_constant
2571 || inst.reloc.exp.X_add_number > 255
2572 || inst.reloc.exp.X_add_number < 0)
2574 inst.error = _("Invalid NOP hint");
2575 return;
2578 /* Arcitectural NOP hints are CPSR sets with no bits selected. */
2579 inst.instruction &= 0xf0000000;
2580 inst.instruction |= 0x0320f000 + inst.reloc.exp.X_add_number;
2583 end_of_line (str);
2586 static void
2587 do_empty (char * str)
2589 /* Do nothing really. */
2590 end_of_line (str);
2593 static void
2594 do_mrs (char * str)
2596 int skip = 0;
2598 /* Only one syntax. */
2599 skip_whitespace (str);
2601 if (reg_required_here (&str, 12) == FAIL)
2603 inst.error = BAD_ARGS;
2604 return;
2607 if (skip_past_comma (&str) == FAIL)
2609 inst.error = _("comma expected after register name");
2610 return;
2613 skip_whitespace (str);
2615 if ( streq (str, "CPSR")
2616 || streq (str, "SPSR")
2617 /* Lower case versions for backwards compatibility. */
2618 || streq (str, "cpsr")
2619 || streq (str, "spsr"))
2620 skip = 4;
2622 /* This is for backwards compatibility with older toolchains. */
2623 else if ( streq (str, "cpsr_all")
2624 || streq (str, "spsr_all"))
2625 skip = 8;
2626 else
2628 inst.error = _("CPSR or SPSR expected");
2629 return;
2632 if (* str == 's' || * str == 'S')
2633 inst.instruction |= SPSR_BIT;
2634 str += skip;
2636 end_of_line (str);
2639 /* Two possible forms:
2640 "{C|S}PSR_<field>, Rm",
2641 "{C|S}PSR_f, #expression". */
2643 static void
2644 do_msr (char * str)
2646 skip_whitespace (str);
2648 if (psr_required_here (& str) == FAIL)
2649 return;
2651 if (skip_past_comma (& str) == FAIL)
2653 inst.error = _("comma missing after psr flags");
2654 return;
2657 skip_whitespace (str);
2659 if (reg_required_here (& str, 0) != FAIL)
2661 inst.error = NULL;
2662 end_of_line (str);
2663 return;
2666 if (! is_immediate_prefix (* str))
2668 inst.error =
2669 _("only a register or immediate value can follow a psr flag");
2670 return;
2673 str ++;
2674 inst.error = NULL;
2676 if (my_get_expression (& inst.reloc.exp, & str))
2678 inst.error =
2679 _("only a register or immediate value can follow a psr flag");
2680 return;
2683 #if 0 /* The first edition of the ARM architecture manual stated that
2684 writing anything other than the flags with an immediate operation
2685 had UNPREDICTABLE effects. This constraint was removed in the
2686 second edition of the specification. */
2687 if ((cpu_variant & ARM_EXT_V5) != ARM_EXT_V5
2688 && inst.instruction & ((PSR_c | PSR_x | PSR_s) << PSR_SHIFT))
2690 inst.error = _("immediate value cannot be used to set this field");
2691 return;
2693 #endif
2695 inst.instruction |= INST_IMMEDIATE;
2697 if (inst.reloc.exp.X_add_symbol)
2699 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
2700 inst.reloc.pc_rel = 0;
2702 else
2704 unsigned value = validate_immediate (inst.reloc.exp.X_add_number);
2706 if (value == (unsigned) FAIL)
2708 inst.error = _("invalid constant");
2709 return;
2712 inst.instruction |= value;
2715 inst.error = NULL;
2716 end_of_line (str);
2719 /* Long Multiply Parser
2720 UMULL RdLo, RdHi, Rm, Rs
2721 SMULL RdLo, RdHi, Rm, Rs
2722 UMLAL RdLo, RdHi, Rm, Rs
2723 SMLAL RdLo, RdHi, Rm, Rs. */
2725 static void
2726 do_mull (char * str)
2728 int rdlo, rdhi, rm, rs;
2730 /* Only one format "rdlo, rdhi, rm, rs". */
2731 skip_whitespace (str);
2733 if ((rdlo = reg_required_here (&str, 12)) == FAIL)
2735 inst.error = BAD_ARGS;
2736 return;
2739 if (skip_past_comma (&str) == FAIL
2740 || (rdhi = reg_required_here (&str, 16)) == FAIL)
2742 inst.error = BAD_ARGS;
2743 return;
2746 if (skip_past_comma (&str) == FAIL
2747 || (rm = reg_required_here (&str, 0)) == FAIL)
2749 inst.error = BAD_ARGS;
2750 return;
2753 /* rdhi, rdlo and rm must all be different. */
2754 if (rdlo == rdhi || rdlo == rm || rdhi == rm)
2755 as_tsktsk (_("rdhi, rdlo and rm must all be different"));
2757 if (skip_past_comma (&str) == FAIL
2758 || (rs = reg_required_here (&str, 8)) == FAIL)
2760 inst.error = BAD_ARGS;
2761 return;
2764 if (rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC)
2766 inst.error = BAD_PC;
2767 return;
2770 end_of_line (str);
2773 static void
2774 do_mul (char * str)
2776 int rd, rm;
2778 /* Only one format "rd, rm, rs". */
2779 skip_whitespace (str);
2781 if ((rd = reg_required_here (&str, 16)) == FAIL)
2783 inst.error = BAD_ARGS;
2784 return;
2787 if (rd == REG_PC)
2789 inst.error = BAD_PC;
2790 return;
2793 if (skip_past_comma (&str) == FAIL
2794 || (rm = reg_required_here (&str, 0)) == FAIL)
2796 inst.error = BAD_ARGS;
2797 return;
2800 if (rm == REG_PC)
2802 inst.error = BAD_PC;
2803 return;
2806 if (rm == rd)
2807 as_tsktsk (_("rd and rm should be different in mul"));
2809 if (skip_past_comma (&str) == FAIL
2810 || (rm = reg_required_here (&str, 8)) == FAIL)
2812 inst.error = BAD_ARGS;
2813 return;
2816 if (rm == REG_PC)
2818 inst.error = BAD_PC;
2819 return;
2822 end_of_line (str);
2825 static void
2826 do_mla (char * str)
2828 int rd, rm;
2830 /* Only one format "rd, rm, rs, rn". */
2831 skip_whitespace (str);
2833 if ((rd = reg_required_here (&str, 16)) == FAIL)
2835 inst.error = BAD_ARGS;
2836 return;
2839 if (rd == REG_PC)
2841 inst.error = BAD_PC;
2842 return;
2845 if (skip_past_comma (&str) == FAIL
2846 || (rm = reg_required_here (&str, 0)) == FAIL)
2848 inst.error = BAD_ARGS;
2849 return;
2852 if (rm == REG_PC)
2854 inst.error = BAD_PC;
2855 return;
2858 if (rm == rd)
2859 as_tsktsk (_("rd and rm should be different in mla"));
2861 if (skip_past_comma (&str) == FAIL
2862 || (rd = reg_required_here (&str, 8)) == FAIL
2863 || skip_past_comma (&str) == FAIL
2864 || (rm = reg_required_here (&str, 12)) == FAIL)
2866 inst.error = BAD_ARGS;
2867 return;
2870 if (rd == REG_PC || rm == REG_PC)
2872 inst.error = BAD_PC;
2873 return;
2876 end_of_line (str);
2879 /* Expects *str -> the characters "acc0", possibly with leading blanks.
2880 Advances *str to the next non-alphanumeric.
2881 Returns 0, or else FAIL (in which case sets inst.error).
2883 (In a future XScale, there may be accumulators other than zero.
2884 At that time this routine and its callers can be upgraded to suit.) */
2886 static int
2887 accum0_required_here (char ** str)
2889 static char buff [128]; /* Note the address is taken. Hence, static. */
2890 char * p = * str;
2891 char c;
2892 int result = 0; /* The accum number. */
2894 skip_whitespace (p);
2896 *str = p; /* Advance caller's string pointer too. */
2897 c = *p++;
2898 while (ISALNUM (c))
2899 c = *p++;
2901 *--p = 0; /* Aap nul into input buffer at non-alnum. */
2903 if (! ( streq (*str, "acc0") || streq (*str, "ACC0")))
2905 sprintf (buff, _("acc0 expected, not '%.100s'"), *str);
2906 inst.error = buff;
2907 result = FAIL;
2910 *p = c; /* Unzap. */
2911 *str = p; /* Caller's string pointer to after match. */
2912 return result;
2915 static int
2916 ldst_extend_v4 (char ** str)
2918 int add = INDEX_UP;
2920 switch (**str)
2922 case '#':
2923 case '$':
2924 (*str)++;
2925 if (my_get_expression (& inst.reloc.exp, str))
2926 return FAIL;
2928 if (inst.reloc.exp.X_op == O_constant)
2930 int value = inst.reloc.exp.X_add_number;
2932 if (value < -255 || value > 255)
2934 inst.error = _("address offset too large");
2935 return FAIL;
2938 if (value < 0)
2940 value = -value;
2941 add = 0;
2944 /* Halfword and signextension instructions have the
2945 immediate value split across bits 11..8 and bits 3..0. */
2946 inst.instruction |= (add | HWOFFSET_IMM
2947 | ((value >> 4) << 8) | (value & 0xF));
2949 else
2951 inst.instruction |= HWOFFSET_IMM;
2952 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
2953 inst.reloc.pc_rel = 0;
2955 return SUCCESS;
2957 case '-':
2958 add = 0;
2959 /* Fall through. */
2961 case '+':
2962 (*str)++;
2963 /* Fall through. */
2965 default:
2966 if (reg_required_here (str, 0) == FAIL)
2967 return FAIL;
2969 inst.instruction |= add;
2970 return SUCCESS;
2974 /* Expects **str -> after a comma. May be leading blanks.
2975 Advances *str, recognizing a load mode, and setting inst.instruction.
2976 Returns rn, or else FAIL (in which case may set inst.error
2977 and not advance str)
2979 Note: doesn't know Rd, so no err checks that require such knowledge. */
2981 static int
2982 ld_mode_required_here (char ** string)
2984 char * str = * string;
2985 int rn;
2986 int pre_inc = 0;
2988 skip_whitespace (str);
2990 if (* str == '[')
2992 str++;
2994 skip_whitespace (str);
2996 if ((rn = reg_required_here (& str, 16)) == FAIL)
2997 return FAIL;
2999 skip_whitespace (str);
3001 if (* str == ']')
3003 str ++;
3005 if (skip_past_comma (& str) == SUCCESS)
3007 /* [Rn],... (post inc) */
3008 if (ldst_extend_v4 (&str) == FAIL)
3009 return FAIL;
3011 else /* [Rn] */
3013 skip_whitespace (str);
3015 if (* str == '!')
3017 str ++;
3018 inst.instruction |= WRITE_BACK;
3021 inst.instruction |= INDEX_UP | HWOFFSET_IMM;
3022 pre_inc = 1;
3025 else /* [Rn,...] */
3027 if (skip_past_comma (& str) == FAIL)
3029 inst.error = _("pre-indexed expression expected");
3030 return FAIL;
3033 pre_inc = 1;
3035 if (ldst_extend_v4 (&str) == FAIL)
3036 return FAIL;
3038 skip_whitespace (str);
3040 if (* str ++ != ']')
3042 inst.error = _("missing ]");
3043 return FAIL;
3046 skip_whitespace (str);
3048 if (* str == '!')
3050 str ++;
3051 inst.instruction |= WRITE_BACK;
3055 else if (* str == '=') /* ldr's "r,=label" syntax */
3056 /* We should never reach here, because <text> = <expression> is
3057 caught gas/read.c read_a_source_file() as a .set operation. */
3058 return FAIL;
3059 else /* PC +- 8 bit immediate offset. */
3061 if (my_get_expression (& inst.reloc.exp, & str))
3062 return FAIL;
3064 inst.instruction |= HWOFFSET_IMM; /* The I bit. */
3065 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
3066 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
3067 inst.reloc.pc_rel = 1;
3068 inst.instruction |= (REG_PC << 16);
3070 rn = REG_PC;
3071 pre_inc = 1;
3074 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
3075 * string = str;
3077 return rn;
3080 /* ARM V5E (El Segundo) signed-multiply-accumulate (argument parse)
3081 SMLAxy{cond} Rd,Rm,Rs,Rn
3082 SMLAWy{cond} Rd,Rm,Rs,Rn
3083 Error if any register is R15. */
3085 static void
3086 do_smla (char * str)
3088 int rd, rm, rs, rn;
3090 skip_whitespace (str);
3092 if ((rd = reg_required_here (& str, 16)) == FAIL
3093 || skip_past_comma (& str) == FAIL
3094 || (rm = reg_required_here (& str, 0)) == FAIL
3095 || skip_past_comma (& str) == FAIL
3096 || (rs = reg_required_here (& str, 8)) == FAIL
3097 || skip_past_comma (& str) == FAIL
3098 || (rn = reg_required_here (& str, 12)) == FAIL)
3099 inst.error = BAD_ARGS;
3101 else if (rd == REG_PC || rm == REG_PC || rs == REG_PC || rn == REG_PC)
3102 inst.error = BAD_PC;
3104 else
3105 end_of_line (str);
3108 /* ARM V5E (El Segundo) signed-multiply-accumulate-long (argument parse)
3109 SMLALxy{cond} Rdlo,Rdhi,Rm,Rs
3110 Error if any register is R15.
3111 Warning if Rdlo == Rdhi. */
3113 static void
3114 do_smlal (char * str)
3116 int rdlo, rdhi, rm, rs;
3118 skip_whitespace (str);
3120 if ((rdlo = reg_required_here (& str, 12)) == FAIL
3121 || skip_past_comma (& str) == FAIL
3122 || (rdhi = reg_required_here (& str, 16)) == FAIL
3123 || skip_past_comma (& str) == FAIL
3124 || (rm = reg_required_here (& str, 0)) == FAIL
3125 || skip_past_comma (& str) == FAIL
3126 || (rs = reg_required_here (& str, 8)) == FAIL)
3128 inst.error = BAD_ARGS;
3129 return;
3132 if (rdlo == REG_PC || rdhi == REG_PC || rm == REG_PC || rs == REG_PC)
3134 inst.error = BAD_PC;
3135 return;
3138 if (rdlo == rdhi)
3139 as_tsktsk (_("rdhi and rdlo must be different"));
3141 end_of_line (str);
3144 /* ARM V5E (El Segundo) signed-multiply (argument parse)
3145 SMULxy{cond} Rd,Rm,Rs
3146 Error if any register is R15. */
3148 static void
3149 do_smul (char * str)
3151 int rd, rm, rs;
3153 skip_whitespace (str);
3155 if ((rd = reg_required_here (& str, 16)) == FAIL
3156 || skip_past_comma (& str) == FAIL
3157 || (rm = reg_required_here (& str, 0)) == FAIL
3158 || skip_past_comma (& str) == FAIL
3159 || (rs = reg_required_here (& str, 8)) == FAIL)
3160 inst.error = BAD_ARGS;
3162 else if (rd == REG_PC || rm == REG_PC || rs == REG_PC)
3163 inst.error = BAD_PC;
3165 else
3166 end_of_line (str);
3169 /* ARM V5E (El Segundo) saturating-add/subtract (argument parse)
3170 Q[D]{ADD,SUB}{cond} Rd,Rm,Rn
3171 Error if any register is R15. */
3173 static void
3174 do_qadd (char * str)
3176 int rd, rm, rn;
3178 skip_whitespace (str);
3180 if ((rd = reg_required_here (& str, 12)) == FAIL
3181 || skip_past_comma (& str) == FAIL
3182 || (rm = reg_required_here (& str, 0)) == FAIL
3183 || skip_past_comma (& str) == FAIL
3184 || (rn = reg_required_here (& str, 16)) == FAIL)
3185 inst.error = BAD_ARGS;
3187 else if (rd == REG_PC || rm == REG_PC || rn == REG_PC)
3188 inst.error = BAD_PC;
3190 else
3191 end_of_line (str);
3194 /* ARM V5E (el Segundo)
3195 MCRRcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
3196 MRRCcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
3198 These are equivalent to the XScale instructions MAR and MRA,
3199 respectively, when coproc == 0, opcode == 0, and CRm == 0.
3201 Result unpredicatable if Rd or Rn is R15. */
3203 static void
3204 do_co_reg2c (char * str)
3206 int rd, rn;
3208 skip_whitespace (str);
3210 if (co_proc_number (& str) == FAIL)
3212 if (!inst.error)
3213 inst.error = BAD_ARGS;
3214 return;
3217 if (skip_past_comma (& str) == FAIL
3218 || cp_opc_expr (& str, 4, 4) == FAIL)
3220 if (!inst.error)
3221 inst.error = BAD_ARGS;
3222 return;
3225 if (skip_past_comma (& str) == FAIL
3226 || (rd = reg_required_here (& str, 12)) == FAIL)
3228 if (!inst.error)
3229 inst.error = BAD_ARGS;
3230 return;
3233 if (skip_past_comma (& str) == FAIL
3234 || (rn = reg_required_here (& str, 16)) == FAIL)
3236 if (!inst.error)
3237 inst.error = BAD_ARGS;
3238 return;
3241 /* Unpredictable result if rd or rn is R15. */
3242 if (rd == REG_PC || rn == REG_PC)
3243 as_tsktsk
3244 (_("Warning: instruction unpredictable when using r15"));
3246 if (skip_past_comma (& str) == FAIL
3247 || cp_reg_required_here (& str, 0) == FAIL)
3249 if (!inst.error)
3250 inst.error = BAD_ARGS;
3251 return;
3254 end_of_line (str);
3257 /* ARM V5 count-leading-zeroes instruction (argument parse)
3258 CLZ{<cond>} <Rd>, <Rm>
3259 Condition defaults to COND_ALWAYS.
3260 Error if Rd or Rm are R15. */
3262 static void
3263 do_clz (char * str)
3265 int rd, rm;
3267 skip_whitespace (str);
3269 if (((rd = reg_required_here (& str, 12)) == FAIL)
3270 || (skip_past_comma (& str) == FAIL)
3271 || ((rm = reg_required_here (& str, 0)) == FAIL))
3272 inst.error = BAD_ARGS;
3274 else if (rd == REG_PC || rm == REG_PC )
3275 inst.error = BAD_PC;
3277 else
3278 end_of_line (str);
3281 /* ARM V5 (argument parse)
3282 LDC2{L} <coproc>, <CRd>, <addressing mode>
3283 STC2{L} <coproc>, <CRd>, <addressing mode>
3284 Instruction is not conditional, and has 0xf in the condition field.
3285 Otherwise, it's the same as LDC/STC. */
3287 static void
3288 do_lstc2 (char * str)
3290 skip_whitespace (str);
3292 if (co_proc_number (& str) == FAIL)
3294 if (!inst.error)
3295 inst.error = BAD_ARGS;
3297 else if (skip_past_comma (& str) == FAIL
3298 || cp_reg_required_here (& str, 12) == FAIL)
3300 if (!inst.error)
3301 inst.error = BAD_ARGS;
3303 else if (skip_past_comma (& str) == FAIL
3304 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
3306 if (! inst.error)
3307 inst.error = BAD_ARGS;
3309 else
3310 end_of_line (str);
3313 /* ARM V5 (argument parse)
3314 CDP2 <coproc>, <opcode_1>, <CRd>, <CRn>, <CRm>, <opcode_2>
3315 Instruction is not conditional, and has 0xf in the condition field.
3316 Otherwise, it's the same as CDP. */
3318 static void
3319 do_cdp2 (char * str)
3321 skip_whitespace (str);
3323 if (co_proc_number (& str) == FAIL)
3325 if (!inst.error)
3326 inst.error = BAD_ARGS;
3327 return;
3330 if (skip_past_comma (& str) == FAIL
3331 || cp_opc_expr (& str, 20,4) == FAIL)
3333 if (!inst.error)
3334 inst.error = BAD_ARGS;
3335 return;
3338 if (skip_past_comma (& str) == FAIL
3339 || cp_reg_required_here (& str, 12) == FAIL)
3341 if (!inst.error)
3342 inst.error = BAD_ARGS;
3343 return;
3346 if (skip_past_comma (& str) == FAIL
3347 || cp_reg_required_here (& str, 16) == FAIL)
3349 if (!inst.error)
3350 inst.error = BAD_ARGS;
3351 return;
3354 if (skip_past_comma (& str) == FAIL
3355 || cp_reg_required_here (& str, 0) == FAIL)
3357 if (!inst.error)
3358 inst.error = BAD_ARGS;
3359 return;
3362 if (skip_past_comma (& str) == SUCCESS)
3364 if (cp_opc_expr (& str, 5, 3) == FAIL)
3366 if (!inst.error)
3367 inst.error = BAD_ARGS;
3368 return;
3372 end_of_line (str);
3375 /* ARM V5 (argument parse)
3376 MCR2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
3377 MRC2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
3378 Instruction is not conditional, and has 0xf in the condition field.
3379 Otherwise, it's the same as MCR/MRC. */
3381 static void
3382 do_co_reg2 (char * str)
3384 skip_whitespace (str);
3386 if (co_proc_number (& str) == FAIL)
3388 if (!inst.error)
3389 inst.error = BAD_ARGS;
3390 return;
3393 if (skip_past_comma (& str) == FAIL
3394 || cp_opc_expr (& str, 21, 3) == FAIL)
3396 if (!inst.error)
3397 inst.error = BAD_ARGS;
3398 return;
3401 if (skip_past_comma (& str) == FAIL
3402 || reg_required_here (& str, 12) == FAIL)
3404 if (!inst.error)
3405 inst.error = BAD_ARGS;
3406 return;
3409 if (skip_past_comma (& str) == FAIL
3410 || cp_reg_required_here (& str, 16) == FAIL)
3412 if (!inst.error)
3413 inst.error = BAD_ARGS;
3414 return;
3417 if (skip_past_comma (& str) == FAIL
3418 || cp_reg_required_here (& str, 0) == FAIL)
3420 if (!inst.error)
3421 inst.error = BAD_ARGS;
3422 return;
3425 if (skip_past_comma (& str) == SUCCESS)
3427 if (cp_opc_expr (& str, 5, 3) == FAIL)
3429 if (!inst.error)
3430 inst.error = BAD_ARGS;
3431 return;
3435 end_of_line (str);
3438 static void
3439 do_bx (char * str)
3441 int reg;
3443 skip_whitespace (str);
3445 if ((reg = reg_required_here (&str, 0)) == FAIL)
3447 inst.error = BAD_ARGS;
3448 return;
3451 /* Note - it is not illegal to do a "bx pc". Useless, but not illegal. */
3452 if (reg == REG_PC)
3453 as_tsktsk (_("use of r15 in bx in ARM mode is not really useful"));
3455 end_of_line (str);
3458 /* ARM v5TEJ. Jump to Jazelle code. */
3460 static void
3461 do_bxj (char * str)
3463 int reg;
3465 skip_whitespace (str);
3467 if ((reg = reg_required_here (&str, 0)) == FAIL)
3469 inst.error = BAD_ARGS;
3470 return;
3473 /* Note - it is not illegal to do a "bxj pc". Useless, but not illegal. */
3474 if (reg == REG_PC)
3475 as_tsktsk (_("use of r15 in bxj is not really useful"));
3477 end_of_line (str);
3480 /* ARM V6 umaal (argument parse). */
3482 static void
3483 do_umaal (char * str)
3485 int rdlo, rdhi, rm, rs;
3487 skip_whitespace (str);
3488 if ((rdlo = reg_required_here (& str, 12)) == FAIL
3489 || skip_past_comma (& str) == FAIL
3490 || (rdhi = reg_required_here (& str, 16)) == FAIL
3491 || skip_past_comma (& str) == FAIL
3492 || (rm = reg_required_here (& str, 0)) == FAIL
3493 || skip_past_comma (& str) == FAIL
3494 || (rs = reg_required_here (& str, 8)) == FAIL)
3496 inst.error = BAD_ARGS;
3497 return;
3500 if (rdlo == REG_PC || rdhi == REG_PC || rm == REG_PC || rs == REG_PC)
3502 inst.error = BAD_PC;
3503 return;
3506 end_of_line (str);
3509 /* ARM V6 strex (argument parse). */
3511 static void
3512 do_strex (char * str)
3514 int rd, rm, rn;
3516 /* Parse Rd, Rm,. */
3517 skip_whitespace (str);
3518 if ((rd = reg_required_here (& str, 12)) == FAIL
3519 || skip_past_comma (& str) == FAIL
3520 || (rm = reg_required_here (& str, 0)) == FAIL
3521 || skip_past_comma (& str) == FAIL)
3523 inst.error = BAD_ARGS;
3524 return;
3526 if (rd == REG_PC || rm == REG_PC)
3528 inst.error = BAD_PC;
3529 return;
3531 if (rd == rm)
3533 inst.error = _("Rd equal to Rm or Rn yields unpredictable results");
3534 return;
3537 /* Skip past '['. */
3538 if ((strlen (str) >= 1)
3539 && strncmp (str, "[", 1) == 0)
3540 str += 1;
3542 skip_whitespace (str);
3544 /* Parse Rn. */
3545 if ((rn = reg_required_here (& str, 16)) == FAIL)
3547 inst.error = BAD_ARGS;
3548 return;
3550 else if (rn == REG_PC)
3552 inst.error = BAD_PC;
3553 return;
3555 if (rd == rn)
3557 inst.error = _("Rd equal to Rm or Rn yields unpredictable results");
3558 return;
3560 skip_whitespace (str);
3562 /* Skip past ']'. */
3563 if ((strlen (str) >= 1)
3564 && strncmp (str, "]", 1) == 0)
3565 str += 1;
3567 end_of_line (str);
3570 /* KIND indicates what kind of shifts are accepted. */
3572 static int
3573 decode_shift (char ** str, int kind)
3575 const struct asm_shift_name * shift;
3576 char * p;
3577 char c;
3579 skip_whitespace (* str);
3581 for (p = * str; ISALPHA (* p); p ++)
3584 if (p == * str)
3586 inst.error = _("shift expression expected");
3587 return FAIL;
3590 c = * p;
3591 * p = '\0';
3592 shift = (const struct asm_shift_name *) hash_find (arm_shift_hsh, * str);
3593 * p = c;
3595 if (shift == NULL)
3597 inst.error = _("shift expression expected");
3598 return FAIL;
3601 assert (shift->properties->index == shift_properties[shift->properties->index].index);
3603 if (kind == SHIFT_LSL_OR_ASR_IMMEDIATE
3604 && shift->properties->index != SHIFT_LSL
3605 && shift->properties->index != SHIFT_ASR)
3607 inst.error = _("'LSL' or 'ASR' required");
3608 return FAIL;
3610 else if (kind == SHIFT_LSL_IMMEDIATE
3611 && shift->properties->index != SHIFT_LSL)
3613 inst.error = _("'LSL' required");
3614 return FAIL;
3616 else if (kind == SHIFT_ASR_IMMEDIATE
3617 && shift->properties->index != SHIFT_ASR)
3619 inst.error = _("'ASR' required");
3620 return FAIL;
3623 if (shift->properties->index == SHIFT_RRX)
3625 * str = p;
3626 inst.instruction |= shift->properties->bit_field;
3627 return SUCCESS;
3630 skip_whitespace (p);
3632 if (kind == NO_SHIFT_RESTRICT && reg_required_here (& p, 8) != FAIL)
3634 inst.instruction |= shift->properties->bit_field | SHIFT_BY_REG;
3635 * str = p;
3636 return SUCCESS;
3638 else if (! is_immediate_prefix (* p))
3640 inst.error = (NO_SHIFT_RESTRICT
3641 ? _("shift requires register or #expression")
3642 : _("shift requires #expression"));
3643 * str = p;
3644 return FAIL;
3647 inst.error = NULL;
3648 p ++;
3650 if (my_get_expression (& inst.reloc.exp, & p))
3651 return FAIL;
3653 /* Validate some simple #expressions. */
3654 if (inst.reloc.exp.X_op == O_constant)
3656 unsigned num = inst.reloc.exp.X_add_number;
3658 /* Reject operations greater than 32. */
3659 if (num > 32
3660 /* Reject a shift of 0 unless the mode allows it. */
3661 || (num == 0 && shift->properties->allows_0 == 0)
3662 /* Reject a shift of 32 unless the mode allows it. */
3663 || (num == 32 && shift->properties->allows_32 == 0)
3666 /* As a special case we allow a shift of zero for
3667 modes that do not support it to be recoded as an
3668 logical shift left of zero (ie nothing). We warn
3669 about this though. */
3670 if (num == 0)
3672 as_warn (_("shift of 0 ignored."));
3673 shift = & shift_names[0];
3674 assert (shift->properties->index == SHIFT_LSL);
3676 else
3678 inst.error = _("invalid immediate shift");
3679 return FAIL;
3683 /* Shifts of 32 are encoded as 0, for those shifts that
3684 support it. */
3685 if (num == 32)
3686 num = 0;
3688 inst.instruction |= (num << 7) | shift->properties->bit_field;
3690 else
3692 inst.reloc.type = BFD_RELOC_ARM_SHIFT_IMM;
3693 inst.reloc.pc_rel = 0;
3694 inst.instruction |= shift->properties->bit_field;
3697 * str = p;
3698 return SUCCESS;
3701 static void
3702 do_sat (char ** str, int bias)
3704 int rd, rm;
3705 expressionS expr;
3707 skip_whitespace (*str);
3709 /* Parse <Rd>, field. */
3710 if ((rd = reg_required_here (str, 12)) == FAIL
3711 || skip_past_comma (str) == FAIL)
3713 inst.error = BAD_ARGS;
3714 return;
3716 if (rd == REG_PC)
3718 inst.error = BAD_PC;
3719 return;
3722 /* Parse #<immed>, field. */
3723 if (is_immediate_prefix (**str))
3724 (*str)++;
3725 else
3727 inst.error = _("immediate expression expected");
3728 return;
3730 if (my_get_expression (&expr, str))
3732 inst.error = _("bad expression");
3733 return;
3735 if (expr.X_op != O_constant)
3737 inst.error = _("constant expression expected");
3738 return;
3740 if (expr.X_add_number + bias < 0
3741 || expr.X_add_number + bias > 31)
3743 inst.error = _("immediate value out of range");
3744 return;
3746 inst.instruction |= (expr.X_add_number + bias) << 16;
3747 if (skip_past_comma (str) == FAIL)
3749 inst.error = BAD_ARGS;
3750 return;
3753 /* Parse <Rm> field. */
3754 if ((rm = reg_required_here (str, 0)) == FAIL)
3756 inst.error = BAD_ARGS;
3757 return;
3759 if (rm == REG_PC)
3761 inst.error = BAD_PC;
3762 return;
3765 if (skip_past_comma (str) == SUCCESS)
3766 decode_shift (str, SHIFT_LSL_OR_ASR_IMMEDIATE);
3769 /* ARM V6 ssat (argument parse). */
3771 static void
3772 do_ssat (char * str)
3774 do_sat (&str, /*bias=*/-1);
3775 end_of_line (str);
3778 /* ARM V6 usat (argument parse). */
3780 static void
3781 do_usat (char * str)
3783 do_sat (&str, /*bias=*/0);
3784 end_of_line (str);
3787 static void
3788 do_sat16 (char ** str, int bias)
3790 int rd, rm;
3791 expressionS expr;
3793 skip_whitespace (*str);
3795 /* Parse the <Rd> field. */
3796 if ((rd = reg_required_here (str, 12)) == FAIL
3797 || skip_past_comma (str) == FAIL)
3799 inst.error = BAD_ARGS;
3800 return;
3802 if (rd == REG_PC)
3804 inst.error = BAD_PC;
3805 return;
3808 /* Parse #<immed>, field. */
3809 if (is_immediate_prefix (**str))
3810 (*str)++;
3811 else
3813 inst.error = _("immediate expression expected");
3814 return;
3816 if (my_get_expression (&expr, str))
3818 inst.error = _("bad expression");
3819 return;
3821 if (expr.X_op != O_constant)
3823 inst.error = _("constant expression expected");
3824 return;
3826 if (expr.X_add_number + bias < 0
3827 || expr.X_add_number + bias > 15)
3829 inst.error = _("immediate value out of range");
3830 return;
3832 inst.instruction |= (expr.X_add_number + bias) << 16;
3833 if (skip_past_comma (str) == FAIL)
3835 inst.error = BAD_ARGS;
3836 return;
3839 /* Parse <Rm> field. */
3840 if ((rm = reg_required_here (str, 0)) == FAIL)
3842 inst.error = BAD_ARGS;
3843 return;
3845 if (rm == REG_PC)
3847 inst.error = BAD_PC;
3848 return;
3852 /* ARM V6 ssat16 (argument parse). */
3854 static void
3855 do_ssat16 (char * str)
3857 do_sat16 (&str, /*bias=*/-1);
3858 end_of_line (str);
3861 static void
3862 do_usat16 (char * str)
3864 do_sat16 (&str, /*bias=*/0);
3865 end_of_line (str);
3868 static void
3869 do_cps_mode (char ** str)
3871 expressionS expr;
3873 skip_whitespace (*str);
3875 if (! is_immediate_prefix (**str))
3877 inst.error = _("immediate expression expected");
3878 return;
3881 (*str)++; /* Strip off the immediate signifier. */
3882 if (my_get_expression (&expr, str))
3884 inst.error = _("bad expression");
3885 return;
3888 if (expr.X_op != O_constant)
3890 inst.error = _("constant expression expected");
3891 return;
3894 /* The mode is a 5 bit field. Valid values are 0-31. */
3895 if (((unsigned) expr.X_add_number) > 31
3896 || (inst.reloc.exp.X_add_number) < 0)
3898 inst.error = _("invalid constant");
3899 return;
3902 inst.instruction |= expr.X_add_number;
3905 /* ARM V6 srs (argument parse). */
3907 static void
3908 do_srs (char * str)
3910 char *exclam;
3911 skip_whitespace (str);
3912 exclam = strchr (str, '!');
3913 if (exclam)
3914 *exclam = '\0';
3915 do_cps_mode (&str);
3916 if (exclam)
3917 *exclam = '!';
3918 if (*str == '!')
3920 inst.instruction |= WRITE_BACK;
3921 str++;
3923 end_of_line (str);
3926 /* ARM V6 SMMUL (argument parse). */
3928 static void
3929 do_smmul (char * str)
3931 int rd, rm, rs;
3933 skip_whitespace (str);
3934 if ((rd = reg_required_here (&str, 16)) == FAIL
3935 || skip_past_comma (&str) == FAIL
3936 || (rm = reg_required_here (&str, 0)) == FAIL
3937 || skip_past_comma (&str) == FAIL
3938 || (rs = reg_required_here (&str, 8)) == FAIL)
3940 inst.error = BAD_ARGS;
3941 return;
3944 if ( rd == REG_PC
3945 || rm == REG_PC
3946 || rs == REG_PC)
3948 inst.error = BAD_PC;
3949 return;
3952 end_of_line (str);
3955 /* ARM V6 SMLALD (argument parse). */
3957 static void
3958 do_smlald (char * str)
3960 int rdlo, rdhi, rm, rs;
3962 skip_whitespace (str);
3963 if ((rdlo = reg_required_here (&str, 12)) == FAIL
3964 || skip_past_comma (&str) == FAIL
3965 || (rdhi = reg_required_here (&str, 16)) == FAIL
3966 || skip_past_comma (&str) == FAIL
3967 || (rm = reg_required_here (&str, 0)) == FAIL
3968 || skip_past_comma (&str) == FAIL
3969 || (rs = reg_required_here (&str, 8)) == FAIL)
3971 inst.error = BAD_ARGS;
3972 return;
3975 if ( rdlo == REG_PC
3976 || rdhi == REG_PC
3977 || rm == REG_PC
3978 || rs == REG_PC)
3980 inst.error = BAD_PC;
3981 return;
3984 end_of_line (str);
3987 /* ARM V6 SMLAD (argument parse). Signed multiply accumulate dual.
3988 smlad{x}{<cond>} Rd, Rm, Rs, Rn */
3990 static void
3991 do_smlad (char * str)
3993 int rd, rm, rs, rn;
3995 skip_whitespace (str);
3996 if ((rd = reg_required_here (&str, 16)) == FAIL
3997 || skip_past_comma (&str) == FAIL
3998 || (rm = reg_required_here (&str, 0)) == FAIL
3999 || skip_past_comma (&str) == FAIL
4000 || (rs = reg_required_here (&str, 8)) == FAIL
4001 || skip_past_comma (&str) == FAIL
4002 || (rn = reg_required_here (&str, 12)) == FAIL)
4004 inst.error = BAD_ARGS;
4005 return;
4008 if ( rd == REG_PC
4009 || rn == REG_PC
4010 || rs == REG_PC
4011 || rm == REG_PC)
4013 inst.error = BAD_PC;
4014 return;
4017 end_of_line (str);
4020 /* Returns true if the endian-specifier indicates big-endianness. */
4022 static int
4023 do_endian_specifier (char * str)
4025 int big_endian = 0;
4027 skip_whitespace (str);
4028 if (strlen (str) < 2)
4029 inst.error = _("missing endian specifier");
4030 else if (strncasecmp (str, "BE", 2) == 0)
4032 str += 2;
4033 big_endian = 1;
4035 else if (strncasecmp (str, "LE", 2) == 0)
4036 str += 2;
4037 else
4038 inst.error = _("valid endian specifiers are be or le");
4040 end_of_line (str);
4042 return big_endian;
4045 /* ARM V6 SETEND (argument parse). Sets the E bit in the CPSR while
4046 preserving the other bits.
4048 setend <endian_specifier>, where <endian_specifier> is either
4049 BE or LE. */
4051 static void
4052 do_setend (char * str)
4054 if (do_endian_specifier (str))
4055 inst.instruction |= 0x200;
4058 /* ARM V6 SXTH.
4060 SXTH {<cond>} <Rd>, <Rm>{, <rotation>}
4061 Condition defaults to COND_ALWAYS.
4062 Error if any register uses R15. */
4064 static void
4065 do_sxth (char * str)
4067 int rd, rm;
4068 expressionS expr;
4069 int rotation_clear_mask = 0xfffff3ff;
4070 int rotation_eight_mask = 0x00000400;
4071 int rotation_sixteen_mask = 0x00000800;
4072 int rotation_twenty_four_mask = 0x00000c00;
4074 skip_whitespace (str);
4075 if ((rd = reg_required_here (&str, 12)) == FAIL
4076 || skip_past_comma (&str) == FAIL
4077 || (rm = reg_required_here (&str, 0)) == FAIL)
4079 inst.error = BAD_ARGS;
4080 return;
4083 else if (rd == REG_PC || rm == REG_PC)
4085 inst.error = BAD_PC;
4086 return;
4089 /* Zero out the rotation field. */
4090 inst.instruction &= rotation_clear_mask;
4092 /* Check for lack of optional rotation field. */
4093 if (skip_past_comma (&str) == FAIL)
4095 end_of_line (str);
4096 return;
4099 /* Move past 'ROR'. */
4100 skip_whitespace (str);
4101 if (strncasecmp (str, "ROR", 3) == 0)
4102 str += 3;
4103 else
4105 inst.error = _("missing rotation field after comma");
4106 return;
4109 /* Get the immediate constant. */
4110 skip_whitespace (str);
4111 if (is_immediate_prefix (* str))
4112 str++;
4113 else
4115 inst.error = _("immediate expression expected");
4116 return;
4119 if (my_get_expression (&expr, &str))
4121 inst.error = _("bad expression");
4122 return;
4125 if (expr.X_op != O_constant)
4127 inst.error = _("constant expression expected");
4128 return;
4131 switch (expr.X_add_number)
4133 case 0:
4134 /* Rotation field has already been zeroed. */
4135 break;
4136 case 8:
4137 inst.instruction |= rotation_eight_mask;
4138 break;
4140 case 16:
4141 inst.instruction |= rotation_sixteen_mask;
4142 break;
4144 case 24:
4145 inst.instruction |= rotation_twenty_four_mask;
4146 break;
4148 default:
4149 inst.error = _("rotation can be 8, 16, 24 or 0 when field is ommited");
4150 break;
4153 end_of_line (str);
4156 /* ARM V6 SXTAH extracts a 16-bit value from a register, sign
4157 extends it to 32-bits, and adds the result to a value in another
4158 register. You can specify a rotation by 0, 8, 16, or 24 bits
4159 before extracting the 16-bit value.
4160 SXTAH{<cond>} <Rd>, <Rn>, <Rm>{, <rotation>}
4161 Condition defaults to COND_ALWAYS.
4162 Error if any register uses R15. */
4164 static void
4165 do_sxtah (char * str)
4167 int rd, rn, rm;
4168 expressionS expr;
4169 int rotation_clear_mask = 0xfffff3ff;
4170 int rotation_eight_mask = 0x00000400;
4171 int rotation_sixteen_mask = 0x00000800;
4172 int rotation_twenty_four_mask = 0x00000c00;
4174 skip_whitespace (str);
4175 if ((rd = reg_required_here (&str, 12)) == FAIL
4176 || skip_past_comma (&str) == FAIL
4177 || (rn = reg_required_here (&str, 16)) == FAIL
4178 || skip_past_comma (&str) == FAIL
4179 || (rm = reg_required_here (&str, 0)) == FAIL)
4181 inst.error = BAD_ARGS;
4182 return;
4185 else if (rd == REG_PC || rn == REG_PC || rm == REG_PC)
4187 inst.error = BAD_PC;
4188 return;
4191 /* Zero out the rotation field. */
4192 inst.instruction &= rotation_clear_mask;
4194 /* Check for lack of optional rotation field. */
4195 if (skip_past_comma (&str) == FAIL)
4197 end_of_line (str);
4198 return;
4201 /* Move past 'ROR'. */
4202 skip_whitespace (str);
4203 if (strncasecmp (str, "ROR", 3) == 0)
4204 str += 3;
4205 else
4207 inst.error = _("missing rotation field after comma");
4208 return;
4211 /* Get the immediate constant. */
4212 skip_whitespace (str);
4213 if (is_immediate_prefix (* str))
4214 str++;
4215 else
4217 inst.error = _("immediate expression expected");
4218 return;
4221 if (my_get_expression (&expr, &str))
4223 inst.error = _("bad expression");
4224 return;
4227 if (expr.X_op != O_constant)
4229 inst.error = _("constant expression expected");
4230 return;
4233 switch (expr.X_add_number)
4235 case 0:
4236 /* Rotation field has already been zeroed. */
4237 break;
4239 case 8:
4240 inst.instruction |= rotation_eight_mask;
4241 break;
4243 case 16:
4244 inst.instruction |= rotation_sixteen_mask;
4245 break;
4247 case 24:
4248 inst.instruction |= rotation_twenty_four_mask;
4249 break;
4251 default:
4252 inst.error = _("rotation can be 8, 16, 24 or 0 when field is ommited");
4253 break;
4256 end_of_line (str);
4260 /* ARM V6 RFE (Return from Exception) loads the PC and CPSR from the
4261 word at the specified address and the following word
4262 respectively.
4263 Unconditionally executed.
4264 Error if Rn is R15. */
4266 static void
4267 do_rfe (char * str)
4269 int rn;
4271 skip_whitespace (str);
4273 if ((rn = reg_required_here (&str, 16)) == FAIL)
4274 return;
4276 if (rn == REG_PC)
4278 inst.error = BAD_PC;
4279 return;
4282 skip_whitespace (str);
4284 if (*str == '!')
4286 inst.instruction |= WRITE_BACK;
4287 str++;
4289 end_of_line (str);
4292 /* ARM V6 REV (Byte Reverse Word) reverses the byte order in a 32-bit
4293 register (argument parse).
4294 REV{<cond>} Rd, Rm.
4295 Condition defaults to COND_ALWAYS.
4296 Error if Rd or Rm are R15. */
4298 static void
4299 do_rev (char * str)
4301 int rd, rm;
4303 skip_whitespace (str);
4305 if ((rd = reg_required_here (&str, 12)) == FAIL
4306 || skip_past_comma (&str) == FAIL
4307 || (rm = reg_required_here (&str, 0)) == FAIL)
4308 inst.error = BAD_ARGS;
4310 else if (rd == REG_PC || rm == REG_PC)
4311 inst.error = BAD_PC;
4313 else
4314 end_of_line (str);
4317 /* ARM V6 Perform Two Sixteen Bit Integer Additions. (argument parse).
4318 QADD16{<cond>} <Rd>, <Rn>, <Rm>
4319 Condition defaults to COND_ALWAYS.
4320 Error if Rd, Rn or Rm are R15. */
4322 static void
4323 do_qadd16 (char * str)
4325 int rd, rm, rn;
4327 skip_whitespace (str);
4329 if ((rd = reg_required_here (&str, 12)) == FAIL
4330 || skip_past_comma (&str) == FAIL
4331 || (rn = reg_required_here (&str, 16)) == FAIL
4332 || skip_past_comma (&str) == FAIL
4333 || (rm = reg_required_here (&str, 0)) == FAIL)
4334 inst.error = BAD_ARGS;
4336 else if (rd == REG_PC || rm == REG_PC || rn == REG_PC)
4337 inst.error = BAD_PC;
4339 else
4340 end_of_line (str);
4343 static void
4344 do_pkh_core (char * str, int shift)
4346 int rd, rn, rm;
4348 skip_whitespace (str);
4349 if (((rd = reg_required_here (&str, 12)) == FAIL)
4350 || (skip_past_comma (&str) == FAIL)
4351 || ((rn = reg_required_here (&str, 16)) == FAIL)
4352 || (skip_past_comma (&str) == FAIL)
4353 || ((rm = reg_required_here (&str, 0)) == FAIL))
4355 inst.error = BAD_ARGS;
4356 return;
4359 else if (rd == REG_PC || rn == REG_PC || rm == REG_PC)
4361 inst.error = BAD_PC;
4362 return;
4365 /* Check for optional shift immediate constant. */
4366 if (skip_past_comma (&str) == FAIL)
4368 if (shift == SHIFT_ASR_IMMEDIATE)
4370 /* If the shift specifier is ommited, turn the instruction
4371 into pkhbt rd, rm, rn. First, switch the instruction
4372 code, and clear the rn and rm fields. */
4373 inst.instruction &= 0xfff0f010;
4374 /* Now, re-encode the registers. */
4375 inst.instruction |= (rm << 16) | rn;
4377 return;
4380 decode_shift (&str, shift);
4383 /* ARM V6 Pack Halfword Bottom Top instruction (argument parse).
4384 PKHBT {<cond>} <Rd>, <Rn>, <Rm> {, LSL #<shift_imm>}
4385 Condition defaults to COND_ALWAYS.
4386 Error if Rd, Rn or Rm are R15. */
4388 static void
4389 do_pkhbt (char * str)
4391 do_pkh_core (str, SHIFT_LSL_IMMEDIATE);
4394 /* ARM V6 PKHTB (Argument Parse). */
4396 static void
4397 do_pkhtb (char * str)
4399 do_pkh_core (str, SHIFT_ASR_IMMEDIATE);
4402 /* ARM V6 Load Register Exclusive instruction (argument parse).
4403 LDREX{,B,D,H}{<cond>} <Rd, [<Rn>]
4404 Condition defaults to COND_ALWAYS.
4405 Error if Rd or Rn are R15.
4406 See ARMARMv6 A4.1.27: LDREX. */
4408 static void
4409 do_ldrex (char * str)
4411 int rd, rn;
4413 skip_whitespace (str);
4415 /* Parse Rd. */
4416 if (((rd = reg_required_here (&str, 12)) == FAIL)
4417 || (skip_past_comma (&str) == FAIL))
4419 inst.error = BAD_ARGS;
4420 return;
4422 else if (rd == REG_PC)
4424 inst.error = BAD_PC;
4425 return;
4427 skip_whitespace (str);
4429 /* Skip past '['. */
4430 if ((strlen (str) >= 1)
4431 &&strncmp (str, "[", 1) == 0)
4432 str += 1;
4433 skip_whitespace (str);
4435 /* Parse Rn. */
4436 if ((rn = reg_required_here (&str, 16)) == FAIL)
4438 inst.error = BAD_ARGS;
4439 return;
4441 else if (rn == REG_PC)
4443 inst.error = BAD_PC;
4444 return;
4446 skip_whitespace (str);
4448 /* Skip past ']'. */
4449 if ((strlen (str) >= 1)
4450 && strncmp (str, "]", 1) == 0)
4451 str += 1;
4453 end_of_line (str);
4456 /* ARM V6 change processor state instruction (argument parse)
4457 CPS, CPSIE, CSPID . */
4459 static void
4460 do_cps (char * str)
4462 do_cps_mode (&str);
4463 end_of_line (str);
4466 static void
4467 do_cps_flags (char ** str, int thumb_p)
4469 struct cps_flag
4471 char character;
4472 unsigned long arm_value;
4473 unsigned long thumb_value;
4475 static struct cps_flag flag_table[] =
4477 {'a', 0x100, 0x4 },
4478 {'i', 0x080, 0x2 },
4479 {'f', 0x040, 0x1 }
4482 int saw_a_flag = 0;
4484 skip_whitespace (*str);
4486 /* Get the a, f and i flags. */
4487 while (**str && **str != ',')
4489 struct cps_flag *p;
4490 struct cps_flag *q = flag_table + sizeof (flag_table)/sizeof (*p);
4492 for (p = flag_table; p < q; ++p)
4493 if (strncasecmp (*str, &p->character, 1) == 0)
4495 inst.instruction |= (thumb_p ? p->thumb_value : p->arm_value);
4496 saw_a_flag = 1;
4497 break;
4499 if (p == q)
4501 inst.error = _("unrecognized flag");
4502 return;
4504 (*str)++;
4507 if (!saw_a_flag)
4508 inst.error = _("no 'a', 'i', or 'f' flags for 'cps'");
4511 static void
4512 do_cpsi (char * str)
4514 do_cps_flags (&str, /*thumb_p=*/0);
4516 if (skip_past_comma (&str) == SUCCESS)
4518 skip_whitespace (str);
4519 do_cps_mode (&str);
4521 end_of_line (str);
4524 /* THUMB V5 breakpoint instruction (argument parse)
4525 BKPT <immed_8>. */
4527 static void
4528 do_t_bkpt (char * str)
4530 expressionS expr;
4531 unsigned long number;
4533 skip_whitespace (str);
4535 /* Allow optional leading '#'. */
4536 if (is_immediate_prefix (*str))
4537 str ++;
4539 memset (& expr, '\0', sizeof (expr));
4540 if (my_get_expression (& expr, & str)
4541 || (expr.X_op != O_constant
4542 /* As a convenience we allow 'bkpt' without an operand. */
4543 && expr.X_op != O_absent))
4545 inst.error = _("bad expression");
4546 return;
4549 number = expr.X_add_number;
4551 /* Check it fits an 8 bit unsigned. */
4552 if (number != (number & 0xff))
4554 inst.error = _("immediate value out of range");
4555 return;
4558 inst.instruction |= number;
4560 end_of_line (str);
4563 static bfd_reloc_code_real_type
4564 arm_parse_reloc (void)
4566 char id [16];
4567 char * ip;
4568 unsigned int i;
4569 static struct
4571 char * str;
4572 int len;
4573 bfd_reloc_code_real_type reloc;
4575 reloc_map[] =
4577 #define MAP(str,reloc) { str, sizeof (str) - 1, reloc }
4578 MAP ("(got)", BFD_RELOC_ARM_GOT32),
4579 MAP ("(gotoff)", BFD_RELOC_ARM_GOTOFF),
4580 /* ScottB: Jan 30, 1998 - Added support for parsing "var(PLT)"
4581 branch instructions generated by GCC for PLT relocs. */
4582 MAP ("(plt)", BFD_RELOC_ARM_PLT32),
4583 MAP ("(target1)", BFD_RELOC_ARM_TARGET1),
4584 MAP ("(sbrel)", BFD_RELOC_ARM_SBREL32),
4585 MAP ("(target2)", BFD_RELOC_ARM_TARGET2),
4586 { NULL, 0, BFD_RELOC_UNUSED }
4587 #undef MAP
4590 for (i = 0, ip = input_line_pointer;
4591 i < sizeof (id) && (ISALNUM (*ip) || ISPUNCT (*ip));
4592 i++, ip++)
4593 id[i] = TOLOWER (*ip);
4595 for (i = 0; reloc_map[i].str; i++)
4596 if (strncmp (id, reloc_map[i].str, reloc_map[i].len) == 0)
4597 break;
4599 input_line_pointer += reloc_map[i].len;
4601 return reloc_map[i].reloc;
4604 /* ARM V5 branch-link-exchange (argument parse) for BLX(1) only.
4605 Expects inst.instruction is set for BLX(1).
4606 Note: this is cloned from do_branch, and the reloc changed to be a
4607 new one that can cope with setting one extra bit (the H bit). */
4609 static void
4610 do_branch25 (char * str)
4612 if (my_get_expression (& inst.reloc.exp, & str))
4613 return;
4615 #ifdef OBJ_ELF
4617 char * save_in;
4619 /* ScottB: February 5, 1998 */
4620 /* Check to see of PLT32 reloc required for the instruction. */
4622 /* arm_parse_reloc() works on input_line_pointer.
4623 We actually want to parse the operands to the branch instruction
4624 passed in 'str'. Save the input pointer and restore it later. */
4625 save_in = input_line_pointer;
4626 input_line_pointer = str;
4628 if (inst.reloc.exp.X_op == O_symbol
4629 && *str == '('
4630 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
4632 inst.reloc.type = BFD_RELOC_ARM_PLT32;
4633 inst.reloc.pc_rel = 0;
4634 /* Modify str to point to after parsed operands, otherwise
4635 end_of_line() will complain about the (PLT) left in str. */
4636 str = input_line_pointer;
4638 else
4640 inst.reloc.type = BFD_RELOC_ARM_PCREL_BLX;
4641 inst.reloc.pc_rel = 1;
4644 input_line_pointer = save_in;
4646 #else
4647 inst.reloc.type = BFD_RELOC_ARM_PCREL_BLX;
4648 inst.reloc.pc_rel = 1;
4649 #endif /* OBJ_ELF */
4651 end_of_line (str);
4654 /* ARM V5 branch-link-exchange instruction (argument parse)
4655 BLX <target_addr> ie BLX(1)
4656 BLX{<condition>} <Rm> ie BLX(2)
4657 Unfortunately, there are two different opcodes for this mnemonic.
4658 So, the insns[].value is not used, and the code here zaps values
4659 into inst.instruction.
4660 Also, the <target_addr> can be 25 bits, hence has its own reloc. */
4662 static void
4663 do_blx (char * str)
4665 char * mystr = str;
4666 int rm;
4668 skip_whitespace (mystr);
4669 rm = reg_required_here (& mystr, 0);
4671 /* The above may set inst.error. Ignore his opinion. */
4672 inst.error = 0;
4674 if (rm != FAIL)
4676 /* Arg is a register.
4677 Use the condition code our caller put in inst.instruction.
4678 Pass ourselves off as a BX with a funny opcode. */
4679 inst.instruction |= 0x012fff30;
4680 do_bx (str);
4682 else
4684 /* This must be is BLX <target address>, no condition allowed. */
4685 if (inst.instruction != COND_ALWAYS)
4687 inst.error = BAD_COND;
4688 return;
4691 inst.instruction = 0xfafffffe;
4693 /* Process like a B/BL, but with a different reloc.
4694 Note that B/BL expecte fffffe, not 0, offset in the opcode table. */
4695 do_branch25 (str);
4699 /* ARM V5 Thumb BLX (argument parse)
4700 BLX <target_addr> which is BLX(1)
4701 BLX <Rm> which is BLX(2)
4702 Unfortunately, there are two different opcodes for this mnemonic.
4703 So, the tinsns[].value is not used, and the code here zaps values
4704 into inst.instruction. */
4706 static void
4707 do_t_blx (char * str)
4709 char * mystr = str;
4710 int rm;
4712 skip_whitespace (mystr);
4713 inst.instruction = 0x4780;
4715 /* Note that this call is to the ARM register recognizer. BLX(2)
4716 uses the ARM register space, not the Thumb one, so a call to
4717 thumb_reg() would be wrong. */
4718 rm = reg_required_here (& mystr, 3);
4719 inst.error = 0;
4721 if (rm != FAIL)
4723 /* It's BLX(2). The .instruction was zapped with rm & is final. */
4724 inst.size = 2;
4726 else
4728 /* No ARM register. This must be BLX(1). Change the .instruction. */
4729 inst.instruction = 0xf7ffeffe;
4730 inst.size = 4;
4732 if (my_get_expression (& inst.reloc.exp, & mystr))
4733 return;
4735 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BLX;
4736 inst.reloc.pc_rel = 1;
4739 end_of_line (mystr);
4742 /* ARM V5 breakpoint instruction (argument parse)
4743 BKPT <16 bit unsigned immediate>
4744 Instruction is not conditional.
4745 The bit pattern given in insns[] has the COND_ALWAYS condition,
4746 and it is an error if the caller tried to override that. */
4748 static void
4749 do_bkpt (char * str)
4751 expressionS expr;
4752 unsigned long number;
4754 skip_whitespace (str);
4756 /* Allow optional leading '#'. */
4757 if (is_immediate_prefix (* str))
4758 str++;
4760 memset (& expr, '\0', sizeof (expr));
4762 if (my_get_expression (& expr, & str)
4763 || (expr.X_op != O_constant
4764 /* As a convenience we allow 'bkpt' without an operand. */
4765 && expr.X_op != O_absent))
4767 inst.error = _("bad expression");
4768 return;
4771 number = expr.X_add_number;
4773 /* Check it fits a 16 bit unsigned. */
4774 if (number != (number & 0xffff))
4776 inst.error = _("immediate value out of range");
4777 return;
4780 /* Top 12 of 16 bits to bits 19:8. */
4781 inst.instruction |= (number & 0xfff0) << 4;
4783 /* Bottom 4 of 16 bits to bits 3:0. */
4784 inst.instruction |= number & 0xf;
4786 end_of_line (str);
4789 /* THUMB CPS instruction (argument parse). */
4791 static void
4792 do_t_cps (char * str)
4794 do_cps_flags (&str, /*thumb_p=*/1);
4795 end_of_line (str);
4798 /* Parse and validate that a register is of the right form, this saves
4799 repeated checking of this information in many similar cases.
4800 Unlike the 32-bit case we do not insert the register into the opcode
4801 here, since the position is often unknown until the full instruction
4802 has been parsed. */
4804 static int
4805 thumb_reg (char ** strp, int hi_lo)
4807 int reg;
4809 if ((reg = reg_required_here (strp, -1)) == FAIL)
4810 return FAIL;
4812 switch (hi_lo)
4814 case THUMB_REG_LO:
4815 if (reg > 7)
4817 inst.error = _("lo register required");
4818 return FAIL;
4820 break;
4822 case THUMB_REG_HI:
4823 if (reg < 8)
4825 inst.error = _("hi register required");
4826 return FAIL;
4828 break;
4830 default:
4831 break;
4834 return reg;
4837 static void
4838 thumb_mov_compare (char * str, int move)
4840 int Rd, Rs = FAIL;
4842 skip_whitespace (str);
4844 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
4845 || skip_past_comma (&str) == FAIL)
4847 if (! inst.error)
4848 inst.error = BAD_ARGS;
4849 return;
4852 if (move != THUMB_CPY && is_immediate_prefix (*str))
4854 str++;
4855 if (my_get_expression (&inst.reloc.exp, &str))
4856 return;
4858 else if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
4859 return;
4861 if (Rs != FAIL)
4863 if (move != THUMB_CPY && Rs < 8 && Rd < 8)
4865 if (move == THUMB_MOVE)
4866 /* A move of two lowregs is encoded as ADD Rd, Rs, #0
4867 since a MOV instruction produces unpredictable results. */
4868 inst.instruction = T_OPCODE_ADD_I3;
4869 else
4870 inst.instruction = T_OPCODE_CMP_LR;
4871 inst.instruction |= Rd | (Rs << 3);
4873 else
4875 if (move == THUMB_MOVE)
4876 inst.instruction = T_OPCODE_MOV_HR;
4877 else if (move != THUMB_CPY)
4878 inst.instruction = T_OPCODE_CMP_HR;
4880 if (Rd > 7)
4881 inst.instruction |= THUMB_H1;
4883 if (Rs > 7)
4884 inst.instruction |= THUMB_H2;
4886 inst.instruction |= (Rd & 7) | ((Rs & 7) << 3);
4889 else
4891 if (Rd > 7)
4893 inst.error = _("only lo regs allowed with immediate");
4894 return;
4897 if (move == THUMB_MOVE)
4898 inst.instruction = T_OPCODE_MOV_I8;
4899 else
4900 inst.instruction = T_OPCODE_CMP_I8;
4902 inst.instruction |= Rd << 8;
4904 if (inst.reloc.exp.X_op != O_constant)
4905 inst.reloc.type = BFD_RELOC_ARM_THUMB_IMM;
4906 else
4908 unsigned value = inst.reloc.exp.X_add_number;
4910 if (value > 255)
4912 inst.error = _("invalid immediate");
4913 return;
4916 inst.instruction |= value;
4920 end_of_line (str);
4923 /* THUMB CPY instruction (argument parse). */
4925 static void
4926 do_t_cpy (char * str)
4928 thumb_mov_compare (str, THUMB_CPY);
4931 /* THUMB SETEND instruction (argument parse). */
4933 static void
4934 do_t_setend (char * str)
4936 if (do_endian_specifier (str))
4937 inst.instruction |= 0x8;
4940 /* Parse INSN_TYPE insn STR having a possible IMMEDIATE_SIZE immediate. */
4942 static unsigned long
4943 check_iwmmxt_insn (char * str,
4944 enum iwmmxt_insn_type insn_type,
4945 int immediate_size)
4947 int reg = 0;
4948 const char * inst_error;
4949 expressionS expr;
4950 unsigned long number;
4952 inst_error = inst.error;
4953 if (!inst.error)
4954 inst.error = BAD_ARGS;
4955 skip_whitespace (str);
4957 switch (insn_type)
4959 case check_rd:
4960 if ((reg = reg_required_here (&str, 12)) == FAIL)
4961 return FAIL;
4962 break;
4964 case check_wr:
4965 if ((wreg_required_here (&str, 0, IWMMXT_REG_WR)) == FAIL)
4966 return FAIL;
4967 break;
4969 case check_wrwr:
4970 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
4971 || skip_past_comma (&str) == FAIL
4972 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL))
4973 return FAIL;
4974 break;
4976 case check_wrwrwr:
4977 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
4978 || skip_past_comma (&str) == FAIL
4979 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
4980 || skip_past_comma (&str) == FAIL
4981 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL))
4982 return FAIL;
4983 break;
4985 case check_wrwrwcg:
4986 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
4987 || skip_past_comma (&str) == FAIL
4988 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
4989 || skip_past_comma (&str) == FAIL
4990 || wreg_required_here (&str, 0, IWMMXT_REG_WCG) == FAIL))
4991 return FAIL;
4992 break;
4994 case check_tbcst:
4995 if ((wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
4996 || skip_past_comma (&str) == FAIL
4997 || reg_required_here (&str, 12) == FAIL))
4998 return FAIL;
4999 break;
5001 case check_tmovmsk:
5002 if ((reg_required_here (&str, 12) == FAIL
5003 || skip_past_comma (&str) == FAIL
5004 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL))
5005 return FAIL;
5006 break;
5008 case check_tmia:
5009 if ((wreg_required_here (&str, 5, IWMMXT_REG_WR) == FAIL
5010 || skip_past_comma (&str) == FAIL
5011 || reg_required_here (&str, 0) == FAIL
5012 || skip_past_comma (&str) == FAIL
5013 || reg_required_here (&str, 12) == FAIL))
5014 return FAIL;
5015 break;
5017 case check_tmcrr:
5018 if ((wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL
5019 || skip_past_comma (&str) == FAIL
5020 || reg_required_here (&str, 12) == FAIL
5021 || skip_past_comma (&str) == FAIL
5022 || reg_required_here (&str, 16) == FAIL))
5023 return FAIL;
5024 break;
5026 case check_tmrrc:
5027 if ((reg_required_here (&str, 12) == FAIL
5028 || skip_past_comma (&str) == FAIL
5029 || reg_required_here (&str, 16) == FAIL
5030 || skip_past_comma (&str) == FAIL
5031 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL))
5032 return FAIL;
5033 break;
5035 case check_tmcr:
5036 if ((wreg_required_here (&str, 16, IWMMXT_REG_WC) == FAIL
5037 || skip_past_comma (&str) == FAIL
5038 || reg_required_here (&str, 12) == FAIL))
5039 return FAIL;
5040 break;
5042 case check_tmrc:
5043 if ((reg_required_here (&str, 12) == FAIL
5044 || skip_past_comma (&str) == FAIL
5045 || wreg_required_here (&str, 16, IWMMXT_REG_WC) == FAIL))
5046 return FAIL;
5047 break;
5049 case check_tinsr:
5050 if ((wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5051 || skip_past_comma (&str) == FAIL
5052 || reg_required_here (&str, 12) == FAIL
5053 || skip_past_comma (&str) == FAIL))
5054 return FAIL;
5055 break;
5057 case check_textrc:
5058 if ((reg_required_here (&str, 12) == FAIL
5059 || skip_past_comma (&str) == FAIL))
5060 return FAIL;
5061 break;
5063 case check_waligni:
5064 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
5065 || skip_past_comma (&str) == FAIL
5066 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5067 || skip_past_comma (&str) == FAIL
5068 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL
5069 || skip_past_comma (&str) == FAIL))
5070 return FAIL;
5071 break;
5073 case check_textrm:
5074 if ((reg_required_here (&str, 12) == FAIL
5075 || skip_past_comma (&str) == FAIL
5076 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5077 || skip_past_comma (&str) == FAIL))
5078 return FAIL;
5079 break;
5081 case check_wshufh:
5082 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
5083 || skip_past_comma (&str) == FAIL
5084 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5085 || skip_past_comma (&str) == FAIL))
5086 return FAIL;
5087 break;
5090 if (immediate_size == 0)
5092 end_of_line (str);
5093 inst.error = inst_error;
5094 return reg;
5096 else
5098 skip_whitespace (str);
5100 /* Allow optional leading '#'. */
5101 if (is_immediate_prefix (* str))
5102 str++;
5104 memset (& expr, '\0', sizeof (expr));
5106 if (my_get_expression (& expr, & str) || (expr.X_op != O_constant))
5108 inst.error = _("bad or missing expression");
5109 return FAIL;
5112 number = expr.X_add_number;
5114 if (number != (number & immediate_size))
5116 inst.error = _("immediate value out of range");
5117 return FAIL;
5119 end_of_line (str);
5120 inst.error = inst_error;
5121 return number;
5125 static void
5126 do_iwmmxt_byte_addr (char * str)
5128 int op = (inst.instruction & 0x300) >> 8;
5129 int reg;
5131 inst.instruction &= ~0x300;
5132 inst.instruction |= (op & 1) << 22 | (op & 2) << 7;
5134 skip_whitespace (str);
5136 if ((reg = wreg_required_here (&str, 12, IWMMXT_REG_WR_OR_WC)) == FAIL
5137 || skip_past_comma (& str) == FAIL
5138 || cp_byte_address_required_here (&str) == FAIL)
5140 if (! inst.error)
5141 inst.error = BAD_ARGS;
5143 else
5144 end_of_line (str);
5146 if (wc_register (reg))
5148 as_bad (_("non-word size not supported with control register"));
5149 inst.instruction |= 0xf0000100;
5150 inst.instruction &= ~0x00400000;
5154 static void
5155 do_iwmmxt_tandc (char * str)
5157 int reg;
5159 reg = check_iwmmxt_insn (str, check_rd, 0);
5161 if (reg != REG_PC && !inst.error)
5162 inst.error = _("only r15 allowed here");
5165 static void
5166 do_iwmmxt_tbcst (char * str)
5168 check_iwmmxt_insn (str, check_tbcst, 0);
5171 static void
5172 do_iwmmxt_textrc (char * str)
5174 unsigned long number;
5176 if ((number = check_iwmmxt_insn (str, check_textrc, 7)) == (unsigned long) FAIL)
5177 return;
5179 inst.instruction |= number & 0x7;
5182 static void
5183 do_iwmmxt_textrm (char * str)
5185 unsigned long number;
5187 if ((number = check_iwmmxt_insn (str, check_textrm, 7)) == (unsigned long) FAIL)
5188 return;
5190 inst.instruction |= number & 0x7;
5193 static void
5194 do_iwmmxt_tinsr (char * str)
5196 unsigned long number;
5198 if ((number = check_iwmmxt_insn (str, check_tinsr, 7)) == (unsigned long) FAIL)
5199 return;
5201 inst.instruction |= number & 0x7;
5204 static void
5205 do_iwmmxt_tmcr (char * str)
5207 check_iwmmxt_insn (str, check_tmcr, 0);
5210 static void
5211 do_iwmmxt_tmcrr (char * str)
5213 check_iwmmxt_insn (str, check_tmcrr, 0);
5216 static void
5217 do_iwmmxt_tmia (char * str)
5219 check_iwmmxt_insn (str, check_tmia, 0);
5222 static void
5223 do_iwmmxt_tmovmsk (char * str)
5225 check_iwmmxt_insn (str, check_tmovmsk, 0);
5228 static void
5229 do_iwmmxt_tmrc (char * str)
5231 check_iwmmxt_insn (str, check_tmrc, 0);
5234 static void
5235 do_iwmmxt_tmrrc (char * str)
5237 check_iwmmxt_insn (str, check_tmrrc, 0);
5240 static void
5241 do_iwmmxt_torc (char * str)
5243 check_iwmmxt_insn (str, check_rd, 0);
5246 static void
5247 do_iwmmxt_waligni (char * str)
5249 unsigned long number;
5251 if ((number = check_iwmmxt_insn (str, check_waligni, 7)) == (unsigned long) FAIL)
5252 return;
5254 inst.instruction |= ((number & 0x7) << 20);
5257 static void
5258 do_iwmmxt_wmov (char * str)
5260 if (check_iwmmxt_insn (str, check_wrwr, 0) == (unsigned long) FAIL)
5261 return;
5263 inst.instruction |= ((inst.instruction >> 16) & 0xf);
5266 static void
5267 do_iwmmxt_word_addr (char * str)
5269 int op = (inst.instruction & 0x300) >> 8;
5270 int reg;
5272 inst.instruction &= ~0x300;
5273 inst.instruction |= (op & 1) << 22 | (op & 2) << 7;
5275 skip_whitespace (str);
5277 if ((reg = wreg_required_here (&str, 12, IWMMXT_REG_WR_OR_WC)) == FAIL
5278 || skip_past_comma (& str) == FAIL
5279 || cp_address_required_here (& str, CP_WB_OK) == FAIL)
5281 if (! inst.error)
5282 inst.error = BAD_ARGS;
5284 else
5285 end_of_line (str);
5287 if (wc_register (reg))
5289 if ((inst.instruction & COND_MASK) != COND_ALWAYS)
5290 as_bad (_("conditional execution not supported with control register"));
5291 if (op != 2)
5292 as_bad (_("non-word size not supported with control register"));
5293 inst.instruction |= 0xf0000100;
5294 inst.instruction &= ~0x00400000;
5298 static void
5299 do_iwmmxt_wrwr (char * str)
5301 check_iwmmxt_insn (str, check_wrwr, 0);
5304 static void
5305 do_iwmmxt_wrwrwcg (char * str)
5307 check_iwmmxt_insn (str, check_wrwrwcg, 0);
5310 static void
5311 do_iwmmxt_wrwrwr (char * str)
5313 check_iwmmxt_insn (str, check_wrwrwr, 0);
5316 static void
5317 do_iwmmxt_wshufh (char * str)
5319 unsigned long number;
5321 if ((number = check_iwmmxt_insn (str, check_wshufh, 0xff)) == (unsigned long) FAIL)
5322 return;
5324 inst.instruction |= ((number & 0xf0) << 16) | (number & 0xf);
5327 static void
5328 do_iwmmxt_wzero (char * str)
5330 if (check_iwmmxt_insn (str, check_wr, 0) == (unsigned long) FAIL)
5331 return;
5333 inst.instruction |= ((inst.instruction & 0xf) << 12) | ((inst.instruction & 0xf) << 16);
5336 /* Xscale multiply-accumulate (argument parse)
5337 MIAcc acc0,Rm,Rs
5338 MIAPHcc acc0,Rm,Rs
5339 MIAxycc acc0,Rm,Rs. */
5341 static void
5342 do_xsc_mia (char * str)
5344 int rs;
5345 int rm;
5347 if (accum0_required_here (& str) == FAIL)
5348 inst.error = ERR_NO_ACCUM;
5350 else if (skip_past_comma (& str) == FAIL
5351 || (rm = reg_required_here (& str, 0)) == FAIL)
5352 inst.error = BAD_ARGS;
5354 else if (skip_past_comma (& str) == FAIL
5355 || (rs = reg_required_here (& str, 12)) == FAIL)
5356 inst.error = BAD_ARGS;
5358 /* inst.instruction has now been zapped with both rm and rs. */
5359 else if (rm == REG_PC || rs == REG_PC)
5360 inst.error = BAD_PC; /* Undefined result if rm or rs is R15. */
5362 else
5363 end_of_line (str);
5366 /* Xscale move-accumulator-register (argument parse)
5368 MARcc acc0,RdLo,RdHi. */
5370 static void
5371 do_xsc_mar (char * str)
5373 int rdlo, rdhi;
5375 if (accum0_required_here (& str) == FAIL)
5376 inst.error = ERR_NO_ACCUM;
5378 else if (skip_past_comma (& str) == FAIL
5379 || (rdlo = reg_required_here (& str, 12)) == FAIL)
5380 inst.error = BAD_ARGS;
5382 else if (skip_past_comma (& str) == FAIL
5383 || (rdhi = reg_required_here (& str, 16)) == FAIL)
5384 inst.error = BAD_ARGS;
5386 /* inst.instruction has now been zapped with both rdlo and rdhi. */
5387 else if (rdlo == REG_PC || rdhi == REG_PC)
5388 inst.error = BAD_PC; /* Undefined result if rdlo or rdhi is R15. */
5390 else
5391 end_of_line (str);
5394 /* Xscale move-register-accumulator (argument parse)
5396 MRAcc RdLo,RdHi,acc0. */
5398 static void
5399 do_xsc_mra (char * str)
5401 int rdlo;
5402 int rdhi;
5404 skip_whitespace (str);
5406 if ((rdlo = reg_required_here (& str, 12)) == FAIL)
5407 inst.error = BAD_ARGS;
5409 else if (skip_past_comma (& str) == FAIL
5410 || (rdhi = reg_required_here (& str, 16)) == FAIL)
5411 inst.error = BAD_ARGS;
5413 else if (skip_past_comma (& str) == FAIL
5414 || accum0_required_here (& str) == FAIL)
5415 inst.error = ERR_NO_ACCUM;
5417 /* inst.instruction has now been zapped with both rdlo and rdhi. */
5418 else if (rdlo == rdhi)
5419 inst.error = BAD_ARGS; /* Undefined result if 2 writes to same reg. */
5421 else if (rdlo == REG_PC || rdhi == REG_PC)
5422 inst.error = BAD_PC; /* Undefined result if rdlo or rdhi is R15. */
5423 else
5424 end_of_line (str);
5427 static int
5428 ldst_extend (char ** str)
5430 int add = INDEX_UP;
5432 switch (**str)
5434 case '#':
5435 case '$':
5436 (*str)++;
5437 if (my_get_expression (& inst.reloc.exp, str))
5438 return FAIL;
5440 if (inst.reloc.exp.X_op == O_constant)
5442 int value = inst.reloc.exp.X_add_number;
5444 if (value < -4095 || value > 4095)
5446 inst.error = _("address offset too large");
5447 return FAIL;
5450 if (value < 0)
5452 value = -value;
5453 add = 0;
5456 inst.instruction |= add | value;
5458 else
5460 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
5461 inst.reloc.pc_rel = 0;
5463 return SUCCESS;
5465 case '-':
5466 add = 0;
5467 /* Fall through. */
5469 case '+':
5470 (*str)++;
5471 /* Fall through. */
5473 default:
5474 if (reg_required_here (str, 0) == FAIL)
5475 return FAIL;
5477 inst.instruction |= add | OFFSET_REG;
5478 if (skip_past_comma (str) == SUCCESS)
5479 return decode_shift (str, SHIFT_IMMEDIATE);
5481 return SUCCESS;
5485 /* ARMv5TE: Preload-Cache
5487 PLD <addr_mode>
5489 Syntactically, like LDR with B=1, W=0, L=1. */
5491 static void
5492 do_pld (char * str)
5494 int rd;
5496 skip_whitespace (str);
5498 if (* str != '[')
5500 inst.error = _("'[' expected after PLD mnemonic");
5501 return;
5504 ++str;
5505 skip_whitespace (str);
5507 if ((rd = reg_required_here (& str, 16)) == FAIL)
5508 return;
5510 skip_whitespace (str);
5512 if (*str == ']')
5514 /* [Rn], ... ? */
5515 ++str;
5516 skip_whitespace (str);
5518 /* Post-indexed addressing is not allowed with PLD. */
5519 if (skip_past_comma (&str) == SUCCESS)
5521 inst.error
5522 = _("post-indexed expression used in preload instruction");
5523 return;
5525 else if (*str == '!') /* [Rn]! */
5527 inst.error = _("writeback used in preload instruction");
5528 ++str;
5530 else /* [Rn] */
5531 inst.instruction |= INDEX_UP | PRE_INDEX;
5533 else /* [Rn, ...] */
5535 if (skip_past_comma (& str) == FAIL)
5537 inst.error = _("pre-indexed expression expected");
5538 return;
5541 if (ldst_extend (&str) == FAIL)
5542 return;
5544 skip_whitespace (str);
5546 if (* str != ']')
5548 inst.error = _("missing ]");
5549 return;
5552 ++ str;
5553 skip_whitespace (str);
5555 if (* str == '!') /* [Rn]! */
5557 inst.error = _("writeback used in preload instruction");
5558 ++ str;
5561 inst.instruction |= PRE_INDEX;
5564 end_of_line (str);
5567 /* ARMv5TE load-consecutive (argument parse)
5568 Mode is like LDRH.
5570 LDRccD R, mode
5571 STRccD R, mode. */
5573 static void
5574 do_ldrd (char * str)
5576 int rd;
5577 int rn;
5579 skip_whitespace (str);
5581 if ((rd = reg_required_here (& str, 12)) == FAIL)
5583 inst.error = BAD_ARGS;
5584 return;
5587 if (skip_past_comma (& str) == FAIL
5588 || (rn = ld_mode_required_here (& str)) == FAIL)
5590 if (!inst.error)
5591 inst.error = BAD_ARGS;
5592 return;
5595 /* inst.instruction has now been zapped with Rd and the addressing mode. */
5596 if (rd & 1) /* Unpredictable result if Rd is odd. */
5598 inst.error = _("destination register must be even");
5599 return;
5602 if (rd == REG_LR)
5604 inst.error = _("r14 not allowed here");
5605 return;
5608 if (((rd == rn) || (rd + 1 == rn))
5609 && ((inst.instruction & WRITE_BACK)
5610 || (!(inst.instruction & PRE_INDEX))))
5611 as_warn (_("pre/post-indexing used when modified address register is destination"));
5613 /* For an index-register load, the index register must not overlap the
5614 destination (even if not write-back). */
5615 if ((inst.instruction & V4_STR_BIT) == 0
5616 && (inst.instruction & HWOFFSET_IMM) == 0)
5618 int rm = inst.instruction & 0x0000000f;
5620 if (rm == rd || (rm == rd + 1))
5621 as_warn (_("ldrd destination registers must not overlap index register"));
5624 end_of_line (str);
5627 /* Returns the index into fp_values of a floating point number,
5628 or -1 if not in the table. */
5630 static int
5631 my_get_float_expression (char ** str)
5633 LITTLENUM_TYPE words[MAX_LITTLENUMS];
5634 char * save_in;
5635 expressionS exp;
5636 int i;
5637 int j;
5639 memset (words, 0, MAX_LITTLENUMS * sizeof (LITTLENUM_TYPE));
5641 /* Look for a raw floating point number. */
5642 if ((save_in = atof_ieee (*str, 'x', words)) != NULL
5643 && is_end_of_line[(unsigned char) *save_in])
5645 for (i = 0; i < NUM_FLOAT_VALS; i++)
5647 for (j = 0; j < MAX_LITTLENUMS; j++)
5649 if (words[j] != fp_values[i][j])
5650 break;
5653 if (j == MAX_LITTLENUMS)
5655 *str = save_in;
5656 return i;
5661 /* Try and parse a more complex expression, this will probably fail
5662 unless the code uses a floating point prefix (eg "0f"). */
5663 save_in = input_line_pointer;
5664 input_line_pointer = *str;
5665 if (expression (&exp) == absolute_section
5666 && exp.X_op == O_big
5667 && exp.X_add_number < 0)
5669 /* FIXME: 5 = X_PRECISION, should be #define'd where we can use it.
5670 Ditto for 15. */
5671 if (gen_to_words (words, 5, (long) 15) == 0)
5673 for (i = 0; i < NUM_FLOAT_VALS; i++)
5675 for (j = 0; j < MAX_LITTLENUMS; j++)
5677 if (words[j] != fp_values[i][j])
5678 break;
5681 if (j == MAX_LITTLENUMS)
5683 *str = input_line_pointer;
5684 input_line_pointer = save_in;
5685 return i;
5691 *str = input_line_pointer;
5692 input_line_pointer = save_in;
5693 return -1;
5696 /* We handle all bad expressions here, so that we can report the faulty
5697 instruction in the error message. */
5698 void
5699 md_operand (expressionS * expr)
5701 if (in_my_get_expression)
5703 expr->X_op = O_illegal;
5704 if (inst.error == NULL)
5705 inst.error = _("bad expression");
5709 /* Do those data_ops which can take a negative immediate constant
5710 by altering the instruction. A bit of a hack really.
5711 MOV <-> MVN
5712 AND <-> BIC
5713 ADC <-> SBC
5714 by inverting the second operand, and
5715 ADD <-> SUB
5716 CMP <-> CMN
5717 by negating the second operand. */
5719 static int
5720 negate_data_op (unsigned long * instruction,
5721 unsigned long value)
5723 int op, new_inst;
5724 unsigned long negated, inverted;
5726 negated = validate_immediate (-value);
5727 inverted = validate_immediate (~value);
5729 op = (*instruction >> DATA_OP_SHIFT) & 0xf;
5730 switch (op)
5732 /* First negates. */
5733 case OPCODE_SUB: /* ADD <-> SUB */
5734 new_inst = OPCODE_ADD;
5735 value = negated;
5736 break;
5738 case OPCODE_ADD:
5739 new_inst = OPCODE_SUB;
5740 value = negated;
5741 break;
5743 case OPCODE_CMP: /* CMP <-> CMN */
5744 new_inst = OPCODE_CMN;
5745 value = negated;
5746 break;
5748 case OPCODE_CMN:
5749 new_inst = OPCODE_CMP;
5750 value = negated;
5751 break;
5753 /* Now Inverted ops. */
5754 case OPCODE_MOV: /* MOV <-> MVN */
5755 new_inst = OPCODE_MVN;
5756 value = inverted;
5757 break;
5759 case OPCODE_MVN:
5760 new_inst = OPCODE_MOV;
5761 value = inverted;
5762 break;
5764 case OPCODE_AND: /* AND <-> BIC */
5765 new_inst = OPCODE_BIC;
5766 value = inverted;
5767 break;
5769 case OPCODE_BIC:
5770 new_inst = OPCODE_AND;
5771 value = inverted;
5772 break;
5774 case OPCODE_ADC: /* ADC <-> SBC */
5775 new_inst = OPCODE_SBC;
5776 value = inverted;
5777 break;
5779 case OPCODE_SBC:
5780 new_inst = OPCODE_ADC;
5781 value = inverted;
5782 break;
5784 /* We cannot do anything. */
5785 default:
5786 return FAIL;
5789 if (value == (unsigned) FAIL)
5790 return FAIL;
5792 *instruction &= OPCODE_MASK;
5793 *instruction |= new_inst << DATA_OP_SHIFT;
5794 return value;
5797 static int
5798 data_op2 (char ** str)
5800 int value;
5801 expressionS expr;
5803 skip_whitespace (* str);
5805 if (reg_required_here (str, 0) != FAIL)
5807 if (skip_past_comma (str) == SUCCESS)
5808 /* Shift operation on register. */
5809 return decode_shift (str, NO_SHIFT_RESTRICT);
5811 return SUCCESS;
5813 else
5815 /* Immediate expression. */
5816 if (is_immediate_prefix (**str))
5818 (*str)++;
5819 inst.error = NULL;
5821 if (my_get_expression (&inst.reloc.exp, str))
5822 return FAIL;
5824 if (inst.reloc.exp.X_add_symbol)
5826 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
5827 inst.reloc.pc_rel = 0;
5829 else
5831 if (skip_past_comma (str) == SUCCESS)
5833 /* #x, y -- ie explicit rotation by Y. */
5834 if (my_get_expression (&expr, str))
5835 return FAIL;
5837 if (expr.X_op != O_constant)
5839 inst.error = _("constant expression expected");
5840 return FAIL;
5843 /* Rotate must be a multiple of 2. */
5844 if (((unsigned) expr.X_add_number) > 30
5845 || (expr.X_add_number & 1) != 0
5846 || ((unsigned) inst.reloc.exp.X_add_number) > 255)
5848 inst.error = _("invalid constant");
5849 return FAIL;
5851 inst.instruction |= INST_IMMEDIATE;
5852 inst.instruction |= inst.reloc.exp.X_add_number;
5853 inst.instruction |= expr.X_add_number << 7;
5854 return SUCCESS;
5857 /* Implicit rotation, select a suitable one. */
5858 value = validate_immediate (inst.reloc.exp.X_add_number);
5860 if (value == FAIL)
5862 /* Can't be done. Perhaps the code reads something like
5863 "add Rd, Rn, #-n", where "sub Rd, Rn, #n" would be OK. */
5864 if ((value = negate_data_op (&inst.instruction,
5865 inst.reloc.exp.X_add_number))
5866 == FAIL)
5868 inst.error = _("invalid constant");
5869 return FAIL;
5873 inst.instruction |= value;
5876 inst.instruction |= INST_IMMEDIATE;
5877 return SUCCESS;
5880 (*str)++;
5881 inst.error = _("register or shift expression expected");
5882 return FAIL;
5886 static int
5887 fp_op2 (char ** str)
5889 skip_whitespace (* str);
5891 if (fp_reg_required_here (str, 0) != FAIL)
5892 return SUCCESS;
5893 else
5895 /* Immediate expression. */
5896 if (*((*str)++) == '#')
5898 int i;
5900 inst.error = NULL;
5902 skip_whitespace (* str);
5904 /* First try and match exact strings, this is to guarantee
5905 that some formats will work even for cross assembly. */
5907 for (i = 0; fp_const[i]; i++)
5909 if (strncmp (*str, fp_const[i], strlen (fp_const[i])) == 0)
5911 char *start = *str;
5913 *str += strlen (fp_const[i]);
5914 if (is_end_of_line[(unsigned char) **str])
5916 inst.instruction |= i + 8;
5917 return SUCCESS;
5919 *str = start;
5923 /* Just because we didn't get a match doesn't mean that the
5924 constant isn't valid, just that it is in a format that we
5925 don't automatically recognize. Try parsing it with
5926 the standard expression routines. */
5927 if ((i = my_get_float_expression (str)) >= 0)
5929 inst.instruction |= i + 8;
5930 return SUCCESS;
5933 inst.error = _("invalid floating point immediate expression");
5934 return FAIL;
5936 inst.error =
5937 _("floating point register or immediate expression expected");
5938 return FAIL;
5942 static void
5943 do_arit (char * str)
5945 skip_whitespace (str);
5947 if (reg_required_here (&str, 12) == FAIL
5948 || skip_past_comma (&str) == FAIL
5949 || reg_required_here (&str, 16) == FAIL
5950 || skip_past_comma (&str) == FAIL
5951 || data_op2 (&str) == FAIL)
5953 if (!inst.error)
5954 inst.error = BAD_ARGS;
5955 return;
5958 end_of_line (str);
5961 static void
5962 do_adr (char * str)
5964 /* This is a pseudo-op of the form "adr rd, label" to be converted
5965 into a relative address of the form "add rd, pc, #label-.-8". */
5966 skip_whitespace (str);
5968 if (reg_required_here (&str, 12) == FAIL
5969 || skip_past_comma (&str) == FAIL
5970 || my_get_expression (&inst.reloc.exp, &str))
5972 if (!inst.error)
5973 inst.error = BAD_ARGS;
5974 return;
5977 /* Frag hacking will turn this into a sub instruction if the offset turns
5978 out to be negative. */
5979 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
5980 #ifndef TE_WINCE
5981 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust. */
5982 #endif
5983 inst.reloc.pc_rel = 1;
5985 end_of_line (str);
5988 static void
5989 do_adrl (char * str)
5991 /* This is a pseudo-op of the form "adrl rd, label" to be converted
5992 into a relative address of the form:
5993 add rd, pc, #low(label-.-8)"
5994 add rd, rd, #high(label-.-8)" */
5996 skip_whitespace (str);
5998 if (reg_required_here (&str, 12) == FAIL
5999 || skip_past_comma (&str) == FAIL
6000 || my_get_expression (&inst.reloc.exp, &str))
6002 if (!inst.error)
6003 inst.error = BAD_ARGS;
6005 return;
6008 end_of_line (str);
6009 /* Frag hacking will turn this into a sub instruction if the offset turns
6010 out to be negative. */
6011 inst.reloc.type = BFD_RELOC_ARM_ADRL_IMMEDIATE;
6012 #ifndef TE_WINCE
6013 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust */
6014 #endif
6015 inst.reloc.pc_rel = 1;
6016 inst.size = INSN_SIZE * 2;
6019 static void
6020 do_cmp (char * str)
6022 skip_whitespace (str);
6024 if (reg_required_here (&str, 16) == FAIL)
6026 if (!inst.error)
6027 inst.error = BAD_ARGS;
6028 return;
6031 if (skip_past_comma (&str) == FAIL
6032 || data_op2 (&str) == FAIL)
6034 if (!inst.error)
6035 inst.error = BAD_ARGS;
6036 return;
6039 end_of_line (str);
6042 static void
6043 do_mov (char * str)
6045 skip_whitespace (str);
6047 if (reg_required_here (&str, 12) == FAIL)
6049 if (!inst.error)
6050 inst.error = BAD_ARGS;
6051 return;
6054 if (skip_past_comma (&str) == FAIL
6055 || data_op2 (&str) == FAIL)
6057 if (!inst.error)
6058 inst.error = BAD_ARGS;
6059 return;
6062 end_of_line (str);
6065 static void
6066 do_ldst (char * str)
6068 int pre_inc = 0;
6069 int conflict_reg;
6070 int value;
6072 skip_whitespace (str);
6074 if ((conflict_reg = reg_required_here (&str, 12)) == FAIL)
6076 if (!inst.error)
6077 inst.error = BAD_ARGS;
6078 return;
6081 if (skip_past_comma (&str) == FAIL)
6083 inst.error = _("address expected");
6084 return;
6087 if (*str == '[')
6089 int reg;
6091 str++;
6093 skip_whitespace (str);
6095 if ((reg = reg_required_here (&str, 16)) == FAIL)
6096 return;
6098 /* Conflicts can occur on stores as well as loads. */
6099 conflict_reg = (conflict_reg == reg);
6101 skip_whitespace (str);
6103 if (*str == ']')
6105 str ++;
6107 if (skip_past_comma (&str) == SUCCESS)
6109 /* [Rn],... (post inc) */
6110 if (ldst_extend (&str) == FAIL)
6111 return;
6112 if (conflict_reg)
6113 as_warn (_("%s register same as write-back base"),
6114 ((inst.instruction & LOAD_BIT)
6115 ? _("destination") : _("source")));
6117 else
6119 /* [Rn] */
6120 skip_whitespace (str);
6122 if (*str == '!')
6124 if (conflict_reg)
6125 as_warn (_("%s register same as write-back base"),
6126 ((inst.instruction & LOAD_BIT)
6127 ? _("destination") : _("source")));
6128 str++;
6129 inst.instruction |= WRITE_BACK;
6132 inst.instruction |= INDEX_UP;
6133 pre_inc = 1;
6136 else
6138 /* [Rn,...] */
6139 if (skip_past_comma (&str) == FAIL)
6141 inst.error = _("pre-indexed expression expected");
6142 return;
6145 pre_inc = 1;
6146 if (ldst_extend (&str) == FAIL)
6147 return;
6149 skip_whitespace (str);
6151 if (*str++ != ']')
6153 inst.error = _("missing ]");
6154 return;
6157 skip_whitespace (str);
6159 if (*str == '!')
6161 if (conflict_reg)
6162 as_warn (_("%s register same as write-back base"),
6163 ((inst.instruction & LOAD_BIT)
6164 ? _("destination") : _("source")));
6165 str++;
6166 inst.instruction |= WRITE_BACK;
6170 else if (*str == '=')
6172 if ((inst.instruction & LOAD_BIT) == 0)
6174 inst.error = _("invalid pseudo operation");
6175 return;
6178 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
6179 str++;
6181 skip_whitespace (str);
6183 if (my_get_expression (&inst.reloc.exp, &str))
6184 return;
6186 if (inst.reloc.exp.X_op != O_constant
6187 && inst.reloc.exp.X_op != O_symbol)
6189 inst.error = _("constant expression expected");
6190 return;
6193 if (inst.reloc.exp.X_op == O_constant)
6195 value = validate_immediate (inst.reloc.exp.X_add_number);
6197 if (value != FAIL)
6199 /* This can be done with a mov instruction. */
6200 inst.instruction &= LITERAL_MASK;
6201 inst.instruction |= (INST_IMMEDIATE
6202 | (OPCODE_MOV << DATA_OP_SHIFT));
6203 inst.instruction |= value & 0xfff;
6204 end_of_line (str);
6205 return;
6208 value = validate_immediate (~inst.reloc.exp.X_add_number);
6210 if (value != FAIL)
6212 /* This can be done with a mvn instruction. */
6213 inst.instruction &= LITERAL_MASK;
6214 inst.instruction |= (INST_IMMEDIATE
6215 | (OPCODE_MVN << DATA_OP_SHIFT));
6216 inst.instruction |= value & 0xfff;
6217 end_of_line (str);
6218 return;
6222 /* Insert into literal pool. */
6223 if (add_to_lit_pool () == FAIL)
6225 if (!inst.error)
6226 inst.error = _("literal pool insertion failed");
6227 return;
6230 /* Change the instruction exp to point to the pool. */
6231 inst.reloc.type = BFD_RELOC_ARM_LITERAL;
6232 inst.reloc.pc_rel = 1;
6233 inst.instruction |= (REG_PC << 16);
6234 pre_inc = 1;
6236 else
6238 if (my_get_expression (&inst.reloc.exp, &str))
6239 return;
6241 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
6242 #ifndef TE_WINCE
6243 /* PC rel adjust. */
6244 inst.reloc.exp.X_add_number -= 8;
6245 #endif
6246 inst.reloc.pc_rel = 1;
6247 inst.instruction |= (REG_PC << 16);
6248 pre_inc = 1;
6251 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
6252 end_of_line (str);
6255 static void
6256 do_ldstt (char * str)
6258 int conflict_reg;
6260 skip_whitespace (str);
6262 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
6264 if (!inst.error)
6265 inst.error = BAD_ARGS;
6266 return;
6269 if (skip_past_comma (& str) == FAIL)
6271 inst.error = _("address expected");
6272 return;
6275 if (*str == '[')
6277 int reg;
6279 str++;
6281 skip_whitespace (str);
6283 if ((reg = reg_required_here (&str, 16)) == FAIL)
6284 return;
6286 /* ldrt/strt always use post-indexed addressing, so if the base is
6287 the same as Rd, we warn. */
6288 if (conflict_reg == reg)
6289 as_warn (_("%s register same as write-back base"),
6290 ((inst.instruction & LOAD_BIT)
6291 ? _("destination") : _("source")));
6293 skip_whitespace (str);
6295 if (*str == ']')
6297 str ++;
6299 if (skip_past_comma (&str) == SUCCESS)
6301 /* [Rn],... (post inc) */
6302 if (ldst_extend (&str) == FAIL)
6303 return;
6305 else
6307 /* [Rn] */
6308 skip_whitespace (str);
6310 /* Skip a write-back '!'. */
6311 if (*str == '!')
6312 str++;
6314 inst.instruction |= INDEX_UP;
6317 else
6319 inst.error = _("post-indexed expression expected");
6320 return;
6323 else
6325 inst.error = _("post-indexed expression expected");
6326 return;
6329 end_of_line (str);
6332 /* Halfword and signed-byte load/store operations. */
6334 static void
6335 do_ldstv4 (char * str)
6337 int pre_inc = 0;
6338 int conflict_reg;
6339 int value;
6341 skip_whitespace (str);
6343 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
6345 if (!inst.error)
6346 inst.error = BAD_ARGS;
6347 return;
6350 if (skip_past_comma (& str) == FAIL)
6352 inst.error = _("address expected");
6353 return;
6356 if (*str == '[')
6358 int reg;
6360 str++;
6362 skip_whitespace (str);
6364 if ((reg = reg_required_here (&str, 16)) == FAIL)
6365 return;
6367 /* Conflicts can occur on stores as well as loads. */
6368 conflict_reg = (conflict_reg == reg);
6370 skip_whitespace (str);
6372 if (*str == ']')
6374 str ++;
6376 if (skip_past_comma (&str) == SUCCESS)
6378 /* [Rn],... (post inc) */
6379 if (ldst_extend_v4 (&str) == FAIL)
6380 return;
6381 if (conflict_reg)
6382 as_warn (_("%s register same as write-back base"),
6383 ((inst.instruction & LOAD_BIT)
6384 ? _("destination") : _("source")));
6386 else
6388 /* [Rn] */
6389 inst.instruction |= HWOFFSET_IMM;
6391 skip_whitespace (str);
6393 if (*str == '!')
6395 if (conflict_reg)
6396 as_warn (_("%s register same as write-back base"),
6397 ((inst.instruction & LOAD_BIT)
6398 ? _("destination") : _("source")));
6399 str++;
6400 inst.instruction |= WRITE_BACK;
6403 inst.instruction |= INDEX_UP;
6404 pre_inc = 1;
6407 else
6409 /* [Rn,...] */
6410 if (skip_past_comma (&str) == FAIL)
6412 inst.error = _("pre-indexed expression expected");
6413 return;
6416 pre_inc = 1;
6417 if (ldst_extend_v4 (&str) == FAIL)
6418 return;
6420 skip_whitespace (str);
6422 if (*str++ != ']')
6424 inst.error = _("missing ]");
6425 return;
6428 skip_whitespace (str);
6430 if (*str == '!')
6432 if (conflict_reg)
6433 as_warn (_("%s register same as write-back base"),
6434 ((inst.instruction & LOAD_BIT)
6435 ? _("destination") : _("source")));
6436 str++;
6437 inst.instruction |= WRITE_BACK;
6441 else if (*str == '=')
6443 if ((inst.instruction & LOAD_BIT) == 0)
6445 inst.error = _("invalid pseudo operation");
6446 return;
6449 /* XXX Does this work correctly for half-word/byte ops? */
6450 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
6451 str++;
6453 skip_whitespace (str);
6455 if (my_get_expression (&inst.reloc.exp, &str))
6456 return;
6458 if (inst.reloc.exp.X_op != O_constant
6459 && inst.reloc.exp.X_op != O_symbol)
6461 inst.error = _("constant expression expected");
6462 return;
6465 if (inst.reloc.exp.X_op == O_constant)
6467 value = validate_immediate (inst.reloc.exp.X_add_number);
6469 if (value != FAIL)
6471 /* This can be done with a mov instruction. */
6472 inst.instruction &= LITERAL_MASK;
6473 inst.instruction |= INST_IMMEDIATE | (OPCODE_MOV << DATA_OP_SHIFT);
6474 inst.instruction |= value & 0xfff;
6475 end_of_line (str);
6476 return;
6479 value = validate_immediate (~ inst.reloc.exp.X_add_number);
6481 if (value != FAIL)
6483 /* This can be done with a mvn instruction. */
6484 inst.instruction &= LITERAL_MASK;
6485 inst.instruction |= INST_IMMEDIATE | (OPCODE_MVN << DATA_OP_SHIFT);
6486 inst.instruction |= value & 0xfff;
6487 end_of_line (str);
6488 return;
6492 /* Insert into literal pool. */
6493 if (add_to_lit_pool () == FAIL)
6495 if (!inst.error)
6496 inst.error = _("literal pool insertion failed");
6497 return;
6500 /* Change the instruction exp to point to the pool. */
6501 inst.instruction |= HWOFFSET_IMM;
6502 inst.reloc.type = BFD_RELOC_ARM_HWLITERAL;
6503 inst.reloc.pc_rel = 1;
6504 inst.instruction |= (REG_PC << 16);
6505 pre_inc = 1;
6507 else
6509 if (my_get_expression (&inst.reloc.exp, &str))
6510 return;
6512 inst.instruction |= HWOFFSET_IMM;
6513 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
6514 #ifndef TE_WINCE
6515 /* PC rel adjust. */
6516 inst.reloc.exp.X_add_number -= 8;
6517 #endif
6518 inst.reloc.pc_rel = 1;
6519 inst.instruction |= (REG_PC << 16);
6520 pre_inc = 1;
6523 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
6524 end_of_line (str);
6527 static long
6528 reg_list (char ** strp)
6530 char * str = * strp;
6531 long range = 0;
6532 int another_range;
6534 /* We come back here if we get ranges concatenated by '+' or '|'. */
6537 another_range = 0;
6539 if (*str == '{')
6541 int in_range = 0;
6542 int cur_reg = -1;
6544 str++;
6547 int reg;
6549 skip_whitespace (str);
6551 if ((reg = reg_required_here (& str, -1)) == FAIL)
6552 return FAIL;
6554 if (in_range)
6556 int i;
6558 if (reg <= cur_reg)
6560 inst.error = _("bad range in register list");
6561 return FAIL;
6564 for (i = cur_reg + 1; i < reg; i++)
6566 if (range & (1 << i))
6567 as_tsktsk
6568 (_("Warning: duplicated register (r%d) in register list"),
6570 else
6571 range |= 1 << i;
6573 in_range = 0;
6576 if (range & (1 << reg))
6577 as_tsktsk (_("Warning: duplicated register (r%d) in register list"),
6578 reg);
6579 else if (reg <= cur_reg)
6580 as_tsktsk (_("Warning: register range not in ascending order"));
6582 range |= 1 << reg;
6583 cur_reg = reg;
6585 while (skip_past_comma (&str) != FAIL
6586 || (in_range = 1, *str++ == '-'));
6587 str--;
6588 skip_whitespace (str);
6590 if (*str++ != '}')
6592 inst.error = _("missing `}'");
6593 return FAIL;
6596 else
6598 expressionS expr;
6600 if (my_get_expression (&expr, &str))
6601 return FAIL;
6603 if (expr.X_op == O_constant)
6605 if (expr.X_add_number
6606 != (expr.X_add_number & 0x0000ffff))
6608 inst.error = _("invalid register mask");
6609 return FAIL;
6612 if ((range & expr.X_add_number) != 0)
6614 int regno = range & expr.X_add_number;
6616 regno &= -regno;
6617 regno = (1 << regno) - 1;
6618 as_tsktsk
6619 (_("Warning: duplicated register (r%d) in register list"),
6620 regno);
6623 range |= expr.X_add_number;
6625 else
6627 if (inst.reloc.type != 0)
6629 inst.error = _("expression too complex");
6630 return FAIL;
6633 memcpy (&inst.reloc.exp, &expr, sizeof (expressionS));
6634 inst.reloc.type = BFD_RELOC_ARM_MULTI;
6635 inst.reloc.pc_rel = 0;
6639 skip_whitespace (str);
6641 if (*str == '|' || *str == '+')
6643 str++;
6644 another_range = 1;
6647 while (another_range);
6649 *strp = str;
6650 return range;
6653 static void
6654 do_ldmstm (char * str)
6656 int base_reg;
6657 long range;
6659 skip_whitespace (str);
6661 if ((base_reg = reg_required_here (&str, 16)) == FAIL)
6662 return;
6664 if (base_reg == REG_PC)
6666 inst.error = _("r15 not allowed as base register");
6667 return;
6670 skip_whitespace (str);
6672 if (*str == '!')
6674 inst.instruction |= WRITE_BACK;
6675 str++;
6678 if (skip_past_comma (&str) == FAIL
6679 || (range = reg_list (&str)) == FAIL)
6681 if (! inst.error)
6682 inst.error = BAD_ARGS;
6683 return;
6686 if (*str == '^')
6688 str++;
6689 inst.instruction |= LDM_TYPE_2_OR_3;
6692 if (inst.instruction & WRITE_BACK)
6694 /* Check for unpredictable uses of writeback. */
6695 if (inst.instruction & LOAD_BIT)
6697 /* Not allowed in LDM type 2. */
6698 if ((inst.instruction & LDM_TYPE_2_OR_3)
6699 && ((range & (1 << REG_PC)) == 0))
6700 as_warn (_("writeback of base register is UNPREDICTABLE"));
6701 /* Only allowed if base reg not in list for other types. */
6702 else if (range & (1 << base_reg))
6703 as_warn (_("writeback of base register when in register list is UNPREDICTABLE"));
6705 else /* STM. */
6707 /* Not allowed for type 2. */
6708 if (inst.instruction & LDM_TYPE_2_OR_3)
6709 as_warn (_("writeback of base register is UNPREDICTABLE"));
6710 /* Only allowed if base reg not in list, or first in list. */
6711 else if ((range & (1 << base_reg))
6712 && (range & ((1 << base_reg) - 1)))
6713 as_warn (_("if writeback register is in list, it must be the lowest reg in the list"));
6717 inst.instruction |= range;
6718 end_of_line (str);
6721 static void
6722 do_smi (char * str)
6724 skip_whitespace (str);
6726 /* Allow optional leading '#'. */
6727 if (is_immediate_prefix (*str))
6728 str++;
6730 if (my_get_expression (& inst.reloc.exp, & str))
6731 return;
6733 inst.reloc.type = BFD_RELOC_ARM_SMI;
6734 inst.reloc.pc_rel = 0;
6735 end_of_line (str);
6738 static void
6739 do_swi (char * str)
6741 skip_whitespace (str);
6743 /* Allow optional leading '#'. */
6744 if (is_immediate_prefix (*str))
6745 str++;
6747 if (my_get_expression (& inst.reloc.exp, & str))
6748 return;
6750 inst.reloc.type = BFD_RELOC_ARM_SWI;
6751 inst.reloc.pc_rel = 0;
6752 end_of_line (str);
6755 static void
6756 do_swap (char * str)
6758 int reg;
6760 skip_whitespace (str);
6762 if ((reg = reg_required_here (&str, 12)) == FAIL)
6763 return;
6765 if (reg == REG_PC)
6767 inst.error = _("r15 not allowed in swap");
6768 return;
6771 if (skip_past_comma (&str) == FAIL
6772 || (reg = reg_required_here (&str, 0)) == FAIL)
6774 if (!inst.error)
6775 inst.error = BAD_ARGS;
6776 return;
6779 if (reg == REG_PC)
6781 inst.error = _("r15 not allowed in swap");
6782 return;
6785 if (skip_past_comma (&str) == FAIL
6786 || *str++ != '[')
6788 inst.error = BAD_ARGS;
6789 return;
6792 skip_whitespace (str);
6794 if ((reg = reg_required_here (&str, 16)) == FAIL)
6795 return;
6797 if (reg == REG_PC)
6799 inst.error = BAD_PC;
6800 return;
6803 skip_whitespace (str);
6805 if (*str++ != ']')
6807 inst.error = _("missing ]");
6808 return;
6811 end_of_line (str);
6814 static void
6815 do_branch (char * str)
6817 if (my_get_expression (&inst.reloc.exp, &str))
6818 return;
6820 #ifdef OBJ_ELF
6822 char * save_in;
6824 /* ScottB: February 5, 1998 - Check to see of PLT32 reloc
6825 required for the instruction. */
6827 /* arm_parse_reloc () works on input_line_pointer.
6828 We actually want to parse the operands to the branch instruction
6829 passed in 'str'. Save the input pointer and restore it later. */
6830 save_in = input_line_pointer;
6831 input_line_pointer = str;
6832 if (inst.reloc.exp.X_op == O_symbol
6833 && *str == '('
6834 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
6836 inst.reloc.type = BFD_RELOC_ARM_PLT32;
6837 inst.reloc.pc_rel = 0;
6838 /* Modify str to point to after parsed operands, otherwise
6839 end_of_line() will complain about the (PLT) left in str. */
6840 str = input_line_pointer;
6842 else
6844 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
6845 inst.reloc.pc_rel = 1;
6847 input_line_pointer = save_in;
6849 #else
6850 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
6851 inst.reloc.pc_rel = 1;
6852 #endif /* OBJ_ELF */
6854 end_of_line (str);
6857 static void
6858 do_cdp (char * str)
6860 /* Co-processor data operation.
6861 Format: CDP{cond} CP#,<expr>,CRd,CRn,CRm{,<expr>} */
6862 skip_whitespace (str);
6864 if (co_proc_number (&str) == FAIL)
6866 if (!inst.error)
6867 inst.error = BAD_ARGS;
6868 return;
6871 if (skip_past_comma (&str) == FAIL
6872 || cp_opc_expr (&str, 20,4) == FAIL)
6874 if (!inst.error)
6875 inst.error = BAD_ARGS;
6876 return;
6879 if (skip_past_comma (&str) == FAIL
6880 || cp_reg_required_here (&str, 12) == FAIL)
6882 if (!inst.error)
6883 inst.error = BAD_ARGS;
6884 return;
6887 if (skip_past_comma (&str) == FAIL
6888 || cp_reg_required_here (&str, 16) == FAIL)
6890 if (!inst.error)
6891 inst.error = BAD_ARGS;
6892 return;
6895 if (skip_past_comma (&str) == FAIL
6896 || cp_reg_required_here (&str, 0) == FAIL)
6898 if (!inst.error)
6899 inst.error = BAD_ARGS;
6900 return;
6903 if (skip_past_comma (&str) == SUCCESS)
6905 if (cp_opc_expr (&str, 5, 3) == FAIL)
6907 if (!inst.error)
6908 inst.error = BAD_ARGS;
6909 return;
6913 end_of_line (str);
6916 static void
6917 do_lstc (char * str)
6919 /* Co-processor register load/store.
6920 Format: <LDC|STC{cond}[L] CP#,CRd,<address> */
6922 skip_whitespace (str);
6924 if (co_proc_number (&str) == FAIL)
6926 if (!inst.error)
6927 inst.error = BAD_ARGS;
6928 return;
6931 if (skip_past_comma (&str) == FAIL
6932 || cp_reg_required_here (&str, 12) == FAIL)
6934 if (!inst.error)
6935 inst.error = BAD_ARGS;
6936 return;
6939 if (skip_past_comma (&str) == FAIL
6940 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
6942 if (! inst.error)
6943 inst.error = BAD_ARGS;
6944 return;
6947 end_of_line (str);
6950 static void
6951 do_co_reg (char * str)
6953 /* Co-processor register transfer.
6954 Format: <MCR|MRC>{cond} CP#,<expr1>,Rd,CRn,CRm{,<expr2>} */
6956 skip_whitespace (str);
6958 if (co_proc_number (&str) == FAIL)
6960 if (!inst.error)
6961 inst.error = BAD_ARGS;
6962 return;
6965 if (skip_past_comma (&str) == FAIL
6966 || cp_opc_expr (&str, 21, 3) == FAIL)
6968 if (!inst.error)
6969 inst.error = BAD_ARGS;
6970 return;
6973 if (skip_past_comma (&str) == FAIL
6974 || reg_required_here (&str, 12) == FAIL)
6976 if (!inst.error)
6977 inst.error = BAD_ARGS;
6978 return;
6981 if (skip_past_comma (&str) == FAIL
6982 || cp_reg_required_here (&str, 16) == FAIL)
6984 if (!inst.error)
6985 inst.error = BAD_ARGS;
6986 return;
6989 if (skip_past_comma (&str) == FAIL
6990 || cp_reg_required_here (&str, 0) == FAIL)
6992 if (!inst.error)
6993 inst.error = BAD_ARGS;
6994 return;
6997 if (skip_past_comma (&str) == SUCCESS)
6999 if (cp_opc_expr (&str, 5, 3) == FAIL)
7001 if (!inst.error)
7002 inst.error = BAD_ARGS;
7003 return;
7007 end_of_line (str);
7010 static void
7011 do_fpa_ctrl (char * str)
7013 /* FP control registers.
7014 Format: <WFS|RFS|WFC|RFC>{cond} Rn */
7016 skip_whitespace (str);
7018 if (reg_required_here (&str, 12) == FAIL)
7020 if (!inst.error)
7021 inst.error = BAD_ARGS;
7022 return;
7025 end_of_line (str);
7028 static void
7029 do_fpa_ldst (char * str)
7031 skip_whitespace (str);
7033 if (fp_reg_required_here (&str, 12) == FAIL)
7035 if (!inst.error)
7036 inst.error = BAD_ARGS;
7037 return;
7040 if (skip_past_comma (&str) == FAIL
7041 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
7043 if (!inst.error)
7044 inst.error = BAD_ARGS;
7045 return;
7048 end_of_line (str);
7051 static void
7052 do_fpa_ldmstm (char * str)
7054 int num_regs;
7056 skip_whitespace (str);
7058 if (fp_reg_required_here (&str, 12) == FAIL)
7060 if (! inst.error)
7061 inst.error = BAD_ARGS;
7062 return;
7065 /* Get Number of registers to transfer. */
7066 if (skip_past_comma (&str) == FAIL
7067 || my_get_expression (&inst.reloc.exp, &str))
7069 if (! inst.error)
7070 inst.error = _("constant expression expected");
7071 return;
7074 if (inst.reloc.exp.X_op != O_constant)
7076 inst.error = _("constant value required for number of registers");
7077 return;
7080 num_regs = inst.reloc.exp.X_add_number;
7082 if (num_regs < 1 || num_regs > 4)
7084 inst.error = _("number of registers must be in the range [1:4]");
7085 return;
7088 switch (num_regs)
7090 case 1:
7091 inst.instruction |= CP_T_X;
7092 break;
7093 case 2:
7094 inst.instruction |= CP_T_Y;
7095 break;
7096 case 3:
7097 inst.instruction |= CP_T_Y | CP_T_X;
7098 break;
7099 case 4:
7100 break;
7101 default:
7102 abort ();
7105 if (inst.instruction & (CP_T_Pre | CP_T_UD)) /* ea/fd format. */
7107 int reg;
7108 int write_back;
7109 int offset;
7111 /* The instruction specified "ea" or "fd", so we can only accept
7112 [Rn]{!}. The instruction does not really support stacking or
7113 unstacking, so we have to emulate these by setting appropriate
7114 bits and offsets. */
7115 if (skip_past_comma (&str) == FAIL
7116 || *str != '[')
7118 if (! inst.error)
7119 inst.error = BAD_ARGS;
7120 return;
7123 str++;
7124 skip_whitespace (str);
7126 if ((reg = reg_required_here (&str, 16)) == FAIL)
7127 return;
7129 skip_whitespace (str);
7131 if (*str != ']')
7133 inst.error = BAD_ARGS;
7134 return;
7137 str++;
7138 if (*str == '!')
7140 write_back = 1;
7141 str++;
7142 if (reg == REG_PC)
7144 inst.error =
7145 _("r15 not allowed as base register with write-back");
7146 return;
7149 else
7150 write_back = 0;
7152 if (inst.instruction & CP_T_Pre)
7154 /* Pre-decrement. */
7155 offset = 3 * num_regs;
7156 if (write_back)
7157 inst.instruction |= CP_T_WB;
7159 else
7161 /* Post-increment. */
7162 if (write_back)
7164 inst.instruction |= CP_T_WB;
7165 offset = 3 * num_regs;
7167 else
7169 /* No write-back, so convert this into a standard pre-increment
7170 instruction -- aesthetically more pleasing. */
7171 inst.instruction |= CP_T_Pre | CP_T_UD;
7172 offset = 0;
7176 inst.instruction |= offset;
7178 else if (skip_past_comma (&str) == FAIL
7179 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
7181 if (! inst.error)
7182 inst.error = BAD_ARGS;
7183 return;
7186 end_of_line (str);
7189 static void
7190 do_fpa_dyadic (char * str)
7192 skip_whitespace (str);
7194 if (fp_reg_required_here (&str, 12) == FAIL)
7196 if (! inst.error)
7197 inst.error = BAD_ARGS;
7198 return;
7201 if (skip_past_comma (&str) == FAIL
7202 || fp_reg_required_here (&str, 16) == FAIL)
7204 if (! inst.error)
7205 inst.error = BAD_ARGS;
7206 return;
7209 if (skip_past_comma (&str) == FAIL
7210 || fp_op2 (&str) == FAIL)
7212 if (! inst.error)
7213 inst.error = BAD_ARGS;
7214 return;
7217 end_of_line (str);
7220 static void
7221 do_fpa_monadic (char * str)
7223 skip_whitespace (str);
7225 if (fp_reg_required_here (&str, 12) == FAIL)
7227 if (! inst.error)
7228 inst.error = BAD_ARGS;
7229 return;
7232 if (skip_past_comma (&str) == FAIL
7233 || fp_op2 (&str) == FAIL)
7235 if (! inst.error)
7236 inst.error = BAD_ARGS;
7237 return;
7240 end_of_line (str);
7243 static void
7244 do_fpa_cmp (char * str)
7246 skip_whitespace (str);
7248 if (fp_reg_required_here (&str, 16) == FAIL)
7250 if (! inst.error)
7251 inst.error = BAD_ARGS;
7252 return;
7255 if (skip_past_comma (&str) == FAIL
7256 || fp_op2 (&str) == FAIL)
7258 if (! inst.error)
7259 inst.error = BAD_ARGS;
7260 return;
7263 end_of_line (str);
7266 static void
7267 do_fpa_from_reg (char * str)
7269 skip_whitespace (str);
7271 if (fp_reg_required_here (&str, 16) == FAIL)
7273 if (! inst.error)
7274 inst.error = BAD_ARGS;
7275 return;
7278 if (skip_past_comma (&str) == FAIL
7279 || reg_required_here (&str, 12) == FAIL)
7281 if (! inst.error)
7282 inst.error = BAD_ARGS;
7283 return;
7286 end_of_line (str);
7289 static void
7290 do_fpa_to_reg (char * str)
7292 skip_whitespace (str);
7294 if (reg_required_here (&str, 12) == FAIL)
7295 return;
7297 if (skip_past_comma (&str) == FAIL
7298 || fp_reg_required_here (&str, 0) == FAIL)
7300 if (! inst.error)
7301 inst.error = BAD_ARGS;
7302 return;
7305 end_of_line (str);
7308 /* Encode a VFP SP register number. */
7310 static void
7311 vfp_sp_encode_reg (int reg, enum vfp_sp_reg_pos pos)
7313 switch (pos)
7315 case VFP_REG_Sd:
7316 inst.instruction |= ((reg >> 1) << 12) | ((reg & 1) << 22);
7317 break;
7319 case VFP_REG_Sn:
7320 inst.instruction |= ((reg >> 1) << 16) | ((reg & 1) << 7);
7321 break;
7323 case VFP_REG_Sm:
7324 inst.instruction |= ((reg >> 1) << 0) | ((reg & 1) << 5);
7325 break;
7327 default:
7328 abort ();
7332 static int
7333 vfp_sp_reg_required_here (char ** str,
7334 enum vfp_sp_reg_pos pos)
7336 int reg;
7337 char * start = *str;
7339 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_SN].htab)) != FAIL)
7341 vfp_sp_encode_reg (reg, pos);
7342 return reg;
7345 /* In the few cases where we might be able to accept something else
7346 this error can be overridden. */
7347 inst.error = _(all_reg_maps[REG_TYPE_SN].expected);
7349 /* Restore the start point. */
7350 *str = start;
7351 return FAIL;
7354 static int
7355 vfp_dp_reg_required_here (char ** str,
7356 enum vfp_dp_reg_pos pos)
7358 int reg;
7359 char * start = *str;
7361 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_DN].htab)) != FAIL)
7363 switch (pos)
7365 case VFP_REG_Dd:
7366 inst.instruction |= reg << 12;
7367 break;
7369 case VFP_REG_Dn:
7370 inst.instruction |= reg << 16;
7371 break;
7373 case VFP_REG_Dm:
7374 inst.instruction |= reg << 0;
7375 break;
7377 default:
7378 abort ();
7380 return reg;
7383 /* In the few cases where we might be able to accept something else
7384 this error can be overridden. */
7385 inst.error = _(all_reg_maps[REG_TYPE_DN].expected);
7387 /* Restore the start point. */
7388 *str = start;
7389 return FAIL;
7392 static void
7393 do_vfp_sp_monadic (char * str)
7395 skip_whitespace (str);
7397 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
7398 return;
7400 if (skip_past_comma (&str) == FAIL
7401 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
7403 if (! inst.error)
7404 inst.error = BAD_ARGS;
7405 return;
7408 end_of_line (str);
7411 static void
7412 do_vfp_dp_monadic (char * str)
7414 skip_whitespace (str);
7416 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
7417 return;
7419 if (skip_past_comma (&str) == FAIL
7420 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
7422 if (! inst.error)
7423 inst.error = BAD_ARGS;
7424 return;
7427 end_of_line (str);
7430 static void
7431 do_vfp_sp_dyadic (char * str)
7433 skip_whitespace (str);
7435 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
7436 return;
7438 if (skip_past_comma (&str) == FAIL
7439 || vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL
7440 || skip_past_comma (&str) == FAIL
7441 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
7443 if (! inst.error)
7444 inst.error = BAD_ARGS;
7445 return;
7448 end_of_line (str);
7451 static void
7452 do_vfp_dp_dyadic (char * str)
7454 skip_whitespace (str);
7456 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
7457 return;
7459 if (skip_past_comma (&str) == FAIL
7460 || vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL
7461 || skip_past_comma (&str) == FAIL
7462 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
7464 if (! inst.error)
7465 inst.error = BAD_ARGS;
7466 return;
7469 end_of_line (str);
7472 static void
7473 do_vfp_reg_from_sp (char * str)
7475 skip_whitespace (str);
7477 if (reg_required_here (&str, 12) == FAIL)
7478 return;
7480 if (skip_past_comma (&str) == FAIL
7481 || vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL)
7483 if (! inst.error)
7484 inst.error = BAD_ARGS;
7485 return;
7488 end_of_line (str);
7491 /* Parse a VFP register list. If the string is invalid return FAIL.
7492 Otherwise return the number of registers, and set PBASE to the first
7493 register. Double precision registers are matched if DP is nonzero. */
7495 static int
7496 vfp_parse_reg_list (char **str, int *pbase, int dp)
7498 int base_reg;
7499 int new_base;
7500 int regtype;
7501 int max_regs;
7502 int count = 0;
7503 int warned = 0;
7504 unsigned long mask = 0;
7505 int i;
7507 if (**str != '{')
7508 return FAIL;
7510 (*str)++;
7511 skip_whitespace (*str);
7513 if (dp)
7515 regtype = REG_TYPE_DN;
7516 max_regs = 16;
7518 else
7520 regtype = REG_TYPE_SN;
7521 max_regs = 32;
7524 base_reg = max_regs;
7528 new_base = arm_reg_parse (str, all_reg_maps[regtype].htab);
7529 if (new_base == FAIL)
7531 inst.error = _(all_reg_maps[regtype].expected);
7532 return FAIL;
7535 if (new_base < base_reg)
7536 base_reg = new_base;
7538 if (mask & (1 << new_base))
7540 inst.error = _("invalid register list");
7541 return FAIL;
7544 if ((mask >> new_base) != 0 && ! warned)
7546 as_tsktsk (_("register list not in ascending order"));
7547 warned = 1;
7550 mask |= 1 << new_base;
7551 count++;
7553 skip_whitespace (*str);
7555 if (**str == '-') /* We have the start of a range expression */
7557 int high_range;
7559 (*str)++;
7561 if ((high_range
7562 = arm_reg_parse (str, all_reg_maps[regtype].htab))
7563 == FAIL)
7565 inst.error = _(all_reg_maps[regtype].expected);
7566 return FAIL;
7569 if (high_range <= new_base)
7571 inst.error = _("register range not in ascending order");
7572 return FAIL;
7575 for (new_base++; new_base <= high_range; new_base++)
7577 if (mask & (1 << new_base))
7579 inst.error = _("invalid register list");
7580 return FAIL;
7583 mask |= 1 << new_base;
7584 count++;
7588 while (skip_past_comma (str) != FAIL);
7590 (*str)++;
7592 /* Sanity check -- should have raised a parse error above. */
7593 if (count == 0 || count > max_regs)
7594 abort ();
7596 *pbase = base_reg;
7598 /* Final test -- the registers must be consecutive. */
7599 mask >>= base_reg;
7600 for (i = 0; i < count; i++)
7602 if ((mask & (1u << i)) == 0)
7604 inst.error = _("non-contiguous register range");
7605 return FAIL;
7609 return count;
7612 static void
7613 do_vfp_reg2_from_sp2 (char * str)
7615 int reg;
7617 skip_whitespace (str);
7619 if (reg_required_here (&str, 12) == FAIL
7620 || skip_past_comma (&str) == FAIL
7621 || reg_required_here (&str, 16) == FAIL
7622 || skip_past_comma (&str) == FAIL)
7624 if (! inst.error)
7625 inst.error = BAD_ARGS;
7626 return;
7629 /* We require exactly two consecutive SP registers. */
7630 if (vfp_parse_reg_list (&str, &reg, 0) != 2)
7632 if (! inst.error)
7633 inst.error = _("only two consecutive VFP SP registers allowed here");
7635 vfp_sp_encode_reg (reg, VFP_REG_Sm);
7637 end_of_line (str);
7640 static void
7641 do_vfp_sp_from_reg (char * str)
7643 skip_whitespace (str);
7645 if (vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL)
7646 return;
7648 if (skip_past_comma (&str) == FAIL
7649 || reg_required_here (&str, 12) == FAIL)
7651 if (! inst.error)
7652 inst.error = BAD_ARGS;
7653 return;
7656 end_of_line (str);
7659 static void
7660 do_vfp_sp2_from_reg2 (char * str)
7662 int reg;
7664 skip_whitespace (str);
7666 /* We require exactly two consecutive SP registers. */
7667 if (vfp_parse_reg_list (&str, &reg, 0) != 2)
7669 if (! inst.error)
7670 inst.error = _("only two consecutive VFP SP registers allowed here");
7672 vfp_sp_encode_reg (reg, VFP_REG_Sm);
7674 if (skip_past_comma (&str) == FAIL
7675 || reg_required_here (&str, 12) == FAIL
7676 || skip_past_comma (&str) == FAIL
7677 || reg_required_here (&str, 16) == FAIL)
7679 if (! inst.error)
7680 inst.error = BAD_ARGS;
7681 return;
7684 end_of_line (str);
7687 static void
7688 do_vfp_reg_from_dp (char * str)
7690 skip_whitespace (str);
7692 if (reg_required_here (&str, 12) == FAIL)
7693 return;
7695 if (skip_past_comma (&str) == FAIL
7696 || vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL)
7698 if (! inst.error)
7699 inst.error = BAD_ARGS;
7700 return;
7703 end_of_line (str);
7706 static void
7707 do_vfp_reg2_from_dp (char * str)
7709 skip_whitespace (str);
7711 if (reg_required_here (&str, 12) == FAIL)
7712 return;
7714 if (skip_past_comma (&str) == FAIL
7715 || reg_required_here (&str, 16) == FAIL
7716 || skip_past_comma (&str) == FAIL
7717 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
7719 if (! inst.error)
7720 inst.error = BAD_ARGS;
7721 return;
7724 end_of_line (str);
7727 static void
7728 do_vfp_dp_from_reg (char * str)
7730 skip_whitespace (str);
7732 if (vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL)
7733 return;
7735 if (skip_past_comma (&str) == FAIL
7736 || reg_required_here (&str, 12) == FAIL)
7738 if (! inst.error)
7739 inst.error = BAD_ARGS;
7740 return;
7743 end_of_line (str);
7746 static void
7747 do_vfp_dp_from_reg2 (char * str)
7749 skip_whitespace (str);
7751 if (vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
7752 return;
7754 if (skip_past_comma (&str) == FAIL
7755 || reg_required_here (&str, 12) == FAIL
7756 || skip_past_comma (&str) == FAIL
7757 || reg_required_here (&str, 16) == FAIL)
7759 if (! inst.error)
7760 inst.error = BAD_ARGS;
7761 return;
7764 end_of_line (str);
7767 static const struct vfp_reg *
7768 vfp_psr_parse (char ** str)
7770 char *start = *str;
7771 char c;
7772 char *p;
7773 const struct vfp_reg *vreg;
7775 p = start;
7777 /* Find the end of the current token. */
7780 c = *p++;
7782 while (ISALPHA (c));
7784 /* Mark it. */
7785 *--p = 0;
7787 for (vreg = vfp_regs + 0;
7788 vreg < vfp_regs + sizeof (vfp_regs) / sizeof (struct vfp_reg);
7789 vreg++)
7791 if (streq (start, vreg->name))
7793 *p = c;
7794 *str = p;
7795 return vreg;
7799 *p = c;
7800 return NULL;
7803 static int
7804 vfp_psr_required_here (char ** str)
7806 char *start = *str;
7807 const struct vfp_reg *vreg;
7809 vreg = vfp_psr_parse (str);
7811 if (vreg)
7813 inst.instruction |= vreg->regno;
7814 return SUCCESS;
7817 inst.error = _("VFP system register expected");
7819 *str = start;
7820 return FAIL;
7823 static void
7824 do_vfp_reg_from_ctrl (char * str)
7826 skip_whitespace (str);
7828 if (reg_required_here (&str, 12) == FAIL)
7829 return;
7831 if (skip_past_comma (&str) == FAIL
7832 || vfp_psr_required_here (&str) == FAIL)
7834 if (! inst.error)
7835 inst.error = BAD_ARGS;
7836 return;
7839 end_of_line (str);
7842 static void
7843 do_vfp_ctrl_from_reg (char * str)
7845 skip_whitespace (str);
7847 if (vfp_psr_required_here (&str) == FAIL)
7848 return;
7850 if (skip_past_comma (&str) == FAIL
7851 || reg_required_here (&str, 12) == FAIL)
7853 if (! inst.error)
7854 inst.error = BAD_ARGS;
7855 return;
7858 end_of_line (str);
7861 static void
7862 do_vfp_sp_ldst (char * str)
7864 skip_whitespace (str);
7866 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
7868 if (!inst.error)
7869 inst.error = BAD_ARGS;
7870 return;
7873 if (skip_past_comma (&str) == FAIL
7874 || cp_address_required_here (&str, CP_NO_WB) == FAIL)
7876 if (!inst.error)
7877 inst.error = BAD_ARGS;
7878 return;
7881 end_of_line (str);
7884 static void
7885 do_vfp_dp_ldst (char * str)
7887 skip_whitespace (str);
7889 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
7891 if (!inst.error)
7892 inst.error = BAD_ARGS;
7893 return;
7896 if (skip_past_comma (&str) == FAIL
7897 || cp_address_required_here (&str, CP_NO_WB) == FAIL)
7899 if (!inst.error)
7900 inst.error = BAD_ARGS;
7901 return;
7904 end_of_line (str);
7908 static void
7909 vfp_sp_ldstm (char * str, enum vfp_ldstm_type ldstm_type)
7911 int count;
7912 int reg;
7914 skip_whitespace (str);
7916 if (reg_required_here (&str, 16) == FAIL)
7917 return;
7919 skip_whitespace (str);
7921 if (*str == '!')
7923 inst.instruction |= WRITE_BACK;
7924 str++;
7926 else if (ldstm_type != VFP_LDSTMIA)
7928 inst.error = _("this addressing mode requires base-register writeback");
7929 return;
7932 if (skip_past_comma (&str) == FAIL
7933 || (count = vfp_parse_reg_list (&str, &reg, 0)) == FAIL)
7935 if (!inst.error)
7936 inst.error = BAD_ARGS;
7937 return;
7939 vfp_sp_encode_reg (reg, VFP_REG_Sd);
7941 inst.instruction |= count;
7942 end_of_line (str);
7945 static void
7946 vfp_dp_ldstm (char * str, enum vfp_ldstm_type ldstm_type)
7948 int count;
7949 int reg;
7951 skip_whitespace (str);
7953 if (reg_required_here (&str, 16) == FAIL)
7954 return;
7956 skip_whitespace (str);
7958 if (*str == '!')
7960 inst.instruction |= WRITE_BACK;
7961 str++;
7963 else if (ldstm_type != VFP_LDSTMIA && ldstm_type != VFP_LDSTMIAX)
7965 inst.error = _("this addressing mode requires base-register writeback");
7966 return;
7969 if (skip_past_comma (&str) == FAIL
7970 || (count = vfp_parse_reg_list (&str, &reg, 1)) == FAIL)
7972 if (!inst.error)
7973 inst.error = BAD_ARGS;
7974 return;
7977 count <<= 1;
7978 if (ldstm_type == VFP_LDSTMIAX || ldstm_type == VFP_LDSTMDBX)
7979 count += 1;
7981 inst.instruction |= (reg << 12) | count;
7982 end_of_line (str);
7985 static void
7986 do_vfp_sp_ldstmia (char * str)
7988 vfp_sp_ldstm (str, VFP_LDSTMIA);
7991 static void
7992 do_vfp_sp_ldstmdb (char * str)
7994 vfp_sp_ldstm (str, VFP_LDSTMDB);
7997 static void
7998 do_vfp_dp_ldstmia (char * str)
8000 vfp_dp_ldstm (str, VFP_LDSTMIA);
8003 static void
8004 do_vfp_dp_ldstmdb (char * str)
8006 vfp_dp_ldstm (str, VFP_LDSTMDB);
8009 static void
8010 do_vfp_xp_ldstmia (char *str)
8012 vfp_dp_ldstm (str, VFP_LDSTMIAX);
8015 static void
8016 do_vfp_xp_ldstmdb (char * str)
8018 vfp_dp_ldstm (str, VFP_LDSTMDBX);
8021 static void
8022 do_vfp_sp_compare_z (char * str)
8024 skip_whitespace (str);
8026 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
8028 if (!inst.error)
8029 inst.error = BAD_ARGS;
8030 return;
8033 end_of_line (str);
8036 static void
8037 do_vfp_dp_compare_z (char * str)
8039 skip_whitespace (str);
8041 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
8043 if (!inst.error)
8044 inst.error = BAD_ARGS;
8045 return;
8048 end_of_line (str);
8051 static void
8052 do_vfp_dp_sp_cvt (char * str)
8054 skip_whitespace (str);
8056 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
8057 return;
8059 if (skip_past_comma (&str) == FAIL
8060 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
8062 if (! inst.error)
8063 inst.error = BAD_ARGS;
8064 return;
8067 end_of_line (str);
8070 static void
8071 do_vfp_sp_dp_cvt (char * str)
8073 skip_whitespace (str);
8075 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
8076 return;
8078 if (skip_past_comma (&str) == FAIL
8079 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
8081 if (! inst.error)
8082 inst.error = BAD_ARGS;
8083 return;
8086 end_of_line (str);
8089 /* Thumb specific routines. */
8091 /* Parse an add or subtract instruction, SUBTRACT is non-zero if the opcode
8092 was SUB. */
8094 static void
8095 thumb_add_sub (char * str, int subtract)
8097 int Rd, Rs, Rn = FAIL;
8099 skip_whitespace (str);
8101 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
8102 || skip_past_comma (&str) == FAIL)
8104 if (! inst.error)
8105 inst.error = BAD_ARGS;
8106 return;
8109 if (is_immediate_prefix (*str))
8111 Rs = Rd;
8112 str++;
8113 if (my_get_expression (&inst.reloc.exp, &str))
8114 return;
8116 else
8118 if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
8119 return;
8121 if (skip_past_comma (&str) == FAIL)
8123 /* Two operand format, shuffle the registers
8124 and pretend there are 3. */
8125 Rn = Rs;
8126 Rs = Rd;
8128 else if (is_immediate_prefix (*str))
8130 str++;
8131 if (my_get_expression (&inst.reloc.exp, &str))
8132 return;
8134 else if ((Rn = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
8135 return;
8138 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
8139 for the latter case, EXPR contains the immediate that was found. */
8140 if (Rn != FAIL)
8142 /* All register format. */
8143 if (Rd > 7 || Rs > 7 || Rn > 7)
8145 if (Rs != Rd)
8147 inst.error = _("dest and source1 must be the same register");
8148 return;
8151 /* Can't do this for SUB. */
8152 if (subtract)
8154 inst.error = _("subtract valid only on lo regs");
8155 return;
8158 inst.instruction = (T_OPCODE_ADD_HI
8159 | (Rd > 7 ? THUMB_H1 : 0)
8160 | (Rn > 7 ? THUMB_H2 : 0));
8161 inst.instruction |= (Rd & 7) | ((Rn & 7) << 3);
8163 else
8165 inst.instruction = subtract ? T_OPCODE_SUB_R3 : T_OPCODE_ADD_R3;
8166 inst.instruction |= Rd | (Rs << 3) | (Rn << 6);
8169 else
8171 /* Immediate expression, now things start to get nasty. */
8173 /* First deal with HI regs, only very restricted cases allowed:
8174 Adjusting SP, and using PC or SP to get an address. */
8175 if ((Rd > 7 && (Rd != REG_SP || Rs != REG_SP))
8176 || (Rs > 7 && Rs != REG_SP && Rs != REG_PC))
8178 inst.error = _("invalid Hi register with immediate");
8179 return;
8182 if (inst.reloc.exp.X_op != O_constant)
8184 /* Value isn't known yet, all we can do is store all the fragments
8185 we know about in the instruction and let the reloc hacking
8186 work it all out. */
8187 inst.instruction = (subtract ? 0x8000 : 0) | (Rd << 4) | Rs;
8188 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
8190 else
8192 int offset = inst.reloc.exp.X_add_number;
8194 if (subtract)
8195 offset = - offset;
8197 if (offset < 0)
8199 offset = - offset;
8200 subtract = 1;
8202 /* Quick check, in case offset is MIN_INT. */
8203 if (offset < 0)
8205 inst.error = _("immediate value out of range");
8206 return;
8209 /* Note - you cannot convert a subtract of 0 into an
8210 add of 0 because the carry flag is set differently. */
8211 else if (offset > 0)
8212 subtract = 0;
8214 if (Rd == REG_SP)
8216 if (offset & ~0x1fc)
8218 inst.error = _("invalid immediate value for stack adjust");
8219 return;
8221 inst.instruction = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
8222 inst.instruction |= offset >> 2;
8224 else if (Rs == REG_PC || Rs == REG_SP)
8226 if (subtract
8227 || (offset & ~0x3fc))
8229 inst.error = _("invalid immediate for address calculation");
8230 return;
8232 inst.instruction = (Rs == REG_PC ? T_OPCODE_ADD_PC
8233 : T_OPCODE_ADD_SP);
8234 inst.instruction |= (Rd << 8) | (offset >> 2);
8236 else if (Rs == Rd)
8238 if (offset & ~0xff)
8240 inst.error = _("immediate value out of range");
8241 return;
8243 inst.instruction = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
8244 inst.instruction |= (Rd << 8) | offset;
8246 else
8248 if (offset & ~0x7)
8250 inst.error = _("immediate value out of range");
8251 return;
8253 inst.instruction = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
8254 inst.instruction |= Rd | (Rs << 3) | (offset << 6);
8259 end_of_line (str);
8262 static void
8263 thumb_shift (char * str, int shift)
8265 int Rd, Rs, Rn = FAIL;
8267 skip_whitespace (str);
8269 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
8270 || skip_past_comma (&str) == FAIL)
8272 if (! inst.error)
8273 inst.error = BAD_ARGS;
8274 return;
8277 if (is_immediate_prefix (*str))
8279 /* Two operand immediate format, set Rs to Rd. */
8280 Rs = Rd;
8281 str ++;
8282 if (my_get_expression (&inst.reloc.exp, &str))
8283 return;
8285 else
8287 if ((Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
8288 return;
8290 if (skip_past_comma (&str) == FAIL)
8292 /* Two operand format, shuffle the registers
8293 and pretend there are 3. */
8294 Rn = Rs;
8295 Rs = Rd;
8297 else if (is_immediate_prefix (*str))
8299 str++;
8300 if (my_get_expression (&inst.reloc.exp, &str))
8301 return;
8303 else if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
8304 return;
8307 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
8308 for the latter case, EXPR contains the immediate that was found. */
8310 if (Rn != FAIL)
8312 if (Rs != Rd)
8314 inst.error = _("source1 and dest must be same register");
8315 return;
8318 switch (shift)
8320 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_R; break;
8321 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_R; break;
8322 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_R; break;
8325 inst.instruction |= Rd | (Rn << 3);
8327 else
8329 switch (shift)
8331 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_I; break;
8332 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_I; break;
8333 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_I; break;
8336 if (inst.reloc.exp.X_op != O_constant)
8338 /* Value isn't known yet, create a dummy reloc and let reloc
8339 hacking fix it up. */
8340 inst.reloc.type = BFD_RELOC_ARM_THUMB_SHIFT;
8342 else
8344 unsigned shift_value = inst.reloc.exp.X_add_number;
8346 if (shift_value > 32 || (shift_value == 32 && shift == THUMB_LSL))
8348 inst.error = _("invalid immediate for shift");
8349 return;
8352 /* Shifts of zero are handled by converting to LSL. */
8353 if (shift_value == 0)
8354 inst.instruction = T_OPCODE_LSL_I;
8356 /* Shifts of 32 are encoded as a shift of zero. */
8357 if (shift_value == 32)
8358 shift_value = 0;
8360 inst.instruction |= shift_value << 6;
8363 inst.instruction |= Rd | (Rs << 3);
8366 end_of_line (str);
8369 static void
8370 thumb_load_store (char * str, int load_store, int size)
8372 int Rd, Rb, Ro = FAIL;
8374 skip_whitespace (str);
8376 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
8377 || skip_past_comma (&str) == FAIL)
8379 if (! inst.error)
8380 inst.error = BAD_ARGS;
8381 return;
8384 if (*str == '[')
8386 str++;
8387 if ((Rb = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
8388 return;
8390 if (skip_past_comma (&str) != FAIL)
8392 if (is_immediate_prefix (*str))
8394 str++;
8395 if (my_get_expression (&inst.reloc.exp, &str))
8396 return;
8398 else if ((Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
8399 return;
8401 else
8403 inst.reloc.exp.X_op = O_constant;
8404 inst.reloc.exp.X_add_number = 0;
8407 if (*str != ']')
8409 inst.error = _("expected ']'");
8410 return;
8412 str++;
8414 else if (*str == '=')
8416 if (load_store != THUMB_LOAD)
8418 inst.error = _("invalid pseudo operation");
8419 return;
8422 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
8423 str++;
8425 skip_whitespace (str);
8427 if (my_get_expression (& inst.reloc.exp, & str))
8428 return;
8430 end_of_line (str);
8432 if ( inst.reloc.exp.X_op != O_constant
8433 && inst.reloc.exp.X_op != O_symbol)
8435 inst.error = "Constant expression expected";
8436 return;
8439 if (inst.reloc.exp.X_op == O_constant
8440 && ((inst.reloc.exp.X_add_number & ~0xFF) == 0))
8442 /* This can be done with a mov instruction. */
8444 inst.instruction = T_OPCODE_MOV_I8 | (Rd << 8);
8445 inst.instruction |= inst.reloc.exp.X_add_number;
8446 return;
8449 /* Insert into literal pool. */
8450 if (add_to_lit_pool () == FAIL)
8452 if (!inst.error)
8453 inst.error = "literal pool insertion failed";
8454 return;
8457 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
8458 inst.reloc.pc_rel = 1;
8459 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
8460 /* Adjust ARM pipeline offset to Thumb. */
8461 inst.reloc.exp.X_add_number += 4;
8463 return;
8465 else
8467 if (my_get_expression (&inst.reloc.exp, &str))
8468 return;
8470 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
8471 inst.reloc.pc_rel = 1;
8472 inst.reloc.exp.X_add_number -= 4; /* Pipeline offset. */
8473 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
8474 end_of_line (str);
8475 return;
8478 if (Rb == REG_PC || Rb == REG_SP)
8480 if (size != THUMB_WORD)
8482 inst.error = _("byte or halfword not valid for base register");
8483 return;
8485 else if (Rb == REG_PC && load_store != THUMB_LOAD)
8487 inst.error = _("r15 based store not allowed");
8488 return;
8490 else if (Ro != FAIL)
8492 inst.error = _("invalid base register for register offset");
8493 return;
8496 if (Rb == REG_PC)
8497 inst.instruction = T_OPCODE_LDR_PC;
8498 else if (load_store == THUMB_LOAD)
8499 inst.instruction = T_OPCODE_LDR_SP;
8500 else
8501 inst.instruction = T_OPCODE_STR_SP;
8503 inst.instruction |= Rd << 8;
8504 if (inst.reloc.exp.X_op == O_constant)
8506 unsigned offset = inst.reloc.exp.X_add_number;
8508 if (offset & ~0x3fc)
8510 inst.error = _("invalid offset");
8511 return;
8514 inst.instruction |= offset >> 2;
8516 else
8517 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
8519 else if (Rb > 7)
8521 inst.error = _("invalid base register in load/store");
8522 return;
8524 else if (Ro == FAIL)
8526 /* Immediate offset. */
8527 if (size == THUMB_WORD)
8528 inst.instruction = (load_store == THUMB_LOAD
8529 ? T_OPCODE_LDR_IW : T_OPCODE_STR_IW);
8530 else if (size == THUMB_HALFWORD)
8531 inst.instruction = (load_store == THUMB_LOAD
8532 ? T_OPCODE_LDR_IH : T_OPCODE_STR_IH);
8533 else
8534 inst.instruction = (load_store == THUMB_LOAD
8535 ? T_OPCODE_LDR_IB : T_OPCODE_STR_IB);
8537 inst.instruction |= Rd | (Rb << 3);
8539 if (inst.reloc.exp.X_op == O_constant)
8541 unsigned offset = inst.reloc.exp.X_add_number;
8543 if (offset & ~(0x1f << size))
8545 inst.error = _("invalid offset");
8546 return;
8548 inst.instruction |= (offset >> size) << 6;
8550 else
8551 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
8553 else
8555 /* Register offset. */
8556 if (size == THUMB_WORD)
8557 inst.instruction = (load_store == THUMB_LOAD
8558 ? T_OPCODE_LDR_RW : T_OPCODE_STR_RW);
8559 else if (size == THUMB_HALFWORD)
8560 inst.instruction = (load_store == THUMB_LOAD
8561 ? T_OPCODE_LDR_RH : T_OPCODE_STR_RH);
8562 else
8563 inst.instruction = (load_store == THUMB_LOAD
8564 ? T_OPCODE_LDR_RB : T_OPCODE_STR_RB);
8566 inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
8569 end_of_line (str);
8572 /* A register must be given at this point.
8574 Shift is the place to put it in inst.instruction.
8576 Restores input start point on err.
8577 Returns the reg#, or FAIL. */
8579 static int
8580 mav_reg_required_here (char ** str, int shift, enum arm_reg_type regtype)
8582 int reg;
8583 char *start = *str;
8585 if ((reg = arm_reg_parse (str, all_reg_maps[regtype].htab)) != FAIL)
8587 if (shift >= 0)
8588 inst.instruction |= reg << shift;
8590 return reg;
8593 /* Restore the start point. */
8594 *str = start;
8596 /* Try generic coprocessor name if applicable. */
8597 if (regtype == REG_TYPE_MVF ||
8598 regtype == REG_TYPE_MVD ||
8599 regtype == REG_TYPE_MVFX ||
8600 regtype == REG_TYPE_MVDX)
8602 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_CN].htab)) != FAIL)
8604 if (shift >= 0)
8605 inst.instruction |= reg << shift;
8607 return reg;
8610 /* Restore the start point. */
8611 *str = start;
8614 /* In the few cases where we might be able to accept something else
8615 this error can be overridden. */
8616 inst.error = _(all_reg_maps[regtype].expected);
8618 return FAIL;
8621 /* Cirrus Maverick Instructions. */
8623 /* Isnsn like "foo X,Y". */
8625 static void
8626 do_mav_binops (char * str,
8627 int mode,
8628 enum arm_reg_type reg0,
8629 enum arm_reg_type reg1)
8631 int shift0, shift1;
8633 shift0 = mode & 0xff;
8634 shift1 = (mode >> 8) & 0xff;
8636 skip_whitespace (str);
8638 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
8639 || skip_past_comma (&str) == FAIL
8640 || mav_reg_required_here (&str, shift1, reg1) == FAIL)
8642 if (!inst.error)
8643 inst.error = BAD_ARGS;
8645 else
8646 end_of_line (str);
8649 /* Isnsn like "foo X,Y,Z". */
8651 static void
8652 do_mav_triple (char * str,
8653 int mode,
8654 enum arm_reg_type reg0,
8655 enum arm_reg_type reg1,
8656 enum arm_reg_type reg2)
8658 int shift0, shift1, shift2;
8660 shift0 = mode & 0xff;
8661 shift1 = (mode >> 8) & 0xff;
8662 shift2 = (mode >> 16) & 0xff;
8664 skip_whitespace (str);
8666 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
8667 || skip_past_comma (&str) == FAIL
8668 || mav_reg_required_here (&str, shift1, reg1) == FAIL
8669 || skip_past_comma (&str) == FAIL
8670 || mav_reg_required_here (&str, shift2, reg2) == FAIL)
8672 if (!inst.error)
8673 inst.error = BAD_ARGS;
8675 else
8676 end_of_line (str);
8679 /* Wrapper functions. */
8681 static void
8682 do_mav_binops_1a (char * str)
8684 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVF);
8687 static void
8688 do_mav_binops_1b (char * str)
8690 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVD);
8693 static void
8694 do_mav_binops_1c (char * str)
8696 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVDX);
8699 static void
8700 do_mav_binops_1d (char * str)
8702 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVF);
8705 static void
8706 do_mav_binops_1e (char * str)
8708 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVD);
8711 static void
8712 do_mav_binops_1f (char * str)
8714 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVF);
8717 static void
8718 do_mav_binops_1g (char * str)
8720 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVD);
8723 static void
8724 do_mav_binops_1h (char * str)
8726 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVFX);
8729 static void
8730 do_mav_binops_1i (char * str)
8732 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVFX);
8735 static void
8736 do_mav_binops_1j (char * str)
8738 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVDX);
8741 static void
8742 do_mav_binops_1k (char * str)
8744 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVDX);
8747 static void
8748 do_mav_binops_1l (char * str)
8750 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVF);
8753 static void
8754 do_mav_binops_1m (char * str)
8756 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVD);
8759 static void
8760 do_mav_binops_1n (char * str)
8762 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVFX);
8765 static void
8766 do_mav_binops_1o (char * str)
8768 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVDX, REG_TYPE_MVDX);
8771 static void
8772 do_mav_binops_2a (char * str)
8774 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVF, REG_TYPE_RN);
8777 static void
8778 do_mav_binops_2b (char * str)
8780 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVD, REG_TYPE_RN);
8783 static void
8784 do_mav_binops_2c (char * str)
8786 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVDX, REG_TYPE_RN);
8789 static void
8790 do_mav_binops_3a (char * str)
8792 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVAX, REG_TYPE_MVFX);
8795 static void
8796 do_mav_binops_3b (char * str)
8798 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVFX, REG_TYPE_MVAX);
8801 static void
8802 do_mav_binops_3c (char * str)
8804 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVAX, REG_TYPE_MVDX);
8807 static void
8808 do_mav_binops_3d (char * str)
8810 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVDX, REG_TYPE_MVAX);
8813 static void
8814 do_mav_triple_4a (char * str)
8816 do_mav_triple (str, MAV_MODE4, REG_TYPE_MVFX, REG_TYPE_MVFX, REG_TYPE_RN);
8819 static void
8820 do_mav_triple_4b (char * str)
8822 do_mav_triple (str, MAV_MODE4, REG_TYPE_MVDX, REG_TYPE_MVDX, REG_TYPE_RN);
8825 static void
8826 do_mav_triple_5a (char * str)
8828 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVF, REG_TYPE_MVF);
8831 static void
8832 do_mav_triple_5b (char * str)
8834 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVD, REG_TYPE_MVD);
8837 static void
8838 do_mav_triple_5c (char * str)
8840 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVFX, REG_TYPE_MVFX);
8843 static void
8844 do_mav_triple_5d (char * str)
8846 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVDX, REG_TYPE_MVDX);
8849 static void
8850 do_mav_triple_5e (char * str)
8852 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVF, REG_TYPE_MVF, REG_TYPE_MVF);
8855 static void
8856 do_mav_triple_5f (char * str)
8858 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVD, REG_TYPE_MVD, REG_TYPE_MVD);
8861 static void
8862 do_mav_triple_5g (char * str)
8864 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVFX, REG_TYPE_MVFX, REG_TYPE_MVFX);
8867 static void
8868 do_mav_triple_5h (char * str)
8870 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVDX, REG_TYPE_MVDX, REG_TYPE_MVDX);
8873 /* Isnsn like "foo W,X,Y,Z".
8874 where W=MVAX[0:3] and X,Y,Z=MVFX[0:15]. */
8876 static void
8877 do_mav_quad (char * str,
8878 int mode,
8879 enum arm_reg_type reg0,
8880 enum arm_reg_type reg1,
8881 enum arm_reg_type reg2,
8882 enum arm_reg_type reg3)
8884 int shift0, shift1, shift2, shift3;
8886 shift0= mode & 0xff;
8887 shift1 = (mode >> 8) & 0xff;
8888 shift2 = (mode >> 16) & 0xff;
8889 shift3 = (mode >> 24) & 0xff;
8891 skip_whitespace (str);
8893 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
8894 || skip_past_comma (&str) == FAIL
8895 || mav_reg_required_here (&str, shift1, reg1) == FAIL
8896 || skip_past_comma (&str) == FAIL
8897 || mav_reg_required_here (&str, shift2, reg2) == FAIL
8898 || skip_past_comma (&str) == FAIL
8899 || mav_reg_required_here (&str, shift3, reg3) == FAIL)
8901 if (!inst.error)
8902 inst.error = BAD_ARGS;
8904 else
8905 end_of_line (str);
8908 static void
8909 do_mav_quad_6a (char * str)
8911 do_mav_quad (str, MAV_MODE6, REG_TYPE_MVAX, REG_TYPE_MVFX, REG_TYPE_MVFX,
8912 REG_TYPE_MVFX);
8915 static void
8916 do_mav_quad_6b (char * str)
8918 do_mav_quad (str, MAV_MODE6, REG_TYPE_MVAX, REG_TYPE_MVAX, REG_TYPE_MVFX,
8919 REG_TYPE_MVFX);
8922 /* cfmvsc32<cond> DSPSC,MVDX[15:0]. */
8923 static void
8924 do_mav_dspsc_1 (char * str)
8926 skip_whitespace (str);
8928 /* cfmvsc32. */
8929 if (mav_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL
8930 || skip_past_comma (&str) == FAIL
8931 || mav_reg_required_here (&str, 12, REG_TYPE_MVDX) == FAIL)
8933 if (!inst.error)
8934 inst.error = BAD_ARGS;
8936 return;
8939 end_of_line (str);
8942 /* cfmv32sc<cond> MVDX[15:0],DSPSC. */
8943 static void
8944 do_mav_dspsc_2 (char * str)
8946 skip_whitespace (str);
8948 /* cfmv32sc. */
8949 if (mav_reg_required_here (&str, 12, REG_TYPE_MVDX) == FAIL
8950 || skip_past_comma (&str) == FAIL
8951 || mav_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL)
8953 if (!inst.error)
8954 inst.error = BAD_ARGS;
8956 return;
8959 end_of_line (str);
8962 /* Maverick shift immediate instructions.
8963 cfsh32<cond> MVFX[15:0],MVFX[15:0],Shift[6:0].
8964 cfsh64<cond> MVDX[15:0],MVDX[15:0],Shift[6:0]. */
8966 static void
8967 do_mav_shift (char * str,
8968 enum arm_reg_type reg0,
8969 enum arm_reg_type reg1)
8971 int error;
8972 int imm, neg = 0;
8974 skip_whitespace (str);
8976 error = 0;
8978 if (mav_reg_required_here (&str, 12, reg0) == FAIL
8979 || skip_past_comma (&str) == FAIL
8980 || mav_reg_required_here (&str, 16, reg1) == FAIL
8981 || skip_past_comma (&str) == FAIL)
8983 if (!inst.error)
8984 inst.error = BAD_ARGS;
8985 return;
8988 /* Calculate the immediate operand.
8989 The operand is a 7bit signed number. */
8990 skip_whitespace (str);
8992 if (*str == '#')
8993 ++str;
8995 if (!ISDIGIT (*str) && *str != '-')
8997 inst.error = _("expecting immediate, 7bit operand");
8998 return;
9001 if (*str == '-')
9003 neg = 1;
9004 ++str;
9007 for (imm = 0; *str && ISDIGIT (*str); ++str)
9008 imm = imm * 10 + *str - '0';
9010 if (imm > 64)
9012 inst.error = _("immediate out of range");
9013 return;
9016 /* Make negative imm's into 7bit signed numbers. */
9017 if (neg)
9019 imm = -imm;
9020 imm &= 0x0000007f;
9023 /* Bits 0-3 of the insn should have bits 0-3 of the immediate.
9024 Bits 5-7 of the insn should have bits 4-6 of the immediate.
9025 Bit 4 should be 0. */
9026 imm = (imm & 0xf) | ((imm & 0x70) << 1);
9028 inst.instruction |= imm;
9029 end_of_line (str);
9032 static void
9033 do_mav_shift_1 (char * str)
9035 do_mav_shift (str, REG_TYPE_MVFX, REG_TYPE_MVFX);
9038 static void
9039 do_mav_shift_2 (char * str)
9041 do_mav_shift (str, REG_TYPE_MVDX, REG_TYPE_MVDX);
9044 static int
9045 mav_parse_offset (char ** str, int * negative)
9047 char * p = *str;
9048 int offset;
9050 *negative = 0;
9052 skip_whitespace (p);
9054 if (*p == '#')
9055 ++p;
9057 if (*p == '-')
9059 *negative = 1;
9060 ++p;
9063 if (!ISDIGIT (*p))
9065 inst.error = _("offset expected");
9066 return 0;
9069 for (offset = 0; *p && ISDIGIT (*p); ++p)
9070 offset = offset * 10 + *p - '0';
9072 if (offset > 0x3fc)
9074 inst.error = _("offset out of range");
9075 return 0;
9077 if (offset & 0x3)
9079 inst.error = _("offset not a multiple of 4");
9080 return 0;
9083 *str = p;
9085 return *negative ? -offset : offset;
9088 /* Maverick load/store instructions.
9089 <insn><cond> CRd,[Rn,<offset>]{!}.
9090 <insn><cond> CRd,[Rn],<offset>. */
9092 static void
9093 do_mav_ldst (char * str, enum arm_reg_type reg0)
9095 int offset, negative;
9097 skip_whitespace (str);
9099 if (mav_reg_required_here (&str, 12, reg0) == FAIL
9100 || skip_past_comma (&str) == FAIL
9101 || *str++ != '['
9102 || reg_required_here (&str, 16) == FAIL)
9103 goto fail_ldst;
9105 if (skip_past_comma (&str) == SUCCESS)
9107 /* You are here: "<offset>]{!}". */
9108 inst.instruction |= PRE_INDEX;
9110 offset = mav_parse_offset (&str, &negative);
9112 if (inst.error)
9113 return;
9115 if (*str++ != ']')
9117 inst.error = _("missing ]");
9118 return;
9121 if (*str == '!')
9123 inst.instruction |= WRITE_BACK;
9124 ++str;
9127 else
9129 /* You are here: "], <offset>". */
9130 if (*str++ != ']')
9132 inst.error = _("missing ]");
9133 return;
9136 if (skip_past_comma (&str) == FAIL
9137 || (offset = mav_parse_offset (&str, &negative), inst.error))
9138 goto fail_ldst;
9140 inst.instruction |= CP_T_WB; /* Post indexed, set bit W. */
9143 if (negative)
9144 offset = -offset;
9145 else
9146 inst.instruction |= CP_T_UD; /* Positive, so set bit U. */
9148 inst.instruction |= offset >> 2;
9149 end_of_line (str);
9150 return;
9152 fail_ldst:
9153 if (!inst.error)
9154 inst.error = BAD_ARGS;
9157 static void
9158 do_mav_ldst_1 (char * str)
9160 do_mav_ldst (str, REG_TYPE_MVF);
9163 static void
9164 do_mav_ldst_2 (char * str)
9166 do_mav_ldst (str, REG_TYPE_MVD);
9169 static void
9170 do_mav_ldst_3 (char * str)
9172 do_mav_ldst (str, REG_TYPE_MVFX);
9175 static void
9176 do_mav_ldst_4 (char * str)
9178 do_mav_ldst (str, REG_TYPE_MVDX);
9181 static void
9182 do_t_nop (char * str)
9184 /* Do nothing. */
9185 end_of_line (str);
9188 /* Handle the Format 4 instructions that do not have equivalents in other
9189 formats. That is, ADC, AND, EOR, SBC, ROR, TST, NEG, CMN, ORR, MUL,
9190 BIC and MVN. */
9192 static void
9193 do_t_arit (char * str)
9195 int Rd, Rs, Rn;
9197 skip_whitespace (str);
9199 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9200 || skip_past_comma (&str) == FAIL
9201 || (Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9203 inst.error = BAD_ARGS;
9204 return;
9207 if (skip_past_comma (&str) != FAIL)
9209 /* Three operand format not allowed for TST, CMN, NEG and MVN.
9210 (It isn't allowed for CMP either, but that isn't handled by this
9211 function.) */
9212 if (inst.instruction == T_OPCODE_TST
9213 || inst.instruction == T_OPCODE_CMN
9214 || inst.instruction == T_OPCODE_NEG
9215 || inst.instruction == T_OPCODE_MVN)
9217 inst.error = BAD_ARGS;
9218 return;
9221 if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9222 return;
9224 if (Rs != Rd)
9226 inst.error = _("dest and source1 must be the same register");
9227 return;
9229 Rs = Rn;
9232 if (inst.instruction == T_OPCODE_MUL
9233 && Rs == Rd)
9234 as_tsktsk (_("Rs and Rd must be different in MUL"));
9236 inst.instruction |= Rd | (Rs << 3);
9237 end_of_line (str);
9240 static void
9241 do_t_add (char * str)
9243 thumb_add_sub (str, 0);
9246 static void
9247 do_t_asr (char * str)
9249 thumb_shift (str, THUMB_ASR);
9252 static void
9253 do_t_branch9 (char * str)
9255 if (my_get_expression (&inst.reloc.exp, &str))
9256 return;
9257 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH9;
9258 inst.reloc.pc_rel = 1;
9259 end_of_line (str);
9262 static void
9263 do_t_branch12 (char * str)
9265 if (my_get_expression (&inst.reloc.exp, &str))
9266 return;
9267 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH12;
9268 inst.reloc.pc_rel = 1;
9269 end_of_line (str);
9272 /* Find the real, Thumb encoded start of a Thumb function. */
9274 static symbolS *
9275 find_real_start (symbolS * symbolP)
9277 char * real_start;
9278 const char * name = S_GET_NAME (symbolP);
9279 symbolS * new_target;
9281 /* This definition must agree with the one in gcc/config/arm/thumb.c. */
9282 #define STUB_NAME ".real_start_of"
9284 if (name == NULL)
9285 abort ();
9287 /* Names that start with '.' are local labels, not function entry points.
9288 The compiler may generate BL instructions to these labels because it
9289 needs to perform a branch to a far away location. */
9290 if (name[0] == '.')
9291 return symbolP;
9293 real_start = malloc (strlen (name) + strlen (STUB_NAME) + 1);
9294 sprintf (real_start, "%s%s", STUB_NAME, name);
9296 new_target = symbol_find (real_start);
9298 if (new_target == NULL)
9300 as_warn ("Failed to find real start of function: %s\n", name);
9301 new_target = symbolP;
9304 free (real_start);
9306 return new_target;
9309 static void
9310 do_t_branch23 (char * str)
9312 if (my_get_expression (& inst.reloc.exp, & str))
9313 return;
9315 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH23;
9316 inst.reloc.pc_rel = 1;
9317 end_of_line (str);
9319 /* If the destination of the branch is a defined symbol which does not have
9320 the THUMB_FUNC attribute, then we must be calling a function which has
9321 the (interfacearm) attribute. We look for the Thumb entry point to that
9322 function and change the branch to refer to that function instead. */
9323 if ( inst.reloc.exp.X_op == O_symbol
9324 && inst.reloc.exp.X_add_symbol != NULL
9325 && S_IS_DEFINED (inst.reloc.exp.X_add_symbol)
9326 && ! THUMB_IS_FUNC (inst.reloc.exp.X_add_symbol))
9327 inst.reloc.exp.X_add_symbol =
9328 find_real_start (inst.reloc.exp.X_add_symbol);
9331 static void
9332 do_t_bx (char * str)
9334 int reg;
9336 skip_whitespace (str);
9338 if ((reg = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
9339 return;
9341 /* This sets THUMB_H2 from the top bit of reg. */
9342 inst.instruction |= reg << 3;
9344 /* ??? FIXME: Should add a hacky reloc here if reg is REG_PC. The reloc
9345 should cause the alignment to be checked once it is known. This is
9346 because BX PC only works if the instruction is word aligned. */
9348 end_of_line (str);
9351 static void
9352 do_t_compare (char * str)
9354 thumb_mov_compare (str, THUMB_COMPARE);
9357 static void
9358 do_t_ldmstm (char * str)
9360 int Rb;
9361 long range;
9363 skip_whitespace (str);
9365 if ((Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9366 return;
9368 if (*str != '!')
9369 as_warn (_("inserted missing '!': load/store multiple always writes back base register"));
9370 else
9371 str++;
9373 if (skip_past_comma (&str) == FAIL
9374 || (range = reg_list (&str)) == FAIL)
9376 if (! inst.error)
9377 inst.error = BAD_ARGS;
9378 return;
9381 if (inst.reloc.type != BFD_RELOC_NONE)
9383 /* This really doesn't seem worth it. */
9384 inst.reloc.type = BFD_RELOC_NONE;
9385 inst.error = _("expression too complex");
9386 return;
9389 if (range & ~0xff)
9391 inst.error = _("only lo-regs valid in load/store multiple");
9392 return;
9395 inst.instruction |= (Rb << 8) | range;
9396 end_of_line (str);
9399 static void
9400 do_t_ldr (char * str)
9402 thumb_load_store (str, THUMB_LOAD, THUMB_WORD);
9405 static void
9406 do_t_ldrb (char * str)
9408 thumb_load_store (str, THUMB_LOAD, THUMB_BYTE);
9411 static void
9412 do_t_ldrh (char * str)
9414 thumb_load_store (str, THUMB_LOAD, THUMB_HALFWORD);
9417 static void
9418 do_t_lds (char * str)
9420 int Rd, Rb, Ro;
9422 skip_whitespace (str);
9424 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9425 || skip_past_comma (&str) == FAIL
9426 || *str++ != '['
9427 || (Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9428 || skip_past_comma (&str) == FAIL
9429 || (Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9430 || *str++ != ']')
9432 if (! inst.error)
9433 inst.error = _("syntax: ldrs[b] Rd, [Rb, Ro]");
9434 return;
9437 inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
9438 end_of_line (str);
9441 static void
9442 do_t_lsl (char * str)
9444 thumb_shift (str, THUMB_LSL);
9447 static void
9448 do_t_lsr (char * str)
9450 thumb_shift (str, THUMB_LSR);
9453 static void
9454 do_t_mov (char * str)
9456 thumb_mov_compare (str, THUMB_MOVE);
9459 static void
9460 do_t_push_pop (char * str)
9462 long range;
9464 skip_whitespace (str);
9466 if ((range = reg_list (&str)) == FAIL)
9468 if (! inst.error)
9469 inst.error = BAD_ARGS;
9470 return;
9473 if (inst.reloc.type != BFD_RELOC_NONE)
9475 /* This really doesn't seem worth it. */
9476 inst.reloc.type = BFD_RELOC_NONE;
9477 inst.error = _("expression too complex");
9478 return;
9481 if (range & ~0xff)
9483 if ((inst.instruction == T_OPCODE_PUSH
9484 && (range & ~0xff) == 1 << REG_LR)
9485 || (inst.instruction == T_OPCODE_POP
9486 && (range & ~0xff) == 1 << REG_PC))
9488 inst.instruction |= THUMB_PP_PC_LR;
9489 range &= 0xff;
9491 else
9493 inst.error = _("invalid register list to push/pop instruction");
9494 return;
9498 inst.instruction |= range;
9499 end_of_line (str);
9502 static void
9503 do_t_str (char * str)
9505 thumb_load_store (str, THUMB_STORE, THUMB_WORD);
9508 static void
9509 do_t_strb (char * str)
9511 thumb_load_store (str, THUMB_STORE, THUMB_BYTE);
9514 static void
9515 do_t_strh (char * str)
9517 thumb_load_store (str, THUMB_STORE, THUMB_HALFWORD);
9520 static void
9521 do_t_sub (char * str)
9523 thumb_add_sub (str, 1);
9526 static void
9527 do_t_swi (char * str)
9529 skip_whitespace (str);
9531 if (my_get_expression (&inst.reloc.exp, &str))
9532 return;
9534 inst.reloc.type = BFD_RELOC_ARM_SWI;
9535 end_of_line (str);
9538 static void
9539 do_t_adr (char * str)
9541 int reg;
9543 /* This is a pseudo-op of the form "adr rd, label" to be converted
9544 into a relative address of the form "add rd, pc, #label-.-4". */
9545 skip_whitespace (str);
9547 /* Store Rd in temporary location inside instruction. */
9548 if ((reg = reg_required_here (&str, 4)) == FAIL
9549 || (reg > 7) /* For Thumb reg must be r0..r7. */
9550 || skip_past_comma (&str) == FAIL
9551 || my_get_expression (&inst.reloc.exp, &str))
9553 if (!inst.error)
9554 inst.error = BAD_ARGS;
9555 return;
9558 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
9559 inst.reloc.exp.X_add_number -= 4; /* PC relative adjust. */
9560 inst.reloc.pc_rel = 1;
9561 inst.instruction |= REG_PC; /* Rd is already placed into the instruction. */
9563 end_of_line (str);
9566 static void
9567 insert_reg (const struct reg_entry * r,
9568 struct hash_control * htab)
9570 int len = strlen (r->name) + 2;
9571 char * buf = xmalloc (len);
9572 char * buf2 = xmalloc (len);
9573 int i = 0;
9575 #ifdef REGISTER_PREFIX
9576 buf[i++] = REGISTER_PREFIX;
9577 #endif
9579 strcpy (buf + i, r->name);
9581 for (i = 0; buf[i]; i++)
9582 buf2[i] = TOUPPER (buf[i]);
9584 buf2[i] = '\0';
9586 hash_insert (htab, buf, (PTR) r);
9587 hash_insert (htab, buf2, (PTR) r);
9590 static void
9591 build_reg_hsh (struct reg_map * map)
9593 const struct reg_entry *r;
9595 if ((map->htab = hash_new ()) == NULL)
9596 as_fatal (_("virtual memory exhausted"));
9598 for (r = map->names; r->name != NULL; r++)
9599 insert_reg (r, map->htab);
9602 static void
9603 insert_reg_alias (char * str,
9604 int regnum,
9605 struct hash_control *htab)
9607 const char * error;
9608 struct reg_entry * new = xmalloc (sizeof (struct reg_entry));
9609 const char * name = xmalloc (strlen (str) + 1);
9611 strcpy ((char *) name, str);
9613 new->name = name;
9614 new->number = regnum;
9615 new->builtin = FALSE;
9617 error = hash_insert (htab, name, (PTR) new);
9618 if (error)
9620 as_bad (_("failed to create an alias for %s, reason: %s"),
9621 str, error);
9622 free ((char *) name);
9623 free (new);
9627 /* Look for the .req directive. This is of the form:
9629 new_register_name .req existing_register_name
9631 If we find one, or if it looks sufficiently like one that we want to
9632 handle any error here, return non-zero. Otherwise return zero. */
9634 static int
9635 create_register_alias (char * newname, char * p)
9637 char * q;
9638 char c;
9640 q = p;
9641 skip_whitespace (q);
9643 c = *p;
9644 *p = '\0';
9646 if (*q && !strncmp (q, ".req ", 5))
9648 char *copy_of_str;
9649 char *r;
9651 #ifndef IGNORE_OPCODE_CASE
9652 newname = original_case_string;
9653 #endif
9654 copy_of_str = newname;
9656 q += 4;
9657 skip_whitespace (q);
9659 for (r = q; *r != '\0'; r++)
9660 if (*r == ' ')
9661 break;
9663 if (r != q)
9665 enum arm_reg_type new_type, old_type;
9666 int old_regno;
9667 char d = *r;
9669 *r = '\0';
9670 old_type = arm_reg_parse_any (q);
9671 *r = d;
9673 new_type = arm_reg_parse_any (newname);
9675 if (new_type == REG_TYPE_MAX)
9677 if (old_type != REG_TYPE_MAX)
9679 old_regno = arm_reg_parse (&q, all_reg_maps[old_type].htab);
9680 insert_reg_alias (newname, old_regno,
9681 all_reg_maps[old_type].htab);
9683 else
9684 as_warn (_("register '%s' does not exist\n"), q);
9686 else if (old_type == REG_TYPE_MAX)
9688 as_warn (_("ignoring redefinition of register alias '%s' to non-existant register '%s'"),
9689 copy_of_str, q);
9691 else
9693 /* Do not warn about redefinitions to the same alias. */
9694 if (new_type != old_type
9695 || (arm_reg_parse (&q, all_reg_maps[old_type].htab)
9696 != arm_reg_parse (&q, all_reg_maps[new_type].htab)))
9697 as_warn (_("ignoring redefinition of register alias '%s'"),
9698 copy_of_str);
9702 else
9703 as_warn (_("ignoring incomplete .req pseuso op"));
9705 *p = c;
9706 return 1;
9709 *p = c;
9710 return 0;
9713 static void
9714 set_constant_flonums (void)
9716 int i;
9718 for (i = 0; i < NUM_FLOAT_VALS; i++)
9719 if (atof_ieee ((char *) fp_const[i], 'x', fp_values[i]) == NULL)
9720 abort ();
9724 static const struct asm_opcode insns[] =
9726 /* Core ARM Instructions. */
9727 {"and", 0xe0000000, 3, ARM_EXT_V1, do_arit},
9728 {"ands", 0xe0100000, 3, ARM_EXT_V1, do_arit},
9729 {"eor", 0xe0200000, 3, ARM_EXT_V1, do_arit},
9730 {"eors", 0xe0300000, 3, ARM_EXT_V1, do_arit},
9731 {"sub", 0xe0400000, 3, ARM_EXT_V1, do_arit},
9732 {"subs", 0xe0500000, 3, ARM_EXT_V1, do_arit},
9733 {"rsb", 0xe0600000, 3, ARM_EXT_V1, do_arit},
9734 {"rsbs", 0xe0700000, 3, ARM_EXT_V1, do_arit},
9735 {"add", 0xe0800000, 3, ARM_EXT_V1, do_arit},
9736 {"adds", 0xe0900000, 3, ARM_EXT_V1, do_arit},
9737 {"adc", 0xe0a00000, 3, ARM_EXT_V1, do_arit},
9738 {"adcs", 0xe0b00000, 3, ARM_EXT_V1, do_arit},
9739 {"sbc", 0xe0c00000, 3, ARM_EXT_V1, do_arit},
9740 {"sbcs", 0xe0d00000, 3, ARM_EXT_V1, do_arit},
9741 {"rsc", 0xe0e00000, 3, ARM_EXT_V1, do_arit},
9742 {"rscs", 0xe0f00000, 3, ARM_EXT_V1, do_arit},
9743 {"orr", 0xe1800000, 3, ARM_EXT_V1, do_arit},
9744 {"orrs", 0xe1900000, 3, ARM_EXT_V1, do_arit},
9745 {"bic", 0xe1c00000, 3, ARM_EXT_V1, do_arit},
9746 {"bics", 0xe1d00000, 3, ARM_EXT_V1, do_arit},
9748 {"tst", 0xe1100000, 3, ARM_EXT_V1, do_cmp},
9749 {"tsts", 0xe1100000, 3, ARM_EXT_V1, do_cmp},
9750 {"tstp", 0xe110f000, 3, ARM_EXT_V1, do_cmp},
9751 {"teq", 0xe1300000, 3, ARM_EXT_V1, do_cmp},
9752 {"teqs", 0xe1300000, 3, ARM_EXT_V1, do_cmp},
9753 {"teqp", 0xe130f000, 3, ARM_EXT_V1, do_cmp},
9754 {"cmp", 0xe1500000, 3, ARM_EXT_V1, do_cmp},
9755 {"cmps", 0xe1500000, 3, ARM_EXT_V1, do_cmp},
9756 {"cmpp", 0xe150f000, 3, ARM_EXT_V1, do_cmp},
9757 {"cmn", 0xe1700000, 3, ARM_EXT_V1, do_cmp},
9758 {"cmns", 0xe1700000, 3, ARM_EXT_V1, do_cmp},
9759 {"cmnp", 0xe170f000, 3, ARM_EXT_V1, do_cmp},
9761 {"mov", 0xe1a00000, 3, ARM_EXT_V1, do_mov},
9762 {"movs", 0xe1b00000, 3, ARM_EXT_V1, do_mov},
9763 {"mvn", 0xe1e00000, 3, ARM_EXT_V1, do_mov},
9764 {"mvns", 0xe1f00000, 3, ARM_EXT_V1, do_mov},
9766 {"ldr", 0xe4100000, 3, ARM_EXT_V1, do_ldst},
9767 {"ldrb", 0xe4500000, 3, ARM_EXT_V1, do_ldst},
9768 {"ldrt", 0xe4300000, 3, ARM_EXT_V1, do_ldstt},
9769 {"ldrbt", 0xe4700000, 3, ARM_EXT_V1, do_ldstt},
9770 {"str", 0xe4000000, 3, ARM_EXT_V1, do_ldst},
9771 {"strb", 0xe4400000, 3, ARM_EXT_V1, do_ldst},
9772 {"strt", 0xe4200000, 3, ARM_EXT_V1, do_ldstt},
9773 {"strbt", 0xe4600000, 3, ARM_EXT_V1, do_ldstt},
9775 {"stmia", 0xe8800000, 3, ARM_EXT_V1, do_ldmstm},
9776 {"stmib", 0xe9800000, 3, ARM_EXT_V1, do_ldmstm},
9777 {"stmda", 0xe8000000, 3, ARM_EXT_V1, do_ldmstm},
9778 {"stmdb", 0xe9000000, 3, ARM_EXT_V1, do_ldmstm},
9779 {"stmfd", 0xe9000000, 3, ARM_EXT_V1, do_ldmstm},
9780 {"stmfa", 0xe9800000, 3, ARM_EXT_V1, do_ldmstm},
9781 {"stmea", 0xe8800000, 3, ARM_EXT_V1, do_ldmstm},
9782 {"stmed", 0xe8000000, 3, ARM_EXT_V1, do_ldmstm},
9784 {"ldmia", 0xe8900000, 3, ARM_EXT_V1, do_ldmstm},
9785 {"ldmib", 0xe9900000, 3, ARM_EXT_V1, do_ldmstm},
9786 {"ldmda", 0xe8100000, 3, ARM_EXT_V1, do_ldmstm},
9787 {"ldmdb", 0xe9100000, 3, ARM_EXT_V1, do_ldmstm},
9788 {"ldmfd", 0xe8900000, 3, ARM_EXT_V1, do_ldmstm},
9789 {"ldmfa", 0xe8100000, 3, ARM_EXT_V1, do_ldmstm},
9790 {"ldmea", 0xe9100000, 3, ARM_EXT_V1, do_ldmstm},
9791 {"ldmed", 0xe9900000, 3, ARM_EXT_V1, do_ldmstm},
9793 {"swi", 0xef000000, 3, ARM_EXT_V1, do_swi},
9794 #ifdef TE_WINCE
9795 /* XXX This is the wrong place to do this. Think multi-arch. */
9796 {"bl", 0xeb000000, 2, ARM_EXT_V1, do_branch},
9797 {"b", 0xea000000, 1, ARM_EXT_V1, do_branch},
9798 #else
9799 {"bl", 0xebfffffe, 2, ARM_EXT_V1, do_branch},
9800 {"b", 0xeafffffe, 1, ARM_EXT_V1, do_branch},
9801 #endif
9803 /* Pseudo ops. */
9804 {"adr", 0xe28f0000, 3, ARM_EXT_V1, do_adr},
9805 {"adrl", 0xe28f0000, 3, ARM_EXT_V1, do_adrl},
9806 {"nop", 0xe1a00000, 3, ARM_EXT_V1, do_nop},
9808 /* ARM 2 multiplies. */
9809 {"mul", 0xe0000090, 3, ARM_EXT_V2, do_mul},
9810 {"muls", 0xe0100090, 3, ARM_EXT_V2, do_mul},
9811 {"mla", 0xe0200090, 3, ARM_EXT_V2, do_mla},
9812 {"mlas", 0xe0300090, 3, ARM_EXT_V2, do_mla},
9814 /* Generic coprocessor instructions. */
9815 {"cdp", 0xee000000, 3, ARM_EXT_V2, do_cdp},
9816 {"ldc", 0xec100000, 3, ARM_EXT_V2, do_lstc},
9817 {"ldcl", 0xec500000, 3, ARM_EXT_V2, do_lstc},
9818 {"stc", 0xec000000, 3, ARM_EXT_V2, do_lstc},
9819 {"stcl", 0xec400000, 3, ARM_EXT_V2, do_lstc},
9820 {"mcr", 0xee000010, 3, ARM_EXT_V2, do_co_reg},
9821 {"mrc", 0xee100010, 3, ARM_EXT_V2, do_co_reg},
9823 /* ARM 3 - swp instructions. */
9824 {"swp", 0xe1000090, 3, ARM_EXT_V2S, do_swap},
9825 {"swpb", 0xe1400090, 3, ARM_EXT_V2S, do_swap},
9827 /* ARM 6 Status register instructions. */
9828 {"mrs", 0xe10f0000, 3, ARM_EXT_V3, do_mrs},
9829 {"msr", 0xe120f000, 3, ARM_EXT_V3, do_msr},
9830 /* ScottB: our code uses 0xe128f000 for msr.
9831 NickC: but this is wrong because the bits 16 through 19 are
9832 handled by the PSR_xxx defines above. */
9834 /* ARM 7M long multiplies. */
9835 {"smull", 0xe0c00090, 5, ARM_EXT_V3M, do_mull},
9836 {"smulls", 0xe0d00090, 5, ARM_EXT_V3M, do_mull},
9837 {"umull", 0xe0800090, 5, ARM_EXT_V3M, do_mull},
9838 {"umulls", 0xe0900090, 5, ARM_EXT_V3M, do_mull},
9839 {"smlal", 0xe0e00090, 5, ARM_EXT_V3M, do_mull},
9840 {"smlals", 0xe0f00090, 5, ARM_EXT_V3M, do_mull},
9841 {"umlal", 0xe0a00090, 5, ARM_EXT_V3M, do_mull},
9842 {"umlals", 0xe0b00090, 5, ARM_EXT_V3M, do_mull},
9844 /* ARM Architecture 4. */
9845 {"ldrh", 0xe01000b0, 3, ARM_EXT_V4, do_ldstv4},
9846 {"ldrsh", 0xe01000f0, 3, ARM_EXT_V4, do_ldstv4},
9847 {"ldrsb", 0xe01000d0, 3, ARM_EXT_V4, do_ldstv4},
9848 {"strh", 0xe00000b0, 3, ARM_EXT_V4, do_ldstv4},
9850 /* ARM Architecture 4T. */
9851 /* Note: bx (and blx) are required on V5, even if the processor does
9852 not support Thumb. */
9853 {"bx", 0xe12fff10, 2, ARM_EXT_V4T | ARM_EXT_V5, do_bx},
9855 /* ARM Architecture 5T. */
9856 /* Note: blx has 2 variants, so the .value is set dynamically.
9857 Only one of the variants has conditional execution. */
9858 {"blx", 0xe0000000, 3, ARM_EXT_V5, do_blx},
9859 {"clz", 0xe16f0f10, 3, ARM_EXT_V5, do_clz},
9860 {"bkpt", 0xe1200070, 0, ARM_EXT_V5, do_bkpt},
9861 {"ldc2", 0xfc100000, 0, ARM_EXT_V5, do_lstc2},
9862 {"ldc2l", 0xfc500000, 0, ARM_EXT_V5, do_lstc2},
9863 {"stc2", 0xfc000000, 0, ARM_EXT_V5, do_lstc2},
9864 {"stc2l", 0xfc400000, 0, ARM_EXT_V5, do_lstc2},
9865 {"cdp2", 0xfe000000, 0, ARM_EXT_V5, do_cdp2},
9866 {"mcr2", 0xfe000010, 0, ARM_EXT_V5, do_co_reg2},
9867 {"mrc2", 0xfe100010, 0, ARM_EXT_V5, do_co_reg2},
9869 /* ARM Architecture 5TExP. */
9870 {"smlabb", 0xe1000080, 6, ARM_EXT_V5ExP, do_smla},
9871 {"smlatb", 0xe10000a0, 6, ARM_EXT_V5ExP, do_smla},
9872 {"smlabt", 0xe10000c0, 6, ARM_EXT_V5ExP, do_smla},
9873 {"smlatt", 0xe10000e0, 6, ARM_EXT_V5ExP, do_smla},
9875 {"smlawb", 0xe1200080, 6, ARM_EXT_V5ExP, do_smla},
9876 {"smlawt", 0xe12000c0, 6, ARM_EXT_V5ExP, do_smla},
9878 {"smlalbb", 0xe1400080, 7, ARM_EXT_V5ExP, do_smlal},
9879 {"smlaltb", 0xe14000a0, 7, ARM_EXT_V5ExP, do_smlal},
9880 {"smlalbt", 0xe14000c0, 7, ARM_EXT_V5ExP, do_smlal},
9881 {"smlaltt", 0xe14000e0, 7, ARM_EXT_V5ExP, do_smlal},
9883 {"smulbb", 0xe1600080, 6, ARM_EXT_V5ExP, do_smul},
9884 {"smultb", 0xe16000a0, 6, ARM_EXT_V5ExP, do_smul},
9885 {"smulbt", 0xe16000c0, 6, ARM_EXT_V5ExP, do_smul},
9886 {"smultt", 0xe16000e0, 6, ARM_EXT_V5ExP, do_smul},
9888 {"smulwb", 0xe12000a0, 6, ARM_EXT_V5ExP, do_smul},
9889 {"smulwt", 0xe12000e0, 6, ARM_EXT_V5ExP, do_smul},
9891 {"qadd", 0xe1000050, 4, ARM_EXT_V5ExP, do_qadd},
9892 {"qdadd", 0xe1400050, 5, ARM_EXT_V5ExP, do_qadd},
9893 {"qsub", 0xe1200050, 4, ARM_EXT_V5ExP, do_qadd},
9894 {"qdsub", 0xe1600050, 5, ARM_EXT_V5ExP, do_qadd},
9896 /* ARM Architecture 5TE. */
9897 {"pld", 0xf450f000, 0, ARM_EXT_V5E, do_pld},
9898 {"ldrd", 0xe00000d0, 3, ARM_EXT_V5E, do_ldrd},
9899 {"strd", 0xe00000f0, 3, ARM_EXT_V5E, do_ldrd},
9901 {"mcrr", 0xec400000, 4, ARM_EXT_V5E, do_co_reg2c},
9902 {"mrrc", 0xec500000, 4, ARM_EXT_V5E, do_co_reg2c},
9904 /* ARM Architecture 5TEJ. */
9905 {"bxj", 0xe12fff20, 3, ARM_EXT_V5J, do_bxj},
9907 /* ARM V6. */
9908 { "cps", 0xf1020000, 0, ARM_EXT_V6, do_cps},
9909 { "cpsie", 0xf1080000, 0, ARM_EXT_V6, do_cpsi},
9910 { "cpsid", 0xf10C0000, 0, ARM_EXT_V6, do_cpsi},
9911 { "ldrex", 0xe1900f9f, 5, ARM_EXT_V6, do_ldrex},
9912 { "mcrr2", 0xfc400000, 0, ARM_EXT_V6, do_co_reg2c},
9913 { "mrrc2", 0xfc500000, 0, ARM_EXT_V6, do_co_reg2c},
9914 { "pkhbt", 0xe6800010, 5, ARM_EXT_V6, do_pkhbt},
9915 { "pkhtb", 0xe6800050, 5, ARM_EXT_V6, do_pkhtb},
9916 { "qadd16", 0xe6200f10, 6, ARM_EXT_V6, do_qadd16},
9917 { "qadd8", 0xe6200f90, 5, ARM_EXT_V6, do_qadd16},
9918 { "qaddsubx", 0xe6200f30, 8, ARM_EXT_V6, do_qadd16},
9919 { "qsub16", 0xe6200f70, 6, ARM_EXT_V6, do_qadd16},
9920 { "qsub8", 0xe6200ff0, 5, ARM_EXT_V6, do_qadd16},
9921 { "qsubaddx", 0xe6200f50, 8, ARM_EXT_V6, do_qadd16},
9922 { "sadd16", 0xe6100f10, 6, ARM_EXT_V6, do_qadd16},
9923 { "sadd8", 0xe6100f90, 5, ARM_EXT_V6, do_qadd16},
9924 { "saddsubx", 0xe6100f30, 8, ARM_EXT_V6, do_qadd16},
9925 { "shadd16", 0xe6300f10, 7, ARM_EXT_V6, do_qadd16},
9926 { "shadd8", 0xe6300f90, 6, ARM_EXT_V6, do_qadd16},
9927 { "shaddsubx", 0xe6300f30, 9, ARM_EXT_V6, do_qadd16},
9928 { "shsub16", 0xe6300f70, 7, ARM_EXT_V6, do_qadd16},
9929 { "shsub8", 0xe6300ff0, 6, ARM_EXT_V6, do_qadd16},
9930 { "shsubaddx", 0xe6300f50, 9, ARM_EXT_V6, do_qadd16},
9931 { "ssub16", 0xe6100f70, 6, ARM_EXT_V6, do_qadd16},
9932 { "ssub8", 0xe6100ff0, 5, ARM_EXT_V6, do_qadd16},
9933 { "ssubaddx", 0xe6100f50, 8, ARM_EXT_V6, do_qadd16},
9934 { "uadd16", 0xe6500f10, 6, ARM_EXT_V6, do_qadd16},
9935 { "uadd8", 0xe6500f90, 5, ARM_EXT_V6, do_qadd16},
9936 { "uaddsubx", 0xe6500f30, 8, ARM_EXT_V6, do_qadd16},
9937 { "uhadd16", 0xe6700f10, 7, ARM_EXT_V6, do_qadd16},
9938 { "uhadd8", 0xe6700f90, 6, ARM_EXT_V6, do_qadd16},
9939 { "uhaddsubx", 0xe6700f30, 9, ARM_EXT_V6, do_qadd16},
9940 { "uhsub16", 0xe6700f70, 7, ARM_EXT_V6, do_qadd16},
9941 { "uhsub8", 0xe6700ff0, 6, ARM_EXT_V6, do_qadd16},
9942 { "uhsubaddx", 0xe6700f50, 9, ARM_EXT_V6, do_qadd16},
9943 { "uqadd16", 0xe6600f10, 7, ARM_EXT_V6, do_qadd16},
9944 { "uqadd8", 0xe6600f90, 6, ARM_EXT_V6, do_qadd16},
9945 { "uqaddsubx", 0xe6600f30, 9, ARM_EXT_V6, do_qadd16},
9946 { "uqsub16", 0xe6600f70, 7, ARM_EXT_V6, do_qadd16},
9947 { "uqsub8", 0xe6600ff0, 6, ARM_EXT_V6, do_qadd16},
9948 { "uqsubaddx", 0xe6600f50, 9, ARM_EXT_V6, do_qadd16},
9949 { "usub16", 0xe6500f70, 6, ARM_EXT_V6, do_qadd16},
9950 { "usub8", 0xe6500ff0, 5, ARM_EXT_V6, do_qadd16},
9951 { "usubaddx", 0xe6500f50, 8, ARM_EXT_V6, do_qadd16},
9952 { "rev", 0xe6bf0f30, 3, ARM_EXT_V6, do_rev},
9953 { "rev16", 0xe6bf0fb0, 5, ARM_EXT_V6, do_rev},
9954 { "revsh", 0xe6ff0fb0, 5, ARM_EXT_V6, do_rev},
9955 { "rfeia", 0xf8900a00, 0, ARM_EXT_V6, do_rfe},
9956 { "rfeib", 0xf9900a00, 0, ARM_EXT_V6, do_rfe},
9957 { "rfeda", 0xf8100a00, 0, ARM_EXT_V6, do_rfe},
9958 { "rfedb", 0xf9100a00, 0, ARM_EXT_V6, do_rfe},
9959 { "rfefd", 0xf8900a00, 0, ARM_EXT_V6, do_rfe},
9960 { "rfefa", 0xf9900a00, 0, ARM_EXT_V6, do_rfe},
9961 { "rfeea", 0xf8100a00, 0, ARM_EXT_V6, do_rfe},
9962 { "rfeed", 0xf9100a00, 0, ARM_EXT_V6, do_rfe},
9963 { "sxtah", 0xe6b00070, 5, ARM_EXT_V6, do_sxtah},
9964 { "sxtab16", 0xe6800070, 7, ARM_EXT_V6, do_sxtah},
9965 { "sxtab", 0xe6a00070, 5, ARM_EXT_V6, do_sxtah},
9966 { "sxth", 0xe6bf0070, 4, ARM_EXT_V6, do_sxth},
9967 { "sxtb16", 0xe68f0070, 6, ARM_EXT_V6, do_sxth},
9968 { "sxtb", 0xe6af0070, 4, ARM_EXT_V6, do_sxth},
9969 { "uxtah", 0xe6f00070, 5, ARM_EXT_V6, do_sxtah},
9970 { "uxtab16", 0xe6c00070, 7, ARM_EXT_V6, do_sxtah},
9971 { "uxtab", 0xe6e00070, 5, ARM_EXT_V6, do_sxtah},
9972 { "uxth", 0xe6ff0070, 4, ARM_EXT_V6, do_sxth},
9973 { "uxtb16", 0xe6cf0070, 6, ARM_EXT_V6, do_sxth},
9974 { "uxtb", 0xe6ef0070, 4, ARM_EXT_V6, do_sxth},
9975 { "sel", 0xe68000b0, 3, ARM_EXT_V6, do_qadd16},
9976 { "setend", 0xf1010000, 0, ARM_EXT_V6, do_setend},
9977 { "smlad", 0xe7000010, 5, ARM_EXT_V6, do_smlad},
9978 { "smladx", 0xe7000030, 6, ARM_EXT_V6, do_smlad},
9979 { "smlald", 0xe7400010, 6, ARM_EXT_V6, do_smlald},
9980 { "smlaldx", 0xe7400030, 7, ARM_EXT_V6, do_smlald},
9981 { "smlsd", 0xe7000050, 5, ARM_EXT_V6, do_smlad},
9982 { "smlsdx", 0xe7000070, 6, ARM_EXT_V6, do_smlad},
9983 { "smlsld", 0xe7400050, 6, ARM_EXT_V6, do_smlald},
9984 { "smlsldx", 0xe7400070, 7, ARM_EXT_V6, do_smlald},
9985 { "smmla", 0xe7500010, 5, ARM_EXT_V6, do_smlad},
9986 { "smmlar", 0xe7500030, 6, ARM_EXT_V6, do_smlad},
9987 { "smmls", 0xe75000d0, 5, ARM_EXT_V6, do_smlad},
9988 { "smmlsr", 0xe75000f0, 6, ARM_EXT_V6, do_smlad},
9989 { "smmul", 0xe750f010, 5, ARM_EXT_V6, do_smmul},
9990 { "smmulr", 0xe750f030, 6, ARM_EXT_V6, do_smmul},
9991 { "smuad", 0xe700f010, 5, ARM_EXT_V6, do_smmul},
9992 { "smuadx", 0xe700f030, 6, ARM_EXT_V6, do_smmul},
9993 { "smusd", 0xe700f050, 5, ARM_EXT_V6, do_smmul},
9994 { "smusdx", 0xe700f070, 6, ARM_EXT_V6, do_smmul},
9995 { "srsia", 0xf8cd0500, 0, ARM_EXT_V6, do_srs},
9996 { "srsib", 0xf9cd0500, 0, ARM_EXT_V6, do_srs},
9997 { "srsda", 0xf84d0500, 0, ARM_EXT_V6, do_srs},
9998 { "srsdb", 0xf94d0500, 0, ARM_EXT_V6, do_srs},
9999 { "ssat", 0xe6a00010, 4, ARM_EXT_V6, do_ssat},
10000 { "ssat16", 0xe6a00f30, 6, ARM_EXT_V6, do_ssat16},
10001 { "strex", 0xe1800f90, 5, ARM_EXT_V6, do_strex},
10002 { "umaal", 0xe0400090, 5, ARM_EXT_V6, do_umaal},
10003 { "usad8", 0xe780f010, 5, ARM_EXT_V6, do_smmul},
10004 { "usada8", 0xe7800010, 6, ARM_EXT_V6, do_smlad},
10005 { "usat", 0xe6e00010, 4, ARM_EXT_V6, do_usat},
10006 { "usat16", 0xe6e00f30, 6, ARM_EXT_V6, do_usat16},
10008 /* ARM V6K. */
10009 { "clrex", 0xf57ff01f, 0, ARM_EXT_V6K, do_empty},
10010 { "ldrexb", 0xe1d00f9f, 6, ARM_EXT_V6K, do_ldrex},
10011 { "ldrexd", 0xe1b00f9f, 6, ARM_EXT_V6K, do_ldrex},
10012 { "ldrexh", 0xe1f00f9f, 6, ARM_EXT_V6K, do_ldrex},
10013 { "sev", 0xe320f004, 3, ARM_EXT_V6K, do_empty},
10014 { "strexb", 0xe1c00f90, 6, ARM_EXT_V6K, do_strex},
10015 { "strexd", 0xe1a00f90, 6, ARM_EXT_V6K, do_strex},
10016 { "strexh", 0xe1e00f90, 6, ARM_EXT_V6K, do_strex},
10017 { "wfe", 0xe320f002, 3, ARM_EXT_V6K, do_empty},
10018 { "wfi", 0xe320f003, 3, ARM_EXT_V6K, do_empty},
10019 { "yield", 0xe320f001, 5, ARM_EXT_V6K, do_empty},
10021 /* ARM V6Z. */
10022 { "smi", 0xe1600070, 3, ARM_EXT_V6Z, do_smi},
10024 /* Core FPA instruction set (V1). */
10025 {"wfs", 0xee200110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
10026 {"rfs", 0xee300110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
10027 {"wfc", 0xee400110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
10028 {"rfc", 0xee500110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
10030 {"ldfs", 0xec100100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10031 {"ldfd", 0xec108100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10032 {"ldfe", 0xec500100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10033 {"ldfp", 0xec508100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10035 {"stfs", 0xec000100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10036 {"stfd", 0xec008100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10037 {"stfe", 0xec400100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10038 {"stfp", 0xec408100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10040 {"mvfs", 0xee008100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10041 {"mvfsp", 0xee008120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10042 {"mvfsm", 0xee008140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10043 {"mvfsz", 0xee008160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10044 {"mvfd", 0xee008180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10045 {"mvfdp", 0xee0081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10046 {"mvfdm", 0xee0081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10047 {"mvfdz", 0xee0081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10048 {"mvfe", 0xee088100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10049 {"mvfep", 0xee088120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10050 {"mvfem", 0xee088140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10051 {"mvfez", 0xee088160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10053 {"mnfs", 0xee108100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10054 {"mnfsp", 0xee108120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10055 {"mnfsm", 0xee108140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10056 {"mnfsz", 0xee108160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10057 {"mnfd", 0xee108180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10058 {"mnfdp", 0xee1081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10059 {"mnfdm", 0xee1081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10060 {"mnfdz", 0xee1081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10061 {"mnfe", 0xee188100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10062 {"mnfep", 0xee188120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10063 {"mnfem", 0xee188140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10064 {"mnfez", 0xee188160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10066 {"abss", 0xee208100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10067 {"abssp", 0xee208120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10068 {"abssm", 0xee208140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10069 {"abssz", 0xee208160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10070 {"absd", 0xee208180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10071 {"absdp", 0xee2081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10072 {"absdm", 0xee2081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10073 {"absdz", 0xee2081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10074 {"abse", 0xee288100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10075 {"absep", 0xee288120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10076 {"absem", 0xee288140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10077 {"absez", 0xee288160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10079 {"rnds", 0xee308100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10080 {"rndsp", 0xee308120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10081 {"rndsm", 0xee308140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10082 {"rndsz", 0xee308160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10083 {"rndd", 0xee308180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10084 {"rnddp", 0xee3081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10085 {"rnddm", 0xee3081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10086 {"rnddz", 0xee3081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10087 {"rnde", 0xee388100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10088 {"rndep", 0xee388120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10089 {"rndem", 0xee388140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10090 {"rndez", 0xee388160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10092 {"sqts", 0xee408100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10093 {"sqtsp", 0xee408120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10094 {"sqtsm", 0xee408140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10095 {"sqtsz", 0xee408160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10096 {"sqtd", 0xee408180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10097 {"sqtdp", 0xee4081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10098 {"sqtdm", 0xee4081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10099 {"sqtdz", 0xee4081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10100 {"sqte", 0xee488100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10101 {"sqtep", 0xee488120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10102 {"sqtem", 0xee488140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10103 {"sqtez", 0xee488160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10105 {"logs", 0xee508100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10106 {"logsp", 0xee508120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10107 {"logsm", 0xee508140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10108 {"logsz", 0xee508160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10109 {"logd", 0xee508180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10110 {"logdp", 0xee5081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10111 {"logdm", 0xee5081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10112 {"logdz", 0xee5081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10113 {"loge", 0xee588100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10114 {"logep", 0xee588120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10115 {"logem", 0xee588140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10116 {"logez", 0xee588160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10118 {"lgns", 0xee608100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10119 {"lgnsp", 0xee608120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10120 {"lgnsm", 0xee608140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10121 {"lgnsz", 0xee608160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10122 {"lgnd", 0xee608180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10123 {"lgndp", 0xee6081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10124 {"lgndm", 0xee6081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10125 {"lgndz", 0xee6081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10126 {"lgne", 0xee688100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10127 {"lgnep", 0xee688120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10128 {"lgnem", 0xee688140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10129 {"lgnez", 0xee688160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10131 {"exps", 0xee708100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10132 {"expsp", 0xee708120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10133 {"expsm", 0xee708140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10134 {"expsz", 0xee708160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10135 {"expd", 0xee708180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10136 {"expdp", 0xee7081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10137 {"expdm", 0xee7081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10138 {"expdz", 0xee7081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10139 {"expe", 0xee788100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10140 {"expep", 0xee788120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10141 {"expem", 0xee788140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10142 {"expdz", 0xee788160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10144 {"sins", 0xee808100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10145 {"sinsp", 0xee808120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10146 {"sinsm", 0xee808140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10147 {"sinsz", 0xee808160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10148 {"sind", 0xee808180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10149 {"sindp", 0xee8081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10150 {"sindm", 0xee8081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10151 {"sindz", 0xee8081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10152 {"sine", 0xee888100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10153 {"sinep", 0xee888120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10154 {"sinem", 0xee888140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10155 {"sinez", 0xee888160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10157 {"coss", 0xee908100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10158 {"cossp", 0xee908120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10159 {"cossm", 0xee908140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10160 {"cossz", 0xee908160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10161 {"cosd", 0xee908180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10162 {"cosdp", 0xee9081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10163 {"cosdm", 0xee9081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10164 {"cosdz", 0xee9081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10165 {"cose", 0xee988100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10166 {"cosep", 0xee988120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10167 {"cosem", 0xee988140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10168 {"cosez", 0xee988160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10170 {"tans", 0xeea08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10171 {"tansp", 0xeea08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10172 {"tansm", 0xeea08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10173 {"tansz", 0xeea08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10174 {"tand", 0xeea08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10175 {"tandp", 0xeea081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10176 {"tandm", 0xeea081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10177 {"tandz", 0xeea081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10178 {"tane", 0xeea88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10179 {"tanep", 0xeea88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10180 {"tanem", 0xeea88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10181 {"tanez", 0xeea88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10183 {"asns", 0xeeb08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10184 {"asnsp", 0xeeb08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10185 {"asnsm", 0xeeb08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10186 {"asnsz", 0xeeb08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10187 {"asnd", 0xeeb08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10188 {"asndp", 0xeeb081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10189 {"asndm", 0xeeb081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10190 {"asndz", 0xeeb081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10191 {"asne", 0xeeb88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10192 {"asnep", 0xeeb88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10193 {"asnem", 0xeeb88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10194 {"asnez", 0xeeb88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10196 {"acss", 0xeec08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10197 {"acssp", 0xeec08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10198 {"acssm", 0xeec08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10199 {"acssz", 0xeec08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10200 {"acsd", 0xeec08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10201 {"acsdp", 0xeec081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10202 {"acsdm", 0xeec081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10203 {"acsdz", 0xeec081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10204 {"acse", 0xeec88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10205 {"acsep", 0xeec88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10206 {"acsem", 0xeec88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10207 {"acsez", 0xeec88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10209 {"atns", 0xeed08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10210 {"atnsp", 0xeed08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10211 {"atnsm", 0xeed08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10212 {"atnsz", 0xeed08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10213 {"atnd", 0xeed08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10214 {"atndp", 0xeed081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10215 {"atndm", 0xeed081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10216 {"atndz", 0xeed081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10217 {"atne", 0xeed88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10218 {"atnep", 0xeed88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10219 {"atnem", 0xeed88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10220 {"atnez", 0xeed88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10222 {"urds", 0xeee08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10223 {"urdsp", 0xeee08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10224 {"urdsm", 0xeee08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10225 {"urdsz", 0xeee08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10226 {"urdd", 0xeee08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10227 {"urddp", 0xeee081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10228 {"urddm", 0xeee081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10229 {"urddz", 0xeee081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10230 {"urde", 0xeee88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10231 {"urdep", 0xeee88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10232 {"urdem", 0xeee88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10233 {"urdez", 0xeee88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10235 {"nrms", 0xeef08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10236 {"nrmsp", 0xeef08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10237 {"nrmsm", 0xeef08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10238 {"nrmsz", 0xeef08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10239 {"nrmd", 0xeef08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10240 {"nrmdp", 0xeef081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10241 {"nrmdm", 0xeef081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10242 {"nrmdz", 0xeef081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10243 {"nrme", 0xeef88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10244 {"nrmep", 0xeef88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10245 {"nrmem", 0xeef88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10246 {"nrmez", 0xeef88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10248 {"adfs", 0xee000100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10249 {"adfsp", 0xee000120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10250 {"adfsm", 0xee000140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10251 {"adfsz", 0xee000160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10252 {"adfd", 0xee000180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10253 {"adfdp", 0xee0001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10254 {"adfdm", 0xee0001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10255 {"adfdz", 0xee0001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10256 {"adfe", 0xee080100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10257 {"adfep", 0xee080120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10258 {"adfem", 0xee080140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10259 {"adfez", 0xee080160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10261 {"sufs", 0xee200100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10262 {"sufsp", 0xee200120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10263 {"sufsm", 0xee200140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10264 {"sufsz", 0xee200160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10265 {"sufd", 0xee200180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10266 {"sufdp", 0xee2001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10267 {"sufdm", 0xee2001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10268 {"sufdz", 0xee2001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10269 {"sufe", 0xee280100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10270 {"sufep", 0xee280120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10271 {"sufem", 0xee280140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10272 {"sufez", 0xee280160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10274 {"rsfs", 0xee300100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10275 {"rsfsp", 0xee300120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10276 {"rsfsm", 0xee300140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10277 {"rsfsz", 0xee300160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10278 {"rsfd", 0xee300180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10279 {"rsfdp", 0xee3001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10280 {"rsfdm", 0xee3001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10281 {"rsfdz", 0xee3001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10282 {"rsfe", 0xee380100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10283 {"rsfep", 0xee380120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10284 {"rsfem", 0xee380140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10285 {"rsfez", 0xee380160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10287 {"mufs", 0xee100100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10288 {"mufsp", 0xee100120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10289 {"mufsm", 0xee100140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10290 {"mufsz", 0xee100160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10291 {"mufd", 0xee100180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10292 {"mufdp", 0xee1001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10293 {"mufdm", 0xee1001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10294 {"mufdz", 0xee1001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10295 {"mufe", 0xee180100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10296 {"mufep", 0xee180120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10297 {"mufem", 0xee180140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10298 {"mufez", 0xee180160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10300 {"dvfs", 0xee400100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10301 {"dvfsp", 0xee400120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10302 {"dvfsm", 0xee400140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10303 {"dvfsz", 0xee400160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10304 {"dvfd", 0xee400180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10305 {"dvfdp", 0xee4001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10306 {"dvfdm", 0xee4001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10307 {"dvfdz", 0xee4001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10308 {"dvfe", 0xee480100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10309 {"dvfep", 0xee480120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10310 {"dvfem", 0xee480140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10311 {"dvfez", 0xee480160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10313 {"rdfs", 0xee500100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10314 {"rdfsp", 0xee500120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10315 {"rdfsm", 0xee500140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10316 {"rdfsz", 0xee500160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10317 {"rdfd", 0xee500180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10318 {"rdfdp", 0xee5001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10319 {"rdfdm", 0xee5001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10320 {"rdfdz", 0xee5001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10321 {"rdfe", 0xee580100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10322 {"rdfep", 0xee580120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10323 {"rdfem", 0xee580140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10324 {"rdfez", 0xee580160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10326 {"pows", 0xee600100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10327 {"powsp", 0xee600120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10328 {"powsm", 0xee600140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10329 {"powsz", 0xee600160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10330 {"powd", 0xee600180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10331 {"powdp", 0xee6001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10332 {"powdm", 0xee6001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10333 {"powdz", 0xee6001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10334 {"powe", 0xee680100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10335 {"powep", 0xee680120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10336 {"powem", 0xee680140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10337 {"powez", 0xee680160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10339 {"rpws", 0xee700100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10340 {"rpwsp", 0xee700120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10341 {"rpwsm", 0xee700140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10342 {"rpwsz", 0xee700160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10343 {"rpwd", 0xee700180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10344 {"rpwdp", 0xee7001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10345 {"rpwdm", 0xee7001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10346 {"rpwdz", 0xee7001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10347 {"rpwe", 0xee780100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10348 {"rpwep", 0xee780120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10349 {"rpwem", 0xee780140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10350 {"rpwez", 0xee780160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10352 {"rmfs", 0xee800100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10353 {"rmfsp", 0xee800120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10354 {"rmfsm", 0xee800140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10355 {"rmfsz", 0xee800160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10356 {"rmfd", 0xee800180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10357 {"rmfdp", 0xee8001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10358 {"rmfdm", 0xee8001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10359 {"rmfdz", 0xee8001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10360 {"rmfe", 0xee880100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10361 {"rmfep", 0xee880120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10362 {"rmfem", 0xee880140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10363 {"rmfez", 0xee880160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10365 {"fmls", 0xee900100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10366 {"fmlsp", 0xee900120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10367 {"fmlsm", 0xee900140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10368 {"fmlsz", 0xee900160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10369 {"fmld", 0xee900180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10370 {"fmldp", 0xee9001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10371 {"fmldm", 0xee9001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10372 {"fmldz", 0xee9001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10373 {"fmle", 0xee980100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10374 {"fmlep", 0xee980120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10375 {"fmlem", 0xee980140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10376 {"fmlez", 0xee980160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10378 {"fdvs", 0xeea00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10379 {"fdvsp", 0xeea00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10380 {"fdvsm", 0xeea00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10381 {"fdvsz", 0xeea00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10382 {"fdvd", 0xeea00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10383 {"fdvdp", 0xeea001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10384 {"fdvdm", 0xeea001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10385 {"fdvdz", 0xeea001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10386 {"fdve", 0xeea80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10387 {"fdvep", 0xeea80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10388 {"fdvem", 0xeea80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10389 {"fdvez", 0xeea80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10391 {"frds", 0xeeb00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10392 {"frdsp", 0xeeb00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10393 {"frdsm", 0xeeb00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10394 {"frdsz", 0xeeb00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10395 {"frdd", 0xeeb00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10396 {"frddp", 0xeeb001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10397 {"frddm", 0xeeb001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10398 {"frddz", 0xeeb001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10399 {"frde", 0xeeb80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10400 {"frdep", 0xeeb80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10401 {"frdem", 0xeeb80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10402 {"frdez", 0xeeb80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10404 {"pols", 0xeec00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10405 {"polsp", 0xeec00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10406 {"polsm", 0xeec00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10407 {"polsz", 0xeec00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10408 {"pold", 0xeec00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10409 {"poldp", 0xeec001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10410 {"poldm", 0xeec001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10411 {"poldz", 0xeec001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10412 {"pole", 0xeec80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10413 {"polep", 0xeec80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10414 {"polem", 0xeec80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10415 {"polez", 0xeec80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10417 {"cmf", 0xee90f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
10418 {"cmfe", 0xeed0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
10419 {"cnf", 0xeeb0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
10420 {"cnfe", 0xeef0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
10421 /* The FPA10 data sheet suggests that the 'E' of cmfe/cnfe should
10422 not be an optional suffix, but part of the instruction. To be
10423 compatible, we accept either. */
10424 {"cmfe", 0xeed0f110, 4, FPU_FPA_EXT_V1, do_fpa_cmp},
10425 {"cnfe", 0xeef0f110, 4, FPU_FPA_EXT_V1, do_fpa_cmp},
10427 {"flts", 0xee000110, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10428 {"fltsp", 0xee000130, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10429 {"fltsm", 0xee000150, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10430 {"fltsz", 0xee000170, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10431 {"fltd", 0xee000190, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10432 {"fltdp", 0xee0001b0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10433 {"fltdm", 0xee0001d0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10434 {"fltdz", 0xee0001f0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10435 {"flte", 0xee080110, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10436 {"fltep", 0xee080130, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10437 {"fltem", 0xee080150, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10438 {"fltez", 0xee080170, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10440 /* The implementation of the FIX instruction is broken on some
10441 assemblers, in that it accepts a precision specifier as well as a
10442 rounding specifier, despite the fact that this is meaningless.
10443 To be more compatible, we accept it as well, though of course it
10444 does not set any bits. */
10445 {"fix", 0xee100110, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10446 {"fixp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10447 {"fixm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10448 {"fixz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10449 {"fixsp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10450 {"fixsm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10451 {"fixsz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10452 {"fixdp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10453 {"fixdm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10454 {"fixdz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10455 {"fixep", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10456 {"fixem", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10457 {"fixez", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10459 /* Instructions that were new with the real FPA, call them V2. */
10460 {"lfm", 0xec100200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10461 {"lfmfd", 0xec900200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10462 {"lfmea", 0xed100200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10463 {"sfm", 0xec000200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10464 {"sfmfd", 0xed000200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10465 {"sfmea", 0xec800200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10467 /* VFP V1xD (single precision). */
10468 /* Moves and type conversions. */
10469 {"fcpys", 0xeeb00a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10470 {"fmrs", 0xee100a10, 4, FPU_VFP_EXT_V1xD, do_vfp_reg_from_sp},
10471 {"fmsr", 0xee000a10, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_from_reg},
10472 {"fmstat", 0xeef1fa10, 6, FPU_VFP_EXT_V1xD, do_empty},
10473 {"fsitos", 0xeeb80ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10474 {"fuitos", 0xeeb80a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10475 {"ftosis", 0xeebd0a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10476 {"ftosizs", 0xeebd0ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10477 {"ftouis", 0xeebc0a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10478 {"ftouizs", 0xeebc0ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10479 {"fmrx", 0xeef00a10, 4, FPU_VFP_EXT_V1xD, do_vfp_reg_from_ctrl},
10480 {"fmxr", 0xeee00a10, 4, FPU_VFP_EXT_V1xD, do_vfp_ctrl_from_reg},
10482 /* Memory operations. */
10483 {"flds", 0xed100a00, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_ldst},
10484 {"fsts", 0xed000a00, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_ldst},
10485 {"fldmias", 0xec900a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
10486 {"fldmfds", 0xec900a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
10487 {"fldmdbs", 0xed300a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
10488 {"fldmeas", 0xed300a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
10489 {"fldmiax", 0xec900b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
10490 {"fldmfdx", 0xec900b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
10491 {"fldmdbx", 0xed300b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
10492 {"fldmeax", 0xed300b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
10493 {"fstmias", 0xec800a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
10494 {"fstmeas", 0xec800a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
10495 {"fstmdbs", 0xed200a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
10496 {"fstmfds", 0xed200a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
10497 {"fstmiax", 0xec800b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
10498 {"fstmeax", 0xec800b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
10499 {"fstmdbx", 0xed200b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
10500 {"fstmfdx", 0xed200b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
10502 /* Monadic operations. */
10503 {"fabss", 0xeeb00ac0, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10504 {"fnegs", 0xeeb10a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10505 {"fsqrts", 0xeeb10ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10507 /* Dyadic operations. */
10508 {"fadds", 0xee300a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10509 {"fsubs", 0xee300a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10510 {"fmuls", 0xee200a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10511 {"fdivs", 0xee800a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10512 {"fmacs", 0xee000a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10513 {"fmscs", 0xee100a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10514 {"fnmuls", 0xee200a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10515 {"fnmacs", 0xee000a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10516 {"fnmscs", 0xee100a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10518 /* Comparisons. */
10519 {"fcmps", 0xeeb40a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10520 {"fcmpzs", 0xeeb50a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_compare_z},
10521 {"fcmpes", 0xeeb40ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10522 {"fcmpezs", 0xeeb50ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_compare_z},
10524 /* VFP V1 (Double precision). */
10525 /* Moves and type conversions. */
10526 {"fcpyd", 0xeeb00b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10527 {"fcvtds", 0xeeb70ac0, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
10528 {"fcvtsd", 0xeeb70bc0, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
10529 {"fmdhr", 0xee200b10, 5, FPU_VFP_EXT_V1, do_vfp_dp_from_reg},
10530 {"fmdlr", 0xee000b10, 5, FPU_VFP_EXT_V1, do_vfp_dp_from_reg},
10531 {"fmrdh", 0xee300b10, 5, FPU_VFP_EXT_V1, do_vfp_reg_from_dp},
10532 {"fmrdl", 0xee100b10, 5, FPU_VFP_EXT_V1, do_vfp_reg_from_dp},
10533 {"fsitod", 0xeeb80bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
10534 {"fuitod", 0xeeb80b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
10535 {"ftosid", 0xeebd0b40, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
10536 {"ftosizd", 0xeebd0bc0, 7, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
10537 {"ftouid", 0xeebc0b40, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
10538 {"ftouizd", 0xeebc0bc0, 7, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
10540 /* Memory operations. */
10541 {"fldd", 0xed100b00, 4, FPU_VFP_EXT_V1, do_vfp_dp_ldst},
10542 {"fstd", 0xed000b00, 4, FPU_VFP_EXT_V1, do_vfp_dp_ldst},
10543 {"fldmiad", 0xec900b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
10544 {"fldmfdd", 0xec900b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
10545 {"fldmdbd", 0xed300b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
10546 {"fldmead", 0xed300b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
10547 {"fstmiad", 0xec800b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
10548 {"fstmead", 0xec800b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
10549 {"fstmdbd", 0xed200b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
10550 {"fstmfdd", 0xed200b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
10552 /* Monadic operations. */
10553 {"fabsd", 0xeeb00bc0, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10554 {"fnegd", 0xeeb10b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10555 {"fsqrtd", 0xeeb10bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10557 /* Dyadic operations. */
10558 {"faddd", 0xee300b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10559 {"fsubd", 0xee300b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10560 {"fmuld", 0xee200b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10561 {"fdivd", 0xee800b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10562 {"fmacd", 0xee000b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10563 {"fmscd", 0xee100b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10564 {"fnmuld", 0xee200b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10565 {"fnmacd", 0xee000b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10566 {"fnmscd", 0xee100b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10568 /* Comparisons. */
10569 {"fcmpd", 0xeeb40b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10570 {"fcmpzd", 0xeeb50b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_compare_z},
10571 {"fcmped", 0xeeb40bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10572 {"fcmpezd", 0xeeb50bc0, 7, FPU_VFP_EXT_V1, do_vfp_dp_compare_z},
10574 /* VFP V2. */
10575 {"fmsrr", 0xec400a10, 5, FPU_VFP_EXT_V2, do_vfp_sp2_from_reg2},
10576 {"fmrrs", 0xec500a10, 5, FPU_VFP_EXT_V2, do_vfp_reg2_from_sp2},
10577 {"fmdrr", 0xec400b10, 5, FPU_VFP_EXT_V2, do_vfp_dp_from_reg2},
10578 {"fmrrd", 0xec500b10, 5, FPU_VFP_EXT_V2, do_vfp_reg2_from_dp},
10580 /* Intel XScale extensions to ARM V5 ISA. (All use CP0). */
10581 {"mia", 0xee200010, 3, ARM_CEXT_XSCALE, do_xsc_mia},
10582 {"miaph", 0xee280010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
10583 {"miabb", 0xee2c0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
10584 {"miabt", 0xee2d0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
10585 {"miatb", 0xee2e0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
10586 {"miatt", 0xee2f0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
10587 {"mar", 0xec400000, 3, ARM_CEXT_XSCALE, do_xsc_mar},
10588 {"mra", 0xec500000, 3, ARM_CEXT_XSCALE, do_xsc_mra},
10590 /* Intel Wireless MMX technology instructions. */
10591 {"tandcb", 0xee130130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
10592 {"tandch", 0xee530130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
10593 {"tandcw", 0xee930130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
10594 {"tbcstb", 0xee400010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
10595 {"tbcsth", 0xee400050, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
10596 {"tbcstw", 0xee400090, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
10597 {"textrcb", 0xee130170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
10598 {"textrch", 0xee530170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
10599 {"textrcw", 0xee930170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
10600 {"textrmub", 0xee100070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10601 {"textrmuh", 0xee500070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10602 {"textrmuw", 0xee900070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10603 {"textrmsb", 0xee100078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10604 {"textrmsh", 0xee500078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10605 {"textrmsw", 0xee900078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10606 {"tinsrb", 0xee600010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
10607 {"tinsrh", 0xee600050, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
10608 {"tinsrw", 0xee600090, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
10609 {"tmcr", 0xee000110, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmcr},
10610 {"tmcrr", 0xec400000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_tmcrr},
10611 {"tmia", 0xee200010, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10612 {"tmiaph", 0xee280010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10613 {"tmiabb", 0xee2c0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10614 {"tmiabt", 0xee2d0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10615 {"tmiatb", 0xee2e0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10616 {"tmiatt", 0xee2f0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10617 {"tmovmskb", 0xee100030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
10618 {"tmovmskh", 0xee500030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
10619 {"tmovmskw", 0xee900030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
10620 {"tmrc", 0xee100110, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmrc},
10621 {"tmrrc", 0xec500000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_tmrrc},
10622 {"torcb", 0xee130150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
10623 {"torch", 0xee530150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
10624 {"torcw", 0xee930150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
10625 {"waccb", 0xee0001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10626 {"wacch", 0xee4001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10627 {"waccw", 0xee8001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10628 {"waddbss", 0xee300180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10629 {"waddb", 0xee000180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10630 {"waddbus", 0xee100180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10631 {"waddhss", 0xee700180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10632 {"waddh", 0xee400180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10633 {"waddhus", 0xee500180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10634 {"waddwss", 0xeeb00180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10635 {"waddw", 0xee800180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10636 {"waddwus", 0xee900180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10637 {"waligni", 0xee000020, 7, ARM_CEXT_IWMMXT, do_iwmmxt_waligni},
10638 {"walignr0", 0xee800020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10639 {"walignr1", 0xee900020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10640 {"walignr2", 0xeea00020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10641 {"walignr3", 0xeeb00020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10642 {"wand", 0xee200000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10643 {"wandn", 0xee300000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10644 {"wavg2b", 0xee800000, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10645 {"wavg2br", 0xee900000, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10646 {"wavg2h", 0xeec00000, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10647 {"wavg2hr", 0xeed00000, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10648 {"wcmpeqb", 0xee000060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10649 {"wcmpeqh", 0xee400060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10650 {"wcmpeqw", 0xee800060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10651 {"wcmpgtub", 0xee100060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10652 {"wcmpgtuh", 0xee500060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10653 {"wcmpgtuw", 0xee900060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10654 {"wcmpgtsb", 0xee300060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10655 {"wcmpgtsh", 0xee700060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10656 {"wcmpgtsw", 0xeeb00060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10657 {"wldrb", 0xec100000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
10658 {"wldrh", 0xec100100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
10659 {"wldrw", 0xec100200, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
10660 {"wldrd", 0xec100300, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
10661 {"wmacs", 0xee600100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10662 {"wmacsz", 0xee700100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10663 {"wmacu", 0xee400100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10664 {"wmacuz", 0xee500100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10665 {"wmadds", 0xeea00100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10666 {"wmaddu", 0xee800100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10667 {"wmaxsb", 0xee200160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10668 {"wmaxsh", 0xee600160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10669 {"wmaxsw", 0xeea00160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10670 {"wmaxub", 0xee000160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10671 {"wmaxuh", 0xee400160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10672 {"wmaxuw", 0xee800160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10673 {"wminsb", 0xee300160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10674 {"wminsh", 0xee700160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10675 {"wminsw", 0xeeb00160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10676 {"wminub", 0xee100160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10677 {"wminuh", 0xee500160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10678 {"wminuw", 0xee900160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10679 {"wmov", 0xee000000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wmov},
10680 {"wmulsm", 0xee300100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10681 {"wmulsl", 0xee200100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10682 {"wmulum", 0xee100100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10683 {"wmulul", 0xee000100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10684 {"wor", 0xee000000, 3, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10685 {"wpackhss", 0xee700080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10686 {"wpackhus", 0xee500080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10687 {"wpackwss", 0xeeb00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10688 {"wpackwus", 0xee900080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10689 {"wpackdss", 0xeef00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10690 {"wpackdus", 0xeed00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10691 {"wrorh", 0xee700040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10692 {"wrorhg", 0xee700148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
10693 {"wrorw", 0xeeb00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10694 {"wrorwg", 0xeeb00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
10695 {"wrord", 0xeef00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10696 {"wrordg", 0xeef00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
10697 {"wsadb", 0xee000120, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10698 {"wsadbz", 0xee100120, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10699 {"wsadh", 0xee400120, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10700 {"wsadhz", 0xee500120, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10701 {"wshufh", 0xee0001e0, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wshufh},
10702 {"wsllh", 0xee500040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10703 {"wsllhg", 0xee500148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
10704 {"wsllw", 0xee900040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10705 {"wsllwg", 0xee900148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
10706 {"wslld", 0xeed00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10707 {"wslldg", 0xeed00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
10708 {"wsrah", 0xee400040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10709 {"wsrahg", 0xee400148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
10710 {"wsraw", 0xee800040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10711 {"wsrawg", 0xee800148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
10712 {"wsrad", 0xeec00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10713 {"wsradg", 0xeec00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
10714 {"wsrlh", 0xee600040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10715 {"wsrlhg", 0xee600148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
10716 {"wsrlw", 0xeea00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10717 {"wsrlwg", 0xeea00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
10718 {"wsrld", 0xeee00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10719 {"wsrldg", 0xeee00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
10720 {"wstrb", 0xec000000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
10721 {"wstrh", 0xec000100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
10722 {"wstrw", 0xec000200, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
10723 {"wstrd", 0xec000300, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
10724 {"wsubbss", 0xee3001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10725 {"wsubb", 0xee0001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10726 {"wsubbus", 0xee1001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10727 {"wsubhss", 0xee7001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10728 {"wsubh", 0xee4001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10729 {"wsubhus", 0xee5001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10730 {"wsubwss", 0xeeb001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10731 {"wsubw", 0xee8001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10732 {"wsubwus", 0xee9001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10733 {"wunpckehub", 0xee0000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10734 {"wunpckehuh", 0xee4000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10735 {"wunpckehuw", 0xee8000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10736 {"wunpckehsb", 0xee2000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10737 {"wunpckehsh", 0xee6000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10738 {"wunpckehsw", 0xeea000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10739 {"wunpckihb", 0xee1000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10740 {"wunpckihh", 0xee5000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10741 {"wunpckihw", 0xee9000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10742 {"wunpckelub", 0xee0000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10743 {"wunpckeluh", 0xee4000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10744 {"wunpckeluw", 0xee8000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10745 {"wunpckelsb", 0xee2000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10746 {"wunpckelsh", 0xee6000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10747 {"wunpckelsw", 0xeea000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10748 {"wunpckilb", 0xee1000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10749 {"wunpckilh", 0xee5000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10750 {"wunpckilw", 0xee9000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10751 {"wxor", 0xee100000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10752 {"wzero", 0xee300000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wzero},
10754 /* Cirrus Maverick instructions. */
10755 {"cfldrs", 0xec100400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_1},
10756 {"cfldrd", 0xec500400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_2},
10757 {"cfldr32", 0xec100500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_3},
10758 {"cfldr64", 0xec500500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_4},
10759 {"cfstrs", 0xec000400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_1},
10760 {"cfstrd", 0xec400400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_2},
10761 {"cfstr32", 0xec000500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_3},
10762 {"cfstr64", 0xec400500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_4},
10763 {"cfmvsr", 0xee000450, 6, ARM_CEXT_MAVERICK, do_mav_binops_2a},
10764 {"cfmvrs", 0xee100450, 6, ARM_CEXT_MAVERICK, do_mav_binops_1a},
10765 {"cfmvdlr", 0xee000410, 7, ARM_CEXT_MAVERICK, do_mav_binops_2b},
10766 {"cfmvrdl", 0xee100410, 7, ARM_CEXT_MAVERICK, do_mav_binops_1b},
10767 {"cfmvdhr", 0xee000430, 7, ARM_CEXT_MAVERICK, do_mav_binops_2b},
10768 {"cfmvrdh", 0xee100430, 7, ARM_CEXT_MAVERICK, do_mav_binops_1b},
10769 {"cfmv64lr", 0xee000510, 8, ARM_CEXT_MAVERICK, do_mav_binops_2c},
10770 {"cfmvr64l", 0xee100510, 8, ARM_CEXT_MAVERICK, do_mav_binops_1c},
10771 {"cfmv64hr", 0xee000530, 8, ARM_CEXT_MAVERICK, do_mav_binops_2c},
10772 {"cfmvr64h", 0xee100530, 8, ARM_CEXT_MAVERICK, do_mav_binops_1c},
10773 {"cfmval32", 0xee200440, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
10774 {"cfmv32al", 0xee100440, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
10775 {"cfmvam32", 0xee200460, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
10776 {"cfmv32am", 0xee100460, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
10777 {"cfmvah32", 0xee200480, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
10778 {"cfmv32ah", 0xee100480, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
10779 {"cfmva32", 0xee2004a0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3a},
10780 {"cfmv32a", 0xee1004a0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3b},
10781 {"cfmva64", 0xee2004c0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3c},
10782 {"cfmv64a", 0xee1004c0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3d},
10783 {"cfmvsc32", 0xee2004e0, 8, ARM_CEXT_MAVERICK, do_mav_dspsc_1},
10784 {"cfmv32sc", 0xee1004e0, 8, ARM_CEXT_MAVERICK, do_mav_dspsc_2},
10785 {"cfcpys", 0xee000400, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
10786 {"cfcpyd", 0xee000420, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
10787 {"cfcvtsd", 0xee000460, 7, ARM_CEXT_MAVERICK, do_mav_binops_1f},
10788 {"cfcvtds", 0xee000440, 7, ARM_CEXT_MAVERICK, do_mav_binops_1g},
10789 {"cfcvt32s", 0xee000480, 8, ARM_CEXT_MAVERICK, do_mav_binops_1h},
10790 {"cfcvt32d", 0xee0004a0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1i},
10791 {"cfcvt64s", 0xee0004c0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1j},
10792 {"cfcvt64d", 0xee0004e0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1k},
10793 {"cfcvts32", 0xee100580, 8, ARM_CEXT_MAVERICK, do_mav_binops_1l},
10794 {"cfcvtd32", 0xee1005a0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1m},
10795 {"cftruncs32", 0xee1005c0, 10, ARM_CEXT_MAVERICK, do_mav_binops_1l},
10796 {"cftruncd32", 0xee1005e0, 10, ARM_CEXT_MAVERICK, do_mav_binops_1m},
10797 {"cfrshl32", 0xee000550, 8, ARM_CEXT_MAVERICK, do_mav_triple_4a},
10798 {"cfrshl64", 0xee000570, 8, ARM_CEXT_MAVERICK, do_mav_triple_4b},
10799 {"cfsh32", 0xee000500, 6, ARM_CEXT_MAVERICK, do_mav_shift_1},
10800 {"cfsh64", 0xee200500, 6, ARM_CEXT_MAVERICK, do_mav_shift_2},
10801 {"cfcmps", 0xee100490, 6, ARM_CEXT_MAVERICK, do_mav_triple_5a},
10802 {"cfcmpd", 0xee1004b0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5b},
10803 {"cfcmp32", 0xee100590, 7, ARM_CEXT_MAVERICK, do_mav_triple_5c},
10804 {"cfcmp64", 0xee1005b0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5d},
10805 {"cfabss", 0xee300400, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
10806 {"cfabsd", 0xee300420, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
10807 {"cfnegs", 0xee300440, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
10808 {"cfnegd", 0xee300460, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
10809 {"cfadds", 0xee300480, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
10810 {"cfaddd", 0xee3004a0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
10811 {"cfsubs", 0xee3004c0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
10812 {"cfsubd", 0xee3004e0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
10813 {"cfmuls", 0xee100400, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
10814 {"cfmuld", 0xee100420, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
10815 {"cfabs32", 0xee300500, 7, ARM_CEXT_MAVERICK, do_mav_binops_1n},
10816 {"cfabs64", 0xee300520, 7, ARM_CEXT_MAVERICK, do_mav_binops_1o},
10817 {"cfneg32", 0xee300540, 7, ARM_CEXT_MAVERICK, do_mav_binops_1n},
10818 {"cfneg64", 0xee300560, 7, ARM_CEXT_MAVERICK, do_mav_binops_1o},
10819 {"cfadd32", 0xee300580, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
10820 {"cfadd64", 0xee3005a0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
10821 {"cfsub32", 0xee3005c0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
10822 {"cfsub64", 0xee3005e0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
10823 {"cfmul32", 0xee100500, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
10824 {"cfmul64", 0xee100520, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
10825 {"cfmac32", 0xee100540, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
10826 {"cfmsc32", 0xee100560, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
10827 {"cfmadd32", 0xee000600, 8, ARM_CEXT_MAVERICK, do_mav_quad_6a},
10828 {"cfmsub32", 0xee100600, 8, ARM_CEXT_MAVERICK, do_mav_quad_6a},
10829 {"cfmadda32", 0xee200600, 9, ARM_CEXT_MAVERICK, do_mav_quad_6b},
10830 {"cfmsuba32", 0xee300600, 9, ARM_CEXT_MAVERICK, do_mav_quad_6b},
10833 /* Iterate over the base tables to create the instruction patterns. */
10835 static void
10836 build_arm_ops_hsh (void)
10838 unsigned int i;
10839 unsigned int j;
10840 static struct obstack insn_obstack;
10842 obstack_begin (&insn_obstack, 4000);
10844 for (i = 0; i < sizeof (insns) / sizeof (struct asm_opcode); i++)
10846 const struct asm_opcode *insn = insns + i;
10848 if (insn->cond_offset != 0)
10850 /* Insn supports conditional execution. Build the varaints
10851 and insert them in the hash table. */
10852 for (j = 0; j < sizeof (conds) / sizeof (struct asm_cond); j++)
10854 unsigned len = strlen (insn->template);
10855 struct asm_opcode *new;
10856 char *template;
10858 new = obstack_alloc (&insn_obstack, sizeof (struct asm_opcode));
10859 /* All condition codes are two characters. */
10860 template = obstack_alloc (&insn_obstack, len + 3);
10862 strncpy (template, insn->template, insn->cond_offset);
10863 strcpy (template + insn->cond_offset, conds[j].template);
10864 if (len > insn->cond_offset)
10865 strcpy (template + insn->cond_offset + 2,
10866 insn->template + insn->cond_offset);
10867 new->template = template;
10868 new->cond_offset = 0;
10869 new->variant = insn->variant;
10870 new->parms = insn->parms;
10871 new->value = (insn->value & ~COND_MASK) | conds[j].value;
10873 hash_insert (arm_ops_hsh, new->template, (PTR) new);
10876 /* Finally, insert the unconditional insn in the table directly;
10877 no need to build a copy. */
10878 hash_insert (arm_ops_hsh, insn->template, (PTR) insn);
10882 #if 0 /* Suppressed - for now. */
10883 #if defined OBJ_ELF || defined OBJ_COFF
10885 #ifdef OBJ_ELF
10886 #define arm_Note Elf_External_Note
10887 #else
10888 typedef struct
10890 unsigned char namesz[4]; /* Size of entry's owner string. */
10891 unsigned char descsz[4]; /* Size of the note descriptor. */
10892 unsigned char type[4]; /* Interpretation of the descriptor. */
10893 char name[1]; /* Start of the name+desc data. */
10894 } arm_Note;
10895 #endif
10897 /* The description is kept to a fix sized in order to make updating
10898 it and merging it easier. */
10899 #define ARM_NOTE_DESCRIPTION_LENGTH 8
10901 static void
10902 arm_add_note (const char * name,
10903 const char * description,
10904 unsigned int type)
10906 arm_Note note ATTRIBUTE_UNUSED;
10907 char * p;
10908 unsigned int name_len;
10910 name_len = (strlen (name) + 1 + 3) & ~3;
10912 p = frag_more (sizeof (note.namesz));
10913 md_number_to_chars (p, (valueT) name_len, sizeof (note.namesz));
10915 p = frag_more (sizeof (note.descsz));
10916 md_number_to_chars (p, (valueT) ARM_NOTE_DESCRIPTION_LENGTH, sizeof (note.descsz));
10918 p = frag_more (sizeof (note.type));
10919 md_number_to_chars (p, (valueT) type, sizeof (note.type));
10921 p = frag_more (name_len);
10922 strcpy (p, name);
10924 p = frag_more (ARM_NOTE_DESCRIPTION_LENGTH);
10925 strncpy (p, description, ARM_NOTE_DESCRIPTION_LENGTH);
10926 frag_align (2, 0, 0);
10928 #endif
10929 #endif
10932 static const struct thumb_opcode tinsns[] =
10934 /* Thumb v1 (ARMv4T). */
10935 {"adc", 0x4140, 2, ARM_EXT_V4T, do_t_arit},
10936 {"add", 0x0000, 2, ARM_EXT_V4T, do_t_add},
10937 {"and", 0x4000, 2, ARM_EXT_V4T, do_t_arit},
10938 {"asr", 0x0000, 2, ARM_EXT_V4T, do_t_asr},
10939 {"b", T_OPCODE_BRANCH, 2, ARM_EXT_V4T, do_t_branch12},
10940 {"beq", 0xd0fe, 2, ARM_EXT_V4T, do_t_branch9},
10941 {"bne", 0xd1fe, 2, ARM_EXT_V4T, do_t_branch9},
10942 {"bcs", 0xd2fe, 2, ARM_EXT_V4T, do_t_branch9},
10943 {"bhs", 0xd2fe, 2, ARM_EXT_V4T, do_t_branch9},
10944 {"bcc", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
10945 {"bul", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
10946 {"blo", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
10947 {"bmi", 0xd4fe, 2, ARM_EXT_V4T, do_t_branch9},
10948 {"bpl", 0xd5fe, 2, ARM_EXT_V4T, do_t_branch9},
10949 {"bvs", 0xd6fe, 2, ARM_EXT_V4T, do_t_branch9},
10950 {"bvc", 0xd7fe, 2, ARM_EXT_V4T, do_t_branch9},
10951 {"bhi", 0xd8fe, 2, ARM_EXT_V4T, do_t_branch9},
10952 {"bls", 0xd9fe, 2, ARM_EXT_V4T, do_t_branch9},
10953 {"bge", 0xdafe, 2, ARM_EXT_V4T, do_t_branch9},
10954 {"blt", 0xdbfe, 2, ARM_EXT_V4T, do_t_branch9},
10955 {"bgt", 0xdcfe, 2, ARM_EXT_V4T, do_t_branch9},
10956 {"ble", 0xddfe, 2, ARM_EXT_V4T, do_t_branch9},
10957 {"bal", 0xdefe, 2, ARM_EXT_V4T, do_t_branch9},
10958 {"bic", 0x4380, 2, ARM_EXT_V4T, do_t_arit},
10959 {"bl", 0xf7fffffe, 4, ARM_EXT_V4T, do_t_branch23},
10960 {"bx", 0x4700, 2, ARM_EXT_V4T, do_t_bx},
10961 {"cmn", T_OPCODE_CMN, 2, ARM_EXT_V4T, do_t_arit},
10962 {"cmp", 0x0000, 2, ARM_EXT_V4T, do_t_compare},
10963 {"eor", 0x4040, 2, ARM_EXT_V4T, do_t_arit},
10964 {"ldmia", 0xc800, 2, ARM_EXT_V4T, do_t_ldmstm},
10965 {"ldr", 0x0000, 2, ARM_EXT_V4T, do_t_ldr},
10966 {"ldrb", 0x0000, 2, ARM_EXT_V4T, do_t_ldrb},
10967 {"ldrh", 0x0000, 2, ARM_EXT_V4T, do_t_ldrh},
10968 {"ldrsb", 0x5600, 2, ARM_EXT_V4T, do_t_lds},
10969 {"ldrsh", 0x5e00, 2, ARM_EXT_V4T, do_t_lds},
10970 {"ldsb", 0x5600, 2, ARM_EXT_V4T, do_t_lds},
10971 {"ldsh", 0x5e00, 2, ARM_EXT_V4T, do_t_lds},
10972 {"lsl", 0x0000, 2, ARM_EXT_V4T, do_t_lsl},
10973 {"lsr", 0x0000, 2, ARM_EXT_V4T, do_t_lsr},
10974 {"mov", 0x0000, 2, ARM_EXT_V4T, do_t_mov},
10975 {"mul", T_OPCODE_MUL, 2, ARM_EXT_V4T, do_t_arit},
10976 {"mvn", T_OPCODE_MVN, 2, ARM_EXT_V4T, do_t_arit},
10977 {"neg", T_OPCODE_NEG, 2, ARM_EXT_V4T, do_t_arit},
10978 {"orr", 0x4300, 2, ARM_EXT_V4T, do_t_arit},
10979 {"pop", 0xbc00, 2, ARM_EXT_V4T, do_t_push_pop},
10980 {"push", 0xb400, 2, ARM_EXT_V4T, do_t_push_pop},
10981 {"ror", 0x41c0, 2, ARM_EXT_V4T, do_t_arit},
10982 {"sbc", 0x4180, 2, ARM_EXT_V4T, do_t_arit},
10983 {"stmia", 0xc000, 2, ARM_EXT_V4T, do_t_ldmstm},
10984 {"str", 0x0000, 2, ARM_EXT_V4T, do_t_str},
10985 {"strb", 0x0000, 2, ARM_EXT_V4T, do_t_strb},
10986 {"strh", 0x0000, 2, ARM_EXT_V4T, do_t_strh},
10987 {"swi", 0xdf00, 2, ARM_EXT_V4T, do_t_swi},
10988 {"sub", 0x0000, 2, ARM_EXT_V4T, do_t_sub},
10989 {"tst", T_OPCODE_TST, 2, ARM_EXT_V4T, do_t_arit},
10990 /* Pseudo ops: */
10991 {"adr", 0x0000, 2, ARM_EXT_V4T, do_t_adr},
10992 {"nop", 0x46C0, 2, ARM_EXT_V4T, do_t_nop}, /* mov r8,r8 */
10993 /* Thumb v2 (ARMv5T). */
10994 {"blx", 0, 0, ARM_EXT_V5T, do_t_blx},
10995 {"bkpt", 0xbe00, 2, ARM_EXT_V5T, do_t_bkpt},
10997 /* ARM V6. */
10998 {"cpsie", 0xb660, 2, ARM_EXT_V6, do_t_cps},
10999 {"cpsid", 0xb670, 2, ARM_EXT_V6, do_t_cps},
11000 {"cpy", 0x4600, 2, ARM_EXT_V6, do_t_cpy},
11001 {"rev", 0xba00, 2, ARM_EXT_V6, do_t_arit},
11002 {"rev16", 0xba40, 2, ARM_EXT_V6, do_t_arit},
11003 {"revsh", 0xbac0, 2, ARM_EXT_V6, do_t_arit},
11004 {"setend", 0xb650, 2, ARM_EXT_V6, do_t_setend},
11005 {"sxth", 0xb200, 2, ARM_EXT_V6, do_t_arit},
11006 {"sxtb", 0xb240, 2, ARM_EXT_V6, do_t_arit},
11007 {"uxth", 0xb280, 2, ARM_EXT_V6, do_t_arit},
11008 {"uxtb", 0xb2c0, 2, ARM_EXT_V6, do_t_arit},
11011 void
11012 md_begin (void)
11014 unsigned mach;
11015 unsigned int i;
11017 if ( (arm_ops_hsh = hash_new ()) == NULL
11018 || (arm_tops_hsh = hash_new ()) == NULL
11019 || (arm_cond_hsh = hash_new ()) == NULL
11020 || (arm_shift_hsh = hash_new ()) == NULL
11021 || (arm_psr_hsh = hash_new ()) == NULL)
11022 as_fatal (_("virtual memory exhausted"));
11024 build_arm_ops_hsh ();
11025 for (i = 0; i < sizeof (tinsns) / sizeof (struct thumb_opcode); i++)
11026 hash_insert (arm_tops_hsh, tinsns[i].template, (PTR) (tinsns + i));
11027 for (i = 0; i < sizeof (conds) / sizeof (struct asm_cond); i++)
11028 hash_insert (arm_cond_hsh, conds[i].template, (PTR) (conds + i));
11029 for (i = 0; i < sizeof (shift_names) / sizeof (struct asm_shift_name); i++)
11030 hash_insert (arm_shift_hsh, shift_names[i].name, (PTR) (shift_names + i));
11031 for (i = 0; i < sizeof (psrs) / sizeof (struct asm_psr); i++)
11032 hash_insert (arm_psr_hsh, psrs[i].template, (PTR) (psrs + i));
11034 for (i = (int) REG_TYPE_FIRST; i < (int) REG_TYPE_MAX; i++)
11035 build_reg_hsh (all_reg_maps + i);
11037 set_constant_flonums ();
11039 /* Set the cpu variant based on the command-line options. We prefer
11040 -mcpu= over -march= if both are set (as for GCC); and we prefer
11041 -mfpu= over any other way of setting the floating point unit.
11042 Use of legacy options with new options are faulted. */
11043 if (legacy_cpu != -1)
11045 if (mcpu_cpu_opt != -1 || march_cpu_opt != -1)
11046 as_bad (_("use of old and new-style options to set CPU type"));
11048 mcpu_cpu_opt = legacy_cpu;
11050 else if (mcpu_cpu_opt == -1)
11051 mcpu_cpu_opt = march_cpu_opt;
11053 if (legacy_fpu != -1)
11055 if (mfpu_opt != -1)
11056 as_bad (_("use of old and new-style options to set FPU type"));
11058 mfpu_opt = legacy_fpu;
11060 else if (mfpu_opt == -1)
11062 #if !(defined (TE_LINUX) || defined (TE_NetBSD))
11063 /* Some environments specify a default FPU. If they don't, infer it
11064 from the processor. */
11065 if (mcpu_fpu_opt != -1)
11066 mfpu_opt = mcpu_fpu_opt;
11067 else
11068 mfpu_opt = march_fpu_opt;
11069 #else
11070 mfpu_opt = FPU_DEFAULT;
11071 #endif
11074 if (mfpu_opt == -1)
11076 if (mcpu_cpu_opt == -1)
11077 mfpu_opt = FPU_DEFAULT;
11078 else if (mcpu_cpu_opt & ARM_EXT_V5)
11079 mfpu_opt = FPU_ARCH_VFP_V2;
11080 else
11081 mfpu_opt = FPU_ARCH_FPA;
11084 if (mcpu_cpu_opt == -1)
11085 mcpu_cpu_opt = CPU_DEFAULT;
11087 cpu_variant = mcpu_cpu_opt | mfpu_opt;
11090 unsigned int flags = 0;
11092 #if defined OBJ_ELF
11093 flags = meabi_flags;
11095 switch (meabi_flags)
11097 case EF_ARM_EABI_UNKNOWN:
11098 #endif
11099 #if defined OBJ_COFF || defined OBJ_ELF
11100 /* Set the flags in the private structure. */
11101 if (uses_apcs_26) flags |= F_APCS26;
11102 if (support_interwork) flags |= F_INTERWORK;
11103 if (uses_apcs_float) flags |= F_APCS_FLOAT;
11104 if (pic_code) flags |= F_PIC;
11105 if ((cpu_variant & FPU_ANY) == FPU_NONE
11106 || (cpu_variant & FPU_ANY) == FPU_ARCH_VFP) /* VFP layout only. */
11107 flags |= F_SOFT_FLOAT;
11109 switch (mfloat_abi_opt)
11111 case ARM_FLOAT_ABI_SOFT:
11112 case ARM_FLOAT_ABI_SOFTFP:
11113 flags |= F_SOFT_FLOAT;
11114 break;
11116 case ARM_FLOAT_ABI_HARD:
11117 if (flags & F_SOFT_FLOAT)
11118 as_bad (_("hard-float conflicts with specified fpu"));
11119 break;
11122 /* Using VFP conventions (even if soft-float). */
11123 if (cpu_variant & FPU_VFP_EXT_NONE)
11124 flags |= F_VFP_FLOAT;
11125 #endif
11126 #if defined OBJ_ELF
11127 if (cpu_variant & FPU_ARCH_MAVERICK)
11128 flags |= EF_ARM_MAVERICK_FLOAT;
11129 break;
11131 case EF_ARM_EABI_VER4:
11132 /* No additional flags to set. */
11133 break;
11135 default:
11136 abort ();
11138 #endif
11139 #if defined OBJ_COFF || defined OBJ_ELF
11140 bfd_set_private_flags (stdoutput, flags);
11142 /* We have run out flags in the COFF header to encode the
11143 status of ATPCS support, so instead we create a dummy,
11144 empty, debug section called .arm.atpcs. */
11145 if (atpcs)
11147 asection * sec;
11149 sec = bfd_make_section (stdoutput, ".arm.atpcs");
11151 if (sec != NULL)
11153 bfd_set_section_flags
11154 (stdoutput, sec, SEC_READONLY | SEC_DEBUGGING /* | SEC_HAS_CONTENTS */);
11155 bfd_set_section_size (stdoutput, sec, 0);
11156 bfd_set_section_contents (stdoutput, sec, NULL, 0, 0);
11159 #endif
11162 /* Record the CPU type as well. */
11163 switch (cpu_variant & ARM_CPU_MASK)
11165 case ARM_2:
11166 mach = bfd_mach_arm_2;
11167 break;
11169 case ARM_3: /* Also ARM_250. */
11170 mach = bfd_mach_arm_2a;
11171 break;
11173 case ARM_6: /* Also ARM_7. */
11174 mach = bfd_mach_arm_3;
11175 break;
11177 default:
11178 mach = bfd_mach_arm_unknown;
11179 break;
11182 /* Catch special cases. */
11183 if (cpu_variant & ARM_CEXT_IWMMXT)
11184 mach = bfd_mach_arm_iWMMXt;
11185 else if (cpu_variant & ARM_CEXT_XSCALE)
11186 mach = bfd_mach_arm_XScale;
11187 else if (cpu_variant & ARM_CEXT_MAVERICK)
11188 mach = bfd_mach_arm_ep9312;
11189 else if (cpu_variant & ARM_EXT_V5E)
11190 mach = bfd_mach_arm_5TE;
11191 else if (cpu_variant & ARM_EXT_V5)
11193 if (cpu_variant & ARM_EXT_V4T)
11194 mach = bfd_mach_arm_5T;
11195 else
11196 mach = bfd_mach_arm_5;
11198 else if (cpu_variant & ARM_EXT_V4)
11200 if (cpu_variant & ARM_EXT_V4T)
11201 mach = bfd_mach_arm_4T;
11202 else
11203 mach = bfd_mach_arm_4;
11205 else if (cpu_variant & ARM_EXT_V3M)
11206 mach = bfd_mach_arm_3M;
11208 #if 0 /* Suppressed - for now. */
11209 #if defined (OBJ_ELF) || defined (OBJ_COFF)
11211 /* Create a .note section to fully identify this arm binary. */
11213 #define NOTE_ARCH_STRING "arch: "
11215 #if defined OBJ_COFF && ! defined NT_VERSION
11216 #define NT_VERSION 1
11217 #define NT_ARCH 2
11218 #endif
11221 segT current_seg = now_seg;
11222 subsegT current_subseg = now_subseg;
11223 asection * arm_arch;
11224 const char * arch_string;
11226 arm_arch = bfd_make_section_old_way (stdoutput, ARM_NOTE_SECTION);
11228 #ifdef OBJ_COFF
11229 bfd_set_section_flags (stdoutput, arm_arch,
11230 SEC_DATA | SEC_ALLOC | SEC_LOAD | SEC_LINK_ONCE \
11231 | SEC_HAS_CONTENTS);
11232 #else
11233 bfd_set_section_flags (stdoutput, arm_arch,
11234 SEC_READONLY | SEC_HAS_CONTENTS);
11235 #endif
11236 arm_arch->output_section = arm_arch;
11237 subseg_set (arm_arch, 0);
11239 switch (mach)
11241 default:
11242 case bfd_mach_arm_unknown: arch_string = "unknown"; break;
11243 case bfd_mach_arm_2: arch_string = "armv2"; break;
11244 case bfd_mach_arm_2a: arch_string = "armv2a"; break;
11245 case bfd_mach_arm_3: arch_string = "armv3"; break;
11246 case bfd_mach_arm_3M: arch_string = "armv3M"; break;
11247 case bfd_mach_arm_4: arch_string = "armv4"; break;
11248 case bfd_mach_arm_4T: arch_string = "armv4t"; break;
11249 case bfd_mach_arm_5: arch_string = "armv5"; break;
11250 case bfd_mach_arm_5T: arch_string = "armv5t"; break;
11251 case bfd_mach_arm_5TE: arch_string = "armv5te"; break;
11252 case bfd_mach_arm_XScale: arch_string = "XScale"; break;
11253 case bfd_mach_arm_ep9312: arch_string = "ep9312"; break;
11254 case bfd_mach_arm_iWMMXt: arch_string = "iWMMXt"; break;
11257 arm_add_note (NOTE_ARCH_STRING, arch_string, NT_ARCH);
11259 subseg_set (current_seg, current_subseg);
11261 #endif
11262 #endif /* Suppressed code. */
11264 bfd_set_arch_mach (stdoutput, TARGET_ARCH, mach);
11267 /* Turn an integer of n bytes (in val) into a stream of bytes appropriate
11268 for use in the a.out file, and stores them in the array pointed to by buf.
11269 This knows about the endian-ness of the target machine and does
11270 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
11271 2 (short) and 4 (long) Floating numbers are put out as a series of
11272 LITTLENUMS (shorts, here at least). */
11274 void
11275 md_number_to_chars (char * buf, valueT val, int n)
11277 if (target_big_endian)
11278 number_to_chars_bigendian (buf, val, n);
11279 else
11280 number_to_chars_littleendian (buf, val, n);
11283 static valueT
11284 md_chars_to_number (char * buf, int n)
11286 valueT result = 0;
11287 unsigned char * where = (unsigned char *) buf;
11289 if (target_big_endian)
11291 while (n--)
11293 result <<= 8;
11294 result |= (*where++ & 255);
11297 else
11299 while (n--)
11301 result <<= 8;
11302 result |= (where[n] & 255);
11306 return result;
11309 /* Turn a string in input_line_pointer into a floating point constant
11310 of type TYPE, and store the appropriate bytes in *LITP. The number
11311 of LITTLENUMS emitted is stored in *SIZEP. An error message is
11312 returned, or NULL on OK.
11314 Note that fp constants aren't represent in the normal way on the ARM.
11315 In big endian mode, things are as expected. However, in little endian
11316 mode fp constants are big-endian word-wise, and little-endian byte-wise
11317 within the words. For example, (double) 1.1 in big endian mode is
11318 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
11319 the byte sequence 99 99 f1 3f 9a 99 99 99.
11321 ??? The format of 12 byte floats is uncertain according to gcc's arm.h. */
11323 char *
11324 md_atof (int type, char * litP, int * sizeP)
11326 int prec;
11327 LITTLENUM_TYPE words[MAX_LITTLENUMS];
11328 char *t;
11329 int i;
11331 switch (type)
11333 case 'f':
11334 case 'F':
11335 case 's':
11336 case 'S':
11337 prec = 2;
11338 break;
11340 case 'd':
11341 case 'D':
11342 case 'r':
11343 case 'R':
11344 prec = 4;
11345 break;
11347 case 'x':
11348 case 'X':
11349 prec = 6;
11350 break;
11352 case 'p':
11353 case 'P':
11354 prec = 6;
11355 break;
11357 default:
11358 *sizeP = 0;
11359 return _("bad call to MD_ATOF()");
11362 t = atof_ieee (input_line_pointer, type, words);
11363 if (t)
11364 input_line_pointer = t;
11365 *sizeP = prec * 2;
11367 if (target_big_endian)
11369 for (i = 0; i < prec; i++)
11371 md_number_to_chars (litP, (valueT) words[i], 2);
11372 litP += 2;
11375 else
11377 if (cpu_variant & FPU_ARCH_VFP)
11378 for (i = prec - 1; i >= 0; i--)
11380 md_number_to_chars (litP, (valueT) words[i], 2);
11381 litP += 2;
11383 else
11384 /* For a 4 byte float the order of elements in `words' is 1 0.
11385 For an 8 byte float the order is 1 0 3 2. */
11386 for (i = 0; i < prec; i += 2)
11388 md_number_to_chars (litP, (valueT) words[i + 1], 2);
11389 md_number_to_chars (litP + 2, (valueT) words[i], 2);
11390 litP += 4;
11394 return 0;
11397 /* The knowledge of the PC's pipeline offset is built into the insns
11398 themselves. */
11400 long
11401 md_pcrel_from (fixS * fixP)
11403 if (fixP->fx_addsy
11404 && S_GET_SEGMENT (fixP->fx_addsy) == undefined_section
11405 && fixP->fx_subsy == NULL)
11406 return 0;
11408 if (fixP->fx_pcrel && (fixP->fx_r_type == BFD_RELOC_ARM_THUMB_ADD))
11410 /* PC relative addressing on the Thumb is slightly odd
11411 as the bottom two bits of the PC are forced to zero
11412 for the calculation. */
11413 return (fixP->fx_where + fixP->fx_frag->fr_address) & ~3;
11416 #ifdef TE_WINCE
11417 /* The pattern was adjusted to accommodate CE's off-by-one fixups,
11418 so we un-adjust here to compensate for the accommodation. */
11419 return fixP->fx_where + fixP->fx_frag->fr_address + 8;
11420 #else
11421 return fixP->fx_where + fixP->fx_frag->fr_address;
11422 #endif
11425 /* Round up a section size to the appropriate boundary. */
11427 valueT
11428 md_section_align (segT segment ATTRIBUTE_UNUSED,
11429 valueT size)
11431 #ifdef OBJ_ELF
11432 return size;
11433 #else
11434 /* Round all sects to multiple of 4. */
11435 return (size + 3) & ~3;
11436 #endif
11439 /* Under ELF we need to default _GLOBAL_OFFSET_TABLE.
11440 Otherwise we have no need to default values of symbols. */
11442 symbolS *
11443 md_undefined_symbol (char * name ATTRIBUTE_UNUSED)
11445 #ifdef OBJ_ELF
11446 if (name[0] == '_' && name[1] == 'G'
11447 && streq (name, GLOBAL_OFFSET_TABLE_NAME))
11449 if (!GOT_symbol)
11451 if (symbol_find (name))
11452 as_bad ("GOT already in the symbol table");
11454 GOT_symbol = symbol_new (name, undefined_section,
11455 (valueT) 0, & zero_address_frag);
11458 return GOT_symbol;
11460 #endif
11462 return 0;
11465 void
11466 md_apply_fix3 (fixS * fixP,
11467 valueT * valP,
11468 segT seg)
11470 offsetT value = * valP;
11471 offsetT newval;
11472 unsigned int newimm;
11473 unsigned long temp;
11474 int sign;
11475 char * buf = fixP->fx_where + fixP->fx_frag->fr_literal;
11476 arm_fix_data * arm_data = (arm_fix_data *) fixP->tc_fix_data;
11478 assert (fixP->fx_r_type < BFD_RELOC_UNUSED);
11480 /* Note whether this will delete the relocation. */
11481 #if 0
11482 /* Patch from REarnshaw to JDavis (disabled for the moment, since it
11483 doesn't work fully.) */
11484 if ((fixP->fx_addsy == 0 || symbol_constant_p (fixP->fx_addsy))
11485 && !fixP->fx_pcrel)
11486 #else
11487 if (fixP->fx_addsy == 0 && !fixP->fx_pcrel)
11488 #endif
11489 fixP->fx_done = 1;
11491 /* If this symbol is in a different section then we need to leave it for
11492 the linker to deal with. Unfortunately, md_pcrel_from can't tell,
11493 so we have to undo it's effects here. */
11494 if (fixP->fx_pcrel)
11496 if (fixP->fx_addsy != NULL
11497 && S_IS_DEFINED (fixP->fx_addsy)
11498 && S_GET_SEGMENT (fixP->fx_addsy) != seg)
11499 value += md_pcrel_from (fixP);
11502 /* Remember value for emit_reloc. */
11503 fixP->fx_addnumber = value;
11505 switch (fixP->fx_r_type)
11507 case BFD_RELOC_ARM_IMMEDIATE:
11508 /* We claim that this fixup has been processed here,
11509 even if in fact we generate an error because we do
11510 not have a reloc for it, so tc_gen_reloc will reject it. */
11511 fixP->fx_done = 1;
11513 if (fixP->fx_addsy
11514 && ! S_IS_DEFINED (fixP->fx_addsy))
11516 as_bad_where (fixP->fx_file, fixP->fx_line,
11517 _("undefined symbol %s used as an immediate value"),
11518 S_GET_NAME (fixP->fx_addsy));
11519 break;
11522 newimm = validate_immediate (value);
11523 temp = md_chars_to_number (buf, INSN_SIZE);
11525 /* If the instruction will fail, see if we can fix things up by
11526 changing the opcode. */
11527 if (newimm == (unsigned int) FAIL
11528 && (newimm = negate_data_op (&temp, value)) == (unsigned int) FAIL)
11530 as_bad_where (fixP->fx_file, fixP->fx_line,
11531 _("invalid constant (%lx) after fixup"),
11532 (unsigned long) value);
11533 break;
11536 newimm |= (temp & 0xfffff000);
11537 md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
11538 break;
11540 case BFD_RELOC_ARM_ADRL_IMMEDIATE:
11542 unsigned int highpart = 0;
11543 unsigned int newinsn = 0xe1a00000; /* nop. */
11545 newimm = validate_immediate (value);
11546 temp = md_chars_to_number (buf, INSN_SIZE);
11548 /* If the instruction will fail, see if we can fix things up by
11549 changing the opcode. */
11550 if (newimm == (unsigned int) FAIL
11551 && (newimm = negate_data_op (& temp, value)) == (unsigned int) FAIL)
11553 /* No ? OK - try using two ADD instructions to generate
11554 the value. */
11555 newimm = validate_immediate_twopart (value, & highpart);
11557 /* Yes - then make sure that the second instruction is
11558 also an add. */
11559 if (newimm != (unsigned int) FAIL)
11560 newinsn = temp;
11561 /* Still No ? Try using a negated value. */
11562 else if ((newimm = validate_immediate_twopart (- value, & highpart)) != (unsigned int) FAIL)
11563 temp = newinsn = (temp & OPCODE_MASK) | OPCODE_SUB << DATA_OP_SHIFT;
11564 /* Otherwise - give up. */
11565 else
11567 as_bad_where (fixP->fx_file, fixP->fx_line,
11568 _("unable to compute ADRL instructions for PC offset of 0x%lx"),
11569 (long) value);
11570 break;
11573 /* Replace the first operand in the 2nd instruction (which
11574 is the PC) with the destination register. We have
11575 already added in the PC in the first instruction and we
11576 do not want to do it again. */
11577 newinsn &= ~ 0xf0000;
11578 newinsn |= ((newinsn & 0x0f000) << 4);
11581 newimm |= (temp & 0xfffff000);
11582 md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
11584 highpart |= (newinsn & 0xfffff000);
11585 md_number_to_chars (buf + INSN_SIZE, (valueT) highpart, INSN_SIZE);
11587 break;
11589 case BFD_RELOC_ARM_OFFSET_IMM:
11590 sign = value >= 0;
11592 if (value < 0)
11593 value = - value;
11595 if (validate_offset_imm (value, 0) == FAIL)
11597 as_bad_where (fixP->fx_file, fixP->fx_line,
11598 _("bad immediate value for offset (%ld)"),
11599 (long) value);
11600 break;
11603 newval = md_chars_to_number (buf, INSN_SIZE);
11604 newval &= 0xff7ff000;
11605 newval |= value | (sign ? INDEX_UP : 0);
11606 md_number_to_chars (buf, newval, INSN_SIZE);
11607 break;
11609 case BFD_RELOC_ARM_OFFSET_IMM8:
11610 case BFD_RELOC_ARM_HWLITERAL:
11611 sign = value >= 0;
11613 if (value < 0)
11614 value = - value;
11616 if (validate_offset_imm (value, 1) == FAIL)
11618 if (fixP->fx_r_type == BFD_RELOC_ARM_HWLITERAL)
11619 as_bad_where (fixP->fx_file, fixP->fx_line,
11620 _("invalid literal constant: pool needs to be closer"));
11621 else
11622 as_bad (_("bad immediate value for half-word offset (%ld)"),
11623 (long) value);
11624 break;
11627 newval = md_chars_to_number (buf, INSN_SIZE);
11628 newval &= 0xff7ff0f0;
11629 newval |= ((value >> 4) << 8) | (value & 0xf) | (sign ? INDEX_UP : 0);
11630 md_number_to_chars (buf, newval, INSN_SIZE);
11631 break;
11633 case BFD_RELOC_ARM_LITERAL:
11634 sign = value >= 0;
11636 if (value < 0)
11637 value = - value;
11639 if (validate_offset_imm (value, 0) == FAIL)
11641 as_bad_where (fixP->fx_file, fixP->fx_line,
11642 _("invalid literal constant: pool needs to be closer"));
11643 break;
11646 newval = md_chars_to_number (buf, INSN_SIZE);
11647 newval &= 0xff7ff000;
11648 newval |= value | (sign ? INDEX_UP : 0);
11649 md_number_to_chars (buf, newval, INSN_SIZE);
11650 break;
11652 case BFD_RELOC_ARM_SHIFT_IMM:
11653 newval = md_chars_to_number (buf, INSN_SIZE);
11654 if (((unsigned long) value) > 32
11655 || (value == 32
11656 && (((newval & 0x60) == 0) || (newval & 0x60) == 0x60)))
11658 as_bad_where (fixP->fx_file, fixP->fx_line,
11659 _("shift expression is too large"));
11660 break;
11663 if (value == 0)
11664 /* Shifts of zero must be done as lsl. */
11665 newval &= ~0x60;
11666 else if (value == 32)
11667 value = 0;
11668 newval &= 0xfffff07f;
11669 newval |= (value & 0x1f) << 7;
11670 md_number_to_chars (buf, newval, INSN_SIZE);
11671 break;
11673 case BFD_RELOC_ARM_SMI:
11674 if (((unsigned long) value) > 0xffff)
11675 as_bad_where (fixP->fx_file, fixP->fx_line,
11676 _("invalid smi expression"));
11677 newval = md_chars_to_number (buf, INSN_SIZE) & 0xfff000f0;
11678 newval |= (value & 0xf) | ((value & 0xfff0) << 4);
11679 md_number_to_chars (buf, newval, INSN_SIZE);
11680 break;
11682 case BFD_RELOC_ARM_SWI:
11683 if (arm_data->thumb_mode)
11685 if (((unsigned long) value) > 0xff)
11686 as_bad_where (fixP->fx_file, fixP->fx_line,
11687 _("invalid swi expression"));
11688 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xff00;
11689 newval |= value;
11690 md_number_to_chars (buf, newval, THUMB_SIZE);
11692 else
11694 if (((unsigned long) value) > 0x00ffffff)
11695 as_bad_where (fixP->fx_file, fixP->fx_line,
11696 _("invalid swi expression"));
11697 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff000000;
11698 newval |= value;
11699 md_number_to_chars (buf, newval, INSN_SIZE);
11701 break;
11703 case BFD_RELOC_ARM_MULTI:
11704 if (((unsigned long) value) > 0xffff)
11705 as_bad_where (fixP->fx_file, fixP->fx_line,
11706 _("invalid expression in load/store multiple"));
11707 newval = value | md_chars_to_number (buf, INSN_SIZE);
11708 md_number_to_chars (buf, newval, INSN_SIZE);
11709 break;
11711 case BFD_RELOC_ARM_PCREL_BRANCH:
11712 newval = md_chars_to_number (buf, INSN_SIZE);
11714 /* Sign-extend a 24-bit number. */
11715 #define SEXT24(x) ((((x) & 0xffffff) ^ (~ 0x7fffff)) + 0x800000)
11717 #ifdef OBJ_ELF
11718 value = fixP->fx_offset;
11719 #endif
11721 /* We are going to store value (shifted right by two) in the
11722 instruction, in a 24 bit, signed field. Thus we need to check
11723 that none of the top 8 bits of the shifted value (top 7 bits of
11724 the unshifted, unsigned value) are set, or that they are all set. */
11725 if ((value & ~ ((offsetT) 0x1ffffff)) != 0
11726 && ((value & ~ ((offsetT) 0x1ffffff)) != ~ ((offsetT) 0x1ffffff)))
11728 #ifdef OBJ_ELF
11729 /* Normally we would be stuck at this point, since we cannot store
11730 the absolute address that is the destination of the branch in the
11731 24 bits of the branch instruction. If however, we happen to know
11732 that the destination of the branch is in the same section as the
11733 branch instruction itself, then we can compute the relocation for
11734 ourselves and not have to bother the linker with it.
11736 FIXME: The test for OBJ_ELF is only here because I have not
11737 worked out how to do this for OBJ_COFF. */
11738 if (fixP->fx_addsy != NULL
11739 && S_IS_DEFINED (fixP->fx_addsy)
11740 && S_GET_SEGMENT (fixP->fx_addsy) == seg)
11742 /* Get pc relative value to go into the branch. */
11743 value = * valP;
11745 /* Permit a backward branch provided that enough bits
11746 are set. Allow a forwards branch, provided that
11747 enough bits are clear. */
11748 if ( (value & ~ ((offsetT) 0x1ffffff)) == ~ ((offsetT) 0x1ffffff)
11749 || (value & ~ ((offsetT) 0x1ffffff)) == 0)
11750 fixP->fx_done = 1;
11753 if (! fixP->fx_done)
11754 #endif
11755 as_bad_where (fixP->fx_file, fixP->fx_line,
11756 _("GAS can't handle same-section branch dest >= 0x04000000"));
11759 value >>= 2;
11760 value += SEXT24 (newval);
11762 if ( (value & ~ ((offsetT) 0xffffff)) != 0
11763 && ((value & ~ ((offsetT) 0xffffff)) != ~ ((offsetT) 0xffffff)))
11764 as_bad_where (fixP->fx_file, fixP->fx_line,
11765 _("out of range branch"));
11767 newval = (value & 0x00ffffff) | (newval & 0xff000000);
11768 md_number_to_chars (buf, newval, INSN_SIZE);
11769 break;
11771 case BFD_RELOC_ARM_PCREL_BLX:
11773 offsetT hbit;
11774 newval = md_chars_to_number (buf, INSN_SIZE);
11776 #ifdef OBJ_ELF
11777 value = fixP->fx_offset;
11778 #endif
11779 hbit = (value >> 1) & 1;
11780 value = (value >> 2) & 0x00ffffff;
11781 value = (value + (newval & 0x00ffffff)) & 0x00ffffff;
11782 newval = value | (newval & 0xfe000000) | (hbit << 24);
11783 md_number_to_chars (buf, newval, INSN_SIZE);
11785 break;
11787 case BFD_RELOC_THUMB_PCREL_BRANCH9: /* Conditional branch. */
11788 newval = md_chars_to_number (buf, THUMB_SIZE);
11790 addressT diff = (newval & 0xff) << 1;
11791 if (diff & 0x100)
11792 diff |= ~0xff;
11794 value += diff;
11795 if ((value & ~0xff) && ((value & ~0xff) != ~0xff))
11796 as_bad_where (fixP->fx_file, fixP->fx_line,
11797 _("branch out of range"));
11798 newval = (newval & 0xff00) | ((value & 0x1ff) >> 1);
11800 md_number_to_chars (buf, newval, THUMB_SIZE);
11801 break;
11803 case BFD_RELOC_THUMB_PCREL_BRANCH12: /* Unconditional branch. */
11804 newval = md_chars_to_number (buf, THUMB_SIZE);
11806 addressT diff = (newval & 0x7ff) << 1;
11807 if (diff & 0x800)
11808 diff |= ~0x7ff;
11810 value += diff;
11811 if ((value & ~0x7ff) && ((value & ~0x7ff) != ~0x7ff))
11812 as_bad_where (fixP->fx_file, fixP->fx_line,
11813 _("branch out of range"));
11814 newval = (newval & 0xf800) | ((value & 0xfff) >> 1);
11816 md_number_to_chars (buf, newval, THUMB_SIZE);
11817 break;
11819 case BFD_RELOC_THUMB_PCREL_BLX:
11820 case BFD_RELOC_THUMB_PCREL_BRANCH23:
11822 offsetT newval2;
11823 addressT diff;
11825 newval = md_chars_to_number (buf, THUMB_SIZE);
11826 newval2 = md_chars_to_number (buf + THUMB_SIZE, THUMB_SIZE);
11827 diff = ((newval & 0x7ff) << 12) | ((newval2 & 0x7ff) << 1);
11828 if (diff & 0x400000)
11829 diff |= ~0x3fffff;
11830 #ifdef OBJ_ELF
11831 value = fixP->fx_offset;
11832 #endif
11833 value += diff;
11835 if ((value & ~0x3fffff) && ((value & ~0x3fffff) != ~0x3fffff))
11836 as_bad_where (fixP->fx_file, fixP->fx_line,
11837 _("branch with link out of range"));
11839 newval = (newval & 0xf800) | ((value & 0x7fffff) >> 12);
11840 newval2 = (newval2 & 0xf800) | ((value & 0xfff) >> 1);
11841 if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX)
11842 /* For a BLX instruction, make sure that the relocation is rounded up
11843 to a word boundary. This follows the semantics of the instruction
11844 which specifies that bit 1 of the target address will come from bit
11845 1 of the base address. */
11846 newval2 = (newval2 + 1) & ~ 1;
11847 md_number_to_chars (buf, newval, THUMB_SIZE);
11848 md_number_to_chars (buf + THUMB_SIZE, newval2, THUMB_SIZE);
11850 break;
11852 case BFD_RELOC_8:
11853 if (fixP->fx_done || fixP->fx_pcrel)
11854 md_number_to_chars (buf, value, 1);
11855 #ifdef OBJ_ELF
11856 else
11858 value = fixP->fx_offset;
11859 md_number_to_chars (buf, value, 1);
11861 #endif
11862 break;
11864 case BFD_RELOC_16:
11865 if (fixP->fx_done || fixP->fx_pcrel)
11866 md_number_to_chars (buf, value, 2);
11867 #ifdef OBJ_ELF
11868 else
11870 value = fixP->fx_offset;
11871 md_number_to_chars (buf, value, 2);
11873 #endif
11874 break;
11876 #ifdef OBJ_ELF
11877 case BFD_RELOC_ARM_GOT32:
11878 case BFD_RELOC_ARM_GOTOFF:
11879 case BFD_RELOC_ARM_TARGET2:
11880 md_number_to_chars (buf, 0, 4);
11881 break;
11882 #endif
11884 case BFD_RELOC_RVA:
11885 case BFD_RELOC_32:
11886 case BFD_RELOC_ARM_TARGET1:
11887 case BFD_RELOC_ARM_ROSEGREL32:
11888 case BFD_RELOC_ARM_SBREL32:
11889 case BFD_RELOC_32_PCREL:
11890 if (fixP->fx_done || fixP->fx_pcrel)
11891 md_number_to_chars (buf, value, 4);
11892 #ifdef OBJ_ELF
11893 else
11895 value = fixP->fx_offset;
11896 md_number_to_chars (buf, value, 4);
11898 #endif
11899 break;
11901 #ifdef OBJ_ELF
11902 case BFD_RELOC_ARM_PREL31:
11903 if (fixP->fx_done || fixP->fx_pcrel)
11905 newval = md_chars_to_number (buf, 4) & 0x80000000;
11906 if ((value ^ (value >> 1)) & 0x40000000)
11908 as_bad_where (fixP->fx_file, fixP->fx_line,
11909 _("rel31 relocation overflow"));
11911 newval |= value & 0x7fffffff;
11912 md_number_to_chars (buf, newval, 4);
11914 break;
11916 case BFD_RELOC_ARM_PLT32:
11917 /* It appears the instruction is fully prepared at this point. */
11918 break;
11919 #endif
11921 case BFD_RELOC_ARM_CP_OFF_IMM:
11922 sign = value >= 0;
11923 if (value < -1023 || value > 1023 || (value & 3))
11924 as_bad_where (fixP->fx_file, fixP->fx_line,
11925 _("illegal value for co-processor offset"));
11926 if (value < 0)
11927 value = -value;
11928 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
11929 newval |= (value >> 2) | (sign ? INDEX_UP : 0);
11930 md_number_to_chars (buf, newval, INSN_SIZE);
11931 break;
11933 case BFD_RELOC_ARM_CP_OFF_IMM_S2:
11934 sign = value >= 0;
11935 if (value < -255 || value > 255)
11936 as_bad_where (fixP->fx_file, fixP->fx_line,
11937 _("Illegal value for co-processor offset"));
11938 if (value < 0)
11939 value = -value;
11940 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
11941 newval |= value | (sign ? INDEX_UP : 0);
11942 md_number_to_chars (buf, newval , INSN_SIZE);
11943 break;
11945 case BFD_RELOC_ARM_THUMB_OFFSET:
11946 newval = md_chars_to_number (buf, THUMB_SIZE);
11947 /* Exactly what ranges, and where the offset is inserted depends
11948 on the type of instruction, we can establish this from the
11949 top 4 bits. */
11950 switch (newval >> 12)
11952 case 4: /* PC load. */
11953 /* Thumb PC loads are somewhat odd, bit 1 of the PC is
11954 forced to zero for these loads, so we will need to round
11955 up the offset if the instruction address is not word
11956 aligned (since the final address produced must be, and
11957 we can only describe word-aligned immediate offsets). */
11959 if ((fixP->fx_frag->fr_address + fixP->fx_where + value) & 3)
11960 as_bad_where (fixP->fx_file, fixP->fx_line,
11961 _("invalid offset, target not word aligned (0x%08X)"),
11962 (unsigned int) (fixP->fx_frag->fr_address
11963 + fixP->fx_where + value));
11965 if ((value + 2) & ~0x3fe)
11966 as_bad_where (fixP->fx_file, fixP->fx_line,
11967 _("invalid offset, value too big (0x%08lX)"),
11968 (long) value);
11970 /* Round up, since pc will be rounded down. */
11971 newval |= (value + 2) >> 2;
11972 break;
11974 case 9: /* SP load/store. */
11975 if (value & ~0x3fc)
11976 as_bad_where (fixP->fx_file, fixP->fx_line,
11977 _("invalid offset, value too big (0x%08lX)"),
11978 (long) value);
11979 newval |= value >> 2;
11980 break;
11982 case 6: /* Word load/store. */
11983 if (value & ~0x7c)
11984 as_bad_where (fixP->fx_file, fixP->fx_line,
11985 _("invalid offset, value too big (0x%08lX)"),
11986 (long) value);
11987 newval |= value << 4; /* 6 - 2. */
11988 break;
11990 case 7: /* Byte load/store. */
11991 if (value & ~0x1f)
11992 as_bad_where (fixP->fx_file, fixP->fx_line,
11993 _("invalid offset, value too big (0x%08lX)"),
11994 (long) value);
11995 newval |= value << 6;
11996 break;
11998 case 8: /* Halfword load/store. */
11999 if (value & ~0x3e)
12000 as_bad_where (fixP->fx_file, fixP->fx_line,
12001 _("invalid offset, value too big (0x%08lX)"),
12002 (long) value);
12003 newval |= value << 5; /* 6 - 1. */
12004 break;
12006 default:
12007 as_bad_where (fixP->fx_file, fixP->fx_line,
12008 "Unable to process relocation for thumb opcode: %lx",
12009 (unsigned long) newval);
12010 break;
12012 md_number_to_chars (buf, newval, THUMB_SIZE);
12013 break;
12015 case BFD_RELOC_ARM_THUMB_ADD:
12016 /* This is a complicated relocation, since we use it for all of
12017 the following immediate relocations:
12019 3bit ADD/SUB
12020 8bit ADD/SUB
12021 9bit ADD/SUB SP word-aligned
12022 10bit ADD PC/SP word-aligned
12024 The type of instruction being processed is encoded in the
12025 instruction field:
12027 0x8000 SUB
12028 0x00F0 Rd
12029 0x000F Rs
12031 newval = md_chars_to_number (buf, THUMB_SIZE);
12033 int rd = (newval >> 4) & 0xf;
12034 int rs = newval & 0xf;
12035 int subtract = newval & 0x8000;
12037 if (rd == REG_SP)
12039 if (value & ~0x1fc)
12040 as_bad_where (fixP->fx_file, fixP->fx_line,
12041 _("invalid immediate for stack address calculation"));
12042 newval = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
12043 newval |= value >> 2;
12045 else if (rs == REG_PC || rs == REG_SP)
12047 if (subtract ||
12048 value & ~0x3fc)
12049 as_bad_where (fixP->fx_file, fixP->fx_line,
12050 _("invalid immediate for address calculation (value = 0x%08lX)"),
12051 (unsigned long) value);
12052 newval = (rs == REG_PC ? T_OPCODE_ADD_PC : T_OPCODE_ADD_SP);
12053 newval |= rd << 8;
12054 newval |= value >> 2;
12056 else if (rs == rd)
12058 if (value & ~0xff)
12059 as_bad_where (fixP->fx_file, fixP->fx_line,
12060 _("invalid 8bit immediate"));
12061 newval = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
12062 newval |= (rd << 8) | value;
12064 else
12066 if (value & ~0x7)
12067 as_bad_where (fixP->fx_file, fixP->fx_line,
12068 _("invalid 3bit immediate"));
12069 newval = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
12070 newval |= rd | (rs << 3) | (value << 6);
12073 md_number_to_chars (buf, newval, THUMB_SIZE);
12074 break;
12076 case BFD_RELOC_ARM_THUMB_IMM:
12077 newval = md_chars_to_number (buf, THUMB_SIZE);
12078 switch (newval >> 11)
12080 case 0x04: /* 8bit immediate MOV. */
12081 case 0x05: /* 8bit immediate CMP. */
12082 if (value < 0 || value > 255)
12083 as_bad_where (fixP->fx_file, fixP->fx_line,
12084 _("invalid immediate: %ld is too large"),
12085 (long) value);
12086 newval |= value;
12087 break;
12089 default:
12090 abort ();
12092 md_number_to_chars (buf, newval, THUMB_SIZE);
12093 break;
12095 case BFD_RELOC_ARM_THUMB_SHIFT:
12096 /* 5bit shift value (0..31). */
12097 if (value < 0 || value > 31)
12098 as_bad_where (fixP->fx_file, fixP->fx_line,
12099 _("illegal Thumb shift value: %ld"), (long) value);
12100 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xf03f;
12101 newval |= value << 6;
12102 md_number_to_chars (buf, newval, THUMB_SIZE);
12103 break;
12105 case BFD_RELOC_VTABLE_INHERIT:
12106 case BFD_RELOC_VTABLE_ENTRY:
12107 fixP->fx_done = 0;
12108 return;
12110 case BFD_RELOC_NONE:
12111 default:
12112 as_bad_where (fixP->fx_file, fixP->fx_line,
12113 _("bad relocation fixup type (%d)"), fixP->fx_r_type);
12117 /* Translate internal representation of relocation info to BFD target
12118 format. */
12120 arelent *
12121 tc_gen_reloc (asection * section ATTRIBUTE_UNUSED,
12122 fixS * fixp)
12124 arelent * reloc;
12125 bfd_reloc_code_real_type code;
12127 reloc = xmalloc (sizeof (arelent));
12129 reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
12130 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
12131 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
12133 /* @@ Why fx_addnumber sometimes and fx_offset other times? */
12134 #ifndef OBJ_ELF
12135 if (fixp->fx_pcrel == 0)
12136 reloc->addend = fixp->fx_offset;
12137 else
12138 reloc->addend = fixp->fx_offset = reloc->address;
12139 #else /* OBJ_ELF */
12140 reloc->addend = fixp->fx_offset;
12141 #endif
12143 switch (fixp->fx_r_type)
12145 case BFD_RELOC_8:
12146 if (fixp->fx_pcrel)
12148 code = BFD_RELOC_8_PCREL;
12149 break;
12152 case BFD_RELOC_16:
12153 if (fixp->fx_pcrel)
12155 code = BFD_RELOC_16_PCREL;
12156 break;
12159 case BFD_RELOC_32:
12160 if (fixp->fx_pcrel)
12162 code = BFD_RELOC_32_PCREL;
12163 break;
12166 case BFD_RELOC_ARM_PCREL_BRANCH:
12167 case BFD_RELOC_ARM_PCREL_BLX:
12168 case BFD_RELOC_RVA:
12169 case BFD_RELOC_THUMB_PCREL_BRANCH9:
12170 case BFD_RELOC_THUMB_PCREL_BRANCH12:
12171 case BFD_RELOC_THUMB_PCREL_BRANCH23:
12172 case BFD_RELOC_THUMB_PCREL_BLX:
12173 case BFD_RELOC_VTABLE_ENTRY:
12174 case BFD_RELOC_VTABLE_INHERIT:
12175 code = fixp->fx_r_type;
12176 break;
12178 case BFD_RELOC_ARM_LITERAL:
12179 case BFD_RELOC_ARM_HWLITERAL:
12180 /* If this is called then the a literal has
12181 been referenced across a section boundary. */
12182 as_bad_where (fixp->fx_file, fixp->fx_line,
12183 _("literal referenced across section boundary"));
12184 return NULL;
12186 #ifdef OBJ_ELF
12187 case BFD_RELOC_ARM_GOT32:
12188 case BFD_RELOC_ARM_GOTOFF:
12189 case BFD_RELOC_ARM_PLT32:
12190 case BFD_RELOC_ARM_TARGET1:
12191 case BFD_RELOC_ARM_ROSEGREL32:
12192 case BFD_RELOC_ARM_SBREL32:
12193 case BFD_RELOC_ARM_PREL31:
12194 case BFD_RELOC_ARM_TARGET2:
12195 code = fixp->fx_r_type;
12196 break;
12197 #endif
12199 case BFD_RELOC_ARM_IMMEDIATE:
12200 as_bad_where (fixp->fx_file, fixp->fx_line,
12201 _("internal relocation (type: IMMEDIATE) not fixed up"));
12202 return NULL;
12204 case BFD_RELOC_ARM_ADRL_IMMEDIATE:
12205 as_bad_where (fixp->fx_file, fixp->fx_line,
12206 _("ADRL used for a symbol not defined in the same file"));
12207 return NULL;
12209 case BFD_RELOC_ARM_OFFSET_IMM:
12210 if (fixp->fx_addsy != NULL
12211 && !S_IS_DEFINED (fixp->fx_addsy)
12212 && S_IS_LOCAL (fixp->fx_addsy))
12214 as_bad_where (fixp->fx_file, fixp->fx_line,
12215 _("undefined local label `%s'"),
12216 S_GET_NAME (fixp->fx_addsy));
12217 return NULL;
12220 as_bad_where (fixp->fx_file, fixp->fx_line,
12221 _("internal_relocation (type: OFFSET_IMM) not fixed up"));
12222 return NULL;
12224 default:
12226 char * type;
12228 switch (fixp->fx_r_type)
12230 case BFD_RELOC_ARM_OFFSET_IMM8: type = "OFFSET_IMM8"; break;
12231 case BFD_RELOC_ARM_SHIFT_IMM: type = "SHIFT_IMM"; break;
12232 case BFD_RELOC_ARM_SMI: type = "SMI"; break;
12233 case BFD_RELOC_ARM_SWI: type = "SWI"; break;
12234 case BFD_RELOC_ARM_MULTI: type = "MULTI"; break;
12235 case BFD_RELOC_ARM_CP_OFF_IMM: type = "CP_OFF_IMM"; break;
12236 case BFD_RELOC_ARM_THUMB_ADD: type = "THUMB_ADD"; break;
12237 case BFD_RELOC_ARM_THUMB_SHIFT: type = "THUMB_SHIFT"; break;
12238 case BFD_RELOC_ARM_THUMB_IMM: type = "THUMB_IMM"; break;
12239 case BFD_RELOC_ARM_THUMB_OFFSET: type = "THUMB_OFFSET"; break;
12240 default: type = _("<unknown>"); break;
12242 as_bad_where (fixp->fx_file, fixp->fx_line,
12243 _("cannot represent %s relocation in this object file format"),
12244 type);
12245 return NULL;
12249 #ifdef OBJ_ELF
12250 if ((code == BFD_RELOC_32_PCREL || code == BFD_RELOC_32)
12251 && GOT_symbol
12252 && fixp->fx_addsy == GOT_symbol)
12254 code = BFD_RELOC_ARM_GOTPC;
12255 reloc->addend = fixp->fx_offset = reloc->address;
12257 #endif
12259 reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
12261 if (reloc->howto == NULL)
12263 as_bad_where (fixp->fx_file, fixp->fx_line,
12264 _("cannot represent %s relocation in this object file format"),
12265 bfd_get_reloc_code_name (code));
12266 return NULL;
12269 /* HACK: Since arm ELF uses Rel instead of Rela, encode the
12270 vtable entry to be used in the relocation's section offset. */
12271 if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
12272 reloc->address = fixp->fx_offset;
12274 return reloc;
12278 md_estimate_size_before_relax (fragS * fragP ATTRIBUTE_UNUSED,
12279 segT segtype ATTRIBUTE_UNUSED)
12281 as_fatal (_("md_estimate_size_before_relax\n"));
12282 return 1;
12285 /* We need to be able to fix up arbitrary expressions in some statements.
12286 This is so that we can handle symbols that are an arbitrary distance from
12287 the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
12288 which returns part of an address in a form which will be valid for
12289 a data instruction. We do this by pushing the expression into a symbol
12290 in the expr_section, and creating a fix for that. */
12292 static void
12293 fix_new_arm (fragS * frag,
12294 int where,
12295 short int size,
12296 expressionS * exp,
12297 int pc_rel,
12298 int reloc)
12300 fixS * new_fix;
12301 arm_fix_data * arm_data;
12303 switch (exp->X_op)
12305 case O_constant:
12306 case O_symbol:
12307 case O_add:
12308 case O_subtract:
12309 new_fix = fix_new_exp (frag, where, size, exp, pc_rel, reloc);
12310 break;
12312 default:
12313 new_fix = fix_new (frag, where, size, make_expr_symbol (exp), 0,
12314 pc_rel, reloc);
12315 break;
12318 /* Mark whether the fix is to a THUMB instruction, or an ARM
12319 instruction. */
12320 arm_data = obstack_alloc (& notes, sizeof (arm_fix_data));
12321 new_fix->tc_fix_data = (PTR) arm_data;
12322 arm_data->thumb_mode = thumb_mode;
12325 static void
12326 output_inst (const char * str)
12328 char * to = NULL;
12330 if (inst.error)
12332 as_bad ("%s -- `%s'", inst.error, str);
12333 return;
12336 to = frag_more (inst.size);
12338 if (thumb_mode && (inst.size > THUMB_SIZE))
12340 assert (inst.size == (2 * THUMB_SIZE));
12341 md_number_to_chars (to, inst.instruction >> 16, THUMB_SIZE);
12342 md_number_to_chars (to + THUMB_SIZE, inst.instruction, THUMB_SIZE);
12344 else if (inst.size > INSN_SIZE)
12346 assert (inst.size == (2 * INSN_SIZE));
12347 md_number_to_chars (to, inst.instruction, INSN_SIZE);
12348 md_number_to_chars (to + INSN_SIZE, inst.instruction, INSN_SIZE);
12350 else
12351 md_number_to_chars (to, inst.instruction, inst.size);
12353 if (inst.reloc.type != BFD_RELOC_NONE)
12354 fix_new_arm (frag_now, to - frag_now->fr_literal,
12355 inst.size, & inst.reloc.exp, inst.reloc.pc_rel,
12356 inst.reloc.type);
12358 #ifdef OBJ_ELF
12359 dwarf2_emit_insn (inst.size);
12360 #endif
12363 void
12364 md_assemble (char * str)
12366 char c;
12367 char *p;
12368 char *start;
12370 /* Align the instruction.
12371 This may not be the right thing to do but ... */
12372 #if 0
12373 arm_align (2, 0);
12374 #endif
12376 /* Align the previous label if needed. */
12377 if (last_label_seen != NULL)
12379 symbol_set_frag (last_label_seen, frag_now);
12380 S_SET_VALUE (last_label_seen, (valueT) frag_now_fix ());
12381 S_SET_SEGMENT (last_label_seen, now_seg);
12384 memset (&inst, '\0', sizeof (inst));
12385 inst.reloc.type = BFD_RELOC_NONE;
12387 skip_whitespace (str);
12389 /* Scan up to the end of the op-code, which must end in white space or
12390 end of string. */
12391 for (start = p = str; *p != '\0'; p++)
12392 if (*p == ' ')
12393 break;
12395 if (p == str)
12397 as_bad (_("no operator -- statement `%s'\n"), str);
12398 return;
12401 if (thumb_mode)
12403 const struct thumb_opcode * opcode;
12405 c = *p;
12406 *p = '\0';
12407 opcode = (const struct thumb_opcode *) hash_find (arm_tops_hsh, str);
12408 *p = c;
12410 if (opcode)
12412 /* Check that this instruction is supported for this CPU. */
12413 if (thumb_mode == 1 && (opcode->variant & cpu_variant) == 0)
12415 as_bad (_("selected processor does not support `%s'"), str);
12416 return;
12419 mapping_state (MAP_THUMB);
12420 inst.instruction = opcode->value;
12421 inst.size = opcode->size;
12422 opcode->parms (p);
12423 output_inst (str);
12424 return;
12427 else
12429 const struct asm_opcode * opcode;
12431 c = *p;
12432 *p = '\0';
12433 opcode = (const struct asm_opcode *) hash_find (arm_ops_hsh, str);
12434 *p = c;
12436 if (opcode)
12438 /* Check that this instruction is supported for this CPU. */
12439 if ((opcode->variant & cpu_variant) == 0)
12441 as_bad (_("selected processor does not support `%s'"), str);
12442 return;
12445 mapping_state (MAP_ARM);
12446 inst.instruction = opcode->value;
12447 inst.size = INSN_SIZE;
12448 opcode->parms (p);
12449 output_inst (str);
12450 return;
12454 /* It wasn't an instruction, but it might be a register alias of the form
12455 alias .req reg. */
12456 if (create_register_alias (str, p))
12457 return;
12459 as_bad (_("bad instruction `%s'"), start);
12462 /* md_parse_option
12463 Invocation line includes a switch not recognized by the base assembler.
12464 See if it's a processor-specific option.
12466 This routine is somewhat complicated by the need for backwards
12467 compatibility (since older releases of gcc can't be changed).
12468 The new options try to make the interface as compatible as
12469 possible with GCC.
12471 New options (supported) are:
12473 -mcpu=<cpu name> Assemble for selected processor
12474 -march=<architecture name> Assemble for selected architecture
12475 -mfpu=<fpu architecture> Assemble for selected FPU.
12476 -EB/-mbig-endian Big-endian
12477 -EL/-mlittle-endian Little-endian
12478 -k Generate PIC code
12479 -mthumb Start in Thumb mode
12480 -mthumb-interwork Code supports ARM/Thumb interworking
12482 For now we will also provide support for:
12484 -mapcs-32 32-bit Program counter
12485 -mapcs-26 26-bit Program counter
12486 -macps-float Floats passed in FP registers
12487 -mapcs-reentrant Reentrant code
12488 -matpcs
12489 (sometime these will probably be replaced with -mapcs=<list of options>
12490 and -matpcs=<list of options>)
12492 The remaining options are only supported for back-wards compatibility.
12493 Cpu variants, the arm part is optional:
12494 -m[arm]1 Currently not supported.
12495 -m[arm]2, -m[arm]250 Arm 2 and Arm 250 processor
12496 -m[arm]3 Arm 3 processor
12497 -m[arm]6[xx], Arm 6 processors
12498 -m[arm]7[xx][t][[d]m] Arm 7 processors
12499 -m[arm]8[10] Arm 8 processors
12500 -m[arm]9[20][tdmi] Arm 9 processors
12501 -mstrongarm[110[0]] StrongARM processors
12502 -mxscale XScale processors
12503 -m[arm]v[2345[t[e]]] Arm architectures
12504 -mall All (except the ARM1)
12505 FP variants:
12506 -mfpa10, -mfpa11 FPA10 and 11 co-processor instructions
12507 -mfpe-old (No float load/store multiples)
12508 -mvfpxd VFP Single precision
12509 -mvfp All VFP
12510 -mno-fpu Disable all floating point instructions
12512 The following CPU names are recognized:
12513 arm1, arm2, arm250, arm3, arm6, arm600, arm610, arm620,
12514 arm7, arm7m, arm7d, arm7dm, arm7di, arm7dmi, arm70, arm700,
12515 arm700i, arm710 arm710t, arm720, arm720t, arm740t, arm710c,
12516 arm7100, arm7500, arm7500fe, arm7tdmi, arm8, arm810, arm9,
12517 arm920, arm920t, arm940t, arm946, arm966, arm9tdmi, arm9e,
12518 arm10t arm10e, arm1020t, arm1020e, arm10200e,
12519 strongarm, strongarm110, strongarm1100, strongarm1110, xscale.
12523 const char * md_shortopts = "m:k";
12525 #ifdef ARM_BI_ENDIAN
12526 #define OPTION_EB (OPTION_MD_BASE + 0)
12527 #define OPTION_EL (OPTION_MD_BASE + 1)
12528 #else
12529 #if TARGET_BYTES_BIG_ENDIAN
12530 #define OPTION_EB (OPTION_MD_BASE + 0)
12531 #else
12532 #define OPTION_EL (OPTION_MD_BASE + 1)
12533 #endif
12534 #endif
12536 struct option md_longopts[] =
12538 #ifdef OPTION_EB
12539 {"EB", no_argument, NULL, OPTION_EB},
12540 #endif
12541 #ifdef OPTION_EL
12542 {"EL", no_argument, NULL, OPTION_EL},
12543 #endif
12544 {NULL, no_argument, NULL, 0}
12547 size_t md_longopts_size = sizeof (md_longopts);
12549 struct arm_option_table
12551 char *option; /* Option name to match. */
12552 char *help; /* Help information. */
12553 int *var; /* Variable to change. */
12554 int value; /* What to change it to. */
12555 char *deprecated; /* If non-null, print this message. */
12558 struct arm_option_table arm_opts[] =
12560 {"k", N_("generate PIC code"), &pic_code, 1, NULL},
12561 {"mthumb", N_("assemble Thumb code"), &thumb_mode, 1, NULL},
12562 {"mthumb-interwork", N_("support ARM/Thumb interworking"),
12563 &support_interwork, 1, NULL},
12564 {"mapcs-32", N_("code uses 32-bit program counter"), &uses_apcs_26, 0, NULL},
12565 {"mapcs-26", N_("code uses 26-bit program counter"), &uses_apcs_26, 1, NULL},
12566 {"mapcs-float", N_("floating point args are in fp regs"), &uses_apcs_float,
12567 1, NULL},
12568 {"mapcs-reentrant", N_("re-entrant code"), &pic_code, 1, NULL},
12569 {"matpcs", N_("code is ATPCS conformant"), &atpcs, 1, NULL},
12570 {"mbig-endian", N_("assemble for big-endian"), &target_big_endian, 1, NULL},
12571 {"mlittle-endian", N_("assemble for little-endian"), &target_big_endian, 1,
12572 NULL},
12574 /* These are recognized by the assembler, but have no affect on code. */
12575 {"mapcs-frame", N_("use frame pointer"), NULL, 0, NULL},
12576 {"mapcs-stack-check", N_("use stack size checking"), NULL, 0, NULL},
12578 /* DON'T add any new processors to this list -- we want the whole list
12579 to go away... Add them to the processors table instead. */
12580 {"marm1", NULL, &legacy_cpu, ARM_ARCH_V1, N_("use -mcpu=arm1")},
12581 {"m1", NULL, &legacy_cpu, ARM_ARCH_V1, N_("use -mcpu=arm1")},
12582 {"marm2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -mcpu=arm2")},
12583 {"m2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -mcpu=arm2")},
12584 {"marm250", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm250")},
12585 {"m250", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm250")},
12586 {"marm3", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm3")},
12587 {"m3", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm3")},
12588 {"marm6", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm6")},
12589 {"m6", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm6")},
12590 {"marm600", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm600")},
12591 {"m600", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm600")},
12592 {"marm610", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm610")},
12593 {"m610", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm610")},
12594 {"marm620", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm620")},
12595 {"m620", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm620")},
12596 {"marm7", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7")},
12597 {"m7", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7")},
12598 {"marm70", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm70")},
12599 {"m70", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm70")},
12600 {"marm700", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700")},
12601 {"m700", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700")},
12602 {"marm700i", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700i")},
12603 {"m700i", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700i")},
12604 {"marm710", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710")},
12605 {"m710", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710")},
12606 {"marm710c", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710c")},
12607 {"m710c", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710c")},
12608 {"marm720", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm720")},
12609 {"m720", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm720")},
12610 {"marm7d", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7d")},
12611 {"m7d", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7d")},
12612 {"marm7di", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7di")},
12613 {"m7di", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7di")},
12614 {"marm7m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7m")},
12615 {"m7m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7m")},
12616 {"marm7dm", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dm")},
12617 {"m7dm", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dm")},
12618 {"marm7dmi", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dmi")},
12619 {"m7dmi", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dmi")},
12620 {"marm7100", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7100")},
12621 {"m7100", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7100")},
12622 {"marm7500", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500")},
12623 {"m7500", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500")},
12624 {"marm7500fe", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500fe")},
12625 {"m7500fe", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500fe")},
12626 {"marm7t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
12627 {"m7t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
12628 {"marm7tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
12629 {"m7tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
12630 {"marm710t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm710t")},
12631 {"m710t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm710t")},
12632 {"marm720t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm720t")},
12633 {"m720t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm720t")},
12634 {"marm740t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm740t")},
12635 {"m740t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm740t")},
12636 {"marm8", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm8")},
12637 {"m8", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm8")},
12638 {"marm810", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm810")},
12639 {"m810", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm810")},
12640 {"marm9", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9")},
12641 {"m9", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9")},
12642 {"marm9tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9tdmi")},
12643 {"m9tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9tdmi")},
12644 {"marm920", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm920")},
12645 {"m920", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm920")},
12646 {"marm940", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm940")},
12647 {"m940", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm940")},
12648 {"mstrongarm", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=strongarm")},
12649 {"mstrongarm110", NULL, &legacy_cpu, ARM_ARCH_V4,
12650 N_("use -mcpu=strongarm110")},
12651 {"mstrongarm1100", NULL, &legacy_cpu, ARM_ARCH_V4,
12652 N_("use -mcpu=strongarm1100")},
12653 {"mstrongarm1110", NULL, &legacy_cpu, ARM_ARCH_V4,
12654 N_("use -mcpu=strongarm1110")},
12655 {"mxscale", NULL, &legacy_cpu, ARM_ARCH_XSCALE, N_("use -mcpu=xscale")},
12656 {"miwmmxt", NULL, &legacy_cpu, ARM_ARCH_IWMMXT, N_("use -mcpu=iwmmxt")},
12657 {"mall", NULL, &legacy_cpu, ARM_ANY, N_("use -mcpu=all")},
12659 /* Architecture variants -- don't add any more to this list either. */
12660 {"mv2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -march=armv2")},
12661 {"marmv2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -march=armv2")},
12662 {"mv2a", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -march=armv2a")},
12663 {"marmv2a", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -march=armv2a")},
12664 {"mv3", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -march=armv3")},
12665 {"marmv3", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -march=armv3")},
12666 {"mv3m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -march=armv3m")},
12667 {"marmv3m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -march=armv3m")},
12668 {"mv4", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -march=armv4")},
12669 {"marmv4", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -march=armv4")},
12670 {"mv4t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -march=armv4t")},
12671 {"marmv4t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -march=armv4t")},
12672 {"mv5", NULL, &legacy_cpu, ARM_ARCH_V5, N_("use -march=armv5")},
12673 {"marmv5", NULL, &legacy_cpu, ARM_ARCH_V5, N_("use -march=armv5")},
12674 {"mv5t", NULL, &legacy_cpu, ARM_ARCH_V5T, N_("use -march=armv5t")},
12675 {"marmv5t", NULL, &legacy_cpu, ARM_ARCH_V5T, N_("use -march=armv5t")},
12676 {"mv5e", NULL, &legacy_cpu, ARM_ARCH_V5TE, N_("use -march=armv5te")},
12677 {"marmv5e", NULL, &legacy_cpu, ARM_ARCH_V5TE, N_("use -march=armv5te")},
12679 /* Floating point variants -- don't add any more to this list either. */
12680 {"mfpe-old", NULL, &legacy_fpu, FPU_ARCH_FPE, N_("use -mfpu=fpe")},
12681 {"mfpa10", NULL, &legacy_fpu, FPU_ARCH_FPA, N_("use -mfpu=fpa10")},
12682 {"mfpa11", NULL, &legacy_fpu, FPU_ARCH_FPA, N_("use -mfpu=fpa11")},
12683 {"mno-fpu", NULL, &legacy_fpu, 0,
12684 N_("use either -mfpu=softfpa or -mfpu=softvfp")},
12686 {NULL, NULL, NULL, 0, NULL}
12689 struct arm_cpu_option_table
12691 char *name;
12692 int value;
12693 /* For some CPUs we assume an FPU unless the user explicitly sets
12694 -mfpu=... */
12695 int default_fpu;
12698 /* This list should, at a minimum, contain all the cpu names
12699 recognized by GCC. */
12700 static struct arm_cpu_option_table arm_cpus[] =
12702 {"all", ARM_ANY, FPU_ARCH_FPA},
12703 {"arm1", ARM_ARCH_V1, FPU_ARCH_FPA},
12704 {"arm2", ARM_ARCH_V2, FPU_ARCH_FPA},
12705 {"arm250", ARM_ARCH_V2S, FPU_ARCH_FPA},
12706 {"arm3", ARM_ARCH_V2S, FPU_ARCH_FPA},
12707 {"arm6", ARM_ARCH_V3, FPU_ARCH_FPA},
12708 {"arm60", ARM_ARCH_V3, FPU_ARCH_FPA},
12709 {"arm600", ARM_ARCH_V3, FPU_ARCH_FPA},
12710 {"arm610", ARM_ARCH_V3, FPU_ARCH_FPA},
12711 {"arm620", ARM_ARCH_V3, FPU_ARCH_FPA},
12712 {"arm7", ARM_ARCH_V3, FPU_ARCH_FPA},
12713 {"arm7m", ARM_ARCH_V3M, FPU_ARCH_FPA},
12714 {"arm7d", ARM_ARCH_V3, FPU_ARCH_FPA},
12715 {"arm7dm", ARM_ARCH_V3M, FPU_ARCH_FPA},
12716 {"arm7di", ARM_ARCH_V3, FPU_ARCH_FPA},
12717 {"arm7dmi", ARM_ARCH_V3M, FPU_ARCH_FPA},
12718 {"arm70", ARM_ARCH_V3, FPU_ARCH_FPA},
12719 {"arm700", ARM_ARCH_V3, FPU_ARCH_FPA},
12720 {"arm700i", ARM_ARCH_V3, FPU_ARCH_FPA},
12721 {"arm710", ARM_ARCH_V3, FPU_ARCH_FPA},
12722 {"arm710t", ARM_ARCH_V4T, FPU_ARCH_FPA},
12723 {"arm720", ARM_ARCH_V3, FPU_ARCH_FPA},
12724 {"arm720t", ARM_ARCH_V4T, FPU_ARCH_FPA},
12725 {"arm740t", ARM_ARCH_V4T, FPU_ARCH_FPA},
12726 {"arm710c", ARM_ARCH_V3, FPU_ARCH_FPA},
12727 {"arm7100", ARM_ARCH_V3, FPU_ARCH_FPA},
12728 {"arm7500", ARM_ARCH_V3, FPU_ARCH_FPA},
12729 {"arm7500fe", ARM_ARCH_V3, FPU_ARCH_FPA},
12730 {"arm7t", ARM_ARCH_V4T, FPU_ARCH_FPA},
12731 {"arm7tdmi", ARM_ARCH_V4T, FPU_ARCH_FPA},
12732 {"arm7tdmi-s", ARM_ARCH_V4T, FPU_ARCH_FPA},
12733 {"arm8", ARM_ARCH_V4, FPU_ARCH_FPA},
12734 {"arm810", ARM_ARCH_V4, FPU_ARCH_FPA},
12735 {"strongarm", ARM_ARCH_V4, FPU_ARCH_FPA},
12736 {"strongarm1", ARM_ARCH_V4, FPU_ARCH_FPA},
12737 {"strongarm110", ARM_ARCH_V4, FPU_ARCH_FPA},
12738 {"strongarm1100", ARM_ARCH_V4, FPU_ARCH_FPA},
12739 {"strongarm1110", ARM_ARCH_V4, FPU_ARCH_FPA},
12740 {"arm9", ARM_ARCH_V4T, FPU_ARCH_FPA},
12741 {"arm920", ARM_ARCH_V4T, FPU_ARCH_FPA},
12742 {"arm920t", ARM_ARCH_V4T, FPU_ARCH_FPA},
12743 {"arm922t", ARM_ARCH_V4T, FPU_ARCH_FPA},
12744 {"arm940t", ARM_ARCH_V4T, FPU_ARCH_FPA},
12745 {"arm9tdmi", ARM_ARCH_V4T, FPU_ARCH_FPA},
12746 /* For V5 or later processors we default to using VFP; but the user
12747 should really set the FPU type explicitly. */
12748 {"arm9e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
12749 {"arm9e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
12750 {"arm926ej", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
12751 {"arm926ejs", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
12752 {"arm926ej-s", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
12753 {"arm946e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
12754 {"arm946e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
12755 {"arm966e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
12756 {"arm966e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
12757 {"arm10t", ARM_ARCH_V5T, FPU_ARCH_VFP_V1},
12758 {"arm10e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
12759 {"arm1020", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
12760 {"arm1020t", ARM_ARCH_V5T, FPU_ARCH_VFP_V1},
12761 {"arm1020e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
12762 {"arm1026ejs", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
12763 {"arm1026ej-s", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
12764 {"arm1136js", ARM_ARCH_V6, FPU_NONE},
12765 {"arm1136j-s", ARM_ARCH_V6, FPU_NONE},
12766 {"arm1136jfs", ARM_ARCH_V6, FPU_ARCH_VFP_V2},
12767 {"arm1136jf-s", ARM_ARCH_V6, FPU_ARCH_VFP_V2},
12768 {"mpcore", ARM_ARCH_V6K, FPU_ARCH_VFP_V2},
12769 {"mpcorenovfp", ARM_ARCH_V6K, FPU_NONE},
12770 {"arm1176jz-s", ARM_ARCH_V6ZK, FPU_NONE},
12771 {"arm1176jzf-s", ARM_ARCH_V6ZK, FPU_ARCH_VFP_V2},
12772 /* ??? XSCALE is really an architecture. */
12773 {"xscale", ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2},
12774 /* ??? iwmmxt is not a processor. */
12775 {"iwmmxt", ARM_ARCH_IWMMXT, FPU_ARCH_VFP_V2},
12776 {"i80200", ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2},
12777 /* Maverick */
12778 {"ep9312", ARM_ARCH_V4T | ARM_CEXT_MAVERICK, FPU_ARCH_MAVERICK},
12779 {NULL, 0, 0}
12782 struct arm_arch_option_table
12784 char *name;
12785 int value;
12786 int default_fpu;
12789 /* This list should, at a minimum, contain all the architecture names
12790 recognized by GCC. */
12791 static struct arm_arch_option_table arm_archs[] =
12793 {"all", ARM_ANY, FPU_ARCH_FPA},
12794 {"armv1", ARM_ARCH_V1, FPU_ARCH_FPA},
12795 {"armv2", ARM_ARCH_V2, FPU_ARCH_FPA},
12796 {"armv2a", ARM_ARCH_V2S, FPU_ARCH_FPA},
12797 {"armv2s", ARM_ARCH_V2S, FPU_ARCH_FPA},
12798 {"armv3", ARM_ARCH_V3, FPU_ARCH_FPA},
12799 {"armv3m", ARM_ARCH_V3M, FPU_ARCH_FPA},
12800 {"armv4", ARM_ARCH_V4, FPU_ARCH_FPA},
12801 {"armv4xm", ARM_ARCH_V4xM, FPU_ARCH_FPA},
12802 {"armv4t", ARM_ARCH_V4T, FPU_ARCH_FPA},
12803 {"armv4txm", ARM_ARCH_V4TxM, FPU_ARCH_FPA},
12804 {"armv5", ARM_ARCH_V5, FPU_ARCH_VFP},
12805 {"armv5t", ARM_ARCH_V5T, FPU_ARCH_VFP},
12806 {"armv5txm", ARM_ARCH_V5TxM, FPU_ARCH_VFP},
12807 {"armv5te", ARM_ARCH_V5TE, FPU_ARCH_VFP},
12808 {"armv5texp", ARM_ARCH_V5TExP, FPU_ARCH_VFP},
12809 {"armv5tej", ARM_ARCH_V5TEJ, FPU_ARCH_VFP},
12810 {"armv6", ARM_ARCH_V6, FPU_ARCH_VFP},
12811 {"armv6j", ARM_ARCH_V6, FPU_ARCH_VFP},
12812 {"armv6k", ARM_ARCH_V6K, FPU_ARCH_VFP},
12813 {"armv6z", ARM_ARCH_V6Z, FPU_ARCH_VFP},
12814 {"armv6zk", ARM_ARCH_V6ZK, FPU_ARCH_VFP},
12815 {"xscale", ARM_ARCH_XSCALE, FPU_ARCH_VFP},
12816 {"iwmmxt", ARM_ARCH_IWMMXT, FPU_ARCH_VFP},
12817 {NULL, 0, 0}
12820 /* ISA extensions in the co-processor space. */
12821 struct arm_arch_extension_table
12823 char *name;
12824 int value;
12827 static struct arm_arch_extension_table arm_extensions[] =
12829 {"maverick", ARM_CEXT_MAVERICK},
12830 {"xscale", ARM_CEXT_XSCALE},
12831 {"iwmmxt", ARM_CEXT_IWMMXT},
12832 {NULL, 0}
12835 struct arm_fpu_option_table
12837 char *name;
12838 int value;
12841 /* This list should, at a minimum, contain all the fpu names
12842 recognized by GCC. */
12843 static struct arm_fpu_option_table arm_fpus[] =
12845 {"softfpa", FPU_NONE},
12846 {"fpe", FPU_ARCH_FPE},
12847 {"fpe2", FPU_ARCH_FPE},
12848 {"fpe3", FPU_ARCH_FPA}, /* Third release supports LFM/SFM. */
12849 {"fpa", FPU_ARCH_FPA},
12850 {"fpa10", FPU_ARCH_FPA},
12851 {"fpa11", FPU_ARCH_FPA},
12852 {"arm7500fe", FPU_ARCH_FPA},
12853 {"softvfp", FPU_ARCH_VFP},
12854 {"softvfp+vfp", FPU_ARCH_VFP_V2},
12855 {"vfp", FPU_ARCH_VFP_V2},
12856 {"vfp9", FPU_ARCH_VFP_V2},
12857 {"vfp10", FPU_ARCH_VFP_V2},
12858 {"vfp10-r0", FPU_ARCH_VFP_V1},
12859 {"vfpxd", FPU_ARCH_VFP_V1xD},
12860 {"arm1020t", FPU_ARCH_VFP_V1},
12861 {"arm1020e", FPU_ARCH_VFP_V2},
12862 {"arm1136jfs", FPU_ARCH_VFP_V2},
12863 {"arm1136jf-s", FPU_ARCH_VFP_V2},
12864 {"maverick", FPU_ARCH_MAVERICK},
12865 {NULL, 0}
12868 struct arm_float_abi_option_table
12870 char *name;
12871 int value;
12874 static struct arm_float_abi_option_table arm_float_abis[] =
12876 {"hard", ARM_FLOAT_ABI_HARD},
12877 {"softfp", ARM_FLOAT_ABI_SOFTFP},
12878 {"soft", ARM_FLOAT_ABI_SOFT},
12879 {NULL, 0}
12882 struct arm_eabi_option_table
12884 char *name;
12885 unsigned int value;
12888 #ifdef OBJ_ELF
12889 /* We only know how to output GNU and ver 4 (AAELF) formats. */
12890 static struct arm_eabi_option_table arm_eabis[] =
12892 {"gnu", EF_ARM_EABI_UNKNOWN},
12893 {"4", EF_ARM_EABI_VER4},
12894 {NULL, 0}
12896 #endif
12898 struct arm_long_option_table
12900 char * option; /* Substring to match. */
12901 char * help; /* Help information. */
12902 int (* func) (char * subopt); /* Function to decode sub-option. */
12903 char * deprecated; /* If non-null, print this message. */
12906 static int
12907 arm_parse_extension (char * str, int * opt_p)
12909 while (str != NULL && *str != 0)
12911 struct arm_arch_extension_table * opt;
12912 char * ext;
12913 int optlen;
12915 if (*str != '+')
12917 as_bad (_("invalid architectural extension"));
12918 return 0;
12921 str++;
12922 ext = strchr (str, '+');
12924 if (ext != NULL)
12925 optlen = ext - str;
12926 else
12927 optlen = strlen (str);
12929 if (optlen == 0)
12931 as_bad (_("missing architectural extension"));
12932 return 0;
12935 for (opt = arm_extensions; opt->name != NULL; opt++)
12936 if (strncmp (opt->name, str, optlen) == 0)
12938 *opt_p |= opt->value;
12939 break;
12942 if (opt->name == NULL)
12944 as_bad (_("unknown architectural extnsion `%s'"), str);
12945 return 0;
12948 str = ext;
12951 return 1;
12954 static int
12955 arm_parse_cpu (char * str)
12957 struct arm_cpu_option_table * opt;
12958 char * ext = strchr (str, '+');
12959 int optlen;
12961 if (ext != NULL)
12962 optlen = ext - str;
12963 else
12964 optlen = strlen (str);
12966 if (optlen == 0)
12968 as_bad (_("missing cpu name `%s'"), str);
12969 return 0;
12972 for (opt = arm_cpus; opt->name != NULL; opt++)
12973 if (strncmp (opt->name, str, optlen) == 0)
12975 mcpu_cpu_opt = opt->value;
12976 mcpu_fpu_opt = opt->default_fpu;
12978 if (ext != NULL)
12979 return arm_parse_extension (ext, &mcpu_cpu_opt);
12981 return 1;
12984 as_bad (_("unknown cpu `%s'"), str);
12985 return 0;
12988 static int
12989 arm_parse_arch (char * str)
12991 struct arm_arch_option_table *opt;
12992 char *ext = strchr (str, '+');
12993 int optlen;
12995 if (ext != NULL)
12996 optlen = ext - str;
12997 else
12998 optlen = strlen (str);
13000 if (optlen == 0)
13002 as_bad (_("missing architecture name `%s'"), str);
13003 return 0;
13007 for (opt = arm_archs; opt->name != NULL; opt++)
13008 if (streq (opt->name, str))
13010 march_cpu_opt = opt->value;
13011 march_fpu_opt = opt->default_fpu;
13013 if (ext != NULL)
13014 return arm_parse_extension (ext, &march_cpu_opt);
13016 return 1;
13019 as_bad (_("unknown architecture `%s'\n"), str);
13020 return 0;
13023 static int
13024 arm_parse_fpu (char * str)
13026 struct arm_fpu_option_table * opt;
13028 for (opt = arm_fpus; opt->name != NULL; opt++)
13029 if (streq (opt->name, str))
13031 mfpu_opt = opt->value;
13032 return 1;
13035 as_bad (_("unknown floating point format `%s'\n"), str);
13036 return 0;
13039 static int
13040 arm_parse_float_abi (char * str)
13042 struct arm_float_abi_option_table * opt;
13044 for (opt = arm_float_abis; opt->name != NULL; opt++)
13045 if (streq (opt->name, str))
13047 mfloat_abi_opt = opt->value;
13048 return 1;
13051 as_bad (_("unknown floating point abi `%s'\n"), str);
13052 return 0;
13055 #ifdef OBJ_ELF
13056 static int
13057 arm_parse_eabi (char * str)
13059 struct arm_eabi_option_table *opt;
13061 for (opt = arm_eabis; opt->name != NULL; opt++)
13062 if (streq (opt->name, str))
13064 meabi_flags = opt->value;
13065 return 1;
13067 as_bad (_("unknown EABI `%s'\n"), str);
13068 return 0;
13070 #endif
13072 struct arm_long_option_table arm_long_opts[] =
13074 {"mcpu=", N_("<cpu name>\t assemble for CPU <cpu name>"),
13075 arm_parse_cpu, NULL},
13076 {"march=", N_("<arch name>\t assemble for architecture <arch name>"),
13077 arm_parse_arch, NULL},
13078 {"mfpu=", N_("<fpu name>\t assemble for FPU architecture <fpu name>"),
13079 arm_parse_fpu, NULL},
13080 {"mfloat-abi=", N_("<abi>\t assemble for floating point ABI <abi>"),
13081 arm_parse_float_abi, NULL},
13082 #ifdef OBJ_ELF
13083 {"meabi=", N_("<ver>\t assemble for eabi version <ver>"),
13084 arm_parse_eabi, NULL},
13085 #endif
13086 {NULL, NULL, 0, NULL}
13090 md_parse_option (int c, char * arg)
13092 struct arm_option_table *opt;
13093 struct arm_long_option_table *lopt;
13095 switch (c)
13097 #ifdef OPTION_EB
13098 case OPTION_EB:
13099 target_big_endian = 1;
13100 break;
13101 #endif
13103 #ifdef OPTION_EL
13104 case OPTION_EL:
13105 target_big_endian = 0;
13106 break;
13107 #endif
13109 case 'a':
13110 /* Listing option. Just ignore these, we don't support additional
13111 ones. */
13112 return 0;
13114 default:
13115 for (opt = arm_opts; opt->option != NULL; opt++)
13117 if (c == opt->option[0]
13118 && ((arg == NULL && opt->option[1] == 0)
13119 || streq (arg, opt->option + 1)))
13121 #if WARN_DEPRECATED
13122 /* If the option is deprecated, tell the user. */
13123 if (opt->deprecated != NULL)
13124 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c,
13125 arg ? arg : "", _(opt->deprecated));
13126 #endif
13128 if (opt->var != NULL)
13129 *opt->var = opt->value;
13131 return 1;
13135 for (lopt = arm_long_opts; lopt->option != NULL; lopt++)
13137 /* These options are expected to have an argument. */
13138 if (c == lopt->option[0]
13139 && arg != NULL
13140 && strncmp (arg, lopt->option + 1,
13141 strlen (lopt->option + 1)) == 0)
13143 #if WARN_DEPRECATED
13144 /* If the option is deprecated, tell the user. */
13145 if (lopt->deprecated != NULL)
13146 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c, arg,
13147 _(lopt->deprecated));
13148 #endif
13150 /* Call the sup-option parser. */
13151 return lopt->func (arg + strlen (lopt->option) - 1);
13155 return 0;
13158 return 1;
13161 void
13162 md_show_usage (FILE * fp)
13164 struct arm_option_table *opt;
13165 struct arm_long_option_table *lopt;
13167 fprintf (fp, _(" ARM-specific assembler options:\n"));
13169 for (opt = arm_opts; opt->option != NULL; opt++)
13170 if (opt->help != NULL)
13171 fprintf (fp, " -%-23s%s\n", opt->option, _(opt->help));
13173 for (lopt = arm_long_opts; lopt->option != NULL; lopt++)
13174 if (lopt->help != NULL)
13175 fprintf (fp, " -%s%s\n", lopt->option, _(lopt->help));
13177 #ifdef OPTION_EB
13178 fprintf (fp, _("\
13179 -EB assemble code for a big-endian cpu\n"));
13180 #endif
13182 #ifdef OPTION_EL
13183 fprintf (fp, _("\
13184 -EL assemble code for a little-endian cpu\n"));
13185 #endif
13188 /* This fix_new is called by cons via TC_CONS_FIX_NEW. */
13190 void
13191 cons_fix_new_arm (fragS * frag,
13192 int where,
13193 int size,
13194 expressionS * exp)
13196 bfd_reloc_code_real_type type;
13197 int pcrel = 0;
13199 /* Pick a reloc.
13200 FIXME: @@ Should look at CPU word size. */
13201 switch (size)
13203 case 1:
13204 type = BFD_RELOC_8;
13205 break;
13206 case 2:
13207 type = BFD_RELOC_16;
13208 break;
13209 case 4:
13210 default:
13211 type = BFD_RELOC_32;
13212 break;
13213 case 8:
13214 type = BFD_RELOC_64;
13215 break;
13218 fix_new_exp (frag, where, (int) size, exp, pcrel, type);
13221 /* A good place to do this, although this was probably not intended
13222 for this kind of use. We need to dump the literal pool before
13223 references are made to a null symbol pointer. */
13225 void
13226 arm_cleanup (void)
13228 literal_pool * pool;
13230 for (pool = list_of_pools; pool; pool = pool->next)
13232 /* Put it at the end of the relevent section. */
13233 subseg_set (pool->section, pool->sub_section);
13234 #ifdef OBJ_ELF
13235 arm_elf_change_section ();
13236 #endif
13237 s_ltorg (0);
13241 void
13242 arm_start_line_hook (void)
13244 last_label_seen = NULL;
13247 void
13248 arm_frob_label (symbolS * sym)
13250 last_label_seen = sym;
13252 ARM_SET_THUMB (sym, thumb_mode);
13254 #if defined OBJ_COFF || defined OBJ_ELF
13255 ARM_SET_INTERWORK (sym, support_interwork);
13256 #endif
13258 /* Note - do not allow local symbols (.Lxxx) to be labeled
13259 as Thumb functions. This is because these labels, whilst
13260 they exist inside Thumb code, are not the entry points for
13261 possible ARM->Thumb calls. Also, these labels can be used
13262 as part of a computed goto or switch statement. eg gcc
13263 can generate code that looks like this:
13265 ldr r2, [pc, .Laaa]
13266 lsl r3, r3, #2
13267 ldr r2, [r3, r2]
13268 mov pc, r2
13270 .Lbbb: .word .Lxxx
13271 .Lccc: .word .Lyyy
13272 ..etc...
13273 .Laaa: .word Lbbb
13275 The first instruction loads the address of the jump table.
13276 The second instruction converts a table index into a byte offset.
13277 The third instruction gets the jump address out of the table.
13278 The fourth instruction performs the jump.
13280 If the address stored at .Laaa is that of a symbol which has the
13281 Thumb_Func bit set, then the linker will arrange for this address
13282 to have the bottom bit set, which in turn would mean that the
13283 address computation performed by the third instruction would end
13284 up with the bottom bit set. Since the ARM is capable of unaligned
13285 word loads, the instruction would then load the incorrect address
13286 out of the jump table, and chaos would ensue. */
13287 if (label_is_thumb_function_name
13288 && (S_GET_NAME (sym)[0] != '.' || S_GET_NAME (sym)[1] != 'L')
13289 && (bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
13291 /* When the address of a Thumb function is taken the bottom
13292 bit of that address should be set. This will allow
13293 interworking between Arm and Thumb functions to work
13294 correctly. */
13296 THUMB_SET_FUNC (sym, 1);
13298 label_is_thumb_function_name = FALSE;
13302 /* Adjust the symbol table. This marks Thumb symbols as distinct from
13303 ARM ones. */
13305 void
13306 arm_adjust_symtab (void)
13308 #ifdef OBJ_COFF
13309 symbolS * sym;
13311 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
13313 if (ARM_IS_THUMB (sym))
13315 if (THUMB_IS_FUNC (sym))
13317 /* Mark the symbol as a Thumb function. */
13318 if ( S_GET_STORAGE_CLASS (sym) == C_STAT
13319 || S_GET_STORAGE_CLASS (sym) == C_LABEL) /* This can happen! */
13320 S_SET_STORAGE_CLASS (sym, C_THUMBSTATFUNC);
13322 else if (S_GET_STORAGE_CLASS (sym) == C_EXT)
13323 S_SET_STORAGE_CLASS (sym, C_THUMBEXTFUNC);
13324 else
13325 as_bad (_("%s: unexpected function type: %d"),
13326 S_GET_NAME (sym), S_GET_STORAGE_CLASS (sym));
13328 else switch (S_GET_STORAGE_CLASS (sym))
13330 case C_EXT:
13331 S_SET_STORAGE_CLASS (sym, C_THUMBEXT);
13332 break;
13333 case C_STAT:
13334 S_SET_STORAGE_CLASS (sym, C_THUMBSTAT);
13335 break;
13336 case C_LABEL:
13337 S_SET_STORAGE_CLASS (sym, C_THUMBLABEL);
13338 break;
13339 default:
13340 /* Do nothing. */
13341 break;
13345 if (ARM_IS_INTERWORK (sym))
13346 coffsymbol (symbol_get_bfdsym (sym))->native->u.syment.n_flags = 0xFF;
13348 #endif
13349 #ifdef OBJ_ELF
13350 symbolS * sym;
13351 char bind;
13353 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
13355 if (ARM_IS_THUMB (sym))
13357 elf_symbol_type * elf_sym;
13359 elf_sym = elf_symbol (symbol_get_bfdsym (sym));
13360 bind = ELF_ST_BIND (elf_sym);
13362 /* If it's a .thumb_func, declare it as so,
13363 otherwise tag label as .code 16. */
13364 if (THUMB_IS_FUNC (sym))
13365 elf_sym->internal_elf_sym.st_info =
13366 ELF_ST_INFO (bind, STT_ARM_TFUNC);
13367 else
13368 elf_sym->internal_elf_sym.st_info =
13369 ELF_ST_INFO (bind, STT_ARM_16BIT);
13372 #endif
13376 arm_data_in_code (void)
13378 if (thumb_mode && ! strncmp (input_line_pointer + 1, "data:", 5))
13380 *input_line_pointer = '/';
13381 input_line_pointer += 5;
13382 *input_line_pointer = 0;
13383 return 1;
13386 return 0;
13389 char *
13390 arm_canonicalize_symbol_name (char * name)
13392 int len;
13394 if (thumb_mode && (len = strlen (name)) > 5
13395 && streq (name + len - 5, "/data"))
13396 *(name + len - 5) = 0;
13398 return name;
13401 #if defined OBJ_COFF || defined OBJ_ELF
13402 void
13403 arm_validate_fix (fixS * fixP)
13405 /* If the destination of the branch is a defined symbol which does not have
13406 the THUMB_FUNC attribute, then we must be calling a function which has
13407 the (interfacearm) attribute. We look for the Thumb entry point to that
13408 function and change the branch to refer to that function instead. */
13409 if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23
13410 && fixP->fx_addsy != NULL
13411 && S_IS_DEFINED (fixP->fx_addsy)
13412 && ! THUMB_IS_FUNC (fixP->fx_addsy))
13414 fixP->fx_addsy = find_real_start (fixP->fx_addsy);
13417 #endif
13420 arm_force_relocation (struct fix * fixp)
13422 #if defined (OBJ_COFF) && defined (TE_PE)
13423 if (fixp->fx_r_type == BFD_RELOC_RVA)
13424 return 1;
13425 #endif
13426 #ifdef OBJ_ELF
13427 if (fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH
13428 || fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BLX
13429 || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX
13430 || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23)
13431 return 1;
13432 #endif
13434 /* Resolve these relocations even if the symbol is extern or weak. */
13435 if (fixp->fx_r_type == BFD_RELOC_ARM_IMMEDIATE
13436 || fixp->fx_r_type == BFD_RELOC_ARM_OFFSET_IMM
13437 || fixp->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE)
13438 return 0;
13440 return generic_force_reloc (fixp);
13443 #ifdef OBJ_COFF
13444 /* This is a little hack to help the gas/arm/adrl.s test. It prevents
13445 local labels from being added to the output symbol table when they
13446 are used with the ADRL pseudo op. The ADRL relocation should always
13447 be resolved before the binbary is emitted, so it is safe to say that
13448 it is adjustable. */
13450 bfd_boolean
13451 arm_fix_adjustable (fixS * fixP)
13453 if (fixP->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE)
13454 return 1;
13455 return 0;
13457 #endif
13459 #ifdef OBJ_ELF
13460 /* Relocations against Thumb function names must be left unadjusted,
13461 so that the linker can use this information to correctly set the
13462 bottom bit of their addresses. The MIPS version of this function
13463 also prevents relocations that are mips-16 specific, but I do not
13464 know why it does this.
13466 FIXME:
13467 There is one other problem that ought to be addressed here, but
13468 which currently is not: Taking the address of a label (rather
13469 than a function) and then later jumping to that address. Such
13470 addresses also ought to have their bottom bit set (assuming that
13471 they reside in Thumb code), but at the moment they will not. */
13473 bfd_boolean
13474 arm_fix_adjustable (fixS * fixP)
13476 if (fixP->fx_addsy == NULL)
13477 return 1;
13479 if (THUMB_IS_FUNC (fixP->fx_addsy)
13480 && fixP->fx_subsy == NULL)
13481 return 0;
13483 /* We need the symbol name for the VTABLE entries. */
13484 if ( fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
13485 || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
13486 return 0;
13488 /* Don't allow symbols to be discarded on GOT related relocs. */
13489 if (fixP->fx_r_type == BFD_RELOC_ARM_PLT32
13490 || fixP->fx_r_type == BFD_RELOC_ARM_GOT32
13491 || fixP->fx_r_type == BFD_RELOC_ARM_GOTOFF
13492 || fixP->fx_r_type == BFD_RELOC_ARM_TARGET2)
13493 return 0;
13495 return 1;
13498 const char *
13499 elf32_arm_target_format (void)
13501 #ifdef TE_SYMBIAN
13502 return (target_big_endian
13503 ? "elf32-bigarm-symbian"
13504 : "elf32-littlearm-symbian");
13505 #else
13506 if (target_big_endian)
13507 return "elf32-bigarm";
13508 else
13509 return "elf32-littlearm";
13510 #endif
13513 void
13514 armelf_frob_symbol (symbolS * symp,
13515 int * puntp)
13517 elf_frob_symbol (symp, puntp);
13520 static void
13521 s_arm_elf_cons (int nbytes)
13523 expressionS exp;
13525 #ifdef md_flush_pending_output
13526 md_flush_pending_output ();
13527 #endif
13529 if (is_it_end_of_statement ())
13531 demand_empty_rest_of_line ();
13532 return;
13535 #ifdef md_cons_align
13536 md_cons_align (nbytes);
13537 #endif
13539 mapping_state (MAP_DATA);
13542 bfd_reloc_code_real_type reloc;
13544 expression (& exp);
13546 if (exp.X_op == O_symbol
13547 && * input_line_pointer == '('
13548 && (reloc = arm_parse_reloc ()) != BFD_RELOC_UNUSED)
13550 reloc_howto_type *howto = bfd_reloc_type_lookup (stdoutput, reloc);
13551 int size = bfd_get_reloc_size (howto);
13553 if (size > nbytes)
13554 as_bad ("%s relocations do not fit in %d bytes",
13555 howto->name, nbytes);
13556 else
13558 char *p = frag_more ((int) nbytes);
13559 int offset = nbytes - size;
13561 fix_new_exp (frag_now, p - frag_now->fr_literal + offset, size,
13562 &exp, 0, reloc);
13565 else
13566 emit_expr (&exp, (unsigned int) nbytes);
13568 while (*input_line_pointer++ == ',');
13570 /* Put terminator back into stream. */
13571 input_line_pointer --;
13572 demand_empty_rest_of_line ();
13576 /* Parse a .rel31 directive. */
13578 static void
13579 s_arm_rel31 (int ignored ATTRIBUTE_UNUSED)
13581 expressionS exp;
13582 char *p;
13583 valueT highbit;
13585 SKIP_WHITESPACE ();
13587 highbit = 0;
13588 if (*input_line_pointer == '1')
13589 highbit = 0x80000000;
13590 else if (*input_line_pointer != '0')
13591 as_bad (_("expected 0 or 1"));
13593 input_line_pointer++;
13594 SKIP_WHITESPACE ();
13595 if (*input_line_pointer != ',')
13596 as_bad (_("missing comma"));
13597 input_line_pointer++;
13599 #ifdef md_flush_pending_output
13600 md_flush_pending_output ();
13601 #endif
13603 #ifdef md_cons_align
13604 md_cons_align (4);
13605 #endif
13607 mapping_state (MAP_DATA);
13609 expression (&exp);
13611 p = frag_more (4);
13612 md_number_to_chars (p, highbit, 4);
13613 fix_new_arm (frag_now, p - frag_now->fr_literal, 4, &exp, 1,
13614 BFD_RELOC_ARM_PREL31);
13616 demand_empty_rest_of_line ();
13619 /* Code to deal with unwinding tables. */
13621 static void add_unwind_adjustsp (offsetT);
13623 /* Switch to section NAME and create section if necessary. It's
13624 rather ugly that we have to manipulate input_line_pointer but I
13625 don't see any other way to accomplish the same thing without
13626 changing obj-elf.c (which may be the Right Thing, in the end).
13627 Copied from tc-ia64.c. */
13629 static void
13630 set_section (char *name)
13632 char *saved_input_line_pointer;
13634 saved_input_line_pointer = input_line_pointer;
13635 input_line_pointer = name;
13636 obj_elf_section (0);
13637 input_line_pointer = saved_input_line_pointer;
13640 /* Cenerate and deferred unwind frame offset. */
13642 static void
13643 flush_pending_unwind (void)
13645 offsetT offset;
13647 offset = unwind.pending_offset;
13648 unwind.pending_offset = 0;
13649 if (offset != 0)
13650 add_unwind_adjustsp (offset);
13653 /* Add an opcode to this list for this function. Two-byte opcodes should
13654 be passed as op[0] << 8 | op[1]. The list of opcodes is built in reverse
13655 order. */
13657 static void
13658 add_unwind_opcode (valueT op, int length)
13660 /* Add any deferred stack adjustment. */
13661 if (unwind.pending_offset)
13662 flush_pending_unwind ();
13664 unwind.sp_restored = 0;
13666 if (unwind.opcode_count + length > unwind.opcode_alloc)
13668 unwind.opcode_alloc += ARM_OPCODE_CHUNK_SIZE;
13669 if (unwind.opcodes)
13670 unwind.opcodes = xrealloc (unwind.opcodes,
13671 unwind.opcode_alloc);
13672 else
13673 unwind.opcodes = xmalloc (unwind.opcode_alloc);
13675 while (length > 0)
13677 length--;
13678 unwind.opcodes[unwind.opcode_count] = op & 0xff;
13679 op >>= 8;
13680 unwind.opcode_count++;
13684 /* Add unwind opcodes to adjust the stack pointer. */
13686 static void
13687 add_unwind_adjustsp (offsetT offset)
13689 valueT op;
13691 if (offset > 0x200)
13693 /* We need at most 5 bytes to hold a 32-bit value in a uleb128. */
13694 char bytes[5];
13695 int n;
13696 valueT o;
13698 /* Long form: 0xb2, uleb128. */
13699 /* This might not fit in a word so add the individual bytes,
13700 remembering the list is built in reverse order. */
13701 o = (valueT) ((offset - 0x204) >> 2);
13702 if (o == 0)
13703 add_unwind_opcode (0, 1);
13705 /* Calculate the uleb128 encoding of the offset. */
13706 n = 0;
13707 while (o)
13709 bytes[n] = o & 0x7f;
13710 o >>= 7;
13711 if (o)
13712 bytes[n] |= 0x80;
13713 n++;
13715 /* Add the insn. */
13716 for (; n; n--)
13717 add_unwind_opcode (bytes[n - 1], 1);
13718 add_unwind_opcode (0xb2, 1);
13720 else if (offset > 0x100)
13722 /* Two short opcodes. */
13723 add_unwind_opcode (0x3f, 1);
13724 op = (offset - 0x104) >> 2;
13725 add_unwind_opcode (op, 1);
13727 else if (offset > 0)
13729 /* Short opcode. */
13730 op = (offset - 4) >> 2;
13731 add_unwind_opcode (op, 1);
13733 else if (offset < 0)
13735 offset = -offset;
13736 while (offset > 0x100)
13738 add_unwind_opcode (0x7f, 1);
13739 offset -= 0x100;
13741 op = ((offset - 4) >> 2) | 0x40;
13742 add_unwind_opcode (op, 1);
13746 /* Finish the list of unwind opcodes for this function. */
13747 static void
13748 finish_unwind_opcodes (void)
13750 valueT op;
13752 if (unwind.fp_used)
13754 /* Adjust sp as neccessary. */
13755 unwind.pending_offset += unwind.fp_offset - unwind.frame_size;
13756 flush_pending_unwind ();
13758 /* After restoring sp from the frame pointer. */
13759 op = 0x90 | unwind.fp_reg;
13760 add_unwind_opcode (op, 1);
13762 else
13763 flush_pending_unwind ();
13767 /* Start an exception table entry. If idx is nonzero this is an index table
13768 entry. */
13770 static void
13771 start_unwind_section (const segT text_seg, int idx)
13773 const char * text_name;
13774 const char * prefix;
13775 const char * prefix_once;
13776 size_t prefix_len;
13777 size_t text_len;
13778 char * sec_name;
13779 size_t sec_name_len;
13781 if (idx)
13783 prefix = ELF_STRING_ARM_unwind;
13784 prefix_once = ELF_STRING_ARM_unwind_once;
13786 else
13788 prefix = ELF_STRING_ARM_unwind_info;
13789 prefix_once = ELF_STRING_ARM_unwind_info_once;
13792 text_name = segment_name (text_seg);
13793 if (streq (text_name, ".text"))
13794 text_name = "";
13796 if (strncmp (text_name, ".gnu.linkonce.t.",
13797 strlen (".gnu.linkonce.t.")) == 0)
13799 prefix = prefix_once;
13800 text_name += strlen (".gnu.linkonce.t.");
13803 prefix_len = strlen (prefix);
13804 text_len = strlen (text_name);
13805 sec_name_len = prefix_len + text_len;
13806 sec_name = alloca (sec_name_len + 1);
13807 memcpy (sec_name, prefix, prefix_len);
13808 memcpy (sec_name + prefix_len, text_name, text_len);
13809 sec_name[prefix_len + text_len] = '\0';
13811 /* Handle COMDAT group. */
13812 if (prefix != prefix_once && (text_seg->flags & SEC_LINK_ONCE) != 0)
13814 char *section;
13815 size_t len, group_name_len;
13816 const char *group_name = elf_group_name (text_seg);
13818 if (group_name == NULL)
13820 as_bad ("Group section `%s' has no group signature",
13821 segment_name (text_seg));
13822 ignore_rest_of_line ();
13823 return;
13825 /* We have to construct a fake section directive. */
13826 group_name_len = strlen (group_name);
13827 if (idx)
13828 prefix_len = 13;
13829 else
13830 prefix_len = 16;
13832 len = (sec_name_len
13833 + prefix_len /* ,"aG",%sectiontype, */
13834 + group_name_len /* ,group_name */
13835 + 7); /* ,comdat */
13837 section = alloca (len + 1);
13838 memcpy (section, sec_name, sec_name_len);
13839 if (idx)
13840 memcpy (section + sec_name_len, ",\"aG\",%exidx,", 13);
13841 else
13842 memcpy (section + sec_name_len, ",\"aG\",%progbits,", 16);
13843 memcpy (section + sec_name_len + prefix_len, group_name, group_name_len);
13844 memcpy (section + len - 7, ",comdat", 7);
13845 section [len] = '\0';
13846 set_section (section);
13848 else
13850 set_section (sec_name);
13851 bfd_set_section_flags (stdoutput, now_seg,
13852 SEC_LOAD | SEC_ALLOC | SEC_READONLY);
13855 /* Set the setion link for index tables. */
13856 if (idx)
13857 elf_linked_to_section (now_seg) = text_seg;
13861 /* Start an unwind table entry. HAVE_DATA is nonzero if we have additional
13862 personality routine data. Returns zero, or the index table value for
13863 and inline entry. */
13865 static valueT
13866 create_unwind_entry (int have_data)
13868 int size;
13869 addressT where;
13870 unsigned char *ptr;
13871 /* The current word of data. */
13872 valueT data;
13873 /* The number of bytes left in this word. */
13874 int n;
13876 finish_unwind_opcodes ();
13878 /* Remember the current text section. */
13879 unwind.saved_seg = now_seg;
13880 unwind.saved_subseg = now_subseg;
13882 start_unwind_section (now_seg, 0);
13884 if (unwind.personality_routine == NULL)
13886 if (unwind.personality_index == -2)
13888 if (have_data)
13889 as_bad (_("handerdata in cantunwind frame"));
13890 return 1; /* EXIDX_CANTUNWIND. */
13893 /* Use a default personality routine if none is specified. */
13894 if (unwind.personality_index == -1)
13896 if (unwind.opcode_count > 3)
13897 unwind.personality_index = 1;
13898 else
13899 unwind.personality_index = 0;
13902 /* Space for the personality routine entry. */
13903 if (unwind.personality_index == 0)
13905 if (unwind.opcode_count > 3)
13906 as_bad (_("too many unwind opcodes for personality routine 0"));
13908 if (!have_data)
13910 /* All the data is inline in the index table. */
13911 data = 0x80;
13912 n = 3;
13913 while (unwind.opcode_count > 0)
13915 unwind.opcode_count--;
13916 data = (data << 8) | unwind.opcodes[unwind.opcode_count];
13917 n--;
13920 /* Pad with "finish" opcodes. */
13921 while (n--)
13922 data = (data << 8) | 0xb0;
13924 return data;
13926 size = 0;
13928 else
13929 /* We get two opcodes "free" in the first word. */
13930 size = unwind.opcode_count - 2;
13932 else
13933 /* An extra byte is required for the opcode count. */
13934 size = unwind.opcode_count + 1;
13936 size = (size + 3) >> 2;
13937 if (size > 0xff)
13938 as_bad (_("too many unwind opcodes"));
13940 frag_align (2, 0, 0);
13941 record_alignment (now_seg, 2);
13942 unwind.table_entry = expr_build_dot ();
13944 /* Allocate the table entry. */
13945 ptr = frag_more ((size << 2) + 4);
13946 where = frag_now_fix () - ((size << 2) + 4);
13948 switch (unwind.personality_index)
13950 case -1:
13951 /* ??? Should this be a PLT generating relocation? */
13952 /* Custom personality routine. */
13953 fix_new (frag_now, where, 4, unwind.personality_routine, 0, 1,
13954 BFD_RELOC_ARM_PREL31);
13955 where += 4;
13956 ptr += 4;
13958 /* Set the first byte to the number of additional words. */
13959 data = size - 1;
13960 n = 3;
13961 break;
13963 /* ABI defined personality routines. */
13964 /* TODO: Emit R_ARM_NONE to the personality routine. */
13965 case 0:
13966 /* Three opcodes bytes are packed into the first word. */
13967 data = 0x80;
13968 n = 3;
13969 break;
13971 case 1:
13972 case 2:
13973 /* The size and first two opcode bytes go in the first word. */
13974 data = ((0x80 + unwind.personality_index) << 8) | size;
13975 n = 2;
13976 break;
13978 default:
13979 /* Should never happen. */
13980 abort ();
13983 /* Pack the opcodes into words (MSB first), reversing the list at the same
13984 time. */
13985 while (unwind.opcode_count > 0)
13987 if (n == 0)
13989 md_number_to_chars (ptr, data, 4);
13990 ptr += 4;
13991 n = 4;
13992 data = 0;
13994 unwind.opcode_count--;
13995 n--;
13996 data = (data << 8) | unwind.opcodes[unwind.opcode_count];
13999 /* Finish off the last word. */
14000 if (n < 4)
14002 /* Pad with "finish" opcodes. */
14003 while (n--)
14004 data = (data << 8) | 0xb0;
14006 md_number_to_chars (ptr, data, 4);
14009 if (!have_data)
14011 /* Add an empty descriptor if there is no user-specified data. */
14012 ptr = frag_more (4);
14013 md_number_to_chars (ptr, 0, 4);
14016 return 0;
14020 /* Parse an unwind_fnstart directive. Simply records the current location. */
14022 static void
14023 s_arm_unwind_fnstart (int ignored ATTRIBUTE_UNUSED)
14025 demand_empty_rest_of_line ();
14026 /* Mark the start of the function. */
14027 unwind.proc_start = expr_build_dot ();
14029 /* Reset the rest of the unwind info. */
14030 unwind.opcode_count = 0;
14031 unwind.table_entry = NULL;
14032 unwind.personality_routine = NULL;
14033 unwind.personality_index = -1;
14034 unwind.frame_size = 0;
14035 unwind.fp_offset = 0;
14036 unwind.fp_reg = 13;
14037 unwind.fp_used = 0;
14038 unwind.sp_restored = 0;
14042 /* Parse a handlerdata directive. Creates the exception handling table entry
14043 for the function. */
14045 static void
14046 s_arm_unwind_handlerdata (int ignored ATTRIBUTE_UNUSED)
14048 demand_empty_rest_of_line ();
14049 if (unwind.table_entry)
14050 as_bad (_("dupicate .handlerdata directive"));
14052 create_unwind_entry (1);
14055 /* Parse an unwind_fnend directive. Generates the index table entry. */
14057 static void
14058 s_arm_unwind_fnend (int ignored ATTRIBUTE_UNUSED)
14060 long where;
14061 unsigned char *ptr;
14062 valueT val;
14064 demand_empty_rest_of_line ();
14066 /* Add eh table entry. */
14067 if (unwind.table_entry == NULL)
14068 val = create_unwind_entry (0);
14069 else
14070 val = 0;
14072 /* Add index table entry. This is two words. */
14073 start_unwind_section (unwind.saved_seg, 1);
14074 frag_align (2, 0, 0);
14075 record_alignment (now_seg, 2);
14077 ptr = frag_more (8);
14078 where = frag_now_fix () - 8;
14080 /* Self relative offset of the function start. */
14081 fix_new (frag_now, where, 4, unwind.proc_start, 0, 1,
14082 BFD_RELOC_ARM_PREL31);
14084 if (val)
14085 /* Inline exception table entry. */
14086 md_number_to_chars (ptr + 4, val, 4);
14087 else
14088 /* Self relative offset of the table entry. */
14089 fix_new (frag_now, where + 4, 4, unwind.table_entry, 0, 1,
14090 BFD_RELOC_ARM_PREL31);
14092 /* Restore the original section. */
14093 subseg_set (unwind.saved_seg, unwind.saved_subseg);
14097 /* Parse an unwind_cantunwind directive. */
14099 static void
14100 s_arm_unwind_cantunwind (int ignored ATTRIBUTE_UNUSED)
14102 demand_empty_rest_of_line ();
14103 if (unwind.personality_routine || unwind.personality_index != -1)
14104 as_bad (_("personality routine specified for cantunwind frame"));
14106 unwind.personality_index = -2;
14110 /* Parse a personalityindex directive. */
14112 static void
14113 s_arm_unwind_personalityindex (int ignored ATTRIBUTE_UNUSED)
14115 expressionS exp;
14117 if (unwind.personality_routine || unwind.personality_index != -1)
14118 as_bad (_("duplicate .personalityindex directive"));
14120 SKIP_WHITESPACE ();
14122 expression (&exp);
14124 if (exp.X_op != O_constant
14125 || exp.X_add_number < 0 || exp.X_add_number > 15)
14127 as_bad (_("bad personality routine number"));
14128 ignore_rest_of_line ();
14129 return;
14132 unwind.personality_index = exp.X_add_number;
14134 demand_empty_rest_of_line ();
14138 /* Parse a personality directive. */
14140 static void
14141 s_arm_unwind_personality (int ignored ATTRIBUTE_UNUSED)
14143 char *name, *p, c;
14145 if (unwind.personality_routine || unwind.personality_index != -1)
14146 as_bad (_("duplicate .personality directive"));
14148 SKIP_WHITESPACE ();
14149 name = input_line_pointer;
14150 c = get_symbol_end ();
14151 p = input_line_pointer;
14152 unwind.personality_routine = symbol_find_or_make (name);
14153 *p = c;
14154 SKIP_WHITESPACE ();
14155 demand_empty_rest_of_line ();
14159 /* Parse a directive saving core registers. */
14161 static void
14162 s_arm_unwind_save_core (void)
14164 valueT op;
14165 long range;
14166 int n;
14168 SKIP_WHITESPACE ();
14169 range = reg_list (&input_line_pointer);
14170 if (range == FAIL)
14172 as_bad (_("expected register list"));
14173 ignore_rest_of_line ();
14174 return;
14177 demand_empty_rest_of_line ();
14179 /* Turn .unwind_movsp ip followed by .unwind_save {..., ip, ...}
14180 into .unwind_save {..., sp...}. We aren't bothered about the value of
14181 ip because it is clobbered by calls. */
14182 if (unwind.sp_restored && unwind.fp_reg == 12
14183 && (range & 0x3000) == 0x1000)
14185 unwind.opcode_count--;
14186 unwind.sp_restored = 0;
14187 range = (range | 0x2000) & ~0x1000;
14188 unwind.pending_offset = 0;
14191 /* See if we can use the short opcodes. These pop a block of upto 8
14192 registers starting with r4, plus maybe r14. */
14193 for (n = 0; n < 8; n++)
14195 /* Break at the first non-saved register. */
14196 if ((range & (1 << (n + 4))) == 0)
14197 break;
14199 /* See if there are any other bits set. */
14200 if (n == 0 || (range & (0xfff0 << n) & 0xbff0) != 0)
14202 /* Use the long form. */
14203 op = 0x8000 | ((range >> 4) & 0xfff);
14204 add_unwind_opcode (op, 2);
14206 else
14208 /* Use the short form. */
14209 if (range & 0x4000)
14210 op = 0xa8; /* Pop r14. */
14211 else
14212 op = 0xa0; /* Do not pop r14. */
14213 op |= (n - 1);
14214 add_unwind_opcode (op, 1);
14217 /* Pop r0-r3. */
14218 if (range & 0xf)
14220 op = 0xb100 | (range & 0xf);
14221 add_unwind_opcode (op, 2);
14224 /* Record the number of bytes pushed. */
14225 for (n = 0; n < 16; n++)
14227 if (range & (1 << n))
14228 unwind.frame_size += 4;
14233 /* Parse a directive saving FPA registers. */
14235 static void
14236 s_arm_unwind_save_fpa (int reg)
14238 expressionS exp;
14239 int num_regs;
14240 valueT op;
14242 /* Get Number of registers to transfer. */
14243 if (skip_past_comma (&input_line_pointer) != FAIL)
14244 expression (&exp);
14245 else
14246 exp.X_op = O_illegal;
14248 if (exp.X_op != O_constant)
14250 as_bad (_("expected , <constant>"));
14251 ignore_rest_of_line ();
14252 return;
14255 num_regs = exp.X_add_number;
14257 if (num_regs < 1 || num_regs > 4)
14259 as_bad (_("number of registers must be in the range [1:4]"));
14260 ignore_rest_of_line ();
14261 return;
14264 demand_empty_rest_of_line ();
14266 if (reg == 4)
14268 /* Short form. */
14269 op = 0xb4 | (num_regs - 1);
14270 add_unwind_opcode (op, 1);
14272 else
14274 /* Long form. */
14275 op = 0xc800 | (reg << 4) | (num_regs - 1);
14276 add_unwind_opcode (op, 2);
14278 unwind.frame_size += num_regs * 12;
14282 /* Parse a directive saving VFP registers. */
14284 static void
14285 s_arm_unwind_save_vfp (void)
14287 int count;
14288 int reg;
14289 valueT op;
14291 count = vfp_parse_reg_list (&input_line_pointer, &reg, 1);
14292 if (count == FAIL)
14294 as_bad (_("expected register list"));
14295 ignore_rest_of_line ();
14296 return;
14299 demand_empty_rest_of_line ();
14301 if (reg == 8)
14303 /* Short form. */
14304 op = 0xb8 | (count - 1);
14305 add_unwind_opcode (op, 1);
14307 else
14309 /* Long form. */
14310 op = 0xb300 | (reg << 4) | (count - 1);
14311 add_unwind_opcode (op, 2);
14313 unwind.frame_size += count * 8 + 4;
14317 /* Parse a directive saving iWMMXt registers. */
14319 static void
14320 s_arm_unwind_save_wmmx (void)
14322 int reg;
14323 int hi_reg;
14324 int i;
14325 unsigned wcg_mask;
14326 unsigned wr_mask;
14327 valueT op;
14329 if (*input_line_pointer == '{')
14330 input_line_pointer++;
14332 wcg_mask = 0;
14333 wr_mask = 0;
14336 reg = arm_reg_parse (&input_line_pointer,
14337 all_reg_maps[REG_TYPE_IWMMXT].htab);
14339 if (wr_register (reg))
14341 i = reg & ~WR_PREFIX;
14342 if (wr_mask >> i)
14343 as_tsktsk (_("register list not in ascending order"));
14344 wr_mask |= 1 << i;
14346 else if (wcg_register (reg))
14348 i = (reg & ~WC_PREFIX) - 8;
14349 if (wcg_mask >> i)
14350 as_tsktsk (_("register list not in ascending order"));
14351 wcg_mask |= 1 << i;
14353 else
14355 as_bad (_("expected wr or wcgr"));
14356 goto error;
14359 SKIP_WHITESPACE ();
14360 if (*input_line_pointer == '-')
14362 hi_reg = arm_reg_parse (&input_line_pointer,
14363 all_reg_maps[REG_TYPE_IWMMXT].htab);
14364 if (wr_register (reg) && wr_register (hi_reg))
14366 for (; reg < hi_reg; reg++)
14367 wr_mask |= 1 << (reg & ~WR_PREFIX);
14369 else if (wcg_register (reg) && wcg_register (hi_reg))
14371 for (; reg < hi_reg; reg++)
14372 wcg_mask |= 1 << ((reg & ~WC_PREFIX) - 8);
14374 else
14376 as_bad (_("bad register range"));
14377 goto error;
14381 while (skip_past_comma (&input_line_pointer) != FAIL);
14383 SKIP_WHITESPACE ();
14384 if (*input_line_pointer == '}')
14385 input_line_pointer++;
14387 demand_empty_rest_of_line ();
14389 if (wr_mask && wcg_mask)
14391 as_bad (_("inconsistent register types"));
14392 goto error;
14395 /* Generate any deferred opcodes becuuse we're going to be looking at
14396 the list. */
14397 flush_pending_unwind ();
14399 if (wcg_mask)
14401 for (i = 0; i < 16; i++)
14403 if (wcg_mask & (1 << i))
14404 unwind.frame_size += 4;
14406 op = 0xc700 | wcg_mask;
14407 add_unwind_opcode (op, 2);
14409 else
14411 for (i = 0; i < 16; i++)
14413 if (wr_mask & (1 << i))
14414 unwind.frame_size += 8;
14416 /* Attempt to combine with a previous opcode. We do this because gcc
14417 likes to output separate unwind directives for a single block of
14418 registers. */
14419 if (unwind.opcode_count > 0)
14421 i = unwind.opcodes[unwind.opcode_count - 1];
14422 if ((i & 0xf8) == 0xc0)
14424 i &= 7;
14425 /* Only merge if the blocks are contiguous. */
14426 if (i < 6)
14428 if ((wr_mask & 0xfe00) == (1 << 9))
14430 wr_mask |= ((1 << (i + 11)) - 1) & 0xfc00;
14431 unwind.opcode_count--;
14434 else if (i == 6 && unwind.opcode_count >= 2)
14436 i = unwind.opcodes[unwind.opcode_count - 2];
14437 reg = i >> 4;
14438 i &= 0xf;
14440 op = 0xffff << (reg - 1);
14441 if (reg > 0
14442 || ((wr_mask & op) == (1u << (reg - 1))))
14444 op = (1 << (reg + i + 1)) - 1;
14445 op &= ~((1 << reg) - 1);
14446 wr_mask |= op;
14447 unwind.opcode_count -= 2;
14453 hi_reg = 15;
14454 /* We want to generate opcodes in the order the registers have been
14455 saved, ie. descending order. */
14456 for (reg = 15; reg >= -1; reg--)
14458 /* Save registers in blocks. */
14459 if (reg < 0
14460 || !(wr_mask & (1 << reg)))
14462 /* We found an unsaved reg. Generate opcodes to save the
14463 preceeding block. */
14464 if (reg != hi_reg)
14466 if (reg == 9)
14468 /* Short form. */
14469 op = 0xc0 | (hi_reg - 10);
14470 add_unwind_opcode (op, 1);
14472 else
14474 /* Long form. */
14475 op = 0xc600 | ((reg + 1) << 4) | ((hi_reg - reg) - 1);
14476 add_unwind_opcode (op, 2);
14479 hi_reg = reg - 1;
14483 return;
14484 error:
14485 ignore_rest_of_line ();
14489 /* Parse an unwind_save directive. */
14491 static void
14492 s_arm_unwind_save (int ignored ATTRIBUTE_UNUSED)
14494 char *saved_ptr;
14495 int reg;
14497 /* Figure out what sort of save we have. */
14498 SKIP_WHITESPACE ();
14499 saved_ptr = input_line_pointer;
14501 reg = arm_reg_parse (&input_line_pointer, all_reg_maps[REG_TYPE_FN].htab);
14502 if (reg != FAIL)
14504 s_arm_unwind_save_fpa (reg);
14505 return;
14508 if (*input_line_pointer == '{')
14509 input_line_pointer++;
14511 SKIP_WHITESPACE ();
14513 reg = arm_reg_parse (&input_line_pointer, all_reg_maps[REG_TYPE_RN].htab);
14514 if (reg != FAIL)
14516 input_line_pointer = saved_ptr;
14517 s_arm_unwind_save_core ();
14518 return;
14521 reg = arm_reg_parse (&input_line_pointer, all_reg_maps[REG_TYPE_DN].htab);
14522 if (reg != FAIL)
14524 input_line_pointer = saved_ptr;
14525 s_arm_unwind_save_vfp ();
14526 return;
14529 reg = arm_reg_parse (&input_line_pointer,
14530 all_reg_maps[REG_TYPE_IWMMXT].htab);
14531 if (reg != FAIL)
14533 input_line_pointer = saved_ptr;
14534 s_arm_unwind_save_wmmx ();
14535 return;
14538 /* TODO: Maverick registers. */
14539 as_bad (_("unrecognised register"));
14543 /* Parse an unwind_movsp directive. */
14545 static void
14546 s_arm_unwind_movsp (int ignored ATTRIBUTE_UNUSED)
14548 int reg;
14549 valueT op;
14551 SKIP_WHITESPACE ();
14552 reg = reg_required_here (&input_line_pointer, -1);
14553 if (reg == FAIL)
14555 as_bad (_("ARM register expected"));
14556 ignore_rest_of_line ();
14557 return;
14560 if (reg == 13 || reg == 15)
14562 as_bad (_("r%d not permitted in .unwind_movsp directive"), reg);
14563 ignore_rest_of_line ();
14564 return;
14567 if (unwind.fp_reg != 13)
14568 as_bad (_("unexpected .unwind_movsp directive"));
14570 /* Generate opcode to restore the value. */
14571 op = 0x90 | reg;
14572 add_unwind_opcode (op, 1);
14574 /* Record the information for later. */
14575 unwind.fp_reg = reg;
14576 unwind.fp_offset = unwind.frame_size;
14577 unwind.sp_restored = 1;
14578 demand_empty_rest_of_line ();
14582 /* Parse #<number>. */
14584 static int
14585 require_hashconst (int * val)
14587 expressionS exp;
14589 SKIP_WHITESPACE ();
14590 if (*input_line_pointer == '#')
14592 input_line_pointer++;
14593 expression (&exp);
14595 else
14596 exp.X_op = O_illegal;
14598 if (exp.X_op != O_constant)
14600 as_bad (_("expected #constant"));
14601 ignore_rest_of_line ();
14602 return FAIL;
14604 *val = exp.X_add_number;
14605 return SUCCESS;
14608 /* Parse an unwind_pad directive. */
14610 static void
14611 s_arm_unwind_pad (int ignored ATTRIBUTE_UNUSED)
14613 int offset;
14615 if (require_hashconst (&offset) == FAIL)
14616 return;
14618 if (offset & 3)
14620 as_bad (_("stack increment must be multiple of 4"));
14621 ignore_rest_of_line ();
14622 return;
14625 /* Don't generate any opcodes, just record the details for later. */
14626 unwind.frame_size += offset;
14627 unwind.pending_offset += offset;
14629 demand_empty_rest_of_line ();
14632 /* Parse an unwind_setfp directive. */
14634 static void
14635 s_arm_unwind_setfp (int ignored ATTRIBUTE_UNUSED)
14637 int sp_reg;
14638 int fp_reg;
14639 int offset;
14641 fp_reg = reg_required_here (&input_line_pointer, -1);
14642 if (skip_past_comma (&input_line_pointer) == FAIL)
14643 sp_reg = FAIL;
14644 else
14645 sp_reg = reg_required_here (&input_line_pointer, -1);
14647 if (fp_reg == FAIL || sp_reg == FAIL)
14649 as_bad (_("expected <reg>, <reg>"));
14650 ignore_rest_of_line ();
14651 return;
14654 /* Optonal constant. */
14655 if (skip_past_comma (&input_line_pointer) != FAIL)
14657 if (require_hashconst (&offset) == FAIL)
14658 return;
14660 else
14661 offset = 0;
14663 demand_empty_rest_of_line ();
14665 if (sp_reg != 13 && sp_reg != unwind.fp_reg)
14667 as_bad (_("register must be either sp or set by a previous"
14668 "unwind_movsp directive"));
14669 return;
14672 /* Don't generate any opcodes, just record the information for later. */
14673 unwind.fp_reg = fp_reg;
14674 unwind.fp_used = 1;
14675 if (sp_reg == 13)
14676 unwind.fp_offset = unwind.frame_size - offset;
14677 else
14678 unwind.fp_offset -= offset;
14681 /* Parse an unwind_raw directive. */
14683 static void
14684 s_arm_unwind_raw (int ignored ATTRIBUTE_UNUSED)
14686 expressionS exp;
14687 /* This is an arbitary limit. */
14688 unsigned char op[16];
14689 int count;
14691 SKIP_WHITESPACE ();
14692 expression (&exp);
14693 if (exp.X_op == O_constant
14694 && skip_past_comma (&input_line_pointer) != FAIL)
14696 unwind.frame_size += exp.X_add_number;
14697 expression (&exp);
14699 else
14700 exp.X_op = O_illegal;
14702 if (exp.X_op != O_constant)
14704 as_bad (_("expected <offset>, <opcode>"));
14705 ignore_rest_of_line ();
14706 return;
14709 count = 0;
14711 /* Parse the opcode. */
14712 for (;;)
14714 if (count >= 16)
14716 as_bad (_("unwind opcode too long"));
14717 ignore_rest_of_line ();
14719 if (exp.X_op != O_constant || exp.X_add_number & ~0xff)
14721 as_bad (_("invalid unwind opcode"));
14722 ignore_rest_of_line ();
14723 return;
14725 op[count++] = exp.X_add_number;
14727 /* Parse the next byte. */
14728 if (skip_past_comma (&input_line_pointer) == FAIL)
14729 break;
14731 expression (&exp);
14734 /* Add the opcode bytes in reverse order. */
14735 while (count--)
14736 add_unwind_opcode (op[count], 1);
14738 demand_empty_rest_of_line ();
14741 #endif /* OBJ_ELF */
14743 /* This is called from HANDLE_ALIGN in write.c. Fill in the contents
14744 of an rs_align_code fragment. */
14746 void
14747 arm_handle_align (fragS * fragP)
14749 static char const arm_noop[4] = { 0x00, 0x00, 0xa0, 0xe1 };
14750 static char const thumb_noop[2] = { 0xc0, 0x46 };
14751 static char const arm_bigend_noop[4] = { 0xe1, 0xa0, 0x00, 0x00 };
14752 static char const thumb_bigend_noop[2] = { 0x46, 0xc0 };
14754 int bytes, fix, noop_size;
14755 char * p;
14756 const char * noop;
14758 if (fragP->fr_type != rs_align_code)
14759 return;
14761 bytes = fragP->fr_next->fr_address - fragP->fr_address - fragP->fr_fix;
14762 p = fragP->fr_literal + fragP->fr_fix;
14763 fix = 0;
14765 if (bytes > MAX_MEM_FOR_RS_ALIGN_CODE)
14766 bytes &= MAX_MEM_FOR_RS_ALIGN_CODE;
14768 if (fragP->tc_frag_data)
14770 if (target_big_endian)
14771 noop = thumb_bigend_noop;
14772 else
14773 noop = thumb_noop;
14774 noop_size = sizeof (thumb_noop);
14776 else
14778 if (target_big_endian)
14779 noop = arm_bigend_noop;
14780 else
14781 noop = arm_noop;
14782 noop_size = sizeof (arm_noop);
14785 if (bytes & (noop_size - 1))
14787 fix = bytes & (noop_size - 1);
14788 memset (p, 0, fix);
14789 p += fix;
14790 bytes -= fix;
14793 while (bytes >= noop_size)
14795 memcpy (p, noop, noop_size);
14796 p += noop_size;
14797 bytes -= noop_size;
14798 fix += noop_size;
14801 fragP->fr_fix += fix;
14802 fragP->fr_var = noop_size;
14805 /* Called from md_do_align. Used to create an alignment
14806 frag in a code section. */
14808 void
14809 arm_frag_align_code (int n, int max)
14811 char * p;
14813 /* We assume that there will never be a requirement
14814 to support alignments greater than 32 bytes. */
14815 if (max > MAX_MEM_FOR_RS_ALIGN_CODE)
14816 as_fatal (_("alignments greater than 32 bytes not supported in .text sections."));
14818 p = frag_var (rs_align_code,
14819 MAX_MEM_FOR_RS_ALIGN_CODE,
14821 (relax_substateT) max,
14822 (symbolS *) NULL,
14823 (offsetT) n,
14824 (char *) NULL);
14825 *p = 0;
14828 /* Perform target specific initialisation of a frag. */
14830 void
14831 arm_init_frag (fragS * fragP)
14833 /* Record whether this frag is in an ARM or a THUMB area. */
14834 fragP->tc_frag_data = thumb_mode;
14837 #ifdef OBJ_ELF
14839 /* Convert REGNAME to a DWARF-2 register number. */
14842 tc_arm_regname_to_dw2regnum (const char *regname)
14844 unsigned int i;
14846 for (i = 0; rn_table[i].name; i++)
14847 if (streq (regname, rn_table[i].name))
14848 return rn_table[i].number;
14850 return -1;
14853 /* Initialize the DWARF-2 unwind information for this procedure. */
14855 void
14856 tc_arm_frame_initial_instructions (void)
14858 cfi_add_CFA_def_cfa (REG_SP, 0);
14860 #endif
14862 /* This table describes all the machine specific pseudo-ops the assembler
14863 has to support. The fields are:
14864 pseudo-op name without dot
14865 function to call to execute this pseudo-op
14866 Integer arg to pass to the function. */
14868 const pseudo_typeS md_pseudo_table[] =
14870 /* Never called because '.req' does not start a line. */
14871 { "req", s_req, 0 },
14872 { "unreq", s_unreq, 0 },
14873 { "bss", s_bss, 0 },
14874 { "align", s_align, 0 },
14875 { "arm", s_arm, 0 },
14876 { "thumb", s_thumb, 0 },
14877 { "code", s_code, 0 },
14878 { "force_thumb", s_force_thumb, 0 },
14879 { "thumb_func", s_thumb_func, 0 },
14880 { "thumb_set", s_thumb_set, 0 },
14881 { "even", s_even, 0 },
14882 { "ltorg", s_ltorg, 0 },
14883 { "pool", s_ltorg, 0 },
14884 #ifdef OBJ_ELF
14885 { "word", s_arm_elf_cons, 4 },
14886 { "long", s_arm_elf_cons, 4 },
14887 { "rel31", s_arm_rel31, 0 },
14888 { "fnstart", s_arm_unwind_fnstart, 0 },
14889 { "fnend", s_arm_unwind_fnend, 0 },
14890 { "cantunwind", s_arm_unwind_cantunwind, 0 },
14891 { "personality", s_arm_unwind_personality, 0 },
14892 { "personalityindex", s_arm_unwind_personalityindex, 0 },
14893 { "handlerdata", s_arm_unwind_handlerdata, 0 },
14894 { "save", s_arm_unwind_save, 0 },
14895 { "movsp", s_arm_unwind_movsp, 0 },
14896 { "pad", s_arm_unwind_pad, 0 },
14897 { "setfp", s_arm_unwind_setfp, 0 },
14898 { "unwind_raw", s_arm_unwind_raw, 0 },
14899 #else
14900 { "word", cons, 4},
14901 #endif
14902 { "extend", float_cons, 'x' },
14903 { "ldouble", float_cons, 'x' },
14904 { "packed", float_cons, 'p' },
14905 { 0, 0, 0 }