* chew.c (paramstuff, outputdots, perform, bang and usage): Remove
[binutils.git] / gas / config / tc-arm.c
blobd2d70341145215016eb0a3cd04927e54c79ba713
1 /* tc-arm.c -- Assemble for the ARM
2 Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
3 Free Software Foundation, Inc.
4 Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org)
5 Modified by David Taylor (dtaylor@armltd.co.uk)
6 Cirrus coprocessor mods by Aldy Hernandez (aldyh@redhat.com)
8 This file is part of GAS, the GNU Assembler.
10 GAS is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2, or (at your option)
13 any later version.
15 GAS is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with GAS; see the file COPYING. If not, write to the Free
22 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
23 02111-1307, USA. */
25 #include <string.h>
26 #define NO_RELOC 0
27 #include "as.h"
28 #include "safe-ctype.h"
30 /* Need TARGET_CPU. */
31 #include "config.h"
32 #include "subsegs.h"
33 #include "obstack.h"
34 #include "symbols.h"
35 #include "listing.h"
37 #ifdef OBJ_ELF
38 #include "elf/arm.h"
39 #include "dwarf2dbg.h"
40 #endif
42 /* XXX Set this to 1 after the next binutils release */
43 #define WARN_DEPRECATED 0
45 /* The following bitmasks control CPU extensions: */
46 #define ARM_EXT_V1 0x00000001 /* All processors (core set). */
47 #define ARM_EXT_V2 0x00000002 /* Multiply instructions. */
48 #define ARM_EXT_V2S 0x00000004 /* SWP instructions. */
49 #define ARM_EXT_V3 0x00000008 /* MSR MRS. */
50 #define ARM_EXT_V3M 0x00000010 /* Allow long multiplies. */
51 #define ARM_EXT_V4 0x00000020 /* Allow half word loads. */
52 #define ARM_EXT_V4T 0x00000040 /* Thumb v1. */
53 #define ARM_EXT_V5 0x00000080 /* Allow CLZ, etc. */
54 #define ARM_EXT_V5T 0x00000100 /* Thumb v2. */
55 #define ARM_EXT_V5ExP 0x00000200 /* DSP core set. */
56 #define ARM_EXT_V5E 0x00000400 /* DSP Double transfers. */
57 #define ARM_EXT_V5J 0x00000800 /* Jazelle extension. */
59 /* Co-processor space extensions. */
60 #define ARM_CEXT_XSCALE 0x00800000 /* Allow MIA etc. */
61 #define ARM_CEXT_MAVERICK 0x00400000 /* Use Cirrus/DSP coprocessor. */
63 /* Architectures are the sum of the base and extensions. The ARM ARM (rev E)
64 defines the following: ARMv3, ARMv3M, ARMv4xM, ARMv4, ARMv4TxM, ARMv4T,
65 ARMv5xM, ARMv5, ARMv5TxM, ARMv5T, ARMv5TExP, ARMv5TE. To these we add
66 three more to cover cores prior to ARM6. Finally, there are cores which
67 implement further extensions in the co-processor space. */
68 #define ARM_ARCH_V1 ARM_EXT_V1
69 #define ARM_ARCH_V2 (ARM_ARCH_V1 | ARM_EXT_V2)
70 #define ARM_ARCH_V2S (ARM_ARCH_V2 | ARM_EXT_V2S)
71 #define ARM_ARCH_V3 (ARM_ARCH_V2S | ARM_EXT_V3)
72 #define ARM_ARCH_V3M (ARM_ARCH_V3 | ARM_EXT_V3M)
73 #define ARM_ARCH_V4xM (ARM_ARCH_V3 | ARM_EXT_V4)
74 #define ARM_ARCH_V4 (ARM_ARCH_V3M | ARM_EXT_V4)
75 #define ARM_ARCH_V4TxM (ARM_ARCH_V4xM | ARM_EXT_V4T)
76 #define ARM_ARCH_V4T (ARM_ARCH_V4 | ARM_EXT_V4T)
77 #define ARM_ARCH_V5xM (ARM_ARCH_V4xM | ARM_EXT_V5)
78 #define ARM_ARCH_V5 (ARM_ARCH_V4 | ARM_EXT_V5)
79 #define ARM_ARCH_V5TxM (ARM_ARCH_V5xM | ARM_EXT_V4T | ARM_EXT_V5T)
80 #define ARM_ARCH_V5T (ARM_ARCH_V5 | ARM_EXT_V4T | ARM_EXT_V5T)
81 #define ARM_ARCH_V5TExP (ARM_ARCH_V5T | ARM_EXT_V5ExP)
82 #define ARM_ARCH_V5TE (ARM_ARCH_V5TExP | ARM_EXT_V5E)
83 #define ARM_ARCH_V5TEJ (ARM_ARCH_V5TE | ARM_EXT_V5J)
85 /* Processors with specific extensions in the co-processor space. */
86 #define ARM_ARCH_XSCALE (ARM_ARCH_V5TE | ARM_CEXT_XSCALE)
88 /* Some useful combinations: */
89 #define ARM_ANY 0x0000ffff /* Any basic core. */
90 #define ARM_ALL 0x00ffffff /* Any core + co-processor */
91 #define CPROC_ANY 0x00ff0000 /* Any co-processor */
92 #define FPU_ANY 0xff000000 /* Note this is ~ARM_ALL. */
95 #define FPU_FPA_EXT_V1 0x80000000 /* Base FPA instruction set. */
96 #define FPU_FPA_EXT_V2 0x40000000 /* LFM/SFM. */
97 #define FPU_VFP_EXT_NONE 0x20000000 /* Use VFP word-ordering. */
98 #define FPU_VFP_EXT_V1xD 0x10000000 /* Base VFP instruction set. */
99 #define FPU_VFP_EXT_V1 0x08000000 /* Double-precision insns. */
100 #define FPU_VFP_EXT_V2 0x04000000 /* ARM10E VFPr1. */
101 #define FPU_NONE 0
103 #define FPU_ARCH_FPE FPU_FPA_EXT_V1
104 #define FPU_ARCH_FPA (FPU_ARCH_FPE | FPU_FPA_EXT_V2)
106 #define FPU_ARCH_VFP FPU_VFP_EXT_NONE
107 #define FPU_ARCH_VFP_V1xD (FPU_VFP_EXT_V1xD | FPU_VFP_EXT_NONE)
108 #define FPU_ARCH_VFP_V1 (FPU_ARCH_VFP_V1xD | FPU_VFP_EXT_V1)
109 #define FPU_ARCH_VFP_V2 (FPU_ARCH_VFP_V1 | FPU_VFP_EXT_V2)
111 /* Types of processor to assemble for. */
112 #define ARM_1 ARM_ARCH_V1
113 #define ARM_2 ARM_ARCH_V2
114 #define ARM_3 ARM_ARCH_V2S
115 #define ARM_250 ARM_ARCH_V2S
116 #define ARM_6 ARM_ARCH_V3
117 #define ARM_7 ARM_ARCH_V3
118 #define ARM_8 ARM_ARCH_V4
119 #define ARM_9 ARM_ARCH_V4T
120 #define ARM_STRONG ARM_ARCH_V4
121 #define ARM_CPU_MASK 0x0000000f /* XXX? */
123 #ifndef CPU_DEFAULT
124 #if defined __XSCALE__
125 #define CPU_DEFAULT (ARM_ARCH_XSCALE)
126 #else
127 #if defined __thumb__
128 #define CPU_DEFAULT (ARM_ARCH_V5T)
129 #else
130 #define CPU_DEFAULT ARM_ANY
131 #endif
132 #endif
133 #endif
135 /* For backwards compatibility we default to the FPA. */
136 #ifndef FPU_DEFAULT
137 #define FPU_DEFAULT FPU_ARCH_FPA
138 #endif
140 #define streq(a, b) (strcmp (a, b) == 0)
141 #define skip_whitespace(str) while (*(str) == ' ') ++(str)
143 static unsigned long cpu_variant;
144 static int target_oabi = 0;
146 /* Flags stored in private area of BFD structure. */
147 static int uses_apcs_26 = false;
148 static int atpcs = false;
149 static int support_interwork = false;
150 static int uses_apcs_float = false;
151 static int pic_code = false;
153 /* Variables that we set while parsing command-line options. Once all
154 options have been read we re-process these values to set the real
155 assembly flags. */
156 static int legacy_cpu = -1;
157 static int legacy_fpu = -1;
159 static int mcpu_cpu_opt = -1;
160 static int mcpu_fpu_opt = -1;
161 static int march_cpu_opt = -1;
162 static int march_fpu_opt = -1;
163 static int mfpu_opt = -1;
165 /* This array holds the chars that always start a comment. If the
166 pre-processor is disabled, these aren't very useful. */
167 const char comment_chars[] = "@";
169 /* This array holds the chars that only start a comment at the beginning of
170 a line. If the line seems to have the form '# 123 filename'
171 .line and .file directives will appear in the pre-processed output. */
172 /* Note that input_file.c hand checks for '#' at the beginning of the
173 first line of the input file. This is because the compiler outputs
174 #NO_APP at the beginning of its output. */
175 /* Also note that comments like this one will always work. */
176 const char line_comment_chars[] = "#";
178 const char line_separator_chars[] = ";";
180 /* Chars that can be used to separate mant
181 from exp in floating point numbers. */
182 const char EXP_CHARS[] = "eE";
184 /* Chars that mean this number is a floating point constant. */
185 /* As in 0f12.456 */
186 /* or 0d1.2345e12 */
188 const char FLT_CHARS[] = "rRsSfFdDxXeEpP";
190 /* Prefix characters that indicate the start of an immediate
191 value. */
192 #define is_immediate_prefix(C) ((C) == '#' || (C) == '$')
194 #ifdef OBJ_ELF
195 /* Pre-defined "_GLOBAL_OFFSET_TABLE_" */
196 symbolS * GOT_symbol;
197 #endif
199 /* Size of relocation record. */
200 const int md_reloc_size = 8;
202 /* 0: assemble for ARM,
203 1: assemble for Thumb,
204 2: assemble for Thumb even though target CPU does not support thumb
205 instructions. */
206 static int thumb_mode = 0;
208 typedef struct arm_fix
210 int thumb_mode;
211 } arm_fix_data;
213 struct arm_it
215 const char * error;
216 unsigned long instruction;
217 int size;
218 struct
220 bfd_reloc_code_real_type type;
221 expressionS exp;
222 int pc_rel;
223 } reloc;
226 struct arm_it inst;
228 enum asm_shift_index
230 SHIFT_LSL = 0,
231 SHIFT_LSR,
232 SHIFT_ASR,
233 SHIFT_ROR,
234 SHIFT_RRX
237 struct asm_shift_properties
239 enum asm_shift_index index;
240 unsigned long bit_field;
241 unsigned int allows_0 : 1;
242 unsigned int allows_32 : 1;
245 static const struct asm_shift_properties shift_properties [] =
247 { SHIFT_LSL, 0, 1, 0},
248 { SHIFT_LSR, 0x20, 0, 1},
249 { SHIFT_ASR, 0x40, 0, 1},
250 { SHIFT_ROR, 0x60, 0, 0},
251 { SHIFT_RRX, 0x60, 0, 0}
254 struct asm_shift_name
256 const char * name;
257 const struct asm_shift_properties * properties;
260 static const struct asm_shift_name shift_names [] =
262 { "asl", shift_properties + SHIFT_LSL },
263 { "lsl", shift_properties + SHIFT_LSL },
264 { "lsr", shift_properties + SHIFT_LSR },
265 { "asr", shift_properties + SHIFT_ASR },
266 { "ror", shift_properties + SHIFT_ROR },
267 { "rrx", shift_properties + SHIFT_RRX },
268 { "ASL", shift_properties + SHIFT_LSL },
269 { "LSL", shift_properties + SHIFT_LSL },
270 { "LSR", shift_properties + SHIFT_LSR },
271 { "ASR", shift_properties + SHIFT_ASR },
272 { "ROR", shift_properties + SHIFT_ROR },
273 { "RRX", shift_properties + SHIFT_RRX }
276 #define NO_SHIFT_RESTRICT 1
277 #define SHIFT_RESTRICT 0
279 #define NUM_FLOAT_VALS 8
281 const char * fp_const[] =
283 "0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0", 0
286 /* Number of littlenums required to hold an extended precision number. */
287 #define MAX_LITTLENUMS 6
289 LITTLENUM_TYPE fp_values[NUM_FLOAT_VALS][MAX_LITTLENUMS];
291 #define FAIL (-1)
292 #define SUCCESS (0)
294 /* Whether a Co-processor load/store operation accepts write-back forms. */
295 #define CP_WB_OK 1
296 #define CP_NO_WB 0
298 #define SUFF_S 1
299 #define SUFF_D 2
300 #define SUFF_E 3
301 #define SUFF_P 4
303 #define CP_T_X 0x00008000
304 #define CP_T_Y 0x00400000
305 #define CP_T_Pre 0x01000000
306 #define CP_T_UD 0x00800000
307 #define CP_T_WB 0x00200000
309 #define CONDS_BIT 0x00100000
310 #define LOAD_BIT 0x00100000
312 #define DOUBLE_LOAD_FLAG 0x00000001
314 struct asm_cond
316 const char * template;
317 unsigned long value;
320 #define COND_ALWAYS 0xe0000000
321 #define COND_MASK 0xf0000000
323 static const struct asm_cond conds[] =
325 {"eq", 0x00000000},
326 {"ne", 0x10000000},
327 {"cs", 0x20000000}, {"hs", 0x20000000},
328 {"cc", 0x30000000}, {"ul", 0x30000000}, {"lo", 0x30000000},
329 {"mi", 0x40000000},
330 {"pl", 0x50000000},
331 {"vs", 0x60000000},
332 {"vc", 0x70000000},
333 {"hi", 0x80000000},
334 {"ls", 0x90000000},
335 {"ge", 0xa0000000},
336 {"lt", 0xb0000000},
337 {"gt", 0xc0000000},
338 {"le", 0xd0000000},
339 {"al", 0xe0000000},
340 {"nv", 0xf0000000}
343 struct asm_psr
345 const char * template;
346 boolean cpsr;
347 unsigned long field;
350 /* The bit that distnguishes CPSR and SPSR. */
351 #define SPSR_BIT (1 << 22)
353 /* How many bits to shift the PSR_xxx bits up by. */
354 #define PSR_SHIFT 16
356 #define PSR_c (1 << 0)
357 #define PSR_x (1 << 1)
358 #define PSR_s (1 << 2)
359 #define PSR_f (1 << 3)
361 static const struct asm_psr psrs[] =
363 {"CPSR", true, PSR_c | PSR_f},
364 {"CPSR_all", true, PSR_c | PSR_f},
365 {"SPSR", false, PSR_c | PSR_f},
366 {"SPSR_all", false, PSR_c | PSR_f},
367 {"CPSR_flg", true, PSR_f},
368 {"CPSR_f", true, PSR_f},
369 {"SPSR_flg", false, PSR_f},
370 {"SPSR_f", false, PSR_f},
371 {"CPSR_c", true, PSR_c},
372 {"CPSR_ctl", true, PSR_c},
373 {"SPSR_c", false, PSR_c},
374 {"SPSR_ctl", false, PSR_c},
375 {"CPSR_x", true, PSR_x},
376 {"CPSR_s", true, PSR_s},
377 {"SPSR_x", false, PSR_x},
378 {"SPSR_s", false, PSR_s},
379 /* Combinations of flags. */
380 {"CPSR_fs", true, PSR_f | PSR_s},
381 {"CPSR_fx", true, PSR_f | PSR_x},
382 {"CPSR_fc", true, PSR_f | PSR_c},
383 {"CPSR_sf", true, PSR_s | PSR_f},
384 {"CPSR_sx", true, PSR_s | PSR_x},
385 {"CPSR_sc", true, PSR_s | PSR_c},
386 {"CPSR_xf", true, PSR_x | PSR_f},
387 {"CPSR_xs", true, PSR_x | PSR_s},
388 {"CPSR_xc", true, PSR_x | PSR_c},
389 {"CPSR_cf", true, PSR_c | PSR_f},
390 {"CPSR_cs", true, PSR_c | PSR_s},
391 {"CPSR_cx", true, PSR_c | PSR_x},
392 {"CPSR_fsx", true, PSR_f | PSR_s | PSR_x},
393 {"CPSR_fsc", true, PSR_f | PSR_s | PSR_c},
394 {"CPSR_fxs", true, PSR_f | PSR_x | PSR_s},
395 {"CPSR_fxc", true, PSR_f | PSR_x | PSR_c},
396 {"CPSR_fcs", true, PSR_f | PSR_c | PSR_s},
397 {"CPSR_fcx", true, PSR_f | PSR_c | PSR_x},
398 {"CPSR_sfx", true, PSR_s | PSR_f | PSR_x},
399 {"CPSR_sfc", true, PSR_s | PSR_f | PSR_c},
400 {"CPSR_sxf", true, PSR_s | PSR_x | PSR_f},
401 {"CPSR_sxc", true, PSR_s | PSR_x | PSR_c},
402 {"CPSR_scf", true, PSR_s | PSR_c | PSR_f},
403 {"CPSR_scx", true, PSR_s | PSR_c | PSR_x},
404 {"CPSR_xfs", true, PSR_x | PSR_f | PSR_s},
405 {"CPSR_xfc", true, PSR_x | PSR_f | PSR_c},
406 {"CPSR_xsf", true, PSR_x | PSR_s | PSR_f},
407 {"CPSR_xsc", true, PSR_x | PSR_s | PSR_c},
408 {"CPSR_xcf", true, PSR_x | PSR_c | PSR_f},
409 {"CPSR_xcs", true, PSR_x | PSR_c | PSR_s},
410 {"CPSR_cfs", true, PSR_c | PSR_f | PSR_s},
411 {"CPSR_cfx", true, PSR_c | PSR_f | PSR_x},
412 {"CPSR_csf", true, PSR_c | PSR_s | PSR_f},
413 {"CPSR_csx", true, PSR_c | PSR_s | PSR_x},
414 {"CPSR_cxf", true, PSR_c | PSR_x | PSR_f},
415 {"CPSR_cxs", true, PSR_c | PSR_x | PSR_s},
416 {"CPSR_fsxc", true, PSR_f | PSR_s | PSR_x | PSR_c},
417 {"CPSR_fscx", true, PSR_f | PSR_s | PSR_c | PSR_x},
418 {"CPSR_fxsc", true, PSR_f | PSR_x | PSR_s | PSR_c},
419 {"CPSR_fxcs", true, PSR_f | PSR_x | PSR_c | PSR_s},
420 {"CPSR_fcsx", true, PSR_f | PSR_c | PSR_s | PSR_x},
421 {"CPSR_fcxs", true, PSR_f | PSR_c | PSR_x | PSR_s},
422 {"CPSR_sfxc", true, PSR_s | PSR_f | PSR_x | PSR_c},
423 {"CPSR_sfcx", true, PSR_s | PSR_f | PSR_c | PSR_x},
424 {"CPSR_sxfc", true, PSR_s | PSR_x | PSR_f | PSR_c},
425 {"CPSR_sxcf", true, PSR_s | PSR_x | PSR_c | PSR_f},
426 {"CPSR_scfx", true, PSR_s | PSR_c | PSR_f | PSR_x},
427 {"CPSR_scxf", true, PSR_s | PSR_c | PSR_x | PSR_f},
428 {"CPSR_xfsc", true, PSR_x | PSR_f | PSR_s | PSR_c},
429 {"CPSR_xfcs", true, PSR_x | PSR_f | PSR_c | PSR_s},
430 {"CPSR_xsfc", true, PSR_x | PSR_s | PSR_f | PSR_c},
431 {"CPSR_xscf", true, PSR_x | PSR_s | PSR_c | PSR_f},
432 {"CPSR_xcfs", true, PSR_x | PSR_c | PSR_f | PSR_s},
433 {"CPSR_xcsf", true, PSR_x | PSR_c | PSR_s | PSR_f},
434 {"CPSR_cfsx", true, PSR_c | PSR_f | PSR_s | PSR_x},
435 {"CPSR_cfxs", true, PSR_c | PSR_f | PSR_x | PSR_s},
436 {"CPSR_csfx", true, PSR_c | PSR_s | PSR_f | PSR_x},
437 {"CPSR_csxf", true, PSR_c | PSR_s | PSR_x | PSR_f},
438 {"CPSR_cxfs", true, PSR_c | PSR_x | PSR_f | PSR_s},
439 {"CPSR_cxsf", true, PSR_c | PSR_x | PSR_s | PSR_f},
440 {"SPSR_fs", false, PSR_f | PSR_s},
441 {"SPSR_fx", false, PSR_f | PSR_x},
442 {"SPSR_fc", false, PSR_f | PSR_c},
443 {"SPSR_sf", false, PSR_s | PSR_f},
444 {"SPSR_sx", false, PSR_s | PSR_x},
445 {"SPSR_sc", false, PSR_s | PSR_c},
446 {"SPSR_xf", false, PSR_x | PSR_f},
447 {"SPSR_xs", false, PSR_x | PSR_s},
448 {"SPSR_xc", false, PSR_x | PSR_c},
449 {"SPSR_cf", false, PSR_c | PSR_f},
450 {"SPSR_cs", false, PSR_c | PSR_s},
451 {"SPSR_cx", false, PSR_c | PSR_x},
452 {"SPSR_fsx", false, PSR_f | PSR_s | PSR_x},
453 {"SPSR_fsc", false, PSR_f | PSR_s | PSR_c},
454 {"SPSR_fxs", false, PSR_f | PSR_x | PSR_s},
455 {"SPSR_fxc", false, PSR_f | PSR_x | PSR_c},
456 {"SPSR_fcs", false, PSR_f | PSR_c | PSR_s},
457 {"SPSR_fcx", false, PSR_f | PSR_c | PSR_x},
458 {"SPSR_sfx", false, PSR_s | PSR_f | PSR_x},
459 {"SPSR_sfc", false, PSR_s | PSR_f | PSR_c},
460 {"SPSR_sxf", false, PSR_s | PSR_x | PSR_f},
461 {"SPSR_sxc", false, PSR_s | PSR_x | PSR_c},
462 {"SPSR_scf", false, PSR_s | PSR_c | PSR_f},
463 {"SPSR_scx", false, PSR_s | PSR_c | PSR_x},
464 {"SPSR_xfs", false, PSR_x | PSR_f | PSR_s},
465 {"SPSR_xfc", false, PSR_x | PSR_f | PSR_c},
466 {"SPSR_xsf", false, PSR_x | PSR_s | PSR_f},
467 {"SPSR_xsc", false, PSR_x | PSR_s | PSR_c},
468 {"SPSR_xcf", false, PSR_x | PSR_c | PSR_f},
469 {"SPSR_xcs", false, PSR_x | PSR_c | PSR_s},
470 {"SPSR_cfs", false, PSR_c | PSR_f | PSR_s},
471 {"SPSR_cfx", false, PSR_c | PSR_f | PSR_x},
472 {"SPSR_csf", false, PSR_c | PSR_s | PSR_f},
473 {"SPSR_csx", false, PSR_c | PSR_s | PSR_x},
474 {"SPSR_cxf", false, PSR_c | PSR_x | PSR_f},
475 {"SPSR_cxs", false, PSR_c | PSR_x | PSR_s},
476 {"SPSR_fsxc", false, PSR_f | PSR_s | PSR_x | PSR_c},
477 {"SPSR_fscx", false, PSR_f | PSR_s | PSR_c | PSR_x},
478 {"SPSR_fxsc", false, PSR_f | PSR_x | PSR_s | PSR_c},
479 {"SPSR_fxcs", false, PSR_f | PSR_x | PSR_c | PSR_s},
480 {"SPSR_fcsx", false, PSR_f | PSR_c | PSR_s | PSR_x},
481 {"SPSR_fcxs", false, PSR_f | PSR_c | PSR_x | PSR_s},
482 {"SPSR_sfxc", false, PSR_s | PSR_f | PSR_x | PSR_c},
483 {"SPSR_sfcx", false, PSR_s | PSR_f | PSR_c | PSR_x},
484 {"SPSR_sxfc", false, PSR_s | PSR_x | PSR_f | PSR_c},
485 {"SPSR_sxcf", false, PSR_s | PSR_x | PSR_c | PSR_f},
486 {"SPSR_scfx", false, PSR_s | PSR_c | PSR_f | PSR_x},
487 {"SPSR_scxf", false, PSR_s | PSR_c | PSR_x | PSR_f},
488 {"SPSR_xfsc", false, PSR_x | PSR_f | PSR_s | PSR_c},
489 {"SPSR_xfcs", false, PSR_x | PSR_f | PSR_c | PSR_s},
490 {"SPSR_xsfc", false, PSR_x | PSR_s | PSR_f | PSR_c},
491 {"SPSR_xscf", false, PSR_x | PSR_s | PSR_c | PSR_f},
492 {"SPSR_xcfs", false, PSR_x | PSR_c | PSR_f | PSR_s},
493 {"SPSR_xcsf", false, PSR_x | PSR_c | PSR_s | PSR_f},
494 {"SPSR_cfsx", false, PSR_c | PSR_f | PSR_s | PSR_x},
495 {"SPSR_cfxs", false, PSR_c | PSR_f | PSR_x | PSR_s},
496 {"SPSR_csfx", false, PSR_c | PSR_s | PSR_f | PSR_x},
497 {"SPSR_csxf", false, PSR_c | PSR_s | PSR_x | PSR_f},
498 {"SPSR_cxfs", false, PSR_c | PSR_x | PSR_f | PSR_s},
499 {"SPSR_cxsf", false, PSR_c | PSR_x | PSR_s | PSR_f},
502 enum vfp_dp_reg_pos
504 VFP_REG_Dd, VFP_REG_Dm, VFP_REG_Dn
507 enum vfp_sp_reg_pos
509 VFP_REG_Sd, VFP_REG_Sm, VFP_REG_Sn
512 enum vfp_ldstm_type
514 VFP_LDSTMIA, VFP_LDSTMDB, VFP_LDSTMIAX, VFP_LDSTMDBX
517 /* VFP system registers. */
518 struct vfp_reg
520 const char *name;
521 unsigned long regno;
524 static const struct vfp_reg vfp_regs[] =
526 {"fpsid", 0x00000000},
527 {"FPSID", 0x00000000},
528 {"fpscr", 0x00010000},
529 {"FPSCR", 0x00010000},
530 {"fpexc", 0x00080000},
531 {"FPEXC", 0x00080000}
534 /* Structure for a hash table entry for a register. */
535 struct reg_entry
537 const char * name;
538 int number;
541 /* Some well known registers that we refer to directly elsewhere. */
542 #define REG_SP 13
543 #define REG_LR 14
544 #define REG_PC 15
546 /* These are the standard names. Users can add aliases with .req. */
547 /* Integer Register Numbers. */
548 static const struct reg_entry rn_table[] =
550 {"r0", 0}, {"r1", 1}, {"r2", 2}, {"r3", 3},
551 {"r4", 4}, {"r5", 5}, {"r6", 6}, {"r7", 7},
552 {"r8", 8}, {"r9", 9}, {"r10", 10}, {"r11", 11},
553 {"r12", 12}, {"r13", REG_SP}, {"r14", REG_LR}, {"r15", REG_PC},
554 /* ATPCS Synonyms. */
555 {"a1", 0}, {"a2", 1}, {"a3", 2}, {"a4", 3},
556 {"v1", 4}, {"v2", 5}, {"v3", 6}, {"v4", 7},
557 {"v5", 8}, {"v6", 9}, {"v7", 10}, {"v8", 11},
558 /* Well-known aliases. */
559 {"wr", 7},
560 {"sb", 9}, {"sl", 10}, {"fp", 11},
561 {"ip", 12}, {"sp", REG_SP}, {"lr", REG_LR}, {"pc", REG_PC},
562 {NULL, 0}
565 /* Co-processor Numbers. */
566 static const struct reg_entry cp_table[] =
568 {"p0", 0}, {"p1", 1}, {"p2", 2}, {"p3", 3},
569 {"p4", 4}, {"p5", 5}, {"p6", 6}, {"p7", 7},
570 {"p8", 8}, {"p9", 9}, {"p10", 10}, {"p11", 11},
571 {"p12", 12}, {"p13", 13}, {"p14", 14}, {"p15", 15},
572 {NULL, 0}
575 /* Co-processor Register Numbers. */
576 static const struct reg_entry cn_table[] =
578 {"c0", 0}, {"c1", 1}, {"c2", 2}, {"c3", 3},
579 {"c4", 4}, {"c5", 5}, {"c6", 6}, {"c7", 7},
580 {"c8", 8}, {"c9", 9}, {"c10", 10}, {"c11", 11},
581 {"c12", 12}, {"c13", 13}, {"c14", 14}, {"c15", 15},
582 /* Not really valid, but kept for back-wards compatibility. */
583 {"cr0", 0}, {"cr1", 1}, {"cr2", 2}, {"cr3", 3},
584 {"cr4", 4}, {"cr5", 5}, {"cr6", 6}, {"cr7", 7},
585 {"cr8", 8}, {"cr9", 9}, {"cr10", 10}, {"cr11", 11},
586 {"cr12", 12}, {"cr13", 13}, {"cr14", 14}, {"cr15", 15},
587 {NULL, 0}
590 /* FPA Registers. */
591 static const struct reg_entry fn_table[] =
593 {"f0", 0}, {"f1", 1}, {"f2", 2}, {"f3", 3},
594 {"f4", 4}, {"f5", 5}, {"f6", 6}, {"f7", 7},
595 {NULL, 0}
598 /* VFP SP Registers. */
599 static const struct reg_entry sn_table[] =
601 {"s0", 0}, {"s1", 1}, {"s2", 2}, {"s3", 3},
602 {"s4", 4}, {"s5", 5}, {"s6", 6}, {"s7", 7},
603 {"s8", 8}, {"s9", 9}, {"s10", 10}, {"s11", 11},
604 {"s12", 12}, {"s13", 13}, {"s14", 14}, {"s15", 15},
605 {"s16", 16}, {"s17", 17}, {"s18", 18}, {"s19", 19},
606 {"s20", 20}, {"s21", 21}, {"s22", 22}, {"s23", 23},
607 {"s24", 24}, {"s25", 25}, {"s26", 26}, {"s27", 27},
608 {"s28", 28}, {"s29", 29}, {"s30", 30}, {"s31", 31},
609 {NULL, 0}
612 /* VFP DP Registers. */
613 static const struct reg_entry dn_table[] =
615 {"d0", 0}, {"d1", 1}, {"d2", 2}, {"d3", 3},
616 {"d4", 4}, {"d5", 5}, {"d6", 6}, {"d7", 7},
617 {"d8", 8}, {"d9", 9}, {"d10", 10}, {"d11", 11},
618 {"d12", 12}, {"d13", 13}, {"d14", 14}, {"d15", 15},
619 {NULL, 0}
622 /* Maverick DSP coprocessor registers. */
623 static const struct reg_entry mav_mvf_table[] =
625 {"mvf0", 0}, {"mvf1", 1}, {"mvf2", 2}, {"mvf3", 3},
626 {"mvf4", 4}, {"mvf5", 5}, {"mvf6", 6}, {"mvf7", 7},
627 {"mvf8", 8}, {"mvf9", 9}, {"mvf10", 10}, {"mvf11", 11},
628 {"mvf12", 12}, {"mvf13", 13}, {"mvf14", 14}, {"mvf15", 15},
629 {NULL, 0}
632 static const struct reg_entry mav_mvd_table[] =
634 {"mvd0", 0}, {"mvd1", 1}, {"mvd2", 2}, {"mvd3", 3},
635 {"mvd4", 4}, {"mvd5", 5}, {"mvd6", 6}, {"mvd7", 7},
636 {"mvd8", 8}, {"mvd9", 9}, {"mvd10", 10}, {"mvd11", 11},
637 {"mvd12", 12}, {"mvd13", 13}, {"mvd14", 14}, {"mvd15", 15},
638 {NULL, 0}
641 static const struct reg_entry mav_mvfx_table[] =
643 {"mvfx0", 0}, {"mvfx1", 1}, {"mvfx2", 2}, {"mvfx3", 3},
644 {"mvfx4", 4}, {"mvfx5", 5}, {"mvfx6", 6}, {"mvfx7", 7},
645 {"mvfx8", 8}, {"mvfx9", 9}, {"mvfx10", 10}, {"mvfx11", 11},
646 {"mvfx12", 12}, {"mvfx13", 13}, {"mvfx14", 14}, {"mvfx15", 15},
647 {NULL, 0}
650 static const struct reg_entry mav_mvdx_table[] =
652 {"mvdx0", 0}, {"mvdx1", 1}, {"mvdx2", 2}, {"mvdx3", 3},
653 {"mvdx4", 4}, {"mvdx5", 5}, {"mvdx6", 6}, {"mvdx7", 7},
654 {"mvdx8", 8}, {"mvdx9", 9}, {"mvdx10", 10}, {"mvdx11", 11},
655 {"mvdx12", 12}, {"mvdx13", 13}, {"mvdx14", 14}, {"mvdx15", 15},
656 {NULL, 0}
659 static const struct reg_entry mav_mvax_table[] =
661 {"mvax0", 0}, {"mvax1", 1}, {"mvax2", 2}, {"mvax3", 3},
662 {NULL, 0}
665 static const struct reg_entry mav_dspsc_table[] =
667 {"dspsc", 0},
668 {NULL, 0}
671 struct reg_map
673 const struct reg_entry *names;
674 int max_regno;
675 struct hash_control *htab;
676 const char *expected;
679 struct reg_map all_reg_maps[] =
681 {rn_table, 15, NULL, N_("ARM register expected")},
682 {cp_table, 15, NULL, N_("bad or missing co-processor number")},
683 {cn_table, 15, NULL, N_("co-processor register expected")},
684 {fn_table, 7, NULL, N_("FPA register expected")},
685 {sn_table, 31, NULL, N_("VFP single precision register expected")},
686 {dn_table, 15, NULL, N_("VFP double precision register expected")},
687 {mav_mvf_table, 15, NULL, N_("Maverick MVF register expected")},
688 {mav_mvd_table, 15, NULL, N_("Maverick MVD register expected")},
689 {mav_mvfx_table, 15, NULL, N_("Maverick MVFX register expected")},
690 {mav_mvdx_table, 15, NULL, N_("Maverick MVFX register expected")},
691 {mav_mvax_table, 3, NULL, N_("Maverick MVAX register expected")},
692 {mav_dspsc_table, 0, NULL, N_("Maverick DSPSC register expected")},
695 /* Enumeration matching entries in table above. */
696 enum arm_reg_type
698 REG_TYPE_RN = 0,
699 #define REG_TYPE_FIRST REG_TYPE_RN
700 REG_TYPE_CP = 1,
701 REG_TYPE_CN = 2,
702 REG_TYPE_FN = 3,
703 REG_TYPE_SN = 4,
704 REG_TYPE_DN = 5,
705 REG_TYPE_MVF = 6,
706 REG_TYPE_MVD = 7,
707 REG_TYPE_MVFX = 8,
708 REG_TYPE_MVDX = 9,
709 REG_TYPE_MVAX = 10,
710 REG_TYPE_DSPSC = 11,
712 REG_TYPE_MAX = 12
715 /* Functions called by parser. */
716 /* ARM instructions. */
717 static void do_arit PARAMS ((char *));
718 static void do_cmp PARAMS ((char *));
719 static void do_mov PARAMS ((char *));
720 static void do_ldst PARAMS ((char *));
721 static void do_ldstt PARAMS ((char *));
722 static void do_ldmstm PARAMS ((char *));
723 static void do_branch PARAMS ((char *));
724 static void do_swi PARAMS ((char *));
726 /* Pseudo Op codes. */
727 static void do_adr PARAMS ((char *));
728 static void do_adrl PARAMS ((char *));
729 static void do_empty PARAMS ((char *));
731 /* ARM v2. */
732 static void do_mul PARAMS ((char *));
733 static void do_mla PARAMS ((char *));
735 /* ARM v2S. */
736 static void do_swap PARAMS ((char *));
738 /* ARM v3. */
739 static void do_msr PARAMS ((char *));
740 static void do_mrs PARAMS ((char *));
742 /* ARM v3M. */
743 static void do_mull PARAMS ((char *));
745 /* ARM v4. */
746 static void do_ldstv4 PARAMS ((char *));
748 /* ARM v4T. */
749 static void do_bx PARAMS ((char *));
751 /* ARM v5T. */
752 static void do_blx PARAMS ((char *));
753 static void do_bkpt PARAMS ((char *));
754 static void do_clz PARAMS ((char *));
755 static void do_lstc2 PARAMS ((char *));
756 static void do_cdp2 PARAMS ((char *));
757 static void do_co_reg2 PARAMS ((char *));
759 /* ARM v5TExP. */
760 static void do_smla PARAMS ((char *));
761 static void do_smlal PARAMS ((char *));
762 static void do_smul PARAMS ((char *));
763 static void do_qadd PARAMS ((char *));
765 /* ARM v5TE. */
766 static void do_pld PARAMS ((char *));
767 static void do_ldrd PARAMS ((char *));
768 static void do_co_reg2c PARAMS ((char *));
770 /* ARM v5TEJ. */
771 static void do_bxj PARAMS ((char *));
773 /* Coprocessor Instructions. */
774 static void do_cdp PARAMS ((char *));
775 static void do_lstc PARAMS ((char *));
776 static void do_co_reg PARAMS ((char *));
778 /* FPA instructions. */
779 static void do_fpa_ctrl PARAMS ((char *));
780 static void do_fpa_ldst PARAMS ((char *));
781 static void do_fpa_ldmstm PARAMS ((char *));
782 static void do_fpa_dyadic PARAMS ((char *));
783 static void do_fpa_monadic PARAMS ((char *));
784 static void do_fpa_cmp PARAMS ((char *));
785 static void do_fpa_from_reg PARAMS ((char *));
786 static void do_fpa_to_reg PARAMS ((char *));
788 /* VFP instructions. */
789 static void do_vfp_sp_monadic PARAMS ((char *));
790 static void do_vfp_dp_monadic PARAMS ((char *));
791 static void do_vfp_sp_dyadic PARAMS ((char *));
792 static void do_vfp_dp_dyadic PARAMS ((char *));
793 static void do_vfp_reg_from_sp PARAMS ((char *));
794 static void do_vfp_sp_from_reg PARAMS ((char *));
795 static void do_vfp_sp_reg2 PARAMS ((char *));
796 static void do_vfp_reg_from_dp PARAMS ((char *));
797 static void do_vfp_reg2_from_dp PARAMS ((char *));
798 static void do_vfp_dp_from_reg PARAMS ((char *));
799 static void do_vfp_dp_from_reg2 PARAMS ((char *));
800 static void do_vfp_reg_from_ctrl PARAMS ((char *));
801 static void do_vfp_ctrl_from_reg PARAMS ((char *));
802 static void do_vfp_sp_ldst PARAMS ((char *));
803 static void do_vfp_dp_ldst PARAMS ((char *));
804 static void do_vfp_sp_ldstmia PARAMS ((char *));
805 static void do_vfp_sp_ldstmdb PARAMS ((char *));
806 static void do_vfp_dp_ldstmia PARAMS ((char *));
807 static void do_vfp_dp_ldstmdb PARAMS ((char *));
808 static void do_vfp_xp_ldstmia PARAMS ((char *));
809 static void do_vfp_xp_ldstmdb PARAMS ((char *));
810 static void do_vfp_sp_compare_z PARAMS ((char *));
811 static void do_vfp_dp_compare_z PARAMS ((char *));
812 static void do_vfp_dp_sp_cvt PARAMS ((char *));
813 static void do_vfp_sp_dp_cvt PARAMS ((char *));
815 /* XScale. */
816 static void do_xsc_mia PARAMS ((char *));
817 static void do_xsc_mar PARAMS ((char *));
818 static void do_xsc_mra PARAMS ((char *));
820 /* Maverick. */
821 static void do_mav_binops PARAMS ((char *, int, enum arm_reg_type,
822 enum arm_reg_type));
823 static void do_mav_binops_1a PARAMS ((char *));
824 static void do_mav_binops_1b PARAMS ((char *));
825 static void do_mav_binops_1c PARAMS ((char *));
826 static void do_mav_binops_1d PARAMS ((char *));
827 static void do_mav_binops_1e PARAMS ((char *));
828 static void do_mav_binops_1f PARAMS ((char *));
829 static void do_mav_binops_1g PARAMS ((char *));
830 static void do_mav_binops_1h PARAMS ((char *));
831 static void do_mav_binops_1i PARAMS ((char *));
832 static void do_mav_binops_1j PARAMS ((char *));
833 static void do_mav_binops_1k PARAMS ((char *));
834 static void do_mav_binops_1l PARAMS ((char *));
835 static void do_mav_binops_1m PARAMS ((char *));
836 static void do_mav_binops_1n PARAMS ((char *));
837 static void do_mav_binops_1o PARAMS ((char *));
838 static void do_mav_binops_2a PARAMS ((char *));
839 static void do_mav_binops_2b PARAMS ((char *));
840 static void do_mav_binops_2c PARAMS ((char *));
841 static void do_mav_binops_3a PARAMS ((char *));
842 static void do_mav_binops_3b PARAMS ((char *));
843 static void do_mav_binops_3c PARAMS ((char *));
844 static void do_mav_binops_3d PARAMS ((char *));
845 static void do_mav_triple PARAMS ((char *, int, enum arm_reg_type,
846 enum arm_reg_type,
847 enum arm_reg_type));
848 static void do_mav_triple_4a PARAMS ((char *));
849 static void do_mav_triple_4b PARAMS ((char *));
850 static void do_mav_triple_5a PARAMS ((char *));
851 static void do_mav_triple_5b PARAMS ((char *));
852 static void do_mav_triple_5c PARAMS ((char *));
853 static void do_mav_triple_5d PARAMS ((char *));
854 static void do_mav_triple_5e PARAMS ((char *));
855 static void do_mav_triple_5f PARAMS ((char *));
856 static void do_mav_triple_5g PARAMS ((char *));
857 static void do_mav_triple_5h PARAMS ((char *));
858 static void do_mav_quad PARAMS ((char *, int, enum arm_reg_type,
859 enum arm_reg_type,
860 enum arm_reg_type,
861 enum arm_reg_type));
862 static void do_mav_quad_6a PARAMS ((char *));
863 static void do_mav_quad_6b PARAMS ((char *));
864 static void do_mav_dspsc_1 PARAMS ((char *));
865 static void do_mav_dspsc_2 PARAMS ((char *));
866 static void do_mav_shift PARAMS ((char *, enum arm_reg_type,
867 enum arm_reg_type));
868 static void do_mav_shift_1 PARAMS ((char *));
869 static void do_mav_shift_2 PARAMS ((char *));
870 static void do_mav_ldst PARAMS ((char *, enum arm_reg_type));
871 static void do_mav_ldst_1 PARAMS ((char *));
872 static void do_mav_ldst_2 PARAMS ((char *));
873 static void do_mav_ldst_3 PARAMS ((char *));
874 static void do_mav_ldst_4 PARAMS ((char *));
876 static int mav_reg_required_here PARAMS ((char **, int,
877 enum arm_reg_type));
878 static int mav_parse_offset PARAMS ((char **, int *));
880 static void fix_new_arm PARAMS ((fragS *, int, short, expressionS *,
881 int, int));
882 static int arm_reg_parse PARAMS ((char **, struct hash_control *));
883 static enum arm_reg_type arm_reg_parse_any PARAMS ((char *));
884 static const struct asm_psr * arm_psr_parse PARAMS ((char **));
885 static void symbol_locate PARAMS ((symbolS *, const char *, segT, valueT,
886 fragS *));
887 static int add_to_lit_pool PARAMS ((void));
888 static unsigned validate_immediate PARAMS ((unsigned));
889 static unsigned validate_immediate_twopart PARAMS ((unsigned int,
890 unsigned int *));
891 static int validate_offset_imm PARAMS ((unsigned int, int));
892 static void opcode_select PARAMS ((int));
893 static void end_of_line PARAMS ((char *));
894 static int reg_required_here PARAMS ((char **, int));
895 static int psr_required_here PARAMS ((char **));
896 static int co_proc_number PARAMS ((char **));
897 static int cp_opc_expr PARAMS ((char **, int, int));
898 static int cp_reg_required_here PARAMS ((char **, int));
899 static int fp_reg_required_here PARAMS ((char **, int));
900 static int vfp_sp_reg_required_here PARAMS ((char **, enum vfp_sp_reg_pos));
901 static int vfp_dp_reg_required_here PARAMS ((char **, enum vfp_dp_reg_pos));
902 static void vfp_sp_ldstm PARAMS ((char *, enum vfp_ldstm_type));
903 static void vfp_dp_ldstm PARAMS ((char *, enum vfp_ldstm_type));
904 static long vfp_sp_reg_list PARAMS ((char **, enum vfp_sp_reg_pos));
905 static long vfp_dp_reg_list PARAMS ((char **));
906 static int vfp_psr_required_here PARAMS ((char **str));
907 static const struct vfp_reg *vfp_psr_parse PARAMS ((char **str));
908 static int cp_address_offset PARAMS ((char **));
909 static int cp_address_required_here PARAMS ((char **, int));
910 static int my_get_float_expression PARAMS ((char **));
911 static int skip_past_comma PARAMS ((char **));
912 static int walk_no_bignums PARAMS ((symbolS *));
913 static int negate_data_op PARAMS ((unsigned long *, unsigned long));
914 static int data_op2 PARAMS ((char **));
915 static int fp_op2 PARAMS ((char **));
916 static long reg_list PARAMS ((char **));
917 static void thumb_load_store PARAMS ((char *, int, int));
918 static int decode_shift PARAMS ((char **, int));
919 static int ldst_extend PARAMS ((char **));
920 static int ldst_extend_v4 PARAMS ((char **));
921 static void thumb_add_sub PARAMS ((char *, int));
922 static void insert_reg PARAMS ((const struct reg_entry *,
923 struct hash_control *));
924 static void thumb_shift PARAMS ((char *, int));
925 static void thumb_mov_compare PARAMS ((char *, int));
926 static void build_arm_ops_hsh PARAMS ((void));
927 static void set_constant_flonums PARAMS ((void));
928 static valueT md_chars_to_number PARAMS ((char *, int));
929 static void build_reg_hsh PARAMS ((struct reg_map *));
930 static void insert_reg_alias PARAMS ((char *, int, struct hash_control *));
931 static int create_register_alias PARAMS ((char *, char *));
932 static void output_inst PARAMS ((const char *));
933 static int accum0_required_here PARAMS ((char **));
934 static int ld_mode_required_here PARAMS ((char **));
935 static void do_branch25 PARAMS ((char *));
936 static symbolS * find_real_start PARAMS ((symbolS *));
937 #ifdef OBJ_ELF
938 static bfd_reloc_code_real_type arm_parse_reloc PARAMS ((void));
939 #endif
941 /* ARM instructions take 4bytes in the object file, Thumb instructions
942 take 2: */
943 #define INSN_SIZE 4
945 /* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
946 #define MAV_MODE1 0x100c
948 /* "INSN<cond> X,Y" where X:bit16, Y:bit12. */
949 #define MAV_MODE2 0x0c10
951 /* "INSN<cond> X,Y" where X:0, Y:bit16. */
952 #define MAV_MODE3 0x1000
954 /* "INSN<cond> X,Y,Z" where X:16, Y:0, Z:12. */
955 #define MAV_MODE4 0x0c0010
957 /* "INSN<cond> X,Y,Z" where X:12, Y:16, Z:0. */
958 #define MAV_MODE5 0x00100c
960 /* "INSN<cond> W,X,Y,Z" where W:5, X:12, Y:16, Z:0. */
961 #define MAV_MODE6 0x00100c05
963 struct asm_opcode
965 /* Basic string to match. */
966 const char * template;
968 /* Basic instruction code. */
969 unsigned long value;
971 /* Offset into the template where the condition code (if any) will be.
972 If zero, then the instruction is never conditional. */
973 unsigned cond_offset;
975 /* Which architecture variant provides this instruction. */
976 unsigned long variant;
978 /* Function to call to parse args. */
979 void (* parms) PARAMS ((char *));
982 static const struct asm_opcode insns[] =
984 /* Core ARM Instructions. */
985 {"and", 0xe0000000, 3, ARM_EXT_V1, do_arit},
986 {"ands", 0xe0100000, 3, ARM_EXT_V1, do_arit},
987 {"eor", 0xe0200000, 3, ARM_EXT_V1, do_arit},
988 {"eors", 0xe0300000, 3, ARM_EXT_V1, do_arit},
989 {"sub", 0xe0400000, 3, ARM_EXT_V1, do_arit},
990 {"subs", 0xe0500000, 3, ARM_EXT_V1, do_arit},
991 {"rsb", 0xe0600000, 3, ARM_EXT_V1, do_arit},
992 {"rsbs", 0xe0700000, 3, ARM_EXT_V1, do_arit},
993 {"add", 0xe0800000, 3, ARM_EXT_V1, do_arit},
994 {"adds", 0xe0900000, 3, ARM_EXT_V1, do_arit},
995 {"adc", 0xe0a00000, 3, ARM_EXT_V1, do_arit},
996 {"adcs", 0xe0b00000, 3, ARM_EXT_V1, do_arit},
997 {"sbc", 0xe0c00000, 3, ARM_EXT_V1, do_arit},
998 {"sbcs", 0xe0d00000, 3, ARM_EXT_V1, do_arit},
999 {"rsc", 0xe0e00000, 3, ARM_EXT_V1, do_arit},
1000 {"rscs", 0xe0f00000, 3, ARM_EXT_V1, do_arit},
1001 {"orr", 0xe1800000, 3, ARM_EXT_V1, do_arit},
1002 {"orrs", 0xe1900000, 3, ARM_EXT_V1, do_arit},
1003 {"bic", 0xe1c00000, 3, ARM_EXT_V1, do_arit},
1004 {"bics", 0xe1d00000, 3, ARM_EXT_V1, do_arit},
1006 {"tst", 0xe1100000, 3, ARM_EXT_V1, do_cmp},
1007 {"tsts", 0xe1100000, 3, ARM_EXT_V1, do_cmp},
1008 {"tstp", 0xe110f000, 3, ARM_EXT_V1, do_cmp},
1009 {"teq", 0xe1300000, 3, ARM_EXT_V1, do_cmp},
1010 {"teqs", 0xe1300000, 3, ARM_EXT_V1, do_cmp},
1011 {"teqp", 0xe130f000, 3, ARM_EXT_V1, do_cmp},
1012 {"cmp", 0xe1500000, 3, ARM_EXT_V1, do_cmp},
1013 {"cmps", 0xe1500000, 3, ARM_EXT_V1, do_cmp},
1014 {"cmpp", 0xe150f000, 3, ARM_EXT_V1, do_cmp},
1015 {"cmn", 0xe1700000, 3, ARM_EXT_V1, do_cmp},
1016 {"cmns", 0xe1700000, 3, ARM_EXT_V1, do_cmp},
1017 {"cmnp", 0xe170f000, 3, ARM_EXT_V1, do_cmp},
1019 {"mov", 0xe1a00000, 3, ARM_EXT_V1, do_mov},
1020 {"movs", 0xe1b00000, 3, ARM_EXT_V1, do_mov},
1021 {"mvn", 0xe1e00000, 3, ARM_EXT_V1, do_mov},
1022 {"mvns", 0xe1f00000, 3, ARM_EXT_V1, do_mov},
1024 {"ldr", 0xe4100000, 3, ARM_EXT_V1, do_ldst},
1025 {"ldrb", 0xe4500000, 3, ARM_EXT_V1, do_ldst},
1026 {"ldrt", 0xe4300000, 3, ARM_EXT_V1, do_ldstt},
1027 {"ldrbt", 0xe4700000, 3, ARM_EXT_V1, do_ldstt},
1028 {"str", 0xe4000000, 3, ARM_EXT_V1, do_ldst},
1029 {"strb", 0xe4400000, 3, ARM_EXT_V1, do_ldst},
1030 {"strt", 0xe4200000, 3, ARM_EXT_V1, do_ldstt},
1031 {"strbt", 0xe4600000, 3, ARM_EXT_V1, do_ldstt},
1033 {"stmia", 0xe8800000, 3, ARM_EXT_V1, do_ldmstm},
1034 {"stmib", 0xe9800000, 3, ARM_EXT_V1, do_ldmstm},
1035 {"stmda", 0xe8000000, 3, ARM_EXT_V1, do_ldmstm},
1036 {"stmdb", 0xe9000000, 3, ARM_EXT_V1, do_ldmstm},
1037 {"stmfd", 0xe9000000, 3, ARM_EXT_V1, do_ldmstm},
1038 {"stmfa", 0xe9800000, 3, ARM_EXT_V1, do_ldmstm},
1039 {"stmea", 0xe8800000, 3, ARM_EXT_V1, do_ldmstm},
1040 {"stmed", 0xe8000000, 3, ARM_EXT_V1, do_ldmstm},
1042 {"ldmia", 0xe8900000, 3, ARM_EXT_V1, do_ldmstm},
1043 {"ldmib", 0xe9900000, 3, ARM_EXT_V1, do_ldmstm},
1044 {"ldmda", 0xe8100000, 3, ARM_EXT_V1, do_ldmstm},
1045 {"ldmdb", 0xe9100000, 3, ARM_EXT_V1, do_ldmstm},
1046 {"ldmfd", 0xe8900000, 3, ARM_EXT_V1, do_ldmstm},
1047 {"ldmfa", 0xe8100000, 3, ARM_EXT_V1, do_ldmstm},
1048 {"ldmea", 0xe9100000, 3, ARM_EXT_V1, do_ldmstm},
1049 {"ldmed", 0xe9900000, 3, ARM_EXT_V1, do_ldmstm},
1051 {"swi", 0xef000000, 3, ARM_EXT_V1, do_swi},
1052 #ifdef TE_WINCE
1053 /* XXX This is the wrong place to do this. Think multi-arch. */
1054 {"bl", 0xeb000000, 2, ARM_EXT_V1, do_branch},
1055 {"b", 0xea000000, 1, ARM_EXT_V1, do_branch},
1056 #else
1057 {"bl", 0xebfffffe, 2, ARM_EXT_V1, do_branch},
1058 {"b", 0xeafffffe, 1, ARM_EXT_V1, do_branch},
1059 #endif
1061 /* Pseudo ops. */
1062 {"adr", 0xe28f0000, 3, ARM_EXT_V1, do_adr},
1063 {"adrl", 0xe28f0000, 3, ARM_EXT_V1, do_adrl},
1064 {"nop", 0xe1a00000, 3, ARM_EXT_V1, do_empty},
1066 /* ARM 2 multiplies. */
1067 {"mul", 0xe0000090, 3, ARM_EXT_V2, do_mul},
1068 {"muls", 0xe0100090, 3, ARM_EXT_V2, do_mul},
1069 {"mla", 0xe0200090, 3, ARM_EXT_V2, do_mla},
1070 {"mlas", 0xe0300090, 3, ARM_EXT_V2, do_mla},
1072 /* Generic copressor instructions. */
1073 {"cdp", 0xee000000, 3, ARM_EXT_V2, do_cdp},
1074 {"ldc", 0xec100000, 3, ARM_EXT_V2, do_lstc},
1075 {"ldcl", 0xec500000, 3, ARM_EXT_V2, do_lstc},
1076 {"stc", 0xec000000, 3, ARM_EXT_V2, do_lstc},
1077 {"stcl", 0xec400000, 3, ARM_EXT_V2, do_lstc},
1078 {"mcr", 0xee000010, 3, ARM_EXT_V2, do_co_reg},
1079 {"mrc", 0xee100010, 3, ARM_EXT_V2, do_co_reg},
1081 /* ARM 3 - swp instructions. */
1082 {"swp", 0xe1000090, 3, ARM_EXT_V2S, do_swap},
1083 {"swpb", 0xe1400090, 3, ARM_EXT_V2S, do_swap},
1085 /* ARM 6 Status register instructions. */
1086 {"mrs", 0xe10f0000, 3, ARM_EXT_V3, do_mrs},
1087 {"msr", 0xe120f000, 3, ARM_EXT_V3, do_msr},
1088 /* ScottB: our code uses 0xe128f000 for msr.
1089 NickC: but this is wrong because the bits 16 through 19 are
1090 handled by the PSR_xxx defines above. */
1092 /* ARM 7M long multiplies. */
1093 {"smull", 0xe0c00090, 5, ARM_EXT_V3M, do_mull},
1094 {"smulls", 0xe0d00090, 5, ARM_EXT_V3M, do_mull},
1095 {"umull", 0xe0800090, 5, ARM_EXT_V3M, do_mull},
1096 {"umulls", 0xe0900090, 5, ARM_EXT_V3M, do_mull},
1097 {"smlal", 0xe0e00090, 5, ARM_EXT_V3M, do_mull},
1098 {"smlals", 0xe0f00090, 5, ARM_EXT_V3M, do_mull},
1099 {"umlal", 0xe0a00090, 5, ARM_EXT_V3M, do_mull},
1100 {"umlals", 0xe0b00090, 5, ARM_EXT_V3M, do_mull},
1102 /* ARM Architecture 4. */
1103 {"ldrh", 0xe01000b0, 3, ARM_EXT_V4, do_ldstv4},
1104 {"ldrsh", 0xe01000f0, 3, ARM_EXT_V4, do_ldstv4},
1105 {"ldrsb", 0xe01000d0, 3, ARM_EXT_V4, do_ldstv4},
1106 {"strh", 0xe00000b0, 3, ARM_EXT_V4, do_ldstv4},
1108 /* ARM Architecture 4T. */
1109 /* Note: bx (and blx) are required on V5, even if the processor does
1110 not support Thumb. */
1111 {"bx", 0xe12fff10, 2, ARM_EXT_V4T | ARM_EXT_V5, do_bx},
1113 /* ARM Architecture 5T. */
1114 /* Note: blx has 2 variants, so the .value is set dynamically.
1115 Only one of the variants has conditional execution. */
1116 {"blx", 0xe0000000, 3, ARM_EXT_V5, do_blx},
1117 {"clz", 0xe16f0f10, 3, ARM_EXT_V5, do_clz},
1118 {"bkpt", 0xe1200070, 0, ARM_EXT_V5, do_bkpt},
1119 {"ldc2", 0xfc100000, 0, ARM_EXT_V5, do_lstc2},
1120 {"ldc2l", 0xfc500000, 0, ARM_EXT_V5, do_lstc2},
1121 {"stc2", 0xfc000000, 0, ARM_EXT_V5, do_lstc2},
1122 {"stc2l", 0xfc400000, 0, ARM_EXT_V5, do_lstc2},
1123 {"cdp2", 0xfe000000, 0, ARM_EXT_V5, do_cdp2},
1124 {"mcr2", 0xfe000010, 0, ARM_EXT_V5, do_co_reg2},
1125 {"mrc2", 0xfe100010, 0, ARM_EXT_V5, do_co_reg2},
1127 /* ARM Architecture 5TExP. */
1128 {"smlabb", 0xe1000080, 6, ARM_EXT_V5ExP, do_smla},
1129 {"smlatb", 0xe10000a0, 6, ARM_EXT_V5ExP, do_smla},
1130 {"smlabt", 0xe10000c0, 6, ARM_EXT_V5ExP, do_smla},
1131 {"smlatt", 0xe10000e0, 6, ARM_EXT_V5ExP, do_smla},
1133 {"smlawb", 0xe1200080, 6, ARM_EXT_V5ExP, do_smla},
1134 {"smlawt", 0xe12000c0, 6, ARM_EXT_V5ExP, do_smla},
1136 {"smlalbb", 0xe1400080, 7, ARM_EXT_V5ExP, do_smlal},
1137 {"smlaltb", 0xe14000a0, 7, ARM_EXT_V5ExP, do_smlal},
1138 {"smlalbt", 0xe14000c0, 7, ARM_EXT_V5ExP, do_smlal},
1139 {"smlaltt", 0xe14000e0, 7, ARM_EXT_V5ExP, do_smlal},
1141 {"smulbb", 0xe1600080, 6, ARM_EXT_V5ExP, do_smul},
1142 {"smultb", 0xe16000a0, 6, ARM_EXT_V5ExP, do_smul},
1143 {"smulbt", 0xe16000c0, 6, ARM_EXT_V5ExP, do_smul},
1144 {"smultt", 0xe16000e0, 6, ARM_EXT_V5ExP, do_smul},
1146 {"smulwb", 0xe12000a0, 6, ARM_EXT_V5ExP, do_smul},
1147 {"smulwt", 0xe12000e0, 6, ARM_EXT_V5ExP, do_smul},
1149 {"qadd", 0xe1000050, 4, ARM_EXT_V5ExP, do_qadd},
1150 {"qdadd", 0xe1400050, 5, ARM_EXT_V5ExP, do_qadd},
1151 {"qsub", 0xe1200050, 4, ARM_EXT_V5ExP, do_qadd},
1152 {"qdsub", 0xe1600050, 5, ARM_EXT_V5ExP, do_qadd},
1154 /* ARM Architecture 5TE. */
1155 {"pld", 0xf450f000, 0, ARM_EXT_V5E, do_pld},
1156 {"ldrd", 0xe00000d0, 3, ARM_EXT_V5E, do_ldrd},
1157 {"strd", 0xe00000f0, 3, ARM_EXT_V5E, do_ldrd},
1159 {"mcrr", 0xec400000, 4, ARM_EXT_V5E, do_co_reg2c},
1160 {"mrrc", 0xec500000, 4, ARM_EXT_V5E, do_co_reg2c},
1162 /* ARM Architecture 5TEJ. */
1163 {"bxj", 0xe12fff20, 3, ARM_EXT_V5J, do_bxj},
1165 /* Core FPA instruction set (V1). */
1166 {"wfs", 0xee200110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
1167 {"rfs", 0xee300110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
1168 {"wfc", 0xee400110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
1169 {"rfc", 0xee500110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
1171 {"ldfs", 0xec100100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1172 {"ldfd", 0xec108100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1173 {"ldfe", 0xec500100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1174 {"ldfp", 0xec508100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1176 {"stfs", 0xec000100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1177 {"stfd", 0xec008100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1178 {"stfe", 0xec400100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1179 {"stfp", 0xec408100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1181 {"mvfs", 0xee008100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1182 {"mvfsp", 0xee008120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1183 {"mvfsm", 0xee008140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1184 {"mvfsz", 0xee008160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1185 {"mvfd", 0xee008180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1186 {"mvfdp", 0xee0081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1187 {"mvfdm", 0xee0081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1188 {"mvfdz", 0xee0081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1189 {"mvfe", 0xee088100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1190 {"mvfep", 0xee088120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1191 {"mvfem", 0xee088140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1192 {"mvfez", 0xee088160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1194 {"mnfs", 0xee108100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1195 {"mnfsp", 0xee108120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1196 {"mnfsm", 0xee108140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1197 {"mnfsz", 0xee108160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1198 {"mnfd", 0xee108180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1199 {"mnfdp", 0xee1081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1200 {"mnfdm", 0xee1081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1201 {"mnfdz", 0xee1081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1202 {"mnfe", 0xee188100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1203 {"mnfep", 0xee188120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1204 {"mnfem", 0xee188140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1205 {"mnfez", 0xee188160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1207 {"abss", 0xee208100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1208 {"abssp", 0xee208120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1209 {"abssm", 0xee208140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1210 {"abssz", 0xee208160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1211 {"absd", 0xee208180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1212 {"absdp", 0xee2081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1213 {"absdm", 0xee2081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1214 {"absdz", 0xee2081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1215 {"abse", 0xee288100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1216 {"absep", 0xee288120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1217 {"absem", 0xee288140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1218 {"absez", 0xee288160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1220 {"rnds", 0xee308100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1221 {"rndsp", 0xee308120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1222 {"rndsm", 0xee308140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1223 {"rndsz", 0xee308160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1224 {"rndd", 0xee308180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1225 {"rnddp", 0xee3081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1226 {"rnddm", 0xee3081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1227 {"rnddz", 0xee3081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1228 {"rnde", 0xee388100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1229 {"rndep", 0xee388120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1230 {"rndem", 0xee388140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1231 {"rndez", 0xee388160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1233 {"sqts", 0xee408100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1234 {"sqtsp", 0xee408120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1235 {"sqtsm", 0xee408140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1236 {"sqtsz", 0xee408160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1237 {"sqtd", 0xee408180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1238 {"sqtdp", 0xee4081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1239 {"sqtdm", 0xee4081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1240 {"sqtdz", 0xee4081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1241 {"sqte", 0xee488100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1242 {"sqtep", 0xee488120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1243 {"sqtem", 0xee488140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1244 {"sqtez", 0xee488160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1246 {"logs", 0xee508100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1247 {"logsp", 0xee508120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1248 {"logsm", 0xee508140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1249 {"logsz", 0xee508160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1250 {"logd", 0xee508180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1251 {"logdp", 0xee5081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1252 {"logdm", 0xee5081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1253 {"logdz", 0xee5081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1254 {"loge", 0xee588100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1255 {"logep", 0xee588120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1256 {"logem", 0xee588140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1257 {"logez", 0xee588160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1259 {"lgns", 0xee608100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1260 {"lgnsp", 0xee608120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1261 {"lgnsm", 0xee608140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1262 {"lgnsz", 0xee608160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1263 {"lgnd", 0xee608180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1264 {"lgndp", 0xee6081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1265 {"lgndm", 0xee6081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1266 {"lgndz", 0xee6081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1267 {"lgne", 0xee688100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1268 {"lgnep", 0xee688120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1269 {"lgnem", 0xee688140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1270 {"lgnez", 0xee688160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1272 {"exps", 0xee708100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1273 {"expsp", 0xee708120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1274 {"expsm", 0xee708140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1275 {"expsz", 0xee708160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1276 {"expd", 0xee708180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1277 {"expdp", 0xee7081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1278 {"expdm", 0xee7081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1279 {"expdz", 0xee7081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1280 {"expe", 0xee788100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1281 {"expep", 0xee788120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1282 {"expem", 0xee788140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1283 {"expdz", 0xee788160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1285 {"sins", 0xee808100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1286 {"sinsp", 0xee808120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1287 {"sinsm", 0xee808140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1288 {"sinsz", 0xee808160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1289 {"sind", 0xee808180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1290 {"sindp", 0xee8081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1291 {"sindm", 0xee8081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1292 {"sindz", 0xee8081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1293 {"sine", 0xee888100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1294 {"sinep", 0xee888120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1295 {"sinem", 0xee888140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1296 {"sinez", 0xee888160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1298 {"coss", 0xee908100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1299 {"cossp", 0xee908120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1300 {"cossm", 0xee908140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1301 {"cossz", 0xee908160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1302 {"cosd", 0xee908180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1303 {"cosdp", 0xee9081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1304 {"cosdm", 0xee9081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1305 {"cosdz", 0xee9081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1306 {"cose", 0xee988100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1307 {"cosep", 0xee988120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1308 {"cosem", 0xee988140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1309 {"cosez", 0xee988160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1311 {"tans", 0xeea08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1312 {"tansp", 0xeea08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1313 {"tansm", 0xeea08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1314 {"tansz", 0xeea08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1315 {"tand", 0xeea08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1316 {"tandp", 0xeea081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1317 {"tandm", 0xeea081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1318 {"tandz", 0xeea081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1319 {"tane", 0xeea88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1320 {"tanep", 0xeea88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1321 {"tanem", 0xeea88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1322 {"tanez", 0xeea88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1324 {"asns", 0xeeb08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1325 {"asnsp", 0xeeb08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1326 {"asnsm", 0xeeb08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1327 {"asnsz", 0xeeb08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1328 {"asnd", 0xeeb08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1329 {"asndp", 0xeeb081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1330 {"asndm", 0xeeb081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1331 {"asndz", 0xeeb081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1332 {"asne", 0xeeb88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1333 {"asnep", 0xeeb88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1334 {"asnem", 0xeeb88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1335 {"asnez", 0xeeb88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1337 {"acss", 0xeec08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1338 {"acssp", 0xeec08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1339 {"acssm", 0xeec08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1340 {"acssz", 0xeec08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1341 {"acsd", 0xeec08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1342 {"acsdp", 0xeec081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1343 {"acsdm", 0xeec081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1344 {"acsdz", 0xeec081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1345 {"acse", 0xeec88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1346 {"acsep", 0xeec88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1347 {"acsem", 0xeec88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1348 {"acsez", 0xeec88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1350 {"atns", 0xeed08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1351 {"atnsp", 0xeed08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1352 {"atnsm", 0xeed08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1353 {"atnsz", 0xeed08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1354 {"atnd", 0xeed08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1355 {"atndp", 0xeed081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1356 {"atndm", 0xeed081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1357 {"atndz", 0xeed081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1358 {"atne", 0xeed88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1359 {"atnep", 0xeed88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1360 {"atnem", 0xeed88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1361 {"atnez", 0xeed88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1363 {"urds", 0xeee08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1364 {"urdsp", 0xeee08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1365 {"urdsm", 0xeee08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1366 {"urdsz", 0xeee08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1367 {"urdd", 0xeee08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1368 {"urddp", 0xeee081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1369 {"urddm", 0xeee081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1370 {"urddz", 0xeee081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1371 {"urde", 0xeee88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1372 {"urdep", 0xeee88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1373 {"urdem", 0xeee88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1374 {"urdez", 0xeee88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1376 {"nrms", 0xeef08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1377 {"nrmsp", 0xeef08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1378 {"nrmsm", 0xeef08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1379 {"nrmsz", 0xeef08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1380 {"nrmd", 0xeef08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1381 {"nrmdp", 0xeef081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1382 {"nrmdm", 0xeef081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1383 {"nrmdz", 0xeef081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1384 {"nrme", 0xeef88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1385 {"nrmep", 0xeef88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1386 {"nrmem", 0xeef88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1387 {"nrmez", 0xeef88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1389 {"adfs", 0xee000100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1390 {"adfsp", 0xee000120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1391 {"adfsm", 0xee000140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1392 {"adfsz", 0xee000160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1393 {"adfd", 0xee000180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1394 {"adfdp", 0xee0001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1395 {"adfdm", 0xee0001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1396 {"adfdz", 0xee0001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1397 {"adfe", 0xee080100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1398 {"adfep", 0xee080120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1399 {"adfem", 0xee080140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1400 {"adfez", 0xee080160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1402 {"sufs", 0xee200100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1403 {"sufsp", 0xee200120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1404 {"sufsm", 0xee200140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1405 {"sufsz", 0xee200160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1406 {"sufd", 0xee200180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1407 {"sufdp", 0xee2001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1408 {"sufdm", 0xee2001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1409 {"sufdz", 0xee2001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1410 {"sufe", 0xee280100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1411 {"sufep", 0xee280120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1412 {"sufem", 0xee280140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1413 {"sufez", 0xee280160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1415 {"rsfs", 0xee300100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1416 {"rsfsp", 0xee300120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1417 {"rsfsm", 0xee300140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1418 {"rsfsz", 0xee300160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1419 {"rsfd", 0xee300180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1420 {"rsfdp", 0xee3001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1421 {"rsfdm", 0xee3001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1422 {"rsfdz", 0xee3001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1423 {"rsfe", 0xee380100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1424 {"rsfep", 0xee380120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1425 {"rsfem", 0xee380140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1426 {"rsfez", 0xee380160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1428 {"mufs", 0xee100100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1429 {"mufsp", 0xee100120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1430 {"mufsm", 0xee100140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1431 {"mufsz", 0xee100160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1432 {"mufd", 0xee100180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1433 {"mufdp", 0xee1001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1434 {"mufdm", 0xee1001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1435 {"mufdz", 0xee1001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1436 {"mufe", 0xee180100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1437 {"mufep", 0xee180120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1438 {"mufem", 0xee180140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1439 {"mufez", 0xee180160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1441 {"dvfs", 0xee400100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1442 {"dvfsp", 0xee400120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1443 {"dvfsm", 0xee400140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1444 {"dvfsz", 0xee400160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1445 {"dvfd", 0xee400180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1446 {"dvfdp", 0xee4001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1447 {"dvfdm", 0xee4001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1448 {"dvfdz", 0xee4001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1449 {"dvfe", 0xee480100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1450 {"dvfep", 0xee480120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1451 {"dvfem", 0xee480140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1452 {"dvfez", 0xee480160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1454 {"rdfs", 0xee500100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1455 {"rdfsp", 0xee500120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1456 {"rdfsm", 0xee500140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1457 {"rdfsz", 0xee500160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1458 {"rdfd", 0xee500180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1459 {"rdfdp", 0xee5001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1460 {"rdfdm", 0xee5001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1461 {"rdfdz", 0xee5001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1462 {"rdfe", 0xee580100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1463 {"rdfep", 0xee580120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1464 {"rdfem", 0xee580140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1465 {"rdfez", 0xee580160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1467 {"pows", 0xee600100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1468 {"powsp", 0xee600120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1469 {"powsm", 0xee600140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1470 {"powsz", 0xee600160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1471 {"powd", 0xee600180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1472 {"powdp", 0xee6001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1473 {"powdm", 0xee6001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1474 {"powdz", 0xee6001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1475 {"powe", 0xee680100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1476 {"powep", 0xee680120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1477 {"powem", 0xee680140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1478 {"powez", 0xee680160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1480 {"rpws", 0xee700100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1481 {"rpwsp", 0xee700120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1482 {"rpwsm", 0xee700140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1483 {"rpwsz", 0xee700160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1484 {"rpwd", 0xee700180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1485 {"rpwdp", 0xee7001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1486 {"rpwdm", 0xee7001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1487 {"rpwdz", 0xee7001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1488 {"rpwe", 0xee780100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1489 {"rpwep", 0xee780120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1490 {"rpwem", 0xee780140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1491 {"rpwez", 0xee780160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1493 {"rmfs", 0xee800100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1494 {"rmfsp", 0xee800120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1495 {"rmfsm", 0xee800140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1496 {"rmfsz", 0xee800160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1497 {"rmfd", 0xee800180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1498 {"rmfdp", 0xee8001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1499 {"rmfdm", 0xee8001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1500 {"rmfdz", 0xee8001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1501 {"rmfe", 0xee880100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1502 {"rmfep", 0xee880120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1503 {"rmfem", 0xee880140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1504 {"rmfez", 0xee880160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1506 {"fmls", 0xee900100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1507 {"fmlsp", 0xee900120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1508 {"fmlsm", 0xee900140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1509 {"fmlsz", 0xee900160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1510 {"fmld", 0xee900180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1511 {"fmldp", 0xee9001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1512 {"fmldm", 0xee9001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1513 {"fmldz", 0xee9001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1514 {"fmle", 0xee980100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1515 {"fmlep", 0xee980120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1516 {"fmlem", 0xee980140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1517 {"fmlez", 0xee980160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1519 {"fdvs", 0xeea00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1520 {"fdvsp", 0xeea00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1521 {"fdvsm", 0xeea00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1522 {"fdvsz", 0xeea00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1523 {"fdvd", 0xeea00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1524 {"fdvdp", 0xeea001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1525 {"fdvdm", 0xeea001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1526 {"fdvdz", 0xeea001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1527 {"fdve", 0xeea80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1528 {"fdvep", 0xeea80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1529 {"fdvem", 0xeea80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1530 {"fdvez", 0xeea80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1532 {"frds", 0xeeb00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1533 {"frdsp", 0xeeb00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1534 {"frdsm", 0xeeb00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1535 {"frdsz", 0xeeb00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1536 {"frdd", 0xeeb00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1537 {"frddp", 0xeeb001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1538 {"frddm", 0xeeb001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1539 {"frddz", 0xeeb001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1540 {"frde", 0xeeb80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1541 {"frdep", 0xeeb80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1542 {"frdem", 0xeeb80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1543 {"frdez", 0xeeb80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1545 {"pols", 0xeec00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1546 {"polsp", 0xeec00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1547 {"polsm", 0xeec00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1548 {"polsz", 0xeec00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1549 {"pold", 0xeec00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1550 {"poldp", 0xeec001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1551 {"poldm", 0xeec001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1552 {"poldz", 0xeec001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1553 {"pole", 0xeec80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1554 {"polep", 0xeec80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1555 {"polem", 0xeec80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1556 {"polez", 0xeec80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1558 {"cmf", 0xee90f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
1559 {"cmfe", 0xeed0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
1560 {"cnf", 0xeeb0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
1561 {"cnfe", 0xeef0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
1562 /* The FPA10 data sheet suggests that the 'E' of cmfe/cnfe should
1563 not be an optional suffix, but part of the instruction. To be
1564 compatible, we accept either. */
1565 {"cmfe", 0xeed0f110, 4, FPU_FPA_EXT_V1, do_fpa_cmp},
1566 {"cnfe", 0xeef0f110, 4, FPU_FPA_EXT_V1, do_fpa_cmp},
1568 {"flts", 0xee000110, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1569 {"fltsp", 0xee000130, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1570 {"fltsm", 0xee000150, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1571 {"fltsz", 0xee000170, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1572 {"fltd", 0xee000190, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1573 {"fltdp", 0xee0001b0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1574 {"fltdm", 0xee0001d0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1575 {"fltdz", 0xee0001f0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1576 {"flte", 0xee080110, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1577 {"fltep", 0xee080130, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1578 {"fltem", 0xee080150, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1579 {"fltez", 0xee080170, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1581 /* The implementation of the FIX instruction is broken on some
1582 assemblers, in that it accepts a precision specifier as well as a
1583 rounding specifier, despite the fact that this is meaningless.
1584 To be more compatible, we accept it as well, though of course it
1585 does not set any bits. */
1586 {"fix", 0xee100110, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1587 {"fixp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1588 {"fixm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1589 {"fixz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1590 {"fixsp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1591 {"fixsm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1592 {"fixsz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1593 {"fixdp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1594 {"fixdm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1595 {"fixdz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1596 {"fixep", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1597 {"fixem", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1598 {"fixez", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1600 /* Instructions that were new with the real FPA, call them V2. */
1601 {"lfm", 0xec100200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1602 {"lfmfd", 0xec900200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1603 {"lfmea", 0xed100200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1604 {"sfm", 0xec000200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1605 {"sfmfd", 0xed000200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1606 {"sfmea", 0xec800200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1608 /* VFP V1xD (single precision). */
1609 /* Moves and type conversions. */
1610 {"fcpys", 0xeeb00a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1611 {"fmrs", 0xee100a10, 4, FPU_VFP_EXT_V1xD, do_vfp_reg_from_sp},
1612 {"fmsr", 0xee000a10, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_from_reg},
1613 {"fmstat", 0xeef1fa10, 6, FPU_VFP_EXT_V1xD, do_empty},
1614 {"fsitos", 0xeeb80ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1615 {"fuitos", 0xeeb80a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1616 {"ftosis", 0xeebd0a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1617 {"ftosizs", 0xeebd0ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1618 {"ftouis", 0xeebc0a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1619 {"ftouizs", 0xeebc0ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1620 {"fmrx", 0xeef00a10, 4, FPU_VFP_EXT_V1xD, do_vfp_reg_from_ctrl},
1621 {"fmxr", 0xeee00a10, 4, FPU_VFP_EXT_V1xD, do_vfp_ctrl_from_reg},
1623 /* Memory operations. */
1624 {"flds", 0xed100a00, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_ldst},
1625 {"fsts", 0xed000a00, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_ldst},
1626 {"fldmias", 0xec900a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
1627 {"fldmfds", 0xec900a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
1628 {"fldmdbs", 0xed300a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
1629 {"fldmeas", 0xed300a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
1630 {"fldmiax", 0xec900b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
1631 {"fldmfdx", 0xec900b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
1632 {"fldmdbx", 0xed300b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
1633 {"fldmeax", 0xed300b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
1634 {"fstmias", 0xec800a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
1635 {"fstmeas", 0xec800a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
1636 {"fstmdbs", 0xed200a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
1637 {"fstmfds", 0xed200a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
1638 {"fstmiax", 0xec800b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
1639 {"fstmeax", 0xec800b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
1640 {"fstmdbx", 0xed200b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
1641 {"fstmfdx", 0xed200b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
1643 /* Monadic operations. */
1644 {"fabss", 0xeeb00ac0, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1645 {"fnegs", 0xeeb10a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1646 {"fsqrts", 0xeeb10ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1648 /* Dyadic operations. */
1649 {"fadds", 0xee300a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1650 {"fsubs", 0xee300a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1651 {"fmuls", 0xee200a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1652 {"fdivs", 0xee800a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1653 {"fmacs", 0xee000a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1654 {"fmscs", 0xee100a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1655 {"fnmuls", 0xee200a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1656 {"fnmacs", 0xee000a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1657 {"fnmscs", 0xee100a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1659 /* Comparisons. */
1660 {"fcmps", 0xeeb40a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1661 {"fcmpzs", 0xeeb50a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_compare_z},
1662 {"fcmpes", 0xeeb40ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1663 {"fcmpezs", 0xeeb50ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_compare_z},
1665 /* VFP V1 (Double precision). */
1666 /* Moves and type conversions. */
1667 {"fcpyd", 0xeeb00b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1668 {"fcvtds", 0xeeb70ac0, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
1669 {"fcvtsd", 0xeeb70bc0, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
1670 {"fmdhr", 0xee200b10, 5, FPU_VFP_EXT_V1, do_vfp_dp_from_reg},
1671 {"fmdlr", 0xee000b10, 5, FPU_VFP_EXT_V1, do_vfp_dp_from_reg},
1672 {"fmrdh", 0xee300b10, 5, FPU_VFP_EXT_V1, do_vfp_reg_from_dp},
1673 {"fmrdl", 0xee100b10, 5, FPU_VFP_EXT_V1, do_vfp_reg_from_dp},
1674 {"fsitod", 0xeeb80bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
1675 {"fuitod", 0xeeb80b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
1676 {"ftosid", 0xeebd0b40, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
1677 {"ftosizd", 0xeebd0bc0, 7, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
1678 {"ftouid", 0xeebc0b40, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
1679 {"ftouizd", 0xeebc0bc0, 7, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
1681 /* Memory operations. */
1682 {"fldd", 0xed100b00, 4, FPU_VFP_EXT_V1, do_vfp_dp_ldst},
1683 {"fstd", 0xed000b00, 4, FPU_VFP_EXT_V1, do_vfp_dp_ldst},
1684 {"fldmiad", 0xec900b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
1685 {"fldmfdd", 0xec900b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
1686 {"fldmdbd", 0xed300b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
1687 {"fldmead", 0xed300b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
1688 {"fstmiad", 0xec800b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
1689 {"fstmead", 0xec800b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
1690 {"fstmdbd", 0xed200b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
1691 {"fstmfdd", 0xed200b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
1693 /* Monadic operations. */
1694 {"fabsd", 0xeeb00bc0, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1695 {"fnegd", 0xeeb10b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1696 {"fsqrtd", 0xeeb10bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1698 /* Dyadic operations. */
1699 {"faddd", 0xee300b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1700 {"fsubd", 0xee300b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1701 {"fmuld", 0xee200b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1702 {"fdivd", 0xee800b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1703 {"fmacd", 0xee000b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1704 {"fmscd", 0xee100b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1705 {"fnmuld", 0xee200b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1706 {"fnmacd", 0xee000b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1707 {"fnmscd", 0xee100b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1709 /* Comparisons. */
1710 {"fcmpd", 0xeeb40b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1711 {"fcmpzd", 0xeeb50b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_compare_z},
1712 {"fcmped", 0xeeb40bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1713 {"fcmpezd", 0xeeb50bc0, 7, FPU_VFP_EXT_V1, do_vfp_dp_compare_z},
1715 /* VFP V2. */
1716 {"fmsrr", 0xec400a10, 5, FPU_VFP_EXT_V2, do_vfp_sp_reg2},
1717 {"fmrrs", 0xec500a10, 5, FPU_VFP_EXT_V2, do_vfp_sp_reg2},
1718 {"fmdrr", 0xec400b10, 5, FPU_VFP_EXT_V2, do_vfp_dp_from_reg2},
1719 {"fmrrd", 0xec500b10, 5, FPU_VFP_EXT_V2, do_vfp_reg2_from_dp},
1721 /* Intel XScale extensions to ARM V5 ISA. (All use CP0). */
1722 {"mia", 0xee200010, 3, ARM_CEXT_XSCALE, do_xsc_mia},
1723 {"miaph", 0xee280010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
1724 {"miabb", 0xee2c0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
1725 {"miabt", 0xee2d0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
1726 {"miatb", 0xee2e0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
1727 {"miatt", 0xee2f0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
1728 {"mar", 0xec400000, 3, ARM_CEXT_XSCALE, do_xsc_mar},
1729 {"mra", 0xec500000, 3, ARM_CEXT_XSCALE, do_xsc_mra},
1731 /* Cirrus Maverick instructions. */
1732 {"cfldrs", 0xec100400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_1},
1733 {"cfldrd", 0xec500400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_2},
1734 {"cfldr32", 0xec100500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_3},
1735 {"cfldr64", 0xec500500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_4},
1736 {"cfstrs", 0xec000400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_1},
1737 {"cfstrd", 0xec400400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_2},
1738 {"cfstr32", 0xec000500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_3},
1739 {"cfstr64", 0xec400500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_4},
1740 {"cfmvsr", 0xee000450, 6, ARM_CEXT_MAVERICK, do_mav_binops_2a},
1741 {"cfmvrs", 0xee100450, 6, ARM_CEXT_MAVERICK, do_mav_binops_1a},
1742 {"cfmvdlr", 0xee000410, 7, ARM_CEXT_MAVERICK, do_mav_binops_2b},
1743 {"cfmvrdl", 0xee100410, 7, ARM_CEXT_MAVERICK, do_mav_binops_1b},
1744 {"cfmvdhr", 0xee000430, 7, ARM_CEXT_MAVERICK, do_mav_binops_2b},
1745 {"cfmvrdh", 0xee100430, 7, ARM_CEXT_MAVERICK, do_mav_binops_1b},
1746 {"cfmv64lr", 0xee000510, 8, ARM_CEXT_MAVERICK, do_mav_binops_2c},
1747 {"cfmvr64l", 0xee100510, 8, ARM_CEXT_MAVERICK, do_mav_binops_1c},
1748 {"cfmv64hr", 0xee000530, 8, ARM_CEXT_MAVERICK, do_mav_binops_2c},
1749 {"cfmvr64h", 0xee100530, 8, ARM_CEXT_MAVERICK, do_mav_binops_1c},
1750 {"cfmval32", 0xee100610, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
1751 {"cfmv32al", 0xee000610, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
1752 {"cfmvam32", 0xee100630, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
1753 {"cfmv32am", 0xee000630, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
1754 {"cfmvah32", 0xee100650, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
1755 {"cfmv32ah", 0xee000650, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
1756 {"cfmva32", 0xee100670, 7, ARM_CEXT_MAVERICK, do_mav_binops_3a},
1757 {"cfmv32a", 0xee000670, 7, ARM_CEXT_MAVERICK, do_mav_binops_3b},
1758 {"cfmva64", 0xee100690, 7, ARM_CEXT_MAVERICK, do_mav_binops_3c},
1759 {"cfmv64a", 0xee000690, 7, ARM_CEXT_MAVERICK, do_mav_binops_3d},
1760 {"cfmvsc32", 0xee1006b0, 8, ARM_CEXT_MAVERICK, do_mav_dspsc_1},
1761 {"cfmv32sc", 0xee0006b0, 8, ARM_CEXT_MAVERICK, do_mav_dspsc_2},
1762 {"cfcpys", 0xee000400, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
1763 {"cfcpyd", 0xee000420, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
1764 {"cfcvtsd", 0xee000460, 7, ARM_CEXT_MAVERICK, do_mav_binops_1f},
1765 {"cfcvtds", 0xee000440, 7, ARM_CEXT_MAVERICK, do_mav_binops_1g},
1766 {"cfcvt32s", 0xee000480, 8, ARM_CEXT_MAVERICK, do_mav_binops_1h},
1767 {"cfcvt32d", 0xee0004a0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1i},
1768 {"cfcvt64s", 0xee0004c0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1j},
1769 {"cfcvt64d", 0xee0004e0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1k},
1770 {"cfcvts32", 0xee100580, 8, ARM_CEXT_MAVERICK, do_mav_binops_1l},
1771 {"cfcvtd32", 0xee1005a0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1m},
1772 {"cftruncs32", 0xee1005c0, 10, ARM_CEXT_MAVERICK, do_mav_binops_1l},
1773 {"cftruncd32", 0xee1005e0, 10, ARM_CEXT_MAVERICK, do_mav_binops_1m},
1774 {"cfrshl32", 0xee000550, 8, ARM_CEXT_MAVERICK, do_mav_triple_4a},
1775 {"cfrshl64", 0xee000570, 8, ARM_CEXT_MAVERICK, do_mav_triple_4b},
1776 {"cfsh32", 0xee000500, 6, ARM_CEXT_MAVERICK, do_mav_shift_1},
1777 {"cfsh64", 0xee200500, 6, ARM_CEXT_MAVERICK, do_mav_shift_2},
1778 {"cfcmps", 0xee100490, 6, ARM_CEXT_MAVERICK, do_mav_triple_5a},
1779 {"cfcmpd", 0xee1004b0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5b},
1780 {"cfcmp32", 0xee100590, 7, ARM_CEXT_MAVERICK, do_mav_triple_5c},
1781 {"cfcmp64", 0xee1005b0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5d},
1782 {"cfabss", 0xee300400, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
1783 {"cfabsd", 0xee300420, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
1784 {"cfnegs", 0xee300440, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
1785 {"cfnegd", 0xee300460, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
1786 {"cfadds", 0xee300480, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
1787 {"cfaddd", 0xee3004a0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
1788 {"cfsubs", 0xee3004c0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
1789 {"cfsubd", 0xee3004e0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
1790 {"cfmuls", 0xee100400, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
1791 {"cfmuld", 0xee100420, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
1792 {"cfabs32", 0xee300500, 7, ARM_CEXT_MAVERICK, do_mav_binops_1n},
1793 {"cfabs64", 0xee300520, 7, ARM_CEXT_MAVERICK, do_mav_binops_1o},
1794 {"cfneg32", 0xee300540, 7, ARM_CEXT_MAVERICK, do_mav_binops_1n},
1795 {"cfneg64", 0xee300560, 7, ARM_CEXT_MAVERICK, do_mav_binops_1o},
1796 {"cfadd32", 0xee300580, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
1797 {"cfadd64", 0xee3005a0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
1798 {"cfsub32", 0xee3005c0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
1799 {"cfsub64", 0xee3005e0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
1800 {"cfmul32", 0xee100500, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
1801 {"cfmul64", 0xee100520, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
1802 {"cfmac32", 0xee100540, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
1803 {"cfmsc32", 0xee100560, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
1804 {"cfmadd32", 0xee000600, 8, ARM_CEXT_MAVERICK, do_mav_quad_6a},
1805 {"cfmsub32", 0xee100600, 8, ARM_CEXT_MAVERICK, do_mav_quad_6a},
1806 {"cfmadda32", 0xee200600, 9, ARM_CEXT_MAVERICK, do_mav_quad_6b},
1807 {"cfmsuba32", 0xee300600, 9, ARM_CEXT_MAVERICK, do_mav_quad_6b},
1810 /* Defines for various bits that we will want to toggle. */
1811 #define INST_IMMEDIATE 0x02000000
1812 #define OFFSET_REG 0x02000000
1813 #define HWOFFSET_IMM 0x00400000
1814 #define SHIFT_BY_REG 0x00000010
1815 #define PRE_INDEX 0x01000000
1816 #define INDEX_UP 0x00800000
1817 #define WRITE_BACK 0x00200000
1818 #define LDM_TYPE_2_OR_3 0x00400000
1820 #define LITERAL_MASK 0xf000f000
1821 #define OPCODE_MASK 0xfe1fffff
1822 #define V4_STR_BIT 0x00000020
1824 #define DATA_OP_SHIFT 21
1826 /* Codes to distinguish the arithmetic instructions. */
1827 #define OPCODE_AND 0
1828 #define OPCODE_EOR 1
1829 #define OPCODE_SUB 2
1830 #define OPCODE_RSB 3
1831 #define OPCODE_ADD 4
1832 #define OPCODE_ADC 5
1833 #define OPCODE_SBC 6
1834 #define OPCODE_RSC 7
1835 #define OPCODE_TST 8
1836 #define OPCODE_TEQ 9
1837 #define OPCODE_CMP 10
1838 #define OPCODE_CMN 11
1839 #define OPCODE_ORR 12
1840 #define OPCODE_MOV 13
1841 #define OPCODE_BIC 14
1842 #define OPCODE_MVN 15
1844 /* Thumb v1 (ARMv4T). */
1845 static void do_t_nop PARAMS ((char *));
1846 static void do_t_arit PARAMS ((char *));
1847 static void do_t_add PARAMS ((char *));
1848 static void do_t_asr PARAMS ((char *));
1849 static void do_t_branch9 PARAMS ((char *));
1850 static void do_t_branch12 PARAMS ((char *));
1851 static void do_t_branch23 PARAMS ((char *));
1852 static void do_t_bx PARAMS ((char *));
1853 static void do_t_compare PARAMS ((char *));
1854 static void do_t_ldmstm PARAMS ((char *));
1855 static void do_t_ldr PARAMS ((char *));
1856 static void do_t_ldrb PARAMS ((char *));
1857 static void do_t_ldrh PARAMS ((char *));
1858 static void do_t_lds PARAMS ((char *));
1859 static void do_t_lsl PARAMS ((char *));
1860 static void do_t_lsr PARAMS ((char *));
1861 static void do_t_mov PARAMS ((char *));
1862 static void do_t_push_pop PARAMS ((char *));
1863 static void do_t_str PARAMS ((char *));
1864 static void do_t_strb PARAMS ((char *));
1865 static void do_t_strh PARAMS ((char *));
1866 static void do_t_sub PARAMS ((char *));
1867 static void do_t_swi PARAMS ((char *));
1868 static void do_t_adr PARAMS ((char *));
1870 /* Thumb v2 (ARMv5T). */
1871 static void do_t_blx PARAMS ((char *));
1872 static void do_t_bkpt PARAMS ((char *));
1874 #define T_OPCODE_MUL 0x4340
1875 #define T_OPCODE_TST 0x4200
1876 #define T_OPCODE_CMN 0x42c0
1877 #define T_OPCODE_NEG 0x4240
1878 #define T_OPCODE_MVN 0x43c0
1880 #define T_OPCODE_ADD_R3 0x1800
1881 #define T_OPCODE_SUB_R3 0x1a00
1882 #define T_OPCODE_ADD_HI 0x4400
1883 #define T_OPCODE_ADD_ST 0xb000
1884 #define T_OPCODE_SUB_ST 0xb080
1885 #define T_OPCODE_ADD_SP 0xa800
1886 #define T_OPCODE_ADD_PC 0xa000
1887 #define T_OPCODE_ADD_I8 0x3000
1888 #define T_OPCODE_SUB_I8 0x3800
1889 #define T_OPCODE_ADD_I3 0x1c00
1890 #define T_OPCODE_SUB_I3 0x1e00
1892 #define T_OPCODE_ASR_R 0x4100
1893 #define T_OPCODE_LSL_R 0x4080
1894 #define T_OPCODE_LSR_R 0x40c0
1895 #define T_OPCODE_ASR_I 0x1000
1896 #define T_OPCODE_LSL_I 0x0000
1897 #define T_OPCODE_LSR_I 0x0800
1899 #define T_OPCODE_MOV_I8 0x2000
1900 #define T_OPCODE_CMP_I8 0x2800
1901 #define T_OPCODE_CMP_LR 0x4280
1902 #define T_OPCODE_MOV_HR 0x4600
1903 #define T_OPCODE_CMP_HR 0x4500
1905 #define T_OPCODE_LDR_PC 0x4800
1906 #define T_OPCODE_LDR_SP 0x9800
1907 #define T_OPCODE_STR_SP 0x9000
1908 #define T_OPCODE_LDR_IW 0x6800
1909 #define T_OPCODE_STR_IW 0x6000
1910 #define T_OPCODE_LDR_IH 0x8800
1911 #define T_OPCODE_STR_IH 0x8000
1912 #define T_OPCODE_LDR_IB 0x7800
1913 #define T_OPCODE_STR_IB 0x7000
1914 #define T_OPCODE_LDR_RW 0x5800
1915 #define T_OPCODE_STR_RW 0x5000
1916 #define T_OPCODE_LDR_RH 0x5a00
1917 #define T_OPCODE_STR_RH 0x5200
1918 #define T_OPCODE_LDR_RB 0x5c00
1919 #define T_OPCODE_STR_RB 0x5400
1921 #define T_OPCODE_PUSH 0xb400
1922 #define T_OPCODE_POP 0xbc00
1924 #define T_OPCODE_BRANCH 0xe7fe
1926 static int thumb_reg PARAMS ((char ** str, int hi_lo));
1928 #define THUMB_SIZE 2 /* Size of thumb instruction. */
1929 #define THUMB_REG_LO 0x1
1930 #define THUMB_REG_HI 0x2
1931 #define THUMB_REG_ANY 0x3
1933 #define THUMB_H1 0x0080
1934 #define THUMB_H2 0x0040
1936 #define THUMB_ASR 0
1937 #define THUMB_LSL 1
1938 #define THUMB_LSR 2
1940 #define THUMB_MOVE 0
1941 #define THUMB_COMPARE 1
1943 #define THUMB_LOAD 0
1944 #define THUMB_STORE 1
1946 #define THUMB_PP_PC_LR 0x0100
1948 /* These three are used for immediate shifts, do not alter. */
1949 #define THUMB_WORD 2
1950 #define THUMB_HALFWORD 1
1951 #define THUMB_BYTE 0
1953 struct thumb_opcode
1955 /* Basic string to match. */
1956 const char * template;
1958 /* Basic instruction code. */
1959 unsigned long value;
1961 int size;
1963 /* Which CPU variants this exists for. */
1964 unsigned long variant;
1966 /* Function to call to parse args. */
1967 void (* parms) PARAMS ((char *));
1970 static const struct thumb_opcode tinsns[] =
1972 /* Thumb v1 (ARMv4T). */
1973 {"adc", 0x4140, 2, ARM_EXT_V4T, do_t_arit},
1974 {"add", 0x0000, 2, ARM_EXT_V4T, do_t_add},
1975 {"and", 0x4000, 2, ARM_EXT_V4T, do_t_arit},
1976 {"asr", 0x0000, 2, ARM_EXT_V4T, do_t_asr},
1977 {"b", T_OPCODE_BRANCH, 2, ARM_EXT_V4T, do_t_branch12},
1978 {"beq", 0xd0fe, 2, ARM_EXT_V4T, do_t_branch9},
1979 {"bne", 0xd1fe, 2, ARM_EXT_V4T, do_t_branch9},
1980 {"bcs", 0xd2fe, 2, ARM_EXT_V4T, do_t_branch9},
1981 {"bhs", 0xd2fe, 2, ARM_EXT_V4T, do_t_branch9},
1982 {"bcc", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
1983 {"bul", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
1984 {"blo", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
1985 {"bmi", 0xd4fe, 2, ARM_EXT_V4T, do_t_branch9},
1986 {"bpl", 0xd5fe, 2, ARM_EXT_V4T, do_t_branch9},
1987 {"bvs", 0xd6fe, 2, ARM_EXT_V4T, do_t_branch9},
1988 {"bvc", 0xd7fe, 2, ARM_EXT_V4T, do_t_branch9},
1989 {"bhi", 0xd8fe, 2, ARM_EXT_V4T, do_t_branch9},
1990 {"bls", 0xd9fe, 2, ARM_EXT_V4T, do_t_branch9},
1991 {"bge", 0xdafe, 2, ARM_EXT_V4T, do_t_branch9},
1992 {"blt", 0xdbfe, 2, ARM_EXT_V4T, do_t_branch9},
1993 {"bgt", 0xdcfe, 2, ARM_EXT_V4T, do_t_branch9},
1994 {"ble", 0xddfe, 2, ARM_EXT_V4T, do_t_branch9},
1995 {"bal", 0xdefe, 2, ARM_EXT_V4T, do_t_branch9},
1996 {"bic", 0x4380, 2, ARM_EXT_V4T, do_t_arit},
1997 {"bl", 0xf7fffffe, 4, ARM_EXT_V4T, do_t_branch23},
1998 {"bx", 0x4700, 2, ARM_EXT_V4T, do_t_bx},
1999 {"cmn", T_OPCODE_CMN, 2, ARM_EXT_V4T, do_t_arit},
2000 {"cmp", 0x0000, 2, ARM_EXT_V4T, do_t_compare},
2001 {"eor", 0x4040, 2, ARM_EXT_V4T, do_t_arit},
2002 {"ldmia", 0xc800, 2, ARM_EXT_V4T, do_t_ldmstm},
2003 {"ldr", 0x0000, 2, ARM_EXT_V4T, do_t_ldr},
2004 {"ldrb", 0x0000, 2, ARM_EXT_V4T, do_t_ldrb},
2005 {"ldrh", 0x0000, 2, ARM_EXT_V4T, do_t_ldrh},
2006 {"ldrsb", 0x5600, 2, ARM_EXT_V4T, do_t_lds},
2007 {"ldrsh", 0x5e00, 2, ARM_EXT_V4T, do_t_lds},
2008 {"ldsb", 0x5600, 2, ARM_EXT_V4T, do_t_lds},
2009 {"ldsh", 0x5e00, 2, ARM_EXT_V4T, do_t_lds},
2010 {"lsl", 0x0000, 2, ARM_EXT_V4T, do_t_lsl},
2011 {"lsr", 0x0000, 2, ARM_EXT_V4T, do_t_lsr},
2012 {"mov", 0x0000, 2, ARM_EXT_V4T, do_t_mov},
2013 {"mul", T_OPCODE_MUL, 2, ARM_EXT_V4T, do_t_arit},
2014 {"mvn", T_OPCODE_MVN, 2, ARM_EXT_V4T, do_t_arit},
2015 {"neg", T_OPCODE_NEG, 2, ARM_EXT_V4T, do_t_arit},
2016 {"orr", 0x4300, 2, ARM_EXT_V4T, do_t_arit},
2017 {"pop", 0xbc00, 2, ARM_EXT_V4T, do_t_push_pop},
2018 {"push", 0xb400, 2, ARM_EXT_V4T, do_t_push_pop},
2019 {"ror", 0x41c0, 2, ARM_EXT_V4T, do_t_arit},
2020 {"sbc", 0x4180, 2, ARM_EXT_V4T, do_t_arit},
2021 {"stmia", 0xc000, 2, ARM_EXT_V4T, do_t_ldmstm},
2022 {"str", 0x0000, 2, ARM_EXT_V4T, do_t_str},
2023 {"strb", 0x0000, 2, ARM_EXT_V4T, do_t_strb},
2024 {"strh", 0x0000, 2, ARM_EXT_V4T, do_t_strh},
2025 {"swi", 0xdf00, 2, ARM_EXT_V4T, do_t_swi},
2026 {"sub", 0x0000, 2, ARM_EXT_V4T, do_t_sub},
2027 {"tst", T_OPCODE_TST, 2, ARM_EXT_V4T, do_t_arit},
2028 /* Pseudo ops: */
2029 {"adr", 0x0000, 2, ARM_EXT_V4T, do_t_adr},
2030 {"nop", 0x46C0, 2, ARM_EXT_V4T, do_t_nop}, /* mov r8,r8 */
2031 /* Thumb v2 (ARMv5T). */
2032 {"blx", 0, 0, ARM_EXT_V5T, do_t_blx},
2033 {"bkpt", 0xbe00, 2, ARM_EXT_V5T, do_t_bkpt},
2036 #define BAD_ARGS _("bad arguments to instruction")
2037 #define BAD_PC _("r15 not allowed here")
2038 #define BAD_COND _("instruction is not conditional")
2039 #define ERR_NO_ACCUM _("acc0 expected")
2041 static struct hash_control * arm_ops_hsh = NULL;
2042 static struct hash_control * arm_tops_hsh = NULL;
2043 static struct hash_control * arm_cond_hsh = NULL;
2044 static struct hash_control * arm_shift_hsh = NULL;
2045 static struct hash_control * arm_psr_hsh = NULL;
2047 /* This table describes all the machine specific pseudo-ops the assembler
2048 has to support. The fields are:
2049 pseudo-op name without dot
2050 function to call to execute this pseudo-op
2051 Integer arg to pass to the function. */
2053 static void s_req PARAMS ((int));
2054 static void s_align PARAMS ((int));
2055 static void s_bss PARAMS ((int));
2056 static void s_even PARAMS ((int));
2057 static void s_ltorg PARAMS ((int));
2058 static void s_arm PARAMS ((int));
2059 static void s_thumb PARAMS ((int));
2060 static void s_code PARAMS ((int));
2061 static void s_force_thumb PARAMS ((int));
2062 static void s_thumb_func PARAMS ((int));
2063 static void s_thumb_set PARAMS ((int));
2064 #ifdef OBJ_ELF
2065 static void s_arm_elf_cons PARAMS ((int));
2066 #endif
2068 static int my_get_expression PARAMS ((expressionS *, char **));
2070 const pseudo_typeS md_pseudo_table[] =
2072 /* Never called becasue '.req' does not start line. */
2073 { "req", s_req, 0 },
2074 { "bss", s_bss, 0 },
2075 { "align", s_align, 0 },
2076 { "arm", s_arm, 0 },
2077 { "thumb", s_thumb, 0 },
2078 { "code", s_code, 0 },
2079 { "force_thumb", s_force_thumb, 0 },
2080 { "thumb_func", s_thumb_func, 0 },
2081 { "thumb_set", s_thumb_set, 0 },
2082 { "even", s_even, 0 },
2083 { "ltorg", s_ltorg, 0 },
2084 { "pool", s_ltorg, 0 },
2085 #ifdef OBJ_ELF
2086 { "word", s_arm_elf_cons, 4 },
2087 { "long", s_arm_elf_cons, 4 },
2088 { "file", (void (*) PARAMS ((int))) dwarf2_directive_file, 0 },
2089 { "loc", dwarf2_directive_loc, 0 },
2090 #else
2091 { "word", cons, 4},
2092 #endif
2093 { "extend", float_cons, 'x' },
2094 { "ldouble", float_cons, 'x' },
2095 { "packed", float_cons, 'p' },
2096 { 0, 0, 0 }
2099 /* Other internal functions. */
2100 static int arm_parse_extension PARAMS ((char *, int *));
2101 static int arm_parse_cpu PARAMS ((char *));
2102 static int arm_parse_arch PARAMS ((char *));
2103 static int arm_parse_fpu PARAMS ((char *));
2105 /* Stuff needed to resolve the label ambiguity
2108 label: <insn>
2109 may differ from:
2111 label:
2112 <insn>
2115 symbolS * last_label_seen;
2116 static int label_is_thumb_function_name = false;
2118 /* Literal Pool stuff. */
2120 #define MAX_LITERAL_POOL_SIZE 1024
2122 /* Literal pool structure. Held on a per-section
2123 and per-sub-section basis. */
2124 typedef struct literal_pool
2126 expressionS literals [MAX_LITERAL_POOL_SIZE];
2127 unsigned int next_free_entry;
2128 unsigned int id;
2129 symbolS * symbol;
2130 segT section;
2131 subsegT sub_section;
2132 struct literal_pool * next;
2133 } literal_pool;
2135 /* Pointer to a linked list of literal pools. */
2136 literal_pool * list_of_pools = NULL;
2138 static literal_pool * find_literal_pool PARAMS ((void));
2139 static literal_pool * find_or_make_literal_pool PARAMS ((void));
2141 static literal_pool *
2142 find_literal_pool ()
2144 literal_pool * pool;
2146 for (pool = list_of_pools; pool != NULL; pool = pool->next)
2148 if (pool->section == now_seg
2149 && pool->sub_section == now_subseg)
2150 break;
2153 return pool;
2156 static literal_pool *
2157 find_or_make_literal_pool ()
2159 /* Next literal pool ID number. */
2160 static unsigned int latest_pool_num = 1;
2161 literal_pool * pool;
2163 pool = find_literal_pool ();
2165 if (pool == NULL)
2167 /* Create a new pool. */
2168 pool = (literal_pool *) xmalloc (sizeof (* pool));
2169 if (! pool)
2170 return NULL;
2172 pool->next_free_entry = 0;
2173 pool->section = now_seg;
2174 pool->sub_section = now_subseg;
2175 pool->next = list_of_pools;
2176 pool->symbol = NULL;
2178 /* Add it to the list. */
2179 list_of_pools = pool;
2182 /* New pools, and emptied pools, will have a NULL symbol. */
2183 if (pool->symbol == NULL)
2185 pool->symbol = symbol_create (FAKE_LABEL_NAME, undefined_section,
2186 (valueT) 0, &zero_address_frag);
2187 pool->id = latest_pool_num ++;
2190 /* Done. */
2191 return pool;
2194 /* Add the literal in the global 'inst'
2195 structure to the relevent literal pool. */
2196 static int
2197 add_to_lit_pool ()
2199 literal_pool * pool;
2200 unsigned int entry;
2202 pool = find_or_make_literal_pool ();
2204 /* Check if this literal value is already in the pool. */
2205 for (entry = 0; entry < pool->next_free_entry; entry ++)
2207 if ((pool->literals[entry].X_op == inst.reloc.exp.X_op)
2208 && (inst.reloc.exp.X_op == O_constant)
2209 && (pool->literals[entry].X_add_number
2210 == inst.reloc.exp.X_add_number)
2211 && (pool->literals[entry].X_unsigned
2212 == inst.reloc.exp.X_unsigned))
2213 break;
2215 if ((pool->literals[entry].X_op == inst.reloc.exp.X_op)
2216 && (inst.reloc.exp.X_op == O_symbol)
2217 && (pool->literals[entry].X_add_number
2218 == inst.reloc.exp.X_add_number)
2219 && (pool->literals[entry].X_add_symbol
2220 == inst.reloc.exp.X_add_symbol)
2221 && (pool->literals[entry].X_op_symbol
2222 == inst.reloc.exp.X_op_symbol))
2223 break;
2226 /* Do we need to create a new entry? */
2227 if (entry == pool->next_free_entry)
2229 if (entry >= MAX_LITERAL_POOL_SIZE)
2231 inst.error = _("literal pool overflow");
2232 return FAIL;
2235 pool->literals[entry] = inst.reloc.exp;
2236 pool->next_free_entry += 1;
2239 inst.reloc.exp.X_op = O_symbol;
2240 inst.reloc.exp.X_add_number = ((int) entry) * 4 - 8;
2241 inst.reloc.exp.X_add_symbol = pool->symbol;
2243 return SUCCESS;
2246 /* Can't use symbol_new here, so have to create a symbol and then at
2247 a later date assign it a value. Thats what these functions do. */
2249 static void
2250 symbol_locate (symbolP, name, segment, valu, frag)
2251 symbolS * symbolP;
2252 const char * name; /* It is copied, the caller can modify. */
2253 segT segment; /* Segment identifier (SEG_<something>). */
2254 valueT valu; /* Symbol value. */
2255 fragS * frag; /* Associated fragment. */
2257 unsigned int name_length;
2258 char * preserved_copy_of_name;
2260 name_length = strlen (name) + 1; /* +1 for \0. */
2261 obstack_grow (&notes, name, name_length);
2262 preserved_copy_of_name = obstack_finish (&notes);
2263 #ifdef STRIP_UNDERSCORE
2264 if (preserved_copy_of_name[0] == '_')
2265 preserved_copy_of_name++;
2266 #endif
2268 #ifdef tc_canonicalize_symbol_name
2269 preserved_copy_of_name =
2270 tc_canonicalize_symbol_name (preserved_copy_of_name);
2271 #endif
2273 S_SET_NAME (symbolP, preserved_copy_of_name);
2275 S_SET_SEGMENT (symbolP, segment);
2276 S_SET_VALUE (symbolP, valu);
2277 symbol_clear_list_pointers (symbolP);
2279 symbol_set_frag (symbolP, frag);
2281 /* Link to end of symbol chain. */
2283 extern int symbol_table_frozen;
2284 if (symbol_table_frozen)
2285 abort ();
2288 symbol_append (symbolP, symbol_lastP, & symbol_rootP, & symbol_lastP);
2290 obj_symbol_new_hook (symbolP);
2292 #ifdef tc_symbol_new_hook
2293 tc_symbol_new_hook (symbolP);
2294 #endif
2296 #ifdef DEBUG_SYMS
2297 verify_symbol_chain (symbol_rootP, symbol_lastP);
2298 #endif /* DEBUG_SYMS */
2301 /* Check that an immediate is valid.
2302 If so, convert it to the right format. */
2304 static unsigned int
2305 validate_immediate (val)
2306 unsigned int val;
2308 unsigned int a;
2309 unsigned int i;
2311 #define rotate_left(v, n) (v << n | v >> (32 - n))
2313 for (i = 0; i < 32; i += 2)
2314 if ((a = rotate_left (val, i)) <= 0xff)
2315 return a | (i << 7); /* 12-bit pack: [shift-cnt,const]. */
2317 return FAIL;
2320 /* Check to see if an immediate can be computed as two seperate immediate
2321 values, added together. We already know that this value cannot be
2322 computed by just one ARM instruction. */
2324 static unsigned int
2325 validate_immediate_twopart (val, highpart)
2326 unsigned int val;
2327 unsigned int * highpart;
2329 unsigned int a;
2330 unsigned int i;
2332 for (i = 0; i < 32; i += 2)
2333 if (((a = rotate_left (val, i)) & 0xff) != 0)
2335 if (a & 0xff00)
2337 if (a & ~ 0xffff)
2338 continue;
2339 * highpart = (a >> 8) | ((i + 24) << 7);
2341 else if (a & 0xff0000)
2343 if (a & 0xff000000)
2344 continue;
2345 * highpart = (a >> 16) | ((i + 16) << 7);
2347 else
2349 assert (a & 0xff000000);
2350 * highpart = (a >> 24) | ((i + 8) << 7);
2353 return (a & 0xff) | (i << 7);
2356 return FAIL;
2359 static int
2360 validate_offset_imm (val, hwse)
2361 unsigned int val;
2362 int hwse;
2364 if ((hwse && val > 255) || val > 4095)
2365 return FAIL;
2366 return val;
2369 static void
2370 s_req (a)
2371 int a ATTRIBUTE_UNUSED;
2373 as_bad (_("invalid syntax for .req directive"));
2376 static void
2377 s_bss (ignore)
2378 int ignore ATTRIBUTE_UNUSED;
2380 /* We don't support putting frags in the BSS segment, we fake it by
2381 marking in_bss, then looking at s_skip for clues. */
2382 subseg_set (bss_section, 0);
2383 demand_empty_rest_of_line ();
2386 static void
2387 s_even (ignore)
2388 int ignore ATTRIBUTE_UNUSED;
2390 /* Never make frag if expect extra pass. */
2391 if (!need_pass_2)
2392 frag_align (1, 0, 0);
2394 record_alignment (now_seg, 1);
2396 demand_empty_rest_of_line ();
2399 static void
2400 s_ltorg (ignored)
2401 int ignored ATTRIBUTE_UNUSED;
2403 unsigned int entry;
2404 literal_pool * pool;
2405 char sym_name[20];
2407 pool = find_literal_pool ();
2408 if (pool == NULL
2409 || pool->symbol == NULL
2410 || pool->next_free_entry == 0)
2411 return;
2413 /* Align pool as you have word accesses.
2414 Only make a frag if we have to. */
2415 if (!need_pass_2)
2416 frag_align (2, 0, 0);
2418 record_alignment (now_seg, 2);
2420 sprintf (sym_name, "$$lit_\002%x", pool->id);
2422 symbol_locate (pool->symbol, sym_name, now_seg,
2423 (valueT) frag_now_fix (), frag_now);
2424 symbol_table_insert (pool->symbol);
2426 ARM_SET_THUMB (pool->symbol, thumb_mode);
2428 #if defined OBJ_COFF || defined OBJ_ELF
2429 ARM_SET_INTERWORK (pool->symbol, support_interwork);
2430 #endif
2432 for (entry = 0; entry < pool->next_free_entry; entry ++)
2433 /* First output the expression in the instruction to the pool. */
2434 emit_expr (&(pool->literals[entry]), 4); /* .word */
2436 /* Mark the pool as empty. */
2437 pool->next_free_entry = 0;
2438 pool->symbol = NULL;
2441 /* Same as s_align_ptwo but align 0 => align 2. */
2443 static void
2444 s_align (unused)
2445 int unused ATTRIBUTE_UNUSED;
2447 register int temp;
2448 register long temp_fill;
2449 long max_alignment = 15;
2451 temp = get_absolute_expression ();
2452 if (temp > max_alignment)
2453 as_bad (_("alignment too large: %d assumed"), temp = max_alignment);
2454 else if (temp < 0)
2456 as_bad (_("alignment negative. 0 assumed."));
2457 temp = 0;
2460 if (*input_line_pointer == ',')
2462 input_line_pointer++;
2463 temp_fill = get_absolute_expression ();
2465 else
2466 temp_fill = 0;
2468 if (!temp)
2469 temp = 2;
2471 /* Only make a frag if we HAVE to. */
2472 if (temp && !need_pass_2)
2473 frag_align (temp, (int) temp_fill, 0);
2474 demand_empty_rest_of_line ();
2476 record_alignment (now_seg, temp);
2479 static void
2480 s_force_thumb (ignore)
2481 int ignore ATTRIBUTE_UNUSED;
2483 /* If we are not already in thumb mode go into it, EVEN if
2484 the target processor does not support thumb instructions.
2485 This is used by gcc/config/arm/lib1funcs.asm for example
2486 to compile interworking support functions even if the
2487 target processor should not support interworking. */
2488 if (! thumb_mode)
2490 thumb_mode = 2;
2492 record_alignment (now_seg, 1);
2495 demand_empty_rest_of_line ();
2498 static void
2499 s_thumb_func (ignore)
2500 int ignore ATTRIBUTE_UNUSED;
2502 if (! thumb_mode)
2503 opcode_select (16);
2505 /* The following label is the name/address of the start of a Thumb function.
2506 We need to know this for the interworking support. */
2507 label_is_thumb_function_name = true;
2509 demand_empty_rest_of_line ();
2512 /* Perform a .set directive, but also mark the alias as
2513 being a thumb function. */
2515 static void
2516 s_thumb_set (equiv)
2517 int equiv;
2519 /* XXX the following is a duplicate of the code for s_set() in read.c
2520 We cannot just call that code as we need to get at the symbol that
2521 is created. */
2522 register char * name;
2523 register char delim;
2524 register char * end_name;
2525 register symbolS * symbolP;
2527 /* Especial apologies for the random logic:
2528 This just grew, and could be parsed much more simply!
2529 Dean - in haste. */
2530 name = input_line_pointer;
2531 delim = get_symbol_end ();
2532 end_name = input_line_pointer;
2533 *end_name = delim;
2535 SKIP_WHITESPACE ();
2537 if (*input_line_pointer != ',')
2539 *end_name = 0;
2540 as_bad (_("expected comma after name \"%s\""), name);
2541 *end_name = delim;
2542 ignore_rest_of_line ();
2543 return;
2546 input_line_pointer++;
2547 *end_name = 0;
2549 if (name[0] == '.' && name[1] == '\0')
2551 /* XXX - this should not happen to .thumb_set. */
2552 abort ();
2555 if ((symbolP = symbol_find (name)) == NULL
2556 && (symbolP = md_undefined_symbol (name)) == NULL)
2558 #ifndef NO_LISTING
2559 /* When doing symbol listings, play games with dummy fragments living
2560 outside the normal fragment chain to record the file and line info
2561 for this symbol. */
2562 if (listing & LISTING_SYMBOLS)
2564 extern struct list_info_struct * listing_tail;
2565 fragS * dummy_frag = (fragS *) xmalloc (sizeof (fragS));
2567 memset (dummy_frag, 0, sizeof (fragS));
2568 dummy_frag->fr_type = rs_fill;
2569 dummy_frag->line = listing_tail;
2570 symbolP = symbol_new (name, undefined_section, 0, dummy_frag);
2571 dummy_frag->fr_symbol = symbolP;
2573 else
2574 #endif
2575 symbolP = symbol_new (name, undefined_section, 0, &zero_address_frag);
2577 #ifdef OBJ_COFF
2578 /* "set" symbols are local unless otherwise specified. */
2579 SF_SET_LOCAL (symbolP);
2580 #endif /* OBJ_COFF */
2581 } /* Make a new symbol. */
2583 symbol_table_insert (symbolP);
2585 * end_name = delim;
2587 if (equiv
2588 && S_IS_DEFINED (symbolP)
2589 && S_GET_SEGMENT (symbolP) != reg_section)
2590 as_bad (_("symbol `%s' already defined"), S_GET_NAME (symbolP));
2592 pseudo_set (symbolP);
2594 demand_empty_rest_of_line ();
2596 /* XXX Now we come to the Thumb specific bit of code. */
2598 THUMB_SET_FUNC (symbolP, 1);
2599 ARM_SET_THUMB (symbolP, 1);
2600 #if defined OBJ_ELF || defined OBJ_COFF
2601 ARM_SET_INTERWORK (symbolP, support_interwork);
2602 #endif
2605 static void
2606 opcode_select (width)
2607 int width;
2609 switch (width)
2611 case 16:
2612 if (! thumb_mode)
2614 if (! (cpu_variant & ARM_EXT_V4T))
2615 as_bad (_("selected processor does not support THUMB opcodes"));
2617 thumb_mode = 1;
2618 /* No need to force the alignment, since we will have been
2619 coming from ARM mode, which is word-aligned. */
2620 record_alignment (now_seg, 1);
2622 break;
2624 case 32:
2625 if (thumb_mode)
2627 if ((cpu_variant & ARM_ALL) == ARM_EXT_V4T)
2628 as_bad (_("selected processor does not support ARM opcodes"));
2630 thumb_mode = 0;
2632 if (!need_pass_2)
2633 frag_align (2, 0, 0);
2635 record_alignment (now_seg, 1);
2637 break;
2639 default:
2640 as_bad (_("invalid instruction size selected (%d)"), width);
2644 static void
2645 s_arm (ignore)
2646 int ignore ATTRIBUTE_UNUSED;
2648 opcode_select (32);
2649 demand_empty_rest_of_line ();
2652 static void
2653 s_thumb (ignore)
2654 int ignore ATTRIBUTE_UNUSED;
2656 opcode_select (16);
2657 demand_empty_rest_of_line ();
2660 static void
2661 s_code (unused)
2662 int unused ATTRIBUTE_UNUSED;
2664 register int temp;
2666 temp = get_absolute_expression ();
2667 switch (temp)
2669 case 16:
2670 case 32:
2671 opcode_select (temp);
2672 break;
2674 default:
2675 as_bad (_("invalid operand to .code directive (%d) (expecting 16 or 32)"), temp);
2679 static void
2680 end_of_line (str)
2681 char *str;
2683 skip_whitespace (str);
2685 if (*str != '\0' && !inst.error)
2686 inst.error = _("garbage following instruction");
2689 static int
2690 skip_past_comma (str)
2691 char ** str;
2693 char * p = * str, c;
2694 int comma = 0;
2696 while ((c = *p) == ' ' || c == ',')
2698 p++;
2699 if (c == ',' && comma++)
2700 return FAIL;
2703 if (c == '\0')
2704 return FAIL;
2706 *str = p;
2707 return comma ? SUCCESS : FAIL;
2710 /* A standard register must be given at this point.
2711 SHIFT is the place to put it in inst.instruction.
2712 Restores input start point on error.
2713 Returns the reg#, or FAIL. */
2715 static int
2716 reg_required_here (str, shift)
2717 char ** str;
2718 int shift;
2720 static char buff [128]; /* XXX */
2721 int reg;
2722 char * start = * str;
2724 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_RN].htab)) != FAIL)
2726 if (shift >= 0)
2727 inst.instruction |= reg << shift;
2728 return reg;
2731 /* Restore the start point, we may have got a reg of the wrong class. */
2732 *str = start;
2734 /* In the few cases where we might be able to accept something else
2735 this error can be overridden. */
2736 sprintf (buff, _("register expected, not '%.100s'"), start);
2737 inst.error = buff;
2739 return FAIL;
2742 static const struct asm_psr *
2743 arm_psr_parse (ccp)
2744 register char ** ccp;
2746 char * start = * ccp;
2747 char c;
2748 char * p;
2749 const struct asm_psr * psr;
2751 p = start;
2753 /* Skip to the end of the next word in the input stream. */
2756 c = *p++;
2758 while (ISALPHA (c) || c == '_');
2760 /* Terminate the word. */
2761 *--p = 0;
2763 /* CPSR's and SPSR's can now be lowercase. This is just a convenience
2764 feature for ease of use and backwards compatibility. */
2765 if (!strncmp (start, "cpsr", 4))
2766 strncpy (start, "CPSR", 4);
2767 else if (!strncmp (start, "spsr", 4))
2768 strncpy (start, "SPSR", 4);
2770 /* Now locate the word in the psr hash table. */
2771 psr = (const struct asm_psr *) hash_find (arm_psr_hsh, start);
2773 /* Restore the input stream. */
2774 *p = c;
2776 /* If we found a valid match, advance the
2777 stream pointer past the end of the word. */
2778 *ccp = p;
2780 return psr;
2783 /* Parse the input looking for a PSR flag. */
2785 static int
2786 psr_required_here (str)
2787 char ** str;
2789 char * start = * str;
2790 const struct asm_psr * psr;
2792 psr = arm_psr_parse (str);
2794 if (psr)
2796 /* If this is the SPSR that is being modified, set the R bit. */
2797 if (! psr->cpsr)
2798 inst.instruction |= SPSR_BIT;
2800 /* Set the psr flags in the MSR instruction. */
2801 inst.instruction |= psr->field << PSR_SHIFT;
2803 return SUCCESS;
2806 /* In the few cases where we might be able to accept
2807 something else this error can be overridden. */
2808 inst.error = _("flag for {c}psr instruction expected");
2810 /* Restore the start point. */
2811 *str = start;
2812 return FAIL;
2815 static int
2816 co_proc_number (str)
2817 char **str;
2819 int processor, pchar;
2820 char *start;
2822 skip_whitespace (*str);
2823 start = *str;
2825 /* The data sheet seems to imply that just a number on its own is valid
2826 here, but the RISC iX assembler seems to accept a prefix 'p'. We will
2827 accept either. */
2828 if ((processor = arm_reg_parse (str, all_reg_maps[REG_TYPE_CP].htab))
2829 == FAIL)
2831 *str = start;
2833 pchar = *(*str)++;
2834 if (pchar >= '0' && pchar <= '9')
2836 processor = pchar - '0';
2837 if (**str >= '0' && **str <= '9')
2839 processor = processor * 10 + *(*str)++ - '0';
2840 if (processor > 15)
2842 inst.error = _("illegal co-processor number");
2843 return FAIL;
2847 else
2849 inst.error = _("bad or missing co-processor number");
2850 return FAIL;
2854 inst.instruction |= processor << 8;
2855 return SUCCESS;
2858 static int
2859 cp_opc_expr (str, where, length)
2860 char ** str;
2861 int where;
2862 int length;
2864 expressionS expr;
2866 skip_whitespace (* str);
2868 memset (&expr, '\0', sizeof (expr));
2870 if (my_get_expression (&expr, str))
2871 return FAIL;
2872 if (expr.X_op != O_constant)
2874 inst.error = _("bad or missing expression");
2875 return FAIL;
2878 if ((expr.X_add_number & ((1 << length) - 1)) != expr.X_add_number)
2880 inst.error = _("immediate co-processor expression too large");
2881 return FAIL;
2884 inst.instruction |= expr.X_add_number << where;
2885 return SUCCESS;
2888 static int
2889 cp_reg_required_here (str, where)
2890 char ** str;
2891 int where;
2893 int reg;
2894 char * start = *str;
2896 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_CN].htab)) != FAIL)
2898 inst.instruction |= reg << where;
2899 return reg;
2902 /* In the few cases where we might be able to accept something else
2903 this error can be overridden. */
2904 inst.error = _("co-processor register expected");
2906 /* Restore the start point. */
2907 *str = start;
2908 return FAIL;
2911 static int
2912 fp_reg_required_here (str, where)
2913 char ** str;
2914 int where;
2916 int reg;
2917 char * start = * str;
2919 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_FN].htab)) != FAIL)
2921 inst.instruction |= reg << where;
2922 return reg;
2925 /* In the few cases where we might be able to accept something else
2926 this error can be overridden. */
2927 inst.error = _("floating point register expected");
2929 /* Restore the start point. */
2930 *str = start;
2931 return FAIL;
2934 static int
2935 cp_address_offset (str)
2936 char ** str;
2938 int offset;
2940 skip_whitespace (* str);
2942 if (! is_immediate_prefix (**str))
2944 inst.error = _("immediate expression expected");
2945 return FAIL;
2948 (*str)++;
2950 if (my_get_expression (& inst.reloc.exp, str))
2951 return FAIL;
2953 if (inst.reloc.exp.X_op == O_constant)
2955 offset = inst.reloc.exp.X_add_number;
2957 if (offset & 3)
2959 inst.error = _("co-processor address must be word aligned");
2960 return FAIL;
2963 if (offset > 1023 || offset < -1023)
2965 inst.error = _("offset too large");
2966 return FAIL;
2969 if (offset >= 0)
2970 inst.instruction |= INDEX_UP;
2971 else
2972 offset = -offset;
2974 inst.instruction |= offset >> 2;
2976 else
2977 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
2979 return SUCCESS;
2982 static int
2983 cp_address_required_here (str, wb_ok)
2984 char ** str;
2985 int wb_ok;
2987 char * p = * str;
2988 int pre_inc = 0;
2989 int write_back = 0;
2991 if (*p == '[')
2993 int reg;
2995 p++;
2996 skip_whitespace (p);
2998 if ((reg = reg_required_here (& p, 16)) == FAIL)
2999 return FAIL;
3001 skip_whitespace (p);
3003 if (*p == ']')
3005 p++;
3007 if (wb_ok && skip_past_comma (& p) == SUCCESS)
3009 /* [Rn], #expr */
3010 write_back = WRITE_BACK;
3012 if (reg == REG_PC)
3014 inst.error = _("pc may not be used in post-increment");
3015 return FAIL;
3018 if (cp_address_offset (& p) == FAIL)
3019 return FAIL;
3021 else
3022 pre_inc = PRE_INDEX | INDEX_UP;
3024 else
3026 /* '['Rn, #expr']'[!] */
3028 if (skip_past_comma (& p) == FAIL)
3030 inst.error = _("pre-indexed expression expected");
3031 return FAIL;
3034 pre_inc = PRE_INDEX;
3036 if (cp_address_offset (& p) == FAIL)
3037 return FAIL;
3039 skip_whitespace (p);
3041 if (*p++ != ']')
3043 inst.error = _("missing ]");
3044 return FAIL;
3047 skip_whitespace (p);
3049 if (wb_ok && *p == '!')
3051 if (reg == REG_PC)
3053 inst.error = _("pc may not be used with write-back");
3054 return FAIL;
3057 p++;
3058 write_back = WRITE_BACK;
3062 else
3064 if (my_get_expression (&inst.reloc.exp, &p))
3065 return FAIL;
3067 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
3068 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
3069 inst.reloc.pc_rel = 1;
3070 inst.instruction |= (REG_PC << 16);
3071 pre_inc = PRE_INDEX;
3074 inst.instruction |= write_back | pre_inc;
3075 *str = p;
3076 return SUCCESS;
3079 static void
3080 do_empty (str)
3081 char * str;
3083 /* Do nothing really. */
3084 end_of_line (str);
3085 return;
3088 static void
3089 do_mrs (str)
3090 char *str;
3092 int skip = 0;
3094 /* Only one syntax. */
3095 skip_whitespace (str);
3097 if (reg_required_here (&str, 12) == FAIL)
3099 inst.error = BAD_ARGS;
3100 return;
3103 if (skip_past_comma (&str) == FAIL)
3105 inst.error = _("comma expected after register name");
3106 return;
3109 skip_whitespace (str);
3111 if ( strcmp (str, "CPSR") == 0
3112 || strcmp (str, "SPSR") == 0
3113 /* Lower case versions for backwards compatability. */
3114 || strcmp (str, "cpsr") == 0
3115 || strcmp (str, "spsr") == 0)
3116 skip = 4;
3118 /* This is for backwards compatability with older toolchains. */
3119 else if ( strcmp (str, "cpsr_all") == 0
3120 || strcmp (str, "spsr_all") == 0)
3121 skip = 8;
3122 else
3124 inst.error = _("CPSR or SPSR expected");
3125 return;
3128 if (* str == 's' || * str == 'S')
3129 inst.instruction |= SPSR_BIT;
3130 str += skip;
3132 end_of_line (str);
3135 /* Two possible forms:
3136 "{C|S}PSR_<field>, Rm",
3137 "{C|S}PSR_f, #expression". */
3139 static void
3140 do_msr (str)
3141 char * str;
3143 skip_whitespace (str);
3145 if (psr_required_here (& str) == FAIL)
3146 return;
3148 if (skip_past_comma (& str) == FAIL)
3150 inst.error = _("comma missing after psr flags");
3151 return;
3154 skip_whitespace (str);
3156 if (reg_required_here (& str, 0) != FAIL)
3158 inst.error = NULL;
3159 end_of_line (str);
3160 return;
3163 if (! is_immediate_prefix (* str))
3165 inst.error =
3166 _("only a register or immediate value can follow a psr flag");
3167 return;
3170 str ++;
3171 inst.error = NULL;
3173 if (my_get_expression (& inst.reloc.exp, & str))
3175 inst.error =
3176 _("only a register or immediate value can follow a psr flag");
3177 return;
3180 #if 0 /* The first edition of the ARM architecture manual stated that
3181 writing anything other than the flags with an immediate operation
3182 had UNPREDICTABLE effects. This constraint was removed in the
3183 second edition of the specification. */
3184 if ((cpu_variant & ARM_EXT_V5) != ARM_EXT_V5
3185 && inst.instruction & ((PSR_c | PSR_x | PSR_s) << PSR_SHIFT))
3187 inst.error = _("immediate value cannot be used to set this field");
3188 return;
3190 #endif
3192 inst.instruction |= INST_IMMEDIATE;
3194 if (inst.reloc.exp.X_add_symbol)
3196 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
3197 inst.reloc.pc_rel = 0;
3199 else
3201 unsigned value = validate_immediate (inst.reloc.exp.X_add_number);
3203 if (value == (unsigned) FAIL)
3205 inst.error = _("invalid constant");
3206 return;
3209 inst.instruction |= value;
3212 inst.error = NULL;
3213 end_of_line (str);
3216 /* Long Multiply Parser
3217 UMULL RdLo, RdHi, Rm, Rs
3218 SMULL RdLo, RdHi, Rm, Rs
3219 UMLAL RdLo, RdHi, Rm, Rs
3220 SMLAL RdLo, RdHi, Rm, Rs. */
3222 static void
3223 do_mull (str)
3224 char * str;
3226 int rdlo, rdhi, rm, rs;
3228 /* Only one format "rdlo, rdhi, rm, rs". */
3229 skip_whitespace (str);
3231 if ((rdlo = reg_required_here (&str, 12)) == FAIL)
3233 inst.error = BAD_ARGS;
3234 return;
3237 if (skip_past_comma (&str) == FAIL
3238 || (rdhi = reg_required_here (&str, 16)) == FAIL)
3240 inst.error = BAD_ARGS;
3241 return;
3244 if (skip_past_comma (&str) == FAIL
3245 || (rm = reg_required_here (&str, 0)) == FAIL)
3247 inst.error = BAD_ARGS;
3248 return;
3251 /* rdhi, rdlo and rm must all be different. */
3252 if (rdlo == rdhi || rdlo == rm || rdhi == rm)
3253 as_tsktsk (_("rdhi, rdlo and rm must all be different"));
3255 if (skip_past_comma (&str) == FAIL
3256 || (rs = reg_required_here (&str, 8)) == FAIL)
3258 inst.error = BAD_ARGS;
3259 return;
3262 if (rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC)
3264 inst.error = BAD_PC;
3265 return;
3268 end_of_line (str);
3269 return;
3272 static void
3273 do_mul (str)
3274 char * str;
3276 int rd, rm;
3278 /* Only one format "rd, rm, rs". */
3279 skip_whitespace (str);
3281 if ((rd = reg_required_here (&str, 16)) == FAIL)
3283 inst.error = BAD_ARGS;
3284 return;
3287 if (rd == REG_PC)
3289 inst.error = BAD_PC;
3290 return;
3293 if (skip_past_comma (&str) == FAIL
3294 || (rm = reg_required_here (&str, 0)) == FAIL)
3296 inst.error = BAD_ARGS;
3297 return;
3300 if (rm == REG_PC)
3302 inst.error = BAD_PC;
3303 return;
3306 if (rm == rd)
3307 as_tsktsk (_("rd and rm should be different in mul"));
3309 if (skip_past_comma (&str) == FAIL
3310 || (rm = reg_required_here (&str, 8)) == FAIL)
3312 inst.error = BAD_ARGS;
3313 return;
3316 if (rm == REG_PC)
3318 inst.error = BAD_PC;
3319 return;
3322 end_of_line (str);
3323 return;
3326 static void
3327 do_mla (str)
3328 char * str;
3330 int rd, rm;
3332 /* Only one format "rd, rm, rs, rn". */
3333 skip_whitespace (str);
3335 if ((rd = reg_required_here (&str, 16)) == FAIL)
3337 inst.error = BAD_ARGS;
3338 return;
3341 if (rd == REG_PC)
3343 inst.error = BAD_PC;
3344 return;
3347 if (skip_past_comma (&str) == FAIL
3348 || (rm = reg_required_here (&str, 0)) == FAIL)
3350 inst.error = BAD_ARGS;
3351 return;
3354 if (rm == REG_PC)
3356 inst.error = BAD_PC;
3357 return;
3360 if (rm == rd)
3361 as_tsktsk (_("rd and rm should be different in mla"));
3363 if (skip_past_comma (&str) == FAIL
3364 || (rd = reg_required_here (&str, 8)) == FAIL
3365 || skip_past_comma (&str) == FAIL
3366 || (rm = reg_required_here (&str, 12)) == FAIL)
3368 inst.error = BAD_ARGS;
3369 return;
3372 if (rd == REG_PC || rm == REG_PC)
3374 inst.error = BAD_PC;
3375 return;
3378 end_of_line (str);
3379 return;
3382 /* Expects *str -> the characters "acc0", possibly with leading blanks.
3383 Advances *str to the next non-alphanumeric.
3384 Returns 0, or else FAIL (in which case sets inst.error).
3386 (In a future XScale, there may be accumulators other than zero.
3387 At that time this routine and its callers can be upgraded to suit.) */
3389 static int
3390 accum0_required_here (str)
3391 char ** str;
3393 static char buff [128]; /* Note the address is taken. Hence, static. */
3394 char * p = * str;
3395 char c;
3396 int result = 0; /* The accum number. */
3398 skip_whitespace (p);
3400 *str = p; /* Advance caller's string pointer too. */
3401 c = *p++;
3402 while (ISALNUM (c))
3403 c = *p++;
3405 *--p = 0; /* Aap nul into input buffer at non-alnum. */
3407 if (! ( streq (*str, "acc0") || streq (*str, "ACC0")))
3409 sprintf (buff, _("acc0 expected, not '%.100s'"), *str);
3410 inst.error = buff;
3411 result = FAIL;
3414 *p = c; /* Unzap. */
3415 *str = p; /* Caller's string pointer to after match. */
3416 return result;
3419 /* Expects **str -> after a comma. May be leading blanks.
3420 Advances *str, recognizing a load mode, and setting inst.instruction.
3421 Returns rn, or else FAIL (in which case may set inst.error
3422 and not advance str)
3424 Note: doesn't know Rd, so no err checks that require such knowledge. */
3426 static int
3427 ld_mode_required_here (string)
3428 char ** string;
3430 char * str = * string;
3431 int rn;
3432 int pre_inc = 0;
3434 skip_whitespace (str);
3436 if (* str == '[')
3438 str++;
3440 skip_whitespace (str);
3442 if ((rn = reg_required_here (& str, 16)) == FAIL)
3443 return FAIL;
3445 skip_whitespace (str);
3447 if (* str == ']')
3449 str ++;
3451 if (skip_past_comma (& str) == SUCCESS)
3453 /* [Rn],... (post inc) */
3454 if (ldst_extend_v4 (&str) == FAIL)
3455 return FAIL;
3457 else /* [Rn] */
3459 skip_whitespace (str);
3461 if (* str == '!')
3463 str ++;
3464 inst.instruction |= WRITE_BACK;
3467 inst.instruction |= INDEX_UP | HWOFFSET_IMM;
3468 pre_inc = 1;
3471 else /* [Rn,...] */
3473 if (skip_past_comma (& str) == FAIL)
3475 inst.error = _("pre-indexed expression expected");
3476 return FAIL;
3479 pre_inc = 1;
3481 if (ldst_extend_v4 (&str) == FAIL)
3482 return FAIL;
3484 skip_whitespace (str);
3486 if (* str ++ != ']')
3488 inst.error = _("missing ]");
3489 return FAIL;
3492 skip_whitespace (str);
3494 if (* str == '!')
3496 str ++;
3497 inst.instruction |= WRITE_BACK;
3501 else if (* str == '=') /* ldr's "r,=label" syntax */
3502 /* We should never reach here, because <text> = <expression> is
3503 caught gas/read.c read_a_source_file() as a .set operation. */
3504 return FAIL;
3505 else /* PC +- 8 bit immediate offset. */
3507 if (my_get_expression (& inst.reloc.exp, & str))
3508 return FAIL;
3510 inst.instruction |= HWOFFSET_IMM; /* The I bit. */
3511 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
3512 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
3513 inst.reloc.pc_rel = 1;
3514 inst.instruction |= (REG_PC << 16);
3516 rn = REG_PC;
3517 pre_inc = 1;
3520 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
3521 * string = str;
3523 return rn;
3526 /* ARM V5E (El Segundo) signed-multiply-accumulate (argument parse)
3527 SMLAxy{cond} Rd,Rm,Rs,Rn
3528 SMLAWy{cond} Rd,Rm,Rs,Rn
3529 Error if any register is R15. */
3531 static void
3532 do_smla (str)
3533 char * str;
3535 int rd, rm, rs, rn;
3537 skip_whitespace (str);
3539 if ((rd = reg_required_here (& str, 16)) == FAIL
3540 || skip_past_comma (& str) == FAIL
3541 || (rm = reg_required_here (& str, 0)) == FAIL
3542 || skip_past_comma (& str) == FAIL
3543 || (rs = reg_required_here (& str, 8)) == FAIL
3544 || skip_past_comma (& str) == FAIL
3545 || (rn = reg_required_here (& str, 12)) == FAIL)
3546 inst.error = BAD_ARGS;
3548 else if (rd == REG_PC || rm == REG_PC || rs == REG_PC || rn == REG_PC)
3549 inst.error = BAD_PC;
3551 else
3552 end_of_line (str);
3555 /* ARM V5E (El Segundo) signed-multiply-accumulate-long (argument parse)
3556 SMLALxy{cond} Rdlo,Rdhi,Rm,Rs
3557 Error if any register is R15.
3558 Warning if Rdlo == Rdhi. */
3560 static void
3561 do_smlal (str)
3562 char * str;
3564 int rdlo, rdhi, rm, rs;
3566 skip_whitespace (str);
3568 if ((rdlo = reg_required_here (& str, 12)) == FAIL
3569 || skip_past_comma (& str) == FAIL
3570 || (rdhi = reg_required_here (& str, 16)) == FAIL
3571 || skip_past_comma (& str) == FAIL
3572 || (rm = reg_required_here (& str, 0)) == FAIL
3573 || skip_past_comma (& str) == FAIL
3574 || (rs = reg_required_here (& str, 8)) == FAIL)
3576 inst.error = BAD_ARGS;
3577 return;
3580 if (rdlo == REG_PC || rdhi == REG_PC || rm == REG_PC || rs == REG_PC)
3582 inst.error = BAD_PC;
3583 return;
3586 if (rdlo == rdhi)
3587 as_tsktsk (_("rdhi and rdlo must be different"));
3589 end_of_line (str);
3592 /* ARM V5E (El Segundo) signed-multiply (argument parse)
3593 SMULxy{cond} Rd,Rm,Rs
3594 Error if any register is R15. */
3596 static void
3597 do_smul (str)
3598 char * str;
3600 int rd, rm, rs;
3602 skip_whitespace (str);
3604 if ((rd = reg_required_here (& str, 16)) == FAIL
3605 || skip_past_comma (& str) == FAIL
3606 || (rm = reg_required_here (& str, 0)) == FAIL
3607 || skip_past_comma (& str) == FAIL
3608 || (rs = reg_required_here (& str, 8)) == FAIL)
3609 inst.error = BAD_ARGS;
3611 else if (rd == REG_PC || rm == REG_PC || rs == REG_PC)
3612 inst.error = BAD_PC;
3614 else
3615 end_of_line (str);
3618 /* ARM V5E (El Segundo) saturating-add/subtract (argument parse)
3619 Q[D]{ADD,SUB}{cond} Rd,Rm,Rn
3620 Error if any register is R15. */
3622 static void
3623 do_qadd (str)
3624 char * str;
3626 int rd, rm, rn;
3628 skip_whitespace (str);
3630 if ((rd = reg_required_here (& str, 12)) == FAIL
3631 || skip_past_comma (& str) == FAIL
3632 || (rm = reg_required_here (& str, 0)) == FAIL
3633 || skip_past_comma (& str) == FAIL
3634 || (rn = reg_required_here (& str, 16)) == FAIL)
3635 inst.error = BAD_ARGS;
3637 else if (rd == REG_PC || rm == REG_PC || rn == REG_PC)
3638 inst.error = BAD_PC;
3640 else
3641 end_of_line (str);
3644 /* ARM V5E (el Segundo)
3645 MCRRcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
3646 MRRCcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
3648 These are equivalent to the XScale instructions MAR and MRA,
3649 respectively, when coproc == 0, opcode == 0, and CRm == 0.
3651 Result unpredicatable if Rd or Rn is R15. */
3653 static void
3654 do_co_reg2c (str)
3655 char * str;
3657 int rd, rn;
3659 skip_whitespace (str);
3661 if (co_proc_number (& str) == FAIL)
3663 if (!inst.error)
3664 inst.error = BAD_ARGS;
3665 return;
3668 if (skip_past_comma (& str) == FAIL
3669 || cp_opc_expr (& str, 4, 4) == FAIL)
3671 if (!inst.error)
3672 inst.error = BAD_ARGS;
3673 return;
3676 if (skip_past_comma (& str) == FAIL
3677 || (rd = reg_required_here (& str, 12)) == FAIL)
3679 if (!inst.error)
3680 inst.error = BAD_ARGS;
3681 return;
3684 if (skip_past_comma (& str) == FAIL
3685 || (rn = reg_required_here (& str, 16)) == FAIL)
3687 if (!inst.error)
3688 inst.error = BAD_ARGS;
3689 return;
3692 /* Unpredictable result if rd or rn is R15. */
3693 if (rd == REG_PC || rn == REG_PC)
3694 as_tsktsk
3695 (_("Warning: instruction unpredictable when using r15"));
3697 if (skip_past_comma (& str) == FAIL
3698 || cp_reg_required_here (& str, 0) == FAIL)
3700 if (!inst.error)
3701 inst.error = BAD_ARGS;
3702 return;
3705 end_of_line (str);
3708 /* ARM V5 count-leading-zeroes instruction (argument parse)
3709 CLZ{<cond>} <Rd>, <Rm>
3710 Condition defaults to COND_ALWAYS.
3711 Error if Rd or Rm are R15. */
3713 static void
3714 do_clz (str)
3715 char * str;
3717 int rd, rm;
3719 skip_whitespace (str);
3721 if (((rd = reg_required_here (& str, 12)) == FAIL)
3722 || (skip_past_comma (& str) == FAIL)
3723 || ((rm = reg_required_here (& str, 0)) == FAIL))
3724 inst.error = BAD_ARGS;
3726 else if (rd == REG_PC || rm == REG_PC )
3727 inst.error = BAD_PC;
3729 else
3730 end_of_line (str);
3733 /* ARM V5 (argument parse)
3734 LDC2{L} <coproc>, <CRd>, <addressing mode>
3735 STC2{L} <coproc>, <CRd>, <addressing mode>
3736 Instruction is not conditional, and has 0xf in the codition field.
3737 Otherwise, it's the same as LDC/STC. */
3739 static void
3740 do_lstc2 (str)
3741 char * str;
3743 skip_whitespace (str);
3745 if (co_proc_number (& str) == FAIL)
3747 if (!inst.error)
3748 inst.error = BAD_ARGS;
3750 else if (skip_past_comma (& str) == FAIL
3751 || cp_reg_required_here (& str, 12) == FAIL)
3753 if (!inst.error)
3754 inst.error = BAD_ARGS;
3756 else if (skip_past_comma (& str) == FAIL
3757 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
3759 if (! inst.error)
3760 inst.error = BAD_ARGS;
3762 else
3763 end_of_line (str);
3766 /* ARM V5 (argument parse)
3767 CDP2 <coproc>, <opcode_1>, <CRd>, <CRn>, <CRm>, <opcode_2>
3768 Instruction is not conditional, and has 0xf in the condition field.
3769 Otherwise, it's the same as CDP. */
3771 static void
3772 do_cdp2 (str)
3773 char * str;
3775 skip_whitespace (str);
3777 if (co_proc_number (& str) == FAIL)
3779 if (!inst.error)
3780 inst.error = BAD_ARGS;
3781 return;
3784 if (skip_past_comma (& str) == FAIL
3785 || cp_opc_expr (& str, 20,4) == FAIL)
3787 if (!inst.error)
3788 inst.error = BAD_ARGS;
3789 return;
3792 if (skip_past_comma (& str) == FAIL
3793 || cp_reg_required_here (& str, 12) == FAIL)
3795 if (!inst.error)
3796 inst.error = BAD_ARGS;
3797 return;
3800 if (skip_past_comma (& str) == FAIL
3801 || cp_reg_required_here (& str, 16) == FAIL)
3803 if (!inst.error)
3804 inst.error = BAD_ARGS;
3805 return;
3808 if (skip_past_comma (& str) == FAIL
3809 || cp_reg_required_here (& str, 0) == FAIL)
3811 if (!inst.error)
3812 inst.error = BAD_ARGS;
3813 return;
3816 if (skip_past_comma (& str) == SUCCESS)
3818 if (cp_opc_expr (& str, 5, 3) == FAIL)
3820 if (!inst.error)
3821 inst.error = BAD_ARGS;
3822 return;
3826 end_of_line (str);
3829 /* ARM V5 (argument parse)
3830 MCR2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
3831 MRC2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
3832 Instruction is not conditional, and has 0xf in the condition field.
3833 Otherwise, it's the same as MCR/MRC. */
3835 static void
3836 do_co_reg2 (str)
3837 char * str;
3839 skip_whitespace (str);
3841 if (co_proc_number (& str) == FAIL)
3843 if (!inst.error)
3844 inst.error = BAD_ARGS;
3845 return;
3848 if (skip_past_comma (& str) == FAIL
3849 || cp_opc_expr (& str, 21, 3) == FAIL)
3851 if (!inst.error)
3852 inst.error = BAD_ARGS;
3853 return;
3856 if (skip_past_comma (& str) == FAIL
3857 || reg_required_here (& str, 12) == FAIL)
3859 if (!inst.error)
3860 inst.error = BAD_ARGS;
3861 return;
3864 if (skip_past_comma (& str) == FAIL
3865 || cp_reg_required_here (& str, 16) == FAIL)
3867 if (!inst.error)
3868 inst.error = BAD_ARGS;
3869 return;
3872 if (skip_past_comma (& str) == FAIL
3873 || cp_reg_required_here (& str, 0) == FAIL)
3875 if (!inst.error)
3876 inst.error = BAD_ARGS;
3877 return;
3880 if (skip_past_comma (& str) == SUCCESS)
3882 if (cp_opc_expr (& str, 5, 3) == FAIL)
3884 if (!inst.error)
3885 inst.error = BAD_ARGS;
3886 return;
3890 end_of_line (str);
3893 /* ARM v5TEJ. Jump to Jazelle code. */
3894 static void
3895 do_bxj (str)
3896 char * str;
3898 int reg;
3900 skip_whitespace (str);
3902 if ((reg = reg_required_here (&str, 0)) == FAIL)
3904 inst.error = BAD_ARGS;
3905 return;
3908 /* Note - it is not illegal to do a "bxj pc". Useless, but not illegal. */
3909 if (reg == REG_PC)
3910 as_tsktsk (_("use of r15 in bxj is not really useful"));
3912 end_of_line (str);
3915 /* THUMB V5 breakpoint instruction (argument parse)
3916 BKPT <immed_8>. */
3918 static void
3919 do_t_bkpt (str)
3920 char * str;
3922 expressionS expr;
3923 unsigned long number;
3925 skip_whitespace (str);
3927 /* Allow optional leading '#'. */
3928 if (is_immediate_prefix (*str))
3929 str ++;
3931 memset (& expr, '\0', sizeof (expr));
3932 if (my_get_expression (& expr, & str) || (expr.X_op != O_constant))
3934 inst.error = _("bad or missing expression");
3935 return;
3938 number = expr.X_add_number;
3940 /* Check it fits an 8 bit unsigned. */
3941 if (number != (number & 0xff))
3943 inst.error = _("immediate value out of range");
3944 return;
3947 inst.instruction |= number;
3949 end_of_line (str);
3952 /* ARM V5 branch-link-exchange (argument parse) for BLX(1) only.
3953 Expects inst.instruction is set for BLX(1).
3954 Note: this is cloned from do_branch, and the reloc changed to be a
3955 new one that can cope with setting one extra bit (the H bit). */
3957 static void
3958 do_branch25 (str)
3959 char * str;
3961 if (my_get_expression (& inst.reloc.exp, & str))
3962 return;
3964 #ifdef OBJ_ELF
3966 char * save_in;
3968 /* ScottB: February 5, 1998 */
3969 /* Check to see of PLT32 reloc required for the instruction. */
3971 /* arm_parse_reloc() works on input_line_pointer.
3972 We actually want to parse the operands to the branch instruction
3973 passed in 'str'. Save the input pointer and restore it later. */
3974 save_in = input_line_pointer;
3975 input_line_pointer = str;
3977 if (inst.reloc.exp.X_op == O_symbol
3978 && *str == '('
3979 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
3981 inst.reloc.type = BFD_RELOC_ARM_PLT32;
3982 inst.reloc.pc_rel = 0;
3983 /* Modify str to point to after parsed operands, otherwise
3984 end_of_line() will complain about the (PLT) left in str. */
3985 str = input_line_pointer;
3987 else
3989 inst.reloc.type = BFD_RELOC_ARM_PCREL_BLX;
3990 inst.reloc.pc_rel = 1;
3993 input_line_pointer = save_in;
3995 #else
3996 inst.reloc.type = BFD_RELOC_ARM_PCREL_BLX;
3997 inst.reloc.pc_rel = 1;
3998 #endif /* OBJ_ELF */
4000 end_of_line (str);
4003 /* ARM V5 branch-link-exchange instruction (argument parse)
4004 BLX <target_addr> ie BLX(1)
4005 BLX{<condition>} <Rm> ie BLX(2)
4006 Unfortunately, there are two different opcodes for this mnemonic.
4007 So, the insns[].value is not used, and the code here zaps values
4008 into inst.instruction.
4009 Also, the <target_addr> can be 25 bits, hence has its own reloc. */
4011 static void
4012 do_blx (str)
4013 char * str;
4015 char * mystr = str;
4016 int rm;
4018 skip_whitespace (mystr);
4019 rm = reg_required_here (& mystr, 0);
4021 /* The above may set inst.error. Ignore his opinion. */
4022 inst.error = 0;
4024 if (rm != FAIL)
4026 /* Arg is a register.
4027 Use the condition code our caller put in inst.instruction.
4028 Pass ourselves off as a BX with a funny opcode. */
4029 inst.instruction |= 0x012fff30;
4030 do_bx (str);
4032 else
4034 /* This must be is BLX <target address>, no condition allowed. */
4035 if (inst.instruction != COND_ALWAYS)
4037 inst.error = BAD_COND;
4038 return;
4041 inst.instruction = 0xfafffffe;
4043 /* Process like a B/BL, but with a different reloc.
4044 Note that B/BL expecte fffffe, not 0, offset in the opcode table. */
4045 do_branch25 (str);
4049 /* ARM V5 Thumb BLX (argument parse)
4050 BLX <target_addr> which is BLX(1)
4051 BLX <Rm> which is BLX(2)
4052 Unfortunately, there are two different opcodes for this mnemonic.
4053 So, the tinsns[].value is not used, and the code here zaps values
4054 into inst.instruction. */
4056 static void
4057 do_t_blx (str)
4058 char * str;
4060 char * mystr = str;
4061 int rm;
4063 skip_whitespace (mystr);
4064 inst.instruction = 0x4780;
4066 /* Note that this call is to the ARM register recognizer. BLX(2)
4067 uses the ARM register space, not the Thumb one, so a call to
4068 thumb_reg() would be wrong. */
4069 rm = reg_required_here (& mystr, 3);
4070 inst.error = 0;
4072 if (rm != FAIL)
4074 /* It's BLX(2). The .instruction was zapped with rm & is final. */
4075 inst.size = 2;
4077 else
4079 /* No ARM register. This must be BLX(1). Change the .instruction. */
4080 inst.instruction = 0xf7ffeffe;
4081 inst.size = 4;
4083 if (my_get_expression (& inst.reloc.exp, & mystr))
4084 return;
4086 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BLX;
4087 inst.reloc.pc_rel = 1;
4090 end_of_line (mystr);
4093 /* ARM V5 breakpoint instruction (argument parse)
4094 BKPT <16 bit unsigned immediate>
4095 Instruction is not conditional.
4096 The bit pattern given in insns[] has the COND_ALWAYS condition,
4097 and it is an error if the caller tried to override that. */
4099 static void
4100 do_bkpt (str)
4101 char * str;
4103 expressionS expr;
4104 unsigned long number;
4106 skip_whitespace (str);
4108 /* Allow optional leading '#'. */
4109 if (is_immediate_prefix (* str))
4110 str++;
4112 memset (& expr, '\0', sizeof (expr));
4114 if (my_get_expression (& expr, & str) || (expr.X_op != O_constant))
4116 inst.error = _("bad or missing expression");
4117 return;
4120 number = expr.X_add_number;
4122 /* Check it fits a 16 bit unsigned. */
4123 if (number != (number & 0xffff))
4125 inst.error = _("immediate value out of range");
4126 return;
4129 /* Top 12 of 16 bits to bits 19:8. */
4130 inst.instruction |= (number & 0xfff0) << 4;
4132 /* Bottom 4 of 16 bits to bits 3:0. */
4133 inst.instruction |= number & 0xf;
4135 end_of_line (str);
4138 /* Xscale multiply-accumulate (argument parse)
4139 MIAcc acc0,Rm,Rs
4140 MIAPHcc acc0,Rm,Rs
4141 MIAxycc acc0,Rm,Rs. */
4143 static void
4144 do_xsc_mia (str)
4145 char * str;
4147 int rs;
4148 int rm;
4150 if (accum0_required_here (& str) == FAIL)
4151 inst.error = ERR_NO_ACCUM;
4153 else if (skip_past_comma (& str) == FAIL
4154 || (rm = reg_required_here (& str, 0)) == FAIL)
4155 inst.error = BAD_ARGS;
4157 else if (skip_past_comma (& str) == FAIL
4158 || (rs = reg_required_here (& str, 12)) == FAIL)
4159 inst.error = BAD_ARGS;
4161 /* inst.instruction has now been zapped with both rm and rs. */
4162 else if (rm == REG_PC || rs == REG_PC)
4163 inst.error = BAD_PC; /* Undefined result if rm or rs is R15. */
4165 else
4166 end_of_line (str);
4169 /* Xscale move-accumulator-register (argument parse)
4171 MARcc acc0,RdLo,RdHi. */
4173 static void
4174 do_xsc_mar (str)
4175 char * str;
4177 int rdlo, rdhi;
4179 if (accum0_required_here (& str) == FAIL)
4180 inst.error = ERR_NO_ACCUM;
4182 else if (skip_past_comma (& str) == FAIL
4183 || (rdlo = reg_required_here (& str, 12)) == FAIL)
4184 inst.error = BAD_ARGS;
4186 else if (skip_past_comma (& str) == FAIL
4187 || (rdhi = reg_required_here (& str, 16)) == FAIL)
4188 inst.error = BAD_ARGS;
4190 /* inst.instruction has now been zapped with both rdlo and rdhi. */
4191 else if (rdlo == REG_PC || rdhi == REG_PC)
4192 inst.error = BAD_PC; /* Undefined result if rdlo or rdhi is R15. */
4194 else
4195 end_of_line (str);
4198 /* Xscale move-register-accumulator (argument parse)
4200 MRAcc RdLo,RdHi,acc0. */
4202 static void
4203 do_xsc_mra (str)
4204 char * str;
4206 int rdlo;
4207 int rdhi;
4209 skip_whitespace (str);
4211 if ((rdlo = reg_required_here (& str, 12)) == FAIL)
4212 inst.error = BAD_ARGS;
4214 else if (skip_past_comma (& str) == FAIL
4215 || (rdhi = reg_required_here (& str, 16)) == FAIL)
4216 inst.error = BAD_ARGS;
4218 else if (skip_past_comma (& str) == FAIL
4219 || accum0_required_here (& str) == FAIL)
4220 inst.error = ERR_NO_ACCUM;
4222 /* inst.instruction has now been zapped with both rdlo and rdhi. */
4223 else if (rdlo == rdhi)
4224 inst.error = BAD_ARGS; /* Undefined result if 2 writes to same reg. */
4226 else if (rdlo == REG_PC || rdhi == REG_PC)
4227 inst.error = BAD_PC; /* Undefined result if rdlo or rdhi is R15. */
4228 else
4229 end_of_line (str);
4232 /* ARMv5TE: Preload-Cache
4234 PLD <addr_mode>
4236 Syntactically, like LDR with B=1, W=0, L=1. */
4238 static void
4239 do_pld (str)
4240 char * str;
4242 int rd;
4244 skip_whitespace (str);
4246 if (* str != '[')
4248 inst.error = _("'[' expected after PLD mnemonic");
4249 return;
4252 ++str;
4253 skip_whitespace (str);
4255 if ((rd = reg_required_here (& str, 16)) == FAIL)
4256 return;
4258 skip_whitespace (str);
4260 if (*str == ']')
4262 /* [Rn], ... ? */
4263 ++str;
4264 skip_whitespace (str);
4266 /* Post-indexed addressing is not allowed with PLD. */
4267 if (skip_past_comma (&str) == SUCCESS)
4269 inst.error
4270 = _("post-indexed expression used in preload instruction");
4271 return;
4273 else if (*str == '!') /* [Rn]! */
4275 inst.error = _("writeback used in preload instruction");
4276 ++str;
4278 else /* [Rn] */
4279 inst.instruction |= INDEX_UP | PRE_INDEX;
4281 else /* [Rn, ...] */
4283 if (skip_past_comma (& str) == FAIL)
4285 inst.error = _("pre-indexed expression expected");
4286 return;
4289 if (ldst_extend (&str) == FAIL)
4290 return;
4292 skip_whitespace (str);
4294 if (* str != ']')
4296 inst.error = _("missing ]");
4297 return;
4300 ++ str;
4301 skip_whitespace (str);
4303 if (* str == '!') /* [Rn]! */
4305 inst.error = _("writeback used in preload instruction");
4306 ++ str;
4309 inst.instruction |= PRE_INDEX;
4312 end_of_line (str);
4315 /* ARMv5TE load-consecutive (argument parse)
4316 Mode is like LDRH.
4318 LDRccD R, mode
4319 STRccD R, mode. */
4321 static void
4322 do_ldrd (str)
4323 char * str;
4325 int rd;
4326 int rn;
4328 skip_whitespace (str);
4330 if ((rd = reg_required_here (& str, 12)) == FAIL)
4332 inst.error = BAD_ARGS;
4333 return;
4336 if (skip_past_comma (& str) == FAIL
4337 || (rn = ld_mode_required_here (& str)) == FAIL)
4339 if (!inst.error)
4340 inst.error = BAD_ARGS;
4341 return;
4344 /* inst.instruction has now been zapped with Rd and the addressing mode. */
4345 if (rd & 1) /* Unpredictable result if Rd is odd. */
4347 inst.error = _("destination register must be even");
4348 return;
4351 if (rd == REG_LR)
4353 inst.error = _("r14 not allowed here");
4354 return;
4357 if (((rd == rn) || (rd + 1 == rn))
4358 && ((inst.instruction & WRITE_BACK)
4359 || (!(inst.instruction & PRE_INDEX))))
4360 as_warn (_("pre/post-indexing used when modified address register is destination"));
4362 /* For an index-register load, the index register must not overlap the
4363 destination (even if not write-back). */
4364 if ((inst.instruction & V4_STR_BIT) == 0
4365 && (inst.instruction & HWOFFSET_IMM) == 0)
4367 int rm = inst.instruction & 0x0000000f;
4369 if (rm == rd || (rm == rd + 1))
4370 as_warn (_("ldrd destination registers must not overlap index register"));
4373 end_of_line (str);
4376 /* Returns the index into fp_values of a floating point number,
4377 or -1 if not in the table. */
4379 static int
4380 my_get_float_expression (str)
4381 char ** str;
4383 LITTLENUM_TYPE words[MAX_LITTLENUMS];
4384 char * save_in;
4385 expressionS exp;
4386 int i;
4387 int j;
4389 memset (words, 0, MAX_LITTLENUMS * sizeof (LITTLENUM_TYPE));
4391 /* Look for a raw floating point number. */
4392 if ((save_in = atof_ieee (*str, 'x', words)) != NULL
4393 && is_end_of_line[(unsigned char) *save_in])
4395 for (i = 0; i < NUM_FLOAT_VALS; i++)
4397 for (j = 0; j < MAX_LITTLENUMS; j++)
4399 if (words[j] != fp_values[i][j])
4400 break;
4403 if (j == MAX_LITTLENUMS)
4405 *str = save_in;
4406 return i;
4411 /* Try and parse a more complex expression, this will probably fail
4412 unless the code uses a floating point prefix (eg "0f"). */
4413 save_in = input_line_pointer;
4414 input_line_pointer = *str;
4415 if (expression (&exp) == absolute_section
4416 && exp.X_op == O_big
4417 && exp.X_add_number < 0)
4419 /* FIXME: 5 = X_PRECISION, should be #define'd where we can use it.
4420 Ditto for 15. */
4421 if (gen_to_words (words, 5, (long) 15) == 0)
4423 for (i = 0; i < NUM_FLOAT_VALS; i++)
4425 for (j = 0; j < MAX_LITTLENUMS; j++)
4427 if (words[j] != fp_values[i][j])
4428 break;
4431 if (j == MAX_LITTLENUMS)
4433 *str = input_line_pointer;
4434 input_line_pointer = save_in;
4435 return i;
4441 *str = input_line_pointer;
4442 input_line_pointer = save_in;
4443 return -1;
4446 /* Return true if anything in the expression is a bignum. */
4448 static int
4449 walk_no_bignums (sp)
4450 symbolS * sp;
4452 if (symbol_get_value_expression (sp)->X_op == O_big)
4453 return 1;
4455 if (symbol_get_value_expression (sp)->X_add_symbol)
4457 return (walk_no_bignums (symbol_get_value_expression (sp)->X_add_symbol)
4458 || (symbol_get_value_expression (sp)->X_op_symbol
4459 && walk_no_bignums (symbol_get_value_expression (sp)->X_op_symbol)));
4462 return 0;
4465 static int in_my_get_expression = 0;
4467 static int
4468 my_get_expression (ep, str)
4469 expressionS * ep;
4470 char ** str;
4472 char * save_in;
4473 segT seg;
4475 save_in = input_line_pointer;
4476 input_line_pointer = *str;
4477 in_my_get_expression = 1;
4478 seg = expression (ep);
4479 in_my_get_expression = 0;
4481 if (ep->X_op == O_illegal)
4483 /* We found a bad expression in md_operand(). */
4484 *str = input_line_pointer;
4485 input_line_pointer = save_in;
4486 return 1;
4489 #ifdef OBJ_AOUT
4490 if (seg != absolute_section
4491 && seg != text_section
4492 && seg != data_section
4493 && seg != bss_section
4494 && seg != undefined_section)
4496 inst.error = _("bad_segment");
4497 *str = input_line_pointer;
4498 input_line_pointer = save_in;
4499 return 1;
4501 #endif
4503 /* Get rid of any bignums now, so that we don't generate an error for which
4504 we can't establish a line number later on. Big numbers are never valid
4505 in instructions, which is where this routine is always called. */
4506 if (ep->X_op == O_big
4507 || (ep->X_add_symbol
4508 && (walk_no_bignums (ep->X_add_symbol)
4509 || (ep->X_op_symbol
4510 && walk_no_bignums (ep->X_op_symbol)))))
4512 inst.error = _("invalid constant");
4513 *str = input_line_pointer;
4514 input_line_pointer = save_in;
4515 return 1;
4518 *str = input_line_pointer;
4519 input_line_pointer = save_in;
4520 return 0;
4523 /* We handle all bad expressions here, so that we can report the faulty
4524 instruction in the error message. */
4525 void
4526 md_operand (expr)
4527 expressionS *expr;
4529 if (in_my_get_expression)
4531 expr->X_op = O_illegal;
4532 if (inst.error == NULL)
4533 inst.error = _("bad expression");
4537 /* UNRESTRICT should be one if <shift> <register> is permitted for this
4538 instruction. */
4540 static int
4541 decode_shift (str, unrestrict)
4542 char ** str;
4543 int unrestrict;
4545 const struct asm_shift_name * shift;
4546 char * p;
4547 char c;
4549 skip_whitespace (* str);
4551 for (p = * str; ISALPHA (* p); p ++)
4554 if (p == * str)
4556 inst.error = _("shift expression expected");
4557 return FAIL;
4560 c = * p;
4561 * p = '\0';
4562 shift = (const struct asm_shift_name *) hash_find (arm_shift_hsh, * str);
4563 * p = c;
4565 if (shift == NULL)
4567 inst.error = _("shift expression expected");
4568 return FAIL;
4571 assert (shift->properties->index == shift_properties[shift->properties->index].index);
4573 if (shift->properties->index == SHIFT_RRX)
4575 * str = p;
4576 inst.instruction |= shift->properties->bit_field;
4577 return SUCCESS;
4580 skip_whitespace (p);
4582 if (unrestrict && reg_required_here (& p, 8) != FAIL)
4584 inst.instruction |= shift->properties->bit_field | SHIFT_BY_REG;
4585 * str = p;
4586 return SUCCESS;
4588 else if (! is_immediate_prefix (* p))
4590 inst.error = (unrestrict
4591 ? _("shift requires register or #expression")
4592 : _("shift requires #expression"));
4593 * str = p;
4594 return FAIL;
4597 inst.error = NULL;
4598 p ++;
4600 if (my_get_expression (& inst.reloc.exp, & p))
4601 return FAIL;
4603 /* Validate some simple #expressions. */
4604 if (inst.reloc.exp.X_op == O_constant)
4606 unsigned num = inst.reloc.exp.X_add_number;
4608 /* Reject operations greater than 32. */
4609 if (num > 32
4610 /* Reject a shift of 0 unless the mode allows it. */
4611 || (num == 0 && shift->properties->allows_0 == 0)
4612 /* Reject a shift of 32 unless the mode allows it. */
4613 || (num == 32 && shift->properties->allows_32 == 0)
4616 /* As a special case we allow a shift of zero for
4617 modes that do not support it to be recoded as an
4618 logical shift left of zero (ie nothing). We warn
4619 about this though. */
4620 if (num == 0)
4622 as_warn (_("shift of 0 ignored."));
4623 shift = & shift_names[0];
4624 assert (shift->properties->index == SHIFT_LSL);
4626 else
4628 inst.error = _("invalid immediate shift");
4629 return FAIL;
4633 /* Shifts of 32 are encoded as 0, for those shifts that
4634 support it. */
4635 if (num == 32)
4636 num = 0;
4638 inst.instruction |= (num << 7) | shift->properties->bit_field;
4640 else
4642 inst.reloc.type = BFD_RELOC_ARM_SHIFT_IMM;
4643 inst.reloc.pc_rel = 0;
4644 inst.instruction |= shift->properties->bit_field;
4647 * str = p;
4648 return SUCCESS;
4651 /* Do those data_ops which can take a negative immediate constant
4652 by altering the instuction. A bit of a hack really.
4653 MOV <-> MVN
4654 AND <-> BIC
4655 ADC <-> SBC
4656 by inverting the second operand, and
4657 ADD <-> SUB
4658 CMP <-> CMN
4659 by negating the second operand. */
4661 static int
4662 negate_data_op (instruction, value)
4663 unsigned long * instruction;
4664 unsigned long value;
4666 int op, new_inst;
4667 unsigned long negated, inverted;
4669 negated = validate_immediate (-value);
4670 inverted = validate_immediate (~value);
4672 op = (*instruction >> DATA_OP_SHIFT) & 0xf;
4673 switch (op)
4675 /* First negates. */
4676 case OPCODE_SUB: /* ADD <-> SUB */
4677 new_inst = OPCODE_ADD;
4678 value = negated;
4679 break;
4681 case OPCODE_ADD:
4682 new_inst = OPCODE_SUB;
4683 value = negated;
4684 break;
4686 case OPCODE_CMP: /* CMP <-> CMN */
4687 new_inst = OPCODE_CMN;
4688 value = negated;
4689 break;
4691 case OPCODE_CMN:
4692 new_inst = OPCODE_CMP;
4693 value = negated;
4694 break;
4696 /* Now Inverted ops. */
4697 case OPCODE_MOV: /* MOV <-> MVN */
4698 new_inst = OPCODE_MVN;
4699 value = inverted;
4700 break;
4702 case OPCODE_MVN:
4703 new_inst = OPCODE_MOV;
4704 value = inverted;
4705 break;
4707 case OPCODE_AND: /* AND <-> BIC */
4708 new_inst = OPCODE_BIC;
4709 value = inverted;
4710 break;
4712 case OPCODE_BIC:
4713 new_inst = OPCODE_AND;
4714 value = inverted;
4715 break;
4717 case OPCODE_ADC: /* ADC <-> SBC */
4718 new_inst = OPCODE_SBC;
4719 value = inverted;
4720 break;
4722 case OPCODE_SBC:
4723 new_inst = OPCODE_ADC;
4724 value = inverted;
4725 break;
4727 /* We cannot do anything. */
4728 default:
4729 return FAIL;
4732 if (value == (unsigned) FAIL)
4733 return FAIL;
4735 *instruction &= OPCODE_MASK;
4736 *instruction |= new_inst << DATA_OP_SHIFT;
4737 return value;
4740 static int
4741 data_op2 (str)
4742 char ** str;
4744 int value;
4745 expressionS expr;
4747 skip_whitespace (* str);
4749 if (reg_required_here (str, 0) != FAIL)
4751 if (skip_past_comma (str) == SUCCESS)
4752 /* Shift operation on register. */
4753 return decode_shift (str, NO_SHIFT_RESTRICT);
4755 return SUCCESS;
4757 else
4759 /* Immediate expression. */
4760 if (is_immediate_prefix (**str))
4762 (*str)++;
4763 inst.error = NULL;
4765 if (my_get_expression (&inst.reloc.exp, str))
4766 return FAIL;
4768 if (inst.reloc.exp.X_add_symbol)
4770 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
4771 inst.reloc.pc_rel = 0;
4773 else
4775 if (skip_past_comma (str) == SUCCESS)
4777 /* #x, y -- ie explicit rotation by Y. */
4778 if (my_get_expression (&expr, str))
4779 return FAIL;
4781 if (expr.X_op != O_constant)
4783 inst.error = _("constant expression expected");
4784 return FAIL;
4787 /* Rotate must be a multiple of 2. */
4788 if (((unsigned) expr.X_add_number) > 30
4789 || (expr.X_add_number & 1) != 0
4790 || ((unsigned) inst.reloc.exp.X_add_number) > 255)
4792 inst.error = _("invalid constant");
4793 return FAIL;
4795 inst.instruction |= INST_IMMEDIATE;
4796 inst.instruction |= inst.reloc.exp.X_add_number;
4797 inst.instruction |= expr.X_add_number << 7;
4798 return SUCCESS;
4801 /* Implicit rotation, select a suitable one. */
4802 value = validate_immediate (inst.reloc.exp.X_add_number);
4804 if (value == FAIL)
4806 /* Can't be done. Perhaps the code reads something like
4807 "add Rd, Rn, #-n", where "sub Rd, Rn, #n" would be OK. */
4808 if ((value = negate_data_op (&inst.instruction,
4809 inst.reloc.exp.X_add_number))
4810 == FAIL)
4812 inst.error = _("invalid constant");
4813 return FAIL;
4817 inst.instruction |= value;
4820 inst.instruction |= INST_IMMEDIATE;
4821 return SUCCESS;
4824 (*str)++;
4825 inst.error = _("register or shift expression expected");
4826 return FAIL;
4830 static int
4831 fp_op2 (str)
4832 char ** str;
4834 skip_whitespace (* str);
4836 if (fp_reg_required_here (str, 0) != FAIL)
4837 return SUCCESS;
4838 else
4840 /* Immediate expression. */
4841 if (*((*str)++) == '#')
4843 int i;
4845 inst.error = NULL;
4847 skip_whitespace (* str);
4849 /* First try and match exact strings, this is to guarantee
4850 that some formats will work even for cross assembly. */
4852 for (i = 0; fp_const[i]; i++)
4854 if (strncmp (*str, fp_const[i], strlen (fp_const[i])) == 0)
4856 char *start = *str;
4858 *str += strlen (fp_const[i]);
4859 if (is_end_of_line[(unsigned char) **str])
4861 inst.instruction |= i + 8;
4862 return SUCCESS;
4864 *str = start;
4868 /* Just because we didn't get a match doesn't mean that the
4869 constant isn't valid, just that it is in a format that we
4870 don't automatically recognize. Try parsing it with
4871 the standard expression routines. */
4872 if ((i = my_get_float_expression (str)) >= 0)
4874 inst.instruction |= i + 8;
4875 return SUCCESS;
4878 inst.error = _("invalid floating point immediate expression");
4879 return FAIL;
4881 inst.error =
4882 _("floating point register or immediate expression expected");
4883 return FAIL;
4887 static void
4888 do_arit (str)
4889 char * str;
4891 skip_whitespace (str);
4893 if (reg_required_here (&str, 12) == FAIL
4894 || skip_past_comma (&str) == FAIL
4895 || reg_required_here (&str, 16) == FAIL
4896 || skip_past_comma (&str) == FAIL
4897 || data_op2 (&str) == FAIL)
4899 if (!inst.error)
4900 inst.error = BAD_ARGS;
4901 return;
4904 end_of_line (str);
4905 return;
4908 static void
4909 do_adr (str)
4910 char * str;
4912 /* This is a pseudo-op of the form "adr rd, label" to be converted
4913 into a relative address of the form "add rd, pc, #label-.-8". */
4914 skip_whitespace (str);
4916 if (reg_required_here (&str, 12) == FAIL
4917 || skip_past_comma (&str) == FAIL
4918 || my_get_expression (&inst.reloc.exp, &str))
4920 if (!inst.error)
4921 inst.error = BAD_ARGS;
4922 return;
4925 /* Frag hacking will turn this into a sub instruction if the offset turns
4926 out to be negative. */
4927 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
4928 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust. */
4929 inst.reloc.pc_rel = 1;
4931 end_of_line (str);
4934 static void
4935 do_adrl (str)
4936 char * str;
4938 /* This is a pseudo-op of the form "adrl rd, label" to be converted
4939 into a relative address of the form:
4940 add rd, pc, #low(label-.-8)"
4941 add rd, rd, #high(label-.-8)" */
4943 skip_whitespace (str);
4945 if (reg_required_here (&str, 12) == FAIL
4946 || skip_past_comma (&str) == FAIL
4947 || my_get_expression (&inst.reloc.exp, &str))
4949 if (!inst.error)
4950 inst.error = BAD_ARGS;
4952 return;
4955 end_of_line (str);
4956 /* Frag hacking will turn this into a sub instruction if the offset turns
4957 out to be negative. */
4958 inst.reloc.type = BFD_RELOC_ARM_ADRL_IMMEDIATE;
4959 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust */
4960 inst.reloc.pc_rel = 1;
4961 inst.size = INSN_SIZE * 2;
4963 return;
4966 static void
4967 do_cmp (str)
4968 char * str;
4970 skip_whitespace (str);
4972 if (reg_required_here (&str, 16) == FAIL)
4974 if (!inst.error)
4975 inst.error = BAD_ARGS;
4976 return;
4979 if (skip_past_comma (&str) == FAIL
4980 || data_op2 (&str) == FAIL)
4982 if (!inst.error)
4983 inst.error = BAD_ARGS;
4984 return;
4987 end_of_line (str);
4988 return;
4991 static void
4992 do_mov (str)
4993 char * str;
4995 skip_whitespace (str);
4997 if (reg_required_here (&str, 12) == FAIL)
4999 if (!inst.error)
5000 inst.error = BAD_ARGS;
5001 return;
5004 if (skip_past_comma (&str) == FAIL
5005 || data_op2 (&str) == FAIL)
5007 if (!inst.error)
5008 inst.error = BAD_ARGS;
5009 return;
5012 end_of_line (str);
5013 return;
5016 static int
5017 ldst_extend (str)
5018 char ** str;
5020 int add = INDEX_UP;
5022 switch (**str)
5024 case '#':
5025 case '$':
5026 (*str)++;
5027 if (my_get_expression (& inst.reloc.exp, str))
5028 return FAIL;
5030 if (inst.reloc.exp.X_op == O_constant)
5032 int value = inst.reloc.exp.X_add_number;
5034 if (value < -4095 || value > 4095)
5036 inst.error = _("address offset too large");
5037 return FAIL;
5040 if (value < 0)
5042 value = -value;
5043 add = 0;
5046 inst.instruction |= add | value;
5048 else
5050 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
5051 inst.reloc.pc_rel = 0;
5053 return SUCCESS;
5055 case '-':
5056 add = 0;
5057 /* Fall through. */
5059 case '+':
5060 (*str)++;
5061 /* Fall through. */
5063 default:
5064 if (reg_required_here (str, 0) == FAIL)
5065 return FAIL;
5067 inst.instruction |= add | OFFSET_REG;
5068 if (skip_past_comma (str) == SUCCESS)
5069 return decode_shift (str, SHIFT_RESTRICT);
5071 return SUCCESS;
5075 static void
5076 do_ldst (str)
5077 char * str;
5079 int pre_inc = 0;
5080 int conflict_reg;
5081 int value;
5083 skip_whitespace (str);
5085 if ((conflict_reg = reg_required_here (&str, 12)) == FAIL)
5087 if (!inst.error)
5088 inst.error = BAD_ARGS;
5089 return;
5092 if (skip_past_comma (&str) == FAIL)
5094 inst.error = _("address expected");
5095 return;
5098 if (*str == '[')
5100 int reg;
5102 str++;
5104 skip_whitespace (str);
5106 if ((reg = reg_required_here (&str, 16)) == FAIL)
5107 return;
5109 /* Conflicts can occur on stores as well as loads. */
5110 conflict_reg = (conflict_reg == reg);
5112 skip_whitespace (str);
5114 if (*str == ']')
5116 str ++;
5118 if (skip_past_comma (&str) == SUCCESS)
5120 /* [Rn],... (post inc) */
5121 if (ldst_extend (&str) == FAIL)
5122 return;
5123 if (conflict_reg)
5124 as_warn (_("%s register same as write-back base"),
5125 ((inst.instruction & LOAD_BIT)
5126 ? _("destination") : _("source")));
5128 else
5130 /* [Rn] */
5131 skip_whitespace (str);
5133 if (*str == '!')
5135 if (conflict_reg)
5136 as_warn (_("%s register same as write-back base"),
5137 ((inst.instruction & LOAD_BIT)
5138 ? _("destination") : _("source")));
5139 str++;
5140 inst.instruction |= WRITE_BACK;
5143 inst.instruction |= INDEX_UP;
5144 pre_inc = 1;
5147 else
5149 /* [Rn,...] */
5150 if (skip_past_comma (&str) == FAIL)
5152 inst.error = _("pre-indexed expression expected");
5153 return;
5156 pre_inc = 1;
5157 if (ldst_extend (&str) == FAIL)
5158 return;
5160 skip_whitespace (str);
5162 if (*str++ != ']')
5164 inst.error = _("missing ]");
5165 return;
5168 skip_whitespace (str);
5170 if (*str == '!')
5172 if (conflict_reg)
5173 as_warn (_("%s register same as write-back base"),
5174 ((inst.instruction & LOAD_BIT)
5175 ? _("destination") : _("source")));
5176 str++;
5177 inst.instruction |= WRITE_BACK;
5181 else if (*str == '=')
5183 if ((inst.instruction & LOAD_BIT) == 0)
5185 inst.error = _("invalid pseudo operation");
5186 return;
5189 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
5190 str++;
5192 skip_whitespace (str);
5194 if (my_get_expression (&inst.reloc.exp, &str))
5195 return;
5197 if (inst.reloc.exp.X_op != O_constant
5198 && inst.reloc.exp.X_op != O_symbol)
5200 inst.error = _("constant expression expected");
5201 return;
5204 if (inst.reloc.exp.X_op == O_constant)
5206 value = validate_immediate (inst.reloc.exp.X_add_number);
5208 if (value != FAIL)
5210 /* This can be done with a mov instruction. */
5211 inst.instruction &= LITERAL_MASK;
5212 inst.instruction |= (INST_IMMEDIATE
5213 | (OPCODE_MOV << DATA_OP_SHIFT));
5214 inst.instruction |= value & 0xfff;
5215 end_of_line (str);
5216 return;
5219 value = validate_immediate (~inst.reloc.exp.X_add_number);
5221 if (value != FAIL)
5223 /* This can be done with a mvn instruction. */
5224 inst.instruction &= LITERAL_MASK;
5225 inst.instruction |= (INST_IMMEDIATE
5226 | (OPCODE_MVN << DATA_OP_SHIFT));
5227 inst.instruction |= value & 0xfff;
5228 end_of_line (str);
5229 return;
5233 /* Insert into literal pool. */
5234 if (add_to_lit_pool () == FAIL)
5236 if (!inst.error)
5237 inst.error = _("literal pool insertion failed");
5238 return;
5241 /* Change the instruction exp to point to the pool. */
5242 inst.reloc.type = BFD_RELOC_ARM_LITERAL;
5243 inst.reloc.pc_rel = 1;
5244 inst.instruction |= (REG_PC << 16);
5245 pre_inc = 1;
5247 else
5249 if (my_get_expression (&inst.reloc.exp, &str))
5250 return;
5252 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
5253 #ifndef TE_WINCE
5254 /* PC rel adjust. */
5255 inst.reloc.exp.X_add_number -= 8;
5256 #endif
5257 inst.reloc.pc_rel = 1;
5258 inst.instruction |= (REG_PC << 16);
5259 pre_inc = 1;
5262 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
5263 end_of_line (str);
5264 return;
5267 static void
5268 do_ldstt (str)
5269 char * str;
5271 int conflict_reg;
5273 skip_whitespace (str);
5275 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
5277 if (!inst.error)
5278 inst.error = BAD_ARGS;
5279 return;
5282 if (skip_past_comma (& str) == FAIL)
5284 inst.error = _("address expected");
5285 return;
5288 if (*str == '[')
5290 int reg;
5292 str++;
5294 skip_whitespace (str);
5296 if ((reg = reg_required_here (&str, 16)) == FAIL)
5297 return;
5299 /* ldrt/strt always use post-indexed addressing, so if the base is
5300 the same as Rd, we warn. */
5301 if (conflict_reg == reg)
5302 as_warn (_("%s register same as write-back base"),
5303 ((inst.instruction & LOAD_BIT)
5304 ? _("destination") : _("source")));
5306 skip_whitespace (str);
5308 if (*str == ']')
5310 str ++;
5312 if (skip_past_comma (&str) == SUCCESS)
5314 /* [Rn],... (post inc) */
5315 if (ldst_extend (&str) == FAIL)
5316 return;
5318 else
5320 /* [Rn] */
5321 skip_whitespace (str);
5323 /* Skip a write-back '!'. */
5324 if (*str == '!')
5325 str++;
5327 inst.instruction |= INDEX_UP;
5330 else
5332 inst.error = _("post-indexed expression expected");
5333 return;
5336 else
5338 inst.error = _("post-indexed expression expected");
5339 return;
5342 end_of_line (str);
5343 return;
5346 static int
5347 ldst_extend_v4 (str)
5348 char ** str;
5350 int add = INDEX_UP;
5352 switch (**str)
5354 case '#':
5355 case '$':
5356 (*str)++;
5357 if (my_get_expression (& inst.reloc.exp, str))
5358 return FAIL;
5360 if (inst.reloc.exp.X_op == O_constant)
5362 int value = inst.reloc.exp.X_add_number;
5364 if (value < -255 || value > 255)
5366 inst.error = _("address offset too large");
5367 return FAIL;
5370 if (value < 0)
5372 value = -value;
5373 add = 0;
5376 /* Halfword and signextension instructions have the
5377 immediate value split across bits 11..8 and bits 3..0. */
5378 inst.instruction |= (add | HWOFFSET_IMM
5379 | ((value >> 4) << 8) | (value & 0xF));
5381 else
5383 inst.instruction |= HWOFFSET_IMM;
5384 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
5385 inst.reloc.pc_rel = 0;
5387 return SUCCESS;
5389 case '-':
5390 add = 0;
5391 /* Fall through. */
5393 case '+':
5394 (*str)++;
5395 /* Fall through. */
5397 default:
5398 if (reg_required_here (str, 0) == FAIL)
5399 return FAIL;
5401 inst.instruction |= add;
5402 return SUCCESS;
5406 /* Halfword and signed-byte load/store operations. */
5407 static void
5408 do_ldstv4 (str)
5409 char * str;
5411 int pre_inc = 0;
5412 int conflict_reg;
5413 int value;
5415 skip_whitespace (str);
5417 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
5419 if (!inst.error)
5420 inst.error = BAD_ARGS;
5421 return;
5424 if (skip_past_comma (& str) == FAIL)
5426 inst.error = _("address expected");
5427 return;
5430 if (*str == '[')
5432 int reg;
5434 str++;
5436 skip_whitespace (str);
5438 if ((reg = reg_required_here (&str, 16)) == FAIL)
5439 return;
5441 /* Conflicts can occur on stores as well as loads. */
5442 conflict_reg = (conflict_reg == reg);
5444 skip_whitespace (str);
5446 if (*str == ']')
5448 str ++;
5450 if (skip_past_comma (&str) == SUCCESS)
5452 /* [Rn],... (post inc) */
5453 if (ldst_extend_v4 (&str) == FAIL)
5454 return;
5455 if (conflict_reg)
5456 as_warn (_("%s register same as write-back base"),
5457 ((inst.instruction & LOAD_BIT)
5458 ? _("destination") : _("source")));
5460 else
5462 /* [Rn] */
5463 inst.instruction |= HWOFFSET_IMM;
5465 skip_whitespace (str);
5467 if (*str == '!')
5469 if (conflict_reg)
5470 as_warn (_("%s register same as write-back base"),
5471 ((inst.instruction & LOAD_BIT)
5472 ? _("destination") : _("source")));
5473 str++;
5474 inst.instruction |= WRITE_BACK;
5477 inst.instruction |= INDEX_UP;
5478 pre_inc = 1;
5481 else
5483 /* [Rn,...] */
5484 if (skip_past_comma (&str) == FAIL)
5486 inst.error = _("pre-indexed expression expected");
5487 return;
5490 pre_inc = 1;
5491 if (ldst_extend_v4 (&str) == FAIL)
5492 return;
5494 skip_whitespace (str);
5496 if (*str++ != ']')
5498 inst.error = _("missing ]");
5499 return;
5502 skip_whitespace (str);
5504 if (*str == '!')
5506 if (conflict_reg)
5507 as_warn (_("%s register same as write-back base"),
5508 ((inst.instruction & LOAD_BIT)
5509 ? _("destination") : _("source")));
5510 str++;
5511 inst.instruction |= WRITE_BACK;
5515 else if (*str == '=')
5517 if ((inst.instruction & LOAD_BIT) == 0)
5519 inst.error = _("invalid pseudo operation");
5520 return;
5523 /* XXX Does this work correctly for half-word/byte ops? */
5524 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
5525 str++;
5527 skip_whitespace (str);
5529 if (my_get_expression (&inst.reloc.exp, &str))
5530 return;
5532 if (inst.reloc.exp.X_op != O_constant
5533 && inst.reloc.exp.X_op != O_symbol)
5535 inst.error = _("constant expression expected");
5536 return;
5539 if (inst.reloc.exp.X_op == O_constant)
5541 value = validate_immediate (inst.reloc.exp.X_add_number);
5543 if (value != FAIL)
5545 /* This can be done with a mov instruction. */
5546 inst.instruction &= LITERAL_MASK;
5547 inst.instruction |= INST_IMMEDIATE | (OPCODE_MOV << DATA_OP_SHIFT);
5548 inst.instruction |= value & 0xfff;
5549 end_of_line (str);
5550 return;
5553 value = validate_immediate (~ inst.reloc.exp.X_add_number);
5555 if (value != FAIL)
5557 /* This can be done with a mvn instruction. */
5558 inst.instruction &= LITERAL_MASK;
5559 inst.instruction |= INST_IMMEDIATE | (OPCODE_MVN << DATA_OP_SHIFT);
5560 inst.instruction |= value & 0xfff;
5561 end_of_line (str);
5562 return;
5566 /* Insert into literal pool. */
5567 if (add_to_lit_pool () == FAIL)
5569 if (!inst.error)
5570 inst.error = _("literal pool insertion failed");
5571 return;
5574 /* Change the instruction exp to point to the pool. */
5575 inst.instruction |= HWOFFSET_IMM;
5576 inst.reloc.type = BFD_RELOC_ARM_HWLITERAL;
5577 inst.reloc.pc_rel = 1;
5578 inst.instruction |= (REG_PC << 16);
5579 pre_inc = 1;
5581 else
5583 if (my_get_expression (&inst.reloc.exp, &str))
5584 return;
5586 inst.instruction |= HWOFFSET_IMM;
5587 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
5588 #ifndef TE_WINCE
5589 /* PC rel adjust. */
5590 inst.reloc.exp.X_add_number -= 8;
5591 #endif
5592 inst.reloc.pc_rel = 1;
5593 inst.instruction |= (REG_PC << 16);
5594 pre_inc = 1;
5597 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
5598 end_of_line (str);
5599 return;
5602 static long
5603 reg_list (strp)
5604 char ** strp;
5606 char * str = * strp;
5607 long range = 0;
5608 int another_range;
5610 /* We come back here if we get ranges concatenated by '+' or '|'. */
5613 another_range = 0;
5615 if (*str == '{')
5617 int in_range = 0;
5618 int cur_reg = -1;
5620 str++;
5623 int reg;
5625 skip_whitespace (str);
5627 if ((reg = reg_required_here (& str, -1)) == FAIL)
5628 return FAIL;
5630 if (in_range)
5632 int i;
5634 if (reg <= cur_reg)
5636 inst.error = _("bad range in register list");
5637 return FAIL;
5640 for (i = cur_reg + 1; i < reg; i++)
5642 if (range & (1 << i))
5643 as_tsktsk
5644 (_("Warning: duplicated register (r%d) in register list"),
5646 else
5647 range |= 1 << i;
5649 in_range = 0;
5652 if (range & (1 << reg))
5653 as_tsktsk (_("Warning: duplicated register (r%d) in register list"),
5654 reg);
5655 else if (reg <= cur_reg)
5656 as_tsktsk (_("Warning: register range not in ascending order"));
5658 range |= 1 << reg;
5659 cur_reg = reg;
5661 while (skip_past_comma (&str) != FAIL
5662 || (in_range = 1, *str++ == '-'));
5663 str--;
5664 skip_whitespace (str);
5666 if (*str++ != '}')
5668 inst.error = _("missing `}'");
5669 return FAIL;
5672 else
5674 expressionS expr;
5676 if (my_get_expression (&expr, &str))
5677 return FAIL;
5679 if (expr.X_op == O_constant)
5681 if (expr.X_add_number
5682 != (expr.X_add_number & 0x0000ffff))
5684 inst.error = _("invalid register mask");
5685 return FAIL;
5688 if ((range & expr.X_add_number) != 0)
5690 int regno = range & expr.X_add_number;
5692 regno &= -regno;
5693 regno = (1 << regno) - 1;
5694 as_tsktsk
5695 (_("Warning: duplicated register (r%d) in register list"),
5696 regno);
5699 range |= expr.X_add_number;
5701 else
5703 if (inst.reloc.type != 0)
5705 inst.error = _("expression too complex");
5706 return FAIL;
5709 memcpy (&inst.reloc.exp, &expr, sizeof (expressionS));
5710 inst.reloc.type = BFD_RELOC_ARM_MULTI;
5711 inst.reloc.pc_rel = 0;
5715 skip_whitespace (str);
5717 if (*str == '|' || *str == '+')
5719 str++;
5720 another_range = 1;
5723 while (another_range);
5725 *strp = str;
5726 return range;
5729 static void
5730 do_ldmstm (str)
5731 char * str;
5733 int base_reg;
5734 long range;
5736 skip_whitespace (str);
5738 if ((base_reg = reg_required_here (&str, 16)) == FAIL)
5739 return;
5741 if (base_reg == REG_PC)
5743 inst.error = _("r15 not allowed as base register");
5744 return;
5747 skip_whitespace (str);
5749 if (*str == '!')
5751 inst.instruction |= WRITE_BACK;
5752 str++;
5755 if (skip_past_comma (&str) == FAIL
5756 || (range = reg_list (&str)) == FAIL)
5758 if (! inst.error)
5759 inst.error = BAD_ARGS;
5760 return;
5763 if (*str == '^')
5765 str++;
5766 inst.instruction |= LDM_TYPE_2_OR_3;
5769 inst.instruction |= range;
5770 end_of_line (str);
5771 return;
5774 static void
5775 do_swi (str)
5776 char * str;
5778 skip_whitespace (str);
5780 /* Allow optional leading '#'. */
5781 if (is_immediate_prefix (*str))
5782 str++;
5784 if (my_get_expression (& inst.reloc.exp, & str))
5785 return;
5787 inst.reloc.type = BFD_RELOC_ARM_SWI;
5788 inst.reloc.pc_rel = 0;
5789 end_of_line (str);
5791 return;
5794 static void
5795 do_swap (str)
5796 char * str;
5798 int reg;
5800 skip_whitespace (str);
5802 if ((reg = reg_required_here (&str, 12)) == FAIL)
5803 return;
5805 if (reg == REG_PC)
5807 inst.error = _("r15 not allowed in swap");
5808 return;
5811 if (skip_past_comma (&str) == FAIL
5812 || (reg = reg_required_here (&str, 0)) == FAIL)
5814 if (!inst.error)
5815 inst.error = BAD_ARGS;
5816 return;
5819 if (reg == REG_PC)
5821 inst.error = _("r15 not allowed in swap");
5822 return;
5825 if (skip_past_comma (&str) == FAIL
5826 || *str++ != '[')
5828 inst.error = BAD_ARGS;
5829 return;
5832 skip_whitespace (str);
5834 if ((reg = reg_required_here (&str, 16)) == FAIL)
5835 return;
5837 if (reg == REG_PC)
5839 inst.error = BAD_PC;
5840 return;
5843 skip_whitespace (str);
5845 if (*str++ != ']')
5847 inst.error = _("missing ]");
5848 return;
5851 end_of_line (str);
5852 return;
5855 static void
5856 do_branch (str)
5857 char * str;
5859 if (my_get_expression (&inst.reloc.exp, &str))
5860 return;
5862 #ifdef OBJ_ELF
5864 char * save_in;
5866 /* ScottB: February 5, 1998 - Check to see of PLT32 reloc
5867 required for the instruction. */
5869 /* arm_parse_reloc () works on input_line_pointer.
5870 We actually want to parse the operands to the branch instruction
5871 passed in 'str'. Save the input pointer and restore it later. */
5872 save_in = input_line_pointer;
5873 input_line_pointer = str;
5874 if (inst.reloc.exp.X_op == O_symbol
5875 && *str == '('
5876 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
5878 inst.reloc.type = BFD_RELOC_ARM_PLT32;
5879 inst.reloc.pc_rel = 0;
5880 /* Modify str to point to after parsed operands, otherwise
5881 end_of_line() will complain about the (PLT) left in str. */
5882 str = input_line_pointer;
5884 else
5886 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
5887 inst.reloc.pc_rel = 1;
5889 input_line_pointer = save_in;
5891 #else
5892 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
5893 inst.reloc.pc_rel = 1;
5894 #endif /* OBJ_ELF */
5896 end_of_line (str);
5897 return;
5900 static void
5901 do_bx (str)
5902 char * str;
5904 int reg;
5906 skip_whitespace (str);
5908 if ((reg = reg_required_here (&str, 0)) == FAIL)
5910 inst.error = BAD_ARGS;
5911 return;
5914 /* Note - it is not illegal to do a "bx pc". Useless, but not illegal. */
5915 if (reg == REG_PC)
5916 as_tsktsk (_("use of r15 in bx in ARM mode is not really useful"));
5918 end_of_line (str);
5921 static void
5922 do_cdp (str)
5923 char * str;
5925 /* Co-processor data operation.
5926 Format: CDP{cond} CP#,<expr>,CRd,CRn,CRm{,<expr>} */
5927 skip_whitespace (str);
5929 if (co_proc_number (&str) == FAIL)
5931 if (!inst.error)
5932 inst.error = BAD_ARGS;
5933 return;
5936 if (skip_past_comma (&str) == FAIL
5937 || cp_opc_expr (&str, 20,4) == FAIL)
5939 if (!inst.error)
5940 inst.error = BAD_ARGS;
5941 return;
5944 if (skip_past_comma (&str) == FAIL
5945 || cp_reg_required_here (&str, 12) == FAIL)
5947 if (!inst.error)
5948 inst.error = BAD_ARGS;
5949 return;
5952 if (skip_past_comma (&str) == FAIL
5953 || cp_reg_required_here (&str, 16) == FAIL)
5955 if (!inst.error)
5956 inst.error = BAD_ARGS;
5957 return;
5960 if (skip_past_comma (&str) == FAIL
5961 || cp_reg_required_here (&str, 0) == FAIL)
5963 if (!inst.error)
5964 inst.error = BAD_ARGS;
5965 return;
5968 if (skip_past_comma (&str) == SUCCESS)
5970 if (cp_opc_expr (&str, 5, 3) == FAIL)
5972 if (!inst.error)
5973 inst.error = BAD_ARGS;
5974 return;
5978 end_of_line (str);
5979 return;
5982 static void
5983 do_lstc (str)
5984 char * str;
5986 /* Co-processor register load/store.
5987 Format: <LDC|STC{cond}[L] CP#,CRd,<address> */
5989 skip_whitespace (str);
5991 if (co_proc_number (&str) == FAIL)
5993 if (!inst.error)
5994 inst.error = BAD_ARGS;
5995 return;
5998 if (skip_past_comma (&str) == FAIL
5999 || cp_reg_required_here (&str, 12) == FAIL)
6001 if (!inst.error)
6002 inst.error = BAD_ARGS;
6003 return;
6006 if (skip_past_comma (&str) == FAIL
6007 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
6009 if (! inst.error)
6010 inst.error = BAD_ARGS;
6011 return;
6014 end_of_line (str);
6015 return;
6018 static void
6019 do_co_reg (str)
6020 char * str;
6022 /* Co-processor register transfer.
6023 Format: <MCR|MRC>{cond} CP#,<expr1>,Rd,CRn,CRm{,<expr2>} */
6025 skip_whitespace (str);
6027 if (co_proc_number (&str) == FAIL)
6029 if (!inst.error)
6030 inst.error = BAD_ARGS;
6031 return;
6034 if (skip_past_comma (&str) == FAIL
6035 || cp_opc_expr (&str, 21, 3) == FAIL)
6037 if (!inst.error)
6038 inst.error = BAD_ARGS;
6039 return;
6042 if (skip_past_comma (&str) == FAIL
6043 || reg_required_here (&str, 12) == FAIL)
6045 if (!inst.error)
6046 inst.error = BAD_ARGS;
6047 return;
6050 if (skip_past_comma (&str) == FAIL
6051 || cp_reg_required_here (&str, 16) == FAIL)
6053 if (!inst.error)
6054 inst.error = BAD_ARGS;
6055 return;
6058 if (skip_past_comma (&str) == FAIL
6059 || cp_reg_required_here (&str, 0) == FAIL)
6061 if (!inst.error)
6062 inst.error = BAD_ARGS;
6063 return;
6066 if (skip_past_comma (&str) == SUCCESS)
6068 if (cp_opc_expr (&str, 5, 3) == FAIL)
6070 if (!inst.error)
6071 inst.error = BAD_ARGS;
6072 return;
6076 end_of_line (str);
6077 return;
6080 static void
6081 do_fpa_ctrl (str)
6082 char * str;
6084 /* FP control registers.
6085 Format: <WFS|RFS|WFC|RFC>{cond} Rn */
6087 skip_whitespace (str);
6089 if (reg_required_here (&str, 12) == FAIL)
6091 if (!inst.error)
6092 inst.error = BAD_ARGS;
6093 return;
6096 end_of_line (str);
6097 return;
6100 static void
6101 do_fpa_ldst (str)
6102 char * str;
6104 skip_whitespace (str);
6106 if (fp_reg_required_here (&str, 12) == FAIL)
6108 if (!inst.error)
6109 inst.error = BAD_ARGS;
6110 return;
6113 if (skip_past_comma (&str) == FAIL
6114 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
6116 if (!inst.error)
6117 inst.error = BAD_ARGS;
6118 return;
6121 end_of_line (str);
6124 static void
6125 do_fpa_ldmstm (str)
6126 char * str;
6128 int num_regs;
6130 skip_whitespace (str);
6132 if (fp_reg_required_here (&str, 12) == FAIL)
6134 if (! inst.error)
6135 inst.error = BAD_ARGS;
6136 return;
6139 /* Get Number of registers to transfer. */
6140 if (skip_past_comma (&str) == FAIL
6141 || my_get_expression (&inst.reloc.exp, &str))
6143 if (! inst.error)
6144 inst.error = _("constant expression expected");
6145 return;
6148 if (inst.reloc.exp.X_op != O_constant)
6150 inst.error = _("constant value required for number of registers");
6151 return;
6154 num_regs = inst.reloc.exp.X_add_number;
6156 if (num_regs < 1 || num_regs > 4)
6158 inst.error = _("number of registers must be in the range [1:4]");
6159 return;
6162 switch (num_regs)
6164 case 1:
6165 inst.instruction |= CP_T_X;
6166 break;
6167 case 2:
6168 inst.instruction |= CP_T_Y;
6169 break;
6170 case 3:
6171 inst.instruction |= CP_T_Y | CP_T_X;
6172 break;
6173 case 4:
6174 break;
6175 default:
6176 abort ();
6179 if (inst.instruction & (CP_T_Pre | CP_T_UD)) /* ea/fd format. */
6181 int reg;
6182 int write_back;
6183 int offset;
6185 /* The instruction specified "ea" or "fd", so we can only accept
6186 [Rn]{!}. The instruction does not really support stacking or
6187 unstacking, so we have to emulate these by setting appropriate
6188 bits and offsets. */
6189 if (skip_past_comma (&str) == FAIL
6190 || *str != '[')
6192 if (! inst.error)
6193 inst.error = BAD_ARGS;
6194 return;
6197 str++;
6198 skip_whitespace (str);
6200 if ((reg = reg_required_here (&str, 16)) == FAIL)
6201 return;
6203 skip_whitespace (str);
6205 if (*str != ']')
6207 inst.error = BAD_ARGS;
6208 return;
6211 str++;
6212 if (*str == '!')
6214 write_back = 1;
6215 str++;
6216 if (reg == REG_PC)
6218 inst.error =
6219 _("r15 not allowed as base register with write-back");
6220 return;
6223 else
6224 write_back = 0;
6226 if (inst.instruction & CP_T_Pre)
6228 /* Pre-decrement. */
6229 offset = 3 * num_regs;
6230 if (write_back)
6231 inst.instruction |= CP_T_WB;
6233 else
6235 /* Post-increment. */
6236 if (write_back)
6238 inst.instruction |= CP_T_WB;
6239 offset = 3 * num_regs;
6241 else
6243 /* No write-back, so convert this into a standard pre-increment
6244 instruction -- aesthetically more pleasing. */
6245 inst.instruction |= CP_T_Pre | CP_T_UD;
6246 offset = 0;
6250 inst.instruction |= offset;
6252 else if (skip_past_comma (&str) == FAIL
6253 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
6255 if (! inst.error)
6256 inst.error = BAD_ARGS;
6257 return;
6260 end_of_line (str);
6263 static void
6264 do_fpa_dyadic (str)
6265 char * str;
6267 skip_whitespace (str);
6269 if (fp_reg_required_here (&str, 12) == FAIL)
6271 if (! inst.error)
6272 inst.error = BAD_ARGS;
6273 return;
6276 if (skip_past_comma (&str) == FAIL
6277 || fp_reg_required_here (&str, 16) == FAIL)
6279 if (! inst.error)
6280 inst.error = BAD_ARGS;
6281 return;
6284 if (skip_past_comma (&str) == FAIL
6285 || fp_op2 (&str) == FAIL)
6287 if (! inst.error)
6288 inst.error = BAD_ARGS;
6289 return;
6292 end_of_line (str);
6293 return;
6296 static void
6297 do_fpa_monadic (str)
6298 char * str;
6300 skip_whitespace (str);
6302 if (fp_reg_required_here (&str, 12) == FAIL)
6304 if (! inst.error)
6305 inst.error = BAD_ARGS;
6306 return;
6309 if (skip_past_comma (&str) == FAIL
6310 || fp_op2 (&str) == FAIL)
6312 if (! inst.error)
6313 inst.error = BAD_ARGS;
6314 return;
6317 end_of_line (str);
6318 return;
6321 static void
6322 do_fpa_cmp (str)
6323 char * str;
6325 skip_whitespace (str);
6327 if (fp_reg_required_here (&str, 16) == FAIL)
6329 if (! inst.error)
6330 inst.error = BAD_ARGS;
6331 return;
6334 if (skip_past_comma (&str) == FAIL
6335 || fp_op2 (&str) == FAIL)
6337 if (! inst.error)
6338 inst.error = BAD_ARGS;
6339 return;
6342 end_of_line (str);
6343 return;
6346 static void
6347 do_fpa_from_reg (str)
6348 char * str;
6350 skip_whitespace (str);
6352 if (fp_reg_required_here (&str, 16) == FAIL)
6354 if (! inst.error)
6355 inst.error = BAD_ARGS;
6356 return;
6359 if (skip_past_comma (&str) == FAIL
6360 || reg_required_here (&str, 12) == FAIL)
6362 if (! inst.error)
6363 inst.error = BAD_ARGS;
6364 return;
6367 end_of_line (str);
6368 return;
6371 static void
6372 do_fpa_to_reg (str)
6373 char * str;
6375 skip_whitespace (str);
6377 if (reg_required_here (&str, 12) == FAIL)
6378 return;
6380 if (skip_past_comma (&str) == FAIL
6381 || fp_reg_required_here (&str, 0) == FAIL)
6383 if (! inst.error)
6384 inst.error = BAD_ARGS;
6385 return;
6388 end_of_line (str);
6389 return;
6392 static int
6393 vfp_sp_reg_required_here (str, pos)
6394 char **str;
6395 enum vfp_sp_reg_pos pos;
6397 int reg;
6398 char *start = *str;
6400 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_SN].htab)) != FAIL)
6402 switch (pos)
6404 case VFP_REG_Sd:
6405 inst.instruction |= ((reg >> 1) << 12) | ((reg & 1) << 22);
6406 break;
6408 case VFP_REG_Sn:
6409 inst.instruction |= ((reg >> 1) << 16) | ((reg & 1) << 7);
6410 break;
6412 case VFP_REG_Sm:
6413 inst.instruction |= ((reg >> 1) << 0) | ((reg & 1) << 5);
6414 break;
6416 default:
6417 abort ();
6419 return reg;
6422 /* In the few cases where we might be able to accept something else
6423 this error can be overridden. */
6424 inst.error = _(all_reg_maps[REG_TYPE_SN].expected);
6426 /* Restore the start point. */
6427 *str = start;
6428 return FAIL;
6431 static int
6432 vfp_dp_reg_required_here (str, pos)
6433 char **str;
6434 enum vfp_dp_reg_pos pos;
6436 int reg;
6437 char *start = *str;
6439 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_DN].htab)) != FAIL)
6441 switch (pos)
6443 case VFP_REG_Dd:
6444 inst.instruction |= reg << 12;
6445 break;
6447 case VFP_REG_Dn:
6448 inst.instruction |= reg << 16;
6449 break;
6451 case VFP_REG_Dm:
6452 inst.instruction |= reg << 0;
6453 break;
6455 default:
6456 abort ();
6458 return reg;
6461 /* In the few cases where we might be able to accept something else
6462 this error can be overridden. */
6463 inst.error = _(all_reg_maps[REG_TYPE_DN].expected);
6465 /* Restore the start point. */
6466 *str = start;
6467 return FAIL;
6470 static void
6471 do_vfp_sp_monadic (str)
6472 char *str;
6474 skip_whitespace (str);
6476 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
6477 return;
6479 if (skip_past_comma (&str) == FAIL
6480 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
6482 if (! inst.error)
6483 inst.error = BAD_ARGS;
6484 return;
6487 end_of_line (str);
6488 return;
6491 static void
6492 do_vfp_dp_monadic (str)
6493 char *str;
6495 skip_whitespace (str);
6497 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
6498 return;
6500 if (skip_past_comma (&str) == FAIL
6501 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
6503 if (! inst.error)
6504 inst.error = BAD_ARGS;
6505 return;
6508 end_of_line (str);
6509 return;
6512 static void
6513 do_vfp_sp_dyadic (str)
6514 char *str;
6516 skip_whitespace (str);
6518 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
6519 return;
6521 if (skip_past_comma (&str) == FAIL
6522 || vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL
6523 || skip_past_comma (&str) == FAIL
6524 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
6526 if (! inst.error)
6527 inst.error = BAD_ARGS;
6528 return;
6531 end_of_line (str);
6532 return;
6535 static void
6536 do_vfp_dp_dyadic (str)
6537 char *str;
6539 skip_whitespace (str);
6541 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
6542 return;
6544 if (skip_past_comma (&str) == FAIL
6545 || vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL
6546 || skip_past_comma (&str) == FAIL
6547 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
6549 if (! inst.error)
6550 inst.error = BAD_ARGS;
6551 return;
6554 end_of_line (str);
6555 return;
6558 static void
6559 do_vfp_reg_from_sp (str)
6560 char *str;
6562 skip_whitespace (str);
6564 if (reg_required_here (&str, 12) == FAIL)
6565 return;
6567 if (skip_past_comma (&str) == FAIL
6568 || vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL)
6570 if (! inst.error)
6571 inst.error = BAD_ARGS;
6572 return;
6575 end_of_line (str);
6576 return;
6579 static void
6580 do_vfp_sp_reg2 (str)
6581 char *str;
6583 skip_whitespace (str);
6585 if (reg_required_here (&str, 12) == FAIL)
6586 return;
6588 if (skip_past_comma (&str) == FAIL
6589 || reg_required_here (&str, 16) == FAIL
6590 || skip_past_comma (&str) == FAIL)
6592 if (! inst.error)
6593 inst.error = BAD_ARGS;
6594 return;
6597 /* We require exactly two consecutive SP registers. */
6598 if (vfp_sp_reg_list (&str, VFP_REG_Sm) != 2)
6600 if (! inst.error)
6601 inst.error = _("only two consecutive VFP SP registers allowed here");
6604 end_of_line (str);
6605 return;
6608 static void
6609 do_vfp_sp_from_reg (str)
6610 char *str;
6612 skip_whitespace (str);
6614 if (vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL)
6615 return;
6617 if (skip_past_comma (&str) == FAIL
6618 || reg_required_here (&str, 12) == FAIL)
6620 if (! inst.error)
6621 inst.error = BAD_ARGS;
6622 return;
6625 end_of_line (str);
6626 return;
6629 static void
6630 do_vfp_reg_from_dp (str)
6631 char *str;
6633 skip_whitespace (str);
6635 if (reg_required_here (&str, 12) == FAIL)
6636 return;
6638 if (skip_past_comma (&str) == FAIL
6639 || vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL)
6641 if (! inst.error)
6642 inst.error = BAD_ARGS;
6643 return;
6646 end_of_line (str);
6647 return;
6650 static void
6651 do_vfp_reg2_from_dp (str)
6652 char *str;
6654 skip_whitespace (str);
6656 if (reg_required_here (&str, 12) == FAIL)
6657 return;
6659 if (skip_past_comma (&str) == FAIL
6660 || reg_required_here (&str, 16) == FAIL
6661 || skip_past_comma (&str) == FAIL
6662 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
6664 if (! inst.error)
6665 inst.error = BAD_ARGS;
6666 return;
6669 end_of_line (str);
6670 return;
6673 static void
6674 do_vfp_dp_from_reg (str)
6675 char *str;
6677 skip_whitespace (str);
6679 if (vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL)
6680 return;
6682 if (skip_past_comma (&str) == FAIL
6683 || reg_required_here (&str, 12) == FAIL)
6685 if (! inst.error)
6686 inst.error = BAD_ARGS;
6687 return;
6690 end_of_line (str);
6691 return;
6694 static void
6695 do_vfp_dp_from_reg2 (str)
6696 char *str;
6698 skip_whitespace (str);
6700 if (vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
6701 return;
6703 if (skip_past_comma (&str) == FAIL
6704 || reg_required_here (&str, 12) == FAIL
6705 || skip_past_comma (&str) == FAIL
6706 || reg_required_here (&str, 16))
6708 if (! inst.error)
6709 inst.error = BAD_ARGS;
6710 return;
6713 end_of_line (str);
6714 return;
6717 static const struct vfp_reg *
6718 vfp_psr_parse (str)
6719 char **str;
6721 char *start = *str;
6722 char c;
6723 char *p;
6724 const struct vfp_reg *vreg;
6726 p = start;
6728 /* Find the end of the current token. */
6731 c = *p++;
6733 while (ISALPHA (c));
6735 /* Mark it. */
6736 *--p = 0;
6738 for (vreg = vfp_regs + 0;
6739 vreg < vfp_regs + sizeof (vfp_regs) / sizeof (struct vfp_reg);
6740 vreg++)
6742 if (strcmp (start, vreg->name) == 0)
6744 *p = c;
6745 *str = p;
6746 return vreg;
6750 *p = c;
6751 return NULL;
6754 static int
6755 vfp_psr_required_here (str)
6756 char **str;
6758 char *start = *str;
6759 const struct vfp_reg *vreg;
6761 vreg = vfp_psr_parse (str);
6763 if (vreg)
6765 inst.instruction |= vreg->regno;
6766 return SUCCESS;
6769 inst.error = _("VFP system register expected");
6771 *str = start;
6772 return FAIL;
6775 static void
6776 do_vfp_reg_from_ctrl (str)
6777 char *str;
6779 skip_whitespace (str);
6781 if (reg_required_here (&str, 12) == FAIL)
6782 return;
6784 if (skip_past_comma (&str) == FAIL
6785 || vfp_psr_required_here (&str) == FAIL)
6787 if (! inst.error)
6788 inst.error = BAD_ARGS;
6789 return;
6792 end_of_line (str);
6793 return;
6796 static void
6797 do_vfp_ctrl_from_reg (str)
6798 char *str;
6800 skip_whitespace (str);
6802 if (vfp_psr_required_here (&str) == FAIL)
6803 return;
6805 if (skip_past_comma (&str) == FAIL
6806 || reg_required_here (&str, 12) == FAIL)
6808 if (! inst.error)
6809 inst.error = BAD_ARGS;
6810 return;
6813 end_of_line (str);
6814 return;
6817 static void
6818 do_vfp_sp_ldst (str)
6819 char *str;
6821 skip_whitespace (str);
6823 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
6825 if (!inst.error)
6826 inst.error = BAD_ARGS;
6827 return;
6830 if (skip_past_comma (&str) == FAIL
6831 || cp_address_required_here (&str, CP_NO_WB) == FAIL)
6833 if (!inst.error)
6834 inst.error = BAD_ARGS;
6835 return;
6838 end_of_line (str);
6839 return;
6842 static void
6843 do_vfp_dp_ldst (str)
6844 char *str;
6846 skip_whitespace (str);
6848 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
6850 if (!inst.error)
6851 inst.error = BAD_ARGS;
6852 return;
6855 if (skip_past_comma (&str) == FAIL
6856 || cp_address_required_here (&str, CP_NO_WB) == FAIL)
6858 if (!inst.error)
6859 inst.error = BAD_ARGS;
6860 return;
6863 end_of_line (str);
6864 return;
6867 /* Parse and encode a VFP SP register list, storing the initial
6868 register in position POS and returning the range as the result. If
6869 the string is invalid return FAIL (an invalid range). */
6870 static long
6871 vfp_sp_reg_list (str, pos)
6872 char **str;
6873 enum vfp_sp_reg_pos pos;
6875 long range = 0;
6876 int base_reg = 0;
6877 int new_base;
6878 long base_bits = 0;
6879 int count = 0;
6880 long tempinst;
6881 unsigned long mask = 0;
6882 int warned = 0;
6884 if (**str != '{')
6885 return FAIL;
6887 (*str)++;
6888 skip_whitespace (*str);
6890 tempinst = inst.instruction;
6894 inst.instruction = 0;
6896 if ((new_base = vfp_sp_reg_required_here (str, pos)) == FAIL)
6897 return FAIL;
6899 if (count == 0 || base_reg > new_base)
6901 base_reg = new_base;
6902 base_bits = inst.instruction;
6905 if (mask & (1 << new_base))
6907 inst.error = _("invalid register list");
6908 return FAIL;
6911 if ((mask >> new_base) != 0 && ! warned)
6913 as_tsktsk (_("register list not in ascending order"));
6914 warned = 1;
6917 mask |= 1 << new_base;
6918 count++;
6920 skip_whitespace (*str);
6922 if (**str == '-') /* We have the start of a range expression */
6924 int high_range;
6926 (*str)++;
6928 if ((high_range
6929 = arm_reg_parse (str, all_reg_maps[REG_TYPE_SN].htab))
6930 == FAIL)
6932 inst.error = _(all_reg_maps[REG_TYPE_SN].expected);
6933 return FAIL;
6936 if (high_range <= new_base)
6938 inst.error = _("register range not in ascending order");
6939 return FAIL;
6942 for (new_base++; new_base <= high_range; new_base++)
6944 if (mask & (1 << new_base))
6946 inst.error = _("invalid register list");
6947 return FAIL;
6950 mask |= 1 << new_base;
6951 count++;
6955 while (skip_past_comma (str) != FAIL);
6957 if (**str != '}')
6959 inst.error = _("invalid register list");
6960 return FAIL;
6963 (*str)++;
6965 range = count;
6967 /* Sanity check -- should have raised a parse error above. */
6968 if (count == 0 || count > 32)
6969 abort ();
6971 /* Final test -- the registers must be consecutive. */
6972 while (count--)
6974 if ((mask & (1 << base_reg++)) == 0)
6976 inst.error = _("non-contiguous register range");
6977 return FAIL;
6981 inst.instruction = tempinst | base_bits;
6982 return range;
6985 static long
6986 vfp_dp_reg_list (str)
6987 char **str;
6989 long range = 0;
6990 int base_reg = 0;
6991 int new_base;
6992 int count = 0;
6993 long tempinst;
6994 unsigned long mask = 0;
6995 int warned = 0;
6997 if (**str != '{')
6998 return FAIL;
7000 (*str)++;
7001 skip_whitespace (*str);
7003 tempinst = inst.instruction;
7007 inst.instruction = 0;
7009 if ((new_base = vfp_dp_reg_required_here (str, VFP_REG_Dd)) == FAIL)
7010 return FAIL;
7012 if (count == 0 || base_reg > new_base)
7014 base_reg = new_base;
7015 range = inst.instruction;
7018 if (mask & (1 << new_base))
7020 inst.error = _("invalid register list");
7021 return FAIL;
7024 if ((mask >> new_base) != 0 && ! warned)
7026 as_tsktsk (_("register list not in ascending order"));
7027 warned = 1;
7030 mask |= 1 << new_base;
7031 count++;
7033 skip_whitespace (*str);
7035 if (**str == '-') /* We have the start of a range expression */
7037 int high_range;
7039 (*str)++;
7041 if ((high_range
7042 = arm_reg_parse (str, all_reg_maps[REG_TYPE_DN].htab))
7043 == FAIL)
7045 inst.error = _(all_reg_maps[REG_TYPE_DN].expected);
7046 return FAIL;
7049 if (high_range <= new_base)
7051 inst.error = _("register range not in ascending order");
7052 return FAIL;
7055 for (new_base++; new_base <= high_range; new_base++)
7057 if (mask & (1 << new_base))
7059 inst.error = _("invalid register list");
7060 return FAIL;
7063 mask |= 1 << new_base;
7064 count++;
7068 while (skip_past_comma (str) != FAIL);
7070 if (**str != '}')
7072 inst.error = _("invalid register list");
7073 return FAIL;
7076 (*str)++;
7078 range |= 2 * count;
7080 /* Sanity check -- should have raised a parse error above. */
7081 if (count == 0 || count > 16)
7082 abort ();
7084 /* Final test -- the registers must be consecutive. */
7085 while (count--)
7087 if ((mask & (1 << base_reg++)) == 0)
7089 inst.error = _("non-contiguous register range");
7090 return FAIL;
7094 inst.instruction = tempinst;
7095 return range;
7098 static void
7099 vfp_sp_ldstm (str, ldstm_type)
7100 char *str;
7101 enum vfp_ldstm_type ldstm_type;
7103 long range;
7105 skip_whitespace (str);
7107 if (reg_required_here (&str, 16) == FAIL)
7108 return;
7110 skip_whitespace (str);
7112 if (*str == '!')
7114 inst.instruction |= WRITE_BACK;
7115 str++;
7117 else if (ldstm_type != VFP_LDSTMIA)
7119 inst.error = _("this addressing mode requires base-register writeback");
7120 return;
7123 if (skip_past_comma (&str) == FAIL
7124 || (range = vfp_sp_reg_list (&str, VFP_REG_Sd)) == FAIL)
7126 if (!inst.error)
7127 inst.error = BAD_ARGS;
7128 return;
7131 inst.instruction |= range;
7132 end_of_line (str);
7135 static void
7136 vfp_dp_ldstm (str, ldstm_type)
7137 char *str;
7138 enum vfp_ldstm_type ldstm_type;
7140 long range;
7142 skip_whitespace (str);
7144 if (reg_required_here (&str, 16) == FAIL)
7145 return;
7147 skip_whitespace (str);
7149 if (*str == '!')
7151 inst.instruction |= WRITE_BACK;
7152 str++;
7154 else if (ldstm_type != VFP_LDSTMIA && ldstm_type != VFP_LDSTMIAX)
7156 inst.error = _("this addressing mode requires base-register writeback");
7157 return;
7160 if (skip_past_comma (&str) == FAIL
7161 || (range = vfp_dp_reg_list (&str)) == FAIL)
7163 if (!inst.error)
7164 inst.error = BAD_ARGS;
7165 return;
7168 if (ldstm_type == VFP_LDSTMIAX || ldstm_type == VFP_LDSTMDBX)
7169 range += 1;
7171 inst.instruction |= range;
7172 end_of_line (str);
7175 static void
7176 do_vfp_sp_ldstmia (str)
7177 char *str;
7179 vfp_sp_ldstm (str, VFP_LDSTMIA);
7182 static void
7183 do_vfp_sp_ldstmdb (str)
7184 char *str;
7186 vfp_sp_ldstm (str, VFP_LDSTMDB);
7189 static void
7190 do_vfp_dp_ldstmia (str)
7191 char *str;
7193 vfp_dp_ldstm (str, VFP_LDSTMIA);
7196 static void
7197 do_vfp_dp_ldstmdb (str)
7198 char *str;
7200 vfp_dp_ldstm (str, VFP_LDSTMDB);
7203 static void
7204 do_vfp_xp_ldstmia (str)
7205 char *str;
7207 vfp_dp_ldstm (str, VFP_LDSTMIAX);
7210 static void
7211 do_vfp_xp_ldstmdb (str)
7212 char *str;
7214 vfp_dp_ldstm (str, VFP_LDSTMDBX);
7217 static void
7218 do_vfp_sp_compare_z (str)
7219 char *str;
7221 skip_whitespace (str);
7223 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
7225 if (!inst.error)
7226 inst.error = BAD_ARGS;
7227 return;
7230 end_of_line (str);
7231 return;
7234 static void
7235 do_vfp_dp_compare_z (str)
7236 char *str;
7238 skip_whitespace (str);
7240 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
7242 if (!inst.error)
7243 inst.error = BAD_ARGS;
7244 return;
7247 end_of_line (str);
7248 return;
7251 static void
7252 do_vfp_dp_sp_cvt (str)
7253 char *str;
7255 skip_whitespace (str);
7257 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
7258 return;
7260 if (skip_past_comma (&str) == FAIL
7261 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
7263 if (! inst.error)
7264 inst.error = BAD_ARGS;
7265 return;
7268 end_of_line (str);
7269 return;
7272 static void
7273 do_vfp_sp_dp_cvt (str)
7274 char *str;
7276 skip_whitespace (str);
7278 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
7279 return;
7281 if (skip_past_comma (&str) == FAIL
7282 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
7284 if (! inst.error)
7285 inst.error = BAD_ARGS;
7286 return;
7289 end_of_line (str);
7290 return;
7293 /* Thumb specific routines. */
7295 /* Parse and validate that a register is of the right form, this saves
7296 repeated checking of this information in many similar cases.
7297 Unlike the 32-bit case we do not insert the register into the opcode
7298 here, since the position is often unknown until the full instruction
7299 has been parsed. */
7301 static int
7302 thumb_reg (strp, hi_lo)
7303 char ** strp;
7304 int hi_lo;
7306 int reg;
7308 if ((reg = reg_required_here (strp, -1)) == FAIL)
7309 return FAIL;
7311 switch (hi_lo)
7313 case THUMB_REG_LO:
7314 if (reg > 7)
7316 inst.error = _("lo register required");
7317 return FAIL;
7319 break;
7321 case THUMB_REG_HI:
7322 if (reg < 8)
7324 inst.error = _("hi register required");
7325 return FAIL;
7327 break;
7329 default:
7330 break;
7333 return reg;
7336 /* Parse an add or subtract instruction, SUBTRACT is non-zero if the opcode
7337 was SUB. */
7339 static void
7340 thumb_add_sub (str, subtract)
7341 char * str;
7342 int subtract;
7344 int Rd, Rs, Rn = FAIL;
7346 skip_whitespace (str);
7348 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
7349 || skip_past_comma (&str) == FAIL)
7351 if (! inst.error)
7352 inst.error = BAD_ARGS;
7353 return;
7356 if (is_immediate_prefix (*str))
7358 Rs = Rd;
7359 str++;
7360 if (my_get_expression (&inst.reloc.exp, &str))
7361 return;
7363 else
7365 if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
7366 return;
7368 if (skip_past_comma (&str) == FAIL)
7370 /* Two operand format, shuffle the registers
7371 and pretend there are 3. */
7372 Rn = Rs;
7373 Rs = Rd;
7375 else if (is_immediate_prefix (*str))
7377 str++;
7378 if (my_get_expression (&inst.reloc.exp, &str))
7379 return;
7381 else if ((Rn = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
7382 return;
7385 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
7386 for the latter case, EXPR contains the immediate that was found. */
7387 if (Rn != FAIL)
7389 /* All register format. */
7390 if (Rd > 7 || Rs > 7 || Rn > 7)
7392 if (Rs != Rd)
7394 inst.error = _("dest and source1 must be the same register");
7395 return;
7398 /* Can't do this for SUB. */
7399 if (subtract)
7401 inst.error = _("subtract valid only on lo regs");
7402 return;
7405 inst.instruction = (T_OPCODE_ADD_HI
7406 | (Rd > 7 ? THUMB_H1 : 0)
7407 | (Rn > 7 ? THUMB_H2 : 0));
7408 inst.instruction |= (Rd & 7) | ((Rn & 7) << 3);
7410 else
7412 inst.instruction = subtract ? T_OPCODE_SUB_R3 : T_OPCODE_ADD_R3;
7413 inst.instruction |= Rd | (Rs << 3) | (Rn << 6);
7416 else
7418 /* Immediate expression, now things start to get nasty. */
7420 /* First deal with HI regs, only very restricted cases allowed:
7421 Adjusting SP, and using PC or SP to get an address. */
7422 if ((Rd > 7 && (Rd != REG_SP || Rs != REG_SP))
7423 || (Rs > 7 && Rs != REG_SP && Rs != REG_PC))
7425 inst.error = _("invalid Hi register with immediate");
7426 return;
7429 if (inst.reloc.exp.X_op != O_constant)
7431 /* Value isn't known yet, all we can do is store all the fragments
7432 we know about in the instruction and let the reloc hacking
7433 work it all out. */
7434 inst.instruction = (subtract ? 0x8000 : 0) | (Rd << 4) | Rs;
7435 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
7437 else
7439 int offset = inst.reloc.exp.X_add_number;
7441 if (subtract)
7442 offset = - offset;
7444 if (offset < 0)
7446 offset = - offset;
7447 subtract = 1;
7449 /* Quick check, in case offset is MIN_INT. */
7450 if (offset < 0)
7452 inst.error = _("immediate value out of range");
7453 return;
7456 /* Note - you cannot convert a subtract of 0 into an
7457 add of 0 because the carry flag is set differently. */
7458 else if (offset > 0)
7459 subtract = 0;
7461 if (Rd == REG_SP)
7463 if (offset & ~0x1fc)
7465 inst.error = _("invalid immediate value for stack adjust");
7466 return;
7468 inst.instruction = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
7469 inst.instruction |= offset >> 2;
7471 else if (Rs == REG_PC || Rs == REG_SP)
7473 if (subtract
7474 || (offset & ~0x3fc))
7476 inst.error = _("invalid immediate for address calculation");
7477 return;
7479 inst.instruction = (Rs == REG_PC ? T_OPCODE_ADD_PC
7480 : T_OPCODE_ADD_SP);
7481 inst.instruction |= (Rd << 8) | (offset >> 2);
7483 else if (Rs == Rd)
7485 if (offset & ~0xff)
7487 inst.error = _("immediate value out of range");
7488 return;
7490 inst.instruction = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
7491 inst.instruction |= (Rd << 8) | offset;
7493 else
7495 if (offset & ~0x7)
7497 inst.error = _("immediate value out of range");
7498 return;
7500 inst.instruction = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
7501 inst.instruction |= Rd | (Rs << 3) | (offset << 6);
7506 end_of_line (str);
7509 static void
7510 thumb_shift (str, shift)
7511 char * str;
7512 int shift;
7514 int Rd, Rs, Rn = FAIL;
7516 skip_whitespace (str);
7518 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
7519 || skip_past_comma (&str) == FAIL)
7521 if (! inst.error)
7522 inst.error = BAD_ARGS;
7523 return;
7526 if (is_immediate_prefix (*str))
7528 /* Two operand immediate format, set Rs to Rd. */
7529 Rs = Rd;
7530 str ++;
7531 if (my_get_expression (&inst.reloc.exp, &str))
7532 return;
7534 else
7536 if ((Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
7537 return;
7539 if (skip_past_comma (&str) == FAIL)
7541 /* Two operand format, shuffle the registers
7542 and pretend there are 3. */
7543 Rn = Rs;
7544 Rs = Rd;
7546 else if (is_immediate_prefix (*str))
7548 str++;
7549 if (my_get_expression (&inst.reloc.exp, &str))
7550 return;
7552 else if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
7553 return;
7556 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
7557 for the latter case, EXPR contains the immediate that was found. */
7559 if (Rn != FAIL)
7561 if (Rs != Rd)
7563 inst.error = _("source1 and dest must be same register");
7564 return;
7567 switch (shift)
7569 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_R; break;
7570 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_R; break;
7571 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_R; break;
7574 inst.instruction |= Rd | (Rn << 3);
7576 else
7578 switch (shift)
7580 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_I; break;
7581 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_I; break;
7582 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_I; break;
7585 if (inst.reloc.exp.X_op != O_constant)
7587 /* Value isn't known yet, create a dummy reloc and let reloc
7588 hacking fix it up. */
7589 inst.reloc.type = BFD_RELOC_ARM_THUMB_SHIFT;
7591 else
7593 unsigned shift_value = inst.reloc.exp.X_add_number;
7595 if (shift_value > 32 || (shift_value == 32 && shift == THUMB_LSL))
7597 inst.error = _("invalid immediate for shift");
7598 return;
7601 /* Shifts of zero are handled by converting to LSL. */
7602 if (shift_value == 0)
7603 inst.instruction = T_OPCODE_LSL_I;
7605 /* Shifts of 32 are encoded as a shift of zero. */
7606 if (shift_value == 32)
7607 shift_value = 0;
7609 inst.instruction |= shift_value << 6;
7612 inst.instruction |= Rd | (Rs << 3);
7615 end_of_line (str);
7618 static void
7619 thumb_mov_compare (str, move)
7620 char * str;
7621 int move;
7623 int Rd, Rs = FAIL;
7625 skip_whitespace (str);
7627 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
7628 || skip_past_comma (&str) == FAIL)
7630 if (! inst.error)
7631 inst.error = BAD_ARGS;
7632 return;
7635 if (is_immediate_prefix (*str))
7637 str++;
7638 if (my_get_expression (&inst.reloc.exp, &str))
7639 return;
7641 else if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
7642 return;
7644 if (Rs != FAIL)
7646 if (Rs < 8 && Rd < 8)
7648 if (move == THUMB_MOVE)
7649 /* A move of two lowregs is encoded as ADD Rd, Rs, #0
7650 since a MOV instruction produces unpredictable results. */
7651 inst.instruction = T_OPCODE_ADD_I3;
7652 else
7653 inst.instruction = T_OPCODE_CMP_LR;
7654 inst.instruction |= Rd | (Rs << 3);
7656 else
7658 if (move == THUMB_MOVE)
7659 inst.instruction = T_OPCODE_MOV_HR;
7660 else
7661 inst.instruction = T_OPCODE_CMP_HR;
7663 if (Rd > 7)
7664 inst.instruction |= THUMB_H1;
7666 if (Rs > 7)
7667 inst.instruction |= THUMB_H2;
7669 inst.instruction |= (Rd & 7) | ((Rs & 7) << 3);
7672 else
7674 if (Rd > 7)
7676 inst.error = _("only lo regs allowed with immediate");
7677 return;
7680 if (move == THUMB_MOVE)
7681 inst.instruction = T_OPCODE_MOV_I8;
7682 else
7683 inst.instruction = T_OPCODE_CMP_I8;
7685 inst.instruction |= Rd << 8;
7687 if (inst.reloc.exp.X_op != O_constant)
7688 inst.reloc.type = BFD_RELOC_ARM_THUMB_IMM;
7689 else
7691 unsigned value = inst.reloc.exp.X_add_number;
7693 if (value > 255)
7695 inst.error = _("invalid immediate");
7696 return;
7699 inst.instruction |= value;
7703 end_of_line (str);
7706 static void
7707 thumb_load_store (str, load_store, size)
7708 char * str;
7709 int load_store;
7710 int size;
7712 int Rd, Rb, Ro = FAIL;
7714 skip_whitespace (str);
7716 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
7717 || skip_past_comma (&str) == FAIL)
7719 if (! inst.error)
7720 inst.error = BAD_ARGS;
7721 return;
7724 if (*str == '[')
7726 str++;
7727 if ((Rb = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
7728 return;
7730 if (skip_past_comma (&str) != FAIL)
7732 if (is_immediate_prefix (*str))
7734 str++;
7735 if (my_get_expression (&inst.reloc.exp, &str))
7736 return;
7738 else if ((Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
7739 return;
7741 else
7743 inst.reloc.exp.X_op = O_constant;
7744 inst.reloc.exp.X_add_number = 0;
7747 if (*str != ']')
7749 inst.error = _("expected ']'");
7750 return;
7752 str++;
7754 else if (*str == '=')
7756 if (load_store != THUMB_LOAD)
7758 inst.error = _("invalid pseudo operation");
7759 return;
7762 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
7763 str++;
7765 skip_whitespace (str);
7767 if (my_get_expression (& inst.reloc.exp, & str))
7768 return;
7770 end_of_line (str);
7772 if ( inst.reloc.exp.X_op != O_constant
7773 && inst.reloc.exp.X_op != O_symbol)
7775 inst.error = "Constant expression expected";
7776 return;
7779 if (inst.reloc.exp.X_op == O_constant
7780 && ((inst.reloc.exp.X_add_number & ~0xFF) == 0))
7782 /* This can be done with a mov instruction. */
7784 inst.instruction = T_OPCODE_MOV_I8 | (Rd << 8);
7785 inst.instruction |= inst.reloc.exp.X_add_number;
7786 return;
7789 /* Insert into literal pool. */
7790 if (add_to_lit_pool () == FAIL)
7792 if (!inst.error)
7793 inst.error = "literal pool insertion failed";
7794 return;
7797 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
7798 inst.reloc.pc_rel = 1;
7799 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
7800 /* Adjust ARM pipeline offset to Thumb. */
7801 inst.reloc.exp.X_add_number += 4;
7803 return;
7805 else
7807 if (my_get_expression (&inst.reloc.exp, &str))
7808 return;
7810 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
7811 inst.reloc.pc_rel = 1;
7812 inst.reloc.exp.X_add_number -= 4; /* Pipeline offset. */
7813 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
7814 end_of_line (str);
7815 return;
7818 if (Rb == REG_PC || Rb == REG_SP)
7820 if (size != THUMB_WORD)
7822 inst.error = _("byte or halfword not valid for base register");
7823 return;
7825 else if (Rb == REG_PC && load_store != THUMB_LOAD)
7827 inst.error = _("r15 based store not allowed");
7828 return;
7830 else if (Ro != FAIL)
7832 inst.error = _("invalid base register for register offset");
7833 return;
7836 if (Rb == REG_PC)
7837 inst.instruction = T_OPCODE_LDR_PC;
7838 else if (load_store == THUMB_LOAD)
7839 inst.instruction = T_OPCODE_LDR_SP;
7840 else
7841 inst.instruction = T_OPCODE_STR_SP;
7843 inst.instruction |= Rd << 8;
7844 if (inst.reloc.exp.X_op == O_constant)
7846 unsigned offset = inst.reloc.exp.X_add_number;
7848 if (offset & ~0x3fc)
7850 inst.error = _("invalid offset");
7851 return;
7854 inst.instruction |= offset >> 2;
7856 else
7857 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
7859 else if (Rb > 7)
7861 inst.error = _("invalid base register in load/store");
7862 return;
7864 else if (Ro == FAIL)
7866 /* Immediate offset. */
7867 if (size == THUMB_WORD)
7868 inst.instruction = (load_store == THUMB_LOAD
7869 ? T_OPCODE_LDR_IW : T_OPCODE_STR_IW);
7870 else if (size == THUMB_HALFWORD)
7871 inst.instruction = (load_store == THUMB_LOAD
7872 ? T_OPCODE_LDR_IH : T_OPCODE_STR_IH);
7873 else
7874 inst.instruction = (load_store == THUMB_LOAD
7875 ? T_OPCODE_LDR_IB : T_OPCODE_STR_IB);
7877 inst.instruction |= Rd | (Rb << 3);
7879 if (inst.reloc.exp.X_op == O_constant)
7881 unsigned offset = inst.reloc.exp.X_add_number;
7883 if (offset & ~(0x1f << size))
7885 inst.error = _("invalid offset");
7886 return;
7888 inst.instruction |= (offset >> size) << 6;
7890 else
7891 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
7893 else
7895 /* Register offset. */
7896 if (size == THUMB_WORD)
7897 inst.instruction = (load_store == THUMB_LOAD
7898 ? T_OPCODE_LDR_RW : T_OPCODE_STR_RW);
7899 else if (size == THUMB_HALFWORD)
7900 inst.instruction = (load_store == THUMB_LOAD
7901 ? T_OPCODE_LDR_RH : T_OPCODE_STR_RH);
7902 else
7903 inst.instruction = (load_store == THUMB_LOAD
7904 ? T_OPCODE_LDR_RB : T_OPCODE_STR_RB);
7906 inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
7909 end_of_line (str);
7912 /* A register must be given at this point.
7914 Shift is the place to put it in inst.instruction.
7916 Restores input start point on err.
7917 Returns the reg#, or FAIL. */
7919 static int
7920 mav_reg_required_here (str, shift, regtype)
7921 char ** str;
7922 int shift;
7923 enum arm_reg_type regtype;
7925 int reg;
7926 char *start = *str;
7928 if ((reg = arm_reg_parse (str, all_reg_maps[regtype].htab)) != FAIL)
7930 if (shift >= 0)
7931 inst.instruction |= reg << shift;
7933 return reg;
7936 /* Restore the start point. */
7937 *str = start;
7939 /* In the few cases where we might be able to accept something else
7940 this error can be overridden. */
7941 inst.error = _(all_reg_maps[regtype].expected);
7943 return FAIL;
7946 /* Cirrus Maverick Instructions. */
7948 /* Wrapper functions. */
7950 static void
7951 do_mav_binops_1a (str)
7952 char * str;
7954 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVF);
7957 static void
7958 do_mav_binops_1b (str)
7959 char * str;
7961 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVD);
7964 static void
7965 do_mav_binops_1c (str)
7966 char * str;
7968 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVDX);
7971 static void
7972 do_mav_binops_1d (str)
7973 char * str;
7975 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVF);
7978 static void
7979 do_mav_binops_1e (str)
7980 char * str;
7982 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVD);
7985 static void
7986 do_mav_binops_1f (str)
7987 char * str;
7989 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVF);
7992 static void
7993 do_mav_binops_1g (str)
7994 char * str;
7996 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVD);
7999 static void
8000 do_mav_binops_1h (str)
8001 char * str;
8003 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVFX);
8006 static void
8007 do_mav_binops_1i (str)
8008 char * str;
8010 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVFX);
8013 static void
8014 do_mav_binops_1j (str)
8015 char * str;
8017 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVDX);
8020 static void
8021 do_mav_binops_1k (str)
8022 char * str;
8024 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVDX);
8027 static void
8028 do_mav_binops_1l (str)
8029 char * str;
8031 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVF);
8034 static void
8035 do_mav_binops_1m (str)
8036 char * str;
8038 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVD);
8041 static void
8042 do_mav_binops_1n (str)
8043 char * str;
8045 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVFX);
8048 static void
8049 do_mav_binops_1o (str)
8050 char * str;
8052 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVDX, REG_TYPE_MVDX);
8055 static void
8056 do_mav_binops_2a (str)
8057 char * str;
8059 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVF, REG_TYPE_RN);
8062 static void
8063 do_mav_binops_2b (str)
8064 char * str;
8066 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVD, REG_TYPE_RN);
8069 static void
8070 do_mav_binops_2c (str)
8071 char * str;
8073 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVDX, REG_TYPE_RN);
8076 static void
8077 do_mav_binops_3a (str)
8078 char * str;
8080 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVAX, REG_TYPE_MVFX);
8083 static void
8084 do_mav_binops_3b (str)
8085 char * str;
8087 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVFX, REG_TYPE_MVAX);
8090 static void
8091 do_mav_binops_3c (str)
8092 char * str;
8094 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVAX, REG_TYPE_MVDX);
8097 static void
8098 do_mav_binops_3d (str)
8099 char * str;
8101 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVDX, REG_TYPE_MVAX);
8104 static void
8105 do_mav_triple_4a (str)
8106 char * str;
8108 do_mav_triple (str, MAV_MODE4, REG_TYPE_MVFX, REG_TYPE_MVFX, REG_TYPE_RN);
8111 static void
8112 do_mav_triple_4b (str)
8113 char * str;
8115 do_mav_triple (str, MAV_MODE4, REG_TYPE_MVDX, REG_TYPE_MVDX, REG_TYPE_RN);
8118 static void
8119 do_mav_triple_5a (str)
8120 char * str;
8122 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVF, REG_TYPE_MVF);
8125 static void
8126 do_mav_triple_5b (str)
8127 char * str;
8129 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVD, REG_TYPE_MVD);
8132 static void
8133 do_mav_triple_5c (str)
8134 char * str;
8136 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVFX, REG_TYPE_MVFX);
8139 static void
8140 do_mav_triple_5d (str)
8141 char * str;
8143 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVDX, REG_TYPE_MVDX);
8146 static void
8147 do_mav_triple_5e (str)
8148 char * str;
8150 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVF, REG_TYPE_MVF, REG_TYPE_MVF);
8153 static void
8154 do_mav_triple_5f (str)
8155 char * str;
8157 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVD, REG_TYPE_MVD, REG_TYPE_MVD);
8160 static void
8161 do_mav_triple_5g (str)
8162 char * str;
8164 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVFX, REG_TYPE_MVFX, REG_TYPE_MVFX);
8167 static void
8168 do_mav_triple_5h (str)
8169 char * str;
8171 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVDX, REG_TYPE_MVDX, REG_TYPE_MVDX);
8174 static void
8175 do_mav_quad_6a (str)
8176 char * str;
8178 do_mav_quad (str, MAV_MODE6, REG_TYPE_MVAX, REG_TYPE_MVFX, REG_TYPE_MVFX,
8179 REG_TYPE_MVFX);
8182 static void
8183 do_mav_quad_6b (str)
8184 char * str;
8186 do_mav_quad (str, MAV_MODE6, REG_TYPE_MVAX, REG_TYPE_MVAX, REG_TYPE_MVFX,
8187 REG_TYPE_MVFX);
8190 /* cfmvsc32<cond> DSPSC,MVFX[15:0]. */
8191 static void
8192 do_mav_dspsc_1 (str)
8193 char * str;
8195 skip_whitespace (str);
8197 /* cfmvsc32. */
8198 if (mav_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL
8199 || skip_past_comma (&str) == FAIL
8200 || mav_reg_required_here (&str, 16, REG_TYPE_MVFX) == FAIL)
8202 if (!inst.error)
8203 inst.error = BAD_ARGS;
8205 return;
8208 end_of_line (str);
8211 /* cfmv32sc<cond> MVFX[15:0],DSPSC. */
8212 static void
8213 do_mav_dspsc_2 (str)
8214 char * str;
8216 skip_whitespace (str);
8218 /* cfmv32sc. */
8219 if (mav_reg_required_here (&str, 0, REG_TYPE_MVFX) == FAIL
8220 || skip_past_comma (&str) == FAIL
8221 || mav_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL)
8223 if (!inst.error)
8224 inst.error = BAD_ARGS;
8226 return;
8229 end_of_line (str);
8232 static void
8233 do_mav_shift_1 (str)
8234 char * str;
8236 do_mav_shift (str, REG_TYPE_MVFX, REG_TYPE_MVFX);
8239 static void
8240 do_mav_shift_2 (str)
8241 char * str;
8243 do_mav_shift (str, REG_TYPE_MVDX, REG_TYPE_MVDX);
8246 static void
8247 do_mav_ldst_1 (str)
8248 char * str;
8250 do_mav_ldst (str, REG_TYPE_MVF);
8253 static void
8254 do_mav_ldst_2 (str)
8255 char * str;
8257 do_mav_ldst (str, REG_TYPE_MVD);
8260 static void
8261 do_mav_ldst_3 (str)
8262 char * str;
8264 do_mav_ldst (str, REG_TYPE_MVFX);
8267 static void
8268 do_mav_ldst_4 (str)
8269 char * str;
8271 do_mav_ldst (str, REG_TYPE_MVDX);
8274 /* Isnsn like "foo X,Y". */
8276 static void
8277 do_mav_binops (str, mode, reg0, reg1)
8278 char * str;
8279 int mode;
8280 enum arm_reg_type reg0;
8281 enum arm_reg_type reg1;
8283 int shift0, shift1;
8285 shift0 = mode & 0xff;
8286 shift1 = (mode >> 8) & 0xff;
8288 skip_whitespace (str);
8290 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
8291 || skip_past_comma (&str) == FAIL
8292 || mav_reg_required_here (&str, shift1, reg1) == FAIL)
8294 if (!inst.error)
8295 inst.error = BAD_ARGS;
8297 else
8298 end_of_line (str);
8301 /* Isnsn like "foo X,Y,Z". */
8303 static void
8304 do_mav_triple (str, mode, reg0, reg1, reg2)
8305 char * str;
8306 int mode;
8307 enum arm_reg_type reg0;
8308 enum arm_reg_type reg1;
8309 enum arm_reg_type reg2;
8311 int shift0, shift1, shift2;
8313 shift0 = mode & 0xff;
8314 shift1 = (mode >> 8) & 0xff;
8315 shift2 = (mode >> 16) & 0xff;
8317 skip_whitespace (str);
8319 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
8320 || skip_past_comma (&str) == FAIL
8321 || mav_reg_required_here (&str, shift1, reg1) == FAIL
8322 || skip_past_comma (&str) == FAIL
8323 || mav_reg_required_here (&str, shift2, reg2) == FAIL)
8325 if (!inst.error)
8326 inst.error = BAD_ARGS;
8328 else
8329 end_of_line (str);
8332 /* Isnsn like "foo W,X,Y,Z".
8333 where W=MVAX[0:3] and X,Y,Z=MVFX[0:15]. */
8335 static void
8336 do_mav_quad (str, mode, reg0, reg1, reg2, reg3)
8337 char * str;
8338 int mode;
8339 enum arm_reg_type reg0;
8340 enum arm_reg_type reg1;
8341 enum arm_reg_type reg2;
8342 enum arm_reg_type reg3;
8344 int shift0, shift1, shift2, shift3;
8346 shift0= mode & 0xff;
8347 shift1 = (mode >> 8) & 0xff;
8348 shift2 = (mode >> 16) & 0xff;
8349 shift3 = (mode >> 24) & 0xff;
8351 skip_whitespace (str);
8353 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
8354 || skip_past_comma (&str) == FAIL
8355 || mav_reg_required_here (&str, shift1, reg1) == FAIL
8356 || skip_past_comma (&str) == FAIL
8357 || mav_reg_required_here (&str, shift2, reg2) == FAIL
8358 || skip_past_comma (&str) == FAIL
8359 || mav_reg_required_here (&str, shift3, reg3) == FAIL)
8361 if (!inst.error)
8362 inst.error = BAD_ARGS;
8364 else
8365 end_of_line (str);
8368 /* Maverick shift immediate instructions.
8369 cfsh32<cond> MVFX[15:0],MVFX[15:0],Shift[6:0].
8370 cfsh64<cond> MVDX[15:0],MVDX[15:0],Shift[6:0]. */
8372 static void
8373 do_mav_shift (str, reg0, reg1)
8374 char * str;
8375 enum arm_reg_type reg0;
8376 enum arm_reg_type reg1;
8378 int error;
8379 int imm, neg = 0;
8381 skip_whitespace (str);
8383 error = 0;
8385 if (mav_reg_required_here (&str, 12, reg0) == FAIL
8386 || skip_past_comma (&str) == FAIL
8387 || mav_reg_required_here (&str, 16, reg1) == FAIL
8388 || skip_past_comma (&str) == FAIL)
8390 if (!inst.error)
8391 inst.error = BAD_ARGS;
8392 return;
8395 /* Calculate the immediate operand.
8396 The operand is a 7bit signed number. */
8397 skip_whitespace (str);
8399 if (*str == '#')
8400 ++str;
8402 if (!ISDIGIT (*str) && *str != '-')
8404 inst.error = _("expecting immediate, 7bit operand");
8405 return;
8408 if (*str == '-')
8410 neg = 1;
8411 ++str;
8414 for (imm = 0; *str && ISDIGIT (*str); ++str)
8415 imm = imm * 10 + *str - '0';
8417 if (imm > 64)
8419 inst.error = _("immediate out of range");
8420 return;
8423 /* Make negative imm's into 7bit signed numbers. */
8424 if (neg)
8426 imm = -imm;
8427 imm &= 0x0000007f;
8430 /* Bits 0-3 of the insn should have bits 0-3 of the immediate.
8431 Bits 5-7 of the insn should have bits 4-6 of the immediate.
8432 Bit 4 should be 0. */
8433 imm = (imm & 0xf) | ((imm & 0x70) << 1);
8435 inst.instruction |= imm;
8436 end_of_line (str);
8439 static int
8440 mav_parse_offset (str, negative)
8441 char ** str;
8442 int *negative;
8444 char * p = *str;
8445 int offset;
8447 *negative = 0;
8449 skip_whitespace (p);
8451 if (*p == '#')
8452 ++p;
8454 if (*p == '-')
8456 *negative = 1;
8457 ++p;
8460 if (!ISDIGIT (*p))
8462 inst.error = _("offset expected");
8463 return 0;
8466 for (offset = 0; *p && ISDIGIT (*p); ++p)
8467 offset = offset * 10 + *p - '0';
8469 if (offset > 0xff)
8471 inst.error = _("offset out of range");
8472 return 0;
8475 *str = p;
8477 return *negative ? -offset : offset;
8480 /* Maverick load/store instructions.
8481 <insn><cond> CRd,[Rn,<offset>]{!}.
8482 <insn><cond> CRd,[Rn],<offset>. */
8484 static void
8485 do_mav_ldst (str, reg0)
8486 char * str;
8487 enum arm_reg_type reg0;
8489 int offset, negative;
8491 skip_whitespace (str);
8493 if (mav_reg_required_here (&str, 12, reg0) == FAIL
8494 || skip_past_comma (&str) == FAIL
8495 || *str++ != '['
8496 || reg_required_here (&str, 16) == FAIL)
8497 goto fail_ldst;
8499 if (skip_past_comma (&str) == SUCCESS)
8501 /* You are here: "<offset>]{!}". */
8502 inst.instruction |= PRE_INDEX;
8504 offset = mav_parse_offset (&str, &negative);
8506 if (inst.error)
8507 return;
8509 if (*str++ != ']')
8511 inst.error = _("missing ]");
8512 return;
8515 if (*str == '!')
8517 inst.instruction |= WRITE_BACK;
8518 ++str;
8521 else
8523 /* You are here: "], <offset>". */
8524 if (*str++ != ']')
8526 inst.error = _("missing ]");
8527 return;
8530 if (skip_past_comma (&str) == FAIL
8531 || (offset = mav_parse_offset (&str, &negative), inst.error))
8532 goto fail_ldst;
8534 inst.instruction |= CP_T_WB; /* Post indexed, set bit W. */
8537 if (negative)
8538 offset = -offset;
8539 else
8540 inst.instruction |= CP_T_UD; /* Postive, so set bit U. */
8542 inst.instruction |= offset >> 2;
8543 end_of_line (str);
8544 return;
8546 fail_ldst:
8547 if (!inst.error)
8548 inst.error = BAD_ARGS;
8549 return;
8552 static void
8553 do_t_nop (str)
8554 char * str;
8556 /* Do nothing. */
8557 end_of_line (str);
8558 return;
8561 /* Handle the Format 4 instructions that do not have equivalents in other
8562 formats. That is, ADC, AND, EOR, SBC, ROR, TST, NEG, CMN, ORR, MUL,
8563 BIC and MVN. */
8565 static void
8566 do_t_arit (str)
8567 char * str;
8569 int Rd, Rs, Rn;
8571 skip_whitespace (str);
8573 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
8574 || skip_past_comma (&str) == FAIL
8575 || (Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
8577 inst.error = BAD_ARGS;
8578 return;
8581 if (skip_past_comma (&str) != FAIL)
8583 /* Three operand format not allowed for TST, CMN, NEG and MVN.
8584 (It isn't allowed for CMP either, but that isn't handled by this
8585 function.) */
8586 if (inst.instruction == T_OPCODE_TST
8587 || inst.instruction == T_OPCODE_CMN
8588 || inst.instruction == T_OPCODE_NEG
8589 || inst.instruction == T_OPCODE_MVN)
8591 inst.error = BAD_ARGS;
8592 return;
8595 if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
8596 return;
8598 if (Rs != Rd)
8600 inst.error = _("dest and source1 must be the same register");
8601 return;
8603 Rs = Rn;
8606 if (inst.instruction == T_OPCODE_MUL
8607 && Rs == Rd)
8608 as_tsktsk (_("Rs and Rd must be different in MUL"));
8610 inst.instruction |= Rd | (Rs << 3);
8611 end_of_line (str);
8614 static void
8615 do_t_add (str)
8616 char * str;
8618 thumb_add_sub (str, 0);
8621 static void
8622 do_t_asr (str)
8623 char * str;
8625 thumb_shift (str, THUMB_ASR);
8628 static void
8629 do_t_branch9 (str)
8630 char * str;
8632 if (my_get_expression (&inst.reloc.exp, &str))
8633 return;
8634 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH9;
8635 inst.reloc.pc_rel = 1;
8636 end_of_line (str);
8639 static void
8640 do_t_branch12 (str)
8641 char * str;
8643 if (my_get_expression (&inst.reloc.exp, &str))
8644 return;
8645 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH12;
8646 inst.reloc.pc_rel = 1;
8647 end_of_line (str);
8650 /* Find the real, Thumb encoded start of a Thumb function. */
8652 static symbolS *
8653 find_real_start (symbolP)
8654 symbolS * symbolP;
8656 char * real_start;
8657 const char * name = S_GET_NAME (symbolP);
8658 symbolS * new_target;
8660 /* This definiton must agree with the one in gcc/config/arm/thumb.c. */
8661 #define STUB_NAME ".real_start_of"
8663 if (name == NULL)
8664 abort ();
8666 /* Names that start with '.' are local labels, not function entry points.
8667 The compiler may generate BL instructions to these labels because it
8668 needs to perform a branch to a far away location. */
8669 if (name[0] == '.')
8670 return symbolP;
8672 real_start = malloc (strlen (name) + strlen (STUB_NAME) + 1);
8673 sprintf (real_start, "%s%s", STUB_NAME, name);
8675 new_target = symbol_find (real_start);
8677 if (new_target == NULL)
8679 as_warn ("Failed to find real start of function: %s\n", name);
8680 new_target = symbolP;
8683 free (real_start);
8685 return new_target;
8688 static void
8689 do_t_branch23 (str)
8690 char * str;
8692 if (my_get_expression (& inst.reloc.exp, & str))
8693 return;
8695 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH23;
8696 inst.reloc.pc_rel = 1;
8697 end_of_line (str);
8699 /* If the destination of the branch is a defined symbol which does not have
8700 the THUMB_FUNC attribute, then we must be calling a function which has
8701 the (interfacearm) attribute. We look for the Thumb entry point to that
8702 function and change the branch to refer to that function instead. */
8703 if ( inst.reloc.exp.X_op == O_symbol
8704 && inst.reloc.exp.X_add_symbol != NULL
8705 && S_IS_DEFINED (inst.reloc.exp.X_add_symbol)
8706 && ! THUMB_IS_FUNC (inst.reloc.exp.X_add_symbol))
8707 inst.reloc.exp.X_add_symbol =
8708 find_real_start (inst.reloc.exp.X_add_symbol);
8711 static void
8712 do_t_bx (str)
8713 char * str;
8715 int reg;
8717 skip_whitespace (str);
8719 if ((reg = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
8720 return;
8722 /* This sets THUMB_H2 from the top bit of reg. */
8723 inst.instruction |= reg << 3;
8725 /* ??? FIXME: Should add a hacky reloc here if reg is REG_PC. The reloc
8726 should cause the alignment to be checked once it is known. This is
8727 because BX PC only works if the instruction is word aligned. */
8729 end_of_line (str);
8732 static void
8733 do_t_compare (str)
8734 char * str;
8736 thumb_mov_compare (str, THUMB_COMPARE);
8739 static void
8740 do_t_ldmstm (str)
8741 char * str;
8743 int Rb;
8744 long range;
8746 skip_whitespace (str);
8748 if ((Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
8749 return;
8751 if (*str != '!')
8752 as_warn (_("inserted missing '!': load/store multiple always writes back base register"));
8753 else
8754 str++;
8756 if (skip_past_comma (&str) == FAIL
8757 || (range = reg_list (&str)) == FAIL)
8759 if (! inst.error)
8760 inst.error = BAD_ARGS;
8761 return;
8764 if (inst.reloc.type != BFD_RELOC_NONE)
8766 /* This really doesn't seem worth it. */
8767 inst.reloc.type = BFD_RELOC_NONE;
8768 inst.error = _("expression too complex");
8769 return;
8772 if (range & ~0xff)
8774 inst.error = _("only lo-regs valid in load/store multiple");
8775 return;
8778 inst.instruction |= (Rb << 8) | range;
8779 end_of_line (str);
8782 static void
8783 do_t_ldr (str)
8784 char * str;
8786 thumb_load_store (str, THUMB_LOAD, THUMB_WORD);
8789 static void
8790 do_t_ldrb (str)
8791 char * str;
8793 thumb_load_store (str, THUMB_LOAD, THUMB_BYTE);
8796 static void
8797 do_t_ldrh (str)
8798 char * str;
8800 thumb_load_store (str, THUMB_LOAD, THUMB_HALFWORD);
8803 static void
8804 do_t_lds (str)
8805 char * str;
8807 int Rd, Rb, Ro;
8809 skip_whitespace (str);
8811 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
8812 || skip_past_comma (&str) == FAIL
8813 || *str++ != '['
8814 || (Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL
8815 || skip_past_comma (&str) == FAIL
8816 || (Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL
8817 || *str++ != ']')
8819 if (! inst.error)
8820 inst.error = _("syntax: ldrs[b] Rd, [Rb, Ro]");
8821 return;
8824 inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
8825 end_of_line (str);
8828 static void
8829 do_t_lsl (str)
8830 char * str;
8832 thumb_shift (str, THUMB_LSL);
8835 static void
8836 do_t_lsr (str)
8837 char * str;
8839 thumb_shift (str, THUMB_LSR);
8842 static void
8843 do_t_mov (str)
8844 char * str;
8846 thumb_mov_compare (str, THUMB_MOVE);
8849 static void
8850 do_t_push_pop (str)
8851 char * str;
8853 long range;
8855 skip_whitespace (str);
8857 if ((range = reg_list (&str)) == FAIL)
8859 if (! inst.error)
8860 inst.error = BAD_ARGS;
8861 return;
8864 if (inst.reloc.type != BFD_RELOC_NONE)
8866 /* This really doesn't seem worth it. */
8867 inst.reloc.type = BFD_RELOC_NONE;
8868 inst.error = _("expression too complex");
8869 return;
8872 if (range & ~0xff)
8874 if ((inst.instruction == T_OPCODE_PUSH
8875 && (range & ~0xff) == 1 << REG_LR)
8876 || (inst.instruction == T_OPCODE_POP
8877 && (range & ~0xff) == 1 << REG_PC))
8879 inst.instruction |= THUMB_PP_PC_LR;
8880 range &= 0xff;
8882 else
8884 inst.error = _("invalid register list to push/pop instruction");
8885 return;
8889 inst.instruction |= range;
8890 end_of_line (str);
8893 static void
8894 do_t_str (str)
8895 char * str;
8897 thumb_load_store (str, THUMB_STORE, THUMB_WORD);
8900 static void
8901 do_t_strb (str)
8902 char * str;
8904 thumb_load_store (str, THUMB_STORE, THUMB_BYTE);
8907 static void
8908 do_t_strh (str)
8909 char * str;
8911 thumb_load_store (str, THUMB_STORE, THUMB_HALFWORD);
8914 static void
8915 do_t_sub (str)
8916 char * str;
8918 thumb_add_sub (str, 1);
8921 static void
8922 do_t_swi (str)
8923 char * str;
8925 skip_whitespace (str);
8927 if (my_get_expression (&inst.reloc.exp, &str))
8928 return;
8930 inst.reloc.type = BFD_RELOC_ARM_SWI;
8931 end_of_line (str);
8932 return;
8935 static void
8936 do_t_adr (str)
8937 char * str;
8939 int reg;
8941 /* This is a pseudo-op of the form "adr rd, label" to be converted
8942 into a relative address of the form "add rd, pc, #label-.-4". */
8943 skip_whitespace (str);
8945 /* Store Rd in temporary location inside instruction. */
8946 if ((reg = reg_required_here (&str, 4)) == FAIL
8947 || (reg > 7) /* For Thumb reg must be r0..r7. */
8948 || skip_past_comma (&str) == FAIL
8949 || my_get_expression (&inst.reloc.exp, &str))
8951 if (!inst.error)
8952 inst.error = BAD_ARGS;
8953 return;
8956 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
8957 inst.reloc.exp.X_add_number -= 4; /* PC relative adjust. */
8958 inst.reloc.pc_rel = 1;
8959 inst.instruction |= REG_PC; /* Rd is already placed into the instruction. */
8961 end_of_line (str);
8964 static void
8965 insert_reg (r, htab)
8966 const struct reg_entry *r;
8967 struct hash_control *htab;
8969 int len = strlen (r->name) + 2;
8970 char * buf = (char *) xmalloc (len);
8971 char * buf2 = (char *) xmalloc (len);
8972 int i = 0;
8974 #ifdef REGISTER_PREFIX
8975 buf[i++] = REGISTER_PREFIX;
8976 #endif
8978 strcpy (buf + i, r->name);
8980 for (i = 0; buf[i]; i++)
8981 buf2[i] = TOUPPER (buf[i]);
8983 buf2[i] = '\0';
8985 hash_insert (htab, buf, (PTR) r);
8986 hash_insert (htab, buf2, (PTR) r);
8989 static void
8990 build_reg_hsh (map)
8991 struct reg_map *map;
8993 const struct reg_entry *r;
8995 if ((map->htab = hash_new ()) == NULL)
8996 as_fatal (_("virtual memory exhausted"));
8998 for (r = map->names; r->name != NULL; r++)
8999 insert_reg (r, map->htab);
9002 static void
9003 insert_reg_alias (str, regnum, htab)
9004 char *str;
9005 int regnum;
9006 struct hash_control *htab;
9008 struct reg_entry *new =
9009 (struct reg_entry *) xmalloc (sizeof (struct reg_entry));
9010 char *name = xmalloc (strlen (str) + 1);
9011 strcpy (name, str);
9013 new->name = name;
9014 new->number = regnum;
9016 hash_insert (htab, name, (PTR) new);
9019 /* Look for the .req directive. This is of the form:
9021 newname .req existing_name
9023 If we find one, or if it looks sufficiently like one that we want to
9024 handle any error here, return non-zero. Otherwise return zero. */
9025 static int
9026 create_register_alias (newname, p)
9027 char *newname;
9028 char *p;
9030 char *q;
9031 char c;
9033 q = p;
9034 skip_whitespace (q);
9036 c = *p;
9037 *p = '\0';
9039 if (*q && !strncmp (q, ".req ", 5))
9041 char *copy_of_str;
9042 char *r;
9044 #ifdef IGNORE_OPCODE_CASE
9045 newname = original_case_string;
9046 #endif
9047 copy_of_str = newname;
9049 q += 4;
9050 skip_whitespace (q);
9052 for (r = q; *r != '\0'; r++)
9053 if (*r == ' ')
9054 break;
9056 if (r != q)
9058 enum arm_reg_type new_type, old_type;
9059 int old_regno;
9060 char d = *r;
9062 *r = '\0';
9063 old_type = arm_reg_parse_any (q);
9064 *r = d;
9066 new_type = arm_reg_parse_any (newname);
9068 if (new_type == REG_TYPE_MAX)
9070 if (old_type != REG_TYPE_MAX)
9072 old_regno = arm_reg_parse (&q, all_reg_maps[old_type].htab);
9073 insert_reg_alias (newname, old_regno,
9074 all_reg_maps[old_type].htab);
9076 else
9077 as_warn (_("register '%s' does not exist\n"), q);
9079 else if (old_type == REG_TYPE_MAX)
9081 as_warn (_("ignoring redefinition of register alias '%s' to non-existant register '%s'"),
9082 copy_of_str, q);
9084 else
9086 /* Do not warn about redefinitions to the same alias. */
9087 if (new_type != old_type
9088 || (arm_reg_parse (&q, all_reg_maps[old_type].htab)
9089 != arm_reg_parse (&q, all_reg_maps[new_type].htab)))
9090 as_warn (_("ignoring redefinition of register alias '%s'"),
9091 copy_of_str);
9095 else
9096 as_warn (_("ignoring incomplete .req pseuso op"));
9098 *p = c;
9099 return 1;
9101 *p = c;
9102 return 0;
9105 static void
9106 set_constant_flonums ()
9108 int i;
9110 for (i = 0; i < NUM_FLOAT_VALS; i++)
9111 if (atof_ieee ((char *) fp_const[i], 'x', fp_values[i]) == NULL)
9112 abort ();
9115 /* Iterate over the base tables to create the instruction patterns. */
9116 static void
9117 build_arm_ops_hsh ()
9119 unsigned int i;
9120 unsigned int j;
9121 static struct obstack insn_obstack;
9123 obstack_begin (&insn_obstack, 4000);
9125 for (i = 0; i < sizeof (insns) / sizeof (struct asm_opcode); i++)
9127 const struct asm_opcode *insn = insns + i;
9129 if (insn->cond_offset != 0)
9131 /* Insn supports conditional execution. Build the varaints
9132 and insert them in the hash table. */
9133 for (j = 0; j < sizeof (conds) / sizeof (struct asm_cond); j++)
9135 unsigned len = strlen (insn->template);
9136 struct asm_opcode *new;
9137 char *template;
9139 new = obstack_alloc (&insn_obstack, sizeof (struct asm_opcode));
9140 /* All condition codes are two characters. */
9141 template = obstack_alloc (&insn_obstack, len + 3);
9143 strncpy (template, insn->template, insn->cond_offset);
9144 strcpy (template + insn->cond_offset, conds[j].template);
9145 if (len > insn->cond_offset)
9146 strcpy (template + insn->cond_offset + 2,
9147 insn->template + insn->cond_offset);
9148 new->template = template;
9149 new->cond_offset = 0;
9150 new->variant = insn->variant;
9151 new->parms = insn->parms;
9152 new->value = (insn->value & ~COND_MASK) | conds[j].value;
9154 hash_insert (arm_ops_hsh, new->template, (PTR) new);
9157 /* Finally, insert the unconditional insn in the table directly;
9158 no need to build a copy. */
9159 hash_insert (arm_ops_hsh, insn->template, (PTR) insn);
9163 void
9164 md_begin ()
9166 unsigned mach;
9167 unsigned int i;
9169 if ( (arm_ops_hsh = hash_new ()) == NULL
9170 || (arm_tops_hsh = hash_new ()) == NULL
9171 || (arm_cond_hsh = hash_new ()) == NULL
9172 || (arm_shift_hsh = hash_new ()) == NULL
9173 || (arm_psr_hsh = hash_new ()) == NULL)
9174 as_fatal (_("virtual memory exhausted"));
9176 build_arm_ops_hsh ();
9177 for (i = 0; i < sizeof (tinsns) / sizeof (struct thumb_opcode); i++)
9178 hash_insert (arm_tops_hsh, tinsns[i].template, (PTR) (tinsns + i));
9179 for (i = 0; i < sizeof (conds) / sizeof (struct asm_cond); i++)
9180 hash_insert (arm_cond_hsh, conds[i].template, (PTR) (conds + i));
9181 for (i = 0; i < sizeof (shift_names) / sizeof (struct asm_shift_name); i++)
9182 hash_insert (arm_shift_hsh, shift_names[i].name, (PTR) (shift_names + i));
9183 for (i = 0; i < sizeof (psrs) / sizeof (struct asm_psr); i++)
9184 hash_insert (arm_psr_hsh, psrs[i].template, (PTR) (psrs + i));
9186 for (i = (int) REG_TYPE_FIRST; i < (int) REG_TYPE_MAX; i++)
9187 build_reg_hsh (all_reg_maps + i);
9189 set_constant_flonums ();
9191 /* Set the cpu variant based on the command-line options. We prefer
9192 -mcpu= over -march= if both are set (as for GCC); and we prefer
9193 -mfpu= over any other way of setting the floating point unit.
9194 Use of legacy options with new options are faulted. */
9195 if (legacy_cpu != -1)
9197 if (mcpu_cpu_opt != -1 || march_cpu_opt != -1)
9198 as_bad (_("use of old and new-style options to set CPU type"));
9200 mcpu_cpu_opt = legacy_cpu;
9202 else if (mcpu_cpu_opt == -1)
9203 mcpu_cpu_opt = march_cpu_opt;
9205 if (legacy_fpu != -1)
9207 if (mfpu_opt != -1)
9208 as_bad (_("use of old and new-style options to set FPU type"));
9210 mfpu_opt = legacy_fpu;
9212 else if (mfpu_opt == -1)
9214 if (mcpu_fpu_opt != -1)
9215 mfpu_opt = mcpu_fpu_opt;
9216 else
9217 mfpu_opt = march_fpu_opt;
9220 if (mfpu_opt == -1)
9222 if (mcpu_cpu_opt == -1)
9223 mfpu_opt = FPU_DEFAULT;
9224 else if (mcpu_cpu_opt & ARM_EXT_V5)
9225 mfpu_opt = FPU_ARCH_VFP_V2;
9226 else
9227 mfpu_opt = FPU_ARCH_FPA;
9230 if (mcpu_cpu_opt == -1)
9231 mcpu_cpu_opt = CPU_DEFAULT;
9233 cpu_variant = mcpu_cpu_opt | mfpu_opt;
9235 #if defined OBJ_COFF || defined OBJ_ELF
9237 unsigned int flags = 0;
9239 /* Set the flags in the private structure. */
9240 if (uses_apcs_26) flags |= F_APCS26;
9241 if (support_interwork) flags |= F_INTERWORK;
9242 if (uses_apcs_float) flags |= F_APCS_FLOAT;
9243 if (pic_code) flags |= F_PIC;
9244 if ((cpu_variant & FPU_ANY) == FPU_NONE
9245 || (cpu_variant & FPU_ANY) == FPU_ARCH_VFP) /* VFP layout only. */
9246 flags |= F_SOFT_FLOAT;
9247 /* Using VFP conventions (even if soft-float). */
9248 if (cpu_variant & FPU_VFP_EXT_NONE) flags |= F_VFP_FLOAT;
9251 bfd_set_private_flags (stdoutput, flags);
9253 /* We have run out flags in the COFF header to encode the
9254 status of ATPCS support, so instead we create a dummy,
9255 empty, debug section called .arm.atpcs. */
9256 if (atpcs)
9258 asection * sec;
9260 sec = bfd_make_section (stdoutput, ".arm.atpcs");
9262 if (sec != NULL)
9264 bfd_set_section_flags
9265 (stdoutput, sec, SEC_READONLY | SEC_DEBUGGING /* | SEC_HAS_CONTENTS */);
9266 bfd_set_section_size (stdoutput, sec, 0);
9267 bfd_set_section_contents (stdoutput, sec, NULL, 0, 0);
9271 #endif
9273 /* Record the CPU type as well. */
9274 switch (cpu_variant & ARM_CPU_MASK)
9276 case ARM_2:
9277 mach = bfd_mach_arm_2;
9278 break;
9280 case ARM_3: /* Also ARM_250. */
9281 mach = bfd_mach_arm_2a;
9282 break;
9284 case ARM_6: /* Also ARM_7. */
9285 mach = bfd_mach_arm_3;
9286 break;
9288 default:
9289 mach = bfd_mach_arm_4;
9290 break;
9293 /* Catch special cases. */
9294 if (cpu_variant & ARM_CEXT_XSCALE)
9295 mach = bfd_mach_arm_XScale;
9296 else if (cpu_variant & ARM_EXT_V5E)
9297 mach = bfd_mach_arm_5TE;
9298 else if (cpu_variant & ARM_EXT_V5)
9300 if (cpu_variant & ARM_EXT_V4T)
9301 mach = bfd_mach_arm_5T;
9302 else
9303 mach = bfd_mach_arm_5;
9305 else if (cpu_variant & ARM_EXT_V4)
9307 if (cpu_variant & ARM_EXT_V4T)
9308 mach = bfd_mach_arm_4T;
9309 else
9310 mach = bfd_mach_arm_4;
9312 else if (cpu_variant & ARM_EXT_V3M)
9313 mach = bfd_mach_arm_3M;
9315 bfd_set_arch_mach (stdoutput, TARGET_ARCH, mach);
9318 /* Turn an integer of n bytes (in val) into a stream of bytes appropriate
9319 for use in the a.out file, and stores them in the array pointed to by buf.
9320 This knows about the endian-ness of the target machine and does
9321 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
9322 2 (short) and 4 (long) Floating numbers are put out as a series of
9323 LITTLENUMS (shorts, here at least). */
9325 void
9326 md_number_to_chars (buf, val, n)
9327 char * buf;
9328 valueT val;
9329 int n;
9331 if (target_big_endian)
9332 number_to_chars_bigendian (buf, val, n);
9333 else
9334 number_to_chars_littleendian (buf, val, n);
9337 static valueT
9338 md_chars_to_number (buf, n)
9339 char * buf;
9340 int n;
9342 valueT result = 0;
9343 unsigned char * where = (unsigned char *) buf;
9345 if (target_big_endian)
9347 while (n--)
9349 result <<= 8;
9350 result |= (*where++ & 255);
9353 else
9355 while (n--)
9357 result <<= 8;
9358 result |= (where[n] & 255);
9362 return result;
9365 /* Turn a string in input_line_pointer into a floating point constant
9366 of type TYPE, and store the appropriate bytes in *LITP. The number
9367 of LITTLENUMS emitted is stored in *SIZEP. An error message is
9368 returned, or NULL on OK.
9370 Note that fp constants aren't represent in the normal way on the ARM.
9371 In big endian mode, things are as expected. However, in little endian
9372 mode fp constants are big-endian word-wise, and little-endian byte-wise
9373 within the words. For example, (double) 1.1 in big endian mode is
9374 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
9375 the byte sequence 99 99 f1 3f 9a 99 99 99.
9377 ??? The format of 12 byte floats is uncertain according to gcc's arm.h. */
9379 char *
9380 md_atof (type, litP, sizeP)
9381 char type;
9382 char * litP;
9383 int * sizeP;
9385 int prec;
9386 LITTLENUM_TYPE words[MAX_LITTLENUMS];
9387 char *t;
9388 int i;
9390 switch (type)
9392 case 'f':
9393 case 'F':
9394 case 's':
9395 case 'S':
9396 prec = 2;
9397 break;
9399 case 'd':
9400 case 'D':
9401 case 'r':
9402 case 'R':
9403 prec = 4;
9404 break;
9406 case 'x':
9407 case 'X':
9408 prec = 6;
9409 break;
9411 case 'p':
9412 case 'P':
9413 prec = 6;
9414 break;
9416 default:
9417 *sizeP = 0;
9418 return _("bad call to MD_ATOF()");
9421 t = atof_ieee (input_line_pointer, type, words);
9422 if (t)
9423 input_line_pointer = t;
9424 *sizeP = prec * 2;
9426 if (target_big_endian)
9428 for (i = 0; i < prec; i++)
9430 md_number_to_chars (litP, (valueT) words[i], 2);
9431 litP += 2;
9434 else
9436 if (cpu_variant & FPU_ARCH_VFP)
9437 for (i = prec - 1; i >= 0; i--)
9439 md_number_to_chars (litP, (valueT) words[i], 2);
9440 litP += 2;
9442 else
9443 /* For a 4 byte float the order of elements in `words' is 1 0.
9444 For an 8 byte float the order is 1 0 3 2. */
9445 for (i = 0; i < prec; i += 2)
9447 md_number_to_chars (litP, (valueT) words[i + 1], 2);
9448 md_number_to_chars (litP + 2, (valueT) words[i], 2);
9449 litP += 4;
9453 return 0;
9456 /* The knowledge of the PC's pipeline offset is built into the insns
9457 themselves. */
9459 long
9460 md_pcrel_from (fixP)
9461 fixS * fixP;
9463 if (fixP->fx_addsy
9464 && S_GET_SEGMENT (fixP->fx_addsy) == undefined_section
9465 && fixP->fx_subsy == NULL)
9466 return 0;
9468 if (fixP->fx_pcrel && (fixP->fx_r_type == BFD_RELOC_ARM_THUMB_ADD))
9470 /* PC relative addressing on the Thumb is slightly odd
9471 as the bottom two bits of the PC are forced to zero
9472 for the calculation. */
9473 return (fixP->fx_where + fixP->fx_frag->fr_address) & ~3;
9476 #ifdef TE_WINCE
9477 /* The pattern was adjusted to accomodate CE's off-by-one fixups,
9478 so we un-adjust here to compensate for the accomodation. */
9479 return fixP->fx_where + fixP->fx_frag->fr_address + 8;
9480 #else
9481 return fixP->fx_where + fixP->fx_frag->fr_address;
9482 #endif
9485 /* Round up a section size to the appropriate boundary. */
9487 valueT
9488 md_section_align (segment, size)
9489 segT segment ATTRIBUTE_UNUSED;
9490 valueT size;
9492 #ifdef OBJ_ELF
9493 return size;
9494 #else
9495 /* Round all sects to multiple of 4. */
9496 return (size + 3) & ~3;
9497 #endif
9500 /* Under ELF we need to default _GLOBAL_OFFSET_TABLE.
9501 Otherwise we have no need to default values of symbols. */
9503 symbolS *
9504 md_undefined_symbol (name)
9505 char * name ATTRIBUTE_UNUSED;
9507 #ifdef OBJ_ELF
9508 if (name[0] == '_' && name[1] == 'G'
9509 && streq (name, GLOBAL_OFFSET_TABLE_NAME))
9511 if (!GOT_symbol)
9513 if (symbol_find (name))
9514 as_bad ("GOT already in the symbol table");
9516 GOT_symbol = symbol_new (name, undefined_section,
9517 (valueT) 0, & zero_address_frag);
9520 return GOT_symbol;
9522 #endif
9524 return 0;
9527 /* arm_reg_parse () := if it looks like a register, return its token and
9528 advance the pointer. */
9530 static int
9531 arm_reg_parse (ccp, htab)
9532 register char ** ccp;
9533 struct hash_control *htab;
9535 char * start = * ccp;
9536 char c;
9537 char * p;
9538 struct reg_entry * reg;
9540 #ifdef REGISTER_PREFIX
9541 if (*start != REGISTER_PREFIX)
9542 return FAIL;
9543 p = start + 1;
9544 #else
9545 p = start;
9546 #ifdef OPTIONAL_REGISTER_PREFIX
9547 if (*p == OPTIONAL_REGISTER_PREFIX)
9548 p++, start++;
9549 #endif
9550 #endif
9551 if (!ISALPHA (*p) || !is_name_beginner (*p))
9552 return FAIL;
9554 c = *p++;
9555 while (ISALPHA (c) || ISDIGIT (c) || c == '_')
9556 c = *p++;
9558 *--p = 0;
9559 reg = (struct reg_entry *) hash_find (htab, start);
9560 *p = c;
9562 if (reg)
9564 *ccp = p;
9565 return reg->number;
9568 return FAIL;
9571 /* Search for the following register name in each of the possible reg name
9572 tables. Return the classification if found, or REG_TYPE_MAX if not
9573 present. */
9574 static enum arm_reg_type
9575 arm_reg_parse_any (cp)
9576 char *cp;
9578 int i;
9580 for (i = (int) REG_TYPE_FIRST; i < (int) REG_TYPE_MAX; i++)
9581 if (arm_reg_parse (&cp, all_reg_maps[i].htab) != FAIL)
9582 return (enum arm_reg_type) i;
9584 return REG_TYPE_MAX;
9587 void
9588 md_apply_fix3 (fixP, valP, seg)
9589 fixS * fixP;
9590 valueT * valP;
9591 segT seg;
9593 offsetT value = * valP;
9594 offsetT newval;
9595 unsigned int newimm;
9596 unsigned long temp;
9597 int sign;
9598 char * buf = fixP->fx_where + fixP->fx_frag->fr_literal;
9599 arm_fix_data * arm_data = (arm_fix_data *) fixP->tc_fix_data;
9601 assert (fixP->fx_r_type < BFD_RELOC_UNUSED);
9603 /* Note whether this will delete the relocation. */
9604 #if 0
9605 /* Patch from REarnshaw to JDavis (disabled for the moment, since it
9606 doesn't work fully.) */
9607 if ((fixP->fx_addsy == 0 || symbol_constant_p (fixP->fx_addsy))
9608 && !fixP->fx_pcrel)
9609 #else
9610 if (fixP->fx_addsy == 0 && !fixP->fx_pcrel)
9611 #endif
9612 fixP->fx_done = 1;
9614 /* If this symbol is in a different section then we need to leave it for
9615 the linker to deal with. Unfortunately, md_pcrel_from can't tell,
9616 so we have to undo it's effects here. */
9617 if (fixP->fx_pcrel)
9619 if (fixP->fx_addsy != NULL
9620 && S_IS_DEFINED (fixP->fx_addsy)
9621 && S_GET_SEGMENT (fixP->fx_addsy) != seg)
9623 if (target_oabi
9624 && (fixP->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH
9625 || fixP->fx_r_type == BFD_RELOC_ARM_PCREL_BLX
9627 value = 0;
9628 else
9629 value += md_pcrel_from (fixP);
9633 /* Remember value for emit_reloc. */
9634 fixP->fx_addnumber = value;
9636 switch (fixP->fx_r_type)
9638 case BFD_RELOC_ARM_IMMEDIATE:
9639 newimm = validate_immediate (value);
9640 temp = md_chars_to_number (buf, INSN_SIZE);
9642 /* If the instruction will fail, see if we can fix things up by
9643 changing the opcode. */
9644 if (newimm == (unsigned int) FAIL
9645 && (newimm = negate_data_op (&temp, value)) == (unsigned int) FAIL)
9647 as_bad_where (fixP->fx_file, fixP->fx_line,
9648 _("invalid constant (%lx) after fixup"),
9649 (unsigned long) value);
9650 break;
9653 newimm |= (temp & 0xfffff000);
9654 md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
9655 break;
9657 case BFD_RELOC_ARM_ADRL_IMMEDIATE:
9659 unsigned int highpart = 0;
9660 unsigned int newinsn = 0xe1a00000; /* nop. */
9661 newimm = validate_immediate (value);
9662 temp = md_chars_to_number (buf, INSN_SIZE);
9664 /* If the instruction will fail, see if we can fix things up by
9665 changing the opcode. */
9666 if (newimm == (unsigned int) FAIL
9667 && (newimm = negate_data_op (& temp, value)) == (unsigned int) FAIL)
9669 /* No ? OK - try using two ADD instructions to generate
9670 the value. */
9671 newimm = validate_immediate_twopart (value, & highpart);
9673 /* Yes - then make sure that the second instruction is
9674 also an add. */
9675 if (newimm != (unsigned int) FAIL)
9676 newinsn = temp;
9677 /* Still No ? Try using a negated value. */
9678 else if ((newimm = validate_immediate_twopart (- value, & highpart)) != (unsigned int) FAIL)
9679 temp = newinsn = (temp & OPCODE_MASK) | OPCODE_SUB << DATA_OP_SHIFT;
9680 /* Otherwise - give up. */
9681 else
9683 as_bad_where (fixP->fx_file, fixP->fx_line,
9684 _("unable to compute ADRL instructions for PC offset of 0x%lx"),
9685 (long) value);
9686 break;
9689 /* Replace the first operand in the 2nd instruction (which
9690 is the PC) with the destination register. We have
9691 already added in the PC in the first instruction and we
9692 do not want to do it again. */
9693 newinsn &= ~ 0xf0000;
9694 newinsn |= ((newinsn & 0x0f000) << 4);
9697 newimm |= (temp & 0xfffff000);
9698 md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
9700 highpart |= (newinsn & 0xfffff000);
9701 md_number_to_chars (buf + INSN_SIZE, (valueT) highpart, INSN_SIZE);
9703 break;
9705 case BFD_RELOC_ARM_OFFSET_IMM:
9706 sign = value >= 0;
9708 if (value < 0)
9709 value = - value;
9711 if (validate_offset_imm (value, 0) == FAIL)
9713 as_bad_where (fixP->fx_file, fixP->fx_line,
9714 _("bad immediate value for offset (%ld)"),
9715 (long) value);
9716 break;
9719 newval = md_chars_to_number (buf, INSN_SIZE);
9720 newval &= 0xff7ff000;
9721 newval |= value | (sign ? INDEX_UP : 0);
9722 md_number_to_chars (buf, newval, INSN_SIZE);
9723 break;
9725 case BFD_RELOC_ARM_OFFSET_IMM8:
9726 case BFD_RELOC_ARM_HWLITERAL:
9727 sign = value >= 0;
9729 if (value < 0)
9730 value = - value;
9732 if (validate_offset_imm (value, 1) == FAIL)
9734 if (fixP->fx_r_type == BFD_RELOC_ARM_HWLITERAL)
9735 as_bad_where (fixP->fx_file, fixP->fx_line,
9736 _("invalid literal constant: pool needs to be closer"));
9737 else
9738 as_bad (_("bad immediate value for half-word offset (%ld)"),
9739 (long) value);
9740 break;
9743 newval = md_chars_to_number (buf, INSN_SIZE);
9744 newval &= 0xff7ff0f0;
9745 newval |= ((value >> 4) << 8) | (value & 0xf) | (sign ? INDEX_UP : 0);
9746 md_number_to_chars (buf, newval, INSN_SIZE);
9747 break;
9749 case BFD_RELOC_ARM_LITERAL:
9750 sign = value >= 0;
9752 if (value < 0)
9753 value = - value;
9755 if (validate_offset_imm (value, 0) == FAIL)
9757 as_bad_where (fixP->fx_file, fixP->fx_line,
9758 _("invalid literal constant: pool needs to be closer"));
9759 break;
9762 newval = md_chars_to_number (buf, INSN_SIZE);
9763 newval &= 0xff7ff000;
9764 newval |= value | (sign ? INDEX_UP : 0);
9765 md_number_to_chars (buf, newval, INSN_SIZE);
9766 break;
9768 case BFD_RELOC_ARM_SHIFT_IMM:
9769 newval = md_chars_to_number (buf, INSN_SIZE);
9770 if (((unsigned long) value) > 32
9771 || (value == 32
9772 && (((newval & 0x60) == 0) || (newval & 0x60) == 0x60)))
9774 as_bad_where (fixP->fx_file, fixP->fx_line,
9775 _("shift expression is too large"));
9776 break;
9779 if (value == 0)
9780 /* Shifts of zero must be done as lsl. */
9781 newval &= ~0x60;
9782 else if (value == 32)
9783 value = 0;
9784 newval &= 0xfffff07f;
9785 newval |= (value & 0x1f) << 7;
9786 md_number_to_chars (buf, newval, INSN_SIZE);
9787 break;
9789 case BFD_RELOC_ARM_SWI:
9790 if (arm_data->thumb_mode)
9792 if (((unsigned long) value) > 0xff)
9793 as_bad_where (fixP->fx_file, fixP->fx_line,
9794 _("invalid swi expression"));
9795 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xff00;
9796 newval |= value;
9797 md_number_to_chars (buf, newval, THUMB_SIZE);
9799 else
9801 if (((unsigned long) value) > 0x00ffffff)
9802 as_bad_where (fixP->fx_file, fixP->fx_line,
9803 _("invalid swi expression"));
9804 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff000000;
9805 newval |= value;
9806 md_number_to_chars (buf, newval, INSN_SIZE);
9808 break;
9810 case BFD_RELOC_ARM_MULTI:
9811 if (((unsigned long) value) > 0xffff)
9812 as_bad_where (fixP->fx_file, fixP->fx_line,
9813 _("invalid expression in load/store multiple"));
9814 newval = value | md_chars_to_number (buf, INSN_SIZE);
9815 md_number_to_chars (buf, newval, INSN_SIZE);
9816 break;
9818 case BFD_RELOC_ARM_PCREL_BRANCH:
9819 newval = md_chars_to_number (buf, INSN_SIZE);
9821 /* Sign-extend a 24-bit number. */
9822 #define SEXT24(x) ((((x) & 0xffffff) ^ (~ 0x7fffff)) + 0x800000)
9824 #ifdef OBJ_ELF
9825 if (! target_oabi)
9826 value = fixP->fx_offset;
9827 #endif
9829 /* We are going to store value (shifted right by two) in the
9830 instruction, in a 24 bit, signed field. Thus we need to check
9831 that none of the top 8 bits of the shifted value (top 7 bits of
9832 the unshifted, unsigned value) are set, or that they are all set. */
9833 if ((value & ~ ((offsetT) 0x1ffffff)) != 0
9834 && ((value & ~ ((offsetT) 0x1ffffff)) != ~ ((offsetT) 0x1ffffff)))
9836 #ifdef OBJ_ELF
9837 /* Normally we would be stuck at this point, since we cannot store
9838 the absolute address that is the destination of the branch in the
9839 24 bits of the branch instruction. If however, we happen to know
9840 that the destination of the branch is in the same section as the
9841 branch instruciton itself, then we can compute the relocation for
9842 ourselves and not have to bother the linker with it.
9844 FIXME: The tests for OBJ_ELF and ! target_oabi are only here
9845 because I have not worked out how to do this for OBJ_COFF or
9846 target_oabi. */
9847 if (! target_oabi
9848 && fixP->fx_addsy != NULL
9849 && S_IS_DEFINED (fixP->fx_addsy)
9850 && S_GET_SEGMENT (fixP->fx_addsy) == seg)
9852 /* Get pc relative value to go into the branch. */
9853 value = * valP;
9855 /* Permit a backward branch provided that enough bits
9856 are set. Allow a forwards branch, provided that
9857 enough bits are clear. */
9858 if ( (value & ~ ((offsetT) 0x1ffffff)) == ~ ((offsetT) 0x1ffffff)
9859 || (value & ~ ((offsetT) 0x1ffffff)) == 0)
9860 fixP->fx_done = 1;
9863 if (! fixP->fx_done)
9864 #endif
9865 as_bad_where (fixP->fx_file, fixP->fx_line,
9866 _("GAS can't handle same-section branch dest >= 0x04000000"));
9869 value >>= 2;
9870 value += SEXT24 (newval);
9872 if ( (value & ~ ((offsetT) 0xffffff)) != 0
9873 && ((value & ~ ((offsetT) 0xffffff)) != ~ ((offsetT) 0xffffff)))
9874 as_bad_where (fixP->fx_file, fixP->fx_line,
9875 _("out of range branch"));
9877 newval = (value & 0x00ffffff) | (newval & 0xff000000);
9878 md_number_to_chars (buf, newval, INSN_SIZE);
9879 break;
9881 case BFD_RELOC_ARM_PCREL_BLX:
9883 offsetT hbit;
9884 newval = md_chars_to_number (buf, INSN_SIZE);
9886 #ifdef OBJ_ELF
9887 if (! target_oabi)
9888 value = fixP->fx_offset;
9889 #endif
9890 hbit = (value >> 1) & 1;
9891 value = (value >> 2) & 0x00ffffff;
9892 value = (value + (newval & 0x00ffffff)) & 0x00ffffff;
9893 newval = value | (newval & 0xfe000000) | (hbit << 24);
9894 md_number_to_chars (buf, newval, INSN_SIZE);
9896 break;
9898 case BFD_RELOC_THUMB_PCREL_BRANCH9: /* Conditional branch. */
9899 newval = md_chars_to_number (buf, THUMB_SIZE);
9901 addressT diff = (newval & 0xff) << 1;
9902 if (diff & 0x100)
9903 diff |= ~0xff;
9905 value += diff;
9906 if ((value & ~0xff) && ((value & ~0xff) != ~0xff))
9907 as_bad_where (fixP->fx_file, fixP->fx_line,
9908 _("branch out of range"));
9909 newval = (newval & 0xff00) | ((value & 0x1ff) >> 1);
9911 md_number_to_chars (buf, newval, THUMB_SIZE);
9912 break;
9914 case BFD_RELOC_THUMB_PCREL_BRANCH12: /* Unconditional branch. */
9915 newval = md_chars_to_number (buf, THUMB_SIZE);
9917 addressT diff = (newval & 0x7ff) << 1;
9918 if (diff & 0x800)
9919 diff |= ~0x7ff;
9921 value += diff;
9922 if ((value & ~0x7ff) && ((value & ~0x7ff) != ~0x7ff))
9923 as_bad_where (fixP->fx_file, fixP->fx_line,
9924 _("branch out of range"));
9925 newval = (newval & 0xf800) | ((value & 0xfff) >> 1);
9927 md_number_to_chars (buf, newval, THUMB_SIZE);
9928 break;
9930 case BFD_RELOC_THUMB_PCREL_BLX:
9931 case BFD_RELOC_THUMB_PCREL_BRANCH23:
9933 offsetT newval2;
9934 addressT diff;
9936 newval = md_chars_to_number (buf, THUMB_SIZE);
9937 newval2 = md_chars_to_number (buf + THUMB_SIZE, THUMB_SIZE);
9938 diff = ((newval & 0x7ff) << 12) | ((newval2 & 0x7ff) << 1);
9939 if (diff & 0x400000)
9940 diff |= ~0x3fffff;
9941 #ifdef OBJ_ELF
9942 value = fixP->fx_offset;
9943 #endif
9944 value += diff;
9946 if ((value & ~0x3fffff) && ((value & ~0x3fffff) != ~0x3fffff))
9947 as_bad_where (fixP->fx_file, fixP->fx_line,
9948 _("branch with link out of range"));
9950 newval = (newval & 0xf800) | ((value & 0x7fffff) >> 12);
9951 newval2 = (newval2 & 0xf800) | ((value & 0xfff) >> 1);
9952 if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX)
9953 /* For a BLX instruction, make sure that the relocation is rounded up
9954 to a word boundary. This follows the semantics of the instruction
9955 which specifies that bit 1 of the target address will come from bit
9956 1 of the base address. */
9957 newval2 = (newval2 + 1) & ~ 1;
9958 md_number_to_chars (buf, newval, THUMB_SIZE);
9959 md_number_to_chars (buf + THUMB_SIZE, newval2, THUMB_SIZE);
9961 break;
9963 case BFD_RELOC_8:
9964 if (fixP->fx_done || fixP->fx_pcrel)
9965 md_number_to_chars (buf, value, 1);
9966 #ifdef OBJ_ELF
9967 else if (!target_oabi)
9969 value = fixP->fx_offset;
9970 md_number_to_chars (buf, value, 1);
9972 #endif
9973 break;
9975 case BFD_RELOC_16:
9976 if (fixP->fx_done || fixP->fx_pcrel)
9977 md_number_to_chars (buf, value, 2);
9978 #ifdef OBJ_ELF
9979 else if (!target_oabi)
9981 value = fixP->fx_offset;
9982 md_number_to_chars (buf, value, 2);
9984 #endif
9985 break;
9987 #ifdef OBJ_ELF
9988 case BFD_RELOC_ARM_GOT32:
9989 case BFD_RELOC_ARM_GOTOFF:
9990 md_number_to_chars (buf, 0, 4);
9991 break;
9992 #endif
9994 case BFD_RELOC_RVA:
9995 case BFD_RELOC_32:
9996 if (fixP->fx_done || fixP->fx_pcrel)
9997 md_number_to_chars (buf, value, 4);
9998 #ifdef OBJ_ELF
9999 else if (!target_oabi)
10001 value = fixP->fx_offset;
10002 md_number_to_chars (buf, value, 4);
10004 #endif
10005 break;
10007 #ifdef OBJ_ELF
10008 case BFD_RELOC_ARM_PLT32:
10009 /* It appears the instruction is fully prepared at this point. */
10010 break;
10011 #endif
10013 case BFD_RELOC_ARM_GOTPC:
10014 md_number_to_chars (buf, value, 4);
10015 break;
10017 case BFD_RELOC_ARM_CP_OFF_IMM:
10018 sign = value >= 0;
10019 if (value < -1023 || value > 1023 || (value & 3))
10020 as_bad_where (fixP->fx_file, fixP->fx_line,
10021 _("illegal value for co-processor offset"));
10022 if (value < 0)
10023 value = -value;
10024 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
10025 newval |= (value >> 2) | (sign ? INDEX_UP : 0);
10026 md_number_to_chars (buf, newval, INSN_SIZE);
10027 break;
10029 case BFD_RELOC_ARM_THUMB_OFFSET:
10030 newval = md_chars_to_number (buf, THUMB_SIZE);
10031 /* Exactly what ranges, and where the offset is inserted depends
10032 on the type of instruction, we can establish this from the
10033 top 4 bits. */
10034 switch (newval >> 12)
10036 case 4: /* PC load. */
10037 /* Thumb PC loads are somewhat odd, bit 1 of the PC is
10038 forced to zero for these loads, so we will need to round
10039 up the offset if the instruction address is not word
10040 aligned (since the final address produced must be, and
10041 we can only describe word-aligned immediate offsets). */
10043 if ((fixP->fx_frag->fr_address + fixP->fx_where + value) & 3)
10044 as_bad_where (fixP->fx_file, fixP->fx_line,
10045 _("invalid offset, target not word aligned (0x%08X)"),
10046 (unsigned int) (fixP->fx_frag->fr_address
10047 + fixP->fx_where + value));
10049 if ((value + 2) & ~0x3fe)
10050 as_bad_where (fixP->fx_file, fixP->fx_line,
10051 _("invalid offset, value too big (0x%08lX)"),
10052 (long) value);
10054 /* Round up, since pc will be rounded down. */
10055 newval |= (value + 2) >> 2;
10056 break;
10058 case 9: /* SP load/store. */
10059 if (value & ~0x3fc)
10060 as_bad_where (fixP->fx_file, fixP->fx_line,
10061 _("invalid offset, value too big (0x%08lX)"),
10062 (long) value);
10063 newval |= value >> 2;
10064 break;
10066 case 6: /* Word load/store. */
10067 if (value & ~0x7c)
10068 as_bad_where (fixP->fx_file, fixP->fx_line,
10069 _("invalid offset, value too big (0x%08lX)"),
10070 (long) value);
10071 newval |= value << 4; /* 6 - 2. */
10072 break;
10074 case 7: /* Byte load/store. */
10075 if (value & ~0x1f)
10076 as_bad_where (fixP->fx_file, fixP->fx_line,
10077 _("invalid offset, value too big (0x%08lX)"),
10078 (long) value);
10079 newval |= value << 6;
10080 break;
10082 case 8: /* Halfword load/store. */
10083 if (value & ~0x3e)
10084 as_bad_where (fixP->fx_file, fixP->fx_line,
10085 _("invalid offset, value too big (0x%08lX)"),
10086 (long) value);
10087 newval |= value << 5; /* 6 - 1. */
10088 break;
10090 default:
10091 as_bad_where (fixP->fx_file, fixP->fx_line,
10092 "Unable to process relocation for thumb opcode: %lx",
10093 (unsigned long) newval);
10094 break;
10096 md_number_to_chars (buf, newval, THUMB_SIZE);
10097 break;
10099 case BFD_RELOC_ARM_THUMB_ADD:
10100 /* This is a complicated relocation, since we use it for all of
10101 the following immediate relocations:
10103 3bit ADD/SUB
10104 8bit ADD/SUB
10105 9bit ADD/SUB SP word-aligned
10106 10bit ADD PC/SP word-aligned
10108 The type of instruction being processed is encoded in the
10109 instruction field:
10111 0x8000 SUB
10112 0x00F0 Rd
10113 0x000F Rs
10115 newval = md_chars_to_number (buf, THUMB_SIZE);
10117 int rd = (newval >> 4) & 0xf;
10118 int rs = newval & 0xf;
10119 int subtract = newval & 0x8000;
10121 if (rd == REG_SP)
10123 if (value & ~0x1fc)
10124 as_bad_where (fixP->fx_file, fixP->fx_line,
10125 _("invalid immediate for stack address calculation"));
10126 newval = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
10127 newval |= value >> 2;
10129 else if (rs == REG_PC || rs == REG_SP)
10131 if (subtract ||
10132 value & ~0x3fc)
10133 as_bad_where (fixP->fx_file, fixP->fx_line,
10134 _("invalid immediate for address calculation (value = 0x%08lX)"),
10135 (unsigned long) value);
10136 newval = (rs == REG_PC ? T_OPCODE_ADD_PC : T_OPCODE_ADD_SP);
10137 newval |= rd << 8;
10138 newval |= value >> 2;
10140 else if (rs == rd)
10142 if (value & ~0xff)
10143 as_bad_where (fixP->fx_file, fixP->fx_line,
10144 _("invalid 8bit immediate"));
10145 newval = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
10146 newval |= (rd << 8) | value;
10148 else
10150 if (value & ~0x7)
10151 as_bad_where (fixP->fx_file, fixP->fx_line,
10152 _("invalid 3bit immediate"));
10153 newval = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
10154 newval |= rd | (rs << 3) | (value << 6);
10157 md_number_to_chars (buf, newval, THUMB_SIZE);
10158 break;
10160 case BFD_RELOC_ARM_THUMB_IMM:
10161 newval = md_chars_to_number (buf, THUMB_SIZE);
10162 switch (newval >> 11)
10164 case 0x04: /* 8bit immediate MOV. */
10165 case 0x05: /* 8bit immediate CMP. */
10166 if (value < 0 || value > 255)
10167 as_bad_where (fixP->fx_file, fixP->fx_line,
10168 _("invalid immediate: %ld is too large"),
10169 (long) value);
10170 newval |= value;
10171 break;
10173 default:
10174 abort ();
10176 md_number_to_chars (buf, newval, THUMB_SIZE);
10177 break;
10179 case BFD_RELOC_ARM_THUMB_SHIFT:
10180 /* 5bit shift value (0..31). */
10181 if (value < 0 || value > 31)
10182 as_bad_where (fixP->fx_file, fixP->fx_line,
10183 _("illegal Thumb shift value: %ld"), (long) value);
10184 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xf03f;
10185 newval |= value << 6;
10186 md_number_to_chars (buf, newval, THUMB_SIZE);
10187 break;
10189 case BFD_RELOC_VTABLE_INHERIT:
10190 case BFD_RELOC_VTABLE_ENTRY:
10191 fixP->fx_done = 0;
10192 return;
10194 case BFD_RELOC_NONE:
10195 default:
10196 as_bad_where (fixP->fx_file, fixP->fx_line,
10197 _("bad relocation fixup type (%d)"), fixP->fx_r_type);
10201 /* Translate internal representation of relocation info to BFD target
10202 format. */
10204 arelent *
10205 tc_gen_reloc (section, fixp)
10206 asection * section ATTRIBUTE_UNUSED;
10207 fixS * fixp;
10209 arelent * reloc;
10210 bfd_reloc_code_real_type code;
10212 reloc = (arelent *) xmalloc (sizeof (arelent));
10214 reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
10215 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
10216 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
10218 /* @@ Why fx_addnumber sometimes and fx_offset other times? */
10219 #ifndef OBJ_ELF
10220 if (fixp->fx_pcrel == 0)
10221 reloc->addend = fixp->fx_offset;
10222 else
10223 reloc->addend = fixp->fx_offset = reloc->address;
10224 #else /* OBJ_ELF */
10225 reloc->addend = fixp->fx_offset;
10226 #endif
10228 switch (fixp->fx_r_type)
10230 case BFD_RELOC_8:
10231 if (fixp->fx_pcrel)
10233 code = BFD_RELOC_8_PCREL;
10234 break;
10237 case BFD_RELOC_16:
10238 if (fixp->fx_pcrel)
10240 code = BFD_RELOC_16_PCREL;
10241 break;
10244 case BFD_RELOC_32:
10245 if (fixp->fx_pcrel)
10247 code = BFD_RELOC_32_PCREL;
10248 break;
10251 case BFD_RELOC_ARM_PCREL_BRANCH:
10252 case BFD_RELOC_ARM_PCREL_BLX:
10253 case BFD_RELOC_RVA:
10254 case BFD_RELOC_THUMB_PCREL_BRANCH9:
10255 case BFD_RELOC_THUMB_PCREL_BRANCH12:
10256 case BFD_RELOC_THUMB_PCREL_BRANCH23:
10257 case BFD_RELOC_THUMB_PCREL_BLX:
10258 case BFD_RELOC_VTABLE_ENTRY:
10259 case BFD_RELOC_VTABLE_INHERIT:
10260 code = fixp->fx_r_type;
10261 break;
10263 case BFD_RELOC_ARM_LITERAL:
10264 case BFD_RELOC_ARM_HWLITERAL:
10265 /* If this is called then the a literal has
10266 been referenced across a section boundary. */
10267 as_bad_where (fixp->fx_file, fixp->fx_line,
10268 _("literal referenced across section boundary"));
10269 return NULL;
10271 #ifdef OBJ_ELF
10272 case BFD_RELOC_ARM_GOT32:
10273 case BFD_RELOC_ARM_GOTOFF:
10274 case BFD_RELOC_ARM_PLT32:
10275 code = fixp->fx_r_type;
10276 break;
10277 #endif
10279 case BFD_RELOC_ARM_IMMEDIATE:
10280 as_bad_where (fixp->fx_file, fixp->fx_line,
10281 _("internal relocation (type %d) not fixed up (IMMEDIATE)"),
10282 fixp->fx_r_type);
10283 return NULL;
10285 case BFD_RELOC_ARM_ADRL_IMMEDIATE:
10286 as_bad_where (fixp->fx_file, fixp->fx_line,
10287 _("ADRL used for a symbol not defined in the same file"));
10288 return NULL;
10290 case BFD_RELOC_ARM_OFFSET_IMM:
10291 as_bad_where (fixp->fx_file, fixp->fx_line,
10292 _("internal_relocation (type %d) not fixed up (OFFSET_IMM)"),
10293 fixp->fx_r_type);
10294 return NULL;
10296 default:
10298 char * type;
10300 switch (fixp->fx_r_type)
10302 case BFD_RELOC_ARM_IMMEDIATE: type = "IMMEDIATE"; break;
10303 case BFD_RELOC_ARM_OFFSET_IMM: type = "OFFSET_IMM"; break;
10304 case BFD_RELOC_ARM_OFFSET_IMM8: type = "OFFSET_IMM8"; break;
10305 case BFD_RELOC_ARM_SHIFT_IMM: type = "SHIFT_IMM"; break;
10306 case BFD_RELOC_ARM_SWI: type = "SWI"; break;
10307 case BFD_RELOC_ARM_MULTI: type = "MULTI"; break;
10308 case BFD_RELOC_ARM_CP_OFF_IMM: type = "CP_OFF_IMM"; break;
10309 case BFD_RELOC_ARM_THUMB_ADD: type = "THUMB_ADD"; break;
10310 case BFD_RELOC_ARM_THUMB_SHIFT: type = "THUMB_SHIFT"; break;
10311 case BFD_RELOC_ARM_THUMB_IMM: type = "THUMB_IMM"; break;
10312 case BFD_RELOC_ARM_THUMB_OFFSET: type = "THUMB_OFFSET"; break;
10313 default: type = _("<unknown>"); break;
10315 as_bad_where (fixp->fx_file, fixp->fx_line,
10316 _("cannot represent %s relocation in this object file format"),
10317 type);
10318 return NULL;
10322 #ifdef OBJ_ELF
10323 if (code == BFD_RELOC_32_PCREL
10324 && GOT_symbol
10325 && fixp->fx_addsy == GOT_symbol)
10327 code = BFD_RELOC_ARM_GOTPC;
10328 reloc->addend = fixp->fx_offset = reloc->address;
10330 #endif
10332 reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
10334 if (reloc->howto == NULL)
10336 as_bad_where (fixp->fx_file, fixp->fx_line,
10337 _("cannot represent %s relocation in this object file format"),
10338 bfd_get_reloc_code_name (code));
10339 return NULL;
10342 /* HACK: Since arm ELF uses Rel instead of Rela, encode the
10343 vtable entry to be used in the relocation's section offset. */
10344 if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
10345 reloc->address = fixp->fx_offset;
10347 return reloc;
10351 md_estimate_size_before_relax (fragP, segtype)
10352 fragS * fragP ATTRIBUTE_UNUSED;
10353 segT segtype ATTRIBUTE_UNUSED;
10355 as_fatal (_("md_estimate_size_before_relax\n"));
10356 return 1;
10359 static void
10360 output_inst (str)
10361 const char *str;
10363 char * to = NULL;
10365 if (inst.error)
10367 as_bad ("%s -- `%s'", inst.error, str);
10368 return;
10371 to = frag_more (inst.size);
10373 if (thumb_mode && (inst.size > THUMB_SIZE))
10375 assert (inst.size == (2 * THUMB_SIZE));
10376 md_number_to_chars (to, inst.instruction >> 16, THUMB_SIZE);
10377 md_number_to_chars (to + THUMB_SIZE, inst.instruction, THUMB_SIZE);
10379 else if (inst.size > INSN_SIZE)
10381 assert (inst.size == (2 * INSN_SIZE));
10382 md_number_to_chars (to, inst.instruction, INSN_SIZE);
10383 md_number_to_chars (to + INSN_SIZE, inst.instruction, INSN_SIZE);
10385 else
10386 md_number_to_chars (to, inst.instruction, inst.size);
10388 if (inst.reloc.type != BFD_RELOC_NONE)
10389 fix_new_arm (frag_now, to - frag_now->fr_literal,
10390 inst.size, & inst.reloc.exp, inst.reloc.pc_rel,
10391 inst.reloc.type);
10393 #ifdef OBJ_ELF
10394 dwarf2_emit_insn (inst.size);
10395 #endif
10398 void
10399 md_assemble (str)
10400 char * str;
10402 char c;
10403 char *p;
10404 char *start;
10406 /* Align the instruction.
10407 This may not be the right thing to do but ... */
10408 #if 0
10409 arm_align (2, 0);
10410 #endif
10412 /* Align the previous label if needed. */
10413 if (last_label_seen != NULL)
10415 symbol_set_frag (last_label_seen, frag_now);
10416 S_SET_VALUE (last_label_seen, (valueT) frag_now_fix ());
10417 S_SET_SEGMENT (last_label_seen, now_seg);
10420 memset (&inst, '\0', sizeof (inst));
10421 inst.reloc.type = BFD_RELOC_NONE;
10423 skip_whitespace (str);
10425 /* Scan up to the end of the op-code, which must end in white space or
10426 end of string. */
10427 for (start = p = str; *p != '\0'; p++)
10428 if (*p == ' ')
10429 break;
10431 if (p == str)
10433 as_bad (_("no operator -- statement `%s'\n"), str);
10434 return;
10437 if (thumb_mode)
10439 const struct thumb_opcode * opcode;
10441 c = *p;
10442 *p = '\0';
10443 opcode = (const struct thumb_opcode *) hash_find (arm_tops_hsh, str);
10444 *p = c;
10446 if (opcode)
10448 /* Check that this instruction is supported for this CPU. */
10449 if (thumb_mode == 1 && (opcode->variant & cpu_variant) == 0)
10451 as_bad (_("selected processor does not support `%s'"), str);
10452 return;
10455 inst.instruction = opcode->value;
10456 inst.size = opcode->size;
10457 (*opcode->parms) (p);
10458 output_inst (str);
10459 return;
10462 else
10464 const struct asm_opcode * opcode;
10466 c = *p;
10467 *p = '\0';
10468 opcode = (const struct asm_opcode *) hash_find (arm_ops_hsh, str);
10469 *p = c;
10471 if (opcode)
10473 /* Check that this instruction is supported for this CPU. */
10474 if ((opcode->variant & cpu_variant) == 0)
10476 as_bad (_("selected processor does not support `%s'"), str);
10477 return;
10480 inst.instruction = opcode->value;
10481 inst.size = INSN_SIZE;
10482 (*opcode->parms) (p);
10483 output_inst (str);
10484 return;
10488 /* It wasn't an instruction, but it might be a register alias of the form
10489 alias .req reg. */
10490 if (create_register_alias (str, p))
10491 return;
10493 as_bad (_("bad instruction `%s'"), start);
10496 /* md_parse_option
10497 Invocation line includes a switch not recognized by the base assembler.
10498 See if it's a processor-specific option.
10500 This routine is somewhat complicated by the need for backwards
10501 compatibility (since older releases of gcc can't be changed).
10502 The new options try to make the interface as compatible as
10503 possible with GCC.
10505 New options (supported) are:
10507 -mcpu=<cpu name> Assemble for selected processor
10508 -march=<architecture name> Assemble for selected architecture
10509 -mfpu=<fpu architecture> Assemble for selected FPU.
10510 -EB/-mbig-endian Big-endian
10511 -EL/-mlittle-endian Little-endian
10512 -k Generate PIC code
10513 -mthumb Start in Thumb mode
10514 -mthumb-interwork Code supports ARM/Thumb interworking
10516 For now we will also provide support for:
10518 -mapcs-32 32-bit Program counter
10519 -mapcs-26 26-bit Program counter
10520 -macps-float Floats passed in FP registers
10521 -mapcs-reentrant Reentrant code
10522 -matpcs
10523 (sometime these will probably be replaced with -mapcs=<list of options>
10524 and -matpcs=<list of options>)
10526 The remaining options are only supported for back-wards compatibility.
10527 Cpu variants, the arm part is optional:
10528 -m[arm]1 Currently not supported.
10529 -m[arm]2, -m[arm]250 Arm 2 and Arm 250 processor
10530 -m[arm]3 Arm 3 processor
10531 -m[arm]6[xx], Arm 6 processors
10532 -m[arm]7[xx][t][[d]m] Arm 7 processors
10533 -m[arm]8[10] Arm 8 processors
10534 -m[arm]9[20][tdmi] Arm 9 processors
10535 -mstrongarm[110[0]] StrongARM processors
10536 -mxscale XScale processors
10537 -m[arm]v[2345[t[e]]] Arm architectures
10538 -mall All (except the ARM1)
10539 FP variants:
10540 -mfpa10, -mfpa11 FPA10 and 11 co-processor instructions
10541 -mfpe-old (No float load/store multiples)
10542 -mvfpxd VFP Single precision
10543 -mvfp All VFP
10544 -mno-fpu Disable all floating point instructions
10546 The following CPU names are recognized:
10547 arm1, arm2, arm250, arm3, arm6, arm600, arm610, arm620,
10548 arm7, arm7m, arm7d, arm7dm, arm7di, arm7dmi, arm70, arm700,
10549 arm700i, arm710 arm710t, arm720, arm720t, arm740t, arm710c,
10550 arm7100, arm7500, arm7500fe, arm7tdmi, arm8, arm810, arm9,
10551 arm920, arm920t, arm940t, arm946, arm966, arm9tdmi, arm9e,
10552 arm10t arm10e, arm1020t, arm1020e, arm10200e,
10553 strongarm, strongarm110, strongarm1100, strongarm1110, xscale.
10557 const char * md_shortopts = "m:k";
10559 #ifdef ARM_BI_ENDIAN
10560 #define OPTION_EB (OPTION_MD_BASE + 0)
10561 #define OPTION_EL (OPTION_MD_BASE + 1)
10562 #else
10563 #if TARGET_BYTES_BIG_ENDIAN
10564 #define OPTION_EB (OPTION_MD_BASE + 0)
10565 #else
10566 #define OPTION_EL (OPTION_MD_BASE + 1)
10567 #endif
10568 #endif
10570 struct option md_longopts[] =
10572 #ifdef OPTION_EB
10573 {"EB", no_argument, NULL, OPTION_EB},
10574 #endif
10575 #ifdef OPTION_EL
10576 {"EL", no_argument, NULL, OPTION_EL},
10577 #endif
10578 {NULL, no_argument, NULL, 0}
10581 size_t md_longopts_size = sizeof (md_longopts);
10583 struct arm_option_table
10585 char *option; /* Option name to match. */
10586 char *help; /* Help information. */
10587 int *var; /* Variable to change. */
10588 int value; /* What to change it to. */
10589 char *deprecated; /* If non-null, print this message. */
10592 struct arm_option_table arm_opts[] =
10594 {"k", N_("generate PIC code"), &pic_code, 1, NULL},
10595 {"mthumb", N_("assemble Thumb code"), &thumb_mode, 1, NULL},
10596 {"mthumb-interwork", N_("support ARM/Thumb interworking"),
10597 &support_interwork, 1, NULL},
10598 {"moabi", N_("use old ABI (ELF only)"), &target_oabi, 1, NULL},
10599 {"mapcs-32", N_("code uses 32-bit program counter"), &uses_apcs_26, 0, NULL},
10600 {"mapcs-26", N_("code uses 26-bit program counter"), &uses_apcs_26, 1, NULL},
10601 {"mapcs-float", N_("floating point args are in fp regs"), &uses_apcs_float,
10602 1, NULL},
10603 {"mapcs-reentrant", N_("re-entrant code"), &pic_code, 1, NULL},
10604 {"matpcs", N_("code is ATPCS conformant"), &atpcs, 1, NULL},
10605 {"mbig-endian", N_("assemble for big-endian"), &target_big_endian, 1, NULL},
10606 {"mlittle-endian", N_("assemble for little-endian"), &target_big_endian, 1,
10607 NULL},
10609 /* These are recognized by the assembler, but have no affect on code. */
10610 {"mapcs-frame", N_("use frame pointer"), NULL, 0, NULL},
10611 {"mapcs-stack-check", N_("use stack size checking"), NULL, 0, NULL},
10613 /* DON'T add any new processors to this list -- we want the whole list
10614 to go away... Add them to the processors table instead. */
10615 {"marm1", NULL, &legacy_cpu, ARM_ARCH_V1, N_("use -mcpu=arm1")},
10616 {"m1", NULL, &legacy_cpu, ARM_ARCH_V1, N_("use -mcpu=arm1")},
10617 {"marm2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -mcpu=arm2")},
10618 {"m2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -mcpu=arm2")},
10619 {"marm250", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm250")},
10620 {"m250", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm250")},
10621 {"marm3", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm3")},
10622 {"m3", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm3")},
10623 {"marm6", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm6")},
10624 {"m6", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm6")},
10625 {"marm600", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm600")},
10626 {"m600", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm600")},
10627 {"marm610", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm610")},
10628 {"m610", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm610")},
10629 {"marm620", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm620")},
10630 {"m620", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm620")},
10631 {"marm7", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7")},
10632 {"m7", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7")},
10633 {"marm70", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm70")},
10634 {"m70", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm70")},
10635 {"marm700", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700")},
10636 {"m700", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700")},
10637 {"marm700i", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700i")},
10638 {"m700i", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700i")},
10639 {"marm710", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710")},
10640 {"m710", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710")},
10641 {"marm710c", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710c")},
10642 {"m710c", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710c")},
10643 {"marm720", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm720")},
10644 {"m720", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm720")},
10645 {"marm7d", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7d")},
10646 {"m7d", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7d")},
10647 {"marm7di", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7di")},
10648 {"m7di", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7di")},
10649 {"marm7m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7m")},
10650 {"m7m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7m")},
10651 {"marm7dm", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dm")},
10652 {"m7dm", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dm")},
10653 {"marm7dmi", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dmi")},
10654 {"m7dmi", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dmi")},
10655 {"marm7100", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7100")},
10656 {"m7100", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7100")},
10657 {"marm7500", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500")},
10658 {"m7500", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500")},
10659 {"marm7500fe", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500fe")},
10660 {"m7500fe", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500fe")},
10661 {"marm7t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
10662 {"m7t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
10663 {"marm7tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
10664 {"m7tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
10665 {"marm710t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm710t")},
10666 {"m710t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm710t")},
10667 {"marm720t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm720t")},
10668 {"m720t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm720t")},
10669 {"marm740t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm740t")},
10670 {"m740t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm740t")},
10671 {"marm8", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm8")},
10672 {"m8", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm8")},
10673 {"marm810", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm810")},
10674 {"m810", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm810")},
10675 {"marm9", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9")},
10676 {"m9", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9")},
10677 {"marm9tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9tdmi")},
10678 {"m9tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9tdmi")},
10679 {"marm920", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm920")},
10680 {"m920", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm920")},
10681 {"marm940", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm940")},
10682 {"m940", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm940")},
10683 {"mstrongarm", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=strongarm")},
10684 {"mstrongarm110", NULL, &legacy_cpu, ARM_ARCH_V4,
10685 N_("use -mcpu=strongarm110")},
10686 {"mstrongarm1100", NULL, &legacy_cpu, ARM_ARCH_V4,
10687 N_("use -mcpu=strongarm1100")},
10688 {"mstrongarm1110", NULL, &legacy_cpu, ARM_ARCH_V4,
10689 N_("use -mcpu=strongarm1110")},
10690 {"mxscale", NULL, &legacy_cpu, ARM_ARCH_XSCALE, N_("use -mcpu=xscale")},
10691 {"mall", NULL, &legacy_cpu, ARM_ANY, N_("use -mcpu=all")},
10693 /* Architecture variants -- don't add any more to this list either. */
10694 {"mv2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -march=armv2")},
10695 {"marmv2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -march=armv2")},
10696 {"mv2a", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -march=armv2a")},
10697 {"marmv2a", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -march=armv2a")},
10698 {"mv3", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -march=armv3")},
10699 {"marmv3", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -march=armv3")},
10700 {"mv3m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -march=armv3m")},
10701 {"marmv3m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -march=armv3m")},
10702 {"mv4", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -march=armv4")},
10703 {"marmv4", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -march=armv4")},
10704 {"mv4t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -march=armv4t")},
10705 {"marmv4t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -march=armv4t")},
10706 {"mv5", NULL, &legacy_cpu, ARM_ARCH_V5, N_("use -march=armv5")},
10707 {"marmv5", NULL, &legacy_cpu, ARM_ARCH_V5, N_("use -march=armv5")},
10708 {"mv5t", NULL, &legacy_cpu, ARM_ARCH_V5T, N_("use -march=armv5t")},
10709 {"marmv5t", NULL, &legacy_cpu, ARM_ARCH_V5T, N_("use -march=armv5t")},
10710 {"mv5e", NULL, &legacy_cpu, ARM_ARCH_V5TE, N_("use -march=armv5te")},
10711 {"marmv5e", NULL, &legacy_cpu, ARM_ARCH_V5TE, N_("use -march=armv5te")},
10713 /* Floating point variants -- don't add any more to this list either. */
10714 {"mfpe-old", NULL, &legacy_fpu, FPU_ARCH_FPE, N_("use -mfpu=fpe")},
10715 {"mfpa10", NULL, &legacy_fpu, FPU_ARCH_FPA, N_("use -mfpu=fpa10")},
10716 {"mfpa11", NULL, &legacy_fpu, FPU_ARCH_FPA, N_("use -mfpu=fpa11")},
10717 {"mno-fpu", NULL, &legacy_fpu, 0,
10718 N_("use either -mfpu=softfpa or -mfpu=softvfp")},
10720 {NULL, NULL, NULL, 0, NULL}
10723 struct arm_cpu_option_table
10725 char *name;
10726 int value;
10727 /* For some CPUs we assume an FPU unless the user explicitly sets
10728 -mfpu=... */
10729 int default_fpu;
10732 /* This list should, at a minimum, contain all the cpu names
10733 recognized by GCC. */
10734 static struct arm_cpu_option_table arm_cpus[] =
10736 {"all", ARM_ANY, FPU_ARCH_FPA},
10737 {"arm1", ARM_ARCH_V1, FPU_ARCH_FPA},
10738 {"arm2", ARM_ARCH_V2, FPU_ARCH_FPA},
10739 {"arm250", ARM_ARCH_V2S, FPU_ARCH_FPA},
10740 {"arm3", ARM_ARCH_V2S, FPU_ARCH_FPA},
10741 {"arm6", ARM_ARCH_V3, FPU_ARCH_FPA},
10742 {"arm60", ARM_ARCH_V3, FPU_ARCH_FPA},
10743 {"arm600", ARM_ARCH_V3, FPU_ARCH_FPA},
10744 {"arm610", ARM_ARCH_V3, FPU_ARCH_FPA},
10745 {"arm620", ARM_ARCH_V3, FPU_ARCH_FPA},
10746 {"arm7", ARM_ARCH_V3, FPU_ARCH_FPA},
10747 {"arm7m", ARM_ARCH_V3M, FPU_ARCH_FPA},
10748 {"arm7d", ARM_ARCH_V3, FPU_ARCH_FPA},
10749 {"arm7dm", ARM_ARCH_V3M, FPU_ARCH_FPA},
10750 {"arm7di", ARM_ARCH_V3, FPU_ARCH_FPA},
10751 {"arm7dmi", ARM_ARCH_V3M, FPU_ARCH_FPA},
10752 {"arm70", ARM_ARCH_V3, FPU_ARCH_FPA},
10753 {"arm700", ARM_ARCH_V3, FPU_ARCH_FPA},
10754 {"arm700i", ARM_ARCH_V3, FPU_ARCH_FPA},
10755 {"arm710", ARM_ARCH_V3, FPU_ARCH_FPA},
10756 {"arm710t", ARM_ARCH_V4T, FPU_ARCH_FPA},
10757 {"arm720", ARM_ARCH_V3, FPU_ARCH_FPA},
10758 {"arm720t", ARM_ARCH_V4T, FPU_ARCH_FPA},
10759 {"arm740t", ARM_ARCH_V4T, FPU_ARCH_FPA},
10760 {"arm710c", ARM_ARCH_V3, FPU_ARCH_FPA},
10761 {"arm7100", ARM_ARCH_V3, FPU_ARCH_FPA},
10762 {"arm7500", ARM_ARCH_V3, FPU_ARCH_FPA},
10763 {"arm7500fe", ARM_ARCH_V3, FPU_ARCH_FPA},
10764 {"arm7t", ARM_ARCH_V4T, FPU_ARCH_FPA},
10765 {"arm7tdmi", ARM_ARCH_V4T, FPU_ARCH_FPA},
10766 {"arm8", ARM_ARCH_V4, FPU_ARCH_FPA},
10767 {"arm810", ARM_ARCH_V4, FPU_ARCH_FPA},
10768 {"strongarm", ARM_ARCH_V4, FPU_ARCH_FPA},
10769 {"strongarm1", ARM_ARCH_V4, FPU_ARCH_FPA},
10770 {"strongarm110", ARM_ARCH_V4, FPU_ARCH_FPA},
10771 {"strongarm1100", ARM_ARCH_V4, FPU_ARCH_FPA},
10772 {"strongarm1110", ARM_ARCH_V4, FPU_ARCH_FPA},
10773 {"arm9", ARM_ARCH_V4T, FPU_ARCH_FPA},
10774 {"arm920", ARM_ARCH_V4T, FPU_ARCH_FPA},
10775 {"arm920t", ARM_ARCH_V4T, FPU_ARCH_FPA},
10776 {"arm922t", ARM_ARCH_V4T, FPU_ARCH_FPA},
10777 {"arm940t", ARM_ARCH_V4T, FPU_ARCH_FPA},
10778 {"arm9tdmi", ARM_ARCH_V4T, FPU_ARCH_FPA},
10779 /* For V5 or later processors we default to using VFP; but the user
10780 should really set the FPU type explicitly. */
10781 {"arm9e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
10782 {"arm9e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
10783 {"arm926ej", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
10784 {"arm946e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
10785 {"arm946e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
10786 {"arm966e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
10787 {"arm966e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
10788 {"arm10t", ARM_ARCH_V5T, FPU_ARCH_VFP_V1},
10789 {"arm10e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
10790 {"arm1020", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
10791 {"arm1020t", ARM_ARCH_V5T, FPU_ARCH_VFP_V1},
10792 {"arm1020e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
10793 /* ??? XSCALE is really an architecture. */
10794 {"xscale", ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2},
10795 {"i80200", ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2},
10796 /* Maverick */
10797 {"ep9312", ARM_ARCH_V4T | ARM_CEXT_MAVERICK, FPU_NONE},
10798 {NULL, 0, 0}
10801 struct arm_arch_option_table
10803 char *name;
10804 int value;
10805 int default_fpu;
10808 /* This list should, at a minimum, contain all the architecture names
10809 recognized by GCC. */
10810 static struct arm_arch_option_table arm_archs[] =
10812 {"all", ARM_ANY, FPU_ARCH_FPA},
10813 {"armv1", ARM_ARCH_V1, FPU_ARCH_FPA},
10814 {"armv2", ARM_ARCH_V2, FPU_ARCH_FPA},
10815 {"armv2a", ARM_ARCH_V2S, FPU_ARCH_FPA},
10816 {"armv2s", ARM_ARCH_V2S, FPU_ARCH_FPA},
10817 {"armv3", ARM_ARCH_V3, FPU_ARCH_FPA},
10818 {"armv3m", ARM_ARCH_V3M, FPU_ARCH_FPA},
10819 {"armv4", ARM_ARCH_V4, FPU_ARCH_FPA},
10820 {"armv4xm", ARM_ARCH_V4xM, FPU_ARCH_FPA},
10821 {"armv4t", ARM_ARCH_V4T, FPU_ARCH_FPA},
10822 {"armv4txm", ARM_ARCH_V4TxM, FPU_ARCH_FPA},
10823 {"armv5", ARM_ARCH_V5, FPU_ARCH_VFP},
10824 {"armv5t", ARM_ARCH_V5T, FPU_ARCH_VFP},
10825 {"armv5txm", ARM_ARCH_V5TxM, FPU_ARCH_VFP},
10826 {"armv5te", ARM_ARCH_V5TE, FPU_ARCH_VFP},
10827 {"armv5texp", ARM_ARCH_V5TExP, FPU_ARCH_VFP},
10828 {"armv5tej", ARM_ARCH_V5TEJ, FPU_ARCH_VFP},
10829 {"xscale", ARM_ARCH_XSCALE, FPU_ARCH_VFP},
10830 {NULL, 0, 0}
10833 /* ISA extensions in the co-processor space. */
10834 struct arm_arch_extension_table
10836 char *name;
10837 int value;
10840 static struct arm_arch_extension_table arm_extensions[] =
10842 {"maverick", ARM_CEXT_MAVERICK},
10843 {"xscale", ARM_CEXT_XSCALE},
10844 {NULL, 0}
10847 struct arm_fpu_option_table
10849 char *name;
10850 int value;
10853 /* This list should, at a minimum, contain all the fpu names
10854 recognized by GCC. */
10855 static struct arm_fpu_option_table arm_fpus[] =
10857 {"softfpa", FPU_NONE},
10858 {"fpe", FPU_ARCH_FPE},
10859 {"fpe2", FPU_ARCH_FPE},
10860 {"fpe3", FPU_ARCH_FPA}, /* Third release supports LFM/SFM. */
10861 {"fpa", FPU_ARCH_FPA},
10862 {"fpa10", FPU_ARCH_FPA},
10863 {"fpa11", FPU_ARCH_FPA},
10864 {"arm7500fe", FPU_ARCH_FPA},
10865 {"softvfp", FPU_ARCH_VFP},
10866 {"softvfp+vfp", FPU_ARCH_VFP_V2},
10867 {"vfp", FPU_ARCH_VFP_V2},
10868 {"vfp9", FPU_ARCH_VFP_V2},
10869 {"vfp10", FPU_ARCH_VFP_V2},
10870 {"vfp10-r0", FPU_ARCH_VFP_V1},
10871 {"vfpxd", FPU_ARCH_VFP_V1xD},
10872 {"arm1020t", FPU_ARCH_VFP_V1},
10873 {"arm1020e", FPU_ARCH_VFP_V2},
10874 {NULL, 0}
10877 struct arm_long_option_table
10879 char *option; /* Substring to match. */
10880 char *help; /* Help information. */
10881 int (*func) PARAMS ((char *subopt)); /* Function to decode sub-option. */
10882 char *deprecated; /* If non-null, print this message. */
10885 static int
10886 arm_parse_extension (str, opt_p)
10887 char *str;
10888 int *opt_p;
10890 while (str != NULL && *str != 0)
10892 struct arm_arch_extension_table *opt;
10893 char *ext;
10894 int optlen;
10896 if (*str != '+')
10898 as_bad (_("invalid architectural extension"));
10899 return 0;
10902 str++;
10903 ext = strchr (str, '+');
10905 if (ext != NULL)
10906 optlen = ext - str;
10907 else
10908 optlen = strlen (str);
10910 if (optlen == 0)
10912 as_bad (_("missing architectural extension"));
10913 return 0;
10916 for (opt = arm_extensions; opt->name != NULL; opt++)
10917 if (strncmp (opt->name, str, optlen) == 0)
10919 *opt_p |= opt->value;
10920 break;
10923 if (opt->name == NULL)
10925 as_bad (_("unknown architectural extnsion `%s'"), str);
10926 return 0;
10929 str = ext;
10932 return 1;
10935 static int
10936 arm_parse_cpu (str)
10937 char *str;
10939 struct arm_cpu_option_table *opt;
10940 char *ext = strchr (str, '+');
10941 int optlen;
10943 if (ext != NULL)
10944 optlen = ext - str;
10945 else
10946 optlen = strlen (str);
10948 if (optlen == 0)
10950 as_bad (_("missing cpu name `%s'"), str);
10951 return 0;
10954 for (opt = arm_cpus; opt->name != NULL; opt++)
10955 if (strncmp (opt->name, str, optlen) == 0)
10957 mcpu_cpu_opt = opt->value;
10958 mcpu_fpu_opt = opt->default_fpu;
10960 if (ext != NULL)
10961 return arm_parse_extension (ext, &mcpu_cpu_opt);
10963 return 1;
10966 as_bad (_("unknown cpu `%s'"), str);
10967 return 0;
10970 static int
10971 arm_parse_arch (str)
10972 char *str;
10974 struct arm_arch_option_table *opt;
10975 char *ext = strchr (str, '+');
10976 int optlen;
10978 if (ext != NULL)
10979 optlen = ext - str;
10980 else
10981 optlen = strlen (str);
10983 if (optlen == 0)
10985 as_bad (_("missing architecture name `%s'"), str);
10986 return 0;
10990 for (opt = arm_archs; opt->name != NULL; opt++)
10991 if (strcmp (opt->name, str) == 0)
10993 march_cpu_opt = opt->value;
10994 march_fpu_opt = opt->default_fpu;
10996 if (ext != NULL)
10997 return arm_parse_extension (ext, &march_cpu_opt);
10999 return 1;
11002 as_bad (_("unknown architecture `%s'\n"), str);
11003 return 0;
11006 static int
11007 arm_parse_fpu (str)
11008 char *str;
11010 struct arm_fpu_option_table *opt;
11012 for (opt = arm_fpus; opt->name != NULL; opt++)
11013 if (strcmp (opt->name, str) == 0)
11015 mfpu_opt = opt->value;
11016 return 1;
11019 as_bad (_("unknown floating point format `%s'\n"), str);
11020 return 0;
11023 struct arm_long_option_table arm_long_opts[] =
11025 {"mcpu=", N_("<cpu name>\t assemble for CPU <cpu name>"),
11026 arm_parse_cpu, NULL},
11027 {"march=", N_("<arch name>\t assemble for architecture <arch name>"),
11028 arm_parse_arch, NULL},
11029 {"mfpu=", N_("<fpu name>\t assemble for FPU architecture <fpu name>"),
11030 arm_parse_fpu, NULL},
11031 {NULL, NULL, 0, NULL}
11035 md_parse_option (c, arg)
11036 int c;
11037 char * arg;
11039 struct arm_option_table *opt;
11040 struct arm_long_option_table *lopt;
11042 switch (c)
11044 #ifdef OPTION_EB
11045 case OPTION_EB:
11046 target_big_endian = 1;
11047 break;
11048 #endif
11050 #ifdef OPTION_EL
11051 case OPTION_EL:
11052 target_big_endian = 0;
11053 break;
11054 #endif
11056 case 'a':
11057 /* Listing option. Just ignore these, we don't support additional
11058 ones. */
11059 return 0;
11061 default:
11062 for (opt = arm_opts; opt->option != NULL; opt++)
11064 if (c == opt->option[0]
11065 && ((arg == NULL && opt->option[1] == 0)
11066 || strcmp (arg, opt->option + 1) == 0))
11068 #if WARN_DEPRECATED
11069 /* If the option is deprecated, tell the user. */
11070 if (opt->deprecated != NULL)
11071 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c,
11072 arg ? arg : "", _(opt->deprecated));
11073 #endif
11075 if (opt->var != NULL)
11076 *opt->var = opt->value;
11078 return 1;
11082 for (lopt = arm_long_opts; lopt->option != NULL; lopt++)
11084 /* These options are expected to have an argument. */
11085 if (c == lopt->option[0]
11086 && arg != NULL
11087 && strncmp (arg, lopt->option + 1,
11088 strlen (lopt->option + 1)) == 0)
11090 #if WARN_DEPRECATED
11091 /* If the option is deprecated, tell the user. */
11092 if (lopt->deprecated != NULL)
11093 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c, arg,
11094 _(lopt->deprecated));
11095 #endif
11097 /* Call the sup-option parser. */
11098 return (*lopt->func)(arg + strlen (lopt->option) - 1);
11102 as_bad (_("unrecognized option `-%c%s'"), c, arg ? arg : "");
11103 return 0;
11106 return 1;
11109 void
11110 md_show_usage (fp)
11111 FILE * fp;
11113 struct arm_option_table *opt;
11114 struct arm_long_option_table *lopt;
11116 fprintf (fp, _(" ARM-specific assembler options:\n"));
11118 for (opt = arm_opts; opt->option != NULL; opt++)
11119 if (opt->help != NULL)
11120 fprintf (fp, " -%-23s%s\n", opt->option, _(opt->help));
11122 for (lopt = arm_long_opts; lopt->option != NULL; lopt++)
11123 if (lopt->help != NULL)
11124 fprintf (fp, " -%s%s\n", lopt->option, _(lopt->help));
11126 #ifdef OPTION_EB
11127 fprintf (fp, _("\
11128 -EB assemble code for a big-endian cpu\n"));
11129 #endif
11131 #ifdef OPTION_EL
11132 fprintf (fp, _("\
11133 -EL assemble code for a little-endian cpu\n"));
11134 #endif
11137 /* We need to be able to fix up arbitrary expressions in some statements.
11138 This is so that we can handle symbols that are an arbitrary distance from
11139 the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
11140 which returns part of an address in a form which will be valid for
11141 a data instruction. We do this by pushing the expression into a symbol
11142 in the expr_section, and creating a fix for that. */
11144 static void
11145 fix_new_arm (frag, where, size, exp, pc_rel, reloc)
11146 fragS * frag;
11147 int where;
11148 short int size;
11149 expressionS * exp;
11150 int pc_rel;
11151 int reloc;
11153 fixS * new_fix;
11154 arm_fix_data * arm_data;
11156 switch (exp->X_op)
11158 case O_constant:
11159 case O_symbol:
11160 case O_add:
11161 case O_subtract:
11162 new_fix = fix_new_exp (frag, where, size, exp, pc_rel, reloc);
11163 break;
11165 default:
11166 new_fix = fix_new (frag, where, size, make_expr_symbol (exp), 0,
11167 pc_rel, reloc);
11168 break;
11171 /* Mark whether the fix is to a THUMB instruction, or an ARM
11172 instruction. */
11173 arm_data = (arm_fix_data *) obstack_alloc (& notes, sizeof (arm_fix_data));
11174 new_fix->tc_fix_data = (PTR) arm_data;
11175 arm_data->thumb_mode = thumb_mode;
11177 return;
11180 /* This fix_new is called by cons via TC_CONS_FIX_NEW. */
11182 void
11183 cons_fix_new_arm (frag, where, size, exp)
11184 fragS * frag;
11185 int where;
11186 int size;
11187 expressionS * exp;
11189 bfd_reloc_code_real_type type;
11190 int pcrel = 0;
11192 /* Pick a reloc.
11193 FIXME: @@ Should look at CPU word size. */
11194 switch (size)
11196 case 1:
11197 type = BFD_RELOC_8;
11198 break;
11199 case 2:
11200 type = BFD_RELOC_16;
11201 break;
11202 case 4:
11203 default:
11204 type = BFD_RELOC_32;
11205 break;
11206 case 8:
11207 type = BFD_RELOC_64;
11208 break;
11211 fix_new_exp (frag, where, (int) size, exp, pcrel, type);
11214 /* A good place to do this, although this was probably not intended
11215 for this kind of use. We need to dump the literal pool before
11216 references are made to a null symbol pointer. */
11218 void
11219 arm_cleanup ()
11221 literal_pool * pool;
11223 for (pool = list_of_pools; pool; pool = pool->next)
11225 /* Put it at the end of the relevent section. */
11226 subseg_set (pool->section, pool->sub_section);
11227 s_ltorg (0);
11231 void
11232 arm_start_line_hook ()
11234 last_label_seen = NULL;
11237 void
11238 arm_frob_label (sym)
11239 symbolS * sym;
11241 last_label_seen = sym;
11243 ARM_SET_THUMB (sym, thumb_mode);
11245 #if defined OBJ_COFF || defined OBJ_ELF
11246 ARM_SET_INTERWORK (sym, support_interwork);
11247 #endif
11249 /* Note - do not allow local symbols (.Lxxx) to be labeled
11250 as Thumb functions. This is because these labels, whilst
11251 they exist inside Thumb code, are not the entry points for
11252 possible ARM->Thumb calls. Also, these labels can be used
11253 as part of a computed goto or switch statement. eg gcc
11254 can generate code that looks like this:
11256 ldr r2, [pc, .Laaa]
11257 lsl r3, r3, #2
11258 ldr r2, [r3, r2]
11259 mov pc, r2
11261 .Lbbb: .word .Lxxx
11262 .Lccc: .word .Lyyy
11263 ..etc...
11264 .Laaa: .word Lbbb
11266 The first instruction loads the address of the jump table.
11267 The second instruction converts a table index into a byte offset.
11268 The third instruction gets the jump address out of the table.
11269 The fourth instruction performs the jump.
11271 If the address stored at .Laaa is that of a symbol which has the
11272 Thumb_Func bit set, then the linker will arrange for this address
11273 to have the bottom bit set, which in turn would mean that the
11274 address computation performed by the third instruction would end
11275 up with the bottom bit set. Since the ARM is capable of unaligned
11276 word loads, the instruction would then load the incorrect address
11277 out of the jump table, and chaos would ensue. */
11278 if (label_is_thumb_function_name
11279 && (S_GET_NAME (sym)[0] != '.' || S_GET_NAME (sym)[1] != 'L')
11280 && (bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
11282 /* When the address of a Thumb function is taken the bottom
11283 bit of that address should be set. This will allow
11284 interworking between Arm and Thumb functions to work
11285 correctly. */
11287 THUMB_SET_FUNC (sym, 1);
11289 label_is_thumb_function_name = false;
11293 /* Adjust the symbol table. This marks Thumb symbols as distinct from
11294 ARM ones. */
11296 void
11297 arm_adjust_symtab ()
11299 #ifdef OBJ_COFF
11300 symbolS * sym;
11302 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
11304 if (ARM_IS_THUMB (sym))
11306 if (THUMB_IS_FUNC (sym))
11308 /* Mark the symbol as a Thumb function. */
11309 if ( S_GET_STORAGE_CLASS (sym) == C_STAT
11310 || S_GET_STORAGE_CLASS (sym) == C_LABEL) /* This can happen! */
11311 S_SET_STORAGE_CLASS (sym, C_THUMBSTATFUNC);
11313 else if (S_GET_STORAGE_CLASS (sym) == C_EXT)
11314 S_SET_STORAGE_CLASS (sym, C_THUMBEXTFUNC);
11315 else
11316 as_bad (_("%s: unexpected function type: %d"),
11317 S_GET_NAME (sym), S_GET_STORAGE_CLASS (sym));
11319 else switch (S_GET_STORAGE_CLASS (sym))
11321 case C_EXT:
11322 S_SET_STORAGE_CLASS (sym, C_THUMBEXT);
11323 break;
11324 case C_STAT:
11325 S_SET_STORAGE_CLASS (sym, C_THUMBSTAT);
11326 break;
11327 case C_LABEL:
11328 S_SET_STORAGE_CLASS (sym, C_THUMBLABEL);
11329 break;
11330 default:
11331 /* Do nothing. */
11332 break;
11336 if (ARM_IS_INTERWORK (sym))
11337 coffsymbol (symbol_get_bfdsym (sym))->native->u.syment.n_flags = 0xFF;
11339 #endif
11340 #ifdef OBJ_ELF
11341 symbolS * sym;
11342 char bind;
11344 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
11346 if (ARM_IS_THUMB (sym))
11348 elf_symbol_type * elf_sym;
11350 elf_sym = elf_symbol (symbol_get_bfdsym (sym));
11351 bind = ELF_ST_BIND (elf_sym);
11353 /* If it's a .thumb_func, declare it as so,
11354 otherwise tag label as .code 16. */
11355 if (THUMB_IS_FUNC (sym))
11356 elf_sym->internal_elf_sym.st_info =
11357 ELF_ST_INFO (bind, STT_ARM_TFUNC);
11358 else
11359 elf_sym->internal_elf_sym.st_info =
11360 ELF_ST_INFO (bind, STT_ARM_16BIT);
11363 #endif
11367 arm_data_in_code ()
11369 if (thumb_mode && ! strncmp (input_line_pointer + 1, "data:", 5))
11371 *input_line_pointer = '/';
11372 input_line_pointer += 5;
11373 *input_line_pointer = 0;
11374 return 1;
11377 return 0;
11380 char *
11381 arm_canonicalize_symbol_name (name)
11382 char * name;
11384 int len;
11386 if (thumb_mode && (len = strlen (name)) > 5
11387 && streq (name + len - 5, "/data"))
11388 *(name + len - 5) = 0;
11390 return name;
11393 boolean
11394 arm_validate_fix (fixP)
11395 fixS * fixP;
11397 /* If the destination of the branch is a defined symbol which does not have
11398 the THUMB_FUNC attribute, then we must be calling a function which has
11399 the (interfacearm) attribute. We look for the Thumb entry point to that
11400 function and change the branch to refer to that function instead. */
11401 if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23
11402 && fixP->fx_addsy != NULL
11403 && S_IS_DEFINED (fixP->fx_addsy)
11404 && ! THUMB_IS_FUNC (fixP->fx_addsy))
11406 fixP->fx_addsy = find_real_start (fixP->fx_addsy);
11407 return true;
11410 return false;
11413 #ifdef OBJ_COFF
11414 /* This is a little hack to help the gas/arm/adrl.s test. It prevents
11415 local labels from being added to the output symbol table when they
11416 are used with the ADRL pseudo op. The ADRL relocation should always
11417 be resolved before the binbary is emitted, so it is safe to say that
11418 it is adjustable. */
11420 boolean
11421 arm_fix_adjustable (fixP)
11422 fixS * fixP;
11424 if (fixP->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE)
11425 return 1;
11426 return 0;
11428 #endif
11429 #ifdef OBJ_ELF
11430 /* Relocations against Thumb function names must be left unadjusted,
11431 so that the linker can use this information to correctly set the
11432 bottom bit of their addresses. The MIPS version of this function
11433 also prevents relocations that are mips-16 specific, but I do not
11434 know why it does this.
11436 FIXME:
11437 There is one other problem that ought to be addressed here, but
11438 which currently is not: Taking the address of a label (rather
11439 than a function) and then later jumping to that address. Such
11440 addresses also ought to have their bottom bit set (assuming that
11441 they reside in Thumb code), but at the moment they will not. */
11443 boolean
11444 arm_fix_adjustable (fixP)
11445 fixS * fixP;
11447 if (fixP->fx_addsy == NULL)
11448 return 1;
11450 /* Prevent all adjustments to global symbols. */
11451 if (S_IS_EXTERN (fixP->fx_addsy))
11452 return 0;
11454 if (S_IS_WEAK (fixP->fx_addsy))
11455 return 0;
11457 if (THUMB_IS_FUNC (fixP->fx_addsy)
11458 && fixP->fx_subsy == NULL)
11459 return 0;
11461 /* We need the symbol name for the VTABLE entries. */
11462 if ( fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
11463 || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
11464 return 0;
11466 return 1;
11469 const char *
11470 elf32_arm_target_format ()
11472 if (target_big_endian)
11474 if (target_oabi)
11475 return "elf32-bigarm-oabi";
11476 else
11477 return "elf32-bigarm";
11479 else
11481 if (target_oabi)
11482 return "elf32-littlearm-oabi";
11483 else
11484 return "elf32-littlearm";
11488 void
11489 armelf_frob_symbol (symp, puntp)
11490 symbolS * symp;
11491 int * puntp;
11493 elf_frob_symbol (symp, puntp);
11497 arm_force_relocation (fixp)
11498 struct fix * fixp;
11500 if ( fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT
11501 || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY
11502 || fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH
11503 || fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BLX
11504 || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX
11505 || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23)
11506 return 1;
11508 return 0;
11511 static bfd_reloc_code_real_type
11512 arm_parse_reloc ()
11514 char id [16];
11515 char * ip;
11516 unsigned int i;
11517 static struct
11519 char * str;
11520 int len;
11521 bfd_reloc_code_real_type reloc;
11523 reloc_map[] =
11525 #define MAP(str,reloc) { str, sizeof (str) - 1, reloc }
11526 MAP ("(got)", BFD_RELOC_ARM_GOT32),
11527 MAP ("(gotoff)", BFD_RELOC_ARM_GOTOFF),
11528 /* ScottB: Jan 30, 1998 - Added support for parsing "var(PLT)"
11529 branch instructions generated by GCC for PLT relocs. */
11530 MAP ("(plt)", BFD_RELOC_ARM_PLT32),
11531 { NULL, 0, BFD_RELOC_UNUSED }
11532 #undef MAP
11535 for (i = 0, ip = input_line_pointer;
11536 i < sizeof (id) && (ISALNUM (*ip) || ISPUNCT (*ip));
11537 i++, ip++)
11538 id[i] = TOLOWER (*ip);
11540 for (i = 0; reloc_map[i].str; i++)
11541 if (strncmp (id, reloc_map[i].str, reloc_map[i].len) == 0)
11542 break;
11544 input_line_pointer += reloc_map[i].len;
11546 return reloc_map[i].reloc;
11549 static void
11550 s_arm_elf_cons (nbytes)
11551 int nbytes;
11553 expressionS exp;
11555 #ifdef md_flush_pending_output
11556 md_flush_pending_output ();
11557 #endif
11559 if (is_it_end_of_statement ())
11561 demand_empty_rest_of_line ();
11562 return;
11565 #ifdef md_cons_align
11566 md_cons_align (nbytes);
11567 #endif
11571 bfd_reloc_code_real_type reloc;
11573 expression (& exp);
11575 if (exp.X_op == O_symbol
11576 && * input_line_pointer == '('
11577 && (reloc = arm_parse_reloc ()) != BFD_RELOC_UNUSED)
11579 reloc_howto_type *howto = bfd_reloc_type_lookup (stdoutput, reloc);
11580 int size = bfd_get_reloc_size (howto);
11582 if (size > nbytes)
11583 as_bad ("%s relocations do not fit in %d bytes",
11584 howto->name, nbytes);
11585 else
11587 register char *p = frag_more ((int) nbytes);
11588 int offset = nbytes - size;
11590 fix_new_exp (frag_now, p - frag_now->fr_literal + offset, size,
11591 &exp, 0, reloc);
11594 else
11595 emit_expr (&exp, (unsigned int) nbytes);
11597 while (*input_line_pointer++ == ',');
11599 /* Put terminator back into stream. */
11600 input_line_pointer --;
11601 demand_empty_rest_of_line ();
11604 #endif /* OBJ_ELF */
11606 /* This is called from HANDLE_ALIGN in write.c. Fill in the contents
11607 of an rs_align_code fragment. */
11609 void
11610 arm_handle_align (fragP)
11611 fragS *fragP;
11613 static char const arm_noop[4] = { 0x00, 0x00, 0xa0, 0xe1 };
11614 static char const thumb_noop[2] = { 0xc0, 0x46 };
11615 static char const arm_bigend_noop[4] = { 0xe1, 0xa0, 0x00, 0x00 };
11616 static char const thumb_bigend_noop[2] = { 0x46, 0xc0 };
11618 int bytes, fix, noop_size;
11619 char * p;
11620 const char * noop;
11622 if (fragP->fr_type != rs_align_code)
11623 return;
11625 bytes = fragP->fr_next->fr_address - fragP->fr_address - fragP->fr_fix;
11626 p = fragP->fr_literal + fragP->fr_fix;
11627 fix = 0;
11629 if (bytes > MAX_MEM_FOR_RS_ALIGN_CODE)
11630 bytes &= MAX_MEM_FOR_RS_ALIGN_CODE;
11632 if (fragP->tc_frag_data)
11634 if (target_big_endian)
11635 noop = thumb_bigend_noop;
11636 else
11637 noop = thumb_noop;
11638 noop_size = sizeof (thumb_noop);
11640 else
11642 if (target_big_endian)
11643 noop = arm_bigend_noop;
11644 else
11645 noop = arm_noop;
11646 noop_size = sizeof (arm_noop);
11649 if (bytes & (noop_size - 1))
11651 fix = bytes & (noop_size - 1);
11652 memset (p, 0, fix);
11653 p += fix;
11654 bytes -= fix;
11657 while (bytes >= noop_size)
11659 memcpy (p, noop, noop_size);
11660 p += noop_size;
11661 bytes -= noop_size;
11662 fix += noop_size;
11665 fragP->fr_fix += fix;
11666 fragP->fr_var = noop_size;
11669 /* Called from md_do_align. Used to create an alignment
11670 frag in a code section. */
11672 void
11673 arm_frag_align_code (n, max)
11674 int n;
11675 int max;
11677 char * p;
11679 /* We assume that there will never be a requirment
11680 to support alignments greater than 32 bytes. */
11681 if (max > MAX_MEM_FOR_RS_ALIGN_CODE)
11682 as_fatal (_("alignments greater than 32 bytes not supported in .text sections."));
11684 p = frag_var (rs_align_code,
11685 MAX_MEM_FOR_RS_ALIGN_CODE,
11687 (relax_substateT) max,
11688 (symbolS *) NULL,
11689 (offsetT) n,
11690 (char *) NULL);
11691 *p = 0;
11695 /* Perform target specific initialisation of a frag. */
11697 void
11698 arm_init_frag (fragP)
11699 fragS *fragP;
11701 /* Record whether this frag is in an ARM or a THUMB area. */
11702 fragP->tc_frag_data = thumb_mode;