2004-03-03 H.J. Lu <hongjiu.lu@intel.com>
[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
195 /* This array holds the chars that always start a comment. If the
196 pre-processor is disabled, these aren't very useful. */
197 const char comment_chars[] = "@";
198
199 /* This array holds the chars that only start a comment at the beginning of
200 a line. If the line seems to have the form '# 123 filename'
201 .line and .file directives will appear in the pre-processed output. */
202 /* Note that input_file.c hand checks for '#' at the beginning of the
203 first line of the input file. This is because the compiler outputs
204 #NO_APP at the beginning of its output. */
205 /* Also note that comments like this one will always work. */
206 const char line_comment_chars[] = "#";
207
208 const char line_separator_chars[] = ";";
209
210 /* Chars that can be used to separate mant
211 from exp in floating point numbers. */
212 const char EXP_CHARS[] = "eE";
213
214 /* Chars that mean this number is a floating point constant. */
215 /* As in 0f12.456 */
216 /* or 0d1.2345e12 */
217
218 const char FLT_CHARS[] = "rRsSfFdDxXeEpP";
219
220 /* Prefix characters that indicate the start of an immediate
221 value. */
222 #define is_immediate_prefix(C) ((C) == '#' || (C) == '$')
223
224 #ifdef OBJ_ELF
225 /* Pre-defined "_GLOBAL_OFFSET_TABLE_" */
226 symbolS * GOT_symbol;
227 #endif
228
229 /* Size of relocation record. */
230 const int md_reloc_size = 8;
231
232 /* 0: assemble for ARM,
233 1: assemble for Thumb,
234 2: assemble for Thumb even though target CPU does not support thumb
235 instructions. */
236 static int thumb_mode = 0;
237
238 typedef struct arm_fix
239 {
240 int thumb_mode;
241 } arm_fix_data;
242
243 struct arm_it
244 {
245 const char * error;
246 unsigned long instruction;
247 int size;
248 struct
249 {
250 bfd_reloc_code_real_type type;
251 expressionS exp;
252 int pc_rel;
253 } reloc;
254 };
255
256 struct arm_it inst;
257
258 enum asm_shift_index
259 {
260 SHIFT_LSL = 0,
261 SHIFT_LSR,
262 SHIFT_ASR,
263 SHIFT_ROR,
264 SHIFT_RRX
265 };
266
267 struct asm_shift_properties
268 {
269 enum asm_shift_index index;
270 unsigned long bit_field;
271 unsigned int allows_0 : 1;
272 unsigned int allows_32 : 1;
273 };
274
275 static const struct asm_shift_properties shift_properties [] =
276 {
277 { SHIFT_LSL, 0, 1, 0},
278 { SHIFT_LSR, 0x20, 0, 1},
279 { SHIFT_ASR, 0x40, 0, 1},
280 { SHIFT_ROR, 0x60, 0, 0},
281 { SHIFT_RRX, 0x60, 0, 0}
282 };
283
284 struct asm_shift_name
285 {
286 const char * name;
287 const struct asm_shift_properties * properties;
288 };
289
290 static const struct asm_shift_name shift_names [] =
291 {
292 { "asl", shift_properties + SHIFT_LSL },
293 { "lsl", shift_properties + SHIFT_LSL },
294 { "lsr", shift_properties + SHIFT_LSR },
295 { "asr", shift_properties + SHIFT_ASR },
296 { "ror", shift_properties + SHIFT_ROR },
297 { "rrx", shift_properties + SHIFT_RRX },
298 { "ASL", shift_properties + SHIFT_LSL },
299 { "LSL", shift_properties + SHIFT_LSL },
300 { "LSR", shift_properties + SHIFT_LSR },
301 { "ASR", shift_properties + SHIFT_ASR },
302 { "ROR", shift_properties + SHIFT_ROR },
303 { "RRX", shift_properties + SHIFT_RRX }
304 };
305
306 /* Any kind of shift is accepted. */
307 #define NO_SHIFT_RESTRICT 1
308 /* The shift operand must be an immediate value, not a register. */
309 #define SHIFT_IMMEDIATE 0
310 /* The shift must be LSL or ASR and the operand must be an immediate. */
311 #define SHIFT_LSL_OR_ASR_IMMEDIATE 2
312 /* The shift must be ASR and the operand must be an immediate. */
313 #define SHIFT_ASR_IMMEDIATE 3
314 /* The shift must be LSL and the operand must be an immediate. */
315 #define SHIFT_LSL_IMMEDIATE 4
316
317 #define NUM_FLOAT_VALS 8
318
319 const char * fp_const[] =
320 {
321 "0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0", 0
322 };
323
324 /* Number of littlenums required to hold an extended precision number. */
325 #define MAX_LITTLENUMS 6
326
327 LITTLENUM_TYPE fp_values[NUM_FLOAT_VALS][MAX_LITTLENUMS];
328
329 #define FAIL (-1)
330 #define SUCCESS (0)
331
332 /* Whether a Co-processor load/store operation accepts write-back forms. */
333 #define CP_WB_OK 1
334 #define CP_NO_WB 0
335
336 #define SUFF_S 1
337 #define SUFF_D 2
338 #define SUFF_E 3
339 #define SUFF_P 4
340
341 #define CP_T_X 0x00008000
342 #define CP_T_Y 0x00400000
343 #define CP_T_Pre 0x01000000
344 #define CP_T_UD 0x00800000
345 #define CP_T_WB 0x00200000
346
347 #define CONDS_BIT 0x00100000
348 #define LOAD_BIT 0x00100000
349
350 #define DOUBLE_LOAD_FLAG 0x00000001
351
352 struct asm_cond
353 {
354 const char * template;
355 unsigned long value;
356 };
357
358 #define COND_ALWAYS 0xe0000000
359 #define COND_MASK 0xf0000000
360
361 static const struct asm_cond conds[] =
362 {
363 {"eq", 0x00000000},
364 {"ne", 0x10000000},
365 {"cs", 0x20000000}, {"hs", 0x20000000},
366 {"cc", 0x30000000}, {"ul", 0x30000000}, {"lo", 0x30000000},
367 {"mi", 0x40000000},
368 {"pl", 0x50000000},
369 {"vs", 0x60000000},
370 {"vc", 0x70000000},
371 {"hi", 0x80000000},
372 {"ls", 0x90000000},
373 {"ge", 0xa0000000},
374 {"lt", 0xb0000000},
375 {"gt", 0xc0000000},
376 {"le", 0xd0000000},
377 {"al", 0xe0000000},
378 {"nv", 0xf0000000}
379 };
380
381 struct asm_psr
382 {
383 const char *template;
384 bfd_boolean cpsr;
385 unsigned long field;
386 };
387
388 /* The bit that distinguishes CPSR and SPSR. */
389 #define SPSR_BIT (1 << 22)
390
391 /* How many bits to shift the PSR_xxx bits up by. */
392 #define PSR_SHIFT 16
393
394 #define PSR_c (1 << 0)
395 #define PSR_x (1 << 1)
396 #define PSR_s (1 << 2)
397 #define PSR_f (1 << 3)
398
399 static const struct asm_psr psrs[] =
400 {
401 {"CPSR", TRUE, PSR_c | PSR_f},
402 {"CPSR_all", TRUE, PSR_c | PSR_f},
403 {"SPSR", FALSE, PSR_c | PSR_f},
404 {"SPSR_all", FALSE, PSR_c | PSR_f},
405 {"CPSR_flg", TRUE, PSR_f},
406 {"CPSR_f", TRUE, PSR_f},
407 {"SPSR_flg", FALSE, PSR_f},
408 {"SPSR_f", FALSE, PSR_f},
409 {"CPSR_c", TRUE, PSR_c},
410 {"CPSR_ctl", TRUE, PSR_c},
411 {"SPSR_c", FALSE, PSR_c},
412 {"SPSR_ctl", FALSE, PSR_c},
413 {"CPSR_x", TRUE, PSR_x},
414 {"CPSR_s", TRUE, PSR_s},
415 {"SPSR_x", FALSE, PSR_x},
416 {"SPSR_s", FALSE, PSR_s},
417 /* Combinations of flags. */
418 {"CPSR_fs", TRUE, PSR_f | PSR_s},
419 {"CPSR_fx", TRUE, PSR_f | PSR_x},
420 {"CPSR_fc", TRUE, PSR_f | PSR_c},
421 {"CPSR_sf", TRUE, PSR_s | PSR_f},
422 {"CPSR_sx", TRUE, PSR_s | PSR_x},
423 {"CPSR_sc", TRUE, PSR_s | PSR_c},
424 {"CPSR_xf", TRUE, PSR_x | PSR_f},
425 {"CPSR_xs", TRUE, PSR_x | PSR_s},
426 {"CPSR_xc", TRUE, PSR_x | PSR_c},
427 {"CPSR_cf", TRUE, PSR_c | PSR_f},
428 {"CPSR_cs", TRUE, PSR_c | PSR_s},
429 {"CPSR_cx", TRUE, PSR_c | PSR_x},
430 {"CPSR_fsx", TRUE, PSR_f | PSR_s | PSR_x},
431 {"CPSR_fsc", TRUE, PSR_f | PSR_s | PSR_c},
432 {"CPSR_fxs", TRUE, PSR_f | PSR_x | PSR_s},
433 {"CPSR_fxc", TRUE, PSR_f | PSR_x | PSR_c},
434 {"CPSR_fcs", TRUE, PSR_f | PSR_c | PSR_s},
435 {"CPSR_fcx", TRUE, PSR_f | PSR_c | PSR_x},
436 {"CPSR_sfx", TRUE, PSR_s | PSR_f | PSR_x},
437 {"CPSR_sfc", TRUE, PSR_s | PSR_f | PSR_c},
438 {"CPSR_sxf", TRUE, PSR_s | PSR_x | PSR_f},
439 {"CPSR_sxc", TRUE, PSR_s | PSR_x | PSR_c},
440 {"CPSR_scf", TRUE, PSR_s | PSR_c | PSR_f},
441 {"CPSR_scx", TRUE, PSR_s | PSR_c | PSR_x},
442 {"CPSR_xfs", TRUE, PSR_x | PSR_f | PSR_s},
443 {"CPSR_xfc", TRUE, PSR_x | PSR_f | PSR_c},
444 {"CPSR_xsf", TRUE, PSR_x | PSR_s | PSR_f},
445 {"CPSR_xsc", TRUE, PSR_x | PSR_s | PSR_c},
446 {"CPSR_xcf", TRUE, PSR_x | PSR_c | PSR_f},
447 {"CPSR_xcs", TRUE, PSR_x | PSR_c | PSR_s},
448 {"CPSR_cfs", TRUE, PSR_c | PSR_f | PSR_s},
449 {"CPSR_cfx", TRUE, PSR_c | PSR_f | PSR_x},
450 {"CPSR_csf", TRUE, PSR_c | PSR_s | PSR_f},
451 {"CPSR_csx", TRUE, PSR_c | PSR_s | PSR_x},
452 {"CPSR_cxf", TRUE, PSR_c | PSR_x | PSR_f},
453 {"CPSR_cxs", TRUE, PSR_c | PSR_x | PSR_s},
454 {"CPSR_fsxc", TRUE, PSR_f | PSR_s | PSR_x | PSR_c},
455 {"CPSR_fscx", TRUE, PSR_f | PSR_s | PSR_c | PSR_x},
456 {"CPSR_fxsc", TRUE, PSR_f | PSR_x | PSR_s | PSR_c},
457 {"CPSR_fxcs", TRUE, PSR_f | PSR_x | PSR_c | PSR_s},
458 {"CPSR_fcsx", TRUE, PSR_f | PSR_c | PSR_s | PSR_x},
459 {"CPSR_fcxs", TRUE, PSR_f | PSR_c | PSR_x | PSR_s},
460 {"CPSR_sfxc", TRUE, PSR_s | PSR_f | PSR_x | PSR_c},
461 {"CPSR_sfcx", TRUE, PSR_s | PSR_f | PSR_c | PSR_x},
462 {"CPSR_sxfc", TRUE, PSR_s | PSR_x | PSR_f | PSR_c},
463 {"CPSR_sxcf", TRUE, PSR_s | PSR_x | PSR_c | PSR_f},
464 {"CPSR_scfx", TRUE, PSR_s | PSR_c | PSR_f | PSR_x},
465 {"CPSR_scxf", TRUE, PSR_s | PSR_c | PSR_x | PSR_f},
466 {"CPSR_xfsc", TRUE, PSR_x | PSR_f | PSR_s | PSR_c},
467 {"CPSR_xfcs", TRUE, PSR_x | PSR_f | PSR_c | PSR_s},
468 {"CPSR_xsfc", TRUE, PSR_x | PSR_s | PSR_f | PSR_c},
469 {"CPSR_xscf", TRUE, PSR_x | PSR_s | PSR_c | PSR_f},
470 {"CPSR_xcfs", TRUE, PSR_x | PSR_c | PSR_f | PSR_s},
471 {"CPSR_xcsf", TRUE, PSR_x | PSR_c | PSR_s | PSR_f},
472 {"CPSR_cfsx", TRUE, PSR_c | PSR_f | PSR_s | PSR_x},
473 {"CPSR_cfxs", TRUE, PSR_c | PSR_f | PSR_x | PSR_s},
474 {"CPSR_csfx", TRUE, PSR_c | PSR_s | PSR_f | PSR_x},
475 {"CPSR_csxf", TRUE, PSR_c | PSR_s | PSR_x | PSR_f},
476 {"CPSR_cxfs", TRUE, PSR_c | PSR_x | PSR_f | PSR_s},
477 {"CPSR_cxsf", TRUE, PSR_c | PSR_x | PSR_s | PSR_f},
478 {"SPSR_fs", FALSE, PSR_f | PSR_s},
479 {"SPSR_fx", FALSE, PSR_f | PSR_x},
480 {"SPSR_fc", FALSE, PSR_f | PSR_c},
481 {"SPSR_sf", FALSE, PSR_s | PSR_f},
482 {"SPSR_sx", FALSE, PSR_s | PSR_x},
483 {"SPSR_sc", FALSE, PSR_s | PSR_c},
484 {"SPSR_xf", FALSE, PSR_x | PSR_f},
485 {"SPSR_xs", FALSE, PSR_x | PSR_s},
486 {"SPSR_xc", FALSE, PSR_x | PSR_c},
487 {"SPSR_cf", FALSE, PSR_c | PSR_f},
488 {"SPSR_cs", FALSE, PSR_c | PSR_s},
489 {"SPSR_cx", FALSE, PSR_c | PSR_x},
490 {"SPSR_fsx", FALSE, PSR_f | PSR_s | PSR_x},
491 {"SPSR_fsc", FALSE, PSR_f | PSR_s | PSR_c},
492 {"SPSR_fxs", FALSE, PSR_f | PSR_x | PSR_s},
493 {"SPSR_fxc", FALSE, PSR_f | PSR_x | PSR_c},
494 {"SPSR_fcs", FALSE, PSR_f | PSR_c | PSR_s},
495 {"SPSR_fcx", FALSE, PSR_f | PSR_c | PSR_x},
496 {"SPSR_sfx", FALSE, PSR_s | PSR_f | PSR_x},
497 {"SPSR_sfc", FALSE, PSR_s | PSR_f | PSR_c},
498 {"SPSR_sxf", FALSE, PSR_s | PSR_x | PSR_f},
499 {"SPSR_sxc", FALSE, PSR_s | PSR_x | PSR_c},
500 {"SPSR_scf", FALSE, PSR_s | PSR_c | PSR_f},
501 {"SPSR_scx", FALSE, PSR_s | PSR_c | PSR_x},
502 {"SPSR_xfs", FALSE, PSR_x | PSR_f | PSR_s},
503 {"SPSR_xfc", FALSE, PSR_x | PSR_f | PSR_c},
504 {"SPSR_xsf", FALSE, PSR_x | PSR_s | PSR_f},
505 {"SPSR_xsc", FALSE, PSR_x | PSR_s | PSR_c},
506 {"SPSR_xcf", FALSE, PSR_x | PSR_c | PSR_f},
507 {"SPSR_xcs", FALSE, PSR_x | PSR_c | PSR_s},
508 {"SPSR_cfs", FALSE, PSR_c | PSR_f | PSR_s},
509 {"SPSR_cfx", FALSE, PSR_c | PSR_f | PSR_x},
510 {"SPSR_csf", FALSE, PSR_c | PSR_s | PSR_f},
511 {"SPSR_csx", FALSE, PSR_c | PSR_s | PSR_x},
512 {"SPSR_cxf", FALSE, PSR_c | PSR_x | PSR_f},
513 {"SPSR_cxs", FALSE, PSR_c | PSR_x | PSR_s},
514 {"SPSR_fsxc", FALSE, PSR_f | PSR_s | PSR_x | PSR_c},
515 {"SPSR_fscx", FALSE, PSR_f | PSR_s | PSR_c | PSR_x},
516 {"SPSR_fxsc", FALSE, PSR_f | PSR_x | PSR_s | PSR_c},
517 {"SPSR_fxcs", FALSE, PSR_f | PSR_x | PSR_c | PSR_s},
518 {"SPSR_fcsx", FALSE, PSR_f | PSR_c | PSR_s | PSR_x},
519 {"SPSR_fcxs", FALSE, PSR_f | PSR_c | PSR_x | PSR_s},
520 {"SPSR_sfxc", FALSE, PSR_s | PSR_f | PSR_x | PSR_c},
521 {"SPSR_sfcx", FALSE, PSR_s | PSR_f | PSR_c | PSR_x},
522 {"SPSR_sxfc", FALSE, PSR_s | PSR_x | PSR_f | PSR_c},
523 {"SPSR_sxcf", FALSE, PSR_s | PSR_x | PSR_c | PSR_f},
524 {"SPSR_scfx", FALSE, PSR_s | PSR_c | PSR_f | PSR_x},
525 {"SPSR_scxf", FALSE, PSR_s | PSR_c | PSR_x | PSR_f},
526 {"SPSR_xfsc", FALSE, PSR_x | PSR_f | PSR_s | PSR_c},
527 {"SPSR_xfcs", FALSE, PSR_x | PSR_f | PSR_c | PSR_s},
528 {"SPSR_xsfc", FALSE, PSR_x | PSR_s | PSR_f | PSR_c},
529 {"SPSR_xscf", FALSE, PSR_x | PSR_s | PSR_c | PSR_f},
530 {"SPSR_xcfs", FALSE, PSR_x | PSR_c | PSR_f | PSR_s},
531 {"SPSR_xcsf", FALSE, PSR_x | PSR_c | PSR_s | PSR_f},
532 {"SPSR_cfsx", FALSE, PSR_c | PSR_f | PSR_s | PSR_x},
533 {"SPSR_cfxs", FALSE, PSR_c | PSR_f | PSR_x | PSR_s},
534 {"SPSR_csfx", FALSE, PSR_c | PSR_s | PSR_f | PSR_x},
535 {"SPSR_csxf", FALSE, PSR_c | PSR_s | PSR_x | PSR_f},
536 {"SPSR_cxfs", FALSE, PSR_c | PSR_x | PSR_f | PSR_s},
537 {"SPSR_cxsf", FALSE, PSR_c | PSR_x | PSR_s | PSR_f},
538 };
539
540 enum wreg_type
541 {
542 IWMMXT_REG_WR = 0,
543 IWMMXT_REG_WC = 1,
544 IWMMXT_REG_WR_OR_WC = 2,
545 IWMMXT_REG_WCG
546 };
547
548 enum iwmmxt_insn_type
549 {
550 check_rd,
551 check_wr,
552 check_wrwr,
553 check_wrwrwr,
554 check_wrwrwcg,
555 check_tbcst,
556 check_tmovmsk,
557 check_tmia,
558 check_tmcrr,
559 check_tmrrc,
560 check_tmcr,
561 check_tmrc,
562 check_tinsr,
563 check_textrc,
564 check_waligni,
565 check_textrm,
566 check_wshufh
567 };
568
569 enum vfp_dp_reg_pos
570 {
571 VFP_REG_Dd, VFP_REG_Dm, VFP_REG_Dn
572 };
573
574 enum vfp_sp_reg_pos
575 {
576 VFP_REG_Sd, VFP_REG_Sm, VFP_REG_Sn
577 };
578
579 enum vfp_ldstm_type
580 {
581 VFP_LDSTMIA, VFP_LDSTMDB, VFP_LDSTMIAX, VFP_LDSTMDBX
582 };
583
584 /* VFP system registers. */
585 struct vfp_reg
586 {
587 const char *name;
588 unsigned long regno;
589 };
590
591 static const struct vfp_reg vfp_regs[] =
592 {
593 {"fpsid", 0x00000000},
594 {"FPSID", 0x00000000},
595 {"fpscr", 0x00010000},
596 {"FPSCR", 0x00010000},
597 {"fpexc", 0x00080000},
598 {"FPEXC", 0x00080000}
599 };
600
601 /* Structure for a hash table entry for a register. */
602 struct reg_entry
603 {
604 const char * name;
605 int number;
606 bfd_boolean builtin;
607 };
608
609 /* Some well known registers that we refer to directly elsewhere. */
610 #define REG_SP 13
611 #define REG_LR 14
612 #define REG_PC 15
613
614 #define wr_register(reg) ((reg ^ WR_PREFIX) >= 0 && (reg ^ WR_PREFIX) <= 15)
615 #define wc_register(reg) ((reg ^ WC_PREFIX) >= 0 && (reg ^ WC_PREFIX) <= 15)
616 #define wcg_register(reg) ((reg ^ WC_PREFIX) >= 8 && (reg ^ WC_PREFIX) <= 11)
617
618 /* These are the standard names. Users can add aliases with .req.
619 and delete them with .unreq. */
620
621 /* Integer Register Numbers. */
622 static const struct reg_entry rn_table[] =
623 {
624 {"r0", 0, TRUE}, {"r1", 1, TRUE}, {"r2", 2, TRUE}, {"r3", 3, TRUE},
625 {"r4", 4, TRUE}, {"r5", 5, TRUE}, {"r6", 6, TRUE}, {"r7", 7, TRUE},
626 {"r8", 8, TRUE}, {"r9", 9, TRUE}, {"r10", 10, TRUE}, {"r11", 11, TRUE},
627 {"r12", 12, TRUE}, {"r13", REG_SP, TRUE}, {"r14", REG_LR, TRUE}, {"r15", REG_PC, TRUE},
628 /* ATPCS Synonyms. */
629 {"a1", 0, TRUE}, {"a2", 1, TRUE}, {"a3", 2, TRUE}, {"a4", 3, TRUE},
630 {"v1", 4, TRUE}, {"v2", 5, TRUE}, {"v3", 6, TRUE}, {"v4", 7, TRUE},
631 {"v5", 8, TRUE}, {"v6", 9, TRUE}, {"v7", 10, TRUE}, {"v8", 11, TRUE},
632 /* Well-known aliases. */
633 {"wr", 7, TRUE}, {"sb", 9, TRUE}, {"sl", 10, TRUE}, {"fp", 11, TRUE},
634 {"ip", 12, TRUE}, {"sp", REG_SP, TRUE}, {"lr", REG_LR, TRUE}, {"pc", REG_PC, TRUE},
635 {NULL, 0, TRUE}
636 };
637
638 #define WR_PREFIX 0x200
639 #define WC_PREFIX 0x400
640
641 static const struct reg_entry iwmmxt_table[] =
642 {
643 /* Intel Wireless MMX technology register names. */
644 { "wr0", 0x0 | WR_PREFIX, TRUE}, {"wr1", 0x1 | WR_PREFIX, TRUE},
645 { "wr2", 0x2 | WR_PREFIX, TRUE}, {"wr3", 0x3 | WR_PREFIX, TRUE},
646 { "wr4", 0x4 | WR_PREFIX, TRUE}, {"wr5", 0x5 | WR_PREFIX, TRUE},
647 { "wr6", 0x6 | WR_PREFIX, TRUE}, {"wr7", 0x7 | WR_PREFIX, TRUE},
648 { "wr8", 0x8 | WR_PREFIX, TRUE}, {"wr9", 0x9 | WR_PREFIX, TRUE},
649 { "wr10", 0xa | WR_PREFIX, TRUE}, {"wr11", 0xb | WR_PREFIX, TRUE},
650 { "wr12", 0xc | WR_PREFIX, TRUE}, {"wr13", 0xd | WR_PREFIX, TRUE},
651 { "wr14", 0xe | WR_PREFIX, TRUE}, {"wr15", 0xf | WR_PREFIX, TRUE},
652 { "wcid", 0x0 | WC_PREFIX, TRUE}, {"wcon", 0x1 | WC_PREFIX, TRUE},
653 {"wcssf", 0x2 | WC_PREFIX, TRUE}, {"wcasf", 0x3 | WC_PREFIX, TRUE},
654 {"wcgr0", 0x8 | WC_PREFIX, TRUE}, {"wcgr1", 0x9 | WC_PREFIX, TRUE},
655 {"wcgr2", 0xa | WC_PREFIX, TRUE}, {"wcgr3", 0xb | WC_PREFIX, TRUE},
656
657 { "wR0", 0x0 | WR_PREFIX, TRUE}, {"wR1", 0x1 | WR_PREFIX, TRUE},
658 { "wR2", 0x2 | WR_PREFIX, TRUE}, {"wR3", 0x3 | WR_PREFIX, TRUE},
659 { "wR4", 0x4 | WR_PREFIX, TRUE}, {"wR5", 0x5 | WR_PREFIX, TRUE},
660 { "wR6", 0x6 | WR_PREFIX, TRUE}, {"wR7", 0x7 | WR_PREFIX, TRUE},
661 { "wR8", 0x8 | WR_PREFIX, TRUE}, {"wR9", 0x9 | WR_PREFIX, TRUE},
662 { "wR10", 0xa | WR_PREFIX, TRUE}, {"wR11", 0xb | WR_PREFIX, TRUE},
663 { "wR12", 0xc | WR_PREFIX, TRUE}, {"wR13", 0xd | WR_PREFIX, TRUE},
664 { "wR14", 0xe | WR_PREFIX, TRUE}, {"wR15", 0xf | WR_PREFIX, TRUE},
665 { "wCID", 0x0 | WC_PREFIX, TRUE}, {"wCon", 0x1 | WC_PREFIX, TRUE},
666 {"wCSSF", 0x2 | WC_PREFIX, TRUE}, {"wCASF", 0x3 | WC_PREFIX, TRUE},
667 {"wCGR0", 0x8 | WC_PREFIX, TRUE}, {"wCGR1", 0x9 | WC_PREFIX, TRUE},
668 {"wCGR2", 0xa | WC_PREFIX, TRUE}, {"wCGR3", 0xb | WC_PREFIX, TRUE},
669 {NULL, 0, TRUE}
670 };
671
672 /* Co-processor Numbers. */
673 static const struct reg_entry cp_table[] =
674 {
675 {"p0", 0, TRUE}, {"p1", 1, TRUE}, {"p2", 2, TRUE}, {"p3", 3, TRUE},
676 {"p4", 4, TRUE}, {"p5", 5, TRUE}, {"p6", 6, TRUE}, {"p7", 7, TRUE},
677 {"p8", 8, TRUE}, {"p9", 9, TRUE}, {"p10", 10, TRUE}, {"p11", 11, TRUE},
678 {"p12", 12, TRUE}, {"p13", 13, TRUE}, {"p14", 14, TRUE}, {"p15", 15, TRUE},
679 {NULL, 0, TRUE}
680 };
681
682 /* Co-processor Register Numbers. */
683 static const struct reg_entry cn_table[] =
684 {
685 {"c0", 0, TRUE}, {"c1", 1, TRUE}, {"c2", 2, TRUE}, {"c3", 3, TRUE},
686 {"c4", 4, TRUE}, {"c5", 5, TRUE}, {"c6", 6, TRUE}, {"c7", 7, TRUE},
687 {"c8", 8, TRUE}, {"c9", 9, TRUE}, {"c10", 10, TRUE}, {"c11", 11, TRUE},
688 {"c12", 12, TRUE}, {"c13", 13, TRUE}, {"c14", 14, TRUE}, {"c15", 15, TRUE},
689 /* Not really valid, but kept for back-wards compatibility. */
690 {"cr0", 0, TRUE}, {"cr1", 1, TRUE}, {"cr2", 2, TRUE}, {"cr3", 3, TRUE},
691 {"cr4", 4, TRUE}, {"cr5", 5, TRUE}, {"cr6", 6, TRUE}, {"cr7", 7, TRUE},
692 {"cr8", 8, TRUE}, {"cr9", 9, TRUE}, {"cr10", 10, TRUE}, {"cr11", 11, TRUE},
693 {"cr12", 12, TRUE}, {"cr13", 13, TRUE}, {"cr14", 14, TRUE}, {"cr15", 15, TRUE},
694 {NULL, 0, TRUE}
695 };
696
697 /* FPA Registers. */
698 static const struct reg_entry fn_table[] =
699 {
700 {"f0", 0, TRUE}, {"f1", 1, TRUE}, {"f2", 2, TRUE}, {"f3", 3, TRUE},
701 {"f4", 4, TRUE}, {"f5", 5, TRUE}, {"f6", 6, TRUE}, {"f7", 7, TRUE},
702 {NULL, 0, TRUE}
703 };
704
705 /* VFP SP Registers. */
706 static const struct reg_entry sn_table[] =
707 {
708 {"s0", 0, TRUE}, {"s1", 1, TRUE}, {"s2", 2, TRUE}, {"s3", 3, TRUE},
709 {"s4", 4, TRUE}, {"s5", 5, TRUE}, {"s6", 6, TRUE}, {"s7", 7, TRUE},
710 {"s8", 8, TRUE}, {"s9", 9, TRUE}, {"s10", 10, TRUE}, {"s11", 11, TRUE},
711 {"s12", 12, TRUE}, {"s13", 13, TRUE}, {"s14", 14, TRUE}, {"s15", 15, TRUE},
712 {"s16", 16, TRUE}, {"s17", 17, TRUE}, {"s18", 18, TRUE}, {"s19", 19, TRUE},
713 {"s20", 20, TRUE}, {"s21", 21, TRUE}, {"s22", 22, TRUE}, {"s23", 23, TRUE},
714 {"s24", 24, TRUE}, {"s25", 25, TRUE}, {"s26", 26, TRUE}, {"s27", 27, TRUE},
715 {"s28", 28, TRUE}, {"s29", 29, TRUE}, {"s30", 30, TRUE}, {"s31", 31, TRUE},
716 {NULL, 0, TRUE}
717 };
718
719 /* VFP DP Registers. */
720 static const struct reg_entry dn_table[] =
721 {
722 {"d0", 0, TRUE}, {"d1", 1, TRUE}, {"d2", 2, TRUE}, {"d3", 3, TRUE},
723 {"d4", 4, TRUE}, {"d5", 5, TRUE}, {"d6", 6, TRUE}, {"d7", 7, TRUE},
724 {"d8", 8, TRUE}, {"d9", 9, TRUE}, {"d10", 10, TRUE}, {"d11", 11, TRUE},
725 {"d12", 12, TRUE}, {"d13", 13, TRUE}, {"d14", 14, TRUE}, {"d15", 15, TRUE},
726 {NULL, 0, TRUE}
727 };
728
729 /* Maverick DSP coprocessor registers. */
730 static const struct reg_entry mav_mvf_table[] =
731 {
732 {"mvf0", 0, TRUE}, {"mvf1", 1, TRUE}, {"mvf2", 2, TRUE}, {"mvf3", 3, TRUE},
733 {"mvf4", 4, TRUE}, {"mvf5", 5, TRUE}, {"mvf6", 6, TRUE}, {"mvf7", 7, TRUE},
734 {"mvf8", 8, TRUE}, {"mvf9", 9, TRUE}, {"mvf10", 10, TRUE}, {"mvf11", 11, TRUE},
735 {"mvf12", 12, TRUE}, {"mvf13", 13, TRUE}, {"mvf14", 14, TRUE}, {"mvf15", 15, TRUE},
736 {NULL, 0, TRUE}
737 };
738
739 static const struct reg_entry mav_mvd_table[] =
740 {
741 {"mvd0", 0, TRUE}, {"mvd1", 1, TRUE}, {"mvd2", 2, TRUE}, {"mvd3", 3, TRUE},
742 {"mvd4", 4, TRUE}, {"mvd5", 5, TRUE}, {"mvd6", 6, TRUE}, {"mvd7", 7, TRUE},
743 {"mvd8", 8, TRUE}, {"mvd9", 9, TRUE}, {"mvd10", 10, TRUE}, {"mvd11", 11, TRUE},
744 {"mvd12", 12, TRUE}, {"mvd13", 13, TRUE}, {"mvd14", 14, TRUE}, {"mvd15", 15, TRUE},
745 {NULL, 0, TRUE}
746 };
747
748 static const struct reg_entry mav_mvfx_table[] =
749 {
750 {"mvfx0", 0, TRUE}, {"mvfx1", 1, TRUE}, {"mvfx2", 2, TRUE}, {"mvfx3", 3, TRUE},
751 {"mvfx4", 4, TRUE}, {"mvfx5", 5, TRUE}, {"mvfx6", 6, TRUE}, {"mvfx7", 7, TRUE},
752 {"mvfx8", 8, TRUE}, {"mvfx9", 9, TRUE}, {"mvfx10", 10, TRUE}, {"mvfx11", 11, TRUE},
753 {"mvfx12", 12, TRUE}, {"mvfx13", 13, TRUE}, {"mvfx14", 14, TRUE}, {"mvfx15", 15, TRUE},
754 {NULL, 0, TRUE}
755 };
756
757 static const struct reg_entry mav_mvdx_table[] =
758 {
759 {"mvdx0", 0, TRUE}, {"mvdx1", 1, TRUE}, {"mvdx2", 2, TRUE}, {"mvdx3", 3, TRUE},
760 {"mvdx4", 4, TRUE}, {"mvdx5", 5, TRUE}, {"mvdx6", 6, TRUE}, {"mvdx7", 7, TRUE},
761 {"mvdx8", 8, TRUE}, {"mvdx9", 9, TRUE}, {"mvdx10", 10, TRUE}, {"mvdx11", 11, TRUE},
762 {"mvdx12", 12, TRUE}, {"mvdx13", 13, TRUE}, {"mvdx14", 14, TRUE}, {"mvdx15", 15, TRUE},
763 {NULL, 0, TRUE}
764 };
765
766 static const struct reg_entry mav_mvax_table[] =
767 {
768 {"mvax0", 0, TRUE}, {"mvax1", 1, TRUE}, {"mvax2", 2, TRUE}, {"mvax3", 3, TRUE},
769 {NULL, 0, TRUE}
770 };
771
772 static const struct reg_entry mav_dspsc_table[] =
773 {
774 {"dspsc", 0, TRUE},
775 {NULL, 0, TRUE}
776 };
777
778 struct reg_map
779 {
780 const struct reg_entry *names;
781 int max_regno;
782 struct hash_control *htab;
783 const char *expected;
784 };
785
786 struct reg_map all_reg_maps[] =
787 {
788 {rn_table, 15, NULL, N_("ARM register expected")},
789 {cp_table, 15, NULL, N_("bad or missing co-processor number")},
790 {cn_table, 15, NULL, N_("co-processor register expected")},
791 {fn_table, 7, NULL, N_("FPA register expected")},
792 {sn_table, 31, NULL, N_("VFP single precision register expected")},
793 {dn_table, 15, NULL, N_("VFP double precision register expected")},
794 {mav_mvf_table, 15, NULL, N_("Maverick MVF register expected")},
795 {mav_mvd_table, 15, NULL, N_("Maverick MVD register expected")},
796 {mav_mvfx_table, 15, NULL, N_("Maverick MVFX register expected")},
797 {mav_mvdx_table, 15, NULL, N_("Maverick MVDX register expected")},
798 {mav_mvax_table, 3, NULL, N_("Maverick MVAX register expected")},
799 {mav_dspsc_table, 0, NULL, N_("Maverick DSPSC register expected")},
800 {iwmmxt_table, 23, NULL, N_("Intel Wireless MMX technology register expected")},
801 };
802
803 /* Enumeration matching entries in table above. */
804 enum arm_reg_type
805 {
806 REG_TYPE_RN = 0,
807 #define REG_TYPE_FIRST REG_TYPE_RN
808 REG_TYPE_CP = 1,
809 REG_TYPE_CN = 2,
810 REG_TYPE_FN = 3,
811 REG_TYPE_SN = 4,
812 REG_TYPE_DN = 5,
813 REG_TYPE_MVF = 6,
814 REG_TYPE_MVD = 7,
815 REG_TYPE_MVFX = 8,
816 REG_TYPE_MVDX = 9,
817 REG_TYPE_MVAX = 10,
818 REG_TYPE_DSPSC = 11,
819 REG_TYPE_IWMMXT = 12,
820
821 REG_TYPE_MAX = 13
822 };
823
824 /* Functions called by parser. */
825 /* ARM instructions. */
826 static void do_arit PARAMS ((char *));
827 static void do_cmp PARAMS ((char *));
828 static void do_mov PARAMS ((char *));
829 static void do_ldst PARAMS ((char *));
830 static void do_ldstt PARAMS ((char *));
831 static void do_ldmstm PARAMS ((char *));
832 static void do_branch PARAMS ((char *));
833 static void do_swi PARAMS ((char *));
834
835 /* Pseudo Op codes. */
836 static void do_adr PARAMS ((char *));
837 static void do_adrl PARAMS ((char *));
838 static void do_empty PARAMS ((char *));
839
840 /* ARM v2. */
841 static void do_mul PARAMS ((char *));
842 static void do_mla PARAMS ((char *));
843
844 /* ARM v2S. */
845 static void do_swap PARAMS ((char *));
846
847 /* ARM v3. */
848 static void do_msr PARAMS ((char *));
849 static void do_mrs PARAMS ((char *));
850
851 /* ARM v3M. */
852 static void do_mull PARAMS ((char *));
853
854 /* ARM v4. */
855 static void do_ldstv4 PARAMS ((char *));
856
857 /* ARM v4T. */
858 static void do_bx PARAMS ((char *));
859
860 /* ARM v5T. */
861 static void do_blx PARAMS ((char *));
862 static void do_bkpt PARAMS ((char *));
863 static void do_clz PARAMS ((char *));
864 static void do_lstc2 PARAMS ((char *));
865 static void do_cdp2 PARAMS ((char *));
866 static void do_co_reg2 PARAMS ((char *));
867
868 /* ARM v5TExP. */
869 static void do_smla PARAMS ((char *));
870 static void do_smlal PARAMS ((char *));
871 static void do_smul PARAMS ((char *));
872 static void do_qadd PARAMS ((char *));
873
874 /* ARM v5TE. */
875 static void do_pld PARAMS ((char *));
876 static void do_ldrd PARAMS ((char *));
877 static void do_co_reg2c PARAMS ((char *));
878
879 /* ARM v5TEJ. */
880 static void do_bxj PARAMS ((char *));
881
882 /* ARM V6. */
883 static void do_cps PARAMS ((char *));
884 static void do_cpsi PARAMS ((char *));
885 static void do_ldrex PARAMS ((char *));
886 static void do_pkhbt PARAMS ((char *));
887 static void do_pkhtb PARAMS ((char *));
888 static void do_qadd16 PARAMS ((char *));
889 static void do_rev PARAMS ((char *));
890 static void do_rfe PARAMS ((char *));
891 static void do_sxtah PARAMS ((char *));
892 static void do_sxth PARAMS ((char *));
893 static void do_setend PARAMS ((char *));
894 static void do_smlad PARAMS ((char *));
895 static void do_smlald PARAMS ((char *));
896 static void do_smmul PARAMS ((char *));
897 static void do_ssat PARAMS ((char *));
898 static void do_usat PARAMS ((char *));
899 static void do_srs PARAMS ((char *));
900 static void do_ssat16 PARAMS ((char *));
901 static void do_usat16 PARAMS ((char *));
902 static void do_strex PARAMS ((char *));
903 static void do_umaal PARAMS ((char *));
904
905 static void do_cps_mode PARAMS ((char **));
906 static void do_cps_flags PARAMS ((char **, int));
907 static int do_endian_specifier PARAMS ((char *));
908 static void do_pkh_core PARAMS ((char *, int));
909 static void do_sat PARAMS ((char **, int));
910 static void do_sat16 PARAMS ((char **, int));
911
912 /* Coprocessor Instructions. */
913 static void do_cdp PARAMS ((char *));
914 static void do_lstc PARAMS ((char *));
915 static void do_co_reg PARAMS ((char *));
916
917 /* FPA instructions. */
918 static void do_fpa_ctrl PARAMS ((char *));
919 static void do_fpa_ldst PARAMS ((char *));
920 static void do_fpa_ldmstm PARAMS ((char *));
921 static void do_fpa_dyadic PARAMS ((char *));
922 static void do_fpa_monadic PARAMS ((char *));
923 static void do_fpa_cmp PARAMS ((char *));
924 static void do_fpa_from_reg PARAMS ((char *));
925 static void do_fpa_to_reg PARAMS ((char *));
926
927 /* VFP instructions. */
928 static void do_vfp_sp_monadic PARAMS ((char *));
929 static void do_vfp_dp_monadic PARAMS ((char *));
930 static void do_vfp_sp_dyadic PARAMS ((char *));
931 static void do_vfp_dp_dyadic PARAMS ((char *));
932 static void do_vfp_reg_from_sp PARAMS ((char *));
933 static void do_vfp_sp_from_reg PARAMS ((char *));
934 static void do_vfp_reg2_from_sp2 PARAMS ((char *));
935 static void do_vfp_sp2_from_reg2 PARAMS ((char *));
936 static void do_vfp_reg_from_dp PARAMS ((char *));
937 static void do_vfp_reg2_from_dp PARAMS ((char *));
938 static void do_vfp_dp_from_reg PARAMS ((char *));
939 static void do_vfp_dp_from_reg2 PARAMS ((char *));
940 static void do_vfp_reg_from_ctrl PARAMS ((char *));
941 static void do_vfp_ctrl_from_reg PARAMS ((char *));
942 static void do_vfp_sp_ldst PARAMS ((char *));
943 static void do_vfp_dp_ldst PARAMS ((char *));
944 static void do_vfp_sp_ldstmia PARAMS ((char *));
945 static void do_vfp_sp_ldstmdb PARAMS ((char *));
946 static void do_vfp_dp_ldstmia PARAMS ((char *));
947 static void do_vfp_dp_ldstmdb PARAMS ((char *));
948 static void do_vfp_xp_ldstmia PARAMS ((char *));
949 static void do_vfp_xp_ldstmdb PARAMS ((char *));
950 static void do_vfp_sp_compare_z PARAMS ((char *));
951 static void do_vfp_dp_compare_z PARAMS ((char *));
952 static void do_vfp_dp_sp_cvt PARAMS ((char *));
953 static void do_vfp_sp_dp_cvt PARAMS ((char *));
954
955 /* XScale. */
956 static void do_xsc_mia PARAMS ((char *));
957 static void do_xsc_mar PARAMS ((char *));
958 static void do_xsc_mra PARAMS ((char *));
959
960 /* Maverick. */
961 static void do_mav_binops PARAMS ((char *, int, enum arm_reg_type,
962 enum arm_reg_type));
963 static void do_mav_binops_1a PARAMS ((char *));
964 static void do_mav_binops_1b PARAMS ((char *));
965 static void do_mav_binops_1c PARAMS ((char *));
966 static void do_mav_binops_1d PARAMS ((char *));
967 static void do_mav_binops_1e PARAMS ((char *));
968 static void do_mav_binops_1f PARAMS ((char *));
969 static void do_mav_binops_1g PARAMS ((char *));
970 static void do_mav_binops_1h PARAMS ((char *));
971 static void do_mav_binops_1i PARAMS ((char *));
972 static void do_mav_binops_1j PARAMS ((char *));
973 static void do_mav_binops_1k PARAMS ((char *));
974 static void do_mav_binops_1l PARAMS ((char *));
975 static void do_mav_binops_1m PARAMS ((char *));
976 static void do_mav_binops_1n PARAMS ((char *));
977 static void do_mav_binops_1o PARAMS ((char *));
978 static void do_mav_binops_2a PARAMS ((char *));
979 static void do_mav_binops_2b PARAMS ((char *));
980 static void do_mav_binops_2c PARAMS ((char *));
981 static void do_mav_binops_3a PARAMS ((char *));
982 static void do_mav_binops_3b PARAMS ((char *));
983 static void do_mav_binops_3c PARAMS ((char *));
984 static void do_mav_binops_3d PARAMS ((char *));
985 static void do_mav_triple PARAMS ((char *, int, enum arm_reg_type,
986 enum arm_reg_type,
987 enum arm_reg_type));
988 static void do_mav_triple_4a PARAMS ((char *));
989 static void do_mav_triple_4b PARAMS ((char *));
990 static void do_mav_triple_5a PARAMS ((char *));
991 static void do_mav_triple_5b PARAMS ((char *));
992 static void do_mav_triple_5c PARAMS ((char *));
993 static void do_mav_triple_5d PARAMS ((char *));
994 static void do_mav_triple_5e PARAMS ((char *));
995 static void do_mav_triple_5f PARAMS ((char *));
996 static void do_mav_triple_5g PARAMS ((char *));
997 static void do_mav_triple_5h PARAMS ((char *));
998 static void do_mav_quad PARAMS ((char *, int, enum arm_reg_type,
999 enum arm_reg_type,
1000 enum arm_reg_type,
1001 enum arm_reg_type));
1002 static void do_mav_quad_6a PARAMS ((char *));
1003 static void do_mav_quad_6b PARAMS ((char *));
1004 static void do_mav_dspsc_1 PARAMS ((char *));
1005 static void do_mav_dspsc_2 PARAMS ((char *));
1006 static void do_mav_shift PARAMS ((char *, enum arm_reg_type,
1007 enum arm_reg_type));
1008 static void do_mav_shift_1 PARAMS ((char *));
1009 static void do_mav_shift_2 PARAMS ((char *));
1010 static void do_mav_ldst PARAMS ((char *, enum arm_reg_type));
1011 static void do_mav_ldst_1 PARAMS ((char *));
1012 static void do_mav_ldst_2 PARAMS ((char *));
1013 static void do_mav_ldst_3 PARAMS ((char *));
1014 static void do_mav_ldst_4 PARAMS ((char *));
1015
1016 static int mav_reg_required_here PARAMS ((char **, int,
1017 enum arm_reg_type));
1018 static int mav_parse_offset PARAMS ((char **, int *));
1019
1020 static void fix_new_arm PARAMS ((fragS *, int, short, expressionS *,
1021 int, int));
1022 static int arm_reg_parse PARAMS ((char **, struct hash_control *));
1023 static enum arm_reg_type arm_reg_parse_any PARAMS ((char *));
1024 static const struct asm_psr * arm_psr_parse PARAMS ((char **));
1025 static void symbol_locate PARAMS ((symbolS *, const char *, segT, valueT,
1026 fragS *));
1027 static int add_to_lit_pool PARAMS ((void));
1028 static unsigned validate_immediate PARAMS ((unsigned));
1029 static unsigned validate_immediate_twopart PARAMS ((unsigned int,
1030 unsigned int *));
1031 static int validate_offset_imm PARAMS ((unsigned int, int));
1032 static void opcode_select PARAMS ((int));
1033 static void end_of_line PARAMS ((char *));
1034 static int reg_required_here PARAMS ((char **, int));
1035 static int psr_required_here PARAMS ((char **));
1036 static int co_proc_number PARAMS ((char **));
1037 static int cp_opc_expr PARAMS ((char **, int, int));
1038 static int cp_reg_required_here PARAMS ((char **, int));
1039 static int fp_reg_required_here PARAMS ((char **, int));
1040 static int vfp_sp_reg_required_here PARAMS ((char **, enum vfp_sp_reg_pos));
1041 static int vfp_dp_reg_required_here PARAMS ((char **, enum vfp_dp_reg_pos));
1042 static void vfp_sp_ldstm PARAMS ((char *, enum vfp_ldstm_type));
1043 static void vfp_dp_ldstm PARAMS ((char *, enum vfp_ldstm_type));
1044 static long vfp_sp_reg_list PARAMS ((char **, enum vfp_sp_reg_pos));
1045 static long vfp_dp_reg_list PARAMS ((char **));
1046 static int vfp_psr_required_here PARAMS ((char **str));
1047 static const struct vfp_reg *vfp_psr_parse PARAMS ((char **str));
1048 static int cp_address_offset PARAMS ((char **));
1049 static int cp_address_required_here PARAMS ((char **, int));
1050 static int my_get_float_expression PARAMS ((char **));
1051 static int skip_past_comma PARAMS ((char **));
1052 static int walk_no_bignums PARAMS ((symbolS *));
1053 static int negate_data_op PARAMS ((unsigned long *, unsigned long));
1054 static int data_op2 PARAMS ((char **));
1055 static int fp_op2 PARAMS ((char **));
1056 static long reg_list PARAMS ((char **));
1057 static void thumb_load_store PARAMS ((char *, int, int));
1058 static int decode_shift PARAMS ((char **, int));
1059 static int ldst_extend PARAMS ((char **));
1060 static int ldst_extend_v4 PARAMS ((char **));
1061 static void thumb_add_sub PARAMS ((char *, int));
1062 static void insert_reg PARAMS ((const struct reg_entry *,
1063 struct hash_control *));
1064 static void thumb_shift PARAMS ((char *, int));
1065 static void thumb_mov_compare PARAMS ((char *, int));
1066 static void build_arm_ops_hsh PARAMS ((void));
1067 static void set_constant_flonums PARAMS ((void));
1068 static valueT md_chars_to_number PARAMS ((char *, int));
1069 static void build_reg_hsh PARAMS ((struct reg_map *));
1070 static void insert_reg_alias PARAMS ((char *, int, struct hash_control *));
1071 static int create_register_alias PARAMS ((char *, char *));
1072 static void output_inst PARAMS ((const char *));
1073 static int accum0_required_here PARAMS ((char **));
1074 static int ld_mode_required_here PARAMS ((char **));
1075 static void do_branch25 PARAMS ((char *));
1076 static symbolS * find_real_start PARAMS ((symbolS *));
1077 #ifdef OBJ_ELF
1078 static bfd_reloc_code_real_type arm_parse_reloc PARAMS ((void));
1079 #endif
1080
1081 static int wreg_required_here PARAMS ((char **, int, enum wreg_type));
1082 static void do_iwmmxt_byte_addr PARAMS ((char *));
1083 static void do_iwmmxt_tandc PARAMS ((char *));
1084 static void do_iwmmxt_tbcst PARAMS ((char *));
1085 static void do_iwmmxt_textrc PARAMS ((char *));
1086 static void do_iwmmxt_textrm PARAMS ((char *));
1087 static void do_iwmmxt_tinsr PARAMS ((char *));
1088 static void do_iwmmxt_tmcr PARAMS ((char *));
1089 static void do_iwmmxt_tmcrr PARAMS ((char *));
1090 static void do_iwmmxt_tmia PARAMS ((char *));
1091 static void do_iwmmxt_tmovmsk PARAMS ((char *));
1092 static void do_iwmmxt_tmrc PARAMS ((char *));
1093 static void do_iwmmxt_tmrrc PARAMS ((char *));
1094 static void do_iwmmxt_torc PARAMS ((char *));
1095 static void do_iwmmxt_waligni PARAMS ((char *));
1096 static void do_iwmmxt_wmov PARAMS ((char *));
1097 static void do_iwmmxt_word_addr PARAMS ((char *));
1098 static void do_iwmmxt_wrwr PARAMS ((char *));
1099 static void do_iwmmxt_wrwrwcg PARAMS ((char *));
1100 static void do_iwmmxt_wrwrwr PARAMS ((char *));
1101 static void do_iwmmxt_wshufh PARAMS ((char *));
1102 static void do_iwmmxt_wzero PARAMS ((char *));
1103 static int cp_byte_address_offset PARAMS ((char **));
1104 static int cp_byte_address_required_here PARAMS ((char **));
1105
1106 /* ARM instructions take 4bytes in the object file, Thumb instructions
1107 take 2: */
1108 #define INSN_SIZE 4
1109
1110 /* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
1111 #define MAV_MODE1 0x100c
1112
1113 /* "INSN<cond> X,Y" where X:bit16, Y:bit12. */
1114 #define MAV_MODE2 0x0c10
1115
1116 /* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
1117 #define MAV_MODE3 0x100c
1118
1119 /* "INSN<cond> X,Y,Z" where X:16, Y:0, Z:12. */
1120 #define MAV_MODE4 0x0c0010
1121
1122 /* "INSN<cond> X,Y,Z" where X:12, Y:16, Z:0. */
1123 #define MAV_MODE5 0x00100c
1124
1125 /* "INSN<cond> W,X,Y,Z" where W:5, X:12, Y:16, Z:0. */
1126 #define MAV_MODE6 0x00100c05
1127
1128 struct asm_opcode
1129 {
1130 /* Basic string to match. */
1131 const char * template;
1132
1133 /* Basic instruction code. */
1134 unsigned long value;
1135
1136 /* Offset into the template where the condition code (if any) will be.
1137 If zero, then the instruction is never conditional. */
1138 unsigned cond_offset;
1139
1140 /* Which architecture variant provides this instruction. */
1141 unsigned long variant;
1142
1143 /* Function to call to parse args. */
1144 void (* parms) PARAMS ((char *));
1145 };
1146
1147 static const struct asm_opcode insns[] =
1148 {
1149 /* Core ARM Instructions. */
1150 {"and", 0xe0000000, 3, ARM_EXT_V1, do_arit},
1151 {"ands", 0xe0100000, 3, ARM_EXT_V1, do_arit},
1152 {"eor", 0xe0200000, 3, ARM_EXT_V1, do_arit},
1153 {"eors", 0xe0300000, 3, ARM_EXT_V1, do_arit},
1154 {"sub", 0xe0400000, 3, ARM_EXT_V1, do_arit},
1155 {"subs", 0xe0500000, 3, ARM_EXT_V1, do_arit},
1156 {"rsb", 0xe0600000, 3, ARM_EXT_V1, do_arit},
1157 {"rsbs", 0xe0700000, 3, ARM_EXT_V1, do_arit},
1158 {"add", 0xe0800000, 3, ARM_EXT_V1, do_arit},
1159 {"adds", 0xe0900000, 3, ARM_EXT_V1, do_arit},
1160 {"adc", 0xe0a00000, 3, ARM_EXT_V1, do_arit},
1161 {"adcs", 0xe0b00000, 3, ARM_EXT_V1, do_arit},
1162 {"sbc", 0xe0c00000, 3, ARM_EXT_V1, do_arit},
1163 {"sbcs", 0xe0d00000, 3, ARM_EXT_V1, do_arit},
1164 {"rsc", 0xe0e00000, 3, ARM_EXT_V1, do_arit},
1165 {"rscs", 0xe0f00000, 3, ARM_EXT_V1, do_arit},
1166 {"orr", 0xe1800000, 3, ARM_EXT_V1, do_arit},
1167 {"orrs", 0xe1900000, 3, ARM_EXT_V1, do_arit},
1168 {"bic", 0xe1c00000, 3, ARM_EXT_V1, do_arit},
1169 {"bics", 0xe1d00000, 3, ARM_EXT_V1, do_arit},
1170
1171 {"tst", 0xe1100000, 3, ARM_EXT_V1, do_cmp},
1172 {"tsts", 0xe1100000, 3, ARM_EXT_V1, do_cmp},
1173 {"tstp", 0xe110f000, 3, ARM_EXT_V1, do_cmp},
1174 {"teq", 0xe1300000, 3, ARM_EXT_V1, do_cmp},
1175 {"teqs", 0xe1300000, 3, ARM_EXT_V1, do_cmp},
1176 {"teqp", 0xe130f000, 3, ARM_EXT_V1, do_cmp},
1177 {"cmp", 0xe1500000, 3, ARM_EXT_V1, do_cmp},
1178 {"cmps", 0xe1500000, 3, ARM_EXT_V1, do_cmp},
1179 {"cmpp", 0xe150f000, 3, ARM_EXT_V1, do_cmp},
1180 {"cmn", 0xe1700000, 3, ARM_EXT_V1, do_cmp},
1181 {"cmns", 0xe1700000, 3, ARM_EXT_V1, do_cmp},
1182 {"cmnp", 0xe170f000, 3, ARM_EXT_V1, do_cmp},
1183
1184 {"mov", 0xe1a00000, 3, ARM_EXT_V1, do_mov},
1185 {"movs", 0xe1b00000, 3, ARM_EXT_V1, do_mov},
1186 {"mvn", 0xe1e00000, 3, ARM_EXT_V1, do_mov},
1187 {"mvns", 0xe1f00000, 3, ARM_EXT_V1, do_mov},
1188
1189 {"ldr", 0xe4100000, 3, ARM_EXT_V1, do_ldst},
1190 {"ldrb", 0xe4500000, 3, ARM_EXT_V1, do_ldst},
1191 {"ldrt", 0xe4300000, 3, ARM_EXT_V1, do_ldstt},
1192 {"ldrbt", 0xe4700000, 3, ARM_EXT_V1, do_ldstt},
1193 {"str", 0xe4000000, 3, ARM_EXT_V1, do_ldst},
1194 {"strb", 0xe4400000, 3, ARM_EXT_V1, do_ldst},
1195 {"strt", 0xe4200000, 3, ARM_EXT_V1, do_ldstt},
1196 {"strbt", 0xe4600000, 3, ARM_EXT_V1, do_ldstt},
1197
1198 {"stmia", 0xe8800000, 3, ARM_EXT_V1, do_ldmstm},
1199 {"stmib", 0xe9800000, 3, ARM_EXT_V1, do_ldmstm},
1200 {"stmda", 0xe8000000, 3, ARM_EXT_V1, do_ldmstm},
1201 {"stmdb", 0xe9000000, 3, ARM_EXT_V1, do_ldmstm},
1202 {"stmfd", 0xe9000000, 3, ARM_EXT_V1, do_ldmstm},
1203 {"stmfa", 0xe9800000, 3, ARM_EXT_V1, do_ldmstm},
1204 {"stmea", 0xe8800000, 3, ARM_EXT_V1, do_ldmstm},
1205 {"stmed", 0xe8000000, 3, ARM_EXT_V1, do_ldmstm},
1206
1207 {"ldmia", 0xe8900000, 3, ARM_EXT_V1, do_ldmstm},
1208 {"ldmib", 0xe9900000, 3, ARM_EXT_V1, do_ldmstm},
1209 {"ldmda", 0xe8100000, 3, ARM_EXT_V1, do_ldmstm},
1210 {"ldmdb", 0xe9100000, 3, ARM_EXT_V1, do_ldmstm},
1211 {"ldmfd", 0xe8900000, 3, ARM_EXT_V1, do_ldmstm},
1212 {"ldmfa", 0xe8100000, 3, ARM_EXT_V1, do_ldmstm},
1213 {"ldmea", 0xe9100000, 3, ARM_EXT_V1, do_ldmstm},
1214 {"ldmed", 0xe9900000, 3, ARM_EXT_V1, do_ldmstm},
1215
1216 {"swi", 0xef000000, 3, ARM_EXT_V1, do_swi},
1217 #ifdef TE_WINCE
1218 /* XXX This is the wrong place to do this. Think multi-arch. */
1219 {"bl", 0xeb000000, 2, ARM_EXT_V1, do_branch},
1220 {"b", 0xea000000, 1, ARM_EXT_V1, do_branch},
1221 #else
1222 {"bl", 0xebfffffe, 2, ARM_EXT_V1, do_branch},
1223 {"b", 0xeafffffe, 1, ARM_EXT_V1, do_branch},
1224 #endif
1225
1226 /* Pseudo ops. */
1227 {"adr", 0xe28f0000, 3, ARM_EXT_V1, do_adr},
1228 {"adrl", 0xe28f0000, 3, ARM_EXT_V1, do_adrl},
1229 {"nop", 0xe1a00000, 3, ARM_EXT_V1, do_empty},
1230
1231 /* ARM 2 multiplies. */
1232 {"mul", 0xe0000090, 3, ARM_EXT_V2, do_mul},
1233 {"muls", 0xe0100090, 3, ARM_EXT_V2, do_mul},
1234 {"mla", 0xe0200090, 3, ARM_EXT_V2, do_mla},
1235 {"mlas", 0xe0300090, 3, ARM_EXT_V2, do_mla},
1236
1237 /* Generic coprocessor instructions. */
1238 {"cdp", 0xee000000, 3, ARM_EXT_V2, do_cdp},
1239 {"ldc", 0xec100000, 3, ARM_EXT_V2, do_lstc},
1240 {"ldcl", 0xec500000, 3, ARM_EXT_V2, do_lstc},
1241 {"stc", 0xec000000, 3, ARM_EXT_V2, do_lstc},
1242 {"stcl", 0xec400000, 3, ARM_EXT_V2, do_lstc},
1243 {"mcr", 0xee000010, 3, ARM_EXT_V2, do_co_reg},
1244 {"mrc", 0xee100010, 3, ARM_EXT_V2, do_co_reg},
1245
1246 /* ARM 3 - swp instructions. */
1247 {"swp", 0xe1000090, 3, ARM_EXT_V2S, do_swap},
1248 {"swpb", 0xe1400090, 3, ARM_EXT_V2S, do_swap},
1249
1250 /* ARM 6 Status register instructions. */
1251 {"mrs", 0xe10f0000, 3, ARM_EXT_V3, do_mrs},
1252 {"msr", 0xe120f000, 3, ARM_EXT_V3, do_msr},
1253 /* ScottB: our code uses 0xe128f000 for msr.
1254 NickC: but this is wrong because the bits 16 through 19 are
1255 handled by the PSR_xxx defines above. */
1256
1257 /* ARM 7M long multiplies. */
1258 {"smull", 0xe0c00090, 5, ARM_EXT_V3M, do_mull},
1259 {"smulls", 0xe0d00090, 5, ARM_EXT_V3M, do_mull},
1260 {"umull", 0xe0800090, 5, ARM_EXT_V3M, do_mull},
1261 {"umulls", 0xe0900090, 5, ARM_EXT_V3M, do_mull},
1262 {"smlal", 0xe0e00090, 5, ARM_EXT_V3M, do_mull},
1263 {"smlals", 0xe0f00090, 5, ARM_EXT_V3M, do_mull},
1264 {"umlal", 0xe0a00090, 5, ARM_EXT_V3M, do_mull},
1265 {"umlals", 0xe0b00090, 5, ARM_EXT_V3M, do_mull},
1266
1267 /* ARM Architecture 4. */
1268 {"ldrh", 0xe01000b0, 3, ARM_EXT_V4, do_ldstv4},
1269 {"ldrsh", 0xe01000f0, 3, ARM_EXT_V4, do_ldstv4},
1270 {"ldrsb", 0xe01000d0, 3, ARM_EXT_V4, do_ldstv4},
1271 {"strh", 0xe00000b0, 3, ARM_EXT_V4, do_ldstv4},
1272
1273 /* ARM Architecture 4T. */
1274 /* Note: bx (and blx) are required on V5, even if the processor does
1275 not support Thumb. */
1276 {"bx", 0xe12fff10, 2, ARM_EXT_V4T | ARM_EXT_V5, do_bx},
1277
1278 /* ARM Architecture 5T. */
1279 /* Note: blx has 2 variants, so the .value is set dynamically.
1280 Only one of the variants has conditional execution. */
1281 {"blx", 0xe0000000, 3, ARM_EXT_V5, do_blx},
1282 {"clz", 0xe16f0f10, 3, ARM_EXT_V5, do_clz},
1283 {"bkpt", 0xe1200070, 0, ARM_EXT_V5, do_bkpt},
1284 {"ldc2", 0xfc100000, 0, ARM_EXT_V5, do_lstc2},
1285 {"ldc2l", 0xfc500000, 0, ARM_EXT_V5, do_lstc2},
1286 {"stc2", 0xfc000000, 0, ARM_EXT_V5, do_lstc2},
1287 {"stc2l", 0xfc400000, 0, ARM_EXT_V5, do_lstc2},
1288 {"cdp2", 0xfe000000, 0, ARM_EXT_V5, do_cdp2},
1289 {"mcr2", 0xfe000010, 0, ARM_EXT_V5, do_co_reg2},
1290 {"mrc2", 0xfe100010, 0, ARM_EXT_V5, do_co_reg2},
1291
1292 /* ARM Architecture 5TExP. */
1293 {"smlabb", 0xe1000080, 6, ARM_EXT_V5ExP, do_smla},
1294 {"smlatb", 0xe10000a0, 6, ARM_EXT_V5ExP, do_smla},
1295 {"smlabt", 0xe10000c0, 6, ARM_EXT_V5ExP, do_smla},
1296 {"smlatt", 0xe10000e0, 6, ARM_EXT_V5ExP, do_smla},
1297
1298 {"smlawb", 0xe1200080, 6, ARM_EXT_V5ExP, do_smla},
1299 {"smlawt", 0xe12000c0, 6, ARM_EXT_V5ExP, do_smla},
1300
1301 {"smlalbb", 0xe1400080, 7, ARM_EXT_V5ExP, do_smlal},
1302 {"smlaltb", 0xe14000a0, 7, ARM_EXT_V5ExP, do_smlal},
1303 {"smlalbt", 0xe14000c0, 7, ARM_EXT_V5ExP, do_smlal},
1304 {"smlaltt", 0xe14000e0, 7, ARM_EXT_V5ExP, do_smlal},
1305
1306 {"smulbb", 0xe1600080, 6, ARM_EXT_V5ExP, do_smul},
1307 {"smultb", 0xe16000a0, 6, ARM_EXT_V5ExP, do_smul},
1308 {"smulbt", 0xe16000c0, 6, ARM_EXT_V5ExP, do_smul},
1309 {"smultt", 0xe16000e0, 6, ARM_EXT_V5ExP, do_smul},
1310
1311 {"smulwb", 0xe12000a0, 6, ARM_EXT_V5ExP, do_smul},
1312 {"smulwt", 0xe12000e0, 6, ARM_EXT_V5ExP, do_smul},
1313
1314 {"qadd", 0xe1000050, 4, ARM_EXT_V5ExP, do_qadd},
1315 {"qdadd", 0xe1400050, 5, ARM_EXT_V5ExP, do_qadd},
1316 {"qsub", 0xe1200050, 4, ARM_EXT_V5ExP, do_qadd},
1317 {"qdsub", 0xe1600050, 5, ARM_EXT_V5ExP, do_qadd},
1318
1319 /* ARM Architecture 5TE. */
1320 {"pld", 0xf450f000, 0, ARM_EXT_V5E, do_pld},
1321 {"ldrd", 0xe00000d0, 3, ARM_EXT_V5E, do_ldrd},
1322 {"strd", 0xe00000f0, 3, ARM_EXT_V5E, do_ldrd},
1323
1324 {"mcrr", 0xec400000, 4, ARM_EXT_V5E, do_co_reg2c},
1325 {"mrrc", 0xec500000, 4, ARM_EXT_V5E, do_co_reg2c},
1326
1327 /* ARM Architecture 5TEJ. */
1328 {"bxj", 0xe12fff20, 3, ARM_EXT_V5J, do_bxj},
1329
1330 /* ARM V6. */
1331 { "cps", 0xf1020000, 0, ARM_EXT_V6, do_cps},
1332 { "cpsie", 0xf1080000, 0, ARM_EXT_V6, do_cpsi},
1333 { "cpsid", 0xf10C0000, 0, ARM_EXT_V6, do_cpsi},
1334 { "ldrex", 0xe1900f9f, 5, ARM_EXT_V6, do_ldrex},
1335 { "mcrr2", 0xfc400000, 0, ARM_EXT_V6, do_co_reg2c},
1336 { "mrrc2", 0xfc500000, 0, ARM_EXT_V6, do_co_reg2c},
1337 { "pkhbt", 0xe6800010, 5, ARM_EXT_V6, do_pkhbt},
1338 { "pkhtb", 0xe6800050, 5, ARM_EXT_V6, do_pkhtb},
1339 { "qadd16", 0xe6200f10, 6, ARM_EXT_V6, do_qadd16},
1340 { "qadd8", 0xe6200f90, 5, ARM_EXT_V6, do_qadd16},
1341 { "qaddsubx", 0xe6200f30, 8, ARM_EXT_V6, do_qadd16},
1342 { "qsub16", 0xe6200f70, 6, ARM_EXT_V6, do_qadd16},
1343 { "qsub8", 0xe6200ff0, 5, ARM_EXT_V6, do_qadd16},
1344 { "qsubaddx", 0xe6200f50, 8, ARM_EXT_V6, do_qadd16},
1345 { "sadd16", 0xe6100f10, 6, ARM_EXT_V6, do_qadd16},
1346 { "sadd8", 0xe6100f90, 5, ARM_EXT_V6, do_qadd16},
1347 { "saddsubx", 0xe6100f30, 8, ARM_EXT_V6, do_qadd16},
1348 { "shadd16", 0xe6300f10, 7, ARM_EXT_V6, do_qadd16},
1349 { "shadd8", 0xe6300f90, 6, ARM_EXT_V6, do_qadd16},
1350 { "shaddsubx", 0xe6300f30, 9, ARM_EXT_V6, do_qadd16},
1351 { "shsub16", 0xe6300f70, 7, ARM_EXT_V6, do_qadd16},
1352 { "shsub8", 0xe6300ff0, 6, ARM_EXT_V6, do_qadd16},
1353 { "shsubaddx", 0xe6300f50, 9, ARM_EXT_V6, do_qadd16},
1354 { "ssub16", 0xe6100f70, 6, ARM_EXT_V6, do_qadd16},
1355 { "ssub8", 0xe6100ff0, 5, ARM_EXT_V6, do_qadd16},
1356 { "ssubaddx", 0xe6100f50, 8, ARM_EXT_V6, do_qadd16},
1357 { "uadd16", 0xe6500f10, 6, ARM_EXT_V6, do_qadd16},
1358 { "uadd8", 0xe6500f90, 5, ARM_EXT_V6, do_qadd16},
1359 { "uaddsubx", 0xe6500f30, 8, ARM_EXT_V6, do_qadd16},
1360 { "uhadd16", 0xe6700f10, 7, ARM_EXT_V6, do_qadd16},
1361 { "uhadd8", 0xe6700f90, 6, ARM_EXT_V6, do_qadd16},
1362 { "uhaddsubx", 0xe6700f30, 9, ARM_EXT_V6, do_qadd16},
1363 { "uhsub16", 0xe6700f70, 7, ARM_EXT_V6, do_qadd16},
1364 { "uhsub8", 0xe6700ff0, 6, ARM_EXT_V6, do_qadd16},
1365 { "uhsubaddx", 0xe6700f50, 9, ARM_EXT_V6, do_qadd16},
1366 { "uqadd16", 0xe6600f10, 7, ARM_EXT_V6, do_qadd16},
1367 { "uqadd8", 0xe6600f90, 6, ARM_EXT_V6, do_qadd16},
1368 { "uqaddsubx", 0xe6600f30, 9, ARM_EXT_V6, do_qadd16},
1369 { "uqsub16", 0xe6600f70, 7, ARM_EXT_V6, do_qadd16},
1370 { "uqsub8", 0xe6600ff0, 6, ARM_EXT_V6, do_qadd16},
1371 { "uqsubaddx", 0xe6600f50, 9, ARM_EXT_V6, do_qadd16},
1372 { "usub16", 0xe6500f70, 6, ARM_EXT_V6, do_qadd16},
1373 { "usub8", 0xe6500ff0, 5, ARM_EXT_V6, do_qadd16},
1374 { "usubaddx", 0xe6500f50, 8, ARM_EXT_V6, do_qadd16},
1375 { "rev", 0xe6bf0f30, 3, ARM_EXT_V6, do_rev},
1376 { "rev16", 0xe6bf0fb0, 5, ARM_EXT_V6, do_rev},
1377 { "revsh", 0xe6ff0fb0, 5, ARM_EXT_V6, do_rev},
1378 { "rfeia", 0xf8900a00, 0, ARM_EXT_V6, do_rfe},
1379 { "rfeib", 0xf9900a00, 0, ARM_EXT_V6, do_rfe},
1380 { "rfeda", 0xf8100a00, 0, ARM_EXT_V6, do_rfe},
1381 { "rfedb", 0xf9100a00, 0, ARM_EXT_V6, do_rfe},
1382 { "rfefd", 0xf8900a00, 0, ARM_EXT_V6, do_rfe},
1383 { "rfefa", 0xf9900a00, 0, ARM_EXT_V6, do_rfe},
1384 { "rfeea", 0xf8100a00, 0, ARM_EXT_V6, do_rfe},
1385 { "rfeed", 0xf9100a00, 0, ARM_EXT_V6, do_rfe},
1386 { "sxtah", 0xe6b00070, 5, ARM_EXT_V6, do_sxtah},
1387 { "sxtab16", 0xe6800070, 7, ARM_EXT_V6, do_sxtah},
1388 { "sxtab", 0xe6a00070, 5, ARM_EXT_V6, do_sxtah},
1389 { "sxth", 0xe6bf0070, 4, ARM_EXT_V6, do_sxth},
1390 { "sxtb16", 0xe68f0070, 6, ARM_EXT_V6, do_sxth},
1391 { "sxtb", 0xe6af0070, 4, ARM_EXT_V6, do_sxth},
1392 { "uxtah", 0xe6f00070, 5, ARM_EXT_V6, do_sxtah},
1393 { "uxtab16", 0xe6c00070, 7, ARM_EXT_V6, do_sxtah},
1394 { "uxtab", 0xe6e00070, 5, ARM_EXT_V6, do_sxtah},
1395 { "uxth", 0xe6ff0070, 4, ARM_EXT_V6, do_sxth},
1396 { "uxtb16", 0xe6cf0070, 6, ARM_EXT_V6, do_sxth},
1397 { "uxtb", 0xe6ef0070, 4, ARM_EXT_V6, do_sxth},
1398 { "sel", 0xe68000b0, 3, ARM_EXT_V6, do_qadd16},
1399 { "setend", 0xf1010000, 0, ARM_EXT_V6, do_setend},
1400 { "smlad", 0xe7000010, 5, ARM_EXT_V6, do_smlad},
1401 { "smladx", 0xe7000030, 6, ARM_EXT_V6, do_smlad},
1402 { "smlald", 0xe7400010, 6, ARM_EXT_V6, do_smlald},
1403 { "smlaldx", 0xe7400030, 7, ARM_EXT_V6, do_smlald},
1404 { "smlsd", 0xe7000050, 5, ARM_EXT_V6, do_smlad},
1405 { "smlsdx", 0xe7000070, 6, ARM_EXT_V6, do_smlad},
1406 { "smlsld", 0xe7400050, 6, ARM_EXT_V6, do_smlald},
1407 { "smlsldx", 0xe7400070, 7, ARM_EXT_V6, do_smlald},
1408 { "smmla", 0xe7500010, 5, ARM_EXT_V6, do_smlad},
1409 { "smmlar", 0xe7500030, 6, ARM_EXT_V6, do_smlad},
1410 { "smmls", 0xe75000d0, 5, ARM_EXT_V6, do_smlad},
1411 { "smmlsr", 0xe75000f0, 6, ARM_EXT_V6, do_smlad},
1412 { "smmul", 0xe750f010, 5, ARM_EXT_V6, do_smmul},
1413 { "smmulr", 0xe750f030, 6, ARM_EXT_V6, do_smmul},
1414 { "smuad", 0xe700f010, 5, ARM_EXT_V6, do_smmul},
1415 { "smuadx", 0xe700f030, 6, ARM_EXT_V6, do_smmul},
1416 { "smusd", 0xe700f050, 5, ARM_EXT_V6, do_smmul},
1417 { "smusdx", 0xe700f070, 6, ARM_EXT_V6, do_smmul},
1418 { "srsia", 0xf8cd0500, 0, ARM_EXT_V6, do_srs},
1419 { "srsib", 0xf9cd0500, 0, ARM_EXT_V6, do_srs},
1420 { "srsda", 0xf84d0500, 0, ARM_EXT_V6, do_srs},
1421 { "srsdb", 0xf94d0500, 0, ARM_EXT_V6, do_srs},
1422 { "ssat", 0xe6a00010, 4, ARM_EXT_V6, do_ssat},
1423 { "ssat16", 0xe6a00f30, 6, ARM_EXT_V6, do_ssat16},
1424 { "strex", 0xe1800f90, 5, ARM_EXT_V6, do_strex},
1425 { "umaal", 0xe0400090, 5, ARM_EXT_V6, do_umaal},
1426 { "usad8", 0xe780f010, 5, ARM_EXT_V6, do_smmul},
1427 { "usada8", 0xe7800010, 6, ARM_EXT_V6, do_smlad},
1428 { "usat", 0xe6e00010, 4, ARM_EXT_V6, do_usat},
1429 { "usat16", 0xe6e00f30, 6, ARM_EXT_V6, do_usat16},
1430
1431 /* Core FPA instruction set (V1). */
1432 {"wfs", 0xee200110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
1433 {"rfs", 0xee300110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
1434 {"wfc", 0xee400110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
1435 {"rfc", 0xee500110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
1436
1437 {"ldfs", 0xec100100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1438 {"ldfd", 0xec108100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1439 {"ldfe", 0xec500100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1440 {"ldfp", 0xec508100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1441
1442 {"stfs", 0xec000100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1443 {"stfd", 0xec008100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1444 {"stfe", 0xec400100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1445 {"stfp", 0xec408100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1446
1447 {"mvfs", 0xee008100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1448 {"mvfsp", 0xee008120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1449 {"mvfsm", 0xee008140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1450 {"mvfsz", 0xee008160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1451 {"mvfd", 0xee008180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1452 {"mvfdp", 0xee0081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1453 {"mvfdm", 0xee0081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1454 {"mvfdz", 0xee0081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1455 {"mvfe", 0xee088100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1456 {"mvfep", 0xee088120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1457 {"mvfem", 0xee088140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1458 {"mvfez", 0xee088160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1459
1460 {"mnfs", 0xee108100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1461 {"mnfsp", 0xee108120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1462 {"mnfsm", 0xee108140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1463 {"mnfsz", 0xee108160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1464 {"mnfd", 0xee108180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1465 {"mnfdp", 0xee1081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1466 {"mnfdm", 0xee1081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1467 {"mnfdz", 0xee1081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1468 {"mnfe", 0xee188100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1469 {"mnfep", 0xee188120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1470 {"mnfem", 0xee188140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1471 {"mnfez", 0xee188160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1472
1473 {"abss", 0xee208100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1474 {"abssp", 0xee208120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1475 {"abssm", 0xee208140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1476 {"abssz", 0xee208160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1477 {"absd", 0xee208180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1478 {"absdp", 0xee2081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1479 {"absdm", 0xee2081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1480 {"absdz", 0xee2081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1481 {"abse", 0xee288100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1482 {"absep", 0xee288120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1483 {"absem", 0xee288140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1484 {"absez", 0xee288160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1485
1486 {"rnds", 0xee308100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1487 {"rndsp", 0xee308120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1488 {"rndsm", 0xee308140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1489 {"rndsz", 0xee308160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1490 {"rndd", 0xee308180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1491 {"rnddp", 0xee3081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1492 {"rnddm", 0xee3081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1493 {"rnddz", 0xee3081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1494 {"rnde", 0xee388100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1495 {"rndep", 0xee388120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1496 {"rndem", 0xee388140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1497 {"rndez", 0xee388160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1498
1499 {"sqts", 0xee408100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1500 {"sqtsp", 0xee408120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1501 {"sqtsm", 0xee408140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1502 {"sqtsz", 0xee408160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1503 {"sqtd", 0xee408180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1504 {"sqtdp", 0xee4081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1505 {"sqtdm", 0xee4081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1506 {"sqtdz", 0xee4081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1507 {"sqte", 0xee488100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1508 {"sqtep", 0xee488120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1509 {"sqtem", 0xee488140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1510 {"sqtez", 0xee488160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1511
1512 {"logs", 0xee508100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1513 {"logsp", 0xee508120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1514 {"logsm", 0xee508140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1515 {"logsz", 0xee508160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1516 {"logd", 0xee508180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1517 {"logdp", 0xee5081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1518 {"logdm", 0xee5081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1519 {"logdz", 0xee5081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1520 {"loge", 0xee588100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1521 {"logep", 0xee588120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1522 {"logem", 0xee588140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1523 {"logez", 0xee588160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1524
1525 {"lgns", 0xee608100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1526 {"lgnsp", 0xee608120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1527 {"lgnsm", 0xee608140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1528 {"lgnsz", 0xee608160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1529 {"lgnd", 0xee608180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1530 {"lgndp", 0xee6081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1531 {"lgndm", 0xee6081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1532 {"lgndz", 0xee6081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1533 {"lgne", 0xee688100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1534 {"lgnep", 0xee688120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1535 {"lgnem", 0xee688140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1536 {"lgnez", 0xee688160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1537
1538 {"exps", 0xee708100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1539 {"expsp", 0xee708120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1540 {"expsm", 0xee708140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1541 {"expsz", 0xee708160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1542 {"expd", 0xee708180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1543 {"expdp", 0xee7081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1544 {"expdm", 0xee7081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1545 {"expdz", 0xee7081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1546 {"expe", 0xee788100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1547 {"expep", 0xee788120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1548 {"expem", 0xee788140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1549 {"expdz", 0xee788160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1550
1551 {"sins", 0xee808100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1552 {"sinsp", 0xee808120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1553 {"sinsm", 0xee808140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1554 {"sinsz", 0xee808160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1555 {"sind", 0xee808180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1556 {"sindp", 0xee8081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1557 {"sindm", 0xee8081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1558 {"sindz", 0xee8081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1559 {"sine", 0xee888100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1560 {"sinep", 0xee888120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1561 {"sinem", 0xee888140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1562 {"sinez", 0xee888160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1563
1564 {"coss", 0xee908100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1565 {"cossp", 0xee908120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1566 {"cossm", 0xee908140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1567 {"cossz", 0xee908160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1568 {"cosd", 0xee908180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1569 {"cosdp", 0xee9081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1570 {"cosdm", 0xee9081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1571 {"cosdz", 0xee9081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1572 {"cose", 0xee988100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1573 {"cosep", 0xee988120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1574 {"cosem", 0xee988140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1575 {"cosez", 0xee988160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1576
1577 {"tans", 0xeea08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1578 {"tansp", 0xeea08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1579 {"tansm", 0xeea08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1580 {"tansz", 0xeea08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1581 {"tand", 0xeea08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1582 {"tandp", 0xeea081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1583 {"tandm", 0xeea081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1584 {"tandz", 0xeea081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1585 {"tane", 0xeea88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1586 {"tanep", 0xeea88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1587 {"tanem", 0xeea88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1588 {"tanez", 0xeea88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1589
1590 {"asns", 0xeeb08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1591 {"asnsp", 0xeeb08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1592 {"asnsm", 0xeeb08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1593 {"asnsz", 0xeeb08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1594 {"asnd", 0xeeb08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1595 {"asndp", 0xeeb081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1596 {"asndm", 0xeeb081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1597 {"asndz", 0xeeb081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1598 {"asne", 0xeeb88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1599 {"asnep", 0xeeb88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1600 {"asnem", 0xeeb88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1601 {"asnez", 0xeeb88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1602
1603 {"acss", 0xeec08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1604 {"acssp", 0xeec08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1605 {"acssm", 0xeec08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1606 {"acssz", 0xeec08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1607 {"acsd", 0xeec08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1608 {"acsdp", 0xeec081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1609 {"acsdm", 0xeec081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1610 {"acsdz", 0xeec081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1611 {"acse", 0xeec88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1612 {"acsep", 0xeec88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1613 {"acsem", 0xeec88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1614 {"acsez", 0xeec88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1615
1616 {"atns", 0xeed08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1617 {"atnsp", 0xeed08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1618 {"atnsm", 0xeed08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1619 {"atnsz", 0xeed08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1620 {"atnd", 0xeed08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1621 {"atndp", 0xeed081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1622 {"atndm", 0xeed081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1623 {"atndz", 0xeed081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1624 {"atne", 0xeed88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1625 {"atnep", 0xeed88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1626 {"atnem", 0xeed88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1627 {"atnez", 0xeed88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1628
1629 {"urds", 0xeee08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1630 {"urdsp", 0xeee08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1631 {"urdsm", 0xeee08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1632 {"urdsz", 0xeee08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1633 {"urdd", 0xeee08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1634 {"urddp", 0xeee081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1635 {"urddm", 0xeee081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1636 {"urddz", 0xeee081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1637 {"urde", 0xeee88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1638 {"urdep", 0xeee88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1639 {"urdem", 0xeee88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1640 {"urdez", 0xeee88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1641
1642 {"nrms", 0xeef08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1643 {"nrmsp", 0xeef08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1644 {"nrmsm", 0xeef08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1645 {"nrmsz", 0xeef08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1646 {"nrmd", 0xeef08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1647 {"nrmdp", 0xeef081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1648 {"nrmdm", 0xeef081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1649 {"nrmdz", 0xeef081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1650 {"nrme", 0xeef88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1651 {"nrmep", 0xeef88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1652 {"nrmem", 0xeef88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1653 {"nrmez", 0xeef88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1654
1655 {"adfs", 0xee000100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1656 {"adfsp", 0xee000120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1657 {"adfsm", 0xee000140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1658 {"adfsz", 0xee000160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1659 {"adfd", 0xee000180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1660 {"adfdp", 0xee0001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1661 {"adfdm", 0xee0001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1662 {"adfdz", 0xee0001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1663 {"adfe", 0xee080100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1664 {"adfep", 0xee080120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1665 {"adfem", 0xee080140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1666 {"adfez", 0xee080160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1667
1668 {"sufs", 0xee200100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1669 {"sufsp", 0xee200120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1670 {"sufsm", 0xee200140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1671 {"sufsz", 0xee200160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1672 {"sufd", 0xee200180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1673 {"sufdp", 0xee2001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1674 {"sufdm", 0xee2001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1675 {"sufdz", 0xee2001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1676 {"sufe", 0xee280100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1677 {"sufep", 0xee280120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1678 {"sufem", 0xee280140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1679 {"sufez", 0xee280160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1680
1681 {"rsfs", 0xee300100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1682 {"rsfsp", 0xee300120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1683 {"rsfsm", 0xee300140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1684 {"rsfsz", 0xee300160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1685 {"rsfd", 0xee300180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1686 {"rsfdp", 0xee3001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1687 {"rsfdm", 0xee3001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1688 {"rsfdz", 0xee3001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1689 {"rsfe", 0xee380100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1690 {"rsfep", 0xee380120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1691 {"rsfem", 0xee380140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1692 {"rsfez", 0xee380160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1693
1694 {"mufs", 0xee100100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1695 {"mufsp", 0xee100120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1696 {"mufsm", 0xee100140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1697 {"mufsz", 0xee100160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1698 {"mufd", 0xee100180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1699 {"mufdp", 0xee1001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1700 {"mufdm", 0xee1001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1701 {"mufdz", 0xee1001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1702 {"mufe", 0xee180100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1703 {"mufep", 0xee180120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1704 {"mufem", 0xee180140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1705 {"mufez", 0xee180160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1706
1707 {"dvfs", 0xee400100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1708 {"dvfsp", 0xee400120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1709 {"dvfsm", 0xee400140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1710 {"dvfsz", 0xee400160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1711 {"dvfd", 0xee400180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1712 {"dvfdp", 0xee4001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1713 {"dvfdm", 0xee4001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1714 {"dvfdz", 0xee4001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1715 {"dvfe", 0xee480100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1716 {"dvfep", 0xee480120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1717 {"dvfem", 0xee480140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1718 {"dvfez", 0xee480160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1719
1720 {"rdfs", 0xee500100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1721 {"rdfsp", 0xee500120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1722 {"rdfsm", 0xee500140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1723 {"rdfsz", 0xee500160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1724 {"rdfd", 0xee500180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1725 {"rdfdp", 0xee5001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1726 {"rdfdm", 0xee5001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1727 {"rdfdz", 0xee5001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1728 {"rdfe", 0xee580100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1729 {"rdfep", 0xee580120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1730 {"rdfem", 0xee580140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1731 {"rdfez", 0xee580160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1732
1733 {"pows", 0xee600100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1734 {"powsp", 0xee600120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1735 {"powsm", 0xee600140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1736 {"powsz", 0xee600160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1737 {"powd", 0xee600180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1738 {"powdp", 0xee6001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1739 {"powdm", 0xee6001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1740 {"powdz", 0xee6001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1741 {"powe", 0xee680100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1742 {"powep", 0xee680120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1743 {"powem", 0xee680140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1744 {"powez", 0xee680160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1745
1746 {"rpws", 0xee700100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1747 {"rpwsp", 0xee700120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1748 {"rpwsm", 0xee700140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1749 {"rpwsz", 0xee700160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1750 {"rpwd", 0xee700180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1751 {"rpwdp", 0xee7001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1752 {"rpwdm", 0xee7001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1753 {"rpwdz", 0xee7001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1754 {"rpwe", 0xee780100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1755 {"rpwep", 0xee780120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1756 {"rpwem", 0xee780140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1757 {"rpwez", 0xee780160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1758
1759 {"rmfs", 0xee800100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1760 {"rmfsp", 0xee800120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1761 {"rmfsm", 0xee800140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1762 {"rmfsz", 0xee800160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1763 {"rmfd", 0xee800180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1764 {"rmfdp", 0xee8001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1765 {"rmfdm", 0xee8001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1766 {"rmfdz", 0xee8001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1767 {"rmfe", 0xee880100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1768 {"rmfep", 0xee880120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1769 {"rmfem", 0xee880140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1770 {"rmfez", 0xee880160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1771
1772 {"fmls", 0xee900100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1773 {"fmlsp", 0xee900120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1774 {"fmlsm", 0xee900140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1775 {"fmlsz", 0xee900160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1776 {"fmld", 0xee900180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1777 {"fmldp", 0xee9001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1778 {"fmldm", 0xee9001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1779 {"fmldz", 0xee9001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1780 {"fmle", 0xee980100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1781 {"fmlep", 0xee980120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1782 {"fmlem", 0xee980140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1783 {"fmlez", 0xee980160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1784
1785 {"fdvs", 0xeea00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1786 {"fdvsp", 0xeea00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1787 {"fdvsm", 0xeea00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1788 {"fdvsz", 0xeea00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1789 {"fdvd", 0xeea00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1790 {"fdvdp", 0xeea001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1791 {"fdvdm", 0xeea001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1792 {"fdvdz", 0xeea001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1793 {"fdve", 0xeea80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1794 {"fdvep", 0xeea80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1795 {"fdvem", 0xeea80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1796 {"fdvez", 0xeea80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1797
1798 {"frds", 0xeeb00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1799 {"frdsp", 0xeeb00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1800 {"frdsm", 0xeeb00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1801 {"frdsz", 0xeeb00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1802 {"frdd", 0xeeb00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1803 {"frddp", 0xeeb001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1804 {"frddm", 0xeeb001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1805 {"frddz", 0xeeb001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1806 {"frde", 0xeeb80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1807 {"frdep", 0xeeb80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1808 {"frdem", 0xeeb80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1809 {"frdez", 0xeeb80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1810
1811 {"pols", 0xeec00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1812 {"polsp", 0xeec00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1813 {"polsm", 0xeec00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1814 {"polsz", 0xeec00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1815 {"pold", 0xeec00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1816 {"poldp", 0xeec001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1817 {"poldm", 0xeec001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1818 {"poldz", 0xeec001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1819 {"pole", 0xeec80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1820 {"polep", 0xeec80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1821 {"polem", 0xeec80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1822 {"polez", 0xeec80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1823
1824 {"cmf", 0xee90f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
1825 {"cmfe", 0xeed0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
1826 {"cnf", 0xeeb0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
1827 {"cnfe", 0xeef0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
1828 /* The FPA10 data sheet suggests that the 'E' of cmfe/cnfe should
1829 not be an optional suffix, but part of the instruction. To be
1830 compatible, we accept either. */
1831 {"cmfe", 0xeed0f110, 4, FPU_FPA_EXT_V1, do_fpa_cmp},
1832 {"cnfe", 0xeef0f110, 4, FPU_FPA_EXT_V1, do_fpa_cmp},
1833
1834 {"flts", 0xee000110, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1835 {"fltsp", 0xee000130, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1836 {"fltsm", 0xee000150, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1837 {"fltsz", 0xee000170, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1838 {"fltd", 0xee000190, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1839 {"fltdp", 0xee0001b0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1840 {"fltdm", 0xee0001d0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1841 {"fltdz", 0xee0001f0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1842 {"flte", 0xee080110, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1843 {"fltep", 0xee080130, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1844 {"fltem", 0xee080150, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1845 {"fltez", 0xee080170, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1846
1847 /* The implementation of the FIX instruction is broken on some
1848 assemblers, in that it accepts a precision specifier as well as a
1849 rounding specifier, despite the fact that this is meaningless.
1850 To be more compatible, we accept it as well, though of course it
1851 does not set any bits. */
1852 {"fix", 0xee100110, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1853 {"fixp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1854 {"fixm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1855 {"fixz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1856 {"fixsp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1857 {"fixsm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1858 {"fixsz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1859 {"fixdp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1860 {"fixdm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1861 {"fixdz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1862 {"fixep", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1863 {"fixem", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1864 {"fixez", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1865
1866 /* Instructions that were new with the real FPA, call them V2. */
1867 {"lfm", 0xec100200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1868 {"lfmfd", 0xec900200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1869 {"lfmea", 0xed100200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1870 {"sfm", 0xec000200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1871 {"sfmfd", 0xed000200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1872 {"sfmea", 0xec800200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1873
1874 /* VFP V1xD (single precision). */
1875 /* Moves and type conversions. */
1876 {"fcpys", 0xeeb00a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1877 {"fmrs", 0xee100a10, 4, FPU_VFP_EXT_V1xD, do_vfp_reg_from_sp},
1878 {"fmsr", 0xee000a10, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_from_reg},
1879 {"fmstat", 0xeef1fa10, 6, FPU_VFP_EXT_V1xD, do_empty},
1880 {"fsitos", 0xeeb80ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1881 {"fuitos", 0xeeb80a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1882 {"ftosis", 0xeebd0a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1883 {"ftosizs", 0xeebd0ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1884 {"ftouis", 0xeebc0a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1885 {"ftouizs", 0xeebc0ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1886 {"fmrx", 0xeef00a10, 4, FPU_VFP_EXT_V1xD, do_vfp_reg_from_ctrl},
1887 {"fmxr", 0xeee00a10, 4, FPU_VFP_EXT_V1xD, do_vfp_ctrl_from_reg},
1888
1889 /* Memory operations. */
1890 {"flds", 0xed100a00, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_ldst},
1891 {"fsts", 0xed000a00, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_ldst},
1892 {"fldmias", 0xec900a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
1893 {"fldmfds", 0xec900a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
1894 {"fldmdbs", 0xed300a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
1895 {"fldmeas", 0xed300a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
1896 {"fldmiax", 0xec900b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
1897 {"fldmfdx", 0xec900b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
1898 {"fldmdbx", 0xed300b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
1899 {"fldmeax", 0xed300b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
1900 {"fstmias", 0xec800a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
1901 {"fstmeas", 0xec800a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
1902 {"fstmdbs", 0xed200a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
1903 {"fstmfds", 0xed200a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
1904 {"fstmiax", 0xec800b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
1905 {"fstmeax", 0xec800b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
1906 {"fstmdbx", 0xed200b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
1907 {"fstmfdx", 0xed200b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
1908
1909 /* Monadic operations. */
1910 {"fabss", 0xeeb00ac0, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1911 {"fnegs", 0xeeb10a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1912 {"fsqrts", 0xeeb10ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1913
1914 /* Dyadic operations. */
1915 {"fadds", 0xee300a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1916 {"fsubs", 0xee300a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1917 {"fmuls", 0xee200a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1918 {"fdivs", 0xee800a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1919 {"fmacs", 0xee000a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1920 {"fmscs", 0xee100a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1921 {"fnmuls", 0xee200a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1922 {"fnmacs", 0xee000a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1923 {"fnmscs", 0xee100a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1924
1925 /* Comparisons. */
1926 {"fcmps", 0xeeb40a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1927 {"fcmpzs", 0xeeb50a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_compare_z},
1928 {"fcmpes", 0xeeb40ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1929 {"fcmpezs", 0xeeb50ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_compare_z},
1930
1931 /* VFP V1 (Double precision). */
1932 /* Moves and type conversions. */
1933 {"fcpyd", 0xeeb00b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1934 {"fcvtds", 0xeeb70ac0, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
1935 {"fcvtsd", 0xeeb70bc0, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
1936 {"fmdhr", 0xee200b10, 5, FPU_VFP_EXT_V1, do_vfp_dp_from_reg},
1937 {"fmdlr", 0xee000b10, 5, FPU_VFP_EXT_V1, do_vfp_dp_from_reg},
1938 {"fmrdh", 0xee300b10, 5, FPU_VFP_EXT_V1, do_vfp_reg_from_dp},
1939 {"fmrdl", 0xee100b10, 5, FPU_VFP_EXT_V1, do_vfp_reg_from_dp},
1940 {"fsitod", 0xeeb80bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
1941 {"fuitod", 0xeeb80b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
1942 {"ftosid", 0xeebd0b40, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
1943 {"ftosizd", 0xeebd0bc0, 7, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
1944 {"ftouid", 0xeebc0b40, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
1945 {"ftouizd", 0xeebc0bc0, 7, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
1946
1947 /* Memory operations. */
1948 {"fldd", 0xed100b00, 4, FPU_VFP_EXT_V1, do_vfp_dp_ldst},
1949 {"fstd", 0xed000b00, 4, FPU_VFP_EXT_V1, do_vfp_dp_ldst},
1950 {"fldmiad", 0xec900b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
1951 {"fldmfdd", 0xec900b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
1952 {"fldmdbd", 0xed300b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
1953 {"fldmead", 0xed300b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
1954 {"fstmiad", 0xec800b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
1955 {"fstmead", 0xec800b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
1956 {"fstmdbd", 0xed200b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
1957 {"fstmfdd", 0xed200b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
1958
1959 /* Monadic operations. */
1960 {"fabsd", 0xeeb00bc0, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1961 {"fnegd", 0xeeb10b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1962 {"fsqrtd", 0xeeb10bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1963
1964 /* Dyadic operations. */
1965 {"faddd", 0xee300b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1966 {"fsubd", 0xee300b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1967 {"fmuld", 0xee200b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1968 {"fdivd", 0xee800b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1969 {"fmacd", 0xee000b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1970 {"fmscd", 0xee100b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1971 {"fnmuld", 0xee200b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1972 {"fnmacd", 0xee000b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1973 {"fnmscd", 0xee100b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1974
1975 /* Comparisons. */
1976 {"fcmpd", 0xeeb40b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1977 {"fcmpzd", 0xeeb50b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_compare_z},
1978 {"fcmped", 0xeeb40bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1979 {"fcmpezd", 0xeeb50bc0, 7, FPU_VFP_EXT_V1, do_vfp_dp_compare_z},
1980
1981 /* VFP V2. */
1982 {"fmsrr", 0xec400a10, 5, FPU_VFP_EXT_V2, do_vfp_sp2_from_reg2},
1983 {"fmrrs", 0xec500a10, 5, FPU_VFP_EXT_V2, do_vfp_reg2_from_sp2},
1984 {"fmdrr", 0xec400b10, 5, FPU_VFP_EXT_V2, do_vfp_dp_from_reg2},
1985 {"fmrrd", 0xec500b10, 5, FPU_VFP_EXT_V2, do_vfp_reg2_from_dp},
1986
1987 /* Intel XScale extensions to ARM V5 ISA. (All use CP0). */
1988 {"mia", 0xee200010, 3, ARM_CEXT_XSCALE, do_xsc_mia},
1989 {"miaph", 0xee280010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
1990 {"miabb", 0xee2c0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
1991 {"miabt", 0xee2d0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
1992 {"miatb", 0xee2e0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
1993 {"miatt", 0xee2f0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
1994 {"mar", 0xec400000, 3, ARM_CEXT_XSCALE, do_xsc_mar},
1995 {"mra", 0xec500000, 3, ARM_CEXT_XSCALE, do_xsc_mra},
1996
1997 /* Intel Wireless MMX technology instructions. */
1998 {"tandcb", 0xee130130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
1999 {"tandch", 0xee530130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
2000 {"tandcw", 0xee930130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
2001 {"tbcstb", 0xee400010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
2002 {"tbcsth", 0xee400050, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
2003 {"tbcstw", 0xee400090, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
2004 {"textrcb", 0xee130170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
2005 {"textrch", 0xee530170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
2006 {"textrcw", 0xee930170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
2007 {"textrmub", 0xee100070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
2008 {"textrmuh", 0xee500070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
2009 {"textrmuw", 0xee900070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
2010 {"textrmsb", 0xee100078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
2011 {"textrmsh", 0xee500078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
2012 {"textrmsw", 0xee900078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
2013 {"tinsrb", 0xee600010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
2014 {"tinsrh", 0xee600050, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
2015 {"tinsrw", 0xee600090, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
2016 {"tmcr", 0xee000110, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmcr},
2017 {"tmcrr", 0xec400000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_tmcrr},
2018 {"tmia", 0xee200010, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
2019 {"tmiaph", 0xee280010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
2020 {"tmiabb", 0xee2c0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
2021 {"tmiabt", 0xee2d0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
2022 {"tmiatb", 0xee2e0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
2023 {"tmiatt", 0xee2f0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
2024 {"tmovmskb", 0xee100030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
2025 {"tmovmskh", 0xee500030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
2026 {"tmovmskw", 0xee900030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
2027 {"tmrc", 0xee100110, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmrc},
2028 {"tmrrc", 0xec500000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_tmrrc},
2029 {"torcb", 0xee130150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
2030 {"torch", 0xee530150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
2031 {"torcw", 0xee930150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
2032 {"waccb", 0xee0001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2033 {"wacch", 0xee4001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2034 {"waccw", 0xee8001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2035 {"waddbss", 0xee300180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2036 {"waddb", 0xee000180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2037 {"waddbus", 0xee100180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2038 {"waddhss", 0xee700180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2039 {"waddh", 0xee400180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2040 {"waddhus", 0xee500180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2041 {"waddwss", 0xeeb00180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2042 {"waddw", 0xee800180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2043 {"waddwus", 0xee900180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2044 {"waligni", 0xee000020, 7, ARM_CEXT_IWMMXT, do_iwmmxt_waligni},
2045 {"walignr0", 0xee800020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2046 {"walignr1", 0xee900020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2047 {"walignr2", 0xeea00020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2048 {"walignr3", 0xeeb00020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2049 {"wand", 0xee200000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2050 {"wandn", 0xee300000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2051 {"wavg2b", 0xee800000, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2052 {"wavg2br", 0xee900000, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2053 {"wavg2h", 0xeec00000, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2054 {"wavg2hr", 0xeed00000, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2055 {"wcmpeqb", 0xee000060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2056 {"wcmpeqh", 0xee400060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2057 {"wcmpeqw", 0xee800060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2058 {"wcmpgtub", 0xee100060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2059 {"wcmpgtuh", 0xee500060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2060 {"wcmpgtuw", 0xee900060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2061 {"wcmpgtsb", 0xee300060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2062 {"wcmpgtsh", 0xee700060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2063 {"wcmpgtsw", 0xeeb00060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2064 {"wldrb", 0xec100000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
2065 {"wldrh", 0xec100100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
2066 {"wldrw", 0xec100200, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
2067 {"wldrd", 0xec100300, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
2068 {"wmacs", 0xee600100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2069 {"wmacsz", 0xee700100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2070 {"wmacu", 0xee400100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2071 {"wmacuz", 0xee500100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2072 {"wmadds", 0xeea00100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2073 {"wmaddu", 0xee800100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2074 {"wmaxsb", 0xee200160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2075 {"wmaxsh", 0xee600160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2076 {"wmaxsw", 0xeea00160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2077 {"wmaxub", 0xee000160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2078 {"wmaxuh", 0xee400160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2079 {"wmaxuw", 0xee800160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2080 {"wminsb", 0xee300160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2081 {"wminsh", 0xee700160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2082 {"wminsw", 0xeeb00160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2083 {"wminub", 0xee100160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2084 {"wminuh", 0xee500160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2085 {"wminuw", 0xee900160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2086 {"wmov", 0xee000000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wmov},
2087 {"wmulsm", 0xee300100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2088 {"wmulsl", 0xee200100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2089 {"wmulum", 0xee100100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2090 {"wmulul", 0xee000100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2091 {"wor", 0xee000000, 3, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2092 {"wpackhss", 0xee700080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2093 {"wpackhus", 0xee500080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2094 {"wpackwss", 0xeeb00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2095 {"wpackwus", 0xee900080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2096 {"wpackdss", 0xeef00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2097 {"wpackdus", 0xeed00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2098 {"wrorh", 0xee700040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2099 {"wrorhg", 0xee700148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2100 {"wrorw", 0xeeb00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2101 {"wrorwg", 0xeeb00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2102 {"wrord", 0xeef00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2103 {"wrordg", 0xeef00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2104 {"wsadb", 0xee000120, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2105 {"wsadbz", 0xee100120, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2106 {"wsadh", 0xee400120, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2107 {"wsadhz", 0xee500120, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2108 {"wshufh", 0xee0001e0, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wshufh},
2109 {"wsllh", 0xee500040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2110 {"wsllhg", 0xee500148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2111 {"wsllw", 0xee900040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2112 {"wsllwg", 0xee900148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2113 {"wslld", 0xeed00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2114 {"wslldg", 0xeed00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2115 {"wsrah", 0xee400040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2116 {"wsrahg", 0xee400148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2117 {"wsraw", 0xee800040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2118 {"wsrawg", 0xee800148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2119 {"wsrad", 0xeec00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2120 {"wsradg", 0xeec00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2121 {"wsrlh", 0xee600040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2122 {"wsrlhg", 0xee600148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2123 {"wsrlw", 0xeea00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2124 {"wsrlwg", 0xeea00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2125 {"wsrld", 0xeee00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2126 {"wsrldg", 0xeee00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2127 {"wstrb", 0xec000000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
2128 {"wstrh", 0xec000100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
2129 {"wstrw", 0xec000200, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
2130 {"wstrd", 0xec000300, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
2131 {"wsubbss", 0xee3001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2132 {"wsubb", 0xee0001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2133 {"wsubbus", 0xee1001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2134 {"wsubhss", 0xee7001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2135 {"wsubh", 0xee4001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2136 {"wsubhus", 0xee5001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2137 {"wsubwss", 0xeeb001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2138 {"wsubw", 0xee8001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2139 {"wsubwus", 0xee9001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2140 {"wunpckehub", 0xee0000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2141 {"wunpckehuh", 0xee4000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2142 {"wunpckehuw", 0xee8000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2143 {"wunpckehsb", 0xee2000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2144 {"wunpckehsh", 0xee6000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2145 {"wunpckehsw", 0xeea000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2146 {"wunpckihb", 0xee1000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2147 {"wunpckihh", 0xee5000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2148 {"wunpckihw", 0xee9000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2149 {"wunpckelub", 0xee0000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2150 {"wunpckeluh", 0xee4000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2151 {"wunpckeluw", 0xee8000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2152 {"wunpckelsb", 0xee2000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2153 {"wunpckelsh", 0xee6000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2154 {"wunpckelsw", 0xeea000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2155 {"wunpckilb", 0xee1000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2156 {"wunpckilh", 0xee5000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2157 {"wunpckilw", 0xee9000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2158 {"wxor", 0xee100000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2159 {"wzero", 0xee300000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wzero},
2160
2161 /* Cirrus Maverick instructions. */
2162 {"cfldrs", 0xec100400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_1},
2163 {"cfldrd", 0xec500400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_2},
2164 {"cfldr32", 0xec100500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_3},
2165 {"cfldr64", 0xec500500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_4},
2166 {"cfstrs", 0xec000400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_1},
2167 {"cfstrd", 0xec400400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_2},
2168 {"cfstr32", 0xec000500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_3},
2169 {"cfstr64", 0xec400500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_4},
2170 {"cfmvsr", 0xee000450, 6, ARM_CEXT_MAVERICK, do_mav_binops_2a},
2171 {"cfmvrs", 0xee100450, 6, ARM_CEXT_MAVERICK, do_mav_binops_1a},
2172 {"cfmvdlr", 0xee000410, 7, ARM_CEXT_MAVERICK, do_mav_binops_2b},
2173 {"cfmvrdl", 0xee100410, 7, ARM_CEXT_MAVERICK, do_mav_binops_1b},
2174 {"cfmvdhr", 0xee000430, 7, ARM_CEXT_MAVERICK, do_mav_binops_2b},
2175 {"cfmvrdh", 0xee100430, 7, ARM_CEXT_MAVERICK, do_mav_binops_1b},
2176 {"cfmv64lr", 0xee000510, 8, ARM_CEXT_MAVERICK, do_mav_binops_2c},
2177 {"cfmvr64l", 0xee100510, 8, ARM_CEXT_MAVERICK, do_mav_binops_1c},
2178 {"cfmv64hr", 0xee000530, 8, ARM_CEXT_MAVERICK, do_mav_binops_2c},
2179 {"cfmvr64h", 0xee100530, 8, ARM_CEXT_MAVERICK, do_mav_binops_1c},
2180 {"cfmval32", 0xee200440, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
2181 {"cfmv32al", 0xee100440, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
2182 {"cfmvam32", 0xee200460, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
2183 {"cfmv32am", 0xee100460, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
2184 {"cfmvah32", 0xee200480, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
2185 {"cfmv32ah", 0xee100480, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
2186 {"cfmva32", 0xee2004a0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3a},
2187 {"cfmv32a", 0xee1004a0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3b},
2188 {"cfmva64", 0xee2004c0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3c},
2189 {"cfmv64a", 0xee1004c0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3d},
2190 {"cfmvsc32", 0xee2004e0, 8, ARM_CEXT_MAVERICK, do_mav_dspsc_1},
2191 {"cfmv32sc", 0xee1004e0, 8, ARM_CEXT_MAVERICK, do_mav_dspsc_2},
2192 {"cfcpys", 0xee000400, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
2193 {"cfcpyd", 0xee000420, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
2194 {"cfcvtsd", 0xee000460, 7, ARM_CEXT_MAVERICK, do_mav_binops_1f},
2195 {"cfcvtds", 0xee000440, 7, ARM_CEXT_MAVERICK, do_mav_binops_1g},
2196 {"cfcvt32s", 0xee000480, 8, ARM_CEXT_MAVERICK, do_mav_binops_1h},
2197 {"cfcvt32d", 0xee0004a0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1i},
2198 {"cfcvt64s", 0xee0004c0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1j},
2199 {"cfcvt64d", 0xee0004e0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1k},
2200 {"cfcvts32", 0xee100580, 8, ARM_CEXT_MAVERICK, do_mav_binops_1l},
2201 {"cfcvtd32", 0xee1005a0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1m},
2202 {"cftruncs32", 0xee1005c0, 10, ARM_CEXT_MAVERICK, do_mav_binops_1l},
2203 {"cftruncd32", 0xee1005e0, 10, ARM_CEXT_MAVERICK, do_mav_binops_1m},
2204 {"cfrshl32", 0xee000550, 8, ARM_CEXT_MAVERICK, do_mav_triple_4a},
2205 {"cfrshl64", 0xee000570, 8, ARM_CEXT_MAVERICK, do_mav_triple_4b},
2206 {"cfsh32", 0xee000500, 6, ARM_CEXT_MAVERICK, do_mav_shift_1},
2207 {"cfsh64", 0xee200500, 6, ARM_CEXT_MAVERICK, do_mav_shift_2},
2208 {"cfcmps", 0xee100490, 6, ARM_CEXT_MAVERICK, do_mav_triple_5a},
2209 {"cfcmpd", 0xee1004b0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5b},
2210 {"cfcmp32", 0xee100590, 7, ARM_CEXT_MAVERICK, do_mav_triple_5c},
2211 {"cfcmp64", 0xee1005b0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5d},
2212 {"cfabss", 0xee300400, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
2213 {"cfabsd", 0xee300420, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
2214 {"cfnegs", 0xee300440, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
2215 {"cfnegd", 0xee300460, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
2216 {"cfadds", 0xee300480, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
2217 {"cfaddd", 0xee3004a0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
2218 {"cfsubs", 0xee3004c0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
2219 {"cfsubd", 0xee3004e0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
2220 {"cfmuls", 0xee100400, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
2221 {"cfmuld", 0xee100420, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
2222 {"cfabs32", 0xee300500, 7, ARM_CEXT_MAVERICK, do_mav_binops_1n},
2223 {"cfabs64", 0xee300520, 7, ARM_CEXT_MAVERICK, do_mav_binops_1o},
2224 {"cfneg32", 0xee300540, 7, ARM_CEXT_MAVERICK, do_mav_binops_1n},
2225 {"cfneg64", 0xee300560, 7, ARM_CEXT_MAVERICK, do_mav_binops_1o},
2226 {"cfadd32", 0xee300580, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
2227 {"cfadd64", 0xee3005a0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
2228 {"cfsub32", 0xee3005c0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
2229 {"cfsub64", 0xee3005e0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
2230 {"cfmul32", 0xee100500, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
2231 {"cfmul64", 0xee100520, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
2232 {"cfmac32", 0xee100540, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
2233 {"cfmsc32", 0xee100560, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
2234 {"cfmadd32", 0xee000600, 8, ARM_CEXT_MAVERICK, do_mav_quad_6a},
2235 {"cfmsub32", 0xee100600, 8, ARM_CEXT_MAVERICK, do_mav_quad_6a},
2236 {"cfmadda32", 0xee200600, 9, ARM_CEXT_MAVERICK, do_mav_quad_6b},
2237 {"cfmsuba32", 0xee300600, 9, ARM_CEXT_MAVERICK, do_mav_quad_6b},
2238 };
2239
2240 /* Defines for various bits that we will want to toggle. */
2241 #define INST_IMMEDIATE 0x02000000
2242 #define OFFSET_REG 0x02000000
2243 #define HWOFFSET_IMM 0x00400000
2244 #define SHIFT_BY_REG 0x00000010
2245 #define PRE_INDEX 0x01000000
2246 #define INDEX_UP 0x00800000
2247 #define WRITE_BACK 0x00200000
2248 #define LDM_TYPE_2_OR_3 0x00400000
2249
2250 #define LITERAL_MASK 0xf000f000
2251 #define OPCODE_MASK 0xfe1fffff
2252 #define V4_STR_BIT 0x00000020
2253
2254 #define DATA_OP_SHIFT 21
2255
2256 /* Codes to distinguish the arithmetic instructions. */
2257 #define OPCODE_AND 0
2258 #define OPCODE_EOR 1
2259 #define OPCODE_SUB 2
2260 #define OPCODE_RSB 3
2261 #define OPCODE_ADD 4
2262 #define OPCODE_ADC 5
2263 #define OPCODE_SBC 6
2264 #define OPCODE_RSC 7
2265 #define OPCODE_TST 8
2266 #define OPCODE_TEQ 9
2267 #define OPCODE_CMP 10
2268 #define OPCODE_CMN 11
2269 #define OPCODE_ORR 12
2270 #define OPCODE_MOV 13
2271 #define OPCODE_BIC 14
2272 #define OPCODE_MVN 15
2273
2274 /* Thumb v1 (ARMv4T). */
2275 static void do_t_nop PARAMS ((char *));
2276 static void do_t_arit PARAMS ((char *));
2277 static void do_t_add PARAMS ((char *));
2278 static void do_t_asr PARAMS ((char *));
2279 static void do_t_branch9 PARAMS ((char *));
2280 static void do_t_branch12 PARAMS ((char *));
2281 static void do_t_branch23 PARAMS ((char *));
2282 static void do_t_bx PARAMS ((char *));
2283 static void do_t_compare PARAMS ((char *));
2284 static void do_t_ldmstm PARAMS ((char *));
2285 static void do_t_ldr PARAMS ((char *));
2286 static void do_t_ldrb PARAMS ((char *));
2287 static void do_t_ldrh PARAMS ((char *));
2288 static void do_t_lds PARAMS ((char *));
2289 static void do_t_lsl PARAMS ((char *));
2290 static void do_t_lsr PARAMS ((char *));
2291 static void do_t_mov PARAMS ((char *));
2292 static void do_t_push_pop PARAMS ((char *));
2293 static void do_t_str PARAMS ((char *));
2294 static void do_t_strb PARAMS ((char *));
2295 static void do_t_strh PARAMS ((char *));
2296 static void do_t_sub PARAMS ((char *));
2297 static void do_t_swi PARAMS ((char *));
2298 static void do_t_adr PARAMS ((char *));
2299
2300 /* Thumb v2 (ARMv5T). */
2301 static void do_t_blx PARAMS ((char *));
2302 static void do_t_bkpt PARAMS ((char *));
2303
2304 /* ARM V6. */
2305 static void do_t_cps PARAMS ((char *));
2306 static void do_t_cpy PARAMS ((char *));
2307 static void do_t_setend PARAMS ((char *));;
2308
2309 #define T_OPCODE_MUL 0x4340
2310 #define T_OPCODE_TST 0x4200
2311 #define T_OPCODE_CMN 0x42c0
2312 #define T_OPCODE_NEG 0x4240
2313 #define T_OPCODE_MVN 0x43c0
2314
2315 #define T_OPCODE_ADD_R3 0x1800
2316 #define T_OPCODE_SUB_R3 0x1a00
2317 #define T_OPCODE_ADD_HI 0x4400
2318 #define T_OPCODE_ADD_ST 0xb000
2319 #define T_OPCODE_SUB_ST 0xb080
2320 #define T_OPCODE_ADD_SP 0xa800
2321 #define T_OPCODE_ADD_PC 0xa000
2322 #define T_OPCODE_ADD_I8 0x3000
2323 #define T_OPCODE_SUB_I8 0x3800
2324 #define T_OPCODE_ADD_I3 0x1c00
2325 #define T_OPCODE_SUB_I3 0x1e00
2326
2327 #define T_OPCODE_ASR_R 0x4100
2328 #define T_OPCODE_LSL_R 0x4080
2329 #define T_OPCODE_LSR_R 0x40c0
2330 #define T_OPCODE_ASR_I 0x1000
2331 #define T_OPCODE_LSL_I 0x0000
2332 #define T_OPCODE_LSR_I 0x0800
2333
2334 #define T_OPCODE_MOV_I8 0x2000
2335 #define T_OPCODE_CMP_I8 0x2800
2336 #define T_OPCODE_CMP_LR 0x4280
2337 #define T_OPCODE_MOV_HR 0x4600
2338 #define T_OPCODE_CMP_HR 0x4500
2339
2340 #define T_OPCODE_LDR_PC 0x4800
2341 #define T_OPCODE_LDR_SP 0x9800
2342 #define T_OPCODE_STR_SP 0x9000
2343 #define T_OPCODE_LDR_IW 0x6800
2344 #define T_OPCODE_STR_IW 0x6000
2345 #define T_OPCODE_LDR_IH 0x8800
2346 #define T_OPCODE_STR_IH 0x8000
2347 #define T_OPCODE_LDR_IB 0x7800
2348 #define T_OPCODE_STR_IB 0x7000
2349 #define T_OPCODE_LDR_RW 0x5800
2350 #define T_OPCODE_STR_RW 0x5000
2351 #define T_OPCODE_LDR_RH 0x5a00
2352 #define T_OPCODE_STR_RH 0x5200
2353 #define T_OPCODE_LDR_RB 0x5c00
2354 #define T_OPCODE_STR_RB 0x5400
2355
2356 #define T_OPCODE_PUSH 0xb400
2357 #define T_OPCODE_POP 0xbc00
2358
2359 #define T_OPCODE_BRANCH 0xe7fe
2360
2361 static int thumb_reg PARAMS ((char ** str, int hi_lo));
2362
2363 #define THUMB_SIZE 2 /* Size of thumb instruction. */
2364 #define THUMB_REG_LO 0x1
2365 #define THUMB_REG_HI 0x2
2366 #define THUMB_REG_ANY 0x3
2367
2368 #define THUMB_H1 0x0080
2369 #define THUMB_H2 0x0040
2370
2371 #define THUMB_ASR 0
2372 #define THUMB_LSL 1
2373 #define THUMB_LSR 2
2374
2375 #define THUMB_MOVE 0
2376 #define THUMB_COMPARE 1
2377 #define THUMB_CPY 2
2378
2379 #define THUMB_LOAD 0
2380 #define THUMB_STORE 1
2381
2382 #define THUMB_PP_PC_LR 0x0100
2383
2384 /* These three are used for immediate shifts, do not alter. */
2385 #define THUMB_WORD 2
2386 #define THUMB_HALFWORD 1
2387 #define THUMB_BYTE 0
2388
2389 struct thumb_opcode
2390 {
2391 /* Basic string to match. */
2392 const char * template;
2393
2394 /* Basic instruction code. */
2395 unsigned long value;
2396
2397 int size;
2398
2399 /* Which CPU variants this exists for. */
2400 unsigned long variant;
2401
2402 /* Function to call to parse args. */
2403 void (* parms) PARAMS ((char *));
2404 };
2405
2406 static const struct thumb_opcode tinsns[] =
2407 {
2408 /* Thumb v1 (ARMv4T). */
2409 {"adc", 0x4140, 2, ARM_EXT_V4T, do_t_arit},
2410 {"add", 0x0000, 2, ARM_EXT_V4T, do_t_add},
2411 {"and", 0x4000, 2, ARM_EXT_V4T, do_t_arit},
2412 {"asr", 0x0000, 2, ARM_EXT_V4T, do_t_asr},
2413 {"b", T_OPCODE_BRANCH, 2, ARM_EXT_V4T, do_t_branch12},
2414 {"beq", 0xd0fe, 2, ARM_EXT_V4T, do_t_branch9},
2415 {"bne", 0xd1fe, 2, ARM_EXT_V4T, do_t_branch9},
2416 {"bcs", 0xd2fe, 2, ARM_EXT_V4T, do_t_branch9},
2417 {"bhs", 0xd2fe, 2, ARM_EXT_V4T, do_t_branch9},
2418 {"bcc", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
2419 {"bul", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
2420 {"blo", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
2421 {"bmi", 0xd4fe, 2, ARM_EXT_V4T, do_t_branch9},
2422 {"bpl", 0xd5fe, 2, ARM_EXT_V4T, do_t_branch9},
2423 {"bvs", 0xd6fe, 2, ARM_EXT_V4T, do_t_branch9},
2424 {"bvc", 0xd7fe, 2, ARM_EXT_V4T, do_t_branch9},
2425 {"bhi", 0xd8fe, 2, ARM_EXT_V4T, do_t_branch9},
2426 {"bls", 0xd9fe, 2, ARM_EXT_V4T, do_t_branch9},
2427 {"bge", 0xdafe, 2, ARM_EXT_V4T, do_t_branch9},
2428 {"blt", 0xdbfe, 2, ARM_EXT_V4T, do_t_branch9},
2429 {"bgt", 0xdcfe, 2, ARM_EXT_V4T, do_t_branch9},
2430 {"ble", 0xddfe, 2, ARM_EXT_V4T, do_t_branch9},
2431 {"bal", 0xdefe, 2, ARM_EXT_V4T, do_t_branch9},
2432 {"bic", 0x4380, 2, ARM_EXT_V4T, do_t_arit},
2433 {"bl", 0xf7fffffe, 4, ARM_EXT_V4T, do_t_branch23},
2434 {"bx", 0x4700, 2, ARM_EXT_V4T, do_t_bx},
2435 {"cmn", T_OPCODE_CMN, 2, ARM_EXT_V4T, do_t_arit},
2436 {"cmp", 0x0000, 2, ARM_EXT_V4T, do_t_compare},
2437 {"eor", 0x4040, 2, ARM_EXT_V4T, do_t_arit},
2438 {"ldmia", 0xc800, 2, ARM_EXT_V4T, do_t_ldmstm},
2439 {"ldr", 0x0000, 2, ARM_EXT_V4T, do_t_ldr},
2440 {"ldrb", 0x0000, 2, ARM_EXT_V4T, do_t_ldrb},
2441 {"ldrh", 0x0000, 2, ARM_EXT_V4T, do_t_ldrh},
2442 {"ldrsb", 0x5600, 2, ARM_EXT_V4T, do_t_lds},
2443 {"ldrsh", 0x5e00, 2, ARM_EXT_V4T, do_t_lds},
2444 {"ldsb", 0x5600, 2, ARM_EXT_V4T, do_t_lds},
2445 {"ldsh", 0x5e00, 2, ARM_EXT_V4T, do_t_lds},
2446 {"lsl", 0x0000, 2, ARM_EXT_V4T, do_t_lsl},
2447 {"lsr", 0x0000, 2, ARM_EXT_V4T, do_t_lsr},
2448 {"mov", 0x0000, 2, ARM_EXT_V4T, do_t_mov},
2449 {"mul", T_OPCODE_MUL, 2, ARM_EXT_V4T, do_t_arit},
2450 {"mvn", T_OPCODE_MVN, 2, ARM_EXT_V4T, do_t_arit},
2451 {"neg", T_OPCODE_NEG, 2, ARM_EXT_V4T, do_t_arit},
2452 {"orr", 0x4300, 2, ARM_EXT_V4T, do_t_arit},
2453 {"pop", 0xbc00, 2, ARM_EXT_V4T, do_t_push_pop},
2454 {"push", 0xb400, 2, ARM_EXT_V4T, do_t_push_pop},
2455 {"ror", 0x41c0, 2, ARM_EXT_V4T, do_t_arit},
2456 {"sbc", 0x4180, 2, ARM_EXT_V4T, do_t_arit},
2457 {"stmia", 0xc000, 2, ARM_EXT_V4T, do_t_ldmstm},
2458 {"str", 0x0000, 2, ARM_EXT_V4T, do_t_str},
2459 {"strb", 0x0000, 2, ARM_EXT_V4T, do_t_strb},
2460 {"strh", 0x0000, 2, ARM_EXT_V4T, do_t_strh},
2461 {"swi", 0xdf00, 2, ARM_EXT_V4T, do_t_swi},
2462 {"sub", 0x0000, 2, ARM_EXT_V4T, do_t_sub},
2463 {"tst", T_OPCODE_TST, 2, ARM_EXT_V4T, do_t_arit},
2464 /* Pseudo ops: */
2465 {"adr", 0x0000, 2, ARM_EXT_V4T, do_t_adr},
2466 {"nop", 0x46C0, 2, ARM_EXT_V4T, do_t_nop}, /* mov r8,r8 */
2467 /* Thumb v2 (ARMv5T). */
2468 {"blx", 0, 0, ARM_EXT_V5T, do_t_blx},
2469 {"bkpt", 0xbe00, 2, ARM_EXT_V5T, do_t_bkpt},
2470
2471 /* ARM V6. */
2472 {"cpsie", 0xb660, 2, ARM_EXT_V6, do_t_cps},
2473 {"cpsid", 0xb670, 2, ARM_EXT_V6, do_t_cps},
2474 {"cpy", 0x4600, 2, ARM_EXT_V6, do_t_cpy},
2475 {"rev", 0xba00, 2, ARM_EXT_V6, do_t_arit},
2476 {"rev16", 0xba40, 2, ARM_EXT_V6, do_t_arit},
2477 {"revsh", 0xbac0, 2, ARM_EXT_V6, do_t_arit},
2478 {"setend", 0xb650, 2, ARM_EXT_V6, do_t_setend},
2479 {"sxth", 0xb200, 2, ARM_EXT_V6, do_t_arit},
2480 {"sxtb", 0xb240, 2, ARM_EXT_V6, do_t_arit},
2481 {"uxth", 0xb280, 2, ARM_EXT_V6, do_t_arit},
2482 {"uxtb", 0xb2c0, 2, ARM_EXT_V6, do_t_arit},
2483 };
2484
2485 #define BAD_ARGS _("bad arguments to instruction")
2486 #define BAD_PC _("r15 not allowed here")
2487 #define BAD_COND _("instruction is not conditional")
2488 #define ERR_NO_ACCUM _("acc0 expected")
2489
2490 static struct hash_control * arm_ops_hsh = NULL;
2491 static struct hash_control * arm_tops_hsh = NULL;
2492 static struct hash_control * arm_cond_hsh = NULL;
2493 static struct hash_control * arm_shift_hsh = NULL;
2494 static struct hash_control * arm_psr_hsh = NULL;
2495
2496 /* This table describes all the machine specific pseudo-ops the assembler
2497 has to support. The fields are:
2498 pseudo-op name without dot
2499 function to call to execute this pseudo-op
2500 Integer arg to pass to the function. */
2501
2502 static void s_req PARAMS ((int));
2503 static void s_unreq PARAMS ((int));
2504 static void s_align PARAMS ((int));
2505 static void s_bss PARAMS ((int));
2506 static void s_even PARAMS ((int));
2507 static void s_ltorg PARAMS ((int));
2508 static void s_arm PARAMS ((int));
2509 static void s_thumb PARAMS ((int));
2510 static void s_code PARAMS ((int));
2511 static void s_force_thumb PARAMS ((int));
2512 static void s_thumb_func PARAMS ((int));
2513 static void s_thumb_set PARAMS ((int));
2514 #ifdef OBJ_ELF
2515 static void s_arm_elf_cons PARAMS ((int));
2516 #endif
2517
2518 static int my_get_expression PARAMS ((expressionS *, char **));
2519
2520 const pseudo_typeS md_pseudo_table[] =
2521 {
2522 /* Never called because '.req' does not start a line. */
2523 { "req", s_req, 0 },
2524 { "unreq", s_unreq, 0 },
2525 { "bss", s_bss, 0 },
2526 { "align", s_align, 0 },
2527 { "arm", s_arm, 0 },
2528 { "thumb", s_thumb, 0 },
2529 { "code", s_code, 0 },
2530 { "force_thumb", s_force_thumb, 0 },
2531 { "thumb_func", s_thumb_func, 0 },
2532 { "thumb_set", s_thumb_set, 0 },
2533 { "even", s_even, 0 },
2534 { "ltorg", s_ltorg, 0 },
2535 { "pool", s_ltorg, 0 },
2536 #ifdef OBJ_ELF
2537 { "word", s_arm_elf_cons, 4 },
2538 { "long", s_arm_elf_cons, 4 },
2539 #else
2540 { "word", cons, 4},
2541 #endif
2542 { "extend", float_cons, 'x' },
2543 { "ldouble", float_cons, 'x' },
2544 { "packed", float_cons, 'p' },
2545 { 0, 0, 0 }
2546 };
2547
2548 /* Other internal functions. */
2549 static int arm_parse_extension PARAMS ((char *, int *));
2550 static int arm_parse_cpu PARAMS ((char *));
2551 static int arm_parse_arch PARAMS ((char *));
2552 static int arm_parse_fpu PARAMS ((char *));
2553 static int arm_parse_float_abi PARAMS ((char *));
2554 #if 0 /* Suppressed - for now. */
2555 #if defined OBJ_COFF || defined OBJ_ELF
2556 static void arm_add_note PARAMS ((const char *, const char *, unsigned int));
2557 #endif
2558 #endif
2559
2560 /* Stuff needed to resolve the label ambiguity
2561 As:
2562 ...
2563 label: <insn>
2564 may differ from:
2565 ...
2566 label:
2567 <insn>
2568 */
2569
2570 symbolS * last_label_seen;
2571 static int label_is_thumb_function_name = FALSE;
2572
2573 /* Literal Pool stuff. */
2574
2575 #define MAX_LITERAL_POOL_SIZE 1024
2576
2577 /* Literal pool structure. Held on a per-section
2578 and per-sub-section basis. */
2579 typedef struct literal_pool
2580 {
2581 expressionS literals [MAX_LITERAL_POOL_SIZE];
2582 unsigned int next_free_entry;
2583 unsigned int id;
2584 symbolS * symbol;
2585 segT section;
2586 subsegT sub_section;
2587 struct literal_pool * next;
2588 } literal_pool;
2589
2590 /* Pointer to a linked list of literal pools. */
2591 literal_pool * list_of_pools = NULL;
2592
2593 static literal_pool * find_literal_pool PARAMS ((void));
2594 static literal_pool * find_or_make_literal_pool PARAMS ((void));
2595
2596 static literal_pool *
2597 find_literal_pool ()
2598 {
2599 literal_pool * pool;
2600
2601 for (pool = list_of_pools; pool != NULL; pool = pool->next)
2602 {
2603 if (pool->section == now_seg
2604 && pool->sub_section == now_subseg)
2605 break;
2606 }
2607
2608 return pool;
2609 }
2610
2611 static literal_pool *
2612 find_or_make_literal_pool ()
2613 {
2614 /* Next literal pool ID number. */
2615 static unsigned int latest_pool_num = 1;
2616 literal_pool * pool;
2617
2618 pool = find_literal_pool ();
2619
2620 if (pool == NULL)
2621 {
2622 /* Create a new pool. */
2623 pool = (literal_pool *) xmalloc (sizeof (* pool));
2624 if (! pool)
2625 return NULL;
2626
2627 pool->next_free_entry = 0;
2628 pool->section = now_seg;
2629 pool->sub_section = now_subseg;
2630 pool->next = list_of_pools;
2631 pool->symbol = NULL;
2632
2633 /* Add it to the list. */
2634 list_of_pools = pool;
2635 }
2636
2637 /* New pools, and emptied pools, will have a NULL symbol. */
2638 if (pool->symbol == NULL)
2639 {
2640 pool->symbol = symbol_create (FAKE_LABEL_NAME, undefined_section,
2641 (valueT) 0, &zero_address_frag);
2642 pool->id = latest_pool_num ++;
2643 }
2644
2645 /* Done. */
2646 return pool;
2647 }
2648
2649 /* Add the literal in the global 'inst'
2650 structure to the relevent literal pool. */
2651 static int
2652 add_to_lit_pool ()
2653 {
2654 literal_pool * pool;
2655 unsigned int entry;
2656
2657 pool = find_or_make_literal_pool ();
2658
2659 /* Check if this literal value is already in the pool. */
2660 for (entry = 0; entry < pool->next_free_entry; entry ++)
2661 {
2662 if ((pool->literals[entry].X_op == inst.reloc.exp.X_op)
2663 && (inst.reloc.exp.X_op == O_constant)
2664 && (pool->literals[entry].X_add_number
2665 == inst.reloc.exp.X_add_number)
2666 && (pool->literals[entry].X_unsigned
2667 == inst.reloc.exp.X_unsigned))
2668 break;
2669
2670 if ((pool->literals[entry].X_op == inst.reloc.exp.X_op)
2671 && (inst.reloc.exp.X_op == O_symbol)
2672 && (pool->literals[entry].X_add_number
2673 == inst.reloc.exp.X_add_number)
2674 && (pool->literals[entry].X_add_symbol
2675 == inst.reloc.exp.X_add_symbol)
2676 && (pool->literals[entry].X_op_symbol
2677 == inst.reloc.exp.X_op_symbol))
2678 break;
2679 }
2680
2681 /* Do we need to create a new entry? */
2682 if (entry == pool->next_free_entry)
2683 {
2684 if (entry >= MAX_LITERAL_POOL_SIZE)
2685 {
2686 inst.error = _("literal pool overflow");
2687 return FAIL;
2688 }
2689
2690 pool->literals[entry] = inst.reloc.exp;
2691 pool->next_free_entry += 1;
2692 }
2693
2694 inst.reloc.exp.X_op = O_symbol;
2695 inst.reloc.exp.X_add_number = ((int) entry) * 4 - 8;
2696 inst.reloc.exp.X_add_symbol = pool->symbol;
2697
2698 return SUCCESS;
2699 }
2700
2701 /* Can't use symbol_new here, so have to create a symbol and then at
2702 a later date assign it a value. Thats what these functions do. */
2703
2704 static void
2705 symbol_locate (symbolP, name, segment, valu, frag)
2706 symbolS * symbolP;
2707 const char * name; /* It is copied, the caller can modify. */
2708 segT segment; /* Segment identifier (SEG_<something>). */
2709 valueT valu; /* Symbol value. */
2710 fragS * frag; /* Associated fragment. */
2711 {
2712 unsigned int name_length;
2713 char * preserved_copy_of_name;
2714
2715 name_length = strlen (name) + 1; /* +1 for \0. */
2716 obstack_grow (&notes, name, name_length);
2717 preserved_copy_of_name = obstack_finish (&notes);
2718 #ifdef STRIP_UNDERSCORE
2719 if (preserved_copy_of_name[0] == '_')
2720 preserved_copy_of_name++;
2721 #endif
2722
2723 #ifdef tc_canonicalize_symbol_name
2724 preserved_copy_of_name =
2725 tc_canonicalize_symbol_name (preserved_copy_of_name);
2726 #endif
2727
2728 S_SET_NAME (symbolP, preserved_copy_of_name);
2729
2730 S_SET_SEGMENT (symbolP, segment);
2731 S_SET_VALUE (symbolP, valu);
2732 symbol_clear_list_pointers (symbolP);
2733
2734 symbol_set_frag (symbolP, frag);
2735
2736 /* Link to end of symbol chain. */
2737 {
2738 extern int symbol_table_frozen;
2739 if (symbol_table_frozen)
2740 abort ();
2741 }
2742
2743 symbol_append (symbolP, symbol_lastP, & symbol_rootP, & symbol_lastP);
2744
2745 obj_symbol_new_hook (symbolP);
2746
2747 #ifdef tc_symbol_new_hook
2748 tc_symbol_new_hook (symbolP);
2749 #endif
2750
2751 #ifdef DEBUG_SYMS
2752 verify_symbol_chain (symbol_rootP, symbol_lastP);
2753 #endif /* DEBUG_SYMS */
2754 }
2755
2756 /* Check that an immediate is valid.
2757 If so, convert it to the right format. */
2758
2759 static unsigned int
2760 validate_immediate (val)
2761 unsigned int val;
2762 {
2763 unsigned int a;
2764 unsigned int i;
2765
2766 #define rotate_left(v, n) (v << n | v >> (32 - n))
2767
2768 for (i = 0; i < 32; i += 2)
2769 if ((a = rotate_left (val, i)) <= 0xff)
2770 return a | (i << 7); /* 12-bit pack: [shift-cnt,const]. */
2771
2772 return FAIL;
2773 }
2774
2775 /* Check to see if an immediate can be computed as two separate immediate
2776 values, added together. We already know that this value cannot be
2777 computed by just one ARM instruction. */
2778
2779 static unsigned int
2780 validate_immediate_twopart (val, highpart)
2781 unsigned int val;
2782 unsigned int * highpart;
2783 {
2784 unsigned int a;
2785 unsigned int i;
2786
2787 for (i = 0; i < 32; i += 2)
2788 if (((a = rotate_left (val, i)) & 0xff) != 0)
2789 {
2790 if (a & 0xff00)
2791 {
2792 if (a & ~ 0xffff)
2793 continue;
2794 * highpart = (a >> 8) | ((i + 24) << 7);
2795 }
2796 else if (a & 0xff0000)
2797 {
2798 if (a & 0xff000000)
2799 continue;
2800 * highpart = (a >> 16) | ((i + 16) << 7);
2801 }
2802 else
2803 {
2804 assert (a & 0xff000000);
2805 * highpart = (a >> 24) | ((i + 8) << 7);
2806 }
2807
2808 return (a & 0xff) | (i << 7);
2809 }
2810
2811 return FAIL;
2812 }
2813
2814 static int
2815 validate_offset_imm (val, hwse)
2816 unsigned int val;
2817 int hwse;
2818 {
2819 if ((hwse && val > 255) || val > 4095)
2820 return FAIL;
2821 return val;
2822 }
2823
2824 \f
2825 #ifdef OBJ_ELF
2826 enum mstate
2827 {
2828 MAP_DATA,
2829 MAP_ARM,
2830 MAP_THUMB
2831 };
2832
2833 /* This code is to handle mapping symbols as defined in the ARM ELF spec.
2834 (This text is taken from version B-02 of the spec):
2835
2836 4.4.7 Mapping and tagging symbols
2837
2838 A section of an ARM ELF file can contain a mixture of ARM code,
2839 Thumb code, and data. There are inline transitions between code
2840 and data at literal pool boundaries. There can also be inline
2841 transitions between ARM code and Thumb code, for example in
2842 ARM-Thumb inter-working veneers. Linkers, machine-level
2843 debuggers, profiling tools, and disassembly tools need to map
2844 images accurately. For example, setting an ARM breakpoint on a
2845 Thumb location, or in a literal pool, can crash the program
2846 being debugged, ruining the debugging session.
2847
2848 ARM ELF entities are mapped (see section 4.4.7.1 below) and
2849 tagged (see section 4.4.7.2 below) using local symbols (with
2850 binding STB_LOCAL). To assist consumers, mapping and tagging
2851 symbols should be collated first in the symbol table, before
2852 other symbols with binding STB_LOCAL.
2853
2854 To allow properly collated mapping and tagging symbols to be
2855 skipped by consumers that have no interest in them, the first
2856 such symbol should have the name $m and its st_value field equal
2857 to the total number of mapping and tagging symbols (including
2858 the $m) in the symbol table.
2859
2860 4.4.7.1 Mapping symbols
2861
2862 $a Labels the first byte of a sequence of ARM instructions.
2863 Its type is STT_FUNC.
2864
2865 $d Labels the first byte of a sequence of data items.
2866 Its type is STT_OBJECT.
2867
2868 $t Labels the first byte of a sequence of Thumb instructions.
2869 Its type is STT_FUNC.
2870
2871 This list of mapping symbols may be extended in the future.
2872
2873 Section-relative mapping symbols
2874
2875 Mapping symbols defined in a section define a sequence of
2876 half-open address intervals that cover the address range of the
2877 section. Each interval starts at the address defined by a
2878 mapping symbol, and continues up to, but not including, the
2879 address defined by the next (in address order) mapping symbol or
2880 the end of the section. A corollary is that there must be a
2881 mapping symbol defined at the beginning of each section.
2882 Consumers can ignore the size of a section-relative mapping
2883 symbol. Producers can set it to 0.
2884
2885 Absolute mapping symbols
2886
2887 Because of the need to crystallize a Thumb address with the
2888 Thumb-bit set, absolute symbol of type STT_FUNC (symbols of type
2889 STT_FUNC defined in section SHN_ABS) need to be mapped with $a
2890 or $t.
2891
2892 The extent of a mapping symbol defined in SHN_ABS is [st_value,
2893 st_value + st_size), or [st_value, st_value + 1) if st_size = 0,
2894 where [x, y) denotes the half-open address range from x,
2895 inclusive, to y, exclusive.
2896
2897 In the absence of a mapping symbol, a consumer can interpret a
2898 function symbol with an odd value as the Thumb code address
2899 obtained by clearing the least significant bit of the
2900 value. This interpretation is deprecated, and it may not work in
2901 the future.
2902
2903 Note - the Tagging symbols ($b, $f, $p $m) have been dropped from
2904 the EABI (which is still under development), so they are not
2905 implemented here. */
2906
2907 static void
2908 mapping_state (enum mstate state)
2909 {
2910 static enum mstate mapstate = MAP_DATA;
2911 symbolS * symbolP;
2912 const char * symname;
2913 int type;
2914
2915 if (mapstate == state)
2916 /* The mapping symbol has already been emitted.
2917 There is nothing else to do. */
2918 return;
2919
2920 mapstate = state;
2921
2922 switch (state)
2923 {
2924 case MAP_DATA:
2925 symname = "$d";
2926 type = BSF_OBJECT;
2927 break;
2928 case MAP_ARM:
2929 symname = "$a";
2930 type = BSF_FUNCTION;
2931 break;
2932 case MAP_THUMB:
2933 symname = "$t";
2934 type = BSF_FUNCTION;
2935 break;
2936 default:
2937 abort ();
2938 }
2939
2940 symbolP = symbol_new (symname, now_seg, (valueT) frag_now_fix (), frag_now);
2941 symbol_table_insert (symbolP);
2942 symbol_get_bfdsym (symbolP)->flags |= type | BSF_LOCAL;
2943
2944 switch (state)
2945 {
2946 case MAP_ARM:
2947 THUMB_SET_FUNC (symbolP, 0);
2948 ARM_SET_THUMB (symbolP, 0);
2949 ARM_SET_INTERWORK (symbolP, support_interwork);
2950 break;
2951
2952 case MAP_THUMB:
2953 THUMB_SET_FUNC (symbolP, 1);
2954 ARM_SET_THUMB (symbolP, 1);
2955 ARM_SET_INTERWORK (symbolP, support_interwork);
2956 break;
2957
2958 case MAP_DATA:
2959 default:
2960 return;
2961 }
2962 }
2963
2964 /* When we change sections we need to issue a new mapping symbol. */
2965
2966 void
2967 arm_elf_change_section (void)
2968 {
2969 flagword flags;
2970
2971 if (!SEG_NORMAL (now_seg))
2972 return;
2973
2974 flags = bfd_get_section_flags (stdoutput, now_seg);
2975
2976 /* We can ignore sections that only contain debug info. */
2977 if ((flags & SEC_ALLOC) == 0)
2978 return;
2979
2980 if (flags & SEC_CODE)
2981 {
2982 if (thumb_mode)
2983 mapping_state (MAP_THUMB);
2984 else
2985 mapping_state (MAP_ARM);
2986 }
2987 else
2988 /* This section does not contain code. Therefore it must contain data. */
2989 mapping_state (MAP_DATA);
2990 }
2991 #else
2992 #define mapping_state(a)
2993 #endif /* OBJ_ELF */
2994 \f
2995
2996 static void
2997 s_req (a)
2998 int a ATTRIBUTE_UNUSED;
2999 {
3000 as_bad (_("invalid syntax for .req directive"));
3001 }
3002
3003 /* The .unreq directive deletes an alias which was previously defined
3004 by .req. For example:
3005
3006 my_alias .req r11
3007 .unreq my_alias */
3008
3009 static void
3010 s_unreq (int a ATTRIBUTE_UNUSED)
3011 {
3012 char *name;
3013 char saved_char;
3014
3015 skip_whitespace (input_line_pointer);
3016 name = input_line_pointer;
3017
3018 while (*input_line_pointer != 0
3019 && *input_line_pointer != ' '
3020 && *input_line_pointer != '\n')
3021 ++input_line_pointer;
3022
3023 saved_char = *input_line_pointer;
3024 *input_line_pointer = 0;
3025
3026 if (*name)
3027 {
3028 enum arm_reg_type req_type = arm_reg_parse_any (name);
3029
3030 if (req_type != REG_TYPE_MAX)
3031 {
3032 char *temp_name = name;
3033 int req_no = arm_reg_parse (&temp_name, all_reg_maps[req_type].htab);
3034
3035 if (req_no != FAIL)
3036 {
3037 struct reg_entry *req_entry;
3038
3039 /* Check to see if this alias is a builtin one. */
3040 req_entry = hash_delete (all_reg_maps[req_type].htab, name);
3041
3042 if (!req_entry)
3043 as_bad (_("unreq: missing hash entry for \"%s\""), name);
3044 else if (req_entry->builtin)
3045 /* FIXME: We are deleting a built in register alias which
3046 points to a const data structure, so we only need to
3047 free up the memory used by the key in the hash table.
3048 Unfortunately we have not recorded this value, so this
3049 is a memory leak. */
3050 /* FIXME: Should we issue a warning message ? */
3051 ;
3052 else
3053 {
3054 /* Deleting a user defined alias. We need to free the
3055 key and the value, but fortunately the key is the same
3056 as the value->name field. */
3057 free ((char *) req_entry->name);
3058 free (req_entry);
3059 }
3060 }
3061 else
3062 as_bad (_(".unreq: unrecognized symbol \"%s\""), name);
3063 }
3064 else
3065 as_bad (_(".unreq: unrecognized symbol \"%s\""), name);
3066 }
3067 else
3068 as_bad (_("invalid syntax for .unreq directive"));
3069
3070 *input_line_pointer = saved_char;
3071 demand_empty_rest_of_line ();
3072 }
3073
3074 static void
3075 s_bss (ignore)
3076 int ignore ATTRIBUTE_UNUSED;
3077 {
3078 /* We don't support putting frags in the BSS segment, we fake it by
3079 marking in_bss, then looking at s_skip for clues. */
3080 subseg_set (bss_section, 0);
3081 demand_empty_rest_of_line ();
3082 mapping_state (MAP_DATA);
3083 }
3084
3085 static void
3086 s_even (ignore)
3087 int ignore ATTRIBUTE_UNUSED;
3088 {
3089 /* Never make frag if expect extra pass. */
3090 if (!need_pass_2)
3091 frag_align (1, 0, 0);
3092
3093 record_alignment (now_seg, 1);
3094
3095 demand_empty_rest_of_line ();
3096 }
3097
3098 static void
3099 s_ltorg (ignored)
3100 int ignored ATTRIBUTE_UNUSED;
3101 {
3102 unsigned int entry;
3103 literal_pool * pool;
3104 char sym_name[20];
3105
3106 pool = find_literal_pool ();
3107 if (pool == NULL
3108 || pool->symbol == NULL
3109 || pool->next_free_entry == 0)
3110 return;
3111
3112 /* Align pool as you have word accesses.
3113 Only make a frag if we have to. */
3114 if (!need_pass_2)
3115 frag_align (2, 0, 0);
3116
3117 record_alignment (now_seg, 2);
3118
3119 sprintf (sym_name, "$$lit_\002%x", pool->id);
3120
3121 symbol_locate (pool->symbol, sym_name, now_seg,
3122 (valueT) frag_now_fix (), frag_now);
3123 symbol_table_insert (pool->symbol);
3124
3125 ARM_SET_THUMB (pool->symbol, thumb_mode);
3126
3127 #if defined OBJ_COFF || defined OBJ_ELF
3128 ARM_SET_INTERWORK (pool->symbol, support_interwork);
3129 #endif
3130
3131 for (entry = 0; entry < pool->next_free_entry; entry ++)
3132 /* First output the expression in the instruction to the pool. */
3133 emit_expr (&(pool->literals[entry]), 4); /* .word */
3134
3135 /* Mark the pool as empty. */
3136 pool->next_free_entry = 0;
3137 pool->symbol = NULL;
3138 }
3139
3140 /* Same as s_align_ptwo but align 0 => align 2. */
3141
3142 static void
3143 s_align (unused)
3144 int unused ATTRIBUTE_UNUSED;
3145 {
3146 register int temp;
3147 register long temp_fill;
3148 long max_alignment = 15;
3149
3150 temp = get_absolute_expression ();
3151 if (temp > max_alignment)
3152 as_bad (_("alignment too large: %d assumed"), temp = max_alignment);
3153 else if (temp < 0)
3154 {
3155 as_bad (_("alignment negative. 0 assumed."));
3156 temp = 0;
3157 }
3158
3159 if (*input_line_pointer == ',')
3160 {
3161 input_line_pointer++;
3162 temp_fill = get_absolute_expression ();
3163 }
3164 else
3165 temp_fill = 0;
3166
3167 if (!temp)
3168 temp = 2;
3169
3170 /* Only make a frag if we HAVE to. */
3171 if (temp && !need_pass_2)
3172 frag_align (temp, (int) temp_fill, 0);
3173 demand_empty_rest_of_line ();
3174
3175 record_alignment (now_seg, temp);
3176 }
3177
3178 static void
3179 s_force_thumb (ignore)
3180 int ignore ATTRIBUTE_UNUSED;
3181 {
3182 /* If we are not already in thumb mode go into it, EVEN if
3183 the target processor does not support thumb instructions.
3184 This is used by gcc/config/arm/lib1funcs.asm for example
3185 to compile interworking support functions even if the
3186 target processor should not support interworking. */
3187 if (! thumb_mode)
3188 {
3189 thumb_mode = 2;
3190
3191 record_alignment (now_seg, 1);
3192 }
3193
3194 demand_empty_rest_of_line ();
3195 }
3196
3197 static void
3198 s_thumb_func (ignore)
3199 int ignore ATTRIBUTE_UNUSED;
3200 {
3201 if (! thumb_mode)
3202 opcode_select (16);
3203
3204 /* The following label is the name/address of the start of a Thumb function.
3205 We need to know this for the interworking support. */
3206 label_is_thumb_function_name = TRUE;
3207
3208 demand_empty_rest_of_line ();
3209 }
3210
3211 /* Perform a .set directive, but also mark the alias as
3212 being a thumb function. */
3213
3214 static void
3215 s_thumb_set (equiv)
3216 int equiv;
3217 {
3218 /* XXX the following is a duplicate of the code for s_set() in read.c
3219 We cannot just call that code as we need to get at the symbol that
3220 is created. */
3221 register char * name;
3222 register char delim;
3223 register char * end_name;
3224 register symbolS * symbolP;
3225
3226 /* Especial apologies for the random logic:
3227 This just grew, and could be parsed much more simply!
3228 Dean - in haste. */
3229 name = input_line_pointer;
3230 delim = get_symbol_end ();
3231 end_name = input_line_pointer;
3232 *end_name = delim;
3233
3234 SKIP_WHITESPACE ();
3235
3236 if (*input_line_pointer != ',')
3237 {
3238 *end_name = 0;
3239 as_bad (_("expected comma after name \"%s\""), name);
3240 *end_name = delim;
3241 ignore_rest_of_line ();
3242 return;
3243 }
3244
3245 input_line_pointer++;
3246 *end_name = 0;
3247
3248 if (name[0] == '.' && name[1] == '\0')
3249 {
3250 /* XXX - this should not happen to .thumb_set. */
3251 abort ();
3252 }
3253
3254 if ((symbolP = symbol_find (name)) == NULL
3255 && (symbolP = md_undefined_symbol (name)) == NULL)
3256 {
3257 #ifndef NO_LISTING
3258 /* When doing symbol listings, play games with dummy fragments living
3259 outside the normal fragment chain to record the file and line info
3260 for this symbol. */
3261 if (listing & LISTING_SYMBOLS)
3262 {
3263 extern struct list_info_struct * listing_tail;
3264 fragS * dummy_frag = (fragS *) xmalloc (sizeof (fragS));
3265
3266 memset (dummy_frag, 0, sizeof (fragS));
3267 dummy_frag->fr_type = rs_fill;
3268 dummy_frag->line = listing_tail;
3269 symbolP = symbol_new (name, undefined_section, 0, dummy_frag);
3270 dummy_frag->fr_symbol = symbolP;
3271 }
3272 else
3273 #endif
3274 symbolP = symbol_new (name, undefined_section, 0, &zero_address_frag);
3275
3276 #ifdef OBJ_COFF
3277 /* "set" symbols are local unless otherwise specified. */
3278 SF_SET_LOCAL (symbolP);
3279 #endif /* OBJ_COFF */
3280 } /* Make a new symbol. */
3281
3282 symbol_table_insert (symbolP);
3283
3284 * end_name = delim;
3285
3286 if (equiv
3287 && S_IS_DEFINED (symbolP)
3288 && S_GET_SEGMENT (symbolP) != reg_section)
3289 as_bad (_("symbol `%s' already defined"), S_GET_NAME (symbolP));
3290
3291 pseudo_set (symbolP);
3292
3293 demand_empty_rest_of_line ();
3294
3295 /* XXX Now we come to the Thumb specific bit of code. */
3296
3297 THUMB_SET_FUNC (symbolP, 1);
3298 ARM_SET_THUMB (symbolP, 1);
3299 #if defined OBJ_ELF || defined OBJ_COFF
3300 ARM_SET_INTERWORK (symbolP, support_interwork);
3301 #endif
3302 }
3303
3304 static void
3305 opcode_select (width)
3306 int width;
3307 {
3308 switch (width)
3309 {
3310 case 16:
3311 if (! thumb_mode)
3312 {
3313 if (! (cpu_variant & ARM_EXT_V4T))
3314 as_bad (_("selected processor does not support THUMB opcodes"));
3315
3316 thumb_mode = 1;
3317 /* No need to force the alignment, since we will have been
3318 coming from ARM mode, which is word-aligned. */
3319 record_alignment (now_seg, 1);
3320 }
3321 mapping_state (MAP_THUMB);
3322 break;
3323
3324 case 32:
3325 if (thumb_mode)
3326 {
3327 if ((cpu_variant & ARM_ALL) == ARM_EXT_V4T)
3328 as_bad (_("selected processor does not support ARM opcodes"));
3329
3330 thumb_mode = 0;
3331
3332 if (!need_pass_2)
3333 frag_align (2, 0, 0);
3334
3335 record_alignment (now_seg, 1);
3336 }
3337 mapping_state (MAP_ARM);
3338 break;
3339
3340 default:
3341 as_bad (_("invalid instruction size selected (%d)"), width);
3342 }
3343 }
3344
3345 static void
3346 s_arm (ignore)
3347 int ignore ATTRIBUTE_UNUSED;
3348 {
3349 opcode_select (32);
3350 demand_empty_rest_of_line ();
3351 }
3352
3353 static void
3354 s_thumb (ignore)
3355 int ignore ATTRIBUTE_UNUSED;
3356 {
3357 opcode_select (16);
3358 demand_empty_rest_of_line ();
3359 }
3360
3361 static void
3362 s_code (unused)
3363 int unused ATTRIBUTE_UNUSED;
3364 {
3365 register int temp;
3366
3367 temp = get_absolute_expression ();
3368 switch (temp)
3369 {
3370 case 16:
3371 case 32:
3372 opcode_select (temp);
3373 break;
3374
3375 default:
3376 as_bad (_("invalid operand to .code directive (%d) (expecting 16 or 32)"), temp);
3377 }
3378 }
3379
3380 static void
3381 end_of_line (str)
3382 char *str;
3383 {
3384 skip_whitespace (str);
3385
3386 if (*str != '\0' && !inst.error)
3387 inst.error = _("garbage following instruction");
3388 }
3389
3390 static int
3391 skip_past_comma (str)
3392 char ** str;
3393 {
3394 char * p = * str, c;
3395 int comma = 0;
3396
3397 while ((c = *p) == ' ' || c == ',')
3398 {
3399 p++;
3400 if (c == ',' && comma++)
3401 return FAIL;
3402 }
3403
3404 if (c == '\0')
3405 return FAIL;
3406
3407 *str = p;
3408 return comma ? SUCCESS : FAIL;
3409 }
3410
3411 /* A standard register must be given at this point.
3412 SHIFT is the place to put it in inst.instruction.
3413 Restores input start point on error.
3414 Returns the reg#, or FAIL. */
3415
3416 static int
3417 reg_required_here (str, shift)
3418 char ** str;
3419 int shift;
3420 {
3421 static char buff [128]; /* XXX */
3422 int reg;
3423 char * start = * str;
3424
3425 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_RN].htab)) != FAIL)
3426 {
3427 if (shift >= 0)
3428 inst.instruction |= reg << shift;
3429 return reg;
3430 }
3431
3432 /* Restore the start point, we may have got a reg of the wrong class. */
3433 *str = start;
3434
3435 /* In the few cases where we might be able to accept something else
3436 this error can be overridden. */
3437 sprintf (buff, _("register expected, not '%.100s'"), start);
3438 inst.error = buff;
3439
3440 return FAIL;
3441 }
3442
3443 /* A Intel Wireless MMX technology register
3444 must be given at this point.
3445 Shift is the place to put it in inst.instruction.
3446 Restores input start point on err.
3447 Returns the reg#, or FAIL. */
3448
3449 static int
3450 wreg_required_here (str, shift, reg_type)
3451 char ** str;
3452 int shift;
3453 enum wreg_type reg_type;
3454 {
3455 static char buff [128];
3456 int reg;
3457 char * start = *str;
3458
3459 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_IWMMXT].htab)) != FAIL)
3460 {
3461 if (wr_register (reg)
3462 && (reg_type == IWMMXT_REG_WR || reg_type == IWMMXT_REG_WR_OR_WC))
3463 {
3464 if (shift >= 0)
3465 inst.instruction |= (reg ^ WR_PREFIX) << shift;
3466 return reg;
3467 }
3468 else if (wc_register (reg)
3469 && (reg_type == IWMMXT_REG_WC || reg_type == IWMMXT_REG_WR_OR_WC))
3470 {
3471 if (shift >= 0)
3472 inst.instruction |= (reg ^ WC_PREFIX) << shift;
3473 return reg;
3474 }
3475 else if ((wcg_register (reg) && reg_type == IWMMXT_REG_WCG))
3476 {
3477 if (shift >= 0)
3478 inst.instruction |= ((reg ^ WC_PREFIX) - 8) << shift;
3479 return reg;
3480 }
3481 }
3482
3483 /* Restore the start point, we may have got a reg of the wrong class. */
3484 *str = start;
3485
3486 /* In the few cases where we might be able to accept
3487 something else this error can be overridden. */
3488 sprintf (buff, _("Intel Wireless MMX technology register expected, not '%.100s'"), start);
3489 inst.error = buff;
3490
3491 return FAIL;
3492 }
3493
3494 static const struct asm_psr *
3495 arm_psr_parse (ccp)
3496 register char ** ccp;
3497 {
3498 char * start = * ccp;
3499 char c;
3500 char * p;
3501 const struct asm_psr * psr;
3502
3503 p = start;
3504
3505 /* Skip to the end of the next word in the input stream. */
3506 do
3507 {
3508 c = *p++;
3509 }
3510 while (ISALPHA (c) || c == '_');
3511
3512 /* Terminate the word. */
3513 *--p = 0;
3514
3515 /* CPSR's and SPSR's can now be lowercase. This is just a convenience
3516 feature for ease of use and backwards compatibility. */
3517 if (!strncmp (start, "cpsr", 4))
3518 strncpy (start, "CPSR", 4);
3519 else if (!strncmp (start, "spsr", 4))
3520 strncpy (start, "SPSR", 4);
3521
3522 /* Now locate the word in the psr hash table. */
3523 psr = (const struct asm_psr *) hash_find (arm_psr_hsh, start);
3524
3525 /* Restore the input stream. */
3526 *p = c;
3527
3528 /* If we found a valid match, advance the
3529 stream pointer past the end of the word. */
3530 *ccp = p;
3531
3532 return psr;
3533 }
3534
3535 /* Parse the input looking for a PSR flag. */
3536
3537 static int
3538 psr_required_here (str)
3539 char ** str;
3540 {
3541 char * start = * str;
3542 const struct asm_psr * psr;
3543
3544 psr = arm_psr_parse (str);
3545
3546 if (psr)
3547 {
3548 /* If this is the SPSR that is being modified, set the R bit. */
3549 if (! psr->cpsr)
3550 inst.instruction |= SPSR_BIT;
3551
3552 /* Set the psr flags in the MSR instruction. */
3553 inst.instruction |= psr->field << PSR_SHIFT;
3554
3555 return SUCCESS;
3556 }
3557
3558 /* In the few cases where we might be able to accept
3559 something else this error can be overridden. */
3560 inst.error = _("flag for {c}psr instruction expected");
3561
3562 /* Restore the start point. */
3563 *str = start;
3564 return FAIL;
3565 }
3566
3567 static int
3568 co_proc_number (str)
3569 char **str;
3570 {
3571 int processor, pchar;
3572 char *start;
3573
3574 skip_whitespace (*str);
3575 start = *str;
3576
3577 /* The data sheet seems to imply that just a number on its own is valid
3578 here, but the RISC iX assembler seems to accept a prefix 'p'. We will
3579 accept either. */
3580 if ((processor = arm_reg_parse (str, all_reg_maps[REG_TYPE_CP].htab))
3581 == FAIL)
3582 {
3583 *str = start;
3584
3585 pchar = *(*str)++;
3586 if (pchar >= '0' && pchar <= '9')
3587 {
3588 processor = pchar - '0';
3589 if (**str >= '0' && **str <= '9')
3590 {
3591 processor = processor * 10 + *(*str)++ - '0';
3592 if (processor > 15)
3593 {
3594 inst.error = _("illegal co-processor number");
3595 return FAIL;
3596 }
3597 }
3598 }
3599 else
3600 {
3601 inst.error = _("bad or missing co-processor number");
3602 return FAIL;
3603 }
3604 }
3605
3606 inst.instruction |= processor << 8;
3607 return SUCCESS;
3608 }
3609
3610 static int
3611 cp_opc_expr (str, where, length)
3612 char ** str;
3613 int where;
3614 int length;
3615 {
3616 expressionS expr;
3617
3618 skip_whitespace (* str);
3619
3620 memset (&expr, '\0', sizeof (expr));
3621
3622 if (my_get_expression (&expr, str))
3623 return FAIL;
3624 if (expr.X_op != O_constant)
3625 {
3626 inst.error = _("bad or missing expression");
3627 return FAIL;
3628 }
3629
3630 if ((expr.X_add_number & ((1 << length) - 1)) != expr.X_add_number)
3631 {
3632 inst.error = _("immediate co-processor expression too large");
3633 return FAIL;
3634 }
3635
3636 inst.instruction |= expr.X_add_number << where;
3637 return SUCCESS;
3638 }
3639
3640 static int
3641 cp_reg_required_here (str, where)
3642 char ** str;
3643 int where;
3644 {
3645 int reg;
3646 char * start = *str;
3647
3648 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_CN].htab)) != FAIL)
3649 {
3650 inst.instruction |= reg << where;
3651 return reg;
3652 }
3653
3654 /* In the few cases where we might be able to accept something else
3655 this error can be overridden. */
3656 inst.error = _("co-processor register expected");
3657
3658 /* Restore the start point. */
3659 *str = start;
3660 return FAIL;
3661 }
3662
3663 static int
3664 fp_reg_required_here (str, where)
3665 char ** str;
3666 int where;
3667 {
3668 int reg;
3669 char * start = * str;
3670
3671 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_FN].htab)) != FAIL)
3672 {
3673 inst.instruction |= reg << where;
3674 return reg;
3675 }
3676
3677 /* In the few cases where we might be able to accept something else
3678 this error can be overridden. */
3679 inst.error = _("floating point register expected");
3680
3681 /* Restore the start point. */
3682 *str = start;
3683 return FAIL;
3684 }
3685
3686 static int
3687 cp_address_offset (str)
3688 char ** str;
3689 {
3690 int offset;
3691
3692 skip_whitespace (* str);
3693
3694 if (! is_immediate_prefix (**str))
3695 {
3696 inst.error = _("immediate expression expected");
3697 return FAIL;
3698 }
3699
3700 (*str)++;
3701
3702 if (my_get_expression (& inst.reloc.exp, str))
3703 return FAIL;
3704
3705 if (inst.reloc.exp.X_op == O_constant)
3706 {
3707 offset = inst.reloc.exp.X_add_number;
3708
3709 if (offset & 3)
3710 {
3711 inst.error = _("co-processor address must be word aligned");
3712 return FAIL;
3713 }
3714
3715 if (offset > 1023 || offset < -1023)
3716 {
3717 inst.error = _("offset too large");
3718 return FAIL;
3719 }
3720
3721 if (offset >= 0)
3722 inst.instruction |= INDEX_UP;
3723 else
3724 offset = -offset;
3725
3726 inst.instruction |= offset >> 2;
3727 }
3728 else
3729 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
3730
3731 return SUCCESS;
3732 }
3733
3734 static int
3735 cp_address_required_here (str, wb_ok)
3736 char ** str;
3737 int wb_ok;
3738 {
3739 char * p = * str;
3740 int pre_inc = 0;
3741 int write_back = 0;
3742
3743 if (*p == '[')
3744 {
3745 int reg;
3746
3747 p++;
3748 skip_whitespace (p);
3749
3750 if ((reg = reg_required_here (& p, 16)) == FAIL)
3751 return FAIL;
3752
3753 skip_whitespace (p);
3754
3755 if (*p == ']')
3756 {
3757 p++;
3758
3759 skip_whitespace (p);
3760
3761 if (*p == '\0')
3762 {
3763 /* As an extension to the official ARM syntax we allow:
3764
3765 [Rn]
3766
3767 as a short hand for:
3768
3769 [Rn,#0] */
3770 inst.instruction |= PRE_INDEX | INDEX_UP;
3771 *str = p;
3772 return SUCCESS;
3773 }
3774
3775 if (skip_past_comma (& p) == FAIL)
3776 {
3777 inst.error = _("comma expected after closing square bracket");
3778 return FAIL;
3779 }
3780
3781 skip_whitespace (p);
3782
3783 if (*p == '#')
3784 {
3785 if (wb_ok)
3786 {
3787 /* [Rn], #expr */
3788 write_back = WRITE_BACK;
3789
3790 if (reg == REG_PC)
3791 {
3792 inst.error = _("pc may not be used in post-increment");
3793 return FAIL;
3794 }
3795
3796 if (cp_address_offset (& p) == FAIL)
3797 return FAIL;
3798 }
3799 else
3800 pre_inc = PRE_INDEX | INDEX_UP;
3801 }
3802 else if (*p == '{')
3803 {
3804 int option;
3805
3806 /* [Rn], {<expr>} */
3807 p++;
3808
3809 skip_whitespace (p);
3810
3811 if (my_get_expression (& inst.reloc.exp, & p))
3812 return FAIL;
3813
3814 if (inst.reloc.exp.X_op == O_constant)
3815 {
3816 option = inst.reloc.exp.X_add_number;
3817
3818 if (option > 255 || option < 0)
3819 {
3820 inst.error = _("'option' field too large");
3821 return FAIL;
3822 }
3823
3824 skip_whitespace (p);
3825
3826 if (*p != '}')
3827 {
3828 inst.error = _("'}' expected at end of 'option' field");
3829 return FAIL;
3830 }
3831 else
3832 {
3833 p++;
3834 inst.instruction |= option;
3835 inst.instruction |= INDEX_UP;
3836 }
3837 }
3838 else
3839 {
3840 inst.error = _("non-constant expressions for 'option' field not supported");
3841 return FAIL;
3842 }
3843 }
3844 else
3845 {
3846 inst.error = _("# or { expected after comma");
3847 return FAIL;
3848 }
3849 }
3850 else
3851 {
3852 /* '['Rn, #expr']'[!] */
3853
3854 if (skip_past_comma (& p) == FAIL)
3855 {
3856 inst.error = _("pre-indexed expression expected");
3857 return FAIL;
3858 }
3859
3860 pre_inc = PRE_INDEX;
3861
3862 if (cp_address_offset (& p) == FAIL)
3863 return FAIL;
3864
3865 skip_whitespace (p);
3866
3867 if (*p++ != ']')
3868 {
3869 inst.error = _("missing ]");
3870 return FAIL;
3871 }
3872
3873 skip_whitespace (p);
3874
3875 if (wb_ok && *p == '!')
3876 {
3877 if (reg == REG_PC)
3878 {
3879 inst.error = _("pc may not be used with write-back");
3880 return FAIL;
3881 }
3882
3883 p++;
3884 write_back = WRITE_BACK;
3885 }
3886 }
3887 }
3888 else
3889 {
3890 if (my_get_expression (&inst.reloc.exp, &p))
3891 return FAIL;
3892
3893 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
3894 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
3895 inst.reloc.pc_rel = 1;
3896 inst.instruction |= (REG_PC << 16);
3897 pre_inc = PRE_INDEX;
3898 }
3899
3900 inst.instruction |= write_back | pre_inc;
3901 *str = p;
3902 return SUCCESS;
3903 }
3904
3905 static int
3906 cp_byte_address_offset (str)
3907 char ** str;
3908 {
3909 int offset;
3910
3911 skip_whitespace (* str);
3912
3913 if (! is_immediate_prefix (**str))
3914 {
3915 inst.error = _("immediate expression expected");
3916 return FAIL;
3917 }
3918
3919 (*str)++;
3920
3921 if (my_get_expression (& inst.reloc.exp, str))
3922 return FAIL;
3923
3924 if (inst.reloc.exp.X_op == O_constant)
3925 {
3926 offset = inst.reloc.exp.X_add_number;
3927
3928 if (offset > 255 || offset < -255)
3929 {
3930 inst.error = _("offset too large");
3931 return FAIL;
3932 }
3933
3934 if (offset >= 0)
3935 inst.instruction |= INDEX_UP;
3936 else
3937 offset = -offset;
3938
3939 inst.instruction |= offset;
3940 }
3941 else
3942 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM_S2;
3943
3944 return SUCCESS;
3945 }
3946
3947 static int
3948 cp_byte_address_required_here (str)
3949 char ** str;
3950 {
3951 char * p = * str;
3952 int pre_inc = 0;
3953 int write_back = 0;
3954
3955 if (*p == '[')
3956 {
3957 int reg;
3958
3959 p++;
3960 skip_whitespace (p);
3961
3962 if ((reg = reg_required_here (& p, 16)) == FAIL)
3963 return FAIL;
3964
3965 skip_whitespace (p);
3966
3967 if (*p == ']')
3968 {
3969 p++;
3970
3971 if (skip_past_comma (& p) == SUCCESS)
3972 {
3973 /* [Rn], #expr */
3974 write_back = WRITE_BACK;
3975
3976 if (reg == REG_PC)
3977 {
3978 inst.error = _("pc may not be used in post-increment");
3979 return FAIL;
3980 }
3981
3982 if (cp_byte_address_offset (& p) == FAIL)
3983 return FAIL;
3984 }
3985 else
3986 pre_inc = PRE_INDEX | INDEX_UP;
3987 }
3988 else
3989 {
3990 /* '['Rn, #expr']'[!] */
3991
3992 if (skip_past_comma (& p) == FAIL)
3993 {
3994 inst.error = _("pre-indexed expression expected");
3995 return FAIL;
3996 }
3997
3998 pre_inc = PRE_INDEX;
3999
4000 if (cp_byte_address_offset (& p) == FAIL)
4001 return FAIL;
4002
4003 skip_whitespace (p);
4004
4005 if (*p++ != ']')
4006 {
4007 inst.error = _("missing ]");
4008 return FAIL;
4009 }
4010
4011 skip_whitespace (p);
4012
4013 if (*p == '!')
4014 {
4015 if (reg == REG_PC)
4016 {
4017 inst.error = _("pc may not be used with write-back");
4018 return FAIL;
4019 }
4020
4021 p++;
4022 write_back = WRITE_BACK;
4023 }
4024 }
4025 }
4026 else
4027 {
4028 if (my_get_expression (&inst.reloc.exp, &p))
4029 return FAIL;
4030
4031 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM_S2;
4032 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
4033 inst.reloc.pc_rel = 1;
4034 inst.instruction |= (REG_PC << 16);
4035 pre_inc = PRE_INDEX;
4036 }
4037
4038 inst.instruction |= write_back | pre_inc;
4039 *str = p;
4040 return SUCCESS;
4041 }
4042
4043 static void
4044 do_empty (str)
4045 char * str;
4046 {
4047 /* Do nothing really. */
4048 end_of_line (str);
4049 }
4050
4051 static void
4052 do_mrs (str)
4053 char *str;
4054 {
4055 int skip = 0;
4056
4057 /* Only one syntax. */
4058 skip_whitespace (str);
4059
4060 if (reg_required_here (&str, 12) == FAIL)
4061 {
4062 inst.error = BAD_ARGS;
4063 return;
4064 }
4065
4066 if (skip_past_comma (&str) == FAIL)
4067 {
4068 inst.error = _("comma expected after register name");
4069 return;
4070 }
4071
4072 skip_whitespace (str);
4073
4074 if ( strcmp (str, "CPSR") == 0
4075 || strcmp (str, "SPSR") == 0
4076 /* Lower case versions for backwards compatibility. */
4077 || strcmp (str, "cpsr") == 0
4078 || strcmp (str, "spsr") == 0)
4079 skip = 4;
4080
4081 /* This is for backwards compatibility with older toolchains. */
4082 else if ( strcmp (str, "cpsr_all") == 0
4083 || strcmp (str, "spsr_all") == 0)
4084 skip = 8;
4085 else
4086 {
4087 inst.error = _("CPSR or SPSR expected");
4088 return;
4089 }
4090
4091 if (* str == 's' || * str == 'S')
4092 inst.instruction |= SPSR_BIT;
4093 str += skip;
4094
4095 end_of_line (str);
4096 }
4097
4098 /* Two possible forms:
4099 "{C|S}PSR_<field>, Rm",
4100 "{C|S}PSR_f, #expression". */
4101
4102 static void
4103 do_msr (str)
4104 char * str;
4105 {
4106 skip_whitespace (str);
4107
4108 if (psr_required_here (& str) == FAIL)
4109 return;
4110
4111 if (skip_past_comma (& str) == FAIL)
4112 {
4113 inst.error = _("comma missing after psr flags");
4114 return;
4115 }
4116
4117 skip_whitespace (str);
4118
4119 if (reg_required_here (& str, 0) != FAIL)
4120 {
4121 inst.error = NULL;
4122 end_of_line (str);
4123 return;
4124 }
4125
4126 if (! is_immediate_prefix (* str))
4127 {
4128 inst.error =
4129 _("only a register or immediate value can follow a psr flag");
4130 return;
4131 }
4132
4133 str ++;
4134 inst.error = NULL;
4135
4136 if (my_get_expression (& inst.reloc.exp, & str))
4137 {
4138 inst.error =
4139 _("only a register or immediate value can follow a psr flag");
4140 return;
4141 }
4142
4143 #if 0 /* The first edition of the ARM architecture manual stated that
4144 writing anything other than the flags with an immediate operation
4145 had UNPREDICTABLE effects. This constraint was removed in the
4146 second edition of the specification. */
4147 if ((cpu_variant & ARM_EXT_V5) != ARM_EXT_V5
4148 && inst.instruction & ((PSR_c | PSR_x | PSR_s) << PSR_SHIFT))
4149 {
4150 inst.error = _("immediate value cannot be used to set this field");
4151 return;
4152 }
4153 #endif
4154
4155 inst.instruction |= INST_IMMEDIATE;
4156
4157 if (inst.reloc.exp.X_add_symbol)
4158 {
4159 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
4160 inst.reloc.pc_rel = 0;
4161 }
4162 else
4163 {
4164 unsigned value = validate_immediate (inst.reloc.exp.X_add_number);
4165
4166 if (value == (unsigned) FAIL)
4167 {
4168 inst.error = _("invalid constant");
4169 return;
4170 }
4171
4172 inst.instruction |= value;
4173 }
4174
4175 inst.error = NULL;
4176 end_of_line (str);
4177 }
4178
4179 /* Long Multiply Parser
4180 UMULL RdLo, RdHi, Rm, Rs
4181 SMULL RdLo, RdHi, Rm, Rs
4182 UMLAL RdLo, RdHi, Rm, Rs
4183 SMLAL RdLo, RdHi, Rm, Rs. */
4184
4185 static void
4186 do_mull (str)
4187 char * str;
4188 {
4189 int rdlo, rdhi, rm, rs;
4190
4191 /* Only one format "rdlo, rdhi, rm, rs". */
4192 skip_whitespace (str);
4193
4194 if ((rdlo = reg_required_here (&str, 12)) == FAIL)
4195 {
4196 inst.error = BAD_ARGS;
4197 return;
4198 }
4199
4200 if (skip_past_comma (&str) == FAIL
4201 || (rdhi = reg_required_here (&str, 16)) == FAIL)
4202 {
4203 inst.error = BAD_ARGS;
4204 return;
4205 }
4206
4207 if (skip_past_comma (&str) == FAIL
4208 || (rm = reg_required_here (&str, 0)) == FAIL)
4209 {
4210 inst.error = BAD_ARGS;
4211 return;
4212 }
4213
4214 /* rdhi, rdlo and rm must all be different. */
4215 if (rdlo == rdhi || rdlo == rm || rdhi == rm)
4216 as_tsktsk (_("rdhi, rdlo and rm must all be different"));
4217
4218 if (skip_past_comma (&str) == FAIL
4219 || (rs = reg_required_here (&str, 8)) == FAIL)
4220 {
4221 inst.error = BAD_ARGS;
4222 return;
4223 }
4224
4225 if (rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC)
4226 {
4227 inst.error = BAD_PC;
4228 return;
4229 }
4230
4231 end_of_line (str);
4232 }
4233
4234 static void
4235 do_mul (str)
4236 char * str;
4237 {
4238 int rd, rm;
4239
4240 /* Only one format "rd, rm, rs". */
4241 skip_whitespace (str);
4242
4243 if ((rd = reg_required_here (&str, 16)) == FAIL)
4244 {
4245 inst.error = BAD_ARGS;
4246 return;
4247 }
4248
4249 if (rd == REG_PC)
4250 {
4251 inst.error = BAD_PC;
4252 return;
4253 }
4254
4255 if (skip_past_comma (&str) == FAIL
4256 || (rm = reg_required_here (&str, 0)) == FAIL)
4257 {
4258 inst.error = BAD_ARGS;
4259 return;
4260 }
4261
4262 if (rm == REG_PC)
4263 {
4264 inst.error = BAD_PC;
4265 return;
4266 }
4267
4268 if (rm == rd)
4269 as_tsktsk (_("rd and rm should be different in mul"));
4270
4271 if (skip_past_comma (&str) == FAIL
4272 || (rm = reg_required_here (&str, 8)) == FAIL)
4273 {
4274 inst.error = BAD_ARGS;
4275 return;
4276 }
4277
4278 if (rm == REG_PC)
4279 {
4280 inst.error = BAD_PC;
4281 return;
4282 }
4283
4284 end_of_line (str);
4285 }
4286
4287 static void
4288 do_mla (str)
4289 char * str;
4290 {
4291 int rd, rm;
4292
4293 /* Only one format "rd, rm, rs, rn". */
4294 skip_whitespace (str);
4295
4296 if ((rd = reg_required_here (&str, 16)) == FAIL)
4297 {
4298 inst.error = BAD_ARGS;
4299 return;
4300 }
4301
4302 if (rd == REG_PC)
4303 {
4304 inst.error = BAD_PC;
4305 return;
4306 }
4307
4308 if (skip_past_comma (&str) == FAIL
4309 || (rm = reg_required_here (&str, 0)) == FAIL)
4310 {
4311 inst.error = BAD_ARGS;
4312 return;
4313 }
4314
4315 if (rm == REG_PC)
4316 {
4317 inst.error = BAD_PC;
4318 return;
4319 }
4320
4321 if (rm == rd)
4322 as_tsktsk (_("rd and rm should be different in mla"));
4323
4324 if (skip_past_comma (&str) == FAIL
4325 || (rd = reg_required_here (&str, 8)) == FAIL
4326 || skip_past_comma (&str) == FAIL
4327 || (rm = reg_required_here (&str, 12)) == FAIL)
4328 {
4329 inst.error = BAD_ARGS;
4330 return;
4331 }
4332
4333 if (rd == REG_PC || rm == REG_PC)
4334 {
4335 inst.error = BAD_PC;
4336 return;
4337 }
4338
4339 end_of_line (str);
4340 }
4341
4342 /* Expects *str -> the characters "acc0", possibly with leading blanks.
4343 Advances *str to the next non-alphanumeric.
4344 Returns 0, or else FAIL (in which case sets inst.error).
4345
4346 (In a future XScale, there may be accumulators other than zero.
4347 At that time this routine and its callers can be upgraded to suit.) */
4348
4349 static int
4350 accum0_required_here (str)
4351 char ** str;
4352 {
4353 static char buff [128]; /* Note the address is taken. Hence, static. */
4354 char * p = * str;
4355 char c;
4356 int result = 0; /* The accum number. */
4357
4358 skip_whitespace (p);
4359
4360 *str = p; /* Advance caller's string pointer too. */
4361 c = *p++;
4362 while (ISALNUM (c))
4363 c = *p++;
4364
4365 *--p = 0; /* Aap nul into input buffer at non-alnum. */
4366
4367 if (! ( streq (*str, "acc0") || streq (*str, "ACC0")))
4368 {
4369 sprintf (buff, _("acc0 expected, not '%.100s'"), *str);
4370 inst.error = buff;
4371 result = FAIL;
4372 }
4373
4374 *p = c; /* Unzap. */
4375 *str = p; /* Caller's string pointer to after match. */
4376 return result;
4377 }
4378
4379 /* Expects **str -> after a comma. May be leading blanks.
4380 Advances *str, recognizing a load mode, and setting inst.instruction.
4381 Returns rn, or else FAIL (in which case may set inst.error
4382 and not advance str)
4383
4384 Note: doesn't know Rd, so no err checks that require such knowledge. */
4385
4386 static int
4387 ld_mode_required_here (string)
4388 char ** string;
4389 {
4390 char * str = * string;
4391 int rn;
4392 int pre_inc = 0;
4393
4394 skip_whitespace (str);
4395
4396 if (* str == '[')
4397 {
4398 str++;
4399
4400 skip_whitespace (str);
4401
4402 if ((rn = reg_required_here (& str, 16)) == FAIL)
4403 return FAIL;
4404
4405 skip_whitespace (str);
4406
4407 if (* str == ']')
4408 {
4409 str ++;
4410
4411 if (skip_past_comma (& str) == SUCCESS)
4412 {
4413 /* [Rn],... (post inc) */
4414 if (ldst_extend_v4 (&str) == FAIL)
4415 return FAIL;
4416 }
4417 else /* [Rn] */
4418 {
4419 skip_whitespace (str);
4420
4421 if (* str == '!')
4422 {
4423 str ++;
4424 inst.instruction |= WRITE_BACK;
4425 }
4426
4427 inst.instruction |= INDEX_UP | HWOFFSET_IMM;
4428 pre_inc = 1;
4429 }
4430 }
4431 else /* [Rn,...] */
4432 {
4433 if (skip_past_comma (& str) == FAIL)
4434 {
4435 inst.error = _("pre-indexed expression expected");
4436 return FAIL;
4437 }
4438
4439 pre_inc = 1;
4440
4441 if (ldst_extend_v4 (&str) == FAIL)
4442 return FAIL;
4443
4444 skip_whitespace (str);
4445
4446 if (* str ++ != ']')
4447 {
4448 inst.error = _("missing ]");
4449 return FAIL;
4450 }
4451
4452 skip_whitespace (str);
4453
4454 if (* str == '!')
4455 {
4456 str ++;
4457 inst.instruction |= WRITE_BACK;
4458 }
4459 }
4460 }
4461 else if (* str == '=') /* ldr's "r,=label" syntax */
4462 /* We should never reach here, because <text> = <expression> is
4463 caught gas/read.c read_a_source_file() as a .set operation. */
4464 return FAIL;
4465 else /* PC +- 8 bit immediate offset. */
4466 {
4467 if (my_get_expression (& inst.reloc.exp, & str))
4468 return FAIL;
4469
4470 inst.instruction |= HWOFFSET_IMM; /* The I bit. */
4471 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
4472 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
4473 inst.reloc.pc_rel = 1;
4474 inst.instruction |= (REG_PC << 16);
4475
4476 rn = REG_PC;
4477 pre_inc = 1;
4478 }
4479
4480 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
4481 * string = str;
4482
4483 return rn;
4484 }
4485
4486 /* ARM V5E (El Segundo) signed-multiply-accumulate (argument parse)
4487 SMLAxy{cond} Rd,Rm,Rs,Rn
4488 SMLAWy{cond} Rd,Rm,Rs,Rn
4489 Error if any register is R15. */
4490
4491 static void
4492 do_smla (str)
4493 char * str;
4494 {
4495 int rd, rm, rs, rn;
4496
4497 skip_whitespace (str);
4498
4499 if ((rd = reg_required_here (& str, 16)) == FAIL
4500 || skip_past_comma (& str) == FAIL
4501 || (rm = reg_required_here (& str, 0)) == FAIL
4502 || skip_past_comma (& str) == FAIL
4503 || (rs = reg_required_here (& str, 8)) == FAIL
4504 || skip_past_comma (& str) == FAIL
4505 || (rn = reg_required_here (& str, 12)) == FAIL)
4506 inst.error = BAD_ARGS;
4507
4508 else if (rd == REG_PC || rm == REG_PC || rs == REG_PC || rn == REG_PC)
4509 inst.error = BAD_PC;
4510
4511 else
4512 end_of_line (str);
4513 }
4514
4515 /* ARM V5E (El Segundo) signed-multiply-accumulate-long (argument parse)
4516 SMLALxy{cond} Rdlo,Rdhi,Rm,Rs
4517 Error if any register is R15.
4518 Warning if Rdlo == Rdhi. */
4519
4520 static void
4521 do_smlal (str)
4522 char * str;
4523 {
4524 int rdlo, rdhi, rm, rs;
4525
4526 skip_whitespace (str);
4527
4528 if ((rdlo = reg_required_here (& str, 12)) == FAIL
4529 || skip_past_comma (& str) == FAIL
4530 || (rdhi = reg_required_here (& str, 16)) == FAIL
4531 || skip_past_comma (& str) == FAIL
4532 || (rm = reg_required_here (& str, 0)) == FAIL
4533 || skip_past_comma (& str) == FAIL
4534 || (rs = reg_required_here (& str, 8)) == FAIL)
4535 {
4536 inst.error = BAD_ARGS;
4537 return;
4538 }
4539
4540 if (rdlo == REG_PC || rdhi == REG_PC || rm == REG_PC || rs == REG_PC)
4541 {
4542 inst.error = BAD_PC;
4543 return;
4544 }
4545
4546 if (rdlo == rdhi)
4547 as_tsktsk (_("rdhi and rdlo must be different"));
4548
4549 end_of_line (str);
4550 }
4551
4552 /* ARM V5E (El Segundo) signed-multiply (argument parse)
4553 SMULxy{cond} Rd,Rm,Rs
4554 Error if any register is R15. */
4555
4556 static void
4557 do_smul (str)
4558 char * str;
4559 {
4560 int rd, rm, rs;
4561
4562 skip_whitespace (str);
4563
4564 if ((rd = reg_required_here (& str, 16)) == FAIL
4565 || skip_past_comma (& str) == FAIL
4566 || (rm = reg_required_here (& str, 0)) == FAIL
4567 || skip_past_comma (& str) == FAIL
4568 || (rs = reg_required_here (& str, 8)) == FAIL)
4569 inst.error = BAD_ARGS;
4570
4571 else if (rd == REG_PC || rm == REG_PC || rs == REG_PC)
4572 inst.error = BAD_PC;
4573
4574 else
4575 end_of_line (str);
4576 }
4577
4578 /* ARM V5E (El Segundo) saturating-add/subtract (argument parse)
4579 Q[D]{ADD,SUB}{cond} Rd,Rm,Rn
4580 Error if any register is R15. */
4581
4582 static void
4583 do_qadd (str)
4584 char * str;
4585 {
4586 int rd, rm, rn;
4587
4588 skip_whitespace (str);
4589
4590 if ((rd = reg_required_here (& str, 12)) == FAIL
4591 || skip_past_comma (& str) == FAIL
4592 || (rm = reg_required_here (& str, 0)) == FAIL
4593 || skip_past_comma (& str) == FAIL
4594 || (rn = reg_required_here (& str, 16)) == FAIL)
4595 inst.error = BAD_ARGS;
4596
4597 else if (rd == REG_PC || rm == REG_PC || rn == REG_PC)
4598 inst.error = BAD_PC;
4599
4600 else
4601 end_of_line (str);
4602 }
4603
4604 /* ARM V5E (el Segundo)
4605 MCRRcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
4606 MRRCcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
4607
4608 These are equivalent to the XScale instructions MAR and MRA,
4609 respectively, when coproc == 0, opcode == 0, and CRm == 0.
4610
4611 Result unpredicatable if Rd or Rn is R15. */
4612
4613 static void
4614 do_co_reg2c (str)
4615 char * str;
4616 {
4617 int rd, rn;
4618
4619 skip_whitespace (str);
4620
4621 if (co_proc_number (& str) == FAIL)
4622 {
4623 if (!inst.error)
4624 inst.error = BAD_ARGS;
4625 return;
4626 }
4627
4628 if (skip_past_comma (& str) == FAIL
4629 || cp_opc_expr (& str, 4, 4) == FAIL)
4630 {
4631 if (!inst.error)
4632 inst.error = BAD_ARGS;
4633 return;
4634 }
4635
4636 if (skip_past_comma (& str) == FAIL
4637 || (rd = reg_required_here (& str, 12)) == FAIL)
4638 {
4639 if (!inst.error)
4640 inst.error = BAD_ARGS;
4641 return;
4642 }
4643
4644 if (skip_past_comma (& str) == FAIL
4645 || (rn = reg_required_here (& str, 16)) == FAIL)
4646 {
4647 if (!inst.error)
4648 inst.error = BAD_ARGS;
4649 return;
4650 }
4651
4652 /* Unpredictable result if rd or rn is R15. */
4653 if (rd == REG_PC || rn == REG_PC)
4654 as_tsktsk
4655 (_("Warning: instruction unpredictable when using r15"));
4656
4657 if (skip_past_comma (& str) == FAIL
4658 || cp_reg_required_here (& str, 0) == FAIL)
4659 {
4660 if (!inst.error)
4661 inst.error = BAD_ARGS;
4662 return;
4663 }
4664
4665 end_of_line (str);
4666 }
4667
4668 /* ARM V5 count-leading-zeroes instruction (argument parse)
4669 CLZ{<cond>} <Rd>, <Rm>
4670 Condition defaults to COND_ALWAYS.
4671 Error if Rd or Rm are R15. */
4672
4673 static void
4674 do_clz (str)
4675 char * str;
4676 {
4677 int rd, rm;
4678
4679 skip_whitespace (str);
4680
4681 if (((rd = reg_required_here (& str, 12)) == FAIL)
4682 || (skip_past_comma (& str) == FAIL)
4683 || ((rm = reg_required_here (& str, 0)) == FAIL))
4684 inst.error = BAD_ARGS;
4685
4686 else if (rd == REG_PC || rm == REG_PC )
4687 inst.error = BAD_PC;
4688
4689 else
4690 end_of_line (str);
4691 }
4692
4693 /* ARM V5 (argument parse)
4694 LDC2{L} <coproc>, <CRd>, <addressing mode>
4695 STC2{L} <coproc>, <CRd>, <addressing mode>
4696 Instruction is not conditional, and has 0xf in the condition field.
4697 Otherwise, it's the same as LDC/STC. */
4698
4699 static void
4700 do_lstc2 (str)
4701 char * str;
4702 {
4703 skip_whitespace (str);
4704
4705 if (co_proc_number (& str) == FAIL)
4706 {
4707 if (!inst.error)
4708 inst.error = BAD_ARGS;
4709 }
4710 else if (skip_past_comma (& str) == FAIL
4711 || cp_reg_required_here (& str, 12) == FAIL)
4712 {
4713 if (!inst.error)
4714 inst.error = BAD_ARGS;
4715 }
4716 else if (skip_past_comma (& str) == FAIL
4717 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
4718 {
4719 if (! inst.error)
4720 inst.error = BAD_ARGS;
4721 }
4722 else
4723 end_of_line (str);
4724 }
4725
4726 /* ARM V5 (argument parse)
4727 CDP2 <coproc>, <opcode_1>, <CRd>, <CRn>, <CRm>, <opcode_2>
4728 Instruction is not conditional, and has 0xf in the condition field.
4729 Otherwise, it's the same as CDP. */
4730
4731 static void
4732 do_cdp2 (str)
4733 char * str;
4734 {
4735 skip_whitespace (str);
4736
4737 if (co_proc_number (& str) == FAIL)
4738 {
4739 if (!inst.error)
4740 inst.error = BAD_ARGS;
4741 return;
4742 }
4743
4744 if (skip_past_comma (& str) == FAIL
4745 || cp_opc_expr (& str, 20,4) == FAIL)
4746 {
4747 if (!inst.error)
4748 inst.error = BAD_ARGS;
4749 return;
4750 }
4751
4752 if (skip_past_comma (& str) == FAIL
4753 || cp_reg_required_here (& str, 12) == FAIL)
4754 {
4755 if (!inst.error)
4756 inst.error = BAD_ARGS;
4757 return;
4758 }
4759
4760 if (skip_past_comma (& str) == FAIL
4761 || cp_reg_required_here (& str, 16) == FAIL)
4762 {
4763 if (!inst.error)
4764 inst.error = BAD_ARGS;
4765 return;
4766 }
4767
4768 if (skip_past_comma (& str) == FAIL
4769 || cp_reg_required_here (& str, 0) == FAIL)
4770 {
4771 if (!inst.error)
4772 inst.error = BAD_ARGS;
4773 return;
4774 }
4775
4776 if (skip_past_comma (& str) == SUCCESS)
4777 {
4778 if (cp_opc_expr (& str, 5, 3) == FAIL)
4779 {
4780 if (!inst.error)
4781 inst.error = BAD_ARGS;
4782 return;
4783 }
4784 }
4785
4786 end_of_line (str);
4787 }
4788
4789 /* ARM V5 (argument parse)
4790 MCR2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
4791 MRC2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
4792 Instruction is not conditional, and has 0xf in the condition field.
4793 Otherwise, it's the same as MCR/MRC. */
4794
4795 static void
4796 do_co_reg2 (str)
4797 char * str;
4798 {
4799 skip_whitespace (str);
4800
4801 if (co_proc_number (& str) == FAIL)
4802 {
4803 if (!inst.error)
4804 inst.error = BAD_ARGS;
4805 return;
4806 }
4807
4808 if (skip_past_comma (& str) == FAIL
4809 || cp_opc_expr (& str, 21, 3) == FAIL)
4810 {
4811 if (!inst.error)
4812 inst.error = BAD_ARGS;
4813 return;
4814 }
4815
4816 if (skip_past_comma (& str) == FAIL
4817 || reg_required_here (& str, 12) == FAIL)
4818 {
4819 if (!inst.error)
4820 inst.error = BAD_ARGS;
4821 return;
4822 }
4823
4824 if (skip_past_comma (& str) == FAIL
4825 || cp_reg_required_here (& str, 16) == FAIL)
4826 {
4827 if (!inst.error)
4828 inst.error = BAD_ARGS;
4829 return;
4830 }
4831
4832 if (skip_past_comma (& str) == FAIL
4833 || cp_reg_required_here (& str, 0) == FAIL)
4834 {
4835 if (!inst.error)
4836 inst.error = BAD_ARGS;
4837 return;
4838 }
4839
4840 if (skip_past_comma (& str) == SUCCESS)
4841 {
4842 if (cp_opc_expr (& str, 5, 3) == FAIL)
4843 {
4844 if (!inst.error)
4845 inst.error = BAD_ARGS;
4846 return;
4847 }
4848 }
4849
4850 end_of_line (str);
4851 }
4852
4853 /* ARM v5TEJ. Jump to Jazelle code. */
4854 static void
4855 do_bxj (str)
4856 char * str;
4857 {
4858 int reg;
4859
4860 skip_whitespace (str);
4861
4862 if ((reg = reg_required_here (&str, 0)) == FAIL)
4863 {
4864 inst.error = BAD_ARGS;
4865 return;
4866 }
4867
4868 /* Note - it is not illegal to do a "bxj pc". Useless, but not illegal. */
4869 if (reg == REG_PC)
4870 as_tsktsk (_("use of r15 in bxj is not really useful"));
4871
4872 end_of_line (str);
4873 }
4874
4875 /* ARM V6 umaal (argument parse). */
4876
4877 static void
4878 do_umaal (str)
4879 char *str;
4880 {
4881
4882 int rdlo, rdhi, rm, rs;
4883
4884 skip_whitespace (str);
4885 if ((rdlo = reg_required_here (& str, 12)) == FAIL
4886 || skip_past_comma (& str) == FAIL
4887 || (rdhi = reg_required_here (& str, 16)) == FAIL
4888 || skip_past_comma (& str) == FAIL
4889 || (rm = reg_required_here (& str, 0)) == FAIL
4890 || skip_past_comma (& str) == FAIL
4891 || (rs = reg_required_here (& str, 8)) == FAIL)
4892 {
4893 inst.error = BAD_ARGS;
4894 return;
4895 }
4896
4897 if (rdlo == REG_PC || rdhi == REG_PC || rm == REG_PC || rs == REG_PC)
4898 {
4899 inst.error = BAD_PC;
4900 return;
4901 }
4902
4903 end_of_line (str);
4904 }
4905
4906 /* ARM V6 strex (argument parse). */
4907
4908 static void
4909 do_strex (str)
4910 char *str;
4911 {
4912 int rd, rm, rn;
4913
4914 /* Parse Rd, Rm,. */
4915 skip_whitespace (str);
4916 if ((rd = reg_required_here (& str, 12)) == FAIL
4917 || skip_past_comma (& str) == FAIL
4918 || (rm = reg_required_here (& str, 0)) == FAIL
4919 || skip_past_comma (& str) == FAIL)
4920 {
4921 inst.error = BAD_ARGS;
4922 return;
4923 }
4924 if (rd == REG_PC || rm == REG_PC)
4925 {
4926 inst.error = BAD_PC;
4927 return;
4928 }
4929 if (rd == rm)
4930 {
4931 inst.error = _("Rd equal to Rm or Rn yields unpredictable results");
4932 return;
4933 }
4934
4935 /* Skip past '['. */
4936 if ((strlen (str) >= 1)
4937 && strncmp (str, "[", 1) == 0)
4938 str+=1;
4939 skip_whitespace (str);
4940
4941 /* Parse Rn. */
4942 if ((rn = reg_required_here (& str, 16)) == FAIL)
4943 {
4944 inst.error = BAD_ARGS;
4945 return;
4946 }
4947 else if (rn == REG_PC)
4948 {
4949 inst.error = BAD_PC;
4950 return;
4951 }
4952 if (rd == rn)
4953 {
4954 inst.error = _("Rd equal to Rm or Rn yields unpredictable results");
4955 return;
4956 }
4957 skip_whitespace (str);
4958
4959 /* Skip past ']'. */
4960 if ((strlen (str) >= 1)
4961 && strncmp (str, "]", 1) == 0)
4962 str+=1;
4963
4964 end_of_line (str);
4965 }
4966
4967 /* ARM V6 ssat (argument parse). */
4968
4969 static void
4970 do_ssat (str)
4971 char* str;
4972 {
4973 do_sat (&str, /*bias=*/-1);
4974 end_of_line (str);
4975 }
4976
4977 /* ARM V6 usat (argument parse). */
4978
4979 static void
4980 do_usat (str)
4981 char* str;
4982 {
4983 do_sat (&str, /*bias=*/0);
4984 end_of_line (str);
4985 }
4986
4987 static void
4988 do_sat (str, bias)
4989 char **str;
4990 int bias;
4991 {
4992 int rd, rm;
4993 expressionS expr;
4994
4995 skip_whitespace (*str);
4996
4997 /* Parse <Rd>, field. */
4998 if ((rd = reg_required_here (str, 12)) == FAIL
4999 || skip_past_comma (str) == FAIL)
5000 {
5001 inst.error = BAD_ARGS;
5002 return;
5003 }
5004 if (rd == REG_PC)
5005 {
5006 inst.error = BAD_PC;
5007 return;
5008 }
5009
5010 /* Parse #<immed>, field. */
5011 if (is_immediate_prefix (**str))
5012 (*str)++;
5013 else
5014 {
5015 inst.error = _("immediate expression expected");
5016 return;
5017 }
5018 if (my_get_expression (&expr, str))
5019 {
5020 inst.error = _("bad expression");
5021 return;
5022 }
5023 if (expr.X_op != O_constant)
5024 {
5025 inst.error = _("constant expression expected");
5026 return;
5027 }
5028 if (expr.X_add_number + bias < 0
5029 || expr.X_add_number + bias > 31)
5030 {
5031 inst.error = _("immediate value out of range");
5032 return;
5033 }
5034 inst.instruction |= (expr.X_add_number + bias) << 16;
5035 if (skip_past_comma (str) == FAIL)
5036 {
5037 inst.error = BAD_ARGS;
5038 return;
5039 }
5040
5041 /* Parse <Rm> field. */
5042 if ((rm = reg_required_here (str, 0)) == FAIL)
5043 {
5044 inst.error = BAD_ARGS;
5045 return;
5046 }
5047 if (rm == REG_PC)
5048 {
5049 inst.error = BAD_PC;
5050 return;
5051 }
5052
5053 if (skip_past_comma (str) == SUCCESS)
5054 decode_shift (str, SHIFT_LSL_OR_ASR_IMMEDIATE);
5055 }
5056
5057 /* ARM V6 ssat16 (argument parse). */
5058
5059 static void
5060 do_ssat16 (str)
5061 char *str;
5062 {
5063 do_sat16 (&str, /*bias=*/-1);
5064 end_of_line (str);
5065 }
5066
5067 static void
5068 do_usat16 (str)
5069 char *str;
5070 {
5071 do_sat16 (&str, /*bias=*/0);
5072 end_of_line (str);
5073 }
5074
5075 static void
5076 do_sat16 (str, bias)
5077 char **str;
5078 int bias;
5079 {
5080 int rd, rm;
5081 expressionS expr;
5082
5083 skip_whitespace (*str);
5084
5085 /* Parse the <Rd> field. */
5086 if ((rd = reg_required_here (str, 12)) == FAIL
5087 || skip_past_comma (str) == FAIL)
5088 {
5089 inst.error = BAD_ARGS;
5090 return;
5091 }
5092 if (rd == REG_PC)
5093 {
5094 inst.error = BAD_PC;
5095 return;
5096 }
5097
5098 /* Parse #<immed>, field. */
5099 if (is_immediate_prefix (**str))
5100 (*str)++;
5101 else
5102 {
5103 inst.error = _("immediate expression expected");
5104 return;
5105 }
5106 if (my_get_expression (&expr, str))
5107 {
5108 inst.error = _("bad expression");
5109 return;
5110 }
5111 if (expr.X_op != O_constant)
5112 {
5113 inst.error = _("constant expression expected");
5114 return;
5115 }
5116 if (expr.X_add_number + bias < 0
5117 || expr.X_add_number + bias > 15)
5118 {
5119 inst.error = _("immediate value out of range");
5120 return;
5121 }
5122 inst.instruction |= (expr.X_add_number + bias) << 16;
5123 if (skip_past_comma (str) == FAIL)
5124 {
5125 inst.error = BAD_ARGS;
5126 return;
5127 }
5128
5129 /* Parse <Rm> field. */
5130 if ((rm = reg_required_here (str, 0)) == FAIL)
5131 {
5132 inst.error = BAD_ARGS;
5133 return;
5134 }
5135 if (rm == REG_PC)
5136 {
5137 inst.error = BAD_PC;
5138 return;
5139 }
5140 }
5141
5142 /* ARM V6 srs (argument parse). */
5143
5144 static void
5145 do_srs (str)
5146 char* str;
5147 {
5148 char *exclam;
5149 skip_whitespace (str);
5150 exclam = strchr (str, '!');
5151 if (exclam)
5152 *exclam = '\0';
5153 do_cps_mode (&str);
5154 if (exclam)
5155 *exclam = '!';
5156 if (*str == '!')
5157 {
5158 inst.instruction |= WRITE_BACK;
5159 str++;
5160 }
5161 end_of_line (str);
5162 }
5163
5164 /* ARM V6 SMMUL (argument parse). */
5165
5166 static void
5167 do_smmul (str)
5168 char* str;
5169 {
5170 int rd, rm, rs;
5171
5172 skip_whitespace (str);
5173 if ((rd = reg_required_here (&str, 16)) == FAIL
5174 || skip_past_comma (&str) == FAIL
5175 || (rm = reg_required_here (&str, 0)) == FAIL
5176 || skip_past_comma (&str) == FAIL
5177 || (rs = reg_required_here (&str, 8)) == FAIL)
5178 {
5179 inst.error = BAD_ARGS;
5180 return;
5181 }
5182
5183 if (rd == REG_PC
5184 || rm == REG_PC
5185 || rs == REG_PC)
5186 {
5187 inst.error = BAD_PC;
5188 return;
5189 }
5190
5191 end_of_line (str);
5192
5193 }
5194
5195 /* ARM V6 SMLALD (argument parse). */
5196
5197 static void
5198 do_smlald (str)
5199 char* str;
5200 {
5201 int rdlo, rdhi, rm, rs;
5202 skip_whitespace (str);
5203 if ((rdlo = reg_required_here (&str, 12)) == FAIL
5204 || skip_past_comma (&str) == FAIL
5205 || (rdhi = reg_required_here (&str, 16)) == FAIL
5206 || skip_past_comma (&str) == FAIL
5207 || (rm = reg_required_here (&str, 0)) == FAIL
5208 || skip_past_comma (&str) == FAIL
5209 || (rs = reg_required_here (&str, 8)) == FAIL)
5210 {
5211 inst.error = BAD_ARGS;
5212 return;
5213 }
5214
5215 if (rdlo == REG_PC
5216 || rdhi == REG_PC
5217 || rm == REG_PC
5218 || rs == REG_PC)
5219 {
5220 inst.error = BAD_PC;
5221 return;
5222 }
5223
5224 end_of_line (str);
5225 }
5226
5227 /* ARM V6 SMLAD (argument parse). Signed multiply accumulate dual.
5228 smlad{x}{<cond>} Rd, Rm, Rs, Rn */
5229
5230 static void
5231 do_smlad (str)
5232 char *str;
5233 {
5234 int rd, rm, rs, rn;
5235
5236 skip_whitespace (str);
5237 if ((rd = reg_required_here (&str, 16)) == FAIL
5238 || skip_past_comma (&str) == FAIL
5239 || (rm = reg_required_here (&str, 0)) == FAIL
5240 || skip_past_comma (&str) == FAIL
5241 || (rs = reg_required_here (&str, 8)) == FAIL
5242 || skip_past_comma (&str) == FAIL
5243 || (rn = reg_required_here (&str, 12)) == FAIL)
5244 {
5245 inst.error = BAD_ARGS;
5246 return;
5247 }
5248
5249 if (rd == REG_PC
5250 || rn == REG_PC
5251 || rs == REG_PC
5252 || rm == REG_PC)
5253 {
5254 inst.error = BAD_PC;
5255 return;
5256 }
5257
5258 end_of_line (str);
5259 }
5260
5261 /* ARM V6 SETEND (argument parse). Sets the E bit in the CPSR while
5262 preserving the other bits.
5263
5264 setend <endian_specifier>, where <endian_specifier> is either
5265 BE or LE. */
5266
5267 static void
5268 do_setend (str)
5269 char *str;
5270 {
5271 if (do_endian_specifier (str))
5272 inst.instruction |= 0x200;
5273 }
5274
5275 /* Returns true if the endian-specifier indicates big-endianness. */
5276
5277 static int
5278 do_endian_specifier (str)
5279 char *str;
5280 {
5281 int big_endian = 0;
5282
5283 skip_whitespace (str);
5284 if (strlen (str) < 2)
5285 inst.error = _("missing endian specifier");
5286 else if (strncasecmp (str, "BE", 2) == 0)
5287 {
5288 str += 2;
5289 big_endian = 1;
5290 }
5291 else if (strncasecmp (str, "LE", 2) == 0)
5292 str += 2;
5293 else
5294 inst.error = _("valid endian specifiers are be or le");
5295
5296 end_of_line (str);
5297
5298 return big_endian;
5299 }
5300
5301 /* ARM V6 SXTH.
5302
5303 SXTH {<cond>} <Rd>, <Rm>{, <rotation>}
5304 Condition defaults to COND_ALWAYS.
5305 Error if any register uses R15. */
5306
5307 static void
5308 do_sxth (str)
5309 char *str;
5310 {
5311 int rd, rm;
5312 expressionS expr;
5313 int rotation_clear_mask = 0xfffff3ff;
5314 int rotation_eight_mask = 0x00000400;
5315 int rotation_sixteen_mask = 0x00000800;
5316 int rotation_twenty_four_mask = 0x00000c00;
5317
5318 skip_whitespace (str);
5319 if ((rd = reg_required_here (&str, 12)) == FAIL
5320 || skip_past_comma (&str) == FAIL
5321 || (rm = reg_required_here (&str, 0)) == FAIL)
5322 {
5323 inst.error = BAD_ARGS;
5324 return;
5325 }
5326
5327 else if (rd == REG_PC || rm == REG_PC)
5328 {
5329 inst.error = BAD_PC;
5330 return;
5331 }
5332
5333 /* Zero out the rotation field. */
5334 inst.instruction &= rotation_clear_mask;
5335
5336 /* Check for lack of optional rotation field. */
5337 if (skip_past_comma (&str) == FAIL)
5338 {
5339 end_of_line (str);
5340 return;
5341 }
5342
5343 /* Move past 'ROR'. */
5344 skip_whitespace (str);
5345 if (strncasecmp (str, "ROR", 3) == 0)
5346 str+=3;
5347 else
5348 {
5349 inst.error = _("missing rotation field after comma");
5350 return;
5351 }
5352
5353 /* Get the immediate constant. */
5354 skip_whitespace (str);
5355 if (is_immediate_prefix (* str))
5356 str++;
5357 else
5358 {
5359 inst.error = _("immediate expression expected");
5360 return;
5361 }
5362
5363 if (my_get_expression (&expr, &str))
5364 {
5365 inst.error = _("bad expression");
5366 return;
5367 }
5368
5369 if (expr.X_op != O_constant)
5370 {
5371 inst.error = _("constant expression expected");
5372 return;
5373 }
5374
5375 switch (expr.X_add_number)
5376 {
5377 case 0:
5378 /* Rotation field has already been zeroed. */
5379 break;
5380 case 8:
5381 inst.instruction |= rotation_eight_mask;
5382 break;
5383
5384 case 16:
5385 inst.instruction |= rotation_sixteen_mask;
5386 break;
5387
5388 case 24:
5389 inst.instruction |= rotation_twenty_four_mask;
5390 break;
5391
5392 default:
5393 inst.error = _("rotation can be 8, 16, 24 or 0 when field is ommited");
5394 break;
5395 }
5396
5397 end_of_line (str);
5398
5399 }
5400
5401 /* ARM V6 SXTAH extracts a 16-bit value from a register, sign
5402 extends it to 32-bits, and adds the result to a value in another
5403 register. You can specify a rotation by 0, 8, 16, or 24 bits
5404 before extracting the 16-bit value.
5405 SXTAH{<cond>} <Rd>, <Rn>, <Rm>{, <rotation>}
5406 Condition defaults to COND_ALWAYS.
5407 Error if any register uses R15. */
5408
5409 static void
5410 do_sxtah (str)
5411 char *str;
5412 {
5413 int rd, rn, rm;
5414 expressionS expr;
5415 int rotation_clear_mask = 0xfffff3ff;
5416 int rotation_eight_mask = 0x00000400;
5417 int rotation_sixteen_mask = 0x00000800;
5418 int rotation_twenty_four_mask = 0x00000c00;
5419
5420 skip_whitespace (str);
5421 if ((rd = reg_required_here (&str, 12)) == FAIL
5422 || skip_past_comma (&str) == FAIL
5423 || (rn = reg_required_here (&str, 16)) == FAIL
5424 || skip_past_comma (&str) == FAIL
5425 || (rm = reg_required_here (&str, 0)) == FAIL)
5426 {
5427 inst.error = BAD_ARGS;
5428 return;
5429 }
5430
5431 else if (rd == REG_PC || rn == REG_PC || rm == REG_PC)
5432 {
5433 inst.error = BAD_PC;
5434 return;
5435 }
5436
5437 /* Zero out the rotation field. */
5438 inst.instruction &= rotation_clear_mask;
5439
5440 /* Check for lack of optional rotation field. */
5441 if (skip_past_comma (&str) == FAIL)
5442 {
5443 end_of_line (str);
5444 return;
5445 }
5446
5447 /* Move past 'ROR'. */
5448 skip_whitespace (str);
5449 if (strncasecmp (str, "ROR", 3) == 0)
5450 str+=3;
5451 else
5452 {
5453 inst.error = _("missing rotation field after comma");
5454 return;
5455 }
5456
5457 /* Get the immediate constant. */
5458 skip_whitespace (str);
5459 if (is_immediate_prefix (* str))
5460 str++;
5461 else
5462 {
5463 inst.error = _("immediate expression expected");
5464 return;
5465 }
5466
5467 if (my_get_expression (&expr, &str))
5468 {
5469 inst.error = _("bad expression");
5470 return;
5471 }
5472
5473 if (expr.X_op != O_constant)
5474 {
5475 inst.error = _("constant expression expected");
5476 return;
5477 }
5478
5479 switch (expr.X_add_number)
5480 {
5481 case 0:
5482 /* Rotation field has already been zeroed. */
5483 break;
5484
5485 case 8:
5486 inst.instruction |= rotation_eight_mask;
5487 break;
5488
5489 case 16:
5490 inst.instruction |= rotation_sixteen_mask;
5491 break;
5492
5493 case 24:
5494 inst.instruction |= rotation_twenty_four_mask;
5495 break;
5496
5497 default:
5498 inst.error = _("rotation can be 8, 16, 24 or 0 when field is ommited");
5499 break;
5500 }
5501
5502 end_of_line (str);
5503
5504 }
5505
5506
5507 /* ARM V6 RFE (Return from Exception) loads the PC and CPSR from the
5508 word at the specified address and the following word
5509 respectively.
5510 Unconditionally executed.
5511 Error if Rn is R15.
5512 */
5513
5514 static void
5515 do_rfe (str)
5516 char *str;
5517 {
5518 int rn;
5519
5520 skip_whitespace (str);
5521
5522 if ((rn = reg_required_here (&str, 16)) == FAIL)
5523 return;
5524
5525 if (rn == REG_PC)
5526 {
5527 inst.error = BAD_PC;
5528 return;
5529 }
5530
5531 skip_whitespace (str);
5532
5533 if (*str == '!')
5534 {
5535 inst.instruction |= WRITE_BACK;
5536 str++;
5537 }
5538 end_of_line (str);
5539 }
5540
5541 /* ARM V6 REV (Byte Reverse Word) reverses the byte order in a 32-bit
5542 register (argument parse).
5543 REV{<cond>} Rd, Rm.
5544 Condition defaults to COND_ALWAYS.
5545 Error if Rd or Rm are R15. */
5546
5547 static void
5548 do_rev (str)
5549 char* str;
5550 {
5551 int rd, rm;
5552
5553 skip_whitespace (str);
5554
5555 if ((rd = reg_required_here (&str, 12)) == FAIL
5556 || skip_past_comma (&str) == FAIL
5557 || (rm = reg_required_here (&str, 0)) == FAIL)
5558 inst.error = BAD_ARGS;
5559
5560 else if (rd == REG_PC || rm == REG_PC)
5561 inst.error = BAD_PC;
5562
5563 else
5564 end_of_line (str);
5565 }
5566
5567 /* ARM V6 Perform Two Sixteen Bit Integer Additions. (argument parse).
5568 QADD16{<cond>} <Rd>, <Rn>, <Rm>
5569 Condition defaults to COND_ALWAYS.
5570 Error if Rd, Rn or Rm are R15. */
5571
5572 static void
5573 do_qadd16 (str)
5574 char* str;
5575 {
5576 int rd, rm, rn;
5577
5578 skip_whitespace (str);
5579
5580 if ((rd = reg_required_here (&str, 12)) == FAIL
5581 || skip_past_comma (&str) == FAIL
5582 || (rn = reg_required_here (&str, 16)) == FAIL
5583 || skip_past_comma (&str) == FAIL
5584 || (rm = reg_required_here (&str, 0)) == FAIL)
5585 inst.error = BAD_ARGS;
5586
5587 else if (rd == REG_PC || rm == REG_PC || rn == REG_PC)
5588 inst.error = BAD_PC;
5589
5590 else
5591 end_of_line (str);
5592 }
5593
5594 /* ARM V6 Pack Halfword Bottom Top instruction (argument parse).
5595 PKHBT {<cond>} <Rd>, <Rn>, <Rm> {, LSL #<shift_imm>}
5596 Condition defaults to COND_ALWAYS.
5597 Error if Rd, Rn or Rm are R15. */
5598
5599 static void
5600 do_pkhbt (str)
5601 char* str;
5602 {
5603 do_pkh_core (str, SHIFT_LSL_IMMEDIATE);
5604 }
5605
5606 /* ARM V6 PKHTB (Argument Parse). */
5607
5608 static void
5609 do_pkhtb (str)
5610 char* str;
5611 {
5612 do_pkh_core (str, SHIFT_ASR_IMMEDIATE);
5613 }
5614
5615 static void
5616 do_pkh_core (str, shift)
5617 char* str;
5618 int shift;
5619 {
5620 int rd, rn, rm;
5621
5622 skip_whitespace (str);
5623 if (((rd = reg_required_here (&str, 12)) == FAIL)
5624 || (skip_past_comma (&str) == FAIL)
5625 || ((rn = reg_required_here (&str, 16)) == FAIL)
5626 || (skip_past_comma (&str) == FAIL)
5627 || ((rm = reg_required_here (&str, 0)) == FAIL))
5628 {
5629 inst.error = BAD_ARGS;
5630 return;
5631 }
5632
5633 else if (rd == REG_PC || rn == REG_PC || rm == REG_PC)
5634 {
5635 inst.error = BAD_PC;
5636 return;
5637 }
5638
5639 /* Check for optional shift immediate constant. */
5640 if (skip_past_comma (&str) == FAIL)
5641 {
5642 if (shift == SHIFT_ASR_IMMEDIATE)
5643 {
5644 /* If the shift specifier is ommited, turn the instruction
5645 into pkhbt rd, rm, rn. First, switch the instruction
5646 code, and clear the rn and rm fields. */
5647 inst.instruction &= 0xfff0f010;
5648 /* Now, re-encode the registers. */
5649 inst.instruction |= (rm << 16) | rn;
5650 }
5651 return;
5652 }
5653
5654 decode_shift (&str, shift);
5655 }
5656
5657 /* ARM V6 Load Register Exclusive instruction (argument parse).
5658 LDREX{<cond>} <Rd, [<Rn>]
5659 Condition defaults to COND_ALWAYS.
5660 Error if Rd or Rn are R15.
5661 See ARMARMv6 A4.1.27: LDREX. */
5662
5663
5664 static void
5665 do_ldrex (str)
5666 char * str;
5667 {
5668 int rd, rn;
5669
5670 skip_whitespace (str);
5671
5672 /* Parse Rd. */
5673 if (((rd = reg_required_here (&str, 12)) == FAIL)
5674 || (skip_past_comma (&str) == FAIL))
5675 {
5676 inst.error = BAD_ARGS;
5677 return;
5678 }
5679 else if (rd == REG_PC)
5680 {
5681 inst.error = BAD_PC;
5682 return;
5683 }
5684 skip_whitespace (str);
5685
5686 /* Skip past '['. */
5687 if ((strlen (str) >= 1)
5688 &&strncmp (str, "[", 1) == 0)
5689 str+=1;
5690 skip_whitespace (str);
5691
5692 /* Parse Rn. */
5693 if ((rn = reg_required_here (&str, 16)) == FAIL)
5694 {
5695 inst.error = BAD_ARGS;
5696 return;
5697 }
5698 else if (rn == REG_PC)
5699 {
5700 inst.error = BAD_PC;
5701 return;
5702 }
5703 skip_whitespace (str);
5704
5705 /* Skip past ']'. */
5706 if ((strlen (str) >= 1)
5707 && strncmp (str, "]", 1) == 0)
5708 str+=1;
5709
5710 end_of_line (str);
5711 }
5712
5713 /* ARM V6 change processor state instruction (argument parse)
5714 CPS, CPSIE, CSPID . */
5715
5716 static void
5717 do_cps (str)
5718 char * str;
5719 {
5720 do_cps_mode (&str);
5721 end_of_line (str);
5722 }
5723
5724 static void
5725 do_cpsi (str)
5726 char * str;
5727 {
5728 do_cps_flags (&str, /*thumb_p=*/0);
5729
5730 if (skip_past_comma (&str) == SUCCESS)
5731 {
5732 skip_whitespace (str);
5733 do_cps_mode (&str);
5734 }
5735 end_of_line (str);
5736 }
5737
5738 static void
5739 do_cps_mode (str)
5740 char **str;
5741 {
5742 expressionS expr;
5743
5744 skip_whitespace (*str);
5745
5746 if (! is_immediate_prefix (**str))
5747 {
5748 inst.error = _("immediate expression expected");
5749 return;
5750 }
5751
5752 (*str)++; /* Strip off the immediate signifier. */
5753 if (my_get_expression (&expr, str))
5754 {
5755 inst.error = _("bad expression");
5756 return;
5757 }
5758
5759 if (expr.X_op != O_constant)
5760 {
5761 inst.error = _("constant expression expected");
5762 return;
5763 }
5764
5765 /* The mode is a 5 bit field. Valid values are 0-31. */
5766 if (((unsigned) expr.X_add_number) > 31
5767 || (inst.reloc.exp.X_add_number) < 0)
5768 {
5769 inst.error = _("invalid constant");
5770 return;
5771 }
5772
5773 inst.instruction |= expr.X_add_number;
5774 }
5775
5776 static void
5777 do_cps_flags (str, thumb_p)
5778 char **str;
5779 int thumb_p;
5780 {
5781 struct cps_flag {
5782 char character;
5783 unsigned long arm_value;
5784 unsigned long thumb_value;
5785 };
5786 static struct cps_flag flag_table[] = {
5787 {'a', 0x100, 0x4 },
5788 {'i', 0x080, 0x2 },
5789 {'f', 0x040, 0x1 }
5790 };
5791
5792 int saw_a_flag = 0;
5793
5794 skip_whitespace (*str);
5795
5796 /* Get the a, f and i flags. */
5797 while (**str && **str != ',')
5798 {
5799 struct cps_flag *p;
5800 struct cps_flag *q = flag_table + sizeof (flag_table)/sizeof (*p);
5801 for (p = flag_table; p < q; ++p)
5802 if (strncasecmp (*str, &p->character, 1) == 0)
5803 {
5804 inst.instruction |= (thumb_p ? p->thumb_value : p->arm_value);
5805 saw_a_flag = 1;
5806 break;
5807 }
5808 if (p == q)
5809 {
5810 inst.error = _("unrecognized flag");
5811 return;
5812 }
5813 (*str)++;
5814 }
5815 if (!saw_a_flag)
5816 inst.error = _("no 'a', 'i', or 'f' flags for 'cps'");
5817 }
5818
5819 /* THUMB V5 breakpoint instruction (argument parse)
5820 BKPT <immed_8>. */
5821
5822 static void
5823 do_t_bkpt (str)
5824 char * str;
5825 {
5826 expressionS expr;
5827 unsigned long number;
5828
5829 skip_whitespace (str);
5830
5831 /* Allow optional leading '#'. */
5832 if (is_immediate_prefix (*str))
5833 str ++;
5834
5835 memset (& expr, '\0', sizeof (expr));
5836 if (my_get_expression (& expr, & str)
5837 || (expr.X_op != O_constant
5838 /* As a convenience we allow 'bkpt' without an operand. */
5839 && expr.X_op != O_absent))
5840 {
5841 inst.error = _("bad expression");
5842 return;
5843 }
5844
5845 number = expr.X_add_number;
5846
5847 /* Check it fits an 8 bit unsigned. */
5848 if (number != (number & 0xff))
5849 {
5850 inst.error = _("immediate value out of range");
5851 return;
5852 }
5853
5854 inst.instruction |= number;
5855
5856 end_of_line (str);
5857 }
5858
5859 /* ARM V5 branch-link-exchange (argument parse) for BLX(1) only.
5860 Expects inst.instruction is set for BLX(1).
5861 Note: this is cloned from do_branch, and the reloc changed to be a
5862 new one that can cope with setting one extra bit (the H bit). */
5863
5864 static void
5865 do_branch25 (str)
5866 char * str;
5867 {
5868 if (my_get_expression (& inst.reloc.exp, & str))
5869 return;
5870
5871 #ifdef OBJ_ELF
5872 {
5873 char * save_in;
5874
5875 /* ScottB: February 5, 1998 */
5876 /* Check to see of PLT32 reloc required for the instruction. */
5877
5878 /* arm_parse_reloc() works on input_line_pointer.
5879 We actually want to parse the operands to the branch instruction
5880 passed in 'str'. Save the input pointer and restore it later. */
5881 save_in = input_line_pointer;
5882 input_line_pointer = str;
5883
5884 if (inst.reloc.exp.X_op == O_symbol
5885 && *str == '('
5886 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
5887 {
5888 inst.reloc.type = BFD_RELOC_ARM_PLT32;
5889 inst.reloc.pc_rel = 0;
5890 /* Modify str to point to after parsed operands, otherwise
5891 end_of_line() will complain about the (PLT) left in str. */
5892 str = input_line_pointer;
5893 }
5894 else
5895 {
5896 inst.reloc.type = BFD_RELOC_ARM_PCREL_BLX;
5897 inst.reloc.pc_rel = 1;
5898 }
5899
5900 input_line_pointer = save_in;
5901 }
5902 #else
5903 inst.reloc.type = BFD_RELOC_ARM_PCREL_BLX;
5904 inst.reloc.pc_rel = 1;
5905 #endif /* OBJ_ELF */
5906
5907 end_of_line (str);
5908 }
5909
5910 /* ARM V5 branch-link-exchange instruction (argument parse)
5911 BLX <target_addr> ie BLX(1)
5912 BLX{<condition>} <Rm> ie BLX(2)
5913 Unfortunately, there are two different opcodes for this mnemonic.
5914 So, the insns[].value is not used, and the code here zaps values
5915 into inst.instruction.
5916 Also, the <target_addr> can be 25 bits, hence has its own reloc. */
5917
5918 static void
5919 do_blx (str)
5920 char * str;
5921 {
5922 char * mystr = str;
5923 int rm;
5924
5925 skip_whitespace (mystr);
5926 rm = reg_required_here (& mystr, 0);
5927
5928 /* The above may set inst.error. Ignore his opinion. */
5929 inst.error = 0;
5930
5931 if (rm != FAIL)
5932 {
5933 /* Arg is a register.
5934 Use the condition code our caller put in inst.instruction.
5935 Pass ourselves off as a BX with a funny opcode. */
5936 inst.instruction |= 0x012fff30;
5937 do_bx (str);
5938 }
5939 else
5940 {
5941 /* This must be is BLX <target address>, no condition allowed. */
5942 if (inst.instruction != COND_ALWAYS)
5943 {
5944 inst.error = BAD_COND;
5945 return;
5946 }
5947
5948 inst.instruction = 0xfafffffe;
5949
5950 /* Process like a B/BL, but with a different reloc.
5951 Note that B/BL expecte fffffe, not 0, offset in the opcode table. */
5952 do_branch25 (str);
5953 }
5954 }
5955
5956 /* ARM V5 Thumb BLX (argument parse)
5957 BLX <target_addr> which is BLX(1)
5958 BLX <Rm> which is BLX(2)
5959 Unfortunately, there are two different opcodes for this mnemonic.
5960 So, the tinsns[].value is not used, and the code here zaps values
5961 into inst.instruction. */
5962
5963 static void
5964 do_t_blx (str)
5965 char * str;
5966 {
5967 char * mystr = str;
5968 int rm;
5969
5970 skip_whitespace (mystr);
5971 inst.instruction = 0x4780;
5972
5973 /* Note that this call is to the ARM register recognizer. BLX(2)
5974 uses the ARM register space, not the Thumb one, so a call to
5975 thumb_reg() would be wrong. */
5976 rm = reg_required_here (& mystr, 3);
5977 inst.error = 0;
5978
5979 if (rm != FAIL)
5980 {
5981 /* It's BLX(2). The .instruction was zapped with rm & is final. */
5982 inst.size = 2;
5983 }
5984 else
5985 {
5986 /* No ARM register. This must be BLX(1). Change the .instruction. */
5987 inst.instruction = 0xf7ffeffe;
5988 inst.size = 4;
5989
5990 if (my_get_expression (& inst.reloc.exp, & mystr))
5991 return;
5992
5993 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BLX;
5994 inst.reloc.pc_rel = 1;
5995 }
5996
5997 end_of_line (mystr);
5998 }
5999
6000 /* ARM V5 breakpoint instruction (argument parse)
6001 BKPT <16 bit unsigned immediate>
6002 Instruction is not conditional.
6003 The bit pattern given in insns[] has the COND_ALWAYS condition,
6004 and it is an error if the caller tried to override that. */
6005
6006 static void
6007 do_bkpt (str)
6008 char * str;
6009 {
6010 expressionS expr;
6011 unsigned long number;
6012
6013 skip_whitespace (str);
6014
6015 /* Allow optional leading '#'. */
6016 if (is_immediate_prefix (* str))
6017 str++;
6018
6019 memset (& expr, '\0', sizeof (expr));
6020
6021 if (my_get_expression (& expr, & str)
6022 || (expr.X_op != O_constant
6023 /* As a convenience we allow 'bkpt' without an operand. */
6024 && expr.X_op != O_absent))
6025 {
6026 inst.error = _("bad expression");
6027 return;
6028 }
6029
6030 number = expr.X_add_number;
6031
6032 /* Check it fits a 16 bit unsigned. */
6033 if (number != (number & 0xffff))
6034 {
6035 inst.error = _("immediate value out of range");
6036 return;
6037 }
6038
6039 /* Top 12 of 16 bits to bits 19:8. */
6040 inst.instruction |= (number & 0xfff0) << 4;
6041
6042 /* Bottom 4 of 16 bits to bits 3:0. */
6043 inst.instruction |= number & 0xf;
6044
6045 end_of_line (str);
6046 }
6047
6048 /* THUMB CPS instruction (argument parse). */
6049
6050 static void
6051 do_t_cps (str)
6052 char *str;
6053 {
6054 do_cps_flags (&str, /*thumb_p=*/1);
6055 end_of_line (str);
6056 }
6057
6058 /* THUMB CPY instruction (argument parse). */
6059
6060 static void
6061 do_t_cpy (str)
6062 char *str;
6063 {
6064 thumb_mov_compare (str, THUMB_CPY);
6065 }
6066
6067 /* THUMB SETEND instruction (argument parse). */
6068
6069 static void
6070 do_t_setend (str)
6071 char *str;
6072 {
6073 if (do_endian_specifier (str))
6074 inst.instruction |= 0x8;
6075 }
6076
6077 static unsigned long check_iwmmxt_insn PARAMS ((char *, enum iwmmxt_insn_type, int));
6078
6079 /* Parse INSN_TYPE insn STR having a possible IMMEDIATE_SIZE immediate. */
6080
6081 static unsigned long
6082 check_iwmmxt_insn (str, insn_type, immediate_size)
6083 char * str;
6084 enum iwmmxt_insn_type insn_type;
6085 int immediate_size;
6086 {
6087 int reg = 0;
6088 const char * inst_error;
6089 expressionS expr;
6090 unsigned long number;
6091
6092 inst_error = inst.error;
6093 if (!inst.error)
6094 inst.error = BAD_ARGS;
6095 skip_whitespace (str);
6096
6097 switch (insn_type)
6098 {
6099 case check_rd:
6100 if ((reg = reg_required_here (&str, 12)) == FAIL)
6101 return FAIL;
6102 break;
6103
6104 case check_wr:
6105 if ((wreg_required_here (&str, 0, IWMMXT_REG_WR)) == FAIL)
6106 return FAIL;
6107 break;
6108
6109 case check_wrwr:
6110 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
6111 || skip_past_comma (&str) == FAIL
6112 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL))
6113 return FAIL;
6114 break;
6115
6116 case check_wrwrwr:
6117 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
6118 || skip_past_comma (&str) == FAIL
6119 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6120 || skip_past_comma (&str) == FAIL
6121 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL))
6122 return FAIL;
6123 break;
6124
6125 case check_wrwrwcg:
6126 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
6127 || skip_past_comma (&str) == FAIL
6128 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6129 || skip_past_comma (&str) == FAIL
6130 || wreg_required_here (&str, 0, IWMMXT_REG_WCG) == FAIL))
6131 return FAIL;
6132 break;
6133
6134 case check_tbcst:
6135 if ((wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6136 || skip_past_comma (&str) == FAIL
6137 || reg_required_here (&str, 12) == FAIL))
6138 return FAIL;
6139 break;
6140
6141 case check_tmovmsk:
6142 if ((reg_required_here (&str, 12) == FAIL
6143 || skip_past_comma (&str) == FAIL
6144 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL))
6145 return FAIL;
6146 break;
6147
6148 case check_tmia:
6149 if ((wreg_required_here (&str, 5, IWMMXT_REG_WR) == FAIL
6150 || skip_past_comma (&str) == FAIL
6151 || reg_required_here (&str, 0) == FAIL
6152 || skip_past_comma (&str) == FAIL
6153 || reg_required_here (&str, 12) == FAIL))
6154 return FAIL;
6155 break;
6156
6157 case check_tmcrr:
6158 if ((wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL
6159 || skip_past_comma (&str) == FAIL
6160 || reg_required_here (&str, 12) == FAIL
6161 || skip_past_comma (&str) == FAIL
6162 || reg_required_here (&str, 16) == FAIL))
6163 return FAIL;
6164 break;
6165
6166 case check_tmrrc:
6167 if ((reg_required_here (&str, 12) == FAIL
6168 || skip_past_comma (&str) == FAIL
6169 || reg_required_here (&str, 16) == FAIL
6170 || skip_past_comma (&str) == FAIL
6171 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL))
6172 return FAIL;
6173 break;
6174
6175 case check_tmcr:
6176 if ((wreg_required_here (&str, 16, IWMMXT_REG_WC) == FAIL
6177 || skip_past_comma (&str) == FAIL
6178 || reg_required_here (&str, 12) == FAIL))
6179 return FAIL;
6180 break;
6181
6182 case check_tmrc:
6183 if ((reg_required_here (&str, 12) == FAIL
6184 || skip_past_comma (&str) == FAIL
6185 || wreg_required_here (&str, 16, IWMMXT_REG_WC) == FAIL))
6186 return FAIL;
6187 break;
6188
6189 case check_tinsr:
6190 if ((wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6191 || skip_past_comma (&str) == FAIL
6192 || reg_required_here (&str, 12) == FAIL
6193 || skip_past_comma (&str) == FAIL))
6194 return FAIL;
6195 break;
6196
6197 case check_textrc:
6198 if ((reg_required_here (&str, 12) == FAIL
6199 || skip_past_comma (&str) == FAIL))
6200 return FAIL;
6201 break;
6202
6203 case check_waligni:
6204 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
6205 || skip_past_comma (&str) == FAIL
6206 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6207 || skip_past_comma (&str) == FAIL
6208 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL
6209 || skip_past_comma (&str) == FAIL))
6210 return FAIL;
6211 break;
6212
6213 case check_textrm:
6214 if ((reg_required_here (&str, 12) == FAIL
6215 || skip_past_comma (&str) == FAIL
6216 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6217 || skip_past_comma (&str) == FAIL))
6218 return FAIL;
6219 break;
6220
6221 case check_wshufh:
6222 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
6223 || skip_past_comma (&str) == FAIL
6224 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6225 || skip_past_comma (&str) == FAIL))
6226 return FAIL;
6227 break;
6228 }
6229
6230 if (immediate_size == 0)
6231 {
6232 end_of_line (str);
6233 inst.error = inst_error;
6234 return reg;
6235 }
6236 else
6237 {
6238 skip_whitespace (str);
6239
6240 /* Allow optional leading '#'. */
6241 if (is_immediate_prefix (* str))
6242 str++;
6243
6244 memset (& expr, '\0', sizeof (expr));
6245
6246 if (my_get_expression (& expr, & str) || (expr.X_op != O_constant))
6247 {
6248 inst.error = _("bad or missing expression");
6249 return FAIL;
6250 }
6251
6252 number = expr.X_add_number;
6253
6254 if (number != (number & immediate_size))
6255 {
6256 inst.error = _("immediate value out of range");
6257 return FAIL;
6258 }
6259 end_of_line (str);
6260 inst.error = inst_error;
6261 return number;
6262 }
6263 }
6264
6265 static void
6266 do_iwmmxt_byte_addr (str)
6267 char * str;
6268 {
6269 int op = (inst.instruction & 0x300) >> 8;
6270 int reg;
6271
6272 inst.instruction &= ~0x300;
6273 inst.instruction |= (op & 1) << 22 | (op & 2) << 7;
6274
6275 skip_whitespace (str);
6276
6277 if ((reg = wreg_required_here (&str, 12, IWMMXT_REG_WR_OR_WC)) == FAIL
6278 || skip_past_comma (& str) == FAIL
6279 || cp_byte_address_required_here (&str) == FAIL)
6280 {
6281 if (! inst.error)
6282 inst.error = BAD_ARGS;
6283 }
6284 else
6285 end_of_line (str);
6286
6287 if (wc_register (reg))
6288 {
6289 as_bad (_("non-word size not supported with control register"));
6290 inst.instruction |= 0xf0000100;
6291 inst.instruction &= ~0x00400000;
6292 }
6293 }
6294
6295 static void
6296 do_iwmmxt_tandc (str)
6297 char * str;
6298 {
6299 int reg;
6300
6301 reg = check_iwmmxt_insn (str, check_rd, 0);
6302
6303 if (reg != REG_PC && !inst.error)
6304 inst.error = _("only r15 allowed here");
6305 }
6306
6307 static void
6308 do_iwmmxt_tbcst (str)
6309 char * str;
6310 {
6311 check_iwmmxt_insn (str, check_tbcst, 0);
6312 }
6313
6314 static void
6315 do_iwmmxt_textrc (str)
6316 char * str;
6317 {
6318 unsigned long number;
6319
6320 if ((number = check_iwmmxt_insn (str, check_textrc, 7)) == (unsigned long) FAIL)
6321 return;
6322
6323 inst.instruction |= number & 0x7;
6324 }
6325
6326 static void
6327 do_iwmmxt_textrm (str)
6328 char * str;
6329 {
6330 unsigned long number;
6331
6332 if ((number = check_iwmmxt_insn (str, check_textrm, 7)) == (unsigned long) FAIL)
6333 return;
6334
6335 inst.instruction |= number & 0x7;
6336 }
6337
6338 static void
6339 do_iwmmxt_tinsr (str)
6340 char * str;
6341 {
6342 unsigned long number;
6343
6344 if ((number = check_iwmmxt_insn (str, check_tinsr, 7)) == (unsigned long) FAIL)
6345 return;
6346
6347 inst.instruction |= number & 0x7;
6348 }
6349
6350 static void
6351 do_iwmmxt_tmcr (str)
6352 char * str;
6353 {
6354 check_iwmmxt_insn (str, check_tmcr, 0);
6355 }
6356
6357 static void
6358 do_iwmmxt_tmcrr (str)
6359 char * str;
6360 {
6361 check_iwmmxt_insn (str, check_tmcrr, 0);
6362 }
6363
6364 static void
6365 do_iwmmxt_tmia (str)
6366 char * str;
6367 {
6368 check_iwmmxt_insn (str, check_tmia, 0);
6369 }
6370
6371 static void
6372 do_iwmmxt_tmovmsk (str)
6373 char * str;
6374 {
6375 check_iwmmxt_insn (str, check_tmovmsk, 0);
6376 }
6377
6378 static void
6379 do_iwmmxt_tmrc (str)
6380 char * str;
6381 {
6382 check_iwmmxt_insn (str, check_tmrc, 0);
6383 }
6384
6385 static void
6386 do_iwmmxt_tmrrc (str)
6387 char * str;
6388 {
6389 check_iwmmxt_insn (str, check_tmrrc, 0);
6390 }
6391
6392 static void
6393 do_iwmmxt_torc (str)
6394 char * str;
6395 {
6396 check_iwmmxt_insn (str, check_rd, 0);
6397 }
6398
6399 static void
6400 do_iwmmxt_waligni (str)
6401 char * str;
6402 {
6403 unsigned long number;
6404
6405 if ((number = check_iwmmxt_insn (str, check_waligni, 7)) == (unsigned long) FAIL)
6406 return;
6407
6408 inst.instruction |= ((number & 0x7) << 20);
6409 }
6410
6411 static void
6412 do_iwmmxt_wmov (str)
6413 char * str;
6414 {
6415 if (check_iwmmxt_insn (str, check_wrwr, 0) == (unsigned long) FAIL)
6416 return;
6417
6418 inst.instruction |= ((inst.instruction >> 16) & 0xf);
6419 }
6420
6421 static void
6422 do_iwmmxt_word_addr (str)
6423 char * str;
6424 {
6425 int op = (inst.instruction & 0x300) >> 8;
6426 int reg;
6427
6428 inst.instruction &= ~0x300;
6429 inst.instruction |= (op & 1) << 22 | (op & 2) << 7;
6430
6431 skip_whitespace (str);
6432
6433 if ((reg = wreg_required_here (&str, 12, IWMMXT_REG_WR_OR_WC)) == FAIL
6434 || skip_past_comma (& str) == FAIL
6435 || cp_address_required_here (& str, CP_WB_OK) == FAIL)
6436 {
6437 if (! inst.error)
6438 inst.error = BAD_ARGS;
6439 }
6440 else
6441 end_of_line (str);
6442
6443 if (wc_register (reg))
6444 {
6445 if ((inst.instruction & COND_MASK) != COND_ALWAYS)
6446 as_bad (_("conditional execution not supported with control register"));
6447 if (op != 2)
6448 as_bad (_("non-word size not supported with control register"));
6449 inst.instruction |= 0xf0000100;
6450 inst.instruction &= ~0x00400000;
6451 }
6452 }
6453
6454 static void
6455 do_iwmmxt_wrwr (str)
6456 char * str;
6457 {
6458 check_iwmmxt_insn (str, check_wrwr, 0);
6459 }
6460
6461 static void
6462 do_iwmmxt_wrwrwcg (str)
6463 char * str;
6464 {
6465 check_iwmmxt_insn (str, check_wrwrwcg, 0);
6466 }
6467
6468 static void
6469 do_iwmmxt_wrwrwr (str)
6470 char * str;
6471 {
6472 check_iwmmxt_insn (str, check_wrwrwr, 0);
6473 }
6474
6475 static void
6476 do_iwmmxt_wshufh (str)
6477 char * str;
6478 {
6479 unsigned long number;
6480
6481 if ((number = check_iwmmxt_insn (str, check_wshufh, 0xff)) == (unsigned long) FAIL)
6482 return;
6483
6484 inst.instruction |= ((number & 0xf0) << 16) | (number & 0xf);
6485 }
6486
6487 static void
6488 do_iwmmxt_wzero (str)
6489 char * str;
6490 {
6491 if (check_iwmmxt_insn (str, check_wr, 0) == (unsigned long) FAIL)
6492 return;
6493
6494 inst.instruction |= ((inst.instruction & 0xf) << 12) | ((inst.instruction & 0xf) << 16);
6495 }
6496
6497 /* Xscale multiply-accumulate (argument parse)
6498 MIAcc acc0,Rm,Rs
6499 MIAPHcc acc0,Rm,Rs
6500 MIAxycc acc0,Rm,Rs. */
6501
6502 static void
6503 do_xsc_mia (str)
6504 char * str;
6505 {
6506 int rs;
6507 int rm;
6508
6509 if (accum0_required_here (& str) == FAIL)
6510 inst.error = ERR_NO_ACCUM;
6511
6512 else if (skip_past_comma (& str) == FAIL
6513 || (rm = reg_required_here (& str, 0)) == FAIL)
6514 inst.error = BAD_ARGS;
6515
6516 else if (skip_past_comma (& str) == FAIL
6517 || (rs = reg_required_here (& str, 12)) == FAIL)
6518 inst.error = BAD_ARGS;
6519
6520 /* inst.instruction has now been zapped with both rm and rs. */
6521 else if (rm == REG_PC || rs == REG_PC)
6522 inst.error = BAD_PC; /* Undefined result if rm or rs is R15. */
6523
6524 else
6525 end_of_line (str);
6526 }
6527
6528 /* Xscale move-accumulator-register (argument parse)
6529
6530 MARcc acc0,RdLo,RdHi. */
6531
6532 static void
6533 do_xsc_mar (str)
6534 char * str;
6535 {
6536 int rdlo, rdhi;
6537
6538 if (accum0_required_here (& str) == FAIL)
6539 inst.error = ERR_NO_ACCUM;
6540
6541 else if (skip_past_comma (& str) == FAIL
6542 || (rdlo = reg_required_here (& str, 12)) == FAIL)
6543 inst.error = BAD_ARGS;
6544
6545 else if (skip_past_comma (& str) == FAIL
6546 || (rdhi = reg_required_here (& str, 16)) == FAIL)
6547 inst.error = BAD_ARGS;
6548
6549 /* inst.instruction has now been zapped with both rdlo and rdhi. */
6550 else if (rdlo == REG_PC || rdhi == REG_PC)
6551 inst.error = BAD_PC; /* Undefined result if rdlo or rdhi is R15. */
6552
6553 else
6554 end_of_line (str);
6555 }
6556
6557 /* Xscale move-register-accumulator (argument parse)
6558
6559 MRAcc RdLo,RdHi,acc0. */
6560
6561 static void
6562 do_xsc_mra (str)
6563 char * str;
6564 {
6565 int rdlo;
6566 int rdhi;
6567
6568 skip_whitespace (str);
6569
6570 if ((rdlo = reg_required_here (& str, 12)) == FAIL)
6571 inst.error = BAD_ARGS;
6572
6573 else if (skip_past_comma (& str) == FAIL
6574 || (rdhi = reg_required_here (& str, 16)) == FAIL)
6575 inst.error = BAD_ARGS;
6576
6577 else if (skip_past_comma (& str) == FAIL
6578 || accum0_required_here (& str) == FAIL)
6579 inst.error = ERR_NO_ACCUM;
6580
6581 /* inst.instruction has now been zapped with both rdlo and rdhi. */
6582 else if (rdlo == rdhi)
6583 inst.error = BAD_ARGS; /* Undefined result if 2 writes to same reg. */
6584
6585 else if (rdlo == REG_PC || rdhi == REG_PC)
6586 inst.error = BAD_PC; /* Undefined result if rdlo or rdhi is R15. */
6587 else
6588 end_of_line (str);
6589 }
6590
6591 /* ARMv5TE: Preload-Cache
6592
6593 PLD <addr_mode>
6594
6595 Syntactically, like LDR with B=1, W=0, L=1. */
6596
6597 static void
6598 do_pld (str)
6599 char * str;
6600 {
6601 int rd;
6602
6603 skip_whitespace (str);
6604
6605 if (* str != '[')
6606 {
6607 inst.error = _("'[' expected after PLD mnemonic");
6608 return;
6609 }
6610
6611 ++str;
6612 skip_whitespace (str);
6613
6614 if ((rd = reg_required_here (& str, 16)) == FAIL)
6615 return;
6616
6617 skip_whitespace (str);
6618
6619 if (*str == ']')
6620 {
6621 /* [Rn], ... ? */
6622 ++str;
6623 skip_whitespace (str);
6624
6625 /* Post-indexed addressing is not allowed with PLD. */
6626 if (skip_past_comma (&str) == SUCCESS)
6627 {
6628 inst.error
6629 = _("post-indexed expression used in preload instruction");
6630 return;
6631 }
6632 else if (*str == '!') /* [Rn]! */
6633 {
6634 inst.error = _("writeback used in preload instruction");
6635 ++str;
6636 }
6637 else /* [Rn] */
6638 inst.instruction |= INDEX_UP | PRE_INDEX;
6639 }
6640 else /* [Rn, ...] */
6641 {
6642 if (skip_past_comma (& str) == FAIL)
6643 {
6644 inst.error = _("pre-indexed expression expected");
6645 return;
6646 }
6647
6648 if (ldst_extend (&str) == FAIL)
6649 return;
6650
6651 skip_whitespace (str);
6652
6653 if (* str != ']')
6654 {
6655 inst.error = _("missing ]");
6656 return;
6657 }
6658
6659 ++ str;
6660 skip_whitespace (str);
6661
6662 if (* str == '!') /* [Rn]! */
6663 {
6664 inst.error = _("writeback used in preload instruction");
6665 ++ str;
6666 }
6667
6668 inst.instruction |= PRE_INDEX;
6669 }
6670
6671 end_of_line (str);
6672 }
6673
6674 /* ARMv5TE load-consecutive (argument parse)
6675 Mode is like LDRH.
6676
6677 LDRccD R, mode
6678 STRccD R, mode. */
6679
6680 static void
6681 do_ldrd (str)
6682 char * str;
6683 {
6684 int rd;
6685 int rn;
6686
6687 skip_whitespace (str);
6688
6689 if ((rd = reg_required_here (& str, 12)) == FAIL)
6690 {
6691 inst.error = BAD_ARGS;
6692 return;
6693 }
6694
6695 if (skip_past_comma (& str) == FAIL
6696 || (rn = ld_mode_required_here (& str)) == FAIL)
6697 {
6698 if (!inst.error)
6699 inst.error = BAD_ARGS;
6700 return;
6701 }
6702
6703 /* inst.instruction has now been zapped with Rd and the addressing mode. */
6704 if (rd & 1) /* Unpredictable result if Rd is odd. */
6705 {
6706 inst.error = _("destination register must be even");
6707 return;
6708 }
6709
6710 if (rd == REG_LR)
6711 {
6712 inst.error = _("r14 not allowed here");
6713 return;
6714 }
6715
6716 if (((rd == rn) || (rd + 1 == rn))
6717 && ((inst.instruction & WRITE_BACK)
6718 || (!(inst.instruction & PRE_INDEX))))
6719 as_warn (_("pre/post-indexing used when modified address register is destination"));
6720
6721 /* For an index-register load, the index register must not overlap the
6722 destination (even if not write-back). */
6723 if ((inst.instruction & V4_STR_BIT) == 0
6724 && (inst.instruction & HWOFFSET_IMM) == 0)
6725 {
6726 int rm = inst.instruction & 0x0000000f;
6727
6728 if (rm == rd || (rm == rd + 1))
6729 as_warn (_("ldrd destination registers must not overlap index register"));
6730 }
6731
6732 end_of_line (str);
6733 }
6734
6735 /* Returns the index into fp_values of a floating point number,
6736 or -1 if not in the table. */
6737
6738 static int
6739 my_get_float_expression (str)
6740 char ** str;
6741 {
6742 LITTLENUM_TYPE words[MAX_LITTLENUMS];
6743 char * save_in;
6744 expressionS exp;
6745 int i;
6746 int j;
6747
6748 memset (words, 0, MAX_LITTLENUMS * sizeof (LITTLENUM_TYPE));
6749
6750 /* Look for a raw floating point number. */
6751 if ((save_in = atof_ieee (*str, 'x', words)) != NULL
6752 && is_end_of_line[(unsigned char) *save_in])
6753 {
6754 for (i = 0; i < NUM_FLOAT_VALS; i++)
6755 {
6756 for (j = 0; j < MAX_LITTLENUMS; j++)
6757 {
6758 if (words[j] != fp_values[i][j])
6759 break;
6760 }
6761
6762 if (j == MAX_LITTLENUMS)
6763 {
6764 *str = save_in;
6765 return i;
6766 }
6767 }
6768 }
6769
6770 /* Try and parse a more complex expression, this will probably fail
6771 unless the code uses a floating point prefix (eg "0f"). */
6772 save_in = input_line_pointer;
6773 input_line_pointer = *str;
6774 if (expression (&exp) == absolute_section
6775 && exp.X_op == O_big
6776 && exp.X_add_number < 0)
6777 {
6778 /* FIXME: 5 = X_PRECISION, should be #define'd where we can use it.
6779 Ditto for 15. */
6780 if (gen_to_words (words, 5, (long) 15) == 0)
6781 {
6782 for (i = 0; i < NUM_FLOAT_VALS; i++)
6783 {
6784 for (j = 0; j < MAX_LITTLENUMS; j++)
6785 {
6786 if (words[j] != fp_values[i][j])
6787 break;
6788 }
6789
6790 if (j == MAX_LITTLENUMS)
6791 {
6792 *str = input_line_pointer;
6793 input_line_pointer = save_in;
6794 return i;
6795 }
6796 }
6797 }
6798 }
6799
6800 *str = input_line_pointer;
6801 input_line_pointer = save_in;
6802 return -1;
6803 }
6804
6805 /* Return TRUE if anything in the expression is a bignum. */
6806
6807 static int
6808 walk_no_bignums (sp)
6809 symbolS * sp;
6810 {
6811 if (symbol_get_value_expression (sp)->X_op == O_big)
6812 return 1;
6813
6814 if (symbol_get_value_expression (sp)->X_add_symbol)
6815 {
6816 return (walk_no_bignums (symbol_get_value_expression (sp)->X_add_symbol)
6817 || (symbol_get_value_expression (sp)->X_op_symbol
6818 && walk_no_bignums (symbol_get_value_expression (sp)->X_op_symbol)));
6819 }
6820
6821 return 0;
6822 }
6823
6824 static int in_my_get_expression = 0;
6825
6826 static int
6827 my_get_expression (ep, str)
6828 expressionS * ep;
6829 char ** str;
6830 {
6831 char * save_in;
6832 segT seg;
6833
6834 save_in = input_line_pointer;
6835 input_line_pointer = *str;
6836 in_my_get_expression = 1;
6837 seg = expression (ep);
6838 in_my_get_expression = 0;
6839
6840 if (ep->X_op == O_illegal)
6841 {
6842 /* We found a bad expression in md_operand(). */
6843 *str = input_line_pointer;
6844 input_line_pointer = save_in;
6845 return 1;
6846 }
6847
6848 #ifdef OBJ_AOUT
6849 if (seg != absolute_section
6850 && seg != text_section
6851 && seg != data_section
6852 && seg != bss_section
6853 && seg != undefined_section)
6854 {
6855 inst.error = _("bad_segment");
6856 *str = input_line_pointer;
6857 input_line_pointer = save_in;
6858 return 1;
6859 }
6860 #endif
6861
6862 /* Get rid of any bignums now, so that we don't generate an error for which
6863 we can't establish a line number later on. Big numbers are never valid
6864 in instructions, which is where this routine is always called. */
6865 if (ep->X_op == O_big
6866 || (ep->X_add_symbol
6867 && (walk_no_bignums (ep->X_add_symbol)
6868 || (ep->X_op_symbol
6869 && walk_no_bignums (ep->X_op_symbol)))))
6870 {
6871 inst.error = _("invalid constant");
6872 *str = input_line_pointer;
6873 input_line_pointer = save_in;
6874 return 1;
6875 }
6876
6877 *str = input_line_pointer;
6878 input_line_pointer = save_in;
6879 return 0;
6880 }
6881
6882 /* We handle all bad expressions here, so that we can report the faulty
6883 instruction in the error message. */
6884 void
6885 md_operand (expr)
6886 expressionS *expr;
6887 {
6888 if (in_my_get_expression)
6889 {
6890 expr->X_op = O_illegal;
6891 if (inst.error == NULL)
6892 inst.error = _("bad expression");
6893 }
6894 }
6895
6896 /* KIND indicates what kind of shifts are accepted. */
6897
6898 static int
6899 decode_shift (str, kind)
6900 char ** str;
6901 int kind;
6902 {
6903 const struct asm_shift_name * shift;
6904 char * p;
6905 char c;
6906
6907 skip_whitespace (* str);
6908
6909 for (p = * str; ISALPHA (* p); p ++)
6910 ;
6911
6912 if (p == * str)
6913 {
6914 inst.error = _("shift expression expected");
6915 return FAIL;
6916 }
6917
6918 c = * p;
6919 * p = '\0';
6920 shift = (const struct asm_shift_name *) hash_find (arm_shift_hsh, * str);
6921 * p = c;
6922
6923 if (shift == NULL)
6924 {
6925 inst.error = _("shift expression expected");
6926 return FAIL;
6927 }
6928
6929 assert (shift->properties->index == shift_properties[shift->properties->index].index);
6930
6931 if (kind == SHIFT_LSL_OR_ASR_IMMEDIATE
6932 && shift->properties->index != SHIFT_LSL
6933 && shift->properties->index != SHIFT_ASR)
6934 {
6935 inst.error = _("'LSL' or 'ASR' required");
6936 return FAIL;
6937 }
6938 else if (kind == SHIFT_LSL_IMMEDIATE
6939 && shift->properties->index != SHIFT_LSL)
6940 {
6941 inst.error = _("'LSL' required");
6942 return FAIL;
6943 }
6944 else if (kind == SHIFT_ASR_IMMEDIATE
6945 && shift->properties->index != SHIFT_ASR)
6946 {
6947 inst.error = _("'ASR' required");
6948 return FAIL;
6949 }
6950
6951 if (shift->properties->index == SHIFT_RRX)
6952 {
6953 * str = p;
6954 inst.instruction |= shift->properties->bit_field;
6955 return SUCCESS;
6956 }
6957
6958 skip_whitespace (p);
6959
6960 if (kind == NO_SHIFT_RESTRICT && reg_required_here (& p, 8) != FAIL)
6961 {
6962 inst.instruction |= shift->properties->bit_field | SHIFT_BY_REG;
6963 * str = p;
6964 return SUCCESS;
6965 }
6966 else if (! is_immediate_prefix (* p))
6967 {
6968 inst.error = (NO_SHIFT_RESTRICT
6969 ? _("shift requires register or #expression")
6970 : _("shift requires #expression"));
6971 * str = p;
6972 return FAIL;
6973 }
6974
6975 inst.error = NULL;
6976 p ++;
6977
6978 if (my_get_expression (& inst.reloc.exp, & p))
6979 return FAIL;
6980
6981 /* Validate some simple #expressions. */
6982 if (inst.reloc.exp.X_op == O_constant)
6983 {
6984 unsigned num = inst.reloc.exp.X_add_number;
6985
6986 /* Reject operations greater than 32. */
6987 if (num > 32
6988 /* Reject a shift of 0 unless the mode allows it. */
6989 || (num == 0 && shift->properties->allows_0 == 0)
6990 /* Reject a shift of 32 unless the mode allows it. */
6991 || (num == 32 && shift->properties->allows_32 == 0)
6992 )
6993 {
6994 /* As a special case we allow a shift of zero for
6995 modes that do not support it to be recoded as an
6996 logical shift left of zero (ie nothing). We warn
6997 about this though. */
6998 if (num == 0)
6999 {
7000 as_warn (_("shift of 0 ignored."));
7001 shift = & shift_names[0];
7002 assert (shift->properties->index == SHIFT_LSL);
7003 }
7004 else
7005 {
7006 inst.error = _("invalid immediate shift");
7007 return FAIL;
7008 }
7009 }
7010
7011 /* Shifts of 32 are encoded as 0, for those shifts that
7012 support it. */
7013 if (num == 32)
7014 num = 0;
7015
7016 inst.instruction |= (num << 7) | shift->properties->bit_field;
7017 }
7018 else
7019 {
7020 inst.reloc.type = BFD_RELOC_ARM_SHIFT_IMM;
7021 inst.reloc.pc_rel = 0;
7022 inst.instruction |= shift->properties->bit_field;
7023 }
7024
7025 * str = p;
7026 return SUCCESS;
7027 }
7028
7029 /* Do those data_ops which can take a negative immediate constant
7030 by altering the instruction. A bit of a hack really.
7031 MOV <-> MVN
7032 AND <-> BIC
7033 ADC <-> SBC
7034 by inverting the second operand, and
7035 ADD <-> SUB
7036 CMP <-> CMN
7037 by negating the second operand. */
7038
7039 static int
7040 negate_data_op (instruction, value)
7041 unsigned long * instruction;
7042 unsigned long value;
7043 {
7044 int op, new_inst;
7045 unsigned long negated, inverted;
7046
7047 negated = validate_immediate (-value);
7048 inverted = validate_immediate (~value);
7049
7050 op = (*instruction >> DATA_OP_SHIFT) & 0xf;
7051 switch (op)
7052 {
7053 /* First negates. */
7054 case OPCODE_SUB: /* ADD <-> SUB */
7055 new_inst = OPCODE_ADD;
7056 value = negated;
7057 break;
7058
7059 case OPCODE_ADD:
7060 new_inst = OPCODE_SUB;
7061 value = negated;
7062 break;
7063
7064 case OPCODE_CMP: /* CMP <-> CMN */
7065 new_inst = OPCODE_CMN;
7066 value = negated;
7067 break;
7068
7069 case OPCODE_CMN:
7070 new_inst = OPCODE_CMP;
7071 value = negated;
7072 break;
7073
7074 /* Now Inverted ops. */
7075 case OPCODE_MOV: /* MOV <-> MVN */
7076 new_inst = OPCODE_MVN;
7077 value = inverted;
7078 break;
7079
7080 case OPCODE_MVN:
7081 new_inst = OPCODE_MOV;
7082 value = inverted;
7083 break;
7084
7085 case OPCODE_AND: /* AND <-> BIC */
7086 new_inst = OPCODE_BIC;
7087 value = inverted;
7088 break;
7089
7090 case OPCODE_BIC:
7091 new_inst = OPCODE_AND;
7092 value = inverted;
7093 break;
7094
7095 case OPCODE_ADC: /* ADC <-> SBC */
7096 new_inst = OPCODE_SBC;
7097 value = inverted;
7098 break;
7099
7100 case OPCODE_SBC:
7101 new_inst = OPCODE_ADC;
7102 value = inverted;
7103 break;
7104
7105 /* We cannot do anything. */
7106 default:
7107 return FAIL;
7108 }
7109
7110 if (value == (unsigned) FAIL)
7111 return FAIL;
7112
7113 *instruction &= OPCODE_MASK;
7114 *instruction |= new_inst << DATA_OP_SHIFT;
7115 return value;
7116 }
7117
7118 static int
7119 data_op2 (str)
7120 char ** str;
7121 {
7122 int value;
7123 expressionS expr;
7124
7125 skip_whitespace (* str);
7126
7127 if (reg_required_here (str, 0) != FAIL)
7128 {
7129 if (skip_past_comma (str) == SUCCESS)
7130 /* Shift operation on register. */
7131 return decode_shift (str, NO_SHIFT_RESTRICT);
7132
7133 return SUCCESS;
7134 }
7135 else
7136 {
7137 /* Immediate expression. */
7138 if (is_immediate_prefix (**str))
7139 {
7140 (*str)++;
7141 inst.error = NULL;
7142
7143 if (my_get_expression (&inst.reloc.exp, str))
7144 return FAIL;
7145
7146 if (inst.reloc.exp.X_add_symbol)
7147 {
7148 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
7149 inst.reloc.pc_rel = 0;
7150 }
7151 else
7152 {
7153 if (skip_past_comma (str) == SUCCESS)
7154 {
7155 /* #x, y -- ie explicit rotation by Y. */
7156 if (my_get_expression (&expr, str))
7157 return FAIL;
7158
7159 if (expr.X_op != O_constant)
7160 {
7161 inst.error = _("constant expression expected");
7162 return FAIL;
7163 }
7164
7165 /* Rotate must be a multiple of 2. */
7166 if (((unsigned) expr.X_add_number) > 30
7167 || (expr.X_add_number & 1) != 0
7168 || ((unsigned) inst.reloc.exp.X_add_number) > 255)
7169 {
7170 inst.error = _("invalid constant");
7171 return FAIL;
7172 }
7173 inst.instruction |= INST_IMMEDIATE;
7174 inst.instruction |= inst.reloc.exp.X_add_number;
7175 inst.instruction |= expr.X_add_number << 7;
7176 return SUCCESS;
7177 }
7178
7179 /* Implicit rotation, select a suitable one. */
7180 value = validate_immediate (inst.reloc.exp.X_add_number);
7181
7182 if (value == FAIL)
7183 {
7184 /* Can't be done. Perhaps the code reads something like
7185 "add Rd, Rn, #-n", where "sub Rd, Rn, #n" would be OK. */
7186 if ((value = negate_data_op (&inst.instruction,
7187 inst.reloc.exp.X_add_number))
7188 == FAIL)
7189 {
7190 inst.error = _("invalid constant");
7191 return FAIL;
7192 }
7193 }
7194
7195 inst.instruction |= value;
7196 }
7197
7198 inst.instruction |= INST_IMMEDIATE;
7199 return SUCCESS;
7200 }
7201
7202 (*str)++;
7203 inst.error = _("register or shift expression expected");
7204 return FAIL;
7205 }
7206 }
7207
7208 static int
7209 fp_op2 (str)
7210 char ** str;
7211 {
7212 skip_whitespace (* str);
7213
7214 if (fp_reg_required_here (str, 0) != FAIL)
7215 return SUCCESS;
7216 else
7217 {
7218 /* Immediate expression. */
7219 if (*((*str)++) == '#')
7220 {
7221 int i;
7222
7223 inst.error = NULL;
7224
7225 skip_whitespace (* str);
7226
7227 /* First try and match exact strings, this is to guarantee
7228 that some formats will work even for cross assembly. */
7229
7230 for (i = 0; fp_const[i]; i++)
7231 {
7232 if (strncmp (*str, fp_const[i], strlen (fp_const[i])) == 0)
7233 {
7234 char *start = *str;
7235
7236 *str += strlen (fp_const[i]);
7237 if (is_end_of_line[(unsigned char) **str])
7238 {
7239 inst.instruction |= i + 8;
7240 return SUCCESS;
7241 }
7242 *str = start;
7243 }
7244 }
7245
7246 /* Just because we didn't get a match doesn't mean that the
7247 constant isn't valid, just that it is in a format that we
7248 don't automatically recognize. Try parsing it with
7249 the standard expression routines. */
7250 if ((i = my_get_float_expression (str)) >= 0)
7251 {
7252 inst.instruction |= i + 8;
7253 return SUCCESS;
7254 }
7255
7256 inst.error = _("invalid floating point immediate expression");
7257 return FAIL;
7258 }
7259 inst.error =
7260 _("floating point register or immediate expression expected");
7261 return FAIL;
7262 }
7263 }
7264
7265 static void
7266 do_arit (str)
7267 char * str;
7268 {
7269 skip_whitespace (str);
7270
7271 if (reg_required_here (&str, 12) == FAIL
7272 || skip_past_comma (&str) == FAIL
7273 || reg_required_here (&str, 16) == FAIL
7274 || skip_past_comma (&str) == FAIL
7275 || data_op2 (&str) == FAIL)
7276 {
7277 if (!inst.error)
7278 inst.error = BAD_ARGS;
7279 return;
7280 }
7281
7282 end_of_line (str);
7283 }
7284
7285 static void
7286 do_adr (str)
7287 char * str;
7288 {
7289 /* This is a pseudo-op of the form "adr rd, label" to be converted
7290 into a relative address of the form "add rd, pc, #label-.-8". */
7291 skip_whitespace (str);
7292
7293 if (reg_required_here (&str, 12) == FAIL
7294 || skip_past_comma (&str) == FAIL
7295 || my_get_expression (&inst.reloc.exp, &str))
7296 {
7297 if (!inst.error)
7298 inst.error = BAD_ARGS;
7299 return;
7300 }
7301
7302 /* Frag hacking will turn this into a sub instruction if the offset turns
7303 out to be negative. */
7304 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
7305 #ifndef TE_WINCE
7306 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust. */
7307 #endif
7308 inst.reloc.pc_rel = 1;
7309
7310 end_of_line (str);
7311 }
7312
7313 static void
7314 do_adrl (str)
7315 char * str;
7316 {
7317 /* This is a pseudo-op of the form "adrl rd, label" to be converted
7318 into a relative address of the form:
7319 add rd, pc, #low(label-.-8)"
7320 add rd, rd, #high(label-.-8)" */
7321
7322 skip_whitespace (str);
7323
7324 if (reg_required_here (&str, 12) == FAIL
7325 || skip_past_comma (&str) == FAIL
7326 || my_get_expression (&inst.reloc.exp, &str))
7327 {
7328 if (!inst.error)
7329 inst.error = BAD_ARGS;
7330
7331 return;
7332 }
7333
7334 end_of_line (str);
7335 /* Frag hacking will turn this into a sub instruction if the offset turns
7336 out to be negative. */
7337 inst.reloc.type = BFD_RELOC_ARM_ADRL_IMMEDIATE;
7338 #ifndef TE_WINCE
7339 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust */
7340 #endif
7341 inst.reloc.pc_rel = 1;
7342 inst.size = INSN_SIZE * 2;
7343 }
7344
7345 static void
7346 do_cmp (str)
7347 char * str;
7348 {
7349 skip_whitespace (str);
7350
7351 if (reg_required_here (&str, 16) == FAIL)
7352 {
7353 if (!inst.error)
7354 inst.error = BAD_ARGS;
7355 return;
7356 }
7357
7358 if (skip_past_comma (&str) == FAIL
7359 || data_op2 (&str) == FAIL)
7360 {
7361 if (!inst.error)
7362 inst.error = BAD_ARGS;
7363 return;
7364 }
7365
7366 end_of_line (str);
7367 }
7368
7369 static void
7370 do_mov (str)
7371 char * str;
7372 {
7373 skip_whitespace (str);
7374
7375 if (reg_required_here (&str, 12) == FAIL)
7376 {
7377 if (!inst.error)
7378 inst.error = BAD_ARGS;
7379 return;
7380 }
7381
7382 if (skip_past_comma (&str) == FAIL
7383 || data_op2 (&str) == FAIL)
7384 {
7385 if (!inst.error)
7386 inst.error = BAD_ARGS;
7387 return;
7388 }
7389
7390 end_of_line (str);
7391 }
7392
7393 static int
7394 ldst_extend (str)
7395 char ** str;
7396 {
7397 int add = INDEX_UP;
7398
7399 switch (**str)
7400 {
7401 case '#':
7402 case '$':
7403 (*str)++;
7404 if (my_get_expression (& inst.reloc.exp, str))
7405 return FAIL;
7406
7407 if (inst.reloc.exp.X_op == O_constant)
7408 {
7409 int value = inst.reloc.exp.X_add_number;
7410
7411 if (value < -4095 || value > 4095)
7412 {
7413 inst.error = _("address offset too large");
7414 return FAIL;
7415 }
7416
7417 if (value < 0)
7418 {
7419 value = -value;
7420 add = 0;
7421 }
7422
7423 inst.instruction |= add | value;
7424 }
7425 else
7426 {
7427 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
7428 inst.reloc.pc_rel = 0;
7429 }
7430 return SUCCESS;
7431
7432 case '-':
7433 add = 0;
7434 /* Fall through. */
7435
7436 case '+':
7437 (*str)++;
7438 /* Fall through. */
7439
7440 default:
7441 if (reg_required_here (str, 0) == FAIL)
7442 return FAIL;
7443
7444 inst.instruction |= add | OFFSET_REG;
7445 if (skip_past_comma (str) == SUCCESS)
7446 return decode_shift (str, SHIFT_IMMEDIATE);
7447
7448 return SUCCESS;
7449 }
7450 }
7451
7452 static void
7453 do_ldst (str)
7454 char * str;
7455 {
7456 int pre_inc = 0;
7457 int conflict_reg;
7458 int value;
7459
7460 skip_whitespace (str);
7461
7462 if ((conflict_reg = reg_required_here (&str, 12)) == FAIL)
7463 {
7464 if (!inst.error)
7465 inst.error = BAD_ARGS;
7466 return;
7467 }
7468
7469 if (skip_past_comma (&str) == FAIL)
7470 {
7471 inst.error = _("address expected");
7472 return;
7473 }
7474
7475 if (*str == '[')
7476 {
7477 int reg;
7478
7479 str++;
7480
7481 skip_whitespace (str);
7482
7483 if ((reg = reg_required_here (&str, 16)) == FAIL)
7484 return;
7485
7486 /* Conflicts can occur on stores as well as loads. */
7487 conflict_reg = (conflict_reg == reg);
7488
7489 skip_whitespace (str);
7490
7491 if (*str == ']')
7492 {
7493 str ++;
7494
7495 if (skip_past_comma (&str) == SUCCESS)
7496 {
7497 /* [Rn],... (post inc) */
7498 if (ldst_extend (&str) == FAIL)
7499 return;
7500 if (conflict_reg)
7501 as_warn (_("%s register same as write-back base"),
7502 ((inst.instruction & LOAD_BIT)
7503 ? _("destination") : _("source")));
7504 }
7505 else
7506 {
7507 /* [Rn] */
7508 skip_whitespace (str);
7509
7510 if (*str == '!')
7511 {
7512 if (conflict_reg)
7513 as_warn (_("%s register same as write-back base"),
7514 ((inst.instruction & LOAD_BIT)
7515 ? _("destination") : _("source")));
7516 str++;
7517 inst.instruction |= WRITE_BACK;
7518 }
7519
7520 inst.instruction |= INDEX_UP;
7521 pre_inc = 1;
7522 }
7523 }
7524 else
7525 {
7526 /* [Rn,...] */
7527 if (skip_past_comma (&str) == FAIL)
7528 {
7529 inst.error = _("pre-indexed expression expected");
7530 return;
7531 }
7532
7533 pre_inc = 1;
7534 if (ldst_extend (&str) == FAIL)
7535 return;
7536
7537 skip_whitespace (str);
7538
7539 if (*str++ != ']')
7540 {
7541 inst.error = _("missing ]");
7542 return;
7543 }
7544
7545 skip_whitespace (str);
7546
7547 if (*str == '!')
7548 {
7549 if (conflict_reg)
7550 as_warn (_("%s register same as write-back base"),
7551 ((inst.instruction & LOAD_BIT)
7552 ? _("destination") : _("source")));
7553 str++;
7554 inst.instruction |= WRITE_BACK;
7555 }
7556 }
7557 }
7558 else if (*str == '=')
7559 {
7560 if ((inst.instruction & LOAD_BIT) == 0)
7561 {
7562 inst.error = _("invalid pseudo operation");
7563 return;
7564 }
7565
7566 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
7567 str++;
7568
7569 skip_whitespace (str);
7570
7571 if (my_get_expression (&inst.reloc.exp, &str))
7572 return;
7573
7574 if (inst.reloc.exp.X_op != O_constant
7575 && inst.reloc.exp.X_op != O_symbol)
7576 {
7577 inst.error = _("constant expression expected");
7578 return;
7579 }
7580
7581 if (inst.reloc.exp.X_op == O_constant)
7582 {
7583 value = validate_immediate (inst.reloc.exp.X_add_number);
7584
7585 if (value != FAIL)
7586 {
7587 /* This can be done with a mov instruction. */
7588 inst.instruction &= LITERAL_MASK;
7589 inst.instruction |= (INST_IMMEDIATE
7590 | (OPCODE_MOV << DATA_OP_SHIFT));
7591 inst.instruction |= value & 0xfff;
7592 end_of_line (str);
7593 return;
7594 }
7595
7596 value = validate_immediate (~inst.reloc.exp.X_add_number);
7597
7598 if (value != FAIL)
7599 {
7600 /* This can be done with a mvn instruction. */
7601 inst.instruction &= LITERAL_MASK;
7602 inst.instruction |= (INST_IMMEDIATE
7603 | (OPCODE_MVN << DATA_OP_SHIFT));
7604 inst.instruction |= value & 0xfff;
7605 end_of_line (str);
7606 return;
7607 }
7608 }
7609
7610 /* Insert into literal pool. */
7611 if (add_to_lit_pool () == FAIL)
7612 {
7613 if (!inst.error)
7614 inst.error = _("literal pool insertion failed");
7615 return;
7616 }
7617
7618 /* Change the instruction exp to point to the pool. */
7619 inst.reloc.type = BFD_RELOC_ARM_LITERAL;
7620 inst.reloc.pc_rel = 1;
7621 inst.instruction |= (REG_PC << 16);
7622 pre_inc = 1;
7623 }
7624 else
7625 {
7626 if (my_get_expression (&inst.reloc.exp, &str))
7627 return;
7628
7629 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
7630 #ifndef TE_WINCE
7631 /* PC rel adjust. */
7632 inst.reloc.exp.X_add_number -= 8;
7633 #endif
7634 inst.reloc.pc_rel = 1;
7635 inst.instruction |= (REG_PC << 16);
7636 pre_inc = 1;
7637 }
7638
7639 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
7640 end_of_line (str);
7641 }
7642
7643 static void
7644 do_ldstt (str)
7645 char * str;
7646 {
7647 int conflict_reg;
7648
7649 skip_whitespace (str);
7650
7651 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
7652 {
7653 if (!inst.error)
7654 inst.error = BAD_ARGS;
7655 return;
7656 }
7657
7658 if (skip_past_comma (& str) == FAIL)
7659 {
7660 inst.error = _("address expected");
7661 return;
7662 }
7663
7664 if (*str == '[')
7665 {
7666 int reg;
7667
7668 str++;
7669
7670 skip_whitespace (str);
7671
7672 if ((reg = reg_required_here (&str, 16)) == FAIL)
7673 return;
7674
7675 /* ldrt/strt always use post-indexed addressing, so if the base is
7676 the same as Rd, we warn. */
7677 if (conflict_reg == reg)
7678 as_warn (_("%s register same as write-back base"),
7679 ((inst.instruction & LOAD_BIT)
7680 ? _("destination") : _("source")));
7681
7682 skip_whitespace (str);
7683
7684 if (*str == ']')
7685 {
7686 str ++;
7687
7688 if (skip_past_comma (&str) == SUCCESS)
7689 {
7690 /* [Rn],... (post inc) */
7691 if (ldst_extend (&str) == FAIL)
7692 return;
7693 }
7694 else
7695 {
7696 /* [Rn] */
7697 skip_whitespace (str);
7698
7699 /* Skip a write-back '!'. */
7700 if (*str == '!')
7701 str++;
7702
7703 inst.instruction |= INDEX_UP;
7704 }
7705 }
7706 else
7707 {
7708 inst.error = _("post-indexed expression expected");
7709 return;
7710 }
7711 }
7712 else
7713 {
7714 inst.error = _("post-indexed expression expected");
7715 return;
7716 }
7717
7718 end_of_line (str);
7719 }
7720
7721 static int
7722 ldst_extend_v4 (str)
7723 char ** str;
7724 {
7725 int add = INDEX_UP;
7726
7727 switch (**str)
7728 {
7729 case '#':
7730 case '$':
7731 (*str)++;
7732 if (my_get_expression (& inst.reloc.exp, str))
7733 return FAIL;
7734
7735 if (inst.reloc.exp.X_op == O_constant)
7736 {
7737 int value = inst.reloc.exp.X_add_number;
7738
7739 if (value < -255 || value > 255)
7740 {
7741 inst.error = _("address offset too large");
7742 return FAIL;
7743 }
7744
7745 if (value < 0)
7746 {
7747 value = -value;
7748 add = 0;
7749 }
7750
7751 /* Halfword and signextension instructions have the
7752 immediate value split across bits 11..8 and bits 3..0. */
7753 inst.instruction |= (add | HWOFFSET_IMM
7754 | ((value >> 4) << 8) | (value & 0xF));
7755 }
7756 else
7757 {
7758 inst.instruction |= HWOFFSET_IMM;
7759 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
7760 inst.reloc.pc_rel = 0;
7761 }
7762 return SUCCESS;
7763
7764 case '-':
7765 add = 0;
7766 /* Fall through. */
7767
7768 case '+':
7769 (*str)++;
7770 /* Fall through. */
7771
7772 default:
7773 if (reg_required_here (str, 0) == FAIL)
7774 return FAIL;
7775
7776 inst.instruction |= add;
7777 return SUCCESS;
7778 }
7779 }
7780
7781 /* Halfword and signed-byte load/store operations. */
7782 static void
7783 do_ldstv4 (str)
7784 char * str;
7785 {
7786 int pre_inc = 0;
7787 int conflict_reg;
7788 int value;
7789
7790 skip_whitespace (str);
7791
7792 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
7793 {
7794 if (!inst.error)
7795 inst.error = BAD_ARGS;
7796 return;
7797 }
7798
7799 if (skip_past_comma (& str) == FAIL)
7800 {
7801 inst.error = _("address expected");
7802 return;
7803 }
7804
7805 if (*str == '[')
7806 {
7807 int reg;
7808
7809 str++;
7810
7811 skip_whitespace (str);
7812
7813 if ((reg = reg_required_here (&str, 16)) == FAIL)
7814 return;
7815
7816 /* Conflicts can occur on stores as well as loads. */
7817 conflict_reg = (conflict_reg == reg);
7818
7819 skip_whitespace (str);
7820
7821 if (*str == ']')
7822 {
7823 str ++;
7824
7825 if (skip_past_comma (&str) == SUCCESS)
7826 {
7827 /* [Rn],... (post inc) */
7828 if (ldst_extend_v4 (&str) == FAIL)
7829 return;
7830 if (conflict_reg)
7831 as_warn (_("%s register same as write-back base"),
7832 ((inst.instruction & LOAD_BIT)
7833 ? _("destination") : _("source")));
7834 }
7835 else
7836 {
7837 /* [Rn] */
7838 inst.instruction |= HWOFFSET_IMM;
7839
7840 skip_whitespace (str);
7841
7842 if (*str == '!')
7843 {
7844 if (conflict_reg)
7845 as_warn (_("%s register same as write-back base"),
7846 ((inst.instruction & LOAD_BIT)
7847 ? _("destination") : _("source")));
7848 str++;
7849 inst.instruction |= WRITE_BACK;
7850 }
7851
7852 inst.instruction |= INDEX_UP;
7853 pre_inc = 1;
7854 }
7855 }
7856 else
7857 {
7858 /* [Rn,...] */
7859 if (skip_past_comma (&str) == FAIL)
7860 {
7861 inst.error = _("pre-indexed expression expected");
7862 return;
7863 }
7864
7865 pre_inc = 1;
7866 if (ldst_extend_v4 (&str) == FAIL)
7867 return;
7868
7869 skip_whitespace (str);
7870
7871 if (*str++ != ']')
7872 {
7873 inst.error = _("missing ]");
7874 return;
7875 }
7876
7877 skip_whitespace (str);
7878
7879 if (*str == '!')
7880 {
7881 if (conflict_reg)
7882 as_warn (_("%s register same as write-back base"),
7883 ((inst.instruction & LOAD_BIT)
7884 ? _("destination") : _("source")));
7885 str++;
7886 inst.instruction |= WRITE_BACK;
7887 }
7888 }
7889 }
7890 else if (*str == '=')
7891 {
7892 if ((inst.instruction & LOAD_BIT) == 0)
7893 {
7894 inst.error = _("invalid pseudo operation");
7895 return;
7896 }
7897
7898 /* XXX Does this work correctly for half-word/byte ops? */
7899 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
7900 str++;
7901
7902 skip_whitespace (str);
7903
7904 if (my_get_expression (&inst.reloc.exp, &str))
7905 return;
7906
7907 if (inst.reloc.exp.X_op != O_constant
7908 && inst.reloc.exp.X_op != O_symbol)
7909 {
7910 inst.error = _("constant expression expected");
7911 return;
7912 }
7913
7914 if (inst.reloc.exp.X_op == O_constant)
7915 {
7916 value = validate_immediate (inst.reloc.exp.X_add_number);
7917
7918 if (value != FAIL)
7919 {
7920 /* This can be done with a mov instruction. */
7921 inst.instruction &= LITERAL_MASK;
7922 inst.instruction |= INST_IMMEDIATE | (OPCODE_MOV << DATA_OP_SHIFT);
7923 inst.instruction |= value & 0xfff;
7924 end_of_line (str);
7925 return;
7926 }
7927
7928 value = validate_immediate (~ inst.reloc.exp.X_add_number);
7929
7930 if (value != FAIL)
7931 {
7932 /* This can be done with a mvn instruction. */
7933 inst.instruction &= LITERAL_MASK;
7934 inst.instruction |= INST_IMMEDIATE | (OPCODE_MVN << DATA_OP_SHIFT);
7935 inst.instruction |= value & 0xfff;
7936 end_of_line (str);
7937 return;
7938 }
7939 }
7940
7941 /* Insert into literal pool. */
7942 if (add_to_lit_pool () == FAIL)
7943 {
7944 if (!inst.error)
7945 inst.error = _("literal pool insertion failed");
7946 return;
7947 }
7948
7949 /* Change the instruction exp to point to the pool. */
7950 inst.instruction |= HWOFFSET_IMM;
7951 inst.reloc.type = BFD_RELOC_ARM_HWLITERAL;
7952 inst.reloc.pc_rel = 1;
7953 inst.instruction |= (REG_PC << 16);
7954 pre_inc = 1;
7955 }
7956 else
7957 {
7958 if (my_get_expression (&inst.reloc.exp, &str))
7959 return;
7960
7961 inst.instruction |= HWOFFSET_IMM;
7962 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
7963 #ifndef TE_WINCE
7964 /* PC rel adjust. */
7965 inst.reloc.exp.X_add_number -= 8;
7966 #endif
7967 inst.reloc.pc_rel = 1;
7968 inst.instruction |= (REG_PC << 16);
7969 pre_inc = 1;
7970 }
7971
7972 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
7973 end_of_line (str);
7974 }
7975
7976 static long
7977 reg_list (strp)
7978 char ** strp;
7979 {
7980 char * str = * strp;
7981 long range = 0;
7982 int another_range;
7983
7984 /* We come back here if we get ranges concatenated by '+' or '|'. */
7985 do
7986 {
7987 another_range = 0;
7988
7989 if (*str == '{')
7990 {
7991 int in_range = 0;
7992 int cur_reg = -1;
7993
7994 str++;
7995 do
7996 {
7997 int reg;
7998
7999 skip_whitespace (str);
8000
8001 if ((reg = reg_required_here (& str, -1)) == FAIL)
8002 return FAIL;
8003
8004 if (in_range)
8005 {
8006 int i;
8007
8008 if (reg <= cur_reg)
8009 {
8010 inst.error = _("bad range in register list");
8011 return FAIL;
8012 }
8013
8014 for (i = cur_reg + 1; i < reg; i++)
8015 {
8016 if (range & (1 << i))
8017 as_tsktsk
8018 (_("Warning: duplicated register (r%d) in register list"),
8019 i);
8020 else
8021 range |= 1 << i;
8022 }
8023 in_range = 0;
8024 }
8025
8026 if (range & (1 << reg))
8027 as_tsktsk (_("Warning: duplicated register (r%d) in register list"),
8028 reg);
8029 else if (reg <= cur_reg)
8030 as_tsktsk (_("Warning: register range not in ascending order"));
8031
8032 range |= 1 << reg;
8033 cur_reg = reg;
8034 }
8035 while (skip_past_comma (&str) != FAIL
8036 || (in_range = 1, *str++ == '-'));
8037 str--;
8038 skip_whitespace (str);
8039
8040 if (*str++ != '}')
8041 {
8042 inst.error = _("missing `}'");
8043 return FAIL;
8044 }
8045 }
8046 else
8047 {
8048 expressionS expr;
8049
8050 if (my_get_expression (&expr, &str))
8051 return FAIL;
8052
8053 if (expr.X_op == O_constant)
8054 {
8055 if (expr.X_add_number
8056 != (expr.X_add_number & 0x0000ffff))
8057 {
8058 inst.error = _("invalid register mask");
8059 return FAIL;
8060 }
8061
8062 if ((range & expr.X_add_number) != 0)
8063 {
8064 int regno = range & expr.X_add_number;
8065
8066 regno &= -regno;
8067 regno = (1 << regno) - 1;
8068 as_tsktsk
8069 (_("Warning: duplicated register (r%d) in register list"),
8070 regno);
8071 }
8072
8073 range |= expr.X_add_number;
8074 }
8075 else
8076 {
8077 if (inst.reloc.type != 0)
8078 {
8079 inst.error = _("expression too complex");
8080 return FAIL;
8081 }
8082
8083 memcpy (&inst.reloc.exp, &expr, sizeof (expressionS));
8084 inst.reloc.type = BFD_RELOC_ARM_MULTI;
8085 inst.reloc.pc_rel = 0;
8086 }
8087 }
8088
8089 skip_whitespace (str);
8090
8091 if (*str == '|' || *str == '+')
8092 {
8093 str++;
8094 another_range = 1;
8095 }
8096 }
8097 while (another_range);
8098
8099 *strp = str;
8100 return range;
8101 }
8102
8103 static void
8104 do_ldmstm (str)
8105 char * str;
8106 {
8107 int base_reg;
8108 long range;
8109
8110 skip_whitespace (str);
8111
8112 if ((base_reg = reg_required_here (&str, 16)) == FAIL)
8113 return;
8114
8115 if (base_reg == REG_PC)
8116 {
8117 inst.error = _("r15 not allowed as base register");
8118 return;
8119 }
8120
8121 skip_whitespace (str);
8122
8123 if (*str == '!')
8124 {
8125 inst.instruction |= WRITE_BACK;
8126 str++;
8127 }
8128
8129 if (skip_past_comma (&str) == FAIL
8130 || (range = reg_list (&str)) == FAIL)
8131 {
8132 if (! inst.error)
8133 inst.error = BAD_ARGS;
8134 return;
8135 }
8136
8137 if (*str == '^')
8138 {
8139 str++;
8140 inst.instruction |= LDM_TYPE_2_OR_3;
8141 }
8142
8143 if (inst.instruction & WRITE_BACK)
8144 {
8145 /* Check for unpredictable uses of writeback. */
8146 if (inst.instruction & LOAD_BIT)
8147 {
8148 /* Not allowed in LDM type 2. */
8149 if ((inst.instruction & LDM_TYPE_2_OR_3)
8150 && ((range & (1 << REG_PC)) == 0))
8151 as_warn (_("writeback of base register is UNPREDICTABLE"));
8152 /* Only allowed if base reg not in list for other types. */
8153 else if (range & (1 << base_reg))
8154 as_warn (_("writeback of base register when in register list is UNPREDICTABLE"));
8155 }
8156 else /* STM. */
8157 {
8158 /* Not allowed for type 2. */
8159 if (inst.instruction & LDM_TYPE_2_OR_3)
8160 as_warn (_("writeback of base register is UNPREDICTABLE"));
8161 /* Only allowed if base reg not in list, or first in list. */
8162 else if ((range & (1 << base_reg))
8163 && (range & ((1 << base_reg) - 1)))
8164 as_warn (_("if writeback register is in list, it must be the lowest reg in the list"));
8165 }
8166 }
8167
8168 inst.instruction |= range;
8169 end_of_line (str);
8170 }
8171
8172 static void
8173 do_swi (str)
8174 char * str;
8175 {
8176 skip_whitespace (str);
8177
8178 /* Allow optional leading '#'. */
8179 if (is_immediate_prefix (*str))
8180 str++;
8181
8182 if (my_get_expression (& inst.reloc.exp, & str))
8183 return;
8184
8185 inst.reloc.type = BFD_RELOC_ARM_SWI;
8186 inst.reloc.pc_rel = 0;
8187 end_of_line (str);
8188 }
8189
8190 static void
8191 do_swap (str)
8192 char * str;
8193 {
8194 int reg;
8195
8196 skip_whitespace (str);
8197
8198 if ((reg = reg_required_here (&str, 12)) == FAIL)
8199 return;
8200
8201 if (reg == REG_PC)
8202 {
8203 inst.error = _("r15 not allowed in swap");
8204 return;
8205 }
8206
8207 if (skip_past_comma (&str) == FAIL
8208 || (reg = reg_required_here (&str, 0)) == FAIL)
8209 {
8210 if (!inst.error)
8211 inst.error = BAD_ARGS;
8212 return;
8213 }
8214
8215 if (reg == REG_PC)
8216 {
8217 inst.error = _("r15 not allowed in swap");
8218 return;
8219 }
8220
8221 if (skip_past_comma (&str) == FAIL
8222 || *str++ != '[')
8223 {
8224 inst.error = BAD_ARGS;
8225 return;
8226 }
8227
8228 skip_whitespace (str);
8229
8230 if ((reg = reg_required_here (&str, 16)) == FAIL)
8231 return;
8232
8233 if (reg == REG_PC)
8234 {
8235 inst.error = BAD_PC;
8236 return;
8237 }
8238
8239 skip_whitespace (str);
8240
8241 if (*str++ != ']')
8242 {
8243 inst.error = _("missing ]");
8244 return;
8245 }
8246
8247 end_of_line (str);
8248 }
8249
8250 static void
8251 do_branch (str)
8252 char * str;
8253 {
8254 if (my_get_expression (&inst.reloc.exp, &str))
8255 return;
8256
8257 #ifdef OBJ_ELF
8258 {
8259 char * save_in;
8260
8261 /* ScottB: February 5, 1998 - Check to see of PLT32 reloc
8262 required for the instruction. */
8263
8264 /* arm_parse_reloc () works on input_line_pointer.
8265 We actually want to parse the operands to the branch instruction
8266 passed in 'str'. Save the input pointer and restore it later. */
8267 save_in = input_line_pointer;
8268 input_line_pointer = str;
8269 if (inst.reloc.exp.X_op == O_symbol
8270 && *str == '('
8271 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
8272 {
8273 inst.reloc.type = BFD_RELOC_ARM_PLT32;
8274 inst.reloc.pc_rel = 0;
8275 /* Modify str to point to after parsed operands, otherwise
8276 end_of_line() will complain about the (PLT) left in str. */
8277 str = input_line_pointer;
8278 }
8279 else
8280 {
8281 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
8282 inst.reloc.pc_rel = 1;
8283 }
8284 input_line_pointer = save_in;
8285 }
8286 #else
8287 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
8288 inst.reloc.pc_rel = 1;
8289 #endif /* OBJ_ELF */
8290
8291 end_of_line (str);
8292 }
8293
8294 static void
8295 do_bx (str)
8296 char * str;
8297 {
8298 int reg;
8299
8300 skip_whitespace (str);
8301
8302 if ((reg = reg_required_here (&str, 0)) == FAIL)
8303 {
8304 inst.error = BAD_ARGS;
8305 return;
8306 }
8307
8308 /* Note - it is not illegal to do a "bx pc". Useless, but not illegal. */
8309 if (reg == REG_PC)
8310 as_tsktsk (_("use of r15 in bx in ARM mode is not really useful"));
8311
8312 end_of_line (str);
8313 }
8314
8315 static void
8316 do_cdp (str)
8317 char * str;
8318 {
8319 /* Co-processor data operation.
8320 Format: CDP{cond} CP#,<expr>,CRd,CRn,CRm{,<expr>} */
8321 skip_whitespace (str);
8322
8323 if (co_proc_number (&str) == FAIL)
8324 {
8325 if (!inst.error)
8326 inst.error = BAD_ARGS;
8327 return;
8328 }
8329
8330 if (skip_past_comma (&str) == FAIL
8331 || cp_opc_expr (&str, 20,4) == FAIL)
8332 {
8333 if (!inst.error)
8334 inst.error = BAD_ARGS;
8335 return;
8336 }
8337
8338 if (skip_past_comma (&str) == FAIL
8339 || cp_reg_required_here (&str, 12) == FAIL)
8340 {
8341 if (!inst.error)
8342 inst.error = BAD_ARGS;
8343 return;
8344 }
8345
8346 if (skip_past_comma (&str) == FAIL
8347 || cp_reg_required_here (&str, 16) == FAIL)
8348 {
8349 if (!inst.error)
8350 inst.error = BAD_ARGS;
8351 return;
8352 }
8353
8354 if (skip_past_comma (&str) == FAIL
8355 || cp_reg_required_here (&str, 0) == FAIL)
8356 {
8357 if (!inst.error)
8358 inst.error = BAD_ARGS;
8359 return;
8360 }
8361
8362 if (skip_past_comma (&str) == SUCCESS)
8363 {
8364 if (cp_opc_expr (&str, 5, 3) == FAIL)
8365 {
8366 if (!inst.error)
8367 inst.error = BAD_ARGS;
8368 return;
8369 }
8370 }
8371
8372 end_of_line (str);
8373 }
8374
8375 static void
8376 do_lstc (str)
8377 char * str;
8378 {
8379 /* Co-processor register load/store.
8380 Format: <LDC|STC{cond}[L] CP#,CRd,<address> */
8381
8382 skip_whitespace (str);
8383
8384 if (co_proc_number (&str) == FAIL)
8385 {
8386 if (!inst.error)
8387 inst.error = BAD_ARGS;
8388 return;
8389 }
8390
8391 if (skip_past_comma (&str) == FAIL
8392 || cp_reg_required_here (&str, 12) == FAIL)
8393 {
8394 if (!inst.error)
8395 inst.error = BAD_ARGS;
8396 return;
8397 }
8398
8399 if (skip_past_comma (&str) == FAIL
8400 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
8401 {
8402 if (! inst.error)
8403 inst.error = BAD_ARGS;
8404 return;
8405 }
8406
8407 end_of_line (str);
8408 }
8409
8410 static void
8411 do_co_reg (str)
8412 char * str;
8413 {
8414 /* Co-processor register transfer.
8415 Format: <MCR|MRC>{cond} CP#,<expr1>,Rd,CRn,CRm{,<expr2>} */
8416
8417 skip_whitespace (str);
8418
8419 if (co_proc_number (&str) == FAIL)
8420 {
8421 if (!inst.error)
8422 inst.error = BAD_ARGS;
8423 return;
8424 }
8425
8426 if (skip_past_comma (&str) == FAIL
8427 || cp_opc_expr (&str, 21, 3) == FAIL)
8428 {
8429 if (!inst.error)
8430 inst.error = BAD_ARGS;
8431 return;
8432 }
8433
8434 if (skip_past_comma (&str) == FAIL
8435 || reg_required_here (&str, 12) == FAIL)
8436 {
8437 if (!inst.error)
8438 inst.error = BAD_ARGS;
8439 return;
8440 }
8441
8442 if (skip_past_comma (&str) == FAIL
8443 || cp_reg_required_here (&str, 16) == FAIL)
8444 {
8445 if (!inst.error)
8446 inst.error = BAD_ARGS;
8447 return;
8448 }
8449
8450 if (skip_past_comma (&str) == FAIL
8451 || cp_reg_required_here (&str, 0) == FAIL)
8452 {
8453 if (!inst.error)
8454 inst.error = BAD_ARGS;
8455 return;
8456 }
8457
8458 if (skip_past_comma (&str) == SUCCESS)
8459 {
8460 if (cp_opc_expr (&str, 5, 3) == FAIL)
8461 {
8462 if (!inst.error)
8463 inst.error = BAD_ARGS;
8464 return;
8465 }
8466 }
8467
8468 end_of_line (str);
8469 }
8470
8471 static void
8472 do_fpa_ctrl (str)
8473 char * str;
8474 {
8475 /* FP control registers.
8476 Format: <WFS|RFS|WFC|RFC>{cond} Rn */
8477
8478 skip_whitespace (str);
8479
8480 if (reg_required_here (&str, 12) == FAIL)
8481 {
8482 if (!inst.error)
8483 inst.error = BAD_ARGS;
8484 return;
8485 }
8486
8487 end_of_line (str);
8488 }
8489
8490 static void
8491 do_fpa_ldst (str)
8492 char * str;
8493 {
8494 skip_whitespace (str);
8495
8496 if (fp_reg_required_here (&str, 12) == FAIL)
8497 {
8498 if (!inst.error)
8499 inst.error = BAD_ARGS;
8500 return;
8501 }
8502
8503 if (skip_past_comma (&str) == FAIL
8504 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
8505 {
8506 if (!inst.error)
8507 inst.error = BAD_ARGS;
8508 return;
8509 }
8510
8511 end_of_line (str);
8512 }
8513
8514 static void
8515 do_fpa_ldmstm (str)
8516 char * str;
8517 {
8518 int num_regs;
8519
8520 skip_whitespace (str);
8521
8522 if (fp_reg_required_here (&str, 12) == FAIL)
8523 {
8524 if (! inst.error)
8525 inst.error = BAD_ARGS;
8526 return;
8527 }
8528
8529 /* Get Number of registers to transfer. */
8530 if (skip_past_comma (&str) == FAIL
8531 || my_get_expression (&inst.reloc.exp, &str))
8532 {
8533 if (! inst.error)
8534 inst.error = _("constant expression expected");
8535 return;
8536 }
8537
8538 if (inst.reloc.exp.X_op != O_constant)
8539 {
8540 inst.error = _("constant value required for number of registers");
8541 return;
8542 }
8543
8544 num_regs = inst.reloc.exp.X_add_number;
8545
8546 if (num_regs < 1 || num_regs > 4)
8547 {
8548 inst.error = _("number of registers must be in the range [1:4]");
8549 return;
8550 }
8551
8552 switch (num_regs)
8553 {
8554 case 1:
8555 inst.instruction |= CP_T_X;
8556 break;
8557 case 2:
8558 inst.instruction |= CP_T_Y;
8559 break;
8560 case 3:
8561 inst.instruction |= CP_T_Y | CP_T_X;
8562 break;
8563 case 4:
8564 break;
8565 default:
8566 abort ();
8567 }
8568
8569 if (inst.instruction & (CP_T_Pre | CP_T_UD)) /* ea/fd format. */
8570 {
8571 int reg;
8572 int write_back;
8573 int offset;
8574
8575 /* The instruction specified "ea" or "fd", so we can only accept
8576 [Rn]{!}. The instruction does not really support stacking or
8577 unstacking, so we have to emulate these by setting appropriate
8578 bits and offsets. */
8579 if (skip_past_comma (&str) == FAIL
8580 || *str != '[')
8581 {
8582 if (! inst.error)
8583 inst.error = BAD_ARGS;
8584 return;
8585 }
8586
8587 str++;
8588 skip_whitespace (str);
8589
8590 if ((reg = reg_required_here (&str, 16)) == FAIL)
8591 return;
8592
8593 skip_whitespace (str);
8594
8595 if (*str != ']')
8596 {
8597 inst.error = BAD_ARGS;
8598 return;
8599 }
8600
8601 str++;
8602 if (*str == '!')
8603 {
8604 write_back = 1;
8605 str++;
8606 if (reg == REG_PC)
8607 {
8608 inst.error =
8609 _("r15 not allowed as base register with write-back");
8610 return;
8611 }
8612 }
8613 else
8614 write_back = 0;
8615
8616 if (inst.instruction & CP_T_Pre)
8617 {
8618 /* Pre-decrement. */
8619 offset = 3 * num_regs;
8620 if (write_back)
8621 inst.instruction |= CP_T_WB;
8622 }
8623 else
8624 {
8625 /* Post-increment. */
8626 if (write_back)
8627 {
8628 inst.instruction |= CP_T_WB;
8629 offset = 3 * num_regs;
8630 }
8631 else
8632 {
8633 /* No write-back, so convert this into a standard pre-increment
8634 instruction -- aesthetically more pleasing. */
8635 inst.instruction |= CP_T_Pre | CP_T_UD;
8636 offset = 0;
8637 }
8638 }
8639
8640 inst.instruction |= offset;
8641 }
8642 else if (skip_past_comma (&str) == FAIL
8643 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
8644 {
8645 if (! inst.error)
8646 inst.error = BAD_ARGS;
8647 return;
8648 }
8649
8650 end_of_line (str);
8651 }
8652
8653 static void
8654 do_fpa_dyadic (str)
8655 char * str;
8656 {
8657 skip_whitespace (str);
8658
8659 if (fp_reg_required_here (&str, 12) == FAIL)
8660 {
8661 if (! inst.error)
8662 inst.error = BAD_ARGS;
8663 return;
8664 }
8665
8666 if (skip_past_comma (&str) == FAIL
8667 || fp_reg_required_here (&str, 16) == FAIL)
8668 {
8669 if (! inst.error)
8670 inst.error = BAD_ARGS;
8671 return;
8672 }
8673
8674 if (skip_past_comma (&str) == FAIL
8675 || fp_op2 (&str) == FAIL)
8676 {
8677 if (! inst.error)
8678 inst.error = BAD_ARGS;
8679 return;
8680 }
8681
8682 end_of_line (str);
8683 }
8684
8685 static void
8686 do_fpa_monadic (str)
8687 char * str;
8688 {
8689 skip_whitespace (str);
8690
8691 if (fp_reg_required_here (&str, 12) == FAIL)
8692 {
8693 if (! inst.error)
8694 inst.error = BAD_ARGS;
8695 return;
8696 }
8697
8698 if (skip_past_comma (&str) == FAIL
8699 || fp_op2 (&str) == FAIL)
8700 {
8701 if (! inst.error)
8702 inst.error = BAD_ARGS;
8703 return;
8704 }
8705
8706 end_of_line (str);
8707 }
8708
8709 static void
8710 do_fpa_cmp (str)
8711 char * str;
8712 {
8713 skip_whitespace (str);
8714
8715 if (fp_reg_required_here (&str, 16) == FAIL)
8716 {
8717 if (! inst.error)
8718 inst.error = BAD_ARGS;
8719 return;
8720 }
8721
8722 if (skip_past_comma (&str) == FAIL
8723 || fp_op2 (&str) == FAIL)
8724 {
8725 if (! inst.error)
8726 inst.error = BAD_ARGS;
8727 return;
8728 }
8729
8730 end_of_line (str);
8731 }
8732
8733 static void
8734 do_fpa_from_reg (str)
8735 char * str;
8736 {
8737 skip_whitespace (str);
8738
8739 if (fp_reg_required_here (&str, 16) == FAIL)
8740 {
8741 if (! inst.error)
8742 inst.error = BAD_ARGS;
8743 return;
8744 }
8745
8746 if (skip_past_comma (&str) == FAIL
8747 || reg_required_here (&str, 12) == FAIL)
8748 {
8749 if (! inst.error)
8750 inst.error = BAD_ARGS;
8751 return;
8752 }
8753
8754 end_of_line (str);
8755 }
8756
8757 static void
8758 do_fpa_to_reg (str)
8759 char * str;
8760 {
8761 skip_whitespace (str);
8762
8763 if (reg_required_here (&str, 12) == FAIL)
8764 return;
8765
8766 if (skip_past_comma (&str) == FAIL
8767 || fp_reg_required_here (&str, 0) == FAIL)
8768 {
8769 if (! inst.error)
8770 inst.error = BAD_ARGS;
8771 return;
8772 }
8773
8774 end_of_line (str);
8775 }
8776
8777 static int
8778 vfp_sp_reg_required_here (str, pos)
8779 char **str;
8780 enum vfp_sp_reg_pos pos;
8781 {
8782 int reg;
8783 char *start = *str;
8784
8785 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_SN].htab)) != FAIL)
8786 {
8787 switch (pos)
8788 {
8789 case VFP_REG_Sd:
8790 inst.instruction |= ((reg >> 1) << 12) | ((reg & 1) << 22);
8791 break;
8792
8793 case VFP_REG_Sn:
8794 inst.instruction |= ((reg >> 1) << 16) | ((reg & 1) << 7);
8795 break;
8796
8797 case VFP_REG_Sm:
8798 inst.instruction |= ((reg >> 1) << 0) | ((reg & 1) << 5);
8799 break;
8800
8801 default:
8802 abort ();
8803 }
8804 return reg;
8805 }
8806
8807 /* In the few cases where we might be able to accept something else
8808 this error can be overridden. */
8809 inst.error = _(all_reg_maps[REG_TYPE_SN].expected);
8810
8811 /* Restore the start point. */
8812 *str = start;
8813 return FAIL;
8814 }
8815
8816 static int
8817 vfp_dp_reg_required_here (str, pos)
8818 char **str;
8819 enum vfp_dp_reg_pos pos;
8820 {
8821 int reg;
8822 char *start = *str;
8823
8824 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_DN].htab)) != FAIL)
8825 {
8826 switch (pos)
8827 {
8828 case VFP_REG_Dd:
8829 inst.instruction |= reg << 12;
8830 break;
8831
8832 case VFP_REG_Dn:
8833 inst.instruction |= reg << 16;
8834 break;
8835
8836 case VFP_REG_Dm:
8837 inst.instruction |= reg << 0;
8838 break;
8839
8840 default:
8841 abort ();
8842 }
8843 return reg;
8844 }
8845
8846 /* In the few cases where we might be able to accept something else
8847 this error can be overridden. */
8848 inst.error = _(all_reg_maps[REG_TYPE_DN].expected);
8849
8850 /* Restore the start point. */
8851 *str = start;
8852 return FAIL;
8853 }
8854
8855 static void
8856 do_vfp_sp_monadic (str)
8857 char *str;
8858 {
8859 skip_whitespace (str);
8860
8861 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
8862 return;
8863
8864 if (skip_past_comma (&str) == FAIL
8865 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
8866 {
8867 if (! inst.error)
8868 inst.error = BAD_ARGS;
8869 return;
8870 }
8871
8872 end_of_line (str);
8873 }
8874
8875 static void
8876 do_vfp_dp_monadic (str)
8877 char *str;
8878 {
8879 skip_whitespace (str);
8880
8881 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
8882 return;
8883
8884 if (skip_past_comma (&str) == FAIL
8885 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
8886 {
8887 if (! inst.error)
8888 inst.error = BAD_ARGS;
8889 return;
8890 }
8891
8892 end_of_line (str);
8893 }
8894
8895 static void
8896 do_vfp_sp_dyadic (str)
8897 char *str;
8898 {
8899 skip_whitespace (str);
8900
8901 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
8902 return;
8903
8904 if (skip_past_comma (&str) == FAIL
8905 || vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL
8906 || skip_past_comma (&str) == FAIL
8907 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
8908 {
8909 if (! inst.error)
8910 inst.error = BAD_ARGS;
8911 return;
8912 }
8913
8914 end_of_line (str);
8915 }
8916
8917 static void
8918 do_vfp_dp_dyadic (str)
8919 char *str;
8920 {
8921 skip_whitespace (str);
8922
8923 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
8924 return;
8925
8926 if (skip_past_comma (&str) == FAIL
8927 || vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL
8928 || skip_past_comma (&str) == FAIL
8929 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
8930 {
8931 if (! inst.error)
8932 inst.error = BAD_ARGS;
8933 return;
8934 }
8935
8936 end_of_line (str);
8937 }
8938
8939 static void
8940 do_vfp_reg_from_sp (str)
8941 char *str;
8942 {
8943 skip_whitespace (str);
8944
8945 if (reg_required_here (&str, 12) == FAIL)
8946 return;
8947
8948 if (skip_past_comma (&str) == FAIL
8949 || vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL)
8950 {
8951 if (! inst.error)
8952 inst.error = BAD_ARGS;
8953 return;
8954 }
8955
8956 end_of_line (str);
8957 }
8958
8959 static void
8960 do_vfp_reg2_from_sp2 (str)
8961 char *str;
8962 {
8963 skip_whitespace (str);
8964
8965 if (reg_required_here (&str, 12) == FAIL
8966 || skip_past_comma (&str) == FAIL
8967 || reg_required_here (&str, 16) == FAIL
8968 || skip_past_comma (&str) == FAIL)
8969 {
8970 if (! inst.error)
8971 inst.error = BAD_ARGS;
8972 return;
8973 }
8974
8975 /* We require exactly two consecutive SP registers. */
8976 if (vfp_sp_reg_list (&str, VFP_REG_Sm) != 2)
8977 {
8978 if (! inst.error)
8979 inst.error = _("only two consecutive VFP SP registers allowed here");
8980 }
8981
8982 end_of_line (str);
8983 }
8984
8985 static void
8986 do_vfp_sp_from_reg (str)
8987 char *str;
8988 {
8989 skip_whitespace (str);
8990
8991 if (vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL)
8992 return;
8993
8994 if (skip_past_comma (&str) == FAIL
8995 || reg_required_here (&str, 12) == FAIL)
8996 {
8997 if (! inst.error)
8998 inst.error = BAD_ARGS;
8999 return;
9000 }
9001
9002 end_of_line (str);
9003 }
9004
9005 static void
9006 do_vfp_sp2_from_reg2 (str)
9007 char *str;
9008 {
9009 skip_whitespace (str);
9010
9011 /* We require exactly two consecutive SP registers. */
9012 if (vfp_sp_reg_list (&str, VFP_REG_Sm) != 2)
9013 {
9014 if (! inst.error)
9015 inst.error = _("only two consecutive VFP SP registers allowed here");
9016 }
9017
9018 if (skip_past_comma (&str) == FAIL
9019 || reg_required_here (&str, 12) == FAIL
9020 || skip_past_comma (&str) == FAIL
9021 || reg_required_here (&str, 16) == FAIL)
9022 {
9023 if (! inst.error)
9024 inst.error = BAD_ARGS;
9025 return;
9026 }
9027
9028 end_of_line (str);
9029 }
9030
9031 static void
9032 do_vfp_reg_from_dp (str)
9033 char *str;
9034 {
9035 skip_whitespace (str);
9036
9037 if (reg_required_here (&str, 12) == FAIL)
9038 return;
9039
9040 if (skip_past_comma (&str) == FAIL
9041 || vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL)
9042 {
9043 if (! inst.error)
9044 inst.error = BAD_ARGS;
9045 return;
9046 }
9047
9048 end_of_line (str);
9049 }
9050
9051 static void
9052 do_vfp_reg2_from_dp (str)
9053 char *str;
9054 {
9055 skip_whitespace (str);
9056
9057 if (reg_required_here (&str, 12) == FAIL)
9058 return;
9059
9060 if (skip_past_comma (&str) == FAIL
9061 || reg_required_here (&str, 16) == FAIL
9062 || skip_past_comma (&str) == FAIL
9063 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
9064 {
9065 if (! inst.error)
9066 inst.error = BAD_ARGS;
9067 return;
9068 }
9069
9070 end_of_line (str);
9071 }
9072
9073 static void
9074 do_vfp_dp_from_reg (str)
9075 char *str;
9076 {
9077 skip_whitespace (str);
9078
9079 if (vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL)
9080 return;
9081
9082 if (skip_past_comma (&str) == FAIL
9083 || reg_required_here (&str, 12) == FAIL)
9084 {
9085 if (! inst.error)
9086 inst.error = BAD_ARGS;
9087 return;
9088 }
9089
9090 end_of_line (str);
9091 }
9092
9093 static void
9094 do_vfp_dp_from_reg2 (str)
9095 char *str;
9096 {
9097 skip_whitespace (str);
9098
9099 if (vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
9100 return;
9101
9102 if (skip_past_comma (&str) == FAIL
9103 || reg_required_here (&str, 12) == FAIL
9104 || skip_past_comma (&str) == FAIL
9105 || reg_required_here (&str, 16) == FAIL)
9106 {
9107 if (! inst.error)
9108 inst.error = BAD_ARGS;
9109 return;
9110 }
9111
9112 end_of_line (str);
9113 }
9114
9115 static const struct vfp_reg *
9116 vfp_psr_parse (str)
9117 char **str;
9118 {
9119 char *start = *str;
9120 char c;
9121 char *p;
9122 const struct vfp_reg *vreg;
9123
9124 p = start;
9125
9126 /* Find the end of the current token. */
9127 do
9128 {
9129 c = *p++;
9130 }
9131 while (ISALPHA (c));
9132
9133 /* Mark it. */
9134 *--p = 0;
9135
9136 for (vreg = vfp_regs + 0;
9137 vreg < vfp_regs + sizeof (vfp_regs) / sizeof (struct vfp_reg);
9138 vreg++)
9139 {
9140 if (strcmp (start, vreg->name) == 0)
9141 {
9142 *p = c;
9143 *str = p;
9144 return vreg;
9145 }
9146 }
9147
9148 *p = c;
9149 return NULL;
9150 }
9151
9152 static int
9153 vfp_psr_required_here (str)
9154 char **str;
9155 {
9156 char *start = *str;
9157 const struct vfp_reg *vreg;
9158
9159 vreg = vfp_psr_parse (str);
9160
9161 if (vreg)
9162 {
9163 inst.instruction |= vreg->regno;
9164 return SUCCESS;
9165 }
9166
9167 inst.error = _("VFP system register expected");
9168
9169 *str = start;
9170 return FAIL;
9171 }
9172
9173 static void
9174 do_vfp_reg_from_ctrl (str)
9175 char *str;
9176 {
9177 skip_whitespace (str);
9178
9179 if (reg_required_here (&str, 12) == FAIL)
9180 return;
9181
9182 if (skip_past_comma (&str) == FAIL
9183 || vfp_psr_required_here (&str) == FAIL)
9184 {
9185 if (! inst.error)
9186 inst.error = BAD_ARGS;
9187 return;
9188 }
9189
9190 end_of_line (str);
9191 }
9192
9193 static void
9194 do_vfp_ctrl_from_reg (str)
9195 char *str;
9196 {
9197 skip_whitespace (str);
9198
9199 if (vfp_psr_required_here (&str) == FAIL)
9200 return;
9201
9202 if (skip_past_comma (&str) == FAIL
9203 || reg_required_here (&str, 12) == FAIL)
9204 {
9205 if (! inst.error)
9206 inst.error = BAD_ARGS;
9207 return;
9208 }
9209
9210 end_of_line (str);
9211 }
9212
9213 static void
9214 do_vfp_sp_ldst (str)
9215 char *str;
9216 {
9217 skip_whitespace (str);
9218
9219 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
9220 {
9221 if (!inst.error)
9222 inst.error = BAD_ARGS;
9223 return;
9224 }
9225
9226 if (skip_past_comma (&str) == FAIL
9227 || cp_address_required_here (&str, CP_NO_WB) == FAIL)
9228 {
9229 if (!inst.error)
9230 inst.error = BAD_ARGS;
9231 return;
9232 }
9233
9234 end_of_line (str);
9235 }
9236
9237 static void
9238 do_vfp_dp_ldst (str)
9239 char *str;
9240 {
9241 skip_whitespace (str);
9242
9243 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
9244 {
9245 if (!inst.error)
9246 inst.error = BAD_ARGS;
9247 return;
9248 }
9249
9250 if (skip_past_comma (&str) == FAIL
9251 || cp_address_required_here (&str, CP_NO_WB) == FAIL)
9252 {
9253 if (!inst.error)
9254 inst.error = BAD_ARGS;
9255 return;
9256 }
9257
9258 end_of_line (str);
9259 }
9260
9261 /* Parse and encode a VFP SP register list, storing the initial
9262 register in position POS and returning the range as the result. If
9263 the string is invalid return FAIL (an invalid range). */
9264 static long
9265 vfp_sp_reg_list (str, pos)
9266 char **str;
9267 enum vfp_sp_reg_pos pos;
9268 {
9269 long range = 0;
9270 int base_reg = 0;
9271 int new_base;
9272 long base_bits = 0;
9273 int count = 0;
9274 long tempinst;
9275 unsigned long mask = 0;
9276 int warned = 0;
9277
9278 if (**str != '{')
9279 return FAIL;
9280
9281 (*str)++;
9282 skip_whitespace (*str);
9283
9284 tempinst = inst.instruction;
9285
9286 do
9287 {
9288 inst.instruction = 0;
9289
9290 if ((new_base = vfp_sp_reg_required_here (str, pos)) == FAIL)
9291 return FAIL;
9292
9293 if (count == 0 || base_reg > new_base)
9294 {
9295 base_reg = new_base;
9296 base_bits = inst.instruction;
9297 }
9298
9299 if (mask & (1 << new_base))
9300 {
9301 inst.error = _("invalid register list");
9302 return FAIL;
9303 }
9304
9305 if ((mask >> new_base) != 0 && ! warned)
9306 {
9307 as_tsktsk (_("register list not in ascending order"));
9308 warned = 1;
9309 }
9310
9311 mask |= 1 << new_base;
9312 count++;
9313
9314 skip_whitespace (*str);
9315
9316 if (**str == '-') /* We have the start of a range expression */
9317 {
9318 int high_range;
9319
9320 (*str)++;
9321
9322 if ((high_range
9323 = arm_reg_parse (str, all_reg_maps[REG_TYPE_SN].htab))
9324 == FAIL)
9325 {
9326 inst.error = _(all_reg_maps[REG_TYPE_SN].expected);
9327 return FAIL;
9328 }
9329
9330 if (high_range <= new_base)
9331 {
9332 inst.error = _("register range not in ascending order");
9333 return FAIL;
9334 }
9335
9336 for (new_base++; new_base <= high_range; new_base++)
9337 {
9338 if (mask & (1 << new_base))
9339 {
9340 inst.error = _("invalid register list");
9341 return FAIL;
9342 }
9343
9344 mask |= 1 << new_base;
9345 count++;
9346 }
9347 }
9348 }
9349 while (skip_past_comma (str) != FAIL);
9350
9351 if (**str != '}')
9352 {
9353 inst.error = _("invalid register list");
9354 return FAIL;
9355 }
9356
9357 (*str)++;
9358
9359 range = count;
9360
9361 /* Sanity check -- should have raised a parse error above. */
9362 if (count == 0 || count > 32)
9363 abort ();
9364
9365 /* Final test -- the registers must be consecutive. */
9366 while (count--)
9367 {
9368 if ((mask & (1 << base_reg++)) == 0)
9369 {
9370 inst.error = _("non-contiguous register range");
9371 return FAIL;
9372 }
9373 }
9374
9375 inst.instruction = tempinst | base_bits;
9376 return range;
9377 }
9378
9379 static long
9380 vfp_dp_reg_list (str)
9381 char **str;
9382 {
9383 long range = 0;
9384 int base_reg = 0;
9385 int new_base;
9386 int count = 0;
9387 long tempinst;
9388 unsigned long mask = 0;
9389 int warned = 0;
9390
9391 if (**str != '{')
9392 return FAIL;
9393
9394 (*str)++;
9395 skip_whitespace (*str);
9396
9397 tempinst = inst.instruction;
9398
9399 do
9400 {
9401 inst.instruction = 0;
9402
9403 if ((new_base = vfp_dp_reg_required_here (str, VFP_REG_Dd)) == FAIL)
9404 return FAIL;
9405
9406 if (count == 0 || base_reg > new_base)
9407 {
9408 base_reg = new_base;
9409 range = inst.instruction;
9410 }
9411
9412 if (mask & (1 << new_base))
9413 {
9414 inst.error = _("invalid register list");
9415 return FAIL;
9416 }
9417
9418 if ((mask >> new_base) != 0 && ! warned)
9419 {
9420 as_tsktsk (_("register list not in ascending order"));
9421 warned = 1;
9422 }
9423
9424 mask |= 1 << new_base;
9425 count++;
9426
9427 skip_whitespace (*str);
9428
9429 if (**str == '-') /* We have the start of a range expression */
9430 {
9431 int high_range;
9432
9433 (*str)++;
9434
9435 if ((high_range
9436 = arm_reg_parse (str, all_reg_maps[REG_TYPE_DN].htab))
9437 == FAIL)
9438 {
9439 inst.error = _(all_reg_maps[REG_TYPE_DN].expected);
9440 return FAIL;
9441 }
9442
9443 if (high_range <= new_base)
9444 {
9445 inst.error = _("register range not in ascending order");
9446 return FAIL;
9447 }
9448
9449 for (new_base++; new_base <= high_range; new_base++)
9450 {
9451 if (mask & (1 << new_base))
9452 {
9453 inst.error = _("invalid register list");
9454 return FAIL;
9455 }
9456
9457 mask |= 1 << new_base;
9458 count++;
9459 }
9460 }
9461 }
9462 while (skip_past_comma (str) != FAIL);
9463
9464 if (**str != '}')
9465 {
9466 inst.error = _("invalid register list");
9467 return FAIL;
9468 }
9469
9470 (*str)++;
9471
9472 range |= 2 * count;
9473
9474 /* Sanity check -- should have raised a parse error above. */
9475 if (count == 0 || count > 16)
9476 abort ();
9477
9478 /* Final test -- the registers must be consecutive. */
9479 while (count--)
9480 {
9481 if ((mask & (1 << base_reg++)) == 0)
9482 {
9483 inst.error = _("non-contiguous register range");
9484 return FAIL;
9485 }
9486 }
9487
9488 inst.instruction = tempinst;
9489 return range;
9490 }
9491
9492 static void
9493 vfp_sp_ldstm (str, ldstm_type)
9494 char *str;
9495 enum vfp_ldstm_type ldstm_type;
9496 {
9497 long range;
9498
9499 skip_whitespace (str);
9500
9501 if (reg_required_here (&str, 16) == FAIL)
9502 return;
9503
9504 skip_whitespace (str);
9505
9506 if (*str == '!')
9507 {
9508 inst.instruction |= WRITE_BACK;
9509 str++;
9510 }
9511 else if (ldstm_type != VFP_LDSTMIA)
9512 {
9513 inst.error = _("this addressing mode requires base-register writeback");
9514 return;
9515 }
9516
9517 if (skip_past_comma (&str) == FAIL
9518 || (range = vfp_sp_reg_list (&str, VFP_REG_Sd)) == FAIL)
9519 {
9520 if (!inst.error)
9521 inst.error = BAD_ARGS;
9522 return;
9523 }
9524
9525 inst.instruction |= range;
9526 end_of_line (str);
9527 }
9528
9529 static void
9530 vfp_dp_ldstm (str, ldstm_type)
9531 char *str;
9532 enum vfp_ldstm_type ldstm_type;
9533 {
9534 long range;
9535
9536 skip_whitespace (str);
9537
9538 if (reg_required_here (&str, 16) == FAIL)
9539 return;
9540
9541 skip_whitespace (str);
9542
9543 if (*str == '!')
9544 {
9545 inst.instruction |= WRITE_BACK;
9546 str++;
9547 }
9548 else if (ldstm_type != VFP_LDSTMIA && ldstm_type != VFP_LDSTMIAX)
9549 {
9550 inst.error = _("this addressing mode requires base-register writeback");
9551 return;
9552 }
9553
9554 if (skip_past_comma (&str) == FAIL
9555 || (range = vfp_dp_reg_list (&str)) == FAIL)
9556 {
9557 if (!inst.error)
9558 inst.error = BAD_ARGS;
9559 return;
9560 }
9561
9562 if (ldstm_type == VFP_LDSTMIAX || ldstm_type == VFP_LDSTMDBX)
9563 range += 1;
9564
9565 inst.instruction |= range;
9566 end_of_line (str);
9567 }
9568
9569 static void
9570 do_vfp_sp_ldstmia (str)
9571 char *str;
9572 {
9573 vfp_sp_ldstm (str, VFP_LDSTMIA);
9574 }
9575
9576 static void
9577 do_vfp_sp_ldstmdb (str)
9578 char *str;
9579 {
9580 vfp_sp_ldstm (str, VFP_LDSTMDB);
9581 }
9582
9583 static void
9584 do_vfp_dp_ldstmia (str)
9585 char *str;
9586 {
9587 vfp_dp_ldstm (str, VFP_LDSTMIA);
9588 }
9589
9590 static void
9591 do_vfp_dp_ldstmdb (str)
9592 char *str;
9593 {
9594 vfp_dp_ldstm (str, VFP_LDSTMDB);
9595 }
9596
9597 static void
9598 do_vfp_xp_ldstmia (str)
9599 char *str;
9600 {
9601 vfp_dp_ldstm (str, VFP_LDSTMIAX);
9602 }
9603
9604 static void
9605 do_vfp_xp_ldstmdb (str)
9606 char *str;
9607 {
9608 vfp_dp_ldstm (str, VFP_LDSTMDBX);
9609 }
9610
9611 static void
9612 do_vfp_sp_compare_z (str)
9613 char *str;
9614 {
9615 skip_whitespace (str);
9616
9617 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
9618 {
9619 if (!inst.error)
9620 inst.error = BAD_ARGS;
9621 return;
9622 }
9623
9624 end_of_line (str);
9625 }
9626
9627 static void
9628 do_vfp_dp_compare_z (str)
9629 char *str;
9630 {
9631 skip_whitespace (str);
9632
9633 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
9634 {
9635 if (!inst.error)
9636 inst.error = BAD_ARGS;
9637 return;
9638 }
9639
9640 end_of_line (str);
9641 }
9642
9643 static void
9644 do_vfp_dp_sp_cvt (str)
9645 char *str;
9646 {
9647 skip_whitespace (str);
9648
9649 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
9650 return;
9651
9652 if (skip_past_comma (&str) == FAIL
9653 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
9654 {
9655 if (! inst.error)
9656 inst.error = BAD_ARGS;
9657 return;
9658 }
9659
9660 end_of_line (str);
9661 }
9662
9663 static void
9664 do_vfp_sp_dp_cvt (str)
9665 char *str;
9666 {
9667 skip_whitespace (str);
9668
9669 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
9670 return;
9671
9672 if (skip_past_comma (&str) == FAIL
9673 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
9674 {
9675 if (! inst.error)
9676 inst.error = BAD_ARGS;
9677 return;
9678 }
9679
9680 end_of_line (str);
9681 }
9682
9683 /* Thumb specific routines. */
9684
9685 /* Parse and validate that a register is of the right form, this saves
9686 repeated checking of this information in many similar cases.
9687 Unlike the 32-bit case we do not insert the register into the opcode
9688 here, since the position is often unknown until the full instruction
9689 has been parsed. */
9690
9691 static int
9692 thumb_reg (strp, hi_lo)
9693 char ** strp;
9694 int hi_lo;
9695 {
9696 int reg;
9697
9698 if ((reg = reg_required_here (strp, -1)) == FAIL)
9699 return FAIL;
9700
9701 switch (hi_lo)
9702 {
9703 case THUMB_REG_LO:
9704 if (reg > 7)
9705 {
9706 inst.error = _("lo register required");
9707 return FAIL;
9708 }
9709 break;
9710
9711 case THUMB_REG_HI:
9712 if (reg < 8)
9713 {
9714 inst.error = _("hi register required");
9715 return FAIL;
9716 }
9717 break;
9718
9719 default:
9720 break;
9721 }
9722
9723 return reg;
9724 }
9725
9726 /* Parse an add or subtract instruction, SUBTRACT is non-zero if the opcode
9727 was SUB. */
9728
9729 static void
9730 thumb_add_sub (str, subtract)
9731 char * str;
9732 int subtract;
9733 {
9734 int Rd, Rs, Rn = FAIL;
9735
9736 skip_whitespace (str);
9737
9738 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
9739 || skip_past_comma (&str) == FAIL)
9740 {
9741 if (! inst.error)
9742 inst.error = BAD_ARGS;
9743 return;
9744 }
9745
9746 if (is_immediate_prefix (*str))
9747 {
9748 Rs = Rd;
9749 str++;
9750 if (my_get_expression (&inst.reloc.exp, &str))
9751 return;
9752 }
9753 else
9754 {
9755 if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
9756 return;
9757
9758 if (skip_past_comma (&str) == FAIL)
9759 {
9760 /* Two operand format, shuffle the registers
9761 and pretend there are 3. */
9762 Rn = Rs;
9763 Rs = Rd;
9764 }
9765 else if (is_immediate_prefix (*str))
9766 {
9767 str++;
9768 if (my_get_expression (&inst.reloc.exp, &str))
9769 return;
9770 }
9771 else if ((Rn = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
9772 return;
9773 }
9774
9775 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
9776 for the latter case, EXPR contains the immediate that was found. */
9777 if (Rn != FAIL)
9778 {
9779 /* All register format. */
9780 if (Rd > 7 || Rs > 7 || Rn > 7)
9781 {
9782 if (Rs != Rd)
9783 {
9784 inst.error = _("dest and source1 must be the same register");
9785 return;
9786 }
9787
9788 /* Can't do this for SUB. */
9789 if (subtract)
9790 {
9791 inst.error = _("subtract valid only on lo regs");
9792 return;
9793 }
9794
9795 inst.instruction = (T_OPCODE_ADD_HI
9796 | (Rd > 7 ? THUMB_H1 : 0)
9797 | (Rn > 7 ? THUMB_H2 : 0));
9798 inst.instruction |= (Rd & 7) | ((Rn & 7) << 3);
9799 }
9800 else
9801 {
9802 inst.instruction = subtract ? T_OPCODE_SUB_R3 : T_OPCODE_ADD_R3;
9803 inst.instruction |= Rd | (Rs << 3) | (Rn << 6);
9804 }
9805 }
9806 else
9807 {
9808 /* Immediate expression, now things start to get nasty. */
9809
9810 /* First deal with HI regs, only very restricted cases allowed:
9811 Adjusting SP, and using PC or SP to get an address. */
9812 if ((Rd > 7 && (Rd != REG_SP || Rs != REG_SP))
9813 || (Rs > 7 && Rs != REG_SP && Rs != REG_PC))
9814 {
9815 inst.error = _("invalid Hi register with immediate");
9816 return;
9817 }
9818
9819 if (inst.reloc.exp.X_op != O_constant)
9820 {
9821 /* Value isn't known yet, all we can do is store all the fragments
9822 we know about in the instruction and let the reloc hacking
9823 work it all out. */
9824 inst.instruction = (subtract ? 0x8000 : 0) | (Rd << 4) | Rs;
9825 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
9826 }
9827 else
9828 {
9829 int offset = inst.reloc.exp.X_add_number;
9830
9831 if (subtract)
9832 offset = - offset;
9833
9834 if (offset < 0)
9835 {
9836 offset = - offset;
9837 subtract = 1;
9838
9839 /* Quick check, in case offset is MIN_INT. */
9840 if (offset < 0)
9841 {
9842 inst.error = _("immediate value out of range");
9843 return;
9844 }
9845 }
9846 /* Note - you cannot convert a subtract of 0 into an
9847 add of 0 because the carry flag is set differently. */
9848 else if (offset > 0)
9849 subtract = 0;
9850
9851 if (Rd == REG_SP)
9852 {
9853 if (offset & ~0x1fc)
9854 {
9855 inst.error = _("invalid immediate value for stack adjust");
9856 return;
9857 }
9858 inst.instruction = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
9859 inst.instruction |= offset >> 2;
9860 }
9861 else if (Rs == REG_PC || Rs == REG_SP)
9862 {
9863 if (subtract
9864 || (offset & ~0x3fc))
9865 {
9866 inst.error = _("invalid immediate for address calculation");
9867 return;
9868 }
9869 inst.instruction = (Rs == REG_PC ? T_OPCODE_ADD_PC
9870 : T_OPCODE_ADD_SP);
9871 inst.instruction |= (Rd << 8) | (offset >> 2);
9872 }
9873 else if (Rs == Rd)
9874 {
9875 if (offset & ~0xff)
9876 {
9877 inst.error = _("immediate value out of range");
9878 return;
9879 }
9880 inst.instruction = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
9881 inst.instruction |= (Rd << 8) | offset;
9882 }
9883 else
9884 {
9885 if (offset & ~0x7)
9886 {
9887 inst.error = _("immediate value out of range");
9888 return;
9889 }
9890 inst.instruction = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
9891 inst.instruction |= Rd | (Rs << 3) | (offset << 6);
9892 }
9893 }
9894 }
9895
9896 end_of_line (str);
9897 }
9898
9899 static void
9900 thumb_shift (str, shift)
9901 char * str;
9902 int shift;
9903 {
9904 int Rd, Rs, Rn = FAIL;
9905
9906 skip_whitespace (str);
9907
9908 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9909 || skip_past_comma (&str) == FAIL)
9910 {
9911 if (! inst.error)
9912 inst.error = BAD_ARGS;
9913 return;
9914 }
9915
9916 if (is_immediate_prefix (*str))
9917 {
9918 /* Two operand immediate format, set Rs to Rd. */
9919 Rs = Rd;
9920 str ++;
9921 if (my_get_expression (&inst.reloc.exp, &str))
9922 return;
9923 }
9924 else
9925 {
9926 if ((Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9927 return;
9928
9929 if (skip_past_comma (&str) == FAIL)
9930 {
9931 /* Two operand format, shuffle the registers
9932 and pretend there are 3. */
9933 Rn = Rs;
9934 Rs = Rd;
9935 }
9936 else if (is_immediate_prefix (*str))
9937 {
9938 str++;
9939 if (my_get_expression (&inst.reloc.exp, &str))
9940 return;
9941 }
9942 else if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9943 return;
9944 }
9945
9946 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
9947 for the latter case, EXPR contains the immediate that was found. */
9948
9949 if (Rn != FAIL)
9950 {
9951 if (Rs != Rd)
9952 {
9953 inst.error = _("source1 and dest must be same register");
9954 return;
9955 }
9956
9957 switch (shift)
9958 {
9959 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_R; break;
9960 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_R; break;
9961 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_R; break;
9962 }
9963
9964 inst.instruction |= Rd | (Rn << 3);
9965 }
9966 else
9967 {
9968 switch (shift)
9969 {
9970 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_I; break;
9971 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_I; break;
9972 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_I; break;
9973 }
9974
9975 if (inst.reloc.exp.X_op != O_constant)
9976 {
9977 /* Value isn't known yet, create a dummy reloc and let reloc
9978 hacking fix it up. */
9979 inst.reloc.type = BFD_RELOC_ARM_THUMB_SHIFT;
9980 }
9981 else
9982 {
9983 unsigned shift_value = inst.reloc.exp.X_add_number;
9984
9985 if (shift_value > 32 || (shift_value == 32 && shift == THUMB_LSL))
9986 {
9987 inst.error = _("invalid immediate for shift");
9988 return;
9989 }
9990
9991 /* Shifts of zero are handled by converting to LSL. */
9992 if (shift_value == 0)
9993 inst.instruction = T_OPCODE_LSL_I;
9994
9995 /* Shifts of 32 are encoded as a shift of zero. */
9996 if (shift_value == 32)
9997 shift_value = 0;
9998
9999 inst.instruction |= shift_value << 6;
10000 }
10001
10002 inst.instruction |= Rd | (Rs << 3);
10003 }
10004
10005 end_of_line (str);
10006 }
10007
10008 static void
10009 thumb_mov_compare (str, move)
10010 char * str;
10011 int move;
10012 {
10013 int Rd, Rs = FAIL;
10014
10015 skip_whitespace (str);
10016
10017 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
10018 || skip_past_comma (&str) == FAIL)
10019 {
10020 if (! inst.error)
10021 inst.error = BAD_ARGS;
10022 return;
10023 }
10024
10025 if (move != THUMB_CPY && is_immediate_prefix (*str))
10026 {
10027 str++;
10028 if (my_get_expression (&inst.reloc.exp, &str))
10029 return;
10030 }
10031 else if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
10032 return;
10033
10034 if (Rs != FAIL)
10035 {
10036 if (move != THUMB_CPY && Rs < 8 && Rd < 8)
10037 {
10038 if (move == THUMB_MOVE)
10039 /* A move of two lowregs is encoded as ADD Rd, Rs, #0
10040 since a MOV instruction produces unpredictable results. */
10041 inst.instruction = T_OPCODE_ADD_I3;
10042 else
10043 inst.instruction = T_OPCODE_CMP_LR;
10044 inst.instruction |= Rd | (Rs << 3);
10045 }
10046 else
10047 {
10048 if (move == THUMB_MOVE)
10049 inst.instruction = T_OPCODE_MOV_HR;
10050 else if (move != THUMB_CPY)
10051 inst.instruction = T_OPCODE_CMP_HR;
10052
10053 if (Rd > 7)
10054 inst.instruction |= THUMB_H1;
10055
10056 if (Rs > 7)
10057 inst.instruction |= THUMB_H2;
10058
10059 inst.instruction |= (Rd & 7) | ((Rs & 7) << 3);
10060 }
10061 }
10062 else
10063 {
10064 if (Rd > 7)
10065 {
10066 inst.error = _("only lo regs allowed with immediate");
10067 return;
10068 }
10069
10070 if (move == THUMB_MOVE)
10071 inst.instruction = T_OPCODE_MOV_I8;
10072 else
10073 inst.instruction = T_OPCODE_CMP_I8;
10074
10075 inst.instruction |= Rd << 8;
10076
10077 if (inst.reloc.exp.X_op != O_constant)
10078 inst.reloc.type = BFD_RELOC_ARM_THUMB_IMM;
10079 else
10080 {
10081 unsigned value = inst.reloc.exp.X_add_number;
10082
10083 if (value > 255)
10084 {
10085 inst.error = _("invalid immediate");
10086 return;
10087 }
10088
10089 inst.instruction |= value;
10090 }
10091 }
10092
10093 end_of_line (str);
10094 }
10095
10096 static void
10097 thumb_load_store (str, load_store, size)
10098 char * str;
10099 int load_store;
10100 int size;
10101 {
10102 int Rd, Rb, Ro = FAIL;
10103
10104 skip_whitespace (str);
10105
10106 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
10107 || skip_past_comma (&str) == FAIL)
10108 {
10109 if (! inst.error)
10110 inst.error = BAD_ARGS;
10111 return;
10112 }
10113
10114 if (*str == '[')
10115 {
10116 str++;
10117 if ((Rb = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
10118 return;
10119
10120 if (skip_past_comma (&str) != FAIL)
10121 {
10122 if (is_immediate_prefix (*str))
10123 {
10124 str++;
10125 if (my_get_expression (&inst.reloc.exp, &str))
10126 return;
10127 }
10128 else if ((Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
10129 return;
10130 }
10131 else
10132 {
10133 inst.reloc.exp.X_op = O_constant;
10134 inst.reloc.exp.X_add_number = 0;
10135 }
10136
10137 if (*str != ']')
10138 {
10139 inst.error = _("expected ']'");
10140 return;
10141 }
10142 str++;
10143 }
10144 else if (*str == '=')
10145 {
10146 if (load_store != THUMB_LOAD)
10147 {
10148 inst.error = _("invalid pseudo operation");
10149 return;
10150 }
10151
10152 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
10153 str++;
10154
10155 skip_whitespace (str);
10156
10157 if (my_get_expression (& inst.reloc.exp, & str))
10158 return;
10159
10160 end_of_line (str);
10161
10162 if ( inst.reloc.exp.X_op != O_constant
10163 && inst.reloc.exp.X_op != O_symbol)
10164 {
10165 inst.error = "Constant expression expected";
10166 return;
10167 }
10168
10169 if (inst.reloc.exp.X_op == O_constant
10170 && ((inst.reloc.exp.X_add_number & ~0xFF) == 0))
10171 {
10172 /* This can be done with a mov instruction. */
10173
10174 inst.instruction = T_OPCODE_MOV_I8 | (Rd << 8);
10175 inst.instruction |= inst.reloc.exp.X_add_number;
10176 return;
10177 }
10178
10179 /* Insert into literal pool. */
10180 if (add_to_lit_pool () == FAIL)
10181 {
10182 if (!inst.error)
10183 inst.error = "literal pool insertion failed";
10184 return;
10185 }
10186
10187 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
10188 inst.reloc.pc_rel = 1;
10189 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
10190 /* Adjust ARM pipeline offset to Thumb. */
10191 inst.reloc.exp.X_add_number += 4;
10192
10193 return;
10194 }
10195 else
10196 {
10197 if (my_get_expression (&inst.reloc.exp, &str))
10198 return;
10199
10200 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
10201 inst.reloc.pc_rel = 1;
10202 inst.reloc.exp.X_add_number -= 4; /* Pipeline offset. */
10203 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
10204 end_of_line (str);
10205 return;
10206 }
10207
10208 if (Rb == REG_PC || Rb == REG_SP)
10209 {
10210 if (size != THUMB_WORD)
10211 {
10212 inst.error = _("byte or halfword not valid for base register");
10213 return;
10214 }
10215 else if (Rb == REG_PC && load_store != THUMB_LOAD)
10216 {
10217 inst.error = _("r15 based store not allowed");
10218 return;
10219 }
10220 else if (Ro != FAIL)
10221 {
10222 inst.error = _("invalid base register for register offset");
10223 return;
10224 }
10225
10226 if (Rb == REG_PC)
10227 inst.instruction = T_OPCODE_LDR_PC;
10228 else if (load_store == THUMB_LOAD)
10229 inst.instruction = T_OPCODE_LDR_SP;
10230 else
10231 inst.instruction = T_OPCODE_STR_SP;
10232
10233 inst.instruction |= Rd << 8;
10234 if (inst.reloc.exp.X_op == O_constant)
10235 {
10236 unsigned offset = inst.reloc.exp.X_add_number;
10237
10238 if (offset & ~0x3fc)
10239 {
10240 inst.error = _("invalid offset");
10241 return;
10242 }
10243
10244 inst.instruction |= offset >> 2;
10245 }
10246 else
10247 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
10248 }
10249 else if (Rb > 7)
10250 {
10251 inst.error = _("invalid base register in load/store");
10252 return;
10253 }
10254 else if (Ro == FAIL)
10255 {
10256 /* Immediate offset. */
10257 if (size == THUMB_WORD)
10258 inst.instruction = (load_store == THUMB_LOAD
10259 ? T_OPCODE_LDR_IW : T_OPCODE_STR_IW);
10260 else if (size == THUMB_HALFWORD)
10261 inst.instruction = (load_store == THUMB_LOAD
10262 ? T_OPCODE_LDR_IH : T_OPCODE_STR_IH);
10263 else
10264 inst.instruction = (load_store == THUMB_LOAD
10265 ? T_OPCODE_LDR_IB : T_OPCODE_STR_IB);
10266
10267 inst.instruction |= Rd | (Rb << 3);
10268
10269 if (inst.reloc.exp.X_op == O_constant)
10270 {
10271 unsigned offset = inst.reloc.exp.X_add_number;
10272
10273 if (offset & ~(0x1f << size))
10274 {
10275 inst.error = _("invalid offset");
10276 return;
10277 }
10278 inst.instruction |= (offset >> size) << 6;
10279 }
10280 else
10281 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
10282 }
10283 else
10284 {
10285 /* Register offset. */
10286 if (size == THUMB_WORD)
10287 inst.instruction = (load_store == THUMB_LOAD
10288 ? T_OPCODE_LDR_RW : T_OPCODE_STR_RW);
10289 else if (size == THUMB_HALFWORD)
10290 inst.instruction = (load_store == THUMB_LOAD
10291 ? T_OPCODE_LDR_RH : T_OPCODE_STR_RH);
10292 else
10293 inst.instruction = (load_store == THUMB_LOAD
10294 ? T_OPCODE_LDR_RB : T_OPCODE_STR_RB);
10295
10296 inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
10297 }
10298
10299 end_of_line (str);
10300 }
10301
10302 /* A register must be given at this point.
10303
10304 Shift is the place to put it in inst.instruction.
10305
10306 Restores input start point on err.
10307 Returns the reg#, or FAIL. */
10308
10309 static int
10310 mav_reg_required_here (str, shift, regtype)
10311 char ** str;
10312 int shift;
10313 enum arm_reg_type regtype;
10314 {
10315 int reg;
10316 char *start = *str;
10317
10318 if ((reg = arm_reg_parse (str, all_reg_maps[regtype].htab)) != FAIL)
10319 {
10320 if (shift >= 0)
10321 inst.instruction |= reg << shift;
10322
10323 return reg;
10324 }
10325
10326 /* Restore the start point. */
10327 *str = start;
10328
10329 /* In the few cases where we might be able to accept something else
10330 this error can be overridden. */
10331 inst.error = _(all_reg_maps[regtype].expected);
10332
10333 return FAIL;
10334 }
10335
10336 /* Cirrus Maverick Instructions. */
10337
10338 /* Wrapper functions. */
10339
10340 static void
10341 do_mav_binops_1a (str)
10342 char * str;
10343 {
10344 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVF);
10345 }
10346
10347 static void
10348 do_mav_binops_1b (str)
10349 char * str;
10350 {
10351 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVD);
10352 }
10353
10354 static void
10355 do_mav_binops_1c (str)
10356 char * str;
10357 {
10358 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVDX);
10359 }
10360
10361 static void
10362 do_mav_binops_1d (str)
10363 char * str;
10364 {
10365 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVF);
10366 }
10367
10368 static void
10369 do_mav_binops_1e (str)
10370 char * str;
10371 {
10372 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVD);
10373 }
10374
10375 static void
10376 do_mav_binops_1f (str)
10377 char * str;
10378 {
10379 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVF);
10380 }
10381
10382 static void
10383 do_mav_binops_1g (str)
10384 char * str;
10385 {
10386 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVD);
10387 }
10388
10389 static void
10390 do_mav_binops_1h (str)
10391 char * str;
10392 {
10393 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVFX);
10394 }
10395
10396 static void
10397 do_mav_binops_1i (str)
10398 char * str;
10399 {
10400 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVFX);
10401 }
10402
10403 static void
10404 do_mav_binops_1j (str)
10405 char * str;
10406 {
10407 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVDX);
10408 }
10409
10410 static void
10411 do_mav_binops_1k (str)
10412 char * str;
10413 {
10414 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVDX);
10415 }
10416
10417 static void
10418 do_mav_binops_1l (str)
10419 char * str;
10420 {
10421 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVF);
10422 }
10423
10424 static void
10425 do_mav_binops_1m (str)
10426 char * str;
10427 {
10428 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVD);
10429 }
10430
10431 static void
10432 do_mav_binops_1n (str)
10433 char * str;
10434 {
10435 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVFX);
10436 }
10437
10438 static void
10439 do_mav_binops_1o (str)
10440 char * str;
10441 {
10442 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVDX, REG_TYPE_MVDX);
10443 }
10444
10445 static void
10446 do_mav_binops_2a (str)
10447 char * str;
10448 {
10449 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVF, REG_TYPE_RN);
10450 }
10451
10452 static void
10453 do_mav_binops_2b (str)
10454 char * str;
10455 {
10456 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVD, REG_TYPE_RN);
10457 }
10458
10459 static void
10460 do_mav_binops_2c (str)
10461 char * str;
10462 {
10463 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVDX, REG_TYPE_RN);
10464 }
10465
10466 static void
10467 do_mav_binops_3a (str)
10468 char * str;
10469 {
10470 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVAX, REG_TYPE_MVFX);
10471 }
10472
10473 static void
10474 do_mav_binops_3b (str)
10475 char * str;
10476 {
10477 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVFX, REG_TYPE_MVAX);
10478 }
10479
10480 static void
10481 do_mav_binops_3c (str)
10482 char * str;
10483 {
10484 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVAX, REG_TYPE_MVDX);
10485 }
10486
10487 static void
10488 do_mav_binops_3d (str)
10489 char * str;
10490 {
10491 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVDX, REG_TYPE_MVAX);
10492 }
10493
10494 static void
10495 do_mav_triple_4a (str)
10496 char * str;
10497 {
10498 do_mav_triple (str, MAV_MODE4, REG_TYPE_MVFX, REG_TYPE_MVFX, REG_TYPE_RN);
10499 }
10500
10501 static void
10502 do_mav_triple_4b (str)
10503 char * str;
10504 {
10505 do_mav_triple (str, MAV_MODE4, REG_TYPE_MVDX, REG_TYPE_MVDX, REG_TYPE_RN);
10506 }
10507
10508 static void
10509 do_mav_triple_5a (str)
10510 char * str;
10511 {
10512 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVF, REG_TYPE_MVF);
10513 }
10514
10515 static void
10516 do_mav_triple_5b (str)
10517 char * str;
10518 {
10519 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVD, REG_TYPE_MVD);
10520 }
10521
10522 static void
10523 do_mav_triple_5c (str)
10524 char * str;
10525 {
10526 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVFX, REG_TYPE_MVFX);
10527 }
10528
10529 static void
10530 do_mav_triple_5d (str)
10531 char * str;
10532 {
10533 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVDX, REG_TYPE_MVDX);
10534 }
10535
10536 static void
10537 do_mav_triple_5e (str)
10538 char * str;
10539 {
10540 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVF, REG_TYPE_MVF, REG_TYPE_MVF);
10541 }
10542
10543 static void
10544 do_mav_triple_5f (str)
10545 char * str;
10546 {
10547 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVD, REG_TYPE_MVD, REG_TYPE_MVD);
10548 }
10549
10550 static void
10551 do_mav_triple_5g (str)
10552 char * str;
10553 {
10554 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVFX, REG_TYPE_MVFX, REG_TYPE_MVFX);
10555 }
10556
10557 static void
10558 do_mav_triple_5h (str)
10559 char * str;
10560 {
10561 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVDX, REG_TYPE_MVDX, REG_TYPE_MVDX);
10562 }
10563
10564 static void
10565 do_mav_quad_6a (str)
10566 char * str;
10567 {
10568 do_mav_quad (str, MAV_MODE6, REG_TYPE_MVAX, REG_TYPE_MVFX, REG_TYPE_MVFX,
10569 REG_TYPE_MVFX);
10570 }
10571
10572 static void
10573 do_mav_quad_6b (str)
10574 char * str;
10575 {
10576 do_mav_quad (str, MAV_MODE6, REG_TYPE_MVAX, REG_TYPE_MVAX, REG_TYPE_MVFX,
10577 REG_TYPE_MVFX);
10578 }
10579
10580 /* cfmvsc32<cond> DSPSC,MVDX[15:0]. */
10581 static void
10582 do_mav_dspsc_1 (str)
10583 char * str;
10584 {
10585 skip_whitespace (str);
10586
10587 /* cfmvsc32. */
10588 if (mav_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL
10589 || skip_past_comma (&str) == FAIL
10590 || mav_reg_required_here (&str, 12, REG_TYPE_MVDX) == FAIL)
10591 {
10592 if (!inst.error)
10593 inst.error = BAD_ARGS;
10594
10595 return;
10596 }
10597
10598 end_of_line (str);
10599 }
10600
10601 /* cfmv32sc<cond> MVDX[15:0],DSPSC. */
10602 static void
10603 do_mav_dspsc_2 (str)
10604 char * str;
10605 {
10606 skip_whitespace (str);
10607
10608 /* cfmv32sc. */
10609 if (mav_reg_required_here (&str, 12, REG_TYPE_MVDX) == FAIL
10610 || skip_past_comma (&str) == FAIL
10611 || mav_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL)
10612 {
10613 if (!inst.error)
10614 inst.error = BAD_ARGS;
10615
10616 return;
10617 }
10618
10619 end_of_line (str);
10620 }
10621
10622 static void
10623 do_mav_shift_1 (str)
10624 char * str;
10625 {
10626 do_mav_shift (str, REG_TYPE_MVFX, REG_TYPE_MVFX);
10627 }
10628
10629 static void
10630 do_mav_shift_2 (str)
10631 char * str;
10632 {
10633 do_mav_shift (str, REG_TYPE_MVDX, REG_TYPE_MVDX);
10634 }
10635
10636 static void
10637 do_mav_ldst_1 (str)
10638 char * str;
10639 {
10640 do_mav_ldst (str, REG_TYPE_MVF);
10641 }
10642
10643 static void
10644 do_mav_ldst_2 (str)
10645 char * str;
10646 {
10647 do_mav_ldst (str, REG_TYPE_MVD);
10648 }
10649
10650 static void
10651 do_mav_ldst_3 (str)
10652 char * str;
10653 {
10654 do_mav_ldst (str, REG_TYPE_MVFX);
10655 }
10656
10657 static void
10658 do_mav_ldst_4 (str)
10659 char * str;
10660 {
10661 do_mav_ldst (str, REG_TYPE_MVDX);
10662 }
10663
10664 /* Isnsn like "foo X,Y". */
10665
10666 static void
10667 do_mav_binops (str, mode, reg0, reg1)
10668 char * str;
10669 int mode;
10670 enum arm_reg_type reg0;
10671 enum arm_reg_type reg1;
10672 {
10673 int shift0, shift1;
10674
10675 shift0 = mode & 0xff;
10676 shift1 = (mode >> 8) & 0xff;
10677
10678 skip_whitespace (str);
10679
10680 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
10681 || skip_past_comma (&str) == FAIL
10682 || mav_reg_required_here (&str, shift1, reg1) == FAIL)
10683 {
10684 if (!inst.error)
10685 inst.error = BAD_ARGS;
10686 }
10687 else
10688 end_of_line (str);
10689 }
10690
10691 /* Isnsn like "foo X,Y,Z". */
10692
10693 static void
10694 do_mav_triple (str, mode, reg0, reg1, reg2)
10695 char * str;
10696 int mode;
10697 enum arm_reg_type reg0;
10698 enum arm_reg_type reg1;
10699 enum arm_reg_type reg2;
10700 {
10701 int shift0, shift1, shift2;
10702
10703 shift0 = mode & 0xff;
10704 shift1 = (mode >> 8) & 0xff;
10705 shift2 = (mode >> 16) & 0xff;
10706
10707 skip_whitespace (str);
10708
10709 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
10710 || skip_past_comma (&str) == FAIL
10711 || mav_reg_required_here (&str, shift1, reg1) == FAIL
10712 || skip_past_comma (&str) == FAIL
10713 || mav_reg_required_here (&str, shift2, reg2) == FAIL)
10714 {
10715 if (!inst.error)
10716 inst.error = BAD_ARGS;
10717 }
10718 else
10719 end_of_line (str);
10720 }
10721
10722 /* Isnsn like "foo W,X,Y,Z".
10723 where W=MVAX[0:3] and X,Y,Z=MVFX[0:15]. */
10724
10725 static void
10726 do_mav_quad (str, mode, reg0, reg1, reg2, reg3)
10727 char * str;
10728 int mode;
10729 enum arm_reg_type reg0;
10730 enum arm_reg_type reg1;
10731 enum arm_reg_type reg2;
10732 enum arm_reg_type reg3;
10733 {
10734 int shift0, shift1, shift2, shift3;
10735
10736 shift0= mode & 0xff;
10737 shift1 = (mode >> 8) & 0xff;
10738 shift2 = (mode >> 16) & 0xff;
10739 shift3 = (mode >> 24) & 0xff;
10740
10741 skip_whitespace (str);
10742
10743 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
10744 || skip_past_comma (&str) == FAIL
10745 || mav_reg_required_here (&str, shift1, reg1) == FAIL
10746 || skip_past_comma (&str) == FAIL
10747 || mav_reg_required_here (&str, shift2, reg2) == FAIL
10748 || skip_past_comma (&str) == FAIL
10749 || mav_reg_required_here (&str, shift3, reg3) == FAIL)
10750 {
10751 if (!inst.error)
10752 inst.error = BAD_ARGS;
10753 }
10754 else
10755 end_of_line (str);
10756 }
10757
10758 /* Maverick shift immediate instructions.
10759 cfsh32<cond> MVFX[15:0],MVFX[15:0],Shift[6:0].
10760 cfsh64<cond> MVDX[15:0],MVDX[15:0],Shift[6:0]. */
10761
10762 static void
10763 do_mav_shift (str, reg0, reg1)
10764 char * str;
10765 enum arm_reg_type reg0;
10766 enum arm_reg_type reg1;
10767 {
10768 int error;
10769 int imm, neg = 0;
10770
10771 skip_whitespace (str);
10772
10773 error = 0;
10774
10775 if (mav_reg_required_here (&str, 12, reg0) == FAIL
10776 || skip_past_comma (&str) == FAIL
10777 || mav_reg_required_here (&str, 16, reg1) == FAIL
10778 || skip_past_comma (&str) == FAIL)
10779 {
10780 if (!inst.error)
10781 inst.error = BAD_ARGS;
10782 return;
10783 }
10784
10785 /* Calculate the immediate operand.
10786 The operand is a 7bit signed number. */
10787 skip_whitespace (str);
10788
10789 if (*str == '#')
10790 ++str;
10791
10792 if (!ISDIGIT (*str) && *str != '-')
10793 {
10794 inst.error = _("expecting immediate, 7bit operand");
10795 return;
10796 }
10797
10798 if (*str == '-')
10799 {
10800 neg = 1;
10801 ++str;
10802 }
10803
10804 for (imm = 0; *str && ISDIGIT (*str); ++str)
10805 imm = imm * 10 + *str - '0';
10806
10807 if (imm > 64)
10808 {
10809 inst.error = _("immediate out of range");
10810 return;
10811 }
10812
10813 /* Make negative imm's into 7bit signed numbers. */
10814 if (neg)
10815 {
10816 imm = -imm;
10817 imm &= 0x0000007f;
10818 }
10819
10820 /* Bits 0-3 of the insn should have bits 0-3 of the immediate.
10821 Bits 5-7 of the insn should have bits 4-6 of the immediate.
10822 Bit 4 should be 0. */
10823 imm = (imm & 0xf) | ((imm & 0x70) << 1);
10824
10825 inst.instruction |= imm;
10826 end_of_line (str);
10827 }
10828
10829 static int
10830 mav_parse_offset (str, negative)
10831 char ** str;
10832 int *negative;
10833 {
10834 char * p = *str;
10835 int offset;
10836
10837 *negative = 0;
10838
10839 skip_whitespace (p);
10840
10841 if (*p == '#')
10842 ++p;
10843
10844 if (*p == '-')
10845 {
10846 *negative = 1;
10847 ++p;
10848 }
10849
10850 if (!ISDIGIT (*p))
10851 {
10852 inst.error = _("offset expected");
10853 return 0;
10854 }
10855
10856 for (offset = 0; *p && ISDIGIT (*p); ++p)
10857 offset = offset * 10 + *p - '0';
10858
10859 if (offset > 0xff)
10860 {
10861 inst.error = _("offset out of range");
10862 return 0;
10863 }
10864
10865 *str = p;
10866
10867 return *negative ? -offset : offset;
10868 }
10869
10870 /* Maverick load/store instructions.
10871 <insn><cond> CRd,[Rn,<offset>]{!}.
10872 <insn><cond> CRd,[Rn],<offset>. */
10873
10874 static void
10875 do_mav_ldst (str, reg0)
10876 char * str;
10877 enum arm_reg_type reg0;
10878 {
10879 int offset, negative;
10880
10881 skip_whitespace (str);
10882
10883 if (mav_reg_required_here (&str, 12, reg0) == FAIL
10884 || skip_past_comma (&str) == FAIL
10885 || *str++ != '['
10886 || reg_required_here (&str, 16) == FAIL)
10887 goto fail_ldst;
10888
10889 if (skip_past_comma (&str) == SUCCESS)
10890 {
10891 /* You are here: "<offset>]{!}". */
10892 inst.instruction |= PRE_INDEX;
10893
10894 offset = mav_parse_offset (&str, &negative);
10895
10896 if (inst.error)
10897 return;
10898
10899 if (*str++ != ']')
10900 {
10901 inst.error = _("missing ]");
10902 return;
10903 }
10904
10905 if (*str == '!')
10906 {
10907 inst.instruction |= WRITE_BACK;
10908 ++str;
10909 }
10910 }
10911 else
10912 {
10913 /* You are here: "], <offset>". */
10914 if (*str++ != ']')
10915 {
10916 inst.error = _("missing ]");
10917 return;
10918 }
10919
10920 if (skip_past_comma (&str) == FAIL
10921 || (offset = mav_parse_offset (&str, &negative), inst.error))
10922 goto fail_ldst;
10923
10924 inst.instruction |= CP_T_WB; /* Post indexed, set bit W. */
10925 }
10926
10927 if (negative)
10928 offset = -offset;
10929 else
10930 inst.instruction |= CP_T_UD; /* Positive, so set bit U. */
10931
10932 inst.instruction |= offset >> 2;
10933 end_of_line (str);
10934 return;
10935
10936 fail_ldst:
10937 if (!inst.error)
10938 inst.error = BAD_ARGS;
10939 }
10940
10941 static void
10942 do_t_nop (str)
10943 char * str;
10944 {
10945 /* Do nothing. */
10946 end_of_line (str);
10947 }
10948
10949 /* Handle the Format 4 instructions that do not have equivalents in other
10950 formats. That is, ADC, AND, EOR, SBC, ROR, TST, NEG, CMN, ORR, MUL,
10951 BIC and MVN. */
10952
10953 static void
10954 do_t_arit (str)
10955 char * str;
10956 {
10957 int Rd, Rs, Rn;
10958
10959 skip_whitespace (str);
10960
10961 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
10962 || skip_past_comma (&str) == FAIL
10963 || (Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
10964 {
10965 inst.error = BAD_ARGS;
10966 return;
10967 }
10968
10969 if (skip_past_comma (&str) != FAIL)
10970 {
10971 /* Three operand format not allowed for TST, CMN, NEG and MVN.
10972 (It isn't allowed for CMP either, but that isn't handled by this
10973 function.) */
10974 if (inst.instruction == T_OPCODE_TST
10975 || inst.instruction == T_OPCODE_CMN
10976 || inst.instruction == T_OPCODE_NEG
10977 || inst.instruction == T_OPCODE_MVN)
10978 {
10979 inst.error = BAD_ARGS;
10980 return;
10981 }
10982
10983 if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
10984 return;
10985
10986 if (Rs != Rd)
10987 {
10988 inst.error = _("dest and source1 must be the same register");
10989 return;
10990 }
10991 Rs = Rn;
10992 }
10993
10994 if (inst.instruction == T_OPCODE_MUL
10995 && Rs == Rd)
10996 as_tsktsk (_("Rs and Rd must be different in MUL"));
10997
10998 inst.instruction |= Rd | (Rs << 3);
10999 end_of_line (str);
11000 }
11001
11002 static void
11003 do_t_add (str)
11004 char * str;
11005 {
11006 thumb_add_sub (str, 0);
11007 }
11008
11009 static void
11010 do_t_asr (str)
11011 char * str;
11012 {
11013 thumb_shift (str, THUMB_ASR);
11014 }
11015
11016 static void
11017 do_t_branch9 (str)
11018 char * str;
11019 {
11020 if (my_get_expression (&inst.reloc.exp, &str))
11021 return;
11022 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH9;
11023 inst.reloc.pc_rel = 1;
11024 end_of_line (str);
11025 }
11026
11027 static void
11028 do_t_branch12 (str)
11029 char * str;
11030 {
11031 if (my_get_expression (&inst.reloc.exp, &str))
11032 return;
11033 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH12;
11034 inst.reloc.pc_rel = 1;
11035 end_of_line (str);
11036 }
11037
11038 /* Find the real, Thumb encoded start of a Thumb function. */
11039
11040 static symbolS *
11041 find_real_start (symbolP)
11042 symbolS * symbolP;
11043 {
11044 char * real_start;
11045 const char * name = S_GET_NAME (symbolP);
11046 symbolS * new_target;
11047
11048 /* This definition must agree with the one in gcc/config/arm/thumb.c. */
11049 #define STUB_NAME ".real_start_of"
11050
11051 if (name == NULL)
11052 abort ();
11053
11054 /* Names that start with '.' are local labels, not function entry points.
11055 The compiler may generate BL instructions to these labels because it
11056 needs to perform a branch to a far away location. */
11057 if (name[0] == '.')
11058 return symbolP;
11059
11060 real_start = malloc (strlen (name) + strlen (STUB_NAME) + 1);
11061 sprintf (real_start, "%s%s", STUB_NAME, name);
11062
11063 new_target = symbol_find (real_start);
11064
11065 if (new_target == NULL)
11066 {
11067 as_warn ("Failed to find real start of function: %s\n", name);
11068 new_target = symbolP;
11069 }
11070
11071 free (real_start);
11072
11073 return new_target;
11074 }
11075
11076 static void
11077 do_t_branch23 (str)
11078 char * str;
11079 {
11080 if (my_get_expression (& inst.reloc.exp, & str))
11081 return;
11082
11083 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH23;
11084 inst.reloc.pc_rel = 1;
11085 end_of_line (str);
11086
11087 /* If the destination of the branch is a defined symbol which does not have
11088 the THUMB_FUNC attribute, then we must be calling a function which has
11089 the (interfacearm) attribute. We look for the Thumb entry point to that
11090 function and change the branch to refer to that function instead. */
11091 if ( inst.reloc.exp.X_op == O_symbol
11092 && inst.reloc.exp.X_add_symbol != NULL
11093 && S_IS_DEFINED (inst.reloc.exp.X_add_symbol)
11094 && ! THUMB_IS_FUNC (inst.reloc.exp.X_add_symbol))
11095 inst.reloc.exp.X_add_symbol =
11096 find_real_start (inst.reloc.exp.X_add_symbol);
11097 }
11098
11099 static void
11100 do_t_bx (str)
11101 char * str;
11102 {
11103 int reg;
11104
11105 skip_whitespace (str);
11106
11107 if ((reg = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
11108 return;
11109
11110 /* This sets THUMB_H2 from the top bit of reg. */
11111 inst.instruction |= reg << 3;
11112
11113 /* ??? FIXME: Should add a hacky reloc here if reg is REG_PC. The reloc
11114 should cause the alignment to be checked once it is known. This is
11115 because BX PC only works if the instruction is word aligned. */
11116
11117 end_of_line (str);
11118 }
11119
11120 static void
11121 do_t_compare (str)
11122 char * str;
11123 {
11124 thumb_mov_compare (str, THUMB_COMPARE);
11125 }
11126
11127 static void
11128 do_t_ldmstm (str)
11129 char * str;
11130 {
11131 int Rb;
11132 long range;
11133
11134 skip_whitespace (str);
11135
11136 if ((Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
11137 return;
11138
11139 if (*str != '!')
11140 as_warn (_("inserted missing '!': load/store multiple always writes back base register"));
11141 else
11142 str++;
11143
11144 if (skip_past_comma (&str) == FAIL
11145 || (range = reg_list (&str)) == FAIL)
11146 {
11147 if (! inst.error)
11148 inst.error = BAD_ARGS;
11149 return;
11150 }
11151
11152 if (inst.reloc.type != BFD_RELOC_NONE)
11153 {
11154 /* This really doesn't seem worth it. */
11155 inst.reloc.type = BFD_RELOC_NONE;
11156 inst.error = _("expression too complex");
11157 return;
11158 }
11159
11160 if (range & ~0xff)
11161 {
11162 inst.error = _("only lo-regs valid in load/store multiple");
11163 return;
11164 }
11165
11166 inst.instruction |= (Rb << 8) | range;
11167 end_of_line (str);
11168 }
11169
11170 static void
11171 do_t_ldr (str)
11172 char * str;
11173 {
11174 thumb_load_store (str, THUMB_LOAD, THUMB_WORD);
11175 }
11176
11177 static void
11178 do_t_ldrb (str)
11179 char * str;
11180 {
11181 thumb_load_store (str, THUMB_LOAD, THUMB_BYTE);
11182 }
11183
11184 static void
11185 do_t_ldrh (str)
11186 char * str;
11187 {
11188 thumb_load_store (str, THUMB_LOAD, THUMB_HALFWORD);
11189 }
11190
11191 static void
11192 do_t_lds (str)
11193 char * str;
11194 {
11195 int Rd, Rb, Ro;
11196
11197 skip_whitespace (str);
11198
11199 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
11200 || skip_past_comma (&str) == FAIL
11201 || *str++ != '['
11202 || (Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL
11203 || skip_past_comma (&str) == FAIL
11204 || (Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL
11205 || *str++ != ']')
11206 {
11207 if (! inst.error)
11208 inst.error = _("syntax: ldrs[b] Rd, [Rb, Ro]");
11209 return;
11210 }
11211
11212 inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
11213 end_of_line (str);
11214 }
11215
11216 static void
11217 do_t_lsl (str)
11218 char * str;
11219 {
11220 thumb_shift (str, THUMB_LSL);
11221 }
11222
11223 static void
11224 do_t_lsr (str)
11225 char * str;
11226 {
11227 thumb_shift (str, THUMB_LSR);
11228 }
11229
11230 static void
11231 do_t_mov (str)
11232 char * str;
11233 {
11234 thumb_mov_compare (str, THUMB_MOVE);
11235 }
11236
11237 static void
11238 do_t_push_pop (str)
11239 char * str;
11240 {
11241 long range;
11242
11243 skip_whitespace (str);
11244
11245 if ((range = reg_list (&str)) == FAIL)
11246 {
11247 if (! inst.error)
11248 inst.error = BAD_ARGS;
11249 return;
11250 }
11251
11252 if (inst.reloc.type != BFD_RELOC_NONE)
11253 {
11254 /* This really doesn't seem worth it. */
11255 inst.reloc.type = BFD_RELOC_NONE;
11256 inst.error = _("expression too complex");
11257 return;
11258 }
11259
11260 if (range & ~0xff)
11261 {
11262 if ((inst.instruction == T_OPCODE_PUSH
11263 && (range & ~0xff) == 1 << REG_LR)
11264 || (inst.instruction == T_OPCODE_POP
11265 && (range & ~0xff) == 1 << REG_PC))
11266 {
11267 inst.instruction |= THUMB_PP_PC_LR;
11268 range &= 0xff;
11269 }
11270 else
11271 {
11272 inst.error = _("invalid register list to push/pop instruction");
11273 return;
11274 }
11275 }
11276
11277 inst.instruction |= range;
11278 end_of_line (str);
11279 }
11280
11281 static void
11282 do_t_str (str)
11283 char * str;
11284 {
11285 thumb_load_store (str, THUMB_STORE, THUMB_WORD);
11286 }
11287
11288 static void
11289 do_t_strb (str)
11290 char * str;
11291 {
11292 thumb_load_store (str, THUMB_STORE, THUMB_BYTE);
11293 }
11294
11295 static void
11296 do_t_strh (str)
11297 char * str;
11298 {
11299 thumb_load_store (str, THUMB_STORE, THUMB_HALFWORD);
11300 }
11301
11302 static void
11303 do_t_sub (str)
11304 char * str;
11305 {
11306 thumb_add_sub (str, 1);
11307 }
11308
11309 static void
11310 do_t_swi (str)
11311 char * str;
11312 {
11313 skip_whitespace (str);
11314
11315 if (my_get_expression (&inst.reloc.exp, &str))
11316 return;
11317
11318 inst.reloc.type = BFD_RELOC_ARM_SWI;
11319 end_of_line (str);
11320 }
11321
11322 static void
11323 do_t_adr (str)
11324 char * str;
11325 {
11326 int reg;
11327
11328 /* This is a pseudo-op of the form "adr rd, label" to be converted
11329 into a relative address of the form "add rd, pc, #label-.-4". */
11330 skip_whitespace (str);
11331
11332 /* Store Rd in temporary location inside instruction. */
11333 if ((reg = reg_required_here (&str, 4)) == FAIL
11334 || (reg > 7) /* For Thumb reg must be r0..r7. */
11335 || skip_past_comma (&str) == FAIL
11336 || my_get_expression (&inst.reloc.exp, &str))
11337 {
11338 if (!inst.error)
11339 inst.error = BAD_ARGS;
11340 return;
11341 }
11342
11343 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
11344 inst.reloc.exp.X_add_number -= 4; /* PC relative adjust. */
11345 inst.reloc.pc_rel = 1;
11346 inst.instruction |= REG_PC; /* Rd is already placed into the instruction. */
11347
11348 end_of_line (str);
11349 }
11350
11351 static void
11352 insert_reg (r, htab)
11353 const struct reg_entry *r;
11354 struct hash_control *htab;
11355 {
11356 int len = strlen (r->name) + 2;
11357 char * buf = (char *) xmalloc (len);
11358 char * buf2 = (char *) xmalloc (len);
11359 int i = 0;
11360
11361 #ifdef REGISTER_PREFIX
11362 buf[i++] = REGISTER_PREFIX;
11363 #endif
11364
11365 strcpy (buf + i, r->name);
11366
11367 for (i = 0; buf[i]; i++)
11368 buf2[i] = TOUPPER (buf[i]);
11369
11370 buf2[i] = '\0';
11371
11372 hash_insert (htab, buf, (PTR) r);
11373 hash_insert (htab, buf2, (PTR) r);
11374 }
11375
11376 static void
11377 build_reg_hsh (map)
11378 struct reg_map *map;
11379 {
11380 const struct reg_entry *r;
11381
11382 if ((map->htab = hash_new ()) == NULL)
11383 as_fatal (_("virtual memory exhausted"));
11384
11385 for (r = map->names; r->name != NULL; r++)
11386 insert_reg (r, map->htab);
11387 }
11388
11389 static void
11390 insert_reg_alias (str, regnum, htab)
11391 char *str;
11392 int regnum;
11393 struct hash_control *htab;
11394 {
11395 const char *error;
11396 struct reg_entry *new = xmalloc (sizeof (struct reg_entry));
11397 const char *name = xmalloc (strlen (str) + 1);
11398
11399 strcpy ((char *) name, str);
11400
11401 new->name = name;
11402 new->number = regnum;
11403 new->builtin = FALSE;
11404
11405 error = hash_insert (htab, name, (PTR) new);
11406 if (error)
11407 {
11408 as_bad (_("failed to create an alias for %s, reason: %s"),
11409 str, error);
11410 free ((char *) name);
11411 free (new);
11412 }
11413 }
11414
11415 /* Look for the .req directive. This is of the form:
11416
11417 new_register_name .req existing_register_name
11418
11419 If we find one, or if it looks sufficiently like one that we want to
11420 handle any error here, return non-zero. Otherwise return zero. */
11421 static int
11422 create_register_alias (newname, p)
11423 char *newname;
11424 char *p;
11425 {
11426 char *q;
11427 char c;
11428
11429 q = p;
11430 skip_whitespace (q);
11431
11432 c = *p;
11433 *p = '\0';
11434
11435 if (*q && !strncmp (q, ".req ", 5))
11436 {
11437 char *copy_of_str;
11438 char *r;
11439
11440 #ifdef IGNORE_OPCODE_CASE
11441 newname = original_case_string;
11442 #endif
11443 copy_of_str = newname;
11444
11445 q += 4;
11446 skip_whitespace (q);
11447
11448 for (r = q; *r != '\0'; r++)
11449 if (*r == ' ')
11450 break;
11451
11452 if (r != q)
11453 {
11454 enum arm_reg_type new_type, old_type;
11455 int old_regno;
11456 char d = *r;
11457
11458 *r = '\0';
11459 old_type = arm_reg_parse_any (q);
11460 *r = d;
11461
11462 new_type = arm_reg_parse_any (newname);
11463
11464 if (new_type == REG_TYPE_MAX)
11465 {
11466 if (old_type != REG_TYPE_MAX)
11467 {
11468 old_regno = arm_reg_parse (&q, all_reg_maps[old_type].htab);
11469 insert_reg_alias (newname, old_regno,
11470 all_reg_maps[old_type].htab);
11471 }
11472 else
11473 as_warn (_("register '%s' does not exist\n"), q);
11474 }
11475 else if (old_type == REG_TYPE_MAX)
11476 {
11477 as_warn (_("ignoring redefinition of register alias '%s' to non-existant register '%s'"),
11478 copy_of_str, q);
11479 }
11480 else
11481 {
11482 /* Do not warn about redefinitions to the same alias. */
11483 if (new_type != old_type
11484 || (arm_reg_parse (&q, all_reg_maps[old_type].htab)
11485 != arm_reg_parse (&q, all_reg_maps[new_type].htab)))
11486 as_warn (_("ignoring redefinition of register alias '%s'"),
11487 copy_of_str);
11488
11489 }
11490 }
11491 else
11492 as_warn (_("ignoring incomplete .req pseuso op"));
11493
11494 *p = c;
11495 return 1;
11496 }
11497
11498 *p = c;
11499 return 0;
11500 }
11501
11502 static void
11503 set_constant_flonums ()
11504 {
11505 int i;
11506
11507 for (i = 0; i < NUM_FLOAT_VALS; i++)
11508 if (atof_ieee ((char *) fp_const[i], 'x', fp_values[i]) == NULL)
11509 abort ();
11510 }
11511
11512 /* Iterate over the base tables to create the instruction patterns. */
11513 static void
11514 build_arm_ops_hsh ()
11515 {
11516 unsigned int i;
11517 unsigned int j;
11518 static struct obstack insn_obstack;
11519
11520 obstack_begin (&insn_obstack, 4000);
11521
11522 for (i = 0; i < sizeof (insns) / sizeof (struct asm_opcode); i++)
11523 {
11524 const struct asm_opcode *insn = insns + i;
11525
11526 if (insn->cond_offset != 0)
11527 {
11528 /* Insn supports conditional execution. Build the varaints
11529 and insert them in the hash table. */
11530 for (j = 0; j < sizeof (conds) / sizeof (struct asm_cond); j++)
11531 {
11532 unsigned len = strlen (insn->template);
11533 struct asm_opcode *new;
11534 char *template;
11535
11536 new = obstack_alloc (&insn_obstack, sizeof (struct asm_opcode));
11537 /* All condition codes are two characters. */
11538 template = obstack_alloc (&insn_obstack, len + 3);
11539
11540 strncpy (template, insn->template, insn->cond_offset);
11541 strcpy (template + insn->cond_offset, conds[j].template);
11542 if (len > insn->cond_offset)
11543 strcpy (template + insn->cond_offset + 2,
11544 insn->template + insn->cond_offset);
11545 new->template = template;
11546 new->cond_offset = 0;
11547 new->variant = insn->variant;
11548 new->parms = insn->parms;
11549 new->value = (insn->value & ~COND_MASK) | conds[j].value;
11550
11551 hash_insert (arm_ops_hsh, new->template, (PTR) new);
11552 }
11553 }
11554 /* Finally, insert the unconditional insn in the table directly;
11555 no need to build a copy. */
11556 hash_insert (arm_ops_hsh, insn->template, (PTR) insn);
11557 }
11558 }
11559
11560 #if 0 /* Suppressed - for now. */
11561 #if defined OBJ_ELF || defined OBJ_COFF
11562
11563 #ifdef OBJ_ELF
11564 #define arm_Note Elf_External_Note
11565 #else
11566 typedef struct
11567 {
11568 unsigned char namesz[4]; /* Size of entry's owner string. */
11569 unsigned char descsz[4]; /* Size of the note descriptor. */
11570 unsigned char type[4]; /* Interpretation of the descriptor. */
11571 char name[1]; /* Start of the name+desc data. */
11572 } arm_Note;
11573 #endif
11574
11575 /* The description is kept to a fix sized in order to make updating
11576 it and merging it easier. */
11577 #define ARM_NOTE_DESCRIPTION_LENGTH 8
11578
11579 static void
11580 arm_add_note (name, description, type)
11581 const char * name;
11582 const char * description;
11583 unsigned int type;
11584 {
11585 arm_Note note ATTRIBUTE_UNUSED;
11586 char * p;
11587 unsigned int name_len;
11588
11589 name_len = (strlen (name) + 1 + 3) & ~3;
11590
11591 p = frag_more (sizeof (note.namesz));
11592 md_number_to_chars (p, (valueT) name_len, sizeof (note.namesz));
11593
11594 p = frag_more (sizeof (note.descsz));
11595 md_number_to_chars (p, (valueT) ARM_NOTE_DESCRIPTION_LENGTH, sizeof (note.descsz));
11596
11597 p = frag_more (sizeof (note.type));
11598 md_number_to_chars (p, (valueT) type, sizeof (note.type));
11599
11600 p = frag_more (name_len);
11601 strcpy (p, name);
11602
11603 p = frag_more (ARM_NOTE_DESCRIPTION_LENGTH);
11604 strncpy (p, description, ARM_NOTE_DESCRIPTION_LENGTH);
11605 frag_align (2, 0, 0);
11606 }
11607 #endif
11608 #endif
11609
11610 void
11611 md_begin ()
11612 {
11613 unsigned mach;
11614 unsigned int i;
11615
11616 if ( (arm_ops_hsh = hash_new ()) == NULL
11617 || (arm_tops_hsh = hash_new ()) == NULL
11618 || (arm_cond_hsh = hash_new ()) == NULL
11619 || (arm_shift_hsh = hash_new ()) == NULL
11620 || (arm_psr_hsh = hash_new ()) == NULL)
11621 as_fatal (_("virtual memory exhausted"));
11622
11623 build_arm_ops_hsh ();
11624 for (i = 0; i < sizeof (tinsns) / sizeof (struct thumb_opcode); i++)
11625 hash_insert (arm_tops_hsh, tinsns[i].template, (PTR) (tinsns + i));
11626 for (i = 0; i < sizeof (conds) / sizeof (struct asm_cond); i++)
11627 hash_insert (arm_cond_hsh, conds[i].template, (PTR) (conds + i));
11628 for (i = 0; i < sizeof (shift_names) / sizeof (struct asm_shift_name); i++)
11629 hash_insert (arm_shift_hsh, shift_names[i].name, (PTR) (shift_names + i));
11630 for (i = 0; i < sizeof (psrs) / sizeof (struct asm_psr); i++)
11631 hash_insert (arm_psr_hsh, psrs[i].template, (PTR) (psrs + i));
11632
11633 for (i = (int) REG_TYPE_FIRST; i < (int) REG_TYPE_MAX; i++)
11634 build_reg_hsh (all_reg_maps + i);
11635
11636 set_constant_flonums ();
11637
11638 /* Set the cpu variant based on the command-line options. We prefer
11639 -mcpu= over -march= if both are set (as for GCC); and we prefer
11640 -mfpu= over any other way of setting the floating point unit.
11641 Use of legacy options with new options are faulted. */
11642 if (legacy_cpu != -1)
11643 {
11644 if (mcpu_cpu_opt != -1 || march_cpu_opt != -1)
11645 as_bad (_("use of old and new-style options to set CPU type"));
11646
11647 mcpu_cpu_opt = legacy_cpu;
11648 }
11649 else if (mcpu_cpu_opt == -1)
11650 mcpu_cpu_opt = march_cpu_opt;
11651
11652 if (legacy_fpu != -1)
11653 {
11654 if (mfpu_opt != -1)
11655 as_bad (_("use of old and new-style options to set FPU type"));
11656
11657 mfpu_opt = legacy_fpu;
11658 }
11659 else if (mfpu_opt == -1)
11660 {
11661 #if !(defined (TE_LINUX) || defined (TE_NetBSD))
11662 /* Some environments specify a default FPU. If they don't, infer it
11663 from the processor. */
11664 if (mcpu_fpu_opt != -1)
11665 mfpu_opt = mcpu_fpu_opt;
11666 else
11667 mfpu_opt = march_fpu_opt;
11668 #else
11669 mfpu_opt = FPU_DEFAULT;
11670 #endif
11671 }
11672
11673 if (mfpu_opt == -1)
11674 {
11675 if (mcpu_cpu_opt == -1)
11676 mfpu_opt = FPU_DEFAULT;
11677 else if (mcpu_cpu_opt & ARM_EXT_V5)
11678 mfpu_opt = FPU_ARCH_VFP_V2;
11679 else
11680 mfpu_opt = FPU_ARCH_FPA;
11681 }
11682
11683 if (mcpu_cpu_opt == -1)
11684 mcpu_cpu_opt = CPU_DEFAULT;
11685
11686 cpu_variant = mcpu_cpu_opt | mfpu_opt;
11687
11688 #if defined OBJ_COFF || defined OBJ_ELF
11689 {
11690 unsigned int flags = 0;
11691
11692 /* Set the flags in the private structure. */
11693 if (uses_apcs_26) flags |= F_APCS26;
11694 if (support_interwork) flags |= F_INTERWORK;
11695 if (uses_apcs_float) flags |= F_APCS_FLOAT;
11696 if (pic_code) flags |= F_PIC;
11697 if ((cpu_variant & FPU_ANY) == FPU_NONE
11698 || (cpu_variant & FPU_ANY) == FPU_ARCH_VFP) /* VFP layout only. */
11699 {
11700 flags |= F_SOFT_FLOAT;
11701 }
11702 switch (mfloat_abi_opt)
11703 {
11704 case ARM_FLOAT_ABI_SOFT:
11705 case ARM_FLOAT_ABI_SOFTFP:
11706 flags |= F_SOFT_FLOAT;
11707 break;
11708
11709 case ARM_FLOAT_ABI_HARD:
11710 if (flags & F_SOFT_FLOAT)
11711 as_bad (_("hard-float conflicts with specified fpu"));
11712 break;
11713 }
11714 /* Using VFP conventions (even if soft-float). */
11715 if (cpu_variant & FPU_VFP_EXT_NONE) flags |= F_VFP_FLOAT;
11716
11717 #if defined OBJ_ELF
11718 if (cpu_variant & FPU_ARCH_MAVERICK)
11719 flags |= EF_ARM_MAVERICK_FLOAT;
11720 #endif
11721
11722 bfd_set_private_flags (stdoutput, flags);
11723
11724 /* We have run out flags in the COFF header to encode the
11725 status of ATPCS support, so instead we create a dummy,
11726 empty, debug section called .arm.atpcs. */
11727 if (atpcs)
11728 {
11729 asection * sec;
11730
11731 sec = bfd_make_section (stdoutput, ".arm.atpcs");
11732
11733 if (sec != NULL)
11734 {
11735 bfd_set_section_flags
11736 (stdoutput, sec, SEC_READONLY | SEC_DEBUGGING /* | SEC_HAS_CONTENTS */);
11737 bfd_set_section_size (stdoutput, sec, 0);
11738 bfd_set_section_contents (stdoutput, sec, NULL, 0, 0);
11739 }
11740 }
11741 }
11742 #endif
11743
11744 /* Record the CPU type as well. */
11745 switch (cpu_variant & ARM_CPU_MASK)
11746 {
11747 case ARM_2:
11748 mach = bfd_mach_arm_2;
11749 break;
11750
11751 case ARM_3: /* Also ARM_250. */
11752 mach = bfd_mach_arm_2a;
11753 break;
11754
11755 case ARM_6: /* Also ARM_7. */
11756 mach = bfd_mach_arm_3;
11757 break;
11758
11759 default:
11760 mach = bfd_mach_arm_unknown;
11761 break;
11762 }
11763
11764 /* Catch special cases. */
11765 if (cpu_variant & ARM_CEXT_IWMMXT)
11766 mach = bfd_mach_arm_iWMMXt;
11767 else if (cpu_variant & ARM_CEXT_XSCALE)
11768 mach = bfd_mach_arm_XScale;
11769 else if (cpu_variant & ARM_CEXT_MAVERICK)
11770 mach = bfd_mach_arm_ep9312;
11771 else if (cpu_variant & ARM_EXT_V5E)
11772 mach = bfd_mach_arm_5TE;
11773 else if (cpu_variant & ARM_EXT_V5)
11774 {
11775 if (cpu_variant & ARM_EXT_V4T)
11776 mach = bfd_mach_arm_5T;
11777 else
11778 mach = bfd_mach_arm_5;
11779 }
11780 else if (cpu_variant & ARM_EXT_V4)
11781 {
11782 if (cpu_variant & ARM_EXT_V4T)
11783 mach = bfd_mach_arm_4T;
11784 else
11785 mach = bfd_mach_arm_4;
11786 }
11787 else if (cpu_variant & ARM_EXT_V3M)
11788 mach = bfd_mach_arm_3M;
11789
11790 #if 0 /* Suppressed - for now. */
11791 #if defined (OBJ_ELF) || defined (OBJ_COFF)
11792
11793 /* Create a .note section to fully identify this arm binary. */
11794
11795 #define NOTE_ARCH_STRING "arch: "
11796
11797 #if defined OBJ_COFF && ! defined NT_VERSION
11798 #define NT_VERSION 1
11799 #define NT_ARCH 2
11800 #endif
11801
11802 {
11803 segT current_seg = now_seg;
11804 subsegT current_subseg = now_subseg;
11805 asection * arm_arch;
11806 const char * arch_string;
11807
11808 arm_arch = bfd_make_section_old_way (stdoutput, ARM_NOTE_SECTION);
11809
11810 #ifdef OBJ_COFF
11811 bfd_set_section_flags (stdoutput, arm_arch,
11812 SEC_DATA | SEC_ALLOC | SEC_LOAD | SEC_LINK_ONCE \
11813 | SEC_HAS_CONTENTS);
11814 #else
11815 bfd_set_section_flags (stdoutput, arm_arch,
11816 SEC_READONLY | SEC_HAS_CONTENTS);
11817 #endif
11818 arm_arch->output_section = arm_arch;
11819 subseg_set (arm_arch, 0);
11820
11821 switch (mach)
11822 {
11823 default:
11824 case bfd_mach_arm_unknown: arch_string = "unknown"; break;
11825 case bfd_mach_arm_2: arch_string = "armv2"; break;
11826 case bfd_mach_arm_2a: arch_string = "armv2a"; break;
11827 case bfd_mach_arm_3: arch_string = "armv3"; break;
11828 case bfd_mach_arm_3M: arch_string = "armv3M"; break;
11829 case bfd_mach_arm_4: arch_string = "armv4"; break;
11830 case bfd_mach_arm_4T: arch_string = "armv4t"; break;
11831 case bfd_mach_arm_5: arch_string = "armv5"; break;
11832 case bfd_mach_arm_5T: arch_string = "armv5t"; break;
11833 case bfd_mach_arm_5TE: arch_string = "armv5te"; break;
11834 case bfd_mach_arm_XScale: arch_string = "XScale"; break;
11835 case bfd_mach_arm_ep9312: arch_string = "ep9312"; break;
11836 case bfd_mach_arm_iWMMXt: arch_string = "iWMMXt"; break;
11837 }
11838
11839 arm_add_note (NOTE_ARCH_STRING, arch_string, NT_ARCH);
11840
11841 subseg_set (current_seg, current_subseg);
11842 }
11843 #endif
11844 #endif /* Suppressed code. */
11845
11846 bfd_set_arch_mach (stdoutput, TARGET_ARCH, mach);
11847 }
11848
11849 /* Turn an integer of n bytes (in val) into a stream of bytes appropriate
11850 for use in the a.out file, and stores them in the array pointed to by buf.
11851 This knows about the endian-ness of the target machine and does
11852 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
11853 2 (short) and 4 (long) Floating numbers are put out as a series of
11854 LITTLENUMS (shorts, here at least). */
11855
11856 void
11857 md_number_to_chars (buf, val, n)
11858 char * buf;
11859 valueT val;
11860 int n;
11861 {
11862 if (target_big_endian)
11863 number_to_chars_bigendian (buf, val, n);
11864 else
11865 number_to_chars_littleendian (buf, val, n);
11866 }
11867
11868 static valueT
11869 md_chars_to_number (buf, n)
11870 char * buf;
11871 int n;
11872 {
11873 valueT result = 0;
11874 unsigned char * where = (unsigned char *) buf;
11875
11876 if (target_big_endian)
11877 {
11878 while (n--)
11879 {
11880 result <<= 8;
11881 result |= (*where++ & 255);
11882 }
11883 }
11884 else
11885 {
11886 while (n--)
11887 {
11888 result <<= 8;
11889 result |= (where[n] & 255);
11890 }
11891 }
11892
11893 return result;
11894 }
11895
11896 /* Turn a string in input_line_pointer into a floating point constant
11897 of type TYPE, and store the appropriate bytes in *LITP. The number
11898 of LITTLENUMS emitted is stored in *SIZEP. An error message is
11899 returned, or NULL on OK.
11900
11901 Note that fp constants aren't represent in the normal way on the ARM.
11902 In big endian mode, things are as expected. However, in little endian
11903 mode fp constants are big-endian word-wise, and little-endian byte-wise
11904 within the words. For example, (double) 1.1 in big endian mode is
11905 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
11906 the byte sequence 99 99 f1 3f 9a 99 99 99.
11907
11908 ??? The format of 12 byte floats is uncertain according to gcc's arm.h. */
11909
11910 char *
11911 md_atof (type, litP, sizeP)
11912 char type;
11913 char * litP;
11914 int * sizeP;
11915 {
11916 int prec;
11917 LITTLENUM_TYPE words[MAX_LITTLENUMS];
11918 char *t;
11919 int i;
11920
11921 switch (type)
11922 {
11923 case 'f':
11924 case 'F':
11925 case 's':
11926 case 'S':
11927 prec = 2;
11928 break;
11929
11930 case 'd':
11931 case 'D':
11932 case 'r':
11933 case 'R':
11934 prec = 4;
11935 break;
11936
11937 case 'x':
11938 case 'X':
11939 prec = 6;
11940 break;
11941
11942 case 'p':
11943 case 'P':
11944 prec = 6;
11945 break;
11946
11947 default:
11948 *sizeP = 0;
11949 return _("bad call to MD_ATOF()");
11950 }
11951
11952 t = atof_ieee (input_line_pointer, type, words);
11953 if (t)
11954 input_line_pointer = t;
11955 *sizeP = prec * 2;
11956
11957 if (target_big_endian)
11958 {
11959 for (i = 0; i < prec; i++)
11960 {
11961 md_number_to_chars (litP, (valueT) words[i], 2);
11962 litP += 2;
11963 }
11964 }
11965 else
11966 {
11967 if (cpu_variant & FPU_ARCH_VFP)
11968 for (i = prec - 1; i >= 0; i--)
11969 {
11970 md_number_to_chars (litP, (valueT) words[i], 2);
11971 litP += 2;
11972 }
11973 else
11974 /* For a 4 byte float the order of elements in `words' is 1 0.
11975 For an 8 byte float the order is 1 0 3 2. */
11976 for (i = 0; i < prec; i += 2)
11977 {
11978 md_number_to_chars (litP, (valueT) words[i + 1], 2);
11979 md_number_to_chars (litP + 2, (valueT) words[i], 2);
11980 litP += 4;
11981 }
11982 }
11983
11984 return 0;
11985 }
11986
11987 /* The knowledge of the PC's pipeline offset is built into the insns
11988 themselves. */
11989
11990 long
11991 md_pcrel_from (fixP)
11992 fixS * fixP;
11993 {
11994 if (fixP->fx_addsy
11995 && S_GET_SEGMENT (fixP->fx_addsy) == undefined_section
11996 && fixP->fx_subsy == NULL)
11997 return 0;
11998
11999 if (fixP->fx_pcrel && (fixP->fx_r_type == BFD_RELOC_ARM_THUMB_ADD))
12000 {
12001 /* PC relative addressing on the Thumb is slightly odd
12002 as the bottom two bits of the PC are forced to zero
12003 for the calculation. */
12004 return (fixP->fx_where + fixP->fx_frag->fr_address) & ~3;
12005 }
12006
12007 #ifdef TE_WINCE
12008 /* The pattern was adjusted to accommodate CE's off-by-one fixups,
12009 so we un-adjust here to compensate for the accommodation. */
12010 return fixP->fx_where + fixP->fx_frag->fr_address + 8;
12011 #else
12012 return fixP->fx_where + fixP->fx_frag->fr_address;
12013 #endif
12014 }
12015
12016 /* Round up a section size to the appropriate boundary. */
12017
12018 valueT
12019 md_section_align (segment, size)
12020 segT segment ATTRIBUTE_UNUSED;
12021 valueT size;
12022 {
12023 #ifdef OBJ_ELF
12024 return size;
12025 #else
12026 /* Round all sects to multiple of 4. */
12027 return (size + 3) & ~3;
12028 #endif
12029 }
12030
12031 /* Under ELF we need to default _GLOBAL_OFFSET_TABLE.
12032 Otherwise we have no need to default values of symbols. */
12033
12034 symbolS *
12035 md_undefined_symbol (name)
12036 char * name ATTRIBUTE_UNUSED;
12037 {
12038 #ifdef OBJ_ELF
12039 if (name[0] == '_' && name[1] == 'G'
12040 && streq (name, GLOBAL_OFFSET_TABLE_NAME))
12041 {
12042 if (!GOT_symbol)
12043 {
12044 if (symbol_find (name))
12045 as_bad ("GOT already in the symbol table");
12046
12047 GOT_symbol = symbol_new (name, undefined_section,
12048 (valueT) 0, & zero_address_frag);
12049 }
12050
12051 return GOT_symbol;
12052 }
12053 #endif
12054
12055 return 0;
12056 }
12057
12058 /* arm_reg_parse () := if it looks like a register, return its token and
12059 advance the pointer. */
12060
12061 static int
12062 arm_reg_parse (ccp, htab)
12063 register char ** ccp;
12064 struct hash_control *htab;
12065 {
12066 char * start = * ccp;
12067 char c;
12068 char * p;
12069 struct reg_entry * reg;
12070
12071 #ifdef REGISTER_PREFIX
12072 if (*start != REGISTER_PREFIX)
12073 return FAIL;
12074 p = start + 1;
12075 #else
12076 p = start;
12077 #ifdef OPTIONAL_REGISTER_PREFIX
12078 if (*p == OPTIONAL_REGISTER_PREFIX)
12079 p++, start++;
12080 #endif
12081 #endif
12082 if (!ISALPHA (*p) || !is_name_beginner (*p))
12083 return FAIL;
12084
12085 c = *p++;
12086 while (ISALPHA (c) || ISDIGIT (c) || c == '_')
12087 c = *p++;
12088
12089 *--p = 0;
12090 reg = (struct reg_entry *) hash_find (htab, start);
12091 *p = c;
12092
12093 if (reg)
12094 {
12095 *ccp = p;
12096 return reg->number;
12097 }
12098
12099 return FAIL;
12100 }
12101
12102 /* Search for the following register name in each of the possible reg name
12103 tables. Return the classification if found, or REG_TYPE_MAX if not
12104 present. */
12105 static enum arm_reg_type
12106 arm_reg_parse_any (cp)
12107 char *cp;
12108 {
12109 int i;
12110
12111 for (i = (int) REG_TYPE_FIRST; i < (int) REG_TYPE_MAX; i++)
12112 if (arm_reg_parse (&cp, all_reg_maps[i].htab) != FAIL)
12113 return (enum arm_reg_type) i;
12114
12115 return REG_TYPE_MAX;
12116 }
12117
12118 void
12119 md_apply_fix3 (fixP, valP, seg)
12120 fixS * fixP;
12121 valueT * valP;
12122 segT seg;
12123 {
12124 offsetT value = * valP;
12125 offsetT newval;
12126 unsigned int newimm;
12127 unsigned long temp;
12128 int sign;
12129 char * buf = fixP->fx_where + fixP->fx_frag->fr_literal;
12130 arm_fix_data * arm_data = (arm_fix_data *) fixP->tc_fix_data;
12131
12132 assert (fixP->fx_r_type < BFD_RELOC_UNUSED);
12133
12134 /* Note whether this will delete the relocation. */
12135 #if 0
12136 /* Patch from REarnshaw to JDavis (disabled for the moment, since it
12137 doesn't work fully.) */
12138 if ((fixP->fx_addsy == 0 || symbol_constant_p (fixP->fx_addsy))
12139 && !fixP->fx_pcrel)
12140 #else
12141 if (fixP->fx_addsy == 0 && !fixP->fx_pcrel)
12142 #endif
12143 fixP->fx_done = 1;
12144
12145 /* If this symbol is in a different section then we need to leave it for
12146 the linker to deal with. Unfortunately, md_pcrel_from can't tell,
12147 so we have to undo it's effects here. */
12148 if (fixP->fx_pcrel)
12149 {
12150 if (fixP->fx_addsy != NULL
12151 && S_IS_DEFINED (fixP->fx_addsy)
12152 && S_GET_SEGMENT (fixP->fx_addsy) != seg)
12153 {
12154 if (target_oabi
12155 && (fixP->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH
12156 || fixP->fx_r_type == BFD_RELOC_ARM_PCREL_BLX
12157 ))
12158 value = 0;
12159 else
12160 value += md_pcrel_from (fixP);
12161 }
12162 }
12163
12164 /* Remember value for emit_reloc. */
12165 fixP->fx_addnumber = value;
12166
12167 switch (fixP->fx_r_type)
12168 {
12169 case BFD_RELOC_ARM_IMMEDIATE:
12170 newimm = validate_immediate (value);
12171 temp = md_chars_to_number (buf, INSN_SIZE);
12172
12173 /* If the instruction will fail, see if we can fix things up by
12174 changing the opcode. */
12175 if (newimm == (unsigned int) FAIL
12176 && (newimm = negate_data_op (&temp, value)) == (unsigned int) FAIL)
12177 {
12178 as_bad_where (fixP->fx_file, fixP->fx_line,
12179 _("invalid constant (%lx) after fixup"),
12180 (unsigned long) value);
12181 break;
12182 }
12183
12184 newimm |= (temp & 0xfffff000);
12185 md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
12186 fixP->fx_done = 1;
12187 break;
12188
12189 case BFD_RELOC_ARM_ADRL_IMMEDIATE:
12190 {
12191 unsigned int highpart = 0;
12192 unsigned int newinsn = 0xe1a00000; /* nop. */
12193
12194 newimm = validate_immediate (value);
12195 temp = md_chars_to_number (buf, INSN_SIZE);
12196
12197 /* If the instruction will fail, see if we can fix things up by
12198 changing the opcode. */
12199 if (newimm == (unsigned int) FAIL
12200 && (newimm = negate_data_op (& temp, value)) == (unsigned int) FAIL)
12201 {
12202 /* No ? OK - try using two ADD instructions to generate
12203 the value. */
12204 newimm = validate_immediate_twopart (value, & highpart);
12205
12206 /* Yes - then make sure that the second instruction is
12207 also an add. */
12208 if (newimm != (unsigned int) FAIL)
12209 newinsn = temp;
12210 /* Still No ? Try using a negated value. */
12211 else if ((newimm = validate_immediate_twopart (- value, & highpart)) != (unsigned int) FAIL)
12212 temp = newinsn = (temp & OPCODE_MASK) | OPCODE_SUB << DATA_OP_SHIFT;
12213 /* Otherwise - give up. */
12214 else
12215 {
12216 as_bad_where (fixP->fx_file, fixP->fx_line,
12217 _("unable to compute ADRL instructions for PC offset of 0x%lx"),
12218 (long) value);
12219 break;
12220 }
12221
12222 /* Replace the first operand in the 2nd instruction (which
12223 is the PC) with the destination register. We have
12224 already added in the PC in the first instruction and we
12225 do not want to do it again. */
12226 newinsn &= ~ 0xf0000;
12227 newinsn |= ((newinsn & 0x0f000) << 4);
12228 }
12229
12230 newimm |= (temp & 0xfffff000);
12231 md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
12232
12233 highpart |= (newinsn & 0xfffff000);
12234 md_number_to_chars (buf + INSN_SIZE, (valueT) highpart, INSN_SIZE);
12235 }
12236 break;
12237
12238 case BFD_RELOC_ARM_OFFSET_IMM:
12239 sign = value >= 0;
12240
12241 if (value < 0)
12242 value = - value;
12243
12244 if (validate_offset_imm (value, 0) == FAIL)
12245 {
12246 as_bad_where (fixP->fx_file, fixP->fx_line,
12247 _("bad immediate value for offset (%ld)"),
12248 (long) value);
12249 break;
12250 }
12251
12252 newval = md_chars_to_number (buf, INSN_SIZE);
12253 newval &= 0xff7ff000;
12254 newval |= value | (sign ? INDEX_UP : 0);
12255 md_number_to_chars (buf, newval, INSN_SIZE);
12256 break;
12257
12258 case BFD_RELOC_ARM_OFFSET_IMM8:
12259 case BFD_RELOC_ARM_HWLITERAL:
12260 sign = value >= 0;
12261
12262 if (value < 0)
12263 value = - value;
12264
12265 if (validate_offset_imm (value, 1) == FAIL)
12266 {
12267 if (fixP->fx_r_type == BFD_RELOC_ARM_HWLITERAL)
12268 as_bad_where (fixP->fx_file, fixP->fx_line,
12269 _("invalid literal constant: pool needs to be closer"));
12270 else
12271 as_bad (_("bad immediate value for half-word offset (%ld)"),
12272 (long) value);
12273 break;
12274 }
12275
12276 newval = md_chars_to_number (buf, INSN_SIZE);
12277 newval &= 0xff7ff0f0;
12278 newval |= ((value >> 4) << 8) | (value & 0xf) | (sign ? INDEX_UP : 0);
12279 md_number_to_chars (buf, newval, INSN_SIZE);
12280 break;
12281
12282 case BFD_RELOC_ARM_LITERAL:
12283 sign = value >= 0;
12284
12285 if (value < 0)
12286 value = - value;
12287
12288 if (validate_offset_imm (value, 0) == FAIL)
12289 {
12290 as_bad_where (fixP->fx_file, fixP->fx_line,
12291 _("invalid literal constant: pool needs to be closer"));
12292 break;
12293 }
12294
12295 newval = md_chars_to_number (buf, INSN_SIZE);
12296 newval &= 0xff7ff000;
12297 newval |= value | (sign ? INDEX_UP : 0);
12298 md_number_to_chars (buf, newval, INSN_SIZE);
12299 break;
12300
12301 case BFD_RELOC_ARM_SHIFT_IMM:
12302 newval = md_chars_to_number (buf, INSN_SIZE);
12303 if (((unsigned long) value) > 32
12304 || (value == 32
12305 && (((newval & 0x60) == 0) || (newval & 0x60) == 0x60)))
12306 {
12307 as_bad_where (fixP->fx_file, fixP->fx_line,
12308 _("shift expression is too large"));
12309 break;
12310 }
12311
12312 if (value == 0)
12313 /* Shifts of zero must be done as lsl. */
12314 newval &= ~0x60;
12315 else if (value == 32)
12316 value = 0;
12317 newval &= 0xfffff07f;
12318 newval |= (value & 0x1f) << 7;
12319 md_number_to_chars (buf, newval, INSN_SIZE);
12320 break;
12321
12322 case BFD_RELOC_ARM_SWI:
12323 if (arm_data->thumb_mode)
12324 {
12325 if (((unsigned long) value) > 0xff)
12326 as_bad_where (fixP->fx_file, fixP->fx_line,
12327 _("invalid swi expression"));
12328 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xff00;
12329 newval |= value;
12330 md_number_to_chars (buf, newval, THUMB_SIZE);
12331 }
12332 else
12333 {
12334 if (((unsigned long) value) > 0x00ffffff)
12335 as_bad_where (fixP->fx_file, fixP->fx_line,
12336 _("invalid swi expression"));
12337 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff000000;
12338 newval |= value;
12339 md_number_to_chars (buf, newval, INSN_SIZE);
12340 }
12341 break;
12342
12343 case BFD_RELOC_ARM_MULTI:
12344 if (((unsigned long) value) > 0xffff)
12345 as_bad_where (fixP->fx_file, fixP->fx_line,
12346 _("invalid expression in load/store multiple"));
12347 newval = value | md_chars_to_number (buf, INSN_SIZE);
12348 md_number_to_chars (buf, newval, INSN_SIZE);
12349 break;
12350
12351 case BFD_RELOC_ARM_PCREL_BRANCH:
12352 newval = md_chars_to_number (buf, INSN_SIZE);
12353
12354 /* Sign-extend a 24-bit number. */
12355 #define SEXT24(x) ((((x) & 0xffffff) ^ (~ 0x7fffff)) + 0x800000)
12356
12357 #ifdef OBJ_ELF
12358 if (! target_oabi)
12359 value = fixP->fx_offset;
12360 #endif
12361
12362 /* We are going to store value (shifted right by two) in the
12363 instruction, in a 24 bit, signed field. Thus we need to check
12364 that none of the top 8 bits of the shifted value (top 7 bits of
12365 the unshifted, unsigned value) are set, or that they are all set. */
12366 if ((value & ~ ((offsetT) 0x1ffffff)) != 0
12367 && ((value & ~ ((offsetT) 0x1ffffff)) != ~ ((offsetT) 0x1ffffff)))
12368 {
12369 #ifdef OBJ_ELF
12370 /* Normally we would be stuck at this point, since we cannot store
12371 the absolute address that is the destination of the branch in the
12372 24 bits of the branch instruction. If however, we happen to know
12373 that the destination of the branch is in the same section as the
12374 branch instruction itself, then we can compute the relocation for
12375 ourselves and not have to bother the linker with it.
12376
12377 FIXME: The tests for OBJ_ELF and ! target_oabi are only here
12378 because I have not worked out how to do this for OBJ_COFF or
12379 target_oabi. */
12380 if (! target_oabi
12381 && fixP->fx_addsy != NULL
12382 && S_IS_DEFINED (fixP->fx_addsy)
12383 && S_GET_SEGMENT (fixP->fx_addsy) == seg)
12384 {
12385 /* Get pc relative value to go into the branch. */
12386 value = * valP;
12387
12388 /* Permit a backward branch provided that enough bits
12389 are set. Allow a forwards branch, provided that
12390 enough bits are clear. */
12391 if ( (value & ~ ((offsetT) 0x1ffffff)) == ~ ((offsetT) 0x1ffffff)
12392 || (value & ~ ((offsetT) 0x1ffffff)) == 0)
12393 fixP->fx_done = 1;
12394 }
12395
12396 if (! fixP->fx_done)
12397 #endif
12398 as_bad_where (fixP->fx_file, fixP->fx_line,
12399 _("GAS can't handle same-section branch dest >= 0x04000000"));
12400 }
12401
12402 value >>= 2;
12403 value += SEXT24 (newval);
12404
12405 if ( (value & ~ ((offsetT) 0xffffff)) != 0
12406 && ((value & ~ ((offsetT) 0xffffff)) != ~ ((offsetT) 0xffffff)))
12407 as_bad_where (fixP->fx_file, fixP->fx_line,
12408 _("out of range branch"));
12409
12410 newval = (value & 0x00ffffff) | (newval & 0xff000000);
12411 md_number_to_chars (buf, newval, INSN_SIZE);
12412 break;
12413
12414 case BFD_RELOC_ARM_PCREL_BLX:
12415 {
12416 offsetT hbit;
12417 newval = md_chars_to_number (buf, INSN_SIZE);
12418
12419 #ifdef OBJ_ELF
12420 if (! target_oabi)
12421 value = fixP->fx_offset;
12422 #endif
12423 hbit = (value >> 1) & 1;
12424 value = (value >> 2) & 0x00ffffff;
12425 value = (value + (newval & 0x00ffffff)) & 0x00ffffff;
12426 newval = value | (newval & 0xfe000000) | (hbit << 24);
12427 md_number_to_chars (buf, newval, INSN_SIZE);
12428 }
12429 break;
12430
12431 case BFD_RELOC_THUMB_PCREL_BRANCH9: /* Conditional branch. */
12432 newval = md_chars_to_number (buf, THUMB_SIZE);
12433 {
12434 addressT diff = (newval & 0xff) << 1;
12435 if (diff & 0x100)
12436 diff |= ~0xff;
12437
12438 value += diff;
12439 if ((value & ~0xff) && ((value & ~0xff) != ~0xff))
12440 as_bad_where (fixP->fx_file, fixP->fx_line,
12441 _("branch out of range"));
12442 newval = (newval & 0xff00) | ((value & 0x1ff) >> 1);
12443 }
12444 md_number_to_chars (buf, newval, THUMB_SIZE);
12445 break;
12446
12447 case BFD_RELOC_THUMB_PCREL_BRANCH12: /* Unconditional branch. */
12448 newval = md_chars_to_number (buf, THUMB_SIZE);
12449 {
12450 addressT diff = (newval & 0x7ff) << 1;
12451 if (diff & 0x800)
12452 diff |= ~0x7ff;
12453
12454 value += diff;
12455 if ((value & ~0x7ff) && ((value & ~0x7ff) != ~0x7ff))
12456 as_bad_where (fixP->fx_file, fixP->fx_line,
12457 _("branch out of range"));
12458 newval = (newval & 0xf800) | ((value & 0xfff) >> 1);
12459 }
12460 md_number_to_chars (buf, newval, THUMB_SIZE);
12461 break;
12462
12463 case BFD_RELOC_THUMB_PCREL_BLX:
12464 case BFD_RELOC_THUMB_PCREL_BRANCH23:
12465 {
12466 offsetT newval2;
12467 addressT diff;
12468
12469 newval = md_chars_to_number (buf, THUMB_SIZE);
12470 newval2 = md_chars_to_number (buf + THUMB_SIZE, THUMB_SIZE);
12471 diff = ((newval & 0x7ff) << 12) | ((newval2 & 0x7ff) << 1);
12472 if (diff & 0x400000)
12473 diff |= ~0x3fffff;
12474 #ifdef OBJ_ELF
12475 value = fixP->fx_offset;
12476 #endif
12477 value += diff;
12478
12479 if ((value & ~0x3fffff) && ((value & ~0x3fffff) != ~0x3fffff))
12480 as_bad_where (fixP->fx_file, fixP->fx_line,
12481 _("branch with link out of range"));
12482
12483 newval = (newval & 0xf800) | ((value & 0x7fffff) >> 12);
12484 newval2 = (newval2 & 0xf800) | ((value & 0xfff) >> 1);
12485 if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX)
12486 /* For a BLX instruction, make sure that the relocation is rounded up
12487 to a word boundary. This follows the semantics of the instruction
12488 which specifies that bit 1 of the target address will come from bit
12489 1 of the base address. */
12490 newval2 = (newval2 + 1) & ~ 1;
12491 md_number_to_chars (buf, newval, THUMB_SIZE);
12492 md_number_to_chars (buf + THUMB_SIZE, newval2, THUMB_SIZE);
12493 }
12494 break;
12495
12496 case BFD_RELOC_8:
12497 if (fixP->fx_done || fixP->fx_pcrel)
12498 md_number_to_chars (buf, value, 1);
12499 #ifdef OBJ_ELF
12500 else if (!target_oabi)
12501 {
12502 value = fixP->fx_offset;
12503 md_number_to_chars (buf, value, 1);
12504 }
12505 #endif
12506 break;
12507
12508 case BFD_RELOC_16:
12509 if (fixP->fx_done || fixP->fx_pcrel)
12510 md_number_to_chars (buf, value, 2);
12511 #ifdef OBJ_ELF
12512 else if (!target_oabi)
12513 {
12514 value = fixP->fx_offset;
12515 md_number_to_chars (buf, value, 2);
12516 }
12517 #endif
12518 break;
12519
12520 #ifdef OBJ_ELF
12521 case BFD_RELOC_ARM_GOT32:
12522 case BFD_RELOC_ARM_GOTOFF:
12523 md_number_to_chars (buf, 0, 4);
12524 break;
12525 #endif
12526
12527 case BFD_RELOC_RVA:
12528 case BFD_RELOC_32:
12529 if (fixP->fx_done || fixP->fx_pcrel)
12530 md_number_to_chars (buf, value, 4);
12531 #ifdef OBJ_ELF
12532 else if (!target_oabi)
12533 {
12534 value = fixP->fx_offset;
12535 md_number_to_chars (buf, value, 4);
12536 }
12537 #endif
12538 break;
12539
12540 #ifdef OBJ_ELF
12541 case BFD_RELOC_ARM_PLT32:
12542 /* It appears the instruction is fully prepared at this point. */
12543 break;
12544 #endif
12545
12546 case BFD_RELOC_ARM_CP_OFF_IMM:
12547 sign = value >= 0;
12548 if (value < -1023 || value > 1023 || (value & 3))
12549 as_bad_where (fixP->fx_file, fixP->fx_line,
12550 _("illegal value for co-processor offset"));
12551 if (value < 0)
12552 value = -value;
12553 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
12554 newval |= (value >> 2) | (sign ? INDEX_UP : 0);
12555 md_number_to_chars (buf, newval, INSN_SIZE);
12556 break;
12557
12558 case BFD_RELOC_ARM_CP_OFF_IMM_S2:
12559 sign = value >= 0;
12560 if (value < -255 || value > 255)
12561 as_bad_where (fixP->fx_file, fixP->fx_line,
12562 _("Illegal value for co-processor offset"));
12563 if (value < 0)
12564 value = -value;
12565 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
12566 newval |= value | (sign ? INDEX_UP : 0);
12567 md_number_to_chars (buf, newval , INSN_SIZE);
12568 break;
12569
12570 case BFD_RELOC_ARM_THUMB_OFFSET:
12571 newval = md_chars_to_number (buf, THUMB_SIZE);
12572 /* Exactly what ranges, and where the offset is inserted depends
12573 on the type of instruction, we can establish this from the
12574 top 4 bits. */
12575 switch (newval >> 12)
12576 {
12577 case 4: /* PC load. */
12578 /* Thumb PC loads are somewhat odd, bit 1 of the PC is
12579 forced to zero for these loads, so we will need to round
12580 up the offset if the instruction address is not word
12581 aligned (since the final address produced must be, and
12582 we can only describe word-aligned immediate offsets). */
12583
12584 if ((fixP->fx_frag->fr_address + fixP->fx_where + value) & 3)
12585 as_bad_where (fixP->fx_file, fixP->fx_line,
12586 _("invalid offset, target not word aligned (0x%08X)"),
12587 (unsigned int) (fixP->fx_frag->fr_address
12588 + fixP->fx_where + value));
12589
12590 if ((value + 2) & ~0x3fe)
12591 as_bad_where (fixP->fx_file, fixP->fx_line,
12592 _("invalid offset, value too big (0x%08lX)"),
12593 (long) value);
12594
12595 /* Round up, since pc will be rounded down. */
12596 newval |= (value + 2) >> 2;
12597 break;
12598
12599 case 9: /* SP load/store. */
12600 if (value & ~0x3fc)
12601 as_bad_where (fixP->fx_file, fixP->fx_line,
12602 _("invalid offset, value too big (0x%08lX)"),
12603 (long) value);
12604 newval |= value >> 2;
12605 break;
12606
12607 case 6: /* Word load/store. */
12608 if (value & ~0x7c)
12609 as_bad_where (fixP->fx_file, fixP->fx_line,
12610 _("invalid offset, value too big (0x%08lX)"),
12611 (long) value);
12612 newval |= value << 4; /* 6 - 2. */
12613 break;
12614
12615 case 7: /* Byte load/store. */
12616 if (value & ~0x1f)
12617 as_bad_where (fixP->fx_file, fixP->fx_line,
12618 _("invalid offset, value too big (0x%08lX)"),
12619 (long) value);
12620 newval |= value << 6;
12621 break;
12622
12623 case 8: /* Halfword load/store. */
12624 if (value & ~0x3e)
12625 as_bad_where (fixP->fx_file, fixP->fx_line,
12626 _("invalid offset, value too big (0x%08lX)"),
12627 (long) value);
12628 newval |= value << 5; /* 6 - 1. */
12629 break;
12630
12631 default:
12632 as_bad_where (fixP->fx_file, fixP->fx_line,
12633 "Unable to process relocation for thumb opcode: %lx",
12634 (unsigned long) newval);
12635 break;
12636 }
12637 md_number_to_chars (buf, newval, THUMB_SIZE);
12638 break;
12639
12640 case BFD_RELOC_ARM_THUMB_ADD:
12641 /* This is a complicated relocation, since we use it for all of
12642 the following immediate relocations:
12643
12644 3bit ADD/SUB
12645 8bit ADD/SUB
12646 9bit ADD/SUB SP word-aligned
12647 10bit ADD PC/SP word-aligned
12648
12649 The type of instruction being processed is encoded in the
12650 instruction field:
12651
12652 0x8000 SUB
12653 0x00F0 Rd
12654 0x000F Rs
12655 */
12656 newval = md_chars_to_number (buf, THUMB_SIZE);
12657 {
12658 int rd = (newval >> 4) & 0xf;
12659 int rs = newval & 0xf;
12660 int subtract = newval & 0x8000;
12661
12662 if (rd == REG_SP)
12663 {
12664 if (value & ~0x1fc)
12665 as_bad_where (fixP->fx_file, fixP->fx_line,
12666 _("invalid immediate for stack address calculation"));
12667 newval = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
12668 newval |= value >> 2;
12669 }
12670 else if (rs == REG_PC || rs == REG_SP)
12671 {
12672 if (subtract ||
12673 value & ~0x3fc)
12674 as_bad_where (fixP->fx_file, fixP->fx_line,
12675 _("invalid immediate for address calculation (value = 0x%08lX)"),
12676 (unsigned long) value);
12677 newval = (rs == REG_PC ? T_OPCODE_ADD_PC : T_OPCODE_ADD_SP);
12678 newval |= rd << 8;
12679 newval |= value >> 2;
12680 }
12681 else if (rs == rd)
12682 {
12683 if (value & ~0xff)
12684 as_bad_where (fixP->fx_file, fixP->fx_line,
12685 _("invalid 8bit immediate"));
12686 newval = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
12687 newval |= (rd << 8) | value;
12688 }
12689 else
12690 {
12691 if (value & ~0x7)
12692 as_bad_where (fixP->fx_file, fixP->fx_line,
12693 _("invalid 3bit immediate"));
12694 newval = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
12695 newval |= rd | (rs << 3) | (value << 6);
12696 }
12697 }
12698 md_number_to_chars (buf, newval, THUMB_SIZE);
12699 break;
12700
12701 case BFD_RELOC_ARM_THUMB_IMM:
12702 newval = md_chars_to_number (buf, THUMB_SIZE);
12703 switch (newval >> 11)
12704 {
12705 case 0x04: /* 8bit immediate MOV. */
12706 case 0x05: /* 8bit immediate CMP. */
12707 if (value < 0 || value > 255)
12708 as_bad_where (fixP->fx_file, fixP->fx_line,
12709 _("invalid immediate: %ld is too large"),
12710 (long) value);
12711 newval |= value;
12712 break;
12713
12714 default:
12715 abort ();
12716 }
12717 md_number_to_chars (buf, newval, THUMB_SIZE);
12718 break;
12719
12720 case BFD_RELOC_ARM_THUMB_SHIFT:
12721 /* 5bit shift value (0..31). */
12722 if (value < 0 || value > 31)
12723 as_bad_where (fixP->fx_file, fixP->fx_line,
12724 _("illegal Thumb shift value: %ld"), (long) value);
12725 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xf03f;
12726 newval |= value << 6;
12727 md_number_to_chars (buf, newval, THUMB_SIZE);
12728 break;
12729
12730 case BFD_RELOC_VTABLE_INHERIT:
12731 case BFD_RELOC_VTABLE_ENTRY:
12732 fixP->fx_done = 0;
12733 return;
12734
12735 case BFD_RELOC_NONE:
12736 default:
12737 as_bad_where (fixP->fx_file, fixP->fx_line,
12738 _("bad relocation fixup type (%d)"), fixP->fx_r_type);
12739 }
12740 }
12741
12742 /* Translate internal representation of relocation info to BFD target
12743 format. */
12744
12745 arelent *
12746 tc_gen_reloc (section, fixp)
12747 asection * section ATTRIBUTE_UNUSED;
12748 fixS * fixp;
12749 {
12750 arelent * reloc;
12751 bfd_reloc_code_real_type code;
12752
12753 reloc = (arelent *) xmalloc (sizeof (arelent));
12754
12755 reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
12756 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
12757 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
12758
12759 /* @@ Why fx_addnumber sometimes and fx_offset other times? */
12760 #ifndef OBJ_ELF
12761 if (fixp->fx_pcrel == 0)
12762 reloc->addend = fixp->fx_offset;
12763 else
12764 reloc->addend = fixp->fx_offset = reloc->address;
12765 #else /* OBJ_ELF */
12766 reloc->addend = fixp->fx_offset;
12767 #endif
12768
12769 switch (fixp->fx_r_type)
12770 {
12771 case BFD_RELOC_8:
12772 if (fixp->fx_pcrel)
12773 {
12774 code = BFD_RELOC_8_PCREL;
12775 break;
12776 }
12777
12778 case BFD_RELOC_16:
12779 if (fixp->fx_pcrel)
12780 {
12781 code = BFD_RELOC_16_PCREL;
12782 break;
12783 }
12784
12785 case BFD_RELOC_32:
12786 if (fixp->fx_pcrel)
12787 {
12788 code = BFD_RELOC_32_PCREL;
12789 break;
12790 }
12791
12792 case BFD_RELOC_ARM_PCREL_BRANCH:
12793 case BFD_RELOC_ARM_PCREL_BLX:
12794 case BFD_RELOC_RVA:
12795 case BFD_RELOC_THUMB_PCREL_BRANCH9:
12796 case BFD_RELOC_THUMB_PCREL_BRANCH12:
12797 case BFD_RELOC_THUMB_PCREL_BRANCH23:
12798 case BFD_RELOC_THUMB_PCREL_BLX:
12799 case BFD_RELOC_VTABLE_ENTRY:
12800 case BFD_RELOC_VTABLE_INHERIT:
12801 code = fixp->fx_r_type;
12802 break;
12803
12804 case BFD_RELOC_ARM_LITERAL:
12805 case BFD_RELOC_ARM_HWLITERAL:
12806 /* If this is called then the a literal has
12807 been referenced across a section boundary. */
12808 as_bad_where (fixp->fx_file, fixp->fx_line,
12809 _("literal referenced across section boundary"));
12810 return NULL;
12811
12812 #ifdef OBJ_ELF
12813 case BFD_RELOC_ARM_GOT32:
12814 case BFD_RELOC_ARM_GOTOFF:
12815 case BFD_RELOC_ARM_PLT32:
12816 code = fixp->fx_r_type;
12817 break;
12818 #endif
12819
12820 case BFD_RELOC_ARM_IMMEDIATE:
12821 as_bad_where (fixp->fx_file, fixp->fx_line,
12822 _("internal relocation (type: IMMEDIATE) not fixed up"));
12823 return NULL;
12824
12825 case BFD_RELOC_ARM_ADRL_IMMEDIATE:
12826 as_bad_where (fixp->fx_file, fixp->fx_line,
12827 _("ADRL used for a symbol not defined in the same file"));
12828 return NULL;
12829
12830 case BFD_RELOC_ARM_OFFSET_IMM:
12831 if (fixp->fx_addsy != NULL
12832 && !S_IS_DEFINED (fixp->fx_addsy)
12833 && S_IS_LOCAL (fixp->fx_addsy))
12834 {
12835 as_bad_where (fixp->fx_file, fixp->fx_line,
12836 _("undefined local label `%s'"),
12837 S_GET_NAME (fixp->fx_addsy));
12838 return NULL;
12839 }
12840
12841 as_bad_where (fixp->fx_file, fixp->fx_line,
12842 _("internal_relocation (type: OFFSET_IMM) not fixed up"));
12843 return NULL;
12844
12845 default:
12846 {
12847 char * type;
12848
12849 switch (fixp->fx_r_type)
12850 {
12851 case BFD_RELOC_ARM_OFFSET_IMM8: type = "OFFSET_IMM8"; break;
12852 case BFD_RELOC_ARM_SHIFT_IMM: type = "SHIFT_IMM"; break;
12853 case BFD_RELOC_ARM_SWI: type = "SWI"; break;
12854 case BFD_RELOC_ARM_MULTI: type = "MULTI"; break;
12855 case BFD_RELOC_ARM_CP_OFF_IMM: type = "CP_OFF_IMM"; break;
12856 case BFD_RELOC_ARM_THUMB_ADD: type = "THUMB_ADD"; break;
12857 case BFD_RELOC_ARM_THUMB_SHIFT: type = "THUMB_SHIFT"; break;
12858 case BFD_RELOC_ARM_THUMB_IMM: type = "THUMB_IMM"; break;
12859 case BFD_RELOC_ARM_THUMB_OFFSET: type = "THUMB_OFFSET"; break;
12860 default: type = _("<unknown>"); break;
12861 }
12862 as_bad_where (fixp->fx_file, fixp->fx_line,
12863 _("cannot represent %s relocation in this object file format"),
12864 type);
12865 return NULL;
12866 }
12867 }
12868
12869 #ifdef OBJ_ELF
12870 if ((code == BFD_RELOC_32_PCREL || code == BFD_RELOC_32)
12871 && GOT_symbol
12872 && fixp->fx_addsy == GOT_symbol)
12873 {
12874 code = BFD_RELOC_ARM_GOTPC;
12875 reloc->addend = fixp->fx_offset = reloc->address;
12876 }
12877 #endif
12878
12879 reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
12880
12881 if (reloc->howto == NULL)
12882 {
12883 as_bad_where (fixp->fx_file, fixp->fx_line,
12884 _("cannot represent %s relocation in this object file format"),
12885 bfd_get_reloc_code_name (code));
12886 return NULL;
12887 }
12888
12889 /* HACK: Since arm ELF uses Rel instead of Rela, encode the
12890 vtable entry to be used in the relocation's section offset. */
12891 if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
12892 reloc->address = fixp->fx_offset;
12893
12894 return reloc;
12895 }
12896
12897 int
12898 md_estimate_size_before_relax (fragP, segtype)
12899 fragS * fragP ATTRIBUTE_UNUSED;
12900 segT segtype ATTRIBUTE_UNUSED;
12901 {
12902 as_fatal (_("md_estimate_size_before_relax\n"));
12903 return 1;
12904 }
12905
12906 static void
12907 output_inst (str)
12908 const char *str;
12909 {
12910 char * to = NULL;
12911
12912 if (inst.error)
12913 {
12914 as_bad ("%s -- `%s'", inst.error, str);
12915 return;
12916 }
12917
12918 to = frag_more (inst.size);
12919
12920 if (thumb_mode && (inst.size > THUMB_SIZE))
12921 {
12922 assert (inst.size == (2 * THUMB_SIZE));
12923 md_number_to_chars (to, inst.instruction >> 16, THUMB_SIZE);
12924 md_number_to_chars (to + THUMB_SIZE, inst.instruction, THUMB_SIZE);
12925 }
12926 else if (inst.size > INSN_SIZE)
12927 {
12928 assert (inst.size == (2 * INSN_SIZE));
12929 md_number_to_chars (to, inst.instruction, INSN_SIZE);
12930 md_number_to_chars (to + INSN_SIZE, inst.instruction, INSN_SIZE);
12931 }
12932 else
12933 md_number_to_chars (to, inst.instruction, inst.size);
12934
12935 if (inst.reloc.type != BFD_RELOC_NONE)
12936 fix_new_arm (frag_now, to - frag_now->fr_literal,
12937 inst.size, & inst.reloc.exp, inst.reloc.pc_rel,
12938 inst.reloc.type);
12939
12940 #ifdef OBJ_ELF
12941 dwarf2_emit_insn (inst.size);
12942 #endif
12943 }
12944
12945 void
12946 md_assemble (str)
12947 char * str;
12948 {
12949 char c;
12950 char *p;
12951 char *start;
12952
12953 /* Align the instruction.
12954 This may not be the right thing to do but ... */
12955 #if 0
12956 arm_align (2, 0);
12957 #endif
12958
12959 /* Align the previous label if needed. */
12960 if (last_label_seen != NULL)
12961 {
12962 symbol_set_frag (last_label_seen, frag_now);
12963 S_SET_VALUE (last_label_seen, (valueT) frag_now_fix ());
12964 S_SET_SEGMENT (last_label_seen, now_seg);
12965 }
12966
12967 memset (&inst, '\0', sizeof (inst));
12968 inst.reloc.type = BFD_RELOC_NONE;
12969
12970 skip_whitespace (str);
12971
12972 /* Scan up to the end of the op-code, which must end in white space or
12973 end of string. */
12974 for (start = p = str; *p != '\0'; p++)
12975 if (*p == ' ')
12976 break;
12977
12978 if (p == str)
12979 {
12980 as_bad (_("no operator -- statement `%s'\n"), str);
12981 return;
12982 }
12983
12984 if (thumb_mode)
12985 {
12986 const struct thumb_opcode * opcode;
12987
12988 c = *p;
12989 *p = '\0';
12990 opcode = (const struct thumb_opcode *) hash_find (arm_tops_hsh, str);
12991 *p = c;
12992
12993 if (opcode)
12994 {
12995 /* Check that this instruction is supported for this CPU. */
12996 if (thumb_mode == 1 && (opcode->variant & cpu_variant) == 0)
12997 {
12998 as_bad (_("selected processor does not support `%s'"), str);
12999 return;
13000 }
13001
13002 mapping_state (MAP_THUMB);
13003 inst.instruction = opcode->value;
13004 inst.size = opcode->size;
13005 (*opcode->parms) (p);
13006 output_inst (str);
13007 return;
13008 }
13009 }
13010 else
13011 {
13012 const struct asm_opcode * opcode;
13013
13014 c = *p;
13015 *p = '\0';
13016 opcode = (const struct asm_opcode *) hash_find (arm_ops_hsh, str);
13017 *p = c;
13018
13019 if (opcode)
13020 {
13021 /* Check that this instruction is supported for this CPU. */
13022 if ((opcode->variant & cpu_variant) == 0)
13023 {
13024 as_bad (_("selected processor does not support `%s'"), str);
13025 return;
13026 }
13027
13028 mapping_state (MAP_ARM);
13029 inst.instruction = opcode->value;
13030 inst.size = INSN_SIZE;
13031 (*opcode->parms) (p);
13032 output_inst (str);
13033 return;
13034 }
13035 }
13036
13037 /* It wasn't an instruction, but it might be a register alias of the form
13038 alias .req reg. */
13039 if (create_register_alias (str, p))
13040 return;
13041
13042 as_bad (_("bad instruction `%s'"), start);
13043 }
13044
13045 /* md_parse_option
13046 Invocation line includes a switch not recognized by the base assembler.
13047 See if it's a processor-specific option.
13048
13049 This routine is somewhat complicated by the need for backwards
13050 compatibility (since older releases of gcc can't be changed).
13051 The new options try to make the interface as compatible as
13052 possible with GCC.
13053
13054 New options (supported) are:
13055
13056 -mcpu=<cpu name> Assemble for selected processor
13057 -march=<architecture name> Assemble for selected architecture
13058 -mfpu=<fpu architecture> Assemble for selected FPU.
13059 -EB/-mbig-endian Big-endian
13060 -EL/-mlittle-endian Little-endian
13061 -k Generate PIC code
13062 -mthumb Start in Thumb mode
13063 -mthumb-interwork Code supports ARM/Thumb interworking
13064
13065 For now we will also provide support for:
13066
13067 -mapcs-32 32-bit Program counter
13068 -mapcs-26 26-bit Program counter
13069 -macps-float Floats passed in FP registers
13070 -mapcs-reentrant Reentrant code
13071 -matpcs
13072 (sometime these will probably be replaced with -mapcs=<list of options>
13073 and -matpcs=<list of options>)
13074
13075 The remaining options are only supported for back-wards compatibility.
13076 Cpu variants, the arm part is optional:
13077 -m[arm]1 Currently not supported.
13078 -m[arm]2, -m[arm]250 Arm 2 and Arm 250 processor
13079 -m[arm]3 Arm 3 processor
13080 -m[arm]6[xx], Arm 6 processors
13081 -m[arm]7[xx][t][[d]m] Arm 7 processors
13082 -m[arm]8[10] Arm 8 processors
13083 -m[arm]9[20][tdmi] Arm 9 processors
13084 -mstrongarm[110[0]] StrongARM processors
13085 -mxscale XScale processors
13086 -m[arm]v[2345[t[e]]] Arm architectures
13087 -mall All (except the ARM1)
13088 FP variants:
13089 -mfpa10, -mfpa11 FPA10 and 11 co-processor instructions
13090 -mfpe-old (No float load/store multiples)
13091 -mvfpxd VFP Single precision
13092 -mvfp All VFP
13093 -mno-fpu Disable all floating point instructions
13094
13095 The following CPU names are recognized:
13096 arm1, arm2, arm250, arm3, arm6, arm600, arm610, arm620,
13097 arm7, arm7m, arm7d, arm7dm, arm7di, arm7dmi, arm70, arm700,
13098 arm700i, arm710 arm710t, arm720, arm720t, arm740t, arm710c,
13099 arm7100, arm7500, arm7500fe, arm7tdmi, arm8, arm810, arm9,
13100 arm920, arm920t, arm940t, arm946, arm966, arm9tdmi, arm9e,
13101 arm10t arm10e, arm1020t, arm1020e, arm10200e,
13102 strongarm, strongarm110, strongarm1100, strongarm1110, xscale.
13103
13104 */
13105
13106 const char * md_shortopts = "m:k";
13107
13108 #ifdef ARM_BI_ENDIAN
13109 #define OPTION_EB (OPTION_MD_BASE + 0)
13110 #define OPTION_EL (OPTION_MD_BASE + 1)
13111 #else
13112 #if TARGET_BYTES_BIG_ENDIAN
13113 #define OPTION_EB (OPTION_MD_BASE + 0)
13114 #else
13115 #define OPTION_EL (OPTION_MD_BASE + 1)
13116 #endif
13117 #endif
13118
13119 struct option md_longopts[] =
13120 {
13121 #ifdef OPTION_EB
13122 {"EB", no_argument, NULL, OPTION_EB},
13123 #endif
13124 #ifdef OPTION_EL
13125 {"EL", no_argument, NULL, OPTION_EL},
13126 #endif
13127 {NULL, no_argument, NULL, 0}
13128 };
13129
13130 size_t md_longopts_size = sizeof (md_longopts);
13131
13132 struct arm_option_table
13133 {
13134 char *option; /* Option name to match. */
13135 char *help; /* Help information. */
13136 int *var; /* Variable to change. */
13137 int value; /* What to change it to. */
13138 char *deprecated; /* If non-null, print this message. */
13139 };
13140
13141 struct arm_option_table arm_opts[] =
13142 {
13143 {"k", N_("generate PIC code"), &pic_code, 1, NULL},
13144 {"mthumb", N_("assemble Thumb code"), &thumb_mode, 1, NULL},
13145 {"mthumb-interwork", N_("support ARM/Thumb interworking"),
13146 &support_interwork, 1, NULL},
13147 {"moabi", N_("use old ABI (ELF only)"), &target_oabi, 1, NULL},
13148 {"mapcs-32", N_("code uses 32-bit program counter"), &uses_apcs_26, 0, NULL},
13149 {"mapcs-26", N_("code uses 26-bit program counter"), &uses_apcs_26, 1, NULL},
13150 {"mapcs-float", N_("floating point args are in fp regs"), &uses_apcs_float,
13151 1, NULL},
13152 {"mapcs-reentrant", N_("re-entrant code"), &pic_code, 1, NULL},
13153 {"matpcs", N_("code is ATPCS conformant"), &atpcs, 1, NULL},
13154 {"mbig-endian", N_("assemble for big-endian"), &target_big_endian, 1, NULL},
13155 {"mlittle-endian", N_("assemble for little-endian"), &target_big_endian, 1,
13156 NULL},
13157
13158 /* These are recognized by the assembler, but have no affect on code. */
13159 {"mapcs-frame", N_("use frame pointer"), NULL, 0, NULL},
13160 {"mapcs-stack-check", N_("use stack size checking"), NULL, 0, NULL},
13161
13162 /* DON'T add any new processors to this list -- we want the whole list
13163 to go away... Add them to the processors table instead. */
13164 {"marm1", NULL, &legacy_cpu, ARM_ARCH_V1, N_("use -mcpu=arm1")},
13165 {"m1", NULL, &legacy_cpu, ARM_ARCH_V1, N_("use -mcpu=arm1")},
13166 {"marm2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -mcpu=arm2")},
13167 {"m2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -mcpu=arm2")},
13168 {"marm250", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm250")},
13169 {"m250", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm250")},
13170 {"marm3", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm3")},
13171 {"m3", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm3")},
13172 {"marm6", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm6")},
13173 {"m6", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm6")},
13174 {"marm600", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm600")},
13175 {"m600", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm600")},
13176 {"marm610", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm610")},
13177 {"m610", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm610")},
13178 {"marm620", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm620")},
13179 {"m620", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm620")},
13180 {"marm7", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7")},
13181 {"m7", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7")},
13182 {"marm70", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm70")},
13183 {"m70", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm70")},
13184 {"marm700", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700")},
13185 {"m700", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700")},
13186 {"marm700i", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700i")},
13187 {"m700i", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700i")},
13188 {"marm710", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710")},
13189 {"m710", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710")},
13190 {"marm710c", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710c")},
13191 {"m710c", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710c")},
13192 {"marm720", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm720")},
13193 {"m720", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm720")},
13194 {"marm7d", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7d")},
13195 {"m7d", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7d")},
13196 {"marm7di", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7di")},
13197 {"m7di", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7di")},
13198 {"marm7m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7m")},
13199 {"m7m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7m")},
13200 {"marm7dm", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dm")},
13201 {"m7dm", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dm")},
13202 {"marm7dmi", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dmi")},
13203 {"m7dmi", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dmi")},
13204 {"marm7100", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7100")},
13205 {"m7100", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7100")},
13206 {"marm7500", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500")},
13207 {"m7500", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500")},
13208 {"marm7500fe", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500fe")},
13209 {"m7500fe", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500fe")},
13210 {"marm7t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
13211 {"m7t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
13212 {"marm7tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
13213 {"m7tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
13214 {"marm710t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm710t")},
13215 {"m710t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm710t")},
13216 {"marm720t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm720t")},
13217 {"m720t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm720t")},
13218 {"marm740t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm740t")},
13219 {"m740t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm740t")},
13220 {"marm8", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm8")},
13221 {"m8", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm8")},
13222 {"marm810", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm810")},
13223 {"m810", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm810")},
13224 {"marm9", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9")},
13225 {"m9", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9")},
13226 {"marm9tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9tdmi")},
13227 {"m9tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9tdmi")},
13228 {"marm920", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm920")},
13229 {"m920", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm920")},
13230 {"marm940", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm940")},
13231 {"m940", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm940")},
13232 {"mstrongarm", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=strongarm")},
13233 {"mstrongarm110", NULL, &legacy_cpu, ARM_ARCH_V4,
13234 N_("use -mcpu=strongarm110")},
13235 {"mstrongarm1100", NULL, &legacy_cpu, ARM_ARCH_V4,
13236 N_("use -mcpu=strongarm1100")},
13237 {"mstrongarm1110", NULL, &legacy_cpu, ARM_ARCH_V4,
13238 N_("use -mcpu=strongarm1110")},
13239 {"mxscale", NULL, &legacy_cpu, ARM_ARCH_XSCALE, N_("use -mcpu=xscale")},
13240 {"miwmmxt", NULL, &legacy_cpu, ARM_ARCH_IWMMXT, N_("use -mcpu=iwmmxt")},
13241 {"mall", NULL, &legacy_cpu, ARM_ANY, N_("use -mcpu=all")},
13242
13243 /* Architecture variants -- don't add any more to this list either. */
13244 {"mv2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -march=armv2")},
13245 {"marmv2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -march=armv2")},
13246 {"mv2a", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -march=armv2a")},
13247 {"marmv2a", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -march=armv2a")},
13248 {"mv3", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -march=armv3")},
13249 {"marmv3", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -march=armv3")},
13250 {"mv3m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -march=armv3m")},
13251 {"marmv3m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -march=armv3m")},
13252 {"mv4", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -march=armv4")},
13253 {"marmv4", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -march=armv4")},
13254 {"mv4t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -march=armv4t")},
13255 {"marmv4t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -march=armv4t")},
13256 {"mv5", NULL, &legacy_cpu, ARM_ARCH_V5, N_("use -march=armv5")},
13257 {"marmv5", NULL, &legacy_cpu, ARM_ARCH_V5, N_("use -march=armv5")},
13258 {"mv5t", NULL, &legacy_cpu, ARM_ARCH_V5T, N_("use -march=armv5t")},
13259 {"marmv5t", NULL, &legacy_cpu, ARM_ARCH_V5T, N_("use -march=armv5t")},
13260 {"mv5e", NULL, &legacy_cpu, ARM_ARCH_V5TE, N_("use -march=armv5te")},
13261 {"marmv5e", NULL, &legacy_cpu, ARM_ARCH_V5TE, N_("use -march=armv5te")},
13262
13263 /* Floating point variants -- don't add any more to this list either. */
13264 {"mfpe-old", NULL, &legacy_fpu, FPU_ARCH_FPE, N_("use -mfpu=fpe")},
13265 {"mfpa10", NULL, &legacy_fpu, FPU_ARCH_FPA, N_("use -mfpu=fpa10")},
13266 {"mfpa11", NULL, &legacy_fpu, FPU_ARCH_FPA, N_("use -mfpu=fpa11")},
13267 {"mno-fpu", NULL, &legacy_fpu, 0,
13268 N_("use either -mfpu=softfpa or -mfpu=softvfp")},
13269
13270 {NULL, NULL, NULL, 0, NULL}
13271 };
13272
13273 struct arm_cpu_option_table
13274 {
13275 char *name;
13276 int value;
13277 /* For some CPUs we assume an FPU unless the user explicitly sets
13278 -mfpu=... */
13279 int default_fpu;
13280 };
13281
13282 /* This list should, at a minimum, contain all the cpu names
13283 recognized by GCC. */
13284 static struct arm_cpu_option_table arm_cpus[] =
13285 {
13286 {"all", ARM_ANY, FPU_ARCH_FPA},
13287 {"arm1", ARM_ARCH_V1, FPU_ARCH_FPA},
13288 {"arm2", ARM_ARCH_V2, FPU_ARCH_FPA},
13289 {"arm250", ARM_ARCH_V2S, FPU_ARCH_FPA},
13290 {"arm3", ARM_ARCH_V2S, FPU_ARCH_FPA},
13291 {"arm6", ARM_ARCH_V3, FPU_ARCH_FPA},
13292 {"arm60", ARM_ARCH_V3, FPU_ARCH_FPA},
13293 {"arm600", ARM_ARCH_V3, FPU_ARCH_FPA},
13294 {"arm610", ARM_ARCH_V3, FPU_ARCH_FPA},
13295 {"arm620", ARM_ARCH_V3, FPU_ARCH_FPA},
13296 {"arm7", ARM_ARCH_V3, FPU_ARCH_FPA},
13297 {"arm7m", ARM_ARCH_V3M, FPU_ARCH_FPA},
13298 {"arm7d", ARM_ARCH_V3, FPU_ARCH_FPA},
13299 {"arm7dm", ARM_ARCH_V3M, FPU_ARCH_FPA},
13300 {"arm7di", ARM_ARCH_V3, FPU_ARCH_FPA},
13301 {"arm7dmi", ARM_ARCH_V3M, FPU_ARCH_FPA},
13302 {"arm70", ARM_ARCH_V3, FPU_ARCH_FPA},
13303 {"arm700", ARM_ARCH_V3, FPU_ARCH_FPA},
13304 {"arm700i", ARM_ARCH_V3, FPU_ARCH_FPA},
13305 {"arm710", ARM_ARCH_V3, FPU_ARCH_FPA},
13306 {"arm710t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13307 {"arm720", ARM_ARCH_V3, FPU_ARCH_FPA},
13308 {"arm720t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13309 {"arm740t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13310 {"arm710c", ARM_ARCH_V3, FPU_ARCH_FPA},
13311 {"arm7100", ARM_ARCH_V3, FPU_ARCH_FPA},
13312 {"arm7500", ARM_ARCH_V3, FPU_ARCH_FPA},
13313 {"arm7500fe", ARM_ARCH_V3, FPU_ARCH_FPA},
13314 {"arm7t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13315 {"arm7tdmi", ARM_ARCH_V4T, FPU_ARCH_FPA},
13316 {"arm8", ARM_ARCH_V4, FPU_ARCH_FPA},
13317 {"arm810", ARM_ARCH_V4, FPU_ARCH_FPA},
13318 {"strongarm", ARM_ARCH_V4, FPU_ARCH_FPA},
13319 {"strongarm1", ARM_ARCH_V4, FPU_ARCH_FPA},
13320 {"strongarm110", ARM_ARCH_V4, FPU_ARCH_FPA},
13321 {"strongarm1100", ARM_ARCH_V4, FPU_ARCH_FPA},
13322 {"strongarm1110", ARM_ARCH_V4, FPU_ARCH_FPA},
13323 {"arm9", ARM_ARCH_V4T, FPU_ARCH_FPA},
13324 {"arm920", ARM_ARCH_V4T, FPU_ARCH_FPA},
13325 {"arm920t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13326 {"arm922t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13327 {"arm940t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13328 {"arm9tdmi", ARM_ARCH_V4T, FPU_ARCH_FPA},
13329 /* For V5 or later processors we default to using VFP; but the user
13330 should really set the FPU type explicitly. */
13331 {"arm9e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
13332 {"arm9e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13333 {"arm926ej", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
13334 {"arm926ejs", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
13335 {"arm946e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
13336 {"arm946e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13337 {"arm966e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
13338 {"arm966e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13339 {"arm10t", ARM_ARCH_V5T, FPU_ARCH_VFP_V1},
13340 {"arm10e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13341 {"arm1020", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13342 {"arm1020t", ARM_ARCH_V5T, FPU_ARCH_VFP_V1},
13343 {"arm1020e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13344 {"arm1026ejs", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13345 {"arm1136js", ARM_ARCH_V6, FPU_NONE},
13346 {"arm1136jfs", ARM_ARCH_V6, FPU_ARCH_VFP_V2},
13347 /* ??? XSCALE is really an architecture. */
13348 {"xscale", ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2},
13349 /* ??? iwmmxt is not a processor. */
13350 {"iwmmxt", ARM_ARCH_IWMMXT, FPU_ARCH_VFP_V2},
13351 {"i80200", ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2},
13352 /* Maverick */
13353 {"ep9312", ARM_ARCH_V4T | ARM_CEXT_MAVERICK, FPU_ARCH_MAVERICK},
13354 {NULL, 0, 0}
13355 };
13356
13357 struct arm_arch_option_table
13358 {
13359 char *name;
13360 int value;
13361 int default_fpu;
13362 };
13363
13364 /* This list should, at a minimum, contain all the architecture names
13365 recognized by GCC. */
13366 static struct arm_arch_option_table arm_archs[] =
13367 {
13368 {"all", ARM_ANY, FPU_ARCH_FPA},
13369 {"armv1", ARM_ARCH_V1, FPU_ARCH_FPA},
13370 {"armv2", ARM_ARCH_V2, FPU_ARCH_FPA},
13371 {"armv2a", ARM_ARCH_V2S, FPU_ARCH_FPA},
13372 {"armv2s", ARM_ARCH_V2S, FPU_ARCH_FPA},
13373 {"armv3", ARM_ARCH_V3, FPU_ARCH_FPA},
13374 {"armv3m", ARM_ARCH_V3M, FPU_ARCH_FPA},
13375 {"armv4", ARM_ARCH_V4, FPU_ARCH_FPA},
13376 {"armv4xm", ARM_ARCH_V4xM, FPU_ARCH_FPA},
13377 {"armv4t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13378 {"armv4txm", ARM_ARCH_V4TxM, FPU_ARCH_FPA},
13379 {"armv5", ARM_ARCH_V5, FPU_ARCH_VFP},
13380 {"armv5t", ARM_ARCH_V5T, FPU_ARCH_VFP},
13381 {"armv5txm", ARM_ARCH_V5TxM, FPU_ARCH_VFP},
13382 {"armv5te", ARM_ARCH_V5TE, FPU_ARCH_VFP},
13383 {"armv5texp", ARM_ARCH_V5TExP, FPU_ARCH_VFP},
13384 {"armv5tej", ARM_ARCH_V5TEJ, FPU_ARCH_VFP},
13385 {"armv6", ARM_ARCH_V6, FPU_ARCH_VFP},
13386 {"armv6j", ARM_ARCH_V6, FPU_ARCH_VFP},
13387 {"xscale", ARM_ARCH_XSCALE, FPU_ARCH_VFP},
13388 {"iwmmxt", ARM_ARCH_IWMMXT, FPU_ARCH_VFP},
13389 {NULL, 0, 0}
13390 };
13391
13392 /* ISA extensions in the co-processor space. */
13393 struct arm_arch_extension_table
13394 {
13395 char *name;
13396 int value;
13397 };
13398
13399 static struct arm_arch_extension_table arm_extensions[] =
13400 {
13401 {"maverick", ARM_CEXT_MAVERICK},
13402 {"xscale", ARM_CEXT_XSCALE},
13403 {"iwmmxt", ARM_CEXT_IWMMXT},
13404 {NULL, 0}
13405 };
13406
13407 struct arm_fpu_option_table
13408 {
13409 char *name;
13410 int value;
13411 };
13412
13413 /* This list should, at a minimum, contain all the fpu names
13414 recognized by GCC. */
13415 static struct arm_fpu_option_table arm_fpus[] =
13416 {
13417 {"softfpa", FPU_NONE},
13418 {"fpe", FPU_ARCH_FPE},
13419 {"fpe2", FPU_ARCH_FPE},
13420 {"fpe3", FPU_ARCH_FPA}, /* Third release supports LFM/SFM. */
13421 {"fpa", FPU_ARCH_FPA},
13422 {"fpa10", FPU_ARCH_FPA},
13423 {"fpa11", FPU_ARCH_FPA},
13424 {"arm7500fe", FPU_ARCH_FPA},
13425 {"softvfp", FPU_ARCH_VFP},
13426 {"softvfp+vfp", FPU_ARCH_VFP_V2},
13427 {"vfp", FPU_ARCH_VFP_V2},
13428 {"vfp9", FPU_ARCH_VFP_V2},
13429 {"vfp10", FPU_ARCH_VFP_V2},
13430 {"vfp10-r0", FPU_ARCH_VFP_V1},
13431 {"vfpxd", FPU_ARCH_VFP_V1xD},
13432 {"arm1020t", FPU_ARCH_VFP_V1},
13433 {"arm1020e", FPU_ARCH_VFP_V2},
13434 {"arm1136jfs", FPU_ARCH_VFP_V2},
13435 {"maverick", FPU_ARCH_MAVERICK},
13436 {NULL, 0}
13437 };
13438
13439 struct arm_float_abi_option_table
13440 {
13441 char *name;
13442 int value;
13443 };
13444
13445 static struct arm_float_abi_option_table arm_float_abis[] =
13446 {
13447 {"hard", ARM_FLOAT_ABI_HARD},
13448 {"softfp", ARM_FLOAT_ABI_SOFTFP},
13449 {"soft", ARM_FLOAT_ABI_SOFT},
13450 {NULL, 0}
13451 };
13452
13453 struct arm_long_option_table
13454 {
13455 char *option; /* Substring to match. */
13456 char *help; /* Help information. */
13457 int (*func) PARAMS ((char *subopt)); /* Function to decode sub-option. */
13458 char *deprecated; /* If non-null, print this message. */
13459 };
13460
13461 static int
13462 arm_parse_extension (str, opt_p)
13463 char *str;
13464 int *opt_p;
13465 {
13466 while (str != NULL && *str != 0)
13467 {
13468 struct arm_arch_extension_table *opt;
13469 char *ext;
13470 int optlen;
13471
13472 if (*str != '+')
13473 {
13474 as_bad (_("invalid architectural extension"));
13475 return 0;
13476 }
13477
13478 str++;
13479 ext = strchr (str, '+');
13480
13481 if (ext != NULL)
13482 optlen = ext - str;
13483 else
13484 optlen = strlen (str);
13485
13486 if (optlen == 0)
13487 {
13488 as_bad (_("missing architectural extension"));
13489 return 0;
13490 }
13491
13492 for (opt = arm_extensions; opt->name != NULL; opt++)
13493 if (strncmp (opt->name, str, optlen) == 0)
13494 {
13495 *opt_p |= opt->value;
13496 break;
13497 }
13498
13499 if (opt->name == NULL)
13500 {
13501 as_bad (_("unknown architectural extnsion `%s'"), str);
13502 return 0;
13503 }
13504
13505 str = ext;
13506 };
13507
13508 return 1;
13509 }
13510
13511 static int
13512 arm_parse_cpu (str)
13513 char *str;
13514 {
13515 struct arm_cpu_option_table *opt;
13516 char *ext = strchr (str, '+');
13517 int optlen;
13518
13519 if (ext != NULL)
13520 optlen = ext - str;
13521 else
13522 optlen = strlen (str);
13523
13524 if (optlen == 0)
13525 {
13526 as_bad (_("missing cpu name `%s'"), str);
13527 return 0;
13528 }
13529
13530 for (opt = arm_cpus; opt->name != NULL; opt++)
13531 if (strncmp (opt->name, str, optlen) == 0)
13532 {
13533 mcpu_cpu_opt = opt->value;
13534 mcpu_fpu_opt = opt->default_fpu;
13535
13536 if (ext != NULL)
13537 return arm_parse_extension (ext, &mcpu_cpu_opt);
13538
13539 return 1;
13540 }
13541
13542 as_bad (_("unknown cpu `%s'"), str);
13543 return 0;
13544 }
13545
13546 static int
13547 arm_parse_arch (str)
13548 char *str;
13549 {
13550 struct arm_arch_option_table *opt;
13551 char *ext = strchr (str, '+');
13552 int optlen;
13553
13554 if (ext != NULL)
13555 optlen = ext - str;
13556 else
13557 optlen = strlen (str);
13558
13559 if (optlen == 0)
13560 {
13561 as_bad (_("missing architecture name `%s'"), str);
13562 return 0;
13563 }
13564
13565
13566 for (opt = arm_archs; opt->name != NULL; opt++)
13567 if (strcmp (opt->name, str) == 0)
13568 {
13569 march_cpu_opt = opt->value;
13570 march_fpu_opt = opt->default_fpu;
13571
13572 if (ext != NULL)
13573 return arm_parse_extension (ext, &march_cpu_opt);
13574
13575 return 1;
13576 }
13577
13578 as_bad (_("unknown architecture `%s'\n"), str);
13579 return 0;
13580 }
13581
13582 static int
13583 arm_parse_fpu (str)
13584 char *str;
13585 {
13586 struct arm_fpu_option_table *opt;
13587
13588 for (opt = arm_fpus; opt->name != NULL; opt++)
13589 if (strcmp (opt->name, str) == 0)
13590 {
13591 mfpu_opt = opt->value;
13592 return 1;
13593 }
13594
13595 as_bad (_("unknown floating point format `%s'\n"), str);
13596 return 0;
13597 }
13598
13599 static int
13600 arm_parse_float_abi (str)
13601 char * str;
13602 {
13603 struct arm_float_abi_option_table *opt;
13604
13605 for (opt = arm_float_abis; opt->name != NULL; opt++)
13606 if (strcmp (opt->name, str) == 0)
13607 {
13608 mfloat_abi_opt = opt->value;
13609 return 1;
13610 }
13611
13612 as_bad (_("unknown floating point abi `%s'\n"), str);
13613 return 0;
13614 }
13615
13616 struct arm_long_option_table arm_long_opts[] =
13617 {
13618 {"mcpu=", N_("<cpu name>\t assemble for CPU <cpu name>"),
13619 arm_parse_cpu, NULL},
13620 {"march=", N_("<arch name>\t assemble for architecture <arch name>"),
13621 arm_parse_arch, NULL},
13622 {"mfpu=", N_("<fpu name>\t assemble for FPU architecture <fpu name>"),
13623 arm_parse_fpu, NULL},
13624 {"mfloat-abi=", N_("<abi>\t assemble for floating point ABI <abi>"),
13625 arm_parse_float_abi, NULL},
13626 {NULL, NULL, 0, NULL}
13627 };
13628
13629 int
13630 md_parse_option (c, arg)
13631 int c;
13632 char * arg;
13633 {
13634 struct arm_option_table *opt;
13635 struct arm_long_option_table *lopt;
13636
13637 switch (c)
13638 {
13639 #ifdef OPTION_EB
13640 case OPTION_EB:
13641 target_big_endian = 1;
13642 break;
13643 #endif
13644
13645 #ifdef OPTION_EL
13646 case OPTION_EL:
13647 target_big_endian = 0;
13648 break;
13649 #endif
13650
13651 case 'a':
13652 /* Listing option. Just ignore these, we don't support additional
13653 ones. */
13654 return 0;
13655
13656 default:
13657 for (opt = arm_opts; opt->option != NULL; opt++)
13658 {
13659 if (c == opt->option[0]
13660 && ((arg == NULL && opt->option[1] == 0)
13661 || strcmp (arg, opt->option + 1) == 0))
13662 {
13663 #if WARN_DEPRECATED
13664 /* If the option is deprecated, tell the user. */
13665 if (opt->deprecated != NULL)
13666 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c,
13667 arg ? arg : "", _(opt->deprecated));
13668 #endif
13669
13670 if (opt->var != NULL)
13671 *opt->var = opt->value;
13672
13673 return 1;
13674 }
13675 }
13676
13677 for (lopt = arm_long_opts; lopt->option != NULL; lopt++)
13678 {
13679 /* These options are expected to have an argument. */
13680 if (c == lopt->option[0]
13681 && arg != NULL
13682 && strncmp (arg, lopt->option + 1,
13683 strlen (lopt->option + 1)) == 0)
13684 {
13685 #if WARN_DEPRECATED
13686 /* If the option is deprecated, tell the user. */
13687 if (lopt->deprecated != NULL)
13688 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c, arg,
13689 _(lopt->deprecated));
13690 #endif
13691
13692 /* Call the sup-option parser. */
13693 return (*lopt->func)(arg + strlen (lopt->option) - 1);
13694 }
13695 }
13696
13697 as_bad (_("unrecognized option `-%c%s'"), c, arg ? arg : "");
13698 return 0;
13699 }
13700
13701 return 1;
13702 }
13703
13704 void
13705 md_show_usage (fp)
13706 FILE * fp;
13707 {
13708 struct arm_option_table *opt;
13709 struct arm_long_option_table *lopt;
13710
13711 fprintf (fp, _(" ARM-specific assembler options:\n"));
13712
13713 for (opt = arm_opts; opt->option != NULL; opt++)
13714 if (opt->help != NULL)
13715 fprintf (fp, " -%-23s%s\n", opt->option, _(opt->help));
13716
13717 for (lopt = arm_long_opts; lopt->option != NULL; lopt++)
13718 if (lopt->help != NULL)
13719 fprintf (fp, " -%s%s\n", lopt->option, _(lopt->help));
13720
13721 #ifdef OPTION_EB
13722 fprintf (fp, _("\
13723 -EB assemble code for a big-endian cpu\n"));
13724 #endif
13725
13726 #ifdef OPTION_EL
13727 fprintf (fp, _("\
13728 -EL assemble code for a little-endian cpu\n"));
13729 #endif
13730 }
13731
13732 /* We need to be able to fix up arbitrary expressions in some statements.
13733 This is so that we can handle symbols that are an arbitrary distance from
13734 the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
13735 which returns part of an address in a form which will be valid for
13736 a data instruction. We do this by pushing the expression into a symbol
13737 in the expr_section, and creating a fix for that. */
13738
13739 static void
13740 fix_new_arm (frag, where, size, exp, pc_rel, reloc)
13741 fragS * frag;
13742 int where;
13743 short int size;
13744 expressionS * exp;
13745 int pc_rel;
13746 int reloc;
13747 {
13748 fixS * new_fix;
13749 arm_fix_data * arm_data;
13750
13751 switch (exp->X_op)
13752 {
13753 case O_constant:
13754 case O_symbol:
13755 case O_add:
13756 case O_subtract:
13757 new_fix = fix_new_exp (frag, where, size, exp, pc_rel, reloc);
13758 break;
13759
13760 default:
13761 new_fix = fix_new (frag, where, size, make_expr_symbol (exp), 0,
13762 pc_rel, reloc);
13763 break;
13764 }
13765
13766 /* Mark whether the fix is to a THUMB instruction, or an ARM
13767 instruction. */
13768 arm_data = (arm_fix_data *) obstack_alloc (& notes, sizeof (arm_fix_data));
13769 new_fix->tc_fix_data = (PTR) arm_data;
13770 arm_data->thumb_mode = thumb_mode;
13771 }
13772
13773 /* This fix_new is called by cons via TC_CONS_FIX_NEW. */
13774
13775 void
13776 cons_fix_new_arm (frag, where, size, exp)
13777 fragS * frag;
13778 int where;
13779 int size;
13780 expressionS * exp;
13781 {
13782 bfd_reloc_code_real_type type;
13783 int pcrel = 0;
13784
13785 /* Pick a reloc.
13786 FIXME: @@ Should look at CPU word size. */
13787 switch (size)
13788 {
13789 case 1:
13790 type = BFD_RELOC_8;
13791 break;
13792 case 2:
13793 type = BFD_RELOC_16;
13794 break;
13795 case 4:
13796 default:
13797 type = BFD_RELOC_32;
13798 break;
13799 case 8:
13800 type = BFD_RELOC_64;
13801 break;
13802 }
13803
13804 fix_new_exp (frag, where, (int) size, exp, pcrel, type);
13805 }
13806
13807 /* A good place to do this, although this was probably not intended
13808 for this kind of use. We need to dump the literal pool before
13809 references are made to a null symbol pointer. */
13810
13811 void
13812 arm_cleanup ()
13813 {
13814 literal_pool * pool;
13815
13816 for (pool = list_of_pools; pool; pool = pool->next)
13817 {
13818 /* Put it at the end of the relevent section. */
13819 subseg_set (pool->section, pool->sub_section);
13820 s_ltorg (0);
13821 }
13822 }
13823
13824 void
13825 arm_start_line_hook ()
13826 {
13827 last_label_seen = NULL;
13828 }
13829
13830 void
13831 arm_frob_label (sym)
13832 symbolS * sym;
13833 {
13834 last_label_seen = sym;
13835
13836 ARM_SET_THUMB (sym, thumb_mode);
13837
13838 #if defined OBJ_COFF || defined OBJ_ELF
13839 ARM_SET_INTERWORK (sym, support_interwork);
13840 #endif
13841
13842 /* Note - do not allow local symbols (.Lxxx) to be labeled
13843 as Thumb functions. This is because these labels, whilst
13844 they exist inside Thumb code, are not the entry points for
13845 possible ARM->Thumb calls. Also, these labels can be used
13846 as part of a computed goto or switch statement. eg gcc
13847 can generate code that looks like this:
13848
13849 ldr r2, [pc, .Laaa]
13850 lsl r3, r3, #2
13851 ldr r2, [r3, r2]
13852 mov pc, r2
13853
13854 .Lbbb: .word .Lxxx
13855 .Lccc: .word .Lyyy
13856 ..etc...
13857 .Laaa: .word Lbbb
13858
13859 The first instruction loads the address of the jump table.
13860 The second instruction converts a table index into a byte offset.
13861 The third instruction gets the jump address out of the table.
13862 The fourth instruction performs the jump.
13863
13864 If the address stored at .Laaa is that of a symbol which has the
13865 Thumb_Func bit set, then the linker will arrange for this address
13866 to have the bottom bit set, which in turn would mean that the
13867 address computation performed by the third instruction would end
13868 up with the bottom bit set. Since the ARM is capable of unaligned
13869 word loads, the instruction would then load the incorrect address
13870 out of the jump table, and chaos would ensue. */
13871 if (label_is_thumb_function_name
13872 && (S_GET_NAME (sym)[0] != '.' || S_GET_NAME (sym)[1] != 'L')
13873 && (bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
13874 {
13875 /* When the address of a Thumb function is taken the bottom
13876 bit of that address should be set. This will allow
13877 interworking between Arm and Thumb functions to work
13878 correctly. */
13879
13880 THUMB_SET_FUNC (sym, 1);
13881
13882 label_is_thumb_function_name = FALSE;
13883 }
13884 }
13885
13886 /* Adjust the symbol table. This marks Thumb symbols as distinct from
13887 ARM ones. */
13888
13889 void
13890 arm_adjust_symtab ()
13891 {
13892 #ifdef OBJ_COFF
13893 symbolS * sym;
13894
13895 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
13896 {
13897 if (ARM_IS_THUMB (sym))
13898 {
13899 if (THUMB_IS_FUNC (sym))
13900 {
13901 /* Mark the symbol as a Thumb function. */
13902 if ( S_GET_STORAGE_CLASS (sym) == C_STAT
13903 || S_GET_STORAGE_CLASS (sym) == C_LABEL) /* This can happen! */
13904 S_SET_STORAGE_CLASS (sym, C_THUMBSTATFUNC);
13905
13906 else if (S_GET_STORAGE_CLASS (sym) == C_EXT)
13907 S_SET_STORAGE_CLASS (sym, C_THUMBEXTFUNC);
13908 else
13909 as_bad (_("%s: unexpected function type: %d"),
13910 S_GET_NAME (sym), S_GET_STORAGE_CLASS (sym));
13911 }
13912 else switch (S_GET_STORAGE_CLASS (sym))
13913 {
13914 case C_EXT:
13915 S_SET_STORAGE_CLASS (sym, C_THUMBEXT);
13916 break;
13917 case C_STAT:
13918 S_SET_STORAGE_CLASS (sym, C_THUMBSTAT);
13919 break;
13920 case C_LABEL:
13921 S_SET_STORAGE_CLASS (sym, C_THUMBLABEL);
13922 break;
13923 default:
13924 /* Do nothing. */
13925 break;
13926 }
13927 }
13928
13929 if (ARM_IS_INTERWORK (sym))
13930 coffsymbol (symbol_get_bfdsym (sym))->native->u.syment.n_flags = 0xFF;
13931 }
13932 #endif
13933 #ifdef OBJ_ELF
13934 symbolS * sym;
13935 char bind;
13936
13937 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
13938 {
13939 if (ARM_IS_THUMB (sym))
13940 {
13941 elf_symbol_type * elf_sym;
13942
13943 elf_sym = elf_symbol (symbol_get_bfdsym (sym));
13944 bind = ELF_ST_BIND (elf_sym);
13945
13946 /* If it's a .thumb_func, declare it as so,
13947 otherwise tag label as .code 16. */
13948 if (THUMB_IS_FUNC (sym))
13949 elf_sym->internal_elf_sym.st_info =
13950 ELF_ST_INFO (bind, STT_ARM_TFUNC);
13951 else
13952 elf_sym->internal_elf_sym.st_info =
13953 ELF_ST_INFO (bind, STT_ARM_16BIT);
13954 }
13955 }
13956 #endif
13957 }
13958
13959 int
13960 arm_data_in_code ()
13961 {
13962 if (thumb_mode && ! strncmp (input_line_pointer + 1, "data:", 5))
13963 {
13964 *input_line_pointer = '/';
13965 input_line_pointer += 5;
13966 *input_line_pointer = 0;
13967 return 1;
13968 }
13969
13970 return 0;
13971 }
13972
13973 char *
13974 arm_canonicalize_symbol_name (name)
13975 char * name;
13976 {
13977 int len;
13978
13979 if (thumb_mode && (len = strlen (name)) > 5
13980 && streq (name + len - 5, "/data"))
13981 *(name + len - 5) = 0;
13982
13983 return name;
13984 }
13985
13986 #if defined OBJ_COFF || defined OBJ_ELF
13987 void
13988 arm_validate_fix (fixP)
13989 fixS * fixP;
13990 {
13991 /* If the destination of the branch is a defined symbol which does not have
13992 the THUMB_FUNC attribute, then we must be calling a function which has
13993 the (interfacearm) attribute. We look for the Thumb entry point to that
13994 function and change the branch to refer to that function instead. */
13995 if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23
13996 && fixP->fx_addsy != NULL
13997 && S_IS_DEFINED (fixP->fx_addsy)
13998 && ! THUMB_IS_FUNC (fixP->fx_addsy))
13999 {
14000 fixP->fx_addsy = find_real_start (fixP->fx_addsy);
14001 }
14002 }
14003 #endif
14004
14005 int
14006 arm_force_relocation (fixp)
14007 struct fix * fixp;
14008 {
14009 #if defined (OBJ_COFF) && defined (TE_PE)
14010 if (fixp->fx_r_type == BFD_RELOC_RVA)
14011 return 1;
14012 #endif
14013 #ifdef OBJ_ELF
14014 if (fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH
14015 || fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BLX
14016 || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX
14017 || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23)
14018 return 1;
14019 #endif
14020
14021 /* Resolve these relocations even if the symbol is extern or weak. */
14022 if (fixp->fx_r_type == BFD_RELOC_ARM_IMMEDIATE
14023 || fixp->fx_r_type == BFD_RELOC_ARM_OFFSET_IMM
14024 || fixp->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE)
14025 return 0;
14026
14027 return generic_force_reloc (fixp);
14028 }
14029
14030 #ifdef OBJ_COFF
14031 /* This is a little hack to help the gas/arm/adrl.s test. It prevents
14032 local labels from being added to the output symbol table when they
14033 are used with the ADRL pseudo op. The ADRL relocation should always
14034 be resolved before the binbary is emitted, so it is safe to say that
14035 it is adjustable. */
14036
14037 bfd_boolean
14038 arm_fix_adjustable (fixP)
14039 fixS * fixP;
14040 {
14041 if (fixP->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE)
14042 return 1;
14043 return 0;
14044 }
14045 #endif
14046
14047 #ifdef OBJ_ELF
14048 /* Relocations against Thumb function names must be left unadjusted,
14049 so that the linker can use this information to correctly set the
14050 bottom bit of their addresses. The MIPS version of this function
14051 also prevents relocations that are mips-16 specific, but I do not
14052 know why it does this.
14053
14054 FIXME:
14055 There is one other problem that ought to be addressed here, but
14056 which currently is not: Taking the address of a label (rather
14057 than a function) and then later jumping to that address. Such
14058 addresses also ought to have their bottom bit set (assuming that
14059 they reside in Thumb code), but at the moment they will not. */
14060
14061 bfd_boolean
14062 arm_fix_adjustable (fixP)
14063 fixS * fixP;
14064 {
14065 if (fixP->fx_addsy == NULL)
14066 return 1;
14067
14068 if (THUMB_IS_FUNC (fixP->fx_addsy)
14069 && fixP->fx_subsy == NULL)
14070 return 0;
14071
14072 /* We need the symbol name for the VTABLE entries. */
14073 if ( fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
14074 || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
14075 return 0;
14076
14077 /* Don't allow symbols to be discarded on GOT related relocs. */
14078 if (fixP->fx_r_type == BFD_RELOC_ARM_PLT32
14079 || fixP->fx_r_type == BFD_RELOC_ARM_GOT32
14080 || fixP->fx_r_type == BFD_RELOC_ARM_GOTOFF)
14081 return 0;
14082
14083 return 1;
14084 }
14085
14086 const char *
14087 elf32_arm_target_format ()
14088 {
14089 if (target_big_endian)
14090 {
14091 if (target_oabi)
14092 return "elf32-bigarm-oabi";
14093 else
14094 return "elf32-bigarm";
14095 }
14096 else
14097 {
14098 if (target_oabi)
14099 return "elf32-littlearm-oabi";
14100 else
14101 return "elf32-littlearm";
14102 }
14103 }
14104
14105 void
14106 armelf_frob_symbol (symp, puntp)
14107 symbolS * symp;
14108 int * puntp;
14109 {
14110 elf_frob_symbol (symp, puntp);
14111 }
14112
14113 static bfd_reloc_code_real_type
14114 arm_parse_reloc ()
14115 {
14116 char id [16];
14117 char * ip;
14118 unsigned int i;
14119 static struct
14120 {
14121 char * str;
14122 int len;
14123 bfd_reloc_code_real_type reloc;
14124 }
14125 reloc_map[] =
14126 {
14127 #define MAP(str,reloc) { str, sizeof (str) - 1, reloc }
14128 MAP ("(got)", BFD_RELOC_ARM_GOT32),
14129 MAP ("(gotoff)", BFD_RELOC_ARM_GOTOFF),
14130 /* ScottB: Jan 30, 1998 - Added support for parsing "var(PLT)"
14131 branch instructions generated by GCC for PLT relocs. */
14132 MAP ("(plt)", BFD_RELOC_ARM_PLT32),
14133 { NULL, 0, BFD_RELOC_UNUSED }
14134 #undef MAP
14135 };
14136
14137 for (i = 0, ip = input_line_pointer;
14138 i < sizeof (id) && (ISALNUM (*ip) || ISPUNCT (*ip));
14139 i++, ip++)
14140 id[i] = TOLOWER (*ip);
14141
14142 for (i = 0; reloc_map[i].str; i++)
14143 if (strncmp (id, reloc_map[i].str, reloc_map[i].len) == 0)
14144 break;
14145
14146 input_line_pointer += reloc_map[i].len;
14147
14148 return reloc_map[i].reloc;
14149 }
14150
14151 static void
14152 s_arm_elf_cons (nbytes)
14153 int nbytes;
14154 {
14155 expressionS exp;
14156
14157 #ifdef md_flush_pending_output
14158 md_flush_pending_output ();
14159 #endif
14160
14161 if (is_it_end_of_statement ())
14162 {
14163 demand_empty_rest_of_line ();
14164 return;
14165 }
14166
14167 #ifdef md_cons_align
14168 md_cons_align (nbytes);
14169 #endif
14170
14171 mapping_state (MAP_DATA);
14172 do
14173 {
14174 bfd_reloc_code_real_type reloc;
14175
14176 expression (& exp);
14177
14178 if (exp.X_op == O_symbol
14179 && * input_line_pointer == '('
14180 && (reloc = arm_parse_reloc ()) != BFD_RELOC_UNUSED)
14181 {
14182 reloc_howto_type *howto = bfd_reloc_type_lookup (stdoutput, reloc);
14183 int size = bfd_get_reloc_size (howto);
14184
14185 if (size > nbytes)
14186 as_bad ("%s relocations do not fit in %d bytes",
14187 howto->name, nbytes);
14188 else
14189 {
14190 register char *p = frag_more ((int) nbytes);
14191 int offset = nbytes - size;
14192
14193 fix_new_exp (frag_now, p - frag_now->fr_literal + offset, size,
14194 &exp, 0, reloc);
14195 }
14196 }
14197 else
14198 emit_expr (&exp, (unsigned int) nbytes);
14199 }
14200 while (*input_line_pointer++ == ',');
14201
14202 /* Put terminator back into stream. */
14203 input_line_pointer --;
14204 demand_empty_rest_of_line ();
14205 }
14206
14207 #endif /* OBJ_ELF */
14208
14209 /* This is called from HANDLE_ALIGN in write.c. Fill in the contents
14210 of an rs_align_code fragment. */
14211
14212 void
14213 arm_handle_align (fragP)
14214 fragS *fragP;
14215 {
14216 static char const arm_noop[4] = { 0x00, 0x00, 0xa0, 0xe1 };
14217 static char const thumb_noop[2] = { 0xc0, 0x46 };
14218 static char const arm_bigend_noop[4] = { 0xe1, 0xa0, 0x00, 0x00 };
14219 static char const thumb_bigend_noop[2] = { 0x46, 0xc0 };
14220
14221 int bytes, fix, noop_size;
14222 char * p;
14223 const char * noop;
14224
14225 if (fragP->fr_type != rs_align_code)
14226 return;
14227
14228 bytes = fragP->fr_next->fr_address - fragP->fr_address - fragP->fr_fix;
14229 p = fragP->fr_literal + fragP->fr_fix;
14230 fix = 0;
14231
14232 if (bytes > MAX_MEM_FOR_RS_ALIGN_CODE)
14233 bytes &= MAX_MEM_FOR_RS_ALIGN_CODE;
14234
14235 if (fragP->tc_frag_data)
14236 {
14237 if (target_big_endian)
14238 noop = thumb_bigend_noop;
14239 else
14240 noop = thumb_noop;
14241 noop_size = sizeof (thumb_noop);
14242 }
14243 else
14244 {
14245 if (target_big_endian)
14246 noop = arm_bigend_noop;
14247 else
14248 noop = arm_noop;
14249 noop_size = sizeof (arm_noop);
14250 }
14251
14252 if (bytes & (noop_size - 1))
14253 {
14254 fix = bytes & (noop_size - 1);
14255 memset (p, 0, fix);
14256 p += fix;
14257 bytes -= fix;
14258 }
14259
14260 while (bytes >= noop_size)
14261 {
14262 memcpy (p, noop, noop_size);
14263 p += noop_size;
14264 bytes -= noop_size;
14265 fix += noop_size;
14266 }
14267
14268 fragP->fr_fix += fix;
14269 fragP->fr_var = noop_size;
14270 }
14271
14272 /* Called from md_do_align. Used to create an alignment
14273 frag in a code section. */
14274
14275 void
14276 arm_frag_align_code (n, max)
14277 int n;
14278 int max;
14279 {
14280 char * p;
14281
14282 /* We assume that there will never be a requirement
14283 to support alignments greater than 32 bytes. */
14284 if (max > MAX_MEM_FOR_RS_ALIGN_CODE)
14285 as_fatal (_("alignments greater than 32 bytes not supported in .text sections."));
14286
14287 p = frag_var (rs_align_code,
14288 MAX_MEM_FOR_RS_ALIGN_CODE,
14289 1,
14290 (relax_substateT) max,
14291 (symbolS *) NULL,
14292 (offsetT) n,
14293 (char *) NULL);
14294 *p = 0;
14295
14296 }
14297
14298 /* Perform target specific initialisation of a frag. */
14299
14300 void
14301 arm_init_frag (fragP)
14302 fragS *fragP;
14303 {
14304 /* Record whether this frag is in an ARM or a THUMB area. */
14305 fragP->tc_frag_data = thumb_mode;
14306 }
This page took 0.358584 seconds and 4 git commands to generate.