make use of meabi_flags be ELF specific
[deliverable/binutils-gdb.git] / gas / config / tc-arm.c
1 /* tc-arm.c -- Assemble for the ARM
2 Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
3 Free Software Foundation, Inc.
4 Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org)
5 Modified by David Taylor (dtaylor@armltd.co.uk)
6 Cirrus coprocessor mods by Aldy Hernandez (aldyh@redhat.com)
7 Cirrus coprocessor fixes by Petko Manolov (petkan@nucleusys.com)
8 Cirrus coprocessor fixes by Vladimir Ivanov (vladitx@nucleusys.com)
9
10 This file is part of GAS, the GNU Assembler.
11
12 GAS is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2, or (at your option)
15 any later version.
16
17 GAS is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
21
22 You should have received a copy of the GNU General Public License
23 along with GAS; see the file COPYING. If not, write to the Free
24 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
25 02111-1307, USA. */
26
27 #include <string.h>
28 #define NO_RELOC 0
29 #include "as.h"
30 #include "safe-ctype.h"
31
32 /* Need TARGET_CPU. */
33 #include "config.h"
34 #include "subsegs.h"
35 #include "obstack.h"
36 #include "symbols.h"
37 #include "listing.h"
38
39 #ifdef OBJ_ELF
40 #include "elf/arm.h"
41 #include "dwarf2dbg.h"
42 #endif
43
44 /* XXX Set this to 1 after the next binutils release */
45 #define WARN_DEPRECATED 0
46
47 /* The following bitmasks control CPU extensions: */
48 #define ARM_EXT_V1 0x00000001 /* All processors (core set). */
49 #define ARM_EXT_V2 0x00000002 /* Multiply instructions. */
50 #define ARM_EXT_V2S 0x00000004 /* SWP instructions. */
51 #define ARM_EXT_V3 0x00000008 /* MSR MRS. */
52 #define ARM_EXT_V3M 0x00000010 /* Allow long multiplies. */
53 #define ARM_EXT_V4 0x00000020 /* Allow half word loads. */
54 #define ARM_EXT_V4T 0x00000040 /* Thumb v1. */
55 #define ARM_EXT_V5 0x00000080 /* Allow CLZ, etc. */
56 #define ARM_EXT_V5T 0x00000100 /* Thumb v2. */
57 #define ARM_EXT_V5ExP 0x00000200 /* DSP core set. */
58 #define ARM_EXT_V5E 0x00000400 /* DSP Double transfers. */
59 #define ARM_EXT_V5J 0x00000800 /* Jazelle extension. */
60 #define ARM_EXT_V6 0x00001000 /* ARM V6. */
61
62 /* Co-processor space extensions. */
63 #define ARM_CEXT_XSCALE 0x00800000 /* Allow MIA etc. */
64 #define ARM_CEXT_MAVERICK 0x00400000 /* Use Cirrus/DSP coprocessor. */
65 #define ARM_CEXT_IWMMXT 0x00200000 /* Intel Wireless MMX technology coprocessor. */
66
67 /* Architectures are the sum of the base and extensions. The ARM ARM (rev E)
68 defines the following: ARMv3, ARMv3M, ARMv4xM, ARMv4, ARMv4TxM, ARMv4T,
69 ARMv5xM, ARMv5, ARMv5TxM, ARMv5T, ARMv5TExP, ARMv5TE. To these we add
70 three more to cover cores prior to ARM6. Finally, there are cores which
71 implement further extensions in the co-processor space. */
72 #define ARM_ARCH_V1 ARM_EXT_V1
73 #define ARM_ARCH_V2 (ARM_ARCH_V1 | ARM_EXT_V2)
74 #define ARM_ARCH_V2S (ARM_ARCH_V2 | ARM_EXT_V2S)
75 #define ARM_ARCH_V3 (ARM_ARCH_V2S | ARM_EXT_V3)
76 #define ARM_ARCH_V3M (ARM_ARCH_V3 | ARM_EXT_V3M)
77 #define ARM_ARCH_V4xM (ARM_ARCH_V3 | ARM_EXT_V4)
78 #define ARM_ARCH_V4 (ARM_ARCH_V3M | ARM_EXT_V4)
79 #define ARM_ARCH_V4TxM (ARM_ARCH_V4xM | ARM_EXT_V4T)
80 #define ARM_ARCH_V4T (ARM_ARCH_V4 | ARM_EXT_V4T)
81 #define ARM_ARCH_V5xM (ARM_ARCH_V4xM | ARM_EXT_V5)
82 #define ARM_ARCH_V5 (ARM_ARCH_V4 | ARM_EXT_V5)
83 #define ARM_ARCH_V5TxM (ARM_ARCH_V5xM | ARM_EXT_V4T | ARM_EXT_V5T)
84 #define ARM_ARCH_V5T (ARM_ARCH_V5 | ARM_EXT_V4T | ARM_EXT_V5T)
85 #define ARM_ARCH_V5TExP (ARM_ARCH_V5T | ARM_EXT_V5ExP)
86 #define ARM_ARCH_V5TE (ARM_ARCH_V5TExP | ARM_EXT_V5E)
87 #define ARM_ARCH_V5TEJ (ARM_ARCH_V5TE | ARM_EXT_V5J)
88 #define ARM_ARCH_V6 (ARM_ARCH_V5TEJ | ARM_EXT_V6)
89
90 /* Processors with specific extensions in the co-processor space. */
91 #define ARM_ARCH_XSCALE (ARM_ARCH_V5TE | ARM_CEXT_XSCALE)
92 #define ARM_ARCH_IWMMXT (ARM_ARCH_XSCALE | ARM_CEXT_IWMMXT)
93
94 /* Some useful combinations: */
95 #define ARM_ANY 0x0000ffff /* Any basic core. */
96 #define ARM_ALL 0x00ffffff /* Any core + co-processor */
97 #define CPROC_ANY 0x00ff0000 /* Any co-processor */
98 #define FPU_ANY 0xff000000 /* Note this is ~ARM_ALL. */
99
100
101 #define FPU_FPA_EXT_V1 0x80000000 /* Base FPA instruction set. */
102 #define FPU_FPA_EXT_V2 0x40000000 /* LFM/SFM. */
103 #define FPU_VFP_EXT_NONE 0x20000000 /* Use VFP word-ordering. */
104 #define FPU_VFP_EXT_V1xD 0x10000000 /* Base VFP instruction set. */
105 #define FPU_VFP_EXT_V1 0x08000000 /* Double-precision insns. */
106 #define FPU_VFP_EXT_V2 0x04000000 /* ARM10E VFPr1. */
107 #define FPU_MAVERICK 0x02000000 /* Cirrus Maverick. */
108 #define FPU_NONE 0
109
110 #define FPU_ARCH_FPE FPU_FPA_EXT_V1
111 #define FPU_ARCH_FPA (FPU_ARCH_FPE | FPU_FPA_EXT_V2)
112
113 #define FPU_ARCH_VFP FPU_VFP_EXT_NONE
114 #define FPU_ARCH_VFP_V1xD (FPU_VFP_EXT_V1xD | FPU_VFP_EXT_NONE)
115 #define FPU_ARCH_VFP_V1 (FPU_ARCH_VFP_V1xD | FPU_VFP_EXT_V1)
116 #define FPU_ARCH_VFP_V2 (FPU_ARCH_VFP_V1 | FPU_VFP_EXT_V2)
117
118 #define FPU_ARCH_MAVERICK FPU_MAVERICK
119
120 enum arm_float_abi
121 {
122 ARM_FLOAT_ABI_HARD,
123 ARM_FLOAT_ABI_SOFTFP,
124 ARM_FLOAT_ABI_SOFT
125 };
126
127 /* Types of processor to assemble for. */
128 #define ARM_1 ARM_ARCH_V1
129 #define ARM_2 ARM_ARCH_V2
130 #define ARM_3 ARM_ARCH_V2S
131 #define ARM_250 ARM_ARCH_V2S
132 #define ARM_6 ARM_ARCH_V3
133 #define ARM_7 ARM_ARCH_V3
134 #define ARM_8 ARM_ARCH_V4
135 #define ARM_9 ARM_ARCH_V4T
136 #define ARM_STRONG ARM_ARCH_V4
137 #define ARM_CPU_MASK 0x0000000f /* XXX? */
138
139 #ifndef CPU_DEFAULT
140 #if defined __XSCALE__
141 #define CPU_DEFAULT (ARM_ARCH_XSCALE)
142 #else
143 #if defined __thumb__
144 #define CPU_DEFAULT (ARM_ARCH_V5T)
145 #else
146 #define CPU_DEFAULT ARM_ANY
147 #endif
148 #endif
149 #endif
150
151 #ifdef TE_LINUX
152 #define FPU_DEFAULT FPU_ARCH_FPA
153 #endif
154
155 #ifdef TE_NetBSD
156 #ifdef OBJ_ELF
157 #define FPU_DEFAULT FPU_ARCH_VFP /* Soft-float, but VFP order. */
158 #else
159 /* Legacy a.out format. */
160 #define FPU_DEFAULT FPU_ARCH_FPA /* Soft-float, but FPA order. */
161 #endif
162 #endif
163
164 /* For backwards compatibility we default to the FPA. */
165 #ifndef FPU_DEFAULT
166 #define FPU_DEFAULT FPU_ARCH_FPA
167 #endif
168
169 #define streq(a, b) (strcmp (a, b) == 0)
170 #define skip_whitespace(str) while (*(str) == ' ') ++(str)
171
172 static unsigned long cpu_variant;
173 static int target_oabi = 0;
174
175 /* Flags stored in private area of BFD structure. */
176 static int uses_apcs_26 = FALSE;
177 static int atpcs = FALSE;
178 static int support_interwork = FALSE;
179 static int uses_apcs_float = FALSE;
180 static int pic_code = FALSE;
181
182 /* Variables that we set while parsing command-line options. Once all
183 options have been read we re-process these values to set the real
184 assembly flags. */
185 static int legacy_cpu = -1;
186 static int legacy_fpu = -1;
187
188 static int mcpu_cpu_opt = -1;
189 static int mcpu_fpu_opt = -1;
190 static int march_cpu_opt = -1;
191 static int march_fpu_opt = -1;
192 static int mfpu_opt = -1;
193 static int mfloat_abi_opt = -1;
194 #ifdef OBJ_ELF
195 static int meabi_flags = EF_ARM_EABI_UNKNOWN;
196 #endif
197
198 /* This array holds the chars that always start a comment. If the
199 pre-processor is disabled, these aren't very useful. */
200 const char comment_chars[] = "@";
201
202 /* This array holds the chars that only start a comment at the beginning of
203 a line. If the line seems to have the form '# 123 filename'
204 .line and .file directives will appear in the pre-processed output. */
205 /* Note that input_file.c hand checks for '#' at the beginning of the
206 first line of the input file. This is because the compiler outputs
207 #NO_APP at the beginning of its output. */
208 /* Also note that comments like this one will always work. */
209 const char line_comment_chars[] = "#";
210
211 const char line_separator_chars[] = ";";
212
213 /* Chars that can be used to separate mant
214 from exp in floating point numbers. */
215 const char EXP_CHARS[] = "eE";
216
217 /* Chars that mean this number is a floating point constant. */
218 /* As in 0f12.456 */
219 /* or 0d1.2345e12 */
220
221 const char FLT_CHARS[] = "rRsSfFdDxXeEpP";
222
223 /* Prefix characters that indicate the start of an immediate
224 value. */
225 #define is_immediate_prefix(C) ((C) == '#' || (C) == '$')
226
227 #ifdef OBJ_ELF
228 /* Pre-defined "_GLOBAL_OFFSET_TABLE_" */
229 symbolS * GOT_symbol;
230 #endif
231
232 /* Size of relocation record. */
233 const int md_reloc_size = 8;
234
235 /* 0: assemble for ARM,
236 1: assemble for Thumb,
237 2: assemble for Thumb even though target CPU does not support thumb
238 instructions. */
239 static int thumb_mode = 0;
240
241 typedef struct arm_fix
242 {
243 int thumb_mode;
244 } arm_fix_data;
245
246 struct arm_it
247 {
248 const char * error;
249 unsigned long instruction;
250 int size;
251 struct
252 {
253 bfd_reloc_code_real_type type;
254 expressionS exp;
255 int pc_rel;
256 } reloc;
257 };
258
259 struct arm_it inst;
260
261 enum asm_shift_index
262 {
263 SHIFT_LSL = 0,
264 SHIFT_LSR,
265 SHIFT_ASR,
266 SHIFT_ROR,
267 SHIFT_RRX
268 };
269
270 struct asm_shift_properties
271 {
272 enum asm_shift_index index;
273 unsigned long bit_field;
274 unsigned int allows_0 : 1;
275 unsigned int allows_32 : 1;
276 };
277
278 static const struct asm_shift_properties shift_properties [] =
279 {
280 { SHIFT_LSL, 0, 1, 0},
281 { SHIFT_LSR, 0x20, 0, 1},
282 { SHIFT_ASR, 0x40, 0, 1},
283 { SHIFT_ROR, 0x60, 0, 0},
284 { SHIFT_RRX, 0x60, 0, 0}
285 };
286
287 struct asm_shift_name
288 {
289 const char * name;
290 const struct asm_shift_properties * properties;
291 };
292
293 static const struct asm_shift_name shift_names [] =
294 {
295 { "asl", shift_properties + SHIFT_LSL },
296 { "lsl", shift_properties + SHIFT_LSL },
297 { "lsr", shift_properties + SHIFT_LSR },
298 { "asr", shift_properties + SHIFT_ASR },
299 { "ror", shift_properties + SHIFT_ROR },
300 { "rrx", shift_properties + SHIFT_RRX },
301 { "ASL", shift_properties + SHIFT_LSL },
302 { "LSL", shift_properties + SHIFT_LSL },
303 { "LSR", shift_properties + SHIFT_LSR },
304 { "ASR", shift_properties + SHIFT_ASR },
305 { "ROR", shift_properties + SHIFT_ROR },
306 { "RRX", shift_properties + SHIFT_RRX }
307 };
308
309 /* Any kind of shift is accepted. */
310 #define NO_SHIFT_RESTRICT 1
311 /* The shift operand must be an immediate value, not a register. */
312 #define SHIFT_IMMEDIATE 0
313 /* The shift must be LSL or ASR and the operand must be an immediate. */
314 #define SHIFT_LSL_OR_ASR_IMMEDIATE 2
315 /* The shift must be ASR and the operand must be an immediate. */
316 #define SHIFT_ASR_IMMEDIATE 3
317 /* The shift must be LSL and the operand must be an immediate. */
318 #define SHIFT_LSL_IMMEDIATE 4
319
320 #define NUM_FLOAT_VALS 8
321
322 const char * fp_const[] =
323 {
324 "0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0", 0
325 };
326
327 /* Number of littlenums required to hold an extended precision number. */
328 #define MAX_LITTLENUMS 6
329
330 LITTLENUM_TYPE fp_values[NUM_FLOAT_VALS][MAX_LITTLENUMS];
331
332 #define FAIL (-1)
333 #define SUCCESS (0)
334
335 /* Whether a Co-processor load/store operation accepts write-back forms. */
336 #define CP_WB_OK 1
337 #define CP_NO_WB 0
338
339 #define SUFF_S 1
340 #define SUFF_D 2
341 #define SUFF_E 3
342 #define SUFF_P 4
343
344 #define CP_T_X 0x00008000
345 #define CP_T_Y 0x00400000
346 #define CP_T_Pre 0x01000000
347 #define CP_T_UD 0x00800000
348 #define CP_T_WB 0x00200000
349
350 #define CONDS_BIT 0x00100000
351 #define LOAD_BIT 0x00100000
352
353 #define DOUBLE_LOAD_FLAG 0x00000001
354
355 struct asm_cond
356 {
357 const char * template;
358 unsigned long value;
359 };
360
361 #define COND_ALWAYS 0xe0000000
362 #define COND_MASK 0xf0000000
363
364 static const struct asm_cond conds[] =
365 {
366 {"eq", 0x00000000},
367 {"ne", 0x10000000},
368 {"cs", 0x20000000}, {"hs", 0x20000000},
369 {"cc", 0x30000000}, {"ul", 0x30000000}, {"lo", 0x30000000},
370 {"mi", 0x40000000},
371 {"pl", 0x50000000},
372 {"vs", 0x60000000},
373 {"vc", 0x70000000},
374 {"hi", 0x80000000},
375 {"ls", 0x90000000},
376 {"ge", 0xa0000000},
377 {"lt", 0xb0000000},
378 {"gt", 0xc0000000},
379 {"le", 0xd0000000},
380 {"al", 0xe0000000},
381 {"nv", 0xf0000000}
382 };
383
384 struct asm_psr
385 {
386 const char *template;
387 bfd_boolean cpsr;
388 unsigned long field;
389 };
390
391 /* The bit that distinguishes CPSR and SPSR. */
392 #define SPSR_BIT (1 << 22)
393
394 /* How many bits to shift the PSR_xxx bits up by. */
395 #define PSR_SHIFT 16
396
397 #define PSR_c (1 << 0)
398 #define PSR_x (1 << 1)
399 #define PSR_s (1 << 2)
400 #define PSR_f (1 << 3)
401
402 static const struct asm_psr psrs[] =
403 {
404 {"CPSR", TRUE, PSR_c | PSR_f},
405 {"CPSR_all", TRUE, PSR_c | PSR_f},
406 {"SPSR", FALSE, PSR_c | PSR_f},
407 {"SPSR_all", FALSE, PSR_c | PSR_f},
408 {"CPSR_flg", TRUE, PSR_f},
409 {"CPSR_f", TRUE, PSR_f},
410 {"SPSR_flg", FALSE, PSR_f},
411 {"SPSR_f", FALSE, PSR_f},
412 {"CPSR_c", TRUE, PSR_c},
413 {"CPSR_ctl", TRUE, PSR_c},
414 {"SPSR_c", FALSE, PSR_c},
415 {"SPSR_ctl", FALSE, PSR_c},
416 {"CPSR_x", TRUE, PSR_x},
417 {"CPSR_s", TRUE, PSR_s},
418 {"SPSR_x", FALSE, PSR_x},
419 {"SPSR_s", FALSE, PSR_s},
420 /* Combinations of flags. */
421 {"CPSR_fs", TRUE, PSR_f | PSR_s},
422 {"CPSR_fx", TRUE, PSR_f | PSR_x},
423 {"CPSR_fc", TRUE, PSR_f | PSR_c},
424 {"CPSR_sf", TRUE, PSR_s | PSR_f},
425 {"CPSR_sx", TRUE, PSR_s | PSR_x},
426 {"CPSR_sc", TRUE, PSR_s | PSR_c},
427 {"CPSR_xf", TRUE, PSR_x | PSR_f},
428 {"CPSR_xs", TRUE, PSR_x | PSR_s},
429 {"CPSR_xc", TRUE, PSR_x | PSR_c},
430 {"CPSR_cf", TRUE, PSR_c | PSR_f},
431 {"CPSR_cs", TRUE, PSR_c | PSR_s},
432 {"CPSR_cx", TRUE, PSR_c | PSR_x},
433 {"CPSR_fsx", TRUE, PSR_f | PSR_s | PSR_x},
434 {"CPSR_fsc", TRUE, PSR_f | PSR_s | PSR_c},
435 {"CPSR_fxs", TRUE, PSR_f | PSR_x | PSR_s},
436 {"CPSR_fxc", TRUE, PSR_f | PSR_x | PSR_c},
437 {"CPSR_fcs", TRUE, PSR_f | PSR_c | PSR_s},
438 {"CPSR_fcx", TRUE, PSR_f | PSR_c | PSR_x},
439 {"CPSR_sfx", TRUE, PSR_s | PSR_f | PSR_x},
440 {"CPSR_sfc", TRUE, PSR_s | PSR_f | PSR_c},
441 {"CPSR_sxf", TRUE, PSR_s | PSR_x | PSR_f},
442 {"CPSR_sxc", TRUE, PSR_s | PSR_x | PSR_c},
443 {"CPSR_scf", TRUE, PSR_s | PSR_c | PSR_f},
444 {"CPSR_scx", TRUE, PSR_s | PSR_c | PSR_x},
445 {"CPSR_xfs", TRUE, PSR_x | PSR_f | PSR_s},
446 {"CPSR_xfc", TRUE, PSR_x | PSR_f | PSR_c},
447 {"CPSR_xsf", TRUE, PSR_x | PSR_s | PSR_f},
448 {"CPSR_xsc", TRUE, PSR_x | PSR_s | PSR_c},
449 {"CPSR_xcf", TRUE, PSR_x | PSR_c | PSR_f},
450 {"CPSR_xcs", TRUE, PSR_x | PSR_c | PSR_s},
451 {"CPSR_cfs", TRUE, PSR_c | PSR_f | PSR_s},
452 {"CPSR_cfx", TRUE, PSR_c | PSR_f | PSR_x},
453 {"CPSR_csf", TRUE, PSR_c | PSR_s | PSR_f},
454 {"CPSR_csx", TRUE, PSR_c | PSR_s | PSR_x},
455 {"CPSR_cxf", TRUE, PSR_c | PSR_x | PSR_f},
456 {"CPSR_cxs", TRUE, PSR_c | PSR_x | PSR_s},
457 {"CPSR_fsxc", TRUE, PSR_f | PSR_s | PSR_x | PSR_c},
458 {"CPSR_fscx", TRUE, PSR_f | PSR_s | PSR_c | PSR_x},
459 {"CPSR_fxsc", TRUE, PSR_f | PSR_x | PSR_s | PSR_c},
460 {"CPSR_fxcs", TRUE, PSR_f | PSR_x | PSR_c | PSR_s},
461 {"CPSR_fcsx", TRUE, PSR_f | PSR_c | PSR_s | PSR_x},
462 {"CPSR_fcxs", TRUE, PSR_f | PSR_c | PSR_x | PSR_s},
463 {"CPSR_sfxc", TRUE, PSR_s | PSR_f | PSR_x | PSR_c},
464 {"CPSR_sfcx", TRUE, PSR_s | PSR_f | PSR_c | PSR_x},
465 {"CPSR_sxfc", TRUE, PSR_s | PSR_x | PSR_f | PSR_c},
466 {"CPSR_sxcf", TRUE, PSR_s | PSR_x | PSR_c | PSR_f},
467 {"CPSR_scfx", TRUE, PSR_s | PSR_c | PSR_f | PSR_x},
468 {"CPSR_scxf", TRUE, PSR_s | PSR_c | PSR_x | PSR_f},
469 {"CPSR_xfsc", TRUE, PSR_x | PSR_f | PSR_s | PSR_c},
470 {"CPSR_xfcs", TRUE, PSR_x | PSR_f | PSR_c | PSR_s},
471 {"CPSR_xsfc", TRUE, PSR_x | PSR_s | PSR_f | PSR_c},
472 {"CPSR_xscf", TRUE, PSR_x | PSR_s | PSR_c | PSR_f},
473 {"CPSR_xcfs", TRUE, PSR_x | PSR_c | PSR_f | PSR_s},
474 {"CPSR_xcsf", TRUE, PSR_x | PSR_c | PSR_s | PSR_f},
475 {"CPSR_cfsx", TRUE, PSR_c | PSR_f | PSR_s | PSR_x},
476 {"CPSR_cfxs", TRUE, PSR_c | PSR_f | PSR_x | PSR_s},
477 {"CPSR_csfx", TRUE, PSR_c | PSR_s | PSR_f | PSR_x},
478 {"CPSR_csxf", TRUE, PSR_c | PSR_s | PSR_x | PSR_f},
479 {"CPSR_cxfs", TRUE, PSR_c | PSR_x | PSR_f | PSR_s},
480 {"CPSR_cxsf", TRUE, PSR_c | PSR_x | PSR_s | PSR_f},
481 {"SPSR_fs", FALSE, PSR_f | PSR_s},
482 {"SPSR_fx", FALSE, PSR_f | PSR_x},
483 {"SPSR_fc", FALSE, PSR_f | PSR_c},
484 {"SPSR_sf", FALSE, PSR_s | PSR_f},
485 {"SPSR_sx", FALSE, PSR_s | PSR_x},
486 {"SPSR_sc", FALSE, PSR_s | PSR_c},
487 {"SPSR_xf", FALSE, PSR_x | PSR_f},
488 {"SPSR_xs", FALSE, PSR_x | PSR_s},
489 {"SPSR_xc", FALSE, PSR_x | PSR_c},
490 {"SPSR_cf", FALSE, PSR_c | PSR_f},
491 {"SPSR_cs", FALSE, PSR_c | PSR_s},
492 {"SPSR_cx", FALSE, PSR_c | PSR_x},
493 {"SPSR_fsx", FALSE, PSR_f | PSR_s | PSR_x},
494 {"SPSR_fsc", FALSE, PSR_f | PSR_s | PSR_c},
495 {"SPSR_fxs", FALSE, PSR_f | PSR_x | PSR_s},
496 {"SPSR_fxc", FALSE, PSR_f | PSR_x | PSR_c},
497 {"SPSR_fcs", FALSE, PSR_f | PSR_c | PSR_s},
498 {"SPSR_fcx", FALSE, PSR_f | PSR_c | PSR_x},
499 {"SPSR_sfx", FALSE, PSR_s | PSR_f | PSR_x},
500 {"SPSR_sfc", FALSE, PSR_s | PSR_f | PSR_c},
501 {"SPSR_sxf", FALSE, PSR_s | PSR_x | PSR_f},
502 {"SPSR_sxc", FALSE, PSR_s | PSR_x | PSR_c},
503 {"SPSR_scf", FALSE, PSR_s | PSR_c | PSR_f},
504 {"SPSR_scx", FALSE, PSR_s | PSR_c | PSR_x},
505 {"SPSR_xfs", FALSE, PSR_x | PSR_f | PSR_s},
506 {"SPSR_xfc", FALSE, PSR_x | PSR_f | PSR_c},
507 {"SPSR_xsf", FALSE, PSR_x | PSR_s | PSR_f},
508 {"SPSR_xsc", FALSE, PSR_x | PSR_s | PSR_c},
509 {"SPSR_xcf", FALSE, PSR_x | PSR_c | PSR_f},
510 {"SPSR_xcs", FALSE, PSR_x | PSR_c | PSR_s},
511 {"SPSR_cfs", FALSE, PSR_c | PSR_f | PSR_s},
512 {"SPSR_cfx", FALSE, PSR_c | PSR_f | PSR_x},
513 {"SPSR_csf", FALSE, PSR_c | PSR_s | PSR_f},
514 {"SPSR_csx", FALSE, PSR_c | PSR_s | PSR_x},
515 {"SPSR_cxf", FALSE, PSR_c | PSR_x | PSR_f},
516 {"SPSR_cxs", FALSE, PSR_c | PSR_x | PSR_s},
517 {"SPSR_fsxc", FALSE, PSR_f | PSR_s | PSR_x | PSR_c},
518 {"SPSR_fscx", FALSE, PSR_f | PSR_s | PSR_c | PSR_x},
519 {"SPSR_fxsc", FALSE, PSR_f | PSR_x | PSR_s | PSR_c},
520 {"SPSR_fxcs", FALSE, PSR_f | PSR_x | PSR_c | PSR_s},
521 {"SPSR_fcsx", FALSE, PSR_f | PSR_c | PSR_s | PSR_x},
522 {"SPSR_fcxs", FALSE, PSR_f | PSR_c | PSR_x | PSR_s},
523 {"SPSR_sfxc", FALSE, PSR_s | PSR_f | PSR_x | PSR_c},
524 {"SPSR_sfcx", FALSE, PSR_s | PSR_f | PSR_c | PSR_x},
525 {"SPSR_sxfc", FALSE, PSR_s | PSR_x | PSR_f | PSR_c},
526 {"SPSR_sxcf", FALSE, PSR_s | PSR_x | PSR_c | PSR_f},
527 {"SPSR_scfx", FALSE, PSR_s | PSR_c | PSR_f | PSR_x},
528 {"SPSR_scxf", FALSE, PSR_s | PSR_c | PSR_x | PSR_f},
529 {"SPSR_xfsc", FALSE, PSR_x | PSR_f | PSR_s | PSR_c},
530 {"SPSR_xfcs", FALSE, PSR_x | PSR_f | PSR_c | PSR_s},
531 {"SPSR_xsfc", FALSE, PSR_x | PSR_s | PSR_f | PSR_c},
532 {"SPSR_xscf", FALSE, PSR_x | PSR_s | PSR_c | PSR_f},
533 {"SPSR_xcfs", FALSE, PSR_x | PSR_c | PSR_f | PSR_s},
534 {"SPSR_xcsf", FALSE, PSR_x | PSR_c | PSR_s | PSR_f},
535 {"SPSR_cfsx", FALSE, PSR_c | PSR_f | PSR_s | PSR_x},
536 {"SPSR_cfxs", FALSE, PSR_c | PSR_f | PSR_x | PSR_s},
537 {"SPSR_csfx", FALSE, PSR_c | PSR_s | PSR_f | PSR_x},
538 {"SPSR_csxf", FALSE, PSR_c | PSR_s | PSR_x | PSR_f},
539 {"SPSR_cxfs", FALSE, PSR_c | PSR_x | PSR_f | PSR_s},
540 {"SPSR_cxsf", FALSE, PSR_c | PSR_x | PSR_s | PSR_f},
541 };
542
543 enum wreg_type
544 {
545 IWMMXT_REG_WR = 0,
546 IWMMXT_REG_WC = 1,
547 IWMMXT_REG_WR_OR_WC = 2,
548 IWMMXT_REG_WCG
549 };
550
551 enum iwmmxt_insn_type
552 {
553 check_rd,
554 check_wr,
555 check_wrwr,
556 check_wrwrwr,
557 check_wrwrwcg,
558 check_tbcst,
559 check_tmovmsk,
560 check_tmia,
561 check_tmcrr,
562 check_tmrrc,
563 check_tmcr,
564 check_tmrc,
565 check_tinsr,
566 check_textrc,
567 check_waligni,
568 check_textrm,
569 check_wshufh
570 };
571
572 enum vfp_dp_reg_pos
573 {
574 VFP_REG_Dd, VFP_REG_Dm, VFP_REG_Dn
575 };
576
577 enum vfp_sp_reg_pos
578 {
579 VFP_REG_Sd, VFP_REG_Sm, VFP_REG_Sn
580 };
581
582 enum vfp_ldstm_type
583 {
584 VFP_LDSTMIA, VFP_LDSTMDB, VFP_LDSTMIAX, VFP_LDSTMDBX
585 };
586
587 /* VFP system registers. */
588 struct vfp_reg
589 {
590 const char *name;
591 unsigned long regno;
592 };
593
594 static const struct vfp_reg vfp_regs[] =
595 {
596 {"fpsid", 0x00000000},
597 {"FPSID", 0x00000000},
598 {"fpscr", 0x00010000},
599 {"FPSCR", 0x00010000},
600 {"fpexc", 0x00080000},
601 {"FPEXC", 0x00080000}
602 };
603
604 /* Structure for a hash table entry for a register. */
605 struct reg_entry
606 {
607 const char * name;
608 int number;
609 bfd_boolean builtin;
610 };
611
612 /* Some well known registers that we refer to directly elsewhere. */
613 #define REG_SP 13
614 #define REG_LR 14
615 #define REG_PC 15
616
617 #define wr_register(reg) ((reg ^ WR_PREFIX) >= 0 && (reg ^ WR_PREFIX) <= 15)
618 #define wc_register(reg) ((reg ^ WC_PREFIX) >= 0 && (reg ^ WC_PREFIX) <= 15)
619 #define wcg_register(reg) ((reg ^ WC_PREFIX) >= 8 && (reg ^ WC_PREFIX) <= 11)
620
621 /* These are the standard names. Users can add aliases with .req.
622 and delete them with .unreq. */
623
624 /* Integer Register Numbers. */
625 static const struct reg_entry rn_table[] =
626 {
627 {"r0", 0, TRUE}, {"r1", 1, TRUE}, {"r2", 2, TRUE}, {"r3", 3, TRUE},
628 {"r4", 4, TRUE}, {"r5", 5, TRUE}, {"r6", 6, TRUE}, {"r7", 7, TRUE},
629 {"r8", 8, TRUE}, {"r9", 9, TRUE}, {"r10", 10, TRUE}, {"r11", 11, TRUE},
630 {"r12", 12, TRUE}, {"r13", REG_SP, TRUE}, {"r14", REG_LR, TRUE}, {"r15", REG_PC, TRUE},
631 /* ATPCS Synonyms. */
632 {"a1", 0, TRUE}, {"a2", 1, TRUE}, {"a3", 2, TRUE}, {"a4", 3, TRUE},
633 {"v1", 4, TRUE}, {"v2", 5, TRUE}, {"v3", 6, TRUE}, {"v4", 7, TRUE},
634 {"v5", 8, TRUE}, {"v6", 9, TRUE}, {"v7", 10, TRUE}, {"v8", 11, TRUE},
635 /* Well-known aliases. */
636 {"wr", 7, TRUE}, {"sb", 9, TRUE}, {"sl", 10, TRUE}, {"fp", 11, TRUE},
637 {"ip", 12, TRUE}, {"sp", REG_SP, TRUE}, {"lr", REG_LR, TRUE}, {"pc", REG_PC, TRUE},
638 {NULL, 0, TRUE}
639 };
640
641 #define WR_PREFIX 0x200
642 #define WC_PREFIX 0x400
643
644 static const struct reg_entry iwmmxt_table[] =
645 {
646 /* Intel Wireless MMX technology register names. */
647 { "wr0", 0x0 | WR_PREFIX, TRUE}, {"wr1", 0x1 | WR_PREFIX, TRUE},
648 { "wr2", 0x2 | WR_PREFIX, TRUE}, {"wr3", 0x3 | WR_PREFIX, TRUE},
649 { "wr4", 0x4 | WR_PREFIX, TRUE}, {"wr5", 0x5 | WR_PREFIX, TRUE},
650 { "wr6", 0x6 | WR_PREFIX, TRUE}, {"wr7", 0x7 | WR_PREFIX, TRUE},
651 { "wr8", 0x8 | WR_PREFIX, TRUE}, {"wr9", 0x9 | WR_PREFIX, TRUE},
652 { "wr10", 0xa | WR_PREFIX, TRUE}, {"wr11", 0xb | WR_PREFIX, TRUE},
653 { "wr12", 0xc | WR_PREFIX, TRUE}, {"wr13", 0xd | WR_PREFIX, TRUE},
654 { "wr14", 0xe | WR_PREFIX, TRUE}, {"wr15", 0xf | WR_PREFIX, TRUE},
655 { "wcid", 0x0 | WC_PREFIX, TRUE}, {"wcon", 0x1 | WC_PREFIX, TRUE},
656 {"wcssf", 0x2 | WC_PREFIX, TRUE}, {"wcasf", 0x3 | WC_PREFIX, TRUE},
657 {"wcgr0", 0x8 | WC_PREFIX, TRUE}, {"wcgr1", 0x9 | WC_PREFIX, TRUE},
658 {"wcgr2", 0xa | WC_PREFIX, TRUE}, {"wcgr3", 0xb | WC_PREFIX, TRUE},
659
660 { "wR0", 0x0 | WR_PREFIX, TRUE}, {"wR1", 0x1 | WR_PREFIX, TRUE},
661 { "wR2", 0x2 | WR_PREFIX, TRUE}, {"wR3", 0x3 | WR_PREFIX, TRUE},
662 { "wR4", 0x4 | WR_PREFIX, TRUE}, {"wR5", 0x5 | WR_PREFIX, TRUE},
663 { "wR6", 0x6 | WR_PREFIX, TRUE}, {"wR7", 0x7 | WR_PREFIX, TRUE},
664 { "wR8", 0x8 | WR_PREFIX, TRUE}, {"wR9", 0x9 | WR_PREFIX, TRUE},
665 { "wR10", 0xa | WR_PREFIX, TRUE}, {"wR11", 0xb | WR_PREFIX, TRUE},
666 { "wR12", 0xc | WR_PREFIX, TRUE}, {"wR13", 0xd | WR_PREFIX, TRUE},
667 { "wR14", 0xe | WR_PREFIX, TRUE}, {"wR15", 0xf | WR_PREFIX, TRUE},
668 { "wCID", 0x0 | WC_PREFIX, TRUE}, {"wCon", 0x1 | WC_PREFIX, TRUE},
669 {"wCSSF", 0x2 | WC_PREFIX, TRUE}, {"wCASF", 0x3 | WC_PREFIX, TRUE},
670 {"wCGR0", 0x8 | WC_PREFIX, TRUE}, {"wCGR1", 0x9 | WC_PREFIX, TRUE},
671 {"wCGR2", 0xa | WC_PREFIX, TRUE}, {"wCGR3", 0xb | WC_PREFIX, TRUE},
672 {NULL, 0, TRUE}
673 };
674
675 /* Co-processor Numbers. */
676 static const struct reg_entry cp_table[] =
677 {
678 {"p0", 0, TRUE}, {"p1", 1, TRUE}, {"p2", 2, TRUE}, {"p3", 3, TRUE},
679 {"p4", 4, TRUE}, {"p5", 5, TRUE}, {"p6", 6, TRUE}, {"p7", 7, TRUE},
680 {"p8", 8, TRUE}, {"p9", 9, TRUE}, {"p10", 10, TRUE}, {"p11", 11, TRUE},
681 {"p12", 12, TRUE}, {"p13", 13, TRUE}, {"p14", 14, TRUE}, {"p15", 15, TRUE},
682 {NULL, 0, TRUE}
683 };
684
685 /* Co-processor Register Numbers. */
686 static const struct reg_entry cn_table[] =
687 {
688 {"c0", 0, TRUE}, {"c1", 1, TRUE}, {"c2", 2, TRUE}, {"c3", 3, TRUE},
689 {"c4", 4, TRUE}, {"c5", 5, TRUE}, {"c6", 6, TRUE}, {"c7", 7, TRUE},
690 {"c8", 8, TRUE}, {"c9", 9, TRUE}, {"c10", 10, TRUE}, {"c11", 11, TRUE},
691 {"c12", 12, TRUE}, {"c13", 13, TRUE}, {"c14", 14, TRUE}, {"c15", 15, TRUE},
692 /* Not really valid, but kept for back-wards compatibility. */
693 {"cr0", 0, TRUE}, {"cr1", 1, TRUE}, {"cr2", 2, TRUE}, {"cr3", 3, TRUE},
694 {"cr4", 4, TRUE}, {"cr5", 5, TRUE}, {"cr6", 6, TRUE}, {"cr7", 7, TRUE},
695 {"cr8", 8, TRUE}, {"cr9", 9, TRUE}, {"cr10", 10, TRUE}, {"cr11", 11, TRUE},
696 {"cr12", 12, TRUE}, {"cr13", 13, TRUE}, {"cr14", 14, TRUE}, {"cr15", 15, TRUE},
697 {NULL, 0, TRUE}
698 };
699
700 /* FPA Registers. */
701 static const struct reg_entry fn_table[] =
702 {
703 {"f0", 0, TRUE}, {"f1", 1, TRUE}, {"f2", 2, TRUE}, {"f3", 3, TRUE},
704 {"f4", 4, TRUE}, {"f5", 5, TRUE}, {"f6", 6, TRUE}, {"f7", 7, TRUE},
705 {NULL, 0, TRUE}
706 };
707
708 /* VFP SP Registers. */
709 static const struct reg_entry sn_table[] =
710 {
711 {"s0", 0, TRUE}, {"s1", 1, TRUE}, {"s2", 2, TRUE}, {"s3", 3, TRUE},
712 {"s4", 4, TRUE}, {"s5", 5, TRUE}, {"s6", 6, TRUE}, {"s7", 7, TRUE},
713 {"s8", 8, TRUE}, {"s9", 9, TRUE}, {"s10", 10, TRUE}, {"s11", 11, TRUE},
714 {"s12", 12, TRUE}, {"s13", 13, TRUE}, {"s14", 14, TRUE}, {"s15", 15, TRUE},
715 {"s16", 16, TRUE}, {"s17", 17, TRUE}, {"s18", 18, TRUE}, {"s19", 19, TRUE},
716 {"s20", 20, TRUE}, {"s21", 21, TRUE}, {"s22", 22, TRUE}, {"s23", 23, TRUE},
717 {"s24", 24, TRUE}, {"s25", 25, TRUE}, {"s26", 26, TRUE}, {"s27", 27, TRUE},
718 {"s28", 28, TRUE}, {"s29", 29, TRUE}, {"s30", 30, TRUE}, {"s31", 31, TRUE},
719 {NULL, 0, TRUE}
720 };
721
722 /* VFP DP Registers. */
723 static const struct reg_entry dn_table[] =
724 {
725 {"d0", 0, TRUE}, {"d1", 1, TRUE}, {"d2", 2, TRUE}, {"d3", 3, TRUE},
726 {"d4", 4, TRUE}, {"d5", 5, TRUE}, {"d6", 6, TRUE}, {"d7", 7, TRUE},
727 {"d8", 8, TRUE}, {"d9", 9, TRUE}, {"d10", 10, TRUE}, {"d11", 11, TRUE},
728 {"d12", 12, TRUE}, {"d13", 13, TRUE}, {"d14", 14, TRUE}, {"d15", 15, TRUE},
729 {NULL, 0, TRUE}
730 };
731
732 /* Maverick DSP coprocessor registers. */
733 static const struct reg_entry mav_mvf_table[] =
734 {
735 {"mvf0", 0, TRUE}, {"mvf1", 1, TRUE}, {"mvf2", 2, TRUE}, {"mvf3", 3, TRUE},
736 {"mvf4", 4, TRUE}, {"mvf5", 5, TRUE}, {"mvf6", 6, TRUE}, {"mvf7", 7, TRUE},
737 {"mvf8", 8, TRUE}, {"mvf9", 9, TRUE}, {"mvf10", 10, TRUE}, {"mvf11", 11, TRUE},
738 {"mvf12", 12, TRUE}, {"mvf13", 13, TRUE}, {"mvf14", 14, TRUE}, {"mvf15", 15, TRUE},
739 {NULL, 0, TRUE}
740 };
741
742 static const struct reg_entry mav_mvd_table[] =
743 {
744 {"mvd0", 0, TRUE}, {"mvd1", 1, TRUE}, {"mvd2", 2, TRUE}, {"mvd3", 3, TRUE},
745 {"mvd4", 4, TRUE}, {"mvd5", 5, TRUE}, {"mvd6", 6, TRUE}, {"mvd7", 7, TRUE},
746 {"mvd8", 8, TRUE}, {"mvd9", 9, TRUE}, {"mvd10", 10, TRUE}, {"mvd11", 11, TRUE},
747 {"mvd12", 12, TRUE}, {"mvd13", 13, TRUE}, {"mvd14", 14, TRUE}, {"mvd15", 15, TRUE},
748 {NULL, 0, TRUE}
749 };
750
751 static const struct reg_entry mav_mvfx_table[] =
752 {
753 {"mvfx0", 0, TRUE}, {"mvfx1", 1, TRUE}, {"mvfx2", 2, TRUE}, {"mvfx3", 3, TRUE},
754 {"mvfx4", 4, TRUE}, {"mvfx5", 5, TRUE}, {"mvfx6", 6, TRUE}, {"mvfx7", 7, TRUE},
755 {"mvfx8", 8, TRUE}, {"mvfx9", 9, TRUE}, {"mvfx10", 10, TRUE}, {"mvfx11", 11, TRUE},
756 {"mvfx12", 12, TRUE}, {"mvfx13", 13, TRUE}, {"mvfx14", 14, TRUE}, {"mvfx15", 15, TRUE},
757 {NULL, 0, TRUE}
758 };
759
760 static const struct reg_entry mav_mvdx_table[] =
761 {
762 {"mvdx0", 0, TRUE}, {"mvdx1", 1, TRUE}, {"mvdx2", 2, TRUE}, {"mvdx3", 3, TRUE},
763 {"mvdx4", 4, TRUE}, {"mvdx5", 5, TRUE}, {"mvdx6", 6, TRUE}, {"mvdx7", 7, TRUE},
764 {"mvdx8", 8, TRUE}, {"mvdx9", 9, TRUE}, {"mvdx10", 10, TRUE}, {"mvdx11", 11, TRUE},
765 {"mvdx12", 12, TRUE}, {"mvdx13", 13, TRUE}, {"mvdx14", 14, TRUE}, {"mvdx15", 15, TRUE},
766 {NULL, 0, TRUE}
767 };
768
769 static const struct reg_entry mav_mvax_table[] =
770 {
771 {"mvax0", 0, TRUE}, {"mvax1", 1, TRUE}, {"mvax2", 2, TRUE}, {"mvax3", 3, TRUE},
772 {NULL, 0, TRUE}
773 };
774
775 static const struct reg_entry mav_dspsc_table[] =
776 {
777 {"dspsc", 0, TRUE},
778 {NULL, 0, TRUE}
779 };
780
781 struct reg_map
782 {
783 const struct reg_entry *names;
784 int max_regno;
785 struct hash_control *htab;
786 const char *expected;
787 };
788
789 struct reg_map all_reg_maps[] =
790 {
791 {rn_table, 15, NULL, N_("ARM register expected")},
792 {cp_table, 15, NULL, N_("bad or missing co-processor number")},
793 {cn_table, 15, NULL, N_("co-processor register expected")},
794 {fn_table, 7, NULL, N_("FPA register expected")},
795 {sn_table, 31, NULL, N_("VFP single precision register expected")},
796 {dn_table, 15, NULL, N_("VFP double precision register expected")},
797 {mav_mvf_table, 15, NULL, N_("Maverick MVF register expected")},
798 {mav_mvd_table, 15, NULL, N_("Maverick MVD register expected")},
799 {mav_mvfx_table, 15, NULL, N_("Maverick MVFX register expected")},
800 {mav_mvdx_table, 15, NULL, N_("Maverick MVDX register expected")},
801 {mav_mvax_table, 3, NULL, N_("Maverick MVAX register expected")},
802 {mav_dspsc_table, 0, NULL, N_("Maverick DSPSC register expected")},
803 {iwmmxt_table, 23, NULL, N_("Intel Wireless MMX technology register expected")},
804 };
805
806 /* Enumeration matching entries in table above. */
807 enum arm_reg_type
808 {
809 REG_TYPE_RN = 0,
810 #define REG_TYPE_FIRST REG_TYPE_RN
811 REG_TYPE_CP = 1,
812 REG_TYPE_CN = 2,
813 REG_TYPE_FN = 3,
814 REG_TYPE_SN = 4,
815 REG_TYPE_DN = 5,
816 REG_TYPE_MVF = 6,
817 REG_TYPE_MVD = 7,
818 REG_TYPE_MVFX = 8,
819 REG_TYPE_MVDX = 9,
820 REG_TYPE_MVAX = 10,
821 REG_TYPE_DSPSC = 11,
822 REG_TYPE_IWMMXT = 12,
823
824 REG_TYPE_MAX = 13
825 };
826
827 /* Functions called by parser. */
828 /* ARM instructions. */
829 static void do_arit PARAMS ((char *));
830 static void do_cmp PARAMS ((char *));
831 static void do_mov PARAMS ((char *));
832 static void do_ldst PARAMS ((char *));
833 static void do_ldstt PARAMS ((char *));
834 static void do_ldmstm PARAMS ((char *));
835 static void do_branch PARAMS ((char *));
836 static void do_swi PARAMS ((char *));
837
838 /* Pseudo Op codes. */
839 static void do_adr PARAMS ((char *));
840 static void do_adrl PARAMS ((char *));
841 static void do_empty PARAMS ((char *));
842
843 /* ARM v2. */
844 static void do_mul PARAMS ((char *));
845 static void do_mla PARAMS ((char *));
846
847 /* ARM v2S. */
848 static void do_swap PARAMS ((char *));
849
850 /* ARM v3. */
851 static void do_msr PARAMS ((char *));
852 static void do_mrs PARAMS ((char *));
853
854 /* ARM v3M. */
855 static void do_mull PARAMS ((char *));
856
857 /* ARM v4. */
858 static void do_ldstv4 PARAMS ((char *));
859
860 /* ARM v4T. */
861 static void do_bx PARAMS ((char *));
862
863 /* ARM v5T. */
864 static void do_blx PARAMS ((char *));
865 static void do_bkpt PARAMS ((char *));
866 static void do_clz PARAMS ((char *));
867 static void do_lstc2 PARAMS ((char *));
868 static void do_cdp2 PARAMS ((char *));
869 static void do_co_reg2 PARAMS ((char *));
870
871 /* ARM v5TExP. */
872 static void do_smla PARAMS ((char *));
873 static void do_smlal PARAMS ((char *));
874 static void do_smul PARAMS ((char *));
875 static void do_qadd PARAMS ((char *));
876
877 /* ARM v5TE. */
878 static void do_pld PARAMS ((char *));
879 static void do_ldrd PARAMS ((char *));
880 static void do_co_reg2c PARAMS ((char *));
881
882 /* ARM v5TEJ. */
883 static void do_bxj PARAMS ((char *));
884
885 /* ARM V6. */
886 static void do_cps PARAMS ((char *));
887 static void do_cpsi PARAMS ((char *));
888 static void do_ldrex PARAMS ((char *));
889 static void do_pkhbt PARAMS ((char *));
890 static void do_pkhtb PARAMS ((char *));
891 static void do_qadd16 PARAMS ((char *));
892 static void do_rev PARAMS ((char *));
893 static void do_rfe PARAMS ((char *));
894 static void do_sxtah PARAMS ((char *));
895 static void do_sxth PARAMS ((char *));
896 static void do_setend PARAMS ((char *));
897 static void do_smlad PARAMS ((char *));
898 static void do_smlald PARAMS ((char *));
899 static void do_smmul PARAMS ((char *));
900 static void do_ssat PARAMS ((char *));
901 static void do_usat PARAMS ((char *));
902 static void do_srs PARAMS ((char *));
903 static void do_ssat16 PARAMS ((char *));
904 static void do_usat16 PARAMS ((char *));
905 static void do_strex PARAMS ((char *));
906 static void do_umaal PARAMS ((char *));
907
908 static void do_cps_mode PARAMS ((char **));
909 static void do_cps_flags PARAMS ((char **, int));
910 static int do_endian_specifier PARAMS ((char *));
911 static void do_pkh_core PARAMS ((char *, int));
912 static void do_sat PARAMS ((char **, int));
913 static void do_sat16 PARAMS ((char **, int));
914
915 /* Coprocessor Instructions. */
916 static void do_cdp PARAMS ((char *));
917 static void do_lstc PARAMS ((char *));
918 static void do_co_reg PARAMS ((char *));
919
920 /* FPA instructions. */
921 static void do_fpa_ctrl PARAMS ((char *));
922 static void do_fpa_ldst PARAMS ((char *));
923 static void do_fpa_ldmstm PARAMS ((char *));
924 static void do_fpa_dyadic PARAMS ((char *));
925 static void do_fpa_monadic PARAMS ((char *));
926 static void do_fpa_cmp PARAMS ((char *));
927 static void do_fpa_from_reg PARAMS ((char *));
928 static void do_fpa_to_reg PARAMS ((char *));
929
930 /* VFP instructions. */
931 static void do_vfp_sp_monadic PARAMS ((char *));
932 static void do_vfp_dp_monadic PARAMS ((char *));
933 static void do_vfp_sp_dyadic PARAMS ((char *));
934 static void do_vfp_dp_dyadic PARAMS ((char *));
935 static void do_vfp_reg_from_sp PARAMS ((char *));
936 static void do_vfp_sp_from_reg PARAMS ((char *));
937 static void do_vfp_reg2_from_sp2 PARAMS ((char *));
938 static void do_vfp_sp2_from_reg2 PARAMS ((char *));
939 static void do_vfp_reg_from_dp PARAMS ((char *));
940 static void do_vfp_reg2_from_dp PARAMS ((char *));
941 static void do_vfp_dp_from_reg PARAMS ((char *));
942 static void do_vfp_dp_from_reg2 PARAMS ((char *));
943 static void do_vfp_reg_from_ctrl PARAMS ((char *));
944 static void do_vfp_ctrl_from_reg PARAMS ((char *));
945 static void do_vfp_sp_ldst PARAMS ((char *));
946 static void do_vfp_dp_ldst PARAMS ((char *));
947 static void do_vfp_sp_ldstmia PARAMS ((char *));
948 static void do_vfp_sp_ldstmdb PARAMS ((char *));
949 static void do_vfp_dp_ldstmia PARAMS ((char *));
950 static void do_vfp_dp_ldstmdb PARAMS ((char *));
951 static void do_vfp_xp_ldstmia PARAMS ((char *));
952 static void do_vfp_xp_ldstmdb PARAMS ((char *));
953 static void do_vfp_sp_compare_z PARAMS ((char *));
954 static void do_vfp_dp_compare_z PARAMS ((char *));
955 static void do_vfp_dp_sp_cvt PARAMS ((char *));
956 static void do_vfp_sp_dp_cvt PARAMS ((char *));
957
958 /* XScale. */
959 static void do_xsc_mia PARAMS ((char *));
960 static void do_xsc_mar PARAMS ((char *));
961 static void do_xsc_mra PARAMS ((char *));
962
963 /* Maverick. */
964 static void do_mav_binops PARAMS ((char *, int, enum arm_reg_type,
965 enum arm_reg_type));
966 static void do_mav_binops_1a PARAMS ((char *));
967 static void do_mav_binops_1b PARAMS ((char *));
968 static void do_mav_binops_1c PARAMS ((char *));
969 static void do_mav_binops_1d PARAMS ((char *));
970 static void do_mav_binops_1e PARAMS ((char *));
971 static void do_mav_binops_1f PARAMS ((char *));
972 static void do_mav_binops_1g PARAMS ((char *));
973 static void do_mav_binops_1h PARAMS ((char *));
974 static void do_mav_binops_1i PARAMS ((char *));
975 static void do_mav_binops_1j PARAMS ((char *));
976 static void do_mav_binops_1k PARAMS ((char *));
977 static void do_mav_binops_1l PARAMS ((char *));
978 static void do_mav_binops_1m PARAMS ((char *));
979 static void do_mav_binops_1n PARAMS ((char *));
980 static void do_mav_binops_1o PARAMS ((char *));
981 static void do_mav_binops_2a PARAMS ((char *));
982 static void do_mav_binops_2b PARAMS ((char *));
983 static void do_mav_binops_2c PARAMS ((char *));
984 static void do_mav_binops_3a PARAMS ((char *));
985 static void do_mav_binops_3b PARAMS ((char *));
986 static void do_mav_binops_3c PARAMS ((char *));
987 static void do_mav_binops_3d PARAMS ((char *));
988 static void do_mav_triple PARAMS ((char *, int, enum arm_reg_type,
989 enum arm_reg_type,
990 enum arm_reg_type));
991 static void do_mav_triple_4a PARAMS ((char *));
992 static void do_mav_triple_4b PARAMS ((char *));
993 static void do_mav_triple_5a PARAMS ((char *));
994 static void do_mav_triple_5b PARAMS ((char *));
995 static void do_mav_triple_5c PARAMS ((char *));
996 static void do_mav_triple_5d PARAMS ((char *));
997 static void do_mav_triple_5e PARAMS ((char *));
998 static void do_mav_triple_5f PARAMS ((char *));
999 static void do_mav_triple_5g PARAMS ((char *));
1000 static void do_mav_triple_5h PARAMS ((char *));
1001 static void do_mav_quad PARAMS ((char *, int, enum arm_reg_type,
1002 enum arm_reg_type,
1003 enum arm_reg_type,
1004 enum arm_reg_type));
1005 static void do_mav_quad_6a PARAMS ((char *));
1006 static void do_mav_quad_6b PARAMS ((char *));
1007 static void do_mav_dspsc_1 PARAMS ((char *));
1008 static void do_mav_dspsc_2 PARAMS ((char *));
1009 static void do_mav_shift PARAMS ((char *, enum arm_reg_type,
1010 enum arm_reg_type));
1011 static void do_mav_shift_1 PARAMS ((char *));
1012 static void do_mav_shift_2 PARAMS ((char *));
1013 static void do_mav_ldst PARAMS ((char *, enum arm_reg_type));
1014 static void do_mav_ldst_1 PARAMS ((char *));
1015 static void do_mav_ldst_2 PARAMS ((char *));
1016 static void do_mav_ldst_3 PARAMS ((char *));
1017 static void do_mav_ldst_4 PARAMS ((char *));
1018
1019 static int mav_reg_required_here PARAMS ((char **, int,
1020 enum arm_reg_type));
1021 static int mav_parse_offset PARAMS ((char **, int *));
1022
1023 static void fix_new_arm PARAMS ((fragS *, int, short, expressionS *,
1024 int, int));
1025 static int arm_reg_parse PARAMS ((char **, struct hash_control *));
1026 static enum arm_reg_type arm_reg_parse_any PARAMS ((char *));
1027 static const struct asm_psr * arm_psr_parse PARAMS ((char **));
1028 static void symbol_locate PARAMS ((symbolS *, const char *, segT, valueT,
1029 fragS *));
1030 static int add_to_lit_pool PARAMS ((void));
1031 static unsigned validate_immediate PARAMS ((unsigned));
1032 static unsigned validate_immediate_twopart PARAMS ((unsigned int,
1033 unsigned int *));
1034 static int validate_offset_imm PARAMS ((unsigned int, int));
1035 static void opcode_select PARAMS ((int));
1036 static void end_of_line PARAMS ((char *));
1037 static int reg_required_here PARAMS ((char **, int));
1038 static int psr_required_here PARAMS ((char **));
1039 static int co_proc_number PARAMS ((char **));
1040 static int cp_opc_expr PARAMS ((char **, int, int));
1041 static int cp_reg_required_here PARAMS ((char **, int));
1042 static int fp_reg_required_here PARAMS ((char **, int));
1043 static int vfp_sp_reg_required_here PARAMS ((char **, enum vfp_sp_reg_pos));
1044 static int vfp_dp_reg_required_here PARAMS ((char **, enum vfp_dp_reg_pos));
1045 static void vfp_sp_ldstm PARAMS ((char *, enum vfp_ldstm_type));
1046 static void vfp_dp_ldstm PARAMS ((char *, enum vfp_ldstm_type));
1047 static long vfp_sp_reg_list PARAMS ((char **, enum vfp_sp_reg_pos));
1048 static long vfp_dp_reg_list PARAMS ((char **));
1049 static int vfp_psr_required_here PARAMS ((char **str));
1050 static const struct vfp_reg *vfp_psr_parse PARAMS ((char **str));
1051 static int cp_address_offset PARAMS ((char **));
1052 static int cp_address_required_here PARAMS ((char **, int));
1053 static int my_get_float_expression PARAMS ((char **));
1054 static int skip_past_comma PARAMS ((char **));
1055 static int walk_no_bignums PARAMS ((symbolS *));
1056 static int negate_data_op PARAMS ((unsigned long *, unsigned long));
1057 static int data_op2 PARAMS ((char **));
1058 static int fp_op2 PARAMS ((char **));
1059 static long reg_list PARAMS ((char **));
1060 static void thumb_load_store PARAMS ((char *, int, int));
1061 static int decode_shift PARAMS ((char **, int));
1062 static int ldst_extend PARAMS ((char **));
1063 static int ldst_extend_v4 PARAMS ((char **));
1064 static void thumb_add_sub PARAMS ((char *, int));
1065 static void insert_reg PARAMS ((const struct reg_entry *,
1066 struct hash_control *));
1067 static void thumb_shift PARAMS ((char *, int));
1068 static void thumb_mov_compare PARAMS ((char *, int));
1069 static void build_arm_ops_hsh PARAMS ((void));
1070 static void set_constant_flonums PARAMS ((void));
1071 static valueT md_chars_to_number PARAMS ((char *, int));
1072 static void build_reg_hsh PARAMS ((struct reg_map *));
1073 static void insert_reg_alias PARAMS ((char *, int, struct hash_control *));
1074 static int create_register_alias PARAMS ((char *, char *));
1075 static void output_inst PARAMS ((const char *));
1076 static int accum0_required_here PARAMS ((char **));
1077 static int ld_mode_required_here PARAMS ((char **));
1078 static void do_branch25 PARAMS ((char *));
1079 static symbolS * find_real_start PARAMS ((symbolS *));
1080 #ifdef OBJ_ELF
1081 static bfd_reloc_code_real_type arm_parse_reloc PARAMS ((void));
1082 #endif
1083
1084 static int wreg_required_here PARAMS ((char **, int, enum wreg_type));
1085 static void do_iwmmxt_byte_addr PARAMS ((char *));
1086 static void do_iwmmxt_tandc PARAMS ((char *));
1087 static void do_iwmmxt_tbcst PARAMS ((char *));
1088 static void do_iwmmxt_textrc PARAMS ((char *));
1089 static void do_iwmmxt_textrm PARAMS ((char *));
1090 static void do_iwmmxt_tinsr PARAMS ((char *));
1091 static void do_iwmmxt_tmcr PARAMS ((char *));
1092 static void do_iwmmxt_tmcrr PARAMS ((char *));
1093 static void do_iwmmxt_tmia PARAMS ((char *));
1094 static void do_iwmmxt_tmovmsk PARAMS ((char *));
1095 static void do_iwmmxt_tmrc PARAMS ((char *));
1096 static void do_iwmmxt_tmrrc PARAMS ((char *));
1097 static void do_iwmmxt_torc PARAMS ((char *));
1098 static void do_iwmmxt_waligni PARAMS ((char *));
1099 static void do_iwmmxt_wmov PARAMS ((char *));
1100 static void do_iwmmxt_word_addr PARAMS ((char *));
1101 static void do_iwmmxt_wrwr PARAMS ((char *));
1102 static void do_iwmmxt_wrwrwcg PARAMS ((char *));
1103 static void do_iwmmxt_wrwrwr PARAMS ((char *));
1104 static void do_iwmmxt_wshufh PARAMS ((char *));
1105 static void do_iwmmxt_wzero PARAMS ((char *));
1106 static int cp_byte_address_offset PARAMS ((char **));
1107 static int cp_byte_address_required_here PARAMS ((char **));
1108
1109 /* ARM instructions take 4bytes in the object file, Thumb instructions
1110 take 2: */
1111 #define INSN_SIZE 4
1112
1113 /* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
1114 #define MAV_MODE1 0x100c
1115
1116 /* "INSN<cond> X,Y" where X:bit16, Y:bit12. */
1117 #define MAV_MODE2 0x0c10
1118
1119 /* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
1120 #define MAV_MODE3 0x100c
1121
1122 /* "INSN<cond> X,Y,Z" where X:16, Y:0, Z:12. */
1123 #define MAV_MODE4 0x0c0010
1124
1125 /* "INSN<cond> X,Y,Z" where X:12, Y:16, Z:0. */
1126 #define MAV_MODE5 0x00100c
1127
1128 /* "INSN<cond> W,X,Y,Z" where W:5, X:12, Y:16, Z:0. */
1129 #define MAV_MODE6 0x00100c05
1130
1131 struct asm_opcode
1132 {
1133 /* Basic string to match. */
1134 const char * template;
1135
1136 /* Basic instruction code. */
1137 unsigned long value;
1138
1139 /* Offset into the template where the condition code (if any) will be.
1140 If zero, then the instruction is never conditional. */
1141 unsigned cond_offset;
1142
1143 /* Which architecture variant provides this instruction. */
1144 unsigned long variant;
1145
1146 /* Function to call to parse args. */
1147 void (* parms) PARAMS ((char *));
1148 };
1149
1150 static const struct asm_opcode insns[] =
1151 {
1152 /* Core ARM Instructions. */
1153 {"and", 0xe0000000, 3, ARM_EXT_V1, do_arit},
1154 {"ands", 0xe0100000, 3, ARM_EXT_V1, do_arit},
1155 {"eor", 0xe0200000, 3, ARM_EXT_V1, do_arit},
1156 {"eors", 0xe0300000, 3, ARM_EXT_V1, do_arit},
1157 {"sub", 0xe0400000, 3, ARM_EXT_V1, do_arit},
1158 {"subs", 0xe0500000, 3, ARM_EXT_V1, do_arit},
1159 {"rsb", 0xe0600000, 3, ARM_EXT_V1, do_arit},
1160 {"rsbs", 0xe0700000, 3, ARM_EXT_V1, do_arit},
1161 {"add", 0xe0800000, 3, ARM_EXT_V1, do_arit},
1162 {"adds", 0xe0900000, 3, ARM_EXT_V1, do_arit},
1163 {"adc", 0xe0a00000, 3, ARM_EXT_V1, do_arit},
1164 {"adcs", 0xe0b00000, 3, ARM_EXT_V1, do_arit},
1165 {"sbc", 0xe0c00000, 3, ARM_EXT_V1, do_arit},
1166 {"sbcs", 0xe0d00000, 3, ARM_EXT_V1, do_arit},
1167 {"rsc", 0xe0e00000, 3, ARM_EXT_V1, do_arit},
1168 {"rscs", 0xe0f00000, 3, ARM_EXT_V1, do_arit},
1169 {"orr", 0xe1800000, 3, ARM_EXT_V1, do_arit},
1170 {"orrs", 0xe1900000, 3, ARM_EXT_V1, do_arit},
1171 {"bic", 0xe1c00000, 3, ARM_EXT_V1, do_arit},
1172 {"bics", 0xe1d00000, 3, ARM_EXT_V1, do_arit},
1173
1174 {"tst", 0xe1100000, 3, ARM_EXT_V1, do_cmp},
1175 {"tsts", 0xe1100000, 3, ARM_EXT_V1, do_cmp},
1176 {"tstp", 0xe110f000, 3, ARM_EXT_V1, do_cmp},
1177 {"teq", 0xe1300000, 3, ARM_EXT_V1, do_cmp},
1178 {"teqs", 0xe1300000, 3, ARM_EXT_V1, do_cmp},
1179 {"teqp", 0xe130f000, 3, ARM_EXT_V1, do_cmp},
1180 {"cmp", 0xe1500000, 3, ARM_EXT_V1, do_cmp},
1181 {"cmps", 0xe1500000, 3, ARM_EXT_V1, do_cmp},
1182 {"cmpp", 0xe150f000, 3, ARM_EXT_V1, do_cmp},
1183 {"cmn", 0xe1700000, 3, ARM_EXT_V1, do_cmp},
1184 {"cmns", 0xe1700000, 3, ARM_EXT_V1, do_cmp},
1185 {"cmnp", 0xe170f000, 3, ARM_EXT_V1, do_cmp},
1186
1187 {"mov", 0xe1a00000, 3, ARM_EXT_V1, do_mov},
1188 {"movs", 0xe1b00000, 3, ARM_EXT_V1, do_mov},
1189 {"mvn", 0xe1e00000, 3, ARM_EXT_V1, do_mov},
1190 {"mvns", 0xe1f00000, 3, ARM_EXT_V1, do_mov},
1191
1192 {"ldr", 0xe4100000, 3, ARM_EXT_V1, do_ldst},
1193 {"ldrb", 0xe4500000, 3, ARM_EXT_V1, do_ldst},
1194 {"ldrt", 0xe4300000, 3, ARM_EXT_V1, do_ldstt},
1195 {"ldrbt", 0xe4700000, 3, ARM_EXT_V1, do_ldstt},
1196 {"str", 0xe4000000, 3, ARM_EXT_V1, do_ldst},
1197 {"strb", 0xe4400000, 3, ARM_EXT_V1, do_ldst},
1198 {"strt", 0xe4200000, 3, ARM_EXT_V1, do_ldstt},
1199 {"strbt", 0xe4600000, 3, ARM_EXT_V1, do_ldstt},
1200
1201 {"stmia", 0xe8800000, 3, ARM_EXT_V1, do_ldmstm},
1202 {"stmib", 0xe9800000, 3, ARM_EXT_V1, do_ldmstm},
1203 {"stmda", 0xe8000000, 3, ARM_EXT_V1, do_ldmstm},
1204 {"stmdb", 0xe9000000, 3, ARM_EXT_V1, do_ldmstm},
1205 {"stmfd", 0xe9000000, 3, ARM_EXT_V1, do_ldmstm},
1206 {"stmfa", 0xe9800000, 3, ARM_EXT_V1, do_ldmstm},
1207 {"stmea", 0xe8800000, 3, ARM_EXT_V1, do_ldmstm},
1208 {"stmed", 0xe8000000, 3, ARM_EXT_V1, do_ldmstm},
1209
1210 {"ldmia", 0xe8900000, 3, ARM_EXT_V1, do_ldmstm},
1211 {"ldmib", 0xe9900000, 3, ARM_EXT_V1, do_ldmstm},
1212 {"ldmda", 0xe8100000, 3, ARM_EXT_V1, do_ldmstm},
1213 {"ldmdb", 0xe9100000, 3, ARM_EXT_V1, do_ldmstm},
1214 {"ldmfd", 0xe8900000, 3, ARM_EXT_V1, do_ldmstm},
1215 {"ldmfa", 0xe8100000, 3, ARM_EXT_V1, do_ldmstm},
1216 {"ldmea", 0xe9100000, 3, ARM_EXT_V1, do_ldmstm},
1217 {"ldmed", 0xe9900000, 3, ARM_EXT_V1, do_ldmstm},
1218
1219 {"swi", 0xef000000, 3, ARM_EXT_V1, do_swi},
1220 #ifdef TE_WINCE
1221 /* XXX This is the wrong place to do this. Think multi-arch. */
1222 {"bl", 0xeb000000, 2, ARM_EXT_V1, do_branch},
1223 {"b", 0xea000000, 1, ARM_EXT_V1, do_branch},
1224 #else
1225 {"bl", 0xebfffffe, 2, ARM_EXT_V1, do_branch},
1226 {"b", 0xeafffffe, 1, ARM_EXT_V1, do_branch},
1227 #endif
1228
1229 /* Pseudo ops. */
1230 {"adr", 0xe28f0000, 3, ARM_EXT_V1, do_adr},
1231 {"adrl", 0xe28f0000, 3, ARM_EXT_V1, do_adrl},
1232 {"nop", 0xe1a00000, 3, ARM_EXT_V1, do_empty},
1233
1234 /* ARM 2 multiplies. */
1235 {"mul", 0xe0000090, 3, ARM_EXT_V2, do_mul},
1236 {"muls", 0xe0100090, 3, ARM_EXT_V2, do_mul},
1237 {"mla", 0xe0200090, 3, ARM_EXT_V2, do_mla},
1238 {"mlas", 0xe0300090, 3, ARM_EXT_V2, do_mla},
1239
1240 /* Generic coprocessor instructions. */
1241 {"cdp", 0xee000000, 3, ARM_EXT_V2, do_cdp},
1242 {"ldc", 0xec100000, 3, ARM_EXT_V2, do_lstc},
1243 {"ldcl", 0xec500000, 3, ARM_EXT_V2, do_lstc},
1244 {"stc", 0xec000000, 3, ARM_EXT_V2, do_lstc},
1245 {"stcl", 0xec400000, 3, ARM_EXT_V2, do_lstc},
1246 {"mcr", 0xee000010, 3, ARM_EXT_V2, do_co_reg},
1247 {"mrc", 0xee100010, 3, ARM_EXT_V2, do_co_reg},
1248
1249 /* ARM 3 - swp instructions. */
1250 {"swp", 0xe1000090, 3, ARM_EXT_V2S, do_swap},
1251 {"swpb", 0xe1400090, 3, ARM_EXT_V2S, do_swap},
1252
1253 /* ARM 6 Status register instructions. */
1254 {"mrs", 0xe10f0000, 3, ARM_EXT_V3, do_mrs},
1255 {"msr", 0xe120f000, 3, ARM_EXT_V3, do_msr},
1256 /* ScottB: our code uses 0xe128f000 for msr.
1257 NickC: but this is wrong because the bits 16 through 19 are
1258 handled by the PSR_xxx defines above. */
1259
1260 /* ARM 7M long multiplies. */
1261 {"smull", 0xe0c00090, 5, ARM_EXT_V3M, do_mull},
1262 {"smulls", 0xe0d00090, 5, ARM_EXT_V3M, do_mull},
1263 {"umull", 0xe0800090, 5, ARM_EXT_V3M, do_mull},
1264 {"umulls", 0xe0900090, 5, ARM_EXT_V3M, do_mull},
1265 {"smlal", 0xe0e00090, 5, ARM_EXT_V3M, do_mull},
1266 {"smlals", 0xe0f00090, 5, ARM_EXT_V3M, do_mull},
1267 {"umlal", 0xe0a00090, 5, ARM_EXT_V3M, do_mull},
1268 {"umlals", 0xe0b00090, 5, ARM_EXT_V3M, do_mull},
1269
1270 /* ARM Architecture 4. */
1271 {"ldrh", 0xe01000b0, 3, ARM_EXT_V4, do_ldstv4},
1272 {"ldrsh", 0xe01000f0, 3, ARM_EXT_V4, do_ldstv4},
1273 {"ldrsb", 0xe01000d0, 3, ARM_EXT_V4, do_ldstv4},
1274 {"strh", 0xe00000b0, 3, ARM_EXT_V4, do_ldstv4},
1275
1276 /* ARM Architecture 4T. */
1277 /* Note: bx (and blx) are required on V5, even if the processor does
1278 not support Thumb. */
1279 {"bx", 0xe12fff10, 2, ARM_EXT_V4T | ARM_EXT_V5, do_bx},
1280
1281 /* ARM Architecture 5T. */
1282 /* Note: blx has 2 variants, so the .value is set dynamically.
1283 Only one of the variants has conditional execution. */
1284 {"blx", 0xe0000000, 3, ARM_EXT_V5, do_blx},
1285 {"clz", 0xe16f0f10, 3, ARM_EXT_V5, do_clz},
1286 {"bkpt", 0xe1200070, 0, ARM_EXT_V5, do_bkpt},
1287 {"ldc2", 0xfc100000, 0, ARM_EXT_V5, do_lstc2},
1288 {"ldc2l", 0xfc500000, 0, ARM_EXT_V5, do_lstc2},
1289 {"stc2", 0xfc000000, 0, ARM_EXT_V5, do_lstc2},
1290 {"stc2l", 0xfc400000, 0, ARM_EXT_V5, do_lstc2},
1291 {"cdp2", 0xfe000000, 0, ARM_EXT_V5, do_cdp2},
1292 {"mcr2", 0xfe000010, 0, ARM_EXT_V5, do_co_reg2},
1293 {"mrc2", 0xfe100010, 0, ARM_EXT_V5, do_co_reg2},
1294
1295 /* ARM Architecture 5TExP. */
1296 {"smlabb", 0xe1000080, 6, ARM_EXT_V5ExP, do_smla},
1297 {"smlatb", 0xe10000a0, 6, ARM_EXT_V5ExP, do_smla},
1298 {"smlabt", 0xe10000c0, 6, ARM_EXT_V5ExP, do_smla},
1299 {"smlatt", 0xe10000e0, 6, ARM_EXT_V5ExP, do_smla},
1300
1301 {"smlawb", 0xe1200080, 6, ARM_EXT_V5ExP, do_smla},
1302 {"smlawt", 0xe12000c0, 6, ARM_EXT_V5ExP, do_smla},
1303
1304 {"smlalbb", 0xe1400080, 7, ARM_EXT_V5ExP, do_smlal},
1305 {"smlaltb", 0xe14000a0, 7, ARM_EXT_V5ExP, do_smlal},
1306 {"smlalbt", 0xe14000c0, 7, ARM_EXT_V5ExP, do_smlal},
1307 {"smlaltt", 0xe14000e0, 7, ARM_EXT_V5ExP, do_smlal},
1308
1309 {"smulbb", 0xe1600080, 6, ARM_EXT_V5ExP, do_smul},
1310 {"smultb", 0xe16000a0, 6, ARM_EXT_V5ExP, do_smul},
1311 {"smulbt", 0xe16000c0, 6, ARM_EXT_V5ExP, do_smul},
1312 {"smultt", 0xe16000e0, 6, ARM_EXT_V5ExP, do_smul},
1313
1314 {"smulwb", 0xe12000a0, 6, ARM_EXT_V5ExP, do_smul},
1315 {"smulwt", 0xe12000e0, 6, ARM_EXT_V5ExP, do_smul},
1316
1317 {"qadd", 0xe1000050, 4, ARM_EXT_V5ExP, do_qadd},
1318 {"qdadd", 0xe1400050, 5, ARM_EXT_V5ExP, do_qadd},
1319 {"qsub", 0xe1200050, 4, ARM_EXT_V5ExP, do_qadd},
1320 {"qdsub", 0xe1600050, 5, ARM_EXT_V5ExP, do_qadd},
1321
1322 /* ARM Architecture 5TE. */
1323 {"pld", 0xf450f000, 0, ARM_EXT_V5E, do_pld},
1324 {"ldrd", 0xe00000d0, 3, ARM_EXT_V5E, do_ldrd},
1325 {"strd", 0xe00000f0, 3, ARM_EXT_V5E, do_ldrd},
1326
1327 {"mcrr", 0xec400000, 4, ARM_EXT_V5E, do_co_reg2c},
1328 {"mrrc", 0xec500000, 4, ARM_EXT_V5E, do_co_reg2c},
1329
1330 /* ARM Architecture 5TEJ. */
1331 {"bxj", 0xe12fff20, 3, ARM_EXT_V5J, do_bxj},
1332
1333 /* ARM V6. */
1334 { "cps", 0xf1020000, 0, ARM_EXT_V6, do_cps},
1335 { "cpsie", 0xf1080000, 0, ARM_EXT_V6, do_cpsi},
1336 { "cpsid", 0xf10C0000, 0, ARM_EXT_V6, do_cpsi},
1337 { "ldrex", 0xe1900f9f, 5, ARM_EXT_V6, do_ldrex},
1338 { "mcrr2", 0xfc400000, 0, ARM_EXT_V6, do_co_reg2c},
1339 { "mrrc2", 0xfc500000, 0, ARM_EXT_V6, do_co_reg2c},
1340 { "pkhbt", 0xe6800010, 5, ARM_EXT_V6, do_pkhbt},
1341 { "pkhtb", 0xe6800050, 5, ARM_EXT_V6, do_pkhtb},
1342 { "qadd16", 0xe6200f10, 6, ARM_EXT_V6, do_qadd16},
1343 { "qadd8", 0xe6200f90, 5, ARM_EXT_V6, do_qadd16},
1344 { "qaddsubx", 0xe6200f30, 8, ARM_EXT_V6, do_qadd16},
1345 { "qsub16", 0xe6200f70, 6, ARM_EXT_V6, do_qadd16},
1346 { "qsub8", 0xe6200ff0, 5, ARM_EXT_V6, do_qadd16},
1347 { "qsubaddx", 0xe6200f50, 8, ARM_EXT_V6, do_qadd16},
1348 { "sadd16", 0xe6100f10, 6, ARM_EXT_V6, do_qadd16},
1349 { "sadd8", 0xe6100f90, 5, ARM_EXT_V6, do_qadd16},
1350 { "saddsubx", 0xe6100f30, 8, ARM_EXT_V6, do_qadd16},
1351 { "shadd16", 0xe6300f10, 7, ARM_EXT_V6, do_qadd16},
1352 { "shadd8", 0xe6300f90, 6, ARM_EXT_V6, do_qadd16},
1353 { "shaddsubx", 0xe6300f30, 9, ARM_EXT_V6, do_qadd16},
1354 { "shsub16", 0xe6300f70, 7, ARM_EXT_V6, do_qadd16},
1355 { "shsub8", 0xe6300ff0, 6, ARM_EXT_V6, do_qadd16},
1356 { "shsubaddx", 0xe6300f50, 9, ARM_EXT_V6, do_qadd16},
1357 { "ssub16", 0xe6100f70, 6, ARM_EXT_V6, do_qadd16},
1358 { "ssub8", 0xe6100ff0, 5, ARM_EXT_V6, do_qadd16},
1359 { "ssubaddx", 0xe6100f50, 8, ARM_EXT_V6, do_qadd16},
1360 { "uadd16", 0xe6500f10, 6, ARM_EXT_V6, do_qadd16},
1361 { "uadd8", 0xe6500f90, 5, ARM_EXT_V6, do_qadd16},
1362 { "uaddsubx", 0xe6500f30, 8, ARM_EXT_V6, do_qadd16},
1363 { "uhadd16", 0xe6700f10, 7, ARM_EXT_V6, do_qadd16},
1364 { "uhadd8", 0xe6700f90, 6, ARM_EXT_V6, do_qadd16},
1365 { "uhaddsubx", 0xe6700f30, 9, ARM_EXT_V6, do_qadd16},
1366 { "uhsub16", 0xe6700f70, 7, ARM_EXT_V6, do_qadd16},
1367 { "uhsub8", 0xe6700ff0, 6, ARM_EXT_V6, do_qadd16},
1368 { "uhsubaddx", 0xe6700f50, 9, ARM_EXT_V6, do_qadd16},
1369 { "uqadd16", 0xe6600f10, 7, ARM_EXT_V6, do_qadd16},
1370 { "uqadd8", 0xe6600f90, 6, ARM_EXT_V6, do_qadd16},
1371 { "uqaddsubx", 0xe6600f30, 9, ARM_EXT_V6, do_qadd16},
1372 { "uqsub16", 0xe6600f70, 7, ARM_EXT_V6, do_qadd16},
1373 { "uqsub8", 0xe6600ff0, 6, ARM_EXT_V6, do_qadd16},
1374 { "uqsubaddx", 0xe6600f50, 9, ARM_EXT_V6, do_qadd16},
1375 { "usub16", 0xe6500f70, 6, ARM_EXT_V6, do_qadd16},
1376 { "usub8", 0xe6500ff0, 5, ARM_EXT_V6, do_qadd16},
1377 { "usubaddx", 0xe6500f50, 8, ARM_EXT_V6, do_qadd16},
1378 { "rev", 0xe6bf0f30, 3, ARM_EXT_V6, do_rev},
1379 { "rev16", 0xe6bf0fb0, 5, ARM_EXT_V6, do_rev},
1380 { "revsh", 0xe6ff0fb0, 5, ARM_EXT_V6, do_rev},
1381 { "rfeia", 0xf8900a00, 0, ARM_EXT_V6, do_rfe},
1382 { "rfeib", 0xf9900a00, 0, ARM_EXT_V6, do_rfe},
1383 { "rfeda", 0xf8100a00, 0, ARM_EXT_V6, do_rfe},
1384 { "rfedb", 0xf9100a00, 0, ARM_EXT_V6, do_rfe},
1385 { "rfefd", 0xf8900a00, 0, ARM_EXT_V6, do_rfe},
1386 { "rfefa", 0xf9900a00, 0, ARM_EXT_V6, do_rfe},
1387 { "rfeea", 0xf8100a00, 0, ARM_EXT_V6, do_rfe},
1388 { "rfeed", 0xf9100a00, 0, ARM_EXT_V6, do_rfe},
1389 { "sxtah", 0xe6b00070, 5, ARM_EXT_V6, do_sxtah},
1390 { "sxtab16", 0xe6800070, 7, ARM_EXT_V6, do_sxtah},
1391 { "sxtab", 0xe6a00070, 5, ARM_EXT_V6, do_sxtah},
1392 { "sxth", 0xe6bf0070, 4, ARM_EXT_V6, do_sxth},
1393 { "sxtb16", 0xe68f0070, 6, ARM_EXT_V6, do_sxth},
1394 { "sxtb", 0xe6af0070, 4, ARM_EXT_V6, do_sxth},
1395 { "uxtah", 0xe6f00070, 5, ARM_EXT_V6, do_sxtah},
1396 { "uxtab16", 0xe6c00070, 7, ARM_EXT_V6, do_sxtah},
1397 { "uxtab", 0xe6e00070, 5, ARM_EXT_V6, do_sxtah},
1398 { "uxth", 0xe6ff0070, 4, ARM_EXT_V6, do_sxth},
1399 { "uxtb16", 0xe6cf0070, 6, ARM_EXT_V6, do_sxth},
1400 { "uxtb", 0xe6ef0070, 4, ARM_EXT_V6, do_sxth},
1401 { "sel", 0xe68000b0, 3, ARM_EXT_V6, do_qadd16},
1402 { "setend", 0xf1010000, 0, ARM_EXT_V6, do_setend},
1403 { "smlad", 0xe7000010, 5, ARM_EXT_V6, do_smlad},
1404 { "smladx", 0xe7000030, 6, ARM_EXT_V6, do_smlad},
1405 { "smlald", 0xe7400010, 6, ARM_EXT_V6, do_smlald},
1406 { "smlaldx", 0xe7400030, 7, ARM_EXT_V6, do_smlald},
1407 { "smlsd", 0xe7000050, 5, ARM_EXT_V6, do_smlad},
1408 { "smlsdx", 0xe7000070, 6, ARM_EXT_V6, do_smlad},
1409 { "smlsld", 0xe7400050, 6, ARM_EXT_V6, do_smlald},
1410 { "smlsldx", 0xe7400070, 7, ARM_EXT_V6, do_smlald},
1411 { "smmla", 0xe7500010, 5, ARM_EXT_V6, do_smlad},
1412 { "smmlar", 0xe7500030, 6, ARM_EXT_V6, do_smlad},
1413 { "smmls", 0xe75000d0, 5, ARM_EXT_V6, do_smlad},
1414 { "smmlsr", 0xe75000f0, 6, ARM_EXT_V6, do_smlad},
1415 { "smmul", 0xe750f010, 5, ARM_EXT_V6, do_smmul},
1416 { "smmulr", 0xe750f030, 6, ARM_EXT_V6, do_smmul},
1417 { "smuad", 0xe700f010, 5, ARM_EXT_V6, do_smmul},
1418 { "smuadx", 0xe700f030, 6, ARM_EXT_V6, do_smmul},
1419 { "smusd", 0xe700f050, 5, ARM_EXT_V6, do_smmul},
1420 { "smusdx", 0xe700f070, 6, ARM_EXT_V6, do_smmul},
1421 { "srsia", 0xf8cd0500, 0, ARM_EXT_V6, do_srs},
1422 { "srsib", 0xf9cd0500, 0, ARM_EXT_V6, do_srs},
1423 { "srsda", 0xf84d0500, 0, ARM_EXT_V6, do_srs},
1424 { "srsdb", 0xf94d0500, 0, ARM_EXT_V6, do_srs},
1425 { "ssat", 0xe6a00010, 4, ARM_EXT_V6, do_ssat},
1426 { "ssat16", 0xe6a00f30, 6, ARM_EXT_V6, do_ssat16},
1427 { "strex", 0xe1800f90, 5, ARM_EXT_V6, do_strex},
1428 { "umaal", 0xe0400090, 5, ARM_EXT_V6, do_umaal},
1429 { "usad8", 0xe780f010, 5, ARM_EXT_V6, do_smmul},
1430 { "usada8", 0xe7800010, 6, ARM_EXT_V6, do_smlad},
1431 { "usat", 0xe6e00010, 4, ARM_EXT_V6, do_usat},
1432 { "usat16", 0xe6e00f30, 6, ARM_EXT_V6, do_usat16},
1433
1434 /* Core FPA instruction set (V1). */
1435 {"wfs", 0xee200110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
1436 {"rfs", 0xee300110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
1437 {"wfc", 0xee400110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
1438 {"rfc", 0xee500110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
1439
1440 {"ldfs", 0xec100100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1441 {"ldfd", 0xec108100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1442 {"ldfe", 0xec500100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1443 {"ldfp", 0xec508100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1444
1445 {"stfs", 0xec000100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1446 {"stfd", 0xec008100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1447 {"stfe", 0xec400100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1448 {"stfp", 0xec408100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1449
1450 {"mvfs", 0xee008100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1451 {"mvfsp", 0xee008120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1452 {"mvfsm", 0xee008140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1453 {"mvfsz", 0xee008160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1454 {"mvfd", 0xee008180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1455 {"mvfdp", 0xee0081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1456 {"mvfdm", 0xee0081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1457 {"mvfdz", 0xee0081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1458 {"mvfe", 0xee088100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1459 {"mvfep", 0xee088120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1460 {"mvfem", 0xee088140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1461 {"mvfez", 0xee088160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1462
1463 {"mnfs", 0xee108100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1464 {"mnfsp", 0xee108120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1465 {"mnfsm", 0xee108140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1466 {"mnfsz", 0xee108160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1467 {"mnfd", 0xee108180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1468 {"mnfdp", 0xee1081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1469 {"mnfdm", 0xee1081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1470 {"mnfdz", 0xee1081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1471 {"mnfe", 0xee188100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1472 {"mnfep", 0xee188120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1473 {"mnfem", 0xee188140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1474 {"mnfez", 0xee188160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1475
1476 {"abss", 0xee208100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1477 {"abssp", 0xee208120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1478 {"abssm", 0xee208140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1479 {"abssz", 0xee208160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1480 {"absd", 0xee208180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1481 {"absdp", 0xee2081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1482 {"absdm", 0xee2081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1483 {"absdz", 0xee2081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1484 {"abse", 0xee288100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1485 {"absep", 0xee288120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1486 {"absem", 0xee288140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1487 {"absez", 0xee288160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1488
1489 {"rnds", 0xee308100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1490 {"rndsp", 0xee308120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1491 {"rndsm", 0xee308140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1492 {"rndsz", 0xee308160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1493 {"rndd", 0xee308180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1494 {"rnddp", 0xee3081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1495 {"rnddm", 0xee3081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1496 {"rnddz", 0xee3081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1497 {"rnde", 0xee388100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1498 {"rndep", 0xee388120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1499 {"rndem", 0xee388140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1500 {"rndez", 0xee388160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1501
1502 {"sqts", 0xee408100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1503 {"sqtsp", 0xee408120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1504 {"sqtsm", 0xee408140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1505 {"sqtsz", 0xee408160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1506 {"sqtd", 0xee408180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1507 {"sqtdp", 0xee4081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1508 {"sqtdm", 0xee4081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1509 {"sqtdz", 0xee4081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1510 {"sqte", 0xee488100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1511 {"sqtep", 0xee488120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1512 {"sqtem", 0xee488140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1513 {"sqtez", 0xee488160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1514
1515 {"logs", 0xee508100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1516 {"logsp", 0xee508120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1517 {"logsm", 0xee508140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1518 {"logsz", 0xee508160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1519 {"logd", 0xee508180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1520 {"logdp", 0xee5081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1521 {"logdm", 0xee5081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1522 {"logdz", 0xee5081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1523 {"loge", 0xee588100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1524 {"logep", 0xee588120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1525 {"logem", 0xee588140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1526 {"logez", 0xee588160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1527
1528 {"lgns", 0xee608100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1529 {"lgnsp", 0xee608120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1530 {"lgnsm", 0xee608140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1531 {"lgnsz", 0xee608160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1532 {"lgnd", 0xee608180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1533 {"lgndp", 0xee6081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1534 {"lgndm", 0xee6081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1535 {"lgndz", 0xee6081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1536 {"lgne", 0xee688100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1537 {"lgnep", 0xee688120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1538 {"lgnem", 0xee688140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1539 {"lgnez", 0xee688160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1540
1541 {"exps", 0xee708100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1542 {"expsp", 0xee708120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1543 {"expsm", 0xee708140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1544 {"expsz", 0xee708160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1545 {"expd", 0xee708180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1546 {"expdp", 0xee7081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1547 {"expdm", 0xee7081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1548 {"expdz", 0xee7081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1549 {"expe", 0xee788100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1550 {"expep", 0xee788120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1551 {"expem", 0xee788140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1552 {"expdz", 0xee788160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1553
1554 {"sins", 0xee808100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1555 {"sinsp", 0xee808120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1556 {"sinsm", 0xee808140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1557 {"sinsz", 0xee808160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1558 {"sind", 0xee808180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1559 {"sindp", 0xee8081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1560 {"sindm", 0xee8081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1561 {"sindz", 0xee8081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1562 {"sine", 0xee888100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1563 {"sinep", 0xee888120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1564 {"sinem", 0xee888140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1565 {"sinez", 0xee888160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1566
1567 {"coss", 0xee908100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1568 {"cossp", 0xee908120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1569 {"cossm", 0xee908140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1570 {"cossz", 0xee908160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1571 {"cosd", 0xee908180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1572 {"cosdp", 0xee9081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1573 {"cosdm", 0xee9081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1574 {"cosdz", 0xee9081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1575 {"cose", 0xee988100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1576 {"cosep", 0xee988120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1577 {"cosem", 0xee988140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1578 {"cosez", 0xee988160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1579
1580 {"tans", 0xeea08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1581 {"tansp", 0xeea08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1582 {"tansm", 0xeea08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1583 {"tansz", 0xeea08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1584 {"tand", 0xeea08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1585 {"tandp", 0xeea081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1586 {"tandm", 0xeea081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1587 {"tandz", 0xeea081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1588 {"tane", 0xeea88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1589 {"tanep", 0xeea88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1590 {"tanem", 0xeea88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1591 {"tanez", 0xeea88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1592
1593 {"asns", 0xeeb08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1594 {"asnsp", 0xeeb08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1595 {"asnsm", 0xeeb08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1596 {"asnsz", 0xeeb08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1597 {"asnd", 0xeeb08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1598 {"asndp", 0xeeb081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1599 {"asndm", 0xeeb081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1600 {"asndz", 0xeeb081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1601 {"asne", 0xeeb88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1602 {"asnep", 0xeeb88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1603 {"asnem", 0xeeb88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1604 {"asnez", 0xeeb88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1605
1606 {"acss", 0xeec08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1607 {"acssp", 0xeec08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1608 {"acssm", 0xeec08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1609 {"acssz", 0xeec08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1610 {"acsd", 0xeec08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1611 {"acsdp", 0xeec081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1612 {"acsdm", 0xeec081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1613 {"acsdz", 0xeec081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1614 {"acse", 0xeec88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1615 {"acsep", 0xeec88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1616 {"acsem", 0xeec88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1617 {"acsez", 0xeec88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1618
1619 {"atns", 0xeed08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1620 {"atnsp", 0xeed08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1621 {"atnsm", 0xeed08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1622 {"atnsz", 0xeed08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1623 {"atnd", 0xeed08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1624 {"atndp", 0xeed081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1625 {"atndm", 0xeed081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1626 {"atndz", 0xeed081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1627 {"atne", 0xeed88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1628 {"atnep", 0xeed88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1629 {"atnem", 0xeed88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1630 {"atnez", 0xeed88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1631
1632 {"urds", 0xeee08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1633 {"urdsp", 0xeee08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1634 {"urdsm", 0xeee08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1635 {"urdsz", 0xeee08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1636 {"urdd", 0xeee08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1637 {"urddp", 0xeee081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1638 {"urddm", 0xeee081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1639 {"urddz", 0xeee081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1640 {"urde", 0xeee88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1641 {"urdep", 0xeee88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1642 {"urdem", 0xeee88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1643 {"urdez", 0xeee88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1644
1645 {"nrms", 0xeef08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1646 {"nrmsp", 0xeef08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1647 {"nrmsm", 0xeef08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1648 {"nrmsz", 0xeef08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1649 {"nrmd", 0xeef08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1650 {"nrmdp", 0xeef081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1651 {"nrmdm", 0xeef081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1652 {"nrmdz", 0xeef081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1653 {"nrme", 0xeef88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1654 {"nrmep", 0xeef88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1655 {"nrmem", 0xeef88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1656 {"nrmez", 0xeef88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1657
1658 {"adfs", 0xee000100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1659 {"adfsp", 0xee000120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1660 {"adfsm", 0xee000140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1661 {"adfsz", 0xee000160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1662 {"adfd", 0xee000180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1663 {"adfdp", 0xee0001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1664 {"adfdm", 0xee0001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1665 {"adfdz", 0xee0001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1666 {"adfe", 0xee080100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1667 {"adfep", 0xee080120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1668 {"adfem", 0xee080140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1669 {"adfez", 0xee080160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1670
1671 {"sufs", 0xee200100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1672 {"sufsp", 0xee200120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1673 {"sufsm", 0xee200140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1674 {"sufsz", 0xee200160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1675 {"sufd", 0xee200180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1676 {"sufdp", 0xee2001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1677 {"sufdm", 0xee2001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1678 {"sufdz", 0xee2001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1679 {"sufe", 0xee280100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1680 {"sufep", 0xee280120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1681 {"sufem", 0xee280140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1682 {"sufez", 0xee280160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1683
1684 {"rsfs", 0xee300100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1685 {"rsfsp", 0xee300120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1686 {"rsfsm", 0xee300140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1687 {"rsfsz", 0xee300160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1688 {"rsfd", 0xee300180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1689 {"rsfdp", 0xee3001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1690 {"rsfdm", 0xee3001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1691 {"rsfdz", 0xee3001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1692 {"rsfe", 0xee380100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1693 {"rsfep", 0xee380120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1694 {"rsfem", 0xee380140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1695 {"rsfez", 0xee380160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1696
1697 {"mufs", 0xee100100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1698 {"mufsp", 0xee100120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1699 {"mufsm", 0xee100140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1700 {"mufsz", 0xee100160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1701 {"mufd", 0xee100180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1702 {"mufdp", 0xee1001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1703 {"mufdm", 0xee1001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1704 {"mufdz", 0xee1001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1705 {"mufe", 0xee180100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1706 {"mufep", 0xee180120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1707 {"mufem", 0xee180140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1708 {"mufez", 0xee180160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1709
1710 {"dvfs", 0xee400100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1711 {"dvfsp", 0xee400120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1712 {"dvfsm", 0xee400140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1713 {"dvfsz", 0xee400160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1714 {"dvfd", 0xee400180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1715 {"dvfdp", 0xee4001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1716 {"dvfdm", 0xee4001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1717 {"dvfdz", 0xee4001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1718 {"dvfe", 0xee480100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1719 {"dvfep", 0xee480120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1720 {"dvfem", 0xee480140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1721 {"dvfez", 0xee480160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1722
1723 {"rdfs", 0xee500100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1724 {"rdfsp", 0xee500120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1725 {"rdfsm", 0xee500140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1726 {"rdfsz", 0xee500160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1727 {"rdfd", 0xee500180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1728 {"rdfdp", 0xee5001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1729 {"rdfdm", 0xee5001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1730 {"rdfdz", 0xee5001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1731 {"rdfe", 0xee580100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1732 {"rdfep", 0xee580120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1733 {"rdfem", 0xee580140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1734 {"rdfez", 0xee580160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1735
1736 {"pows", 0xee600100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1737 {"powsp", 0xee600120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1738 {"powsm", 0xee600140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1739 {"powsz", 0xee600160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1740 {"powd", 0xee600180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1741 {"powdp", 0xee6001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1742 {"powdm", 0xee6001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1743 {"powdz", 0xee6001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1744 {"powe", 0xee680100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1745 {"powep", 0xee680120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1746 {"powem", 0xee680140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1747 {"powez", 0xee680160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1748
1749 {"rpws", 0xee700100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1750 {"rpwsp", 0xee700120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1751 {"rpwsm", 0xee700140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1752 {"rpwsz", 0xee700160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1753 {"rpwd", 0xee700180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1754 {"rpwdp", 0xee7001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1755 {"rpwdm", 0xee7001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1756 {"rpwdz", 0xee7001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1757 {"rpwe", 0xee780100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1758 {"rpwep", 0xee780120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1759 {"rpwem", 0xee780140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1760 {"rpwez", 0xee780160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1761
1762 {"rmfs", 0xee800100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1763 {"rmfsp", 0xee800120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1764 {"rmfsm", 0xee800140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1765 {"rmfsz", 0xee800160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1766 {"rmfd", 0xee800180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1767 {"rmfdp", 0xee8001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1768 {"rmfdm", 0xee8001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1769 {"rmfdz", 0xee8001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1770 {"rmfe", 0xee880100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1771 {"rmfep", 0xee880120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1772 {"rmfem", 0xee880140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1773 {"rmfez", 0xee880160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1774
1775 {"fmls", 0xee900100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1776 {"fmlsp", 0xee900120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1777 {"fmlsm", 0xee900140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1778 {"fmlsz", 0xee900160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1779 {"fmld", 0xee900180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1780 {"fmldp", 0xee9001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1781 {"fmldm", 0xee9001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1782 {"fmldz", 0xee9001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1783 {"fmle", 0xee980100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1784 {"fmlep", 0xee980120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1785 {"fmlem", 0xee980140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1786 {"fmlez", 0xee980160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1787
1788 {"fdvs", 0xeea00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1789 {"fdvsp", 0xeea00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1790 {"fdvsm", 0xeea00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1791 {"fdvsz", 0xeea00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1792 {"fdvd", 0xeea00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1793 {"fdvdp", 0xeea001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1794 {"fdvdm", 0xeea001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1795 {"fdvdz", 0xeea001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1796 {"fdve", 0xeea80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1797 {"fdvep", 0xeea80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1798 {"fdvem", 0xeea80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1799 {"fdvez", 0xeea80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1800
1801 {"frds", 0xeeb00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1802 {"frdsp", 0xeeb00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1803 {"frdsm", 0xeeb00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1804 {"frdsz", 0xeeb00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1805 {"frdd", 0xeeb00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1806 {"frddp", 0xeeb001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1807 {"frddm", 0xeeb001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1808 {"frddz", 0xeeb001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1809 {"frde", 0xeeb80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1810 {"frdep", 0xeeb80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1811 {"frdem", 0xeeb80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1812 {"frdez", 0xeeb80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1813
1814 {"pols", 0xeec00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1815 {"polsp", 0xeec00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1816 {"polsm", 0xeec00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1817 {"polsz", 0xeec00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1818 {"pold", 0xeec00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1819 {"poldp", 0xeec001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1820 {"poldm", 0xeec001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1821 {"poldz", 0xeec001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1822 {"pole", 0xeec80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1823 {"polep", 0xeec80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1824 {"polem", 0xeec80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1825 {"polez", 0xeec80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1826
1827 {"cmf", 0xee90f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
1828 {"cmfe", 0xeed0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
1829 {"cnf", 0xeeb0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
1830 {"cnfe", 0xeef0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
1831 /* The FPA10 data sheet suggests that the 'E' of cmfe/cnfe should
1832 not be an optional suffix, but part of the instruction. To be
1833 compatible, we accept either. */
1834 {"cmfe", 0xeed0f110, 4, FPU_FPA_EXT_V1, do_fpa_cmp},
1835 {"cnfe", 0xeef0f110, 4, FPU_FPA_EXT_V1, do_fpa_cmp},
1836
1837 {"flts", 0xee000110, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1838 {"fltsp", 0xee000130, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1839 {"fltsm", 0xee000150, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1840 {"fltsz", 0xee000170, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1841 {"fltd", 0xee000190, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1842 {"fltdp", 0xee0001b0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1843 {"fltdm", 0xee0001d0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1844 {"fltdz", 0xee0001f0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1845 {"flte", 0xee080110, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1846 {"fltep", 0xee080130, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1847 {"fltem", 0xee080150, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1848 {"fltez", 0xee080170, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1849
1850 /* The implementation of the FIX instruction is broken on some
1851 assemblers, in that it accepts a precision specifier as well as a
1852 rounding specifier, despite the fact that this is meaningless.
1853 To be more compatible, we accept it as well, though of course it
1854 does not set any bits. */
1855 {"fix", 0xee100110, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1856 {"fixp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1857 {"fixm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1858 {"fixz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1859 {"fixsp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1860 {"fixsm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1861 {"fixsz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1862 {"fixdp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1863 {"fixdm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1864 {"fixdz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1865 {"fixep", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1866 {"fixem", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1867 {"fixez", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1868
1869 /* Instructions that were new with the real FPA, call them V2. */
1870 {"lfm", 0xec100200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1871 {"lfmfd", 0xec900200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1872 {"lfmea", 0xed100200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1873 {"sfm", 0xec000200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1874 {"sfmfd", 0xed000200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1875 {"sfmea", 0xec800200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1876
1877 /* VFP V1xD (single precision). */
1878 /* Moves and type conversions. */
1879 {"fcpys", 0xeeb00a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1880 {"fmrs", 0xee100a10, 4, FPU_VFP_EXT_V1xD, do_vfp_reg_from_sp},
1881 {"fmsr", 0xee000a10, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_from_reg},
1882 {"fmstat", 0xeef1fa10, 6, FPU_VFP_EXT_V1xD, do_empty},
1883 {"fsitos", 0xeeb80ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1884 {"fuitos", 0xeeb80a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1885 {"ftosis", 0xeebd0a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1886 {"ftosizs", 0xeebd0ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1887 {"ftouis", 0xeebc0a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1888 {"ftouizs", 0xeebc0ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1889 {"fmrx", 0xeef00a10, 4, FPU_VFP_EXT_V1xD, do_vfp_reg_from_ctrl},
1890 {"fmxr", 0xeee00a10, 4, FPU_VFP_EXT_V1xD, do_vfp_ctrl_from_reg},
1891
1892 /* Memory operations. */
1893 {"flds", 0xed100a00, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_ldst},
1894 {"fsts", 0xed000a00, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_ldst},
1895 {"fldmias", 0xec900a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
1896 {"fldmfds", 0xec900a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
1897 {"fldmdbs", 0xed300a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
1898 {"fldmeas", 0xed300a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
1899 {"fldmiax", 0xec900b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
1900 {"fldmfdx", 0xec900b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
1901 {"fldmdbx", 0xed300b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
1902 {"fldmeax", 0xed300b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
1903 {"fstmias", 0xec800a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
1904 {"fstmeas", 0xec800a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
1905 {"fstmdbs", 0xed200a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
1906 {"fstmfds", 0xed200a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
1907 {"fstmiax", 0xec800b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
1908 {"fstmeax", 0xec800b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
1909 {"fstmdbx", 0xed200b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
1910 {"fstmfdx", 0xed200b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
1911
1912 /* Monadic operations. */
1913 {"fabss", 0xeeb00ac0, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1914 {"fnegs", 0xeeb10a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1915 {"fsqrts", 0xeeb10ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1916
1917 /* Dyadic operations. */
1918 {"fadds", 0xee300a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1919 {"fsubs", 0xee300a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1920 {"fmuls", 0xee200a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1921 {"fdivs", 0xee800a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1922 {"fmacs", 0xee000a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1923 {"fmscs", 0xee100a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1924 {"fnmuls", 0xee200a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1925 {"fnmacs", 0xee000a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1926 {"fnmscs", 0xee100a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1927
1928 /* Comparisons. */
1929 {"fcmps", 0xeeb40a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1930 {"fcmpzs", 0xeeb50a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_compare_z},
1931 {"fcmpes", 0xeeb40ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1932 {"fcmpezs", 0xeeb50ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_compare_z},
1933
1934 /* VFP V1 (Double precision). */
1935 /* Moves and type conversions. */
1936 {"fcpyd", 0xeeb00b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1937 {"fcvtds", 0xeeb70ac0, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
1938 {"fcvtsd", 0xeeb70bc0, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
1939 {"fmdhr", 0xee200b10, 5, FPU_VFP_EXT_V1, do_vfp_dp_from_reg},
1940 {"fmdlr", 0xee000b10, 5, FPU_VFP_EXT_V1, do_vfp_dp_from_reg},
1941 {"fmrdh", 0xee300b10, 5, FPU_VFP_EXT_V1, do_vfp_reg_from_dp},
1942 {"fmrdl", 0xee100b10, 5, FPU_VFP_EXT_V1, do_vfp_reg_from_dp},
1943 {"fsitod", 0xeeb80bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
1944 {"fuitod", 0xeeb80b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
1945 {"ftosid", 0xeebd0b40, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
1946 {"ftosizd", 0xeebd0bc0, 7, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
1947 {"ftouid", 0xeebc0b40, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
1948 {"ftouizd", 0xeebc0bc0, 7, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
1949
1950 /* Memory operations. */
1951 {"fldd", 0xed100b00, 4, FPU_VFP_EXT_V1, do_vfp_dp_ldst},
1952 {"fstd", 0xed000b00, 4, FPU_VFP_EXT_V1, do_vfp_dp_ldst},
1953 {"fldmiad", 0xec900b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
1954 {"fldmfdd", 0xec900b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
1955 {"fldmdbd", 0xed300b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
1956 {"fldmead", 0xed300b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
1957 {"fstmiad", 0xec800b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
1958 {"fstmead", 0xec800b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
1959 {"fstmdbd", 0xed200b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
1960 {"fstmfdd", 0xed200b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
1961
1962 /* Monadic operations. */
1963 {"fabsd", 0xeeb00bc0, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1964 {"fnegd", 0xeeb10b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1965 {"fsqrtd", 0xeeb10bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1966
1967 /* Dyadic operations. */
1968 {"faddd", 0xee300b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1969 {"fsubd", 0xee300b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1970 {"fmuld", 0xee200b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1971 {"fdivd", 0xee800b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1972 {"fmacd", 0xee000b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1973 {"fmscd", 0xee100b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1974 {"fnmuld", 0xee200b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1975 {"fnmacd", 0xee000b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1976 {"fnmscd", 0xee100b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1977
1978 /* Comparisons. */
1979 {"fcmpd", 0xeeb40b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1980 {"fcmpzd", 0xeeb50b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_compare_z},
1981 {"fcmped", 0xeeb40bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1982 {"fcmpezd", 0xeeb50bc0, 7, FPU_VFP_EXT_V1, do_vfp_dp_compare_z},
1983
1984 /* VFP V2. */
1985 {"fmsrr", 0xec400a10, 5, FPU_VFP_EXT_V2, do_vfp_sp2_from_reg2},
1986 {"fmrrs", 0xec500a10, 5, FPU_VFP_EXT_V2, do_vfp_reg2_from_sp2},
1987 {"fmdrr", 0xec400b10, 5, FPU_VFP_EXT_V2, do_vfp_dp_from_reg2},
1988 {"fmrrd", 0xec500b10, 5, FPU_VFP_EXT_V2, do_vfp_reg2_from_dp},
1989
1990 /* Intel XScale extensions to ARM V5 ISA. (All use CP0). */
1991 {"mia", 0xee200010, 3, ARM_CEXT_XSCALE, do_xsc_mia},
1992 {"miaph", 0xee280010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
1993 {"miabb", 0xee2c0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
1994 {"miabt", 0xee2d0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
1995 {"miatb", 0xee2e0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
1996 {"miatt", 0xee2f0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
1997 {"mar", 0xec400000, 3, ARM_CEXT_XSCALE, do_xsc_mar},
1998 {"mra", 0xec500000, 3, ARM_CEXT_XSCALE, do_xsc_mra},
1999
2000 /* Intel Wireless MMX technology instructions. */
2001 {"tandcb", 0xee130130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
2002 {"tandch", 0xee530130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
2003 {"tandcw", 0xee930130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
2004 {"tbcstb", 0xee400010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
2005 {"tbcsth", 0xee400050, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
2006 {"tbcstw", 0xee400090, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
2007 {"textrcb", 0xee130170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
2008 {"textrch", 0xee530170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
2009 {"textrcw", 0xee930170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
2010 {"textrmub", 0xee100070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
2011 {"textrmuh", 0xee500070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
2012 {"textrmuw", 0xee900070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
2013 {"textrmsb", 0xee100078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
2014 {"textrmsh", 0xee500078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
2015 {"textrmsw", 0xee900078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
2016 {"tinsrb", 0xee600010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
2017 {"tinsrh", 0xee600050, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
2018 {"tinsrw", 0xee600090, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
2019 {"tmcr", 0xee000110, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmcr},
2020 {"tmcrr", 0xec400000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_tmcrr},
2021 {"tmia", 0xee200010, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
2022 {"tmiaph", 0xee280010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
2023 {"tmiabb", 0xee2c0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
2024 {"tmiabt", 0xee2d0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
2025 {"tmiatb", 0xee2e0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
2026 {"tmiatt", 0xee2f0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
2027 {"tmovmskb", 0xee100030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
2028 {"tmovmskh", 0xee500030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
2029 {"tmovmskw", 0xee900030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
2030 {"tmrc", 0xee100110, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmrc},
2031 {"tmrrc", 0xec500000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_tmrrc},
2032 {"torcb", 0xee130150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
2033 {"torch", 0xee530150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
2034 {"torcw", 0xee930150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
2035 {"waccb", 0xee0001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2036 {"wacch", 0xee4001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2037 {"waccw", 0xee8001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2038 {"waddbss", 0xee300180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2039 {"waddb", 0xee000180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2040 {"waddbus", 0xee100180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2041 {"waddhss", 0xee700180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2042 {"waddh", 0xee400180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2043 {"waddhus", 0xee500180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2044 {"waddwss", 0xeeb00180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2045 {"waddw", 0xee800180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2046 {"waddwus", 0xee900180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2047 {"waligni", 0xee000020, 7, ARM_CEXT_IWMMXT, do_iwmmxt_waligni},
2048 {"walignr0", 0xee800020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2049 {"walignr1", 0xee900020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2050 {"walignr2", 0xeea00020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2051 {"walignr3", 0xeeb00020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2052 {"wand", 0xee200000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2053 {"wandn", 0xee300000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2054 {"wavg2b", 0xee800000, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2055 {"wavg2br", 0xee900000, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2056 {"wavg2h", 0xeec00000, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2057 {"wavg2hr", 0xeed00000, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2058 {"wcmpeqb", 0xee000060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2059 {"wcmpeqh", 0xee400060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2060 {"wcmpeqw", 0xee800060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2061 {"wcmpgtub", 0xee100060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2062 {"wcmpgtuh", 0xee500060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2063 {"wcmpgtuw", 0xee900060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2064 {"wcmpgtsb", 0xee300060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2065 {"wcmpgtsh", 0xee700060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2066 {"wcmpgtsw", 0xeeb00060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2067 {"wldrb", 0xec100000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
2068 {"wldrh", 0xec100100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
2069 {"wldrw", 0xec100200, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
2070 {"wldrd", 0xec100300, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
2071 {"wmacs", 0xee600100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2072 {"wmacsz", 0xee700100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2073 {"wmacu", 0xee400100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2074 {"wmacuz", 0xee500100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2075 {"wmadds", 0xeea00100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2076 {"wmaddu", 0xee800100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2077 {"wmaxsb", 0xee200160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2078 {"wmaxsh", 0xee600160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2079 {"wmaxsw", 0xeea00160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2080 {"wmaxub", 0xee000160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2081 {"wmaxuh", 0xee400160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2082 {"wmaxuw", 0xee800160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2083 {"wminsb", 0xee300160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2084 {"wminsh", 0xee700160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2085 {"wminsw", 0xeeb00160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2086 {"wminub", 0xee100160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2087 {"wminuh", 0xee500160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2088 {"wminuw", 0xee900160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2089 {"wmov", 0xee000000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wmov},
2090 {"wmulsm", 0xee300100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2091 {"wmulsl", 0xee200100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2092 {"wmulum", 0xee100100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2093 {"wmulul", 0xee000100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2094 {"wor", 0xee000000, 3, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2095 {"wpackhss", 0xee700080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2096 {"wpackhus", 0xee500080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2097 {"wpackwss", 0xeeb00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2098 {"wpackwus", 0xee900080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2099 {"wpackdss", 0xeef00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2100 {"wpackdus", 0xeed00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2101 {"wrorh", 0xee700040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2102 {"wrorhg", 0xee700148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2103 {"wrorw", 0xeeb00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2104 {"wrorwg", 0xeeb00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2105 {"wrord", 0xeef00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2106 {"wrordg", 0xeef00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2107 {"wsadb", 0xee000120, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2108 {"wsadbz", 0xee100120, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2109 {"wsadh", 0xee400120, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2110 {"wsadhz", 0xee500120, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2111 {"wshufh", 0xee0001e0, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wshufh},
2112 {"wsllh", 0xee500040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2113 {"wsllhg", 0xee500148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2114 {"wsllw", 0xee900040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2115 {"wsllwg", 0xee900148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2116 {"wslld", 0xeed00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2117 {"wslldg", 0xeed00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2118 {"wsrah", 0xee400040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2119 {"wsrahg", 0xee400148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2120 {"wsraw", 0xee800040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2121 {"wsrawg", 0xee800148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2122 {"wsrad", 0xeec00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2123 {"wsradg", 0xeec00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2124 {"wsrlh", 0xee600040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2125 {"wsrlhg", 0xee600148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2126 {"wsrlw", 0xeea00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2127 {"wsrlwg", 0xeea00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2128 {"wsrld", 0xeee00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2129 {"wsrldg", 0xeee00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2130 {"wstrb", 0xec000000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
2131 {"wstrh", 0xec000100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
2132 {"wstrw", 0xec000200, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
2133 {"wstrd", 0xec000300, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
2134 {"wsubbss", 0xee3001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2135 {"wsubb", 0xee0001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2136 {"wsubbus", 0xee1001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2137 {"wsubhss", 0xee7001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2138 {"wsubh", 0xee4001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2139 {"wsubhus", 0xee5001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2140 {"wsubwss", 0xeeb001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2141 {"wsubw", 0xee8001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2142 {"wsubwus", 0xee9001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2143 {"wunpckehub", 0xee0000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2144 {"wunpckehuh", 0xee4000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2145 {"wunpckehuw", 0xee8000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2146 {"wunpckehsb", 0xee2000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2147 {"wunpckehsh", 0xee6000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2148 {"wunpckehsw", 0xeea000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2149 {"wunpckihb", 0xee1000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2150 {"wunpckihh", 0xee5000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2151 {"wunpckihw", 0xee9000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2152 {"wunpckelub", 0xee0000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2153 {"wunpckeluh", 0xee4000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2154 {"wunpckeluw", 0xee8000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2155 {"wunpckelsb", 0xee2000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2156 {"wunpckelsh", 0xee6000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2157 {"wunpckelsw", 0xeea000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2158 {"wunpckilb", 0xee1000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2159 {"wunpckilh", 0xee5000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2160 {"wunpckilw", 0xee9000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2161 {"wxor", 0xee100000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2162 {"wzero", 0xee300000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wzero},
2163
2164 /* Cirrus Maverick instructions. */
2165 {"cfldrs", 0xec100400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_1},
2166 {"cfldrd", 0xec500400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_2},
2167 {"cfldr32", 0xec100500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_3},
2168 {"cfldr64", 0xec500500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_4},
2169 {"cfstrs", 0xec000400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_1},
2170 {"cfstrd", 0xec400400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_2},
2171 {"cfstr32", 0xec000500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_3},
2172 {"cfstr64", 0xec400500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_4},
2173 {"cfmvsr", 0xee000450, 6, ARM_CEXT_MAVERICK, do_mav_binops_2a},
2174 {"cfmvrs", 0xee100450, 6, ARM_CEXT_MAVERICK, do_mav_binops_1a},
2175 {"cfmvdlr", 0xee000410, 7, ARM_CEXT_MAVERICK, do_mav_binops_2b},
2176 {"cfmvrdl", 0xee100410, 7, ARM_CEXT_MAVERICK, do_mav_binops_1b},
2177 {"cfmvdhr", 0xee000430, 7, ARM_CEXT_MAVERICK, do_mav_binops_2b},
2178 {"cfmvrdh", 0xee100430, 7, ARM_CEXT_MAVERICK, do_mav_binops_1b},
2179 {"cfmv64lr", 0xee000510, 8, ARM_CEXT_MAVERICK, do_mav_binops_2c},
2180 {"cfmvr64l", 0xee100510, 8, ARM_CEXT_MAVERICK, do_mav_binops_1c},
2181 {"cfmv64hr", 0xee000530, 8, ARM_CEXT_MAVERICK, do_mav_binops_2c},
2182 {"cfmvr64h", 0xee100530, 8, ARM_CEXT_MAVERICK, do_mav_binops_1c},
2183 {"cfmval32", 0xee200440, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
2184 {"cfmv32al", 0xee100440, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
2185 {"cfmvam32", 0xee200460, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
2186 {"cfmv32am", 0xee100460, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
2187 {"cfmvah32", 0xee200480, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
2188 {"cfmv32ah", 0xee100480, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
2189 {"cfmva32", 0xee2004a0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3a},
2190 {"cfmv32a", 0xee1004a0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3b},
2191 {"cfmva64", 0xee2004c0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3c},
2192 {"cfmv64a", 0xee1004c0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3d},
2193 {"cfmvsc32", 0xee2004e0, 8, ARM_CEXT_MAVERICK, do_mav_dspsc_1},
2194 {"cfmv32sc", 0xee1004e0, 8, ARM_CEXT_MAVERICK, do_mav_dspsc_2},
2195 {"cfcpys", 0xee000400, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
2196 {"cfcpyd", 0xee000420, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
2197 {"cfcvtsd", 0xee000460, 7, ARM_CEXT_MAVERICK, do_mav_binops_1f},
2198 {"cfcvtds", 0xee000440, 7, ARM_CEXT_MAVERICK, do_mav_binops_1g},
2199 {"cfcvt32s", 0xee000480, 8, ARM_CEXT_MAVERICK, do_mav_binops_1h},
2200 {"cfcvt32d", 0xee0004a0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1i},
2201 {"cfcvt64s", 0xee0004c0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1j},
2202 {"cfcvt64d", 0xee0004e0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1k},
2203 {"cfcvts32", 0xee100580, 8, ARM_CEXT_MAVERICK, do_mav_binops_1l},
2204 {"cfcvtd32", 0xee1005a0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1m},
2205 {"cftruncs32", 0xee1005c0, 10, ARM_CEXT_MAVERICK, do_mav_binops_1l},
2206 {"cftruncd32", 0xee1005e0, 10, ARM_CEXT_MAVERICK, do_mav_binops_1m},
2207 {"cfrshl32", 0xee000550, 8, ARM_CEXT_MAVERICK, do_mav_triple_4a},
2208 {"cfrshl64", 0xee000570, 8, ARM_CEXT_MAVERICK, do_mav_triple_4b},
2209 {"cfsh32", 0xee000500, 6, ARM_CEXT_MAVERICK, do_mav_shift_1},
2210 {"cfsh64", 0xee200500, 6, ARM_CEXT_MAVERICK, do_mav_shift_2},
2211 {"cfcmps", 0xee100490, 6, ARM_CEXT_MAVERICK, do_mav_triple_5a},
2212 {"cfcmpd", 0xee1004b0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5b},
2213 {"cfcmp32", 0xee100590, 7, ARM_CEXT_MAVERICK, do_mav_triple_5c},
2214 {"cfcmp64", 0xee1005b0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5d},
2215 {"cfabss", 0xee300400, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
2216 {"cfabsd", 0xee300420, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
2217 {"cfnegs", 0xee300440, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
2218 {"cfnegd", 0xee300460, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
2219 {"cfadds", 0xee300480, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
2220 {"cfaddd", 0xee3004a0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
2221 {"cfsubs", 0xee3004c0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
2222 {"cfsubd", 0xee3004e0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
2223 {"cfmuls", 0xee100400, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
2224 {"cfmuld", 0xee100420, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
2225 {"cfabs32", 0xee300500, 7, ARM_CEXT_MAVERICK, do_mav_binops_1n},
2226 {"cfabs64", 0xee300520, 7, ARM_CEXT_MAVERICK, do_mav_binops_1o},
2227 {"cfneg32", 0xee300540, 7, ARM_CEXT_MAVERICK, do_mav_binops_1n},
2228 {"cfneg64", 0xee300560, 7, ARM_CEXT_MAVERICK, do_mav_binops_1o},
2229 {"cfadd32", 0xee300580, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
2230 {"cfadd64", 0xee3005a0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
2231 {"cfsub32", 0xee3005c0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
2232 {"cfsub64", 0xee3005e0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
2233 {"cfmul32", 0xee100500, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
2234 {"cfmul64", 0xee100520, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
2235 {"cfmac32", 0xee100540, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
2236 {"cfmsc32", 0xee100560, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
2237 {"cfmadd32", 0xee000600, 8, ARM_CEXT_MAVERICK, do_mav_quad_6a},
2238 {"cfmsub32", 0xee100600, 8, ARM_CEXT_MAVERICK, do_mav_quad_6a},
2239 {"cfmadda32", 0xee200600, 9, ARM_CEXT_MAVERICK, do_mav_quad_6b},
2240 {"cfmsuba32", 0xee300600, 9, ARM_CEXT_MAVERICK, do_mav_quad_6b},
2241 };
2242
2243 /* Defines for various bits that we will want to toggle. */
2244 #define INST_IMMEDIATE 0x02000000
2245 #define OFFSET_REG 0x02000000
2246 #define HWOFFSET_IMM 0x00400000
2247 #define SHIFT_BY_REG 0x00000010
2248 #define PRE_INDEX 0x01000000
2249 #define INDEX_UP 0x00800000
2250 #define WRITE_BACK 0x00200000
2251 #define LDM_TYPE_2_OR_3 0x00400000
2252
2253 #define LITERAL_MASK 0xf000f000
2254 #define OPCODE_MASK 0xfe1fffff
2255 #define V4_STR_BIT 0x00000020
2256
2257 #define DATA_OP_SHIFT 21
2258
2259 /* Codes to distinguish the arithmetic instructions. */
2260 #define OPCODE_AND 0
2261 #define OPCODE_EOR 1
2262 #define OPCODE_SUB 2
2263 #define OPCODE_RSB 3
2264 #define OPCODE_ADD 4
2265 #define OPCODE_ADC 5
2266 #define OPCODE_SBC 6
2267 #define OPCODE_RSC 7
2268 #define OPCODE_TST 8
2269 #define OPCODE_TEQ 9
2270 #define OPCODE_CMP 10
2271 #define OPCODE_CMN 11
2272 #define OPCODE_ORR 12
2273 #define OPCODE_MOV 13
2274 #define OPCODE_BIC 14
2275 #define OPCODE_MVN 15
2276
2277 /* Thumb v1 (ARMv4T). */
2278 static void do_t_nop PARAMS ((char *));
2279 static void do_t_arit PARAMS ((char *));
2280 static void do_t_add PARAMS ((char *));
2281 static void do_t_asr PARAMS ((char *));
2282 static void do_t_branch9 PARAMS ((char *));
2283 static void do_t_branch12 PARAMS ((char *));
2284 static void do_t_branch23 PARAMS ((char *));
2285 static void do_t_bx PARAMS ((char *));
2286 static void do_t_compare PARAMS ((char *));
2287 static void do_t_ldmstm PARAMS ((char *));
2288 static void do_t_ldr PARAMS ((char *));
2289 static void do_t_ldrb PARAMS ((char *));
2290 static void do_t_ldrh PARAMS ((char *));
2291 static void do_t_lds PARAMS ((char *));
2292 static void do_t_lsl PARAMS ((char *));
2293 static void do_t_lsr PARAMS ((char *));
2294 static void do_t_mov PARAMS ((char *));
2295 static void do_t_push_pop PARAMS ((char *));
2296 static void do_t_str PARAMS ((char *));
2297 static void do_t_strb PARAMS ((char *));
2298 static void do_t_strh PARAMS ((char *));
2299 static void do_t_sub PARAMS ((char *));
2300 static void do_t_swi PARAMS ((char *));
2301 static void do_t_adr PARAMS ((char *));
2302
2303 /* Thumb v2 (ARMv5T). */
2304 static void do_t_blx PARAMS ((char *));
2305 static void do_t_bkpt PARAMS ((char *));
2306
2307 /* ARM V6. */
2308 static void do_t_cps PARAMS ((char *));
2309 static void do_t_cpy PARAMS ((char *));
2310 static void do_t_setend PARAMS ((char *));;
2311
2312 #define T_OPCODE_MUL 0x4340
2313 #define T_OPCODE_TST 0x4200
2314 #define T_OPCODE_CMN 0x42c0
2315 #define T_OPCODE_NEG 0x4240
2316 #define T_OPCODE_MVN 0x43c0
2317
2318 #define T_OPCODE_ADD_R3 0x1800
2319 #define T_OPCODE_SUB_R3 0x1a00
2320 #define T_OPCODE_ADD_HI 0x4400
2321 #define T_OPCODE_ADD_ST 0xb000
2322 #define T_OPCODE_SUB_ST 0xb080
2323 #define T_OPCODE_ADD_SP 0xa800
2324 #define T_OPCODE_ADD_PC 0xa000
2325 #define T_OPCODE_ADD_I8 0x3000
2326 #define T_OPCODE_SUB_I8 0x3800
2327 #define T_OPCODE_ADD_I3 0x1c00
2328 #define T_OPCODE_SUB_I3 0x1e00
2329
2330 #define T_OPCODE_ASR_R 0x4100
2331 #define T_OPCODE_LSL_R 0x4080
2332 #define T_OPCODE_LSR_R 0x40c0
2333 #define T_OPCODE_ASR_I 0x1000
2334 #define T_OPCODE_LSL_I 0x0000
2335 #define T_OPCODE_LSR_I 0x0800
2336
2337 #define T_OPCODE_MOV_I8 0x2000
2338 #define T_OPCODE_CMP_I8 0x2800
2339 #define T_OPCODE_CMP_LR 0x4280
2340 #define T_OPCODE_MOV_HR 0x4600
2341 #define T_OPCODE_CMP_HR 0x4500
2342
2343 #define T_OPCODE_LDR_PC 0x4800
2344 #define T_OPCODE_LDR_SP 0x9800
2345 #define T_OPCODE_STR_SP 0x9000
2346 #define T_OPCODE_LDR_IW 0x6800
2347 #define T_OPCODE_STR_IW 0x6000
2348 #define T_OPCODE_LDR_IH 0x8800
2349 #define T_OPCODE_STR_IH 0x8000
2350 #define T_OPCODE_LDR_IB 0x7800
2351 #define T_OPCODE_STR_IB 0x7000
2352 #define T_OPCODE_LDR_RW 0x5800
2353 #define T_OPCODE_STR_RW 0x5000
2354 #define T_OPCODE_LDR_RH 0x5a00
2355 #define T_OPCODE_STR_RH 0x5200
2356 #define T_OPCODE_LDR_RB 0x5c00
2357 #define T_OPCODE_STR_RB 0x5400
2358
2359 #define T_OPCODE_PUSH 0xb400
2360 #define T_OPCODE_POP 0xbc00
2361
2362 #define T_OPCODE_BRANCH 0xe7fe
2363
2364 static int thumb_reg PARAMS ((char ** str, int hi_lo));
2365
2366 #define THUMB_SIZE 2 /* Size of thumb instruction. */
2367 #define THUMB_REG_LO 0x1
2368 #define THUMB_REG_HI 0x2
2369 #define THUMB_REG_ANY 0x3
2370
2371 #define THUMB_H1 0x0080
2372 #define THUMB_H2 0x0040
2373
2374 #define THUMB_ASR 0
2375 #define THUMB_LSL 1
2376 #define THUMB_LSR 2
2377
2378 #define THUMB_MOVE 0
2379 #define THUMB_COMPARE 1
2380 #define THUMB_CPY 2
2381
2382 #define THUMB_LOAD 0
2383 #define THUMB_STORE 1
2384
2385 #define THUMB_PP_PC_LR 0x0100
2386
2387 /* These three are used for immediate shifts, do not alter. */
2388 #define THUMB_WORD 2
2389 #define THUMB_HALFWORD 1
2390 #define THUMB_BYTE 0
2391
2392 struct thumb_opcode
2393 {
2394 /* Basic string to match. */
2395 const char * template;
2396
2397 /* Basic instruction code. */
2398 unsigned long value;
2399
2400 int size;
2401
2402 /* Which CPU variants this exists for. */
2403 unsigned long variant;
2404
2405 /* Function to call to parse args. */
2406 void (* parms) PARAMS ((char *));
2407 };
2408
2409 static const struct thumb_opcode tinsns[] =
2410 {
2411 /* Thumb v1 (ARMv4T). */
2412 {"adc", 0x4140, 2, ARM_EXT_V4T, do_t_arit},
2413 {"add", 0x0000, 2, ARM_EXT_V4T, do_t_add},
2414 {"and", 0x4000, 2, ARM_EXT_V4T, do_t_arit},
2415 {"asr", 0x0000, 2, ARM_EXT_V4T, do_t_asr},
2416 {"b", T_OPCODE_BRANCH, 2, ARM_EXT_V4T, do_t_branch12},
2417 {"beq", 0xd0fe, 2, ARM_EXT_V4T, do_t_branch9},
2418 {"bne", 0xd1fe, 2, ARM_EXT_V4T, do_t_branch9},
2419 {"bcs", 0xd2fe, 2, ARM_EXT_V4T, do_t_branch9},
2420 {"bhs", 0xd2fe, 2, ARM_EXT_V4T, do_t_branch9},
2421 {"bcc", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
2422 {"bul", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
2423 {"blo", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
2424 {"bmi", 0xd4fe, 2, ARM_EXT_V4T, do_t_branch9},
2425 {"bpl", 0xd5fe, 2, ARM_EXT_V4T, do_t_branch9},
2426 {"bvs", 0xd6fe, 2, ARM_EXT_V4T, do_t_branch9},
2427 {"bvc", 0xd7fe, 2, ARM_EXT_V4T, do_t_branch9},
2428 {"bhi", 0xd8fe, 2, ARM_EXT_V4T, do_t_branch9},
2429 {"bls", 0xd9fe, 2, ARM_EXT_V4T, do_t_branch9},
2430 {"bge", 0xdafe, 2, ARM_EXT_V4T, do_t_branch9},
2431 {"blt", 0xdbfe, 2, ARM_EXT_V4T, do_t_branch9},
2432 {"bgt", 0xdcfe, 2, ARM_EXT_V4T, do_t_branch9},
2433 {"ble", 0xddfe, 2, ARM_EXT_V4T, do_t_branch9},
2434 {"bal", 0xdefe, 2, ARM_EXT_V4T, do_t_branch9},
2435 {"bic", 0x4380, 2, ARM_EXT_V4T, do_t_arit},
2436 {"bl", 0xf7fffffe, 4, ARM_EXT_V4T, do_t_branch23},
2437 {"bx", 0x4700, 2, ARM_EXT_V4T, do_t_bx},
2438 {"cmn", T_OPCODE_CMN, 2, ARM_EXT_V4T, do_t_arit},
2439 {"cmp", 0x0000, 2, ARM_EXT_V4T, do_t_compare},
2440 {"eor", 0x4040, 2, ARM_EXT_V4T, do_t_arit},
2441 {"ldmia", 0xc800, 2, ARM_EXT_V4T, do_t_ldmstm},
2442 {"ldr", 0x0000, 2, ARM_EXT_V4T, do_t_ldr},
2443 {"ldrb", 0x0000, 2, ARM_EXT_V4T, do_t_ldrb},
2444 {"ldrh", 0x0000, 2, ARM_EXT_V4T, do_t_ldrh},
2445 {"ldrsb", 0x5600, 2, ARM_EXT_V4T, do_t_lds},
2446 {"ldrsh", 0x5e00, 2, ARM_EXT_V4T, do_t_lds},
2447 {"ldsb", 0x5600, 2, ARM_EXT_V4T, do_t_lds},
2448 {"ldsh", 0x5e00, 2, ARM_EXT_V4T, do_t_lds},
2449 {"lsl", 0x0000, 2, ARM_EXT_V4T, do_t_lsl},
2450 {"lsr", 0x0000, 2, ARM_EXT_V4T, do_t_lsr},
2451 {"mov", 0x0000, 2, ARM_EXT_V4T, do_t_mov},
2452 {"mul", T_OPCODE_MUL, 2, ARM_EXT_V4T, do_t_arit},
2453 {"mvn", T_OPCODE_MVN, 2, ARM_EXT_V4T, do_t_arit},
2454 {"neg", T_OPCODE_NEG, 2, ARM_EXT_V4T, do_t_arit},
2455 {"orr", 0x4300, 2, ARM_EXT_V4T, do_t_arit},
2456 {"pop", 0xbc00, 2, ARM_EXT_V4T, do_t_push_pop},
2457 {"push", 0xb400, 2, ARM_EXT_V4T, do_t_push_pop},
2458 {"ror", 0x41c0, 2, ARM_EXT_V4T, do_t_arit},
2459 {"sbc", 0x4180, 2, ARM_EXT_V4T, do_t_arit},
2460 {"stmia", 0xc000, 2, ARM_EXT_V4T, do_t_ldmstm},
2461 {"str", 0x0000, 2, ARM_EXT_V4T, do_t_str},
2462 {"strb", 0x0000, 2, ARM_EXT_V4T, do_t_strb},
2463 {"strh", 0x0000, 2, ARM_EXT_V4T, do_t_strh},
2464 {"swi", 0xdf00, 2, ARM_EXT_V4T, do_t_swi},
2465 {"sub", 0x0000, 2, ARM_EXT_V4T, do_t_sub},
2466 {"tst", T_OPCODE_TST, 2, ARM_EXT_V4T, do_t_arit},
2467 /* Pseudo ops: */
2468 {"adr", 0x0000, 2, ARM_EXT_V4T, do_t_adr},
2469 {"nop", 0x46C0, 2, ARM_EXT_V4T, do_t_nop}, /* mov r8,r8 */
2470 /* Thumb v2 (ARMv5T). */
2471 {"blx", 0, 0, ARM_EXT_V5T, do_t_blx},
2472 {"bkpt", 0xbe00, 2, ARM_EXT_V5T, do_t_bkpt},
2473
2474 /* ARM V6. */
2475 {"cpsie", 0xb660, 2, ARM_EXT_V6, do_t_cps},
2476 {"cpsid", 0xb670, 2, ARM_EXT_V6, do_t_cps},
2477 {"cpy", 0x4600, 2, ARM_EXT_V6, do_t_cpy},
2478 {"rev", 0xba00, 2, ARM_EXT_V6, do_t_arit},
2479 {"rev16", 0xba40, 2, ARM_EXT_V6, do_t_arit},
2480 {"revsh", 0xbac0, 2, ARM_EXT_V6, do_t_arit},
2481 {"setend", 0xb650, 2, ARM_EXT_V6, do_t_setend},
2482 {"sxth", 0xb200, 2, ARM_EXT_V6, do_t_arit},
2483 {"sxtb", 0xb240, 2, ARM_EXT_V6, do_t_arit},
2484 {"uxth", 0xb280, 2, ARM_EXT_V6, do_t_arit},
2485 {"uxtb", 0xb2c0, 2, ARM_EXT_V6, do_t_arit},
2486 };
2487
2488 #define BAD_ARGS _("bad arguments to instruction")
2489 #define BAD_PC _("r15 not allowed here")
2490 #define BAD_COND _("instruction is not conditional")
2491 #define ERR_NO_ACCUM _("acc0 expected")
2492
2493 static struct hash_control * arm_ops_hsh = NULL;
2494 static struct hash_control * arm_tops_hsh = NULL;
2495 static struct hash_control * arm_cond_hsh = NULL;
2496 static struct hash_control * arm_shift_hsh = NULL;
2497 static struct hash_control * arm_psr_hsh = NULL;
2498
2499 /* This table describes all the machine specific pseudo-ops the assembler
2500 has to support. The fields are:
2501 pseudo-op name without dot
2502 function to call to execute this pseudo-op
2503 Integer arg to pass to the function. */
2504
2505 static void s_req PARAMS ((int));
2506 static void s_unreq PARAMS ((int));
2507 static void s_align PARAMS ((int));
2508 static void s_bss PARAMS ((int));
2509 static void s_even PARAMS ((int));
2510 static void s_ltorg PARAMS ((int));
2511 static void s_arm PARAMS ((int));
2512 static void s_thumb PARAMS ((int));
2513 static void s_code PARAMS ((int));
2514 static void s_force_thumb PARAMS ((int));
2515 static void s_thumb_func PARAMS ((int));
2516 static void s_thumb_set PARAMS ((int));
2517 #ifdef OBJ_ELF
2518 static void s_arm_elf_cons PARAMS ((int));
2519 #endif
2520
2521 static int my_get_expression PARAMS ((expressionS *, char **));
2522
2523 const pseudo_typeS md_pseudo_table[] =
2524 {
2525 /* Never called because '.req' does not start a line. */
2526 { "req", s_req, 0 },
2527 { "unreq", s_unreq, 0 },
2528 { "bss", s_bss, 0 },
2529 { "align", s_align, 0 },
2530 { "arm", s_arm, 0 },
2531 { "thumb", s_thumb, 0 },
2532 { "code", s_code, 0 },
2533 { "force_thumb", s_force_thumb, 0 },
2534 { "thumb_func", s_thumb_func, 0 },
2535 { "thumb_set", s_thumb_set, 0 },
2536 { "even", s_even, 0 },
2537 { "ltorg", s_ltorg, 0 },
2538 { "pool", s_ltorg, 0 },
2539 #ifdef OBJ_ELF
2540 { "word", s_arm_elf_cons, 4 },
2541 { "long", s_arm_elf_cons, 4 },
2542 #else
2543 { "word", cons, 4},
2544 #endif
2545 { "extend", float_cons, 'x' },
2546 { "ldouble", float_cons, 'x' },
2547 { "packed", float_cons, 'p' },
2548 { 0, 0, 0 }
2549 };
2550
2551 /* Other internal functions. */
2552 static int arm_parse_extension PARAMS ((char *, int *));
2553 static int arm_parse_cpu PARAMS ((char *));
2554 static int arm_parse_arch PARAMS ((char *));
2555 static int arm_parse_fpu PARAMS ((char *));
2556 static int arm_parse_float_abi PARAMS ((char *));
2557 #ifdef OBJ_ELF
2558 static int arm_parse_eabi PARAMS ((char *));
2559 #endif
2560 #if 0 /* Suppressed - for now. */
2561 #if defined OBJ_COFF || defined OBJ_ELF
2562 static void arm_add_note PARAMS ((const char *, const char *, unsigned int));
2563 #endif
2564 #endif
2565
2566 /* Stuff needed to resolve the label ambiguity
2567 As:
2568 ...
2569 label: <insn>
2570 may differ from:
2571 ...
2572 label:
2573 <insn>
2574 */
2575
2576 symbolS * last_label_seen;
2577 static int label_is_thumb_function_name = FALSE;
2578
2579 /* Literal Pool stuff. */
2580
2581 #define MAX_LITERAL_POOL_SIZE 1024
2582
2583 /* Literal pool structure. Held on a per-section
2584 and per-sub-section basis. */
2585 typedef struct literal_pool
2586 {
2587 expressionS literals [MAX_LITERAL_POOL_SIZE];
2588 unsigned int next_free_entry;
2589 unsigned int id;
2590 symbolS * symbol;
2591 segT section;
2592 subsegT sub_section;
2593 struct literal_pool * next;
2594 } literal_pool;
2595
2596 /* Pointer to a linked list of literal pools. */
2597 literal_pool * list_of_pools = NULL;
2598
2599 static literal_pool * find_literal_pool PARAMS ((void));
2600 static literal_pool * find_or_make_literal_pool PARAMS ((void));
2601
2602 static literal_pool *
2603 find_literal_pool ()
2604 {
2605 literal_pool * pool;
2606
2607 for (pool = list_of_pools; pool != NULL; pool = pool->next)
2608 {
2609 if (pool->section == now_seg
2610 && pool->sub_section == now_subseg)
2611 break;
2612 }
2613
2614 return pool;
2615 }
2616
2617 static literal_pool *
2618 find_or_make_literal_pool ()
2619 {
2620 /* Next literal pool ID number. */
2621 static unsigned int latest_pool_num = 1;
2622 literal_pool * pool;
2623
2624 pool = find_literal_pool ();
2625
2626 if (pool == NULL)
2627 {
2628 /* Create a new pool. */
2629 pool = (literal_pool *) xmalloc (sizeof (* pool));
2630 if (! pool)
2631 return NULL;
2632
2633 pool->next_free_entry = 0;
2634 pool->section = now_seg;
2635 pool->sub_section = now_subseg;
2636 pool->next = list_of_pools;
2637 pool->symbol = NULL;
2638
2639 /* Add it to the list. */
2640 list_of_pools = pool;
2641 }
2642
2643 /* New pools, and emptied pools, will have a NULL symbol. */
2644 if (pool->symbol == NULL)
2645 {
2646 pool->symbol = symbol_create (FAKE_LABEL_NAME, undefined_section,
2647 (valueT) 0, &zero_address_frag);
2648 pool->id = latest_pool_num ++;
2649 }
2650
2651 /* Done. */
2652 return pool;
2653 }
2654
2655 /* Add the literal in the global 'inst'
2656 structure to the relevent literal pool. */
2657 static int
2658 add_to_lit_pool ()
2659 {
2660 literal_pool * pool;
2661 unsigned int entry;
2662
2663 pool = find_or_make_literal_pool ();
2664
2665 /* Check if this literal value is already in the pool. */
2666 for (entry = 0; entry < pool->next_free_entry; entry ++)
2667 {
2668 if ((pool->literals[entry].X_op == inst.reloc.exp.X_op)
2669 && (inst.reloc.exp.X_op == O_constant)
2670 && (pool->literals[entry].X_add_number
2671 == inst.reloc.exp.X_add_number)
2672 && (pool->literals[entry].X_unsigned
2673 == inst.reloc.exp.X_unsigned))
2674 break;
2675
2676 if ((pool->literals[entry].X_op == inst.reloc.exp.X_op)
2677 && (inst.reloc.exp.X_op == O_symbol)
2678 && (pool->literals[entry].X_add_number
2679 == inst.reloc.exp.X_add_number)
2680 && (pool->literals[entry].X_add_symbol
2681 == inst.reloc.exp.X_add_symbol)
2682 && (pool->literals[entry].X_op_symbol
2683 == inst.reloc.exp.X_op_symbol))
2684 break;
2685 }
2686
2687 /* Do we need to create a new entry? */
2688 if (entry == pool->next_free_entry)
2689 {
2690 if (entry >= MAX_LITERAL_POOL_SIZE)
2691 {
2692 inst.error = _("literal pool overflow");
2693 return FAIL;
2694 }
2695
2696 pool->literals[entry] = inst.reloc.exp;
2697 pool->next_free_entry += 1;
2698 }
2699
2700 inst.reloc.exp.X_op = O_symbol;
2701 inst.reloc.exp.X_add_number = ((int) entry) * 4 - 8;
2702 inst.reloc.exp.X_add_symbol = pool->symbol;
2703
2704 return SUCCESS;
2705 }
2706
2707 /* Can't use symbol_new here, so have to create a symbol and then at
2708 a later date assign it a value. Thats what these functions do. */
2709
2710 static void
2711 symbol_locate (symbolP, name, segment, valu, frag)
2712 symbolS * symbolP;
2713 const char * name; /* It is copied, the caller can modify. */
2714 segT segment; /* Segment identifier (SEG_<something>). */
2715 valueT valu; /* Symbol value. */
2716 fragS * frag; /* Associated fragment. */
2717 {
2718 unsigned int name_length;
2719 char * preserved_copy_of_name;
2720
2721 name_length = strlen (name) + 1; /* +1 for \0. */
2722 obstack_grow (&notes, name, name_length);
2723 preserved_copy_of_name = obstack_finish (&notes);
2724 #ifdef STRIP_UNDERSCORE
2725 if (preserved_copy_of_name[0] == '_')
2726 preserved_copy_of_name++;
2727 #endif
2728
2729 #ifdef tc_canonicalize_symbol_name
2730 preserved_copy_of_name =
2731 tc_canonicalize_symbol_name (preserved_copy_of_name);
2732 #endif
2733
2734 S_SET_NAME (symbolP, preserved_copy_of_name);
2735
2736 S_SET_SEGMENT (symbolP, segment);
2737 S_SET_VALUE (symbolP, valu);
2738 symbol_clear_list_pointers (symbolP);
2739
2740 symbol_set_frag (symbolP, frag);
2741
2742 /* Link to end of symbol chain. */
2743 {
2744 extern int symbol_table_frozen;
2745 if (symbol_table_frozen)
2746 abort ();
2747 }
2748
2749 symbol_append (symbolP, symbol_lastP, & symbol_rootP, & symbol_lastP);
2750
2751 obj_symbol_new_hook (symbolP);
2752
2753 #ifdef tc_symbol_new_hook
2754 tc_symbol_new_hook (symbolP);
2755 #endif
2756
2757 #ifdef DEBUG_SYMS
2758 verify_symbol_chain (symbol_rootP, symbol_lastP);
2759 #endif /* DEBUG_SYMS */
2760 }
2761
2762 /* Check that an immediate is valid.
2763 If so, convert it to the right format. */
2764
2765 static unsigned int
2766 validate_immediate (val)
2767 unsigned int val;
2768 {
2769 unsigned int a;
2770 unsigned int i;
2771
2772 #define rotate_left(v, n) (v << n | v >> (32 - n))
2773
2774 for (i = 0; i < 32; i += 2)
2775 if ((a = rotate_left (val, i)) <= 0xff)
2776 return a | (i << 7); /* 12-bit pack: [shift-cnt,const]. */
2777
2778 return FAIL;
2779 }
2780
2781 /* Check to see if an immediate can be computed as two separate immediate
2782 values, added together. We already know that this value cannot be
2783 computed by just one ARM instruction. */
2784
2785 static unsigned int
2786 validate_immediate_twopart (val, highpart)
2787 unsigned int val;
2788 unsigned int * highpart;
2789 {
2790 unsigned int a;
2791 unsigned int i;
2792
2793 for (i = 0; i < 32; i += 2)
2794 if (((a = rotate_left (val, i)) & 0xff) != 0)
2795 {
2796 if (a & 0xff00)
2797 {
2798 if (a & ~ 0xffff)
2799 continue;
2800 * highpart = (a >> 8) | ((i + 24) << 7);
2801 }
2802 else if (a & 0xff0000)
2803 {
2804 if (a & 0xff000000)
2805 continue;
2806 * highpart = (a >> 16) | ((i + 16) << 7);
2807 }
2808 else
2809 {
2810 assert (a & 0xff000000);
2811 * highpart = (a >> 24) | ((i + 8) << 7);
2812 }
2813
2814 return (a & 0xff) | (i << 7);
2815 }
2816
2817 return FAIL;
2818 }
2819
2820 static int
2821 validate_offset_imm (val, hwse)
2822 unsigned int val;
2823 int hwse;
2824 {
2825 if ((hwse && val > 255) || val > 4095)
2826 return FAIL;
2827 return val;
2828 }
2829
2830 \f
2831 #ifdef OBJ_ELF
2832 enum mstate
2833 {
2834 MAP_DATA,
2835 MAP_ARM,
2836 MAP_THUMB
2837 };
2838
2839 /* This code is to handle mapping symbols as defined in the ARM ELF spec.
2840 (This text is taken from version B-02 of the spec):
2841
2842 4.4.7 Mapping and tagging symbols
2843
2844 A section of an ARM ELF file can contain a mixture of ARM code,
2845 Thumb code, and data. There are inline transitions between code
2846 and data at literal pool boundaries. There can also be inline
2847 transitions between ARM code and Thumb code, for example in
2848 ARM-Thumb inter-working veneers. Linkers, machine-level
2849 debuggers, profiling tools, and disassembly tools need to map
2850 images accurately. For example, setting an ARM breakpoint on a
2851 Thumb location, or in a literal pool, can crash the program
2852 being debugged, ruining the debugging session.
2853
2854 ARM ELF entities are mapped (see section 4.4.7.1 below) and
2855 tagged (see section 4.4.7.2 below) using local symbols (with
2856 binding STB_LOCAL). To assist consumers, mapping and tagging
2857 symbols should be collated first in the symbol table, before
2858 other symbols with binding STB_LOCAL.
2859
2860 To allow properly collated mapping and tagging symbols to be
2861 skipped by consumers that have no interest in them, the first
2862 such symbol should have the name $m and its st_value field equal
2863 to the total number of mapping and tagging symbols (including
2864 the $m) in the symbol table.
2865
2866 4.4.7.1 Mapping symbols
2867
2868 $a Labels the first byte of a sequence of ARM instructions.
2869 Its type is STT_FUNC.
2870
2871 $d Labels the first byte of a sequence of data items.
2872 Its type is STT_OBJECT.
2873
2874 $t Labels the first byte of a sequence of Thumb instructions.
2875 Its type is STT_FUNC.
2876
2877 This list of mapping symbols may be extended in the future.
2878
2879 Section-relative mapping symbols
2880
2881 Mapping symbols defined in a section define a sequence of
2882 half-open address intervals that cover the address range of the
2883 section. Each interval starts at the address defined by a
2884 mapping symbol, and continues up to, but not including, the
2885 address defined by the next (in address order) mapping symbol or
2886 the end of the section. A corollary is that there must be a
2887 mapping symbol defined at the beginning of each section.
2888 Consumers can ignore the size of a section-relative mapping
2889 symbol. Producers can set it to 0.
2890
2891 Absolute mapping symbols
2892
2893 Because of the need to crystallize a Thumb address with the
2894 Thumb-bit set, absolute symbol of type STT_FUNC (symbols of type
2895 STT_FUNC defined in section SHN_ABS) need to be mapped with $a
2896 or $t.
2897
2898 The extent of a mapping symbol defined in SHN_ABS is [st_value,
2899 st_value + st_size), or [st_value, st_value + 1) if st_size = 0,
2900 where [x, y) denotes the half-open address range from x,
2901 inclusive, to y, exclusive.
2902
2903 In the absence of a mapping symbol, a consumer can interpret a
2904 function symbol with an odd value as the Thumb code address
2905 obtained by clearing the least significant bit of the
2906 value. This interpretation is deprecated, and it may not work in
2907 the future.
2908
2909 Note - the Tagging symbols ($b, $f, $p $m) have been dropped from
2910 the EABI (which is still under development), so they are not
2911 implemented here. */
2912
2913 static void
2914 mapping_state (enum mstate state)
2915 {
2916 static enum mstate mapstate = MAP_DATA;
2917 symbolS * symbolP;
2918 const char * symname;
2919 int type;
2920
2921 if (mapstate == state)
2922 /* The mapping symbol has already been emitted.
2923 There is nothing else to do. */
2924 return;
2925
2926 mapstate = state;
2927
2928 switch (state)
2929 {
2930 case MAP_DATA:
2931 symname = "$d";
2932 type = BSF_OBJECT;
2933 break;
2934 case MAP_ARM:
2935 symname = "$a";
2936 type = BSF_FUNCTION;
2937 break;
2938 case MAP_THUMB:
2939 symname = "$t";
2940 type = BSF_FUNCTION;
2941 break;
2942 default:
2943 abort ();
2944 }
2945
2946 symbolP = symbol_new (symname, now_seg, (valueT) frag_now_fix (), frag_now);
2947 symbol_table_insert (symbolP);
2948 symbol_get_bfdsym (symbolP)->flags |= type | BSF_LOCAL;
2949
2950 switch (state)
2951 {
2952 case MAP_ARM:
2953 THUMB_SET_FUNC (symbolP, 0);
2954 ARM_SET_THUMB (symbolP, 0);
2955 ARM_SET_INTERWORK (symbolP, support_interwork);
2956 break;
2957
2958 case MAP_THUMB:
2959 THUMB_SET_FUNC (symbolP, 1);
2960 ARM_SET_THUMB (symbolP, 1);
2961 ARM_SET_INTERWORK (symbolP, support_interwork);
2962 break;
2963
2964 case MAP_DATA:
2965 default:
2966 return;
2967 }
2968 }
2969
2970 /* When we change sections we need to issue a new mapping symbol. */
2971
2972 void
2973 arm_elf_change_section (void)
2974 {
2975 flagword flags;
2976
2977 if (!SEG_NORMAL (now_seg))
2978 return;
2979
2980 flags = bfd_get_section_flags (stdoutput, now_seg);
2981
2982 /* We can ignore sections that only contain debug info. */
2983 if ((flags & SEC_ALLOC) == 0)
2984 return;
2985
2986 if (flags & SEC_CODE)
2987 {
2988 if (thumb_mode)
2989 mapping_state (MAP_THUMB);
2990 else
2991 mapping_state (MAP_ARM);
2992 }
2993 else
2994 /* This section does not contain code. Therefore it must contain data. */
2995 mapping_state (MAP_DATA);
2996 }
2997 #else
2998 #define mapping_state(a)
2999 #endif /* OBJ_ELF */
3000 \f
3001
3002 static void
3003 s_req (a)
3004 int a ATTRIBUTE_UNUSED;
3005 {
3006 as_bad (_("invalid syntax for .req directive"));
3007 }
3008
3009 /* The .unreq directive deletes an alias which was previously defined
3010 by .req. For example:
3011
3012 my_alias .req r11
3013 .unreq my_alias */
3014
3015 static void
3016 s_unreq (int a ATTRIBUTE_UNUSED)
3017 {
3018 char *name;
3019 char saved_char;
3020
3021 skip_whitespace (input_line_pointer);
3022 name = input_line_pointer;
3023
3024 while (*input_line_pointer != 0
3025 && *input_line_pointer != ' '
3026 && *input_line_pointer != '\n')
3027 ++input_line_pointer;
3028
3029 saved_char = *input_line_pointer;
3030 *input_line_pointer = 0;
3031
3032 if (*name)
3033 {
3034 enum arm_reg_type req_type = arm_reg_parse_any (name);
3035
3036 if (req_type != REG_TYPE_MAX)
3037 {
3038 char *temp_name = name;
3039 int req_no = arm_reg_parse (&temp_name, all_reg_maps[req_type].htab);
3040
3041 if (req_no != FAIL)
3042 {
3043 struct reg_entry *req_entry;
3044
3045 /* Check to see if this alias is a builtin one. */
3046 req_entry = hash_delete (all_reg_maps[req_type].htab, name);
3047
3048 if (!req_entry)
3049 as_bad (_("unreq: missing hash entry for \"%s\""), name);
3050 else if (req_entry->builtin)
3051 /* FIXME: We are deleting a built in register alias which
3052 points to a const data structure, so we only need to
3053 free up the memory used by the key in the hash table.
3054 Unfortunately we have not recorded this value, so this
3055 is a memory leak. */
3056 /* FIXME: Should we issue a warning message ? */
3057 ;
3058 else
3059 {
3060 /* Deleting a user defined alias. We need to free the
3061 key and the value, but fortunately the key is the same
3062 as the value->name field. */
3063 free ((char *) req_entry->name);
3064 free (req_entry);
3065 }
3066 }
3067 else
3068 as_bad (_(".unreq: unrecognized symbol \"%s\""), name);
3069 }
3070 else
3071 as_bad (_(".unreq: unrecognized symbol \"%s\""), name);
3072 }
3073 else
3074 as_bad (_("invalid syntax for .unreq directive"));
3075
3076 *input_line_pointer = saved_char;
3077 demand_empty_rest_of_line ();
3078 }
3079
3080 static void
3081 s_bss (ignore)
3082 int ignore ATTRIBUTE_UNUSED;
3083 {
3084 /* We don't support putting frags in the BSS segment, we fake it by
3085 marking in_bss, then looking at s_skip for clues. */
3086 subseg_set (bss_section, 0);
3087 demand_empty_rest_of_line ();
3088 mapping_state (MAP_DATA);
3089 }
3090
3091 static void
3092 s_even (ignore)
3093 int ignore ATTRIBUTE_UNUSED;
3094 {
3095 /* Never make frag if expect extra pass. */
3096 if (!need_pass_2)
3097 frag_align (1, 0, 0);
3098
3099 record_alignment (now_seg, 1);
3100
3101 demand_empty_rest_of_line ();
3102 }
3103
3104 static void
3105 s_ltorg (ignored)
3106 int ignored ATTRIBUTE_UNUSED;
3107 {
3108 unsigned int entry;
3109 literal_pool * pool;
3110 char sym_name[20];
3111
3112 pool = find_literal_pool ();
3113 if (pool == NULL
3114 || pool->symbol == NULL
3115 || pool->next_free_entry == 0)
3116 return;
3117
3118 /* Align pool as you have word accesses.
3119 Only make a frag if we have to. */
3120 if (!need_pass_2)
3121 frag_align (2, 0, 0);
3122
3123 record_alignment (now_seg, 2);
3124
3125 sprintf (sym_name, "$$lit_\002%x", pool->id);
3126
3127 symbol_locate (pool->symbol, sym_name, now_seg,
3128 (valueT) frag_now_fix (), frag_now);
3129 symbol_table_insert (pool->symbol);
3130
3131 ARM_SET_THUMB (pool->symbol, thumb_mode);
3132
3133 #if defined OBJ_COFF || defined OBJ_ELF
3134 ARM_SET_INTERWORK (pool->symbol, support_interwork);
3135 #endif
3136
3137 for (entry = 0; entry < pool->next_free_entry; entry ++)
3138 /* First output the expression in the instruction to the pool. */
3139 emit_expr (&(pool->literals[entry]), 4); /* .word */
3140
3141 /* Mark the pool as empty. */
3142 pool->next_free_entry = 0;
3143 pool->symbol = NULL;
3144 }
3145
3146 /* Same as s_align_ptwo but align 0 => align 2. */
3147
3148 static void
3149 s_align (unused)
3150 int unused ATTRIBUTE_UNUSED;
3151 {
3152 register int temp;
3153 register long temp_fill;
3154 long max_alignment = 15;
3155
3156 temp = get_absolute_expression ();
3157 if (temp > max_alignment)
3158 as_bad (_("alignment too large: %d assumed"), temp = max_alignment);
3159 else if (temp < 0)
3160 {
3161 as_bad (_("alignment negative. 0 assumed."));
3162 temp = 0;
3163 }
3164
3165 if (*input_line_pointer == ',')
3166 {
3167 input_line_pointer++;
3168 temp_fill = get_absolute_expression ();
3169 }
3170 else
3171 temp_fill = 0;
3172
3173 if (!temp)
3174 temp = 2;
3175
3176 /* Only make a frag if we HAVE to. */
3177 if (temp && !need_pass_2)
3178 frag_align (temp, (int) temp_fill, 0);
3179 demand_empty_rest_of_line ();
3180
3181 record_alignment (now_seg, temp);
3182 }
3183
3184 static void
3185 s_force_thumb (ignore)
3186 int ignore ATTRIBUTE_UNUSED;
3187 {
3188 /* If we are not already in thumb mode go into it, EVEN if
3189 the target processor does not support thumb instructions.
3190 This is used by gcc/config/arm/lib1funcs.asm for example
3191 to compile interworking support functions even if the
3192 target processor should not support interworking. */
3193 if (! thumb_mode)
3194 {
3195 thumb_mode = 2;
3196
3197 record_alignment (now_seg, 1);
3198 }
3199
3200 demand_empty_rest_of_line ();
3201 }
3202
3203 static void
3204 s_thumb_func (ignore)
3205 int ignore ATTRIBUTE_UNUSED;
3206 {
3207 if (! thumb_mode)
3208 opcode_select (16);
3209
3210 /* The following label is the name/address of the start of a Thumb function.
3211 We need to know this for the interworking support. */
3212 label_is_thumb_function_name = TRUE;
3213
3214 demand_empty_rest_of_line ();
3215 }
3216
3217 /* Perform a .set directive, but also mark the alias as
3218 being a thumb function. */
3219
3220 static void
3221 s_thumb_set (equiv)
3222 int equiv;
3223 {
3224 /* XXX the following is a duplicate of the code for s_set() in read.c
3225 We cannot just call that code as we need to get at the symbol that
3226 is created. */
3227 register char * name;
3228 register char delim;
3229 register char * end_name;
3230 register symbolS * symbolP;
3231
3232 /* Especial apologies for the random logic:
3233 This just grew, and could be parsed much more simply!
3234 Dean - in haste. */
3235 name = input_line_pointer;
3236 delim = get_symbol_end ();
3237 end_name = input_line_pointer;
3238 *end_name = delim;
3239
3240 SKIP_WHITESPACE ();
3241
3242 if (*input_line_pointer != ',')
3243 {
3244 *end_name = 0;
3245 as_bad (_("expected comma after name \"%s\""), name);
3246 *end_name = delim;
3247 ignore_rest_of_line ();
3248 return;
3249 }
3250
3251 input_line_pointer++;
3252 *end_name = 0;
3253
3254 if (name[0] == '.' && name[1] == '\0')
3255 {
3256 /* XXX - this should not happen to .thumb_set. */
3257 abort ();
3258 }
3259
3260 if ((symbolP = symbol_find (name)) == NULL
3261 && (symbolP = md_undefined_symbol (name)) == NULL)
3262 {
3263 #ifndef NO_LISTING
3264 /* When doing symbol listings, play games with dummy fragments living
3265 outside the normal fragment chain to record the file and line info
3266 for this symbol. */
3267 if (listing & LISTING_SYMBOLS)
3268 {
3269 extern struct list_info_struct * listing_tail;
3270 fragS * dummy_frag = (fragS *) xmalloc (sizeof (fragS));
3271
3272 memset (dummy_frag, 0, sizeof (fragS));
3273 dummy_frag->fr_type = rs_fill;
3274 dummy_frag->line = listing_tail;
3275 symbolP = symbol_new (name, undefined_section, 0, dummy_frag);
3276 dummy_frag->fr_symbol = symbolP;
3277 }
3278 else
3279 #endif
3280 symbolP = symbol_new (name, undefined_section, 0, &zero_address_frag);
3281
3282 #ifdef OBJ_COFF
3283 /* "set" symbols are local unless otherwise specified. */
3284 SF_SET_LOCAL (symbolP);
3285 #endif /* OBJ_COFF */
3286 } /* Make a new symbol. */
3287
3288 symbol_table_insert (symbolP);
3289
3290 * end_name = delim;
3291
3292 if (equiv
3293 && S_IS_DEFINED (symbolP)
3294 && S_GET_SEGMENT (symbolP) != reg_section)
3295 as_bad (_("symbol `%s' already defined"), S_GET_NAME (symbolP));
3296
3297 pseudo_set (symbolP);
3298
3299 demand_empty_rest_of_line ();
3300
3301 /* XXX Now we come to the Thumb specific bit of code. */
3302
3303 THUMB_SET_FUNC (symbolP, 1);
3304 ARM_SET_THUMB (symbolP, 1);
3305 #if defined OBJ_ELF || defined OBJ_COFF
3306 ARM_SET_INTERWORK (symbolP, support_interwork);
3307 #endif
3308 }
3309
3310 static void
3311 opcode_select (width)
3312 int width;
3313 {
3314 switch (width)
3315 {
3316 case 16:
3317 if (! thumb_mode)
3318 {
3319 if (! (cpu_variant & ARM_EXT_V4T))
3320 as_bad (_("selected processor does not support THUMB opcodes"));
3321
3322 thumb_mode = 1;
3323 /* No need to force the alignment, since we will have been
3324 coming from ARM mode, which is word-aligned. */
3325 record_alignment (now_seg, 1);
3326 }
3327 mapping_state (MAP_THUMB);
3328 break;
3329
3330 case 32:
3331 if (thumb_mode)
3332 {
3333 if ((cpu_variant & ARM_ALL) == ARM_EXT_V4T)
3334 as_bad (_("selected processor does not support ARM opcodes"));
3335
3336 thumb_mode = 0;
3337
3338 if (!need_pass_2)
3339 frag_align (2, 0, 0);
3340
3341 record_alignment (now_seg, 1);
3342 }
3343 mapping_state (MAP_ARM);
3344 break;
3345
3346 default:
3347 as_bad (_("invalid instruction size selected (%d)"), width);
3348 }
3349 }
3350
3351 static void
3352 s_arm (ignore)
3353 int ignore ATTRIBUTE_UNUSED;
3354 {
3355 opcode_select (32);
3356 demand_empty_rest_of_line ();
3357 }
3358
3359 static void
3360 s_thumb (ignore)
3361 int ignore ATTRIBUTE_UNUSED;
3362 {
3363 opcode_select (16);
3364 demand_empty_rest_of_line ();
3365 }
3366
3367 static void
3368 s_code (unused)
3369 int unused ATTRIBUTE_UNUSED;
3370 {
3371 register int temp;
3372
3373 temp = get_absolute_expression ();
3374 switch (temp)
3375 {
3376 case 16:
3377 case 32:
3378 opcode_select (temp);
3379 break;
3380
3381 default:
3382 as_bad (_("invalid operand to .code directive (%d) (expecting 16 or 32)"), temp);
3383 }
3384 }
3385
3386 static void
3387 end_of_line (str)
3388 char *str;
3389 {
3390 skip_whitespace (str);
3391
3392 if (*str != '\0' && !inst.error)
3393 inst.error = _("garbage following instruction");
3394 }
3395
3396 static int
3397 skip_past_comma (str)
3398 char ** str;
3399 {
3400 char * p = * str, c;
3401 int comma = 0;
3402
3403 while ((c = *p) == ' ' || c == ',')
3404 {
3405 p++;
3406 if (c == ',' && comma++)
3407 return FAIL;
3408 }
3409
3410 if (c == '\0')
3411 return FAIL;
3412
3413 *str = p;
3414 return comma ? SUCCESS : FAIL;
3415 }
3416
3417 /* A standard register must be given at this point.
3418 SHIFT is the place to put it in inst.instruction.
3419 Restores input start point on error.
3420 Returns the reg#, or FAIL. */
3421
3422 static int
3423 reg_required_here (str, shift)
3424 char ** str;
3425 int shift;
3426 {
3427 static char buff [128]; /* XXX */
3428 int reg;
3429 char * start = * str;
3430
3431 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_RN].htab)) != FAIL)
3432 {
3433 if (shift >= 0)
3434 inst.instruction |= reg << shift;
3435 return reg;
3436 }
3437
3438 /* Restore the start point, we may have got a reg of the wrong class. */
3439 *str = start;
3440
3441 /* In the few cases where we might be able to accept something else
3442 this error can be overridden. */
3443 sprintf (buff, _("register expected, not '%.100s'"), start);
3444 inst.error = buff;
3445
3446 return FAIL;
3447 }
3448
3449 /* A Intel Wireless MMX technology register
3450 must be given at this point.
3451 Shift is the place to put it in inst.instruction.
3452 Restores input start point on err.
3453 Returns the reg#, or FAIL. */
3454
3455 static int
3456 wreg_required_here (str, shift, reg_type)
3457 char ** str;
3458 int shift;
3459 enum wreg_type reg_type;
3460 {
3461 static char buff [128];
3462 int reg;
3463 char * start = *str;
3464
3465 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_IWMMXT].htab)) != FAIL)
3466 {
3467 if (wr_register (reg)
3468 && (reg_type == IWMMXT_REG_WR || reg_type == IWMMXT_REG_WR_OR_WC))
3469 {
3470 if (shift >= 0)
3471 inst.instruction |= (reg ^ WR_PREFIX) << shift;
3472 return reg;
3473 }
3474 else if (wc_register (reg)
3475 && (reg_type == IWMMXT_REG_WC || reg_type == IWMMXT_REG_WR_OR_WC))
3476 {
3477 if (shift >= 0)
3478 inst.instruction |= (reg ^ WC_PREFIX) << shift;
3479 return reg;
3480 }
3481 else if ((wcg_register (reg) && reg_type == IWMMXT_REG_WCG))
3482 {
3483 if (shift >= 0)
3484 inst.instruction |= ((reg ^ WC_PREFIX) - 8) << shift;
3485 return reg;
3486 }
3487 }
3488
3489 /* Restore the start point, we may have got a reg of the wrong class. */
3490 *str = start;
3491
3492 /* In the few cases where we might be able to accept
3493 something else this error can be overridden. */
3494 sprintf (buff, _("Intel Wireless MMX technology register expected, not '%.100s'"), start);
3495 inst.error = buff;
3496
3497 return FAIL;
3498 }
3499
3500 static const struct asm_psr *
3501 arm_psr_parse (ccp)
3502 register char ** ccp;
3503 {
3504 char * start = * ccp;
3505 char c;
3506 char * p;
3507 const struct asm_psr * psr;
3508
3509 p = start;
3510
3511 /* Skip to the end of the next word in the input stream. */
3512 do
3513 {
3514 c = *p++;
3515 }
3516 while (ISALPHA (c) || c == '_');
3517
3518 /* Terminate the word. */
3519 *--p = 0;
3520
3521 /* CPSR's and SPSR's can now be lowercase. This is just a convenience
3522 feature for ease of use and backwards compatibility. */
3523 if (!strncmp (start, "cpsr", 4))
3524 strncpy (start, "CPSR", 4);
3525 else if (!strncmp (start, "spsr", 4))
3526 strncpy (start, "SPSR", 4);
3527
3528 /* Now locate the word in the psr hash table. */
3529 psr = (const struct asm_psr *) hash_find (arm_psr_hsh, start);
3530
3531 /* Restore the input stream. */
3532 *p = c;
3533
3534 /* If we found a valid match, advance the
3535 stream pointer past the end of the word. */
3536 *ccp = p;
3537
3538 return psr;
3539 }
3540
3541 /* Parse the input looking for a PSR flag. */
3542
3543 static int
3544 psr_required_here (str)
3545 char ** str;
3546 {
3547 char * start = * str;
3548 const struct asm_psr * psr;
3549
3550 psr = arm_psr_parse (str);
3551
3552 if (psr)
3553 {
3554 /* If this is the SPSR that is being modified, set the R bit. */
3555 if (! psr->cpsr)
3556 inst.instruction |= SPSR_BIT;
3557
3558 /* Set the psr flags in the MSR instruction. */
3559 inst.instruction |= psr->field << PSR_SHIFT;
3560
3561 return SUCCESS;
3562 }
3563
3564 /* In the few cases where we might be able to accept
3565 something else this error can be overridden. */
3566 inst.error = _("flag for {c}psr instruction expected");
3567
3568 /* Restore the start point. */
3569 *str = start;
3570 return FAIL;
3571 }
3572
3573 static int
3574 co_proc_number (str)
3575 char **str;
3576 {
3577 int processor, pchar;
3578 char *start;
3579
3580 skip_whitespace (*str);
3581 start = *str;
3582
3583 /* The data sheet seems to imply that just a number on its own is valid
3584 here, but the RISC iX assembler seems to accept a prefix 'p'. We will
3585 accept either. */
3586 if ((processor = arm_reg_parse (str, all_reg_maps[REG_TYPE_CP].htab))
3587 == FAIL)
3588 {
3589 *str = start;
3590
3591 pchar = *(*str)++;
3592 if (pchar >= '0' && pchar <= '9')
3593 {
3594 processor = pchar - '0';
3595 if (**str >= '0' && **str <= '9')
3596 {
3597 processor = processor * 10 + *(*str)++ - '0';
3598 if (processor > 15)
3599 {
3600 inst.error = _("illegal co-processor number");
3601 return FAIL;
3602 }
3603 }
3604 }
3605 else
3606 {
3607 inst.error = _("bad or missing co-processor number");
3608 return FAIL;
3609 }
3610 }
3611
3612 inst.instruction |= processor << 8;
3613 return SUCCESS;
3614 }
3615
3616 static int
3617 cp_opc_expr (str, where, length)
3618 char ** str;
3619 int where;
3620 int length;
3621 {
3622 expressionS expr;
3623
3624 skip_whitespace (* str);
3625
3626 memset (&expr, '\0', sizeof (expr));
3627
3628 if (my_get_expression (&expr, str))
3629 return FAIL;
3630 if (expr.X_op != O_constant)
3631 {
3632 inst.error = _("bad or missing expression");
3633 return FAIL;
3634 }
3635
3636 if ((expr.X_add_number & ((1 << length) - 1)) != expr.X_add_number)
3637 {
3638 inst.error = _("immediate co-processor expression too large");
3639 return FAIL;
3640 }
3641
3642 inst.instruction |= expr.X_add_number << where;
3643 return SUCCESS;
3644 }
3645
3646 static int
3647 cp_reg_required_here (str, where)
3648 char ** str;
3649 int where;
3650 {
3651 int reg;
3652 char * start = *str;
3653
3654 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_CN].htab)) != FAIL)
3655 {
3656 inst.instruction |= reg << where;
3657 return reg;
3658 }
3659
3660 /* In the few cases where we might be able to accept something else
3661 this error can be overridden. */
3662 inst.error = _("co-processor register expected");
3663
3664 /* Restore the start point. */
3665 *str = start;
3666 return FAIL;
3667 }
3668
3669 static int
3670 fp_reg_required_here (str, where)
3671 char ** str;
3672 int where;
3673 {
3674 int reg;
3675 char * start = * str;
3676
3677 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_FN].htab)) != FAIL)
3678 {
3679 inst.instruction |= reg << where;
3680 return reg;
3681 }
3682
3683 /* In the few cases where we might be able to accept something else
3684 this error can be overridden. */
3685 inst.error = _("floating point register expected");
3686
3687 /* Restore the start point. */
3688 *str = start;
3689 return FAIL;
3690 }
3691
3692 static int
3693 cp_address_offset (str)
3694 char ** str;
3695 {
3696 int offset;
3697
3698 skip_whitespace (* str);
3699
3700 if (! is_immediate_prefix (**str))
3701 {
3702 inst.error = _("immediate expression expected");
3703 return FAIL;
3704 }
3705
3706 (*str)++;
3707
3708 if (my_get_expression (& inst.reloc.exp, str))
3709 return FAIL;
3710
3711 if (inst.reloc.exp.X_op == O_constant)
3712 {
3713 offset = inst.reloc.exp.X_add_number;
3714
3715 if (offset & 3)
3716 {
3717 inst.error = _("co-processor address must be word aligned");
3718 return FAIL;
3719 }
3720
3721 if (offset > 1023 || offset < -1023)
3722 {
3723 inst.error = _("offset too large");
3724 return FAIL;
3725 }
3726
3727 if (offset >= 0)
3728 inst.instruction |= INDEX_UP;
3729 else
3730 offset = -offset;
3731
3732 inst.instruction |= offset >> 2;
3733 }
3734 else
3735 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
3736
3737 return SUCCESS;
3738 }
3739
3740 static int
3741 cp_address_required_here (str, wb_ok)
3742 char ** str;
3743 int wb_ok;
3744 {
3745 char * p = * str;
3746 int pre_inc = 0;
3747 int write_back = 0;
3748
3749 if (*p == '[')
3750 {
3751 int reg;
3752
3753 p++;
3754 skip_whitespace (p);
3755
3756 if ((reg = reg_required_here (& p, 16)) == FAIL)
3757 return FAIL;
3758
3759 skip_whitespace (p);
3760
3761 if (*p == ']')
3762 {
3763 p++;
3764
3765 skip_whitespace (p);
3766
3767 if (*p == '\0')
3768 {
3769 /* As an extension to the official ARM syntax we allow:
3770
3771 [Rn]
3772
3773 as a short hand for:
3774
3775 [Rn,#0] */
3776 inst.instruction |= PRE_INDEX | INDEX_UP;
3777 *str = p;
3778 return SUCCESS;
3779 }
3780
3781 if (skip_past_comma (& p) == FAIL)
3782 {
3783 inst.error = _("comma expected after closing square bracket");
3784 return FAIL;
3785 }
3786
3787 skip_whitespace (p);
3788
3789 if (*p == '#')
3790 {
3791 if (wb_ok)
3792 {
3793 /* [Rn], #expr */
3794 write_back = WRITE_BACK;
3795
3796 if (reg == REG_PC)
3797 {
3798 inst.error = _("pc may not be used in post-increment");
3799 return FAIL;
3800 }
3801
3802 if (cp_address_offset (& p) == FAIL)
3803 return FAIL;
3804 }
3805 else
3806 pre_inc = PRE_INDEX | INDEX_UP;
3807 }
3808 else if (*p == '{')
3809 {
3810 int option;
3811
3812 /* [Rn], {<expr>} */
3813 p++;
3814
3815 skip_whitespace (p);
3816
3817 if (my_get_expression (& inst.reloc.exp, & p))
3818 return FAIL;
3819
3820 if (inst.reloc.exp.X_op == O_constant)
3821 {
3822 option = inst.reloc.exp.X_add_number;
3823
3824 if (option > 255 || option < 0)
3825 {
3826 inst.error = _("'option' field too large");
3827 return FAIL;
3828 }
3829
3830 skip_whitespace (p);
3831
3832 if (*p != '}')
3833 {
3834 inst.error = _("'}' expected at end of 'option' field");
3835 return FAIL;
3836 }
3837 else
3838 {
3839 p++;
3840 inst.instruction |= option;
3841 inst.instruction |= INDEX_UP;
3842 }
3843 }
3844 else
3845 {
3846 inst.error = _("non-constant expressions for 'option' field not supported");
3847 return FAIL;
3848 }
3849 }
3850 else
3851 {
3852 inst.error = _("# or { expected after comma");
3853 return FAIL;
3854 }
3855 }
3856 else
3857 {
3858 /* '['Rn, #expr']'[!] */
3859
3860 if (skip_past_comma (& p) == FAIL)
3861 {
3862 inst.error = _("pre-indexed expression expected");
3863 return FAIL;
3864 }
3865
3866 pre_inc = PRE_INDEX;
3867
3868 if (cp_address_offset (& p) == FAIL)
3869 return FAIL;
3870
3871 skip_whitespace (p);
3872
3873 if (*p++ != ']')
3874 {
3875 inst.error = _("missing ]");
3876 return FAIL;
3877 }
3878
3879 skip_whitespace (p);
3880
3881 if (wb_ok && *p == '!')
3882 {
3883 if (reg == REG_PC)
3884 {
3885 inst.error = _("pc may not be used with write-back");
3886 return FAIL;
3887 }
3888
3889 p++;
3890 write_back = WRITE_BACK;
3891 }
3892 }
3893 }
3894 else
3895 {
3896 if (my_get_expression (&inst.reloc.exp, &p))
3897 return FAIL;
3898
3899 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
3900 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
3901 inst.reloc.pc_rel = 1;
3902 inst.instruction |= (REG_PC << 16);
3903 pre_inc = PRE_INDEX;
3904 }
3905
3906 inst.instruction |= write_back | pre_inc;
3907 *str = p;
3908 return SUCCESS;
3909 }
3910
3911 static int
3912 cp_byte_address_offset (str)
3913 char ** str;
3914 {
3915 int offset;
3916
3917 skip_whitespace (* str);
3918
3919 if (! is_immediate_prefix (**str))
3920 {
3921 inst.error = _("immediate expression expected");
3922 return FAIL;
3923 }
3924
3925 (*str)++;
3926
3927 if (my_get_expression (& inst.reloc.exp, str))
3928 return FAIL;
3929
3930 if (inst.reloc.exp.X_op == O_constant)
3931 {
3932 offset = inst.reloc.exp.X_add_number;
3933
3934 if (offset > 255 || offset < -255)
3935 {
3936 inst.error = _("offset too large");
3937 return FAIL;
3938 }
3939
3940 if (offset >= 0)
3941 inst.instruction |= INDEX_UP;
3942 else
3943 offset = -offset;
3944
3945 inst.instruction |= offset;
3946 }
3947 else
3948 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM_S2;
3949
3950 return SUCCESS;
3951 }
3952
3953 static int
3954 cp_byte_address_required_here (str)
3955 char ** str;
3956 {
3957 char * p = * str;
3958 int pre_inc = 0;
3959 int write_back = 0;
3960
3961 if (*p == '[')
3962 {
3963 int reg;
3964
3965 p++;
3966 skip_whitespace (p);
3967
3968 if ((reg = reg_required_here (& p, 16)) == FAIL)
3969 return FAIL;
3970
3971 skip_whitespace (p);
3972
3973 if (*p == ']')
3974 {
3975 p++;
3976
3977 if (skip_past_comma (& p) == SUCCESS)
3978 {
3979 /* [Rn], #expr */
3980 write_back = WRITE_BACK;
3981
3982 if (reg == REG_PC)
3983 {
3984 inst.error = _("pc may not be used in post-increment");
3985 return FAIL;
3986 }
3987
3988 if (cp_byte_address_offset (& p) == FAIL)
3989 return FAIL;
3990 }
3991 else
3992 pre_inc = PRE_INDEX | INDEX_UP;
3993 }
3994 else
3995 {
3996 /* '['Rn, #expr']'[!] */
3997
3998 if (skip_past_comma (& p) == FAIL)
3999 {
4000 inst.error = _("pre-indexed expression expected");
4001 return FAIL;
4002 }
4003
4004 pre_inc = PRE_INDEX;
4005
4006 if (cp_byte_address_offset (& p) == FAIL)
4007 return FAIL;
4008
4009 skip_whitespace (p);
4010
4011 if (*p++ != ']')
4012 {
4013 inst.error = _("missing ]");
4014 return FAIL;
4015 }
4016
4017 skip_whitespace (p);
4018
4019 if (*p == '!')
4020 {
4021 if (reg == REG_PC)
4022 {
4023 inst.error = _("pc may not be used with write-back");
4024 return FAIL;
4025 }
4026
4027 p++;
4028 write_back = WRITE_BACK;
4029 }
4030 }
4031 }
4032 else
4033 {
4034 if (my_get_expression (&inst.reloc.exp, &p))
4035 return FAIL;
4036
4037 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM_S2;
4038 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
4039 inst.reloc.pc_rel = 1;
4040 inst.instruction |= (REG_PC << 16);
4041 pre_inc = PRE_INDEX;
4042 }
4043
4044 inst.instruction |= write_back | pre_inc;
4045 *str = p;
4046 return SUCCESS;
4047 }
4048
4049 static void
4050 do_empty (str)
4051 char * str;
4052 {
4053 /* Do nothing really. */
4054 end_of_line (str);
4055 }
4056
4057 static void
4058 do_mrs (str)
4059 char *str;
4060 {
4061 int skip = 0;
4062
4063 /* Only one syntax. */
4064 skip_whitespace (str);
4065
4066 if (reg_required_here (&str, 12) == FAIL)
4067 {
4068 inst.error = BAD_ARGS;
4069 return;
4070 }
4071
4072 if (skip_past_comma (&str) == FAIL)
4073 {
4074 inst.error = _("comma expected after register name");
4075 return;
4076 }
4077
4078 skip_whitespace (str);
4079
4080 if ( strcmp (str, "CPSR") == 0
4081 || strcmp (str, "SPSR") == 0
4082 /* Lower case versions for backwards compatibility. */
4083 || strcmp (str, "cpsr") == 0
4084 || strcmp (str, "spsr") == 0)
4085 skip = 4;
4086
4087 /* This is for backwards compatibility with older toolchains. */
4088 else if ( strcmp (str, "cpsr_all") == 0
4089 || strcmp (str, "spsr_all") == 0)
4090 skip = 8;
4091 else
4092 {
4093 inst.error = _("CPSR or SPSR expected");
4094 return;
4095 }
4096
4097 if (* str == 's' || * str == 'S')
4098 inst.instruction |= SPSR_BIT;
4099 str += skip;
4100
4101 end_of_line (str);
4102 }
4103
4104 /* Two possible forms:
4105 "{C|S}PSR_<field>, Rm",
4106 "{C|S}PSR_f, #expression". */
4107
4108 static void
4109 do_msr (str)
4110 char * str;
4111 {
4112 skip_whitespace (str);
4113
4114 if (psr_required_here (& str) == FAIL)
4115 return;
4116
4117 if (skip_past_comma (& str) == FAIL)
4118 {
4119 inst.error = _("comma missing after psr flags");
4120 return;
4121 }
4122
4123 skip_whitespace (str);
4124
4125 if (reg_required_here (& str, 0) != FAIL)
4126 {
4127 inst.error = NULL;
4128 end_of_line (str);
4129 return;
4130 }
4131
4132 if (! is_immediate_prefix (* str))
4133 {
4134 inst.error =
4135 _("only a register or immediate value can follow a psr flag");
4136 return;
4137 }
4138
4139 str ++;
4140 inst.error = NULL;
4141
4142 if (my_get_expression (& inst.reloc.exp, & str))
4143 {
4144 inst.error =
4145 _("only a register or immediate value can follow a psr flag");
4146 return;
4147 }
4148
4149 #if 0 /* The first edition of the ARM architecture manual stated that
4150 writing anything other than the flags with an immediate operation
4151 had UNPREDICTABLE effects. This constraint was removed in the
4152 second edition of the specification. */
4153 if ((cpu_variant & ARM_EXT_V5) != ARM_EXT_V5
4154 && inst.instruction & ((PSR_c | PSR_x | PSR_s) << PSR_SHIFT))
4155 {
4156 inst.error = _("immediate value cannot be used to set this field");
4157 return;
4158 }
4159 #endif
4160
4161 inst.instruction |= INST_IMMEDIATE;
4162
4163 if (inst.reloc.exp.X_add_symbol)
4164 {
4165 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
4166 inst.reloc.pc_rel = 0;
4167 }
4168 else
4169 {
4170 unsigned value = validate_immediate (inst.reloc.exp.X_add_number);
4171
4172 if (value == (unsigned) FAIL)
4173 {
4174 inst.error = _("invalid constant");
4175 return;
4176 }
4177
4178 inst.instruction |= value;
4179 }
4180
4181 inst.error = NULL;
4182 end_of_line (str);
4183 }
4184
4185 /* Long Multiply Parser
4186 UMULL RdLo, RdHi, Rm, Rs
4187 SMULL RdLo, RdHi, Rm, Rs
4188 UMLAL RdLo, RdHi, Rm, Rs
4189 SMLAL RdLo, RdHi, Rm, Rs. */
4190
4191 static void
4192 do_mull (str)
4193 char * str;
4194 {
4195 int rdlo, rdhi, rm, rs;
4196
4197 /* Only one format "rdlo, rdhi, rm, rs". */
4198 skip_whitespace (str);
4199
4200 if ((rdlo = reg_required_here (&str, 12)) == FAIL)
4201 {
4202 inst.error = BAD_ARGS;
4203 return;
4204 }
4205
4206 if (skip_past_comma (&str) == FAIL
4207 || (rdhi = reg_required_here (&str, 16)) == FAIL)
4208 {
4209 inst.error = BAD_ARGS;
4210 return;
4211 }
4212
4213 if (skip_past_comma (&str) == FAIL
4214 || (rm = reg_required_here (&str, 0)) == FAIL)
4215 {
4216 inst.error = BAD_ARGS;
4217 return;
4218 }
4219
4220 /* rdhi, rdlo and rm must all be different. */
4221 if (rdlo == rdhi || rdlo == rm || rdhi == rm)
4222 as_tsktsk (_("rdhi, rdlo and rm must all be different"));
4223
4224 if (skip_past_comma (&str) == FAIL
4225 || (rs = reg_required_here (&str, 8)) == FAIL)
4226 {
4227 inst.error = BAD_ARGS;
4228 return;
4229 }
4230
4231 if (rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC)
4232 {
4233 inst.error = BAD_PC;
4234 return;
4235 }
4236
4237 end_of_line (str);
4238 }
4239
4240 static void
4241 do_mul (str)
4242 char * str;
4243 {
4244 int rd, rm;
4245
4246 /* Only one format "rd, rm, rs". */
4247 skip_whitespace (str);
4248
4249 if ((rd = reg_required_here (&str, 16)) == FAIL)
4250 {
4251 inst.error = BAD_ARGS;
4252 return;
4253 }
4254
4255 if (rd == REG_PC)
4256 {
4257 inst.error = BAD_PC;
4258 return;
4259 }
4260
4261 if (skip_past_comma (&str) == FAIL
4262 || (rm = reg_required_here (&str, 0)) == FAIL)
4263 {
4264 inst.error = BAD_ARGS;
4265 return;
4266 }
4267
4268 if (rm == REG_PC)
4269 {
4270 inst.error = BAD_PC;
4271 return;
4272 }
4273
4274 if (rm == rd)
4275 as_tsktsk (_("rd and rm should be different in mul"));
4276
4277 if (skip_past_comma (&str) == FAIL
4278 || (rm = reg_required_here (&str, 8)) == FAIL)
4279 {
4280 inst.error = BAD_ARGS;
4281 return;
4282 }
4283
4284 if (rm == REG_PC)
4285 {
4286 inst.error = BAD_PC;
4287 return;
4288 }
4289
4290 end_of_line (str);
4291 }
4292
4293 static void
4294 do_mla (str)
4295 char * str;
4296 {
4297 int rd, rm;
4298
4299 /* Only one format "rd, rm, rs, rn". */
4300 skip_whitespace (str);
4301
4302 if ((rd = reg_required_here (&str, 16)) == FAIL)
4303 {
4304 inst.error = BAD_ARGS;
4305 return;
4306 }
4307
4308 if (rd == REG_PC)
4309 {
4310 inst.error = BAD_PC;
4311 return;
4312 }
4313
4314 if (skip_past_comma (&str) == FAIL
4315 || (rm = reg_required_here (&str, 0)) == FAIL)
4316 {
4317 inst.error = BAD_ARGS;
4318 return;
4319 }
4320
4321 if (rm == REG_PC)
4322 {
4323 inst.error = BAD_PC;
4324 return;
4325 }
4326
4327 if (rm == rd)
4328 as_tsktsk (_("rd and rm should be different in mla"));
4329
4330 if (skip_past_comma (&str) == FAIL
4331 || (rd = reg_required_here (&str, 8)) == FAIL
4332 || skip_past_comma (&str) == FAIL
4333 || (rm = reg_required_here (&str, 12)) == FAIL)
4334 {
4335 inst.error = BAD_ARGS;
4336 return;
4337 }
4338
4339 if (rd == REG_PC || rm == REG_PC)
4340 {
4341 inst.error = BAD_PC;
4342 return;
4343 }
4344
4345 end_of_line (str);
4346 }
4347
4348 /* Expects *str -> the characters "acc0", possibly with leading blanks.
4349 Advances *str to the next non-alphanumeric.
4350 Returns 0, or else FAIL (in which case sets inst.error).
4351
4352 (In a future XScale, there may be accumulators other than zero.
4353 At that time this routine and its callers can be upgraded to suit.) */
4354
4355 static int
4356 accum0_required_here (str)
4357 char ** str;
4358 {
4359 static char buff [128]; /* Note the address is taken. Hence, static. */
4360 char * p = * str;
4361 char c;
4362 int result = 0; /* The accum number. */
4363
4364 skip_whitespace (p);
4365
4366 *str = p; /* Advance caller's string pointer too. */
4367 c = *p++;
4368 while (ISALNUM (c))
4369 c = *p++;
4370
4371 *--p = 0; /* Aap nul into input buffer at non-alnum. */
4372
4373 if (! ( streq (*str, "acc0") || streq (*str, "ACC0")))
4374 {
4375 sprintf (buff, _("acc0 expected, not '%.100s'"), *str);
4376 inst.error = buff;
4377 result = FAIL;
4378 }
4379
4380 *p = c; /* Unzap. */
4381 *str = p; /* Caller's string pointer to after match. */
4382 return result;
4383 }
4384
4385 /* Expects **str -> after a comma. May be leading blanks.
4386 Advances *str, recognizing a load mode, and setting inst.instruction.
4387 Returns rn, or else FAIL (in which case may set inst.error
4388 and not advance str)
4389
4390 Note: doesn't know Rd, so no err checks that require such knowledge. */
4391
4392 static int
4393 ld_mode_required_here (string)
4394 char ** string;
4395 {
4396 char * str = * string;
4397 int rn;
4398 int pre_inc = 0;
4399
4400 skip_whitespace (str);
4401
4402 if (* str == '[')
4403 {
4404 str++;
4405
4406 skip_whitespace (str);
4407
4408 if ((rn = reg_required_here (& str, 16)) == FAIL)
4409 return FAIL;
4410
4411 skip_whitespace (str);
4412
4413 if (* str == ']')
4414 {
4415 str ++;
4416
4417 if (skip_past_comma (& str) == SUCCESS)
4418 {
4419 /* [Rn],... (post inc) */
4420 if (ldst_extend_v4 (&str) == FAIL)
4421 return FAIL;
4422 }
4423 else /* [Rn] */
4424 {
4425 skip_whitespace (str);
4426
4427 if (* str == '!')
4428 {
4429 str ++;
4430 inst.instruction |= WRITE_BACK;
4431 }
4432
4433 inst.instruction |= INDEX_UP | HWOFFSET_IMM;
4434 pre_inc = 1;
4435 }
4436 }
4437 else /* [Rn,...] */
4438 {
4439 if (skip_past_comma (& str) == FAIL)
4440 {
4441 inst.error = _("pre-indexed expression expected");
4442 return FAIL;
4443 }
4444
4445 pre_inc = 1;
4446
4447 if (ldst_extend_v4 (&str) == FAIL)
4448 return FAIL;
4449
4450 skip_whitespace (str);
4451
4452 if (* str ++ != ']')
4453 {
4454 inst.error = _("missing ]");
4455 return FAIL;
4456 }
4457
4458 skip_whitespace (str);
4459
4460 if (* str == '!')
4461 {
4462 str ++;
4463 inst.instruction |= WRITE_BACK;
4464 }
4465 }
4466 }
4467 else if (* str == '=') /* ldr's "r,=label" syntax */
4468 /* We should never reach here, because <text> = <expression> is
4469 caught gas/read.c read_a_source_file() as a .set operation. */
4470 return FAIL;
4471 else /* PC +- 8 bit immediate offset. */
4472 {
4473 if (my_get_expression (& inst.reloc.exp, & str))
4474 return FAIL;
4475
4476 inst.instruction |= HWOFFSET_IMM; /* The I bit. */
4477 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
4478 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
4479 inst.reloc.pc_rel = 1;
4480 inst.instruction |= (REG_PC << 16);
4481
4482 rn = REG_PC;
4483 pre_inc = 1;
4484 }
4485
4486 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
4487 * string = str;
4488
4489 return rn;
4490 }
4491
4492 /* ARM V5E (El Segundo) signed-multiply-accumulate (argument parse)
4493 SMLAxy{cond} Rd,Rm,Rs,Rn
4494 SMLAWy{cond} Rd,Rm,Rs,Rn
4495 Error if any register is R15. */
4496
4497 static void
4498 do_smla (str)
4499 char * str;
4500 {
4501 int rd, rm, rs, rn;
4502
4503 skip_whitespace (str);
4504
4505 if ((rd = reg_required_here (& str, 16)) == FAIL
4506 || skip_past_comma (& str) == FAIL
4507 || (rm = reg_required_here (& str, 0)) == FAIL
4508 || skip_past_comma (& str) == FAIL
4509 || (rs = reg_required_here (& str, 8)) == FAIL
4510 || skip_past_comma (& str) == FAIL
4511 || (rn = reg_required_here (& str, 12)) == FAIL)
4512 inst.error = BAD_ARGS;
4513
4514 else if (rd == REG_PC || rm == REG_PC || rs == REG_PC || rn == REG_PC)
4515 inst.error = BAD_PC;
4516
4517 else
4518 end_of_line (str);
4519 }
4520
4521 /* ARM V5E (El Segundo) signed-multiply-accumulate-long (argument parse)
4522 SMLALxy{cond} Rdlo,Rdhi,Rm,Rs
4523 Error if any register is R15.
4524 Warning if Rdlo == Rdhi. */
4525
4526 static void
4527 do_smlal (str)
4528 char * str;
4529 {
4530 int rdlo, rdhi, rm, rs;
4531
4532 skip_whitespace (str);
4533
4534 if ((rdlo = reg_required_here (& str, 12)) == FAIL
4535 || skip_past_comma (& str) == FAIL
4536 || (rdhi = reg_required_here (& str, 16)) == FAIL
4537 || skip_past_comma (& str) == FAIL
4538 || (rm = reg_required_here (& str, 0)) == FAIL
4539 || skip_past_comma (& str) == FAIL
4540 || (rs = reg_required_here (& str, 8)) == FAIL)
4541 {
4542 inst.error = BAD_ARGS;
4543 return;
4544 }
4545
4546 if (rdlo == REG_PC || rdhi == REG_PC || rm == REG_PC || rs == REG_PC)
4547 {
4548 inst.error = BAD_PC;
4549 return;
4550 }
4551
4552 if (rdlo == rdhi)
4553 as_tsktsk (_("rdhi and rdlo must be different"));
4554
4555 end_of_line (str);
4556 }
4557
4558 /* ARM V5E (El Segundo) signed-multiply (argument parse)
4559 SMULxy{cond} Rd,Rm,Rs
4560 Error if any register is R15. */
4561
4562 static void
4563 do_smul (str)
4564 char * str;
4565 {
4566 int rd, rm, rs;
4567
4568 skip_whitespace (str);
4569
4570 if ((rd = reg_required_here (& str, 16)) == FAIL
4571 || skip_past_comma (& str) == FAIL
4572 || (rm = reg_required_here (& str, 0)) == FAIL
4573 || skip_past_comma (& str) == FAIL
4574 || (rs = reg_required_here (& str, 8)) == FAIL)
4575 inst.error = BAD_ARGS;
4576
4577 else if (rd == REG_PC || rm == REG_PC || rs == REG_PC)
4578 inst.error = BAD_PC;
4579
4580 else
4581 end_of_line (str);
4582 }
4583
4584 /* ARM V5E (El Segundo) saturating-add/subtract (argument parse)
4585 Q[D]{ADD,SUB}{cond} Rd,Rm,Rn
4586 Error if any register is R15. */
4587
4588 static void
4589 do_qadd (str)
4590 char * str;
4591 {
4592 int rd, rm, rn;
4593
4594 skip_whitespace (str);
4595
4596 if ((rd = reg_required_here (& str, 12)) == FAIL
4597 || skip_past_comma (& str) == FAIL
4598 || (rm = reg_required_here (& str, 0)) == FAIL
4599 || skip_past_comma (& str) == FAIL
4600 || (rn = reg_required_here (& str, 16)) == FAIL)
4601 inst.error = BAD_ARGS;
4602
4603 else if (rd == REG_PC || rm == REG_PC || rn == REG_PC)
4604 inst.error = BAD_PC;
4605
4606 else
4607 end_of_line (str);
4608 }
4609
4610 /* ARM V5E (el Segundo)
4611 MCRRcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
4612 MRRCcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
4613
4614 These are equivalent to the XScale instructions MAR and MRA,
4615 respectively, when coproc == 0, opcode == 0, and CRm == 0.
4616
4617 Result unpredicatable if Rd or Rn is R15. */
4618
4619 static void
4620 do_co_reg2c (str)
4621 char * str;
4622 {
4623 int rd, rn;
4624
4625 skip_whitespace (str);
4626
4627 if (co_proc_number (& str) == FAIL)
4628 {
4629 if (!inst.error)
4630 inst.error = BAD_ARGS;
4631 return;
4632 }
4633
4634 if (skip_past_comma (& str) == FAIL
4635 || cp_opc_expr (& str, 4, 4) == FAIL)
4636 {
4637 if (!inst.error)
4638 inst.error = BAD_ARGS;
4639 return;
4640 }
4641
4642 if (skip_past_comma (& str) == FAIL
4643 || (rd = reg_required_here (& str, 12)) == FAIL)
4644 {
4645 if (!inst.error)
4646 inst.error = BAD_ARGS;
4647 return;
4648 }
4649
4650 if (skip_past_comma (& str) == FAIL
4651 || (rn = reg_required_here (& str, 16)) == FAIL)
4652 {
4653 if (!inst.error)
4654 inst.error = BAD_ARGS;
4655 return;
4656 }
4657
4658 /* Unpredictable result if rd or rn is R15. */
4659 if (rd == REG_PC || rn == REG_PC)
4660 as_tsktsk
4661 (_("Warning: instruction unpredictable when using r15"));
4662
4663 if (skip_past_comma (& str) == FAIL
4664 || cp_reg_required_here (& str, 0) == FAIL)
4665 {
4666 if (!inst.error)
4667 inst.error = BAD_ARGS;
4668 return;
4669 }
4670
4671 end_of_line (str);
4672 }
4673
4674 /* ARM V5 count-leading-zeroes instruction (argument parse)
4675 CLZ{<cond>} <Rd>, <Rm>
4676 Condition defaults to COND_ALWAYS.
4677 Error if Rd or Rm are R15. */
4678
4679 static void
4680 do_clz (str)
4681 char * str;
4682 {
4683 int rd, rm;
4684
4685 skip_whitespace (str);
4686
4687 if (((rd = reg_required_here (& str, 12)) == FAIL)
4688 || (skip_past_comma (& str) == FAIL)
4689 || ((rm = reg_required_here (& str, 0)) == FAIL))
4690 inst.error = BAD_ARGS;
4691
4692 else if (rd == REG_PC || rm == REG_PC )
4693 inst.error = BAD_PC;
4694
4695 else
4696 end_of_line (str);
4697 }
4698
4699 /* ARM V5 (argument parse)
4700 LDC2{L} <coproc>, <CRd>, <addressing mode>
4701 STC2{L} <coproc>, <CRd>, <addressing mode>
4702 Instruction is not conditional, and has 0xf in the condition field.
4703 Otherwise, it's the same as LDC/STC. */
4704
4705 static void
4706 do_lstc2 (str)
4707 char * str;
4708 {
4709 skip_whitespace (str);
4710
4711 if (co_proc_number (& str) == FAIL)
4712 {
4713 if (!inst.error)
4714 inst.error = BAD_ARGS;
4715 }
4716 else if (skip_past_comma (& str) == FAIL
4717 || cp_reg_required_here (& str, 12) == FAIL)
4718 {
4719 if (!inst.error)
4720 inst.error = BAD_ARGS;
4721 }
4722 else if (skip_past_comma (& str) == FAIL
4723 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
4724 {
4725 if (! inst.error)
4726 inst.error = BAD_ARGS;
4727 }
4728 else
4729 end_of_line (str);
4730 }
4731
4732 /* ARM V5 (argument parse)
4733 CDP2 <coproc>, <opcode_1>, <CRd>, <CRn>, <CRm>, <opcode_2>
4734 Instruction is not conditional, and has 0xf in the condition field.
4735 Otherwise, it's the same as CDP. */
4736
4737 static void
4738 do_cdp2 (str)
4739 char * str;
4740 {
4741 skip_whitespace (str);
4742
4743 if (co_proc_number (& str) == FAIL)
4744 {
4745 if (!inst.error)
4746 inst.error = BAD_ARGS;
4747 return;
4748 }
4749
4750 if (skip_past_comma (& str) == FAIL
4751 || cp_opc_expr (& str, 20,4) == FAIL)
4752 {
4753 if (!inst.error)
4754 inst.error = BAD_ARGS;
4755 return;
4756 }
4757
4758 if (skip_past_comma (& str) == FAIL
4759 || cp_reg_required_here (& str, 12) == FAIL)
4760 {
4761 if (!inst.error)
4762 inst.error = BAD_ARGS;
4763 return;
4764 }
4765
4766 if (skip_past_comma (& str) == FAIL
4767 || cp_reg_required_here (& str, 16) == FAIL)
4768 {
4769 if (!inst.error)
4770 inst.error = BAD_ARGS;
4771 return;
4772 }
4773
4774 if (skip_past_comma (& str) == FAIL
4775 || cp_reg_required_here (& str, 0) == FAIL)
4776 {
4777 if (!inst.error)
4778 inst.error = BAD_ARGS;
4779 return;
4780 }
4781
4782 if (skip_past_comma (& str) == SUCCESS)
4783 {
4784 if (cp_opc_expr (& str, 5, 3) == FAIL)
4785 {
4786 if (!inst.error)
4787 inst.error = BAD_ARGS;
4788 return;
4789 }
4790 }
4791
4792 end_of_line (str);
4793 }
4794
4795 /* ARM V5 (argument parse)
4796 MCR2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
4797 MRC2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
4798 Instruction is not conditional, and has 0xf in the condition field.
4799 Otherwise, it's the same as MCR/MRC. */
4800
4801 static void
4802 do_co_reg2 (str)
4803 char * str;
4804 {
4805 skip_whitespace (str);
4806
4807 if (co_proc_number (& str) == FAIL)
4808 {
4809 if (!inst.error)
4810 inst.error = BAD_ARGS;
4811 return;
4812 }
4813
4814 if (skip_past_comma (& str) == FAIL
4815 || cp_opc_expr (& str, 21, 3) == FAIL)
4816 {
4817 if (!inst.error)
4818 inst.error = BAD_ARGS;
4819 return;
4820 }
4821
4822 if (skip_past_comma (& str) == FAIL
4823 || reg_required_here (& str, 12) == FAIL)
4824 {
4825 if (!inst.error)
4826 inst.error = BAD_ARGS;
4827 return;
4828 }
4829
4830 if (skip_past_comma (& str) == FAIL
4831 || cp_reg_required_here (& str, 16) == FAIL)
4832 {
4833 if (!inst.error)
4834 inst.error = BAD_ARGS;
4835 return;
4836 }
4837
4838 if (skip_past_comma (& str) == FAIL
4839 || cp_reg_required_here (& str, 0) == FAIL)
4840 {
4841 if (!inst.error)
4842 inst.error = BAD_ARGS;
4843 return;
4844 }
4845
4846 if (skip_past_comma (& str) == SUCCESS)
4847 {
4848 if (cp_opc_expr (& str, 5, 3) == FAIL)
4849 {
4850 if (!inst.error)
4851 inst.error = BAD_ARGS;
4852 return;
4853 }
4854 }
4855
4856 end_of_line (str);
4857 }
4858
4859 /* ARM v5TEJ. Jump to Jazelle code. */
4860 static void
4861 do_bxj (str)
4862 char * str;
4863 {
4864 int reg;
4865
4866 skip_whitespace (str);
4867
4868 if ((reg = reg_required_here (&str, 0)) == FAIL)
4869 {
4870 inst.error = BAD_ARGS;
4871 return;
4872 }
4873
4874 /* Note - it is not illegal to do a "bxj pc". Useless, but not illegal. */
4875 if (reg == REG_PC)
4876 as_tsktsk (_("use of r15 in bxj is not really useful"));
4877
4878 end_of_line (str);
4879 }
4880
4881 /* ARM V6 umaal (argument parse). */
4882
4883 static void
4884 do_umaal (str)
4885 char *str;
4886 {
4887
4888 int rdlo, rdhi, rm, rs;
4889
4890 skip_whitespace (str);
4891 if ((rdlo = reg_required_here (& str, 12)) == FAIL
4892 || skip_past_comma (& str) == FAIL
4893 || (rdhi = reg_required_here (& str, 16)) == FAIL
4894 || skip_past_comma (& str) == FAIL
4895 || (rm = reg_required_here (& str, 0)) == FAIL
4896 || skip_past_comma (& str) == FAIL
4897 || (rs = reg_required_here (& str, 8)) == FAIL)
4898 {
4899 inst.error = BAD_ARGS;
4900 return;
4901 }
4902
4903 if (rdlo == REG_PC || rdhi == REG_PC || rm == REG_PC || rs == REG_PC)
4904 {
4905 inst.error = BAD_PC;
4906 return;
4907 }
4908
4909 end_of_line (str);
4910 }
4911
4912 /* ARM V6 strex (argument parse). */
4913
4914 static void
4915 do_strex (str)
4916 char *str;
4917 {
4918 int rd, rm, rn;
4919
4920 /* Parse Rd, Rm,. */
4921 skip_whitespace (str);
4922 if ((rd = reg_required_here (& str, 12)) == FAIL
4923 || skip_past_comma (& str) == FAIL
4924 || (rm = reg_required_here (& str, 0)) == FAIL
4925 || skip_past_comma (& str) == FAIL)
4926 {
4927 inst.error = BAD_ARGS;
4928 return;
4929 }
4930 if (rd == REG_PC || rm == REG_PC)
4931 {
4932 inst.error = BAD_PC;
4933 return;
4934 }
4935 if (rd == rm)
4936 {
4937 inst.error = _("Rd equal to Rm or Rn yields unpredictable results");
4938 return;
4939 }
4940
4941 /* Skip past '['. */
4942 if ((strlen (str) >= 1)
4943 && strncmp (str, "[", 1) == 0)
4944 str+=1;
4945 skip_whitespace (str);
4946
4947 /* Parse Rn. */
4948 if ((rn = reg_required_here (& str, 16)) == FAIL)
4949 {
4950 inst.error = BAD_ARGS;
4951 return;
4952 }
4953 else if (rn == REG_PC)
4954 {
4955 inst.error = BAD_PC;
4956 return;
4957 }
4958 if (rd == rn)
4959 {
4960 inst.error = _("Rd equal to Rm or Rn yields unpredictable results");
4961 return;
4962 }
4963 skip_whitespace (str);
4964
4965 /* Skip past ']'. */
4966 if ((strlen (str) >= 1)
4967 && strncmp (str, "]", 1) == 0)
4968 str+=1;
4969
4970 end_of_line (str);
4971 }
4972
4973 /* ARM V6 ssat (argument parse). */
4974
4975 static void
4976 do_ssat (str)
4977 char* str;
4978 {
4979 do_sat (&str, /*bias=*/-1);
4980 end_of_line (str);
4981 }
4982
4983 /* ARM V6 usat (argument parse). */
4984
4985 static void
4986 do_usat (str)
4987 char* str;
4988 {
4989 do_sat (&str, /*bias=*/0);
4990 end_of_line (str);
4991 }
4992
4993 static void
4994 do_sat (str, bias)
4995 char **str;
4996 int bias;
4997 {
4998 int rd, rm;
4999 expressionS expr;
5000
5001 skip_whitespace (*str);
5002
5003 /* Parse <Rd>, field. */
5004 if ((rd = reg_required_here (str, 12)) == FAIL
5005 || skip_past_comma (str) == FAIL)
5006 {
5007 inst.error = BAD_ARGS;
5008 return;
5009 }
5010 if (rd == REG_PC)
5011 {
5012 inst.error = BAD_PC;
5013 return;
5014 }
5015
5016 /* Parse #<immed>, field. */
5017 if (is_immediate_prefix (**str))
5018 (*str)++;
5019 else
5020 {
5021 inst.error = _("immediate expression expected");
5022 return;
5023 }
5024 if (my_get_expression (&expr, str))
5025 {
5026 inst.error = _("bad expression");
5027 return;
5028 }
5029 if (expr.X_op != O_constant)
5030 {
5031 inst.error = _("constant expression expected");
5032 return;
5033 }
5034 if (expr.X_add_number + bias < 0
5035 || expr.X_add_number + bias > 31)
5036 {
5037 inst.error = _("immediate value out of range");
5038 return;
5039 }
5040 inst.instruction |= (expr.X_add_number + bias) << 16;
5041 if (skip_past_comma (str) == FAIL)
5042 {
5043 inst.error = BAD_ARGS;
5044 return;
5045 }
5046
5047 /* Parse <Rm> field. */
5048 if ((rm = reg_required_here (str, 0)) == FAIL)
5049 {
5050 inst.error = BAD_ARGS;
5051 return;
5052 }
5053 if (rm == REG_PC)
5054 {
5055 inst.error = BAD_PC;
5056 return;
5057 }
5058
5059 if (skip_past_comma (str) == SUCCESS)
5060 decode_shift (str, SHIFT_LSL_OR_ASR_IMMEDIATE);
5061 }
5062
5063 /* ARM V6 ssat16 (argument parse). */
5064
5065 static void
5066 do_ssat16 (str)
5067 char *str;
5068 {
5069 do_sat16 (&str, /*bias=*/-1);
5070 end_of_line (str);
5071 }
5072
5073 static void
5074 do_usat16 (str)
5075 char *str;
5076 {
5077 do_sat16 (&str, /*bias=*/0);
5078 end_of_line (str);
5079 }
5080
5081 static void
5082 do_sat16 (str, bias)
5083 char **str;
5084 int bias;
5085 {
5086 int rd, rm;
5087 expressionS expr;
5088
5089 skip_whitespace (*str);
5090
5091 /* Parse the <Rd> field. */
5092 if ((rd = reg_required_here (str, 12)) == FAIL
5093 || skip_past_comma (str) == FAIL)
5094 {
5095 inst.error = BAD_ARGS;
5096 return;
5097 }
5098 if (rd == REG_PC)
5099 {
5100 inst.error = BAD_PC;
5101 return;
5102 }
5103
5104 /* Parse #<immed>, field. */
5105 if (is_immediate_prefix (**str))
5106 (*str)++;
5107 else
5108 {
5109 inst.error = _("immediate expression expected");
5110 return;
5111 }
5112 if (my_get_expression (&expr, str))
5113 {
5114 inst.error = _("bad expression");
5115 return;
5116 }
5117 if (expr.X_op != O_constant)
5118 {
5119 inst.error = _("constant expression expected");
5120 return;
5121 }
5122 if (expr.X_add_number + bias < 0
5123 || expr.X_add_number + bias > 15)
5124 {
5125 inst.error = _("immediate value out of range");
5126 return;
5127 }
5128 inst.instruction |= (expr.X_add_number + bias) << 16;
5129 if (skip_past_comma (str) == FAIL)
5130 {
5131 inst.error = BAD_ARGS;
5132 return;
5133 }
5134
5135 /* Parse <Rm> field. */
5136 if ((rm = reg_required_here (str, 0)) == FAIL)
5137 {
5138 inst.error = BAD_ARGS;
5139 return;
5140 }
5141 if (rm == REG_PC)
5142 {
5143 inst.error = BAD_PC;
5144 return;
5145 }
5146 }
5147
5148 /* ARM V6 srs (argument parse). */
5149
5150 static void
5151 do_srs (str)
5152 char* str;
5153 {
5154 char *exclam;
5155 skip_whitespace (str);
5156 exclam = strchr (str, '!');
5157 if (exclam)
5158 *exclam = '\0';
5159 do_cps_mode (&str);
5160 if (exclam)
5161 *exclam = '!';
5162 if (*str == '!')
5163 {
5164 inst.instruction |= WRITE_BACK;
5165 str++;
5166 }
5167 end_of_line (str);
5168 }
5169
5170 /* ARM V6 SMMUL (argument parse). */
5171
5172 static void
5173 do_smmul (str)
5174 char* str;
5175 {
5176 int rd, rm, rs;
5177
5178 skip_whitespace (str);
5179 if ((rd = reg_required_here (&str, 16)) == FAIL
5180 || skip_past_comma (&str) == FAIL
5181 || (rm = reg_required_here (&str, 0)) == FAIL
5182 || skip_past_comma (&str) == FAIL
5183 || (rs = reg_required_here (&str, 8)) == FAIL)
5184 {
5185 inst.error = BAD_ARGS;
5186 return;
5187 }
5188
5189 if (rd == REG_PC
5190 || rm == REG_PC
5191 || rs == REG_PC)
5192 {
5193 inst.error = BAD_PC;
5194 return;
5195 }
5196
5197 end_of_line (str);
5198
5199 }
5200
5201 /* ARM V6 SMLALD (argument parse). */
5202
5203 static void
5204 do_smlald (str)
5205 char* str;
5206 {
5207 int rdlo, rdhi, rm, rs;
5208 skip_whitespace (str);
5209 if ((rdlo = reg_required_here (&str, 12)) == FAIL
5210 || skip_past_comma (&str) == FAIL
5211 || (rdhi = reg_required_here (&str, 16)) == FAIL
5212 || skip_past_comma (&str) == FAIL
5213 || (rm = reg_required_here (&str, 0)) == FAIL
5214 || skip_past_comma (&str) == FAIL
5215 || (rs = reg_required_here (&str, 8)) == FAIL)
5216 {
5217 inst.error = BAD_ARGS;
5218 return;
5219 }
5220
5221 if (rdlo == REG_PC
5222 || rdhi == REG_PC
5223 || rm == REG_PC
5224 || rs == REG_PC)
5225 {
5226 inst.error = BAD_PC;
5227 return;
5228 }
5229
5230 end_of_line (str);
5231 }
5232
5233 /* ARM V6 SMLAD (argument parse). Signed multiply accumulate dual.
5234 smlad{x}{<cond>} Rd, Rm, Rs, Rn */
5235
5236 static void
5237 do_smlad (str)
5238 char *str;
5239 {
5240 int rd, rm, rs, rn;
5241
5242 skip_whitespace (str);
5243 if ((rd = reg_required_here (&str, 16)) == FAIL
5244 || skip_past_comma (&str) == FAIL
5245 || (rm = reg_required_here (&str, 0)) == FAIL
5246 || skip_past_comma (&str) == FAIL
5247 || (rs = reg_required_here (&str, 8)) == FAIL
5248 || skip_past_comma (&str) == FAIL
5249 || (rn = reg_required_here (&str, 12)) == FAIL)
5250 {
5251 inst.error = BAD_ARGS;
5252 return;
5253 }
5254
5255 if (rd == REG_PC
5256 || rn == REG_PC
5257 || rs == REG_PC
5258 || rm == REG_PC)
5259 {
5260 inst.error = BAD_PC;
5261 return;
5262 }
5263
5264 end_of_line (str);
5265 }
5266
5267 /* ARM V6 SETEND (argument parse). Sets the E bit in the CPSR while
5268 preserving the other bits.
5269
5270 setend <endian_specifier>, where <endian_specifier> is either
5271 BE or LE. */
5272
5273 static void
5274 do_setend (str)
5275 char *str;
5276 {
5277 if (do_endian_specifier (str))
5278 inst.instruction |= 0x200;
5279 }
5280
5281 /* Returns true if the endian-specifier indicates big-endianness. */
5282
5283 static int
5284 do_endian_specifier (str)
5285 char *str;
5286 {
5287 int big_endian = 0;
5288
5289 skip_whitespace (str);
5290 if (strlen (str) < 2)
5291 inst.error = _("missing endian specifier");
5292 else if (strncasecmp (str, "BE", 2) == 0)
5293 {
5294 str += 2;
5295 big_endian = 1;
5296 }
5297 else if (strncasecmp (str, "LE", 2) == 0)
5298 str += 2;
5299 else
5300 inst.error = _("valid endian specifiers are be or le");
5301
5302 end_of_line (str);
5303
5304 return big_endian;
5305 }
5306
5307 /* ARM V6 SXTH.
5308
5309 SXTH {<cond>} <Rd>, <Rm>{, <rotation>}
5310 Condition defaults to COND_ALWAYS.
5311 Error if any register uses R15. */
5312
5313 static void
5314 do_sxth (str)
5315 char *str;
5316 {
5317 int rd, rm;
5318 expressionS expr;
5319 int rotation_clear_mask = 0xfffff3ff;
5320 int rotation_eight_mask = 0x00000400;
5321 int rotation_sixteen_mask = 0x00000800;
5322 int rotation_twenty_four_mask = 0x00000c00;
5323
5324 skip_whitespace (str);
5325 if ((rd = reg_required_here (&str, 12)) == FAIL
5326 || skip_past_comma (&str) == FAIL
5327 || (rm = reg_required_here (&str, 0)) == FAIL)
5328 {
5329 inst.error = BAD_ARGS;
5330 return;
5331 }
5332
5333 else if (rd == REG_PC || rm == REG_PC)
5334 {
5335 inst.error = BAD_PC;
5336 return;
5337 }
5338
5339 /* Zero out the rotation field. */
5340 inst.instruction &= rotation_clear_mask;
5341
5342 /* Check for lack of optional rotation field. */
5343 if (skip_past_comma (&str) == FAIL)
5344 {
5345 end_of_line (str);
5346 return;
5347 }
5348
5349 /* Move past 'ROR'. */
5350 skip_whitespace (str);
5351 if (strncasecmp (str, "ROR", 3) == 0)
5352 str+=3;
5353 else
5354 {
5355 inst.error = _("missing rotation field after comma");
5356 return;
5357 }
5358
5359 /* Get the immediate constant. */
5360 skip_whitespace (str);
5361 if (is_immediate_prefix (* str))
5362 str++;
5363 else
5364 {
5365 inst.error = _("immediate expression expected");
5366 return;
5367 }
5368
5369 if (my_get_expression (&expr, &str))
5370 {
5371 inst.error = _("bad expression");
5372 return;
5373 }
5374
5375 if (expr.X_op != O_constant)
5376 {
5377 inst.error = _("constant expression expected");
5378 return;
5379 }
5380
5381 switch (expr.X_add_number)
5382 {
5383 case 0:
5384 /* Rotation field has already been zeroed. */
5385 break;
5386 case 8:
5387 inst.instruction |= rotation_eight_mask;
5388 break;
5389
5390 case 16:
5391 inst.instruction |= rotation_sixteen_mask;
5392 break;
5393
5394 case 24:
5395 inst.instruction |= rotation_twenty_four_mask;
5396 break;
5397
5398 default:
5399 inst.error = _("rotation can be 8, 16, 24 or 0 when field is ommited");
5400 break;
5401 }
5402
5403 end_of_line (str);
5404
5405 }
5406
5407 /* ARM V6 SXTAH extracts a 16-bit value from a register, sign
5408 extends it to 32-bits, and adds the result to a value in another
5409 register. You can specify a rotation by 0, 8, 16, or 24 bits
5410 before extracting the 16-bit value.
5411 SXTAH{<cond>} <Rd>, <Rn>, <Rm>{, <rotation>}
5412 Condition defaults to COND_ALWAYS.
5413 Error if any register uses R15. */
5414
5415 static void
5416 do_sxtah (str)
5417 char *str;
5418 {
5419 int rd, rn, rm;
5420 expressionS expr;
5421 int rotation_clear_mask = 0xfffff3ff;
5422 int rotation_eight_mask = 0x00000400;
5423 int rotation_sixteen_mask = 0x00000800;
5424 int rotation_twenty_four_mask = 0x00000c00;
5425
5426 skip_whitespace (str);
5427 if ((rd = reg_required_here (&str, 12)) == FAIL
5428 || skip_past_comma (&str) == FAIL
5429 || (rn = reg_required_here (&str, 16)) == FAIL
5430 || skip_past_comma (&str) == FAIL
5431 || (rm = reg_required_here (&str, 0)) == FAIL)
5432 {
5433 inst.error = BAD_ARGS;
5434 return;
5435 }
5436
5437 else if (rd == REG_PC || rn == REG_PC || rm == REG_PC)
5438 {
5439 inst.error = BAD_PC;
5440 return;
5441 }
5442
5443 /* Zero out the rotation field. */
5444 inst.instruction &= rotation_clear_mask;
5445
5446 /* Check for lack of optional rotation field. */
5447 if (skip_past_comma (&str) == FAIL)
5448 {
5449 end_of_line (str);
5450 return;
5451 }
5452
5453 /* Move past 'ROR'. */
5454 skip_whitespace (str);
5455 if (strncasecmp (str, "ROR", 3) == 0)
5456 str+=3;
5457 else
5458 {
5459 inst.error = _("missing rotation field after comma");
5460 return;
5461 }
5462
5463 /* Get the immediate constant. */
5464 skip_whitespace (str);
5465 if (is_immediate_prefix (* str))
5466 str++;
5467 else
5468 {
5469 inst.error = _("immediate expression expected");
5470 return;
5471 }
5472
5473 if (my_get_expression (&expr, &str))
5474 {
5475 inst.error = _("bad expression");
5476 return;
5477 }
5478
5479 if (expr.X_op != O_constant)
5480 {
5481 inst.error = _("constant expression expected");
5482 return;
5483 }
5484
5485 switch (expr.X_add_number)
5486 {
5487 case 0:
5488 /* Rotation field has already been zeroed. */
5489 break;
5490
5491 case 8:
5492 inst.instruction |= rotation_eight_mask;
5493 break;
5494
5495 case 16:
5496 inst.instruction |= rotation_sixteen_mask;
5497 break;
5498
5499 case 24:
5500 inst.instruction |= rotation_twenty_four_mask;
5501 break;
5502
5503 default:
5504 inst.error = _("rotation can be 8, 16, 24 or 0 when field is ommited");
5505 break;
5506 }
5507
5508 end_of_line (str);
5509
5510 }
5511
5512
5513 /* ARM V6 RFE (Return from Exception) loads the PC and CPSR from the
5514 word at the specified address and the following word
5515 respectively.
5516 Unconditionally executed.
5517 Error if Rn is R15.
5518 */
5519
5520 static void
5521 do_rfe (str)
5522 char *str;
5523 {
5524 int rn;
5525
5526 skip_whitespace (str);
5527
5528 if ((rn = reg_required_here (&str, 16)) == FAIL)
5529 return;
5530
5531 if (rn == REG_PC)
5532 {
5533 inst.error = BAD_PC;
5534 return;
5535 }
5536
5537 skip_whitespace (str);
5538
5539 if (*str == '!')
5540 {
5541 inst.instruction |= WRITE_BACK;
5542 str++;
5543 }
5544 end_of_line (str);
5545 }
5546
5547 /* ARM V6 REV (Byte Reverse Word) reverses the byte order in a 32-bit
5548 register (argument parse).
5549 REV{<cond>} Rd, Rm.
5550 Condition defaults to COND_ALWAYS.
5551 Error if Rd or Rm are R15. */
5552
5553 static void
5554 do_rev (str)
5555 char* str;
5556 {
5557 int rd, rm;
5558
5559 skip_whitespace (str);
5560
5561 if ((rd = reg_required_here (&str, 12)) == FAIL
5562 || skip_past_comma (&str) == FAIL
5563 || (rm = reg_required_here (&str, 0)) == FAIL)
5564 inst.error = BAD_ARGS;
5565
5566 else if (rd == REG_PC || rm == REG_PC)
5567 inst.error = BAD_PC;
5568
5569 else
5570 end_of_line (str);
5571 }
5572
5573 /* ARM V6 Perform Two Sixteen Bit Integer Additions. (argument parse).
5574 QADD16{<cond>} <Rd>, <Rn>, <Rm>
5575 Condition defaults to COND_ALWAYS.
5576 Error if Rd, Rn or Rm are R15. */
5577
5578 static void
5579 do_qadd16 (str)
5580 char* str;
5581 {
5582 int rd, rm, rn;
5583
5584 skip_whitespace (str);
5585
5586 if ((rd = reg_required_here (&str, 12)) == FAIL
5587 || skip_past_comma (&str) == FAIL
5588 || (rn = reg_required_here (&str, 16)) == FAIL
5589 || skip_past_comma (&str) == FAIL
5590 || (rm = reg_required_here (&str, 0)) == FAIL)
5591 inst.error = BAD_ARGS;
5592
5593 else if (rd == REG_PC || rm == REG_PC || rn == REG_PC)
5594 inst.error = BAD_PC;
5595
5596 else
5597 end_of_line (str);
5598 }
5599
5600 /* ARM V6 Pack Halfword Bottom Top instruction (argument parse).
5601 PKHBT {<cond>} <Rd>, <Rn>, <Rm> {, LSL #<shift_imm>}
5602 Condition defaults to COND_ALWAYS.
5603 Error if Rd, Rn or Rm are R15. */
5604
5605 static void
5606 do_pkhbt (str)
5607 char* str;
5608 {
5609 do_pkh_core (str, SHIFT_LSL_IMMEDIATE);
5610 }
5611
5612 /* ARM V6 PKHTB (Argument Parse). */
5613
5614 static void
5615 do_pkhtb (str)
5616 char* str;
5617 {
5618 do_pkh_core (str, SHIFT_ASR_IMMEDIATE);
5619 }
5620
5621 static void
5622 do_pkh_core (str, shift)
5623 char* str;
5624 int shift;
5625 {
5626 int rd, rn, rm;
5627
5628 skip_whitespace (str);
5629 if (((rd = reg_required_here (&str, 12)) == FAIL)
5630 || (skip_past_comma (&str) == FAIL)
5631 || ((rn = reg_required_here (&str, 16)) == FAIL)
5632 || (skip_past_comma (&str) == FAIL)
5633 || ((rm = reg_required_here (&str, 0)) == FAIL))
5634 {
5635 inst.error = BAD_ARGS;
5636 return;
5637 }
5638
5639 else if (rd == REG_PC || rn == REG_PC || rm == REG_PC)
5640 {
5641 inst.error = BAD_PC;
5642 return;
5643 }
5644
5645 /* Check for optional shift immediate constant. */
5646 if (skip_past_comma (&str) == FAIL)
5647 {
5648 if (shift == SHIFT_ASR_IMMEDIATE)
5649 {
5650 /* If the shift specifier is ommited, turn the instruction
5651 into pkhbt rd, rm, rn. First, switch the instruction
5652 code, and clear the rn and rm fields. */
5653 inst.instruction &= 0xfff0f010;
5654 /* Now, re-encode the registers. */
5655 inst.instruction |= (rm << 16) | rn;
5656 }
5657 return;
5658 }
5659
5660 decode_shift (&str, shift);
5661 }
5662
5663 /* ARM V6 Load Register Exclusive instruction (argument parse).
5664 LDREX{<cond>} <Rd, [<Rn>]
5665 Condition defaults to COND_ALWAYS.
5666 Error if Rd or Rn are R15.
5667 See ARMARMv6 A4.1.27: LDREX. */
5668
5669
5670 static void
5671 do_ldrex (str)
5672 char * str;
5673 {
5674 int rd, rn;
5675
5676 skip_whitespace (str);
5677
5678 /* Parse Rd. */
5679 if (((rd = reg_required_here (&str, 12)) == FAIL)
5680 || (skip_past_comma (&str) == FAIL))
5681 {
5682 inst.error = BAD_ARGS;
5683 return;
5684 }
5685 else if (rd == REG_PC)
5686 {
5687 inst.error = BAD_PC;
5688 return;
5689 }
5690 skip_whitespace (str);
5691
5692 /* Skip past '['. */
5693 if ((strlen (str) >= 1)
5694 &&strncmp (str, "[", 1) == 0)
5695 str+=1;
5696 skip_whitespace (str);
5697
5698 /* Parse Rn. */
5699 if ((rn = reg_required_here (&str, 16)) == FAIL)
5700 {
5701 inst.error = BAD_ARGS;
5702 return;
5703 }
5704 else if (rn == REG_PC)
5705 {
5706 inst.error = BAD_PC;
5707 return;
5708 }
5709 skip_whitespace (str);
5710
5711 /* Skip past ']'. */
5712 if ((strlen (str) >= 1)
5713 && strncmp (str, "]", 1) == 0)
5714 str+=1;
5715
5716 end_of_line (str);
5717 }
5718
5719 /* ARM V6 change processor state instruction (argument parse)
5720 CPS, CPSIE, CSPID . */
5721
5722 static void
5723 do_cps (str)
5724 char * str;
5725 {
5726 do_cps_mode (&str);
5727 end_of_line (str);
5728 }
5729
5730 static void
5731 do_cpsi (str)
5732 char * str;
5733 {
5734 do_cps_flags (&str, /*thumb_p=*/0);
5735
5736 if (skip_past_comma (&str) == SUCCESS)
5737 {
5738 skip_whitespace (str);
5739 do_cps_mode (&str);
5740 }
5741 end_of_line (str);
5742 }
5743
5744 static void
5745 do_cps_mode (str)
5746 char **str;
5747 {
5748 expressionS expr;
5749
5750 skip_whitespace (*str);
5751
5752 if (! is_immediate_prefix (**str))
5753 {
5754 inst.error = _("immediate expression expected");
5755 return;
5756 }
5757
5758 (*str)++; /* Strip off the immediate signifier. */
5759 if (my_get_expression (&expr, str))
5760 {
5761 inst.error = _("bad expression");
5762 return;
5763 }
5764
5765 if (expr.X_op != O_constant)
5766 {
5767 inst.error = _("constant expression expected");
5768 return;
5769 }
5770
5771 /* The mode is a 5 bit field. Valid values are 0-31. */
5772 if (((unsigned) expr.X_add_number) > 31
5773 || (inst.reloc.exp.X_add_number) < 0)
5774 {
5775 inst.error = _("invalid constant");
5776 return;
5777 }
5778
5779 inst.instruction |= expr.X_add_number;
5780 }
5781
5782 static void
5783 do_cps_flags (str, thumb_p)
5784 char **str;
5785 int thumb_p;
5786 {
5787 struct cps_flag {
5788 char character;
5789 unsigned long arm_value;
5790 unsigned long thumb_value;
5791 };
5792 static struct cps_flag flag_table[] = {
5793 {'a', 0x100, 0x4 },
5794 {'i', 0x080, 0x2 },
5795 {'f', 0x040, 0x1 }
5796 };
5797
5798 int saw_a_flag = 0;
5799
5800 skip_whitespace (*str);
5801
5802 /* Get the a, f and i flags. */
5803 while (**str && **str != ',')
5804 {
5805 struct cps_flag *p;
5806 struct cps_flag *q = flag_table + sizeof (flag_table)/sizeof (*p);
5807 for (p = flag_table; p < q; ++p)
5808 if (strncasecmp (*str, &p->character, 1) == 0)
5809 {
5810 inst.instruction |= (thumb_p ? p->thumb_value : p->arm_value);
5811 saw_a_flag = 1;
5812 break;
5813 }
5814 if (p == q)
5815 {
5816 inst.error = _("unrecognized flag");
5817 return;
5818 }
5819 (*str)++;
5820 }
5821 if (!saw_a_flag)
5822 inst.error = _("no 'a', 'i', or 'f' flags for 'cps'");
5823 }
5824
5825 /* THUMB V5 breakpoint instruction (argument parse)
5826 BKPT <immed_8>. */
5827
5828 static void
5829 do_t_bkpt (str)
5830 char * str;
5831 {
5832 expressionS expr;
5833 unsigned long number;
5834
5835 skip_whitespace (str);
5836
5837 /* Allow optional leading '#'. */
5838 if (is_immediate_prefix (*str))
5839 str ++;
5840
5841 memset (& expr, '\0', sizeof (expr));
5842 if (my_get_expression (& expr, & str)
5843 || (expr.X_op != O_constant
5844 /* As a convenience we allow 'bkpt' without an operand. */
5845 && expr.X_op != O_absent))
5846 {
5847 inst.error = _("bad expression");
5848 return;
5849 }
5850
5851 number = expr.X_add_number;
5852
5853 /* Check it fits an 8 bit unsigned. */
5854 if (number != (number & 0xff))
5855 {
5856 inst.error = _("immediate value out of range");
5857 return;
5858 }
5859
5860 inst.instruction |= number;
5861
5862 end_of_line (str);
5863 }
5864
5865 /* ARM V5 branch-link-exchange (argument parse) for BLX(1) only.
5866 Expects inst.instruction is set for BLX(1).
5867 Note: this is cloned from do_branch, and the reloc changed to be a
5868 new one that can cope with setting one extra bit (the H bit). */
5869
5870 static void
5871 do_branch25 (str)
5872 char * str;
5873 {
5874 if (my_get_expression (& inst.reloc.exp, & str))
5875 return;
5876
5877 #ifdef OBJ_ELF
5878 {
5879 char * save_in;
5880
5881 /* ScottB: February 5, 1998 */
5882 /* Check to see of PLT32 reloc required for the instruction. */
5883
5884 /* arm_parse_reloc() works on input_line_pointer.
5885 We actually want to parse the operands to the branch instruction
5886 passed in 'str'. Save the input pointer and restore it later. */
5887 save_in = input_line_pointer;
5888 input_line_pointer = str;
5889
5890 if (inst.reloc.exp.X_op == O_symbol
5891 && *str == '('
5892 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
5893 {
5894 inst.reloc.type = BFD_RELOC_ARM_PLT32;
5895 inst.reloc.pc_rel = 0;
5896 /* Modify str to point to after parsed operands, otherwise
5897 end_of_line() will complain about the (PLT) left in str. */
5898 str = input_line_pointer;
5899 }
5900 else
5901 {
5902 inst.reloc.type = BFD_RELOC_ARM_PCREL_BLX;
5903 inst.reloc.pc_rel = 1;
5904 }
5905
5906 input_line_pointer = save_in;
5907 }
5908 #else
5909 inst.reloc.type = BFD_RELOC_ARM_PCREL_BLX;
5910 inst.reloc.pc_rel = 1;
5911 #endif /* OBJ_ELF */
5912
5913 end_of_line (str);
5914 }
5915
5916 /* ARM V5 branch-link-exchange instruction (argument parse)
5917 BLX <target_addr> ie BLX(1)
5918 BLX{<condition>} <Rm> ie BLX(2)
5919 Unfortunately, there are two different opcodes for this mnemonic.
5920 So, the insns[].value is not used, and the code here zaps values
5921 into inst.instruction.
5922 Also, the <target_addr> can be 25 bits, hence has its own reloc. */
5923
5924 static void
5925 do_blx (str)
5926 char * str;
5927 {
5928 char * mystr = str;
5929 int rm;
5930
5931 skip_whitespace (mystr);
5932 rm = reg_required_here (& mystr, 0);
5933
5934 /* The above may set inst.error. Ignore his opinion. */
5935 inst.error = 0;
5936
5937 if (rm != FAIL)
5938 {
5939 /* Arg is a register.
5940 Use the condition code our caller put in inst.instruction.
5941 Pass ourselves off as a BX with a funny opcode. */
5942 inst.instruction |= 0x012fff30;
5943 do_bx (str);
5944 }
5945 else
5946 {
5947 /* This must be is BLX <target address>, no condition allowed. */
5948 if (inst.instruction != COND_ALWAYS)
5949 {
5950 inst.error = BAD_COND;
5951 return;
5952 }
5953
5954 inst.instruction = 0xfafffffe;
5955
5956 /* Process like a B/BL, but with a different reloc.
5957 Note that B/BL expecte fffffe, not 0, offset in the opcode table. */
5958 do_branch25 (str);
5959 }
5960 }
5961
5962 /* ARM V5 Thumb BLX (argument parse)
5963 BLX <target_addr> which is BLX(1)
5964 BLX <Rm> which is BLX(2)
5965 Unfortunately, there are two different opcodes for this mnemonic.
5966 So, the tinsns[].value is not used, and the code here zaps values
5967 into inst.instruction. */
5968
5969 static void
5970 do_t_blx (str)
5971 char * str;
5972 {
5973 char * mystr = str;
5974 int rm;
5975
5976 skip_whitespace (mystr);
5977 inst.instruction = 0x4780;
5978
5979 /* Note that this call is to the ARM register recognizer. BLX(2)
5980 uses the ARM register space, not the Thumb one, so a call to
5981 thumb_reg() would be wrong. */
5982 rm = reg_required_here (& mystr, 3);
5983 inst.error = 0;
5984
5985 if (rm != FAIL)
5986 {
5987 /* It's BLX(2). The .instruction was zapped with rm & is final. */
5988 inst.size = 2;
5989 }
5990 else
5991 {
5992 /* No ARM register. This must be BLX(1). Change the .instruction. */
5993 inst.instruction = 0xf7ffeffe;
5994 inst.size = 4;
5995
5996 if (my_get_expression (& inst.reloc.exp, & mystr))
5997 return;
5998
5999 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BLX;
6000 inst.reloc.pc_rel = 1;
6001 }
6002
6003 end_of_line (mystr);
6004 }
6005
6006 /* ARM V5 breakpoint instruction (argument parse)
6007 BKPT <16 bit unsigned immediate>
6008 Instruction is not conditional.
6009 The bit pattern given in insns[] has the COND_ALWAYS condition,
6010 and it is an error if the caller tried to override that. */
6011
6012 static void
6013 do_bkpt (str)
6014 char * str;
6015 {
6016 expressionS expr;
6017 unsigned long number;
6018
6019 skip_whitespace (str);
6020
6021 /* Allow optional leading '#'. */
6022 if (is_immediate_prefix (* str))
6023 str++;
6024
6025 memset (& expr, '\0', sizeof (expr));
6026
6027 if (my_get_expression (& expr, & str)
6028 || (expr.X_op != O_constant
6029 /* As a convenience we allow 'bkpt' without an operand. */
6030 && expr.X_op != O_absent))
6031 {
6032 inst.error = _("bad expression");
6033 return;
6034 }
6035
6036 number = expr.X_add_number;
6037
6038 /* Check it fits a 16 bit unsigned. */
6039 if (number != (number & 0xffff))
6040 {
6041 inst.error = _("immediate value out of range");
6042 return;
6043 }
6044
6045 /* Top 12 of 16 bits to bits 19:8. */
6046 inst.instruction |= (number & 0xfff0) << 4;
6047
6048 /* Bottom 4 of 16 bits to bits 3:0. */
6049 inst.instruction |= number & 0xf;
6050
6051 end_of_line (str);
6052 }
6053
6054 /* THUMB CPS instruction (argument parse). */
6055
6056 static void
6057 do_t_cps (str)
6058 char *str;
6059 {
6060 do_cps_flags (&str, /*thumb_p=*/1);
6061 end_of_line (str);
6062 }
6063
6064 /* THUMB CPY instruction (argument parse). */
6065
6066 static void
6067 do_t_cpy (str)
6068 char *str;
6069 {
6070 thumb_mov_compare (str, THUMB_CPY);
6071 }
6072
6073 /* THUMB SETEND instruction (argument parse). */
6074
6075 static void
6076 do_t_setend (str)
6077 char *str;
6078 {
6079 if (do_endian_specifier (str))
6080 inst.instruction |= 0x8;
6081 }
6082
6083 static unsigned long check_iwmmxt_insn PARAMS ((char *, enum iwmmxt_insn_type, int));
6084
6085 /* Parse INSN_TYPE insn STR having a possible IMMEDIATE_SIZE immediate. */
6086
6087 static unsigned long
6088 check_iwmmxt_insn (str, insn_type, immediate_size)
6089 char * str;
6090 enum iwmmxt_insn_type insn_type;
6091 int immediate_size;
6092 {
6093 int reg = 0;
6094 const char * inst_error;
6095 expressionS expr;
6096 unsigned long number;
6097
6098 inst_error = inst.error;
6099 if (!inst.error)
6100 inst.error = BAD_ARGS;
6101 skip_whitespace (str);
6102
6103 switch (insn_type)
6104 {
6105 case check_rd:
6106 if ((reg = reg_required_here (&str, 12)) == FAIL)
6107 return FAIL;
6108 break;
6109
6110 case check_wr:
6111 if ((wreg_required_here (&str, 0, IWMMXT_REG_WR)) == FAIL)
6112 return FAIL;
6113 break;
6114
6115 case check_wrwr:
6116 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
6117 || skip_past_comma (&str) == FAIL
6118 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL))
6119 return FAIL;
6120 break;
6121
6122 case check_wrwrwr:
6123 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
6124 || skip_past_comma (&str) == FAIL
6125 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6126 || skip_past_comma (&str) == FAIL
6127 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL))
6128 return FAIL;
6129 break;
6130
6131 case check_wrwrwcg:
6132 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
6133 || skip_past_comma (&str) == FAIL
6134 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6135 || skip_past_comma (&str) == FAIL
6136 || wreg_required_here (&str, 0, IWMMXT_REG_WCG) == FAIL))
6137 return FAIL;
6138 break;
6139
6140 case check_tbcst:
6141 if ((wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6142 || skip_past_comma (&str) == FAIL
6143 || reg_required_here (&str, 12) == FAIL))
6144 return FAIL;
6145 break;
6146
6147 case check_tmovmsk:
6148 if ((reg_required_here (&str, 12) == FAIL
6149 || skip_past_comma (&str) == FAIL
6150 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL))
6151 return FAIL;
6152 break;
6153
6154 case check_tmia:
6155 if ((wreg_required_here (&str, 5, IWMMXT_REG_WR) == FAIL
6156 || skip_past_comma (&str) == FAIL
6157 || reg_required_here (&str, 0) == FAIL
6158 || skip_past_comma (&str) == FAIL
6159 || reg_required_here (&str, 12) == FAIL))
6160 return FAIL;
6161 break;
6162
6163 case check_tmcrr:
6164 if ((wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL
6165 || skip_past_comma (&str) == FAIL
6166 || reg_required_here (&str, 12) == FAIL
6167 || skip_past_comma (&str) == FAIL
6168 || reg_required_here (&str, 16) == FAIL))
6169 return FAIL;
6170 break;
6171
6172 case check_tmrrc:
6173 if ((reg_required_here (&str, 12) == FAIL
6174 || skip_past_comma (&str) == FAIL
6175 || reg_required_here (&str, 16) == FAIL
6176 || skip_past_comma (&str) == FAIL
6177 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL))
6178 return FAIL;
6179 break;
6180
6181 case check_tmcr:
6182 if ((wreg_required_here (&str, 16, IWMMXT_REG_WC) == FAIL
6183 || skip_past_comma (&str) == FAIL
6184 || reg_required_here (&str, 12) == FAIL))
6185 return FAIL;
6186 break;
6187
6188 case check_tmrc:
6189 if ((reg_required_here (&str, 12) == FAIL
6190 || skip_past_comma (&str) == FAIL
6191 || wreg_required_here (&str, 16, IWMMXT_REG_WC) == FAIL))
6192 return FAIL;
6193 break;
6194
6195 case check_tinsr:
6196 if ((wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6197 || skip_past_comma (&str) == FAIL
6198 || reg_required_here (&str, 12) == FAIL
6199 || skip_past_comma (&str) == FAIL))
6200 return FAIL;
6201 break;
6202
6203 case check_textrc:
6204 if ((reg_required_here (&str, 12) == FAIL
6205 || skip_past_comma (&str) == FAIL))
6206 return FAIL;
6207 break;
6208
6209 case check_waligni:
6210 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
6211 || skip_past_comma (&str) == FAIL
6212 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6213 || skip_past_comma (&str) == FAIL
6214 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL
6215 || skip_past_comma (&str) == FAIL))
6216 return FAIL;
6217 break;
6218
6219 case check_textrm:
6220 if ((reg_required_here (&str, 12) == FAIL
6221 || skip_past_comma (&str) == FAIL
6222 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6223 || skip_past_comma (&str) == FAIL))
6224 return FAIL;
6225 break;
6226
6227 case check_wshufh:
6228 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
6229 || skip_past_comma (&str) == FAIL
6230 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6231 || skip_past_comma (&str) == FAIL))
6232 return FAIL;
6233 break;
6234 }
6235
6236 if (immediate_size == 0)
6237 {
6238 end_of_line (str);
6239 inst.error = inst_error;
6240 return reg;
6241 }
6242 else
6243 {
6244 skip_whitespace (str);
6245
6246 /* Allow optional leading '#'. */
6247 if (is_immediate_prefix (* str))
6248 str++;
6249
6250 memset (& expr, '\0', sizeof (expr));
6251
6252 if (my_get_expression (& expr, & str) || (expr.X_op != O_constant))
6253 {
6254 inst.error = _("bad or missing expression");
6255 return FAIL;
6256 }
6257
6258 number = expr.X_add_number;
6259
6260 if (number != (number & immediate_size))
6261 {
6262 inst.error = _("immediate value out of range");
6263 return FAIL;
6264 }
6265 end_of_line (str);
6266 inst.error = inst_error;
6267 return number;
6268 }
6269 }
6270
6271 static void
6272 do_iwmmxt_byte_addr (str)
6273 char * str;
6274 {
6275 int op = (inst.instruction & 0x300) >> 8;
6276 int reg;
6277
6278 inst.instruction &= ~0x300;
6279 inst.instruction |= (op & 1) << 22 | (op & 2) << 7;
6280
6281 skip_whitespace (str);
6282
6283 if ((reg = wreg_required_here (&str, 12, IWMMXT_REG_WR_OR_WC)) == FAIL
6284 || skip_past_comma (& str) == FAIL
6285 || cp_byte_address_required_here (&str) == FAIL)
6286 {
6287 if (! inst.error)
6288 inst.error = BAD_ARGS;
6289 }
6290 else
6291 end_of_line (str);
6292
6293 if (wc_register (reg))
6294 {
6295 as_bad (_("non-word size not supported with control register"));
6296 inst.instruction |= 0xf0000100;
6297 inst.instruction &= ~0x00400000;
6298 }
6299 }
6300
6301 static void
6302 do_iwmmxt_tandc (str)
6303 char * str;
6304 {
6305 int reg;
6306
6307 reg = check_iwmmxt_insn (str, check_rd, 0);
6308
6309 if (reg != REG_PC && !inst.error)
6310 inst.error = _("only r15 allowed here");
6311 }
6312
6313 static void
6314 do_iwmmxt_tbcst (str)
6315 char * str;
6316 {
6317 check_iwmmxt_insn (str, check_tbcst, 0);
6318 }
6319
6320 static void
6321 do_iwmmxt_textrc (str)
6322 char * str;
6323 {
6324 unsigned long number;
6325
6326 if ((number = check_iwmmxt_insn (str, check_textrc, 7)) == (unsigned long) FAIL)
6327 return;
6328
6329 inst.instruction |= number & 0x7;
6330 }
6331
6332 static void
6333 do_iwmmxt_textrm (str)
6334 char * str;
6335 {
6336 unsigned long number;
6337
6338 if ((number = check_iwmmxt_insn (str, check_textrm, 7)) == (unsigned long) FAIL)
6339 return;
6340
6341 inst.instruction |= number & 0x7;
6342 }
6343
6344 static void
6345 do_iwmmxt_tinsr (str)
6346 char * str;
6347 {
6348 unsigned long number;
6349
6350 if ((number = check_iwmmxt_insn (str, check_tinsr, 7)) == (unsigned long) FAIL)
6351 return;
6352
6353 inst.instruction |= number & 0x7;
6354 }
6355
6356 static void
6357 do_iwmmxt_tmcr (str)
6358 char * str;
6359 {
6360 check_iwmmxt_insn (str, check_tmcr, 0);
6361 }
6362
6363 static void
6364 do_iwmmxt_tmcrr (str)
6365 char * str;
6366 {
6367 check_iwmmxt_insn (str, check_tmcrr, 0);
6368 }
6369
6370 static void
6371 do_iwmmxt_tmia (str)
6372 char * str;
6373 {
6374 check_iwmmxt_insn (str, check_tmia, 0);
6375 }
6376
6377 static void
6378 do_iwmmxt_tmovmsk (str)
6379 char * str;
6380 {
6381 check_iwmmxt_insn (str, check_tmovmsk, 0);
6382 }
6383
6384 static void
6385 do_iwmmxt_tmrc (str)
6386 char * str;
6387 {
6388 check_iwmmxt_insn (str, check_tmrc, 0);
6389 }
6390
6391 static void
6392 do_iwmmxt_tmrrc (str)
6393 char * str;
6394 {
6395 check_iwmmxt_insn (str, check_tmrrc, 0);
6396 }
6397
6398 static void
6399 do_iwmmxt_torc (str)
6400 char * str;
6401 {
6402 check_iwmmxt_insn (str, check_rd, 0);
6403 }
6404
6405 static void
6406 do_iwmmxt_waligni (str)
6407 char * str;
6408 {
6409 unsigned long number;
6410
6411 if ((number = check_iwmmxt_insn (str, check_waligni, 7)) == (unsigned long) FAIL)
6412 return;
6413
6414 inst.instruction |= ((number & 0x7) << 20);
6415 }
6416
6417 static void
6418 do_iwmmxt_wmov (str)
6419 char * str;
6420 {
6421 if (check_iwmmxt_insn (str, check_wrwr, 0) == (unsigned long) FAIL)
6422 return;
6423
6424 inst.instruction |= ((inst.instruction >> 16) & 0xf);
6425 }
6426
6427 static void
6428 do_iwmmxt_word_addr (str)
6429 char * str;
6430 {
6431 int op = (inst.instruction & 0x300) >> 8;
6432 int reg;
6433
6434 inst.instruction &= ~0x300;
6435 inst.instruction |= (op & 1) << 22 | (op & 2) << 7;
6436
6437 skip_whitespace (str);
6438
6439 if ((reg = wreg_required_here (&str, 12, IWMMXT_REG_WR_OR_WC)) == FAIL
6440 || skip_past_comma (& str) == FAIL
6441 || cp_address_required_here (& str, CP_WB_OK) == FAIL)
6442 {
6443 if (! inst.error)
6444 inst.error = BAD_ARGS;
6445 }
6446 else
6447 end_of_line (str);
6448
6449 if (wc_register (reg))
6450 {
6451 if ((inst.instruction & COND_MASK) != COND_ALWAYS)
6452 as_bad (_("conditional execution not supported with control register"));
6453 if (op != 2)
6454 as_bad (_("non-word size not supported with control register"));
6455 inst.instruction |= 0xf0000100;
6456 inst.instruction &= ~0x00400000;
6457 }
6458 }
6459
6460 static void
6461 do_iwmmxt_wrwr (str)
6462 char * str;
6463 {
6464 check_iwmmxt_insn (str, check_wrwr, 0);
6465 }
6466
6467 static void
6468 do_iwmmxt_wrwrwcg (str)
6469 char * str;
6470 {
6471 check_iwmmxt_insn (str, check_wrwrwcg, 0);
6472 }
6473
6474 static void
6475 do_iwmmxt_wrwrwr (str)
6476 char * str;
6477 {
6478 check_iwmmxt_insn (str, check_wrwrwr, 0);
6479 }
6480
6481 static void
6482 do_iwmmxt_wshufh (str)
6483 char * str;
6484 {
6485 unsigned long number;
6486
6487 if ((number = check_iwmmxt_insn (str, check_wshufh, 0xff)) == (unsigned long) FAIL)
6488 return;
6489
6490 inst.instruction |= ((number & 0xf0) << 16) | (number & 0xf);
6491 }
6492
6493 static void
6494 do_iwmmxt_wzero (str)
6495 char * str;
6496 {
6497 if (check_iwmmxt_insn (str, check_wr, 0) == (unsigned long) FAIL)
6498 return;
6499
6500 inst.instruction |= ((inst.instruction & 0xf) << 12) | ((inst.instruction & 0xf) << 16);
6501 }
6502
6503 /* Xscale multiply-accumulate (argument parse)
6504 MIAcc acc0,Rm,Rs
6505 MIAPHcc acc0,Rm,Rs
6506 MIAxycc acc0,Rm,Rs. */
6507
6508 static void
6509 do_xsc_mia (str)
6510 char * str;
6511 {
6512 int rs;
6513 int rm;
6514
6515 if (accum0_required_here (& str) == FAIL)
6516 inst.error = ERR_NO_ACCUM;
6517
6518 else if (skip_past_comma (& str) == FAIL
6519 || (rm = reg_required_here (& str, 0)) == FAIL)
6520 inst.error = BAD_ARGS;
6521
6522 else if (skip_past_comma (& str) == FAIL
6523 || (rs = reg_required_here (& str, 12)) == FAIL)
6524 inst.error = BAD_ARGS;
6525
6526 /* inst.instruction has now been zapped with both rm and rs. */
6527 else if (rm == REG_PC || rs == REG_PC)
6528 inst.error = BAD_PC; /* Undefined result if rm or rs is R15. */
6529
6530 else
6531 end_of_line (str);
6532 }
6533
6534 /* Xscale move-accumulator-register (argument parse)
6535
6536 MARcc acc0,RdLo,RdHi. */
6537
6538 static void
6539 do_xsc_mar (str)
6540 char * str;
6541 {
6542 int rdlo, rdhi;
6543
6544 if (accum0_required_here (& str) == FAIL)
6545 inst.error = ERR_NO_ACCUM;
6546
6547 else if (skip_past_comma (& str) == FAIL
6548 || (rdlo = reg_required_here (& str, 12)) == FAIL)
6549 inst.error = BAD_ARGS;
6550
6551 else if (skip_past_comma (& str) == FAIL
6552 || (rdhi = reg_required_here (& str, 16)) == FAIL)
6553 inst.error = BAD_ARGS;
6554
6555 /* inst.instruction has now been zapped with both rdlo and rdhi. */
6556 else if (rdlo == REG_PC || rdhi == REG_PC)
6557 inst.error = BAD_PC; /* Undefined result if rdlo or rdhi is R15. */
6558
6559 else
6560 end_of_line (str);
6561 }
6562
6563 /* Xscale move-register-accumulator (argument parse)
6564
6565 MRAcc RdLo,RdHi,acc0. */
6566
6567 static void
6568 do_xsc_mra (str)
6569 char * str;
6570 {
6571 int rdlo;
6572 int rdhi;
6573
6574 skip_whitespace (str);
6575
6576 if ((rdlo = reg_required_here (& str, 12)) == FAIL)
6577 inst.error = BAD_ARGS;
6578
6579 else if (skip_past_comma (& str) == FAIL
6580 || (rdhi = reg_required_here (& str, 16)) == FAIL)
6581 inst.error = BAD_ARGS;
6582
6583 else if (skip_past_comma (& str) == FAIL
6584 || accum0_required_here (& str) == FAIL)
6585 inst.error = ERR_NO_ACCUM;
6586
6587 /* inst.instruction has now been zapped with both rdlo and rdhi. */
6588 else if (rdlo == rdhi)
6589 inst.error = BAD_ARGS; /* Undefined result if 2 writes to same reg. */
6590
6591 else if (rdlo == REG_PC || rdhi == REG_PC)
6592 inst.error = BAD_PC; /* Undefined result if rdlo or rdhi is R15. */
6593 else
6594 end_of_line (str);
6595 }
6596
6597 /* ARMv5TE: Preload-Cache
6598
6599 PLD <addr_mode>
6600
6601 Syntactically, like LDR with B=1, W=0, L=1. */
6602
6603 static void
6604 do_pld (str)
6605 char * str;
6606 {
6607 int rd;
6608
6609 skip_whitespace (str);
6610
6611 if (* str != '[')
6612 {
6613 inst.error = _("'[' expected after PLD mnemonic");
6614 return;
6615 }
6616
6617 ++str;
6618 skip_whitespace (str);
6619
6620 if ((rd = reg_required_here (& str, 16)) == FAIL)
6621 return;
6622
6623 skip_whitespace (str);
6624
6625 if (*str == ']')
6626 {
6627 /* [Rn], ... ? */
6628 ++str;
6629 skip_whitespace (str);
6630
6631 /* Post-indexed addressing is not allowed with PLD. */
6632 if (skip_past_comma (&str) == SUCCESS)
6633 {
6634 inst.error
6635 = _("post-indexed expression used in preload instruction");
6636 return;
6637 }
6638 else if (*str == '!') /* [Rn]! */
6639 {
6640 inst.error = _("writeback used in preload instruction");
6641 ++str;
6642 }
6643 else /* [Rn] */
6644 inst.instruction |= INDEX_UP | PRE_INDEX;
6645 }
6646 else /* [Rn, ...] */
6647 {
6648 if (skip_past_comma (& str) == FAIL)
6649 {
6650 inst.error = _("pre-indexed expression expected");
6651 return;
6652 }
6653
6654 if (ldst_extend (&str) == FAIL)
6655 return;
6656
6657 skip_whitespace (str);
6658
6659 if (* str != ']')
6660 {
6661 inst.error = _("missing ]");
6662 return;
6663 }
6664
6665 ++ str;
6666 skip_whitespace (str);
6667
6668 if (* str == '!') /* [Rn]! */
6669 {
6670 inst.error = _("writeback used in preload instruction");
6671 ++ str;
6672 }
6673
6674 inst.instruction |= PRE_INDEX;
6675 }
6676
6677 end_of_line (str);
6678 }
6679
6680 /* ARMv5TE load-consecutive (argument parse)
6681 Mode is like LDRH.
6682
6683 LDRccD R, mode
6684 STRccD R, mode. */
6685
6686 static void
6687 do_ldrd (str)
6688 char * str;
6689 {
6690 int rd;
6691 int rn;
6692
6693 skip_whitespace (str);
6694
6695 if ((rd = reg_required_here (& str, 12)) == FAIL)
6696 {
6697 inst.error = BAD_ARGS;
6698 return;
6699 }
6700
6701 if (skip_past_comma (& str) == FAIL
6702 || (rn = ld_mode_required_here (& str)) == FAIL)
6703 {
6704 if (!inst.error)
6705 inst.error = BAD_ARGS;
6706 return;
6707 }
6708
6709 /* inst.instruction has now been zapped with Rd and the addressing mode. */
6710 if (rd & 1) /* Unpredictable result if Rd is odd. */
6711 {
6712 inst.error = _("destination register must be even");
6713 return;
6714 }
6715
6716 if (rd == REG_LR)
6717 {
6718 inst.error = _("r14 not allowed here");
6719 return;
6720 }
6721
6722 if (((rd == rn) || (rd + 1 == rn))
6723 && ((inst.instruction & WRITE_BACK)
6724 || (!(inst.instruction & PRE_INDEX))))
6725 as_warn (_("pre/post-indexing used when modified address register is destination"));
6726
6727 /* For an index-register load, the index register must not overlap the
6728 destination (even if not write-back). */
6729 if ((inst.instruction & V4_STR_BIT) == 0
6730 && (inst.instruction & HWOFFSET_IMM) == 0)
6731 {
6732 int rm = inst.instruction & 0x0000000f;
6733
6734 if (rm == rd || (rm == rd + 1))
6735 as_warn (_("ldrd destination registers must not overlap index register"));
6736 }
6737
6738 end_of_line (str);
6739 }
6740
6741 /* Returns the index into fp_values of a floating point number,
6742 or -1 if not in the table. */
6743
6744 static int
6745 my_get_float_expression (str)
6746 char ** str;
6747 {
6748 LITTLENUM_TYPE words[MAX_LITTLENUMS];
6749 char * save_in;
6750 expressionS exp;
6751 int i;
6752 int j;
6753
6754 memset (words, 0, MAX_LITTLENUMS * sizeof (LITTLENUM_TYPE));
6755
6756 /* Look for a raw floating point number. */
6757 if ((save_in = atof_ieee (*str, 'x', words)) != NULL
6758 && is_end_of_line[(unsigned char) *save_in])
6759 {
6760 for (i = 0; i < NUM_FLOAT_VALS; i++)
6761 {
6762 for (j = 0; j < MAX_LITTLENUMS; j++)
6763 {
6764 if (words[j] != fp_values[i][j])
6765 break;
6766 }
6767
6768 if (j == MAX_LITTLENUMS)
6769 {
6770 *str = save_in;
6771 return i;
6772 }
6773 }
6774 }
6775
6776 /* Try and parse a more complex expression, this will probably fail
6777 unless the code uses a floating point prefix (eg "0f"). */
6778 save_in = input_line_pointer;
6779 input_line_pointer = *str;
6780 if (expression (&exp) == absolute_section
6781 && exp.X_op == O_big
6782 && exp.X_add_number < 0)
6783 {
6784 /* FIXME: 5 = X_PRECISION, should be #define'd where we can use it.
6785 Ditto for 15. */
6786 if (gen_to_words (words, 5, (long) 15) == 0)
6787 {
6788 for (i = 0; i < NUM_FLOAT_VALS; i++)
6789 {
6790 for (j = 0; j < MAX_LITTLENUMS; j++)
6791 {
6792 if (words[j] != fp_values[i][j])
6793 break;
6794 }
6795
6796 if (j == MAX_LITTLENUMS)
6797 {
6798 *str = input_line_pointer;
6799 input_line_pointer = save_in;
6800 return i;
6801 }
6802 }
6803 }
6804 }
6805
6806 *str = input_line_pointer;
6807 input_line_pointer = save_in;
6808 return -1;
6809 }
6810
6811 /* Return TRUE if anything in the expression is a bignum. */
6812
6813 static int
6814 walk_no_bignums (sp)
6815 symbolS * sp;
6816 {
6817 if (symbol_get_value_expression (sp)->X_op == O_big)
6818 return 1;
6819
6820 if (symbol_get_value_expression (sp)->X_add_symbol)
6821 {
6822 return (walk_no_bignums (symbol_get_value_expression (sp)->X_add_symbol)
6823 || (symbol_get_value_expression (sp)->X_op_symbol
6824 && walk_no_bignums (symbol_get_value_expression (sp)->X_op_symbol)));
6825 }
6826
6827 return 0;
6828 }
6829
6830 static int in_my_get_expression = 0;
6831
6832 static int
6833 my_get_expression (ep, str)
6834 expressionS * ep;
6835 char ** str;
6836 {
6837 char * save_in;
6838 segT seg;
6839
6840 save_in = input_line_pointer;
6841 input_line_pointer = *str;
6842 in_my_get_expression = 1;
6843 seg = expression (ep);
6844 in_my_get_expression = 0;
6845
6846 if (ep->X_op == O_illegal)
6847 {
6848 /* We found a bad expression in md_operand(). */
6849 *str = input_line_pointer;
6850 input_line_pointer = save_in;
6851 return 1;
6852 }
6853
6854 #ifdef OBJ_AOUT
6855 if (seg != absolute_section
6856 && seg != text_section
6857 && seg != data_section
6858 && seg != bss_section
6859 && seg != undefined_section)
6860 {
6861 inst.error = _("bad_segment");
6862 *str = input_line_pointer;
6863 input_line_pointer = save_in;
6864 return 1;
6865 }
6866 #endif
6867
6868 /* Get rid of any bignums now, so that we don't generate an error for which
6869 we can't establish a line number later on. Big numbers are never valid
6870 in instructions, which is where this routine is always called. */
6871 if (ep->X_op == O_big
6872 || (ep->X_add_symbol
6873 && (walk_no_bignums (ep->X_add_symbol)
6874 || (ep->X_op_symbol
6875 && walk_no_bignums (ep->X_op_symbol)))))
6876 {
6877 inst.error = _("invalid constant");
6878 *str = input_line_pointer;
6879 input_line_pointer = save_in;
6880 return 1;
6881 }
6882
6883 *str = input_line_pointer;
6884 input_line_pointer = save_in;
6885 return 0;
6886 }
6887
6888 /* We handle all bad expressions here, so that we can report the faulty
6889 instruction in the error message. */
6890 void
6891 md_operand (expr)
6892 expressionS *expr;
6893 {
6894 if (in_my_get_expression)
6895 {
6896 expr->X_op = O_illegal;
6897 if (inst.error == NULL)
6898 inst.error = _("bad expression");
6899 }
6900 }
6901
6902 /* KIND indicates what kind of shifts are accepted. */
6903
6904 static int
6905 decode_shift (str, kind)
6906 char ** str;
6907 int kind;
6908 {
6909 const struct asm_shift_name * shift;
6910 char * p;
6911 char c;
6912
6913 skip_whitespace (* str);
6914
6915 for (p = * str; ISALPHA (* p); p ++)
6916 ;
6917
6918 if (p == * str)
6919 {
6920 inst.error = _("shift expression expected");
6921 return FAIL;
6922 }
6923
6924 c = * p;
6925 * p = '\0';
6926 shift = (const struct asm_shift_name *) hash_find (arm_shift_hsh, * str);
6927 * p = c;
6928
6929 if (shift == NULL)
6930 {
6931 inst.error = _("shift expression expected");
6932 return FAIL;
6933 }
6934
6935 assert (shift->properties->index == shift_properties[shift->properties->index].index);
6936
6937 if (kind == SHIFT_LSL_OR_ASR_IMMEDIATE
6938 && shift->properties->index != SHIFT_LSL
6939 && shift->properties->index != SHIFT_ASR)
6940 {
6941 inst.error = _("'LSL' or 'ASR' required");
6942 return FAIL;
6943 }
6944 else if (kind == SHIFT_LSL_IMMEDIATE
6945 && shift->properties->index != SHIFT_LSL)
6946 {
6947 inst.error = _("'LSL' required");
6948 return FAIL;
6949 }
6950 else if (kind == SHIFT_ASR_IMMEDIATE
6951 && shift->properties->index != SHIFT_ASR)
6952 {
6953 inst.error = _("'ASR' required");
6954 return FAIL;
6955 }
6956
6957 if (shift->properties->index == SHIFT_RRX)
6958 {
6959 * str = p;
6960 inst.instruction |= shift->properties->bit_field;
6961 return SUCCESS;
6962 }
6963
6964 skip_whitespace (p);
6965
6966 if (kind == NO_SHIFT_RESTRICT && reg_required_here (& p, 8) != FAIL)
6967 {
6968 inst.instruction |= shift->properties->bit_field | SHIFT_BY_REG;
6969 * str = p;
6970 return SUCCESS;
6971 }
6972 else if (! is_immediate_prefix (* p))
6973 {
6974 inst.error = (NO_SHIFT_RESTRICT
6975 ? _("shift requires register or #expression")
6976 : _("shift requires #expression"));
6977 * str = p;
6978 return FAIL;
6979 }
6980
6981 inst.error = NULL;
6982 p ++;
6983
6984 if (my_get_expression (& inst.reloc.exp, & p))
6985 return FAIL;
6986
6987 /* Validate some simple #expressions. */
6988 if (inst.reloc.exp.X_op == O_constant)
6989 {
6990 unsigned num = inst.reloc.exp.X_add_number;
6991
6992 /* Reject operations greater than 32. */
6993 if (num > 32
6994 /* Reject a shift of 0 unless the mode allows it. */
6995 || (num == 0 && shift->properties->allows_0 == 0)
6996 /* Reject a shift of 32 unless the mode allows it. */
6997 || (num == 32 && shift->properties->allows_32 == 0)
6998 )
6999 {
7000 /* As a special case we allow a shift of zero for
7001 modes that do not support it to be recoded as an
7002 logical shift left of zero (ie nothing). We warn
7003 about this though. */
7004 if (num == 0)
7005 {
7006 as_warn (_("shift of 0 ignored."));
7007 shift = & shift_names[0];
7008 assert (shift->properties->index == SHIFT_LSL);
7009 }
7010 else
7011 {
7012 inst.error = _("invalid immediate shift");
7013 return FAIL;
7014 }
7015 }
7016
7017 /* Shifts of 32 are encoded as 0, for those shifts that
7018 support it. */
7019 if (num == 32)
7020 num = 0;
7021
7022 inst.instruction |= (num << 7) | shift->properties->bit_field;
7023 }
7024 else
7025 {
7026 inst.reloc.type = BFD_RELOC_ARM_SHIFT_IMM;
7027 inst.reloc.pc_rel = 0;
7028 inst.instruction |= shift->properties->bit_field;
7029 }
7030
7031 * str = p;
7032 return SUCCESS;
7033 }
7034
7035 /* Do those data_ops which can take a negative immediate constant
7036 by altering the instruction. A bit of a hack really.
7037 MOV <-> MVN
7038 AND <-> BIC
7039 ADC <-> SBC
7040 by inverting the second operand, and
7041 ADD <-> SUB
7042 CMP <-> CMN
7043 by negating the second operand. */
7044
7045 static int
7046 negate_data_op (instruction, value)
7047 unsigned long * instruction;
7048 unsigned long value;
7049 {
7050 int op, new_inst;
7051 unsigned long negated, inverted;
7052
7053 negated = validate_immediate (-value);
7054 inverted = validate_immediate (~value);
7055
7056 op = (*instruction >> DATA_OP_SHIFT) & 0xf;
7057 switch (op)
7058 {
7059 /* First negates. */
7060 case OPCODE_SUB: /* ADD <-> SUB */
7061 new_inst = OPCODE_ADD;
7062 value = negated;
7063 break;
7064
7065 case OPCODE_ADD:
7066 new_inst = OPCODE_SUB;
7067 value = negated;
7068 break;
7069
7070 case OPCODE_CMP: /* CMP <-> CMN */
7071 new_inst = OPCODE_CMN;
7072 value = negated;
7073 break;
7074
7075 case OPCODE_CMN:
7076 new_inst = OPCODE_CMP;
7077 value = negated;
7078 break;
7079
7080 /* Now Inverted ops. */
7081 case OPCODE_MOV: /* MOV <-> MVN */
7082 new_inst = OPCODE_MVN;
7083 value = inverted;
7084 break;
7085
7086 case OPCODE_MVN:
7087 new_inst = OPCODE_MOV;
7088 value = inverted;
7089 break;
7090
7091 case OPCODE_AND: /* AND <-> BIC */
7092 new_inst = OPCODE_BIC;
7093 value = inverted;
7094 break;
7095
7096 case OPCODE_BIC:
7097 new_inst = OPCODE_AND;
7098 value = inverted;
7099 break;
7100
7101 case OPCODE_ADC: /* ADC <-> SBC */
7102 new_inst = OPCODE_SBC;
7103 value = inverted;
7104 break;
7105
7106 case OPCODE_SBC:
7107 new_inst = OPCODE_ADC;
7108 value = inverted;
7109 break;
7110
7111 /* We cannot do anything. */
7112 default:
7113 return FAIL;
7114 }
7115
7116 if (value == (unsigned) FAIL)
7117 return FAIL;
7118
7119 *instruction &= OPCODE_MASK;
7120 *instruction |= new_inst << DATA_OP_SHIFT;
7121 return value;
7122 }
7123
7124 static int
7125 data_op2 (str)
7126 char ** str;
7127 {
7128 int value;
7129 expressionS expr;
7130
7131 skip_whitespace (* str);
7132
7133 if (reg_required_here (str, 0) != FAIL)
7134 {
7135 if (skip_past_comma (str) == SUCCESS)
7136 /* Shift operation on register. */
7137 return decode_shift (str, NO_SHIFT_RESTRICT);
7138
7139 return SUCCESS;
7140 }
7141 else
7142 {
7143 /* Immediate expression. */
7144 if (is_immediate_prefix (**str))
7145 {
7146 (*str)++;
7147 inst.error = NULL;
7148
7149 if (my_get_expression (&inst.reloc.exp, str))
7150 return FAIL;
7151
7152 if (inst.reloc.exp.X_add_symbol)
7153 {
7154 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
7155 inst.reloc.pc_rel = 0;
7156 }
7157 else
7158 {
7159 if (skip_past_comma (str) == SUCCESS)
7160 {
7161 /* #x, y -- ie explicit rotation by Y. */
7162 if (my_get_expression (&expr, str))
7163 return FAIL;
7164
7165 if (expr.X_op != O_constant)
7166 {
7167 inst.error = _("constant expression expected");
7168 return FAIL;
7169 }
7170
7171 /* Rotate must be a multiple of 2. */
7172 if (((unsigned) expr.X_add_number) > 30
7173 || (expr.X_add_number & 1) != 0
7174 || ((unsigned) inst.reloc.exp.X_add_number) > 255)
7175 {
7176 inst.error = _("invalid constant");
7177 return FAIL;
7178 }
7179 inst.instruction |= INST_IMMEDIATE;
7180 inst.instruction |= inst.reloc.exp.X_add_number;
7181 inst.instruction |= expr.X_add_number << 7;
7182 return SUCCESS;
7183 }
7184
7185 /* Implicit rotation, select a suitable one. */
7186 value = validate_immediate (inst.reloc.exp.X_add_number);
7187
7188 if (value == FAIL)
7189 {
7190 /* Can't be done. Perhaps the code reads something like
7191 "add Rd, Rn, #-n", where "sub Rd, Rn, #n" would be OK. */
7192 if ((value = negate_data_op (&inst.instruction,
7193 inst.reloc.exp.X_add_number))
7194 == FAIL)
7195 {
7196 inst.error = _("invalid constant");
7197 return FAIL;
7198 }
7199 }
7200
7201 inst.instruction |= value;
7202 }
7203
7204 inst.instruction |= INST_IMMEDIATE;
7205 return SUCCESS;
7206 }
7207
7208 (*str)++;
7209 inst.error = _("register or shift expression expected");
7210 return FAIL;
7211 }
7212 }
7213
7214 static int
7215 fp_op2 (str)
7216 char ** str;
7217 {
7218 skip_whitespace (* str);
7219
7220 if (fp_reg_required_here (str, 0) != FAIL)
7221 return SUCCESS;
7222 else
7223 {
7224 /* Immediate expression. */
7225 if (*((*str)++) == '#')
7226 {
7227 int i;
7228
7229 inst.error = NULL;
7230
7231 skip_whitespace (* str);
7232
7233 /* First try and match exact strings, this is to guarantee
7234 that some formats will work even for cross assembly. */
7235
7236 for (i = 0; fp_const[i]; i++)
7237 {
7238 if (strncmp (*str, fp_const[i], strlen (fp_const[i])) == 0)
7239 {
7240 char *start = *str;
7241
7242 *str += strlen (fp_const[i]);
7243 if (is_end_of_line[(unsigned char) **str])
7244 {
7245 inst.instruction |= i + 8;
7246 return SUCCESS;
7247 }
7248 *str = start;
7249 }
7250 }
7251
7252 /* Just because we didn't get a match doesn't mean that the
7253 constant isn't valid, just that it is in a format that we
7254 don't automatically recognize. Try parsing it with
7255 the standard expression routines. */
7256 if ((i = my_get_float_expression (str)) >= 0)
7257 {
7258 inst.instruction |= i + 8;
7259 return SUCCESS;
7260 }
7261
7262 inst.error = _("invalid floating point immediate expression");
7263 return FAIL;
7264 }
7265 inst.error =
7266 _("floating point register or immediate expression expected");
7267 return FAIL;
7268 }
7269 }
7270
7271 static void
7272 do_arit (str)
7273 char * str;
7274 {
7275 skip_whitespace (str);
7276
7277 if (reg_required_here (&str, 12) == FAIL
7278 || skip_past_comma (&str) == FAIL
7279 || reg_required_here (&str, 16) == FAIL
7280 || skip_past_comma (&str) == FAIL
7281 || data_op2 (&str) == FAIL)
7282 {
7283 if (!inst.error)
7284 inst.error = BAD_ARGS;
7285 return;
7286 }
7287
7288 end_of_line (str);
7289 }
7290
7291 static void
7292 do_adr (str)
7293 char * str;
7294 {
7295 /* This is a pseudo-op of the form "adr rd, label" to be converted
7296 into a relative address of the form "add rd, pc, #label-.-8". */
7297 skip_whitespace (str);
7298
7299 if (reg_required_here (&str, 12) == FAIL
7300 || skip_past_comma (&str) == FAIL
7301 || my_get_expression (&inst.reloc.exp, &str))
7302 {
7303 if (!inst.error)
7304 inst.error = BAD_ARGS;
7305 return;
7306 }
7307
7308 /* Frag hacking will turn this into a sub instruction if the offset turns
7309 out to be negative. */
7310 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
7311 #ifndef TE_WINCE
7312 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust. */
7313 #endif
7314 inst.reloc.pc_rel = 1;
7315
7316 end_of_line (str);
7317 }
7318
7319 static void
7320 do_adrl (str)
7321 char * str;
7322 {
7323 /* This is a pseudo-op of the form "adrl rd, label" to be converted
7324 into a relative address of the form:
7325 add rd, pc, #low(label-.-8)"
7326 add rd, rd, #high(label-.-8)" */
7327
7328 skip_whitespace (str);
7329
7330 if (reg_required_here (&str, 12) == FAIL
7331 || skip_past_comma (&str) == FAIL
7332 || my_get_expression (&inst.reloc.exp, &str))
7333 {
7334 if (!inst.error)
7335 inst.error = BAD_ARGS;
7336
7337 return;
7338 }
7339
7340 end_of_line (str);
7341 /* Frag hacking will turn this into a sub instruction if the offset turns
7342 out to be negative. */
7343 inst.reloc.type = BFD_RELOC_ARM_ADRL_IMMEDIATE;
7344 #ifndef TE_WINCE
7345 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust */
7346 #endif
7347 inst.reloc.pc_rel = 1;
7348 inst.size = INSN_SIZE * 2;
7349 }
7350
7351 static void
7352 do_cmp (str)
7353 char * str;
7354 {
7355 skip_whitespace (str);
7356
7357 if (reg_required_here (&str, 16) == FAIL)
7358 {
7359 if (!inst.error)
7360 inst.error = BAD_ARGS;
7361 return;
7362 }
7363
7364 if (skip_past_comma (&str) == FAIL
7365 || data_op2 (&str) == FAIL)
7366 {
7367 if (!inst.error)
7368 inst.error = BAD_ARGS;
7369 return;
7370 }
7371
7372 end_of_line (str);
7373 }
7374
7375 static void
7376 do_mov (str)
7377 char * str;
7378 {
7379 skip_whitespace (str);
7380
7381 if (reg_required_here (&str, 12) == FAIL)
7382 {
7383 if (!inst.error)
7384 inst.error = BAD_ARGS;
7385 return;
7386 }
7387
7388 if (skip_past_comma (&str) == FAIL
7389 || data_op2 (&str) == FAIL)
7390 {
7391 if (!inst.error)
7392 inst.error = BAD_ARGS;
7393 return;
7394 }
7395
7396 end_of_line (str);
7397 }
7398
7399 static int
7400 ldst_extend (str)
7401 char ** str;
7402 {
7403 int add = INDEX_UP;
7404
7405 switch (**str)
7406 {
7407 case '#':
7408 case '$':
7409 (*str)++;
7410 if (my_get_expression (& inst.reloc.exp, str))
7411 return FAIL;
7412
7413 if (inst.reloc.exp.X_op == O_constant)
7414 {
7415 int value = inst.reloc.exp.X_add_number;
7416
7417 if (value < -4095 || value > 4095)
7418 {
7419 inst.error = _("address offset too large");
7420 return FAIL;
7421 }
7422
7423 if (value < 0)
7424 {
7425 value = -value;
7426 add = 0;
7427 }
7428
7429 inst.instruction |= add | value;
7430 }
7431 else
7432 {
7433 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
7434 inst.reloc.pc_rel = 0;
7435 }
7436 return SUCCESS;
7437
7438 case '-':
7439 add = 0;
7440 /* Fall through. */
7441
7442 case '+':
7443 (*str)++;
7444 /* Fall through. */
7445
7446 default:
7447 if (reg_required_here (str, 0) == FAIL)
7448 return FAIL;
7449
7450 inst.instruction |= add | OFFSET_REG;
7451 if (skip_past_comma (str) == SUCCESS)
7452 return decode_shift (str, SHIFT_IMMEDIATE);
7453
7454 return SUCCESS;
7455 }
7456 }
7457
7458 static void
7459 do_ldst (str)
7460 char * str;
7461 {
7462 int pre_inc = 0;
7463 int conflict_reg;
7464 int value;
7465
7466 skip_whitespace (str);
7467
7468 if ((conflict_reg = reg_required_here (&str, 12)) == FAIL)
7469 {
7470 if (!inst.error)
7471 inst.error = BAD_ARGS;
7472 return;
7473 }
7474
7475 if (skip_past_comma (&str) == FAIL)
7476 {
7477 inst.error = _("address expected");
7478 return;
7479 }
7480
7481 if (*str == '[')
7482 {
7483 int reg;
7484
7485 str++;
7486
7487 skip_whitespace (str);
7488
7489 if ((reg = reg_required_here (&str, 16)) == FAIL)
7490 return;
7491
7492 /* Conflicts can occur on stores as well as loads. */
7493 conflict_reg = (conflict_reg == reg);
7494
7495 skip_whitespace (str);
7496
7497 if (*str == ']')
7498 {
7499 str ++;
7500
7501 if (skip_past_comma (&str) == SUCCESS)
7502 {
7503 /* [Rn],... (post inc) */
7504 if (ldst_extend (&str) == FAIL)
7505 return;
7506 if (conflict_reg)
7507 as_warn (_("%s register same as write-back base"),
7508 ((inst.instruction & LOAD_BIT)
7509 ? _("destination") : _("source")));
7510 }
7511 else
7512 {
7513 /* [Rn] */
7514 skip_whitespace (str);
7515
7516 if (*str == '!')
7517 {
7518 if (conflict_reg)
7519 as_warn (_("%s register same as write-back base"),
7520 ((inst.instruction & LOAD_BIT)
7521 ? _("destination") : _("source")));
7522 str++;
7523 inst.instruction |= WRITE_BACK;
7524 }
7525
7526 inst.instruction |= INDEX_UP;
7527 pre_inc = 1;
7528 }
7529 }
7530 else
7531 {
7532 /* [Rn,...] */
7533 if (skip_past_comma (&str) == FAIL)
7534 {
7535 inst.error = _("pre-indexed expression expected");
7536 return;
7537 }
7538
7539 pre_inc = 1;
7540 if (ldst_extend (&str) == FAIL)
7541 return;
7542
7543 skip_whitespace (str);
7544
7545 if (*str++ != ']')
7546 {
7547 inst.error = _("missing ]");
7548 return;
7549 }
7550
7551 skip_whitespace (str);
7552
7553 if (*str == '!')
7554 {
7555 if (conflict_reg)
7556 as_warn (_("%s register same as write-back base"),
7557 ((inst.instruction & LOAD_BIT)
7558 ? _("destination") : _("source")));
7559 str++;
7560 inst.instruction |= WRITE_BACK;
7561 }
7562 }
7563 }
7564 else if (*str == '=')
7565 {
7566 if ((inst.instruction & LOAD_BIT) == 0)
7567 {
7568 inst.error = _("invalid pseudo operation");
7569 return;
7570 }
7571
7572 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
7573 str++;
7574
7575 skip_whitespace (str);
7576
7577 if (my_get_expression (&inst.reloc.exp, &str))
7578 return;
7579
7580 if (inst.reloc.exp.X_op != O_constant
7581 && inst.reloc.exp.X_op != O_symbol)
7582 {
7583 inst.error = _("constant expression expected");
7584 return;
7585 }
7586
7587 if (inst.reloc.exp.X_op == O_constant)
7588 {
7589 value = validate_immediate (inst.reloc.exp.X_add_number);
7590
7591 if (value != FAIL)
7592 {
7593 /* This can be done with a mov instruction. */
7594 inst.instruction &= LITERAL_MASK;
7595 inst.instruction |= (INST_IMMEDIATE
7596 | (OPCODE_MOV << DATA_OP_SHIFT));
7597 inst.instruction |= value & 0xfff;
7598 end_of_line (str);
7599 return;
7600 }
7601
7602 value = validate_immediate (~inst.reloc.exp.X_add_number);
7603
7604 if (value != FAIL)
7605 {
7606 /* This can be done with a mvn instruction. */
7607 inst.instruction &= LITERAL_MASK;
7608 inst.instruction |= (INST_IMMEDIATE
7609 | (OPCODE_MVN << DATA_OP_SHIFT));
7610 inst.instruction |= value & 0xfff;
7611 end_of_line (str);
7612 return;
7613 }
7614 }
7615
7616 /* Insert into literal pool. */
7617 if (add_to_lit_pool () == FAIL)
7618 {
7619 if (!inst.error)
7620 inst.error = _("literal pool insertion failed");
7621 return;
7622 }
7623
7624 /* Change the instruction exp to point to the pool. */
7625 inst.reloc.type = BFD_RELOC_ARM_LITERAL;
7626 inst.reloc.pc_rel = 1;
7627 inst.instruction |= (REG_PC << 16);
7628 pre_inc = 1;
7629 }
7630 else
7631 {
7632 if (my_get_expression (&inst.reloc.exp, &str))
7633 return;
7634
7635 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
7636 #ifndef TE_WINCE
7637 /* PC rel adjust. */
7638 inst.reloc.exp.X_add_number -= 8;
7639 #endif
7640 inst.reloc.pc_rel = 1;
7641 inst.instruction |= (REG_PC << 16);
7642 pre_inc = 1;
7643 }
7644
7645 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
7646 end_of_line (str);
7647 }
7648
7649 static void
7650 do_ldstt (str)
7651 char * str;
7652 {
7653 int conflict_reg;
7654
7655 skip_whitespace (str);
7656
7657 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
7658 {
7659 if (!inst.error)
7660 inst.error = BAD_ARGS;
7661 return;
7662 }
7663
7664 if (skip_past_comma (& str) == FAIL)
7665 {
7666 inst.error = _("address expected");
7667 return;
7668 }
7669
7670 if (*str == '[')
7671 {
7672 int reg;
7673
7674 str++;
7675
7676 skip_whitespace (str);
7677
7678 if ((reg = reg_required_here (&str, 16)) == FAIL)
7679 return;
7680
7681 /* ldrt/strt always use post-indexed addressing, so if the base is
7682 the same as Rd, we warn. */
7683 if (conflict_reg == reg)
7684 as_warn (_("%s register same as write-back base"),
7685 ((inst.instruction & LOAD_BIT)
7686 ? _("destination") : _("source")));
7687
7688 skip_whitespace (str);
7689
7690 if (*str == ']')
7691 {
7692 str ++;
7693
7694 if (skip_past_comma (&str) == SUCCESS)
7695 {
7696 /* [Rn],... (post inc) */
7697 if (ldst_extend (&str) == FAIL)
7698 return;
7699 }
7700 else
7701 {
7702 /* [Rn] */
7703 skip_whitespace (str);
7704
7705 /* Skip a write-back '!'. */
7706 if (*str == '!')
7707 str++;
7708
7709 inst.instruction |= INDEX_UP;
7710 }
7711 }
7712 else
7713 {
7714 inst.error = _("post-indexed expression expected");
7715 return;
7716 }
7717 }
7718 else
7719 {
7720 inst.error = _("post-indexed expression expected");
7721 return;
7722 }
7723
7724 end_of_line (str);
7725 }
7726
7727 static int
7728 ldst_extend_v4 (str)
7729 char ** str;
7730 {
7731 int add = INDEX_UP;
7732
7733 switch (**str)
7734 {
7735 case '#':
7736 case '$':
7737 (*str)++;
7738 if (my_get_expression (& inst.reloc.exp, str))
7739 return FAIL;
7740
7741 if (inst.reloc.exp.X_op == O_constant)
7742 {
7743 int value = inst.reloc.exp.X_add_number;
7744
7745 if (value < -255 || value > 255)
7746 {
7747 inst.error = _("address offset too large");
7748 return FAIL;
7749 }
7750
7751 if (value < 0)
7752 {
7753 value = -value;
7754 add = 0;
7755 }
7756
7757 /* Halfword and signextension instructions have the
7758 immediate value split across bits 11..8 and bits 3..0. */
7759 inst.instruction |= (add | HWOFFSET_IMM
7760 | ((value >> 4) << 8) | (value & 0xF));
7761 }
7762 else
7763 {
7764 inst.instruction |= HWOFFSET_IMM;
7765 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
7766 inst.reloc.pc_rel = 0;
7767 }
7768 return SUCCESS;
7769
7770 case '-':
7771 add = 0;
7772 /* Fall through. */
7773
7774 case '+':
7775 (*str)++;
7776 /* Fall through. */
7777
7778 default:
7779 if (reg_required_here (str, 0) == FAIL)
7780 return FAIL;
7781
7782 inst.instruction |= add;
7783 return SUCCESS;
7784 }
7785 }
7786
7787 /* Halfword and signed-byte load/store operations. */
7788 static void
7789 do_ldstv4 (str)
7790 char * str;
7791 {
7792 int pre_inc = 0;
7793 int conflict_reg;
7794 int value;
7795
7796 skip_whitespace (str);
7797
7798 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
7799 {
7800 if (!inst.error)
7801 inst.error = BAD_ARGS;
7802 return;
7803 }
7804
7805 if (skip_past_comma (& str) == FAIL)
7806 {
7807 inst.error = _("address expected");
7808 return;
7809 }
7810
7811 if (*str == '[')
7812 {
7813 int reg;
7814
7815 str++;
7816
7817 skip_whitespace (str);
7818
7819 if ((reg = reg_required_here (&str, 16)) == FAIL)
7820 return;
7821
7822 /* Conflicts can occur on stores as well as loads. */
7823 conflict_reg = (conflict_reg == reg);
7824
7825 skip_whitespace (str);
7826
7827 if (*str == ']')
7828 {
7829 str ++;
7830
7831 if (skip_past_comma (&str) == SUCCESS)
7832 {
7833 /* [Rn],... (post inc) */
7834 if (ldst_extend_v4 (&str) == FAIL)
7835 return;
7836 if (conflict_reg)
7837 as_warn (_("%s register same as write-back base"),
7838 ((inst.instruction & LOAD_BIT)
7839 ? _("destination") : _("source")));
7840 }
7841 else
7842 {
7843 /* [Rn] */
7844 inst.instruction |= HWOFFSET_IMM;
7845
7846 skip_whitespace (str);
7847
7848 if (*str == '!')
7849 {
7850 if (conflict_reg)
7851 as_warn (_("%s register same as write-back base"),
7852 ((inst.instruction & LOAD_BIT)
7853 ? _("destination") : _("source")));
7854 str++;
7855 inst.instruction |= WRITE_BACK;
7856 }
7857
7858 inst.instruction |= INDEX_UP;
7859 pre_inc = 1;
7860 }
7861 }
7862 else
7863 {
7864 /* [Rn,...] */
7865 if (skip_past_comma (&str) == FAIL)
7866 {
7867 inst.error = _("pre-indexed expression expected");
7868 return;
7869 }
7870
7871 pre_inc = 1;
7872 if (ldst_extend_v4 (&str) == FAIL)
7873 return;
7874
7875 skip_whitespace (str);
7876
7877 if (*str++ != ']')
7878 {
7879 inst.error = _("missing ]");
7880 return;
7881 }
7882
7883 skip_whitespace (str);
7884
7885 if (*str == '!')
7886 {
7887 if (conflict_reg)
7888 as_warn (_("%s register same as write-back base"),
7889 ((inst.instruction & LOAD_BIT)
7890 ? _("destination") : _("source")));
7891 str++;
7892 inst.instruction |= WRITE_BACK;
7893 }
7894 }
7895 }
7896 else if (*str == '=')
7897 {
7898 if ((inst.instruction & LOAD_BIT) == 0)
7899 {
7900 inst.error = _("invalid pseudo operation");
7901 return;
7902 }
7903
7904 /* XXX Does this work correctly for half-word/byte ops? */
7905 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
7906 str++;
7907
7908 skip_whitespace (str);
7909
7910 if (my_get_expression (&inst.reloc.exp, &str))
7911 return;
7912
7913 if (inst.reloc.exp.X_op != O_constant
7914 && inst.reloc.exp.X_op != O_symbol)
7915 {
7916 inst.error = _("constant expression expected");
7917 return;
7918 }
7919
7920 if (inst.reloc.exp.X_op == O_constant)
7921 {
7922 value = validate_immediate (inst.reloc.exp.X_add_number);
7923
7924 if (value != FAIL)
7925 {
7926 /* This can be done with a mov instruction. */
7927 inst.instruction &= LITERAL_MASK;
7928 inst.instruction |= INST_IMMEDIATE | (OPCODE_MOV << DATA_OP_SHIFT);
7929 inst.instruction |= value & 0xfff;
7930 end_of_line (str);
7931 return;
7932 }
7933
7934 value = validate_immediate (~ inst.reloc.exp.X_add_number);
7935
7936 if (value != FAIL)
7937 {
7938 /* This can be done with a mvn instruction. */
7939 inst.instruction &= LITERAL_MASK;
7940 inst.instruction |= INST_IMMEDIATE | (OPCODE_MVN << DATA_OP_SHIFT);
7941 inst.instruction |= value & 0xfff;
7942 end_of_line (str);
7943 return;
7944 }
7945 }
7946
7947 /* Insert into literal pool. */
7948 if (add_to_lit_pool () == FAIL)
7949 {
7950 if (!inst.error)
7951 inst.error = _("literal pool insertion failed");
7952 return;
7953 }
7954
7955 /* Change the instruction exp to point to the pool. */
7956 inst.instruction |= HWOFFSET_IMM;
7957 inst.reloc.type = BFD_RELOC_ARM_HWLITERAL;
7958 inst.reloc.pc_rel = 1;
7959 inst.instruction |= (REG_PC << 16);
7960 pre_inc = 1;
7961 }
7962 else
7963 {
7964 if (my_get_expression (&inst.reloc.exp, &str))
7965 return;
7966
7967 inst.instruction |= HWOFFSET_IMM;
7968 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
7969 #ifndef TE_WINCE
7970 /* PC rel adjust. */
7971 inst.reloc.exp.X_add_number -= 8;
7972 #endif
7973 inst.reloc.pc_rel = 1;
7974 inst.instruction |= (REG_PC << 16);
7975 pre_inc = 1;
7976 }
7977
7978 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
7979 end_of_line (str);
7980 }
7981
7982 static long
7983 reg_list (strp)
7984 char ** strp;
7985 {
7986 char * str = * strp;
7987 long range = 0;
7988 int another_range;
7989
7990 /* We come back here if we get ranges concatenated by '+' or '|'. */
7991 do
7992 {
7993 another_range = 0;
7994
7995 if (*str == '{')
7996 {
7997 int in_range = 0;
7998 int cur_reg = -1;
7999
8000 str++;
8001 do
8002 {
8003 int reg;
8004
8005 skip_whitespace (str);
8006
8007 if ((reg = reg_required_here (& str, -1)) == FAIL)
8008 return FAIL;
8009
8010 if (in_range)
8011 {
8012 int i;
8013
8014 if (reg <= cur_reg)
8015 {
8016 inst.error = _("bad range in register list");
8017 return FAIL;
8018 }
8019
8020 for (i = cur_reg + 1; i < reg; i++)
8021 {
8022 if (range & (1 << i))
8023 as_tsktsk
8024 (_("Warning: duplicated register (r%d) in register list"),
8025 i);
8026 else
8027 range |= 1 << i;
8028 }
8029 in_range = 0;
8030 }
8031
8032 if (range & (1 << reg))
8033 as_tsktsk (_("Warning: duplicated register (r%d) in register list"),
8034 reg);
8035 else if (reg <= cur_reg)
8036 as_tsktsk (_("Warning: register range not in ascending order"));
8037
8038 range |= 1 << reg;
8039 cur_reg = reg;
8040 }
8041 while (skip_past_comma (&str) != FAIL
8042 || (in_range = 1, *str++ == '-'));
8043 str--;
8044 skip_whitespace (str);
8045
8046 if (*str++ != '}')
8047 {
8048 inst.error = _("missing `}'");
8049 return FAIL;
8050 }
8051 }
8052 else
8053 {
8054 expressionS expr;
8055
8056 if (my_get_expression (&expr, &str))
8057 return FAIL;
8058
8059 if (expr.X_op == O_constant)
8060 {
8061 if (expr.X_add_number
8062 != (expr.X_add_number & 0x0000ffff))
8063 {
8064 inst.error = _("invalid register mask");
8065 return FAIL;
8066 }
8067
8068 if ((range & expr.X_add_number) != 0)
8069 {
8070 int regno = range & expr.X_add_number;
8071
8072 regno &= -regno;
8073 regno = (1 << regno) - 1;
8074 as_tsktsk
8075 (_("Warning: duplicated register (r%d) in register list"),
8076 regno);
8077 }
8078
8079 range |= expr.X_add_number;
8080 }
8081 else
8082 {
8083 if (inst.reloc.type != 0)
8084 {
8085 inst.error = _("expression too complex");
8086 return FAIL;
8087 }
8088
8089 memcpy (&inst.reloc.exp, &expr, sizeof (expressionS));
8090 inst.reloc.type = BFD_RELOC_ARM_MULTI;
8091 inst.reloc.pc_rel = 0;
8092 }
8093 }
8094
8095 skip_whitespace (str);
8096
8097 if (*str == '|' || *str == '+')
8098 {
8099 str++;
8100 another_range = 1;
8101 }
8102 }
8103 while (another_range);
8104
8105 *strp = str;
8106 return range;
8107 }
8108
8109 static void
8110 do_ldmstm (str)
8111 char * str;
8112 {
8113 int base_reg;
8114 long range;
8115
8116 skip_whitespace (str);
8117
8118 if ((base_reg = reg_required_here (&str, 16)) == FAIL)
8119 return;
8120
8121 if (base_reg == REG_PC)
8122 {
8123 inst.error = _("r15 not allowed as base register");
8124 return;
8125 }
8126
8127 skip_whitespace (str);
8128
8129 if (*str == '!')
8130 {
8131 inst.instruction |= WRITE_BACK;
8132 str++;
8133 }
8134
8135 if (skip_past_comma (&str) == FAIL
8136 || (range = reg_list (&str)) == FAIL)
8137 {
8138 if (! inst.error)
8139 inst.error = BAD_ARGS;
8140 return;
8141 }
8142
8143 if (*str == '^')
8144 {
8145 str++;
8146 inst.instruction |= LDM_TYPE_2_OR_3;
8147 }
8148
8149 if (inst.instruction & WRITE_BACK)
8150 {
8151 /* Check for unpredictable uses of writeback. */
8152 if (inst.instruction & LOAD_BIT)
8153 {
8154 /* Not allowed in LDM type 2. */
8155 if ((inst.instruction & LDM_TYPE_2_OR_3)
8156 && ((range & (1 << REG_PC)) == 0))
8157 as_warn (_("writeback of base register is UNPREDICTABLE"));
8158 /* Only allowed if base reg not in list for other types. */
8159 else if (range & (1 << base_reg))
8160 as_warn (_("writeback of base register when in register list is UNPREDICTABLE"));
8161 }
8162 else /* STM. */
8163 {
8164 /* Not allowed for type 2. */
8165 if (inst.instruction & LDM_TYPE_2_OR_3)
8166 as_warn (_("writeback of base register is UNPREDICTABLE"));
8167 /* Only allowed if base reg not in list, or first in list. */
8168 else if ((range & (1 << base_reg))
8169 && (range & ((1 << base_reg) - 1)))
8170 as_warn (_("if writeback register is in list, it must be the lowest reg in the list"));
8171 }
8172 }
8173
8174 inst.instruction |= range;
8175 end_of_line (str);
8176 }
8177
8178 static void
8179 do_swi (str)
8180 char * str;
8181 {
8182 skip_whitespace (str);
8183
8184 /* Allow optional leading '#'. */
8185 if (is_immediate_prefix (*str))
8186 str++;
8187
8188 if (my_get_expression (& inst.reloc.exp, & str))
8189 return;
8190
8191 inst.reloc.type = BFD_RELOC_ARM_SWI;
8192 inst.reloc.pc_rel = 0;
8193 end_of_line (str);
8194 }
8195
8196 static void
8197 do_swap (str)
8198 char * str;
8199 {
8200 int reg;
8201
8202 skip_whitespace (str);
8203
8204 if ((reg = reg_required_here (&str, 12)) == FAIL)
8205 return;
8206
8207 if (reg == REG_PC)
8208 {
8209 inst.error = _("r15 not allowed in swap");
8210 return;
8211 }
8212
8213 if (skip_past_comma (&str) == FAIL
8214 || (reg = reg_required_here (&str, 0)) == FAIL)
8215 {
8216 if (!inst.error)
8217 inst.error = BAD_ARGS;
8218 return;
8219 }
8220
8221 if (reg == REG_PC)
8222 {
8223 inst.error = _("r15 not allowed in swap");
8224 return;
8225 }
8226
8227 if (skip_past_comma (&str) == FAIL
8228 || *str++ != '[')
8229 {
8230 inst.error = BAD_ARGS;
8231 return;
8232 }
8233
8234 skip_whitespace (str);
8235
8236 if ((reg = reg_required_here (&str, 16)) == FAIL)
8237 return;
8238
8239 if (reg == REG_PC)
8240 {
8241 inst.error = BAD_PC;
8242 return;
8243 }
8244
8245 skip_whitespace (str);
8246
8247 if (*str++ != ']')
8248 {
8249 inst.error = _("missing ]");
8250 return;
8251 }
8252
8253 end_of_line (str);
8254 }
8255
8256 static void
8257 do_branch (str)
8258 char * str;
8259 {
8260 if (my_get_expression (&inst.reloc.exp, &str))
8261 return;
8262
8263 #ifdef OBJ_ELF
8264 {
8265 char * save_in;
8266
8267 /* ScottB: February 5, 1998 - Check to see of PLT32 reloc
8268 required for the instruction. */
8269
8270 /* arm_parse_reloc () works on input_line_pointer.
8271 We actually want to parse the operands to the branch instruction
8272 passed in 'str'. Save the input pointer and restore it later. */
8273 save_in = input_line_pointer;
8274 input_line_pointer = str;
8275 if (inst.reloc.exp.X_op == O_symbol
8276 && *str == '('
8277 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
8278 {
8279 inst.reloc.type = BFD_RELOC_ARM_PLT32;
8280 inst.reloc.pc_rel = 0;
8281 /* Modify str to point to after parsed operands, otherwise
8282 end_of_line() will complain about the (PLT) left in str. */
8283 str = input_line_pointer;
8284 }
8285 else
8286 {
8287 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
8288 inst.reloc.pc_rel = 1;
8289 }
8290 input_line_pointer = save_in;
8291 }
8292 #else
8293 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
8294 inst.reloc.pc_rel = 1;
8295 #endif /* OBJ_ELF */
8296
8297 end_of_line (str);
8298 }
8299
8300 static void
8301 do_bx (str)
8302 char * str;
8303 {
8304 int reg;
8305
8306 skip_whitespace (str);
8307
8308 if ((reg = reg_required_here (&str, 0)) == FAIL)
8309 {
8310 inst.error = BAD_ARGS;
8311 return;
8312 }
8313
8314 /* Note - it is not illegal to do a "bx pc". Useless, but not illegal. */
8315 if (reg == REG_PC)
8316 as_tsktsk (_("use of r15 in bx in ARM mode is not really useful"));
8317
8318 end_of_line (str);
8319 }
8320
8321 static void
8322 do_cdp (str)
8323 char * str;
8324 {
8325 /* Co-processor data operation.
8326 Format: CDP{cond} CP#,<expr>,CRd,CRn,CRm{,<expr>} */
8327 skip_whitespace (str);
8328
8329 if (co_proc_number (&str) == FAIL)
8330 {
8331 if (!inst.error)
8332 inst.error = BAD_ARGS;
8333 return;
8334 }
8335
8336 if (skip_past_comma (&str) == FAIL
8337 || cp_opc_expr (&str, 20,4) == FAIL)
8338 {
8339 if (!inst.error)
8340 inst.error = BAD_ARGS;
8341 return;
8342 }
8343
8344 if (skip_past_comma (&str) == FAIL
8345 || cp_reg_required_here (&str, 12) == FAIL)
8346 {
8347 if (!inst.error)
8348 inst.error = BAD_ARGS;
8349 return;
8350 }
8351
8352 if (skip_past_comma (&str) == FAIL
8353 || cp_reg_required_here (&str, 16) == FAIL)
8354 {
8355 if (!inst.error)
8356 inst.error = BAD_ARGS;
8357 return;
8358 }
8359
8360 if (skip_past_comma (&str) == FAIL
8361 || cp_reg_required_here (&str, 0) == FAIL)
8362 {
8363 if (!inst.error)
8364 inst.error = BAD_ARGS;
8365 return;
8366 }
8367
8368 if (skip_past_comma (&str) == SUCCESS)
8369 {
8370 if (cp_opc_expr (&str, 5, 3) == FAIL)
8371 {
8372 if (!inst.error)
8373 inst.error = BAD_ARGS;
8374 return;
8375 }
8376 }
8377
8378 end_of_line (str);
8379 }
8380
8381 static void
8382 do_lstc (str)
8383 char * str;
8384 {
8385 /* Co-processor register load/store.
8386 Format: <LDC|STC{cond}[L] CP#,CRd,<address> */
8387
8388 skip_whitespace (str);
8389
8390 if (co_proc_number (&str) == FAIL)
8391 {
8392 if (!inst.error)
8393 inst.error = BAD_ARGS;
8394 return;
8395 }
8396
8397 if (skip_past_comma (&str) == FAIL
8398 || cp_reg_required_here (&str, 12) == FAIL)
8399 {
8400 if (!inst.error)
8401 inst.error = BAD_ARGS;
8402 return;
8403 }
8404
8405 if (skip_past_comma (&str) == FAIL
8406 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
8407 {
8408 if (! inst.error)
8409 inst.error = BAD_ARGS;
8410 return;
8411 }
8412
8413 end_of_line (str);
8414 }
8415
8416 static void
8417 do_co_reg (str)
8418 char * str;
8419 {
8420 /* Co-processor register transfer.
8421 Format: <MCR|MRC>{cond} CP#,<expr1>,Rd,CRn,CRm{,<expr2>} */
8422
8423 skip_whitespace (str);
8424
8425 if (co_proc_number (&str) == FAIL)
8426 {
8427 if (!inst.error)
8428 inst.error = BAD_ARGS;
8429 return;
8430 }
8431
8432 if (skip_past_comma (&str) == FAIL
8433 || cp_opc_expr (&str, 21, 3) == FAIL)
8434 {
8435 if (!inst.error)
8436 inst.error = BAD_ARGS;
8437 return;
8438 }
8439
8440 if (skip_past_comma (&str) == FAIL
8441 || reg_required_here (&str, 12) == FAIL)
8442 {
8443 if (!inst.error)
8444 inst.error = BAD_ARGS;
8445 return;
8446 }
8447
8448 if (skip_past_comma (&str) == FAIL
8449 || cp_reg_required_here (&str, 16) == FAIL)
8450 {
8451 if (!inst.error)
8452 inst.error = BAD_ARGS;
8453 return;
8454 }
8455
8456 if (skip_past_comma (&str) == FAIL
8457 || cp_reg_required_here (&str, 0) == FAIL)
8458 {
8459 if (!inst.error)
8460 inst.error = BAD_ARGS;
8461 return;
8462 }
8463
8464 if (skip_past_comma (&str) == SUCCESS)
8465 {
8466 if (cp_opc_expr (&str, 5, 3) == FAIL)
8467 {
8468 if (!inst.error)
8469 inst.error = BAD_ARGS;
8470 return;
8471 }
8472 }
8473
8474 end_of_line (str);
8475 }
8476
8477 static void
8478 do_fpa_ctrl (str)
8479 char * str;
8480 {
8481 /* FP control registers.
8482 Format: <WFS|RFS|WFC|RFC>{cond} Rn */
8483
8484 skip_whitespace (str);
8485
8486 if (reg_required_here (&str, 12) == FAIL)
8487 {
8488 if (!inst.error)
8489 inst.error = BAD_ARGS;
8490 return;
8491 }
8492
8493 end_of_line (str);
8494 }
8495
8496 static void
8497 do_fpa_ldst (str)
8498 char * str;
8499 {
8500 skip_whitespace (str);
8501
8502 if (fp_reg_required_here (&str, 12) == FAIL)
8503 {
8504 if (!inst.error)
8505 inst.error = BAD_ARGS;
8506 return;
8507 }
8508
8509 if (skip_past_comma (&str) == FAIL
8510 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
8511 {
8512 if (!inst.error)
8513 inst.error = BAD_ARGS;
8514 return;
8515 }
8516
8517 end_of_line (str);
8518 }
8519
8520 static void
8521 do_fpa_ldmstm (str)
8522 char * str;
8523 {
8524 int num_regs;
8525
8526 skip_whitespace (str);
8527
8528 if (fp_reg_required_here (&str, 12) == FAIL)
8529 {
8530 if (! inst.error)
8531 inst.error = BAD_ARGS;
8532 return;
8533 }
8534
8535 /* Get Number of registers to transfer. */
8536 if (skip_past_comma (&str) == FAIL
8537 || my_get_expression (&inst.reloc.exp, &str))
8538 {
8539 if (! inst.error)
8540 inst.error = _("constant expression expected");
8541 return;
8542 }
8543
8544 if (inst.reloc.exp.X_op != O_constant)
8545 {
8546 inst.error = _("constant value required for number of registers");
8547 return;
8548 }
8549
8550 num_regs = inst.reloc.exp.X_add_number;
8551
8552 if (num_regs < 1 || num_regs > 4)
8553 {
8554 inst.error = _("number of registers must be in the range [1:4]");
8555 return;
8556 }
8557
8558 switch (num_regs)
8559 {
8560 case 1:
8561 inst.instruction |= CP_T_X;
8562 break;
8563 case 2:
8564 inst.instruction |= CP_T_Y;
8565 break;
8566 case 3:
8567 inst.instruction |= CP_T_Y | CP_T_X;
8568 break;
8569 case 4:
8570 break;
8571 default:
8572 abort ();
8573 }
8574
8575 if (inst.instruction & (CP_T_Pre | CP_T_UD)) /* ea/fd format. */
8576 {
8577 int reg;
8578 int write_back;
8579 int offset;
8580
8581 /* The instruction specified "ea" or "fd", so we can only accept
8582 [Rn]{!}. The instruction does not really support stacking or
8583 unstacking, so we have to emulate these by setting appropriate
8584 bits and offsets. */
8585 if (skip_past_comma (&str) == FAIL
8586 || *str != '[')
8587 {
8588 if (! inst.error)
8589 inst.error = BAD_ARGS;
8590 return;
8591 }
8592
8593 str++;
8594 skip_whitespace (str);
8595
8596 if ((reg = reg_required_here (&str, 16)) == FAIL)
8597 return;
8598
8599 skip_whitespace (str);
8600
8601 if (*str != ']')
8602 {
8603 inst.error = BAD_ARGS;
8604 return;
8605 }
8606
8607 str++;
8608 if (*str == '!')
8609 {
8610 write_back = 1;
8611 str++;
8612 if (reg == REG_PC)
8613 {
8614 inst.error =
8615 _("r15 not allowed as base register with write-back");
8616 return;
8617 }
8618 }
8619 else
8620 write_back = 0;
8621
8622 if (inst.instruction & CP_T_Pre)
8623 {
8624 /* Pre-decrement. */
8625 offset = 3 * num_regs;
8626 if (write_back)
8627 inst.instruction |= CP_T_WB;
8628 }
8629 else
8630 {
8631 /* Post-increment. */
8632 if (write_back)
8633 {
8634 inst.instruction |= CP_T_WB;
8635 offset = 3 * num_regs;
8636 }
8637 else
8638 {
8639 /* No write-back, so convert this into a standard pre-increment
8640 instruction -- aesthetically more pleasing. */
8641 inst.instruction |= CP_T_Pre | CP_T_UD;
8642 offset = 0;
8643 }
8644 }
8645
8646 inst.instruction |= offset;
8647 }
8648 else if (skip_past_comma (&str) == FAIL
8649 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
8650 {
8651 if (! inst.error)
8652 inst.error = BAD_ARGS;
8653 return;
8654 }
8655
8656 end_of_line (str);
8657 }
8658
8659 static void
8660 do_fpa_dyadic (str)
8661 char * str;
8662 {
8663 skip_whitespace (str);
8664
8665 if (fp_reg_required_here (&str, 12) == FAIL)
8666 {
8667 if (! inst.error)
8668 inst.error = BAD_ARGS;
8669 return;
8670 }
8671
8672 if (skip_past_comma (&str) == FAIL
8673 || fp_reg_required_here (&str, 16) == FAIL)
8674 {
8675 if (! inst.error)
8676 inst.error = BAD_ARGS;
8677 return;
8678 }
8679
8680 if (skip_past_comma (&str) == FAIL
8681 || fp_op2 (&str) == FAIL)
8682 {
8683 if (! inst.error)
8684 inst.error = BAD_ARGS;
8685 return;
8686 }
8687
8688 end_of_line (str);
8689 }
8690
8691 static void
8692 do_fpa_monadic (str)
8693 char * str;
8694 {
8695 skip_whitespace (str);
8696
8697 if (fp_reg_required_here (&str, 12) == FAIL)
8698 {
8699 if (! inst.error)
8700 inst.error = BAD_ARGS;
8701 return;
8702 }
8703
8704 if (skip_past_comma (&str) == FAIL
8705 || fp_op2 (&str) == FAIL)
8706 {
8707 if (! inst.error)
8708 inst.error = BAD_ARGS;
8709 return;
8710 }
8711
8712 end_of_line (str);
8713 }
8714
8715 static void
8716 do_fpa_cmp (str)
8717 char * str;
8718 {
8719 skip_whitespace (str);
8720
8721 if (fp_reg_required_here (&str, 16) == FAIL)
8722 {
8723 if (! inst.error)
8724 inst.error = BAD_ARGS;
8725 return;
8726 }
8727
8728 if (skip_past_comma (&str) == FAIL
8729 || fp_op2 (&str) == FAIL)
8730 {
8731 if (! inst.error)
8732 inst.error = BAD_ARGS;
8733 return;
8734 }
8735
8736 end_of_line (str);
8737 }
8738
8739 static void
8740 do_fpa_from_reg (str)
8741 char * str;
8742 {
8743 skip_whitespace (str);
8744
8745 if (fp_reg_required_here (&str, 16) == FAIL)
8746 {
8747 if (! inst.error)
8748 inst.error = BAD_ARGS;
8749 return;
8750 }
8751
8752 if (skip_past_comma (&str) == FAIL
8753 || reg_required_here (&str, 12) == FAIL)
8754 {
8755 if (! inst.error)
8756 inst.error = BAD_ARGS;
8757 return;
8758 }
8759
8760 end_of_line (str);
8761 }
8762
8763 static void
8764 do_fpa_to_reg (str)
8765 char * str;
8766 {
8767 skip_whitespace (str);
8768
8769 if (reg_required_here (&str, 12) == FAIL)
8770 return;
8771
8772 if (skip_past_comma (&str) == FAIL
8773 || fp_reg_required_here (&str, 0) == FAIL)
8774 {
8775 if (! inst.error)
8776 inst.error = BAD_ARGS;
8777 return;
8778 }
8779
8780 end_of_line (str);
8781 }
8782
8783 static int
8784 vfp_sp_reg_required_here (str, pos)
8785 char **str;
8786 enum vfp_sp_reg_pos pos;
8787 {
8788 int reg;
8789 char *start = *str;
8790
8791 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_SN].htab)) != FAIL)
8792 {
8793 switch (pos)
8794 {
8795 case VFP_REG_Sd:
8796 inst.instruction |= ((reg >> 1) << 12) | ((reg & 1) << 22);
8797 break;
8798
8799 case VFP_REG_Sn:
8800 inst.instruction |= ((reg >> 1) << 16) | ((reg & 1) << 7);
8801 break;
8802
8803 case VFP_REG_Sm:
8804 inst.instruction |= ((reg >> 1) << 0) | ((reg & 1) << 5);
8805 break;
8806
8807 default:
8808 abort ();
8809 }
8810 return reg;
8811 }
8812
8813 /* In the few cases where we might be able to accept something else
8814 this error can be overridden. */
8815 inst.error = _(all_reg_maps[REG_TYPE_SN].expected);
8816
8817 /* Restore the start point. */
8818 *str = start;
8819 return FAIL;
8820 }
8821
8822 static int
8823 vfp_dp_reg_required_here (str, pos)
8824 char **str;
8825 enum vfp_dp_reg_pos pos;
8826 {
8827 int reg;
8828 char *start = *str;
8829
8830 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_DN].htab)) != FAIL)
8831 {
8832 switch (pos)
8833 {
8834 case VFP_REG_Dd:
8835 inst.instruction |= reg << 12;
8836 break;
8837
8838 case VFP_REG_Dn:
8839 inst.instruction |= reg << 16;
8840 break;
8841
8842 case VFP_REG_Dm:
8843 inst.instruction |= reg << 0;
8844 break;
8845
8846 default:
8847 abort ();
8848 }
8849 return reg;
8850 }
8851
8852 /* In the few cases where we might be able to accept something else
8853 this error can be overridden. */
8854 inst.error = _(all_reg_maps[REG_TYPE_DN].expected);
8855
8856 /* Restore the start point. */
8857 *str = start;
8858 return FAIL;
8859 }
8860
8861 static void
8862 do_vfp_sp_monadic (str)
8863 char *str;
8864 {
8865 skip_whitespace (str);
8866
8867 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
8868 return;
8869
8870 if (skip_past_comma (&str) == FAIL
8871 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
8872 {
8873 if (! inst.error)
8874 inst.error = BAD_ARGS;
8875 return;
8876 }
8877
8878 end_of_line (str);
8879 }
8880
8881 static void
8882 do_vfp_dp_monadic (str)
8883 char *str;
8884 {
8885 skip_whitespace (str);
8886
8887 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
8888 return;
8889
8890 if (skip_past_comma (&str) == FAIL
8891 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
8892 {
8893 if (! inst.error)
8894 inst.error = BAD_ARGS;
8895 return;
8896 }
8897
8898 end_of_line (str);
8899 }
8900
8901 static void
8902 do_vfp_sp_dyadic (str)
8903 char *str;
8904 {
8905 skip_whitespace (str);
8906
8907 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
8908 return;
8909
8910 if (skip_past_comma (&str) == FAIL
8911 || vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL
8912 || skip_past_comma (&str) == FAIL
8913 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
8914 {
8915 if (! inst.error)
8916 inst.error = BAD_ARGS;
8917 return;
8918 }
8919
8920 end_of_line (str);
8921 }
8922
8923 static void
8924 do_vfp_dp_dyadic (str)
8925 char *str;
8926 {
8927 skip_whitespace (str);
8928
8929 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
8930 return;
8931
8932 if (skip_past_comma (&str) == FAIL
8933 || vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL
8934 || skip_past_comma (&str) == FAIL
8935 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
8936 {
8937 if (! inst.error)
8938 inst.error = BAD_ARGS;
8939 return;
8940 }
8941
8942 end_of_line (str);
8943 }
8944
8945 static void
8946 do_vfp_reg_from_sp (str)
8947 char *str;
8948 {
8949 skip_whitespace (str);
8950
8951 if (reg_required_here (&str, 12) == FAIL)
8952 return;
8953
8954 if (skip_past_comma (&str) == FAIL
8955 || vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL)
8956 {
8957 if (! inst.error)
8958 inst.error = BAD_ARGS;
8959 return;
8960 }
8961
8962 end_of_line (str);
8963 }
8964
8965 static void
8966 do_vfp_reg2_from_sp2 (str)
8967 char *str;
8968 {
8969 skip_whitespace (str);
8970
8971 if (reg_required_here (&str, 12) == FAIL
8972 || skip_past_comma (&str) == FAIL
8973 || reg_required_here (&str, 16) == FAIL
8974 || skip_past_comma (&str) == FAIL)
8975 {
8976 if (! inst.error)
8977 inst.error = BAD_ARGS;
8978 return;
8979 }
8980
8981 /* We require exactly two consecutive SP registers. */
8982 if (vfp_sp_reg_list (&str, VFP_REG_Sm) != 2)
8983 {
8984 if (! inst.error)
8985 inst.error = _("only two consecutive VFP SP registers allowed here");
8986 }
8987
8988 end_of_line (str);
8989 }
8990
8991 static void
8992 do_vfp_sp_from_reg (str)
8993 char *str;
8994 {
8995 skip_whitespace (str);
8996
8997 if (vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL)
8998 return;
8999
9000 if (skip_past_comma (&str) == FAIL
9001 || reg_required_here (&str, 12) == FAIL)
9002 {
9003 if (! inst.error)
9004 inst.error = BAD_ARGS;
9005 return;
9006 }
9007
9008 end_of_line (str);
9009 }
9010
9011 static void
9012 do_vfp_sp2_from_reg2 (str)
9013 char *str;
9014 {
9015 skip_whitespace (str);
9016
9017 /* We require exactly two consecutive SP registers. */
9018 if (vfp_sp_reg_list (&str, VFP_REG_Sm) != 2)
9019 {
9020 if (! inst.error)
9021 inst.error = _("only two consecutive VFP SP registers allowed here");
9022 }
9023
9024 if (skip_past_comma (&str) == FAIL
9025 || reg_required_here (&str, 12) == FAIL
9026 || skip_past_comma (&str) == FAIL
9027 || reg_required_here (&str, 16) == FAIL)
9028 {
9029 if (! inst.error)
9030 inst.error = BAD_ARGS;
9031 return;
9032 }
9033
9034 end_of_line (str);
9035 }
9036
9037 static void
9038 do_vfp_reg_from_dp (str)
9039 char *str;
9040 {
9041 skip_whitespace (str);
9042
9043 if (reg_required_here (&str, 12) == FAIL)
9044 return;
9045
9046 if (skip_past_comma (&str) == FAIL
9047 || vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL)
9048 {
9049 if (! inst.error)
9050 inst.error = BAD_ARGS;
9051 return;
9052 }
9053
9054 end_of_line (str);
9055 }
9056
9057 static void
9058 do_vfp_reg2_from_dp (str)
9059 char *str;
9060 {
9061 skip_whitespace (str);
9062
9063 if (reg_required_here (&str, 12) == FAIL)
9064 return;
9065
9066 if (skip_past_comma (&str) == FAIL
9067 || reg_required_here (&str, 16) == FAIL
9068 || skip_past_comma (&str) == FAIL
9069 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
9070 {
9071 if (! inst.error)
9072 inst.error = BAD_ARGS;
9073 return;
9074 }
9075
9076 end_of_line (str);
9077 }
9078
9079 static void
9080 do_vfp_dp_from_reg (str)
9081 char *str;
9082 {
9083 skip_whitespace (str);
9084
9085 if (vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL)
9086 return;
9087
9088 if (skip_past_comma (&str) == FAIL
9089 || reg_required_here (&str, 12) == FAIL)
9090 {
9091 if (! inst.error)
9092 inst.error = BAD_ARGS;
9093 return;
9094 }
9095
9096 end_of_line (str);
9097 }
9098
9099 static void
9100 do_vfp_dp_from_reg2 (str)
9101 char *str;
9102 {
9103 skip_whitespace (str);
9104
9105 if (vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
9106 return;
9107
9108 if (skip_past_comma (&str) == FAIL
9109 || reg_required_here (&str, 12) == FAIL
9110 || skip_past_comma (&str) == FAIL
9111 || reg_required_here (&str, 16) == FAIL)
9112 {
9113 if (! inst.error)
9114 inst.error = BAD_ARGS;
9115 return;
9116 }
9117
9118 end_of_line (str);
9119 }
9120
9121 static const struct vfp_reg *
9122 vfp_psr_parse (str)
9123 char **str;
9124 {
9125 char *start = *str;
9126 char c;
9127 char *p;
9128 const struct vfp_reg *vreg;
9129
9130 p = start;
9131
9132 /* Find the end of the current token. */
9133 do
9134 {
9135 c = *p++;
9136 }
9137 while (ISALPHA (c));
9138
9139 /* Mark it. */
9140 *--p = 0;
9141
9142 for (vreg = vfp_regs + 0;
9143 vreg < vfp_regs + sizeof (vfp_regs) / sizeof (struct vfp_reg);
9144 vreg++)
9145 {
9146 if (strcmp (start, vreg->name) == 0)
9147 {
9148 *p = c;
9149 *str = p;
9150 return vreg;
9151 }
9152 }
9153
9154 *p = c;
9155 return NULL;
9156 }
9157
9158 static int
9159 vfp_psr_required_here (str)
9160 char **str;
9161 {
9162 char *start = *str;
9163 const struct vfp_reg *vreg;
9164
9165 vreg = vfp_psr_parse (str);
9166
9167 if (vreg)
9168 {
9169 inst.instruction |= vreg->regno;
9170 return SUCCESS;
9171 }
9172
9173 inst.error = _("VFP system register expected");
9174
9175 *str = start;
9176 return FAIL;
9177 }
9178
9179 static void
9180 do_vfp_reg_from_ctrl (str)
9181 char *str;
9182 {
9183 skip_whitespace (str);
9184
9185 if (reg_required_here (&str, 12) == FAIL)
9186 return;
9187
9188 if (skip_past_comma (&str) == FAIL
9189 || vfp_psr_required_here (&str) == FAIL)
9190 {
9191 if (! inst.error)
9192 inst.error = BAD_ARGS;
9193 return;
9194 }
9195
9196 end_of_line (str);
9197 }
9198
9199 static void
9200 do_vfp_ctrl_from_reg (str)
9201 char *str;
9202 {
9203 skip_whitespace (str);
9204
9205 if (vfp_psr_required_here (&str) == FAIL)
9206 return;
9207
9208 if (skip_past_comma (&str) == FAIL
9209 || reg_required_here (&str, 12) == FAIL)
9210 {
9211 if (! inst.error)
9212 inst.error = BAD_ARGS;
9213 return;
9214 }
9215
9216 end_of_line (str);
9217 }
9218
9219 static void
9220 do_vfp_sp_ldst (str)
9221 char *str;
9222 {
9223 skip_whitespace (str);
9224
9225 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
9226 {
9227 if (!inst.error)
9228 inst.error = BAD_ARGS;
9229 return;
9230 }
9231
9232 if (skip_past_comma (&str) == FAIL
9233 || cp_address_required_here (&str, CP_NO_WB) == FAIL)
9234 {
9235 if (!inst.error)
9236 inst.error = BAD_ARGS;
9237 return;
9238 }
9239
9240 end_of_line (str);
9241 }
9242
9243 static void
9244 do_vfp_dp_ldst (str)
9245 char *str;
9246 {
9247 skip_whitespace (str);
9248
9249 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
9250 {
9251 if (!inst.error)
9252 inst.error = BAD_ARGS;
9253 return;
9254 }
9255
9256 if (skip_past_comma (&str) == FAIL
9257 || cp_address_required_here (&str, CP_NO_WB) == FAIL)
9258 {
9259 if (!inst.error)
9260 inst.error = BAD_ARGS;
9261 return;
9262 }
9263
9264 end_of_line (str);
9265 }
9266
9267 /* Parse and encode a VFP SP register list, storing the initial
9268 register in position POS and returning the range as the result. If
9269 the string is invalid return FAIL (an invalid range). */
9270 static long
9271 vfp_sp_reg_list (str, pos)
9272 char **str;
9273 enum vfp_sp_reg_pos pos;
9274 {
9275 long range = 0;
9276 int base_reg = 0;
9277 int new_base;
9278 long base_bits = 0;
9279 int count = 0;
9280 long tempinst;
9281 unsigned long mask = 0;
9282 int warned = 0;
9283
9284 if (**str != '{')
9285 return FAIL;
9286
9287 (*str)++;
9288 skip_whitespace (*str);
9289
9290 tempinst = inst.instruction;
9291
9292 do
9293 {
9294 inst.instruction = 0;
9295
9296 if ((new_base = vfp_sp_reg_required_here (str, pos)) == FAIL)
9297 return FAIL;
9298
9299 if (count == 0 || base_reg > new_base)
9300 {
9301 base_reg = new_base;
9302 base_bits = inst.instruction;
9303 }
9304
9305 if (mask & (1 << new_base))
9306 {
9307 inst.error = _("invalid register list");
9308 return FAIL;
9309 }
9310
9311 if ((mask >> new_base) != 0 && ! warned)
9312 {
9313 as_tsktsk (_("register list not in ascending order"));
9314 warned = 1;
9315 }
9316
9317 mask |= 1 << new_base;
9318 count++;
9319
9320 skip_whitespace (*str);
9321
9322 if (**str == '-') /* We have the start of a range expression */
9323 {
9324 int high_range;
9325
9326 (*str)++;
9327
9328 if ((high_range
9329 = arm_reg_parse (str, all_reg_maps[REG_TYPE_SN].htab))
9330 == FAIL)
9331 {
9332 inst.error = _(all_reg_maps[REG_TYPE_SN].expected);
9333 return FAIL;
9334 }
9335
9336 if (high_range <= new_base)
9337 {
9338 inst.error = _("register range not in ascending order");
9339 return FAIL;
9340 }
9341
9342 for (new_base++; new_base <= high_range; new_base++)
9343 {
9344 if (mask & (1 << new_base))
9345 {
9346 inst.error = _("invalid register list");
9347 return FAIL;
9348 }
9349
9350 mask |= 1 << new_base;
9351 count++;
9352 }
9353 }
9354 }
9355 while (skip_past_comma (str) != FAIL);
9356
9357 if (**str != '}')
9358 {
9359 inst.error = _("invalid register list");
9360 return FAIL;
9361 }
9362
9363 (*str)++;
9364
9365 range = count;
9366
9367 /* Sanity check -- should have raised a parse error above. */
9368 if (count == 0 || count > 32)
9369 abort ();
9370
9371 /* Final test -- the registers must be consecutive. */
9372 while (count--)
9373 {
9374 if ((mask & (1 << base_reg++)) == 0)
9375 {
9376 inst.error = _("non-contiguous register range");
9377 return FAIL;
9378 }
9379 }
9380
9381 inst.instruction = tempinst | base_bits;
9382 return range;
9383 }
9384
9385 static long
9386 vfp_dp_reg_list (str)
9387 char **str;
9388 {
9389 long range = 0;
9390 int base_reg = 0;
9391 int new_base;
9392 int count = 0;
9393 long tempinst;
9394 unsigned long mask = 0;
9395 int warned = 0;
9396
9397 if (**str != '{')
9398 return FAIL;
9399
9400 (*str)++;
9401 skip_whitespace (*str);
9402
9403 tempinst = inst.instruction;
9404
9405 do
9406 {
9407 inst.instruction = 0;
9408
9409 if ((new_base = vfp_dp_reg_required_here (str, VFP_REG_Dd)) == FAIL)
9410 return FAIL;
9411
9412 if (count == 0 || base_reg > new_base)
9413 {
9414 base_reg = new_base;
9415 range = inst.instruction;
9416 }
9417
9418 if (mask & (1 << new_base))
9419 {
9420 inst.error = _("invalid register list");
9421 return FAIL;
9422 }
9423
9424 if ((mask >> new_base) != 0 && ! warned)
9425 {
9426 as_tsktsk (_("register list not in ascending order"));
9427 warned = 1;
9428 }
9429
9430 mask |= 1 << new_base;
9431 count++;
9432
9433 skip_whitespace (*str);
9434
9435 if (**str == '-') /* We have the start of a range expression */
9436 {
9437 int high_range;
9438
9439 (*str)++;
9440
9441 if ((high_range
9442 = arm_reg_parse (str, all_reg_maps[REG_TYPE_DN].htab))
9443 == FAIL)
9444 {
9445 inst.error = _(all_reg_maps[REG_TYPE_DN].expected);
9446 return FAIL;
9447 }
9448
9449 if (high_range <= new_base)
9450 {
9451 inst.error = _("register range not in ascending order");
9452 return FAIL;
9453 }
9454
9455 for (new_base++; new_base <= high_range; new_base++)
9456 {
9457 if (mask & (1 << new_base))
9458 {
9459 inst.error = _("invalid register list");
9460 return FAIL;
9461 }
9462
9463 mask |= 1 << new_base;
9464 count++;
9465 }
9466 }
9467 }
9468 while (skip_past_comma (str) != FAIL);
9469
9470 if (**str != '}')
9471 {
9472 inst.error = _("invalid register list");
9473 return FAIL;
9474 }
9475
9476 (*str)++;
9477
9478 range |= 2 * count;
9479
9480 /* Sanity check -- should have raised a parse error above. */
9481 if (count == 0 || count > 16)
9482 abort ();
9483
9484 /* Final test -- the registers must be consecutive. */
9485 while (count--)
9486 {
9487 if ((mask & (1 << base_reg++)) == 0)
9488 {
9489 inst.error = _("non-contiguous register range");
9490 return FAIL;
9491 }
9492 }
9493
9494 inst.instruction = tempinst;
9495 return range;
9496 }
9497
9498 static void
9499 vfp_sp_ldstm (str, ldstm_type)
9500 char *str;
9501 enum vfp_ldstm_type ldstm_type;
9502 {
9503 long range;
9504
9505 skip_whitespace (str);
9506
9507 if (reg_required_here (&str, 16) == FAIL)
9508 return;
9509
9510 skip_whitespace (str);
9511
9512 if (*str == '!')
9513 {
9514 inst.instruction |= WRITE_BACK;
9515 str++;
9516 }
9517 else if (ldstm_type != VFP_LDSTMIA)
9518 {
9519 inst.error = _("this addressing mode requires base-register writeback");
9520 return;
9521 }
9522
9523 if (skip_past_comma (&str) == FAIL
9524 || (range = vfp_sp_reg_list (&str, VFP_REG_Sd)) == FAIL)
9525 {
9526 if (!inst.error)
9527 inst.error = BAD_ARGS;
9528 return;
9529 }
9530
9531 inst.instruction |= range;
9532 end_of_line (str);
9533 }
9534
9535 static void
9536 vfp_dp_ldstm (str, ldstm_type)
9537 char *str;
9538 enum vfp_ldstm_type ldstm_type;
9539 {
9540 long range;
9541
9542 skip_whitespace (str);
9543
9544 if (reg_required_here (&str, 16) == FAIL)
9545 return;
9546
9547 skip_whitespace (str);
9548
9549 if (*str == '!')
9550 {
9551 inst.instruction |= WRITE_BACK;
9552 str++;
9553 }
9554 else if (ldstm_type != VFP_LDSTMIA && ldstm_type != VFP_LDSTMIAX)
9555 {
9556 inst.error = _("this addressing mode requires base-register writeback");
9557 return;
9558 }
9559
9560 if (skip_past_comma (&str) == FAIL
9561 || (range = vfp_dp_reg_list (&str)) == FAIL)
9562 {
9563 if (!inst.error)
9564 inst.error = BAD_ARGS;
9565 return;
9566 }
9567
9568 if (ldstm_type == VFP_LDSTMIAX || ldstm_type == VFP_LDSTMDBX)
9569 range += 1;
9570
9571 inst.instruction |= range;
9572 end_of_line (str);
9573 }
9574
9575 static void
9576 do_vfp_sp_ldstmia (str)
9577 char *str;
9578 {
9579 vfp_sp_ldstm (str, VFP_LDSTMIA);
9580 }
9581
9582 static void
9583 do_vfp_sp_ldstmdb (str)
9584 char *str;
9585 {
9586 vfp_sp_ldstm (str, VFP_LDSTMDB);
9587 }
9588
9589 static void
9590 do_vfp_dp_ldstmia (str)
9591 char *str;
9592 {
9593 vfp_dp_ldstm (str, VFP_LDSTMIA);
9594 }
9595
9596 static void
9597 do_vfp_dp_ldstmdb (str)
9598 char *str;
9599 {
9600 vfp_dp_ldstm (str, VFP_LDSTMDB);
9601 }
9602
9603 static void
9604 do_vfp_xp_ldstmia (str)
9605 char *str;
9606 {
9607 vfp_dp_ldstm (str, VFP_LDSTMIAX);
9608 }
9609
9610 static void
9611 do_vfp_xp_ldstmdb (str)
9612 char *str;
9613 {
9614 vfp_dp_ldstm (str, VFP_LDSTMDBX);
9615 }
9616
9617 static void
9618 do_vfp_sp_compare_z (str)
9619 char *str;
9620 {
9621 skip_whitespace (str);
9622
9623 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
9624 {
9625 if (!inst.error)
9626 inst.error = BAD_ARGS;
9627 return;
9628 }
9629
9630 end_of_line (str);
9631 }
9632
9633 static void
9634 do_vfp_dp_compare_z (str)
9635 char *str;
9636 {
9637 skip_whitespace (str);
9638
9639 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
9640 {
9641 if (!inst.error)
9642 inst.error = BAD_ARGS;
9643 return;
9644 }
9645
9646 end_of_line (str);
9647 }
9648
9649 static void
9650 do_vfp_dp_sp_cvt (str)
9651 char *str;
9652 {
9653 skip_whitespace (str);
9654
9655 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
9656 return;
9657
9658 if (skip_past_comma (&str) == FAIL
9659 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
9660 {
9661 if (! inst.error)
9662 inst.error = BAD_ARGS;
9663 return;
9664 }
9665
9666 end_of_line (str);
9667 }
9668
9669 static void
9670 do_vfp_sp_dp_cvt (str)
9671 char *str;
9672 {
9673 skip_whitespace (str);
9674
9675 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
9676 return;
9677
9678 if (skip_past_comma (&str) == FAIL
9679 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
9680 {
9681 if (! inst.error)
9682 inst.error = BAD_ARGS;
9683 return;
9684 }
9685
9686 end_of_line (str);
9687 }
9688
9689 /* Thumb specific routines. */
9690
9691 /* Parse and validate that a register is of the right form, this saves
9692 repeated checking of this information in many similar cases.
9693 Unlike the 32-bit case we do not insert the register into the opcode
9694 here, since the position is often unknown until the full instruction
9695 has been parsed. */
9696
9697 static int
9698 thumb_reg (strp, hi_lo)
9699 char ** strp;
9700 int hi_lo;
9701 {
9702 int reg;
9703
9704 if ((reg = reg_required_here (strp, -1)) == FAIL)
9705 return FAIL;
9706
9707 switch (hi_lo)
9708 {
9709 case THUMB_REG_LO:
9710 if (reg > 7)
9711 {
9712 inst.error = _("lo register required");
9713 return FAIL;
9714 }
9715 break;
9716
9717 case THUMB_REG_HI:
9718 if (reg < 8)
9719 {
9720 inst.error = _("hi register required");
9721 return FAIL;
9722 }
9723 break;
9724
9725 default:
9726 break;
9727 }
9728
9729 return reg;
9730 }
9731
9732 /* Parse an add or subtract instruction, SUBTRACT is non-zero if the opcode
9733 was SUB. */
9734
9735 static void
9736 thumb_add_sub (str, subtract)
9737 char * str;
9738 int subtract;
9739 {
9740 int Rd, Rs, Rn = FAIL;
9741
9742 skip_whitespace (str);
9743
9744 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
9745 || skip_past_comma (&str) == FAIL)
9746 {
9747 if (! inst.error)
9748 inst.error = BAD_ARGS;
9749 return;
9750 }
9751
9752 if (is_immediate_prefix (*str))
9753 {
9754 Rs = Rd;
9755 str++;
9756 if (my_get_expression (&inst.reloc.exp, &str))
9757 return;
9758 }
9759 else
9760 {
9761 if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
9762 return;
9763
9764 if (skip_past_comma (&str) == FAIL)
9765 {
9766 /* Two operand format, shuffle the registers
9767 and pretend there are 3. */
9768 Rn = Rs;
9769 Rs = Rd;
9770 }
9771 else if (is_immediate_prefix (*str))
9772 {
9773 str++;
9774 if (my_get_expression (&inst.reloc.exp, &str))
9775 return;
9776 }
9777 else if ((Rn = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
9778 return;
9779 }
9780
9781 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
9782 for the latter case, EXPR contains the immediate that was found. */
9783 if (Rn != FAIL)
9784 {
9785 /* All register format. */
9786 if (Rd > 7 || Rs > 7 || Rn > 7)
9787 {
9788 if (Rs != Rd)
9789 {
9790 inst.error = _("dest and source1 must be the same register");
9791 return;
9792 }
9793
9794 /* Can't do this for SUB. */
9795 if (subtract)
9796 {
9797 inst.error = _("subtract valid only on lo regs");
9798 return;
9799 }
9800
9801 inst.instruction = (T_OPCODE_ADD_HI
9802 | (Rd > 7 ? THUMB_H1 : 0)
9803 | (Rn > 7 ? THUMB_H2 : 0));
9804 inst.instruction |= (Rd & 7) | ((Rn & 7) << 3);
9805 }
9806 else
9807 {
9808 inst.instruction = subtract ? T_OPCODE_SUB_R3 : T_OPCODE_ADD_R3;
9809 inst.instruction |= Rd | (Rs << 3) | (Rn << 6);
9810 }
9811 }
9812 else
9813 {
9814 /* Immediate expression, now things start to get nasty. */
9815
9816 /* First deal with HI regs, only very restricted cases allowed:
9817 Adjusting SP, and using PC or SP to get an address. */
9818 if ((Rd > 7 && (Rd != REG_SP || Rs != REG_SP))
9819 || (Rs > 7 && Rs != REG_SP && Rs != REG_PC))
9820 {
9821 inst.error = _("invalid Hi register with immediate");
9822 return;
9823 }
9824
9825 if (inst.reloc.exp.X_op != O_constant)
9826 {
9827 /* Value isn't known yet, all we can do is store all the fragments
9828 we know about in the instruction and let the reloc hacking
9829 work it all out. */
9830 inst.instruction = (subtract ? 0x8000 : 0) | (Rd << 4) | Rs;
9831 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
9832 }
9833 else
9834 {
9835 int offset = inst.reloc.exp.X_add_number;
9836
9837 if (subtract)
9838 offset = - offset;
9839
9840 if (offset < 0)
9841 {
9842 offset = - offset;
9843 subtract = 1;
9844
9845 /* Quick check, in case offset is MIN_INT. */
9846 if (offset < 0)
9847 {
9848 inst.error = _("immediate value out of range");
9849 return;
9850 }
9851 }
9852 /* Note - you cannot convert a subtract of 0 into an
9853 add of 0 because the carry flag is set differently. */
9854 else if (offset > 0)
9855 subtract = 0;
9856
9857 if (Rd == REG_SP)
9858 {
9859 if (offset & ~0x1fc)
9860 {
9861 inst.error = _("invalid immediate value for stack adjust");
9862 return;
9863 }
9864 inst.instruction = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
9865 inst.instruction |= offset >> 2;
9866 }
9867 else if (Rs == REG_PC || Rs == REG_SP)
9868 {
9869 if (subtract
9870 || (offset & ~0x3fc))
9871 {
9872 inst.error = _("invalid immediate for address calculation");
9873 return;
9874 }
9875 inst.instruction = (Rs == REG_PC ? T_OPCODE_ADD_PC
9876 : T_OPCODE_ADD_SP);
9877 inst.instruction |= (Rd << 8) | (offset >> 2);
9878 }
9879 else if (Rs == Rd)
9880 {
9881 if (offset & ~0xff)
9882 {
9883 inst.error = _("immediate value out of range");
9884 return;
9885 }
9886 inst.instruction = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
9887 inst.instruction |= (Rd << 8) | offset;
9888 }
9889 else
9890 {
9891 if (offset & ~0x7)
9892 {
9893 inst.error = _("immediate value out of range");
9894 return;
9895 }
9896 inst.instruction = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
9897 inst.instruction |= Rd | (Rs << 3) | (offset << 6);
9898 }
9899 }
9900 }
9901
9902 end_of_line (str);
9903 }
9904
9905 static void
9906 thumb_shift (str, shift)
9907 char * str;
9908 int shift;
9909 {
9910 int Rd, Rs, Rn = FAIL;
9911
9912 skip_whitespace (str);
9913
9914 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9915 || skip_past_comma (&str) == FAIL)
9916 {
9917 if (! inst.error)
9918 inst.error = BAD_ARGS;
9919 return;
9920 }
9921
9922 if (is_immediate_prefix (*str))
9923 {
9924 /* Two operand immediate format, set Rs to Rd. */
9925 Rs = Rd;
9926 str ++;
9927 if (my_get_expression (&inst.reloc.exp, &str))
9928 return;
9929 }
9930 else
9931 {
9932 if ((Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9933 return;
9934
9935 if (skip_past_comma (&str) == FAIL)
9936 {
9937 /* Two operand format, shuffle the registers
9938 and pretend there are 3. */
9939 Rn = Rs;
9940 Rs = Rd;
9941 }
9942 else if (is_immediate_prefix (*str))
9943 {
9944 str++;
9945 if (my_get_expression (&inst.reloc.exp, &str))
9946 return;
9947 }
9948 else if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9949 return;
9950 }
9951
9952 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
9953 for the latter case, EXPR contains the immediate that was found. */
9954
9955 if (Rn != FAIL)
9956 {
9957 if (Rs != Rd)
9958 {
9959 inst.error = _("source1 and dest must be same register");
9960 return;
9961 }
9962
9963 switch (shift)
9964 {
9965 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_R; break;
9966 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_R; break;
9967 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_R; break;
9968 }
9969
9970 inst.instruction |= Rd | (Rn << 3);
9971 }
9972 else
9973 {
9974 switch (shift)
9975 {
9976 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_I; break;
9977 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_I; break;
9978 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_I; break;
9979 }
9980
9981 if (inst.reloc.exp.X_op != O_constant)
9982 {
9983 /* Value isn't known yet, create a dummy reloc and let reloc
9984 hacking fix it up. */
9985 inst.reloc.type = BFD_RELOC_ARM_THUMB_SHIFT;
9986 }
9987 else
9988 {
9989 unsigned shift_value = inst.reloc.exp.X_add_number;
9990
9991 if (shift_value > 32 || (shift_value == 32 && shift == THUMB_LSL))
9992 {
9993 inst.error = _("invalid immediate for shift");
9994 return;
9995 }
9996
9997 /* Shifts of zero are handled by converting to LSL. */
9998 if (shift_value == 0)
9999 inst.instruction = T_OPCODE_LSL_I;
10000
10001 /* Shifts of 32 are encoded as a shift of zero. */
10002 if (shift_value == 32)
10003 shift_value = 0;
10004
10005 inst.instruction |= shift_value << 6;
10006 }
10007
10008 inst.instruction |= Rd | (Rs << 3);
10009 }
10010
10011 end_of_line (str);
10012 }
10013
10014 static void
10015 thumb_mov_compare (str, move)
10016 char * str;
10017 int move;
10018 {
10019 int Rd, Rs = FAIL;
10020
10021 skip_whitespace (str);
10022
10023 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
10024 || skip_past_comma (&str) == FAIL)
10025 {
10026 if (! inst.error)
10027 inst.error = BAD_ARGS;
10028 return;
10029 }
10030
10031 if (move != THUMB_CPY && is_immediate_prefix (*str))
10032 {
10033 str++;
10034 if (my_get_expression (&inst.reloc.exp, &str))
10035 return;
10036 }
10037 else if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
10038 return;
10039
10040 if (Rs != FAIL)
10041 {
10042 if (move != THUMB_CPY && Rs < 8 && Rd < 8)
10043 {
10044 if (move == THUMB_MOVE)
10045 /* A move of two lowregs is encoded as ADD Rd, Rs, #0
10046 since a MOV instruction produces unpredictable results. */
10047 inst.instruction = T_OPCODE_ADD_I3;
10048 else
10049 inst.instruction = T_OPCODE_CMP_LR;
10050 inst.instruction |= Rd | (Rs << 3);
10051 }
10052 else
10053 {
10054 if (move == THUMB_MOVE)
10055 inst.instruction = T_OPCODE_MOV_HR;
10056 else if (move != THUMB_CPY)
10057 inst.instruction = T_OPCODE_CMP_HR;
10058
10059 if (Rd > 7)
10060 inst.instruction |= THUMB_H1;
10061
10062 if (Rs > 7)
10063 inst.instruction |= THUMB_H2;
10064
10065 inst.instruction |= (Rd & 7) | ((Rs & 7) << 3);
10066 }
10067 }
10068 else
10069 {
10070 if (Rd > 7)
10071 {
10072 inst.error = _("only lo regs allowed with immediate");
10073 return;
10074 }
10075
10076 if (move == THUMB_MOVE)
10077 inst.instruction = T_OPCODE_MOV_I8;
10078 else
10079 inst.instruction = T_OPCODE_CMP_I8;
10080
10081 inst.instruction |= Rd << 8;
10082
10083 if (inst.reloc.exp.X_op != O_constant)
10084 inst.reloc.type = BFD_RELOC_ARM_THUMB_IMM;
10085 else
10086 {
10087 unsigned value = inst.reloc.exp.X_add_number;
10088
10089 if (value > 255)
10090 {
10091 inst.error = _("invalid immediate");
10092 return;
10093 }
10094
10095 inst.instruction |= value;
10096 }
10097 }
10098
10099 end_of_line (str);
10100 }
10101
10102 static void
10103 thumb_load_store (str, load_store, size)
10104 char * str;
10105 int load_store;
10106 int size;
10107 {
10108 int Rd, Rb, Ro = FAIL;
10109
10110 skip_whitespace (str);
10111
10112 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
10113 || skip_past_comma (&str) == FAIL)
10114 {
10115 if (! inst.error)
10116 inst.error = BAD_ARGS;
10117 return;
10118 }
10119
10120 if (*str == '[')
10121 {
10122 str++;
10123 if ((Rb = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
10124 return;
10125
10126 if (skip_past_comma (&str) != FAIL)
10127 {
10128 if (is_immediate_prefix (*str))
10129 {
10130 str++;
10131 if (my_get_expression (&inst.reloc.exp, &str))
10132 return;
10133 }
10134 else if ((Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
10135 return;
10136 }
10137 else
10138 {
10139 inst.reloc.exp.X_op = O_constant;
10140 inst.reloc.exp.X_add_number = 0;
10141 }
10142
10143 if (*str != ']')
10144 {
10145 inst.error = _("expected ']'");
10146 return;
10147 }
10148 str++;
10149 }
10150 else if (*str == '=')
10151 {
10152 if (load_store != THUMB_LOAD)
10153 {
10154 inst.error = _("invalid pseudo operation");
10155 return;
10156 }
10157
10158 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
10159 str++;
10160
10161 skip_whitespace (str);
10162
10163 if (my_get_expression (& inst.reloc.exp, & str))
10164 return;
10165
10166 end_of_line (str);
10167
10168 if ( inst.reloc.exp.X_op != O_constant
10169 && inst.reloc.exp.X_op != O_symbol)
10170 {
10171 inst.error = "Constant expression expected";
10172 return;
10173 }
10174
10175 if (inst.reloc.exp.X_op == O_constant
10176 && ((inst.reloc.exp.X_add_number & ~0xFF) == 0))
10177 {
10178 /* This can be done with a mov instruction. */
10179
10180 inst.instruction = T_OPCODE_MOV_I8 | (Rd << 8);
10181 inst.instruction |= inst.reloc.exp.X_add_number;
10182 return;
10183 }
10184
10185 /* Insert into literal pool. */
10186 if (add_to_lit_pool () == FAIL)
10187 {
10188 if (!inst.error)
10189 inst.error = "literal pool insertion failed";
10190 return;
10191 }
10192
10193 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
10194 inst.reloc.pc_rel = 1;
10195 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
10196 /* Adjust ARM pipeline offset to Thumb. */
10197 inst.reloc.exp.X_add_number += 4;
10198
10199 return;
10200 }
10201 else
10202 {
10203 if (my_get_expression (&inst.reloc.exp, &str))
10204 return;
10205
10206 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
10207 inst.reloc.pc_rel = 1;
10208 inst.reloc.exp.X_add_number -= 4; /* Pipeline offset. */
10209 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
10210 end_of_line (str);
10211 return;
10212 }
10213
10214 if (Rb == REG_PC || Rb == REG_SP)
10215 {
10216 if (size != THUMB_WORD)
10217 {
10218 inst.error = _("byte or halfword not valid for base register");
10219 return;
10220 }
10221 else if (Rb == REG_PC && load_store != THUMB_LOAD)
10222 {
10223 inst.error = _("r15 based store not allowed");
10224 return;
10225 }
10226 else if (Ro != FAIL)
10227 {
10228 inst.error = _("invalid base register for register offset");
10229 return;
10230 }
10231
10232 if (Rb == REG_PC)
10233 inst.instruction = T_OPCODE_LDR_PC;
10234 else if (load_store == THUMB_LOAD)
10235 inst.instruction = T_OPCODE_LDR_SP;
10236 else
10237 inst.instruction = T_OPCODE_STR_SP;
10238
10239 inst.instruction |= Rd << 8;
10240 if (inst.reloc.exp.X_op == O_constant)
10241 {
10242 unsigned offset = inst.reloc.exp.X_add_number;
10243
10244 if (offset & ~0x3fc)
10245 {
10246 inst.error = _("invalid offset");
10247 return;
10248 }
10249
10250 inst.instruction |= offset >> 2;
10251 }
10252 else
10253 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
10254 }
10255 else if (Rb > 7)
10256 {
10257 inst.error = _("invalid base register in load/store");
10258 return;
10259 }
10260 else if (Ro == FAIL)
10261 {
10262 /* Immediate offset. */
10263 if (size == THUMB_WORD)
10264 inst.instruction = (load_store == THUMB_LOAD
10265 ? T_OPCODE_LDR_IW : T_OPCODE_STR_IW);
10266 else if (size == THUMB_HALFWORD)
10267 inst.instruction = (load_store == THUMB_LOAD
10268 ? T_OPCODE_LDR_IH : T_OPCODE_STR_IH);
10269 else
10270 inst.instruction = (load_store == THUMB_LOAD
10271 ? T_OPCODE_LDR_IB : T_OPCODE_STR_IB);
10272
10273 inst.instruction |= Rd | (Rb << 3);
10274
10275 if (inst.reloc.exp.X_op == O_constant)
10276 {
10277 unsigned offset = inst.reloc.exp.X_add_number;
10278
10279 if (offset & ~(0x1f << size))
10280 {
10281 inst.error = _("invalid offset");
10282 return;
10283 }
10284 inst.instruction |= (offset >> size) << 6;
10285 }
10286 else
10287 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
10288 }
10289 else
10290 {
10291 /* Register offset. */
10292 if (size == THUMB_WORD)
10293 inst.instruction = (load_store == THUMB_LOAD
10294 ? T_OPCODE_LDR_RW : T_OPCODE_STR_RW);
10295 else if (size == THUMB_HALFWORD)
10296 inst.instruction = (load_store == THUMB_LOAD
10297 ? T_OPCODE_LDR_RH : T_OPCODE_STR_RH);
10298 else
10299 inst.instruction = (load_store == THUMB_LOAD
10300 ? T_OPCODE_LDR_RB : T_OPCODE_STR_RB);
10301
10302 inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
10303 }
10304
10305 end_of_line (str);
10306 }
10307
10308 /* A register must be given at this point.
10309
10310 Shift is the place to put it in inst.instruction.
10311
10312 Restores input start point on err.
10313 Returns the reg#, or FAIL. */
10314
10315 static int
10316 mav_reg_required_here (str, shift, regtype)
10317 char ** str;
10318 int shift;
10319 enum arm_reg_type regtype;
10320 {
10321 int reg;
10322 char *start = *str;
10323
10324 if ((reg = arm_reg_parse (str, all_reg_maps[regtype].htab)) != FAIL)
10325 {
10326 if (shift >= 0)
10327 inst.instruction |= reg << shift;
10328
10329 return reg;
10330 }
10331
10332 /* Restore the start point. */
10333 *str = start;
10334
10335 /* In the few cases where we might be able to accept something else
10336 this error can be overridden. */
10337 inst.error = _(all_reg_maps[regtype].expected);
10338
10339 return FAIL;
10340 }
10341
10342 /* Cirrus Maverick Instructions. */
10343
10344 /* Wrapper functions. */
10345
10346 static void
10347 do_mav_binops_1a (str)
10348 char * str;
10349 {
10350 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVF);
10351 }
10352
10353 static void
10354 do_mav_binops_1b (str)
10355 char * str;
10356 {
10357 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVD);
10358 }
10359
10360 static void
10361 do_mav_binops_1c (str)
10362 char * str;
10363 {
10364 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVDX);
10365 }
10366
10367 static void
10368 do_mav_binops_1d (str)
10369 char * str;
10370 {
10371 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVF);
10372 }
10373
10374 static void
10375 do_mav_binops_1e (str)
10376 char * str;
10377 {
10378 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVD);
10379 }
10380
10381 static void
10382 do_mav_binops_1f (str)
10383 char * str;
10384 {
10385 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVF);
10386 }
10387
10388 static void
10389 do_mav_binops_1g (str)
10390 char * str;
10391 {
10392 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVD);
10393 }
10394
10395 static void
10396 do_mav_binops_1h (str)
10397 char * str;
10398 {
10399 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVFX);
10400 }
10401
10402 static void
10403 do_mav_binops_1i (str)
10404 char * str;
10405 {
10406 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVFX);
10407 }
10408
10409 static void
10410 do_mav_binops_1j (str)
10411 char * str;
10412 {
10413 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVDX);
10414 }
10415
10416 static void
10417 do_mav_binops_1k (str)
10418 char * str;
10419 {
10420 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVDX);
10421 }
10422
10423 static void
10424 do_mav_binops_1l (str)
10425 char * str;
10426 {
10427 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVF);
10428 }
10429
10430 static void
10431 do_mav_binops_1m (str)
10432 char * str;
10433 {
10434 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVD);
10435 }
10436
10437 static void
10438 do_mav_binops_1n (str)
10439 char * str;
10440 {
10441 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVFX);
10442 }
10443
10444 static void
10445 do_mav_binops_1o (str)
10446 char * str;
10447 {
10448 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVDX, REG_TYPE_MVDX);
10449 }
10450
10451 static void
10452 do_mav_binops_2a (str)
10453 char * str;
10454 {
10455 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVF, REG_TYPE_RN);
10456 }
10457
10458 static void
10459 do_mav_binops_2b (str)
10460 char * str;
10461 {
10462 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVD, REG_TYPE_RN);
10463 }
10464
10465 static void
10466 do_mav_binops_2c (str)
10467 char * str;
10468 {
10469 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVDX, REG_TYPE_RN);
10470 }
10471
10472 static void
10473 do_mav_binops_3a (str)
10474 char * str;
10475 {
10476 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVAX, REG_TYPE_MVFX);
10477 }
10478
10479 static void
10480 do_mav_binops_3b (str)
10481 char * str;
10482 {
10483 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVFX, REG_TYPE_MVAX);
10484 }
10485
10486 static void
10487 do_mav_binops_3c (str)
10488 char * str;
10489 {
10490 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVAX, REG_TYPE_MVDX);
10491 }
10492
10493 static void
10494 do_mav_binops_3d (str)
10495 char * str;
10496 {
10497 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVDX, REG_TYPE_MVAX);
10498 }
10499
10500 static void
10501 do_mav_triple_4a (str)
10502 char * str;
10503 {
10504 do_mav_triple (str, MAV_MODE4, REG_TYPE_MVFX, REG_TYPE_MVFX, REG_TYPE_RN);
10505 }
10506
10507 static void
10508 do_mav_triple_4b (str)
10509 char * str;
10510 {
10511 do_mav_triple (str, MAV_MODE4, REG_TYPE_MVDX, REG_TYPE_MVDX, REG_TYPE_RN);
10512 }
10513
10514 static void
10515 do_mav_triple_5a (str)
10516 char * str;
10517 {
10518 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVF, REG_TYPE_MVF);
10519 }
10520
10521 static void
10522 do_mav_triple_5b (str)
10523 char * str;
10524 {
10525 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVD, REG_TYPE_MVD);
10526 }
10527
10528 static void
10529 do_mav_triple_5c (str)
10530 char * str;
10531 {
10532 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVFX, REG_TYPE_MVFX);
10533 }
10534
10535 static void
10536 do_mav_triple_5d (str)
10537 char * str;
10538 {
10539 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVDX, REG_TYPE_MVDX);
10540 }
10541
10542 static void
10543 do_mav_triple_5e (str)
10544 char * str;
10545 {
10546 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVF, REG_TYPE_MVF, REG_TYPE_MVF);
10547 }
10548
10549 static void
10550 do_mav_triple_5f (str)
10551 char * str;
10552 {
10553 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVD, REG_TYPE_MVD, REG_TYPE_MVD);
10554 }
10555
10556 static void
10557 do_mav_triple_5g (str)
10558 char * str;
10559 {
10560 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVFX, REG_TYPE_MVFX, REG_TYPE_MVFX);
10561 }
10562
10563 static void
10564 do_mav_triple_5h (str)
10565 char * str;
10566 {
10567 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVDX, REG_TYPE_MVDX, REG_TYPE_MVDX);
10568 }
10569
10570 static void
10571 do_mav_quad_6a (str)
10572 char * str;
10573 {
10574 do_mav_quad (str, MAV_MODE6, REG_TYPE_MVAX, REG_TYPE_MVFX, REG_TYPE_MVFX,
10575 REG_TYPE_MVFX);
10576 }
10577
10578 static void
10579 do_mav_quad_6b (str)
10580 char * str;
10581 {
10582 do_mav_quad (str, MAV_MODE6, REG_TYPE_MVAX, REG_TYPE_MVAX, REG_TYPE_MVFX,
10583 REG_TYPE_MVFX);
10584 }
10585
10586 /* cfmvsc32<cond> DSPSC,MVDX[15:0]. */
10587 static void
10588 do_mav_dspsc_1 (str)
10589 char * str;
10590 {
10591 skip_whitespace (str);
10592
10593 /* cfmvsc32. */
10594 if (mav_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL
10595 || skip_past_comma (&str) == FAIL
10596 || mav_reg_required_here (&str, 12, REG_TYPE_MVDX) == FAIL)
10597 {
10598 if (!inst.error)
10599 inst.error = BAD_ARGS;
10600
10601 return;
10602 }
10603
10604 end_of_line (str);
10605 }
10606
10607 /* cfmv32sc<cond> MVDX[15:0],DSPSC. */
10608 static void
10609 do_mav_dspsc_2 (str)
10610 char * str;
10611 {
10612 skip_whitespace (str);
10613
10614 /* cfmv32sc. */
10615 if (mav_reg_required_here (&str, 12, REG_TYPE_MVDX) == FAIL
10616 || skip_past_comma (&str) == FAIL
10617 || mav_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL)
10618 {
10619 if (!inst.error)
10620 inst.error = BAD_ARGS;
10621
10622 return;
10623 }
10624
10625 end_of_line (str);
10626 }
10627
10628 static void
10629 do_mav_shift_1 (str)
10630 char * str;
10631 {
10632 do_mav_shift (str, REG_TYPE_MVFX, REG_TYPE_MVFX);
10633 }
10634
10635 static void
10636 do_mav_shift_2 (str)
10637 char * str;
10638 {
10639 do_mav_shift (str, REG_TYPE_MVDX, REG_TYPE_MVDX);
10640 }
10641
10642 static void
10643 do_mav_ldst_1 (str)
10644 char * str;
10645 {
10646 do_mav_ldst (str, REG_TYPE_MVF);
10647 }
10648
10649 static void
10650 do_mav_ldst_2 (str)
10651 char * str;
10652 {
10653 do_mav_ldst (str, REG_TYPE_MVD);
10654 }
10655
10656 static void
10657 do_mav_ldst_3 (str)
10658 char * str;
10659 {
10660 do_mav_ldst (str, REG_TYPE_MVFX);
10661 }
10662
10663 static void
10664 do_mav_ldst_4 (str)
10665 char * str;
10666 {
10667 do_mav_ldst (str, REG_TYPE_MVDX);
10668 }
10669
10670 /* Isnsn like "foo X,Y". */
10671
10672 static void
10673 do_mav_binops (str, mode, reg0, reg1)
10674 char * str;
10675 int mode;
10676 enum arm_reg_type reg0;
10677 enum arm_reg_type reg1;
10678 {
10679 int shift0, shift1;
10680
10681 shift0 = mode & 0xff;
10682 shift1 = (mode >> 8) & 0xff;
10683
10684 skip_whitespace (str);
10685
10686 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
10687 || skip_past_comma (&str) == FAIL
10688 || mav_reg_required_here (&str, shift1, reg1) == FAIL)
10689 {
10690 if (!inst.error)
10691 inst.error = BAD_ARGS;
10692 }
10693 else
10694 end_of_line (str);
10695 }
10696
10697 /* Isnsn like "foo X,Y,Z". */
10698
10699 static void
10700 do_mav_triple (str, mode, reg0, reg1, reg2)
10701 char * str;
10702 int mode;
10703 enum arm_reg_type reg0;
10704 enum arm_reg_type reg1;
10705 enum arm_reg_type reg2;
10706 {
10707 int shift0, shift1, shift2;
10708
10709 shift0 = mode & 0xff;
10710 shift1 = (mode >> 8) & 0xff;
10711 shift2 = (mode >> 16) & 0xff;
10712
10713 skip_whitespace (str);
10714
10715 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
10716 || skip_past_comma (&str) == FAIL
10717 || mav_reg_required_here (&str, shift1, reg1) == FAIL
10718 || skip_past_comma (&str) == FAIL
10719 || mav_reg_required_here (&str, shift2, reg2) == FAIL)
10720 {
10721 if (!inst.error)
10722 inst.error = BAD_ARGS;
10723 }
10724 else
10725 end_of_line (str);
10726 }
10727
10728 /* Isnsn like "foo W,X,Y,Z".
10729 where W=MVAX[0:3] and X,Y,Z=MVFX[0:15]. */
10730
10731 static void
10732 do_mav_quad (str, mode, reg0, reg1, reg2, reg3)
10733 char * str;
10734 int mode;
10735 enum arm_reg_type reg0;
10736 enum arm_reg_type reg1;
10737 enum arm_reg_type reg2;
10738 enum arm_reg_type reg3;
10739 {
10740 int shift0, shift1, shift2, shift3;
10741
10742 shift0= mode & 0xff;
10743 shift1 = (mode >> 8) & 0xff;
10744 shift2 = (mode >> 16) & 0xff;
10745 shift3 = (mode >> 24) & 0xff;
10746
10747 skip_whitespace (str);
10748
10749 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
10750 || skip_past_comma (&str) == FAIL
10751 || mav_reg_required_here (&str, shift1, reg1) == FAIL
10752 || skip_past_comma (&str) == FAIL
10753 || mav_reg_required_here (&str, shift2, reg2) == FAIL
10754 || skip_past_comma (&str) == FAIL
10755 || mav_reg_required_here (&str, shift3, reg3) == FAIL)
10756 {
10757 if (!inst.error)
10758 inst.error = BAD_ARGS;
10759 }
10760 else
10761 end_of_line (str);
10762 }
10763
10764 /* Maverick shift immediate instructions.
10765 cfsh32<cond> MVFX[15:0],MVFX[15:0],Shift[6:0].
10766 cfsh64<cond> MVDX[15:0],MVDX[15:0],Shift[6:0]. */
10767
10768 static void
10769 do_mav_shift (str, reg0, reg1)
10770 char * str;
10771 enum arm_reg_type reg0;
10772 enum arm_reg_type reg1;
10773 {
10774 int error;
10775 int imm, neg = 0;
10776
10777 skip_whitespace (str);
10778
10779 error = 0;
10780
10781 if (mav_reg_required_here (&str, 12, reg0) == FAIL
10782 || skip_past_comma (&str) == FAIL
10783 || mav_reg_required_here (&str, 16, reg1) == FAIL
10784 || skip_past_comma (&str) == FAIL)
10785 {
10786 if (!inst.error)
10787 inst.error = BAD_ARGS;
10788 return;
10789 }
10790
10791 /* Calculate the immediate operand.
10792 The operand is a 7bit signed number. */
10793 skip_whitespace (str);
10794
10795 if (*str == '#')
10796 ++str;
10797
10798 if (!ISDIGIT (*str) && *str != '-')
10799 {
10800 inst.error = _("expecting immediate, 7bit operand");
10801 return;
10802 }
10803
10804 if (*str == '-')
10805 {
10806 neg = 1;
10807 ++str;
10808 }
10809
10810 for (imm = 0; *str && ISDIGIT (*str); ++str)
10811 imm = imm * 10 + *str - '0';
10812
10813 if (imm > 64)
10814 {
10815 inst.error = _("immediate out of range");
10816 return;
10817 }
10818
10819 /* Make negative imm's into 7bit signed numbers. */
10820 if (neg)
10821 {
10822 imm = -imm;
10823 imm &= 0x0000007f;
10824 }
10825
10826 /* Bits 0-3 of the insn should have bits 0-3 of the immediate.
10827 Bits 5-7 of the insn should have bits 4-6 of the immediate.
10828 Bit 4 should be 0. */
10829 imm = (imm & 0xf) | ((imm & 0x70) << 1);
10830
10831 inst.instruction |= imm;
10832 end_of_line (str);
10833 }
10834
10835 static int
10836 mav_parse_offset (str, negative)
10837 char ** str;
10838 int *negative;
10839 {
10840 char * p = *str;
10841 int offset;
10842
10843 *negative = 0;
10844
10845 skip_whitespace (p);
10846
10847 if (*p == '#')
10848 ++p;
10849
10850 if (*p == '-')
10851 {
10852 *negative = 1;
10853 ++p;
10854 }
10855
10856 if (!ISDIGIT (*p))
10857 {
10858 inst.error = _("offset expected");
10859 return 0;
10860 }
10861
10862 for (offset = 0; *p && ISDIGIT (*p); ++p)
10863 offset = offset * 10 + *p - '0';
10864
10865 if (offset > 0xff)
10866 {
10867 inst.error = _("offset out of range");
10868 return 0;
10869 }
10870
10871 *str = p;
10872
10873 return *negative ? -offset : offset;
10874 }
10875
10876 /* Maverick load/store instructions.
10877 <insn><cond> CRd,[Rn,<offset>]{!}.
10878 <insn><cond> CRd,[Rn],<offset>. */
10879
10880 static void
10881 do_mav_ldst (str, reg0)
10882 char * str;
10883 enum arm_reg_type reg0;
10884 {
10885 int offset, negative;
10886
10887 skip_whitespace (str);
10888
10889 if (mav_reg_required_here (&str, 12, reg0) == FAIL
10890 || skip_past_comma (&str) == FAIL
10891 || *str++ != '['
10892 || reg_required_here (&str, 16) == FAIL)
10893 goto fail_ldst;
10894
10895 if (skip_past_comma (&str) == SUCCESS)
10896 {
10897 /* You are here: "<offset>]{!}". */
10898 inst.instruction |= PRE_INDEX;
10899
10900 offset = mav_parse_offset (&str, &negative);
10901
10902 if (inst.error)
10903 return;
10904
10905 if (*str++ != ']')
10906 {
10907 inst.error = _("missing ]");
10908 return;
10909 }
10910
10911 if (*str == '!')
10912 {
10913 inst.instruction |= WRITE_BACK;
10914 ++str;
10915 }
10916 }
10917 else
10918 {
10919 /* You are here: "], <offset>". */
10920 if (*str++ != ']')
10921 {
10922 inst.error = _("missing ]");
10923 return;
10924 }
10925
10926 if (skip_past_comma (&str) == FAIL
10927 || (offset = mav_parse_offset (&str, &negative), inst.error))
10928 goto fail_ldst;
10929
10930 inst.instruction |= CP_T_WB; /* Post indexed, set bit W. */
10931 }
10932
10933 if (negative)
10934 offset = -offset;
10935 else
10936 inst.instruction |= CP_T_UD; /* Positive, so set bit U. */
10937
10938 inst.instruction |= offset >> 2;
10939 end_of_line (str);
10940 return;
10941
10942 fail_ldst:
10943 if (!inst.error)
10944 inst.error = BAD_ARGS;
10945 }
10946
10947 static void
10948 do_t_nop (str)
10949 char * str;
10950 {
10951 /* Do nothing. */
10952 end_of_line (str);
10953 }
10954
10955 /* Handle the Format 4 instructions that do not have equivalents in other
10956 formats. That is, ADC, AND, EOR, SBC, ROR, TST, NEG, CMN, ORR, MUL,
10957 BIC and MVN. */
10958
10959 static void
10960 do_t_arit (str)
10961 char * str;
10962 {
10963 int Rd, Rs, Rn;
10964
10965 skip_whitespace (str);
10966
10967 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
10968 || skip_past_comma (&str) == FAIL
10969 || (Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
10970 {
10971 inst.error = BAD_ARGS;
10972 return;
10973 }
10974
10975 if (skip_past_comma (&str) != FAIL)
10976 {
10977 /* Three operand format not allowed for TST, CMN, NEG and MVN.
10978 (It isn't allowed for CMP either, but that isn't handled by this
10979 function.) */
10980 if (inst.instruction == T_OPCODE_TST
10981 || inst.instruction == T_OPCODE_CMN
10982 || inst.instruction == T_OPCODE_NEG
10983 || inst.instruction == T_OPCODE_MVN)
10984 {
10985 inst.error = BAD_ARGS;
10986 return;
10987 }
10988
10989 if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
10990 return;
10991
10992 if (Rs != Rd)
10993 {
10994 inst.error = _("dest and source1 must be the same register");
10995 return;
10996 }
10997 Rs = Rn;
10998 }
10999
11000 if (inst.instruction == T_OPCODE_MUL
11001 && Rs == Rd)
11002 as_tsktsk (_("Rs and Rd must be different in MUL"));
11003
11004 inst.instruction |= Rd | (Rs << 3);
11005 end_of_line (str);
11006 }
11007
11008 static void
11009 do_t_add (str)
11010 char * str;
11011 {
11012 thumb_add_sub (str, 0);
11013 }
11014
11015 static void
11016 do_t_asr (str)
11017 char * str;
11018 {
11019 thumb_shift (str, THUMB_ASR);
11020 }
11021
11022 static void
11023 do_t_branch9 (str)
11024 char * str;
11025 {
11026 if (my_get_expression (&inst.reloc.exp, &str))
11027 return;
11028 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH9;
11029 inst.reloc.pc_rel = 1;
11030 end_of_line (str);
11031 }
11032
11033 static void
11034 do_t_branch12 (str)
11035 char * str;
11036 {
11037 if (my_get_expression (&inst.reloc.exp, &str))
11038 return;
11039 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH12;
11040 inst.reloc.pc_rel = 1;
11041 end_of_line (str);
11042 }
11043
11044 /* Find the real, Thumb encoded start of a Thumb function. */
11045
11046 static symbolS *
11047 find_real_start (symbolP)
11048 symbolS * symbolP;
11049 {
11050 char * real_start;
11051 const char * name = S_GET_NAME (symbolP);
11052 symbolS * new_target;
11053
11054 /* This definition must agree with the one in gcc/config/arm/thumb.c. */
11055 #define STUB_NAME ".real_start_of"
11056
11057 if (name == NULL)
11058 abort ();
11059
11060 /* Names that start with '.' are local labels, not function entry points.
11061 The compiler may generate BL instructions to these labels because it
11062 needs to perform a branch to a far away location. */
11063 if (name[0] == '.')
11064 return symbolP;
11065
11066 real_start = malloc (strlen (name) + strlen (STUB_NAME) + 1);
11067 sprintf (real_start, "%s%s", STUB_NAME, name);
11068
11069 new_target = symbol_find (real_start);
11070
11071 if (new_target == NULL)
11072 {
11073 as_warn ("Failed to find real start of function: %s\n", name);
11074 new_target = symbolP;
11075 }
11076
11077 free (real_start);
11078
11079 return new_target;
11080 }
11081
11082 static void
11083 do_t_branch23 (str)
11084 char * str;
11085 {
11086 if (my_get_expression (& inst.reloc.exp, & str))
11087 return;
11088
11089 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH23;
11090 inst.reloc.pc_rel = 1;
11091 end_of_line (str);
11092
11093 /* If the destination of the branch is a defined symbol which does not have
11094 the THUMB_FUNC attribute, then we must be calling a function which has
11095 the (interfacearm) attribute. We look for the Thumb entry point to that
11096 function and change the branch to refer to that function instead. */
11097 if ( inst.reloc.exp.X_op == O_symbol
11098 && inst.reloc.exp.X_add_symbol != NULL
11099 && S_IS_DEFINED (inst.reloc.exp.X_add_symbol)
11100 && ! THUMB_IS_FUNC (inst.reloc.exp.X_add_symbol))
11101 inst.reloc.exp.X_add_symbol =
11102 find_real_start (inst.reloc.exp.X_add_symbol);
11103 }
11104
11105 static void
11106 do_t_bx (str)
11107 char * str;
11108 {
11109 int reg;
11110
11111 skip_whitespace (str);
11112
11113 if ((reg = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
11114 return;
11115
11116 /* This sets THUMB_H2 from the top bit of reg. */
11117 inst.instruction |= reg << 3;
11118
11119 /* ??? FIXME: Should add a hacky reloc here if reg is REG_PC. The reloc
11120 should cause the alignment to be checked once it is known. This is
11121 because BX PC only works if the instruction is word aligned. */
11122
11123 end_of_line (str);
11124 }
11125
11126 static void
11127 do_t_compare (str)
11128 char * str;
11129 {
11130 thumb_mov_compare (str, THUMB_COMPARE);
11131 }
11132
11133 static void
11134 do_t_ldmstm (str)
11135 char * str;
11136 {
11137 int Rb;
11138 long range;
11139
11140 skip_whitespace (str);
11141
11142 if ((Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
11143 return;
11144
11145 if (*str != '!')
11146 as_warn (_("inserted missing '!': load/store multiple always writes back base register"));
11147 else
11148 str++;
11149
11150 if (skip_past_comma (&str) == FAIL
11151 || (range = reg_list (&str)) == FAIL)
11152 {
11153 if (! inst.error)
11154 inst.error = BAD_ARGS;
11155 return;
11156 }
11157
11158 if (inst.reloc.type != BFD_RELOC_NONE)
11159 {
11160 /* This really doesn't seem worth it. */
11161 inst.reloc.type = BFD_RELOC_NONE;
11162 inst.error = _("expression too complex");
11163 return;
11164 }
11165
11166 if (range & ~0xff)
11167 {
11168 inst.error = _("only lo-regs valid in load/store multiple");
11169 return;
11170 }
11171
11172 inst.instruction |= (Rb << 8) | range;
11173 end_of_line (str);
11174 }
11175
11176 static void
11177 do_t_ldr (str)
11178 char * str;
11179 {
11180 thumb_load_store (str, THUMB_LOAD, THUMB_WORD);
11181 }
11182
11183 static void
11184 do_t_ldrb (str)
11185 char * str;
11186 {
11187 thumb_load_store (str, THUMB_LOAD, THUMB_BYTE);
11188 }
11189
11190 static void
11191 do_t_ldrh (str)
11192 char * str;
11193 {
11194 thumb_load_store (str, THUMB_LOAD, THUMB_HALFWORD);
11195 }
11196
11197 static void
11198 do_t_lds (str)
11199 char * str;
11200 {
11201 int Rd, Rb, Ro;
11202
11203 skip_whitespace (str);
11204
11205 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
11206 || skip_past_comma (&str) == FAIL
11207 || *str++ != '['
11208 || (Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL
11209 || skip_past_comma (&str) == FAIL
11210 || (Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL
11211 || *str++ != ']')
11212 {
11213 if (! inst.error)
11214 inst.error = _("syntax: ldrs[b] Rd, [Rb, Ro]");
11215 return;
11216 }
11217
11218 inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
11219 end_of_line (str);
11220 }
11221
11222 static void
11223 do_t_lsl (str)
11224 char * str;
11225 {
11226 thumb_shift (str, THUMB_LSL);
11227 }
11228
11229 static void
11230 do_t_lsr (str)
11231 char * str;
11232 {
11233 thumb_shift (str, THUMB_LSR);
11234 }
11235
11236 static void
11237 do_t_mov (str)
11238 char * str;
11239 {
11240 thumb_mov_compare (str, THUMB_MOVE);
11241 }
11242
11243 static void
11244 do_t_push_pop (str)
11245 char * str;
11246 {
11247 long range;
11248
11249 skip_whitespace (str);
11250
11251 if ((range = reg_list (&str)) == FAIL)
11252 {
11253 if (! inst.error)
11254 inst.error = BAD_ARGS;
11255 return;
11256 }
11257
11258 if (inst.reloc.type != BFD_RELOC_NONE)
11259 {
11260 /* This really doesn't seem worth it. */
11261 inst.reloc.type = BFD_RELOC_NONE;
11262 inst.error = _("expression too complex");
11263 return;
11264 }
11265
11266 if (range & ~0xff)
11267 {
11268 if ((inst.instruction == T_OPCODE_PUSH
11269 && (range & ~0xff) == 1 << REG_LR)
11270 || (inst.instruction == T_OPCODE_POP
11271 && (range & ~0xff) == 1 << REG_PC))
11272 {
11273 inst.instruction |= THUMB_PP_PC_LR;
11274 range &= 0xff;
11275 }
11276 else
11277 {
11278 inst.error = _("invalid register list to push/pop instruction");
11279 return;
11280 }
11281 }
11282
11283 inst.instruction |= range;
11284 end_of_line (str);
11285 }
11286
11287 static void
11288 do_t_str (str)
11289 char * str;
11290 {
11291 thumb_load_store (str, THUMB_STORE, THUMB_WORD);
11292 }
11293
11294 static void
11295 do_t_strb (str)
11296 char * str;
11297 {
11298 thumb_load_store (str, THUMB_STORE, THUMB_BYTE);
11299 }
11300
11301 static void
11302 do_t_strh (str)
11303 char * str;
11304 {
11305 thumb_load_store (str, THUMB_STORE, THUMB_HALFWORD);
11306 }
11307
11308 static void
11309 do_t_sub (str)
11310 char * str;
11311 {
11312 thumb_add_sub (str, 1);
11313 }
11314
11315 static void
11316 do_t_swi (str)
11317 char * str;
11318 {
11319 skip_whitespace (str);
11320
11321 if (my_get_expression (&inst.reloc.exp, &str))
11322 return;
11323
11324 inst.reloc.type = BFD_RELOC_ARM_SWI;
11325 end_of_line (str);
11326 }
11327
11328 static void
11329 do_t_adr (str)
11330 char * str;
11331 {
11332 int reg;
11333
11334 /* This is a pseudo-op of the form "adr rd, label" to be converted
11335 into a relative address of the form "add rd, pc, #label-.-4". */
11336 skip_whitespace (str);
11337
11338 /* Store Rd in temporary location inside instruction. */
11339 if ((reg = reg_required_here (&str, 4)) == FAIL
11340 || (reg > 7) /* For Thumb reg must be r0..r7. */
11341 || skip_past_comma (&str) == FAIL
11342 || my_get_expression (&inst.reloc.exp, &str))
11343 {
11344 if (!inst.error)
11345 inst.error = BAD_ARGS;
11346 return;
11347 }
11348
11349 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
11350 inst.reloc.exp.X_add_number -= 4; /* PC relative adjust. */
11351 inst.reloc.pc_rel = 1;
11352 inst.instruction |= REG_PC; /* Rd is already placed into the instruction. */
11353
11354 end_of_line (str);
11355 }
11356
11357 static void
11358 insert_reg (r, htab)
11359 const struct reg_entry *r;
11360 struct hash_control *htab;
11361 {
11362 int len = strlen (r->name) + 2;
11363 char * buf = (char *) xmalloc (len);
11364 char * buf2 = (char *) xmalloc (len);
11365 int i = 0;
11366
11367 #ifdef REGISTER_PREFIX
11368 buf[i++] = REGISTER_PREFIX;
11369 #endif
11370
11371 strcpy (buf + i, r->name);
11372
11373 for (i = 0; buf[i]; i++)
11374 buf2[i] = TOUPPER (buf[i]);
11375
11376 buf2[i] = '\0';
11377
11378 hash_insert (htab, buf, (PTR) r);
11379 hash_insert (htab, buf2, (PTR) r);
11380 }
11381
11382 static void
11383 build_reg_hsh (map)
11384 struct reg_map *map;
11385 {
11386 const struct reg_entry *r;
11387
11388 if ((map->htab = hash_new ()) == NULL)
11389 as_fatal (_("virtual memory exhausted"));
11390
11391 for (r = map->names; r->name != NULL; r++)
11392 insert_reg (r, map->htab);
11393 }
11394
11395 static void
11396 insert_reg_alias (str, regnum, htab)
11397 char *str;
11398 int regnum;
11399 struct hash_control *htab;
11400 {
11401 const char *error;
11402 struct reg_entry *new = xmalloc (sizeof (struct reg_entry));
11403 const char *name = xmalloc (strlen (str) + 1);
11404
11405 strcpy ((char *) name, str);
11406
11407 new->name = name;
11408 new->number = regnum;
11409 new->builtin = FALSE;
11410
11411 error = hash_insert (htab, name, (PTR) new);
11412 if (error)
11413 {
11414 as_bad (_("failed to create an alias for %s, reason: %s"),
11415 str, error);
11416 free ((char *) name);
11417 free (new);
11418 }
11419 }
11420
11421 /* Look for the .req directive. This is of the form:
11422
11423 new_register_name .req existing_register_name
11424
11425 If we find one, or if it looks sufficiently like one that we want to
11426 handle any error here, return non-zero. Otherwise return zero. */
11427 static int
11428 create_register_alias (newname, p)
11429 char *newname;
11430 char *p;
11431 {
11432 char *q;
11433 char c;
11434
11435 q = p;
11436 skip_whitespace (q);
11437
11438 c = *p;
11439 *p = '\0';
11440
11441 if (*q && !strncmp (q, ".req ", 5))
11442 {
11443 char *copy_of_str;
11444 char *r;
11445
11446 #ifdef IGNORE_OPCODE_CASE
11447 newname = original_case_string;
11448 #endif
11449 copy_of_str = newname;
11450
11451 q += 4;
11452 skip_whitespace (q);
11453
11454 for (r = q; *r != '\0'; r++)
11455 if (*r == ' ')
11456 break;
11457
11458 if (r != q)
11459 {
11460 enum arm_reg_type new_type, old_type;
11461 int old_regno;
11462 char d = *r;
11463
11464 *r = '\0';
11465 old_type = arm_reg_parse_any (q);
11466 *r = d;
11467
11468 new_type = arm_reg_parse_any (newname);
11469
11470 if (new_type == REG_TYPE_MAX)
11471 {
11472 if (old_type != REG_TYPE_MAX)
11473 {
11474 old_regno = arm_reg_parse (&q, all_reg_maps[old_type].htab);
11475 insert_reg_alias (newname, old_regno,
11476 all_reg_maps[old_type].htab);
11477 }
11478 else
11479 as_warn (_("register '%s' does not exist\n"), q);
11480 }
11481 else if (old_type == REG_TYPE_MAX)
11482 {
11483 as_warn (_("ignoring redefinition of register alias '%s' to non-existant register '%s'"),
11484 copy_of_str, q);
11485 }
11486 else
11487 {
11488 /* Do not warn about redefinitions to the same alias. */
11489 if (new_type != old_type
11490 || (arm_reg_parse (&q, all_reg_maps[old_type].htab)
11491 != arm_reg_parse (&q, all_reg_maps[new_type].htab)))
11492 as_warn (_("ignoring redefinition of register alias '%s'"),
11493 copy_of_str);
11494
11495 }
11496 }
11497 else
11498 as_warn (_("ignoring incomplete .req pseuso op"));
11499
11500 *p = c;
11501 return 1;
11502 }
11503
11504 *p = c;
11505 return 0;
11506 }
11507
11508 static void
11509 set_constant_flonums ()
11510 {
11511 int i;
11512
11513 for (i = 0; i < NUM_FLOAT_VALS; i++)
11514 if (atof_ieee ((char *) fp_const[i], 'x', fp_values[i]) == NULL)
11515 abort ();
11516 }
11517
11518 /* Iterate over the base tables to create the instruction patterns. */
11519 static void
11520 build_arm_ops_hsh ()
11521 {
11522 unsigned int i;
11523 unsigned int j;
11524 static struct obstack insn_obstack;
11525
11526 obstack_begin (&insn_obstack, 4000);
11527
11528 for (i = 0; i < sizeof (insns) / sizeof (struct asm_opcode); i++)
11529 {
11530 const struct asm_opcode *insn = insns + i;
11531
11532 if (insn->cond_offset != 0)
11533 {
11534 /* Insn supports conditional execution. Build the varaints
11535 and insert them in the hash table. */
11536 for (j = 0; j < sizeof (conds) / sizeof (struct asm_cond); j++)
11537 {
11538 unsigned len = strlen (insn->template);
11539 struct asm_opcode *new;
11540 char *template;
11541
11542 new = obstack_alloc (&insn_obstack, sizeof (struct asm_opcode));
11543 /* All condition codes are two characters. */
11544 template = obstack_alloc (&insn_obstack, len + 3);
11545
11546 strncpy (template, insn->template, insn->cond_offset);
11547 strcpy (template + insn->cond_offset, conds[j].template);
11548 if (len > insn->cond_offset)
11549 strcpy (template + insn->cond_offset + 2,
11550 insn->template + insn->cond_offset);
11551 new->template = template;
11552 new->cond_offset = 0;
11553 new->variant = insn->variant;
11554 new->parms = insn->parms;
11555 new->value = (insn->value & ~COND_MASK) | conds[j].value;
11556
11557 hash_insert (arm_ops_hsh, new->template, (PTR) new);
11558 }
11559 }
11560 /* Finally, insert the unconditional insn in the table directly;
11561 no need to build a copy. */
11562 hash_insert (arm_ops_hsh, insn->template, (PTR) insn);
11563 }
11564 }
11565
11566 #if 0 /* Suppressed - for now. */
11567 #if defined OBJ_ELF || defined OBJ_COFF
11568
11569 #ifdef OBJ_ELF
11570 #define arm_Note Elf_External_Note
11571 #else
11572 typedef struct
11573 {
11574 unsigned char namesz[4]; /* Size of entry's owner string. */
11575 unsigned char descsz[4]; /* Size of the note descriptor. */
11576 unsigned char type[4]; /* Interpretation of the descriptor. */
11577 char name[1]; /* Start of the name+desc data. */
11578 } arm_Note;
11579 #endif
11580
11581 /* The description is kept to a fix sized in order to make updating
11582 it and merging it easier. */
11583 #define ARM_NOTE_DESCRIPTION_LENGTH 8
11584
11585 static void
11586 arm_add_note (name, description, type)
11587 const char * name;
11588 const char * description;
11589 unsigned int type;
11590 {
11591 arm_Note note ATTRIBUTE_UNUSED;
11592 char * p;
11593 unsigned int name_len;
11594
11595 name_len = (strlen (name) + 1 + 3) & ~3;
11596
11597 p = frag_more (sizeof (note.namesz));
11598 md_number_to_chars (p, (valueT) name_len, sizeof (note.namesz));
11599
11600 p = frag_more (sizeof (note.descsz));
11601 md_number_to_chars (p, (valueT) ARM_NOTE_DESCRIPTION_LENGTH, sizeof (note.descsz));
11602
11603 p = frag_more (sizeof (note.type));
11604 md_number_to_chars (p, (valueT) type, sizeof (note.type));
11605
11606 p = frag_more (name_len);
11607 strcpy (p, name);
11608
11609 p = frag_more (ARM_NOTE_DESCRIPTION_LENGTH);
11610 strncpy (p, description, ARM_NOTE_DESCRIPTION_LENGTH);
11611 frag_align (2, 0, 0);
11612 }
11613 #endif
11614 #endif
11615
11616 void
11617 md_begin ()
11618 {
11619 unsigned mach;
11620 unsigned int i;
11621
11622 if ( (arm_ops_hsh = hash_new ()) == NULL
11623 || (arm_tops_hsh = hash_new ()) == NULL
11624 || (arm_cond_hsh = hash_new ()) == NULL
11625 || (arm_shift_hsh = hash_new ()) == NULL
11626 || (arm_psr_hsh = hash_new ()) == NULL)
11627 as_fatal (_("virtual memory exhausted"));
11628
11629 build_arm_ops_hsh ();
11630 for (i = 0; i < sizeof (tinsns) / sizeof (struct thumb_opcode); i++)
11631 hash_insert (arm_tops_hsh, tinsns[i].template, (PTR) (tinsns + i));
11632 for (i = 0; i < sizeof (conds) / sizeof (struct asm_cond); i++)
11633 hash_insert (arm_cond_hsh, conds[i].template, (PTR) (conds + i));
11634 for (i = 0; i < sizeof (shift_names) / sizeof (struct asm_shift_name); i++)
11635 hash_insert (arm_shift_hsh, shift_names[i].name, (PTR) (shift_names + i));
11636 for (i = 0; i < sizeof (psrs) / sizeof (struct asm_psr); i++)
11637 hash_insert (arm_psr_hsh, psrs[i].template, (PTR) (psrs + i));
11638
11639 for (i = (int) REG_TYPE_FIRST; i < (int) REG_TYPE_MAX; i++)
11640 build_reg_hsh (all_reg_maps + i);
11641
11642 set_constant_flonums ();
11643
11644 /* Set the cpu variant based on the command-line options. We prefer
11645 -mcpu= over -march= if both are set (as for GCC); and we prefer
11646 -mfpu= over any other way of setting the floating point unit.
11647 Use of legacy options with new options are faulted. */
11648 if (legacy_cpu != -1)
11649 {
11650 if (mcpu_cpu_opt != -1 || march_cpu_opt != -1)
11651 as_bad (_("use of old and new-style options to set CPU type"));
11652
11653 mcpu_cpu_opt = legacy_cpu;
11654 }
11655 else if (mcpu_cpu_opt == -1)
11656 mcpu_cpu_opt = march_cpu_opt;
11657
11658 if (legacy_fpu != -1)
11659 {
11660 if (mfpu_opt != -1)
11661 as_bad (_("use of old and new-style options to set FPU type"));
11662
11663 mfpu_opt = legacy_fpu;
11664 }
11665 else if (mfpu_opt == -1)
11666 {
11667 #if !(defined (TE_LINUX) || defined (TE_NetBSD))
11668 /* Some environments specify a default FPU. If they don't, infer it
11669 from the processor. */
11670 if (mcpu_fpu_opt != -1)
11671 mfpu_opt = mcpu_fpu_opt;
11672 else
11673 mfpu_opt = march_fpu_opt;
11674 #else
11675 mfpu_opt = FPU_DEFAULT;
11676 #endif
11677 }
11678
11679 if (mfpu_opt == -1)
11680 {
11681 if (mcpu_cpu_opt == -1)
11682 mfpu_opt = FPU_DEFAULT;
11683 else if (mcpu_cpu_opt & ARM_EXT_V5)
11684 mfpu_opt = FPU_ARCH_VFP_V2;
11685 else
11686 mfpu_opt = FPU_ARCH_FPA;
11687 }
11688
11689 if (mcpu_cpu_opt == -1)
11690 mcpu_cpu_opt = CPU_DEFAULT;
11691
11692 cpu_variant = mcpu_cpu_opt | mfpu_opt;
11693
11694 {
11695 unsigned int flags = 0;
11696
11697 #if defined OBJ_ELF
11698 flags = meabi_flags;
11699
11700 switch (meabi_flags)
11701 {
11702 case EF_ARM_EABI_UNKNOWN:
11703 #endif
11704 #if defined OBJ_COFF || defined OBJ_ELF
11705 /* Set the flags in the private structure. */
11706 if (uses_apcs_26) flags |= F_APCS26;
11707 if (support_interwork) flags |= F_INTERWORK;
11708 if (uses_apcs_float) flags |= F_APCS_FLOAT;
11709 if (pic_code) flags |= F_PIC;
11710 if ((cpu_variant & FPU_ANY) == FPU_NONE
11711 || (cpu_variant & FPU_ANY) == FPU_ARCH_VFP) /* VFP layout only. */
11712 flags |= F_SOFT_FLOAT;
11713
11714 switch (mfloat_abi_opt)
11715 {
11716 case ARM_FLOAT_ABI_SOFT:
11717 case ARM_FLOAT_ABI_SOFTFP:
11718 flags |= F_SOFT_FLOAT;
11719 break;
11720
11721 case ARM_FLOAT_ABI_HARD:
11722 if (flags & F_SOFT_FLOAT)
11723 as_bad (_("hard-float conflicts with specified fpu"));
11724 break;
11725 }
11726
11727 /* Using VFP conventions (even if soft-float). */
11728 if (cpu_variant & FPU_VFP_EXT_NONE)
11729 flags |= F_VFP_FLOAT;
11730 #endif
11731 #if defined OBJ_ELF
11732 if (cpu_variant & FPU_ARCH_MAVERICK)
11733 flags |= EF_ARM_MAVERICK_FLOAT;
11734 break;
11735
11736 case EF_ARM_EABI_VER3:
11737 /* No additional flags to set. */
11738 break;
11739
11740 default:
11741 abort ();
11742 }
11743 #endif
11744 #if defined OBJ_COFF || defined OBJ_ELF
11745 bfd_set_private_flags (stdoutput, flags);
11746
11747 /* We have run out flags in the COFF header to encode the
11748 status of ATPCS support, so instead we create a dummy,
11749 empty, debug section called .arm.atpcs. */
11750 if (atpcs)
11751 {
11752 asection * sec;
11753
11754 sec = bfd_make_section (stdoutput, ".arm.atpcs");
11755
11756 if (sec != NULL)
11757 {
11758 bfd_set_section_flags
11759 (stdoutput, sec, SEC_READONLY | SEC_DEBUGGING /* | SEC_HAS_CONTENTS */);
11760 bfd_set_section_size (stdoutput, sec, 0);
11761 bfd_set_section_contents (stdoutput, sec, NULL, 0, 0);
11762 }
11763 }
11764 #endif
11765 }
11766
11767 /* Record the CPU type as well. */
11768 switch (cpu_variant & ARM_CPU_MASK)
11769 {
11770 case ARM_2:
11771 mach = bfd_mach_arm_2;
11772 break;
11773
11774 case ARM_3: /* Also ARM_250. */
11775 mach = bfd_mach_arm_2a;
11776 break;
11777
11778 case ARM_6: /* Also ARM_7. */
11779 mach = bfd_mach_arm_3;
11780 break;
11781
11782 default:
11783 mach = bfd_mach_arm_unknown;
11784 break;
11785 }
11786
11787 /* Catch special cases. */
11788 if (cpu_variant & ARM_CEXT_IWMMXT)
11789 mach = bfd_mach_arm_iWMMXt;
11790 else if (cpu_variant & ARM_CEXT_XSCALE)
11791 mach = bfd_mach_arm_XScale;
11792 else if (cpu_variant & ARM_CEXT_MAVERICK)
11793 mach = bfd_mach_arm_ep9312;
11794 else if (cpu_variant & ARM_EXT_V5E)
11795 mach = bfd_mach_arm_5TE;
11796 else if (cpu_variant & ARM_EXT_V5)
11797 {
11798 if (cpu_variant & ARM_EXT_V4T)
11799 mach = bfd_mach_arm_5T;
11800 else
11801 mach = bfd_mach_arm_5;
11802 }
11803 else if (cpu_variant & ARM_EXT_V4)
11804 {
11805 if (cpu_variant & ARM_EXT_V4T)
11806 mach = bfd_mach_arm_4T;
11807 else
11808 mach = bfd_mach_arm_4;
11809 }
11810 else if (cpu_variant & ARM_EXT_V3M)
11811 mach = bfd_mach_arm_3M;
11812
11813 #if 0 /* Suppressed - for now. */
11814 #if defined (OBJ_ELF) || defined (OBJ_COFF)
11815
11816 /* Create a .note section to fully identify this arm binary. */
11817
11818 #define NOTE_ARCH_STRING "arch: "
11819
11820 #if defined OBJ_COFF && ! defined NT_VERSION
11821 #define NT_VERSION 1
11822 #define NT_ARCH 2
11823 #endif
11824
11825 {
11826 segT current_seg = now_seg;
11827 subsegT current_subseg = now_subseg;
11828 asection * arm_arch;
11829 const char * arch_string;
11830
11831 arm_arch = bfd_make_section_old_way (stdoutput, ARM_NOTE_SECTION);
11832
11833 #ifdef OBJ_COFF
11834 bfd_set_section_flags (stdoutput, arm_arch,
11835 SEC_DATA | SEC_ALLOC | SEC_LOAD | SEC_LINK_ONCE \
11836 | SEC_HAS_CONTENTS);
11837 #else
11838 bfd_set_section_flags (stdoutput, arm_arch,
11839 SEC_READONLY | SEC_HAS_CONTENTS);
11840 #endif
11841 arm_arch->output_section = arm_arch;
11842 subseg_set (arm_arch, 0);
11843
11844 switch (mach)
11845 {
11846 default:
11847 case bfd_mach_arm_unknown: arch_string = "unknown"; break;
11848 case bfd_mach_arm_2: arch_string = "armv2"; break;
11849 case bfd_mach_arm_2a: arch_string = "armv2a"; break;
11850 case bfd_mach_arm_3: arch_string = "armv3"; break;
11851 case bfd_mach_arm_3M: arch_string = "armv3M"; break;
11852 case bfd_mach_arm_4: arch_string = "armv4"; break;
11853 case bfd_mach_arm_4T: arch_string = "armv4t"; break;
11854 case bfd_mach_arm_5: arch_string = "armv5"; break;
11855 case bfd_mach_arm_5T: arch_string = "armv5t"; break;
11856 case bfd_mach_arm_5TE: arch_string = "armv5te"; break;
11857 case bfd_mach_arm_XScale: arch_string = "XScale"; break;
11858 case bfd_mach_arm_ep9312: arch_string = "ep9312"; break;
11859 case bfd_mach_arm_iWMMXt: arch_string = "iWMMXt"; break;
11860 }
11861
11862 arm_add_note (NOTE_ARCH_STRING, arch_string, NT_ARCH);
11863
11864 subseg_set (current_seg, current_subseg);
11865 }
11866 #endif
11867 #endif /* Suppressed code. */
11868
11869 bfd_set_arch_mach (stdoutput, TARGET_ARCH, mach);
11870 }
11871
11872 /* Turn an integer of n bytes (in val) into a stream of bytes appropriate
11873 for use in the a.out file, and stores them in the array pointed to by buf.
11874 This knows about the endian-ness of the target machine and does
11875 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
11876 2 (short) and 4 (long) Floating numbers are put out as a series of
11877 LITTLENUMS (shorts, here at least). */
11878
11879 void
11880 md_number_to_chars (buf, val, n)
11881 char * buf;
11882 valueT val;
11883 int n;
11884 {
11885 if (target_big_endian)
11886 number_to_chars_bigendian (buf, val, n);
11887 else
11888 number_to_chars_littleendian (buf, val, n);
11889 }
11890
11891 static valueT
11892 md_chars_to_number (buf, n)
11893 char * buf;
11894 int n;
11895 {
11896 valueT result = 0;
11897 unsigned char * where = (unsigned char *) buf;
11898
11899 if (target_big_endian)
11900 {
11901 while (n--)
11902 {
11903 result <<= 8;
11904 result |= (*where++ & 255);
11905 }
11906 }
11907 else
11908 {
11909 while (n--)
11910 {
11911 result <<= 8;
11912 result |= (where[n] & 255);
11913 }
11914 }
11915
11916 return result;
11917 }
11918
11919 /* Turn a string in input_line_pointer into a floating point constant
11920 of type TYPE, and store the appropriate bytes in *LITP. The number
11921 of LITTLENUMS emitted is stored in *SIZEP. An error message is
11922 returned, or NULL on OK.
11923
11924 Note that fp constants aren't represent in the normal way on the ARM.
11925 In big endian mode, things are as expected. However, in little endian
11926 mode fp constants are big-endian word-wise, and little-endian byte-wise
11927 within the words. For example, (double) 1.1 in big endian mode is
11928 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
11929 the byte sequence 99 99 f1 3f 9a 99 99 99.
11930
11931 ??? The format of 12 byte floats is uncertain according to gcc's arm.h. */
11932
11933 char *
11934 md_atof (type, litP, sizeP)
11935 char type;
11936 char * litP;
11937 int * sizeP;
11938 {
11939 int prec;
11940 LITTLENUM_TYPE words[MAX_LITTLENUMS];
11941 char *t;
11942 int i;
11943
11944 switch (type)
11945 {
11946 case 'f':
11947 case 'F':
11948 case 's':
11949 case 'S':
11950 prec = 2;
11951 break;
11952
11953 case 'd':
11954 case 'D':
11955 case 'r':
11956 case 'R':
11957 prec = 4;
11958 break;
11959
11960 case 'x':
11961 case 'X':
11962 prec = 6;
11963 break;
11964
11965 case 'p':
11966 case 'P':
11967 prec = 6;
11968 break;
11969
11970 default:
11971 *sizeP = 0;
11972 return _("bad call to MD_ATOF()");
11973 }
11974
11975 t = atof_ieee (input_line_pointer, type, words);
11976 if (t)
11977 input_line_pointer = t;
11978 *sizeP = prec * 2;
11979
11980 if (target_big_endian)
11981 {
11982 for (i = 0; i < prec; i++)
11983 {
11984 md_number_to_chars (litP, (valueT) words[i], 2);
11985 litP += 2;
11986 }
11987 }
11988 else
11989 {
11990 if (cpu_variant & FPU_ARCH_VFP)
11991 for (i = prec - 1; i >= 0; i--)
11992 {
11993 md_number_to_chars (litP, (valueT) words[i], 2);
11994 litP += 2;
11995 }
11996 else
11997 /* For a 4 byte float the order of elements in `words' is 1 0.
11998 For an 8 byte float the order is 1 0 3 2. */
11999 for (i = 0; i < prec; i += 2)
12000 {
12001 md_number_to_chars (litP, (valueT) words[i + 1], 2);
12002 md_number_to_chars (litP + 2, (valueT) words[i], 2);
12003 litP += 4;
12004 }
12005 }
12006
12007 return 0;
12008 }
12009
12010 /* The knowledge of the PC's pipeline offset is built into the insns
12011 themselves. */
12012
12013 long
12014 md_pcrel_from (fixP)
12015 fixS * fixP;
12016 {
12017 if (fixP->fx_addsy
12018 && S_GET_SEGMENT (fixP->fx_addsy) == undefined_section
12019 && fixP->fx_subsy == NULL)
12020 return 0;
12021
12022 if (fixP->fx_pcrel && (fixP->fx_r_type == BFD_RELOC_ARM_THUMB_ADD))
12023 {
12024 /* PC relative addressing on the Thumb is slightly odd
12025 as the bottom two bits of the PC are forced to zero
12026 for the calculation. */
12027 return (fixP->fx_where + fixP->fx_frag->fr_address) & ~3;
12028 }
12029
12030 #ifdef TE_WINCE
12031 /* The pattern was adjusted to accommodate CE's off-by-one fixups,
12032 so we un-adjust here to compensate for the accommodation. */
12033 return fixP->fx_where + fixP->fx_frag->fr_address + 8;
12034 #else
12035 return fixP->fx_where + fixP->fx_frag->fr_address;
12036 #endif
12037 }
12038
12039 /* Round up a section size to the appropriate boundary. */
12040
12041 valueT
12042 md_section_align (segment, size)
12043 segT segment ATTRIBUTE_UNUSED;
12044 valueT size;
12045 {
12046 #ifdef OBJ_ELF
12047 return size;
12048 #else
12049 /* Round all sects to multiple of 4. */
12050 return (size + 3) & ~3;
12051 #endif
12052 }
12053
12054 /* Under ELF we need to default _GLOBAL_OFFSET_TABLE.
12055 Otherwise we have no need to default values of symbols. */
12056
12057 symbolS *
12058 md_undefined_symbol (name)
12059 char * name ATTRIBUTE_UNUSED;
12060 {
12061 #ifdef OBJ_ELF
12062 if (name[0] == '_' && name[1] == 'G'
12063 && streq (name, GLOBAL_OFFSET_TABLE_NAME))
12064 {
12065 if (!GOT_symbol)
12066 {
12067 if (symbol_find (name))
12068 as_bad ("GOT already in the symbol table");
12069
12070 GOT_symbol = symbol_new (name, undefined_section,
12071 (valueT) 0, & zero_address_frag);
12072 }
12073
12074 return GOT_symbol;
12075 }
12076 #endif
12077
12078 return 0;
12079 }
12080
12081 /* arm_reg_parse () := if it looks like a register, return its token and
12082 advance the pointer. */
12083
12084 static int
12085 arm_reg_parse (ccp, htab)
12086 register char ** ccp;
12087 struct hash_control *htab;
12088 {
12089 char * start = * ccp;
12090 char c;
12091 char * p;
12092 struct reg_entry * reg;
12093
12094 #ifdef REGISTER_PREFIX
12095 if (*start != REGISTER_PREFIX)
12096 return FAIL;
12097 p = start + 1;
12098 #else
12099 p = start;
12100 #ifdef OPTIONAL_REGISTER_PREFIX
12101 if (*p == OPTIONAL_REGISTER_PREFIX)
12102 p++, start++;
12103 #endif
12104 #endif
12105 if (!ISALPHA (*p) || !is_name_beginner (*p))
12106 return FAIL;
12107
12108 c = *p++;
12109 while (ISALPHA (c) || ISDIGIT (c) || c == '_')
12110 c = *p++;
12111
12112 *--p = 0;
12113 reg = (struct reg_entry *) hash_find (htab, start);
12114 *p = c;
12115
12116 if (reg)
12117 {
12118 *ccp = p;
12119 return reg->number;
12120 }
12121
12122 return FAIL;
12123 }
12124
12125 /* Search for the following register name in each of the possible reg name
12126 tables. Return the classification if found, or REG_TYPE_MAX if not
12127 present. */
12128 static enum arm_reg_type
12129 arm_reg_parse_any (cp)
12130 char *cp;
12131 {
12132 int i;
12133
12134 for (i = (int) REG_TYPE_FIRST; i < (int) REG_TYPE_MAX; i++)
12135 if (arm_reg_parse (&cp, all_reg_maps[i].htab) != FAIL)
12136 return (enum arm_reg_type) i;
12137
12138 return REG_TYPE_MAX;
12139 }
12140
12141 void
12142 md_apply_fix3 (fixP, valP, seg)
12143 fixS * fixP;
12144 valueT * valP;
12145 segT seg;
12146 {
12147 offsetT value = * valP;
12148 offsetT newval;
12149 unsigned int newimm;
12150 unsigned long temp;
12151 int sign;
12152 char * buf = fixP->fx_where + fixP->fx_frag->fr_literal;
12153 arm_fix_data * arm_data = (arm_fix_data *) fixP->tc_fix_data;
12154
12155 assert (fixP->fx_r_type < BFD_RELOC_UNUSED);
12156
12157 /* Note whether this will delete the relocation. */
12158 #if 0
12159 /* Patch from REarnshaw to JDavis (disabled for the moment, since it
12160 doesn't work fully.) */
12161 if ((fixP->fx_addsy == 0 || symbol_constant_p (fixP->fx_addsy))
12162 && !fixP->fx_pcrel)
12163 #else
12164 if (fixP->fx_addsy == 0 && !fixP->fx_pcrel)
12165 #endif
12166 fixP->fx_done = 1;
12167
12168 /* If this symbol is in a different section then we need to leave it for
12169 the linker to deal with. Unfortunately, md_pcrel_from can't tell,
12170 so we have to undo it's effects here. */
12171 if (fixP->fx_pcrel)
12172 {
12173 if (fixP->fx_addsy != NULL
12174 && S_IS_DEFINED (fixP->fx_addsy)
12175 && S_GET_SEGMENT (fixP->fx_addsy) != seg)
12176 {
12177 if (target_oabi
12178 && (fixP->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH
12179 || fixP->fx_r_type == BFD_RELOC_ARM_PCREL_BLX
12180 ))
12181 value = 0;
12182 else
12183 value += md_pcrel_from (fixP);
12184 }
12185 }
12186
12187 /* Remember value for emit_reloc. */
12188 fixP->fx_addnumber = value;
12189
12190 switch (fixP->fx_r_type)
12191 {
12192 case BFD_RELOC_ARM_IMMEDIATE:
12193 newimm = validate_immediate (value);
12194 temp = md_chars_to_number (buf, INSN_SIZE);
12195
12196 /* If the instruction will fail, see if we can fix things up by
12197 changing the opcode. */
12198 if (newimm == (unsigned int) FAIL
12199 && (newimm = negate_data_op (&temp, value)) == (unsigned int) FAIL)
12200 {
12201 as_bad_where (fixP->fx_file, fixP->fx_line,
12202 _("invalid constant (%lx) after fixup"),
12203 (unsigned long) value);
12204 break;
12205 }
12206
12207 newimm |= (temp & 0xfffff000);
12208 md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
12209 fixP->fx_done = 1;
12210 break;
12211
12212 case BFD_RELOC_ARM_ADRL_IMMEDIATE:
12213 {
12214 unsigned int highpart = 0;
12215 unsigned int newinsn = 0xe1a00000; /* nop. */
12216
12217 newimm = validate_immediate (value);
12218 temp = md_chars_to_number (buf, INSN_SIZE);
12219
12220 /* If the instruction will fail, see if we can fix things up by
12221 changing the opcode. */
12222 if (newimm == (unsigned int) FAIL
12223 && (newimm = negate_data_op (& temp, value)) == (unsigned int) FAIL)
12224 {
12225 /* No ? OK - try using two ADD instructions to generate
12226 the value. */
12227 newimm = validate_immediate_twopart (value, & highpart);
12228
12229 /* Yes - then make sure that the second instruction is
12230 also an add. */
12231 if (newimm != (unsigned int) FAIL)
12232 newinsn = temp;
12233 /* Still No ? Try using a negated value. */
12234 else if ((newimm = validate_immediate_twopart (- value, & highpart)) != (unsigned int) FAIL)
12235 temp = newinsn = (temp & OPCODE_MASK) | OPCODE_SUB << DATA_OP_SHIFT;
12236 /* Otherwise - give up. */
12237 else
12238 {
12239 as_bad_where (fixP->fx_file, fixP->fx_line,
12240 _("unable to compute ADRL instructions for PC offset of 0x%lx"),
12241 (long) value);
12242 break;
12243 }
12244
12245 /* Replace the first operand in the 2nd instruction (which
12246 is the PC) with the destination register. We have
12247 already added in the PC in the first instruction and we
12248 do not want to do it again. */
12249 newinsn &= ~ 0xf0000;
12250 newinsn |= ((newinsn & 0x0f000) << 4);
12251 }
12252
12253 newimm |= (temp & 0xfffff000);
12254 md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
12255
12256 highpart |= (newinsn & 0xfffff000);
12257 md_number_to_chars (buf + INSN_SIZE, (valueT) highpart, INSN_SIZE);
12258 }
12259 break;
12260
12261 case BFD_RELOC_ARM_OFFSET_IMM:
12262 sign = value >= 0;
12263
12264 if (value < 0)
12265 value = - value;
12266
12267 if (validate_offset_imm (value, 0) == FAIL)
12268 {
12269 as_bad_where (fixP->fx_file, fixP->fx_line,
12270 _("bad immediate value for offset (%ld)"),
12271 (long) value);
12272 break;
12273 }
12274
12275 newval = md_chars_to_number (buf, INSN_SIZE);
12276 newval &= 0xff7ff000;
12277 newval |= value | (sign ? INDEX_UP : 0);
12278 md_number_to_chars (buf, newval, INSN_SIZE);
12279 break;
12280
12281 case BFD_RELOC_ARM_OFFSET_IMM8:
12282 case BFD_RELOC_ARM_HWLITERAL:
12283 sign = value >= 0;
12284
12285 if (value < 0)
12286 value = - value;
12287
12288 if (validate_offset_imm (value, 1) == FAIL)
12289 {
12290 if (fixP->fx_r_type == BFD_RELOC_ARM_HWLITERAL)
12291 as_bad_where (fixP->fx_file, fixP->fx_line,
12292 _("invalid literal constant: pool needs to be closer"));
12293 else
12294 as_bad (_("bad immediate value for half-word offset (%ld)"),
12295 (long) value);
12296 break;
12297 }
12298
12299 newval = md_chars_to_number (buf, INSN_SIZE);
12300 newval &= 0xff7ff0f0;
12301 newval |= ((value >> 4) << 8) | (value & 0xf) | (sign ? INDEX_UP : 0);
12302 md_number_to_chars (buf, newval, INSN_SIZE);
12303 break;
12304
12305 case BFD_RELOC_ARM_LITERAL:
12306 sign = value >= 0;
12307
12308 if (value < 0)
12309 value = - value;
12310
12311 if (validate_offset_imm (value, 0) == FAIL)
12312 {
12313 as_bad_where (fixP->fx_file, fixP->fx_line,
12314 _("invalid literal constant: pool needs to be closer"));
12315 break;
12316 }
12317
12318 newval = md_chars_to_number (buf, INSN_SIZE);
12319 newval &= 0xff7ff000;
12320 newval |= value | (sign ? INDEX_UP : 0);
12321 md_number_to_chars (buf, newval, INSN_SIZE);
12322 break;
12323
12324 case BFD_RELOC_ARM_SHIFT_IMM:
12325 newval = md_chars_to_number (buf, INSN_SIZE);
12326 if (((unsigned long) value) > 32
12327 || (value == 32
12328 && (((newval & 0x60) == 0) || (newval & 0x60) == 0x60)))
12329 {
12330 as_bad_where (fixP->fx_file, fixP->fx_line,
12331 _("shift expression is too large"));
12332 break;
12333 }
12334
12335 if (value == 0)
12336 /* Shifts of zero must be done as lsl. */
12337 newval &= ~0x60;
12338 else if (value == 32)
12339 value = 0;
12340 newval &= 0xfffff07f;
12341 newval |= (value & 0x1f) << 7;
12342 md_number_to_chars (buf, newval, INSN_SIZE);
12343 break;
12344
12345 case BFD_RELOC_ARM_SWI:
12346 if (arm_data->thumb_mode)
12347 {
12348 if (((unsigned long) value) > 0xff)
12349 as_bad_where (fixP->fx_file, fixP->fx_line,
12350 _("invalid swi expression"));
12351 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xff00;
12352 newval |= value;
12353 md_number_to_chars (buf, newval, THUMB_SIZE);
12354 }
12355 else
12356 {
12357 if (((unsigned long) value) > 0x00ffffff)
12358 as_bad_where (fixP->fx_file, fixP->fx_line,
12359 _("invalid swi expression"));
12360 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff000000;
12361 newval |= value;
12362 md_number_to_chars (buf, newval, INSN_SIZE);
12363 }
12364 break;
12365
12366 case BFD_RELOC_ARM_MULTI:
12367 if (((unsigned long) value) > 0xffff)
12368 as_bad_where (fixP->fx_file, fixP->fx_line,
12369 _("invalid expression in load/store multiple"));
12370 newval = value | md_chars_to_number (buf, INSN_SIZE);
12371 md_number_to_chars (buf, newval, INSN_SIZE);
12372 break;
12373
12374 case BFD_RELOC_ARM_PCREL_BRANCH:
12375 newval = md_chars_to_number (buf, INSN_SIZE);
12376
12377 /* Sign-extend a 24-bit number. */
12378 #define SEXT24(x) ((((x) & 0xffffff) ^ (~ 0x7fffff)) + 0x800000)
12379
12380 #ifdef OBJ_ELF
12381 if (! target_oabi)
12382 value = fixP->fx_offset;
12383 #endif
12384
12385 /* We are going to store value (shifted right by two) in the
12386 instruction, in a 24 bit, signed field. Thus we need to check
12387 that none of the top 8 bits of the shifted value (top 7 bits of
12388 the unshifted, unsigned value) are set, or that they are all set. */
12389 if ((value & ~ ((offsetT) 0x1ffffff)) != 0
12390 && ((value & ~ ((offsetT) 0x1ffffff)) != ~ ((offsetT) 0x1ffffff)))
12391 {
12392 #ifdef OBJ_ELF
12393 /* Normally we would be stuck at this point, since we cannot store
12394 the absolute address that is the destination of the branch in the
12395 24 bits of the branch instruction. If however, we happen to know
12396 that the destination of the branch is in the same section as the
12397 branch instruction itself, then we can compute the relocation for
12398 ourselves and not have to bother the linker with it.
12399
12400 FIXME: The tests for OBJ_ELF and ! target_oabi are only here
12401 because I have not worked out how to do this for OBJ_COFF or
12402 target_oabi. */
12403 if (! target_oabi
12404 && fixP->fx_addsy != NULL
12405 && S_IS_DEFINED (fixP->fx_addsy)
12406 && S_GET_SEGMENT (fixP->fx_addsy) == seg)
12407 {
12408 /* Get pc relative value to go into the branch. */
12409 value = * valP;
12410
12411 /* Permit a backward branch provided that enough bits
12412 are set. Allow a forwards branch, provided that
12413 enough bits are clear. */
12414 if ( (value & ~ ((offsetT) 0x1ffffff)) == ~ ((offsetT) 0x1ffffff)
12415 || (value & ~ ((offsetT) 0x1ffffff)) == 0)
12416 fixP->fx_done = 1;
12417 }
12418
12419 if (! fixP->fx_done)
12420 #endif
12421 as_bad_where (fixP->fx_file, fixP->fx_line,
12422 _("GAS can't handle same-section branch dest >= 0x04000000"));
12423 }
12424
12425 value >>= 2;
12426 value += SEXT24 (newval);
12427
12428 if ( (value & ~ ((offsetT) 0xffffff)) != 0
12429 && ((value & ~ ((offsetT) 0xffffff)) != ~ ((offsetT) 0xffffff)))
12430 as_bad_where (fixP->fx_file, fixP->fx_line,
12431 _("out of range branch"));
12432
12433 newval = (value & 0x00ffffff) | (newval & 0xff000000);
12434 md_number_to_chars (buf, newval, INSN_SIZE);
12435 break;
12436
12437 case BFD_RELOC_ARM_PCREL_BLX:
12438 {
12439 offsetT hbit;
12440 newval = md_chars_to_number (buf, INSN_SIZE);
12441
12442 #ifdef OBJ_ELF
12443 if (! target_oabi)
12444 value = fixP->fx_offset;
12445 #endif
12446 hbit = (value >> 1) & 1;
12447 value = (value >> 2) & 0x00ffffff;
12448 value = (value + (newval & 0x00ffffff)) & 0x00ffffff;
12449 newval = value | (newval & 0xfe000000) | (hbit << 24);
12450 md_number_to_chars (buf, newval, INSN_SIZE);
12451 }
12452 break;
12453
12454 case BFD_RELOC_THUMB_PCREL_BRANCH9: /* Conditional branch. */
12455 newval = md_chars_to_number (buf, THUMB_SIZE);
12456 {
12457 addressT diff = (newval & 0xff) << 1;
12458 if (diff & 0x100)
12459 diff |= ~0xff;
12460
12461 value += diff;
12462 if ((value & ~0xff) && ((value & ~0xff) != ~0xff))
12463 as_bad_where (fixP->fx_file, fixP->fx_line,
12464 _("branch out of range"));
12465 newval = (newval & 0xff00) | ((value & 0x1ff) >> 1);
12466 }
12467 md_number_to_chars (buf, newval, THUMB_SIZE);
12468 break;
12469
12470 case BFD_RELOC_THUMB_PCREL_BRANCH12: /* Unconditional branch. */
12471 newval = md_chars_to_number (buf, THUMB_SIZE);
12472 {
12473 addressT diff = (newval & 0x7ff) << 1;
12474 if (diff & 0x800)
12475 diff |= ~0x7ff;
12476
12477 value += diff;
12478 if ((value & ~0x7ff) && ((value & ~0x7ff) != ~0x7ff))
12479 as_bad_where (fixP->fx_file, fixP->fx_line,
12480 _("branch out of range"));
12481 newval = (newval & 0xf800) | ((value & 0xfff) >> 1);
12482 }
12483 md_number_to_chars (buf, newval, THUMB_SIZE);
12484 break;
12485
12486 case BFD_RELOC_THUMB_PCREL_BLX:
12487 case BFD_RELOC_THUMB_PCREL_BRANCH23:
12488 {
12489 offsetT newval2;
12490 addressT diff;
12491
12492 newval = md_chars_to_number (buf, THUMB_SIZE);
12493 newval2 = md_chars_to_number (buf + THUMB_SIZE, THUMB_SIZE);
12494 diff = ((newval & 0x7ff) << 12) | ((newval2 & 0x7ff) << 1);
12495 if (diff & 0x400000)
12496 diff |= ~0x3fffff;
12497 #ifdef OBJ_ELF
12498 value = fixP->fx_offset;
12499 #endif
12500 value += diff;
12501
12502 if ((value & ~0x3fffff) && ((value & ~0x3fffff) != ~0x3fffff))
12503 as_bad_where (fixP->fx_file, fixP->fx_line,
12504 _("branch with link out of range"));
12505
12506 newval = (newval & 0xf800) | ((value & 0x7fffff) >> 12);
12507 newval2 = (newval2 & 0xf800) | ((value & 0xfff) >> 1);
12508 if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX)
12509 /* For a BLX instruction, make sure that the relocation is rounded up
12510 to a word boundary. This follows the semantics of the instruction
12511 which specifies that bit 1 of the target address will come from bit
12512 1 of the base address. */
12513 newval2 = (newval2 + 1) & ~ 1;
12514 md_number_to_chars (buf, newval, THUMB_SIZE);
12515 md_number_to_chars (buf + THUMB_SIZE, newval2, THUMB_SIZE);
12516 }
12517 break;
12518
12519 case BFD_RELOC_8:
12520 if (fixP->fx_done || fixP->fx_pcrel)
12521 md_number_to_chars (buf, value, 1);
12522 #ifdef OBJ_ELF
12523 else if (!target_oabi)
12524 {
12525 value = fixP->fx_offset;
12526 md_number_to_chars (buf, value, 1);
12527 }
12528 #endif
12529 break;
12530
12531 case BFD_RELOC_16:
12532 if (fixP->fx_done || fixP->fx_pcrel)
12533 md_number_to_chars (buf, value, 2);
12534 #ifdef OBJ_ELF
12535 else if (!target_oabi)
12536 {
12537 value = fixP->fx_offset;
12538 md_number_to_chars (buf, value, 2);
12539 }
12540 #endif
12541 break;
12542
12543 #ifdef OBJ_ELF
12544 case BFD_RELOC_ARM_GOT32:
12545 case BFD_RELOC_ARM_GOTOFF:
12546 md_number_to_chars (buf, 0, 4);
12547 break;
12548 #endif
12549
12550 case BFD_RELOC_RVA:
12551 case BFD_RELOC_32:
12552 if (fixP->fx_done || fixP->fx_pcrel)
12553 md_number_to_chars (buf, value, 4);
12554 #ifdef OBJ_ELF
12555 else if (!target_oabi)
12556 {
12557 value = fixP->fx_offset;
12558 md_number_to_chars (buf, value, 4);
12559 }
12560 #endif
12561 break;
12562
12563 #ifdef OBJ_ELF
12564 case BFD_RELOC_ARM_PLT32:
12565 /* It appears the instruction is fully prepared at this point. */
12566 break;
12567 #endif
12568
12569 case BFD_RELOC_ARM_CP_OFF_IMM:
12570 sign = value >= 0;
12571 if (value < -1023 || value > 1023 || (value & 3))
12572 as_bad_where (fixP->fx_file, fixP->fx_line,
12573 _("illegal value for co-processor offset"));
12574 if (value < 0)
12575 value = -value;
12576 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
12577 newval |= (value >> 2) | (sign ? INDEX_UP : 0);
12578 md_number_to_chars (buf, newval, INSN_SIZE);
12579 break;
12580
12581 case BFD_RELOC_ARM_CP_OFF_IMM_S2:
12582 sign = value >= 0;
12583 if (value < -255 || value > 255)
12584 as_bad_where (fixP->fx_file, fixP->fx_line,
12585 _("Illegal value for co-processor offset"));
12586 if (value < 0)
12587 value = -value;
12588 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
12589 newval |= value | (sign ? INDEX_UP : 0);
12590 md_number_to_chars (buf, newval , INSN_SIZE);
12591 break;
12592
12593 case BFD_RELOC_ARM_THUMB_OFFSET:
12594 newval = md_chars_to_number (buf, THUMB_SIZE);
12595 /* Exactly what ranges, and where the offset is inserted depends
12596 on the type of instruction, we can establish this from the
12597 top 4 bits. */
12598 switch (newval >> 12)
12599 {
12600 case 4: /* PC load. */
12601 /* Thumb PC loads are somewhat odd, bit 1 of the PC is
12602 forced to zero for these loads, so we will need to round
12603 up the offset if the instruction address is not word
12604 aligned (since the final address produced must be, and
12605 we can only describe word-aligned immediate offsets). */
12606
12607 if ((fixP->fx_frag->fr_address + fixP->fx_where + value) & 3)
12608 as_bad_where (fixP->fx_file, fixP->fx_line,
12609 _("invalid offset, target not word aligned (0x%08X)"),
12610 (unsigned int) (fixP->fx_frag->fr_address
12611 + fixP->fx_where + value));
12612
12613 if ((value + 2) & ~0x3fe)
12614 as_bad_where (fixP->fx_file, fixP->fx_line,
12615 _("invalid offset, value too big (0x%08lX)"),
12616 (long) value);
12617
12618 /* Round up, since pc will be rounded down. */
12619 newval |= (value + 2) >> 2;
12620 break;
12621
12622 case 9: /* SP load/store. */
12623 if (value & ~0x3fc)
12624 as_bad_where (fixP->fx_file, fixP->fx_line,
12625 _("invalid offset, value too big (0x%08lX)"),
12626 (long) value);
12627 newval |= value >> 2;
12628 break;
12629
12630 case 6: /* Word load/store. */
12631 if (value & ~0x7c)
12632 as_bad_where (fixP->fx_file, fixP->fx_line,
12633 _("invalid offset, value too big (0x%08lX)"),
12634 (long) value);
12635 newval |= value << 4; /* 6 - 2. */
12636 break;
12637
12638 case 7: /* Byte load/store. */
12639 if (value & ~0x1f)
12640 as_bad_where (fixP->fx_file, fixP->fx_line,
12641 _("invalid offset, value too big (0x%08lX)"),
12642 (long) value);
12643 newval |= value << 6;
12644 break;
12645
12646 case 8: /* Halfword load/store. */
12647 if (value & ~0x3e)
12648 as_bad_where (fixP->fx_file, fixP->fx_line,
12649 _("invalid offset, value too big (0x%08lX)"),
12650 (long) value);
12651 newval |= value << 5; /* 6 - 1. */
12652 break;
12653
12654 default:
12655 as_bad_where (fixP->fx_file, fixP->fx_line,
12656 "Unable to process relocation for thumb opcode: %lx",
12657 (unsigned long) newval);
12658 break;
12659 }
12660 md_number_to_chars (buf, newval, THUMB_SIZE);
12661 break;
12662
12663 case BFD_RELOC_ARM_THUMB_ADD:
12664 /* This is a complicated relocation, since we use it for all of
12665 the following immediate relocations:
12666
12667 3bit ADD/SUB
12668 8bit ADD/SUB
12669 9bit ADD/SUB SP word-aligned
12670 10bit ADD PC/SP word-aligned
12671
12672 The type of instruction being processed is encoded in the
12673 instruction field:
12674
12675 0x8000 SUB
12676 0x00F0 Rd
12677 0x000F Rs
12678 */
12679 newval = md_chars_to_number (buf, THUMB_SIZE);
12680 {
12681 int rd = (newval >> 4) & 0xf;
12682 int rs = newval & 0xf;
12683 int subtract = newval & 0x8000;
12684
12685 if (rd == REG_SP)
12686 {
12687 if (value & ~0x1fc)
12688 as_bad_where (fixP->fx_file, fixP->fx_line,
12689 _("invalid immediate for stack address calculation"));
12690 newval = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
12691 newval |= value >> 2;
12692 }
12693 else if (rs == REG_PC || rs == REG_SP)
12694 {
12695 if (subtract ||
12696 value & ~0x3fc)
12697 as_bad_where (fixP->fx_file, fixP->fx_line,
12698 _("invalid immediate for address calculation (value = 0x%08lX)"),
12699 (unsigned long) value);
12700 newval = (rs == REG_PC ? T_OPCODE_ADD_PC : T_OPCODE_ADD_SP);
12701 newval |= rd << 8;
12702 newval |= value >> 2;
12703 }
12704 else if (rs == rd)
12705 {
12706 if (value & ~0xff)
12707 as_bad_where (fixP->fx_file, fixP->fx_line,
12708 _("invalid 8bit immediate"));
12709 newval = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
12710 newval |= (rd << 8) | value;
12711 }
12712 else
12713 {
12714 if (value & ~0x7)
12715 as_bad_where (fixP->fx_file, fixP->fx_line,
12716 _("invalid 3bit immediate"));
12717 newval = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
12718 newval |= rd | (rs << 3) | (value << 6);
12719 }
12720 }
12721 md_number_to_chars (buf, newval, THUMB_SIZE);
12722 break;
12723
12724 case BFD_RELOC_ARM_THUMB_IMM:
12725 newval = md_chars_to_number (buf, THUMB_SIZE);
12726 switch (newval >> 11)
12727 {
12728 case 0x04: /* 8bit immediate MOV. */
12729 case 0x05: /* 8bit immediate CMP. */
12730 if (value < 0 || value > 255)
12731 as_bad_where (fixP->fx_file, fixP->fx_line,
12732 _("invalid immediate: %ld is too large"),
12733 (long) value);
12734 newval |= value;
12735 break;
12736
12737 default:
12738 abort ();
12739 }
12740 md_number_to_chars (buf, newval, THUMB_SIZE);
12741 break;
12742
12743 case BFD_RELOC_ARM_THUMB_SHIFT:
12744 /* 5bit shift value (0..31). */
12745 if (value < 0 || value > 31)
12746 as_bad_where (fixP->fx_file, fixP->fx_line,
12747 _("illegal Thumb shift value: %ld"), (long) value);
12748 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xf03f;
12749 newval |= value << 6;
12750 md_number_to_chars (buf, newval, THUMB_SIZE);
12751 break;
12752
12753 case BFD_RELOC_VTABLE_INHERIT:
12754 case BFD_RELOC_VTABLE_ENTRY:
12755 fixP->fx_done = 0;
12756 return;
12757
12758 case BFD_RELOC_NONE:
12759 default:
12760 as_bad_where (fixP->fx_file, fixP->fx_line,
12761 _("bad relocation fixup type (%d)"), fixP->fx_r_type);
12762 }
12763 }
12764
12765 /* Translate internal representation of relocation info to BFD target
12766 format. */
12767
12768 arelent *
12769 tc_gen_reloc (section, fixp)
12770 asection * section ATTRIBUTE_UNUSED;
12771 fixS * fixp;
12772 {
12773 arelent * reloc;
12774 bfd_reloc_code_real_type code;
12775
12776 reloc = (arelent *) xmalloc (sizeof (arelent));
12777
12778 reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
12779 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
12780 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
12781
12782 /* @@ Why fx_addnumber sometimes and fx_offset other times? */
12783 #ifndef OBJ_ELF
12784 if (fixp->fx_pcrel == 0)
12785 reloc->addend = fixp->fx_offset;
12786 else
12787 reloc->addend = fixp->fx_offset = reloc->address;
12788 #else /* OBJ_ELF */
12789 reloc->addend = fixp->fx_offset;
12790 #endif
12791
12792 switch (fixp->fx_r_type)
12793 {
12794 case BFD_RELOC_8:
12795 if (fixp->fx_pcrel)
12796 {
12797 code = BFD_RELOC_8_PCREL;
12798 break;
12799 }
12800
12801 case BFD_RELOC_16:
12802 if (fixp->fx_pcrel)
12803 {
12804 code = BFD_RELOC_16_PCREL;
12805 break;
12806 }
12807
12808 case BFD_RELOC_32:
12809 if (fixp->fx_pcrel)
12810 {
12811 code = BFD_RELOC_32_PCREL;
12812 break;
12813 }
12814
12815 case BFD_RELOC_ARM_PCREL_BRANCH:
12816 case BFD_RELOC_ARM_PCREL_BLX:
12817 case BFD_RELOC_RVA:
12818 case BFD_RELOC_THUMB_PCREL_BRANCH9:
12819 case BFD_RELOC_THUMB_PCREL_BRANCH12:
12820 case BFD_RELOC_THUMB_PCREL_BRANCH23:
12821 case BFD_RELOC_THUMB_PCREL_BLX:
12822 case BFD_RELOC_VTABLE_ENTRY:
12823 case BFD_RELOC_VTABLE_INHERIT:
12824 code = fixp->fx_r_type;
12825 break;
12826
12827 case BFD_RELOC_ARM_LITERAL:
12828 case BFD_RELOC_ARM_HWLITERAL:
12829 /* If this is called then the a literal has
12830 been referenced across a section boundary. */
12831 as_bad_where (fixp->fx_file, fixp->fx_line,
12832 _("literal referenced across section boundary"));
12833 return NULL;
12834
12835 #ifdef OBJ_ELF
12836 case BFD_RELOC_ARM_GOT32:
12837 case BFD_RELOC_ARM_GOTOFF:
12838 case BFD_RELOC_ARM_PLT32:
12839 code = fixp->fx_r_type;
12840 break;
12841 #endif
12842
12843 case BFD_RELOC_ARM_IMMEDIATE:
12844 as_bad_where (fixp->fx_file, fixp->fx_line,
12845 _("internal relocation (type: IMMEDIATE) not fixed up"));
12846 return NULL;
12847
12848 case BFD_RELOC_ARM_ADRL_IMMEDIATE:
12849 as_bad_where (fixp->fx_file, fixp->fx_line,
12850 _("ADRL used for a symbol not defined in the same file"));
12851 return NULL;
12852
12853 case BFD_RELOC_ARM_OFFSET_IMM:
12854 if (fixp->fx_addsy != NULL
12855 && !S_IS_DEFINED (fixp->fx_addsy)
12856 && S_IS_LOCAL (fixp->fx_addsy))
12857 {
12858 as_bad_where (fixp->fx_file, fixp->fx_line,
12859 _("undefined local label `%s'"),
12860 S_GET_NAME (fixp->fx_addsy));
12861 return NULL;
12862 }
12863
12864 as_bad_where (fixp->fx_file, fixp->fx_line,
12865 _("internal_relocation (type: OFFSET_IMM) not fixed up"));
12866 return NULL;
12867
12868 default:
12869 {
12870 char * type;
12871
12872 switch (fixp->fx_r_type)
12873 {
12874 case BFD_RELOC_ARM_OFFSET_IMM8: type = "OFFSET_IMM8"; break;
12875 case BFD_RELOC_ARM_SHIFT_IMM: type = "SHIFT_IMM"; break;
12876 case BFD_RELOC_ARM_SWI: type = "SWI"; break;
12877 case BFD_RELOC_ARM_MULTI: type = "MULTI"; break;
12878 case BFD_RELOC_ARM_CP_OFF_IMM: type = "CP_OFF_IMM"; break;
12879 case BFD_RELOC_ARM_THUMB_ADD: type = "THUMB_ADD"; break;
12880 case BFD_RELOC_ARM_THUMB_SHIFT: type = "THUMB_SHIFT"; break;
12881 case BFD_RELOC_ARM_THUMB_IMM: type = "THUMB_IMM"; break;
12882 case BFD_RELOC_ARM_THUMB_OFFSET: type = "THUMB_OFFSET"; break;
12883 default: type = _("<unknown>"); break;
12884 }
12885 as_bad_where (fixp->fx_file, fixp->fx_line,
12886 _("cannot represent %s relocation in this object file format"),
12887 type);
12888 return NULL;
12889 }
12890 }
12891
12892 #ifdef OBJ_ELF
12893 if ((code == BFD_RELOC_32_PCREL || code == BFD_RELOC_32)
12894 && GOT_symbol
12895 && fixp->fx_addsy == GOT_symbol)
12896 {
12897 code = BFD_RELOC_ARM_GOTPC;
12898 reloc->addend = fixp->fx_offset = reloc->address;
12899 }
12900 #endif
12901
12902 reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
12903
12904 if (reloc->howto == NULL)
12905 {
12906 as_bad_where (fixp->fx_file, fixp->fx_line,
12907 _("cannot represent %s relocation in this object file format"),
12908 bfd_get_reloc_code_name (code));
12909 return NULL;
12910 }
12911
12912 /* HACK: Since arm ELF uses Rel instead of Rela, encode the
12913 vtable entry to be used in the relocation's section offset. */
12914 if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
12915 reloc->address = fixp->fx_offset;
12916
12917 return reloc;
12918 }
12919
12920 int
12921 md_estimate_size_before_relax (fragP, segtype)
12922 fragS * fragP ATTRIBUTE_UNUSED;
12923 segT segtype ATTRIBUTE_UNUSED;
12924 {
12925 as_fatal (_("md_estimate_size_before_relax\n"));
12926 return 1;
12927 }
12928
12929 static void
12930 output_inst (str)
12931 const char *str;
12932 {
12933 char * to = NULL;
12934
12935 if (inst.error)
12936 {
12937 as_bad ("%s -- `%s'", inst.error, str);
12938 return;
12939 }
12940
12941 to = frag_more (inst.size);
12942
12943 if (thumb_mode && (inst.size > THUMB_SIZE))
12944 {
12945 assert (inst.size == (2 * THUMB_SIZE));
12946 md_number_to_chars (to, inst.instruction >> 16, THUMB_SIZE);
12947 md_number_to_chars (to + THUMB_SIZE, inst.instruction, THUMB_SIZE);
12948 }
12949 else if (inst.size > INSN_SIZE)
12950 {
12951 assert (inst.size == (2 * INSN_SIZE));
12952 md_number_to_chars (to, inst.instruction, INSN_SIZE);
12953 md_number_to_chars (to + INSN_SIZE, inst.instruction, INSN_SIZE);
12954 }
12955 else
12956 md_number_to_chars (to, inst.instruction, inst.size);
12957
12958 if (inst.reloc.type != BFD_RELOC_NONE)
12959 fix_new_arm (frag_now, to - frag_now->fr_literal,
12960 inst.size, & inst.reloc.exp, inst.reloc.pc_rel,
12961 inst.reloc.type);
12962
12963 #ifdef OBJ_ELF
12964 dwarf2_emit_insn (inst.size);
12965 #endif
12966 }
12967
12968 void
12969 md_assemble (str)
12970 char * str;
12971 {
12972 char c;
12973 char *p;
12974 char *start;
12975
12976 /* Align the instruction.
12977 This may not be the right thing to do but ... */
12978 #if 0
12979 arm_align (2, 0);
12980 #endif
12981
12982 /* Align the previous label if needed. */
12983 if (last_label_seen != NULL)
12984 {
12985 symbol_set_frag (last_label_seen, frag_now);
12986 S_SET_VALUE (last_label_seen, (valueT) frag_now_fix ());
12987 S_SET_SEGMENT (last_label_seen, now_seg);
12988 }
12989
12990 memset (&inst, '\0', sizeof (inst));
12991 inst.reloc.type = BFD_RELOC_NONE;
12992
12993 skip_whitespace (str);
12994
12995 /* Scan up to the end of the op-code, which must end in white space or
12996 end of string. */
12997 for (start = p = str; *p != '\0'; p++)
12998 if (*p == ' ')
12999 break;
13000
13001 if (p == str)
13002 {
13003 as_bad (_("no operator -- statement `%s'\n"), str);
13004 return;
13005 }
13006
13007 if (thumb_mode)
13008 {
13009 const struct thumb_opcode * opcode;
13010
13011 c = *p;
13012 *p = '\0';
13013 opcode = (const struct thumb_opcode *) hash_find (arm_tops_hsh, str);
13014 *p = c;
13015
13016 if (opcode)
13017 {
13018 /* Check that this instruction is supported for this CPU. */
13019 if (thumb_mode == 1 && (opcode->variant & cpu_variant) == 0)
13020 {
13021 as_bad (_("selected processor does not support `%s'"), str);
13022 return;
13023 }
13024
13025 mapping_state (MAP_THUMB);
13026 inst.instruction = opcode->value;
13027 inst.size = opcode->size;
13028 (*opcode->parms) (p);
13029 output_inst (str);
13030 return;
13031 }
13032 }
13033 else
13034 {
13035 const struct asm_opcode * opcode;
13036
13037 c = *p;
13038 *p = '\0';
13039 opcode = (const struct asm_opcode *) hash_find (arm_ops_hsh, str);
13040 *p = c;
13041
13042 if (opcode)
13043 {
13044 /* Check that this instruction is supported for this CPU. */
13045 if ((opcode->variant & cpu_variant) == 0)
13046 {
13047 as_bad (_("selected processor does not support `%s'"), str);
13048 return;
13049 }
13050
13051 mapping_state (MAP_ARM);
13052 inst.instruction = opcode->value;
13053 inst.size = INSN_SIZE;
13054 (*opcode->parms) (p);
13055 output_inst (str);
13056 return;
13057 }
13058 }
13059
13060 /* It wasn't an instruction, but it might be a register alias of the form
13061 alias .req reg. */
13062 if (create_register_alias (str, p))
13063 return;
13064
13065 as_bad (_("bad instruction `%s'"), start);
13066 }
13067
13068 /* md_parse_option
13069 Invocation line includes a switch not recognized by the base assembler.
13070 See if it's a processor-specific option.
13071
13072 This routine is somewhat complicated by the need for backwards
13073 compatibility (since older releases of gcc can't be changed).
13074 The new options try to make the interface as compatible as
13075 possible with GCC.
13076
13077 New options (supported) are:
13078
13079 -mcpu=<cpu name> Assemble for selected processor
13080 -march=<architecture name> Assemble for selected architecture
13081 -mfpu=<fpu architecture> Assemble for selected FPU.
13082 -EB/-mbig-endian Big-endian
13083 -EL/-mlittle-endian Little-endian
13084 -k Generate PIC code
13085 -mthumb Start in Thumb mode
13086 -mthumb-interwork Code supports ARM/Thumb interworking
13087
13088 For now we will also provide support for:
13089
13090 -mapcs-32 32-bit Program counter
13091 -mapcs-26 26-bit Program counter
13092 -macps-float Floats passed in FP registers
13093 -mapcs-reentrant Reentrant code
13094 -matpcs
13095 (sometime these will probably be replaced with -mapcs=<list of options>
13096 and -matpcs=<list of options>)
13097
13098 The remaining options are only supported for back-wards compatibility.
13099 Cpu variants, the arm part is optional:
13100 -m[arm]1 Currently not supported.
13101 -m[arm]2, -m[arm]250 Arm 2 and Arm 250 processor
13102 -m[arm]3 Arm 3 processor
13103 -m[arm]6[xx], Arm 6 processors
13104 -m[arm]7[xx][t][[d]m] Arm 7 processors
13105 -m[arm]8[10] Arm 8 processors
13106 -m[arm]9[20][tdmi] Arm 9 processors
13107 -mstrongarm[110[0]] StrongARM processors
13108 -mxscale XScale processors
13109 -m[arm]v[2345[t[e]]] Arm architectures
13110 -mall All (except the ARM1)
13111 FP variants:
13112 -mfpa10, -mfpa11 FPA10 and 11 co-processor instructions
13113 -mfpe-old (No float load/store multiples)
13114 -mvfpxd VFP Single precision
13115 -mvfp All VFP
13116 -mno-fpu Disable all floating point instructions
13117
13118 The following CPU names are recognized:
13119 arm1, arm2, arm250, arm3, arm6, arm600, arm610, arm620,
13120 arm7, arm7m, arm7d, arm7dm, arm7di, arm7dmi, arm70, arm700,
13121 arm700i, arm710 arm710t, arm720, arm720t, arm740t, arm710c,
13122 arm7100, arm7500, arm7500fe, arm7tdmi, arm8, arm810, arm9,
13123 arm920, arm920t, arm940t, arm946, arm966, arm9tdmi, arm9e,
13124 arm10t arm10e, arm1020t, arm1020e, arm10200e,
13125 strongarm, strongarm110, strongarm1100, strongarm1110, xscale.
13126
13127 */
13128
13129 const char * md_shortopts = "m:k";
13130
13131 #ifdef ARM_BI_ENDIAN
13132 #define OPTION_EB (OPTION_MD_BASE + 0)
13133 #define OPTION_EL (OPTION_MD_BASE + 1)
13134 #else
13135 #if TARGET_BYTES_BIG_ENDIAN
13136 #define OPTION_EB (OPTION_MD_BASE + 0)
13137 #else
13138 #define OPTION_EL (OPTION_MD_BASE + 1)
13139 #endif
13140 #endif
13141
13142 struct option md_longopts[] =
13143 {
13144 #ifdef OPTION_EB
13145 {"EB", no_argument, NULL, OPTION_EB},
13146 #endif
13147 #ifdef OPTION_EL
13148 {"EL", no_argument, NULL, OPTION_EL},
13149 #endif
13150 {NULL, no_argument, NULL, 0}
13151 };
13152
13153 size_t md_longopts_size = sizeof (md_longopts);
13154
13155 struct arm_option_table
13156 {
13157 char *option; /* Option name to match. */
13158 char *help; /* Help information. */
13159 int *var; /* Variable to change. */
13160 int value; /* What to change it to. */
13161 char *deprecated; /* If non-null, print this message. */
13162 };
13163
13164 struct arm_option_table arm_opts[] =
13165 {
13166 {"k", N_("generate PIC code"), &pic_code, 1, NULL},
13167 {"mthumb", N_("assemble Thumb code"), &thumb_mode, 1, NULL},
13168 {"mthumb-interwork", N_("support ARM/Thumb interworking"),
13169 &support_interwork, 1, NULL},
13170 {"moabi", N_("use old ABI (ELF only)"), &target_oabi, 1, NULL},
13171 {"mapcs-32", N_("code uses 32-bit program counter"), &uses_apcs_26, 0, NULL},
13172 {"mapcs-26", N_("code uses 26-bit program counter"), &uses_apcs_26, 1, NULL},
13173 {"mapcs-float", N_("floating point args are in fp regs"), &uses_apcs_float,
13174 1, NULL},
13175 {"mapcs-reentrant", N_("re-entrant code"), &pic_code, 1, NULL},
13176 {"matpcs", N_("code is ATPCS conformant"), &atpcs, 1, NULL},
13177 {"mbig-endian", N_("assemble for big-endian"), &target_big_endian, 1, NULL},
13178 {"mlittle-endian", N_("assemble for little-endian"), &target_big_endian, 1,
13179 NULL},
13180
13181 /* These are recognized by the assembler, but have no affect on code. */
13182 {"mapcs-frame", N_("use frame pointer"), NULL, 0, NULL},
13183 {"mapcs-stack-check", N_("use stack size checking"), NULL, 0, NULL},
13184
13185 /* DON'T add any new processors to this list -- we want the whole list
13186 to go away... Add them to the processors table instead. */
13187 {"marm1", NULL, &legacy_cpu, ARM_ARCH_V1, N_("use -mcpu=arm1")},
13188 {"m1", NULL, &legacy_cpu, ARM_ARCH_V1, N_("use -mcpu=arm1")},
13189 {"marm2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -mcpu=arm2")},
13190 {"m2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -mcpu=arm2")},
13191 {"marm250", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm250")},
13192 {"m250", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm250")},
13193 {"marm3", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm3")},
13194 {"m3", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm3")},
13195 {"marm6", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm6")},
13196 {"m6", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm6")},
13197 {"marm600", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm600")},
13198 {"m600", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm600")},
13199 {"marm610", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm610")},
13200 {"m610", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm610")},
13201 {"marm620", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm620")},
13202 {"m620", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm620")},
13203 {"marm7", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7")},
13204 {"m7", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7")},
13205 {"marm70", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm70")},
13206 {"m70", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm70")},
13207 {"marm700", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700")},
13208 {"m700", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700")},
13209 {"marm700i", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700i")},
13210 {"m700i", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700i")},
13211 {"marm710", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710")},
13212 {"m710", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710")},
13213 {"marm710c", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710c")},
13214 {"m710c", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710c")},
13215 {"marm720", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm720")},
13216 {"m720", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm720")},
13217 {"marm7d", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7d")},
13218 {"m7d", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7d")},
13219 {"marm7di", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7di")},
13220 {"m7di", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7di")},
13221 {"marm7m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7m")},
13222 {"m7m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7m")},
13223 {"marm7dm", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dm")},
13224 {"m7dm", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dm")},
13225 {"marm7dmi", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dmi")},
13226 {"m7dmi", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dmi")},
13227 {"marm7100", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7100")},
13228 {"m7100", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7100")},
13229 {"marm7500", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500")},
13230 {"m7500", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500")},
13231 {"marm7500fe", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500fe")},
13232 {"m7500fe", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500fe")},
13233 {"marm7t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
13234 {"m7t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
13235 {"marm7tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
13236 {"m7tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
13237 {"marm710t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm710t")},
13238 {"m710t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm710t")},
13239 {"marm720t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm720t")},
13240 {"m720t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm720t")},
13241 {"marm740t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm740t")},
13242 {"m740t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm740t")},
13243 {"marm8", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm8")},
13244 {"m8", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm8")},
13245 {"marm810", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm810")},
13246 {"m810", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm810")},
13247 {"marm9", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9")},
13248 {"m9", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9")},
13249 {"marm9tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9tdmi")},
13250 {"m9tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9tdmi")},
13251 {"marm920", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm920")},
13252 {"m920", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm920")},
13253 {"marm940", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm940")},
13254 {"m940", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm940")},
13255 {"mstrongarm", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=strongarm")},
13256 {"mstrongarm110", NULL, &legacy_cpu, ARM_ARCH_V4,
13257 N_("use -mcpu=strongarm110")},
13258 {"mstrongarm1100", NULL, &legacy_cpu, ARM_ARCH_V4,
13259 N_("use -mcpu=strongarm1100")},
13260 {"mstrongarm1110", NULL, &legacy_cpu, ARM_ARCH_V4,
13261 N_("use -mcpu=strongarm1110")},
13262 {"mxscale", NULL, &legacy_cpu, ARM_ARCH_XSCALE, N_("use -mcpu=xscale")},
13263 {"miwmmxt", NULL, &legacy_cpu, ARM_ARCH_IWMMXT, N_("use -mcpu=iwmmxt")},
13264 {"mall", NULL, &legacy_cpu, ARM_ANY, N_("use -mcpu=all")},
13265
13266 /* Architecture variants -- don't add any more to this list either. */
13267 {"mv2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -march=armv2")},
13268 {"marmv2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -march=armv2")},
13269 {"mv2a", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -march=armv2a")},
13270 {"marmv2a", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -march=armv2a")},
13271 {"mv3", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -march=armv3")},
13272 {"marmv3", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -march=armv3")},
13273 {"mv3m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -march=armv3m")},
13274 {"marmv3m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -march=armv3m")},
13275 {"mv4", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -march=armv4")},
13276 {"marmv4", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -march=armv4")},
13277 {"mv4t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -march=armv4t")},
13278 {"marmv4t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -march=armv4t")},
13279 {"mv5", NULL, &legacy_cpu, ARM_ARCH_V5, N_("use -march=armv5")},
13280 {"marmv5", NULL, &legacy_cpu, ARM_ARCH_V5, N_("use -march=armv5")},
13281 {"mv5t", NULL, &legacy_cpu, ARM_ARCH_V5T, N_("use -march=armv5t")},
13282 {"marmv5t", NULL, &legacy_cpu, ARM_ARCH_V5T, N_("use -march=armv5t")},
13283 {"mv5e", NULL, &legacy_cpu, ARM_ARCH_V5TE, N_("use -march=armv5te")},
13284 {"marmv5e", NULL, &legacy_cpu, ARM_ARCH_V5TE, N_("use -march=armv5te")},
13285
13286 /* Floating point variants -- don't add any more to this list either. */
13287 {"mfpe-old", NULL, &legacy_fpu, FPU_ARCH_FPE, N_("use -mfpu=fpe")},
13288 {"mfpa10", NULL, &legacy_fpu, FPU_ARCH_FPA, N_("use -mfpu=fpa10")},
13289 {"mfpa11", NULL, &legacy_fpu, FPU_ARCH_FPA, N_("use -mfpu=fpa11")},
13290 {"mno-fpu", NULL, &legacy_fpu, 0,
13291 N_("use either -mfpu=softfpa or -mfpu=softvfp")},
13292
13293 {NULL, NULL, NULL, 0, NULL}
13294 };
13295
13296 struct arm_cpu_option_table
13297 {
13298 char *name;
13299 int value;
13300 /* For some CPUs we assume an FPU unless the user explicitly sets
13301 -mfpu=... */
13302 int default_fpu;
13303 };
13304
13305 /* This list should, at a minimum, contain all the cpu names
13306 recognized by GCC. */
13307 static struct arm_cpu_option_table arm_cpus[] =
13308 {
13309 {"all", ARM_ANY, FPU_ARCH_FPA},
13310 {"arm1", ARM_ARCH_V1, FPU_ARCH_FPA},
13311 {"arm2", ARM_ARCH_V2, FPU_ARCH_FPA},
13312 {"arm250", ARM_ARCH_V2S, FPU_ARCH_FPA},
13313 {"arm3", ARM_ARCH_V2S, FPU_ARCH_FPA},
13314 {"arm6", ARM_ARCH_V3, FPU_ARCH_FPA},
13315 {"arm60", ARM_ARCH_V3, FPU_ARCH_FPA},
13316 {"arm600", ARM_ARCH_V3, FPU_ARCH_FPA},
13317 {"arm610", ARM_ARCH_V3, FPU_ARCH_FPA},
13318 {"arm620", ARM_ARCH_V3, FPU_ARCH_FPA},
13319 {"arm7", ARM_ARCH_V3, FPU_ARCH_FPA},
13320 {"arm7m", ARM_ARCH_V3M, FPU_ARCH_FPA},
13321 {"arm7d", ARM_ARCH_V3, FPU_ARCH_FPA},
13322 {"arm7dm", ARM_ARCH_V3M, FPU_ARCH_FPA},
13323 {"arm7di", ARM_ARCH_V3, FPU_ARCH_FPA},
13324 {"arm7dmi", ARM_ARCH_V3M, FPU_ARCH_FPA},
13325 {"arm70", ARM_ARCH_V3, FPU_ARCH_FPA},
13326 {"arm700", ARM_ARCH_V3, FPU_ARCH_FPA},
13327 {"arm700i", ARM_ARCH_V3, FPU_ARCH_FPA},
13328 {"arm710", ARM_ARCH_V3, FPU_ARCH_FPA},
13329 {"arm710t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13330 {"arm720", ARM_ARCH_V3, FPU_ARCH_FPA},
13331 {"arm720t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13332 {"arm740t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13333 {"arm710c", ARM_ARCH_V3, FPU_ARCH_FPA},
13334 {"arm7100", ARM_ARCH_V3, FPU_ARCH_FPA},
13335 {"arm7500", ARM_ARCH_V3, FPU_ARCH_FPA},
13336 {"arm7500fe", ARM_ARCH_V3, FPU_ARCH_FPA},
13337 {"arm7t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13338 {"arm7tdmi", ARM_ARCH_V4T, FPU_ARCH_FPA},
13339 {"arm8", ARM_ARCH_V4, FPU_ARCH_FPA},
13340 {"arm810", ARM_ARCH_V4, FPU_ARCH_FPA},
13341 {"strongarm", ARM_ARCH_V4, FPU_ARCH_FPA},
13342 {"strongarm1", ARM_ARCH_V4, FPU_ARCH_FPA},
13343 {"strongarm110", ARM_ARCH_V4, FPU_ARCH_FPA},
13344 {"strongarm1100", ARM_ARCH_V4, FPU_ARCH_FPA},
13345 {"strongarm1110", ARM_ARCH_V4, FPU_ARCH_FPA},
13346 {"arm9", ARM_ARCH_V4T, FPU_ARCH_FPA},
13347 {"arm920", ARM_ARCH_V4T, FPU_ARCH_FPA},
13348 {"arm920t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13349 {"arm922t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13350 {"arm940t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13351 {"arm9tdmi", ARM_ARCH_V4T, FPU_ARCH_FPA},
13352 /* For V5 or later processors we default to using VFP; but the user
13353 should really set the FPU type explicitly. */
13354 {"arm9e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
13355 {"arm9e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13356 {"arm926ej", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
13357 {"arm926ejs", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
13358 {"arm946e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
13359 {"arm946e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13360 {"arm966e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
13361 {"arm966e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13362 {"arm10t", ARM_ARCH_V5T, FPU_ARCH_VFP_V1},
13363 {"arm10e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13364 {"arm1020", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13365 {"arm1020t", ARM_ARCH_V5T, FPU_ARCH_VFP_V1},
13366 {"arm1020e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13367 {"arm1026ejs", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13368 {"arm1136js", ARM_ARCH_V6, FPU_NONE},
13369 {"arm1136jfs", ARM_ARCH_V6, FPU_ARCH_VFP_V2},
13370 /* ??? XSCALE is really an architecture. */
13371 {"xscale", ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2},
13372 /* ??? iwmmxt is not a processor. */
13373 {"iwmmxt", ARM_ARCH_IWMMXT, FPU_ARCH_VFP_V2},
13374 {"i80200", ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2},
13375 /* Maverick */
13376 {"ep9312", ARM_ARCH_V4T | ARM_CEXT_MAVERICK, FPU_ARCH_MAVERICK},
13377 {NULL, 0, 0}
13378 };
13379
13380 struct arm_arch_option_table
13381 {
13382 char *name;
13383 int value;
13384 int default_fpu;
13385 };
13386
13387 /* This list should, at a minimum, contain all the architecture names
13388 recognized by GCC. */
13389 static struct arm_arch_option_table arm_archs[] =
13390 {
13391 {"all", ARM_ANY, FPU_ARCH_FPA},
13392 {"armv1", ARM_ARCH_V1, FPU_ARCH_FPA},
13393 {"armv2", ARM_ARCH_V2, FPU_ARCH_FPA},
13394 {"armv2a", ARM_ARCH_V2S, FPU_ARCH_FPA},
13395 {"armv2s", ARM_ARCH_V2S, FPU_ARCH_FPA},
13396 {"armv3", ARM_ARCH_V3, FPU_ARCH_FPA},
13397 {"armv3m", ARM_ARCH_V3M, FPU_ARCH_FPA},
13398 {"armv4", ARM_ARCH_V4, FPU_ARCH_FPA},
13399 {"armv4xm", ARM_ARCH_V4xM, FPU_ARCH_FPA},
13400 {"armv4t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13401 {"armv4txm", ARM_ARCH_V4TxM, FPU_ARCH_FPA},
13402 {"armv5", ARM_ARCH_V5, FPU_ARCH_VFP},
13403 {"armv5t", ARM_ARCH_V5T, FPU_ARCH_VFP},
13404 {"armv5txm", ARM_ARCH_V5TxM, FPU_ARCH_VFP},
13405 {"armv5te", ARM_ARCH_V5TE, FPU_ARCH_VFP},
13406 {"armv5texp", ARM_ARCH_V5TExP, FPU_ARCH_VFP},
13407 {"armv5tej", ARM_ARCH_V5TEJ, FPU_ARCH_VFP},
13408 {"armv6", ARM_ARCH_V6, FPU_ARCH_VFP},
13409 {"armv6j", ARM_ARCH_V6, FPU_ARCH_VFP},
13410 {"xscale", ARM_ARCH_XSCALE, FPU_ARCH_VFP},
13411 {"iwmmxt", ARM_ARCH_IWMMXT, FPU_ARCH_VFP},
13412 {NULL, 0, 0}
13413 };
13414
13415 /* ISA extensions in the co-processor space. */
13416 struct arm_arch_extension_table
13417 {
13418 char *name;
13419 int value;
13420 };
13421
13422 static struct arm_arch_extension_table arm_extensions[] =
13423 {
13424 {"maverick", ARM_CEXT_MAVERICK},
13425 {"xscale", ARM_CEXT_XSCALE},
13426 {"iwmmxt", ARM_CEXT_IWMMXT},
13427 {NULL, 0}
13428 };
13429
13430 struct arm_fpu_option_table
13431 {
13432 char *name;
13433 int value;
13434 };
13435
13436 /* This list should, at a minimum, contain all the fpu names
13437 recognized by GCC. */
13438 static struct arm_fpu_option_table arm_fpus[] =
13439 {
13440 {"softfpa", FPU_NONE},
13441 {"fpe", FPU_ARCH_FPE},
13442 {"fpe2", FPU_ARCH_FPE},
13443 {"fpe3", FPU_ARCH_FPA}, /* Third release supports LFM/SFM. */
13444 {"fpa", FPU_ARCH_FPA},
13445 {"fpa10", FPU_ARCH_FPA},
13446 {"fpa11", FPU_ARCH_FPA},
13447 {"arm7500fe", FPU_ARCH_FPA},
13448 {"softvfp", FPU_ARCH_VFP},
13449 {"softvfp+vfp", FPU_ARCH_VFP_V2},
13450 {"vfp", FPU_ARCH_VFP_V2},
13451 {"vfp9", FPU_ARCH_VFP_V2},
13452 {"vfp10", FPU_ARCH_VFP_V2},
13453 {"vfp10-r0", FPU_ARCH_VFP_V1},
13454 {"vfpxd", FPU_ARCH_VFP_V1xD},
13455 {"arm1020t", FPU_ARCH_VFP_V1},
13456 {"arm1020e", FPU_ARCH_VFP_V2},
13457 {"arm1136jfs", FPU_ARCH_VFP_V2},
13458 {"maverick", FPU_ARCH_MAVERICK},
13459 {NULL, 0}
13460 };
13461
13462 struct arm_float_abi_option_table
13463 {
13464 char *name;
13465 int value;
13466 };
13467
13468 static struct arm_float_abi_option_table arm_float_abis[] =
13469 {
13470 {"hard", ARM_FLOAT_ABI_HARD},
13471 {"softfp", ARM_FLOAT_ABI_SOFTFP},
13472 {"soft", ARM_FLOAT_ABI_SOFT},
13473 {NULL, 0}
13474 };
13475
13476 struct arm_eabi_option_table
13477 {
13478 char *name;
13479 unsigned int value;
13480 };
13481
13482 #ifdef OBJ_ELF
13483 /* We only know hot to output GNU and ver 3 (AAELF) formats. */
13484 static struct arm_eabi_option_table arm_eabis[] =
13485 {
13486 {"gnu", EF_ARM_EABI_UNKNOWN},
13487 {"3", EF_ARM_EABI_VER3},
13488 {NULL, 0}
13489 };
13490 #endif
13491
13492 struct arm_long_option_table
13493 {
13494 char *option; /* Substring to match. */
13495 char *help; /* Help information. */
13496 int (*func) PARAMS ((char *subopt)); /* Function to decode sub-option. */
13497 char *deprecated; /* If non-null, print this message. */
13498 };
13499
13500 static int
13501 arm_parse_extension (str, opt_p)
13502 char *str;
13503 int *opt_p;
13504 {
13505 while (str != NULL && *str != 0)
13506 {
13507 struct arm_arch_extension_table *opt;
13508 char *ext;
13509 int optlen;
13510
13511 if (*str != '+')
13512 {
13513 as_bad (_("invalid architectural extension"));
13514 return 0;
13515 }
13516
13517 str++;
13518 ext = strchr (str, '+');
13519
13520 if (ext != NULL)
13521 optlen = ext - str;
13522 else
13523 optlen = strlen (str);
13524
13525 if (optlen == 0)
13526 {
13527 as_bad (_("missing architectural extension"));
13528 return 0;
13529 }
13530
13531 for (opt = arm_extensions; opt->name != NULL; opt++)
13532 if (strncmp (opt->name, str, optlen) == 0)
13533 {
13534 *opt_p |= opt->value;
13535 break;
13536 }
13537
13538 if (opt->name == NULL)
13539 {
13540 as_bad (_("unknown architectural extnsion `%s'"), str);
13541 return 0;
13542 }
13543
13544 str = ext;
13545 };
13546
13547 return 1;
13548 }
13549
13550 static int
13551 arm_parse_cpu (str)
13552 char *str;
13553 {
13554 struct arm_cpu_option_table *opt;
13555 char *ext = strchr (str, '+');
13556 int optlen;
13557
13558 if (ext != NULL)
13559 optlen = ext - str;
13560 else
13561 optlen = strlen (str);
13562
13563 if (optlen == 0)
13564 {
13565 as_bad (_("missing cpu name `%s'"), str);
13566 return 0;
13567 }
13568
13569 for (opt = arm_cpus; opt->name != NULL; opt++)
13570 if (strncmp (opt->name, str, optlen) == 0)
13571 {
13572 mcpu_cpu_opt = opt->value;
13573 mcpu_fpu_opt = opt->default_fpu;
13574
13575 if (ext != NULL)
13576 return arm_parse_extension (ext, &mcpu_cpu_opt);
13577
13578 return 1;
13579 }
13580
13581 as_bad (_("unknown cpu `%s'"), str);
13582 return 0;
13583 }
13584
13585 static int
13586 arm_parse_arch (str)
13587 char *str;
13588 {
13589 struct arm_arch_option_table *opt;
13590 char *ext = strchr (str, '+');
13591 int optlen;
13592
13593 if (ext != NULL)
13594 optlen = ext - str;
13595 else
13596 optlen = strlen (str);
13597
13598 if (optlen == 0)
13599 {
13600 as_bad (_("missing architecture name `%s'"), str);
13601 return 0;
13602 }
13603
13604
13605 for (opt = arm_archs; opt->name != NULL; opt++)
13606 if (strcmp (opt->name, str) == 0)
13607 {
13608 march_cpu_opt = opt->value;
13609 march_fpu_opt = opt->default_fpu;
13610
13611 if (ext != NULL)
13612 return arm_parse_extension (ext, &march_cpu_opt);
13613
13614 return 1;
13615 }
13616
13617 as_bad (_("unknown architecture `%s'\n"), str);
13618 return 0;
13619 }
13620
13621 static int
13622 arm_parse_fpu (str)
13623 char *str;
13624 {
13625 struct arm_fpu_option_table *opt;
13626
13627 for (opt = arm_fpus; opt->name != NULL; opt++)
13628 if (strcmp (opt->name, str) == 0)
13629 {
13630 mfpu_opt = opt->value;
13631 return 1;
13632 }
13633
13634 as_bad (_("unknown floating point format `%s'\n"), str);
13635 return 0;
13636 }
13637
13638 static int
13639 arm_parse_float_abi (str)
13640 char * str;
13641 {
13642 struct arm_float_abi_option_table *opt;
13643
13644 for (opt = arm_float_abis; opt->name != NULL; opt++)
13645 if (strcmp (opt->name, str) == 0)
13646 {
13647 mfloat_abi_opt = opt->value;
13648 return 1;
13649 }
13650
13651 as_bad (_("unknown floating point abi `%s'\n"), str);
13652 return 0;
13653 }
13654
13655 #ifdef OBJ_ELF
13656 static int
13657 arm_parse_eabi (str)
13658 char * str;
13659 {
13660 struct arm_eabi_option_table *opt;
13661
13662 for (opt = arm_eabis; opt->name != NULL; opt++)
13663 if (strcmp (opt->name, str) == 0)
13664 {
13665 meabi_flags = opt->value;
13666 return 1;
13667 }
13668 as_bad (_("unknown EABI `%s'\n"), str);
13669 return 0;
13670 }
13671 #endif
13672
13673 struct arm_long_option_table arm_long_opts[] =
13674 {
13675 {"mcpu=", N_("<cpu name>\t assemble for CPU <cpu name>"),
13676 arm_parse_cpu, NULL},
13677 {"march=", N_("<arch name>\t assemble for architecture <arch name>"),
13678 arm_parse_arch, NULL},
13679 {"mfpu=", N_("<fpu name>\t assemble for FPU architecture <fpu name>"),
13680 arm_parse_fpu, NULL},
13681 {"mfloat-abi=", N_("<abi>\t assemble for floating point ABI <abi>"),
13682 arm_parse_float_abi, NULL},
13683 #ifdef OBJ_ELF
13684 {"meabi=", N_("<ver>\t assemble for eabi version <ver>"),
13685 arm_parse_eabi, NULL},
13686 #endif
13687 {NULL, NULL, 0, NULL}
13688 };
13689
13690 int
13691 md_parse_option (c, arg)
13692 int c;
13693 char * arg;
13694 {
13695 struct arm_option_table *opt;
13696 struct arm_long_option_table *lopt;
13697
13698 switch (c)
13699 {
13700 #ifdef OPTION_EB
13701 case OPTION_EB:
13702 target_big_endian = 1;
13703 break;
13704 #endif
13705
13706 #ifdef OPTION_EL
13707 case OPTION_EL:
13708 target_big_endian = 0;
13709 break;
13710 #endif
13711
13712 case 'a':
13713 /* Listing option. Just ignore these, we don't support additional
13714 ones. */
13715 return 0;
13716
13717 default:
13718 for (opt = arm_opts; opt->option != NULL; opt++)
13719 {
13720 if (c == opt->option[0]
13721 && ((arg == NULL && opt->option[1] == 0)
13722 || strcmp (arg, opt->option + 1) == 0))
13723 {
13724 #if WARN_DEPRECATED
13725 /* If the option is deprecated, tell the user. */
13726 if (opt->deprecated != NULL)
13727 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c,
13728 arg ? arg : "", _(opt->deprecated));
13729 #endif
13730
13731 if (opt->var != NULL)
13732 *opt->var = opt->value;
13733
13734 return 1;
13735 }
13736 }
13737
13738 for (lopt = arm_long_opts; lopt->option != NULL; lopt++)
13739 {
13740 /* These options are expected to have an argument. */
13741 if (c == lopt->option[0]
13742 && arg != NULL
13743 && strncmp (arg, lopt->option + 1,
13744 strlen (lopt->option + 1)) == 0)
13745 {
13746 #if WARN_DEPRECATED
13747 /* If the option is deprecated, tell the user. */
13748 if (lopt->deprecated != NULL)
13749 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c, arg,
13750 _(lopt->deprecated));
13751 #endif
13752
13753 /* Call the sup-option parser. */
13754 return (*lopt->func)(arg + strlen (lopt->option) - 1);
13755 }
13756 }
13757
13758 as_bad (_("unrecognized option `-%c%s'"), c, arg ? arg : "");
13759 return 0;
13760 }
13761
13762 return 1;
13763 }
13764
13765 void
13766 md_show_usage (fp)
13767 FILE * fp;
13768 {
13769 struct arm_option_table *opt;
13770 struct arm_long_option_table *lopt;
13771
13772 fprintf (fp, _(" ARM-specific assembler options:\n"));
13773
13774 for (opt = arm_opts; opt->option != NULL; opt++)
13775 if (opt->help != NULL)
13776 fprintf (fp, " -%-23s%s\n", opt->option, _(opt->help));
13777
13778 for (lopt = arm_long_opts; lopt->option != NULL; lopt++)
13779 if (lopt->help != NULL)
13780 fprintf (fp, " -%s%s\n", lopt->option, _(lopt->help));
13781
13782 #ifdef OPTION_EB
13783 fprintf (fp, _("\
13784 -EB assemble code for a big-endian cpu\n"));
13785 #endif
13786
13787 #ifdef OPTION_EL
13788 fprintf (fp, _("\
13789 -EL assemble code for a little-endian cpu\n"));
13790 #endif
13791 }
13792
13793 /* We need to be able to fix up arbitrary expressions in some statements.
13794 This is so that we can handle symbols that are an arbitrary distance from
13795 the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
13796 which returns part of an address in a form which will be valid for
13797 a data instruction. We do this by pushing the expression into a symbol
13798 in the expr_section, and creating a fix for that. */
13799
13800 static void
13801 fix_new_arm (frag, where, size, exp, pc_rel, reloc)
13802 fragS * frag;
13803 int where;
13804 short int size;
13805 expressionS * exp;
13806 int pc_rel;
13807 int reloc;
13808 {
13809 fixS * new_fix;
13810 arm_fix_data * arm_data;
13811
13812 switch (exp->X_op)
13813 {
13814 case O_constant:
13815 case O_symbol:
13816 case O_add:
13817 case O_subtract:
13818 new_fix = fix_new_exp (frag, where, size, exp, pc_rel, reloc);
13819 break;
13820
13821 default:
13822 new_fix = fix_new (frag, where, size, make_expr_symbol (exp), 0,
13823 pc_rel, reloc);
13824 break;
13825 }
13826
13827 /* Mark whether the fix is to a THUMB instruction, or an ARM
13828 instruction. */
13829 arm_data = (arm_fix_data *) obstack_alloc (& notes, sizeof (arm_fix_data));
13830 new_fix->tc_fix_data = (PTR) arm_data;
13831 arm_data->thumb_mode = thumb_mode;
13832 }
13833
13834 /* This fix_new is called by cons via TC_CONS_FIX_NEW. */
13835
13836 void
13837 cons_fix_new_arm (frag, where, size, exp)
13838 fragS * frag;
13839 int where;
13840 int size;
13841 expressionS * exp;
13842 {
13843 bfd_reloc_code_real_type type;
13844 int pcrel = 0;
13845
13846 /* Pick a reloc.
13847 FIXME: @@ Should look at CPU word size. */
13848 switch (size)
13849 {
13850 case 1:
13851 type = BFD_RELOC_8;
13852 break;
13853 case 2:
13854 type = BFD_RELOC_16;
13855 break;
13856 case 4:
13857 default:
13858 type = BFD_RELOC_32;
13859 break;
13860 case 8:
13861 type = BFD_RELOC_64;
13862 break;
13863 }
13864
13865 fix_new_exp (frag, where, (int) size, exp, pcrel, type);
13866 }
13867
13868 /* A good place to do this, although this was probably not intended
13869 for this kind of use. We need to dump the literal pool before
13870 references are made to a null symbol pointer. */
13871
13872 void
13873 arm_cleanup ()
13874 {
13875 literal_pool * pool;
13876
13877 for (pool = list_of_pools; pool; pool = pool->next)
13878 {
13879 /* Put it at the end of the relevent section. */
13880 subseg_set (pool->section, pool->sub_section);
13881 s_ltorg (0);
13882 }
13883 }
13884
13885 void
13886 arm_start_line_hook ()
13887 {
13888 last_label_seen = NULL;
13889 }
13890
13891 void
13892 arm_frob_label (sym)
13893 symbolS * sym;
13894 {
13895 last_label_seen = sym;
13896
13897 ARM_SET_THUMB (sym, thumb_mode);
13898
13899 #if defined OBJ_COFF || defined OBJ_ELF
13900 ARM_SET_INTERWORK (sym, support_interwork);
13901 #endif
13902
13903 /* Note - do not allow local symbols (.Lxxx) to be labeled
13904 as Thumb functions. This is because these labels, whilst
13905 they exist inside Thumb code, are not the entry points for
13906 possible ARM->Thumb calls. Also, these labels can be used
13907 as part of a computed goto or switch statement. eg gcc
13908 can generate code that looks like this:
13909
13910 ldr r2, [pc, .Laaa]
13911 lsl r3, r3, #2
13912 ldr r2, [r3, r2]
13913 mov pc, r2
13914
13915 .Lbbb: .word .Lxxx
13916 .Lccc: .word .Lyyy
13917 ..etc...
13918 .Laaa: .word Lbbb
13919
13920 The first instruction loads the address of the jump table.
13921 The second instruction converts a table index into a byte offset.
13922 The third instruction gets the jump address out of the table.
13923 The fourth instruction performs the jump.
13924
13925 If the address stored at .Laaa is that of a symbol which has the
13926 Thumb_Func bit set, then the linker will arrange for this address
13927 to have the bottom bit set, which in turn would mean that the
13928 address computation performed by the third instruction would end
13929 up with the bottom bit set. Since the ARM is capable of unaligned
13930 word loads, the instruction would then load the incorrect address
13931 out of the jump table, and chaos would ensue. */
13932 if (label_is_thumb_function_name
13933 && (S_GET_NAME (sym)[0] != '.' || S_GET_NAME (sym)[1] != 'L')
13934 && (bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
13935 {
13936 /* When the address of a Thumb function is taken the bottom
13937 bit of that address should be set. This will allow
13938 interworking between Arm and Thumb functions to work
13939 correctly. */
13940
13941 THUMB_SET_FUNC (sym, 1);
13942
13943 label_is_thumb_function_name = FALSE;
13944 }
13945 }
13946
13947 /* Adjust the symbol table. This marks Thumb symbols as distinct from
13948 ARM ones. */
13949
13950 void
13951 arm_adjust_symtab ()
13952 {
13953 #ifdef OBJ_COFF
13954 symbolS * sym;
13955
13956 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
13957 {
13958 if (ARM_IS_THUMB (sym))
13959 {
13960 if (THUMB_IS_FUNC (sym))
13961 {
13962 /* Mark the symbol as a Thumb function. */
13963 if ( S_GET_STORAGE_CLASS (sym) == C_STAT
13964 || S_GET_STORAGE_CLASS (sym) == C_LABEL) /* This can happen! */
13965 S_SET_STORAGE_CLASS (sym, C_THUMBSTATFUNC);
13966
13967 else if (S_GET_STORAGE_CLASS (sym) == C_EXT)
13968 S_SET_STORAGE_CLASS (sym, C_THUMBEXTFUNC);
13969 else
13970 as_bad (_("%s: unexpected function type: %d"),
13971 S_GET_NAME (sym), S_GET_STORAGE_CLASS (sym));
13972 }
13973 else switch (S_GET_STORAGE_CLASS (sym))
13974 {
13975 case C_EXT:
13976 S_SET_STORAGE_CLASS (sym, C_THUMBEXT);
13977 break;
13978 case C_STAT:
13979 S_SET_STORAGE_CLASS (sym, C_THUMBSTAT);
13980 break;
13981 case C_LABEL:
13982 S_SET_STORAGE_CLASS (sym, C_THUMBLABEL);
13983 break;
13984 default:
13985 /* Do nothing. */
13986 break;
13987 }
13988 }
13989
13990 if (ARM_IS_INTERWORK (sym))
13991 coffsymbol (symbol_get_bfdsym (sym))->native->u.syment.n_flags = 0xFF;
13992 }
13993 #endif
13994 #ifdef OBJ_ELF
13995 symbolS * sym;
13996 char bind;
13997
13998 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
13999 {
14000 if (ARM_IS_THUMB (sym))
14001 {
14002 elf_symbol_type * elf_sym;
14003
14004 elf_sym = elf_symbol (symbol_get_bfdsym (sym));
14005 bind = ELF_ST_BIND (elf_sym);
14006
14007 /* If it's a .thumb_func, declare it as so,
14008 otherwise tag label as .code 16. */
14009 if (THUMB_IS_FUNC (sym))
14010 elf_sym->internal_elf_sym.st_info =
14011 ELF_ST_INFO (bind, STT_ARM_TFUNC);
14012 else
14013 elf_sym->internal_elf_sym.st_info =
14014 ELF_ST_INFO (bind, STT_ARM_16BIT);
14015 }
14016 }
14017 #endif
14018 }
14019
14020 int
14021 arm_data_in_code ()
14022 {
14023 if (thumb_mode && ! strncmp (input_line_pointer + 1, "data:", 5))
14024 {
14025 *input_line_pointer = '/';
14026 input_line_pointer += 5;
14027 *input_line_pointer = 0;
14028 return 1;
14029 }
14030
14031 return 0;
14032 }
14033
14034 char *
14035 arm_canonicalize_symbol_name (name)
14036 char * name;
14037 {
14038 int len;
14039
14040 if (thumb_mode && (len = strlen (name)) > 5
14041 && streq (name + len - 5, "/data"))
14042 *(name + len - 5) = 0;
14043
14044 return name;
14045 }
14046
14047 #if defined OBJ_COFF || defined OBJ_ELF
14048 void
14049 arm_validate_fix (fixP)
14050 fixS * fixP;
14051 {
14052 /* If the destination of the branch is a defined symbol which does not have
14053 the THUMB_FUNC attribute, then we must be calling a function which has
14054 the (interfacearm) attribute. We look for the Thumb entry point to that
14055 function and change the branch to refer to that function instead. */
14056 if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23
14057 && fixP->fx_addsy != NULL
14058 && S_IS_DEFINED (fixP->fx_addsy)
14059 && ! THUMB_IS_FUNC (fixP->fx_addsy))
14060 {
14061 fixP->fx_addsy = find_real_start (fixP->fx_addsy);
14062 }
14063 }
14064 #endif
14065
14066 int
14067 arm_force_relocation (fixp)
14068 struct fix * fixp;
14069 {
14070 #if defined (OBJ_COFF) && defined (TE_PE)
14071 if (fixp->fx_r_type == BFD_RELOC_RVA)
14072 return 1;
14073 #endif
14074 #ifdef OBJ_ELF
14075 if (fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH
14076 || fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BLX
14077 || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX
14078 || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23)
14079 return 1;
14080 #endif
14081
14082 /* Resolve these relocations even if the symbol is extern or weak. */
14083 if (fixp->fx_r_type == BFD_RELOC_ARM_IMMEDIATE
14084 || fixp->fx_r_type == BFD_RELOC_ARM_OFFSET_IMM
14085 || fixp->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE)
14086 return 0;
14087
14088 return generic_force_reloc (fixp);
14089 }
14090
14091 #ifdef OBJ_COFF
14092 /* This is a little hack to help the gas/arm/adrl.s test. It prevents
14093 local labels from being added to the output symbol table when they
14094 are used with the ADRL pseudo op. The ADRL relocation should always
14095 be resolved before the binbary is emitted, so it is safe to say that
14096 it is adjustable. */
14097
14098 bfd_boolean
14099 arm_fix_adjustable (fixP)
14100 fixS * fixP;
14101 {
14102 if (fixP->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE)
14103 return 1;
14104 return 0;
14105 }
14106 #endif
14107
14108 #ifdef OBJ_ELF
14109 /* Relocations against Thumb function names must be left unadjusted,
14110 so that the linker can use this information to correctly set the
14111 bottom bit of their addresses. The MIPS version of this function
14112 also prevents relocations that are mips-16 specific, but I do not
14113 know why it does this.
14114
14115 FIXME:
14116 There is one other problem that ought to be addressed here, but
14117 which currently is not: Taking the address of a label (rather
14118 than a function) and then later jumping to that address. Such
14119 addresses also ought to have their bottom bit set (assuming that
14120 they reside in Thumb code), but at the moment they will not. */
14121
14122 bfd_boolean
14123 arm_fix_adjustable (fixP)
14124 fixS * fixP;
14125 {
14126 if (fixP->fx_addsy == NULL)
14127 return 1;
14128
14129 if (THUMB_IS_FUNC (fixP->fx_addsy)
14130 && fixP->fx_subsy == NULL)
14131 return 0;
14132
14133 /* We need the symbol name for the VTABLE entries. */
14134 if ( fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
14135 || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
14136 return 0;
14137
14138 /* Don't allow symbols to be discarded on GOT related relocs. */
14139 if (fixP->fx_r_type == BFD_RELOC_ARM_PLT32
14140 || fixP->fx_r_type == BFD_RELOC_ARM_GOT32
14141 || fixP->fx_r_type == BFD_RELOC_ARM_GOTOFF)
14142 return 0;
14143
14144 return 1;
14145 }
14146
14147 const char *
14148 elf32_arm_target_format ()
14149 {
14150 if (target_big_endian)
14151 {
14152 if (target_oabi)
14153 return "elf32-bigarm-oabi";
14154 else
14155 return "elf32-bigarm";
14156 }
14157 else
14158 {
14159 if (target_oabi)
14160 return "elf32-littlearm-oabi";
14161 else
14162 return "elf32-littlearm";
14163 }
14164 }
14165
14166 void
14167 armelf_frob_symbol (symp, puntp)
14168 symbolS * symp;
14169 int * puntp;
14170 {
14171 elf_frob_symbol (symp, puntp);
14172 }
14173
14174 static bfd_reloc_code_real_type
14175 arm_parse_reloc ()
14176 {
14177 char id [16];
14178 char * ip;
14179 unsigned int i;
14180 static struct
14181 {
14182 char * str;
14183 int len;
14184 bfd_reloc_code_real_type reloc;
14185 }
14186 reloc_map[] =
14187 {
14188 #define MAP(str,reloc) { str, sizeof (str) - 1, reloc }
14189 MAP ("(got)", BFD_RELOC_ARM_GOT32),
14190 MAP ("(gotoff)", BFD_RELOC_ARM_GOTOFF),
14191 /* ScottB: Jan 30, 1998 - Added support for parsing "var(PLT)"
14192 branch instructions generated by GCC for PLT relocs. */
14193 MAP ("(plt)", BFD_RELOC_ARM_PLT32),
14194 { NULL, 0, BFD_RELOC_UNUSED }
14195 #undef MAP
14196 };
14197
14198 for (i = 0, ip = input_line_pointer;
14199 i < sizeof (id) && (ISALNUM (*ip) || ISPUNCT (*ip));
14200 i++, ip++)
14201 id[i] = TOLOWER (*ip);
14202
14203 for (i = 0; reloc_map[i].str; i++)
14204 if (strncmp (id, reloc_map[i].str, reloc_map[i].len) == 0)
14205 break;
14206
14207 input_line_pointer += reloc_map[i].len;
14208
14209 return reloc_map[i].reloc;
14210 }
14211
14212 static void
14213 s_arm_elf_cons (nbytes)
14214 int nbytes;
14215 {
14216 expressionS exp;
14217
14218 #ifdef md_flush_pending_output
14219 md_flush_pending_output ();
14220 #endif
14221
14222 if (is_it_end_of_statement ())
14223 {
14224 demand_empty_rest_of_line ();
14225 return;
14226 }
14227
14228 #ifdef md_cons_align
14229 md_cons_align (nbytes);
14230 #endif
14231
14232 mapping_state (MAP_DATA);
14233 do
14234 {
14235 bfd_reloc_code_real_type reloc;
14236
14237 expression (& exp);
14238
14239 if (exp.X_op == O_symbol
14240 && * input_line_pointer == '('
14241 && (reloc = arm_parse_reloc ()) != BFD_RELOC_UNUSED)
14242 {
14243 reloc_howto_type *howto = bfd_reloc_type_lookup (stdoutput, reloc);
14244 int size = bfd_get_reloc_size (howto);
14245
14246 if (size > nbytes)
14247 as_bad ("%s relocations do not fit in %d bytes",
14248 howto->name, nbytes);
14249 else
14250 {
14251 register char *p = frag_more ((int) nbytes);
14252 int offset = nbytes - size;
14253
14254 fix_new_exp (frag_now, p - frag_now->fr_literal + offset, size,
14255 &exp, 0, reloc);
14256 }
14257 }
14258 else
14259 emit_expr (&exp, (unsigned int) nbytes);
14260 }
14261 while (*input_line_pointer++ == ',');
14262
14263 /* Put terminator back into stream. */
14264 input_line_pointer --;
14265 demand_empty_rest_of_line ();
14266 }
14267
14268 #endif /* OBJ_ELF */
14269
14270 /* This is called from HANDLE_ALIGN in write.c. Fill in the contents
14271 of an rs_align_code fragment. */
14272
14273 void
14274 arm_handle_align (fragP)
14275 fragS *fragP;
14276 {
14277 static char const arm_noop[4] = { 0x00, 0x00, 0xa0, 0xe1 };
14278 static char const thumb_noop[2] = { 0xc0, 0x46 };
14279 static char const arm_bigend_noop[4] = { 0xe1, 0xa0, 0x00, 0x00 };
14280 static char const thumb_bigend_noop[2] = { 0x46, 0xc0 };
14281
14282 int bytes, fix, noop_size;
14283 char * p;
14284 const char * noop;
14285
14286 if (fragP->fr_type != rs_align_code)
14287 return;
14288
14289 bytes = fragP->fr_next->fr_address - fragP->fr_address - fragP->fr_fix;
14290 p = fragP->fr_literal + fragP->fr_fix;
14291 fix = 0;
14292
14293 if (bytes > MAX_MEM_FOR_RS_ALIGN_CODE)
14294 bytes &= MAX_MEM_FOR_RS_ALIGN_CODE;
14295
14296 if (fragP->tc_frag_data)
14297 {
14298 if (target_big_endian)
14299 noop = thumb_bigend_noop;
14300 else
14301 noop = thumb_noop;
14302 noop_size = sizeof (thumb_noop);
14303 }
14304 else
14305 {
14306 if (target_big_endian)
14307 noop = arm_bigend_noop;
14308 else
14309 noop = arm_noop;
14310 noop_size = sizeof (arm_noop);
14311 }
14312
14313 if (bytes & (noop_size - 1))
14314 {
14315 fix = bytes & (noop_size - 1);
14316 memset (p, 0, fix);
14317 p += fix;
14318 bytes -= fix;
14319 }
14320
14321 while (bytes >= noop_size)
14322 {
14323 memcpy (p, noop, noop_size);
14324 p += noop_size;
14325 bytes -= noop_size;
14326 fix += noop_size;
14327 }
14328
14329 fragP->fr_fix += fix;
14330 fragP->fr_var = noop_size;
14331 }
14332
14333 /* Called from md_do_align. Used to create an alignment
14334 frag in a code section. */
14335
14336 void
14337 arm_frag_align_code (n, max)
14338 int n;
14339 int max;
14340 {
14341 char * p;
14342
14343 /* We assume that there will never be a requirement
14344 to support alignments greater than 32 bytes. */
14345 if (max > MAX_MEM_FOR_RS_ALIGN_CODE)
14346 as_fatal (_("alignments greater than 32 bytes not supported in .text sections."));
14347
14348 p = frag_var (rs_align_code,
14349 MAX_MEM_FOR_RS_ALIGN_CODE,
14350 1,
14351 (relax_substateT) max,
14352 (symbolS *) NULL,
14353 (offsetT) n,
14354 (char *) NULL);
14355 *p = 0;
14356
14357 }
14358
14359 /* Perform target specific initialisation of a frag. */
14360
14361 void
14362 arm_init_frag (fragP)
14363 fragS *fragP;
14364 {
14365 /* Record whether this frag is in an ARM or a THUMB area. */
14366 fragP->tc_frag_data = thumb_mode;
14367 }
This page took 0.450705 seconds and 4 git commands to generate.