85afdc28d7b6fe79944c1e6ba34e7d4cb1548868
[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
8 This file is part of GAS, the GNU Assembler.
9
10 GAS is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2, or (at your option)
13 any later version.
14
15 GAS is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with GAS; see the file COPYING. If not, write to the Free
22 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
23 02111-1307, USA. */
24
25 #include <string.h>
26 #define NO_RELOC 0
27 #include "as.h"
28 #include "safe-ctype.h"
29
30 /* Need TARGET_CPU. */
31 #include "config.h"
32 #include "subsegs.h"
33 #include "obstack.h"
34 #include "symbols.h"
35 #include "listing.h"
36
37 #ifdef OBJ_ELF
38 #include "elf/arm.h"
39 #include "dwarf2dbg.h"
40 #endif
41
42 /* XXX Set this to 1 after the next binutils release */
43 #define WARN_DEPRECATED 0
44
45 /* The following bitmasks control CPU extensions: */
46 #define ARM_EXT_V1 0x00000001 /* All processors (core set). */
47 #define ARM_EXT_V2 0x00000002 /* Multiply instructions. */
48 #define ARM_EXT_V2S 0x00000004 /* SWP instructions. */
49 #define ARM_EXT_V3 0x00000008 /* MSR MRS. */
50 #define ARM_EXT_V3M 0x00000010 /* Allow long multiplies. */
51 #define ARM_EXT_V4 0x00000020 /* Allow half word loads. */
52 #define ARM_EXT_V4T 0x00000040 /* Thumb v1. */
53 #define ARM_EXT_V5 0x00000080 /* Allow CLZ, etc. */
54 #define ARM_EXT_V5T 0x00000100 /* Thumb v2. */
55 #define ARM_EXT_V5ExP 0x00000200 /* DSP core set. */
56 #define ARM_EXT_V5E 0x00000400 /* DSP Double transfers. */
57 #define ARM_EXT_V5J 0x00000800 /* Jazelle extension. */
58 #define ARM_EXT_V6 0x00001000 /* ARM V6. */
59
60 /* Co-processor space extensions. */
61 #define ARM_CEXT_XSCALE 0x00800000 /* Allow MIA etc. */
62 #define ARM_CEXT_MAVERICK 0x00400000 /* Use Cirrus/DSP coprocessor. */
63 #define ARM_CEXT_IWMMXT 0x00200000 /* Intel Wireless MMX technology coprocessor. */
64
65 /* Architectures are the sum of the base and extensions. The ARM ARM (rev E)
66 defines the following: ARMv3, ARMv3M, ARMv4xM, ARMv4, ARMv4TxM, ARMv4T,
67 ARMv5xM, ARMv5, ARMv5TxM, ARMv5T, ARMv5TExP, ARMv5TE. To these we add
68 three more to cover cores prior to ARM6. Finally, there are cores which
69 implement further extensions in the co-processor space. */
70 #define ARM_ARCH_V1 ARM_EXT_V1
71 #define ARM_ARCH_V2 (ARM_ARCH_V1 | ARM_EXT_V2)
72 #define ARM_ARCH_V2S (ARM_ARCH_V2 | ARM_EXT_V2S)
73 #define ARM_ARCH_V3 (ARM_ARCH_V2S | ARM_EXT_V3)
74 #define ARM_ARCH_V3M (ARM_ARCH_V3 | ARM_EXT_V3M)
75 #define ARM_ARCH_V4xM (ARM_ARCH_V3 | ARM_EXT_V4)
76 #define ARM_ARCH_V4 (ARM_ARCH_V3M | ARM_EXT_V4)
77 #define ARM_ARCH_V4TxM (ARM_ARCH_V4xM | ARM_EXT_V4T)
78 #define ARM_ARCH_V4T (ARM_ARCH_V4 | ARM_EXT_V4T)
79 #define ARM_ARCH_V5xM (ARM_ARCH_V4xM | ARM_EXT_V5)
80 #define ARM_ARCH_V5 (ARM_ARCH_V4 | ARM_EXT_V5)
81 #define ARM_ARCH_V5TxM (ARM_ARCH_V5xM | ARM_EXT_V4T | ARM_EXT_V5T)
82 #define ARM_ARCH_V5T (ARM_ARCH_V5 | ARM_EXT_V4T | ARM_EXT_V5T)
83 #define ARM_ARCH_V5TExP (ARM_ARCH_V5T | ARM_EXT_V5ExP)
84 #define ARM_ARCH_V5TE (ARM_ARCH_V5TExP | ARM_EXT_V5E)
85 #define ARM_ARCH_V5TEJ (ARM_ARCH_V5TE | ARM_EXT_V5J)
86 #define ARM_ARCH_V6 (ARM_ARCH_V5TEJ | ARM_EXT_V6)
87
88 /* Processors with specific extensions in the co-processor space. */
89 #define ARM_ARCH_XSCALE (ARM_ARCH_V5TE | ARM_CEXT_XSCALE)
90 #define ARM_ARCH_IWMMXT (ARM_ARCH_XSCALE | ARM_CEXT_IWMMXT)
91
92 /* Some useful combinations: */
93 #define ARM_ANY 0x0000ffff /* Any basic core. */
94 #define ARM_ALL 0x00ffffff /* Any core + co-processor */
95 #define CPROC_ANY 0x00ff0000 /* Any co-processor */
96 #define FPU_ANY 0xff000000 /* Note this is ~ARM_ALL. */
97
98
99 #define FPU_FPA_EXT_V1 0x80000000 /* Base FPA instruction set. */
100 #define FPU_FPA_EXT_V2 0x40000000 /* LFM/SFM. */
101 #define FPU_VFP_EXT_NONE 0x20000000 /* Use VFP word-ordering. */
102 #define FPU_VFP_EXT_V1xD 0x10000000 /* Base VFP instruction set. */
103 #define FPU_VFP_EXT_V1 0x08000000 /* Double-precision insns. */
104 #define FPU_VFP_EXT_V2 0x04000000 /* ARM10E VFPr1. */
105 #define FPU_MAVERICK 0x02000000 /* Cirrus Maverick. */
106 #define FPU_NONE 0
107
108 #define FPU_ARCH_FPE FPU_FPA_EXT_V1
109 #define FPU_ARCH_FPA (FPU_ARCH_FPE | FPU_FPA_EXT_V2)
110
111 #define FPU_ARCH_VFP FPU_VFP_EXT_NONE
112 #define FPU_ARCH_VFP_V1xD (FPU_VFP_EXT_V1xD | FPU_VFP_EXT_NONE)
113 #define FPU_ARCH_VFP_V1 (FPU_ARCH_VFP_V1xD | FPU_VFP_EXT_V1)
114 #define FPU_ARCH_VFP_V2 (FPU_ARCH_VFP_V1 | FPU_VFP_EXT_V2)
115
116 #define FPU_ARCH_MAVERICK FPU_MAVERICK
117
118 enum arm_float_abi
119 {
120 ARM_FLOAT_ABI_HARD,
121 ARM_FLOAT_ABI_SOFTFP,
122 ARM_FLOAT_ABI_SOFT
123 };
124
125 /* Types of processor to assemble for. */
126 #define ARM_1 ARM_ARCH_V1
127 #define ARM_2 ARM_ARCH_V2
128 #define ARM_3 ARM_ARCH_V2S
129 #define ARM_250 ARM_ARCH_V2S
130 #define ARM_6 ARM_ARCH_V3
131 #define ARM_7 ARM_ARCH_V3
132 #define ARM_8 ARM_ARCH_V4
133 #define ARM_9 ARM_ARCH_V4T
134 #define ARM_STRONG ARM_ARCH_V4
135 #define ARM_CPU_MASK 0x0000000f /* XXX? */
136
137 #ifndef CPU_DEFAULT
138 #if defined __XSCALE__
139 #define CPU_DEFAULT (ARM_ARCH_XSCALE)
140 #else
141 #if defined __thumb__
142 #define CPU_DEFAULT (ARM_ARCH_V5T)
143 #else
144 #define CPU_DEFAULT ARM_ANY
145 #endif
146 #endif
147 #endif
148
149 #ifdef TE_LINUX
150 #define FPU_DEFAULT FPU_ARCH_FPA
151 #endif
152
153 #ifdef TE_NetBSD
154 #ifdef OBJ_ELF
155 #define FPU_DEFAULT FPU_ARCH_VFP /* Soft-float, but VFP order. */
156 #else
157 /* Legacy a.out format. */
158 #define FPU_DEFAULT FPU_ARCH_FPA /* Soft-float, but FPA order. */
159 #endif
160 #endif
161
162 /* For backwards compatibility we default to the FPA. */
163 #ifndef FPU_DEFAULT
164 #define FPU_DEFAULT FPU_ARCH_FPA
165 #endif
166
167 #define streq(a, b) (strcmp (a, b) == 0)
168 #define skip_whitespace(str) while (*(str) == ' ') ++(str)
169
170 static unsigned long cpu_variant;
171 static int target_oabi = 0;
172
173 /* Flags stored in private area of BFD structure. */
174 static int uses_apcs_26 = FALSE;
175 static int atpcs = FALSE;
176 static int support_interwork = FALSE;
177 static int uses_apcs_float = FALSE;
178 static int pic_code = FALSE;
179
180 /* Variables that we set while parsing command-line options. Once all
181 options have been read we re-process these values to set the real
182 assembly flags. */
183 static int legacy_cpu = -1;
184 static int legacy_fpu = -1;
185
186 static int mcpu_cpu_opt = -1;
187 static int mcpu_fpu_opt = -1;
188 static int march_cpu_opt = -1;
189 static int march_fpu_opt = -1;
190 static int mfpu_opt = -1;
191 static int mfloat_abi_opt = -1;
192
193 /* This array holds the chars that always start a comment. If the
194 pre-processor is disabled, these aren't very useful. */
195 const char comment_chars[] = "@";
196
197 /* This array holds the chars that only start a comment at the beginning of
198 a line. If the line seems to have the form '# 123 filename'
199 .line and .file directives will appear in the pre-processed output. */
200 /* Note that input_file.c hand checks for '#' at the beginning of the
201 first line of the input file. This is because the compiler outputs
202 #NO_APP at the beginning of its output. */
203 /* Also note that comments like this one will always work. */
204 const char line_comment_chars[] = "#";
205
206 const char line_separator_chars[] = ";";
207
208 /* Chars that can be used to separate mant
209 from exp in floating point numbers. */
210 const char EXP_CHARS[] = "eE";
211
212 /* Chars that mean this number is a floating point constant. */
213 /* As in 0f12.456 */
214 /* or 0d1.2345e12 */
215
216 const char FLT_CHARS[] = "rRsSfFdDxXeEpP";
217
218 /* Prefix characters that indicate the start of an immediate
219 value. */
220 #define is_immediate_prefix(C) ((C) == '#' || (C) == '$')
221
222 #ifdef OBJ_ELF
223 /* Pre-defined "_GLOBAL_OFFSET_TABLE_" */
224 symbolS * GOT_symbol;
225 #endif
226
227 /* Size of relocation record. */
228 const int md_reloc_size = 8;
229
230 /* 0: assemble for ARM,
231 1: assemble for Thumb,
232 2: assemble for Thumb even though target CPU does not support thumb
233 instructions. */
234 static int thumb_mode = 0;
235
236 typedef struct arm_fix
237 {
238 int thumb_mode;
239 } arm_fix_data;
240
241 struct arm_it
242 {
243 const char * error;
244 unsigned long instruction;
245 int size;
246 struct
247 {
248 bfd_reloc_code_real_type type;
249 expressionS exp;
250 int pc_rel;
251 } reloc;
252 };
253
254 struct arm_it inst;
255
256 enum asm_shift_index
257 {
258 SHIFT_LSL = 0,
259 SHIFT_LSR,
260 SHIFT_ASR,
261 SHIFT_ROR,
262 SHIFT_RRX
263 };
264
265 struct asm_shift_properties
266 {
267 enum asm_shift_index index;
268 unsigned long bit_field;
269 unsigned int allows_0 : 1;
270 unsigned int allows_32 : 1;
271 };
272
273 static const struct asm_shift_properties shift_properties [] =
274 {
275 { SHIFT_LSL, 0, 1, 0},
276 { SHIFT_LSR, 0x20, 0, 1},
277 { SHIFT_ASR, 0x40, 0, 1},
278 { SHIFT_ROR, 0x60, 0, 0},
279 { SHIFT_RRX, 0x60, 0, 0}
280 };
281
282 struct asm_shift_name
283 {
284 const char * name;
285 const struct asm_shift_properties * properties;
286 };
287
288 static const struct asm_shift_name shift_names [] =
289 {
290 { "asl", shift_properties + SHIFT_LSL },
291 { "lsl", shift_properties + SHIFT_LSL },
292 { "lsr", shift_properties + SHIFT_LSR },
293 { "asr", shift_properties + SHIFT_ASR },
294 { "ror", shift_properties + SHIFT_ROR },
295 { "rrx", shift_properties + SHIFT_RRX },
296 { "ASL", shift_properties + SHIFT_LSL },
297 { "LSL", shift_properties + SHIFT_LSL },
298 { "LSR", shift_properties + SHIFT_LSR },
299 { "ASR", shift_properties + SHIFT_ASR },
300 { "ROR", shift_properties + SHIFT_ROR },
301 { "RRX", shift_properties + SHIFT_RRX }
302 };
303
304 /* Any kind of shift is accepted. */
305 #define NO_SHIFT_RESTRICT 1
306 /* The shift operand must be an immediate value, not a register. */
307 #define SHIFT_IMMEDIATE 0
308 /* The shift must be LSL or ASR and the operand must be an immediate. */
309 #define SHIFT_LSL_OR_ASR_IMMEDIATE 2
310 /* The shift must be ASR and the operand must be an immediate. */
311 #define SHIFT_ASR_IMMEDIATE 3
312 /* The shift must be LSL and the operand must be an immediate. */
313 #define SHIFT_LSL_IMMEDIATE 4
314
315 #define NUM_FLOAT_VALS 8
316
317 const char * fp_const[] =
318 {
319 "0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0", 0
320 };
321
322 /* Number of littlenums required to hold an extended precision number. */
323 #define MAX_LITTLENUMS 6
324
325 LITTLENUM_TYPE fp_values[NUM_FLOAT_VALS][MAX_LITTLENUMS];
326
327 #define FAIL (-1)
328 #define SUCCESS (0)
329
330 /* Whether a Co-processor load/store operation accepts write-back forms. */
331 #define CP_WB_OK 1
332 #define CP_NO_WB 0
333
334 #define SUFF_S 1
335 #define SUFF_D 2
336 #define SUFF_E 3
337 #define SUFF_P 4
338
339 #define CP_T_X 0x00008000
340 #define CP_T_Y 0x00400000
341 #define CP_T_Pre 0x01000000
342 #define CP_T_UD 0x00800000
343 #define CP_T_WB 0x00200000
344
345 #define CONDS_BIT 0x00100000
346 #define LOAD_BIT 0x00100000
347
348 #define DOUBLE_LOAD_FLAG 0x00000001
349
350 struct asm_cond
351 {
352 const char * template;
353 unsigned long value;
354 };
355
356 #define COND_ALWAYS 0xe0000000
357 #define COND_MASK 0xf0000000
358
359 static const struct asm_cond conds[] =
360 {
361 {"eq", 0x00000000},
362 {"ne", 0x10000000},
363 {"cs", 0x20000000}, {"hs", 0x20000000},
364 {"cc", 0x30000000}, {"ul", 0x30000000}, {"lo", 0x30000000},
365 {"mi", 0x40000000},
366 {"pl", 0x50000000},
367 {"vs", 0x60000000},
368 {"vc", 0x70000000},
369 {"hi", 0x80000000},
370 {"ls", 0x90000000},
371 {"ge", 0xa0000000},
372 {"lt", 0xb0000000},
373 {"gt", 0xc0000000},
374 {"le", 0xd0000000},
375 {"al", 0xe0000000},
376 {"nv", 0xf0000000}
377 };
378
379 struct asm_psr
380 {
381 const char *template;
382 bfd_boolean cpsr;
383 unsigned long field;
384 };
385
386 /* The bit that distinguishes CPSR and SPSR. */
387 #define SPSR_BIT (1 << 22)
388
389 /* How many bits to shift the PSR_xxx bits up by. */
390 #define PSR_SHIFT 16
391
392 #define PSR_c (1 << 0)
393 #define PSR_x (1 << 1)
394 #define PSR_s (1 << 2)
395 #define PSR_f (1 << 3)
396
397 static const struct asm_psr psrs[] =
398 {
399 {"CPSR", TRUE, PSR_c | PSR_f},
400 {"CPSR_all", TRUE, PSR_c | PSR_f},
401 {"SPSR", FALSE, PSR_c | PSR_f},
402 {"SPSR_all", FALSE, PSR_c | PSR_f},
403 {"CPSR_flg", TRUE, PSR_f},
404 {"CPSR_f", TRUE, PSR_f},
405 {"SPSR_flg", FALSE, PSR_f},
406 {"SPSR_f", FALSE, PSR_f},
407 {"CPSR_c", TRUE, PSR_c},
408 {"CPSR_ctl", TRUE, PSR_c},
409 {"SPSR_c", FALSE, PSR_c},
410 {"SPSR_ctl", FALSE, PSR_c},
411 {"CPSR_x", TRUE, PSR_x},
412 {"CPSR_s", TRUE, PSR_s},
413 {"SPSR_x", FALSE, PSR_x},
414 {"SPSR_s", FALSE, PSR_s},
415 /* Combinations of flags. */
416 {"CPSR_fs", TRUE, PSR_f | PSR_s},
417 {"CPSR_fx", TRUE, PSR_f | PSR_x},
418 {"CPSR_fc", TRUE, PSR_f | PSR_c},
419 {"CPSR_sf", TRUE, PSR_s | PSR_f},
420 {"CPSR_sx", TRUE, PSR_s | PSR_x},
421 {"CPSR_sc", TRUE, PSR_s | PSR_c},
422 {"CPSR_xf", TRUE, PSR_x | PSR_f},
423 {"CPSR_xs", TRUE, PSR_x | PSR_s},
424 {"CPSR_xc", TRUE, PSR_x | PSR_c},
425 {"CPSR_cf", TRUE, PSR_c | PSR_f},
426 {"CPSR_cs", TRUE, PSR_c | PSR_s},
427 {"CPSR_cx", TRUE, PSR_c | PSR_x},
428 {"CPSR_fsx", TRUE, PSR_f | PSR_s | PSR_x},
429 {"CPSR_fsc", TRUE, PSR_f | PSR_s | PSR_c},
430 {"CPSR_fxs", TRUE, PSR_f | PSR_x | PSR_s},
431 {"CPSR_fxc", TRUE, PSR_f | PSR_x | PSR_c},
432 {"CPSR_fcs", TRUE, PSR_f | PSR_c | PSR_s},
433 {"CPSR_fcx", TRUE, PSR_f | PSR_c | PSR_x},
434 {"CPSR_sfx", TRUE, PSR_s | PSR_f | PSR_x},
435 {"CPSR_sfc", TRUE, PSR_s | PSR_f | PSR_c},
436 {"CPSR_sxf", TRUE, PSR_s | PSR_x | PSR_f},
437 {"CPSR_sxc", TRUE, PSR_s | PSR_x | PSR_c},
438 {"CPSR_scf", TRUE, PSR_s | PSR_c | PSR_f},
439 {"CPSR_scx", TRUE, PSR_s | PSR_c | PSR_x},
440 {"CPSR_xfs", TRUE, PSR_x | PSR_f | PSR_s},
441 {"CPSR_xfc", TRUE, PSR_x | PSR_f | PSR_c},
442 {"CPSR_xsf", TRUE, PSR_x | PSR_s | PSR_f},
443 {"CPSR_xsc", TRUE, PSR_x | PSR_s | PSR_c},
444 {"CPSR_xcf", TRUE, PSR_x | PSR_c | PSR_f},
445 {"CPSR_xcs", TRUE, PSR_x | PSR_c | PSR_s},
446 {"CPSR_cfs", TRUE, PSR_c | PSR_f | PSR_s},
447 {"CPSR_cfx", TRUE, PSR_c | PSR_f | PSR_x},
448 {"CPSR_csf", TRUE, PSR_c | PSR_s | PSR_f},
449 {"CPSR_csx", TRUE, PSR_c | PSR_s | PSR_x},
450 {"CPSR_cxf", TRUE, PSR_c | PSR_x | PSR_f},
451 {"CPSR_cxs", TRUE, PSR_c | PSR_x | PSR_s},
452 {"CPSR_fsxc", TRUE, PSR_f | PSR_s | PSR_x | PSR_c},
453 {"CPSR_fscx", TRUE, PSR_f | PSR_s | PSR_c | PSR_x},
454 {"CPSR_fxsc", TRUE, PSR_f | PSR_x | PSR_s | PSR_c},
455 {"CPSR_fxcs", TRUE, PSR_f | PSR_x | PSR_c | PSR_s},
456 {"CPSR_fcsx", TRUE, PSR_f | PSR_c | PSR_s | PSR_x},
457 {"CPSR_fcxs", TRUE, PSR_f | PSR_c | PSR_x | PSR_s},
458 {"CPSR_sfxc", TRUE, PSR_s | PSR_f | PSR_x | PSR_c},
459 {"CPSR_sfcx", TRUE, PSR_s | PSR_f | PSR_c | PSR_x},
460 {"CPSR_sxfc", TRUE, PSR_s | PSR_x | PSR_f | PSR_c},
461 {"CPSR_sxcf", TRUE, PSR_s | PSR_x | PSR_c | PSR_f},
462 {"CPSR_scfx", TRUE, PSR_s | PSR_c | PSR_f | PSR_x},
463 {"CPSR_scxf", TRUE, PSR_s | PSR_c | PSR_x | PSR_f},
464 {"CPSR_xfsc", TRUE, PSR_x | PSR_f | PSR_s | PSR_c},
465 {"CPSR_xfcs", TRUE, PSR_x | PSR_f | PSR_c | PSR_s},
466 {"CPSR_xsfc", TRUE, PSR_x | PSR_s | PSR_f | PSR_c},
467 {"CPSR_xscf", TRUE, PSR_x | PSR_s | PSR_c | PSR_f},
468 {"CPSR_xcfs", TRUE, PSR_x | PSR_c | PSR_f | PSR_s},
469 {"CPSR_xcsf", TRUE, PSR_x | PSR_c | PSR_s | PSR_f},
470 {"CPSR_cfsx", TRUE, PSR_c | PSR_f | PSR_s | PSR_x},
471 {"CPSR_cfxs", TRUE, PSR_c | PSR_f | PSR_x | PSR_s},
472 {"CPSR_csfx", TRUE, PSR_c | PSR_s | PSR_f | PSR_x},
473 {"CPSR_csxf", TRUE, PSR_c | PSR_s | PSR_x | PSR_f},
474 {"CPSR_cxfs", TRUE, PSR_c | PSR_x | PSR_f | PSR_s},
475 {"CPSR_cxsf", TRUE, PSR_c | PSR_x | PSR_s | PSR_f},
476 {"SPSR_fs", FALSE, PSR_f | PSR_s},
477 {"SPSR_fx", FALSE, PSR_f | PSR_x},
478 {"SPSR_fc", FALSE, PSR_f | PSR_c},
479 {"SPSR_sf", FALSE, PSR_s | PSR_f},
480 {"SPSR_sx", FALSE, PSR_s | PSR_x},
481 {"SPSR_sc", FALSE, PSR_s | PSR_c},
482 {"SPSR_xf", FALSE, PSR_x | PSR_f},
483 {"SPSR_xs", FALSE, PSR_x | PSR_s},
484 {"SPSR_xc", FALSE, PSR_x | PSR_c},
485 {"SPSR_cf", FALSE, PSR_c | PSR_f},
486 {"SPSR_cs", FALSE, PSR_c | PSR_s},
487 {"SPSR_cx", FALSE, PSR_c | PSR_x},
488 {"SPSR_fsx", FALSE, PSR_f | PSR_s | PSR_x},
489 {"SPSR_fsc", FALSE, PSR_f | PSR_s | PSR_c},
490 {"SPSR_fxs", FALSE, PSR_f | PSR_x | PSR_s},
491 {"SPSR_fxc", FALSE, PSR_f | PSR_x | PSR_c},
492 {"SPSR_fcs", FALSE, PSR_f | PSR_c | PSR_s},
493 {"SPSR_fcx", FALSE, PSR_f | PSR_c | PSR_x},
494 {"SPSR_sfx", FALSE, PSR_s | PSR_f | PSR_x},
495 {"SPSR_sfc", FALSE, PSR_s | PSR_f | PSR_c},
496 {"SPSR_sxf", FALSE, PSR_s | PSR_x | PSR_f},
497 {"SPSR_sxc", FALSE, PSR_s | PSR_x | PSR_c},
498 {"SPSR_scf", FALSE, PSR_s | PSR_c | PSR_f},
499 {"SPSR_scx", FALSE, PSR_s | PSR_c | PSR_x},
500 {"SPSR_xfs", FALSE, PSR_x | PSR_f | PSR_s},
501 {"SPSR_xfc", FALSE, PSR_x | PSR_f | PSR_c},
502 {"SPSR_xsf", FALSE, PSR_x | PSR_s | PSR_f},
503 {"SPSR_xsc", FALSE, PSR_x | PSR_s | PSR_c},
504 {"SPSR_xcf", FALSE, PSR_x | PSR_c | PSR_f},
505 {"SPSR_xcs", FALSE, PSR_x | PSR_c | PSR_s},
506 {"SPSR_cfs", FALSE, PSR_c | PSR_f | PSR_s},
507 {"SPSR_cfx", FALSE, PSR_c | PSR_f | PSR_x},
508 {"SPSR_csf", FALSE, PSR_c | PSR_s | PSR_f},
509 {"SPSR_csx", FALSE, PSR_c | PSR_s | PSR_x},
510 {"SPSR_cxf", FALSE, PSR_c | PSR_x | PSR_f},
511 {"SPSR_cxs", FALSE, PSR_c | PSR_x | PSR_s},
512 {"SPSR_fsxc", FALSE, PSR_f | PSR_s | PSR_x | PSR_c},
513 {"SPSR_fscx", FALSE, PSR_f | PSR_s | PSR_c | PSR_x},
514 {"SPSR_fxsc", FALSE, PSR_f | PSR_x | PSR_s | PSR_c},
515 {"SPSR_fxcs", FALSE, PSR_f | PSR_x | PSR_c | PSR_s},
516 {"SPSR_fcsx", FALSE, PSR_f | PSR_c | PSR_s | PSR_x},
517 {"SPSR_fcxs", FALSE, PSR_f | PSR_c | PSR_x | PSR_s},
518 {"SPSR_sfxc", FALSE, PSR_s | PSR_f | PSR_x | PSR_c},
519 {"SPSR_sfcx", FALSE, PSR_s | PSR_f | PSR_c | PSR_x},
520 {"SPSR_sxfc", FALSE, PSR_s | PSR_x | PSR_f | PSR_c},
521 {"SPSR_sxcf", FALSE, PSR_s | PSR_x | PSR_c | PSR_f},
522 {"SPSR_scfx", FALSE, PSR_s | PSR_c | PSR_f | PSR_x},
523 {"SPSR_scxf", FALSE, PSR_s | PSR_c | PSR_x | PSR_f},
524 {"SPSR_xfsc", FALSE, PSR_x | PSR_f | PSR_s | PSR_c},
525 {"SPSR_xfcs", FALSE, PSR_x | PSR_f | PSR_c | PSR_s},
526 {"SPSR_xsfc", FALSE, PSR_x | PSR_s | PSR_f | PSR_c},
527 {"SPSR_xscf", FALSE, PSR_x | PSR_s | PSR_c | PSR_f},
528 {"SPSR_xcfs", FALSE, PSR_x | PSR_c | PSR_f | PSR_s},
529 {"SPSR_xcsf", FALSE, PSR_x | PSR_c | PSR_s | PSR_f},
530 {"SPSR_cfsx", FALSE, PSR_c | PSR_f | PSR_s | PSR_x},
531 {"SPSR_cfxs", FALSE, PSR_c | PSR_f | PSR_x | PSR_s},
532 {"SPSR_csfx", FALSE, PSR_c | PSR_s | PSR_f | PSR_x},
533 {"SPSR_csxf", FALSE, PSR_c | PSR_s | PSR_x | PSR_f},
534 {"SPSR_cxfs", FALSE, PSR_c | PSR_x | PSR_f | PSR_s},
535 {"SPSR_cxsf", FALSE, PSR_c | PSR_x | PSR_s | PSR_f},
536 };
537
538 enum wreg_type
539 {
540 IWMMXT_REG_WR = 0,
541 IWMMXT_REG_WC = 1,
542 IWMMXT_REG_WR_OR_WC = 2,
543 IWMMXT_REG_WCG
544 };
545
546 enum iwmmxt_insn_type
547 {
548 check_rd,
549 check_wr,
550 check_wrwr,
551 check_wrwrwr,
552 check_wrwrwcg,
553 check_tbcst,
554 check_tmovmsk,
555 check_tmia,
556 check_tmcrr,
557 check_tmrrc,
558 check_tmcr,
559 check_tmrc,
560 check_tinsr,
561 check_textrc,
562 check_waligni,
563 check_textrm,
564 check_wshufh
565 };
566
567 enum vfp_dp_reg_pos
568 {
569 VFP_REG_Dd, VFP_REG_Dm, VFP_REG_Dn
570 };
571
572 enum vfp_sp_reg_pos
573 {
574 VFP_REG_Sd, VFP_REG_Sm, VFP_REG_Sn
575 };
576
577 enum vfp_ldstm_type
578 {
579 VFP_LDSTMIA, VFP_LDSTMDB, VFP_LDSTMIAX, VFP_LDSTMDBX
580 };
581
582 /* VFP system registers. */
583 struct vfp_reg
584 {
585 const char *name;
586 unsigned long regno;
587 };
588
589 static const struct vfp_reg vfp_regs[] =
590 {
591 {"fpsid", 0x00000000},
592 {"FPSID", 0x00000000},
593 {"fpscr", 0x00010000},
594 {"FPSCR", 0x00010000},
595 {"fpexc", 0x00080000},
596 {"FPEXC", 0x00080000}
597 };
598
599 /* Structure for a hash table entry for a register. */
600 struct reg_entry
601 {
602 const char * name;
603 int number;
604 bfd_boolean builtin;
605 };
606
607 /* Some well known registers that we refer to directly elsewhere. */
608 #define REG_SP 13
609 #define REG_LR 14
610 #define REG_PC 15
611
612 #define wr_register(reg) ((reg ^ WR_PREFIX) >= 0 && (reg ^ WR_PREFIX) <= 15)
613 #define wc_register(reg) ((reg ^ WC_PREFIX) >= 0 && (reg ^ WC_PREFIX) <= 15)
614 #define wcg_register(reg) ((reg ^ WC_PREFIX) >= 8 && (reg ^ WC_PREFIX) <= 11)
615
616 /* These are the standard names. Users can add aliases with .req.
617 and delete them with .unreq. */
618
619 /* Integer Register Numbers. */
620 static const struct reg_entry rn_table[] =
621 {
622 {"r0", 0, TRUE}, {"r1", 1, TRUE}, {"r2", 2, TRUE}, {"r3", 3, TRUE},
623 {"r4", 4, TRUE}, {"r5", 5, TRUE}, {"r6", 6, TRUE}, {"r7", 7, TRUE},
624 {"r8", 8, TRUE}, {"r9", 9, TRUE}, {"r10", 10, TRUE}, {"r11", 11, TRUE},
625 {"r12", 12, TRUE}, {"r13", REG_SP, TRUE}, {"r14", REG_LR, TRUE}, {"r15", REG_PC, TRUE},
626 /* ATPCS Synonyms. */
627 {"a1", 0, TRUE}, {"a2", 1, TRUE}, {"a3", 2, TRUE}, {"a4", 3, TRUE},
628 {"v1", 4, TRUE}, {"v2", 5, TRUE}, {"v3", 6, TRUE}, {"v4", 7, TRUE},
629 {"v5", 8, TRUE}, {"v6", 9, TRUE}, {"v7", 10, TRUE}, {"v8", 11, TRUE},
630 /* Well-known aliases. */
631 {"wr", 7, TRUE}, {"sb", 9, TRUE}, {"sl", 10, TRUE}, {"fp", 11, TRUE},
632 {"ip", 12, TRUE}, {"sp", REG_SP, TRUE}, {"lr", REG_LR, TRUE}, {"pc", REG_PC, TRUE},
633 {NULL, 0, TRUE}
634 };
635
636 #define WR_PREFIX 0x200
637 #define WC_PREFIX 0x400
638
639 static const struct reg_entry iwmmxt_table[] =
640 {
641 /* Intel Wireless MMX technology register names. */
642 { "wr0", 0x0 | WR_PREFIX, TRUE}, {"wr1", 0x1 | WR_PREFIX, TRUE},
643 { "wr2", 0x2 | WR_PREFIX, TRUE}, {"wr3", 0x3 | WR_PREFIX, TRUE},
644 { "wr4", 0x4 | WR_PREFIX, TRUE}, {"wr5", 0x5 | WR_PREFIX, TRUE},
645 { "wr6", 0x6 | WR_PREFIX, TRUE}, {"wr7", 0x7 | WR_PREFIX, TRUE},
646 { "wr8", 0x8 | WR_PREFIX, TRUE}, {"wr9", 0x9 | WR_PREFIX, TRUE},
647 { "wr10", 0xa | WR_PREFIX, TRUE}, {"wr11", 0xb | WR_PREFIX, TRUE},
648 { "wr12", 0xc | WR_PREFIX, TRUE}, {"wr13", 0xd | WR_PREFIX, TRUE},
649 { "wr14", 0xe | WR_PREFIX, TRUE}, {"wr15", 0xf | WR_PREFIX, TRUE},
650 { "wcid", 0x0 | WC_PREFIX, TRUE}, {"wcon", 0x1 | WC_PREFIX, TRUE},
651 {"wcssf", 0x2 | WC_PREFIX, TRUE}, {"wcasf", 0x3 | WC_PREFIX, TRUE},
652 {"wcgr0", 0x8 | WC_PREFIX, TRUE}, {"wcgr1", 0x9 | WC_PREFIX, TRUE},
653 {"wcgr2", 0xa | WC_PREFIX, TRUE}, {"wcgr3", 0xb | WC_PREFIX, TRUE},
654
655 { "wR0", 0x0 | WR_PREFIX, TRUE}, {"wR1", 0x1 | WR_PREFIX, TRUE},
656 { "wR2", 0x2 | WR_PREFIX, TRUE}, {"wR3", 0x3 | WR_PREFIX, TRUE},
657 { "wR4", 0x4 | WR_PREFIX, TRUE}, {"wR5", 0x5 | WR_PREFIX, TRUE},
658 { "wR6", 0x6 | WR_PREFIX, TRUE}, {"wR7", 0x7 | WR_PREFIX, TRUE},
659 { "wR8", 0x8 | WR_PREFIX, TRUE}, {"wR9", 0x9 | WR_PREFIX, TRUE},
660 { "wR10", 0xa | WR_PREFIX, TRUE}, {"wR11", 0xb | WR_PREFIX, TRUE},
661 { "wR12", 0xc | WR_PREFIX, TRUE}, {"wR13", 0xd | WR_PREFIX, TRUE},
662 { "wR14", 0xe | WR_PREFIX, TRUE}, {"wR15", 0xf | WR_PREFIX, TRUE},
663 { "wCID", 0x0 | WC_PREFIX, TRUE}, {"wCon", 0x1 | WC_PREFIX, TRUE},
664 {"wCSSF", 0x2 | WC_PREFIX, TRUE}, {"wCASF", 0x3 | WC_PREFIX, TRUE},
665 {"wCGR0", 0x8 | WC_PREFIX, TRUE}, {"wCGR1", 0x9 | WC_PREFIX, TRUE},
666 {"wCGR2", 0xa | WC_PREFIX, TRUE}, {"wCGR3", 0xb | WC_PREFIX, TRUE},
667 {NULL, 0, TRUE}
668 };
669
670 /* Co-processor Numbers. */
671 static const struct reg_entry cp_table[] =
672 {
673 {"p0", 0, TRUE}, {"p1", 1, TRUE}, {"p2", 2, TRUE}, {"p3", 3, TRUE},
674 {"p4", 4, TRUE}, {"p5", 5, TRUE}, {"p6", 6, TRUE}, {"p7", 7, TRUE},
675 {"p8", 8, TRUE}, {"p9", 9, TRUE}, {"p10", 10, TRUE}, {"p11", 11, TRUE},
676 {"p12", 12, TRUE}, {"p13", 13, TRUE}, {"p14", 14, TRUE}, {"p15", 15, TRUE},
677 {NULL, 0, TRUE}
678 };
679
680 /* Co-processor Register Numbers. */
681 static const struct reg_entry cn_table[] =
682 {
683 {"c0", 0, TRUE}, {"c1", 1, TRUE}, {"c2", 2, TRUE}, {"c3", 3, TRUE},
684 {"c4", 4, TRUE}, {"c5", 5, TRUE}, {"c6", 6, TRUE}, {"c7", 7, TRUE},
685 {"c8", 8, TRUE}, {"c9", 9, TRUE}, {"c10", 10, TRUE}, {"c11", 11, TRUE},
686 {"c12", 12, TRUE}, {"c13", 13, TRUE}, {"c14", 14, TRUE}, {"c15", 15, TRUE},
687 /* Not really valid, but kept for back-wards compatibility. */
688 {"cr0", 0, TRUE}, {"cr1", 1, TRUE}, {"cr2", 2, TRUE}, {"cr3", 3, TRUE},
689 {"cr4", 4, TRUE}, {"cr5", 5, TRUE}, {"cr6", 6, TRUE}, {"cr7", 7, TRUE},
690 {"cr8", 8, TRUE}, {"cr9", 9, TRUE}, {"cr10", 10, TRUE}, {"cr11", 11, TRUE},
691 {"cr12", 12, TRUE}, {"cr13", 13, TRUE}, {"cr14", 14, TRUE}, {"cr15", 15, TRUE},
692 {NULL, 0, TRUE}
693 };
694
695 /* FPA Registers. */
696 static const struct reg_entry fn_table[] =
697 {
698 {"f0", 0, TRUE}, {"f1", 1, TRUE}, {"f2", 2, TRUE}, {"f3", 3, TRUE},
699 {"f4", 4, TRUE}, {"f5", 5, TRUE}, {"f6", 6, TRUE}, {"f7", 7, TRUE},
700 {NULL, 0, TRUE}
701 };
702
703 /* VFP SP Registers. */
704 static const struct reg_entry sn_table[] =
705 {
706 {"s0", 0, TRUE}, {"s1", 1, TRUE}, {"s2", 2, TRUE}, {"s3", 3, TRUE},
707 {"s4", 4, TRUE}, {"s5", 5, TRUE}, {"s6", 6, TRUE}, {"s7", 7, TRUE},
708 {"s8", 8, TRUE}, {"s9", 9, TRUE}, {"s10", 10, TRUE}, {"s11", 11, TRUE},
709 {"s12", 12, TRUE}, {"s13", 13, TRUE}, {"s14", 14, TRUE}, {"s15", 15, TRUE},
710 {"s16", 16, TRUE}, {"s17", 17, TRUE}, {"s18", 18, TRUE}, {"s19", 19, TRUE},
711 {"s20", 20, TRUE}, {"s21", 21, TRUE}, {"s22", 22, TRUE}, {"s23", 23, TRUE},
712 {"s24", 24, TRUE}, {"s25", 25, TRUE}, {"s26", 26, TRUE}, {"s27", 27, TRUE},
713 {"s28", 28, TRUE}, {"s29", 29, TRUE}, {"s30", 30, TRUE}, {"s31", 31, TRUE},
714 {NULL, 0, TRUE}
715 };
716
717 /* VFP DP Registers. */
718 static const struct reg_entry dn_table[] =
719 {
720 {"d0", 0, TRUE}, {"d1", 1, TRUE}, {"d2", 2, TRUE}, {"d3", 3, TRUE},
721 {"d4", 4, TRUE}, {"d5", 5, TRUE}, {"d6", 6, TRUE}, {"d7", 7, TRUE},
722 {"d8", 8, TRUE}, {"d9", 9, TRUE}, {"d10", 10, TRUE}, {"d11", 11, TRUE},
723 {"d12", 12, TRUE}, {"d13", 13, TRUE}, {"d14", 14, TRUE}, {"d15", 15, TRUE},
724 {NULL, 0, TRUE}
725 };
726
727 /* Maverick DSP coprocessor registers. */
728 static const struct reg_entry mav_mvf_table[] =
729 {
730 {"mvf0", 0, TRUE}, {"mvf1", 1, TRUE}, {"mvf2", 2, TRUE}, {"mvf3", 3, TRUE},
731 {"mvf4", 4, TRUE}, {"mvf5", 5, TRUE}, {"mvf6", 6, TRUE}, {"mvf7", 7, TRUE},
732 {"mvf8", 8, TRUE}, {"mvf9", 9, TRUE}, {"mvf10", 10, TRUE}, {"mvf11", 11, TRUE},
733 {"mvf12", 12, TRUE}, {"mvf13", 13, TRUE}, {"mvf14", 14, TRUE}, {"mvf15", 15, TRUE},
734 {NULL, 0, TRUE}
735 };
736
737 static const struct reg_entry mav_mvd_table[] =
738 {
739 {"mvd0", 0, TRUE}, {"mvd1", 1, TRUE}, {"mvd2", 2, TRUE}, {"mvd3", 3, TRUE},
740 {"mvd4", 4, TRUE}, {"mvd5", 5, TRUE}, {"mvd6", 6, TRUE}, {"mvd7", 7, TRUE},
741 {"mvd8", 8, TRUE}, {"mvd9", 9, TRUE}, {"mvd10", 10, TRUE}, {"mvd11", 11, TRUE},
742 {"mvd12", 12, TRUE}, {"mvd13", 13, TRUE}, {"mvd14", 14, TRUE}, {"mvd15", 15, TRUE},
743 {NULL, 0, TRUE}
744 };
745
746 static const struct reg_entry mav_mvfx_table[] =
747 {
748 {"mvfx0", 0, TRUE}, {"mvfx1", 1, TRUE}, {"mvfx2", 2, TRUE}, {"mvfx3", 3, TRUE},
749 {"mvfx4", 4, TRUE}, {"mvfx5", 5, TRUE}, {"mvfx6", 6, TRUE}, {"mvfx7", 7, TRUE},
750 {"mvfx8", 8, TRUE}, {"mvfx9", 9, TRUE}, {"mvfx10", 10, TRUE}, {"mvfx11", 11, TRUE},
751 {"mvfx12", 12, TRUE}, {"mvfx13", 13, TRUE}, {"mvfx14", 14, TRUE}, {"mvfx15", 15, TRUE},
752 {NULL, 0, TRUE}
753 };
754
755 static const struct reg_entry mav_mvdx_table[] =
756 {
757 {"mvdx0", 0, TRUE}, {"mvdx1", 1, TRUE}, {"mvdx2", 2, TRUE}, {"mvdx3", 3, TRUE},
758 {"mvdx4", 4, TRUE}, {"mvdx5", 5, TRUE}, {"mvdx6", 6, TRUE}, {"mvdx7", 7, TRUE},
759 {"mvdx8", 8, TRUE}, {"mvdx9", 9, TRUE}, {"mvdx10", 10, TRUE}, {"mvdx11", 11, TRUE},
760 {"mvdx12", 12, TRUE}, {"mvdx13", 13, TRUE}, {"mvdx14", 14, TRUE}, {"mvdx15", 15, TRUE},
761 {NULL, 0, TRUE}
762 };
763
764 static const struct reg_entry mav_mvax_table[] =
765 {
766 {"mvax0", 0, TRUE}, {"mvax1", 1, TRUE}, {"mvax2", 2, TRUE}, {"mvax3", 3, TRUE},
767 {NULL, 0, TRUE}
768 };
769
770 static const struct reg_entry mav_dspsc_table[] =
771 {
772 {"dspsc", 0, TRUE},
773 {NULL, 0, TRUE}
774 };
775
776 struct reg_map
777 {
778 const struct reg_entry *names;
779 int max_regno;
780 struct hash_control *htab;
781 const char *expected;
782 };
783
784 struct reg_map all_reg_maps[] =
785 {
786 {rn_table, 15, NULL, N_("ARM register expected")},
787 {cp_table, 15, NULL, N_("bad or missing co-processor number")},
788 {cn_table, 15, NULL, N_("co-processor register expected")},
789 {fn_table, 7, NULL, N_("FPA register expected")},
790 {sn_table, 31, NULL, N_("VFP single precision register expected")},
791 {dn_table, 15, NULL, N_("VFP double precision register expected")},
792 {mav_mvf_table, 15, NULL, N_("Maverick MVF register expected")},
793 {mav_mvd_table, 15, NULL, N_("Maverick MVD register expected")},
794 {mav_mvfx_table, 15, NULL, N_("Maverick MVFX register expected")},
795 {mav_mvdx_table, 15, NULL, N_("Maverick MVDX register expected")},
796 {mav_mvax_table, 3, NULL, N_("Maverick MVAX register expected")},
797 {mav_dspsc_table, 0, NULL, N_("Maverick DSPSC register expected")},
798 {iwmmxt_table, 23, NULL, N_("Intel Wireless MMX technology register expected")},
799 };
800
801 /* Enumeration matching entries in table above. */
802 enum arm_reg_type
803 {
804 REG_TYPE_RN = 0,
805 #define REG_TYPE_FIRST REG_TYPE_RN
806 REG_TYPE_CP = 1,
807 REG_TYPE_CN = 2,
808 REG_TYPE_FN = 3,
809 REG_TYPE_SN = 4,
810 REG_TYPE_DN = 5,
811 REG_TYPE_MVF = 6,
812 REG_TYPE_MVD = 7,
813 REG_TYPE_MVFX = 8,
814 REG_TYPE_MVDX = 9,
815 REG_TYPE_MVAX = 10,
816 REG_TYPE_DSPSC = 11,
817 REG_TYPE_IWMMXT = 12,
818
819 REG_TYPE_MAX = 13
820 };
821
822 /* Functions called by parser. */
823 /* ARM instructions. */
824 static void do_arit PARAMS ((char *));
825 static void do_cmp PARAMS ((char *));
826 static void do_mov PARAMS ((char *));
827 static void do_ldst PARAMS ((char *));
828 static void do_ldstt PARAMS ((char *));
829 static void do_ldmstm PARAMS ((char *));
830 static void do_branch PARAMS ((char *));
831 static void do_swi PARAMS ((char *));
832
833 /* Pseudo Op codes. */
834 static void do_adr PARAMS ((char *));
835 static void do_adrl PARAMS ((char *));
836 static void do_empty PARAMS ((char *));
837
838 /* ARM v2. */
839 static void do_mul PARAMS ((char *));
840 static void do_mla PARAMS ((char *));
841
842 /* ARM v2S. */
843 static void do_swap PARAMS ((char *));
844
845 /* ARM v3. */
846 static void do_msr PARAMS ((char *));
847 static void do_mrs PARAMS ((char *));
848
849 /* ARM v3M. */
850 static void do_mull PARAMS ((char *));
851
852 /* ARM v4. */
853 static void do_ldstv4 PARAMS ((char *));
854
855 /* ARM v4T. */
856 static void do_bx PARAMS ((char *));
857
858 /* ARM v5T. */
859 static void do_blx PARAMS ((char *));
860 static void do_bkpt PARAMS ((char *));
861 static void do_clz PARAMS ((char *));
862 static void do_lstc2 PARAMS ((char *));
863 static void do_cdp2 PARAMS ((char *));
864 static void do_co_reg2 PARAMS ((char *));
865
866 /* ARM v5TExP. */
867 static void do_smla PARAMS ((char *));
868 static void do_smlal PARAMS ((char *));
869 static void do_smul PARAMS ((char *));
870 static void do_qadd PARAMS ((char *));
871
872 /* ARM v5TE. */
873 static void do_pld PARAMS ((char *));
874 static void do_ldrd PARAMS ((char *));
875 static void do_co_reg2c PARAMS ((char *));
876
877 /* ARM v5TEJ. */
878 static void do_bxj PARAMS ((char *));
879
880 /* ARM V6. */
881 static void do_cps PARAMS ((char *));
882 static void do_cpsi PARAMS ((char *));
883 static void do_ldrex PARAMS ((char *));
884 static void do_pkhbt PARAMS ((char *));
885 static void do_pkhtb PARAMS ((char *));
886 static void do_qadd16 PARAMS ((char *));
887 static void do_rev PARAMS ((char *));
888 static void do_rfe PARAMS ((char *));
889 static void do_sxtah PARAMS ((char *));
890 static void do_sxth PARAMS ((char *));
891 static void do_setend PARAMS ((char *));
892 static void do_smlad PARAMS ((char *));
893 static void do_smlald PARAMS ((char *));
894 static void do_smmul PARAMS ((char *));
895 static void do_ssat PARAMS ((char *));
896 static void do_usat PARAMS ((char *));
897 static void do_srs PARAMS ((char *));
898 static void do_ssat16 PARAMS ((char *));
899 static void do_usat16 PARAMS ((char *));
900 static void do_strex PARAMS ((char *));
901 static void do_umaal PARAMS ((char *));
902
903 static void do_cps_mode PARAMS ((char **));
904 static void do_cps_flags PARAMS ((char **, int));
905 static int do_endian_specifier PARAMS ((char *));
906 static void do_pkh_core PARAMS ((char *, int));
907 static void do_sat PARAMS ((char **, int));
908 static void do_sat16 PARAMS ((char **, int));
909
910 /* Coprocessor Instructions. */
911 static void do_cdp PARAMS ((char *));
912 static void do_lstc PARAMS ((char *));
913 static void do_co_reg PARAMS ((char *));
914
915 /* FPA instructions. */
916 static void do_fpa_ctrl PARAMS ((char *));
917 static void do_fpa_ldst PARAMS ((char *));
918 static void do_fpa_ldmstm PARAMS ((char *));
919 static void do_fpa_dyadic PARAMS ((char *));
920 static void do_fpa_monadic PARAMS ((char *));
921 static void do_fpa_cmp PARAMS ((char *));
922 static void do_fpa_from_reg PARAMS ((char *));
923 static void do_fpa_to_reg PARAMS ((char *));
924
925 /* VFP instructions. */
926 static void do_vfp_sp_monadic PARAMS ((char *));
927 static void do_vfp_dp_monadic PARAMS ((char *));
928 static void do_vfp_sp_dyadic PARAMS ((char *));
929 static void do_vfp_dp_dyadic PARAMS ((char *));
930 static void do_vfp_reg_from_sp PARAMS ((char *));
931 static void do_vfp_sp_from_reg PARAMS ((char *));
932 static void do_vfp_sp_reg2 PARAMS ((char *));
933 static void do_vfp_reg_from_dp PARAMS ((char *));
934 static void do_vfp_reg2_from_dp PARAMS ((char *));
935 static void do_vfp_dp_from_reg PARAMS ((char *));
936 static void do_vfp_dp_from_reg2 PARAMS ((char *));
937 static void do_vfp_reg_from_ctrl PARAMS ((char *));
938 static void do_vfp_ctrl_from_reg PARAMS ((char *));
939 static void do_vfp_sp_ldst PARAMS ((char *));
940 static void do_vfp_dp_ldst PARAMS ((char *));
941 static void do_vfp_sp_ldstmia PARAMS ((char *));
942 static void do_vfp_sp_ldstmdb PARAMS ((char *));
943 static void do_vfp_dp_ldstmia PARAMS ((char *));
944 static void do_vfp_dp_ldstmdb PARAMS ((char *));
945 static void do_vfp_xp_ldstmia PARAMS ((char *));
946 static void do_vfp_xp_ldstmdb PARAMS ((char *));
947 static void do_vfp_sp_compare_z PARAMS ((char *));
948 static void do_vfp_dp_compare_z PARAMS ((char *));
949 static void do_vfp_dp_sp_cvt PARAMS ((char *));
950 static void do_vfp_sp_dp_cvt PARAMS ((char *));
951
952 /* XScale. */
953 static void do_xsc_mia PARAMS ((char *));
954 static void do_xsc_mar PARAMS ((char *));
955 static void do_xsc_mra PARAMS ((char *));
956
957 /* Maverick. */
958 static void do_mav_binops PARAMS ((char *, int, enum arm_reg_type,
959 enum arm_reg_type));
960 static void do_mav_binops_1a PARAMS ((char *));
961 static void do_mav_binops_1b PARAMS ((char *));
962 static void do_mav_binops_1c PARAMS ((char *));
963 static void do_mav_binops_1d PARAMS ((char *));
964 static void do_mav_binops_1e PARAMS ((char *));
965 static void do_mav_binops_1f PARAMS ((char *));
966 static void do_mav_binops_1g PARAMS ((char *));
967 static void do_mav_binops_1h PARAMS ((char *));
968 static void do_mav_binops_1i PARAMS ((char *));
969 static void do_mav_binops_1j PARAMS ((char *));
970 static void do_mav_binops_1k PARAMS ((char *));
971 static void do_mav_binops_1l PARAMS ((char *));
972 static void do_mav_binops_1m PARAMS ((char *));
973 static void do_mav_binops_1n PARAMS ((char *));
974 static void do_mav_binops_1o PARAMS ((char *));
975 static void do_mav_binops_2a PARAMS ((char *));
976 static void do_mav_binops_2b PARAMS ((char *));
977 static void do_mav_binops_2c PARAMS ((char *));
978 static void do_mav_binops_3a PARAMS ((char *));
979 static void do_mav_binops_3b PARAMS ((char *));
980 static void do_mav_binops_3c PARAMS ((char *));
981 static void do_mav_binops_3d PARAMS ((char *));
982 static void do_mav_triple PARAMS ((char *, int, enum arm_reg_type,
983 enum arm_reg_type,
984 enum arm_reg_type));
985 static void do_mav_triple_4a PARAMS ((char *));
986 static void do_mav_triple_4b PARAMS ((char *));
987 static void do_mav_triple_5a PARAMS ((char *));
988 static void do_mav_triple_5b PARAMS ((char *));
989 static void do_mav_triple_5c PARAMS ((char *));
990 static void do_mav_triple_5d PARAMS ((char *));
991 static void do_mav_triple_5e PARAMS ((char *));
992 static void do_mav_triple_5f PARAMS ((char *));
993 static void do_mav_triple_5g PARAMS ((char *));
994 static void do_mav_triple_5h PARAMS ((char *));
995 static void do_mav_quad PARAMS ((char *, int, enum arm_reg_type,
996 enum arm_reg_type,
997 enum arm_reg_type,
998 enum arm_reg_type));
999 static void do_mav_quad_6a PARAMS ((char *));
1000 static void do_mav_quad_6b PARAMS ((char *));
1001 static void do_mav_dspsc_1 PARAMS ((char *));
1002 static void do_mav_dspsc_2 PARAMS ((char *));
1003 static void do_mav_shift PARAMS ((char *, enum arm_reg_type,
1004 enum arm_reg_type));
1005 static void do_mav_shift_1 PARAMS ((char *));
1006 static void do_mav_shift_2 PARAMS ((char *));
1007 static void do_mav_ldst PARAMS ((char *, enum arm_reg_type));
1008 static void do_mav_ldst_1 PARAMS ((char *));
1009 static void do_mav_ldst_2 PARAMS ((char *));
1010 static void do_mav_ldst_3 PARAMS ((char *));
1011 static void do_mav_ldst_4 PARAMS ((char *));
1012
1013 static int mav_reg_required_here PARAMS ((char **, int,
1014 enum arm_reg_type));
1015 static int mav_parse_offset PARAMS ((char **, int *));
1016
1017 static void fix_new_arm PARAMS ((fragS *, int, short, expressionS *,
1018 int, int));
1019 static int arm_reg_parse PARAMS ((char **, struct hash_control *));
1020 static enum arm_reg_type arm_reg_parse_any PARAMS ((char *));
1021 static const struct asm_psr * arm_psr_parse PARAMS ((char **));
1022 static void symbol_locate PARAMS ((symbolS *, const char *, segT, valueT,
1023 fragS *));
1024 static int add_to_lit_pool PARAMS ((void));
1025 static unsigned validate_immediate PARAMS ((unsigned));
1026 static unsigned validate_immediate_twopart PARAMS ((unsigned int,
1027 unsigned int *));
1028 static int validate_offset_imm PARAMS ((unsigned int, int));
1029 static void opcode_select PARAMS ((int));
1030 static void end_of_line PARAMS ((char *));
1031 static int reg_required_here PARAMS ((char **, int));
1032 static int psr_required_here PARAMS ((char **));
1033 static int co_proc_number PARAMS ((char **));
1034 static int cp_opc_expr PARAMS ((char **, int, int));
1035 static int cp_reg_required_here PARAMS ((char **, int));
1036 static int fp_reg_required_here PARAMS ((char **, int));
1037 static int vfp_sp_reg_required_here PARAMS ((char **, enum vfp_sp_reg_pos));
1038 static int vfp_dp_reg_required_here PARAMS ((char **, enum vfp_dp_reg_pos));
1039 static void vfp_sp_ldstm PARAMS ((char *, enum vfp_ldstm_type));
1040 static void vfp_dp_ldstm PARAMS ((char *, enum vfp_ldstm_type));
1041 static long vfp_sp_reg_list PARAMS ((char **, enum vfp_sp_reg_pos));
1042 static long vfp_dp_reg_list PARAMS ((char **));
1043 static int vfp_psr_required_here PARAMS ((char **str));
1044 static const struct vfp_reg *vfp_psr_parse PARAMS ((char **str));
1045 static int cp_address_offset PARAMS ((char **));
1046 static int cp_address_required_here PARAMS ((char **, int));
1047 static int my_get_float_expression PARAMS ((char **));
1048 static int skip_past_comma PARAMS ((char **));
1049 static int walk_no_bignums PARAMS ((symbolS *));
1050 static int negate_data_op PARAMS ((unsigned long *, unsigned long));
1051 static int data_op2 PARAMS ((char **));
1052 static int fp_op2 PARAMS ((char **));
1053 static long reg_list PARAMS ((char **));
1054 static void thumb_load_store PARAMS ((char *, int, int));
1055 static int decode_shift PARAMS ((char **, int));
1056 static int ldst_extend PARAMS ((char **));
1057 static int ldst_extend_v4 PARAMS ((char **));
1058 static void thumb_add_sub PARAMS ((char *, int));
1059 static void insert_reg PARAMS ((const struct reg_entry *,
1060 struct hash_control *));
1061 static void thumb_shift PARAMS ((char *, int));
1062 static void thumb_mov_compare PARAMS ((char *, int));
1063 static void build_arm_ops_hsh PARAMS ((void));
1064 static void set_constant_flonums PARAMS ((void));
1065 static valueT md_chars_to_number PARAMS ((char *, int));
1066 static void build_reg_hsh PARAMS ((struct reg_map *));
1067 static void insert_reg_alias PARAMS ((char *, int, struct hash_control *));
1068 static int create_register_alias PARAMS ((char *, char *));
1069 static void output_inst PARAMS ((const char *));
1070 static int accum0_required_here PARAMS ((char **));
1071 static int ld_mode_required_here PARAMS ((char **));
1072 static void do_branch25 PARAMS ((char *));
1073 static symbolS * find_real_start PARAMS ((symbolS *));
1074 #ifdef OBJ_ELF
1075 static bfd_reloc_code_real_type arm_parse_reloc PARAMS ((void));
1076 #endif
1077
1078 static int wreg_required_here PARAMS ((char **, int, enum wreg_type));
1079 static void do_iwmmxt_byte_addr PARAMS ((char *));
1080 static void do_iwmmxt_tandc PARAMS ((char *));
1081 static void do_iwmmxt_tbcst PARAMS ((char *));
1082 static void do_iwmmxt_textrc PARAMS ((char *));
1083 static void do_iwmmxt_textrm PARAMS ((char *));
1084 static void do_iwmmxt_tinsr PARAMS ((char *));
1085 static void do_iwmmxt_tmcr PARAMS ((char *));
1086 static void do_iwmmxt_tmcrr PARAMS ((char *));
1087 static void do_iwmmxt_tmia PARAMS ((char *));
1088 static void do_iwmmxt_tmovmsk PARAMS ((char *));
1089 static void do_iwmmxt_tmrc PARAMS ((char *));
1090 static void do_iwmmxt_tmrrc PARAMS ((char *));
1091 static void do_iwmmxt_torc PARAMS ((char *));
1092 static void do_iwmmxt_waligni PARAMS ((char *));
1093 static void do_iwmmxt_wmov PARAMS ((char *));
1094 static void do_iwmmxt_word_addr PARAMS ((char *));
1095 static void do_iwmmxt_wrwr PARAMS ((char *));
1096 static void do_iwmmxt_wrwrwcg PARAMS ((char *));
1097 static void do_iwmmxt_wrwrwr PARAMS ((char *));
1098 static void do_iwmmxt_wshufh PARAMS ((char *));
1099 static void do_iwmmxt_wzero PARAMS ((char *));
1100 static int cp_byte_address_offset PARAMS ((char **));
1101 static int cp_byte_address_required_here PARAMS ((char **));
1102
1103 /* ARM instructions take 4bytes in the object file, Thumb instructions
1104 take 2: */
1105 #define INSN_SIZE 4
1106
1107 /* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
1108 #define MAV_MODE1 0x100c
1109
1110 /* "INSN<cond> X,Y" where X:bit16, Y:bit12. */
1111 #define MAV_MODE2 0x0c10
1112
1113 /* "INSN<cond> X,Y" where X:0, Y:bit16. */
1114 #define MAV_MODE3 0x1000
1115
1116 /* "INSN<cond> X,Y,Z" where X:16, Y:0, Z:12. */
1117 #define MAV_MODE4 0x0c0010
1118
1119 /* "INSN<cond> X,Y,Z" where X:12, Y:16, Z:0. */
1120 #define MAV_MODE5 0x00100c
1121
1122 /* "INSN<cond> W,X,Y,Z" where W:5, X:12, Y:16, Z:0. */
1123 #define MAV_MODE6 0x00100c05
1124
1125 struct asm_opcode
1126 {
1127 /* Basic string to match. */
1128 const char * template;
1129
1130 /* Basic instruction code. */
1131 unsigned long value;
1132
1133 /* Offset into the template where the condition code (if any) will be.
1134 If zero, then the instruction is never conditional. */
1135 unsigned cond_offset;
1136
1137 /* Which architecture variant provides this instruction. */
1138 unsigned long variant;
1139
1140 /* Function to call to parse args. */
1141 void (* parms) PARAMS ((char *));
1142 };
1143
1144 static const struct asm_opcode insns[] =
1145 {
1146 /* Core ARM Instructions. */
1147 {"and", 0xe0000000, 3, ARM_EXT_V1, do_arit},
1148 {"ands", 0xe0100000, 3, ARM_EXT_V1, do_arit},
1149 {"eor", 0xe0200000, 3, ARM_EXT_V1, do_arit},
1150 {"eors", 0xe0300000, 3, ARM_EXT_V1, do_arit},
1151 {"sub", 0xe0400000, 3, ARM_EXT_V1, do_arit},
1152 {"subs", 0xe0500000, 3, ARM_EXT_V1, do_arit},
1153 {"rsb", 0xe0600000, 3, ARM_EXT_V1, do_arit},
1154 {"rsbs", 0xe0700000, 3, ARM_EXT_V1, do_arit},
1155 {"add", 0xe0800000, 3, ARM_EXT_V1, do_arit},
1156 {"adds", 0xe0900000, 3, ARM_EXT_V1, do_arit},
1157 {"adc", 0xe0a00000, 3, ARM_EXT_V1, do_arit},
1158 {"adcs", 0xe0b00000, 3, ARM_EXT_V1, do_arit},
1159 {"sbc", 0xe0c00000, 3, ARM_EXT_V1, do_arit},
1160 {"sbcs", 0xe0d00000, 3, ARM_EXT_V1, do_arit},
1161 {"rsc", 0xe0e00000, 3, ARM_EXT_V1, do_arit},
1162 {"rscs", 0xe0f00000, 3, ARM_EXT_V1, do_arit},
1163 {"orr", 0xe1800000, 3, ARM_EXT_V1, do_arit},
1164 {"orrs", 0xe1900000, 3, ARM_EXT_V1, do_arit},
1165 {"bic", 0xe1c00000, 3, ARM_EXT_V1, do_arit},
1166 {"bics", 0xe1d00000, 3, ARM_EXT_V1, do_arit},
1167
1168 {"tst", 0xe1100000, 3, ARM_EXT_V1, do_cmp},
1169 {"tsts", 0xe1100000, 3, ARM_EXT_V1, do_cmp},
1170 {"tstp", 0xe110f000, 3, ARM_EXT_V1, do_cmp},
1171 {"teq", 0xe1300000, 3, ARM_EXT_V1, do_cmp},
1172 {"teqs", 0xe1300000, 3, ARM_EXT_V1, do_cmp},
1173 {"teqp", 0xe130f000, 3, ARM_EXT_V1, do_cmp},
1174 {"cmp", 0xe1500000, 3, ARM_EXT_V1, do_cmp},
1175 {"cmps", 0xe1500000, 3, ARM_EXT_V1, do_cmp},
1176 {"cmpp", 0xe150f000, 3, ARM_EXT_V1, do_cmp},
1177 {"cmn", 0xe1700000, 3, ARM_EXT_V1, do_cmp},
1178 {"cmns", 0xe1700000, 3, ARM_EXT_V1, do_cmp},
1179 {"cmnp", 0xe170f000, 3, ARM_EXT_V1, do_cmp},
1180
1181 {"mov", 0xe1a00000, 3, ARM_EXT_V1, do_mov},
1182 {"movs", 0xe1b00000, 3, ARM_EXT_V1, do_mov},
1183 {"mvn", 0xe1e00000, 3, ARM_EXT_V1, do_mov},
1184 {"mvns", 0xe1f00000, 3, ARM_EXT_V1, do_mov},
1185
1186 {"ldr", 0xe4100000, 3, ARM_EXT_V1, do_ldst},
1187 {"ldrb", 0xe4500000, 3, ARM_EXT_V1, do_ldst},
1188 {"ldrt", 0xe4300000, 3, ARM_EXT_V1, do_ldstt},
1189 {"ldrbt", 0xe4700000, 3, ARM_EXT_V1, do_ldstt},
1190 {"str", 0xe4000000, 3, ARM_EXT_V1, do_ldst},
1191 {"strb", 0xe4400000, 3, ARM_EXT_V1, do_ldst},
1192 {"strt", 0xe4200000, 3, ARM_EXT_V1, do_ldstt},
1193 {"strbt", 0xe4600000, 3, ARM_EXT_V1, do_ldstt},
1194
1195 {"stmia", 0xe8800000, 3, ARM_EXT_V1, do_ldmstm},
1196 {"stmib", 0xe9800000, 3, ARM_EXT_V1, do_ldmstm},
1197 {"stmda", 0xe8000000, 3, ARM_EXT_V1, do_ldmstm},
1198 {"stmdb", 0xe9000000, 3, ARM_EXT_V1, do_ldmstm},
1199 {"stmfd", 0xe9000000, 3, ARM_EXT_V1, do_ldmstm},
1200 {"stmfa", 0xe9800000, 3, ARM_EXT_V1, do_ldmstm},
1201 {"stmea", 0xe8800000, 3, ARM_EXT_V1, do_ldmstm},
1202 {"stmed", 0xe8000000, 3, ARM_EXT_V1, do_ldmstm},
1203
1204 {"ldmia", 0xe8900000, 3, ARM_EXT_V1, do_ldmstm},
1205 {"ldmib", 0xe9900000, 3, ARM_EXT_V1, do_ldmstm},
1206 {"ldmda", 0xe8100000, 3, ARM_EXT_V1, do_ldmstm},
1207 {"ldmdb", 0xe9100000, 3, ARM_EXT_V1, do_ldmstm},
1208 {"ldmfd", 0xe8900000, 3, ARM_EXT_V1, do_ldmstm},
1209 {"ldmfa", 0xe8100000, 3, ARM_EXT_V1, do_ldmstm},
1210 {"ldmea", 0xe9100000, 3, ARM_EXT_V1, do_ldmstm},
1211 {"ldmed", 0xe9900000, 3, ARM_EXT_V1, do_ldmstm},
1212
1213 {"swi", 0xef000000, 3, ARM_EXT_V1, do_swi},
1214 #ifdef TE_WINCE
1215 /* XXX This is the wrong place to do this. Think multi-arch. */
1216 {"bl", 0xeb000000, 2, ARM_EXT_V1, do_branch},
1217 {"b", 0xea000000, 1, ARM_EXT_V1, do_branch},
1218 #else
1219 {"bl", 0xebfffffe, 2, ARM_EXT_V1, do_branch},
1220 {"b", 0xeafffffe, 1, ARM_EXT_V1, do_branch},
1221 #endif
1222
1223 /* Pseudo ops. */
1224 {"adr", 0xe28f0000, 3, ARM_EXT_V1, do_adr},
1225 {"adrl", 0xe28f0000, 3, ARM_EXT_V1, do_adrl},
1226 {"nop", 0xe1a00000, 3, ARM_EXT_V1, do_empty},
1227
1228 /* ARM 2 multiplies. */
1229 {"mul", 0xe0000090, 3, ARM_EXT_V2, do_mul},
1230 {"muls", 0xe0100090, 3, ARM_EXT_V2, do_mul},
1231 {"mla", 0xe0200090, 3, ARM_EXT_V2, do_mla},
1232 {"mlas", 0xe0300090, 3, ARM_EXT_V2, do_mla},
1233
1234 /* Generic coprocessor instructions. */
1235 {"cdp", 0xee000000, 3, ARM_EXT_V2, do_cdp},
1236 {"ldc", 0xec100000, 3, ARM_EXT_V2, do_lstc},
1237 {"ldcl", 0xec500000, 3, ARM_EXT_V2, do_lstc},
1238 {"stc", 0xec000000, 3, ARM_EXT_V2, do_lstc},
1239 {"stcl", 0xec400000, 3, ARM_EXT_V2, do_lstc},
1240 {"mcr", 0xee000010, 3, ARM_EXT_V2, do_co_reg},
1241 {"mrc", 0xee100010, 3, ARM_EXT_V2, do_co_reg},
1242
1243 /* ARM 3 - swp instructions. */
1244 {"swp", 0xe1000090, 3, ARM_EXT_V2S, do_swap},
1245 {"swpb", 0xe1400090, 3, ARM_EXT_V2S, do_swap},
1246
1247 /* ARM 6 Status register instructions. */
1248 {"mrs", 0xe10f0000, 3, ARM_EXT_V3, do_mrs},
1249 {"msr", 0xe120f000, 3, ARM_EXT_V3, do_msr},
1250 /* ScottB: our code uses 0xe128f000 for msr.
1251 NickC: but this is wrong because the bits 16 through 19 are
1252 handled by the PSR_xxx defines above. */
1253
1254 /* ARM 7M long multiplies. */
1255 {"smull", 0xe0c00090, 5, ARM_EXT_V3M, do_mull},
1256 {"smulls", 0xe0d00090, 5, ARM_EXT_V3M, do_mull},
1257 {"umull", 0xe0800090, 5, ARM_EXT_V3M, do_mull},
1258 {"umulls", 0xe0900090, 5, ARM_EXT_V3M, do_mull},
1259 {"smlal", 0xe0e00090, 5, ARM_EXT_V3M, do_mull},
1260 {"smlals", 0xe0f00090, 5, ARM_EXT_V3M, do_mull},
1261 {"umlal", 0xe0a00090, 5, ARM_EXT_V3M, do_mull},
1262 {"umlals", 0xe0b00090, 5, ARM_EXT_V3M, do_mull},
1263
1264 /* ARM Architecture 4. */
1265 {"ldrh", 0xe01000b0, 3, ARM_EXT_V4, do_ldstv4},
1266 {"ldrsh", 0xe01000f0, 3, ARM_EXT_V4, do_ldstv4},
1267 {"ldrsb", 0xe01000d0, 3, ARM_EXT_V4, do_ldstv4},
1268 {"strh", 0xe00000b0, 3, ARM_EXT_V4, do_ldstv4},
1269
1270 /* ARM Architecture 4T. */
1271 /* Note: bx (and blx) are required on V5, even if the processor does
1272 not support Thumb. */
1273 {"bx", 0xe12fff10, 2, ARM_EXT_V4T | ARM_EXT_V5, do_bx},
1274
1275 /* ARM Architecture 5T. */
1276 /* Note: blx has 2 variants, so the .value is set dynamically.
1277 Only one of the variants has conditional execution. */
1278 {"blx", 0xe0000000, 3, ARM_EXT_V5, do_blx},
1279 {"clz", 0xe16f0f10, 3, ARM_EXT_V5, do_clz},
1280 {"bkpt", 0xe1200070, 0, ARM_EXT_V5, do_bkpt},
1281 {"ldc2", 0xfc100000, 0, ARM_EXT_V5, do_lstc2},
1282 {"ldc2l", 0xfc500000, 0, ARM_EXT_V5, do_lstc2},
1283 {"stc2", 0xfc000000, 0, ARM_EXT_V5, do_lstc2},
1284 {"stc2l", 0xfc400000, 0, ARM_EXT_V5, do_lstc2},
1285 {"cdp2", 0xfe000000, 0, ARM_EXT_V5, do_cdp2},
1286 {"mcr2", 0xfe000010, 0, ARM_EXT_V5, do_co_reg2},
1287 {"mrc2", 0xfe100010, 0, ARM_EXT_V5, do_co_reg2},
1288
1289 /* ARM Architecture 5TExP. */
1290 {"smlabb", 0xe1000080, 6, ARM_EXT_V5ExP, do_smla},
1291 {"smlatb", 0xe10000a0, 6, ARM_EXT_V5ExP, do_smla},
1292 {"smlabt", 0xe10000c0, 6, ARM_EXT_V5ExP, do_smla},
1293 {"smlatt", 0xe10000e0, 6, ARM_EXT_V5ExP, do_smla},
1294
1295 {"smlawb", 0xe1200080, 6, ARM_EXT_V5ExP, do_smla},
1296 {"smlawt", 0xe12000c0, 6, ARM_EXT_V5ExP, do_smla},
1297
1298 {"smlalbb", 0xe1400080, 7, ARM_EXT_V5ExP, do_smlal},
1299 {"smlaltb", 0xe14000a0, 7, ARM_EXT_V5ExP, do_smlal},
1300 {"smlalbt", 0xe14000c0, 7, ARM_EXT_V5ExP, do_smlal},
1301 {"smlaltt", 0xe14000e0, 7, ARM_EXT_V5ExP, do_smlal},
1302
1303 {"smulbb", 0xe1600080, 6, ARM_EXT_V5ExP, do_smul},
1304 {"smultb", 0xe16000a0, 6, ARM_EXT_V5ExP, do_smul},
1305 {"smulbt", 0xe16000c0, 6, ARM_EXT_V5ExP, do_smul},
1306 {"smultt", 0xe16000e0, 6, ARM_EXT_V5ExP, do_smul},
1307
1308 {"smulwb", 0xe12000a0, 6, ARM_EXT_V5ExP, do_smul},
1309 {"smulwt", 0xe12000e0, 6, ARM_EXT_V5ExP, do_smul},
1310
1311 {"qadd", 0xe1000050, 4, ARM_EXT_V5ExP, do_qadd},
1312 {"qdadd", 0xe1400050, 5, ARM_EXT_V5ExP, do_qadd},
1313 {"qsub", 0xe1200050, 4, ARM_EXT_V5ExP, do_qadd},
1314 {"qdsub", 0xe1600050, 5, ARM_EXT_V5ExP, do_qadd},
1315
1316 /* ARM Architecture 5TE. */
1317 {"pld", 0xf450f000, 0, ARM_EXT_V5E, do_pld},
1318 {"ldrd", 0xe00000d0, 3, ARM_EXT_V5E, do_ldrd},
1319 {"strd", 0xe00000f0, 3, ARM_EXT_V5E, do_ldrd},
1320
1321 {"mcrr", 0xec400000, 4, ARM_EXT_V5E, do_co_reg2c},
1322 {"mrrc", 0xec500000, 4, ARM_EXT_V5E, do_co_reg2c},
1323
1324 /* ARM Architecture 5TEJ. */
1325 {"bxj", 0xe12fff20, 3, ARM_EXT_V5J, do_bxj},
1326
1327 /* ARM V6. */
1328 { "cps", 0xf1020000, 0, ARM_EXT_V6, do_cps},
1329 { "cpsie", 0xf1080000, 0, ARM_EXT_V6, do_cpsi},
1330 { "cpsid", 0xf10C0000, 0, ARM_EXT_V6, do_cpsi},
1331 { "ldrex", 0xe1900f9f, 5, ARM_EXT_V6, do_ldrex},
1332 { "mcrr2", 0xfc400000, 0, ARM_EXT_V6, do_co_reg2c},
1333 { "mrrc2", 0xfc500000, 0, ARM_EXT_V6, do_co_reg2c},
1334 { "pkhbt", 0xe6800010, 5, ARM_EXT_V6, do_pkhbt},
1335 { "pkhtb", 0xe6800050, 5, ARM_EXT_V6, do_pkhtb},
1336 { "qadd16", 0xe6200f10, 6, ARM_EXT_V6, do_qadd16},
1337 { "qadd8", 0xe6200f90, 5, ARM_EXT_V6, do_qadd16},
1338 { "qaddsubx", 0xe6200f30, 8, ARM_EXT_V6, do_qadd16},
1339 { "qsub16", 0xe6200f70, 6, ARM_EXT_V6, do_qadd16},
1340 { "qsub8", 0xe6200ff0, 5, ARM_EXT_V6, do_qadd16},
1341 { "qsubaddx", 0xe6200f50, 8, ARM_EXT_V6, do_qadd16},
1342 { "sadd16", 0xe6100f10, 6, ARM_EXT_V6, do_qadd16},
1343 { "sadd8", 0xe6100f90, 5, ARM_EXT_V6, do_qadd16},
1344 { "saddsubx", 0xe6100f30, 8, ARM_EXT_V6, do_qadd16},
1345 { "shadd16", 0xe6300f10, 7, ARM_EXT_V6, do_qadd16},
1346 { "shadd8", 0xe6300f90, 6, ARM_EXT_V6, do_qadd16},
1347 { "shaddsubx", 0xe6300f30, 9, ARM_EXT_V6, do_qadd16},
1348 { "shsub16", 0xe6300f70, 7, ARM_EXT_V6, do_qadd16},
1349 { "shsub8", 0xe6300ff0, 6, ARM_EXT_V6, do_qadd16},
1350 { "shsubaddx", 0xe6300f50, 9, ARM_EXT_V6, do_qadd16},
1351 { "ssub16", 0xe6100f70, 6, ARM_EXT_V6, do_qadd16},
1352 { "ssub8", 0xe6100ff0, 5, ARM_EXT_V6, do_qadd16},
1353 { "ssubaddx", 0xe6100f50, 8, ARM_EXT_V6, do_qadd16},
1354 { "uadd16", 0xe6500f10, 6, ARM_EXT_V6, do_qadd16},
1355 { "uadd8", 0xe6500f90, 5, ARM_EXT_V6, do_qadd16},
1356 { "uaddsubx", 0xe6500f30, 8, ARM_EXT_V6, do_qadd16},
1357 { "uhadd16", 0xe6700f10, 7, ARM_EXT_V6, do_qadd16},
1358 { "uhadd8", 0xe6700f90, 6, ARM_EXT_V6, do_qadd16},
1359 { "uhaddsubx", 0xe6700f30, 9, ARM_EXT_V6, do_qadd16},
1360 { "uhsub16", 0xe6700f70, 7, ARM_EXT_V6, do_qadd16},
1361 { "uhsub8", 0xe6700ff0, 6, ARM_EXT_V6, do_qadd16},
1362 { "uhsubaddx", 0xe6700f50, 9, ARM_EXT_V6, do_qadd16},
1363 { "uqadd16", 0xe6600f10, 7, ARM_EXT_V6, do_qadd16},
1364 { "uqadd8", 0xe6600f90, 6, ARM_EXT_V6, do_qadd16},
1365 { "uqaddsubx", 0xe6600f30, 9, ARM_EXT_V6, do_qadd16},
1366 { "uqsub16", 0xe6600f70, 7, ARM_EXT_V6, do_qadd16},
1367 { "uqsub8", 0xe6600ff0, 6, ARM_EXT_V6, do_qadd16},
1368 { "uqsubaddx", 0xe6600f50, 9, ARM_EXT_V6, do_qadd16},
1369 { "usub16", 0xe6500f70, 6, ARM_EXT_V6, do_qadd16},
1370 { "usub8", 0xe6500ff0, 5, ARM_EXT_V6, do_qadd16},
1371 { "usubaddx", 0xe6500f50, 8, ARM_EXT_V6, do_qadd16},
1372 { "rev", 0xe6bf0f30, 3, ARM_EXT_V6, do_rev},
1373 { "rev16", 0xe6bf0fb0, 5, ARM_EXT_V6, do_rev},
1374 { "revsh", 0xe6ff0fb0, 5, ARM_EXT_V6, do_rev},
1375 { "rfeia", 0xf8900a00, 0, ARM_EXT_V6, do_rfe},
1376 { "rfeib", 0xf9900a00, 0, ARM_EXT_V6, do_rfe},
1377 { "rfeda", 0xf8100a00, 0, ARM_EXT_V6, do_rfe},
1378 { "rfedb", 0xf9100a00, 0, ARM_EXT_V6, do_rfe},
1379 { "rfefd", 0xf8900a00, 0, ARM_EXT_V6, do_rfe},
1380 { "rfefa", 0xf9900a00, 0, ARM_EXT_V6, do_rfe},
1381 { "rfeea", 0xf8100a00, 0, ARM_EXT_V6, do_rfe},
1382 { "rfeed", 0xf9100a00, 0, ARM_EXT_V6, do_rfe},
1383 { "sxtah", 0xe6b00070, 5, ARM_EXT_V6, do_sxtah},
1384 { "sxtab16", 0xe6800070, 7, ARM_EXT_V6, do_sxtah},
1385 { "sxtab", 0xe6a00070, 5, ARM_EXT_V6, do_sxtah},
1386 { "sxth", 0xe6bf0070, 4, ARM_EXT_V6, do_sxth},
1387 { "sxtb16", 0xe68f0070, 6, ARM_EXT_V6, do_sxth},
1388 { "sxtb", 0xe6af0070, 4, ARM_EXT_V6, do_sxth},
1389 { "uxtah", 0xe6f00070, 5, ARM_EXT_V6, do_sxtah},
1390 { "uxtab16", 0xe6c00070, 7, ARM_EXT_V6, do_sxtah},
1391 { "uxtab", 0xe6e00070, 5, ARM_EXT_V6, do_sxtah},
1392 { "uxth", 0xe6ff0070, 4, ARM_EXT_V6, do_sxth},
1393 { "uxtb16", 0xe6cf0070, 6, ARM_EXT_V6, do_sxth},
1394 { "uxtb", 0xe6ef0070, 4, ARM_EXT_V6, do_sxth},
1395 { "sel", 0xe68000b0, 3, ARM_EXT_V6, do_qadd16},
1396 { "setend", 0xf1010000, 0, ARM_EXT_V6, do_setend},
1397 { "smlad", 0xe7000010, 5, ARM_EXT_V6, do_smlad},
1398 { "smladx", 0xe7000030, 6, ARM_EXT_V6, do_smlad},
1399 { "smlald", 0xe7400010, 6, ARM_EXT_V6, do_smlald},
1400 { "smlaldx", 0xe7400030, 7, ARM_EXT_V6, do_smlald},
1401 { "smlsd", 0xe7000050, 5, ARM_EXT_V6, do_smlad},
1402 { "smlsdx", 0xe7000070, 6, ARM_EXT_V6, do_smlad},
1403 { "smlsld", 0xe7400050, 6, ARM_EXT_V6, do_smlald},
1404 { "smlsldx", 0xe7400070, 7, ARM_EXT_V6, do_smlald},
1405 { "smmla", 0xe7500010, 5, ARM_EXT_V6, do_smlad},
1406 { "smmlar", 0xe7500030, 6, ARM_EXT_V6, do_smlad},
1407 { "smmls", 0xe75000d0, 5, ARM_EXT_V6, do_smlad},
1408 { "smmlsr", 0xe75000f0, 6, ARM_EXT_V6, do_smlad},
1409 { "smmul", 0xe750f010, 5, ARM_EXT_V6, do_smmul},
1410 { "smmulr", 0xe750f030, 6, ARM_EXT_V6, do_smmul},
1411 { "smuad", 0xe700f010, 5, ARM_EXT_V6, do_smmul},
1412 { "smuadx", 0xe700f030, 6, ARM_EXT_V6, do_smmul},
1413 { "smusd", 0xe700f050, 5, ARM_EXT_V6, do_smmul},
1414 { "smusdx", 0xe700f070, 6, ARM_EXT_V6, do_smmul},
1415 { "srsia", 0xf8cd0500, 0, ARM_EXT_V6, do_srs},
1416 { "srsib", 0xf9cd0500, 0, ARM_EXT_V6, do_srs},
1417 { "srsda", 0xf84d0500, 0, ARM_EXT_V6, do_srs},
1418 { "srsdb", 0xf94d0500, 0, ARM_EXT_V6, do_srs},
1419 { "ssat", 0xe6a00010, 4, ARM_EXT_V6, do_ssat},
1420 { "ssat16", 0xe6a00f30, 6, ARM_EXT_V6, do_ssat16},
1421 { "strex", 0xe1800f90, 5, ARM_EXT_V6, do_strex},
1422 { "umaal", 0xe0400090, 5, ARM_EXT_V6, do_umaal},
1423 { "usad8", 0xe780f010, 5, ARM_EXT_V6, do_smmul},
1424 { "usada8", 0xe7800010, 6, ARM_EXT_V6, do_smlad},
1425 { "usat", 0xe6e00010, 4, ARM_EXT_V6, do_usat},
1426 { "usat16", 0xe6e00f30, 6, ARM_EXT_V6, do_usat16},
1427
1428 /* Core FPA instruction set (V1). */
1429 {"wfs", 0xee200110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
1430 {"rfs", 0xee300110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
1431 {"wfc", 0xee400110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
1432 {"rfc", 0xee500110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
1433
1434 {"ldfs", 0xec100100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1435 {"ldfd", 0xec108100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1436 {"ldfe", 0xec500100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1437 {"ldfp", 0xec508100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1438
1439 {"stfs", 0xec000100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1440 {"stfd", 0xec008100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1441 {"stfe", 0xec400100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1442 {"stfp", 0xec408100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1443
1444 {"mvfs", 0xee008100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1445 {"mvfsp", 0xee008120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1446 {"mvfsm", 0xee008140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1447 {"mvfsz", 0xee008160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1448 {"mvfd", 0xee008180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1449 {"mvfdp", 0xee0081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1450 {"mvfdm", 0xee0081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1451 {"mvfdz", 0xee0081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1452 {"mvfe", 0xee088100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1453 {"mvfep", 0xee088120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1454 {"mvfem", 0xee088140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1455 {"mvfez", 0xee088160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1456
1457 {"mnfs", 0xee108100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1458 {"mnfsp", 0xee108120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1459 {"mnfsm", 0xee108140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1460 {"mnfsz", 0xee108160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1461 {"mnfd", 0xee108180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1462 {"mnfdp", 0xee1081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1463 {"mnfdm", 0xee1081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1464 {"mnfdz", 0xee1081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1465 {"mnfe", 0xee188100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1466 {"mnfep", 0xee188120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1467 {"mnfem", 0xee188140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1468 {"mnfez", 0xee188160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1469
1470 {"abss", 0xee208100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1471 {"abssp", 0xee208120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1472 {"abssm", 0xee208140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1473 {"abssz", 0xee208160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1474 {"absd", 0xee208180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1475 {"absdp", 0xee2081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1476 {"absdm", 0xee2081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1477 {"absdz", 0xee2081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1478 {"abse", 0xee288100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1479 {"absep", 0xee288120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1480 {"absem", 0xee288140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1481 {"absez", 0xee288160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1482
1483 {"rnds", 0xee308100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1484 {"rndsp", 0xee308120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1485 {"rndsm", 0xee308140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1486 {"rndsz", 0xee308160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1487 {"rndd", 0xee308180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1488 {"rnddp", 0xee3081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1489 {"rnddm", 0xee3081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1490 {"rnddz", 0xee3081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1491 {"rnde", 0xee388100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1492 {"rndep", 0xee388120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1493 {"rndem", 0xee388140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1494 {"rndez", 0xee388160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1495
1496 {"sqts", 0xee408100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1497 {"sqtsp", 0xee408120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1498 {"sqtsm", 0xee408140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1499 {"sqtsz", 0xee408160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1500 {"sqtd", 0xee408180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1501 {"sqtdp", 0xee4081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1502 {"sqtdm", 0xee4081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1503 {"sqtdz", 0xee4081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1504 {"sqte", 0xee488100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1505 {"sqtep", 0xee488120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1506 {"sqtem", 0xee488140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1507 {"sqtez", 0xee488160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1508
1509 {"logs", 0xee508100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1510 {"logsp", 0xee508120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1511 {"logsm", 0xee508140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1512 {"logsz", 0xee508160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1513 {"logd", 0xee508180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1514 {"logdp", 0xee5081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1515 {"logdm", 0xee5081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1516 {"logdz", 0xee5081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1517 {"loge", 0xee588100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1518 {"logep", 0xee588120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1519 {"logem", 0xee588140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1520 {"logez", 0xee588160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1521
1522 {"lgns", 0xee608100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1523 {"lgnsp", 0xee608120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1524 {"lgnsm", 0xee608140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1525 {"lgnsz", 0xee608160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1526 {"lgnd", 0xee608180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1527 {"lgndp", 0xee6081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1528 {"lgndm", 0xee6081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1529 {"lgndz", 0xee6081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1530 {"lgne", 0xee688100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1531 {"lgnep", 0xee688120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1532 {"lgnem", 0xee688140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1533 {"lgnez", 0xee688160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1534
1535 {"exps", 0xee708100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1536 {"expsp", 0xee708120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1537 {"expsm", 0xee708140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1538 {"expsz", 0xee708160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1539 {"expd", 0xee708180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1540 {"expdp", 0xee7081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1541 {"expdm", 0xee7081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1542 {"expdz", 0xee7081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1543 {"expe", 0xee788100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1544 {"expep", 0xee788120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1545 {"expem", 0xee788140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1546 {"expdz", 0xee788160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1547
1548 {"sins", 0xee808100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1549 {"sinsp", 0xee808120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1550 {"sinsm", 0xee808140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1551 {"sinsz", 0xee808160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1552 {"sind", 0xee808180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1553 {"sindp", 0xee8081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1554 {"sindm", 0xee8081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1555 {"sindz", 0xee8081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1556 {"sine", 0xee888100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1557 {"sinep", 0xee888120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1558 {"sinem", 0xee888140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1559 {"sinez", 0xee888160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1560
1561 {"coss", 0xee908100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1562 {"cossp", 0xee908120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1563 {"cossm", 0xee908140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1564 {"cossz", 0xee908160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1565 {"cosd", 0xee908180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1566 {"cosdp", 0xee9081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1567 {"cosdm", 0xee9081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1568 {"cosdz", 0xee9081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1569 {"cose", 0xee988100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1570 {"cosep", 0xee988120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1571 {"cosem", 0xee988140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1572 {"cosez", 0xee988160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1573
1574 {"tans", 0xeea08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1575 {"tansp", 0xeea08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1576 {"tansm", 0xeea08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1577 {"tansz", 0xeea08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1578 {"tand", 0xeea08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1579 {"tandp", 0xeea081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1580 {"tandm", 0xeea081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1581 {"tandz", 0xeea081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1582 {"tane", 0xeea88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1583 {"tanep", 0xeea88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1584 {"tanem", 0xeea88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1585 {"tanez", 0xeea88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1586
1587 {"asns", 0xeeb08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1588 {"asnsp", 0xeeb08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1589 {"asnsm", 0xeeb08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1590 {"asnsz", 0xeeb08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1591 {"asnd", 0xeeb08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1592 {"asndp", 0xeeb081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1593 {"asndm", 0xeeb081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1594 {"asndz", 0xeeb081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1595 {"asne", 0xeeb88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1596 {"asnep", 0xeeb88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1597 {"asnem", 0xeeb88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1598 {"asnez", 0xeeb88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1599
1600 {"acss", 0xeec08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1601 {"acssp", 0xeec08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1602 {"acssm", 0xeec08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1603 {"acssz", 0xeec08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1604 {"acsd", 0xeec08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1605 {"acsdp", 0xeec081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1606 {"acsdm", 0xeec081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1607 {"acsdz", 0xeec081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1608 {"acse", 0xeec88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1609 {"acsep", 0xeec88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1610 {"acsem", 0xeec88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1611 {"acsez", 0xeec88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1612
1613 {"atns", 0xeed08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1614 {"atnsp", 0xeed08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1615 {"atnsm", 0xeed08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1616 {"atnsz", 0xeed08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1617 {"atnd", 0xeed08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1618 {"atndp", 0xeed081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1619 {"atndm", 0xeed081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1620 {"atndz", 0xeed081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1621 {"atne", 0xeed88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1622 {"atnep", 0xeed88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1623 {"atnem", 0xeed88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1624 {"atnez", 0xeed88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1625
1626 {"urds", 0xeee08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1627 {"urdsp", 0xeee08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1628 {"urdsm", 0xeee08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1629 {"urdsz", 0xeee08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1630 {"urdd", 0xeee08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1631 {"urddp", 0xeee081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1632 {"urddm", 0xeee081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1633 {"urddz", 0xeee081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1634 {"urde", 0xeee88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1635 {"urdep", 0xeee88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1636 {"urdem", 0xeee88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1637 {"urdez", 0xeee88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1638
1639 {"nrms", 0xeef08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1640 {"nrmsp", 0xeef08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1641 {"nrmsm", 0xeef08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1642 {"nrmsz", 0xeef08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1643 {"nrmd", 0xeef08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1644 {"nrmdp", 0xeef081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1645 {"nrmdm", 0xeef081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1646 {"nrmdz", 0xeef081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1647 {"nrme", 0xeef88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1648 {"nrmep", 0xeef88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1649 {"nrmem", 0xeef88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1650 {"nrmez", 0xeef88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1651
1652 {"adfs", 0xee000100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1653 {"adfsp", 0xee000120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1654 {"adfsm", 0xee000140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1655 {"adfsz", 0xee000160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1656 {"adfd", 0xee000180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1657 {"adfdp", 0xee0001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1658 {"adfdm", 0xee0001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1659 {"adfdz", 0xee0001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1660 {"adfe", 0xee080100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1661 {"adfep", 0xee080120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1662 {"adfem", 0xee080140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1663 {"adfez", 0xee080160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1664
1665 {"sufs", 0xee200100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1666 {"sufsp", 0xee200120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1667 {"sufsm", 0xee200140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1668 {"sufsz", 0xee200160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1669 {"sufd", 0xee200180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1670 {"sufdp", 0xee2001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1671 {"sufdm", 0xee2001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1672 {"sufdz", 0xee2001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1673 {"sufe", 0xee280100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1674 {"sufep", 0xee280120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1675 {"sufem", 0xee280140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1676 {"sufez", 0xee280160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1677
1678 {"rsfs", 0xee300100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1679 {"rsfsp", 0xee300120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1680 {"rsfsm", 0xee300140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1681 {"rsfsz", 0xee300160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1682 {"rsfd", 0xee300180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1683 {"rsfdp", 0xee3001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1684 {"rsfdm", 0xee3001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1685 {"rsfdz", 0xee3001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1686 {"rsfe", 0xee380100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1687 {"rsfep", 0xee380120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1688 {"rsfem", 0xee380140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1689 {"rsfez", 0xee380160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1690
1691 {"mufs", 0xee100100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1692 {"mufsp", 0xee100120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1693 {"mufsm", 0xee100140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1694 {"mufsz", 0xee100160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1695 {"mufd", 0xee100180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1696 {"mufdp", 0xee1001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1697 {"mufdm", 0xee1001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1698 {"mufdz", 0xee1001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1699 {"mufe", 0xee180100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1700 {"mufep", 0xee180120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1701 {"mufem", 0xee180140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1702 {"mufez", 0xee180160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1703
1704 {"dvfs", 0xee400100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1705 {"dvfsp", 0xee400120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1706 {"dvfsm", 0xee400140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1707 {"dvfsz", 0xee400160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1708 {"dvfd", 0xee400180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1709 {"dvfdp", 0xee4001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1710 {"dvfdm", 0xee4001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1711 {"dvfdz", 0xee4001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1712 {"dvfe", 0xee480100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1713 {"dvfep", 0xee480120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1714 {"dvfem", 0xee480140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1715 {"dvfez", 0xee480160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1716
1717 {"rdfs", 0xee500100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1718 {"rdfsp", 0xee500120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1719 {"rdfsm", 0xee500140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1720 {"rdfsz", 0xee500160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1721 {"rdfd", 0xee500180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1722 {"rdfdp", 0xee5001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1723 {"rdfdm", 0xee5001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1724 {"rdfdz", 0xee5001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1725 {"rdfe", 0xee580100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1726 {"rdfep", 0xee580120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1727 {"rdfem", 0xee580140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1728 {"rdfez", 0xee580160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1729
1730 {"pows", 0xee600100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1731 {"powsp", 0xee600120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1732 {"powsm", 0xee600140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1733 {"powsz", 0xee600160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1734 {"powd", 0xee600180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1735 {"powdp", 0xee6001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1736 {"powdm", 0xee6001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1737 {"powdz", 0xee6001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1738 {"powe", 0xee680100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1739 {"powep", 0xee680120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1740 {"powem", 0xee680140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1741 {"powez", 0xee680160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1742
1743 {"rpws", 0xee700100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1744 {"rpwsp", 0xee700120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1745 {"rpwsm", 0xee700140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1746 {"rpwsz", 0xee700160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1747 {"rpwd", 0xee700180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1748 {"rpwdp", 0xee7001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1749 {"rpwdm", 0xee7001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1750 {"rpwdz", 0xee7001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1751 {"rpwe", 0xee780100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1752 {"rpwep", 0xee780120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1753 {"rpwem", 0xee780140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1754 {"rpwez", 0xee780160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1755
1756 {"rmfs", 0xee800100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1757 {"rmfsp", 0xee800120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1758 {"rmfsm", 0xee800140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1759 {"rmfsz", 0xee800160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1760 {"rmfd", 0xee800180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1761 {"rmfdp", 0xee8001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1762 {"rmfdm", 0xee8001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1763 {"rmfdz", 0xee8001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1764 {"rmfe", 0xee880100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1765 {"rmfep", 0xee880120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1766 {"rmfem", 0xee880140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1767 {"rmfez", 0xee880160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1768
1769 {"fmls", 0xee900100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1770 {"fmlsp", 0xee900120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1771 {"fmlsm", 0xee900140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1772 {"fmlsz", 0xee900160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1773 {"fmld", 0xee900180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1774 {"fmldp", 0xee9001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1775 {"fmldm", 0xee9001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1776 {"fmldz", 0xee9001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1777 {"fmle", 0xee980100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1778 {"fmlep", 0xee980120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1779 {"fmlem", 0xee980140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1780 {"fmlez", 0xee980160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1781
1782 {"fdvs", 0xeea00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1783 {"fdvsp", 0xeea00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1784 {"fdvsm", 0xeea00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1785 {"fdvsz", 0xeea00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1786 {"fdvd", 0xeea00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1787 {"fdvdp", 0xeea001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1788 {"fdvdm", 0xeea001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1789 {"fdvdz", 0xeea001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1790 {"fdve", 0xeea80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1791 {"fdvep", 0xeea80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1792 {"fdvem", 0xeea80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1793 {"fdvez", 0xeea80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1794
1795 {"frds", 0xeeb00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1796 {"frdsp", 0xeeb00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1797 {"frdsm", 0xeeb00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1798 {"frdsz", 0xeeb00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1799 {"frdd", 0xeeb00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1800 {"frddp", 0xeeb001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1801 {"frddm", 0xeeb001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1802 {"frddz", 0xeeb001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1803 {"frde", 0xeeb80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1804 {"frdep", 0xeeb80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1805 {"frdem", 0xeeb80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1806 {"frdez", 0xeeb80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1807
1808 {"pols", 0xeec00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1809 {"polsp", 0xeec00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1810 {"polsm", 0xeec00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1811 {"polsz", 0xeec00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1812 {"pold", 0xeec00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1813 {"poldp", 0xeec001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1814 {"poldm", 0xeec001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1815 {"poldz", 0xeec001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1816 {"pole", 0xeec80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1817 {"polep", 0xeec80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1818 {"polem", 0xeec80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1819 {"polez", 0xeec80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1820
1821 {"cmf", 0xee90f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
1822 {"cmfe", 0xeed0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
1823 {"cnf", 0xeeb0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
1824 {"cnfe", 0xeef0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
1825 /* The FPA10 data sheet suggests that the 'E' of cmfe/cnfe should
1826 not be an optional suffix, but part of the instruction. To be
1827 compatible, we accept either. */
1828 {"cmfe", 0xeed0f110, 4, FPU_FPA_EXT_V1, do_fpa_cmp},
1829 {"cnfe", 0xeef0f110, 4, FPU_FPA_EXT_V1, do_fpa_cmp},
1830
1831 {"flts", 0xee000110, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1832 {"fltsp", 0xee000130, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1833 {"fltsm", 0xee000150, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1834 {"fltsz", 0xee000170, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1835 {"fltd", 0xee000190, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1836 {"fltdp", 0xee0001b0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1837 {"fltdm", 0xee0001d0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1838 {"fltdz", 0xee0001f0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1839 {"flte", 0xee080110, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1840 {"fltep", 0xee080130, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1841 {"fltem", 0xee080150, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1842 {"fltez", 0xee080170, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1843
1844 /* The implementation of the FIX instruction is broken on some
1845 assemblers, in that it accepts a precision specifier as well as a
1846 rounding specifier, despite the fact that this is meaningless.
1847 To be more compatible, we accept it as well, though of course it
1848 does not set any bits. */
1849 {"fix", 0xee100110, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1850 {"fixp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1851 {"fixm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1852 {"fixz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1853 {"fixsp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1854 {"fixsm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1855 {"fixsz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1856 {"fixdp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1857 {"fixdm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1858 {"fixdz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1859 {"fixep", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1860 {"fixem", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1861 {"fixez", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1862
1863 /* Instructions that were new with the real FPA, call them V2. */
1864 {"lfm", 0xec100200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1865 {"lfmfd", 0xec900200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1866 {"lfmea", 0xed100200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1867 {"sfm", 0xec000200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1868 {"sfmfd", 0xed000200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1869 {"sfmea", 0xec800200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1870
1871 /* VFP V1xD (single precision). */
1872 /* Moves and type conversions. */
1873 {"fcpys", 0xeeb00a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1874 {"fmrs", 0xee100a10, 4, FPU_VFP_EXT_V1xD, do_vfp_reg_from_sp},
1875 {"fmsr", 0xee000a10, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_from_reg},
1876 {"fmstat", 0xeef1fa10, 6, FPU_VFP_EXT_V1xD, do_empty},
1877 {"fsitos", 0xeeb80ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1878 {"fuitos", 0xeeb80a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1879 {"ftosis", 0xeebd0a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1880 {"ftosizs", 0xeebd0ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1881 {"ftouis", 0xeebc0a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1882 {"ftouizs", 0xeebc0ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1883 {"fmrx", 0xeef00a10, 4, FPU_VFP_EXT_V1xD, do_vfp_reg_from_ctrl},
1884 {"fmxr", 0xeee00a10, 4, FPU_VFP_EXT_V1xD, do_vfp_ctrl_from_reg},
1885
1886 /* Memory operations. */
1887 {"flds", 0xed100a00, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_ldst},
1888 {"fsts", 0xed000a00, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_ldst},
1889 {"fldmias", 0xec900a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
1890 {"fldmfds", 0xec900a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
1891 {"fldmdbs", 0xed300a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
1892 {"fldmeas", 0xed300a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
1893 {"fldmiax", 0xec900b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
1894 {"fldmfdx", 0xec900b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
1895 {"fldmdbx", 0xed300b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
1896 {"fldmeax", 0xed300b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
1897 {"fstmias", 0xec800a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
1898 {"fstmeas", 0xec800a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
1899 {"fstmdbs", 0xed200a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
1900 {"fstmfds", 0xed200a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
1901 {"fstmiax", 0xec800b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
1902 {"fstmeax", 0xec800b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
1903 {"fstmdbx", 0xed200b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
1904 {"fstmfdx", 0xed200b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
1905
1906 /* Monadic operations. */
1907 {"fabss", 0xeeb00ac0, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1908 {"fnegs", 0xeeb10a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1909 {"fsqrts", 0xeeb10ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1910
1911 /* Dyadic operations. */
1912 {"fadds", 0xee300a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1913 {"fsubs", 0xee300a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1914 {"fmuls", 0xee200a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1915 {"fdivs", 0xee800a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1916 {"fmacs", 0xee000a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1917 {"fmscs", 0xee100a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1918 {"fnmuls", 0xee200a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1919 {"fnmacs", 0xee000a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1920 {"fnmscs", 0xee100a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1921
1922 /* Comparisons. */
1923 {"fcmps", 0xeeb40a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1924 {"fcmpzs", 0xeeb50a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_compare_z},
1925 {"fcmpes", 0xeeb40ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1926 {"fcmpezs", 0xeeb50ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_compare_z},
1927
1928 /* VFP V1 (Double precision). */
1929 /* Moves and type conversions. */
1930 {"fcpyd", 0xeeb00b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1931 {"fcvtds", 0xeeb70ac0, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
1932 {"fcvtsd", 0xeeb70bc0, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
1933 {"fmdhr", 0xee200b10, 5, FPU_VFP_EXT_V1, do_vfp_dp_from_reg},
1934 {"fmdlr", 0xee000b10, 5, FPU_VFP_EXT_V1, do_vfp_dp_from_reg},
1935 {"fmrdh", 0xee300b10, 5, FPU_VFP_EXT_V1, do_vfp_reg_from_dp},
1936 {"fmrdl", 0xee100b10, 5, FPU_VFP_EXT_V1, do_vfp_reg_from_dp},
1937 {"fsitod", 0xeeb80bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
1938 {"fuitod", 0xeeb80b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
1939 {"ftosid", 0xeebd0b40, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
1940 {"ftosizd", 0xeebd0bc0, 7, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
1941 {"ftouid", 0xeebc0b40, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
1942 {"ftouizd", 0xeebc0bc0, 7, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
1943
1944 /* Memory operations. */
1945 {"fldd", 0xed100b00, 4, FPU_VFP_EXT_V1, do_vfp_dp_ldst},
1946 {"fstd", 0xed000b00, 4, FPU_VFP_EXT_V1, do_vfp_dp_ldst},
1947 {"fldmiad", 0xec900b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
1948 {"fldmfdd", 0xec900b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
1949 {"fldmdbd", 0xed300b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
1950 {"fldmead", 0xed300b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
1951 {"fstmiad", 0xec800b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
1952 {"fstmead", 0xec800b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
1953 {"fstmdbd", 0xed200b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
1954 {"fstmfdd", 0xed200b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
1955
1956 /* Monadic operations. */
1957 {"fabsd", 0xeeb00bc0, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1958 {"fnegd", 0xeeb10b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1959 {"fsqrtd", 0xeeb10bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1960
1961 /* Dyadic operations. */
1962 {"faddd", 0xee300b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1963 {"fsubd", 0xee300b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1964 {"fmuld", 0xee200b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1965 {"fdivd", 0xee800b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1966 {"fmacd", 0xee000b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1967 {"fmscd", 0xee100b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1968 {"fnmuld", 0xee200b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1969 {"fnmacd", 0xee000b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1970 {"fnmscd", 0xee100b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1971
1972 /* Comparisons. */
1973 {"fcmpd", 0xeeb40b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1974 {"fcmpzd", 0xeeb50b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_compare_z},
1975 {"fcmped", 0xeeb40bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1976 {"fcmpezd", 0xeeb50bc0, 7, FPU_VFP_EXT_V1, do_vfp_dp_compare_z},
1977
1978 /* VFP V2. */
1979 {"fmsrr", 0xec400a10, 5, FPU_VFP_EXT_V2, do_vfp_sp_reg2},
1980 {"fmrrs", 0xec500a10, 5, FPU_VFP_EXT_V2, do_vfp_sp_reg2},
1981 {"fmdrr", 0xec400b10, 5, FPU_VFP_EXT_V2, do_vfp_dp_from_reg2},
1982 {"fmrrd", 0xec500b10, 5, FPU_VFP_EXT_V2, do_vfp_reg2_from_dp},
1983
1984 /* Intel XScale extensions to ARM V5 ISA. (All use CP0). */
1985 {"mia", 0xee200010, 3, ARM_CEXT_XSCALE, do_xsc_mia},
1986 {"miaph", 0xee280010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
1987 {"miabb", 0xee2c0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
1988 {"miabt", 0xee2d0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
1989 {"miatb", 0xee2e0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
1990 {"miatt", 0xee2f0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
1991 {"mar", 0xec400000, 3, ARM_CEXT_XSCALE, do_xsc_mar},
1992 {"mra", 0xec500000, 3, ARM_CEXT_XSCALE, do_xsc_mra},
1993
1994 /* Intel Wireless MMX technology instructions. */
1995 {"tandcb", 0xee130130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
1996 {"tandch", 0xee530130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
1997 {"tandcw", 0xee930130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
1998 {"tbcstb", 0xee400010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
1999 {"tbcsth", 0xee400050, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
2000 {"tbcstw", 0xee400090, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
2001 {"textrcb", 0xee130170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
2002 {"textrch", 0xee530170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
2003 {"textrcw", 0xee930170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
2004 {"textrmub", 0xee100070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
2005 {"textrmuh", 0xee500070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
2006 {"textrmuw", 0xee900070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
2007 {"textrmsb", 0xee100078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
2008 {"textrmsh", 0xee500078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
2009 {"textrmsw", 0xee900078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
2010 {"tinsrb", 0xee600010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
2011 {"tinsrh", 0xee600050, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
2012 {"tinsrw", 0xee600090, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
2013 {"tmcr", 0xee000110, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmcr},
2014 {"tmcrr", 0xec400000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_tmcrr},
2015 {"tmia", 0xee200010, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
2016 {"tmiaph", 0xee280010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
2017 {"tmiabb", 0xee2c0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
2018 {"tmiabt", 0xee2d0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
2019 {"tmiatb", 0xee2e0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
2020 {"tmiatt", 0xee2f0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
2021 {"tmovmskb", 0xee100030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
2022 {"tmovmskh", 0xee500030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
2023 {"tmovmskw", 0xee900030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
2024 {"tmrc", 0xee100110, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmrc},
2025 {"tmrrc", 0xec500000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_tmrrc},
2026 {"torcb", 0xee130150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
2027 {"torch", 0xee530150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
2028 {"torcw", 0xee930150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
2029 {"waccb", 0xee0001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2030 {"wacch", 0xee4001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2031 {"waccw", 0xee8001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2032 {"waddbss", 0xee300180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2033 {"waddb", 0xee000180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2034 {"waddbus", 0xee100180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2035 {"waddhss", 0xee700180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2036 {"waddh", 0xee400180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2037 {"waddhus", 0xee500180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2038 {"waddwss", 0xeeb00180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2039 {"waddw", 0xee800180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2040 {"waddwus", 0xee900180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2041 {"waligni", 0xee000020, 7, ARM_CEXT_IWMMXT, do_iwmmxt_waligni},
2042 {"walignr0", 0xee800020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2043 {"walignr1", 0xee900020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2044 {"walignr2", 0xeea00020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2045 {"walignr3", 0xeeb00020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2046 {"wand", 0xee200000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2047 {"wandn", 0xee300000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2048 {"wavg2b", 0xee800000, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2049 {"wavg2br", 0xee900000, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2050 {"wavg2h", 0xeec00000, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2051 {"wavg2hr", 0xeed00000, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2052 {"wcmpeqb", 0xee000060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2053 {"wcmpeqh", 0xee400060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2054 {"wcmpeqw", 0xee800060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2055 {"wcmpgtub", 0xee100060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2056 {"wcmpgtuh", 0xee500060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2057 {"wcmpgtuw", 0xee900060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2058 {"wcmpgtsb", 0xee300060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2059 {"wcmpgtsh", 0xee700060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2060 {"wcmpgtsw", 0xeeb00060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2061 {"wldrb", 0xec100000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
2062 {"wldrh", 0xec100100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
2063 {"wldrw", 0xec100200, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
2064 {"wldrd", 0xec100300, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
2065 {"wmacs", 0xee600100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2066 {"wmacsz", 0xee700100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2067 {"wmacu", 0xee400100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2068 {"wmacuz", 0xee500100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2069 {"wmadds", 0xeea00100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2070 {"wmaddu", 0xee800100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2071 {"wmaxsb", 0xee200160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2072 {"wmaxsh", 0xee600160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2073 {"wmaxsw", 0xeea00160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2074 {"wmaxub", 0xee000160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2075 {"wmaxuh", 0xee400160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2076 {"wmaxuw", 0xee800160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2077 {"wminsb", 0xee300160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2078 {"wminsh", 0xee700160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2079 {"wminsw", 0xeeb00160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2080 {"wminub", 0xee100160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2081 {"wminuh", 0xee500160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2082 {"wminuw", 0xee900160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2083 {"wmov", 0xee000000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wmov},
2084 {"wmulsm", 0xee300100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2085 {"wmulsl", 0xee200100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2086 {"wmulum", 0xee100100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2087 {"wmulul", 0xee000100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2088 {"wor", 0xee000000, 3, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2089 {"wpackhss", 0xee700080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2090 {"wpackhus", 0xee500080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2091 {"wpackwss", 0xeeb00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2092 {"wpackwus", 0xee900080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2093 {"wpackdss", 0xeef00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2094 {"wpackdus", 0xeed00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2095 {"wrorh", 0xee700040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2096 {"wrorhg", 0xee700148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2097 {"wrorw", 0xeeb00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2098 {"wrorwg", 0xeeb00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2099 {"wrord", 0xeef00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2100 {"wrordg", 0xeef00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2101 {"wsadb", 0xee000120, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2102 {"wsadbz", 0xee100120, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2103 {"wsadh", 0xee400120, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2104 {"wsadhz", 0xee500120, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2105 {"wshufh", 0xee0001e0, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wshufh},
2106 {"wsllh", 0xee500040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2107 {"wsllhg", 0xee500148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2108 {"wsllw", 0xee900040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2109 {"wsllwg", 0xee900148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2110 {"wslld", 0xeed00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2111 {"wslldg", 0xeed00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2112 {"wsrah", 0xee400040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2113 {"wsrahg", 0xee400148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2114 {"wsraw", 0xee800040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2115 {"wsrawg", 0xee800148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2116 {"wsrad", 0xeec00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2117 {"wsradg", 0xeec00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2118 {"wsrlh", 0xee600040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2119 {"wsrlhg", 0xee600148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2120 {"wsrlw", 0xeea00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2121 {"wsrlwg", 0xeea00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2122 {"wsrld", 0xeee00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2123 {"wsrldg", 0xeee00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2124 {"wstrb", 0xec000000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
2125 {"wstrh", 0xec000100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
2126 {"wstrw", 0xec000200, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
2127 {"wstrd", 0xec000300, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
2128 {"wsubbss", 0xee3001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2129 {"wsubb", 0xee0001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2130 {"wsubbus", 0xee1001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2131 {"wsubhss", 0xee7001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2132 {"wsubh", 0xee4001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2133 {"wsubhus", 0xee5001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2134 {"wsubwss", 0xeeb001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2135 {"wsubw", 0xee8001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2136 {"wsubwus", 0xee9001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2137 {"wunpckehub", 0xee0000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2138 {"wunpckehuh", 0xee4000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2139 {"wunpckehuw", 0xee8000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2140 {"wunpckehsb", 0xee2000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2141 {"wunpckehsh", 0xee6000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2142 {"wunpckehsw", 0xeea000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2143 {"wunpckihb", 0xee1000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2144 {"wunpckihh", 0xee5000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2145 {"wunpckihw", 0xee9000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2146 {"wunpckelub", 0xee0000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2147 {"wunpckeluh", 0xee4000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2148 {"wunpckeluw", 0xee8000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2149 {"wunpckelsb", 0xee2000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2150 {"wunpckelsh", 0xee6000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2151 {"wunpckelsw", 0xeea000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2152 {"wunpckilb", 0xee1000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2153 {"wunpckilh", 0xee5000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2154 {"wunpckilw", 0xee9000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2155 {"wxor", 0xee100000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2156 {"wzero", 0xee300000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wzero},
2157
2158 /* Cirrus Maverick instructions. */
2159 {"cfldrs", 0xec100400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_1},
2160 {"cfldrd", 0xec500400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_2},
2161 {"cfldr32", 0xec100500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_3},
2162 {"cfldr64", 0xec500500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_4},
2163 {"cfstrs", 0xec000400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_1},
2164 {"cfstrd", 0xec400400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_2},
2165 {"cfstr32", 0xec000500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_3},
2166 {"cfstr64", 0xec400500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_4},
2167 {"cfmvsr", 0xee000450, 6, ARM_CEXT_MAVERICK, do_mav_binops_2a},
2168 {"cfmvrs", 0xee100450, 6, ARM_CEXT_MAVERICK, do_mav_binops_1a},
2169 {"cfmvdlr", 0xee000410, 7, ARM_CEXT_MAVERICK, do_mav_binops_2b},
2170 {"cfmvrdl", 0xee100410, 7, ARM_CEXT_MAVERICK, do_mav_binops_1b},
2171 {"cfmvdhr", 0xee000430, 7, ARM_CEXT_MAVERICK, do_mav_binops_2b},
2172 {"cfmvrdh", 0xee100430, 7, ARM_CEXT_MAVERICK, do_mav_binops_1b},
2173 {"cfmv64lr", 0xee000510, 8, ARM_CEXT_MAVERICK, do_mav_binops_2c},
2174 {"cfmvr64l", 0xee100510, 8, ARM_CEXT_MAVERICK, do_mav_binops_1c},
2175 {"cfmv64hr", 0xee000530, 8, ARM_CEXT_MAVERICK, do_mav_binops_2c},
2176 {"cfmvr64h", 0xee100530, 8, ARM_CEXT_MAVERICK, do_mav_binops_1c},
2177 {"cfmval32", 0xee100610, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
2178 {"cfmv32al", 0xee000610, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
2179 {"cfmvam32", 0xee100630, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
2180 {"cfmv32am", 0xee000630, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
2181 {"cfmvah32", 0xee100650, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
2182 {"cfmv32ah", 0xee000650, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
2183 {"cfmva32", 0xee100670, 7, ARM_CEXT_MAVERICK, do_mav_binops_3a},
2184 {"cfmv32a", 0xee000670, 7, ARM_CEXT_MAVERICK, do_mav_binops_3b},
2185 {"cfmva64", 0xee100690, 7, ARM_CEXT_MAVERICK, do_mav_binops_3c},
2186 {"cfmv64a", 0xee000690, 7, ARM_CEXT_MAVERICK, do_mav_binops_3d},
2187 {"cfmvsc32", 0xee1006b0, 8, ARM_CEXT_MAVERICK, do_mav_dspsc_1},
2188 {"cfmv32sc", 0xee0006b0, 8, ARM_CEXT_MAVERICK, do_mav_dspsc_2},
2189 {"cfcpys", 0xee000400, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
2190 {"cfcpyd", 0xee000420, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
2191 {"cfcvtsd", 0xee000460, 7, ARM_CEXT_MAVERICK, do_mav_binops_1f},
2192 {"cfcvtds", 0xee000440, 7, ARM_CEXT_MAVERICK, do_mav_binops_1g},
2193 {"cfcvt32s", 0xee000480, 8, ARM_CEXT_MAVERICK, do_mav_binops_1h},
2194 {"cfcvt32d", 0xee0004a0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1i},
2195 {"cfcvt64s", 0xee0004c0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1j},
2196 {"cfcvt64d", 0xee0004e0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1k},
2197 {"cfcvts32", 0xee100580, 8, ARM_CEXT_MAVERICK, do_mav_binops_1l},
2198 {"cfcvtd32", 0xee1005a0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1m},
2199 {"cftruncs32", 0xee1005c0, 10, ARM_CEXT_MAVERICK, do_mav_binops_1l},
2200 {"cftruncd32", 0xee1005e0, 10, ARM_CEXT_MAVERICK, do_mav_binops_1m},
2201 {"cfrshl32", 0xee000550, 8, ARM_CEXT_MAVERICK, do_mav_triple_4a},
2202 {"cfrshl64", 0xee000570, 8, ARM_CEXT_MAVERICK, do_mav_triple_4b},
2203 {"cfsh32", 0xee000500, 6, ARM_CEXT_MAVERICK, do_mav_shift_1},
2204 {"cfsh64", 0xee200500, 6, ARM_CEXT_MAVERICK, do_mav_shift_2},
2205 {"cfcmps", 0xee100490, 6, ARM_CEXT_MAVERICK, do_mav_triple_5a},
2206 {"cfcmpd", 0xee1004b0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5b},
2207 {"cfcmp32", 0xee100590, 7, ARM_CEXT_MAVERICK, do_mav_triple_5c},
2208 {"cfcmp64", 0xee1005b0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5d},
2209 {"cfabss", 0xee300400, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
2210 {"cfabsd", 0xee300420, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
2211 {"cfnegs", 0xee300440, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
2212 {"cfnegd", 0xee300460, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
2213 {"cfadds", 0xee300480, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
2214 {"cfaddd", 0xee3004a0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
2215 {"cfsubs", 0xee3004c0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
2216 {"cfsubd", 0xee3004e0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
2217 {"cfmuls", 0xee100400, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
2218 {"cfmuld", 0xee100420, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
2219 {"cfabs32", 0xee300500, 7, ARM_CEXT_MAVERICK, do_mav_binops_1n},
2220 {"cfabs64", 0xee300520, 7, ARM_CEXT_MAVERICK, do_mav_binops_1o},
2221 {"cfneg32", 0xee300540, 7, ARM_CEXT_MAVERICK, do_mav_binops_1n},
2222 {"cfneg64", 0xee300560, 7, ARM_CEXT_MAVERICK, do_mav_binops_1o},
2223 {"cfadd32", 0xee300580, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
2224 {"cfadd64", 0xee3005a0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
2225 {"cfsub32", 0xee3005c0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
2226 {"cfsub64", 0xee3005e0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
2227 {"cfmul32", 0xee100500, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
2228 {"cfmul64", 0xee100520, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
2229 {"cfmac32", 0xee100540, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
2230 {"cfmsc32", 0xee100560, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
2231 {"cfmadd32", 0xee000600, 8, ARM_CEXT_MAVERICK, do_mav_quad_6a},
2232 {"cfmsub32", 0xee100600, 8, ARM_CEXT_MAVERICK, do_mav_quad_6a},
2233 {"cfmadda32", 0xee200600, 9, ARM_CEXT_MAVERICK, do_mav_quad_6b},
2234 {"cfmsuba32", 0xee300600, 9, ARM_CEXT_MAVERICK, do_mav_quad_6b},
2235 };
2236
2237 /* Defines for various bits that we will want to toggle. */
2238 #define INST_IMMEDIATE 0x02000000
2239 #define OFFSET_REG 0x02000000
2240 #define HWOFFSET_IMM 0x00400000
2241 #define SHIFT_BY_REG 0x00000010
2242 #define PRE_INDEX 0x01000000
2243 #define INDEX_UP 0x00800000
2244 #define WRITE_BACK 0x00200000
2245 #define LDM_TYPE_2_OR_3 0x00400000
2246
2247 #define LITERAL_MASK 0xf000f000
2248 #define OPCODE_MASK 0xfe1fffff
2249 #define V4_STR_BIT 0x00000020
2250
2251 #define DATA_OP_SHIFT 21
2252
2253 /* Codes to distinguish the arithmetic instructions. */
2254 #define OPCODE_AND 0
2255 #define OPCODE_EOR 1
2256 #define OPCODE_SUB 2
2257 #define OPCODE_RSB 3
2258 #define OPCODE_ADD 4
2259 #define OPCODE_ADC 5
2260 #define OPCODE_SBC 6
2261 #define OPCODE_RSC 7
2262 #define OPCODE_TST 8
2263 #define OPCODE_TEQ 9
2264 #define OPCODE_CMP 10
2265 #define OPCODE_CMN 11
2266 #define OPCODE_ORR 12
2267 #define OPCODE_MOV 13
2268 #define OPCODE_BIC 14
2269 #define OPCODE_MVN 15
2270
2271 /* Thumb v1 (ARMv4T). */
2272 static void do_t_nop PARAMS ((char *));
2273 static void do_t_arit PARAMS ((char *));
2274 static void do_t_add PARAMS ((char *));
2275 static void do_t_asr PARAMS ((char *));
2276 static void do_t_branch9 PARAMS ((char *));
2277 static void do_t_branch12 PARAMS ((char *));
2278 static void do_t_branch23 PARAMS ((char *));
2279 static void do_t_bx PARAMS ((char *));
2280 static void do_t_compare PARAMS ((char *));
2281 static void do_t_ldmstm PARAMS ((char *));
2282 static void do_t_ldr PARAMS ((char *));
2283 static void do_t_ldrb PARAMS ((char *));
2284 static void do_t_ldrh PARAMS ((char *));
2285 static void do_t_lds PARAMS ((char *));
2286 static void do_t_lsl PARAMS ((char *));
2287 static void do_t_lsr PARAMS ((char *));
2288 static void do_t_mov PARAMS ((char *));
2289 static void do_t_push_pop PARAMS ((char *));
2290 static void do_t_str PARAMS ((char *));
2291 static void do_t_strb PARAMS ((char *));
2292 static void do_t_strh PARAMS ((char *));
2293 static void do_t_sub PARAMS ((char *));
2294 static void do_t_swi PARAMS ((char *));
2295 static void do_t_adr PARAMS ((char *));
2296
2297 /* Thumb v2 (ARMv5T). */
2298 static void do_t_blx PARAMS ((char *));
2299 static void do_t_bkpt PARAMS ((char *));
2300
2301 /* ARM V6. */
2302 static void do_t_cps PARAMS ((char *));
2303 static void do_t_cpy PARAMS ((char *));
2304 static void do_t_setend PARAMS ((char *));;
2305
2306 #define T_OPCODE_MUL 0x4340
2307 #define T_OPCODE_TST 0x4200
2308 #define T_OPCODE_CMN 0x42c0
2309 #define T_OPCODE_NEG 0x4240
2310 #define T_OPCODE_MVN 0x43c0
2311
2312 #define T_OPCODE_ADD_R3 0x1800
2313 #define T_OPCODE_SUB_R3 0x1a00
2314 #define T_OPCODE_ADD_HI 0x4400
2315 #define T_OPCODE_ADD_ST 0xb000
2316 #define T_OPCODE_SUB_ST 0xb080
2317 #define T_OPCODE_ADD_SP 0xa800
2318 #define T_OPCODE_ADD_PC 0xa000
2319 #define T_OPCODE_ADD_I8 0x3000
2320 #define T_OPCODE_SUB_I8 0x3800
2321 #define T_OPCODE_ADD_I3 0x1c00
2322 #define T_OPCODE_SUB_I3 0x1e00
2323
2324 #define T_OPCODE_ASR_R 0x4100
2325 #define T_OPCODE_LSL_R 0x4080
2326 #define T_OPCODE_LSR_R 0x40c0
2327 #define T_OPCODE_ASR_I 0x1000
2328 #define T_OPCODE_LSL_I 0x0000
2329 #define T_OPCODE_LSR_I 0x0800
2330
2331 #define T_OPCODE_MOV_I8 0x2000
2332 #define T_OPCODE_CMP_I8 0x2800
2333 #define T_OPCODE_CMP_LR 0x4280
2334 #define T_OPCODE_MOV_HR 0x4600
2335 #define T_OPCODE_CMP_HR 0x4500
2336
2337 #define T_OPCODE_LDR_PC 0x4800
2338 #define T_OPCODE_LDR_SP 0x9800
2339 #define T_OPCODE_STR_SP 0x9000
2340 #define T_OPCODE_LDR_IW 0x6800
2341 #define T_OPCODE_STR_IW 0x6000
2342 #define T_OPCODE_LDR_IH 0x8800
2343 #define T_OPCODE_STR_IH 0x8000
2344 #define T_OPCODE_LDR_IB 0x7800
2345 #define T_OPCODE_STR_IB 0x7000
2346 #define T_OPCODE_LDR_RW 0x5800
2347 #define T_OPCODE_STR_RW 0x5000
2348 #define T_OPCODE_LDR_RH 0x5a00
2349 #define T_OPCODE_STR_RH 0x5200
2350 #define T_OPCODE_LDR_RB 0x5c00
2351 #define T_OPCODE_STR_RB 0x5400
2352
2353 #define T_OPCODE_PUSH 0xb400
2354 #define T_OPCODE_POP 0xbc00
2355
2356 #define T_OPCODE_BRANCH 0xe7fe
2357
2358 static int thumb_reg PARAMS ((char ** str, int hi_lo));
2359
2360 #define THUMB_SIZE 2 /* Size of thumb instruction. */
2361 #define THUMB_REG_LO 0x1
2362 #define THUMB_REG_HI 0x2
2363 #define THUMB_REG_ANY 0x3
2364
2365 #define THUMB_H1 0x0080
2366 #define THUMB_H2 0x0040
2367
2368 #define THUMB_ASR 0
2369 #define THUMB_LSL 1
2370 #define THUMB_LSR 2
2371
2372 #define THUMB_MOVE 0
2373 #define THUMB_COMPARE 1
2374 #define THUMB_CPY 2
2375
2376 #define THUMB_LOAD 0
2377 #define THUMB_STORE 1
2378
2379 #define THUMB_PP_PC_LR 0x0100
2380
2381 /* These three are used for immediate shifts, do not alter. */
2382 #define THUMB_WORD 2
2383 #define THUMB_HALFWORD 1
2384 #define THUMB_BYTE 0
2385
2386 struct thumb_opcode
2387 {
2388 /* Basic string to match. */
2389 const char * template;
2390
2391 /* Basic instruction code. */
2392 unsigned long value;
2393
2394 int size;
2395
2396 /* Which CPU variants this exists for. */
2397 unsigned long variant;
2398
2399 /* Function to call to parse args. */
2400 void (* parms) PARAMS ((char *));
2401 };
2402
2403 static const struct thumb_opcode tinsns[] =
2404 {
2405 /* Thumb v1 (ARMv4T). */
2406 {"adc", 0x4140, 2, ARM_EXT_V4T, do_t_arit},
2407 {"add", 0x0000, 2, ARM_EXT_V4T, do_t_add},
2408 {"and", 0x4000, 2, ARM_EXT_V4T, do_t_arit},
2409 {"asr", 0x0000, 2, ARM_EXT_V4T, do_t_asr},
2410 {"b", T_OPCODE_BRANCH, 2, ARM_EXT_V4T, do_t_branch12},
2411 {"beq", 0xd0fe, 2, ARM_EXT_V4T, do_t_branch9},
2412 {"bne", 0xd1fe, 2, ARM_EXT_V4T, do_t_branch9},
2413 {"bcs", 0xd2fe, 2, ARM_EXT_V4T, do_t_branch9},
2414 {"bhs", 0xd2fe, 2, ARM_EXT_V4T, do_t_branch9},
2415 {"bcc", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
2416 {"bul", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
2417 {"blo", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
2418 {"bmi", 0xd4fe, 2, ARM_EXT_V4T, do_t_branch9},
2419 {"bpl", 0xd5fe, 2, ARM_EXT_V4T, do_t_branch9},
2420 {"bvs", 0xd6fe, 2, ARM_EXT_V4T, do_t_branch9},
2421 {"bvc", 0xd7fe, 2, ARM_EXT_V4T, do_t_branch9},
2422 {"bhi", 0xd8fe, 2, ARM_EXT_V4T, do_t_branch9},
2423 {"bls", 0xd9fe, 2, ARM_EXT_V4T, do_t_branch9},
2424 {"bge", 0xdafe, 2, ARM_EXT_V4T, do_t_branch9},
2425 {"blt", 0xdbfe, 2, ARM_EXT_V4T, do_t_branch9},
2426 {"bgt", 0xdcfe, 2, ARM_EXT_V4T, do_t_branch9},
2427 {"ble", 0xddfe, 2, ARM_EXT_V4T, do_t_branch9},
2428 {"bal", 0xdefe, 2, ARM_EXT_V4T, do_t_branch9},
2429 {"bic", 0x4380, 2, ARM_EXT_V4T, do_t_arit},
2430 {"bl", 0xf7fffffe, 4, ARM_EXT_V4T, do_t_branch23},
2431 {"bx", 0x4700, 2, ARM_EXT_V4T, do_t_bx},
2432 {"cmn", T_OPCODE_CMN, 2, ARM_EXT_V4T, do_t_arit},
2433 {"cmp", 0x0000, 2, ARM_EXT_V4T, do_t_compare},
2434 {"eor", 0x4040, 2, ARM_EXT_V4T, do_t_arit},
2435 {"ldmia", 0xc800, 2, ARM_EXT_V4T, do_t_ldmstm},
2436 {"ldr", 0x0000, 2, ARM_EXT_V4T, do_t_ldr},
2437 {"ldrb", 0x0000, 2, ARM_EXT_V4T, do_t_ldrb},
2438 {"ldrh", 0x0000, 2, ARM_EXT_V4T, do_t_ldrh},
2439 {"ldrsb", 0x5600, 2, ARM_EXT_V4T, do_t_lds},
2440 {"ldrsh", 0x5e00, 2, ARM_EXT_V4T, do_t_lds},
2441 {"ldsb", 0x5600, 2, ARM_EXT_V4T, do_t_lds},
2442 {"ldsh", 0x5e00, 2, ARM_EXT_V4T, do_t_lds},
2443 {"lsl", 0x0000, 2, ARM_EXT_V4T, do_t_lsl},
2444 {"lsr", 0x0000, 2, ARM_EXT_V4T, do_t_lsr},
2445 {"mov", 0x0000, 2, ARM_EXT_V4T, do_t_mov},
2446 {"mul", T_OPCODE_MUL, 2, ARM_EXT_V4T, do_t_arit},
2447 {"mvn", T_OPCODE_MVN, 2, ARM_EXT_V4T, do_t_arit},
2448 {"neg", T_OPCODE_NEG, 2, ARM_EXT_V4T, do_t_arit},
2449 {"orr", 0x4300, 2, ARM_EXT_V4T, do_t_arit},
2450 {"pop", 0xbc00, 2, ARM_EXT_V4T, do_t_push_pop},
2451 {"push", 0xb400, 2, ARM_EXT_V4T, do_t_push_pop},
2452 {"ror", 0x41c0, 2, ARM_EXT_V4T, do_t_arit},
2453 {"sbc", 0x4180, 2, ARM_EXT_V4T, do_t_arit},
2454 {"stmia", 0xc000, 2, ARM_EXT_V4T, do_t_ldmstm},
2455 {"str", 0x0000, 2, ARM_EXT_V4T, do_t_str},
2456 {"strb", 0x0000, 2, ARM_EXT_V4T, do_t_strb},
2457 {"strh", 0x0000, 2, ARM_EXT_V4T, do_t_strh},
2458 {"swi", 0xdf00, 2, ARM_EXT_V4T, do_t_swi},
2459 {"sub", 0x0000, 2, ARM_EXT_V4T, do_t_sub},
2460 {"tst", T_OPCODE_TST, 2, ARM_EXT_V4T, do_t_arit},
2461 /* Pseudo ops: */
2462 {"adr", 0x0000, 2, ARM_EXT_V4T, do_t_adr},
2463 {"nop", 0x46C0, 2, ARM_EXT_V4T, do_t_nop}, /* mov r8,r8 */
2464 /* Thumb v2 (ARMv5T). */
2465 {"blx", 0, 0, ARM_EXT_V5T, do_t_blx},
2466 {"bkpt", 0xbe00, 2, ARM_EXT_V5T, do_t_bkpt},
2467
2468 /* ARM V6. */
2469 {"cpsie", 0xb660, 2, ARM_EXT_V6, do_t_cps},
2470 {"cpsid", 0xb670, 2, ARM_EXT_V6, do_t_cps},
2471 {"cpy", 0x4600, 2, ARM_EXT_V6, do_t_cpy},
2472 {"rev", 0xba00, 2, ARM_EXT_V6, do_t_arit},
2473 {"rev16", 0xba40, 2, ARM_EXT_V6, do_t_arit},
2474 {"revsh", 0xbac0, 2, ARM_EXT_V6, do_t_arit},
2475 {"setend", 0xb650, 2, ARM_EXT_V6, do_t_setend},
2476 {"sxth", 0xb200, 2, ARM_EXT_V6, do_t_arit},
2477 {"sxtb", 0xb240, 2, ARM_EXT_V6, do_t_arit},
2478 {"uxth", 0xb280, 2, ARM_EXT_V6, do_t_arit},
2479 {"uxtb", 0xb2c0, 2, ARM_EXT_V6, do_t_arit},
2480 };
2481
2482 #define BAD_ARGS _("bad arguments to instruction")
2483 #define BAD_PC _("r15 not allowed here")
2484 #define BAD_COND _("instruction is not conditional")
2485 #define ERR_NO_ACCUM _("acc0 expected")
2486
2487 static struct hash_control * arm_ops_hsh = NULL;
2488 static struct hash_control * arm_tops_hsh = NULL;
2489 static struct hash_control * arm_cond_hsh = NULL;
2490 static struct hash_control * arm_shift_hsh = NULL;
2491 static struct hash_control * arm_psr_hsh = NULL;
2492
2493 /* This table describes all the machine specific pseudo-ops the assembler
2494 has to support. The fields are:
2495 pseudo-op name without dot
2496 function to call to execute this pseudo-op
2497 Integer arg to pass to the function. */
2498
2499 static void s_req PARAMS ((int));
2500 static void s_unreq PARAMS ((int));
2501 static void s_align PARAMS ((int));
2502 static void s_bss PARAMS ((int));
2503 static void s_even PARAMS ((int));
2504 static void s_ltorg PARAMS ((int));
2505 static void s_arm PARAMS ((int));
2506 static void s_thumb PARAMS ((int));
2507 static void s_code PARAMS ((int));
2508 static void s_force_thumb PARAMS ((int));
2509 static void s_thumb_func PARAMS ((int));
2510 static void s_thumb_set PARAMS ((int));
2511 #ifdef OBJ_ELF
2512 static void s_arm_elf_cons PARAMS ((int));
2513 #endif
2514
2515 static int my_get_expression PARAMS ((expressionS *, char **));
2516
2517 const pseudo_typeS md_pseudo_table[] =
2518 {
2519 /* Never called because '.req' does not start a line. */
2520 { "req", s_req, 0 },
2521 { "unreq", s_unreq, 0 },
2522 { "bss", s_bss, 0 },
2523 { "align", s_align, 0 },
2524 { "arm", s_arm, 0 },
2525 { "thumb", s_thumb, 0 },
2526 { "code", s_code, 0 },
2527 { "force_thumb", s_force_thumb, 0 },
2528 { "thumb_func", s_thumb_func, 0 },
2529 { "thumb_set", s_thumb_set, 0 },
2530 { "even", s_even, 0 },
2531 { "ltorg", s_ltorg, 0 },
2532 { "pool", s_ltorg, 0 },
2533 #ifdef OBJ_ELF
2534 { "word", s_arm_elf_cons, 4 },
2535 { "long", s_arm_elf_cons, 4 },
2536 #else
2537 { "word", cons, 4},
2538 #endif
2539 { "extend", float_cons, 'x' },
2540 { "ldouble", float_cons, 'x' },
2541 { "packed", float_cons, 'p' },
2542 { 0, 0, 0 }
2543 };
2544
2545 /* Other internal functions. */
2546 static int arm_parse_extension PARAMS ((char *, int *));
2547 static int arm_parse_cpu PARAMS ((char *));
2548 static int arm_parse_arch PARAMS ((char *));
2549 static int arm_parse_fpu PARAMS ((char *));
2550 static int arm_parse_float_abi PARAMS ((char *));
2551 #if 0 /* Suppressed - for now. */
2552 #if defined OBJ_COFF || defined OBJ_ELF
2553 static void arm_add_note PARAMS ((const char *, const char *, unsigned int));
2554 #endif
2555 #endif
2556
2557 /* Stuff needed to resolve the label ambiguity
2558 As:
2559 ...
2560 label: <insn>
2561 may differ from:
2562 ...
2563 label:
2564 <insn>
2565 */
2566
2567 symbolS * last_label_seen;
2568 static int label_is_thumb_function_name = FALSE;
2569
2570 /* Literal Pool stuff. */
2571
2572 #define MAX_LITERAL_POOL_SIZE 1024
2573
2574 /* Literal pool structure. Held on a per-section
2575 and per-sub-section basis. */
2576 typedef struct literal_pool
2577 {
2578 expressionS literals [MAX_LITERAL_POOL_SIZE];
2579 unsigned int next_free_entry;
2580 unsigned int id;
2581 symbolS * symbol;
2582 segT section;
2583 subsegT sub_section;
2584 struct literal_pool * next;
2585 } literal_pool;
2586
2587 /* Pointer to a linked list of literal pools. */
2588 literal_pool * list_of_pools = NULL;
2589
2590 static literal_pool * find_literal_pool PARAMS ((void));
2591 static literal_pool * find_or_make_literal_pool PARAMS ((void));
2592
2593 static literal_pool *
2594 find_literal_pool ()
2595 {
2596 literal_pool * pool;
2597
2598 for (pool = list_of_pools; pool != NULL; pool = pool->next)
2599 {
2600 if (pool->section == now_seg
2601 && pool->sub_section == now_subseg)
2602 break;
2603 }
2604
2605 return pool;
2606 }
2607
2608 static literal_pool *
2609 find_or_make_literal_pool ()
2610 {
2611 /* Next literal pool ID number. */
2612 static unsigned int latest_pool_num = 1;
2613 literal_pool * pool;
2614
2615 pool = find_literal_pool ();
2616
2617 if (pool == NULL)
2618 {
2619 /* Create a new pool. */
2620 pool = (literal_pool *) xmalloc (sizeof (* pool));
2621 if (! pool)
2622 return NULL;
2623
2624 pool->next_free_entry = 0;
2625 pool->section = now_seg;
2626 pool->sub_section = now_subseg;
2627 pool->next = list_of_pools;
2628 pool->symbol = NULL;
2629
2630 /* Add it to the list. */
2631 list_of_pools = pool;
2632 }
2633
2634 /* New pools, and emptied pools, will have a NULL symbol. */
2635 if (pool->symbol == NULL)
2636 {
2637 pool->symbol = symbol_create (FAKE_LABEL_NAME, undefined_section,
2638 (valueT) 0, &zero_address_frag);
2639 pool->id = latest_pool_num ++;
2640 }
2641
2642 /* Done. */
2643 return pool;
2644 }
2645
2646 /* Add the literal in the global 'inst'
2647 structure to the relevent literal pool. */
2648 static int
2649 add_to_lit_pool ()
2650 {
2651 literal_pool * pool;
2652 unsigned int entry;
2653
2654 pool = find_or_make_literal_pool ();
2655
2656 /* Check if this literal value is already in the pool. */
2657 for (entry = 0; entry < pool->next_free_entry; entry ++)
2658 {
2659 if ((pool->literals[entry].X_op == inst.reloc.exp.X_op)
2660 && (inst.reloc.exp.X_op == O_constant)
2661 && (pool->literals[entry].X_add_number
2662 == inst.reloc.exp.X_add_number)
2663 && (pool->literals[entry].X_unsigned
2664 == inst.reloc.exp.X_unsigned))
2665 break;
2666
2667 if ((pool->literals[entry].X_op == inst.reloc.exp.X_op)
2668 && (inst.reloc.exp.X_op == O_symbol)
2669 && (pool->literals[entry].X_add_number
2670 == inst.reloc.exp.X_add_number)
2671 && (pool->literals[entry].X_add_symbol
2672 == inst.reloc.exp.X_add_symbol)
2673 && (pool->literals[entry].X_op_symbol
2674 == inst.reloc.exp.X_op_symbol))
2675 break;
2676 }
2677
2678 /* Do we need to create a new entry? */
2679 if (entry == pool->next_free_entry)
2680 {
2681 if (entry >= MAX_LITERAL_POOL_SIZE)
2682 {
2683 inst.error = _("literal pool overflow");
2684 return FAIL;
2685 }
2686
2687 pool->literals[entry] = inst.reloc.exp;
2688 pool->next_free_entry += 1;
2689 }
2690
2691 inst.reloc.exp.X_op = O_symbol;
2692 inst.reloc.exp.X_add_number = ((int) entry) * 4 - 8;
2693 inst.reloc.exp.X_add_symbol = pool->symbol;
2694
2695 return SUCCESS;
2696 }
2697
2698 /* Can't use symbol_new here, so have to create a symbol and then at
2699 a later date assign it a value. Thats what these functions do. */
2700
2701 static void
2702 symbol_locate (symbolP, name, segment, valu, frag)
2703 symbolS * symbolP;
2704 const char * name; /* It is copied, the caller can modify. */
2705 segT segment; /* Segment identifier (SEG_<something>). */
2706 valueT valu; /* Symbol value. */
2707 fragS * frag; /* Associated fragment. */
2708 {
2709 unsigned int name_length;
2710 char * preserved_copy_of_name;
2711
2712 name_length = strlen (name) + 1; /* +1 for \0. */
2713 obstack_grow (&notes, name, name_length);
2714 preserved_copy_of_name = obstack_finish (&notes);
2715 #ifdef STRIP_UNDERSCORE
2716 if (preserved_copy_of_name[0] == '_')
2717 preserved_copy_of_name++;
2718 #endif
2719
2720 #ifdef tc_canonicalize_symbol_name
2721 preserved_copy_of_name =
2722 tc_canonicalize_symbol_name (preserved_copy_of_name);
2723 #endif
2724
2725 S_SET_NAME (symbolP, preserved_copy_of_name);
2726
2727 S_SET_SEGMENT (symbolP, segment);
2728 S_SET_VALUE (symbolP, valu);
2729 symbol_clear_list_pointers (symbolP);
2730
2731 symbol_set_frag (symbolP, frag);
2732
2733 /* Link to end of symbol chain. */
2734 {
2735 extern int symbol_table_frozen;
2736 if (symbol_table_frozen)
2737 abort ();
2738 }
2739
2740 symbol_append (symbolP, symbol_lastP, & symbol_rootP, & symbol_lastP);
2741
2742 obj_symbol_new_hook (symbolP);
2743
2744 #ifdef tc_symbol_new_hook
2745 tc_symbol_new_hook (symbolP);
2746 #endif
2747
2748 #ifdef DEBUG_SYMS
2749 verify_symbol_chain (symbol_rootP, symbol_lastP);
2750 #endif /* DEBUG_SYMS */
2751 }
2752
2753 /* Check that an immediate is valid.
2754 If so, convert it to the right format. */
2755
2756 static unsigned int
2757 validate_immediate (val)
2758 unsigned int val;
2759 {
2760 unsigned int a;
2761 unsigned int i;
2762
2763 #define rotate_left(v, n) (v << n | v >> (32 - n))
2764
2765 for (i = 0; i < 32; i += 2)
2766 if ((a = rotate_left (val, i)) <= 0xff)
2767 return a | (i << 7); /* 12-bit pack: [shift-cnt,const]. */
2768
2769 return FAIL;
2770 }
2771
2772 /* Check to see if an immediate can be computed as two separate immediate
2773 values, added together. We already know that this value cannot be
2774 computed by just one ARM instruction. */
2775
2776 static unsigned int
2777 validate_immediate_twopart (val, highpart)
2778 unsigned int val;
2779 unsigned int * highpart;
2780 {
2781 unsigned int a;
2782 unsigned int i;
2783
2784 for (i = 0; i < 32; i += 2)
2785 if (((a = rotate_left (val, i)) & 0xff) != 0)
2786 {
2787 if (a & 0xff00)
2788 {
2789 if (a & ~ 0xffff)
2790 continue;
2791 * highpart = (a >> 8) | ((i + 24) << 7);
2792 }
2793 else if (a & 0xff0000)
2794 {
2795 if (a & 0xff000000)
2796 continue;
2797 * highpart = (a >> 16) | ((i + 16) << 7);
2798 }
2799 else
2800 {
2801 assert (a & 0xff000000);
2802 * highpart = (a >> 24) | ((i + 8) << 7);
2803 }
2804
2805 return (a & 0xff) | (i << 7);
2806 }
2807
2808 return FAIL;
2809 }
2810
2811 static int
2812 validate_offset_imm (val, hwse)
2813 unsigned int val;
2814 int hwse;
2815 {
2816 if ((hwse && val > 255) || val > 4095)
2817 return FAIL;
2818 return val;
2819 }
2820
2821 \f
2822 #ifdef OBJ_ELF
2823 enum mstate
2824 {
2825 MAP_DATA,
2826 MAP_ARM,
2827 MAP_THUMB
2828 };
2829
2830 /* This code is to handle mapping symbols as defined in the ARM ELF spec.
2831 (This text is taken from version B-02 of the spec):
2832
2833 4.4.7 Mapping and tagging symbols
2834
2835 A section of an ARM ELF file can contain a mixture of ARM code,
2836 Thumb code, and data. There are inline transitions between code
2837 and data at literal pool boundaries. There can also be inline
2838 transitions between ARM code and Thumb code, for example in
2839 ARM-Thumb inter-working veneers. Linkers, machine-level
2840 debuggers, profiling tools, and disassembly tools need to map
2841 images accurately. For example, setting an ARM breakpoint on a
2842 Thumb location, or in a literal pool, can crash the program
2843 being debugged, ruining the debugging session.
2844
2845 ARM ELF entities are mapped (see section 4.4.7.1 below) and
2846 tagged (see section 4.4.7.2 below) using local symbols (with
2847 binding STB_LOCAL). To assist consumers, mapping and tagging
2848 symbols should be collated first in the symbol table, before
2849 other symbols with binding STB_LOCAL.
2850
2851 To allow properly collated mapping and tagging symbols to be
2852 skipped by consumers that have no interest in them, the first
2853 such symbol should have the name $m and its st_value field equal
2854 to the total number of mapping and tagging symbols (including
2855 the $m) in the symbol table.
2856
2857 4.4.7.1 Mapping symbols
2858
2859 $a Labels the first byte of a sequence of ARM instructions.
2860 Its type is STT_FUNC.
2861
2862 $d Labels the first byte of a sequence of data items.
2863 Its type is STT_OBJECT.
2864
2865 $t Labels the first byte of a sequence of Thumb instructions.
2866 Its type is STT_FUNC.
2867
2868 This list of mapping symbols may be extended in the future.
2869
2870 Section-relative mapping symbols
2871
2872 Mapping symbols defined in a section define a sequence of
2873 half-open address intervals that cover the address range of the
2874 section. Each interval starts at the address defined by a
2875 mapping symbol, and continues up to, but not including, the
2876 address defined by the next (in address order) mapping symbol or
2877 the end of the section. A corollary is that there must be a
2878 mapping symbol defined at the beginning of each section.
2879 Consumers can ignore the size of a section-relative mapping
2880 symbol. Producers can set it to 0.
2881
2882 Absolute mapping symbols
2883
2884 Because of the need to crystallize a Thumb address with the
2885 Thumb-bit set, absolute symbol of type STT_FUNC (symbols of type
2886 STT_FUNC defined in section SHN_ABS) need to be mapped with $a
2887 or $t.
2888
2889 The extent of a mapping symbol defined in SHN_ABS is [st_value,
2890 st_value + st_size), or [st_value, st_value + 1) if st_size = 0,
2891 where [x, y) denotes the half-open address range from x,
2892 inclusive, to y, exclusive.
2893
2894 In the absence of a mapping symbol, a consumer can interpret a
2895 function symbol with an odd value as the Thumb code address
2896 obtained by clearing the least significant bit of the
2897 value. This interpretation is deprecated, and it may not work in
2898 the future.
2899
2900 Note - the Tagging symbols ($b, $f, $p $m) have been dropped from
2901 the EABI (which is still under development), so they are not
2902 implemented here. */
2903
2904 static void
2905 mapping_state (enum mstate state)
2906 {
2907 static enum mstate mapstate = MAP_DATA;
2908 symbolS * symbolP;
2909 const char * symname;
2910 int type;
2911
2912 if (mapstate == state)
2913 /* The mapping symbol has already been emitted.
2914 There is nothing else to do. */
2915 return;
2916
2917 mapstate = state;
2918
2919 switch (state)
2920 {
2921 case MAP_DATA:
2922 symname = "$d";
2923 type = BSF_OBJECT;
2924 break;
2925 case MAP_ARM:
2926 symname = "$a";
2927 type = BSF_FUNCTION;
2928 break;
2929 case MAP_THUMB:
2930 symname = "$t";
2931 type = BSF_FUNCTION;
2932 break;
2933 default:
2934 abort ();
2935 }
2936
2937 symbolP = symbol_new (symname, now_seg, (valueT) frag_now_fix (), frag_now);
2938 symbol_table_insert (symbolP);
2939 symbol_get_bfdsym (symbolP)->flags |= type | BSF_LOCAL;
2940
2941 switch (state)
2942 {
2943 case MAP_ARM:
2944 THUMB_SET_FUNC (symbolP, 0);
2945 ARM_SET_THUMB (symbolP, 0);
2946 ARM_SET_INTERWORK (symbolP, support_interwork);
2947 break;
2948
2949 case MAP_THUMB:
2950 THUMB_SET_FUNC (symbolP, 1);
2951 ARM_SET_THUMB (symbolP, 1);
2952 ARM_SET_INTERWORK (symbolP, support_interwork);
2953 break;
2954
2955 case MAP_DATA:
2956 default:
2957 return;
2958 }
2959 }
2960
2961 /* When we change sections we need to issue a new mapping symbol. */
2962
2963 void
2964 arm_elf_change_section (void)
2965 {
2966 flagword flags;
2967
2968 if (!SEG_NORMAL (now_seg))
2969 return;
2970
2971 flags = bfd_get_section_flags (stdoutput, now_seg);
2972
2973 /* We can ignore sections that only contain debug info. */
2974 if ((flags & SEC_ALLOC) == 0)
2975 return;
2976
2977 if (flags & SEC_CODE)
2978 {
2979 if (thumb_mode)
2980 mapping_state (MAP_THUMB);
2981 else
2982 mapping_state (MAP_ARM);
2983 }
2984 else
2985 /* This section does not contain code. Therefore it must contain data. */
2986 mapping_state (MAP_DATA);
2987 }
2988 #else
2989 #define mapping_state(a)
2990 #endif /* OBJ_ELF */
2991 \f
2992
2993 static void
2994 s_req (a)
2995 int a ATTRIBUTE_UNUSED;
2996 {
2997 as_bad (_("invalid syntax for .req directive"));
2998 }
2999
3000 /* The .unreq directive deletes an alias which was previously defined
3001 by .req. For example:
3002
3003 my_alias .req r11
3004 .unreq my_alias */
3005
3006 static void
3007 s_unreq (int a ATTRIBUTE_UNUSED)
3008 {
3009 char *name;
3010 char saved_char;
3011
3012 skip_whitespace (input_line_pointer);
3013 name = input_line_pointer;
3014
3015 while (*input_line_pointer != 0
3016 && *input_line_pointer != ' '
3017 && *input_line_pointer != '\n')
3018 ++input_line_pointer;
3019
3020 saved_char = *input_line_pointer;
3021 *input_line_pointer = 0;
3022
3023 if (*name)
3024 {
3025 enum arm_reg_type req_type = arm_reg_parse_any (name);
3026
3027 if (req_type != REG_TYPE_MAX)
3028 {
3029 char *temp_name = name;
3030 int req_no = arm_reg_parse (&temp_name, all_reg_maps[req_type].htab);
3031
3032 if (req_no != FAIL)
3033 {
3034 struct reg_entry *req_entry;
3035
3036 /* Check to see if this alias is a builtin one. */
3037 req_entry = hash_delete (all_reg_maps[req_type].htab, name);
3038
3039 if (!req_entry)
3040 as_bad (_("unreq: missing hash entry for \"%s\""), name);
3041 else if (req_entry->builtin)
3042 /* FIXME: We are deleting a built in register alias which
3043 points to a const data structure, so we only need to
3044 free up the memory used by the key in the hash table.
3045 Unfortunately we have not recorded this value, so this
3046 is a memory leak. */
3047 /* FIXME: Should we issue a warning message ? */
3048 ;
3049 else
3050 {
3051 /* Deleting a user defined alias. We need to free the
3052 key and the value, but fortunately the key is the same
3053 as the value->name field. */
3054 free ((char *) req_entry->name);
3055 free (req_entry);
3056 }
3057 }
3058 else
3059 as_bad (_(".unreq: unrecognized symbol \"%s\""), name);
3060 }
3061 else
3062 as_bad (_(".unreq: unrecognized symbol \"%s\""), name);
3063 }
3064 else
3065 as_bad (_("invalid syntax for .unreq directive"));
3066
3067 *input_line_pointer = saved_char;
3068 demand_empty_rest_of_line ();
3069 }
3070
3071 static void
3072 s_bss (ignore)
3073 int ignore ATTRIBUTE_UNUSED;
3074 {
3075 /* We don't support putting frags in the BSS segment, we fake it by
3076 marking in_bss, then looking at s_skip for clues. */
3077 subseg_set (bss_section, 0);
3078 demand_empty_rest_of_line ();
3079 mapping_state (MAP_DATA);
3080 }
3081
3082 static void
3083 s_even (ignore)
3084 int ignore ATTRIBUTE_UNUSED;
3085 {
3086 /* Never make frag if expect extra pass. */
3087 if (!need_pass_2)
3088 frag_align (1, 0, 0);
3089
3090 record_alignment (now_seg, 1);
3091
3092 demand_empty_rest_of_line ();
3093 }
3094
3095 static void
3096 s_ltorg (ignored)
3097 int ignored ATTRIBUTE_UNUSED;
3098 {
3099 unsigned int entry;
3100 literal_pool * pool;
3101 char sym_name[20];
3102
3103 pool = find_literal_pool ();
3104 if (pool == NULL
3105 || pool->symbol == NULL
3106 || pool->next_free_entry == 0)
3107 return;
3108
3109 /* Align pool as you have word accesses.
3110 Only make a frag if we have to. */
3111 if (!need_pass_2)
3112 frag_align (2, 0, 0);
3113
3114 record_alignment (now_seg, 2);
3115
3116 sprintf (sym_name, "$$lit_\002%x", pool->id);
3117
3118 symbol_locate (pool->symbol, sym_name, now_seg,
3119 (valueT) frag_now_fix (), frag_now);
3120 symbol_table_insert (pool->symbol);
3121
3122 ARM_SET_THUMB (pool->symbol, thumb_mode);
3123
3124 #if defined OBJ_COFF || defined OBJ_ELF
3125 ARM_SET_INTERWORK (pool->symbol, support_interwork);
3126 #endif
3127
3128 for (entry = 0; entry < pool->next_free_entry; entry ++)
3129 /* First output the expression in the instruction to the pool. */
3130 emit_expr (&(pool->literals[entry]), 4); /* .word */
3131
3132 /* Mark the pool as empty. */
3133 pool->next_free_entry = 0;
3134 pool->symbol = NULL;
3135 }
3136
3137 /* Same as s_align_ptwo but align 0 => align 2. */
3138
3139 static void
3140 s_align (unused)
3141 int unused ATTRIBUTE_UNUSED;
3142 {
3143 register int temp;
3144 register long temp_fill;
3145 long max_alignment = 15;
3146
3147 temp = get_absolute_expression ();
3148 if (temp > max_alignment)
3149 as_bad (_("alignment too large: %d assumed"), temp = max_alignment);
3150 else if (temp < 0)
3151 {
3152 as_bad (_("alignment negative. 0 assumed."));
3153 temp = 0;
3154 }
3155
3156 if (*input_line_pointer == ',')
3157 {
3158 input_line_pointer++;
3159 temp_fill = get_absolute_expression ();
3160 }
3161 else
3162 temp_fill = 0;
3163
3164 if (!temp)
3165 temp = 2;
3166
3167 /* Only make a frag if we HAVE to. */
3168 if (temp && !need_pass_2)
3169 frag_align (temp, (int) temp_fill, 0);
3170 demand_empty_rest_of_line ();
3171
3172 record_alignment (now_seg, temp);
3173 }
3174
3175 static void
3176 s_force_thumb (ignore)
3177 int ignore ATTRIBUTE_UNUSED;
3178 {
3179 /* If we are not already in thumb mode go into it, EVEN if
3180 the target processor does not support thumb instructions.
3181 This is used by gcc/config/arm/lib1funcs.asm for example
3182 to compile interworking support functions even if the
3183 target processor should not support interworking. */
3184 if (! thumb_mode)
3185 {
3186 thumb_mode = 2;
3187
3188 record_alignment (now_seg, 1);
3189 }
3190
3191 demand_empty_rest_of_line ();
3192 }
3193
3194 static void
3195 s_thumb_func (ignore)
3196 int ignore ATTRIBUTE_UNUSED;
3197 {
3198 if (! thumb_mode)
3199 opcode_select (16);
3200
3201 /* The following label is the name/address of the start of a Thumb function.
3202 We need to know this for the interworking support. */
3203 label_is_thumb_function_name = TRUE;
3204
3205 demand_empty_rest_of_line ();
3206 }
3207
3208 /* Perform a .set directive, but also mark the alias as
3209 being a thumb function. */
3210
3211 static void
3212 s_thumb_set (equiv)
3213 int equiv;
3214 {
3215 /* XXX the following is a duplicate of the code for s_set() in read.c
3216 We cannot just call that code as we need to get at the symbol that
3217 is created. */
3218 register char * name;
3219 register char delim;
3220 register char * end_name;
3221 register symbolS * symbolP;
3222
3223 /* Especial apologies for the random logic:
3224 This just grew, and could be parsed much more simply!
3225 Dean - in haste. */
3226 name = input_line_pointer;
3227 delim = get_symbol_end ();
3228 end_name = input_line_pointer;
3229 *end_name = delim;
3230
3231 SKIP_WHITESPACE ();
3232
3233 if (*input_line_pointer != ',')
3234 {
3235 *end_name = 0;
3236 as_bad (_("expected comma after name \"%s\""), name);
3237 *end_name = delim;
3238 ignore_rest_of_line ();
3239 return;
3240 }
3241
3242 input_line_pointer++;
3243 *end_name = 0;
3244
3245 if (name[0] == '.' && name[1] == '\0')
3246 {
3247 /* XXX - this should not happen to .thumb_set. */
3248 abort ();
3249 }
3250
3251 if ((symbolP = symbol_find (name)) == NULL
3252 && (symbolP = md_undefined_symbol (name)) == NULL)
3253 {
3254 #ifndef NO_LISTING
3255 /* When doing symbol listings, play games with dummy fragments living
3256 outside the normal fragment chain to record the file and line info
3257 for this symbol. */
3258 if (listing & LISTING_SYMBOLS)
3259 {
3260 extern struct list_info_struct * listing_tail;
3261 fragS * dummy_frag = (fragS *) xmalloc (sizeof (fragS));
3262
3263 memset (dummy_frag, 0, sizeof (fragS));
3264 dummy_frag->fr_type = rs_fill;
3265 dummy_frag->line = listing_tail;
3266 symbolP = symbol_new (name, undefined_section, 0, dummy_frag);
3267 dummy_frag->fr_symbol = symbolP;
3268 }
3269 else
3270 #endif
3271 symbolP = symbol_new (name, undefined_section, 0, &zero_address_frag);
3272
3273 #ifdef OBJ_COFF
3274 /* "set" symbols are local unless otherwise specified. */
3275 SF_SET_LOCAL (symbolP);
3276 #endif /* OBJ_COFF */
3277 } /* Make a new symbol. */
3278
3279 symbol_table_insert (symbolP);
3280
3281 * end_name = delim;
3282
3283 if (equiv
3284 && S_IS_DEFINED (symbolP)
3285 && S_GET_SEGMENT (symbolP) != reg_section)
3286 as_bad (_("symbol `%s' already defined"), S_GET_NAME (symbolP));
3287
3288 pseudo_set (symbolP);
3289
3290 demand_empty_rest_of_line ();
3291
3292 /* XXX Now we come to the Thumb specific bit of code. */
3293
3294 THUMB_SET_FUNC (symbolP, 1);
3295 ARM_SET_THUMB (symbolP, 1);
3296 #if defined OBJ_ELF || defined OBJ_COFF
3297 ARM_SET_INTERWORK (symbolP, support_interwork);
3298 #endif
3299 }
3300
3301 static void
3302 opcode_select (width)
3303 int width;
3304 {
3305 switch (width)
3306 {
3307 case 16:
3308 if (! thumb_mode)
3309 {
3310 if (! (cpu_variant & ARM_EXT_V4T))
3311 as_bad (_("selected processor does not support THUMB opcodes"));
3312
3313 thumb_mode = 1;
3314 /* No need to force the alignment, since we will have been
3315 coming from ARM mode, which is word-aligned. */
3316 record_alignment (now_seg, 1);
3317 }
3318 mapping_state (MAP_THUMB);
3319 break;
3320
3321 case 32:
3322 if (thumb_mode)
3323 {
3324 if ((cpu_variant & ARM_ALL) == ARM_EXT_V4T)
3325 as_bad (_("selected processor does not support ARM opcodes"));
3326
3327 thumb_mode = 0;
3328
3329 if (!need_pass_2)
3330 frag_align (2, 0, 0);
3331
3332 record_alignment (now_seg, 1);
3333 }
3334 mapping_state (MAP_ARM);
3335 break;
3336
3337 default:
3338 as_bad (_("invalid instruction size selected (%d)"), width);
3339 }
3340 }
3341
3342 static void
3343 s_arm (ignore)
3344 int ignore ATTRIBUTE_UNUSED;
3345 {
3346 opcode_select (32);
3347 demand_empty_rest_of_line ();
3348 }
3349
3350 static void
3351 s_thumb (ignore)
3352 int ignore ATTRIBUTE_UNUSED;
3353 {
3354 opcode_select (16);
3355 demand_empty_rest_of_line ();
3356 }
3357
3358 static void
3359 s_code (unused)
3360 int unused ATTRIBUTE_UNUSED;
3361 {
3362 register int temp;
3363
3364 temp = get_absolute_expression ();
3365 switch (temp)
3366 {
3367 case 16:
3368 case 32:
3369 opcode_select (temp);
3370 break;
3371
3372 default:
3373 as_bad (_("invalid operand to .code directive (%d) (expecting 16 or 32)"), temp);
3374 }
3375 }
3376
3377 static void
3378 end_of_line (str)
3379 char *str;
3380 {
3381 skip_whitespace (str);
3382
3383 if (*str != '\0' && !inst.error)
3384 inst.error = _("garbage following instruction");
3385 }
3386
3387 static int
3388 skip_past_comma (str)
3389 char ** str;
3390 {
3391 char * p = * str, c;
3392 int comma = 0;
3393
3394 while ((c = *p) == ' ' || c == ',')
3395 {
3396 p++;
3397 if (c == ',' && comma++)
3398 return FAIL;
3399 }
3400
3401 if (c == '\0')
3402 return FAIL;
3403
3404 *str = p;
3405 return comma ? SUCCESS : FAIL;
3406 }
3407
3408 /* A standard register must be given at this point.
3409 SHIFT is the place to put it in inst.instruction.
3410 Restores input start point on error.
3411 Returns the reg#, or FAIL. */
3412
3413 static int
3414 reg_required_here (str, shift)
3415 char ** str;
3416 int shift;
3417 {
3418 static char buff [128]; /* XXX */
3419 int reg;
3420 char * start = * str;
3421
3422 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_RN].htab)) != FAIL)
3423 {
3424 if (shift >= 0)
3425 inst.instruction |= reg << shift;
3426 return reg;
3427 }
3428
3429 /* Restore the start point, we may have got a reg of the wrong class. */
3430 *str = start;
3431
3432 /* In the few cases where we might be able to accept something else
3433 this error can be overridden. */
3434 sprintf (buff, _("register expected, not '%.100s'"), start);
3435 inst.error = buff;
3436
3437 return FAIL;
3438 }
3439
3440 /* A Intel Wireless MMX technology register
3441 must be given at this point.
3442 Shift is the place to put it in inst.instruction.
3443 Restores input start point on err.
3444 Returns the reg#, or FAIL. */
3445
3446 static int
3447 wreg_required_here (str, shift, reg_type)
3448 char ** str;
3449 int shift;
3450 enum wreg_type reg_type;
3451 {
3452 static char buff [128];
3453 int reg;
3454 char * start = *str;
3455
3456 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_IWMMXT].htab)) != FAIL)
3457 {
3458 if (wr_register (reg)
3459 && (reg_type == IWMMXT_REG_WR || reg_type == IWMMXT_REG_WR_OR_WC))
3460 {
3461 if (shift >= 0)
3462 inst.instruction |= (reg ^ WR_PREFIX) << shift;
3463 return reg;
3464 }
3465 else if (wc_register (reg)
3466 && (reg_type == IWMMXT_REG_WC || reg_type == IWMMXT_REG_WR_OR_WC))
3467 {
3468 if (shift >= 0)
3469 inst.instruction |= (reg ^ WC_PREFIX) << shift;
3470 return reg;
3471 }
3472 else if ((wcg_register (reg) && reg_type == IWMMXT_REG_WCG))
3473 {
3474 if (shift >= 0)
3475 inst.instruction |= ((reg ^ WC_PREFIX) - 8) << shift;
3476 return reg;
3477 }
3478 }
3479
3480 /* Restore the start point, we may have got a reg of the wrong class. */
3481 *str = start;
3482
3483 /* In the few cases where we might be able to accept
3484 something else this error can be overridden. */
3485 sprintf (buff, _("Intel Wireless MMX technology register expected, not '%.100s'"), start);
3486 inst.error = buff;
3487
3488 return FAIL;
3489 }
3490
3491 static const struct asm_psr *
3492 arm_psr_parse (ccp)
3493 register char ** ccp;
3494 {
3495 char * start = * ccp;
3496 char c;
3497 char * p;
3498 const struct asm_psr * psr;
3499
3500 p = start;
3501
3502 /* Skip to the end of the next word in the input stream. */
3503 do
3504 {
3505 c = *p++;
3506 }
3507 while (ISALPHA (c) || c == '_');
3508
3509 /* Terminate the word. */
3510 *--p = 0;
3511
3512 /* CPSR's and SPSR's can now be lowercase. This is just a convenience
3513 feature for ease of use and backwards compatibility. */
3514 if (!strncmp (start, "cpsr", 4))
3515 strncpy (start, "CPSR", 4);
3516 else if (!strncmp (start, "spsr", 4))
3517 strncpy (start, "SPSR", 4);
3518
3519 /* Now locate the word in the psr hash table. */
3520 psr = (const struct asm_psr *) hash_find (arm_psr_hsh, start);
3521
3522 /* Restore the input stream. */
3523 *p = c;
3524
3525 /* If we found a valid match, advance the
3526 stream pointer past the end of the word. */
3527 *ccp = p;
3528
3529 return psr;
3530 }
3531
3532 /* Parse the input looking for a PSR flag. */
3533
3534 static int
3535 psr_required_here (str)
3536 char ** str;
3537 {
3538 char * start = * str;
3539 const struct asm_psr * psr;
3540
3541 psr = arm_psr_parse (str);
3542
3543 if (psr)
3544 {
3545 /* If this is the SPSR that is being modified, set the R bit. */
3546 if (! psr->cpsr)
3547 inst.instruction |= SPSR_BIT;
3548
3549 /* Set the psr flags in the MSR instruction. */
3550 inst.instruction |= psr->field << PSR_SHIFT;
3551
3552 return SUCCESS;
3553 }
3554
3555 /* In the few cases where we might be able to accept
3556 something else this error can be overridden. */
3557 inst.error = _("flag for {c}psr instruction expected");
3558
3559 /* Restore the start point. */
3560 *str = start;
3561 return FAIL;
3562 }
3563
3564 static int
3565 co_proc_number (str)
3566 char **str;
3567 {
3568 int processor, pchar;
3569 char *start;
3570
3571 skip_whitespace (*str);
3572 start = *str;
3573
3574 /* The data sheet seems to imply that just a number on its own is valid
3575 here, but the RISC iX assembler seems to accept a prefix 'p'. We will
3576 accept either. */
3577 if ((processor = arm_reg_parse (str, all_reg_maps[REG_TYPE_CP].htab))
3578 == FAIL)
3579 {
3580 *str = start;
3581
3582 pchar = *(*str)++;
3583 if (pchar >= '0' && pchar <= '9')
3584 {
3585 processor = pchar - '0';
3586 if (**str >= '0' && **str <= '9')
3587 {
3588 processor = processor * 10 + *(*str)++ - '0';
3589 if (processor > 15)
3590 {
3591 inst.error = _("illegal co-processor number");
3592 return FAIL;
3593 }
3594 }
3595 }
3596 else
3597 {
3598 inst.error = _("bad or missing co-processor number");
3599 return FAIL;
3600 }
3601 }
3602
3603 inst.instruction |= processor << 8;
3604 return SUCCESS;
3605 }
3606
3607 static int
3608 cp_opc_expr (str, where, length)
3609 char ** str;
3610 int where;
3611 int length;
3612 {
3613 expressionS expr;
3614
3615 skip_whitespace (* str);
3616
3617 memset (&expr, '\0', sizeof (expr));
3618
3619 if (my_get_expression (&expr, str))
3620 return FAIL;
3621 if (expr.X_op != O_constant)
3622 {
3623 inst.error = _("bad or missing expression");
3624 return FAIL;
3625 }
3626
3627 if ((expr.X_add_number & ((1 << length) - 1)) != expr.X_add_number)
3628 {
3629 inst.error = _("immediate co-processor expression too large");
3630 return FAIL;
3631 }
3632
3633 inst.instruction |= expr.X_add_number << where;
3634 return SUCCESS;
3635 }
3636
3637 static int
3638 cp_reg_required_here (str, where)
3639 char ** str;
3640 int where;
3641 {
3642 int reg;
3643 char * start = *str;
3644
3645 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_CN].htab)) != FAIL)
3646 {
3647 inst.instruction |= reg << where;
3648 return reg;
3649 }
3650
3651 /* In the few cases where we might be able to accept something else
3652 this error can be overridden. */
3653 inst.error = _("co-processor register expected");
3654
3655 /* Restore the start point. */
3656 *str = start;
3657 return FAIL;
3658 }
3659
3660 static int
3661 fp_reg_required_here (str, where)
3662 char ** str;
3663 int where;
3664 {
3665 int reg;
3666 char * start = * str;
3667
3668 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_FN].htab)) != FAIL)
3669 {
3670 inst.instruction |= reg << where;
3671 return reg;
3672 }
3673
3674 /* In the few cases where we might be able to accept something else
3675 this error can be overridden. */
3676 inst.error = _("floating point register expected");
3677
3678 /* Restore the start point. */
3679 *str = start;
3680 return FAIL;
3681 }
3682
3683 static int
3684 cp_address_offset (str)
3685 char ** str;
3686 {
3687 int offset;
3688
3689 skip_whitespace (* str);
3690
3691 if (! is_immediate_prefix (**str))
3692 {
3693 inst.error = _("immediate expression expected");
3694 return FAIL;
3695 }
3696
3697 (*str)++;
3698
3699 if (my_get_expression (& inst.reloc.exp, str))
3700 return FAIL;
3701
3702 if (inst.reloc.exp.X_op == O_constant)
3703 {
3704 offset = inst.reloc.exp.X_add_number;
3705
3706 if (offset & 3)
3707 {
3708 inst.error = _("co-processor address must be word aligned");
3709 return FAIL;
3710 }
3711
3712 if (offset > 1023 || offset < -1023)
3713 {
3714 inst.error = _("offset too large");
3715 return FAIL;
3716 }
3717
3718 if (offset >= 0)
3719 inst.instruction |= INDEX_UP;
3720 else
3721 offset = -offset;
3722
3723 inst.instruction |= offset >> 2;
3724 }
3725 else
3726 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
3727
3728 return SUCCESS;
3729 }
3730
3731 static int
3732 cp_address_required_here (str, wb_ok)
3733 char ** str;
3734 int wb_ok;
3735 {
3736 char * p = * str;
3737 int pre_inc = 0;
3738 int write_back = 0;
3739
3740 if (*p == '[')
3741 {
3742 int reg;
3743
3744 p++;
3745 skip_whitespace (p);
3746
3747 if ((reg = reg_required_here (& p, 16)) == FAIL)
3748 return FAIL;
3749
3750 skip_whitespace (p);
3751
3752 if (*p == ']')
3753 {
3754 p++;
3755
3756 skip_whitespace (p);
3757
3758 if (*p == '\0')
3759 {
3760 /* As an extension to the official ARM syntax we allow:
3761
3762 [Rn]
3763
3764 as a short hand for:
3765
3766 [Rn,#0] */
3767 inst.instruction |= PRE_INDEX | INDEX_UP;
3768 *str = p;
3769 return SUCCESS;
3770 }
3771
3772 if (skip_past_comma (& p) == FAIL)
3773 {
3774 inst.error = _("comma expected after closing square bracket");
3775 return FAIL;
3776 }
3777
3778 skip_whitespace (p);
3779
3780 if (*p == '#')
3781 {
3782 if (wb_ok)
3783 {
3784 /* [Rn], #expr */
3785 write_back = WRITE_BACK;
3786
3787 if (reg == REG_PC)
3788 {
3789 inst.error = _("pc may not be used in post-increment");
3790 return FAIL;
3791 }
3792
3793 if (cp_address_offset (& p) == FAIL)
3794 return FAIL;
3795 }
3796 else
3797 pre_inc = PRE_INDEX | INDEX_UP;
3798 }
3799 else if (*p == '{')
3800 {
3801 int option;
3802
3803 /* [Rn], {<expr>} */
3804 p++;
3805
3806 skip_whitespace (p);
3807
3808 if (my_get_expression (& inst.reloc.exp, & p))
3809 return FAIL;
3810
3811 if (inst.reloc.exp.X_op == O_constant)
3812 {
3813 option = inst.reloc.exp.X_add_number;
3814
3815 if (option > 255 || option < 0)
3816 {
3817 inst.error = _("'option' field too large");
3818 return FAIL;
3819 }
3820
3821 skip_whitespace (p);
3822
3823 if (*p != '}')
3824 {
3825 inst.error = _("'}' expected at end of 'option' field");
3826 return FAIL;
3827 }
3828 else
3829 {
3830 p++;
3831 inst.instruction |= option;
3832 inst.instruction |= INDEX_UP;
3833 }
3834 }
3835 else
3836 {
3837 inst.error = _("non-constant expressions for 'option' field not supported");
3838 return FAIL;
3839 }
3840 }
3841 else
3842 {
3843 inst.error = _("# or { expected after comma");
3844 return FAIL;
3845 }
3846 }
3847 else
3848 {
3849 /* '['Rn, #expr']'[!] */
3850
3851 if (skip_past_comma (& p) == FAIL)
3852 {
3853 inst.error = _("pre-indexed expression expected");
3854 return FAIL;
3855 }
3856
3857 pre_inc = PRE_INDEX;
3858
3859 if (cp_address_offset (& p) == FAIL)
3860 return FAIL;
3861
3862 skip_whitespace (p);
3863
3864 if (*p++ != ']')
3865 {
3866 inst.error = _("missing ]");
3867 return FAIL;
3868 }
3869
3870 skip_whitespace (p);
3871
3872 if (wb_ok && *p == '!')
3873 {
3874 if (reg == REG_PC)
3875 {
3876 inst.error = _("pc may not be used with write-back");
3877 return FAIL;
3878 }
3879
3880 p++;
3881 write_back = WRITE_BACK;
3882 }
3883 }
3884 }
3885 else
3886 {
3887 if (my_get_expression (&inst.reloc.exp, &p))
3888 return FAIL;
3889
3890 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
3891 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
3892 inst.reloc.pc_rel = 1;
3893 inst.instruction |= (REG_PC << 16);
3894 pre_inc = PRE_INDEX;
3895 }
3896
3897 inst.instruction |= write_back | pre_inc;
3898 *str = p;
3899 return SUCCESS;
3900 }
3901
3902 static int
3903 cp_byte_address_offset (str)
3904 char ** str;
3905 {
3906 int offset;
3907
3908 skip_whitespace (* str);
3909
3910 if (! is_immediate_prefix (**str))
3911 {
3912 inst.error = _("immediate expression expected");
3913 return FAIL;
3914 }
3915
3916 (*str)++;
3917
3918 if (my_get_expression (& inst.reloc.exp, str))
3919 return FAIL;
3920
3921 if (inst.reloc.exp.X_op == O_constant)
3922 {
3923 offset = inst.reloc.exp.X_add_number;
3924
3925 if (offset > 255 || offset < -255)
3926 {
3927 inst.error = _("offset too large");
3928 return FAIL;
3929 }
3930
3931 if (offset >= 0)
3932 inst.instruction |= INDEX_UP;
3933 else
3934 offset = -offset;
3935
3936 inst.instruction |= offset;
3937 }
3938 else
3939 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM_S2;
3940
3941 return SUCCESS;
3942 }
3943
3944 static int
3945 cp_byte_address_required_here (str)
3946 char ** str;
3947 {
3948 char * p = * str;
3949 int pre_inc = 0;
3950 int write_back = 0;
3951
3952 if (*p == '[')
3953 {
3954 int reg;
3955
3956 p++;
3957 skip_whitespace (p);
3958
3959 if ((reg = reg_required_here (& p, 16)) == FAIL)
3960 return FAIL;
3961
3962 skip_whitespace (p);
3963
3964 if (*p == ']')
3965 {
3966 p++;
3967
3968 if (skip_past_comma (& p) == SUCCESS)
3969 {
3970 /* [Rn], #expr */
3971 write_back = WRITE_BACK;
3972
3973 if (reg == REG_PC)
3974 {
3975 inst.error = _("pc may not be used in post-increment");
3976 return FAIL;
3977 }
3978
3979 if (cp_byte_address_offset (& p) == FAIL)
3980 return FAIL;
3981 }
3982 else
3983 pre_inc = PRE_INDEX | INDEX_UP;
3984 }
3985 else
3986 {
3987 /* '['Rn, #expr']'[!] */
3988
3989 if (skip_past_comma (& p) == FAIL)
3990 {
3991 inst.error = _("pre-indexed expression expected");
3992 return FAIL;
3993 }
3994
3995 pre_inc = PRE_INDEX;
3996
3997 if (cp_byte_address_offset (& p) == FAIL)
3998 return FAIL;
3999
4000 skip_whitespace (p);
4001
4002 if (*p++ != ']')
4003 {
4004 inst.error = _("missing ]");
4005 return FAIL;
4006 }
4007
4008 skip_whitespace (p);
4009
4010 if (*p == '!')
4011 {
4012 if (reg == REG_PC)
4013 {
4014 inst.error = _("pc may not be used with write-back");
4015 return FAIL;
4016 }
4017
4018 p++;
4019 write_back = WRITE_BACK;
4020 }
4021 }
4022 }
4023 else
4024 {
4025 if (my_get_expression (&inst.reloc.exp, &p))
4026 return FAIL;
4027
4028 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM_S2;
4029 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
4030 inst.reloc.pc_rel = 1;
4031 inst.instruction |= (REG_PC << 16);
4032 pre_inc = PRE_INDEX;
4033 }
4034
4035 inst.instruction |= write_back | pre_inc;
4036 *str = p;
4037 return SUCCESS;
4038 }
4039
4040 static void
4041 do_empty (str)
4042 char * str;
4043 {
4044 /* Do nothing really. */
4045 end_of_line (str);
4046 }
4047
4048 static void
4049 do_mrs (str)
4050 char *str;
4051 {
4052 int skip = 0;
4053
4054 /* Only one syntax. */
4055 skip_whitespace (str);
4056
4057 if (reg_required_here (&str, 12) == FAIL)
4058 {
4059 inst.error = BAD_ARGS;
4060 return;
4061 }
4062
4063 if (skip_past_comma (&str) == FAIL)
4064 {
4065 inst.error = _("comma expected after register name");
4066 return;
4067 }
4068
4069 skip_whitespace (str);
4070
4071 if ( strcmp (str, "CPSR") == 0
4072 || strcmp (str, "SPSR") == 0
4073 /* Lower case versions for backwards compatibility. */
4074 || strcmp (str, "cpsr") == 0
4075 || strcmp (str, "spsr") == 0)
4076 skip = 4;
4077
4078 /* This is for backwards compatibility with older toolchains. */
4079 else if ( strcmp (str, "cpsr_all") == 0
4080 || strcmp (str, "spsr_all") == 0)
4081 skip = 8;
4082 else
4083 {
4084 inst.error = _("CPSR or SPSR expected");
4085 return;
4086 }
4087
4088 if (* str == 's' || * str == 'S')
4089 inst.instruction |= SPSR_BIT;
4090 str += skip;
4091
4092 end_of_line (str);
4093 }
4094
4095 /* Two possible forms:
4096 "{C|S}PSR_<field>, Rm",
4097 "{C|S}PSR_f, #expression". */
4098
4099 static void
4100 do_msr (str)
4101 char * str;
4102 {
4103 skip_whitespace (str);
4104
4105 if (psr_required_here (& str) == FAIL)
4106 return;
4107
4108 if (skip_past_comma (& str) == FAIL)
4109 {
4110 inst.error = _("comma missing after psr flags");
4111 return;
4112 }
4113
4114 skip_whitespace (str);
4115
4116 if (reg_required_here (& str, 0) != FAIL)
4117 {
4118 inst.error = NULL;
4119 end_of_line (str);
4120 return;
4121 }
4122
4123 if (! is_immediate_prefix (* str))
4124 {
4125 inst.error =
4126 _("only a register or immediate value can follow a psr flag");
4127 return;
4128 }
4129
4130 str ++;
4131 inst.error = NULL;
4132
4133 if (my_get_expression (& inst.reloc.exp, & str))
4134 {
4135 inst.error =
4136 _("only a register or immediate value can follow a psr flag");
4137 return;
4138 }
4139
4140 #if 0 /* The first edition of the ARM architecture manual stated that
4141 writing anything other than the flags with an immediate operation
4142 had UNPREDICTABLE effects. This constraint was removed in the
4143 second edition of the specification. */
4144 if ((cpu_variant & ARM_EXT_V5) != ARM_EXT_V5
4145 && inst.instruction & ((PSR_c | PSR_x | PSR_s) << PSR_SHIFT))
4146 {
4147 inst.error = _("immediate value cannot be used to set this field");
4148 return;
4149 }
4150 #endif
4151
4152 inst.instruction |= INST_IMMEDIATE;
4153
4154 if (inst.reloc.exp.X_add_symbol)
4155 {
4156 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
4157 inst.reloc.pc_rel = 0;
4158 }
4159 else
4160 {
4161 unsigned value = validate_immediate (inst.reloc.exp.X_add_number);
4162
4163 if (value == (unsigned) FAIL)
4164 {
4165 inst.error = _("invalid constant");
4166 return;
4167 }
4168
4169 inst.instruction |= value;
4170 }
4171
4172 inst.error = NULL;
4173 end_of_line (str);
4174 }
4175
4176 /* Long Multiply Parser
4177 UMULL RdLo, RdHi, Rm, Rs
4178 SMULL RdLo, RdHi, Rm, Rs
4179 UMLAL RdLo, RdHi, Rm, Rs
4180 SMLAL RdLo, RdHi, Rm, Rs. */
4181
4182 static void
4183 do_mull (str)
4184 char * str;
4185 {
4186 int rdlo, rdhi, rm, rs;
4187
4188 /* Only one format "rdlo, rdhi, rm, rs". */
4189 skip_whitespace (str);
4190
4191 if ((rdlo = reg_required_here (&str, 12)) == FAIL)
4192 {
4193 inst.error = BAD_ARGS;
4194 return;
4195 }
4196
4197 if (skip_past_comma (&str) == FAIL
4198 || (rdhi = reg_required_here (&str, 16)) == FAIL)
4199 {
4200 inst.error = BAD_ARGS;
4201 return;
4202 }
4203
4204 if (skip_past_comma (&str) == FAIL
4205 || (rm = reg_required_here (&str, 0)) == FAIL)
4206 {
4207 inst.error = BAD_ARGS;
4208 return;
4209 }
4210
4211 /* rdhi, rdlo and rm must all be different. */
4212 if (rdlo == rdhi || rdlo == rm || rdhi == rm)
4213 as_tsktsk (_("rdhi, rdlo and rm must all be different"));
4214
4215 if (skip_past_comma (&str) == FAIL
4216 || (rs = reg_required_here (&str, 8)) == FAIL)
4217 {
4218 inst.error = BAD_ARGS;
4219 return;
4220 }
4221
4222 if (rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC)
4223 {
4224 inst.error = BAD_PC;
4225 return;
4226 }
4227
4228 end_of_line (str);
4229 }
4230
4231 static void
4232 do_mul (str)
4233 char * str;
4234 {
4235 int rd, rm;
4236
4237 /* Only one format "rd, rm, rs". */
4238 skip_whitespace (str);
4239
4240 if ((rd = reg_required_here (&str, 16)) == FAIL)
4241 {
4242 inst.error = BAD_ARGS;
4243 return;
4244 }
4245
4246 if (rd == REG_PC)
4247 {
4248 inst.error = BAD_PC;
4249 return;
4250 }
4251
4252 if (skip_past_comma (&str) == FAIL
4253 || (rm = reg_required_here (&str, 0)) == FAIL)
4254 {
4255 inst.error = BAD_ARGS;
4256 return;
4257 }
4258
4259 if (rm == REG_PC)
4260 {
4261 inst.error = BAD_PC;
4262 return;
4263 }
4264
4265 if (rm == rd)
4266 as_tsktsk (_("rd and rm should be different in mul"));
4267
4268 if (skip_past_comma (&str) == FAIL
4269 || (rm = reg_required_here (&str, 8)) == FAIL)
4270 {
4271 inst.error = BAD_ARGS;
4272 return;
4273 }
4274
4275 if (rm == REG_PC)
4276 {
4277 inst.error = BAD_PC;
4278 return;
4279 }
4280
4281 end_of_line (str);
4282 }
4283
4284 static void
4285 do_mla (str)
4286 char * str;
4287 {
4288 int rd, rm;
4289
4290 /* Only one format "rd, rm, rs, rn". */
4291 skip_whitespace (str);
4292
4293 if ((rd = reg_required_here (&str, 16)) == FAIL)
4294 {
4295 inst.error = BAD_ARGS;
4296 return;
4297 }
4298
4299 if (rd == REG_PC)
4300 {
4301 inst.error = BAD_PC;
4302 return;
4303 }
4304
4305 if (skip_past_comma (&str) == FAIL
4306 || (rm = reg_required_here (&str, 0)) == FAIL)
4307 {
4308 inst.error = BAD_ARGS;
4309 return;
4310 }
4311
4312 if (rm == REG_PC)
4313 {
4314 inst.error = BAD_PC;
4315 return;
4316 }
4317
4318 if (rm == rd)
4319 as_tsktsk (_("rd and rm should be different in mla"));
4320
4321 if (skip_past_comma (&str) == FAIL
4322 || (rd = reg_required_here (&str, 8)) == FAIL
4323 || skip_past_comma (&str) == FAIL
4324 || (rm = reg_required_here (&str, 12)) == FAIL)
4325 {
4326 inst.error = BAD_ARGS;
4327 return;
4328 }
4329
4330 if (rd == REG_PC || rm == REG_PC)
4331 {
4332 inst.error = BAD_PC;
4333 return;
4334 }
4335
4336 end_of_line (str);
4337 }
4338
4339 /* Expects *str -> the characters "acc0", possibly with leading blanks.
4340 Advances *str to the next non-alphanumeric.
4341 Returns 0, or else FAIL (in which case sets inst.error).
4342
4343 (In a future XScale, there may be accumulators other than zero.
4344 At that time this routine and its callers can be upgraded to suit.) */
4345
4346 static int
4347 accum0_required_here (str)
4348 char ** str;
4349 {
4350 static char buff [128]; /* Note the address is taken. Hence, static. */
4351 char * p = * str;
4352 char c;
4353 int result = 0; /* The accum number. */
4354
4355 skip_whitespace (p);
4356
4357 *str = p; /* Advance caller's string pointer too. */
4358 c = *p++;
4359 while (ISALNUM (c))
4360 c = *p++;
4361
4362 *--p = 0; /* Aap nul into input buffer at non-alnum. */
4363
4364 if (! ( streq (*str, "acc0") || streq (*str, "ACC0")))
4365 {
4366 sprintf (buff, _("acc0 expected, not '%.100s'"), *str);
4367 inst.error = buff;
4368 result = FAIL;
4369 }
4370
4371 *p = c; /* Unzap. */
4372 *str = p; /* Caller's string pointer to after match. */
4373 return result;
4374 }
4375
4376 /* Expects **str -> after a comma. May be leading blanks.
4377 Advances *str, recognizing a load mode, and setting inst.instruction.
4378 Returns rn, or else FAIL (in which case may set inst.error
4379 and not advance str)
4380
4381 Note: doesn't know Rd, so no err checks that require such knowledge. */
4382
4383 static int
4384 ld_mode_required_here (string)
4385 char ** string;
4386 {
4387 char * str = * string;
4388 int rn;
4389 int pre_inc = 0;
4390
4391 skip_whitespace (str);
4392
4393 if (* str == '[')
4394 {
4395 str++;
4396
4397 skip_whitespace (str);
4398
4399 if ((rn = reg_required_here (& str, 16)) == FAIL)
4400 return FAIL;
4401
4402 skip_whitespace (str);
4403
4404 if (* str == ']')
4405 {
4406 str ++;
4407
4408 if (skip_past_comma (& str) == SUCCESS)
4409 {
4410 /* [Rn],... (post inc) */
4411 if (ldst_extend_v4 (&str) == FAIL)
4412 return FAIL;
4413 }
4414 else /* [Rn] */
4415 {
4416 skip_whitespace (str);
4417
4418 if (* str == '!')
4419 {
4420 str ++;
4421 inst.instruction |= WRITE_BACK;
4422 }
4423
4424 inst.instruction |= INDEX_UP | HWOFFSET_IMM;
4425 pre_inc = 1;
4426 }
4427 }
4428 else /* [Rn,...] */
4429 {
4430 if (skip_past_comma (& str) == FAIL)
4431 {
4432 inst.error = _("pre-indexed expression expected");
4433 return FAIL;
4434 }
4435
4436 pre_inc = 1;
4437
4438 if (ldst_extend_v4 (&str) == FAIL)
4439 return FAIL;
4440
4441 skip_whitespace (str);
4442
4443 if (* str ++ != ']')
4444 {
4445 inst.error = _("missing ]");
4446 return FAIL;
4447 }
4448
4449 skip_whitespace (str);
4450
4451 if (* str == '!')
4452 {
4453 str ++;
4454 inst.instruction |= WRITE_BACK;
4455 }
4456 }
4457 }
4458 else if (* str == '=') /* ldr's "r,=label" syntax */
4459 /* We should never reach here, because <text> = <expression> is
4460 caught gas/read.c read_a_source_file() as a .set operation. */
4461 return FAIL;
4462 else /* PC +- 8 bit immediate offset. */
4463 {
4464 if (my_get_expression (& inst.reloc.exp, & str))
4465 return FAIL;
4466
4467 inst.instruction |= HWOFFSET_IMM; /* The I bit. */
4468 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
4469 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
4470 inst.reloc.pc_rel = 1;
4471 inst.instruction |= (REG_PC << 16);
4472
4473 rn = REG_PC;
4474 pre_inc = 1;
4475 }
4476
4477 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
4478 * string = str;
4479
4480 return rn;
4481 }
4482
4483 /* ARM V5E (El Segundo) signed-multiply-accumulate (argument parse)
4484 SMLAxy{cond} Rd,Rm,Rs,Rn
4485 SMLAWy{cond} Rd,Rm,Rs,Rn
4486 Error if any register is R15. */
4487
4488 static void
4489 do_smla (str)
4490 char * str;
4491 {
4492 int rd, rm, rs, rn;
4493
4494 skip_whitespace (str);
4495
4496 if ((rd = reg_required_here (& str, 16)) == FAIL
4497 || skip_past_comma (& str) == FAIL
4498 || (rm = reg_required_here (& str, 0)) == FAIL
4499 || skip_past_comma (& str) == FAIL
4500 || (rs = reg_required_here (& str, 8)) == FAIL
4501 || skip_past_comma (& str) == FAIL
4502 || (rn = reg_required_here (& str, 12)) == FAIL)
4503 inst.error = BAD_ARGS;
4504
4505 else if (rd == REG_PC || rm == REG_PC || rs == REG_PC || rn == REG_PC)
4506 inst.error = BAD_PC;
4507
4508 else
4509 end_of_line (str);
4510 }
4511
4512 /* ARM V5E (El Segundo) signed-multiply-accumulate-long (argument parse)
4513 SMLALxy{cond} Rdlo,Rdhi,Rm,Rs
4514 Error if any register is R15.
4515 Warning if Rdlo == Rdhi. */
4516
4517 static void
4518 do_smlal (str)
4519 char * str;
4520 {
4521 int rdlo, rdhi, rm, rs;
4522
4523 skip_whitespace (str);
4524
4525 if ((rdlo = reg_required_here (& str, 12)) == FAIL
4526 || skip_past_comma (& str) == FAIL
4527 || (rdhi = reg_required_here (& str, 16)) == FAIL
4528 || skip_past_comma (& str) == FAIL
4529 || (rm = reg_required_here (& str, 0)) == FAIL
4530 || skip_past_comma (& str) == FAIL
4531 || (rs = reg_required_here (& str, 8)) == FAIL)
4532 {
4533 inst.error = BAD_ARGS;
4534 return;
4535 }
4536
4537 if (rdlo == REG_PC || rdhi == REG_PC || rm == REG_PC || rs == REG_PC)
4538 {
4539 inst.error = BAD_PC;
4540 return;
4541 }
4542
4543 if (rdlo == rdhi)
4544 as_tsktsk (_("rdhi and rdlo must be different"));
4545
4546 end_of_line (str);
4547 }
4548
4549 /* ARM V5E (El Segundo) signed-multiply (argument parse)
4550 SMULxy{cond} Rd,Rm,Rs
4551 Error if any register is R15. */
4552
4553 static void
4554 do_smul (str)
4555 char * str;
4556 {
4557 int rd, rm, rs;
4558
4559 skip_whitespace (str);
4560
4561 if ((rd = reg_required_here (& str, 16)) == FAIL
4562 || skip_past_comma (& str) == FAIL
4563 || (rm = reg_required_here (& str, 0)) == FAIL
4564 || skip_past_comma (& str) == FAIL
4565 || (rs = reg_required_here (& str, 8)) == FAIL)
4566 inst.error = BAD_ARGS;
4567
4568 else if (rd == REG_PC || rm == REG_PC || rs == REG_PC)
4569 inst.error = BAD_PC;
4570
4571 else
4572 end_of_line (str);
4573 }
4574
4575 /* ARM V5E (El Segundo) saturating-add/subtract (argument parse)
4576 Q[D]{ADD,SUB}{cond} Rd,Rm,Rn
4577 Error if any register is R15. */
4578
4579 static void
4580 do_qadd (str)
4581 char * str;
4582 {
4583 int rd, rm, rn;
4584
4585 skip_whitespace (str);
4586
4587 if ((rd = reg_required_here (& str, 12)) == FAIL
4588 || skip_past_comma (& str) == FAIL
4589 || (rm = reg_required_here (& str, 0)) == FAIL
4590 || skip_past_comma (& str) == FAIL
4591 || (rn = reg_required_here (& str, 16)) == FAIL)
4592 inst.error = BAD_ARGS;
4593
4594 else if (rd == REG_PC || rm == REG_PC || rn == REG_PC)
4595 inst.error = BAD_PC;
4596
4597 else
4598 end_of_line (str);
4599 }
4600
4601 /* ARM V5E (el Segundo)
4602 MCRRcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
4603 MRRCcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
4604
4605 These are equivalent to the XScale instructions MAR and MRA,
4606 respectively, when coproc == 0, opcode == 0, and CRm == 0.
4607
4608 Result unpredicatable if Rd or Rn is R15. */
4609
4610 static void
4611 do_co_reg2c (str)
4612 char * str;
4613 {
4614 int rd, rn;
4615
4616 skip_whitespace (str);
4617
4618 if (co_proc_number (& str) == FAIL)
4619 {
4620 if (!inst.error)
4621 inst.error = BAD_ARGS;
4622 return;
4623 }
4624
4625 if (skip_past_comma (& str) == FAIL
4626 || cp_opc_expr (& str, 4, 4) == FAIL)
4627 {
4628 if (!inst.error)
4629 inst.error = BAD_ARGS;
4630 return;
4631 }
4632
4633 if (skip_past_comma (& str) == FAIL
4634 || (rd = reg_required_here (& str, 12)) == FAIL)
4635 {
4636 if (!inst.error)
4637 inst.error = BAD_ARGS;
4638 return;
4639 }
4640
4641 if (skip_past_comma (& str) == FAIL
4642 || (rn = reg_required_here (& str, 16)) == FAIL)
4643 {
4644 if (!inst.error)
4645 inst.error = BAD_ARGS;
4646 return;
4647 }
4648
4649 /* Unpredictable result if rd or rn is R15. */
4650 if (rd == REG_PC || rn == REG_PC)
4651 as_tsktsk
4652 (_("Warning: instruction unpredictable when using r15"));
4653
4654 if (skip_past_comma (& str) == FAIL
4655 || cp_reg_required_here (& str, 0) == FAIL)
4656 {
4657 if (!inst.error)
4658 inst.error = BAD_ARGS;
4659 return;
4660 }
4661
4662 end_of_line (str);
4663 }
4664
4665 /* ARM V5 count-leading-zeroes instruction (argument parse)
4666 CLZ{<cond>} <Rd>, <Rm>
4667 Condition defaults to COND_ALWAYS.
4668 Error if Rd or Rm are R15. */
4669
4670 static void
4671 do_clz (str)
4672 char * str;
4673 {
4674 int rd, rm;
4675
4676 skip_whitespace (str);
4677
4678 if (((rd = reg_required_here (& str, 12)) == FAIL)
4679 || (skip_past_comma (& str) == FAIL)
4680 || ((rm = reg_required_here (& str, 0)) == FAIL))
4681 inst.error = BAD_ARGS;
4682
4683 else if (rd == REG_PC || rm == REG_PC )
4684 inst.error = BAD_PC;
4685
4686 else
4687 end_of_line (str);
4688 }
4689
4690 /* ARM V5 (argument parse)
4691 LDC2{L} <coproc>, <CRd>, <addressing mode>
4692 STC2{L} <coproc>, <CRd>, <addressing mode>
4693 Instruction is not conditional, and has 0xf in the condition field.
4694 Otherwise, it's the same as LDC/STC. */
4695
4696 static void
4697 do_lstc2 (str)
4698 char * str;
4699 {
4700 skip_whitespace (str);
4701
4702 if (co_proc_number (& str) == FAIL)
4703 {
4704 if (!inst.error)
4705 inst.error = BAD_ARGS;
4706 }
4707 else if (skip_past_comma (& str) == FAIL
4708 || cp_reg_required_here (& str, 12) == FAIL)
4709 {
4710 if (!inst.error)
4711 inst.error = BAD_ARGS;
4712 }
4713 else if (skip_past_comma (& str) == FAIL
4714 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
4715 {
4716 if (! inst.error)
4717 inst.error = BAD_ARGS;
4718 }
4719 else
4720 end_of_line (str);
4721 }
4722
4723 /* ARM V5 (argument parse)
4724 CDP2 <coproc>, <opcode_1>, <CRd>, <CRn>, <CRm>, <opcode_2>
4725 Instruction is not conditional, and has 0xf in the condition field.
4726 Otherwise, it's the same as CDP. */
4727
4728 static void
4729 do_cdp2 (str)
4730 char * str;
4731 {
4732 skip_whitespace (str);
4733
4734 if (co_proc_number (& str) == FAIL)
4735 {
4736 if (!inst.error)
4737 inst.error = BAD_ARGS;
4738 return;
4739 }
4740
4741 if (skip_past_comma (& str) == FAIL
4742 || cp_opc_expr (& str, 20,4) == FAIL)
4743 {
4744 if (!inst.error)
4745 inst.error = BAD_ARGS;
4746 return;
4747 }
4748
4749 if (skip_past_comma (& str) == FAIL
4750 || cp_reg_required_here (& str, 12) == FAIL)
4751 {
4752 if (!inst.error)
4753 inst.error = BAD_ARGS;
4754 return;
4755 }
4756
4757 if (skip_past_comma (& str) == FAIL
4758 || cp_reg_required_here (& str, 16) == FAIL)
4759 {
4760 if (!inst.error)
4761 inst.error = BAD_ARGS;
4762 return;
4763 }
4764
4765 if (skip_past_comma (& str) == FAIL
4766 || cp_reg_required_here (& str, 0) == FAIL)
4767 {
4768 if (!inst.error)
4769 inst.error = BAD_ARGS;
4770 return;
4771 }
4772
4773 if (skip_past_comma (& str) == SUCCESS)
4774 {
4775 if (cp_opc_expr (& str, 5, 3) == FAIL)
4776 {
4777 if (!inst.error)
4778 inst.error = BAD_ARGS;
4779 return;
4780 }
4781 }
4782
4783 end_of_line (str);
4784 }
4785
4786 /* ARM V5 (argument parse)
4787 MCR2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
4788 MRC2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
4789 Instruction is not conditional, and has 0xf in the condition field.
4790 Otherwise, it's the same as MCR/MRC. */
4791
4792 static void
4793 do_co_reg2 (str)
4794 char * str;
4795 {
4796 skip_whitespace (str);
4797
4798 if (co_proc_number (& str) == FAIL)
4799 {
4800 if (!inst.error)
4801 inst.error = BAD_ARGS;
4802 return;
4803 }
4804
4805 if (skip_past_comma (& str) == FAIL
4806 || cp_opc_expr (& str, 21, 3) == FAIL)
4807 {
4808 if (!inst.error)
4809 inst.error = BAD_ARGS;
4810 return;
4811 }
4812
4813 if (skip_past_comma (& str) == FAIL
4814 || reg_required_here (& str, 12) == FAIL)
4815 {
4816 if (!inst.error)
4817 inst.error = BAD_ARGS;
4818 return;
4819 }
4820
4821 if (skip_past_comma (& str) == FAIL
4822 || cp_reg_required_here (& str, 16) == FAIL)
4823 {
4824 if (!inst.error)
4825 inst.error = BAD_ARGS;
4826 return;
4827 }
4828
4829 if (skip_past_comma (& str) == FAIL
4830 || cp_reg_required_here (& str, 0) == FAIL)
4831 {
4832 if (!inst.error)
4833 inst.error = BAD_ARGS;
4834 return;
4835 }
4836
4837 if (skip_past_comma (& str) == SUCCESS)
4838 {
4839 if (cp_opc_expr (& str, 5, 3) == FAIL)
4840 {
4841 if (!inst.error)
4842 inst.error = BAD_ARGS;
4843 return;
4844 }
4845 }
4846
4847 end_of_line (str);
4848 }
4849
4850 /* ARM v5TEJ. Jump to Jazelle code. */
4851 static void
4852 do_bxj (str)
4853 char * str;
4854 {
4855 int reg;
4856
4857 skip_whitespace (str);
4858
4859 if ((reg = reg_required_here (&str, 0)) == FAIL)
4860 {
4861 inst.error = BAD_ARGS;
4862 return;
4863 }
4864
4865 /* Note - it is not illegal to do a "bxj pc". Useless, but not illegal. */
4866 if (reg == REG_PC)
4867 as_tsktsk (_("use of r15 in bxj is not really useful"));
4868
4869 end_of_line (str);
4870 }
4871
4872 /* ARM V6 umaal (argument parse). */
4873
4874 static void
4875 do_umaal (str)
4876 char *str;
4877 {
4878
4879 int rdlo, rdhi, rm, rs;
4880
4881 skip_whitespace (str);
4882 if ((rdlo = reg_required_here (& str, 12)) == FAIL
4883 || skip_past_comma (& str) == FAIL
4884 || (rdhi = reg_required_here (& str, 16)) == FAIL
4885 || skip_past_comma (& str) == FAIL
4886 || (rm = reg_required_here (& str, 0)) == FAIL
4887 || skip_past_comma (& str) == FAIL
4888 || (rs = reg_required_here (& str, 8)) == FAIL)
4889 {
4890 inst.error = BAD_ARGS;
4891 return;
4892 }
4893
4894 if (rdlo == REG_PC || rdhi == REG_PC || rm == REG_PC || rs == REG_PC)
4895 {
4896 inst.error = BAD_PC;
4897 return;
4898 }
4899
4900 end_of_line (str);
4901 }
4902
4903 /* ARM V6 strex (argument parse). */
4904
4905 static void
4906 do_strex (str)
4907 char *str;
4908 {
4909 int rd, rm, rn;
4910
4911 /* Parse Rd, Rm,. */
4912 skip_whitespace (str);
4913 if ((rd = reg_required_here (& str, 12)) == FAIL
4914 || skip_past_comma (& str) == FAIL
4915 || (rm = reg_required_here (& str, 0)) == FAIL
4916 || skip_past_comma (& str) == FAIL)
4917 {
4918 inst.error = BAD_ARGS;
4919 return;
4920 }
4921 if (rd == REG_PC || rm == REG_PC)
4922 {
4923 inst.error = BAD_PC;
4924 return;
4925 }
4926 if (rd == rm)
4927 {
4928 inst.error = _("Rd equal to Rm or Rn yields unpredictable results");
4929 return;
4930 }
4931
4932 /* Skip past '['. */
4933 if ((strlen (str) >= 1)
4934 && strncmp (str, "[", 1) == 0)
4935 str+=1;
4936 skip_whitespace (str);
4937
4938 /* Parse Rn. */
4939 if ((rn = reg_required_here (& str, 16)) == FAIL)
4940 {
4941 inst.error = BAD_ARGS;
4942 return;
4943 }
4944 else if (rn == REG_PC)
4945 {
4946 inst.error = BAD_PC;
4947 return;
4948 }
4949 if (rd == rn)
4950 {
4951 inst.error = _("Rd equal to Rm or Rn yields unpredictable results");
4952 return;
4953 }
4954 skip_whitespace (str);
4955
4956 /* Skip past ']'. */
4957 if ((strlen (str) >= 1)
4958 && strncmp (str, "]", 1) == 0)
4959 str+=1;
4960
4961 end_of_line (str);
4962 }
4963
4964 /* ARM V6 ssat (argument parse). */
4965
4966 static void
4967 do_ssat (str)
4968 char* str;
4969 {
4970 do_sat (&str, /*bias=*/-1);
4971 end_of_line (str);
4972 }
4973
4974 /* ARM V6 usat (argument parse). */
4975
4976 static void
4977 do_usat (str)
4978 char* str;
4979 {
4980 do_sat (&str, /*bias=*/0);
4981 end_of_line (str);
4982 }
4983
4984 static void
4985 do_sat (str, bias)
4986 char **str;
4987 int bias;
4988 {
4989 int rd, rm;
4990 expressionS expr;
4991
4992 skip_whitespace (*str);
4993
4994 /* Parse <Rd>, field. */
4995 if ((rd = reg_required_here (str, 12)) == FAIL
4996 || skip_past_comma (str) == FAIL)
4997 {
4998 inst.error = BAD_ARGS;
4999 return;
5000 }
5001 if (rd == REG_PC)
5002 {
5003 inst.error = BAD_PC;
5004 return;
5005 }
5006
5007 /* Parse #<immed>, field. */
5008 if (is_immediate_prefix (**str))
5009 (*str)++;
5010 else
5011 {
5012 inst.error = _("immediate expression expected");
5013 return;
5014 }
5015 if (my_get_expression (&expr, str))
5016 {
5017 inst.error = _("bad expression");
5018 return;
5019 }
5020 if (expr.X_op != O_constant)
5021 {
5022 inst.error = _("constant expression expected");
5023 return;
5024 }
5025 if (expr.X_add_number + bias < 0
5026 || expr.X_add_number + bias > 31)
5027 {
5028 inst.error = _("immediate value out of range");
5029 return;
5030 }
5031 inst.instruction |= (expr.X_add_number + bias) << 16;
5032 if (skip_past_comma (str) == FAIL)
5033 {
5034 inst.error = BAD_ARGS;
5035 return;
5036 }
5037
5038 /* Parse <Rm> field. */
5039 if ((rm = reg_required_here (str, 0)) == FAIL)
5040 {
5041 inst.error = BAD_ARGS;
5042 return;
5043 }
5044 if (rm == REG_PC)
5045 {
5046 inst.error = BAD_PC;
5047 return;
5048 }
5049
5050 if (skip_past_comma (str) == SUCCESS)
5051 decode_shift (str, SHIFT_LSL_OR_ASR_IMMEDIATE);
5052 }
5053
5054 /* ARM V6 ssat16 (argument parse). */
5055
5056 static void
5057 do_ssat16 (str)
5058 char *str;
5059 {
5060 do_sat16 (&str, /*bias=*/-1);
5061 end_of_line (str);
5062 }
5063
5064 static void
5065 do_usat16 (str)
5066 char *str;
5067 {
5068 do_sat16 (&str, /*bias=*/0);
5069 end_of_line (str);
5070 }
5071
5072 static void
5073 do_sat16 (str, bias)
5074 char **str;
5075 int bias;
5076 {
5077 int rd, rm;
5078 expressionS expr;
5079
5080 skip_whitespace (*str);
5081
5082 /* Parse the <Rd> field. */
5083 if ((rd = reg_required_here (str, 12)) == FAIL
5084 || skip_past_comma (str) == FAIL)
5085 {
5086 inst.error = BAD_ARGS;
5087 return;
5088 }
5089 if (rd == REG_PC)
5090 {
5091 inst.error = BAD_PC;
5092 return;
5093 }
5094
5095 /* Parse #<immed>, field. */
5096 if (is_immediate_prefix (**str))
5097 (*str)++;
5098 else
5099 {
5100 inst.error = _("immediate expression expected");
5101 return;
5102 }
5103 if (my_get_expression (&expr, str))
5104 {
5105 inst.error = _("bad expression");
5106 return;
5107 }
5108 if (expr.X_op != O_constant)
5109 {
5110 inst.error = _("constant expression expected");
5111 return;
5112 }
5113 if (expr.X_add_number + bias < 0
5114 || expr.X_add_number + bias > 15)
5115 {
5116 inst.error = _("immediate value out of range");
5117 return;
5118 }
5119 inst.instruction |= (expr.X_add_number + bias) << 16;
5120 if (skip_past_comma (str) == FAIL)
5121 {
5122 inst.error = BAD_ARGS;
5123 return;
5124 }
5125
5126 /* Parse <Rm> field. */
5127 if ((rm = reg_required_here (str, 0)) == FAIL)
5128 {
5129 inst.error = BAD_ARGS;
5130 return;
5131 }
5132 if (rm == REG_PC)
5133 {
5134 inst.error = BAD_PC;
5135 return;
5136 }
5137 }
5138
5139 /* ARM V6 srs (argument parse). */
5140
5141 static void
5142 do_srs (str)
5143 char* str;
5144 {
5145 char *exclam;
5146 skip_whitespace (str);
5147 exclam = strchr (str, '!');
5148 if (exclam)
5149 *exclam = '\0';
5150 do_cps_mode (&str);
5151 if (exclam)
5152 *exclam = '!';
5153 if (*str == '!')
5154 {
5155 inst.instruction |= WRITE_BACK;
5156 str++;
5157 }
5158 end_of_line (str);
5159 }
5160
5161 /* ARM V6 SMMUL (argument parse). */
5162
5163 static void
5164 do_smmul (str)
5165 char* str;
5166 {
5167 int rd, rm, rs;
5168
5169 skip_whitespace (str);
5170 if ((rd = reg_required_here (&str, 16)) == FAIL
5171 || skip_past_comma (&str) == FAIL
5172 || (rm = reg_required_here (&str, 0)) == FAIL
5173 || skip_past_comma (&str) == FAIL
5174 || (rs = reg_required_here (&str, 8)) == FAIL)
5175 {
5176 inst.error = BAD_ARGS;
5177 return;
5178 }
5179
5180 if (rd == REG_PC
5181 || rm == REG_PC
5182 || rs == REG_PC)
5183 {
5184 inst.error = BAD_PC;
5185 return;
5186 }
5187
5188 end_of_line (str);
5189
5190 }
5191
5192 /* ARM V6 SMLALD (argument parse). */
5193
5194 static void
5195 do_smlald (str)
5196 char* str;
5197 {
5198 int rdlo, rdhi, rm, rs;
5199 skip_whitespace (str);
5200 if ((rdlo = reg_required_here (&str, 12)) == FAIL
5201 || skip_past_comma (&str) == FAIL
5202 || (rdhi = reg_required_here (&str, 16)) == FAIL
5203 || skip_past_comma (&str) == FAIL
5204 || (rm = reg_required_here (&str, 0)) == FAIL
5205 || skip_past_comma (&str) == FAIL
5206 || (rs = reg_required_here (&str, 8)) == FAIL)
5207 {
5208 inst.error = BAD_ARGS;
5209 return;
5210 }
5211
5212 if (rdlo == REG_PC
5213 || rdhi == REG_PC
5214 || rm == REG_PC
5215 || rs == REG_PC)
5216 {
5217 inst.error = BAD_PC;
5218 return;
5219 }
5220
5221 end_of_line (str);
5222 }
5223
5224 /* ARM V6 SMLAD (argument parse). Signed multiply accumulate dual.
5225 smlad{x}{<cond>} Rd, Rm, Rs, Rn */
5226
5227 static void
5228 do_smlad (str)
5229 char *str;
5230 {
5231 int rd, rm, rs, rn;
5232
5233 skip_whitespace (str);
5234 if ((rd = reg_required_here (&str, 16)) == FAIL
5235 || skip_past_comma (&str) == FAIL
5236 || (rm = reg_required_here (&str, 0)) == FAIL
5237 || skip_past_comma (&str) == FAIL
5238 || (rs = reg_required_here (&str, 8)) == FAIL
5239 || skip_past_comma (&str) == FAIL
5240 || (rn = reg_required_here (&str, 12)) == FAIL)
5241 {
5242 inst.error = BAD_ARGS;
5243 return;
5244 }
5245
5246 if (rd == REG_PC
5247 || rn == REG_PC
5248 || rs == REG_PC
5249 || rm == REG_PC)
5250 {
5251 inst.error = BAD_PC;
5252 return;
5253 }
5254
5255 end_of_line (str);
5256 }
5257
5258 /* ARM V6 SETEND (argument parse). Sets the E bit in the CPSR while
5259 preserving the other bits.
5260
5261 setend <endian_specifier>, where <endian_specifier> is either
5262 BE or LE. */
5263
5264 static void
5265 do_setend (str)
5266 char *str;
5267 {
5268 if (do_endian_specifier (str))
5269 inst.instruction |= 0x200;
5270 }
5271
5272 /* Returns true if the endian-specifier indicates big-endianness. */
5273
5274 static int
5275 do_endian_specifier (str)
5276 char *str;
5277 {
5278 int big_endian = 0;
5279
5280 skip_whitespace (str);
5281 if (strlen (str) < 2)
5282 inst.error = _("missing endian specifier");
5283 else if (strncasecmp (str, "BE", 2) == 0)
5284 {
5285 str += 2;
5286 big_endian = 1;
5287 }
5288 else if (strncasecmp (str, "LE", 2) == 0)
5289 str += 2;
5290 else
5291 inst.error = _("valid endian specifiers are be or le");
5292
5293 end_of_line (str);
5294
5295 return big_endian;
5296 }
5297
5298 /* ARM V6 SXTH.
5299
5300 SXTH {<cond>} <Rd>, <Rm>{, <rotation>}
5301 Condition defaults to COND_ALWAYS.
5302 Error if any register uses R15. */
5303
5304 static void
5305 do_sxth (str)
5306 char *str;
5307 {
5308 int rd, rm;
5309 expressionS expr;
5310 int rotation_clear_mask = 0xfffff3ff;
5311 int rotation_eight_mask = 0x00000400;
5312 int rotation_sixteen_mask = 0x00000800;
5313 int rotation_twenty_four_mask = 0x00000c00;
5314
5315 skip_whitespace (str);
5316 if ((rd = reg_required_here (&str, 12)) == FAIL
5317 || skip_past_comma (&str) == FAIL
5318 || (rm = reg_required_here (&str, 0)) == FAIL)
5319 {
5320 inst.error = BAD_ARGS;
5321 return;
5322 }
5323
5324 else if (rd == REG_PC || rm == REG_PC)
5325 {
5326 inst.error = BAD_PC;
5327 return;
5328 }
5329
5330 /* Zero out the rotation field. */
5331 inst.instruction &= rotation_clear_mask;
5332
5333 /* Check for lack of optional rotation field. */
5334 if (skip_past_comma (&str) == FAIL)
5335 {
5336 end_of_line (str);
5337 return;
5338 }
5339
5340 /* Move past 'ROR'. */
5341 skip_whitespace (str);
5342 if (strncasecmp (str, "ROR", 3) == 0)
5343 str+=3;
5344 else
5345 {
5346 inst.error = _("missing rotation field after comma");
5347 return;
5348 }
5349
5350 /* Get the immediate constant. */
5351 skip_whitespace (str);
5352 if (is_immediate_prefix (* str))
5353 str++;
5354 else
5355 {
5356 inst.error = _("immediate expression expected");
5357 return;
5358 }
5359
5360 if (my_get_expression (&expr, &str))
5361 {
5362 inst.error = _("bad expression");
5363 return;
5364 }
5365
5366 if (expr.X_op != O_constant)
5367 {
5368 inst.error = _("constant expression expected");
5369 return;
5370 }
5371
5372 switch (expr.X_add_number)
5373 {
5374 case 0:
5375 /* Rotation field has already been zeroed. */
5376 break;
5377 case 8:
5378 inst.instruction |= rotation_eight_mask;
5379 break;
5380
5381 case 16:
5382 inst.instruction |= rotation_sixteen_mask;
5383 break;
5384
5385 case 24:
5386 inst.instruction |= rotation_twenty_four_mask;
5387 break;
5388
5389 default:
5390 inst.error = _("rotation can be 8, 16, 24 or 0 when field is ommited");
5391 break;
5392 }
5393
5394 end_of_line (str);
5395
5396 }
5397
5398 /* ARM V6 SXTAH extracts a 16-bit value from a register, sign
5399 extends it to 32-bits, and adds the result to a value in another
5400 register. You can specify a rotation by 0, 8, 16, or 24 bits
5401 before extracting the 16-bit value.
5402 SXTAH{<cond>} <Rd>, <Rn>, <Rm>{, <rotation>}
5403 Condition defaults to COND_ALWAYS.
5404 Error if any register uses R15. */
5405
5406 static void
5407 do_sxtah (str)
5408 char *str;
5409 {
5410 int rd, rn, rm;
5411 expressionS expr;
5412 int rotation_clear_mask = 0xfffff3ff;
5413 int rotation_eight_mask = 0x00000400;
5414 int rotation_sixteen_mask = 0x00000800;
5415 int rotation_twenty_four_mask = 0x00000c00;
5416
5417 skip_whitespace (str);
5418 if ((rd = reg_required_here (&str, 12)) == FAIL
5419 || skip_past_comma (&str) == FAIL
5420 || (rn = reg_required_here (&str, 16)) == FAIL
5421 || skip_past_comma (&str) == FAIL
5422 || (rm = reg_required_here (&str, 0)) == FAIL)
5423 {
5424 inst.error = BAD_ARGS;
5425 return;
5426 }
5427
5428 else if (rd == REG_PC || rn == REG_PC || rm == REG_PC)
5429 {
5430 inst.error = BAD_PC;
5431 return;
5432 }
5433
5434 /* Zero out the rotation field. */
5435 inst.instruction &= rotation_clear_mask;
5436
5437 /* Check for lack of optional rotation field. */
5438 if (skip_past_comma (&str) == FAIL)
5439 {
5440 end_of_line (str);
5441 return;
5442 }
5443
5444 /* Move past 'ROR'. */
5445 skip_whitespace (str);
5446 if (strncasecmp (str, "ROR", 3) == 0)
5447 str+=3;
5448 else
5449 {
5450 inst.error = _("missing rotation field after comma");
5451 return;
5452 }
5453
5454 /* Get the immediate constant. */
5455 skip_whitespace (str);
5456 if (is_immediate_prefix (* str))
5457 str++;
5458 else
5459 {
5460 inst.error = _("immediate expression expected");
5461 return;
5462 }
5463
5464 if (my_get_expression (&expr, &str))
5465 {
5466 inst.error = _("bad expression");
5467 return;
5468 }
5469
5470 if (expr.X_op != O_constant)
5471 {
5472 inst.error = _("constant expression expected");
5473 return;
5474 }
5475
5476 switch (expr.X_add_number)
5477 {
5478 case 0:
5479 /* Rotation field has already been zeroed. */
5480 break;
5481
5482 case 8:
5483 inst.instruction |= rotation_eight_mask;
5484 break;
5485
5486 case 16:
5487 inst.instruction |= rotation_sixteen_mask;
5488 break;
5489
5490 case 24:
5491 inst.instruction |= rotation_twenty_four_mask;
5492 break;
5493
5494 default:
5495 inst.error = _("rotation can be 8, 16, 24 or 0 when field is ommited");
5496 break;
5497 }
5498
5499 end_of_line (str);
5500
5501 }
5502
5503
5504 /* ARM V6 RFE (Return from Exception) loads the PC and CPSR from the
5505 word at the specified address and the following word
5506 respectively.
5507 Unconditionally executed.
5508 Error if Rn is R15.
5509 */
5510
5511 static void
5512 do_rfe (str)
5513 char *str;
5514 {
5515 int rn;
5516
5517 skip_whitespace (str);
5518
5519 if ((rn = reg_required_here (&str, 16)) == FAIL)
5520 return;
5521
5522 if (rn == REG_PC)
5523 {
5524 inst.error = BAD_PC;
5525 return;
5526 }
5527
5528 skip_whitespace (str);
5529
5530 if (*str == '!')
5531 {
5532 inst.instruction |= WRITE_BACK;
5533 str++;
5534 }
5535 end_of_line (str);
5536 }
5537
5538 /* ARM V6 REV (Byte Reverse Word) reverses the byte order in a 32-bit
5539 register (argument parse).
5540 REV{<cond>} Rd, Rm.
5541 Condition defaults to COND_ALWAYS.
5542 Error if Rd or Rm are R15. */
5543
5544 static void
5545 do_rev (str)
5546 char* str;
5547 {
5548 int rd, rm;
5549
5550 skip_whitespace (str);
5551
5552 if ((rd = reg_required_here (&str, 12)) == FAIL
5553 || skip_past_comma (&str) == FAIL
5554 || (rm = reg_required_here (&str, 0)) == FAIL)
5555 inst.error = BAD_ARGS;
5556
5557 else if (rd == REG_PC || rm == REG_PC)
5558 inst.error = BAD_PC;
5559
5560 else
5561 end_of_line (str);
5562 }
5563
5564 /* ARM V6 Perform Two Sixteen Bit Integer Additions. (argument parse).
5565 QADD16{<cond>} <Rd>, <Rn>, <Rm>
5566 Condition defaults to COND_ALWAYS.
5567 Error if Rd, Rn or Rm are R15. */
5568
5569 static void
5570 do_qadd16 (str)
5571 char* str;
5572 {
5573 int rd, rm, rn;
5574
5575 skip_whitespace (str);
5576
5577 if ((rd = reg_required_here (&str, 12)) == FAIL
5578 || skip_past_comma (&str) == FAIL
5579 || (rn = reg_required_here (&str, 16)) == FAIL
5580 || skip_past_comma (&str) == FAIL
5581 || (rm = reg_required_here (&str, 0)) == FAIL)
5582 inst.error = BAD_ARGS;
5583
5584 else if (rd == REG_PC || rm == REG_PC || rn == REG_PC)
5585 inst.error = BAD_PC;
5586
5587 else
5588 end_of_line (str);
5589 }
5590
5591 /* ARM V6 Pack Halfword Bottom Top instruction (argument parse).
5592 PKHBT {<cond>} <Rd>, <Rn>, <Rm> {, LSL #<shift_imm>}
5593 Condition defaults to COND_ALWAYS.
5594 Error if Rd, Rn or Rm are R15. */
5595
5596 static void
5597 do_pkhbt (str)
5598 char* str;
5599 {
5600 do_pkh_core (str, SHIFT_LSL_IMMEDIATE);
5601 }
5602
5603 /* ARM V6 PKHTB (Argument Parse). */
5604
5605 static void
5606 do_pkhtb (str)
5607 char* str;
5608 {
5609 do_pkh_core (str, SHIFT_ASR_IMMEDIATE);
5610 }
5611
5612 static void
5613 do_pkh_core (str, shift)
5614 char* str;
5615 int shift;
5616 {
5617 int rd, rn, rm;
5618
5619 skip_whitespace (str);
5620 if (((rd = reg_required_here (&str, 12)) == FAIL)
5621 || (skip_past_comma (&str) == FAIL)
5622 || ((rn = reg_required_here (&str, 16)) == FAIL)
5623 || (skip_past_comma (&str) == FAIL)
5624 || ((rm = reg_required_here (&str, 0)) == FAIL))
5625 {
5626 inst.error = BAD_ARGS;
5627 return;
5628 }
5629
5630 else if (rd == REG_PC || rn == REG_PC || rm == REG_PC)
5631 {
5632 inst.error = BAD_PC;
5633 return;
5634 }
5635
5636 /* Check for optional shift immediate constant. */
5637 if (skip_past_comma (&str) == FAIL)
5638 {
5639 if (shift == SHIFT_ASR_IMMEDIATE)
5640 {
5641 /* If the shift specifier is ommited, turn the instruction
5642 into pkhbt rd, rm, rn. First, switch the instruction
5643 code, and clear the rn and rm fields. */
5644 inst.instruction &= 0xfff0f010;
5645 /* Now, re-encode the registers. */
5646 inst.instruction |= (rm << 16) | rn;
5647 }
5648 return;
5649 }
5650
5651 decode_shift (&str, shift);
5652 }
5653
5654 /* ARM V6 Load Register Exclusive instruction (argument parse).
5655 LDREX{<cond>} <Rd, [<Rn>]
5656 Condition defaults to COND_ALWAYS.
5657 Error if Rd or Rn are R15.
5658 See ARMARMv6 A4.1.27: LDREX. */
5659
5660
5661 static void
5662 do_ldrex (str)
5663 char * str;
5664 {
5665 int rd, rn;
5666
5667 skip_whitespace (str);
5668
5669 /* Parse Rd. */
5670 if (((rd = reg_required_here (&str, 12)) == FAIL)
5671 || (skip_past_comma (&str) == FAIL))
5672 {
5673 inst.error = BAD_ARGS;
5674 return;
5675 }
5676 else if (rd == REG_PC)
5677 {
5678 inst.error = BAD_PC;
5679 return;
5680 }
5681 skip_whitespace (str);
5682
5683 /* Skip past '['. */
5684 if ((strlen (str) >= 1)
5685 &&strncmp (str, "[", 1) == 0)
5686 str+=1;
5687 skip_whitespace (str);
5688
5689 /* Parse Rn. */
5690 if ((rn = reg_required_here (&str, 16)) == FAIL)
5691 {
5692 inst.error = BAD_ARGS;
5693 return;
5694 }
5695 else if (rn == REG_PC)
5696 {
5697 inst.error = BAD_PC;
5698 return;
5699 }
5700 skip_whitespace (str);
5701
5702 /* Skip past ']'. */
5703 if ((strlen (str) >= 1)
5704 && strncmp (str, "]", 1) == 0)
5705 str+=1;
5706
5707 end_of_line (str);
5708 }
5709
5710 /* ARM V6 change processor state instruction (argument parse)
5711 CPS, CPSIE, CSPID . */
5712
5713 static void
5714 do_cps (str)
5715 char * str;
5716 {
5717 do_cps_mode (&str);
5718 end_of_line (str);
5719 }
5720
5721 static void
5722 do_cpsi (str)
5723 char * str;
5724 {
5725 do_cps_flags (&str, /*thumb_p=*/0);
5726
5727 if (skip_past_comma (&str) == SUCCESS)
5728 {
5729 skip_whitespace (str);
5730 do_cps_mode (&str);
5731 }
5732 end_of_line (str);
5733 }
5734
5735 static void
5736 do_cps_mode (str)
5737 char **str;
5738 {
5739 expressionS expr;
5740
5741 skip_whitespace (*str);
5742
5743 if (! is_immediate_prefix (**str))
5744 {
5745 inst.error = _("immediate expression expected");
5746 return;
5747 }
5748
5749 (*str)++; /* Strip off the immediate signifier. */
5750 if (my_get_expression (&expr, str))
5751 {
5752 inst.error = _("bad expression");
5753 return;
5754 }
5755
5756 if (expr.X_op != O_constant)
5757 {
5758 inst.error = _("constant expression expected");
5759 return;
5760 }
5761
5762 /* The mode is a 5 bit field. Valid values are 0-31. */
5763 if (((unsigned) expr.X_add_number) > 31
5764 || (inst.reloc.exp.X_add_number) < 0)
5765 {
5766 inst.error = _("invalid constant");
5767 return;
5768 }
5769
5770 inst.instruction |= expr.X_add_number;
5771 }
5772
5773 static void
5774 do_cps_flags (str, thumb_p)
5775 char **str;
5776 int thumb_p;
5777 {
5778 struct cps_flag {
5779 char character;
5780 unsigned long arm_value;
5781 unsigned long thumb_value;
5782 };
5783 static struct cps_flag flag_table[] = {
5784 {'a', 0x100, 0x4 },
5785 {'i', 0x080, 0x2 },
5786 {'f', 0x040, 0x1 }
5787 };
5788
5789 int saw_a_flag = 0;
5790
5791 skip_whitespace (*str);
5792
5793 /* Get the a, f and i flags. */
5794 while (**str && **str != ',')
5795 {
5796 struct cps_flag *p;
5797 struct cps_flag *q = flag_table + sizeof (flag_table)/sizeof (*p);
5798 for (p = flag_table; p < q; ++p)
5799 if (strncasecmp (*str, &p->character, 1) == 0)
5800 {
5801 inst.instruction |= (thumb_p ? p->thumb_value : p->arm_value);
5802 saw_a_flag = 1;
5803 break;
5804 }
5805 if (p == q)
5806 {
5807 inst.error = _("unrecognized flag");
5808 return;
5809 }
5810 (*str)++;
5811 }
5812 if (!saw_a_flag)
5813 inst.error = _("no 'a', 'i', or 'f' flags for 'cps'");
5814 }
5815
5816 /* THUMB V5 breakpoint instruction (argument parse)
5817 BKPT <immed_8>. */
5818
5819 static void
5820 do_t_bkpt (str)
5821 char * str;
5822 {
5823 expressionS expr;
5824 unsigned long number;
5825
5826 skip_whitespace (str);
5827
5828 /* Allow optional leading '#'. */
5829 if (is_immediate_prefix (*str))
5830 str ++;
5831
5832 memset (& expr, '\0', sizeof (expr));
5833 if (my_get_expression (& expr, & str)
5834 || (expr.X_op != O_constant
5835 /* As a convenience we allow 'bkpt' without an operand. */
5836 && expr.X_op != O_absent))
5837 {
5838 inst.error = _("bad expression");
5839 return;
5840 }
5841
5842 number = expr.X_add_number;
5843
5844 /* Check it fits an 8 bit unsigned. */
5845 if (number != (number & 0xff))
5846 {
5847 inst.error = _("immediate value out of range");
5848 return;
5849 }
5850
5851 inst.instruction |= number;
5852
5853 end_of_line (str);
5854 }
5855
5856 /* ARM V5 branch-link-exchange (argument parse) for BLX(1) only.
5857 Expects inst.instruction is set for BLX(1).
5858 Note: this is cloned from do_branch, and the reloc changed to be a
5859 new one that can cope with setting one extra bit (the H bit). */
5860
5861 static void
5862 do_branch25 (str)
5863 char * str;
5864 {
5865 if (my_get_expression (& inst.reloc.exp, & str))
5866 return;
5867
5868 #ifdef OBJ_ELF
5869 {
5870 char * save_in;
5871
5872 /* ScottB: February 5, 1998 */
5873 /* Check to see of PLT32 reloc required for the instruction. */
5874
5875 /* arm_parse_reloc() works on input_line_pointer.
5876 We actually want to parse the operands to the branch instruction
5877 passed in 'str'. Save the input pointer and restore it later. */
5878 save_in = input_line_pointer;
5879 input_line_pointer = str;
5880
5881 if (inst.reloc.exp.X_op == O_symbol
5882 && *str == '('
5883 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
5884 {
5885 inst.reloc.type = BFD_RELOC_ARM_PLT32;
5886 inst.reloc.pc_rel = 0;
5887 /* Modify str to point to after parsed operands, otherwise
5888 end_of_line() will complain about the (PLT) left in str. */
5889 str = input_line_pointer;
5890 }
5891 else
5892 {
5893 inst.reloc.type = BFD_RELOC_ARM_PCREL_BLX;
5894 inst.reloc.pc_rel = 1;
5895 }
5896
5897 input_line_pointer = save_in;
5898 }
5899 #else
5900 inst.reloc.type = BFD_RELOC_ARM_PCREL_BLX;
5901 inst.reloc.pc_rel = 1;
5902 #endif /* OBJ_ELF */
5903
5904 end_of_line (str);
5905 }
5906
5907 /* ARM V5 branch-link-exchange instruction (argument parse)
5908 BLX <target_addr> ie BLX(1)
5909 BLX{<condition>} <Rm> ie BLX(2)
5910 Unfortunately, there are two different opcodes for this mnemonic.
5911 So, the insns[].value is not used, and the code here zaps values
5912 into inst.instruction.
5913 Also, the <target_addr> can be 25 bits, hence has its own reloc. */
5914
5915 static void
5916 do_blx (str)
5917 char * str;
5918 {
5919 char * mystr = str;
5920 int rm;
5921
5922 skip_whitespace (mystr);
5923 rm = reg_required_here (& mystr, 0);
5924
5925 /* The above may set inst.error. Ignore his opinion. */
5926 inst.error = 0;
5927
5928 if (rm != FAIL)
5929 {
5930 /* Arg is a register.
5931 Use the condition code our caller put in inst.instruction.
5932 Pass ourselves off as a BX with a funny opcode. */
5933 inst.instruction |= 0x012fff30;
5934 do_bx (str);
5935 }
5936 else
5937 {
5938 /* This must be is BLX <target address>, no condition allowed. */
5939 if (inst.instruction != COND_ALWAYS)
5940 {
5941 inst.error = BAD_COND;
5942 return;
5943 }
5944
5945 inst.instruction = 0xfafffffe;
5946
5947 /* Process like a B/BL, but with a different reloc.
5948 Note that B/BL expecte fffffe, not 0, offset in the opcode table. */
5949 do_branch25 (str);
5950 }
5951 }
5952
5953 /* ARM V5 Thumb BLX (argument parse)
5954 BLX <target_addr> which is BLX(1)
5955 BLX <Rm> which is BLX(2)
5956 Unfortunately, there are two different opcodes for this mnemonic.
5957 So, the tinsns[].value is not used, and the code here zaps values
5958 into inst.instruction. */
5959
5960 static void
5961 do_t_blx (str)
5962 char * str;
5963 {
5964 char * mystr = str;
5965 int rm;
5966
5967 skip_whitespace (mystr);
5968 inst.instruction = 0x4780;
5969
5970 /* Note that this call is to the ARM register recognizer. BLX(2)
5971 uses the ARM register space, not the Thumb one, so a call to
5972 thumb_reg() would be wrong. */
5973 rm = reg_required_here (& mystr, 3);
5974 inst.error = 0;
5975
5976 if (rm != FAIL)
5977 {
5978 /* It's BLX(2). The .instruction was zapped with rm & is final. */
5979 inst.size = 2;
5980 }
5981 else
5982 {
5983 /* No ARM register. This must be BLX(1). Change the .instruction. */
5984 inst.instruction = 0xf7ffeffe;
5985 inst.size = 4;
5986
5987 if (my_get_expression (& inst.reloc.exp, & mystr))
5988 return;
5989
5990 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BLX;
5991 inst.reloc.pc_rel = 1;
5992 }
5993
5994 end_of_line (mystr);
5995 }
5996
5997 /* ARM V5 breakpoint instruction (argument parse)
5998 BKPT <16 bit unsigned immediate>
5999 Instruction is not conditional.
6000 The bit pattern given in insns[] has the COND_ALWAYS condition,
6001 and it is an error if the caller tried to override that. */
6002
6003 static void
6004 do_bkpt (str)
6005 char * str;
6006 {
6007 expressionS expr;
6008 unsigned long number;
6009
6010 skip_whitespace (str);
6011
6012 /* Allow optional leading '#'. */
6013 if (is_immediate_prefix (* str))
6014 str++;
6015
6016 memset (& expr, '\0', sizeof (expr));
6017
6018 if (my_get_expression (& expr, & str)
6019 || (expr.X_op != O_constant
6020 /* As a convenience we allow 'bkpt' without an operand. */
6021 && expr.X_op != O_absent))
6022 {
6023 inst.error = _("bad expression");
6024 return;
6025 }
6026
6027 number = expr.X_add_number;
6028
6029 /* Check it fits a 16 bit unsigned. */
6030 if (number != (number & 0xffff))
6031 {
6032 inst.error = _("immediate value out of range");
6033 return;
6034 }
6035
6036 /* Top 12 of 16 bits to bits 19:8. */
6037 inst.instruction |= (number & 0xfff0) << 4;
6038
6039 /* Bottom 4 of 16 bits to bits 3:0. */
6040 inst.instruction |= number & 0xf;
6041
6042 end_of_line (str);
6043 }
6044
6045 /* THUMB CPS instruction (argument parse). */
6046
6047 static void
6048 do_t_cps (str)
6049 char *str;
6050 {
6051 do_cps_flags (&str, /*thumb_p=*/1);
6052 end_of_line (str);
6053 }
6054
6055 /* THUMB CPY instruction (argument parse). */
6056
6057 static void
6058 do_t_cpy (str)
6059 char *str;
6060 {
6061 thumb_mov_compare (str, THUMB_CPY);
6062 }
6063
6064 /* THUMB SETEND instruction (argument parse). */
6065
6066 static void
6067 do_t_setend (str)
6068 char *str;
6069 {
6070 if (do_endian_specifier (str))
6071 inst.instruction |= 0x8;
6072 }
6073
6074 static unsigned long check_iwmmxt_insn PARAMS ((char *, enum iwmmxt_insn_type, int));
6075
6076 /* Parse INSN_TYPE insn STR having a possible IMMEDIATE_SIZE immediate. */
6077
6078 static unsigned long
6079 check_iwmmxt_insn (str, insn_type, immediate_size)
6080 char * str;
6081 enum iwmmxt_insn_type insn_type;
6082 int immediate_size;
6083 {
6084 int reg = 0;
6085 const char * inst_error;
6086 expressionS expr;
6087 unsigned long number;
6088
6089 inst_error = inst.error;
6090 if (!inst.error)
6091 inst.error = BAD_ARGS;
6092 skip_whitespace (str);
6093
6094 switch (insn_type)
6095 {
6096 case check_rd:
6097 if ((reg = reg_required_here (&str, 12)) == FAIL)
6098 return FAIL;
6099 break;
6100
6101 case check_wr:
6102 if ((wreg_required_here (&str, 0, IWMMXT_REG_WR)) == FAIL)
6103 return FAIL;
6104 break;
6105
6106 case check_wrwr:
6107 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
6108 || skip_past_comma (&str) == FAIL
6109 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL))
6110 return FAIL;
6111 break;
6112
6113 case check_wrwrwr:
6114 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
6115 || skip_past_comma (&str) == FAIL
6116 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6117 || skip_past_comma (&str) == FAIL
6118 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL))
6119 return FAIL;
6120 break;
6121
6122 case check_wrwrwcg:
6123 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
6124 || skip_past_comma (&str) == FAIL
6125 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6126 || skip_past_comma (&str) == FAIL
6127 || wreg_required_here (&str, 0, IWMMXT_REG_WCG) == FAIL))
6128 return FAIL;
6129 break;
6130
6131 case check_tbcst:
6132 if ((wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6133 || skip_past_comma (&str) == FAIL
6134 || reg_required_here (&str, 12) == FAIL))
6135 return FAIL;
6136 break;
6137
6138 case check_tmovmsk:
6139 if ((reg_required_here (&str, 12) == FAIL
6140 || skip_past_comma (&str) == FAIL
6141 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL))
6142 return FAIL;
6143 break;
6144
6145 case check_tmia:
6146 if ((wreg_required_here (&str, 5, IWMMXT_REG_WR) == FAIL
6147 || skip_past_comma (&str) == FAIL
6148 || reg_required_here (&str, 0) == FAIL
6149 || skip_past_comma (&str) == FAIL
6150 || reg_required_here (&str, 12) == FAIL))
6151 return FAIL;
6152 break;
6153
6154 case check_tmcrr:
6155 if ((wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL
6156 || skip_past_comma (&str) == FAIL
6157 || reg_required_here (&str, 12) == FAIL
6158 || skip_past_comma (&str) == FAIL
6159 || reg_required_here (&str, 16) == FAIL))
6160 return FAIL;
6161 break;
6162
6163 case check_tmrrc:
6164 if ((reg_required_here (&str, 12) == FAIL
6165 || skip_past_comma (&str) == FAIL
6166 || reg_required_here (&str, 16) == FAIL
6167 || skip_past_comma (&str) == FAIL
6168 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL))
6169 return FAIL;
6170 break;
6171
6172 case check_tmcr:
6173 if ((wreg_required_here (&str, 16, IWMMXT_REG_WC) == FAIL
6174 || skip_past_comma (&str) == FAIL
6175 || reg_required_here (&str, 12) == FAIL))
6176 return FAIL;
6177 break;
6178
6179 case check_tmrc:
6180 if ((reg_required_here (&str, 12) == FAIL
6181 || skip_past_comma (&str) == FAIL
6182 || wreg_required_here (&str, 16, IWMMXT_REG_WC) == FAIL))
6183 return FAIL;
6184 break;
6185
6186 case check_tinsr:
6187 if ((wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6188 || skip_past_comma (&str) == FAIL
6189 || reg_required_here (&str, 12) == FAIL
6190 || skip_past_comma (&str) == FAIL))
6191 return FAIL;
6192 break;
6193
6194 case check_textrc:
6195 if ((reg_required_here (&str, 12) == FAIL
6196 || skip_past_comma (&str) == FAIL))
6197 return FAIL;
6198 break;
6199
6200 case check_waligni:
6201 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
6202 || skip_past_comma (&str) == FAIL
6203 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6204 || skip_past_comma (&str) == FAIL
6205 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL
6206 || skip_past_comma (&str) == FAIL))
6207 return FAIL;
6208 break;
6209
6210 case check_textrm:
6211 if ((reg_required_here (&str, 12) == FAIL
6212 || skip_past_comma (&str) == FAIL
6213 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6214 || skip_past_comma (&str) == FAIL))
6215 return FAIL;
6216 break;
6217
6218 case check_wshufh:
6219 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
6220 || skip_past_comma (&str) == FAIL
6221 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6222 || skip_past_comma (&str) == FAIL))
6223 return FAIL;
6224 break;
6225 }
6226
6227 if (immediate_size == 0)
6228 {
6229 end_of_line (str);
6230 inst.error = inst_error;
6231 return reg;
6232 }
6233 else
6234 {
6235 skip_whitespace (str);
6236
6237 /* Allow optional leading '#'. */
6238 if (is_immediate_prefix (* str))
6239 str++;
6240
6241 memset (& expr, '\0', sizeof (expr));
6242
6243 if (my_get_expression (& expr, & str) || (expr.X_op != O_constant))
6244 {
6245 inst.error = _("bad or missing expression");
6246 return FAIL;
6247 }
6248
6249 number = expr.X_add_number;
6250
6251 if (number != (number & immediate_size))
6252 {
6253 inst.error = _("immediate value out of range");
6254 return FAIL;
6255 }
6256 end_of_line (str);
6257 inst.error = inst_error;
6258 return number;
6259 }
6260 }
6261
6262 static void
6263 do_iwmmxt_byte_addr (str)
6264 char * str;
6265 {
6266 int op = (inst.instruction & 0x300) >> 8;
6267 int reg;
6268
6269 inst.instruction &= ~0x300;
6270 inst.instruction |= (op & 1) << 22 | (op & 2) << 7;
6271
6272 skip_whitespace (str);
6273
6274 if ((reg = wreg_required_here (&str, 12, IWMMXT_REG_WR_OR_WC)) == FAIL
6275 || skip_past_comma (& str) == FAIL
6276 || cp_byte_address_required_here (&str) == FAIL)
6277 {
6278 if (! inst.error)
6279 inst.error = BAD_ARGS;
6280 }
6281 else
6282 end_of_line (str);
6283
6284 if (wc_register (reg))
6285 {
6286 as_bad (_("non-word size not supported with control register"));
6287 inst.instruction |= 0xf0000100;
6288 inst.instruction &= ~0x00400000;
6289 }
6290 }
6291
6292 static void
6293 do_iwmmxt_tandc (str)
6294 char * str;
6295 {
6296 int reg;
6297
6298 reg = check_iwmmxt_insn (str, check_rd, 0);
6299
6300 if (reg != REG_PC && !inst.error)
6301 inst.error = _("only r15 allowed here");
6302 }
6303
6304 static void
6305 do_iwmmxt_tbcst (str)
6306 char * str;
6307 {
6308 check_iwmmxt_insn (str, check_tbcst, 0);
6309 }
6310
6311 static void
6312 do_iwmmxt_textrc (str)
6313 char * str;
6314 {
6315 unsigned long number;
6316
6317 if ((number = check_iwmmxt_insn (str, check_textrc, 7)) == (unsigned long) FAIL)
6318 return;
6319
6320 inst.instruction |= number & 0x7;
6321 }
6322
6323 static void
6324 do_iwmmxt_textrm (str)
6325 char * str;
6326 {
6327 unsigned long number;
6328
6329 if ((number = check_iwmmxt_insn (str, check_textrm, 7)) == (unsigned long) FAIL)
6330 return;
6331
6332 inst.instruction |= number & 0x7;
6333 }
6334
6335 static void
6336 do_iwmmxt_tinsr (str)
6337 char * str;
6338 {
6339 unsigned long number;
6340
6341 if ((number = check_iwmmxt_insn (str, check_tinsr, 7)) == (unsigned long) FAIL)
6342 return;
6343
6344 inst.instruction |= number & 0x7;
6345 }
6346
6347 static void
6348 do_iwmmxt_tmcr (str)
6349 char * str;
6350 {
6351 check_iwmmxt_insn (str, check_tmcr, 0);
6352 }
6353
6354 static void
6355 do_iwmmxt_tmcrr (str)
6356 char * str;
6357 {
6358 check_iwmmxt_insn (str, check_tmcrr, 0);
6359 }
6360
6361 static void
6362 do_iwmmxt_tmia (str)
6363 char * str;
6364 {
6365 check_iwmmxt_insn (str, check_tmia, 0);
6366 }
6367
6368 static void
6369 do_iwmmxt_tmovmsk (str)
6370 char * str;
6371 {
6372 check_iwmmxt_insn (str, check_tmovmsk, 0);
6373 }
6374
6375 static void
6376 do_iwmmxt_tmrc (str)
6377 char * str;
6378 {
6379 check_iwmmxt_insn (str, check_tmrc, 0);
6380 }
6381
6382 static void
6383 do_iwmmxt_tmrrc (str)
6384 char * str;
6385 {
6386 check_iwmmxt_insn (str, check_tmrrc, 0);
6387 }
6388
6389 static void
6390 do_iwmmxt_torc (str)
6391 char * str;
6392 {
6393 check_iwmmxt_insn (str, check_rd, 0);
6394 }
6395
6396 static void
6397 do_iwmmxt_waligni (str)
6398 char * str;
6399 {
6400 unsigned long number;
6401
6402 if ((number = check_iwmmxt_insn (str, check_waligni, 7)) == (unsigned long) FAIL)
6403 return;
6404
6405 inst.instruction |= ((number & 0x7) << 20);
6406 }
6407
6408 static void
6409 do_iwmmxt_wmov (str)
6410 char * str;
6411 {
6412 if (check_iwmmxt_insn (str, check_wrwr, 0) == (unsigned long) FAIL)
6413 return;
6414
6415 inst.instruction |= ((inst.instruction >> 16) & 0xf);
6416 }
6417
6418 static void
6419 do_iwmmxt_word_addr (str)
6420 char * str;
6421 {
6422 int op = (inst.instruction & 0x300) >> 8;
6423 int reg;
6424
6425 inst.instruction &= ~0x300;
6426 inst.instruction |= (op & 1) << 22 | (op & 2) << 7;
6427
6428 skip_whitespace (str);
6429
6430 if ((reg = wreg_required_here (&str, 12, IWMMXT_REG_WR_OR_WC)) == FAIL
6431 || skip_past_comma (& str) == FAIL
6432 || cp_address_required_here (& str, CP_WB_OK) == FAIL)
6433 {
6434 if (! inst.error)
6435 inst.error = BAD_ARGS;
6436 }
6437 else
6438 end_of_line (str);
6439
6440 if (wc_register (reg))
6441 {
6442 if ((inst.instruction & COND_MASK) != COND_ALWAYS)
6443 as_bad (_("conditional execution not supported with control register"));
6444 if (op != 2)
6445 as_bad (_("non-word size not supported with control register"));
6446 inst.instruction |= 0xf0000100;
6447 inst.instruction &= ~0x00400000;
6448 }
6449 }
6450
6451 static void
6452 do_iwmmxt_wrwr (str)
6453 char * str;
6454 {
6455 check_iwmmxt_insn (str, check_wrwr, 0);
6456 }
6457
6458 static void
6459 do_iwmmxt_wrwrwcg (str)
6460 char * str;
6461 {
6462 check_iwmmxt_insn (str, check_wrwrwcg, 0);
6463 }
6464
6465 static void
6466 do_iwmmxt_wrwrwr (str)
6467 char * str;
6468 {
6469 check_iwmmxt_insn (str, check_wrwrwr, 0);
6470 }
6471
6472 static void
6473 do_iwmmxt_wshufh (str)
6474 char * str;
6475 {
6476 unsigned long number;
6477
6478 if ((number = check_iwmmxt_insn (str, check_wshufh, 0xff)) == (unsigned long) FAIL)
6479 return;
6480
6481 inst.instruction |= ((number & 0xf0) << 16) | (number & 0xf);
6482 }
6483
6484 static void
6485 do_iwmmxt_wzero (str)
6486 char * str;
6487 {
6488 if (check_iwmmxt_insn (str, check_wr, 0) == (unsigned long) FAIL)
6489 return;
6490
6491 inst.instruction |= ((inst.instruction & 0xf) << 12) | ((inst.instruction & 0xf) << 16);
6492 }
6493
6494 /* Xscale multiply-accumulate (argument parse)
6495 MIAcc acc0,Rm,Rs
6496 MIAPHcc acc0,Rm,Rs
6497 MIAxycc acc0,Rm,Rs. */
6498
6499 static void
6500 do_xsc_mia (str)
6501 char * str;
6502 {
6503 int rs;
6504 int rm;
6505
6506 if (accum0_required_here (& str) == FAIL)
6507 inst.error = ERR_NO_ACCUM;
6508
6509 else if (skip_past_comma (& str) == FAIL
6510 || (rm = reg_required_here (& str, 0)) == FAIL)
6511 inst.error = BAD_ARGS;
6512
6513 else if (skip_past_comma (& str) == FAIL
6514 || (rs = reg_required_here (& str, 12)) == FAIL)
6515 inst.error = BAD_ARGS;
6516
6517 /* inst.instruction has now been zapped with both rm and rs. */
6518 else if (rm == REG_PC || rs == REG_PC)
6519 inst.error = BAD_PC; /* Undefined result if rm or rs is R15. */
6520
6521 else
6522 end_of_line (str);
6523 }
6524
6525 /* Xscale move-accumulator-register (argument parse)
6526
6527 MARcc acc0,RdLo,RdHi. */
6528
6529 static void
6530 do_xsc_mar (str)
6531 char * str;
6532 {
6533 int rdlo, rdhi;
6534
6535 if (accum0_required_here (& str) == FAIL)
6536 inst.error = ERR_NO_ACCUM;
6537
6538 else if (skip_past_comma (& str) == FAIL
6539 || (rdlo = reg_required_here (& str, 12)) == FAIL)
6540 inst.error = BAD_ARGS;
6541
6542 else if (skip_past_comma (& str) == FAIL
6543 || (rdhi = reg_required_here (& str, 16)) == FAIL)
6544 inst.error = BAD_ARGS;
6545
6546 /* inst.instruction has now been zapped with both rdlo and rdhi. */
6547 else if (rdlo == REG_PC || rdhi == REG_PC)
6548 inst.error = BAD_PC; /* Undefined result if rdlo or rdhi is R15. */
6549
6550 else
6551 end_of_line (str);
6552 }
6553
6554 /* Xscale move-register-accumulator (argument parse)
6555
6556 MRAcc RdLo,RdHi,acc0. */
6557
6558 static void
6559 do_xsc_mra (str)
6560 char * str;
6561 {
6562 int rdlo;
6563 int rdhi;
6564
6565 skip_whitespace (str);
6566
6567 if ((rdlo = reg_required_here (& str, 12)) == FAIL)
6568 inst.error = BAD_ARGS;
6569
6570 else if (skip_past_comma (& str) == FAIL
6571 || (rdhi = reg_required_here (& str, 16)) == FAIL)
6572 inst.error = BAD_ARGS;
6573
6574 else if (skip_past_comma (& str) == FAIL
6575 || accum0_required_here (& str) == FAIL)
6576 inst.error = ERR_NO_ACCUM;
6577
6578 /* inst.instruction has now been zapped with both rdlo and rdhi. */
6579 else if (rdlo == rdhi)
6580 inst.error = BAD_ARGS; /* Undefined result if 2 writes to same reg. */
6581
6582 else if (rdlo == REG_PC || rdhi == REG_PC)
6583 inst.error = BAD_PC; /* Undefined result if rdlo or rdhi is R15. */
6584 else
6585 end_of_line (str);
6586 }
6587
6588 /* ARMv5TE: Preload-Cache
6589
6590 PLD <addr_mode>
6591
6592 Syntactically, like LDR with B=1, W=0, L=1. */
6593
6594 static void
6595 do_pld (str)
6596 char * str;
6597 {
6598 int rd;
6599
6600 skip_whitespace (str);
6601
6602 if (* str != '[')
6603 {
6604 inst.error = _("'[' expected after PLD mnemonic");
6605 return;
6606 }
6607
6608 ++str;
6609 skip_whitespace (str);
6610
6611 if ((rd = reg_required_here (& str, 16)) == FAIL)
6612 return;
6613
6614 skip_whitespace (str);
6615
6616 if (*str == ']')
6617 {
6618 /* [Rn], ... ? */
6619 ++str;
6620 skip_whitespace (str);
6621
6622 /* Post-indexed addressing is not allowed with PLD. */
6623 if (skip_past_comma (&str) == SUCCESS)
6624 {
6625 inst.error
6626 = _("post-indexed expression used in preload instruction");
6627 return;
6628 }
6629 else if (*str == '!') /* [Rn]! */
6630 {
6631 inst.error = _("writeback used in preload instruction");
6632 ++str;
6633 }
6634 else /* [Rn] */
6635 inst.instruction |= INDEX_UP | PRE_INDEX;
6636 }
6637 else /* [Rn, ...] */
6638 {
6639 if (skip_past_comma (& str) == FAIL)
6640 {
6641 inst.error = _("pre-indexed expression expected");
6642 return;
6643 }
6644
6645 if (ldst_extend (&str) == FAIL)
6646 return;
6647
6648 skip_whitespace (str);
6649
6650 if (* str != ']')
6651 {
6652 inst.error = _("missing ]");
6653 return;
6654 }
6655
6656 ++ str;
6657 skip_whitespace (str);
6658
6659 if (* str == '!') /* [Rn]! */
6660 {
6661 inst.error = _("writeback used in preload instruction");
6662 ++ str;
6663 }
6664
6665 inst.instruction |= PRE_INDEX;
6666 }
6667
6668 end_of_line (str);
6669 }
6670
6671 /* ARMv5TE load-consecutive (argument parse)
6672 Mode is like LDRH.
6673
6674 LDRccD R, mode
6675 STRccD R, mode. */
6676
6677 static void
6678 do_ldrd (str)
6679 char * str;
6680 {
6681 int rd;
6682 int rn;
6683
6684 skip_whitespace (str);
6685
6686 if ((rd = reg_required_here (& str, 12)) == FAIL)
6687 {
6688 inst.error = BAD_ARGS;
6689 return;
6690 }
6691
6692 if (skip_past_comma (& str) == FAIL
6693 || (rn = ld_mode_required_here (& str)) == FAIL)
6694 {
6695 if (!inst.error)
6696 inst.error = BAD_ARGS;
6697 return;
6698 }
6699
6700 /* inst.instruction has now been zapped with Rd and the addressing mode. */
6701 if (rd & 1) /* Unpredictable result if Rd is odd. */
6702 {
6703 inst.error = _("destination register must be even");
6704 return;
6705 }
6706
6707 if (rd == REG_LR)
6708 {
6709 inst.error = _("r14 not allowed here");
6710 return;
6711 }
6712
6713 if (((rd == rn) || (rd + 1 == rn))
6714 && ((inst.instruction & WRITE_BACK)
6715 || (!(inst.instruction & PRE_INDEX))))
6716 as_warn (_("pre/post-indexing used when modified address register is destination"));
6717
6718 /* For an index-register load, the index register must not overlap the
6719 destination (even if not write-back). */
6720 if ((inst.instruction & V4_STR_BIT) == 0
6721 && (inst.instruction & HWOFFSET_IMM) == 0)
6722 {
6723 int rm = inst.instruction & 0x0000000f;
6724
6725 if (rm == rd || (rm == rd + 1))
6726 as_warn (_("ldrd destination registers must not overlap index register"));
6727 }
6728
6729 end_of_line (str);
6730 }
6731
6732 /* Returns the index into fp_values of a floating point number,
6733 or -1 if not in the table. */
6734
6735 static int
6736 my_get_float_expression (str)
6737 char ** str;
6738 {
6739 LITTLENUM_TYPE words[MAX_LITTLENUMS];
6740 char * save_in;
6741 expressionS exp;
6742 int i;
6743 int j;
6744
6745 memset (words, 0, MAX_LITTLENUMS * sizeof (LITTLENUM_TYPE));
6746
6747 /* Look for a raw floating point number. */
6748 if ((save_in = atof_ieee (*str, 'x', words)) != NULL
6749 && is_end_of_line[(unsigned char) *save_in])
6750 {
6751 for (i = 0; i < NUM_FLOAT_VALS; i++)
6752 {
6753 for (j = 0; j < MAX_LITTLENUMS; j++)
6754 {
6755 if (words[j] != fp_values[i][j])
6756 break;
6757 }
6758
6759 if (j == MAX_LITTLENUMS)
6760 {
6761 *str = save_in;
6762 return i;
6763 }
6764 }
6765 }
6766
6767 /* Try and parse a more complex expression, this will probably fail
6768 unless the code uses a floating point prefix (eg "0f"). */
6769 save_in = input_line_pointer;
6770 input_line_pointer = *str;
6771 if (expression (&exp) == absolute_section
6772 && exp.X_op == O_big
6773 && exp.X_add_number < 0)
6774 {
6775 /* FIXME: 5 = X_PRECISION, should be #define'd where we can use it.
6776 Ditto for 15. */
6777 if (gen_to_words (words, 5, (long) 15) == 0)
6778 {
6779 for (i = 0; i < NUM_FLOAT_VALS; i++)
6780 {
6781 for (j = 0; j < MAX_LITTLENUMS; j++)
6782 {
6783 if (words[j] != fp_values[i][j])
6784 break;
6785 }
6786
6787 if (j == MAX_LITTLENUMS)
6788 {
6789 *str = input_line_pointer;
6790 input_line_pointer = save_in;
6791 return i;
6792 }
6793 }
6794 }
6795 }
6796
6797 *str = input_line_pointer;
6798 input_line_pointer = save_in;
6799 return -1;
6800 }
6801
6802 /* Return TRUE if anything in the expression is a bignum. */
6803
6804 static int
6805 walk_no_bignums (sp)
6806 symbolS * sp;
6807 {
6808 if (symbol_get_value_expression (sp)->X_op == O_big)
6809 return 1;
6810
6811 if (symbol_get_value_expression (sp)->X_add_symbol)
6812 {
6813 return (walk_no_bignums (symbol_get_value_expression (sp)->X_add_symbol)
6814 || (symbol_get_value_expression (sp)->X_op_symbol
6815 && walk_no_bignums (symbol_get_value_expression (sp)->X_op_symbol)));
6816 }
6817
6818 return 0;
6819 }
6820
6821 static int in_my_get_expression = 0;
6822
6823 static int
6824 my_get_expression (ep, str)
6825 expressionS * ep;
6826 char ** str;
6827 {
6828 char * save_in;
6829 segT seg;
6830
6831 save_in = input_line_pointer;
6832 input_line_pointer = *str;
6833 in_my_get_expression = 1;
6834 seg = expression (ep);
6835 in_my_get_expression = 0;
6836
6837 if (ep->X_op == O_illegal)
6838 {
6839 /* We found a bad expression in md_operand(). */
6840 *str = input_line_pointer;
6841 input_line_pointer = save_in;
6842 return 1;
6843 }
6844
6845 #ifdef OBJ_AOUT
6846 if (seg != absolute_section
6847 && seg != text_section
6848 && seg != data_section
6849 && seg != bss_section
6850 && seg != undefined_section)
6851 {
6852 inst.error = _("bad_segment");
6853 *str = input_line_pointer;
6854 input_line_pointer = save_in;
6855 return 1;
6856 }
6857 #endif
6858
6859 /* Get rid of any bignums now, so that we don't generate an error for which
6860 we can't establish a line number later on. Big numbers are never valid
6861 in instructions, which is where this routine is always called. */
6862 if (ep->X_op == O_big
6863 || (ep->X_add_symbol
6864 && (walk_no_bignums (ep->X_add_symbol)
6865 || (ep->X_op_symbol
6866 && walk_no_bignums (ep->X_op_symbol)))))
6867 {
6868 inst.error = _("invalid constant");
6869 *str = input_line_pointer;
6870 input_line_pointer = save_in;
6871 return 1;
6872 }
6873
6874 *str = input_line_pointer;
6875 input_line_pointer = save_in;
6876 return 0;
6877 }
6878
6879 /* We handle all bad expressions here, so that we can report the faulty
6880 instruction in the error message. */
6881 void
6882 md_operand (expr)
6883 expressionS *expr;
6884 {
6885 if (in_my_get_expression)
6886 {
6887 expr->X_op = O_illegal;
6888 if (inst.error == NULL)
6889 inst.error = _("bad expression");
6890 }
6891 }
6892
6893 /* KIND indicates what kind of shifts are accepted. */
6894
6895 static int
6896 decode_shift (str, kind)
6897 char ** str;
6898 int kind;
6899 {
6900 const struct asm_shift_name * shift;
6901 char * p;
6902 char c;
6903
6904 skip_whitespace (* str);
6905
6906 for (p = * str; ISALPHA (* p); p ++)
6907 ;
6908
6909 if (p == * str)
6910 {
6911 inst.error = _("shift expression expected");
6912 return FAIL;
6913 }
6914
6915 c = * p;
6916 * p = '\0';
6917 shift = (const struct asm_shift_name *) hash_find (arm_shift_hsh, * str);
6918 * p = c;
6919
6920 if (shift == NULL)
6921 {
6922 inst.error = _("shift expression expected");
6923 return FAIL;
6924 }
6925
6926 assert (shift->properties->index == shift_properties[shift->properties->index].index);
6927
6928 if (kind == SHIFT_LSL_OR_ASR_IMMEDIATE
6929 && shift->properties->index != SHIFT_LSL
6930 && shift->properties->index != SHIFT_ASR)
6931 {
6932 inst.error = _("'LSL' or 'ASR' required");
6933 return FAIL;
6934 }
6935 else if (kind == SHIFT_LSL_IMMEDIATE
6936 && shift->properties->index != SHIFT_LSL)
6937 {
6938 inst.error = _("'LSL' required");
6939 return FAIL;
6940 }
6941 else if (kind == SHIFT_ASR_IMMEDIATE
6942 && shift->properties->index != SHIFT_ASR)
6943 {
6944 inst.error = _("'ASR' required");
6945 return FAIL;
6946 }
6947
6948 if (shift->properties->index == SHIFT_RRX)
6949 {
6950 * str = p;
6951 inst.instruction |= shift->properties->bit_field;
6952 return SUCCESS;
6953 }
6954
6955 skip_whitespace (p);
6956
6957 if (kind == NO_SHIFT_RESTRICT && reg_required_here (& p, 8) != FAIL)
6958 {
6959 inst.instruction |= shift->properties->bit_field | SHIFT_BY_REG;
6960 * str = p;
6961 return SUCCESS;
6962 }
6963 else if (! is_immediate_prefix (* p))
6964 {
6965 inst.error = (NO_SHIFT_RESTRICT
6966 ? _("shift requires register or #expression")
6967 : _("shift requires #expression"));
6968 * str = p;
6969 return FAIL;
6970 }
6971
6972 inst.error = NULL;
6973 p ++;
6974
6975 if (my_get_expression (& inst.reloc.exp, & p))
6976 return FAIL;
6977
6978 /* Validate some simple #expressions. */
6979 if (inst.reloc.exp.X_op == O_constant)
6980 {
6981 unsigned num = inst.reloc.exp.X_add_number;
6982
6983 /* Reject operations greater than 32. */
6984 if (num > 32
6985 /* Reject a shift of 0 unless the mode allows it. */
6986 || (num == 0 && shift->properties->allows_0 == 0)
6987 /* Reject a shift of 32 unless the mode allows it. */
6988 || (num == 32 && shift->properties->allows_32 == 0)
6989 )
6990 {
6991 /* As a special case we allow a shift of zero for
6992 modes that do not support it to be recoded as an
6993 logical shift left of zero (ie nothing). We warn
6994 about this though. */
6995 if (num == 0)
6996 {
6997 as_warn (_("shift of 0 ignored."));
6998 shift = & shift_names[0];
6999 assert (shift->properties->index == SHIFT_LSL);
7000 }
7001 else
7002 {
7003 inst.error = _("invalid immediate shift");
7004 return FAIL;
7005 }
7006 }
7007
7008 /* Shifts of 32 are encoded as 0, for those shifts that
7009 support it. */
7010 if (num == 32)
7011 num = 0;
7012
7013 inst.instruction |= (num << 7) | shift->properties->bit_field;
7014 }
7015 else
7016 {
7017 inst.reloc.type = BFD_RELOC_ARM_SHIFT_IMM;
7018 inst.reloc.pc_rel = 0;
7019 inst.instruction |= shift->properties->bit_field;
7020 }
7021
7022 * str = p;
7023 return SUCCESS;
7024 }
7025
7026 /* Do those data_ops which can take a negative immediate constant
7027 by altering the instruction. A bit of a hack really.
7028 MOV <-> MVN
7029 AND <-> BIC
7030 ADC <-> SBC
7031 by inverting the second operand, and
7032 ADD <-> SUB
7033 CMP <-> CMN
7034 by negating the second operand. */
7035
7036 static int
7037 negate_data_op (instruction, value)
7038 unsigned long * instruction;
7039 unsigned long value;
7040 {
7041 int op, new_inst;
7042 unsigned long negated, inverted;
7043
7044 negated = validate_immediate (-value);
7045 inverted = validate_immediate (~value);
7046
7047 op = (*instruction >> DATA_OP_SHIFT) & 0xf;
7048 switch (op)
7049 {
7050 /* First negates. */
7051 case OPCODE_SUB: /* ADD <-> SUB */
7052 new_inst = OPCODE_ADD;
7053 value = negated;
7054 break;
7055
7056 case OPCODE_ADD:
7057 new_inst = OPCODE_SUB;
7058 value = negated;
7059 break;
7060
7061 case OPCODE_CMP: /* CMP <-> CMN */
7062 new_inst = OPCODE_CMN;
7063 value = negated;
7064 break;
7065
7066 case OPCODE_CMN:
7067 new_inst = OPCODE_CMP;
7068 value = negated;
7069 break;
7070
7071 /* Now Inverted ops. */
7072 case OPCODE_MOV: /* MOV <-> MVN */
7073 new_inst = OPCODE_MVN;
7074 value = inverted;
7075 break;
7076
7077 case OPCODE_MVN:
7078 new_inst = OPCODE_MOV;
7079 value = inverted;
7080 break;
7081
7082 case OPCODE_AND: /* AND <-> BIC */
7083 new_inst = OPCODE_BIC;
7084 value = inverted;
7085 break;
7086
7087 case OPCODE_BIC:
7088 new_inst = OPCODE_AND;
7089 value = inverted;
7090 break;
7091
7092 case OPCODE_ADC: /* ADC <-> SBC */
7093 new_inst = OPCODE_SBC;
7094 value = inverted;
7095 break;
7096
7097 case OPCODE_SBC:
7098 new_inst = OPCODE_ADC;
7099 value = inverted;
7100 break;
7101
7102 /* We cannot do anything. */
7103 default:
7104 return FAIL;
7105 }
7106
7107 if (value == (unsigned) FAIL)
7108 return FAIL;
7109
7110 *instruction &= OPCODE_MASK;
7111 *instruction |= new_inst << DATA_OP_SHIFT;
7112 return value;
7113 }
7114
7115 static int
7116 data_op2 (str)
7117 char ** str;
7118 {
7119 int value;
7120 expressionS expr;
7121
7122 skip_whitespace (* str);
7123
7124 if (reg_required_here (str, 0) != FAIL)
7125 {
7126 if (skip_past_comma (str) == SUCCESS)
7127 /* Shift operation on register. */
7128 return decode_shift (str, NO_SHIFT_RESTRICT);
7129
7130 return SUCCESS;
7131 }
7132 else
7133 {
7134 /* Immediate expression. */
7135 if (is_immediate_prefix (**str))
7136 {
7137 (*str)++;
7138 inst.error = NULL;
7139
7140 if (my_get_expression (&inst.reloc.exp, str))
7141 return FAIL;
7142
7143 if (inst.reloc.exp.X_add_symbol)
7144 {
7145 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
7146 inst.reloc.pc_rel = 0;
7147 }
7148 else
7149 {
7150 if (skip_past_comma (str) == SUCCESS)
7151 {
7152 /* #x, y -- ie explicit rotation by Y. */
7153 if (my_get_expression (&expr, str))
7154 return FAIL;
7155
7156 if (expr.X_op != O_constant)
7157 {
7158 inst.error = _("constant expression expected");
7159 return FAIL;
7160 }
7161
7162 /* Rotate must be a multiple of 2. */
7163 if (((unsigned) expr.X_add_number) > 30
7164 || (expr.X_add_number & 1) != 0
7165 || ((unsigned) inst.reloc.exp.X_add_number) > 255)
7166 {
7167 inst.error = _("invalid constant");
7168 return FAIL;
7169 }
7170 inst.instruction |= INST_IMMEDIATE;
7171 inst.instruction |= inst.reloc.exp.X_add_number;
7172 inst.instruction |= expr.X_add_number << 7;
7173 return SUCCESS;
7174 }
7175
7176 /* Implicit rotation, select a suitable one. */
7177 value = validate_immediate (inst.reloc.exp.X_add_number);
7178
7179 if (value == FAIL)
7180 {
7181 /* Can't be done. Perhaps the code reads something like
7182 "add Rd, Rn, #-n", where "sub Rd, Rn, #n" would be OK. */
7183 if ((value = negate_data_op (&inst.instruction,
7184 inst.reloc.exp.X_add_number))
7185 == FAIL)
7186 {
7187 inst.error = _("invalid constant");
7188 return FAIL;
7189 }
7190 }
7191
7192 inst.instruction |= value;
7193 }
7194
7195 inst.instruction |= INST_IMMEDIATE;
7196 return SUCCESS;
7197 }
7198
7199 (*str)++;
7200 inst.error = _("register or shift expression expected");
7201 return FAIL;
7202 }
7203 }
7204
7205 static int
7206 fp_op2 (str)
7207 char ** str;
7208 {
7209 skip_whitespace (* str);
7210
7211 if (fp_reg_required_here (str, 0) != FAIL)
7212 return SUCCESS;
7213 else
7214 {
7215 /* Immediate expression. */
7216 if (*((*str)++) == '#')
7217 {
7218 int i;
7219
7220 inst.error = NULL;
7221
7222 skip_whitespace (* str);
7223
7224 /* First try and match exact strings, this is to guarantee
7225 that some formats will work even for cross assembly. */
7226
7227 for (i = 0; fp_const[i]; i++)
7228 {
7229 if (strncmp (*str, fp_const[i], strlen (fp_const[i])) == 0)
7230 {
7231 char *start = *str;
7232
7233 *str += strlen (fp_const[i]);
7234 if (is_end_of_line[(unsigned char) **str])
7235 {
7236 inst.instruction |= i + 8;
7237 return SUCCESS;
7238 }
7239 *str = start;
7240 }
7241 }
7242
7243 /* Just because we didn't get a match doesn't mean that the
7244 constant isn't valid, just that it is in a format that we
7245 don't automatically recognize. Try parsing it with
7246 the standard expression routines. */
7247 if ((i = my_get_float_expression (str)) >= 0)
7248 {
7249 inst.instruction |= i + 8;
7250 return SUCCESS;
7251 }
7252
7253 inst.error = _("invalid floating point immediate expression");
7254 return FAIL;
7255 }
7256 inst.error =
7257 _("floating point register or immediate expression expected");
7258 return FAIL;
7259 }
7260 }
7261
7262 static void
7263 do_arit (str)
7264 char * str;
7265 {
7266 skip_whitespace (str);
7267
7268 if (reg_required_here (&str, 12) == FAIL
7269 || skip_past_comma (&str) == FAIL
7270 || reg_required_here (&str, 16) == FAIL
7271 || skip_past_comma (&str) == FAIL
7272 || data_op2 (&str) == FAIL)
7273 {
7274 if (!inst.error)
7275 inst.error = BAD_ARGS;
7276 return;
7277 }
7278
7279 end_of_line (str);
7280 }
7281
7282 static void
7283 do_adr (str)
7284 char * str;
7285 {
7286 /* This is a pseudo-op of the form "adr rd, label" to be converted
7287 into a relative address of the form "add rd, pc, #label-.-8". */
7288 skip_whitespace (str);
7289
7290 if (reg_required_here (&str, 12) == FAIL
7291 || skip_past_comma (&str) == FAIL
7292 || my_get_expression (&inst.reloc.exp, &str))
7293 {
7294 if (!inst.error)
7295 inst.error = BAD_ARGS;
7296 return;
7297 }
7298
7299 /* Frag hacking will turn this into a sub instruction if the offset turns
7300 out to be negative. */
7301 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
7302 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust. */
7303 inst.reloc.pc_rel = 1;
7304
7305 end_of_line (str);
7306 }
7307
7308 static void
7309 do_adrl (str)
7310 char * str;
7311 {
7312 /* This is a pseudo-op of the form "adrl rd, label" to be converted
7313 into a relative address of the form:
7314 add rd, pc, #low(label-.-8)"
7315 add rd, rd, #high(label-.-8)" */
7316
7317 skip_whitespace (str);
7318
7319 if (reg_required_here (&str, 12) == FAIL
7320 || skip_past_comma (&str) == FAIL
7321 || my_get_expression (&inst.reloc.exp, &str))
7322 {
7323 if (!inst.error)
7324 inst.error = BAD_ARGS;
7325
7326 return;
7327 }
7328
7329 end_of_line (str);
7330 /* Frag hacking will turn this into a sub instruction if the offset turns
7331 out to be negative. */
7332 inst.reloc.type = BFD_RELOC_ARM_ADRL_IMMEDIATE;
7333 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust */
7334 inst.reloc.pc_rel = 1;
7335 inst.size = INSN_SIZE * 2;
7336 }
7337
7338 static void
7339 do_cmp (str)
7340 char * str;
7341 {
7342 skip_whitespace (str);
7343
7344 if (reg_required_here (&str, 16) == FAIL)
7345 {
7346 if (!inst.error)
7347 inst.error = BAD_ARGS;
7348 return;
7349 }
7350
7351 if (skip_past_comma (&str) == FAIL
7352 || data_op2 (&str) == FAIL)
7353 {
7354 if (!inst.error)
7355 inst.error = BAD_ARGS;
7356 return;
7357 }
7358
7359 end_of_line (str);
7360 }
7361
7362 static void
7363 do_mov (str)
7364 char * str;
7365 {
7366 skip_whitespace (str);
7367
7368 if (reg_required_here (&str, 12) == FAIL)
7369 {
7370 if (!inst.error)
7371 inst.error = BAD_ARGS;
7372 return;
7373 }
7374
7375 if (skip_past_comma (&str) == FAIL
7376 || data_op2 (&str) == FAIL)
7377 {
7378 if (!inst.error)
7379 inst.error = BAD_ARGS;
7380 return;
7381 }
7382
7383 end_of_line (str);
7384 }
7385
7386 static int
7387 ldst_extend (str)
7388 char ** str;
7389 {
7390 int add = INDEX_UP;
7391
7392 switch (**str)
7393 {
7394 case '#':
7395 case '$':
7396 (*str)++;
7397 if (my_get_expression (& inst.reloc.exp, str))
7398 return FAIL;
7399
7400 if (inst.reloc.exp.X_op == O_constant)
7401 {
7402 int value = inst.reloc.exp.X_add_number;
7403
7404 if (value < -4095 || value > 4095)
7405 {
7406 inst.error = _("address offset too large");
7407 return FAIL;
7408 }
7409
7410 if (value < 0)
7411 {
7412 value = -value;
7413 add = 0;
7414 }
7415
7416 inst.instruction |= add | value;
7417 }
7418 else
7419 {
7420 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
7421 inst.reloc.pc_rel = 0;
7422 }
7423 return SUCCESS;
7424
7425 case '-':
7426 add = 0;
7427 /* Fall through. */
7428
7429 case '+':
7430 (*str)++;
7431 /* Fall through. */
7432
7433 default:
7434 if (reg_required_here (str, 0) == FAIL)
7435 return FAIL;
7436
7437 inst.instruction |= add | OFFSET_REG;
7438 if (skip_past_comma (str) == SUCCESS)
7439 return decode_shift (str, SHIFT_IMMEDIATE);
7440
7441 return SUCCESS;
7442 }
7443 }
7444
7445 static void
7446 do_ldst (str)
7447 char * str;
7448 {
7449 int pre_inc = 0;
7450 int conflict_reg;
7451 int value;
7452
7453 skip_whitespace (str);
7454
7455 if ((conflict_reg = reg_required_here (&str, 12)) == FAIL)
7456 {
7457 if (!inst.error)
7458 inst.error = BAD_ARGS;
7459 return;
7460 }
7461
7462 if (skip_past_comma (&str) == FAIL)
7463 {
7464 inst.error = _("address expected");
7465 return;
7466 }
7467
7468 if (*str == '[')
7469 {
7470 int reg;
7471
7472 str++;
7473
7474 skip_whitespace (str);
7475
7476 if ((reg = reg_required_here (&str, 16)) == FAIL)
7477 return;
7478
7479 /* Conflicts can occur on stores as well as loads. */
7480 conflict_reg = (conflict_reg == reg);
7481
7482 skip_whitespace (str);
7483
7484 if (*str == ']')
7485 {
7486 str ++;
7487
7488 if (skip_past_comma (&str) == SUCCESS)
7489 {
7490 /* [Rn],... (post inc) */
7491 if (ldst_extend (&str) == FAIL)
7492 return;
7493 if (conflict_reg)
7494 as_warn (_("%s register same as write-back base"),
7495 ((inst.instruction & LOAD_BIT)
7496 ? _("destination") : _("source")));
7497 }
7498 else
7499 {
7500 /* [Rn] */
7501 skip_whitespace (str);
7502
7503 if (*str == '!')
7504 {
7505 if (conflict_reg)
7506 as_warn (_("%s register same as write-back base"),
7507 ((inst.instruction & LOAD_BIT)
7508 ? _("destination") : _("source")));
7509 str++;
7510 inst.instruction |= WRITE_BACK;
7511 }
7512
7513 inst.instruction |= INDEX_UP;
7514 pre_inc = 1;
7515 }
7516 }
7517 else
7518 {
7519 /* [Rn,...] */
7520 if (skip_past_comma (&str) == FAIL)
7521 {
7522 inst.error = _("pre-indexed expression expected");
7523 return;
7524 }
7525
7526 pre_inc = 1;
7527 if (ldst_extend (&str) == FAIL)
7528 return;
7529
7530 skip_whitespace (str);
7531
7532 if (*str++ != ']')
7533 {
7534 inst.error = _("missing ]");
7535 return;
7536 }
7537
7538 skip_whitespace (str);
7539
7540 if (*str == '!')
7541 {
7542 if (conflict_reg)
7543 as_warn (_("%s register same as write-back base"),
7544 ((inst.instruction & LOAD_BIT)
7545 ? _("destination") : _("source")));
7546 str++;
7547 inst.instruction |= WRITE_BACK;
7548 }
7549 }
7550 }
7551 else if (*str == '=')
7552 {
7553 if ((inst.instruction & LOAD_BIT) == 0)
7554 {
7555 inst.error = _("invalid pseudo operation");
7556 return;
7557 }
7558
7559 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
7560 str++;
7561
7562 skip_whitespace (str);
7563
7564 if (my_get_expression (&inst.reloc.exp, &str))
7565 return;
7566
7567 if (inst.reloc.exp.X_op != O_constant
7568 && inst.reloc.exp.X_op != O_symbol)
7569 {
7570 inst.error = _("constant expression expected");
7571 return;
7572 }
7573
7574 if (inst.reloc.exp.X_op == O_constant)
7575 {
7576 value = validate_immediate (inst.reloc.exp.X_add_number);
7577
7578 if (value != FAIL)
7579 {
7580 /* This can be done with a mov instruction. */
7581 inst.instruction &= LITERAL_MASK;
7582 inst.instruction |= (INST_IMMEDIATE
7583 | (OPCODE_MOV << DATA_OP_SHIFT));
7584 inst.instruction |= value & 0xfff;
7585 end_of_line (str);
7586 return;
7587 }
7588
7589 value = validate_immediate (~inst.reloc.exp.X_add_number);
7590
7591 if (value != FAIL)
7592 {
7593 /* This can be done with a mvn instruction. */
7594 inst.instruction &= LITERAL_MASK;
7595 inst.instruction |= (INST_IMMEDIATE
7596 | (OPCODE_MVN << DATA_OP_SHIFT));
7597 inst.instruction |= value & 0xfff;
7598 end_of_line (str);
7599 return;
7600 }
7601 }
7602
7603 /* Insert into literal pool. */
7604 if (add_to_lit_pool () == FAIL)
7605 {
7606 if (!inst.error)
7607 inst.error = _("literal pool insertion failed");
7608 return;
7609 }
7610
7611 /* Change the instruction exp to point to the pool. */
7612 inst.reloc.type = BFD_RELOC_ARM_LITERAL;
7613 inst.reloc.pc_rel = 1;
7614 inst.instruction |= (REG_PC << 16);
7615 pre_inc = 1;
7616 }
7617 else
7618 {
7619 if (my_get_expression (&inst.reloc.exp, &str))
7620 return;
7621
7622 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
7623 #ifndef TE_WINCE
7624 /* PC rel adjust. */
7625 inst.reloc.exp.X_add_number -= 8;
7626 #endif
7627 inst.reloc.pc_rel = 1;
7628 inst.instruction |= (REG_PC << 16);
7629 pre_inc = 1;
7630 }
7631
7632 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
7633 end_of_line (str);
7634 }
7635
7636 static void
7637 do_ldstt (str)
7638 char * str;
7639 {
7640 int conflict_reg;
7641
7642 skip_whitespace (str);
7643
7644 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
7645 {
7646 if (!inst.error)
7647 inst.error = BAD_ARGS;
7648 return;
7649 }
7650
7651 if (skip_past_comma (& str) == FAIL)
7652 {
7653 inst.error = _("address expected");
7654 return;
7655 }
7656
7657 if (*str == '[')
7658 {
7659 int reg;
7660
7661 str++;
7662
7663 skip_whitespace (str);
7664
7665 if ((reg = reg_required_here (&str, 16)) == FAIL)
7666 return;
7667
7668 /* ldrt/strt always use post-indexed addressing, so if the base is
7669 the same as Rd, we warn. */
7670 if (conflict_reg == reg)
7671 as_warn (_("%s register same as write-back base"),
7672 ((inst.instruction & LOAD_BIT)
7673 ? _("destination") : _("source")));
7674
7675 skip_whitespace (str);
7676
7677 if (*str == ']')
7678 {
7679 str ++;
7680
7681 if (skip_past_comma (&str) == SUCCESS)
7682 {
7683 /* [Rn],... (post inc) */
7684 if (ldst_extend (&str) == FAIL)
7685 return;
7686 }
7687 else
7688 {
7689 /* [Rn] */
7690 skip_whitespace (str);
7691
7692 /* Skip a write-back '!'. */
7693 if (*str == '!')
7694 str++;
7695
7696 inst.instruction |= INDEX_UP;
7697 }
7698 }
7699 else
7700 {
7701 inst.error = _("post-indexed expression expected");
7702 return;
7703 }
7704 }
7705 else
7706 {
7707 inst.error = _("post-indexed expression expected");
7708 return;
7709 }
7710
7711 end_of_line (str);
7712 }
7713
7714 static int
7715 ldst_extend_v4 (str)
7716 char ** str;
7717 {
7718 int add = INDEX_UP;
7719
7720 switch (**str)
7721 {
7722 case '#':
7723 case '$':
7724 (*str)++;
7725 if (my_get_expression (& inst.reloc.exp, str))
7726 return FAIL;
7727
7728 if (inst.reloc.exp.X_op == O_constant)
7729 {
7730 int value = inst.reloc.exp.X_add_number;
7731
7732 if (value < -255 || value > 255)
7733 {
7734 inst.error = _("address offset too large");
7735 return FAIL;
7736 }
7737
7738 if (value < 0)
7739 {
7740 value = -value;
7741 add = 0;
7742 }
7743
7744 /* Halfword and signextension instructions have the
7745 immediate value split across bits 11..8 and bits 3..0. */
7746 inst.instruction |= (add | HWOFFSET_IMM
7747 | ((value >> 4) << 8) | (value & 0xF));
7748 }
7749 else
7750 {
7751 inst.instruction |= HWOFFSET_IMM;
7752 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
7753 inst.reloc.pc_rel = 0;
7754 }
7755 return SUCCESS;
7756
7757 case '-':
7758 add = 0;
7759 /* Fall through. */
7760
7761 case '+':
7762 (*str)++;
7763 /* Fall through. */
7764
7765 default:
7766 if (reg_required_here (str, 0) == FAIL)
7767 return FAIL;
7768
7769 inst.instruction |= add;
7770 return SUCCESS;
7771 }
7772 }
7773
7774 /* Halfword and signed-byte load/store operations. */
7775 static void
7776 do_ldstv4 (str)
7777 char * str;
7778 {
7779 int pre_inc = 0;
7780 int conflict_reg;
7781 int value;
7782
7783 skip_whitespace (str);
7784
7785 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
7786 {
7787 if (!inst.error)
7788 inst.error = BAD_ARGS;
7789 return;
7790 }
7791
7792 if (skip_past_comma (& str) == FAIL)
7793 {
7794 inst.error = _("address expected");
7795 return;
7796 }
7797
7798 if (*str == '[')
7799 {
7800 int reg;
7801
7802 str++;
7803
7804 skip_whitespace (str);
7805
7806 if ((reg = reg_required_here (&str, 16)) == FAIL)
7807 return;
7808
7809 /* Conflicts can occur on stores as well as loads. */
7810 conflict_reg = (conflict_reg == reg);
7811
7812 skip_whitespace (str);
7813
7814 if (*str == ']')
7815 {
7816 str ++;
7817
7818 if (skip_past_comma (&str) == SUCCESS)
7819 {
7820 /* [Rn],... (post inc) */
7821 if (ldst_extend_v4 (&str) == FAIL)
7822 return;
7823 if (conflict_reg)
7824 as_warn (_("%s register same as write-back base"),
7825 ((inst.instruction & LOAD_BIT)
7826 ? _("destination") : _("source")));
7827 }
7828 else
7829 {
7830 /* [Rn] */
7831 inst.instruction |= HWOFFSET_IMM;
7832
7833 skip_whitespace (str);
7834
7835 if (*str == '!')
7836 {
7837 if (conflict_reg)
7838 as_warn (_("%s register same as write-back base"),
7839 ((inst.instruction & LOAD_BIT)
7840 ? _("destination") : _("source")));
7841 str++;
7842 inst.instruction |= WRITE_BACK;
7843 }
7844
7845 inst.instruction |= INDEX_UP;
7846 pre_inc = 1;
7847 }
7848 }
7849 else
7850 {
7851 /* [Rn,...] */
7852 if (skip_past_comma (&str) == FAIL)
7853 {
7854 inst.error = _("pre-indexed expression expected");
7855 return;
7856 }
7857
7858 pre_inc = 1;
7859 if (ldst_extend_v4 (&str) == FAIL)
7860 return;
7861
7862 skip_whitespace (str);
7863
7864 if (*str++ != ']')
7865 {
7866 inst.error = _("missing ]");
7867 return;
7868 }
7869
7870 skip_whitespace (str);
7871
7872 if (*str == '!')
7873 {
7874 if (conflict_reg)
7875 as_warn (_("%s register same as write-back base"),
7876 ((inst.instruction & LOAD_BIT)
7877 ? _("destination") : _("source")));
7878 str++;
7879 inst.instruction |= WRITE_BACK;
7880 }
7881 }
7882 }
7883 else if (*str == '=')
7884 {
7885 if ((inst.instruction & LOAD_BIT) == 0)
7886 {
7887 inst.error = _("invalid pseudo operation");
7888 return;
7889 }
7890
7891 /* XXX Does this work correctly for half-word/byte ops? */
7892 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
7893 str++;
7894
7895 skip_whitespace (str);
7896
7897 if (my_get_expression (&inst.reloc.exp, &str))
7898 return;
7899
7900 if (inst.reloc.exp.X_op != O_constant
7901 && inst.reloc.exp.X_op != O_symbol)
7902 {
7903 inst.error = _("constant expression expected");
7904 return;
7905 }
7906
7907 if (inst.reloc.exp.X_op == O_constant)
7908 {
7909 value = validate_immediate (inst.reloc.exp.X_add_number);
7910
7911 if (value != FAIL)
7912 {
7913 /* This can be done with a mov instruction. */
7914 inst.instruction &= LITERAL_MASK;
7915 inst.instruction |= INST_IMMEDIATE | (OPCODE_MOV << DATA_OP_SHIFT);
7916 inst.instruction |= value & 0xfff;
7917 end_of_line (str);
7918 return;
7919 }
7920
7921 value = validate_immediate (~ inst.reloc.exp.X_add_number);
7922
7923 if (value != FAIL)
7924 {
7925 /* This can be done with a mvn instruction. */
7926 inst.instruction &= LITERAL_MASK;
7927 inst.instruction |= INST_IMMEDIATE | (OPCODE_MVN << DATA_OP_SHIFT);
7928 inst.instruction |= value & 0xfff;
7929 end_of_line (str);
7930 return;
7931 }
7932 }
7933
7934 /* Insert into literal pool. */
7935 if (add_to_lit_pool () == FAIL)
7936 {
7937 if (!inst.error)
7938 inst.error = _("literal pool insertion failed");
7939 return;
7940 }
7941
7942 /* Change the instruction exp to point to the pool. */
7943 inst.instruction |= HWOFFSET_IMM;
7944 inst.reloc.type = BFD_RELOC_ARM_HWLITERAL;
7945 inst.reloc.pc_rel = 1;
7946 inst.instruction |= (REG_PC << 16);
7947 pre_inc = 1;
7948 }
7949 else
7950 {
7951 if (my_get_expression (&inst.reloc.exp, &str))
7952 return;
7953
7954 inst.instruction |= HWOFFSET_IMM;
7955 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
7956 #ifndef TE_WINCE
7957 /* PC rel adjust. */
7958 inst.reloc.exp.X_add_number -= 8;
7959 #endif
7960 inst.reloc.pc_rel = 1;
7961 inst.instruction |= (REG_PC << 16);
7962 pre_inc = 1;
7963 }
7964
7965 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
7966 end_of_line (str);
7967 }
7968
7969 static long
7970 reg_list (strp)
7971 char ** strp;
7972 {
7973 char * str = * strp;
7974 long range = 0;
7975 int another_range;
7976
7977 /* We come back here if we get ranges concatenated by '+' or '|'. */
7978 do
7979 {
7980 another_range = 0;
7981
7982 if (*str == '{')
7983 {
7984 int in_range = 0;
7985 int cur_reg = -1;
7986
7987 str++;
7988 do
7989 {
7990 int reg;
7991
7992 skip_whitespace (str);
7993
7994 if ((reg = reg_required_here (& str, -1)) == FAIL)
7995 return FAIL;
7996
7997 if (in_range)
7998 {
7999 int i;
8000
8001 if (reg <= cur_reg)
8002 {
8003 inst.error = _("bad range in register list");
8004 return FAIL;
8005 }
8006
8007 for (i = cur_reg + 1; i < reg; i++)
8008 {
8009 if (range & (1 << i))
8010 as_tsktsk
8011 (_("Warning: duplicated register (r%d) in register list"),
8012 i);
8013 else
8014 range |= 1 << i;
8015 }
8016 in_range = 0;
8017 }
8018
8019 if (range & (1 << reg))
8020 as_tsktsk (_("Warning: duplicated register (r%d) in register list"),
8021 reg);
8022 else if (reg <= cur_reg)
8023 as_tsktsk (_("Warning: register range not in ascending order"));
8024
8025 range |= 1 << reg;
8026 cur_reg = reg;
8027 }
8028 while (skip_past_comma (&str) != FAIL
8029 || (in_range = 1, *str++ == '-'));
8030 str--;
8031 skip_whitespace (str);
8032
8033 if (*str++ != '}')
8034 {
8035 inst.error = _("missing `}'");
8036 return FAIL;
8037 }
8038 }
8039 else
8040 {
8041 expressionS expr;
8042
8043 if (my_get_expression (&expr, &str))
8044 return FAIL;
8045
8046 if (expr.X_op == O_constant)
8047 {
8048 if (expr.X_add_number
8049 != (expr.X_add_number & 0x0000ffff))
8050 {
8051 inst.error = _("invalid register mask");
8052 return FAIL;
8053 }
8054
8055 if ((range & expr.X_add_number) != 0)
8056 {
8057 int regno = range & expr.X_add_number;
8058
8059 regno &= -regno;
8060 regno = (1 << regno) - 1;
8061 as_tsktsk
8062 (_("Warning: duplicated register (r%d) in register list"),
8063 regno);
8064 }
8065
8066 range |= expr.X_add_number;
8067 }
8068 else
8069 {
8070 if (inst.reloc.type != 0)
8071 {
8072 inst.error = _("expression too complex");
8073 return FAIL;
8074 }
8075
8076 memcpy (&inst.reloc.exp, &expr, sizeof (expressionS));
8077 inst.reloc.type = BFD_RELOC_ARM_MULTI;
8078 inst.reloc.pc_rel = 0;
8079 }
8080 }
8081
8082 skip_whitespace (str);
8083
8084 if (*str == '|' || *str == '+')
8085 {
8086 str++;
8087 another_range = 1;
8088 }
8089 }
8090 while (another_range);
8091
8092 *strp = str;
8093 return range;
8094 }
8095
8096 static void
8097 do_ldmstm (str)
8098 char * str;
8099 {
8100 int base_reg;
8101 long range;
8102
8103 skip_whitespace (str);
8104
8105 if ((base_reg = reg_required_here (&str, 16)) == FAIL)
8106 return;
8107
8108 if (base_reg == REG_PC)
8109 {
8110 inst.error = _("r15 not allowed as base register");
8111 return;
8112 }
8113
8114 skip_whitespace (str);
8115
8116 if (*str == '!')
8117 {
8118 inst.instruction |= WRITE_BACK;
8119 str++;
8120 }
8121
8122 if (skip_past_comma (&str) == FAIL
8123 || (range = reg_list (&str)) == FAIL)
8124 {
8125 if (! inst.error)
8126 inst.error = BAD_ARGS;
8127 return;
8128 }
8129
8130 if (*str == '^')
8131 {
8132 str++;
8133 inst.instruction |= LDM_TYPE_2_OR_3;
8134 }
8135
8136 if (inst.instruction & WRITE_BACK)
8137 {
8138 /* Check for unpredictable uses of writeback. */
8139 if (inst.instruction & LOAD_BIT)
8140 {
8141 /* Not allowed in LDM type 2. */
8142 if ((inst.instruction & LDM_TYPE_2_OR_3)
8143 && ((range & (1 << REG_PC)) == 0))
8144 as_warn (_("writeback of base register is UNPREDICTABLE"));
8145 /* Only allowed if base reg not in list for other types. */
8146 else if (range & (1 << base_reg))
8147 as_warn (_("writeback of base register when in register list is UNPREDICTABLE"));
8148 }
8149 else /* STM. */
8150 {
8151 /* Not allowed for type 2. */
8152 if (inst.instruction & LDM_TYPE_2_OR_3)
8153 as_warn (_("writeback of base register is UNPREDICTABLE"));
8154 /* Only allowed if base reg not in list, or first in list. */
8155 else if ((range & (1 << base_reg))
8156 && (range & ((1 << base_reg) - 1)))
8157 as_warn (_("if writeback register is in list, it must be the lowest reg in the list"));
8158 }
8159 }
8160
8161 inst.instruction |= range;
8162 end_of_line (str);
8163 }
8164
8165 static void
8166 do_swi (str)
8167 char * str;
8168 {
8169 skip_whitespace (str);
8170
8171 /* Allow optional leading '#'. */
8172 if (is_immediate_prefix (*str))
8173 str++;
8174
8175 if (my_get_expression (& inst.reloc.exp, & str))
8176 return;
8177
8178 inst.reloc.type = BFD_RELOC_ARM_SWI;
8179 inst.reloc.pc_rel = 0;
8180 end_of_line (str);
8181 }
8182
8183 static void
8184 do_swap (str)
8185 char * str;
8186 {
8187 int reg;
8188
8189 skip_whitespace (str);
8190
8191 if ((reg = reg_required_here (&str, 12)) == FAIL)
8192 return;
8193
8194 if (reg == REG_PC)
8195 {
8196 inst.error = _("r15 not allowed in swap");
8197 return;
8198 }
8199
8200 if (skip_past_comma (&str) == FAIL
8201 || (reg = reg_required_here (&str, 0)) == FAIL)
8202 {
8203 if (!inst.error)
8204 inst.error = BAD_ARGS;
8205 return;
8206 }
8207
8208 if (reg == REG_PC)
8209 {
8210 inst.error = _("r15 not allowed in swap");
8211 return;
8212 }
8213
8214 if (skip_past_comma (&str) == FAIL
8215 || *str++ != '[')
8216 {
8217 inst.error = BAD_ARGS;
8218 return;
8219 }
8220
8221 skip_whitespace (str);
8222
8223 if ((reg = reg_required_here (&str, 16)) == FAIL)
8224 return;
8225
8226 if (reg == REG_PC)
8227 {
8228 inst.error = BAD_PC;
8229 return;
8230 }
8231
8232 skip_whitespace (str);
8233
8234 if (*str++ != ']')
8235 {
8236 inst.error = _("missing ]");
8237 return;
8238 }
8239
8240 end_of_line (str);
8241 }
8242
8243 static void
8244 do_branch (str)
8245 char * str;
8246 {
8247 if (my_get_expression (&inst.reloc.exp, &str))
8248 return;
8249
8250 #ifdef OBJ_ELF
8251 {
8252 char * save_in;
8253
8254 /* ScottB: February 5, 1998 - Check to see of PLT32 reloc
8255 required for the instruction. */
8256
8257 /* arm_parse_reloc () works on input_line_pointer.
8258 We actually want to parse the operands to the branch instruction
8259 passed in 'str'. Save the input pointer and restore it later. */
8260 save_in = input_line_pointer;
8261 input_line_pointer = str;
8262 if (inst.reloc.exp.X_op == O_symbol
8263 && *str == '('
8264 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
8265 {
8266 inst.reloc.type = BFD_RELOC_ARM_PLT32;
8267 inst.reloc.pc_rel = 0;
8268 /* Modify str to point to after parsed operands, otherwise
8269 end_of_line() will complain about the (PLT) left in str. */
8270 str = input_line_pointer;
8271 }
8272 else
8273 {
8274 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
8275 inst.reloc.pc_rel = 1;
8276 }
8277 input_line_pointer = save_in;
8278 }
8279 #else
8280 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
8281 inst.reloc.pc_rel = 1;
8282 #endif /* OBJ_ELF */
8283
8284 end_of_line (str);
8285 }
8286
8287 static void
8288 do_bx (str)
8289 char * str;
8290 {
8291 int reg;
8292
8293 skip_whitespace (str);
8294
8295 if ((reg = reg_required_here (&str, 0)) == FAIL)
8296 {
8297 inst.error = BAD_ARGS;
8298 return;
8299 }
8300
8301 /* Note - it is not illegal to do a "bx pc". Useless, but not illegal. */
8302 if (reg == REG_PC)
8303 as_tsktsk (_("use of r15 in bx in ARM mode is not really useful"));
8304
8305 end_of_line (str);
8306 }
8307
8308 static void
8309 do_cdp (str)
8310 char * str;
8311 {
8312 /* Co-processor data operation.
8313 Format: CDP{cond} CP#,<expr>,CRd,CRn,CRm{,<expr>} */
8314 skip_whitespace (str);
8315
8316 if (co_proc_number (&str) == FAIL)
8317 {
8318 if (!inst.error)
8319 inst.error = BAD_ARGS;
8320 return;
8321 }
8322
8323 if (skip_past_comma (&str) == FAIL
8324 || cp_opc_expr (&str, 20,4) == FAIL)
8325 {
8326 if (!inst.error)
8327 inst.error = BAD_ARGS;
8328 return;
8329 }
8330
8331 if (skip_past_comma (&str) == FAIL
8332 || cp_reg_required_here (&str, 12) == FAIL)
8333 {
8334 if (!inst.error)
8335 inst.error = BAD_ARGS;
8336 return;
8337 }
8338
8339 if (skip_past_comma (&str) == FAIL
8340 || cp_reg_required_here (&str, 16) == FAIL)
8341 {
8342 if (!inst.error)
8343 inst.error = BAD_ARGS;
8344 return;
8345 }
8346
8347 if (skip_past_comma (&str) == FAIL
8348 || cp_reg_required_here (&str, 0) == FAIL)
8349 {
8350 if (!inst.error)
8351 inst.error = BAD_ARGS;
8352 return;
8353 }
8354
8355 if (skip_past_comma (&str) == SUCCESS)
8356 {
8357 if (cp_opc_expr (&str, 5, 3) == FAIL)
8358 {
8359 if (!inst.error)
8360 inst.error = BAD_ARGS;
8361 return;
8362 }
8363 }
8364
8365 end_of_line (str);
8366 }
8367
8368 static void
8369 do_lstc (str)
8370 char * str;
8371 {
8372 /* Co-processor register load/store.
8373 Format: <LDC|STC{cond}[L] CP#,CRd,<address> */
8374
8375 skip_whitespace (str);
8376
8377 if (co_proc_number (&str) == FAIL)
8378 {
8379 if (!inst.error)
8380 inst.error = BAD_ARGS;
8381 return;
8382 }
8383
8384 if (skip_past_comma (&str) == FAIL
8385 || cp_reg_required_here (&str, 12) == FAIL)
8386 {
8387 if (!inst.error)
8388 inst.error = BAD_ARGS;
8389 return;
8390 }
8391
8392 if (skip_past_comma (&str) == FAIL
8393 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
8394 {
8395 if (! inst.error)
8396 inst.error = BAD_ARGS;
8397 return;
8398 }
8399
8400 end_of_line (str);
8401 }
8402
8403 static void
8404 do_co_reg (str)
8405 char * str;
8406 {
8407 /* Co-processor register transfer.
8408 Format: <MCR|MRC>{cond} CP#,<expr1>,Rd,CRn,CRm{,<expr2>} */
8409
8410 skip_whitespace (str);
8411
8412 if (co_proc_number (&str) == FAIL)
8413 {
8414 if (!inst.error)
8415 inst.error = BAD_ARGS;
8416 return;
8417 }
8418
8419 if (skip_past_comma (&str) == FAIL
8420 || cp_opc_expr (&str, 21, 3) == FAIL)
8421 {
8422 if (!inst.error)
8423 inst.error = BAD_ARGS;
8424 return;
8425 }
8426
8427 if (skip_past_comma (&str) == FAIL
8428 || reg_required_here (&str, 12) == FAIL)
8429 {
8430 if (!inst.error)
8431 inst.error = BAD_ARGS;
8432 return;
8433 }
8434
8435 if (skip_past_comma (&str) == FAIL
8436 || cp_reg_required_here (&str, 16) == FAIL)
8437 {
8438 if (!inst.error)
8439 inst.error = BAD_ARGS;
8440 return;
8441 }
8442
8443 if (skip_past_comma (&str) == FAIL
8444 || cp_reg_required_here (&str, 0) == FAIL)
8445 {
8446 if (!inst.error)
8447 inst.error = BAD_ARGS;
8448 return;
8449 }
8450
8451 if (skip_past_comma (&str) == SUCCESS)
8452 {
8453 if (cp_opc_expr (&str, 5, 3) == FAIL)
8454 {
8455 if (!inst.error)
8456 inst.error = BAD_ARGS;
8457 return;
8458 }
8459 }
8460
8461 end_of_line (str);
8462 }
8463
8464 static void
8465 do_fpa_ctrl (str)
8466 char * str;
8467 {
8468 /* FP control registers.
8469 Format: <WFS|RFS|WFC|RFC>{cond} Rn */
8470
8471 skip_whitespace (str);
8472
8473 if (reg_required_here (&str, 12) == FAIL)
8474 {
8475 if (!inst.error)
8476 inst.error = BAD_ARGS;
8477 return;
8478 }
8479
8480 end_of_line (str);
8481 }
8482
8483 static void
8484 do_fpa_ldst (str)
8485 char * str;
8486 {
8487 skip_whitespace (str);
8488
8489 if (fp_reg_required_here (&str, 12) == FAIL)
8490 {
8491 if (!inst.error)
8492 inst.error = BAD_ARGS;
8493 return;
8494 }
8495
8496 if (skip_past_comma (&str) == FAIL
8497 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
8498 {
8499 if (!inst.error)
8500 inst.error = BAD_ARGS;
8501 return;
8502 }
8503
8504 end_of_line (str);
8505 }
8506
8507 static void
8508 do_fpa_ldmstm (str)
8509 char * str;
8510 {
8511 int num_regs;
8512
8513 skip_whitespace (str);
8514
8515 if (fp_reg_required_here (&str, 12) == FAIL)
8516 {
8517 if (! inst.error)
8518 inst.error = BAD_ARGS;
8519 return;
8520 }
8521
8522 /* Get Number of registers to transfer. */
8523 if (skip_past_comma (&str) == FAIL
8524 || my_get_expression (&inst.reloc.exp, &str))
8525 {
8526 if (! inst.error)
8527 inst.error = _("constant expression expected");
8528 return;
8529 }
8530
8531 if (inst.reloc.exp.X_op != O_constant)
8532 {
8533 inst.error = _("constant value required for number of registers");
8534 return;
8535 }
8536
8537 num_regs = inst.reloc.exp.X_add_number;
8538
8539 if (num_regs < 1 || num_regs > 4)
8540 {
8541 inst.error = _("number of registers must be in the range [1:4]");
8542 return;
8543 }
8544
8545 switch (num_regs)
8546 {
8547 case 1:
8548 inst.instruction |= CP_T_X;
8549 break;
8550 case 2:
8551 inst.instruction |= CP_T_Y;
8552 break;
8553 case 3:
8554 inst.instruction |= CP_T_Y | CP_T_X;
8555 break;
8556 case 4:
8557 break;
8558 default:
8559 abort ();
8560 }
8561
8562 if (inst.instruction & (CP_T_Pre | CP_T_UD)) /* ea/fd format. */
8563 {
8564 int reg;
8565 int write_back;
8566 int offset;
8567
8568 /* The instruction specified "ea" or "fd", so we can only accept
8569 [Rn]{!}. The instruction does not really support stacking or
8570 unstacking, so we have to emulate these by setting appropriate
8571 bits and offsets. */
8572 if (skip_past_comma (&str) == FAIL
8573 || *str != '[')
8574 {
8575 if (! inst.error)
8576 inst.error = BAD_ARGS;
8577 return;
8578 }
8579
8580 str++;
8581 skip_whitespace (str);
8582
8583 if ((reg = reg_required_here (&str, 16)) == FAIL)
8584 return;
8585
8586 skip_whitespace (str);
8587
8588 if (*str != ']')
8589 {
8590 inst.error = BAD_ARGS;
8591 return;
8592 }
8593
8594 str++;
8595 if (*str == '!')
8596 {
8597 write_back = 1;
8598 str++;
8599 if (reg == REG_PC)
8600 {
8601 inst.error =
8602 _("r15 not allowed as base register with write-back");
8603 return;
8604 }
8605 }
8606 else
8607 write_back = 0;
8608
8609 if (inst.instruction & CP_T_Pre)
8610 {
8611 /* Pre-decrement. */
8612 offset = 3 * num_regs;
8613 if (write_back)
8614 inst.instruction |= CP_T_WB;
8615 }
8616 else
8617 {
8618 /* Post-increment. */
8619 if (write_back)
8620 {
8621 inst.instruction |= CP_T_WB;
8622 offset = 3 * num_regs;
8623 }
8624 else
8625 {
8626 /* No write-back, so convert this into a standard pre-increment
8627 instruction -- aesthetically more pleasing. */
8628 inst.instruction |= CP_T_Pre | CP_T_UD;
8629 offset = 0;
8630 }
8631 }
8632
8633 inst.instruction |= offset;
8634 }
8635 else if (skip_past_comma (&str) == FAIL
8636 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
8637 {
8638 if (! inst.error)
8639 inst.error = BAD_ARGS;
8640 return;
8641 }
8642
8643 end_of_line (str);
8644 }
8645
8646 static void
8647 do_fpa_dyadic (str)
8648 char * str;
8649 {
8650 skip_whitespace (str);
8651
8652 if (fp_reg_required_here (&str, 12) == FAIL)
8653 {
8654 if (! inst.error)
8655 inst.error = BAD_ARGS;
8656 return;
8657 }
8658
8659 if (skip_past_comma (&str) == FAIL
8660 || fp_reg_required_here (&str, 16) == FAIL)
8661 {
8662 if (! inst.error)
8663 inst.error = BAD_ARGS;
8664 return;
8665 }
8666
8667 if (skip_past_comma (&str) == FAIL
8668 || fp_op2 (&str) == FAIL)
8669 {
8670 if (! inst.error)
8671 inst.error = BAD_ARGS;
8672 return;
8673 }
8674
8675 end_of_line (str);
8676 }
8677
8678 static void
8679 do_fpa_monadic (str)
8680 char * str;
8681 {
8682 skip_whitespace (str);
8683
8684 if (fp_reg_required_here (&str, 12) == FAIL)
8685 {
8686 if (! inst.error)
8687 inst.error = BAD_ARGS;
8688 return;
8689 }
8690
8691 if (skip_past_comma (&str) == FAIL
8692 || fp_op2 (&str) == FAIL)
8693 {
8694 if (! inst.error)
8695 inst.error = BAD_ARGS;
8696 return;
8697 }
8698
8699 end_of_line (str);
8700 }
8701
8702 static void
8703 do_fpa_cmp (str)
8704 char * str;
8705 {
8706 skip_whitespace (str);
8707
8708 if (fp_reg_required_here (&str, 16) == FAIL)
8709 {
8710 if (! inst.error)
8711 inst.error = BAD_ARGS;
8712 return;
8713 }
8714
8715 if (skip_past_comma (&str) == FAIL
8716 || fp_op2 (&str) == FAIL)
8717 {
8718 if (! inst.error)
8719 inst.error = BAD_ARGS;
8720 return;
8721 }
8722
8723 end_of_line (str);
8724 }
8725
8726 static void
8727 do_fpa_from_reg (str)
8728 char * str;
8729 {
8730 skip_whitespace (str);
8731
8732 if (fp_reg_required_here (&str, 16) == FAIL)
8733 {
8734 if (! inst.error)
8735 inst.error = BAD_ARGS;
8736 return;
8737 }
8738
8739 if (skip_past_comma (&str) == FAIL
8740 || reg_required_here (&str, 12) == FAIL)
8741 {
8742 if (! inst.error)
8743 inst.error = BAD_ARGS;
8744 return;
8745 }
8746
8747 end_of_line (str);
8748 }
8749
8750 static void
8751 do_fpa_to_reg (str)
8752 char * str;
8753 {
8754 skip_whitespace (str);
8755
8756 if (reg_required_here (&str, 12) == FAIL)
8757 return;
8758
8759 if (skip_past_comma (&str) == FAIL
8760 || fp_reg_required_here (&str, 0) == FAIL)
8761 {
8762 if (! inst.error)
8763 inst.error = BAD_ARGS;
8764 return;
8765 }
8766
8767 end_of_line (str);
8768 }
8769
8770 static int
8771 vfp_sp_reg_required_here (str, pos)
8772 char **str;
8773 enum vfp_sp_reg_pos pos;
8774 {
8775 int reg;
8776 char *start = *str;
8777
8778 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_SN].htab)) != FAIL)
8779 {
8780 switch (pos)
8781 {
8782 case VFP_REG_Sd:
8783 inst.instruction |= ((reg >> 1) << 12) | ((reg & 1) << 22);
8784 break;
8785
8786 case VFP_REG_Sn:
8787 inst.instruction |= ((reg >> 1) << 16) | ((reg & 1) << 7);
8788 break;
8789
8790 case VFP_REG_Sm:
8791 inst.instruction |= ((reg >> 1) << 0) | ((reg & 1) << 5);
8792 break;
8793
8794 default:
8795 abort ();
8796 }
8797 return reg;
8798 }
8799
8800 /* In the few cases where we might be able to accept something else
8801 this error can be overridden. */
8802 inst.error = _(all_reg_maps[REG_TYPE_SN].expected);
8803
8804 /* Restore the start point. */
8805 *str = start;
8806 return FAIL;
8807 }
8808
8809 static int
8810 vfp_dp_reg_required_here (str, pos)
8811 char **str;
8812 enum vfp_dp_reg_pos pos;
8813 {
8814 int reg;
8815 char *start = *str;
8816
8817 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_DN].htab)) != FAIL)
8818 {
8819 switch (pos)
8820 {
8821 case VFP_REG_Dd:
8822 inst.instruction |= reg << 12;
8823 break;
8824
8825 case VFP_REG_Dn:
8826 inst.instruction |= reg << 16;
8827 break;
8828
8829 case VFP_REG_Dm:
8830 inst.instruction |= reg << 0;
8831 break;
8832
8833 default:
8834 abort ();
8835 }
8836 return reg;
8837 }
8838
8839 /* In the few cases where we might be able to accept something else
8840 this error can be overridden. */
8841 inst.error = _(all_reg_maps[REG_TYPE_DN].expected);
8842
8843 /* Restore the start point. */
8844 *str = start;
8845 return FAIL;
8846 }
8847
8848 static void
8849 do_vfp_sp_monadic (str)
8850 char *str;
8851 {
8852 skip_whitespace (str);
8853
8854 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
8855 return;
8856
8857 if (skip_past_comma (&str) == FAIL
8858 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
8859 {
8860 if (! inst.error)
8861 inst.error = BAD_ARGS;
8862 return;
8863 }
8864
8865 end_of_line (str);
8866 }
8867
8868 static void
8869 do_vfp_dp_monadic (str)
8870 char *str;
8871 {
8872 skip_whitespace (str);
8873
8874 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
8875 return;
8876
8877 if (skip_past_comma (&str) == FAIL
8878 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
8879 {
8880 if (! inst.error)
8881 inst.error = BAD_ARGS;
8882 return;
8883 }
8884
8885 end_of_line (str);
8886 }
8887
8888 static void
8889 do_vfp_sp_dyadic (str)
8890 char *str;
8891 {
8892 skip_whitespace (str);
8893
8894 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
8895 return;
8896
8897 if (skip_past_comma (&str) == FAIL
8898 || vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL
8899 || skip_past_comma (&str) == FAIL
8900 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
8901 {
8902 if (! inst.error)
8903 inst.error = BAD_ARGS;
8904 return;
8905 }
8906
8907 end_of_line (str);
8908 }
8909
8910 static void
8911 do_vfp_dp_dyadic (str)
8912 char *str;
8913 {
8914 skip_whitespace (str);
8915
8916 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
8917 return;
8918
8919 if (skip_past_comma (&str) == FAIL
8920 || vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL
8921 || skip_past_comma (&str) == FAIL
8922 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
8923 {
8924 if (! inst.error)
8925 inst.error = BAD_ARGS;
8926 return;
8927 }
8928
8929 end_of_line (str);
8930 }
8931
8932 static void
8933 do_vfp_reg_from_sp (str)
8934 char *str;
8935 {
8936 skip_whitespace (str);
8937
8938 if (reg_required_here (&str, 12) == FAIL)
8939 return;
8940
8941 if (skip_past_comma (&str) == FAIL
8942 || vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL)
8943 {
8944 if (! inst.error)
8945 inst.error = BAD_ARGS;
8946 return;
8947 }
8948
8949 end_of_line (str);
8950 }
8951
8952 static void
8953 do_vfp_sp_reg2 (str)
8954 char *str;
8955 {
8956 skip_whitespace (str);
8957
8958 if (reg_required_here (&str, 12) == FAIL)
8959 return;
8960
8961 if (skip_past_comma (&str) == FAIL
8962 || reg_required_here (&str, 16) == FAIL
8963 || skip_past_comma (&str) == FAIL)
8964 {
8965 if (! inst.error)
8966 inst.error = BAD_ARGS;
8967 return;
8968 }
8969
8970 /* We require exactly two consecutive SP registers. */
8971 if (vfp_sp_reg_list (&str, VFP_REG_Sm) != 2)
8972 {
8973 if (! inst.error)
8974 inst.error = _("only two consecutive VFP SP registers allowed here");
8975 }
8976
8977 end_of_line (str);
8978 }
8979
8980 static void
8981 do_vfp_sp_from_reg (str)
8982 char *str;
8983 {
8984 skip_whitespace (str);
8985
8986 if (vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL)
8987 return;
8988
8989 if (skip_past_comma (&str) == FAIL
8990 || reg_required_here (&str, 12) == FAIL)
8991 {
8992 if (! inst.error)
8993 inst.error = BAD_ARGS;
8994 return;
8995 }
8996
8997 end_of_line (str);
8998 }
8999
9000 static void
9001 do_vfp_reg_from_dp (str)
9002 char *str;
9003 {
9004 skip_whitespace (str);
9005
9006 if (reg_required_here (&str, 12) == FAIL)
9007 return;
9008
9009 if (skip_past_comma (&str) == FAIL
9010 || vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL)
9011 {
9012 if (! inst.error)
9013 inst.error = BAD_ARGS;
9014 return;
9015 }
9016
9017 end_of_line (str);
9018 }
9019
9020 static void
9021 do_vfp_reg2_from_dp (str)
9022 char *str;
9023 {
9024 skip_whitespace (str);
9025
9026 if (reg_required_here (&str, 12) == FAIL)
9027 return;
9028
9029 if (skip_past_comma (&str) == FAIL
9030 || reg_required_here (&str, 16) == FAIL
9031 || skip_past_comma (&str) == FAIL
9032 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
9033 {
9034 if (! inst.error)
9035 inst.error = BAD_ARGS;
9036 return;
9037 }
9038
9039 end_of_line (str);
9040 }
9041
9042 static void
9043 do_vfp_dp_from_reg (str)
9044 char *str;
9045 {
9046 skip_whitespace (str);
9047
9048 if (vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL)
9049 return;
9050
9051 if (skip_past_comma (&str) == FAIL
9052 || reg_required_here (&str, 12) == FAIL)
9053 {
9054 if (! inst.error)
9055 inst.error = BAD_ARGS;
9056 return;
9057 }
9058
9059 end_of_line (str);
9060 }
9061
9062 static void
9063 do_vfp_dp_from_reg2 (str)
9064 char *str;
9065 {
9066 skip_whitespace (str);
9067
9068 if (vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
9069 return;
9070
9071 if (skip_past_comma (&str) == FAIL
9072 || reg_required_here (&str, 12) == FAIL
9073 || skip_past_comma (&str) == FAIL
9074 || reg_required_here (&str, 16))
9075 {
9076 if (! inst.error)
9077 inst.error = BAD_ARGS;
9078 return;
9079 }
9080
9081 end_of_line (str);
9082 }
9083
9084 static const struct vfp_reg *
9085 vfp_psr_parse (str)
9086 char **str;
9087 {
9088 char *start = *str;
9089 char c;
9090 char *p;
9091 const struct vfp_reg *vreg;
9092
9093 p = start;
9094
9095 /* Find the end of the current token. */
9096 do
9097 {
9098 c = *p++;
9099 }
9100 while (ISALPHA (c));
9101
9102 /* Mark it. */
9103 *--p = 0;
9104
9105 for (vreg = vfp_regs + 0;
9106 vreg < vfp_regs + sizeof (vfp_regs) / sizeof (struct vfp_reg);
9107 vreg++)
9108 {
9109 if (strcmp (start, vreg->name) == 0)
9110 {
9111 *p = c;
9112 *str = p;
9113 return vreg;
9114 }
9115 }
9116
9117 *p = c;
9118 return NULL;
9119 }
9120
9121 static int
9122 vfp_psr_required_here (str)
9123 char **str;
9124 {
9125 char *start = *str;
9126 const struct vfp_reg *vreg;
9127
9128 vreg = vfp_psr_parse (str);
9129
9130 if (vreg)
9131 {
9132 inst.instruction |= vreg->regno;
9133 return SUCCESS;
9134 }
9135
9136 inst.error = _("VFP system register expected");
9137
9138 *str = start;
9139 return FAIL;
9140 }
9141
9142 static void
9143 do_vfp_reg_from_ctrl (str)
9144 char *str;
9145 {
9146 skip_whitespace (str);
9147
9148 if (reg_required_here (&str, 12) == FAIL)
9149 return;
9150
9151 if (skip_past_comma (&str) == FAIL
9152 || vfp_psr_required_here (&str) == FAIL)
9153 {
9154 if (! inst.error)
9155 inst.error = BAD_ARGS;
9156 return;
9157 }
9158
9159 end_of_line (str);
9160 }
9161
9162 static void
9163 do_vfp_ctrl_from_reg (str)
9164 char *str;
9165 {
9166 skip_whitespace (str);
9167
9168 if (vfp_psr_required_here (&str) == FAIL)
9169 return;
9170
9171 if (skip_past_comma (&str) == FAIL
9172 || reg_required_here (&str, 12) == FAIL)
9173 {
9174 if (! inst.error)
9175 inst.error = BAD_ARGS;
9176 return;
9177 }
9178
9179 end_of_line (str);
9180 }
9181
9182 static void
9183 do_vfp_sp_ldst (str)
9184 char *str;
9185 {
9186 skip_whitespace (str);
9187
9188 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
9189 {
9190 if (!inst.error)
9191 inst.error = BAD_ARGS;
9192 return;
9193 }
9194
9195 if (skip_past_comma (&str) == FAIL
9196 || cp_address_required_here (&str, CP_NO_WB) == FAIL)
9197 {
9198 if (!inst.error)
9199 inst.error = BAD_ARGS;
9200 return;
9201 }
9202
9203 end_of_line (str);
9204 }
9205
9206 static void
9207 do_vfp_dp_ldst (str)
9208 char *str;
9209 {
9210 skip_whitespace (str);
9211
9212 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
9213 {
9214 if (!inst.error)
9215 inst.error = BAD_ARGS;
9216 return;
9217 }
9218
9219 if (skip_past_comma (&str) == FAIL
9220 || cp_address_required_here (&str, CP_NO_WB) == FAIL)
9221 {
9222 if (!inst.error)
9223 inst.error = BAD_ARGS;
9224 return;
9225 }
9226
9227 end_of_line (str);
9228 }
9229
9230 /* Parse and encode a VFP SP register list, storing the initial
9231 register in position POS and returning the range as the result. If
9232 the string is invalid return FAIL (an invalid range). */
9233 static long
9234 vfp_sp_reg_list (str, pos)
9235 char **str;
9236 enum vfp_sp_reg_pos pos;
9237 {
9238 long range = 0;
9239 int base_reg = 0;
9240 int new_base;
9241 long base_bits = 0;
9242 int count = 0;
9243 long tempinst;
9244 unsigned long mask = 0;
9245 int warned = 0;
9246
9247 if (**str != '{')
9248 return FAIL;
9249
9250 (*str)++;
9251 skip_whitespace (*str);
9252
9253 tempinst = inst.instruction;
9254
9255 do
9256 {
9257 inst.instruction = 0;
9258
9259 if ((new_base = vfp_sp_reg_required_here (str, pos)) == FAIL)
9260 return FAIL;
9261
9262 if (count == 0 || base_reg > new_base)
9263 {
9264 base_reg = new_base;
9265 base_bits = inst.instruction;
9266 }
9267
9268 if (mask & (1 << new_base))
9269 {
9270 inst.error = _("invalid register list");
9271 return FAIL;
9272 }
9273
9274 if ((mask >> new_base) != 0 && ! warned)
9275 {
9276 as_tsktsk (_("register list not in ascending order"));
9277 warned = 1;
9278 }
9279
9280 mask |= 1 << new_base;
9281 count++;
9282
9283 skip_whitespace (*str);
9284
9285 if (**str == '-') /* We have the start of a range expression */
9286 {
9287 int high_range;
9288
9289 (*str)++;
9290
9291 if ((high_range
9292 = arm_reg_parse (str, all_reg_maps[REG_TYPE_SN].htab))
9293 == FAIL)
9294 {
9295 inst.error = _(all_reg_maps[REG_TYPE_SN].expected);
9296 return FAIL;
9297 }
9298
9299 if (high_range <= new_base)
9300 {
9301 inst.error = _("register range not in ascending order");
9302 return FAIL;
9303 }
9304
9305 for (new_base++; new_base <= high_range; new_base++)
9306 {
9307 if (mask & (1 << new_base))
9308 {
9309 inst.error = _("invalid register list");
9310 return FAIL;
9311 }
9312
9313 mask |= 1 << new_base;
9314 count++;
9315 }
9316 }
9317 }
9318 while (skip_past_comma (str) != FAIL);
9319
9320 if (**str != '}')
9321 {
9322 inst.error = _("invalid register list");
9323 return FAIL;
9324 }
9325
9326 (*str)++;
9327
9328 range = count;
9329
9330 /* Sanity check -- should have raised a parse error above. */
9331 if (count == 0 || count > 32)
9332 abort ();
9333
9334 /* Final test -- the registers must be consecutive. */
9335 while (count--)
9336 {
9337 if ((mask & (1 << base_reg++)) == 0)
9338 {
9339 inst.error = _("non-contiguous register range");
9340 return FAIL;
9341 }
9342 }
9343
9344 inst.instruction = tempinst | base_bits;
9345 return range;
9346 }
9347
9348 static long
9349 vfp_dp_reg_list (str)
9350 char **str;
9351 {
9352 long range = 0;
9353 int base_reg = 0;
9354 int new_base;
9355 int count = 0;
9356 long tempinst;
9357 unsigned long mask = 0;
9358 int warned = 0;
9359
9360 if (**str != '{')
9361 return FAIL;
9362
9363 (*str)++;
9364 skip_whitespace (*str);
9365
9366 tempinst = inst.instruction;
9367
9368 do
9369 {
9370 inst.instruction = 0;
9371
9372 if ((new_base = vfp_dp_reg_required_here (str, VFP_REG_Dd)) == FAIL)
9373 return FAIL;
9374
9375 if (count == 0 || base_reg > new_base)
9376 {
9377 base_reg = new_base;
9378 range = inst.instruction;
9379 }
9380
9381 if (mask & (1 << new_base))
9382 {
9383 inst.error = _("invalid register list");
9384 return FAIL;
9385 }
9386
9387 if ((mask >> new_base) != 0 && ! warned)
9388 {
9389 as_tsktsk (_("register list not in ascending order"));
9390 warned = 1;
9391 }
9392
9393 mask |= 1 << new_base;
9394 count++;
9395
9396 skip_whitespace (*str);
9397
9398 if (**str == '-') /* We have the start of a range expression */
9399 {
9400 int high_range;
9401
9402 (*str)++;
9403
9404 if ((high_range
9405 = arm_reg_parse (str, all_reg_maps[REG_TYPE_DN].htab))
9406 == FAIL)
9407 {
9408 inst.error = _(all_reg_maps[REG_TYPE_DN].expected);
9409 return FAIL;
9410 }
9411
9412 if (high_range <= new_base)
9413 {
9414 inst.error = _("register range not in ascending order");
9415 return FAIL;
9416 }
9417
9418 for (new_base++; new_base <= high_range; new_base++)
9419 {
9420 if (mask & (1 << new_base))
9421 {
9422 inst.error = _("invalid register list");
9423 return FAIL;
9424 }
9425
9426 mask |= 1 << new_base;
9427 count++;
9428 }
9429 }
9430 }
9431 while (skip_past_comma (str) != FAIL);
9432
9433 if (**str != '}')
9434 {
9435 inst.error = _("invalid register list");
9436 return FAIL;
9437 }
9438
9439 (*str)++;
9440
9441 range |= 2 * count;
9442
9443 /* Sanity check -- should have raised a parse error above. */
9444 if (count == 0 || count > 16)
9445 abort ();
9446
9447 /* Final test -- the registers must be consecutive. */
9448 while (count--)
9449 {
9450 if ((mask & (1 << base_reg++)) == 0)
9451 {
9452 inst.error = _("non-contiguous register range");
9453 return FAIL;
9454 }
9455 }
9456
9457 inst.instruction = tempinst;
9458 return range;
9459 }
9460
9461 static void
9462 vfp_sp_ldstm (str, ldstm_type)
9463 char *str;
9464 enum vfp_ldstm_type ldstm_type;
9465 {
9466 long range;
9467
9468 skip_whitespace (str);
9469
9470 if (reg_required_here (&str, 16) == FAIL)
9471 return;
9472
9473 skip_whitespace (str);
9474
9475 if (*str == '!')
9476 {
9477 inst.instruction |= WRITE_BACK;
9478 str++;
9479 }
9480 else if (ldstm_type != VFP_LDSTMIA)
9481 {
9482 inst.error = _("this addressing mode requires base-register writeback");
9483 return;
9484 }
9485
9486 if (skip_past_comma (&str) == FAIL
9487 || (range = vfp_sp_reg_list (&str, VFP_REG_Sd)) == FAIL)
9488 {
9489 if (!inst.error)
9490 inst.error = BAD_ARGS;
9491 return;
9492 }
9493
9494 inst.instruction |= range;
9495 end_of_line (str);
9496 }
9497
9498 static void
9499 vfp_dp_ldstm (str, ldstm_type)
9500 char *str;
9501 enum vfp_ldstm_type ldstm_type;
9502 {
9503 long range;
9504
9505 skip_whitespace (str);
9506
9507 if (reg_required_here (&str, 16) == FAIL)
9508 return;
9509
9510 skip_whitespace (str);
9511
9512 if (*str == '!')
9513 {
9514 inst.instruction |= WRITE_BACK;
9515 str++;
9516 }
9517 else if (ldstm_type != VFP_LDSTMIA && ldstm_type != VFP_LDSTMIAX)
9518 {
9519 inst.error = _("this addressing mode requires base-register writeback");
9520 return;
9521 }
9522
9523 if (skip_past_comma (&str) == FAIL
9524 || (range = vfp_dp_reg_list (&str)) == FAIL)
9525 {
9526 if (!inst.error)
9527 inst.error = BAD_ARGS;
9528 return;
9529 }
9530
9531 if (ldstm_type == VFP_LDSTMIAX || ldstm_type == VFP_LDSTMDBX)
9532 range += 1;
9533
9534 inst.instruction |= range;
9535 end_of_line (str);
9536 }
9537
9538 static void
9539 do_vfp_sp_ldstmia (str)
9540 char *str;
9541 {
9542 vfp_sp_ldstm (str, VFP_LDSTMIA);
9543 }
9544
9545 static void
9546 do_vfp_sp_ldstmdb (str)
9547 char *str;
9548 {
9549 vfp_sp_ldstm (str, VFP_LDSTMDB);
9550 }
9551
9552 static void
9553 do_vfp_dp_ldstmia (str)
9554 char *str;
9555 {
9556 vfp_dp_ldstm (str, VFP_LDSTMIA);
9557 }
9558
9559 static void
9560 do_vfp_dp_ldstmdb (str)
9561 char *str;
9562 {
9563 vfp_dp_ldstm (str, VFP_LDSTMDB);
9564 }
9565
9566 static void
9567 do_vfp_xp_ldstmia (str)
9568 char *str;
9569 {
9570 vfp_dp_ldstm (str, VFP_LDSTMIAX);
9571 }
9572
9573 static void
9574 do_vfp_xp_ldstmdb (str)
9575 char *str;
9576 {
9577 vfp_dp_ldstm (str, VFP_LDSTMDBX);
9578 }
9579
9580 static void
9581 do_vfp_sp_compare_z (str)
9582 char *str;
9583 {
9584 skip_whitespace (str);
9585
9586 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
9587 {
9588 if (!inst.error)
9589 inst.error = BAD_ARGS;
9590 return;
9591 }
9592
9593 end_of_line (str);
9594 }
9595
9596 static void
9597 do_vfp_dp_compare_z (str)
9598 char *str;
9599 {
9600 skip_whitespace (str);
9601
9602 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
9603 {
9604 if (!inst.error)
9605 inst.error = BAD_ARGS;
9606 return;
9607 }
9608
9609 end_of_line (str);
9610 }
9611
9612 static void
9613 do_vfp_dp_sp_cvt (str)
9614 char *str;
9615 {
9616 skip_whitespace (str);
9617
9618 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
9619 return;
9620
9621 if (skip_past_comma (&str) == FAIL
9622 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
9623 {
9624 if (! inst.error)
9625 inst.error = BAD_ARGS;
9626 return;
9627 }
9628
9629 end_of_line (str);
9630 }
9631
9632 static void
9633 do_vfp_sp_dp_cvt (str)
9634 char *str;
9635 {
9636 skip_whitespace (str);
9637
9638 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
9639 return;
9640
9641 if (skip_past_comma (&str) == FAIL
9642 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
9643 {
9644 if (! inst.error)
9645 inst.error = BAD_ARGS;
9646 return;
9647 }
9648
9649 end_of_line (str);
9650 }
9651
9652 /* Thumb specific routines. */
9653
9654 /* Parse and validate that a register is of the right form, this saves
9655 repeated checking of this information in many similar cases.
9656 Unlike the 32-bit case we do not insert the register into the opcode
9657 here, since the position is often unknown until the full instruction
9658 has been parsed. */
9659
9660 static int
9661 thumb_reg (strp, hi_lo)
9662 char ** strp;
9663 int hi_lo;
9664 {
9665 int reg;
9666
9667 if ((reg = reg_required_here (strp, -1)) == FAIL)
9668 return FAIL;
9669
9670 switch (hi_lo)
9671 {
9672 case THUMB_REG_LO:
9673 if (reg > 7)
9674 {
9675 inst.error = _("lo register required");
9676 return FAIL;
9677 }
9678 break;
9679
9680 case THUMB_REG_HI:
9681 if (reg < 8)
9682 {
9683 inst.error = _("hi register required");
9684 return FAIL;
9685 }
9686 break;
9687
9688 default:
9689 break;
9690 }
9691
9692 return reg;
9693 }
9694
9695 /* Parse an add or subtract instruction, SUBTRACT is non-zero if the opcode
9696 was SUB. */
9697
9698 static void
9699 thumb_add_sub (str, subtract)
9700 char * str;
9701 int subtract;
9702 {
9703 int Rd, Rs, Rn = FAIL;
9704
9705 skip_whitespace (str);
9706
9707 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
9708 || skip_past_comma (&str) == FAIL)
9709 {
9710 if (! inst.error)
9711 inst.error = BAD_ARGS;
9712 return;
9713 }
9714
9715 if (is_immediate_prefix (*str))
9716 {
9717 Rs = Rd;
9718 str++;
9719 if (my_get_expression (&inst.reloc.exp, &str))
9720 return;
9721 }
9722 else
9723 {
9724 if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
9725 return;
9726
9727 if (skip_past_comma (&str) == FAIL)
9728 {
9729 /* Two operand format, shuffle the registers
9730 and pretend there are 3. */
9731 Rn = Rs;
9732 Rs = Rd;
9733 }
9734 else if (is_immediate_prefix (*str))
9735 {
9736 str++;
9737 if (my_get_expression (&inst.reloc.exp, &str))
9738 return;
9739 }
9740 else if ((Rn = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
9741 return;
9742 }
9743
9744 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
9745 for the latter case, EXPR contains the immediate that was found. */
9746 if (Rn != FAIL)
9747 {
9748 /* All register format. */
9749 if (Rd > 7 || Rs > 7 || Rn > 7)
9750 {
9751 if (Rs != Rd)
9752 {
9753 inst.error = _("dest and source1 must be the same register");
9754 return;
9755 }
9756
9757 /* Can't do this for SUB. */
9758 if (subtract)
9759 {
9760 inst.error = _("subtract valid only on lo regs");
9761 return;
9762 }
9763
9764 inst.instruction = (T_OPCODE_ADD_HI
9765 | (Rd > 7 ? THUMB_H1 : 0)
9766 | (Rn > 7 ? THUMB_H2 : 0));
9767 inst.instruction |= (Rd & 7) | ((Rn & 7) << 3);
9768 }
9769 else
9770 {
9771 inst.instruction = subtract ? T_OPCODE_SUB_R3 : T_OPCODE_ADD_R3;
9772 inst.instruction |= Rd | (Rs << 3) | (Rn << 6);
9773 }
9774 }
9775 else
9776 {
9777 /* Immediate expression, now things start to get nasty. */
9778
9779 /* First deal with HI regs, only very restricted cases allowed:
9780 Adjusting SP, and using PC or SP to get an address. */
9781 if ((Rd > 7 && (Rd != REG_SP || Rs != REG_SP))
9782 || (Rs > 7 && Rs != REG_SP && Rs != REG_PC))
9783 {
9784 inst.error = _("invalid Hi register with immediate");
9785 return;
9786 }
9787
9788 if (inst.reloc.exp.X_op != O_constant)
9789 {
9790 /* Value isn't known yet, all we can do is store all the fragments
9791 we know about in the instruction and let the reloc hacking
9792 work it all out. */
9793 inst.instruction = (subtract ? 0x8000 : 0) | (Rd << 4) | Rs;
9794 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
9795 }
9796 else
9797 {
9798 int offset = inst.reloc.exp.X_add_number;
9799
9800 if (subtract)
9801 offset = - offset;
9802
9803 if (offset < 0)
9804 {
9805 offset = - offset;
9806 subtract = 1;
9807
9808 /* Quick check, in case offset is MIN_INT. */
9809 if (offset < 0)
9810 {
9811 inst.error = _("immediate value out of range");
9812 return;
9813 }
9814 }
9815 /* Note - you cannot convert a subtract of 0 into an
9816 add of 0 because the carry flag is set differently. */
9817 else if (offset > 0)
9818 subtract = 0;
9819
9820 if (Rd == REG_SP)
9821 {
9822 if (offset & ~0x1fc)
9823 {
9824 inst.error = _("invalid immediate value for stack adjust");
9825 return;
9826 }
9827 inst.instruction = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
9828 inst.instruction |= offset >> 2;
9829 }
9830 else if (Rs == REG_PC || Rs == REG_SP)
9831 {
9832 if (subtract
9833 || (offset & ~0x3fc))
9834 {
9835 inst.error = _("invalid immediate for address calculation");
9836 return;
9837 }
9838 inst.instruction = (Rs == REG_PC ? T_OPCODE_ADD_PC
9839 : T_OPCODE_ADD_SP);
9840 inst.instruction |= (Rd << 8) | (offset >> 2);
9841 }
9842 else if (Rs == Rd)
9843 {
9844 if (offset & ~0xff)
9845 {
9846 inst.error = _("immediate value out of range");
9847 return;
9848 }
9849 inst.instruction = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
9850 inst.instruction |= (Rd << 8) | offset;
9851 }
9852 else
9853 {
9854 if (offset & ~0x7)
9855 {
9856 inst.error = _("immediate value out of range");
9857 return;
9858 }
9859 inst.instruction = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
9860 inst.instruction |= Rd | (Rs << 3) | (offset << 6);
9861 }
9862 }
9863 }
9864
9865 end_of_line (str);
9866 }
9867
9868 static void
9869 thumb_shift (str, shift)
9870 char * str;
9871 int shift;
9872 {
9873 int Rd, Rs, Rn = FAIL;
9874
9875 skip_whitespace (str);
9876
9877 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9878 || skip_past_comma (&str) == FAIL)
9879 {
9880 if (! inst.error)
9881 inst.error = BAD_ARGS;
9882 return;
9883 }
9884
9885 if (is_immediate_prefix (*str))
9886 {
9887 /* Two operand immediate format, set Rs to Rd. */
9888 Rs = Rd;
9889 str ++;
9890 if (my_get_expression (&inst.reloc.exp, &str))
9891 return;
9892 }
9893 else
9894 {
9895 if ((Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9896 return;
9897
9898 if (skip_past_comma (&str) == FAIL)
9899 {
9900 /* Two operand format, shuffle the registers
9901 and pretend there are 3. */
9902 Rn = Rs;
9903 Rs = Rd;
9904 }
9905 else if (is_immediate_prefix (*str))
9906 {
9907 str++;
9908 if (my_get_expression (&inst.reloc.exp, &str))
9909 return;
9910 }
9911 else if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9912 return;
9913 }
9914
9915 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
9916 for the latter case, EXPR contains the immediate that was found. */
9917
9918 if (Rn != FAIL)
9919 {
9920 if (Rs != Rd)
9921 {
9922 inst.error = _("source1 and dest must be same register");
9923 return;
9924 }
9925
9926 switch (shift)
9927 {
9928 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_R; break;
9929 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_R; break;
9930 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_R; break;
9931 }
9932
9933 inst.instruction |= Rd | (Rn << 3);
9934 }
9935 else
9936 {
9937 switch (shift)
9938 {
9939 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_I; break;
9940 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_I; break;
9941 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_I; break;
9942 }
9943
9944 if (inst.reloc.exp.X_op != O_constant)
9945 {
9946 /* Value isn't known yet, create a dummy reloc and let reloc
9947 hacking fix it up. */
9948 inst.reloc.type = BFD_RELOC_ARM_THUMB_SHIFT;
9949 }
9950 else
9951 {
9952 unsigned shift_value = inst.reloc.exp.X_add_number;
9953
9954 if (shift_value > 32 || (shift_value == 32 && shift == THUMB_LSL))
9955 {
9956 inst.error = _("invalid immediate for shift");
9957 return;
9958 }
9959
9960 /* Shifts of zero are handled by converting to LSL. */
9961 if (shift_value == 0)
9962 inst.instruction = T_OPCODE_LSL_I;
9963
9964 /* Shifts of 32 are encoded as a shift of zero. */
9965 if (shift_value == 32)
9966 shift_value = 0;
9967
9968 inst.instruction |= shift_value << 6;
9969 }
9970
9971 inst.instruction |= Rd | (Rs << 3);
9972 }
9973
9974 end_of_line (str);
9975 }
9976
9977 static void
9978 thumb_mov_compare (str, move)
9979 char * str;
9980 int move;
9981 {
9982 int Rd, Rs = FAIL;
9983
9984 skip_whitespace (str);
9985
9986 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
9987 || skip_past_comma (&str) == FAIL)
9988 {
9989 if (! inst.error)
9990 inst.error = BAD_ARGS;
9991 return;
9992 }
9993
9994 if (move != THUMB_CPY && is_immediate_prefix (*str))
9995 {
9996 str++;
9997 if (my_get_expression (&inst.reloc.exp, &str))
9998 return;
9999 }
10000 else if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
10001 return;
10002
10003 if (Rs != FAIL)
10004 {
10005 if (move != THUMB_CPY && Rs < 8 && Rd < 8)
10006 {
10007 if (move == THUMB_MOVE)
10008 /* A move of two lowregs is encoded as ADD Rd, Rs, #0
10009 since a MOV instruction produces unpredictable results. */
10010 inst.instruction = T_OPCODE_ADD_I3;
10011 else
10012 inst.instruction = T_OPCODE_CMP_LR;
10013 inst.instruction |= Rd | (Rs << 3);
10014 }
10015 else
10016 {
10017 if (move == THUMB_MOVE)
10018 inst.instruction = T_OPCODE_MOV_HR;
10019 else if (move != THUMB_CPY)
10020 inst.instruction = T_OPCODE_CMP_HR;
10021
10022 if (Rd > 7)
10023 inst.instruction |= THUMB_H1;
10024
10025 if (Rs > 7)
10026 inst.instruction |= THUMB_H2;
10027
10028 inst.instruction |= (Rd & 7) | ((Rs & 7) << 3);
10029 }
10030 }
10031 else
10032 {
10033 if (Rd > 7)
10034 {
10035 inst.error = _("only lo regs allowed with immediate");
10036 return;
10037 }
10038
10039 if (move == THUMB_MOVE)
10040 inst.instruction = T_OPCODE_MOV_I8;
10041 else
10042 inst.instruction = T_OPCODE_CMP_I8;
10043
10044 inst.instruction |= Rd << 8;
10045
10046 if (inst.reloc.exp.X_op != O_constant)
10047 inst.reloc.type = BFD_RELOC_ARM_THUMB_IMM;
10048 else
10049 {
10050 unsigned value = inst.reloc.exp.X_add_number;
10051
10052 if (value > 255)
10053 {
10054 inst.error = _("invalid immediate");
10055 return;
10056 }
10057
10058 inst.instruction |= value;
10059 }
10060 }
10061
10062 end_of_line (str);
10063 }
10064
10065 static void
10066 thumb_load_store (str, load_store, size)
10067 char * str;
10068 int load_store;
10069 int size;
10070 {
10071 int Rd, Rb, Ro = FAIL;
10072
10073 skip_whitespace (str);
10074
10075 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
10076 || skip_past_comma (&str) == FAIL)
10077 {
10078 if (! inst.error)
10079 inst.error = BAD_ARGS;
10080 return;
10081 }
10082
10083 if (*str == '[')
10084 {
10085 str++;
10086 if ((Rb = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
10087 return;
10088
10089 if (skip_past_comma (&str) != FAIL)
10090 {
10091 if (is_immediate_prefix (*str))
10092 {
10093 str++;
10094 if (my_get_expression (&inst.reloc.exp, &str))
10095 return;
10096 }
10097 else if ((Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
10098 return;
10099 }
10100 else
10101 {
10102 inst.reloc.exp.X_op = O_constant;
10103 inst.reloc.exp.X_add_number = 0;
10104 }
10105
10106 if (*str != ']')
10107 {
10108 inst.error = _("expected ']'");
10109 return;
10110 }
10111 str++;
10112 }
10113 else if (*str == '=')
10114 {
10115 if (load_store != THUMB_LOAD)
10116 {
10117 inst.error = _("invalid pseudo operation");
10118 return;
10119 }
10120
10121 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
10122 str++;
10123
10124 skip_whitespace (str);
10125
10126 if (my_get_expression (& inst.reloc.exp, & str))
10127 return;
10128
10129 end_of_line (str);
10130
10131 if ( inst.reloc.exp.X_op != O_constant
10132 && inst.reloc.exp.X_op != O_symbol)
10133 {
10134 inst.error = "Constant expression expected";
10135 return;
10136 }
10137
10138 if (inst.reloc.exp.X_op == O_constant
10139 && ((inst.reloc.exp.X_add_number & ~0xFF) == 0))
10140 {
10141 /* This can be done with a mov instruction. */
10142
10143 inst.instruction = T_OPCODE_MOV_I8 | (Rd << 8);
10144 inst.instruction |= inst.reloc.exp.X_add_number;
10145 return;
10146 }
10147
10148 /* Insert into literal pool. */
10149 if (add_to_lit_pool () == FAIL)
10150 {
10151 if (!inst.error)
10152 inst.error = "literal pool insertion failed";
10153 return;
10154 }
10155
10156 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
10157 inst.reloc.pc_rel = 1;
10158 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
10159 /* Adjust ARM pipeline offset to Thumb. */
10160 inst.reloc.exp.X_add_number += 4;
10161
10162 return;
10163 }
10164 else
10165 {
10166 if (my_get_expression (&inst.reloc.exp, &str))
10167 return;
10168
10169 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
10170 inst.reloc.pc_rel = 1;
10171 inst.reloc.exp.X_add_number -= 4; /* Pipeline offset. */
10172 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
10173 end_of_line (str);
10174 return;
10175 }
10176
10177 if (Rb == REG_PC || Rb == REG_SP)
10178 {
10179 if (size != THUMB_WORD)
10180 {
10181 inst.error = _("byte or halfword not valid for base register");
10182 return;
10183 }
10184 else if (Rb == REG_PC && load_store != THUMB_LOAD)
10185 {
10186 inst.error = _("r15 based store not allowed");
10187 return;
10188 }
10189 else if (Ro != FAIL)
10190 {
10191 inst.error = _("invalid base register for register offset");
10192 return;
10193 }
10194
10195 if (Rb == REG_PC)
10196 inst.instruction = T_OPCODE_LDR_PC;
10197 else if (load_store == THUMB_LOAD)
10198 inst.instruction = T_OPCODE_LDR_SP;
10199 else
10200 inst.instruction = T_OPCODE_STR_SP;
10201
10202 inst.instruction |= Rd << 8;
10203 if (inst.reloc.exp.X_op == O_constant)
10204 {
10205 unsigned offset = inst.reloc.exp.X_add_number;
10206
10207 if (offset & ~0x3fc)
10208 {
10209 inst.error = _("invalid offset");
10210 return;
10211 }
10212
10213 inst.instruction |= offset >> 2;
10214 }
10215 else
10216 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
10217 }
10218 else if (Rb > 7)
10219 {
10220 inst.error = _("invalid base register in load/store");
10221 return;
10222 }
10223 else if (Ro == FAIL)
10224 {
10225 /* Immediate offset. */
10226 if (size == THUMB_WORD)
10227 inst.instruction = (load_store == THUMB_LOAD
10228 ? T_OPCODE_LDR_IW : T_OPCODE_STR_IW);
10229 else if (size == THUMB_HALFWORD)
10230 inst.instruction = (load_store == THUMB_LOAD
10231 ? T_OPCODE_LDR_IH : T_OPCODE_STR_IH);
10232 else
10233 inst.instruction = (load_store == THUMB_LOAD
10234 ? T_OPCODE_LDR_IB : T_OPCODE_STR_IB);
10235
10236 inst.instruction |= Rd | (Rb << 3);
10237
10238 if (inst.reloc.exp.X_op == O_constant)
10239 {
10240 unsigned offset = inst.reloc.exp.X_add_number;
10241
10242 if (offset & ~(0x1f << size))
10243 {
10244 inst.error = _("invalid offset");
10245 return;
10246 }
10247 inst.instruction |= (offset >> size) << 6;
10248 }
10249 else
10250 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
10251 }
10252 else
10253 {
10254 /* Register offset. */
10255 if (size == THUMB_WORD)
10256 inst.instruction = (load_store == THUMB_LOAD
10257 ? T_OPCODE_LDR_RW : T_OPCODE_STR_RW);
10258 else if (size == THUMB_HALFWORD)
10259 inst.instruction = (load_store == THUMB_LOAD
10260 ? T_OPCODE_LDR_RH : T_OPCODE_STR_RH);
10261 else
10262 inst.instruction = (load_store == THUMB_LOAD
10263 ? T_OPCODE_LDR_RB : T_OPCODE_STR_RB);
10264
10265 inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
10266 }
10267
10268 end_of_line (str);
10269 }
10270
10271 /* A register must be given at this point.
10272
10273 Shift is the place to put it in inst.instruction.
10274
10275 Restores input start point on err.
10276 Returns the reg#, or FAIL. */
10277
10278 static int
10279 mav_reg_required_here (str, shift, regtype)
10280 char ** str;
10281 int shift;
10282 enum arm_reg_type regtype;
10283 {
10284 int reg;
10285 char *start = *str;
10286
10287 if ((reg = arm_reg_parse (str, all_reg_maps[regtype].htab)) != FAIL)
10288 {
10289 if (shift >= 0)
10290 inst.instruction |= reg << shift;
10291
10292 return reg;
10293 }
10294
10295 /* Restore the start point. */
10296 *str = start;
10297
10298 /* In the few cases where we might be able to accept something else
10299 this error can be overridden. */
10300 inst.error = _(all_reg_maps[regtype].expected);
10301
10302 return FAIL;
10303 }
10304
10305 /* Cirrus Maverick Instructions. */
10306
10307 /* Wrapper functions. */
10308
10309 static void
10310 do_mav_binops_1a (str)
10311 char * str;
10312 {
10313 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVF);
10314 }
10315
10316 static void
10317 do_mav_binops_1b (str)
10318 char * str;
10319 {
10320 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVD);
10321 }
10322
10323 static void
10324 do_mav_binops_1c (str)
10325 char * str;
10326 {
10327 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVDX);
10328 }
10329
10330 static void
10331 do_mav_binops_1d (str)
10332 char * str;
10333 {
10334 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVF);
10335 }
10336
10337 static void
10338 do_mav_binops_1e (str)
10339 char * str;
10340 {
10341 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVD);
10342 }
10343
10344 static void
10345 do_mav_binops_1f (str)
10346 char * str;
10347 {
10348 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVF);
10349 }
10350
10351 static void
10352 do_mav_binops_1g (str)
10353 char * str;
10354 {
10355 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVD);
10356 }
10357
10358 static void
10359 do_mav_binops_1h (str)
10360 char * str;
10361 {
10362 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVFX);
10363 }
10364
10365 static void
10366 do_mav_binops_1i (str)
10367 char * str;
10368 {
10369 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVFX);
10370 }
10371
10372 static void
10373 do_mav_binops_1j (str)
10374 char * str;
10375 {
10376 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVDX);
10377 }
10378
10379 static void
10380 do_mav_binops_1k (str)
10381 char * str;
10382 {
10383 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVDX);
10384 }
10385
10386 static void
10387 do_mav_binops_1l (str)
10388 char * str;
10389 {
10390 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVF);
10391 }
10392
10393 static void
10394 do_mav_binops_1m (str)
10395 char * str;
10396 {
10397 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVD);
10398 }
10399
10400 static void
10401 do_mav_binops_1n (str)
10402 char * str;
10403 {
10404 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVFX);
10405 }
10406
10407 static void
10408 do_mav_binops_1o (str)
10409 char * str;
10410 {
10411 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVDX, REG_TYPE_MVDX);
10412 }
10413
10414 static void
10415 do_mav_binops_2a (str)
10416 char * str;
10417 {
10418 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVF, REG_TYPE_RN);
10419 }
10420
10421 static void
10422 do_mav_binops_2b (str)
10423 char * str;
10424 {
10425 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVD, REG_TYPE_RN);
10426 }
10427
10428 static void
10429 do_mav_binops_2c (str)
10430 char * str;
10431 {
10432 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVDX, REG_TYPE_RN);
10433 }
10434
10435 static void
10436 do_mav_binops_3a (str)
10437 char * str;
10438 {
10439 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVAX, REG_TYPE_MVFX);
10440 }
10441
10442 static void
10443 do_mav_binops_3b (str)
10444 char * str;
10445 {
10446 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVFX, REG_TYPE_MVAX);
10447 }
10448
10449 static void
10450 do_mav_binops_3c (str)
10451 char * str;
10452 {
10453 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVAX, REG_TYPE_MVDX);
10454 }
10455
10456 static void
10457 do_mav_binops_3d (str)
10458 char * str;
10459 {
10460 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVDX, REG_TYPE_MVAX);
10461 }
10462
10463 static void
10464 do_mav_triple_4a (str)
10465 char * str;
10466 {
10467 do_mav_triple (str, MAV_MODE4, REG_TYPE_MVFX, REG_TYPE_MVFX, REG_TYPE_RN);
10468 }
10469
10470 static void
10471 do_mav_triple_4b (str)
10472 char * str;
10473 {
10474 do_mav_triple (str, MAV_MODE4, REG_TYPE_MVDX, REG_TYPE_MVDX, REG_TYPE_RN);
10475 }
10476
10477 static void
10478 do_mav_triple_5a (str)
10479 char * str;
10480 {
10481 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVF, REG_TYPE_MVF);
10482 }
10483
10484 static void
10485 do_mav_triple_5b (str)
10486 char * str;
10487 {
10488 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVD, REG_TYPE_MVD);
10489 }
10490
10491 static void
10492 do_mav_triple_5c (str)
10493 char * str;
10494 {
10495 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVFX, REG_TYPE_MVFX);
10496 }
10497
10498 static void
10499 do_mav_triple_5d (str)
10500 char * str;
10501 {
10502 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVDX, REG_TYPE_MVDX);
10503 }
10504
10505 static void
10506 do_mav_triple_5e (str)
10507 char * str;
10508 {
10509 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVF, REG_TYPE_MVF, REG_TYPE_MVF);
10510 }
10511
10512 static void
10513 do_mav_triple_5f (str)
10514 char * str;
10515 {
10516 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVD, REG_TYPE_MVD, REG_TYPE_MVD);
10517 }
10518
10519 static void
10520 do_mav_triple_5g (str)
10521 char * str;
10522 {
10523 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVFX, REG_TYPE_MVFX, REG_TYPE_MVFX);
10524 }
10525
10526 static void
10527 do_mav_triple_5h (str)
10528 char * str;
10529 {
10530 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVDX, REG_TYPE_MVDX, REG_TYPE_MVDX);
10531 }
10532
10533 static void
10534 do_mav_quad_6a (str)
10535 char * str;
10536 {
10537 do_mav_quad (str, MAV_MODE6, REG_TYPE_MVAX, REG_TYPE_MVFX, REG_TYPE_MVFX,
10538 REG_TYPE_MVFX);
10539 }
10540
10541 static void
10542 do_mav_quad_6b (str)
10543 char * str;
10544 {
10545 do_mav_quad (str, MAV_MODE6, REG_TYPE_MVAX, REG_TYPE_MVAX, REG_TYPE_MVFX,
10546 REG_TYPE_MVFX);
10547 }
10548
10549 /* cfmvsc32<cond> DSPSC,MVFX[15:0]. */
10550 static void
10551 do_mav_dspsc_1 (str)
10552 char * str;
10553 {
10554 skip_whitespace (str);
10555
10556 /* cfmvsc32. */
10557 if (mav_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL
10558 || skip_past_comma (&str) == FAIL
10559 || mav_reg_required_here (&str, 16, REG_TYPE_MVFX) == FAIL)
10560 {
10561 if (!inst.error)
10562 inst.error = BAD_ARGS;
10563
10564 return;
10565 }
10566
10567 end_of_line (str);
10568 }
10569
10570 /* cfmv32sc<cond> MVFX[15:0],DSPSC. */
10571 static void
10572 do_mav_dspsc_2 (str)
10573 char * str;
10574 {
10575 skip_whitespace (str);
10576
10577 /* cfmv32sc. */
10578 if (mav_reg_required_here (&str, 0, REG_TYPE_MVFX) == FAIL
10579 || skip_past_comma (&str) == FAIL
10580 || mav_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL)
10581 {
10582 if (!inst.error)
10583 inst.error = BAD_ARGS;
10584
10585 return;
10586 }
10587
10588 end_of_line (str);
10589 }
10590
10591 static void
10592 do_mav_shift_1 (str)
10593 char * str;
10594 {
10595 do_mav_shift (str, REG_TYPE_MVFX, REG_TYPE_MVFX);
10596 }
10597
10598 static void
10599 do_mav_shift_2 (str)
10600 char * str;
10601 {
10602 do_mav_shift (str, REG_TYPE_MVDX, REG_TYPE_MVDX);
10603 }
10604
10605 static void
10606 do_mav_ldst_1 (str)
10607 char * str;
10608 {
10609 do_mav_ldst (str, REG_TYPE_MVF);
10610 }
10611
10612 static void
10613 do_mav_ldst_2 (str)
10614 char * str;
10615 {
10616 do_mav_ldst (str, REG_TYPE_MVD);
10617 }
10618
10619 static void
10620 do_mav_ldst_3 (str)
10621 char * str;
10622 {
10623 do_mav_ldst (str, REG_TYPE_MVFX);
10624 }
10625
10626 static void
10627 do_mav_ldst_4 (str)
10628 char * str;
10629 {
10630 do_mav_ldst (str, REG_TYPE_MVDX);
10631 }
10632
10633 /* Isnsn like "foo X,Y". */
10634
10635 static void
10636 do_mav_binops (str, mode, reg0, reg1)
10637 char * str;
10638 int mode;
10639 enum arm_reg_type reg0;
10640 enum arm_reg_type reg1;
10641 {
10642 int shift0, shift1;
10643
10644 shift0 = mode & 0xff;
10645 shift1 = (mode >> 8) & 0xff;
10646
10647 skip_whitespace (str);
10648
10649 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
10650 || skip_past_comma (&str) == FAIL
10651 || mav_reg_required_here (&str, shift1, reg1) == FAIL)
10652 {
10653 if (!inst.error)
10654 inst.error = BAD_ARGS;
10655 }
10656 else
10657 end_of_line (str);
10658 }
10659
10660 /* Isnsn like "foo X,Y,Z". */
10661
10662 static void
10663 do_mav_triple (str, mode, reg0, reg1, reg2)
10664 char * str;
10665 int mode;
10666 enum arm_reg_type reg0;
10667 enum arm_reg_type reg1;
10668 enum arm_reg_type reg2;
10669 {
10670 int shift0, shift1, shift2;
10671
10672 shift0 = mode & 0xff;
10673 shift1 = (mode >> 8) & 0xff;
10674 shift2 = (mode >> 16) & 0xff;
10675
10676 skip_whitespace (str);
10677
10678 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
10679 || skip_past_comma (&str) == FAIL
10680 || mav_reg_required_here (&str, shift1, reg1) == FAIL
10681 || skip_past_comma (&str) == FAIL
10682 || mav_reg_required_here (&str, shift2, reg2) == 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 W,X,Y,Z".
10692 where W=MVAX[0:3] and X,Y,Z=MVFX[0:15]. */
10693
10694 static void
10695 do_mav_quad (str, mode, reg0, reg1, reg2, reg3)
10696 char * str;
10697 int mode;
10698 enum arm_reg_type reg0;
10699 enum arm_reg_type reg1;
10700 enum arm_reg_type reg2;
10701 enum arm_reg_type reg3;
10702 {
10703 int shift0, shift1, shift2, shift3;
10704
10705 shift0= mode & 0xff;
10706 shift1 = (mode >> 8) & 0xff;
10707 shift2 = (mode >> 16) & 0xff;
10708 shift3 = (mode >> 24) & 0xff;
10709
10710 skip_whitespace (str);
10711
10712 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
10713 || skip_past_comma (&str) == FAIL
10714 || mav_reg_required_here (&str, shift1, reg1) == FAIL
10715 || skip_past_comma (&str) == FAIL
10716 || mav_reg_required_here (&str, shift2, reg2) == FAIL
10717 || skip_past_comma (&str) == FAIL
10718 || mav_reg_required_here (&str, shift3, reg3) == FAIL)
10719 {
10720 if (!inst.error)
10721 inst.error = BAD_ARGS;
10722 }
10723 else
10724 end_of_line (str);
10725 }
10726
10727 /* Maverick shift immediate instructions.
10728 cfsh32<cond> MVFX[15:0],MVFX[15:0],Shift[6:0].
10729 cfsh64<cond> MVDX[15:0],MVDX[15:0],Shift[6:0]. */
10730
10731 static void
10732 do_mav_shift (str, reg0, reg1)
10733 char * str;
10734 enum arm_reg_type reg0;
10735 enum arm_reg_type reg1;
10736 {
10737 int error;
10738 int imm, neg = 0;
10739
10740 skip_whitespace (str);
10741
10742 error = 0;
10743
10744 if (mav_reg_required_here (&str, 12, reg0) == FAIL
10745 || skip_past_comma (&str) == FAIL
10746 || mav_reg_required_here (&str, 16, reg1) == FAIL
10747 || skip_past_comma (&str) == FAIL)
10748 {
10749 if (!inst.error)
10750 inst.error = BAD_ARGS;
10751 return;
10752 }
10753
10754 /* Calculate the immediate operand.
10755 The operand is a 7bit signed number. */
10756 skip_whitespace (str);
10757
10758 if (*str == '#')
10759 ++str;
10760
10761 if (!ISDIGIT (*str) && *str != '-')
10762 {
10763 inst.error = _("expecting immediate, 7bit operand");
10764 return;
10765 }
10766
10767 if (*str == '-')
10768 {
10769 neg = 1;
10770 ++str;
10771 }
10772
10773 for (imm = 0; *str && ISDIGIT (*str); ++str)
10774 imm = imm * 10 + *str - '0';
10775
10776 if (imm > 64)
10777 {
10778 inst.error = _("immediate out of range");
10779 return;
10780 }
10781
10782 /* Make negative imm's into 7bit signed numbers. */
10783 if (neg)
10784 {
10785 imm = -imm;
10786 imm &= 0x0000007f;
10787 }
10788
10789 /* Bits 0-3 of the insn should have bits 0-3 of the immediate.
10790 Bits 5-7 of the insn should have bits 4-6 of the immediate.
10791 Bit 4 should be 0. */
10792 imm = (imm & 0xf) | ((imm & 0x70) << 1);
10793
10794 inst.instruction |= imm;
10795 end_of_line (str);
10796 }
10797
10798 static int
10799 mav_parse_offset (str, negative)
10800 char ** str;
10801 int *negative;
10802 {
10803 char * p = *str;
10804 int offset;
10805
10806 *negative = 0;
10807
10808 skip_whitespace (p);
10809
10810 if (*p == '#')
10811 ++p;
10812
10813 if (*p == '-')
10814 {
10815 *negative = 1;
10816 ++p;
10817 }
10818
10819 if (!ISDIGIT (*p))
10820 {
10821 inst.error = _("offset expected");
10822 return 0;
10823 }
10824
10825 for (offset = 0; *p && ISDIGIT (*p); ++p)
10826 offset = offset * 10 + *p - '0';
10827
10828 if (offset > 0xff)
10829 {
10830 inst.error = _("offset out of range");
10831 return 0;
10832 }
10833
10834 *str = p;
10835
10836 return *negative ? -offset : offset;
10837 }
10838
10839 /* Maverick load/store instructions.
10840 <insn><cond> CRd,[Rn,<offset>]{!}.
10841 <insn><cond> CRd,[Rn],<offset>. */
10842
10843 static void
10844 do_mav_ldst (str, reg0)
10845 char * str;
10846 enum arm_reg_type reg0;
10847 {
10848 int offset, negative;
10849
10850 skip_whitespace (str);
10851
10852 if (mav_reg_required_here (&str, 12, reg0) == FAIL
10853 || skip_past_comma (&str) == FAIL
10854 || *str++ != '['
10855 || reg_required_here (&str, 16) == FAIL)
10856 goto fail_ldst;
10857
10858 if (skip_past_comma (&str) == SUCCESS)
10859 {
10860 /* You are here: "<offset>]{!}". */
10861 inst.instruction |= PRE_INDEX;
10862
10863 offset = mav_parse_offset (&str, &negative);
10864
10865 if (inst.error)
10866 return;
10867
10868 if (*str++ != ']')
10869 {
10870 inst.error = _("missing ]");
10871 return;
10872 }
10873
10874 if (*str == '!')
10875 {
10876 inst.instruction |= WRITE_BACK;
10877 ++str;
10878 }
10879 }
10880 else
10881 {
10882 /* You are here: "], <offset>". */
10883 if (*str++ != ']')
10884 {
10885 inst.error = _("missing ]");
10886 return;
10887 }
10888
10889 if (skip_past_comma (&str) == FAIL
10890 || (offset = mav_parse_offset (&str, &negative), inst.error))
10891 goto fail_ldst;
10892
10893 inst.instruction |= CP_T_WB; /* Post indexed, set bit W. */
10894 }
10895
10896 if (negative)
10897 offset = -offset;
10898 else
10899 inst.instruction |= CP_T_UD; /* Positive, so set bit U. */
10900
10901 inst.instruction |= offset >> 2;
10902 end_of_line (str);
10903 return;
10904
10905 fail_ldst:
10906 if (!inst.error)
10907 inst.error = BAD_ARGS;
10908 }
10909
10910 static void
10911 do_t_nop (str)
10912 char * str;
10913 {
10914 /* Do nothing. */
10915 end_of_line (str);
10916 }
10917
10918 /* Handle the Format 4 instructions that do not have equivalents in other
10919 formats. That is, ADC, AND, EOR, SBC, ROR, TST, NEG, CMN, ORR, MUL,
10920 BIC and MVN. */
10921
10922 static void
10923 do_t_arit (str)
10924 char * str;
10925 {
10926 int Rd, Rs, Rn;
10927
10928 skip_whitespace (str);
10929
10930 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
10931 || skip_past_comma (&str) == FAIL
10932 || (Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
10933 {
10934 inst.error = BAD_ARGS;
10935 return;
10936 }
10937
10938 if (skip_past_comma (&str) != FAIL)
10939 {
10940 /* Three operand format not allowed for TST, CMN, NEG and MVN.
10941 (It isn't allowed for CMP either, but that isn't handled by this
10942 function.) */
10943 if (inst.instruction == T_OPCODE_TST
10944 || inst.instruction == T_OPCODE_CMN
10945 || inst.instruction == T_OPCODE_NEG
10946 || inst.instruction == T_OPCODE_MVN)
10947 {
10948 inst.error = BAD_ARGS;
10949 return;
10950 }
10951
10952 if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
10953 return;
10954
10955 if (Rs != Rd)
10956 {
10957 inst.error = _("dest and source1 must be the same register");
10958 return;
10959 }
10960 Rs = Rn;
10961 }
10962
10963 if (inst.instruction == T_OPCODE_MUL
10964 && Rs == Rd)
10965 as_tsktsk (_("Rs and Rd must be different in MUL"));
10966
10967 inst.instruction |= Rd | (Rs << 3);
10968 end_of_line (str);
10969 }
10970
10971 static void
10972 do_t_add (str)
10973 char * str;
10974 {
10975 thumb_add_sub (str, 0);
10976 }
10977
10978 static void
10979 do_t_asr (str)
10980 char * str;
10981 {
10982 thumb_shift (str, THUMB_ASR);
10983 }
10984
10985 static void
10986 do_t_branch9 (str)
10987 char * str;
10988 {
10989 if (my_get_expression (&inst.reloc.exp, &str))
10990 return;
10991 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH9;
10992 inst.reloc.pc_rel = 1;
10993 end_of_line (str);
10994 }
10995
10996 static void
10997 do_t_branch12 (str)
10998 char * str;
10999 {
11000 if (my_get_expression (&inst.reloc.exp, &str))
11001 return;
11002 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH12;
11003 inst.reloc.pc_rel = 1;
11004 end_of_line (str);
11005 }
11006
11007 /* Find the real, Thumb encoded start of a Thumb function. */
11008
11009 static symbolS *
11010 find_real_start (symbolP)
11011 symbolS * symbolP;
11012 {
11013 char * real_start;
11014 const char * name = S_GET_NAME (symbolP);
11015 symbolS * new_target;
11016
11017 /* This definition must agree with the one in gcc/config/arm/thumb.c. */
11018 #define STUB_NAME ".real_start_of"
11019
11020 if (name == NULL)
11021 abort ();
11022
11023 /* Names that start with '.' are local labels, not function entry points.
11024 The compiler may generate BL instructions to these labels because it
11025 needs to perform a branch to a far away location. */
11026 if (name[0] == '.')
11027 return symbolP;
11028
11029 real_start = malloc (strlen (name) + strlen (STUB_NAME) + 1);
11030 sprintf (real_start, "%s%s", STUB_NAME, name);
11031
11032 new_target = symbol_find (real_start);
11033
11034 if (new_target == NULL)
11035 {
11036 as_warn ("Failed to find real start of function: %s\n", name);
11037 new_target = symbolP;
11038 }
11039
11040 free (real_start);
11041
11042 return new_target;
11043 }
11044
11045 static void
11046 do_t_branch23 (str)
11047 char * str;
11048 {
11049 if (my_get_expression (& inst.reloc.exp, & str))
11050 return;
11051
11052 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH23;
11053 inst.reloc.pc_rel = 1;
11054 end_of_line (str);
11055
11056 /* If the destination of the branch is a defined symbol which does not have
11057 the THUMB_FUNC attribute, then we must be calling a function which has
11058 the (interfacearm) attribute. We look for the Thumb entry point to that
11059 function and change the branch to refer to that function instead. */
11060 if ( inst.reloc.exp.X_op == O_symbol
11061 && inst.reloc.exp.X_add_symbol != NULL
11062 && S_IS_DEFINED (inst.reloc.exp.X_add_symbol)
11063 && ! THUMB_IS_FUNC (inst.reloc.exp.X_add_symbol))
11064 inst.reloc.exp.X_add_symbol =
11065 find_real_start (inst.reloc.exp.X_add_symbol);
11066 }
11067
11068 static void
11069 do_t_bx (str)
11070 char * str;
11071 {
11072 int reg;
11073
11074 skip_whitespace (str);
11075
11076 if ((reg = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
11077 return;
11078
11079 /* This sets THUMB_H2 from the top bit of reg. */
11080 inst.instruction |= reg << 3;
11081
11082 /* ??? FIXME: Should add a hacky reloc here if reg is REG_PC. The reloc
11083 should cause the alignment to be checked once it is known. This is
11084 because BX PC only works if the instruction is word aligned. */
11085
11086 end_of_line (str);
11087 }
11088
11089 static void
11090 do_t_compare (str)
11091 char * str;
11092 {
11093 thumb_mov_compare (str, THUMB_COMPARE);
11094 }
11095
11096 static void
11097 do_t_ldmstm (str)
11098 char * str;
11099 {
11100 int Rb;
11101 long range;
11102
11103 skip_whitespace (str);
11104
11105 if ((Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
11106 return;
11107
11108 if (*str != '!')
11109 as_warn (_("inserted missing '!': load/store multiple always writes back base register"));
11110 else
11111 str++;
11112
11113 if (skip_past_comma (&str) == FAIL
11114 || (range = reg_list (&str)) == FAIL)
11115 {
11116 if (! inst.error)
11117 inst.error = BAD_ARGS;
11118 return;
11119 }
11120
11121 if (inst.reloc.type != BFD_RELOC_NONE)
11122 {
11123 /* This really doesn't seem worth it. */
11124 inst.reloc.type = BFD_RELOC_NONE;
11125 inst.error = _("expression too complex");
11126 return;
11127 }
11128
11129 if (range & ~0xff)
11130 {
11131 inst.error = _("only lo-regs valid in load/store multiple");
11132 return;
11133 }
11134
11135 inst.instruction |= (Rb << 8) | range;
11136 end_of_line (str);
11137 }
11138
11139 static void
11140 do_t_ldr (str)
11141 char * str;
11142 {
11143 thumb_load_store (str, THUMB_LOAD, THUMB_WORD);
11144 }
11145
11146 static void
11147 do_t_ldrb (str)
11148 char * str;
11149 {
11150 thumb_load_store (str, THUMB_LOAD, THUMB_BYTE);
11151 }
11152
11153 static void
11154 do_t_ldrh (str)
11155 char * str;
11156 {
11157 thumb_load_store (str, THUMB_LOAD, THUMB_HALFWORD);
11158 }
11159
11160 static void
11161 do_t_lds (str)
11162 char * str;
11163 {
11164 int Rd, Rb, Ro;
11165
11166 skip_whitespace (str);
11167
11168 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
11169 || skip_past_comma (&str) == FAIL
11170 || *str++ != '['
11171 || (Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL
11172 || skip_past_comma (&str) == FAIL
11173 || (Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL
11174 || *str++ != ']')
11175 {
11176 if (! inst.error)
11177 inst.error = _("syntax: ldrs[b] Rd, [Rb, Ro]");
11178 return;
11179 }
11180
11181 inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
11182 end_of_line (str);
11183 }
11184
11185 static void
11186 do_t_lsl (str)
11187 char * str;
11188 {
11189 thumb_shift (str, THUMB_LSL);
11190 }
11191
11192 static void
11193 do_t_lsr (str)
11194 char * str;
11195 {
11196 thumb_shift (str, THUMB_LSR);
11197 }
11198
11199 static void
11200 do_t_mov (str)
11201 char * str;
11202 {
11203 thumb_mov_compare (str, THUMB_MOVE);
11204 }
11205
11206 static void
11207 do_t_push_pop (str)
11208 char * str;
11209 {
11210 long range;
11211
11212 skip_whitespace (str);
11213
11214 if ((range = reg_list (&str)) == FAIL)
11215 {
11216 if (! inst.error)
11217 inst.error = BAD_ARGS;
11218 return;
11219 }
11220
11221 if (inst.reloc.type != BFD_RELOC_NONE)
11222 {
11223 /* This really doesn't seem worth it. */
11224 inst.reloc.type = BFD_RELOC_NONE;
11225 inst.error = _("expression too complex");
11226 return;
11227 }
11228
11229 if (range & ~0xff)
11230 {
11231 if ((inst.instruction == T_OPCODE_PUSH
11232 && (range & ~0xff) == 1 << REG_LR)
11233 || (inst.instruction == T_OPCODE_POP
11234 && (range & ~0xff) == 1 << REG_PC))
11235 {
11236 inst.instruction |= THUMB_PP_PC_LR;
11237 range &= 0xff;
11238 }
11239 else
11240 {
11241 inst.error = _("invalid register list to push/pop instruction");
11242 return;
11243 }
11244 }
11245
11246 inst.instruction |= range;
11247 end_of_line (str);
11248 }
11249
11250 static void
11251 do_t_str (str)
11252 char * str;
11253 {
11254 thumb_load_store (str, THUMB_STORE, THUMB_WORD);
11255 }
11256
11257 static void
11258 do_t_strb (str)
11259 char * str;
11260 {
11261 thumb_load_store (str, THUMB_STORE, THUMB_BYTE);
11262 }
11263
11264 static void
11265 do_t_strh (str)
11266 char * str;
11267 {
11268 thumb_load_store (str, THUMB_STORE, THUMB_HALFWORD);
11269 }
11270
11271 static void
11272 do_t_sub (str)
11273 char * str;
11274 {
11275 thumb_add_sub (str, 1);
11276 }
11277
11278 static void
11279 do_t_swi (str)
11280 char * str;
11281 {
11282 skip_whitespace (str);
11283
11284 if (my_get_expression (&inst.reloc.exp, &str))
11285 return;
11286
11287 inst.reloc.type = BFD_RELOC_ARM_SWI;
11288 end_of_line (str);
11289 }
11290
11291 static void
11292 do_t_adr (str)
11293 char * str;
11294 {
11295 int reg;
11296
11297 /* This is a pseudo-op of the form "adr rd, label" to be converted
11298 into a relative address of the form "add rd, pc, #label-.-4". */
11299 skip_whitespace (str);
11300
11301 /* Store Rd in temporary location inside instruction. */
11302 if ((reg = reg_required_here (&str, 4)) == FAIL
11303 || (reg > 7) /* For Thumb reg must be r0..r7. */
11304 || skip_past_comma (&str) == FAIL
11305 || my_get_expression (&inst.reloc.exp, &str))
11306 {
11307 if (!inst.error)
11308 inst.error = BAD_ARGS;
11309 return;
11310 }
11311
11312 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
11313 inst.reloc.exp.X_add_number -= 4; /* PC relative adjust. */
11314 inst.reloc.pc_rel = 1;
11315 inst.instruction |= REG_PC; /* Rd is already placed into the instruction. */
11316
11317 end_of_line (str);
11318 }
11319
11320 static void
11321 insert_reg (r, htab)
11322 const struct reg_entry *r;
11323 struct hash_control *htab;
11324 {
11325 int len = strlen (r->name) + 2;
11326 char * buf = (char *) xmalloc (len);
11327 char * buf2 = (char *) xmalloc (len);
11328 int i = 0;
11329
11330 #ifdef REGISTER_PREFIX
11331 buf[i++] = REGISTER_PREFIX;
11332 #endif
11333
11334 strcpy (buf + i, r->name);
11335
11336 for (i = 0; buf[i]; i++)
11337 buf2[i] = TOUPPER (buf[i]);
11338
11339 buf2[i] = '\0';
11340
11341 hash_insert (htab, buf, (PTR) r);
11342 hash_insert (htab, buf2, (PTR) r);
11343 }
11344
11345 static void
11346 build_reg_hsh (map)
11347 struct reg_map *map;
11348 {
11349 const struct reg_entry *r;
11350
11351 if ((map->htab = hash_new ()) == NULL)
11352 as_fatal (_("virtual memory exhausted"));
11353
11354 for (r = map->names; r->name != NULL; r++)
11355 insert_reg (r, map->htab);
11356 }
11357
11358 static void
11359 insert_reg_alias (str, regnum, htab)
11360 char *str;
11361 int regnum;
11362 struct hash_control *htab;
11363 {
11364 const char *error;
11365 struct reg_entry *new = xmalloc (sizeof (struct reg_entry));
11366 const char *name = xmalloc (strlen (str) + 1);
11367
11368 strcpy ((char *) name, str);
11369
11370 new->name = name;
11371 new->number = regnum;
11372 new->builtin = FALSE;
11373
11374 error = hash_insert (htab, name, (PTR) new);
11375 if (error)
11376 {
11377 as_bad (_("failed to create an alias for %s, reason: %s"),
11378 str, error);
11379 free ((char *) name);
11380 free (new);
11381 }
11382 }
11383
11384 /* Look for the .req directive. This is of the form:
11385
11386 new_register_name .req existing_register_name
11387
11388 If we find one, or if it looks sufficiently like one that we want to
11389 handle any error here, return non-zero. Otherwise return zero. */
11390 static int
11391 create_register_alias (newname, p)
11392 char *newname;
11393 char *p;
11394 {
11395 char *q;
11396 char c;
11397
11398 q = p;
11399 skip_whitespace (q);
11400
11401 c = *p;
11402 *p = '\0';
11403
11404 if (*q && !strncmp (q, ".req ", 5))
11405 {
11406 char *copy_of_str;
11407 char *r;
11408
11409 #ifdef IGNORE_OPCODE_CASE
11410 newname = original_case_string;
11411 #endif
11412 copy_of_str = newname;
11413
11414 q += 4;
11415 skip_whitespace (q);
11416
11417 for (r = q; *r != '\0'; r++)
11418 if (*r == ' ')
11419 break;
11420
11421 if (r != q)
11422 {
11423 enum arm_reg_type new_type, old_type;
11424 int old_regno;
11425 char d = *r;
11426
11427 *r = '\0';
11428 old_type = arm_reg_parse_any (q);
11429 *r = d;
11430
11431 new_type = arm_reg_parse_any (newname);
11432
11433 if (new_type == REG_TYPE_MAX)
11434 {
11435 if (old_type != REG_TYPE_MAX)
11436 {
11437 old_regno = arm_reg_parse (&q, all_reg_maps[old_type].htab);
11438 insert_reg_alias (newname, old_regno,
11439 all_reg_maps[old_type].htab);
11440 }
11441 else
11442 as_warn (_("register '%s' does not exist\n"), q);
11443 }
11444 else if (old_type == REG_TYPE_MAX)
11445 {
11446 as_warn (_("ignoring redefinition of register alias '%s' to non-existant register '%s'"),
11447 copy_of_str, q);
11448 }
11449 else
11450 {
11451 /* Do not warn about redefinitions to the same alias. */
11452 if (new_type != old_type
11453 || (arm_reg_parse (&q, all_reg_maps[old_type].htab)
11454 != arm_reg_parse (&q, all_reg_maps[new_type].htab)))
11455 as_warn (_("ignoring redefinition of register alias '%s'"),
11456 copy_of_str);
11457
11458 }
11459 }
11460 else
11461 as_warn (_("ignoring incomplete .req pseuso op"));
11462
11463 *p = c;
11464 return 1;
11465 }
11466
11467 *p = c;
11468 return 0;
11469 }
11470
11471 static void
11472 set_constant_flonums ()
11473 {
11474 int i;
11475
11476 for (i = 0; i < NUM_FLOAT_VALS; i++)
11477 if (atof_ieee ((char *) fp_const[i], 'x', fp_values[i]) == NULL)
11478 abort ();
11479 }
11480
11481 /* Iterate over the base tables to create the instruction patterns. */
11482 static void
11483 build_arm_ops_hsh ()
11484 {
11485 unsigned int i;
11486 unsigned int j;
11487 static struct obstack insn_obstack;
11488
11489 obstack_begin (&insn_obstack, 4000);
11490
11491 for (i = 0; i < sizeof (insns) / sizeof (struct asm_opcode); i++)
11492 {
11493 const struct asm_opcode *insn = insns + i;
11494
11495 if (insn->cond_offset != 0)
11496 {
11497 /* Insn supports conditional execution. Build the varaints
11498 and insert them in the hash table. */
11499 for (j = 0; j < sizeof (conds) / sizeof (struct asm_cond); j++)
11500 {
11501 unsigned len = strlen (insn->template);
11502 struct asm_opcode *new;
11503 char *template;
11504
11505 new = obstack_alloc (&insn_obstack, sizeof (struct asm_opcode));
11506 /* All condition codes are two characters. */
11507 template = obstack_alloc (&insn_obstack, len + 3);
11508
11509 strncpy (template, insn->template, insn->cond_offset);
11510 strcpy (template + insn->cond_offset, conds[j].template);
11511 if (len > insn->cond_offset)
11512 strcpy (template + insn->cond_offset + 2,
11513 insn->template + insn->cond_offset);
11514 new->template = template;
11515 new->cond_offset = 0;
11516 new->variant = insn->variant;
11517 new->parms = insn->parms;
11518 new->value = (insn->value & ~COND_MASK) | conds[j].value;
11519
11520 hash_insert (arm_ops_hsh, new->template, (PTR) new);
11521 }
11522 }
11523 /* Finally, insert the unconditional insn in the table directly;
11524 no need to build a copy. */
11525 hash_insert (arm_ops_hsh, insn->template, (PTR) insn);
11526 }
11527 }
11528
11529 #if 0 /* Suppressed - for now. */
11530 #if defined OBJ_ELF || defined OBJ_COFF
11531
11532 #ifdef OBJ_ELF
11533 #define arm_Note Elf_External_Note
11534 #else
11535 typedef struct
11536 {
11537 unsigned char namesz[4]; /* Size of entry's owner string. */
11538 unsigned char descsz[4]; /* Size of the note descriptor. */
11539 unsigned char type[4]; /* Interpretation of the descriptor. */
11540 char name[1]; /* Start of the name+desc data. */
11541 } arm_Note;
11542 #endif
11543
11544 /* The description is kept to a fix sized in order to make updating
11545 it and merging it easier. */
11546 #define ARM_NOTE_DESCRIPTION_LENGTH 8
11547
11548 static void
11549 arm_add_note (name, description, type)
11550 const char * name;
11551 const char * description;
11552 unsigned int type;
11553 {
11554 arm_Note note ATTRIBUTE_UNUSED;
11555 char * p;
11556 unsigned int name_len;
11557
11558 name_len = (strlen (name) + 1 + 3) & ~3;
11559
11560 p = frag_more (sizeof (note.namesz));
11561 md_number_to_chars (p, (valueT) name_len, sizeof (note.namesz));
11562
11563 p = frag_more (sizeof (note.descsz));
11564 md_number_to_chars (p, (valueT) ARM_NOTE_DESCRIPTION_LENGTH, sizeof (note.descsz));
11565
11566 p = frag_more (sizeof (note.type));
11567 md_number_to_chars (p, (valueT) type, sizeof (note.type));
11568
11569 p = frag_more (name_len);
11570 strcpy (p, name);
11571
11572 p = frag_more (ARM_NOTE_DESCRIPTION_LENGTH);
11573 strncpy (p, description, ARM_NOTE_DESCRIPTION_LENGTH);
11574 frag_align (2, 0, 0);
11575 }
11576 #endif
11577 #endif
11578
11579 void
11580 md_begin ()
11581 {
11582 unsigned mach;
11583 unsigned int i;
11584
11585 if ( (arm_ops_hsh = hash_new ()) == NULL
11586 || (arm_tops_hsh = hash_new ()) == NULL
11587 || (arm_cond_hsh = hash_new ()) == NULL
11588 || (arm_shift_hsh = hash_new ()) == NULL
11589 || (arm_psr_hsh = hash_new ()) == NULL)
11590 as_fatal (_("virtual memory exhausted"));
11591
11592 build_arm_ops_hsh ();
11593 for (i = 0; i < sizeof (tinsns) / sizeof (struct thumb_opcode); i++)
11594 hash_insert (arm_tops_hsh, tinsns[i].template, (PTR) (tinsns + i));
11595 for (i = 0; i < sizeof (conds) / sizeof (struct asm_cond); i++)
11596 hash_insert (arm_cond_hsh, conds[i].template, (PTR) (conds + i));
11597 for (i = 0; i < sizeof (shift_names) / sizeof (struct asm_shift_name); i++)
11598 hash_insert (arm_shift_hsh, shift_names[i].name, (PTR) (shift_names + i));
11599 for (i = 0; i < sizeof (psrs) / sizeof (struct asm_psr); i++)
11600 hash_insert (arm_psr_hsh, psrs[i].template, (PTR) (psrs + i));
11601
11602 for (i = (int) REG_TYPE_FIRST; i < (int) REG_TYPE_MAX; i++)
11603 build_reg_hsh (all_reg_maps + i);
11604
11605 set_constant_flonums ();
11606
11607 /* Set the cpu variant based on the command-line options. We prefer
11608 -mcpu= over -march= if both are set (as for GCC); and we prefer
11609 -mfpu= over any other way of setting the floating point unit.
11610 Use of legacy options with new options are faulted. */
11611 if (legacy_cpu != -1)
11612 {
11613 if (mcpu_cpu_opt != -1 || march_cpu_opt != -1)
11614 as_bad (_("use of old and new-style options to set CPU type"));
11615
11616 mcpu_cpu_opt = legacy_cpu;
11617 }
11618 else if (mcpu_cpu_opt == -1)
11619 mcpu_cpu_opt = march_cpu_opt;
11620
11621 if (legacy_fpu != -1)
11622 {
11623 if (mfpu_opt != -1)
11624 as_bad (_("use of old and new-style options to set FPU type"));
11625
11626 mfpu_opt = legacy_fpu;
11627 }
11628 else if (mfpu_opt == -1)
11629 {
11630 #if !(defined (TE_LINUX) || defined (TE_NetBSD))
11631 /* Some environments specify a default FPU. If they don't, infer it
11632 from the processor. */
11633 if (mcpu_fpu_opt != -1)
11634 mfpu_opt = mcpu_fpu_opt;
11635 else
11636 mfpu_opt = march_fpu_opt;
11637 #else
11638 mfpu_opt = FPU_DEFAULT;
11639 #endif
11640 }
11641
11642 if (mfpu_opt == -1)
11643 {
11644 if (mcpu_cpu_opt == -1)
11645 mfpu_opt = FPU_DEFAULT;
11646 else if (mcpu_cpu_opt & ARM_EXT_V5)
11647 mfpu_opt = FPU_ARCH_VFP_V2;
11648 else
11649 mfpu_opt = FPU_ARCH_FPA;
11650 }
11651
11652 if (mcpu_cpu_opt == -1)
11653 mcpu_cpu_opt = CPU_DEFAULT;
11654
11655 cpu_variant = mcpu_cpu_opt | mfpu_opt;
11656
11657 #if defined OBJ_COFF || defined OBJ_ELF
11658 {
11659 unsigned int flags = 0;
11660
11661 /* Set the flags in the private structure. */
11662 if (uses_apcs_26) flags |= F_APCS26;
11663 if (support_interwork) flags |= F_INTERWORK;
11664 if (uses_apcs_float) flags |= F_APCS_FLOAT;
11665 if (pic_code) flags |= F_PIC;
11666 if ((cpu_variant & FPU_ANY) == FPU_NONE
11667 || (cpu_variant & FPU_ANY) == FPU_ARCH_VFP) /* VFP layout only. */
11668 {
11669 flags |= F_SOFT_FLOAT;
11670 }
11671 switch (mfloat_abi_opt)
11672 {
11673 case ARM_FLOAT_ABI_SOFT:
11674 case ARM_FLOAT_ABI_SOFTFP:
11675 flags |= F_SOFT_FLOAT;
11676 break;
11677
11678 case ARM_FLOAT_ABI_HARD:
11679 if (flags & F_SOFT_FLOAT)
11680 as_bad (_("hard-float conflicts with specified fpu"));
11681 break;
11682 }
11683 /* Using VFP conventions (even if soft-float). */
11684 if (cpu_variant & FPU_VFP_EXT_NONE) flags |= F_VFP_FLOAT;
11685
11686 #if defined OBJ_ELF
11687 if (cpu_variant & FPU_ARCH_MAVERICK)
11688 flags |= EF_ARM_MAVERICK_FLOAT;
11689 #endif
11690
11691 bfd_set_private_flags (stdoutput, flags);
11692
11693 /* We have run out flags in the COFF header to encode the
11694 status of ATPCS support, so instead we create a dummy,
11695 empty, debug section called .arm.atpcs. */
11696 if (atpcs)
11697 {
11698 asection * sec;
11699
11700 sec = bfd_make_section (stdoutput, ".arm.atpcs");
11701
11702 if (sec != NULL)
11703 {
11704 bfd_set_section_flags
11705 (stdoutput, sec, SEC_READONLY | SEC_DEBUGGING /* | SEC_HAS_CONTENTS */);
11706 bfd_set_section_size (stdoutput, sec, 0);
11707 bfd_set_section_contents (stdoutput, sec, NULL, 0, 0);
11708 }
11709 }
11710 }
11711 #endif
11712
11713 /* Record the CPU type as well. */
11714 switch (cpu_variant & ARM_CPU_MASK)
11715 {
11716 case ARM_2:
11717 mach = bfd_mach_arm_2;
11718 break;
11719
11720 case ARM_3: /* Also ARM_250. */
11721 mach = bfd_mach_arm_2a;
11722 break;
11723
11724 case ARM_6: /* Also ARM_7. */
11725 mach = bfd_mach_arm_3;
11726 break;
11727
11728 default:
11729 mach = bfd_mach_arm_unknown;
11730 break;
11731 }
11732
11733 /* Catch special cases. */
11734 if (cpu_variant & ARM_CEXT_IWMMXT)
11735 mach = bfd_mach_arm_iWMMXt;
11736 else if (cpu_variant & ARM_CEXT_XSCALE)
11737 mach = bfd_mach_arm_XScale;
11738 else if (cpu_variant & ARM_CEXT_MAVERICK)
11739 mach = bfd_mach_arm_ep9312;
11740 else if (cpu_variant & ARM_EXT_V5E)
11741 mach = bfd_mach_arm_5TE;
11742 else if (cpu_variant & ARM_EXT_V5)
11743 {
11744 if (cpu_variant & ARM_EXT_V4T)
11745 mach = bfd_mach_arm_5T;
11746 else
11747 mach = bfd_mach_arm_5;
11748 }
11749 else if (cpu_variant & ARM_EXT_V4)
11750 {
11751 if (cpu_variant & ARM_EXT_V4T)
11752 mach = bfd_mach_arm_4T;
11753 else
11754 mach = bfd_mach_arm_4;
11755 }
11756 else if (cpu_variant & ARM_EXT_V3M)
11757 mach = bfd_mach_arm_3M;
11758
11759 #if 0 /* Suppressed - for now. */
11760 #if defined (OBJ_ELF) || defined (OBJ_COFF)
11761
11762 /* Create a .note section to fully identify this arm binary. */
11763
11764 #define NOTE_ARCH_STRING "arch: "
11765
11766 #if defined OBJ_COFF && ! defined NT_VERSION
11767 #define NT_VERSION 1
11768 #define NT_ARCH 2
11769 #endif
11770
11771 {
11772 segT current_seg = now_seg;
11773 subsegT current_subseg = now_subseg;
11774 asection * arm_arch;
11775 const char * arch_string;
11776
11777 arm_arch = bfd_make_section_old_way (stdoutput, ARM_NOTE_SECTION);
11778
11779 #ifdef OBJ_COFF
11780 bfd_set_section_flags (stdoutput, arm_arch,
11781 SEC_DATA | SEC_ALLOC | SEC_LOAD | SEC_LINK_ONCE \
11782 | SEC_HAS_CONTENTS);
11783 #endif
11784 arm_arch->output_section = arm_arch;
11785 subseg_set (arm_arch, 0);
11786
11787 switch (mach)
11788 {
11789 default:
11790 case bfd_mach_arm_unknown: arch_string = "unknown"; break;
11791 case bfd_mach_arm_2: arch_string = "armv2"; break;
11792 case bfd_mach_arm_2a: arch_string = "armv2a"; break;
11793 case bfd_mach_arm_3: arch_string = "armv3"; break;
11794 case bfd_mach_arm_3M: arch_string = "armv3M"; break;
11795 case bfd_mach_arm_4: arch_string = "armv4"; break;
11796 case bfd_mach_arm_4T: arch_string = "armv4t"; break;
11797 case bfd_mach_arm_5: arch_string = "armv5"; break;
11798 case bfd_mach_arm_5T: arch_string = "armv5t"; break;
11799 case bfd_mach_arm_5TE: arch_string = "armv5te"; break;
11800 case bfd_mach_arm_XScale: arch_string = "XScale"; break;
11801 case bfd_mach_arm_ep9312: arch_string = "ep9312"; break;
11802 case bfd_mach_arm_iWMMXt: arch_string = "iWMMXt"; break;
11803 }
11804
11805 arm_add_note (NOTE_ARCH_STRING, arch_string, NT_ARCH);
11806
11807 subseg_set (current_seg, current_subseg);
11808 }
11809 #endif
11810 #endif /* Suppressed code. */
11811
11812 bfd_set_arch_mach (stdoutput, TARGET_ARCH, mach);
11813 }
11814
11815 /* Turn an integer of n bytes (in val) into a stream of bytes appropriate
11816 for use in the a.out file, and stores them in the array pointed to by buf.
11817 This knows about the endian-ness of the target machine and does
11818 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
11819 2 (short) and 4 (long) Floating numbers are put out as a series of
11820 LITTLENUMS (shorts, here at least). */
11821
11822 void
11823 md_number_to_chars (buf, val, n)
11824 char * buf;
11825 valueT val;
11826 int n;
11827 {
11828 if (target_big_endian)
11829 number_to_chars_bigendian (buf, val, n);
11830 else
11831 number_to_chars_littleendian (buf, val, n);
11832 }
11833
11834 static valueT
11835 md_chars_to_number (buf, n)
11836 char * buf;
11837 int n;
11838 {
11839 valueT result = 0;
11840 unsigned char * where = (unsigned char *) buf;
11841
11842 if (target_big_endian)
11843 {
11844 while (n--)
11845 {
11846 result <<= 8;
11847 result |= (*where++ & 255);
11848 }
11849 }
11850 else
11851 {
11852 while (n--)
11853 {
11854 result <<= 8;
11855 result |= (where[n] & 255);
11856 }
11857 }
11858
11859 return result;
11860 }
11861
11862 /* Turn a string in input_line_pointer into a floating point constant
11863 of type TYPE, and store the appropriate bytes in *LITP. The number
11864 of LITTLENUMS emitted is stored in *SIZEP. An error message is
11865 returned, or NULL on OK.
11866
11867 Note that fp constants aren't represent in the normal way on the ARM.
11868 In big endian mode, things are as expected. However, in little endian
11869 mode fp constants are big-endian word-wise, and little-endian byte-wise
11870 within the words. For example, (double) 1.1 in big endian mode is
11871 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
11872 the byte sequence 99 99 f1 3f 9a 99 99 99.
11873
11874 ??? The format of 12 byte floats is uncertain according to gcc's arm.h. */
11875
11876 char *
11877 md_atof (type, litP, sizeP)
11878 char type;
11879 char * litP;
11880 int * sizeP;
11881 {
11882 int prec;
11883 LITTLENUM_TYPE words[MAX_LITTLENUMS];
11884 char *t;
11885 int i;
11886
11887 switch (type)
11888 {
11889 case 'f':
11890 case 'F':
11891 case 's':
11892 case 'S':
11893 prec = 2;
11894 break;
11895
11896 case 'd':
11897 case 'D':
11898 case 'r':
11899 case 'R':
11900 prec = 4;
11901 break;
11902
11903 case 'x':
11904 case 'X':
11905 prec = 6;
11906 break;
11907
11908 case 'p':
11909 case 'P':
11910 prec = 6;
11911 break;
11912
11913 default:
11914 *sizeP = 0;
11915 return _("bad call to MD_ATOF()");
11916 }
11917
11918 t = atof_ieee (input_line_pointer, type, words);
11919 if (t)
11920 input_line_pointer = t;
11921 *sizeP = prec * 2;
11922
11923 if (target_big_endian)
11924 {
11925 for (i = 0; i < prec; i++)
11926 {
11927 md_number_to_chars (litP, (valueT) words[i], 2);
11928 litP += 2;
11929 }
11930 }
11931 else
11932 {
11933 if (cpu_variant & FPU_ARCH_VFP)
11934 for (i = prec - 1; i >= 0; i--)
11935 {
11936 md_number_to_chars (litP, (valueT) words[i], 2);
11937 litP += 2;
11938 }
11939 else
11940 /* For a 4 byte float the order of elements in `words' is 1 0.
11941 For an 8 byte float the order is 1 0 3 2. */
11942 for (i = 0; i < prec; i += 2)
11943 {
11944 md_number_to_chars (litP, (valueT) words[i + 1], 2);
11945 md_number_to_chars (litP + 2, (valueT) words[i], 2);
11946 litP += 4;
11947 }
11948 }
11949
11950 return 0;
11951 }
11952
11953 /* The knowledge of the PC's pipeline offset is built into the insns
11954 themselves. */
11955
11956 long
11957 md_pcrel_from (fixP)
11958 fixS * fixP;
11959 {
11960 if (fixP->fx_addsy
11961 && S_GET_SEGMENT (fixP->fx_addsy) == undefined_section
11962 && fixP->fx_subsy == NULL)
11963 return 0;
11964
11965 if (fixP->fx_pcrel && (fixP->fx_r_type == BFD_RELOC_ARM_THUMB_ADD))
11966 {
11967 /* PC relative addressing on the Thumb is slightly odd
11968 as the bottom two bits of the PC are forced to zero
11969 for the calculation. */
11970 return (fixP->fx_where + fixP->fx_frag->fr_address) & ~3;
11971 }
11972
11973 #ifdef TE_WINCE
11974 /* The pattern was adjusted to accommodate CE's off-by-one fixups,
11975 so we un-adjust here to compensate for the accommodation. */
11976 return fixP->fx_where + fixP->fx_frag->fr_address + 8;
11977 #else
11978 return fixP->fx_where + fixP->fx_frag->fr_address;
11979 #endif
11980 }
11981
11982 /* Round up a section size to the appropriate boundary. */
11983
11984 valueT
11985 md_section_align (segment, size)
11986 segT segment ATTRIBUTE_UNUSED;
11987 valueT size;
11988 {
11989 #ifdef OBJ_ELF
11990 return size;
11991 #else
11992 /* Round all sects to multiple of 4. */
11993 return (size + 3) & ~3;
11994 #endif
11995 }
11996
11997 /* Under ELF we need to default _GLOBAL_OFFSET_TABLE.
11998 Otherwise we have no need to default values of symbols. */
11999
12000 symbolS *
12001 md_undefined_symbol (name)
12002 char * name ATTRIBUTE_UNUSED;
12003 {
12004 #ifdef OBJ_ELF
12005 if (name[0] == '_' && name[1] == 'G'
12006 && streq (name, GLOBAL_OFFSET_TABLE_NAME))
12007 {
12008 if (!GOT_symbol)
12009 {
12010 if (symbol_find (name))
12011 as_bad ("GOT already in the symbol table");
12012
12013 GOT_symbol = symbol_new (name, undefined_section,
12014 (valueT) 0, & zero_address_frag);
12015 }
12016
12017 return GOT_symbol;
12018 }
12019 #endif
12020
12021 return 0;
12022 }
12023
12024 /* arm_reg_parse () := if it looks like a register, return its token and
12025 advance the pointer. */
12026
12027 static int
12028 arm_reg_parse (ccp, htab)
12029 register char ** ccp;
12030 struct hash_control *htab;
12031 {
12032 char * start = * ccp;
12033 char c;
12034 char * p;
12035 struct reg_entry * reg;
12036
12037 #ifdef REGISTER_PREFIX
12038 if (*start != REGISTER_PREFIX)
12039 return FAIL;
12040 p = start + 1;
12041 #else
12042 p = start;
12043 #ifdef OPTIONAL_REGISTER_PREFIX
12044 if (*p == OPTIONAL_REGISTER_PREFIX)
12045 p++, start++;
12046 #endif
12047 #endif
12048 if (!ISALPHA (*p) || !is_name_beginner (*p))
12049 return FAIL;
12050
12051 c = *p++;
12052 while (ISALPHA (c) || ISDIGIT (c) || c == '_')
12053 c = *p++;
12054
12055 *--p = 0;
12056 reg = (struct reg_entry *) hash_find (htab, start);
12057 *p = c;
12058
12059 if (reg)
12060 {
12061 *ccp = p;
12062 return reg->number;
12063 }
12064
12065 return FAIL;
12066 }
12067
12068 /* Search for the following register name in each of the possible reg name
12069 tables. Return the classification if found, or REG_TYPE_MAX if not
12070 present. */
12071 static enum arm_reg_type
12072 arm_reg_parse_any (cp)
12073 char *cp;
12074 {
12075 int i;
12076
12077 for (i = (int) REG_TYPE_FIRST; i < (int) REG_TYPE_MAX; i++)
12078 if (arm_reg_parse (&cp, all_reg_maps[i].htab) != FAIL)
12079 return (enum arm_reg_type) i;
12080
12081 return REG_TYPE_MAX;
12082 }
12083
12084 void
12085 md_apply_fix3 (fixP, valP, seg)
12086 fixS * fixP;
12087 valueT * valP;
12088 segT seg;
12089 {
12090 offsetT value = * valP;
12091 offsetT newval;
12092 unsigned int newimm;
12093 unsigned long temp;
12094 int sign;
12095 char * buf = fixP->fx_where + fixP->fx_frag->fr_literal;
12096 arm_fix_data * arm_data = (arm_fix_data *) fixP->tc_fix_data;
12097
12098 assert (fixP->fx_r_type < BFD_RELOC_UNUSED);
12099
12100 /* Note whether this will delete the relocation. */
12101 #if 0
12102 /* Patch from REarnshaw to JDavis (disabled for the moment, since it
12103 doesn't work fully.) */
12104 if ((fixP->fx_addsy == 0 || symbol_constant_p (fixP->fx_addsy))
12105 && !fixP->fx_pcrel)
12106 #else
12107 if (fixP->fx_addsy == 0 && !fixP->fx_pcrel)
12108 #endif
12109 fixP->fx_done = 1;
12110
12111 /* If this symbol is in a different section then we need to leave it for
12112 the linker to deal with. Unfortunately, md_pcrel_from can't tell,
12113 so we have to undo it's effects here. */
12114 if (fixP->fx_pcrel)
12115 {
12116 if (fixP->fx_addsy != NULL
12117 && S_IS_DEFINED (fixP->fx_addsy)
12118 && S_GET_SEGMENT (fixP->fx_addsy) != seg)
12119 {
12120 if (target_oabi
12121 && (fixP->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH
12122 || fixP->fx_r_type == BFD_RELOC_ARM_PCREL_BLX
12123 ))
12124 value = 0;
12125 else
12126 value += md_pcrel_from (fixP);
12127 }
12128 }
12129
12130 /* Remember value for emit_reloc. */
12131 fixP->fx_addnumber = value;
12132
12133 switch (fixP->fx_r_type)
12134 {
12135 case BFD_RELOC_ARM_IMMEDIATE:
12136 newimm = validate_immediate (value);
12137 temp = md_chars_to_number (buf, INSN_SIZE);
12138
12139 /* If the instruction will fail, see if we can fix things up by
12140 changing the opcode. */
12141 if (newimm == (unsigned int) FAIL
12142 && (newimm = negate_data_op (&temp, value)) == (unsigned int) FAIL)
12143 {
12144 as_bad_where (fixP->fx_file, fixP->fx_line,
12145 _("invalid constant (%lx) after fixup"),
12146 (unsigned long) value);
12147 break;
12148 }
12149
12150 newimm |= (temp & 0xfffff000);
12151 md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
12152 fixP->fx_done = 1;
12153 break;
12154
12155 case BFD_RELOC_ARM_ADRL_IMMEDIATE:
12156 {
12157 unsigned int highpart = 0;
12158 unsigned int newinsn = 0xe1a00000; /* nop. */
12159
12160 newimm = validate_immediate (value);
12161 temp = md_chars_to_number (buf, INSN_SIZE);
12162
12163 /* If the instruction will fail, see if we can fix things up by
12164 changing the opcode. */
12165 if (newimm == (unsigned int) FAIL
12166 && (newimm = negate_data_op (& temp, value)) == (unsigned int) FAIL)
12167 {
12168 /* No ? OK - try using two ADD instructions to generate
12169 the value. */
12170 newimm = validate_immediate_twopart (value, & highpart);
12171
12172 /* Yes - then make sure that the second instruction is
12173 also an add. */
12174 if (newimm != (unsigned int) FAIL)
12175 newinsn = temp;
12176 /* Still No ? Try using a negated value. */
12177 else if ((newimm = validate_immediate_twopart (- value, & highpart)) != (unsigned int) FAIL)
12178 temp = newinsn = (temp & OPCODE_MASK) | OPCODE_SUB << DATA_OP_SHIFT;
12179 /* Otherwise - give up. */
12180 else
12181 {
12182 as_bad_where (fixP->fx_file, fixP->fx_line,
12183 _("unable to compute ADRL instructions for PC offset of 0x%lx"),
12184 (long) value);
12185 break;
12186 }
12187
12188 /* Replace the first operand in the 2nd instruction (which
12189 is the PC) with the destination register. We have
12190 already added in the PC in the first instruction and we
12191 do not want to do it again. */
12192 newinsn &= ~ 0xf0000;
12193 newinsn |= ((newinsn & 0x0f000) << 4);
12194 }
12195
12196 newimm |= (temp & 0xfffff000);
12197 md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
12198
12199 highpart |= (newinsn & 0xfffff000);
12200 md_number_to_chars (buf + INSN_SIZE, (valueT) highpart, INSN_SIZE);
12201 }
12202 break;
12203
12204 case BFD_RELOC_ARM_OFFSET_IMM:
12205 sign = value >= 0;
12206
12207 if (value < 0)
12208 value = - value;
12209
12210 if (validate_offset_imm (value, 0) == FAIL)
12211 {
12212 as_bad_where (fixP->fx_file, fixP->fx_line,
12213 _("bad immediate value for offset (%ld)"),
12214 (long) value);
12215 break;
12216 }
12217
12218 newval = md_chars_to_number (buf, INSN_SIZE);
12219 newval &= 0xff7ff000;
12220 newval |= value | (sign ? INDEX_UP : 0);
12221 md_number_to_chars (buf, newval, INSN_SIZE);
12222 break;
12223
12224 case BFD_RELOC_ARM_OFFSET_IMM8:
12225 case BFD_RELOC_ARM_HWLITERAL:
12226 sign = value >= 0;
12227
12228 if (value < 0)
12229 value = - value;
12230
12231 if (validate_offset_imm (value, 1) == FAIL)
12232 {
12233 if (fixP->fx_r_type == BFD_RELOC_ARM_HWLITERAL)
12234 as_bad_where (fixP->fx_file, fixP->fx_line,
12235 _("invalid literal constant: pool needs to be closer"));
12236 else
12237 as_bad (_("bad immediate value for half-word offset (%ld)"),
12238 (long) value);
12239 break;
12240 }
12241
12242 newval = md_chars_to_number (buf, INSN_SIZE);
12243 newval &= 0xff7ff0f0;
12244 newval |= ((value >> 4) << 8) | (value & 0xf) | (sign ? INDEX_UP : 0);
12245 md_number_to_chars (buf, newval, INSN_SIZE);
12246 break;
12247
12248 case BFD_RELOC_ARM_LITERAL:
12249 sign = value >= 0;
12250
12251 if (value < 0)
12252 value = - value;
12253
12254 if (validate_offset_imm (value, 0) == FAIL)
12255 {
12256 as_bad_where (fixP->fx_file, fixP->fx_line,
12257 _("invalid literal constant: pool needs to be closer"));
12258 break;
12259 }
12260
12261 newval = md_chars_to_number (buf, INSN_SIZE);
12262 newval &= 0xff7ff000;
12263 newval |= value | (sign ? INDEX_UP : 0);
12264 md_number_to_chars (buf, newval, INSN_SIZE);
12265 break;
12266
12267 case BFD_RELOC_ARM_SHIFT_IMM:
12268 newval = md_chars_to_number (buf, INSN_SIZE);
12269 if (((unsigned long) value) > 32
12270 || (value == 32
12271 && (((newval & 0x60) == 0) || (newval & 0x60) == 0x60)))
12272 {
12273 as_bad_where (fixP->fx_file, fixP->fx_line,
12274 _("shift expression is too large"));
12275 break;
12276 }
12277
12278 if (value == 0)
12279 /* Shifts of zero must be done as lsl. */
12280 newval &= ~0x60;
12281 else if (value == 32)
12282 value = 0;
12283 newval &= 0xfffff07f;
12284 newval |= (value & 0x1f) << 7;
12285 md_number_to_chars (buf, newval, INSN_SIZE);
12286 break;
12287
12288 case BFD_RELOC_ARM_SWI:
12289 if (arm_data->thumb_mode)
12290 {
12291 if (((unsigned long) value) > 0xff)
12292 as_bad_where (fixP->fx_file, fixP->fx_line,
12293 _("invalid swi expression"));
12294 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xff00;
12295 newval |= value;
12296 md_number_to_chars (buf, newval, THUMB_SIZE);
12297 }
12298 else
12299 {
12300 if (((unsigned long) value) > 0x00ffffff)
12301 as_bad_where (fixP->fx_file, fixP->fx_line,
12302 _("invalid swi expression"));
12303 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff000000;
12304 newval |= value;
12305 md_number_to_chars (buf, newval, INSN_SIZE);
12306 }
12307 break;
12308
12309 case BFD_RELOC_ARM_MULTI:
12310 if (((unsigned long) value) > 0xffff)
12311 as_bad_where (fixP->fx_file, fixP->fx_line,
12312 _("invalid expression in load/store multiple"));
12313 newval = value | md_chars_to_number (buf, INSN_SIZE);
12314 md_number_to_chars (buf, newval, INSN_SIZE);
12315 break;
12316
12317 case BFD_RELOC_ARM_PCREL_BRANCH:
12318 newval = md_chars_to_number (buf, INSN_SIZE);
12319
12320 /* Sign-extend a 24-bit number. */
12321 #define SEXT24(x) ((((x) & 0xffffff) ^ (~ 0x7fffff)) + 0x800000)
12322
12323 #ifdef OBJ_ELF
12324 if (! target_oabi)
12325 value = fixP->fx_offset;
12326 #endif
12327
12328 /* We are going to store value (shifted right by two) in the
12329 instruction, in a 24 bit, signed field. Thus we need to check
12330 that none of the top 8 bits of the shifted value (top 7 bits of
12331 the unshifted, unsigned value) are set, or that they are all set. */
12332 if ((value & ~ ((offsetT) 0x1ffffff)) != 0
12333 && ((value & ~ ((offsetT) 0x1ffffff)) != ~ ((offsetT) 0x1ffffff)))
12334 {
12335 #ifdef OBJ_ELF
12336 /* Normally we would be stuck at this point, since we cannot store
12337 the absolute address that is the destination of the branch in the
12338 24 bits of the branch instruction. If however, we happen to know
12339 that the destination of the branch is in the same section as the
12340 branch instruction itself, then we can compute the relocation for
12341 ourselves and not have to bother the linker with it.
12342
12343 FIXME: The tests for OBJ_ELF and ! target_oabi are only here
12344 because I have not worked out how to do this for OBJ_COFF or
12345 target_oabi. */
12346 if (! target_oabi
12347 && fixP->fx_addsy != NULL
12348 && S_IS_DEFINED (fixP->fx_addsy)
12349 && S_GET_SEGMENT (fixP->fx_addsy) == seg)
12350 {
12351 /* Get pc relative value to go into the branch. */
12352 value = * valP;
12353
12354 /* Permit a backward branch provided that enough bits
12355 are set. Allow a forwards branch, provided that
12356 enough bits are clear. */
12357 if ( (value & ~ ((offsetT) 0x1ffffff)) == ~ ((offsetT) 0x1ffffff)
12358 || (value & ~ ((offsetT) 0x1ffffff)) == 0)
12359 fixP->fx_done = 1;
12360 }
12361
12362 if (! fixP->fx_done)
12363 #endif
12364 as_bad_where (fixP->fx_file, fixP->fx_line,
12365 _("GAS can't handle same-section branch dest >= 0x04000000"));
12366 }
12367
12368 value >>= 2;
12369 value += SEXT24 (newval);
12370
12371 if ( (value & ~ ((offsetT) 0xffffff)) != 0
12372 && ((value & ~ ((offsetT) 0xffffff)) != ~ ((offsetT) 0xffffff)))
12373 as_bad_where (fixP->fx_file, fixP->fx_line,
12374 _("out of range branch"));
12375
12376 newval = (value & 0x00ffffff) | (newval & 0xff000000);
12377 md_number_to_chars (buf, newval, INSN_SIZE);
12378 break;
12379
12380 case BFD_RELOC_ARM_PCREL_BLX:
12381 {
12382 offsetT hbit;
12383 newval = md_chars_to_number (buf, INSN_SIZE);
12384
12385 #ifdef OBJ_ELF
12386 if (! target_oabi)
12387 value = fixP->fx_offset;
12388 #endif
12389 hbit = (value >> 1) & 1;
12390 value = (value >> 2) & 0x00ffffff;
12391 value = (value + (newval & 0x00ffffff)) & 0x00ffffff;
12392 newval = value | (newval & 0xfe000000) | (hbit << 24);
12393 md_number_to_chars (buf, newval, INSN_SIZE);
12394 }
12395 break;
12396
12397 case BFD_RELOC_THUMB_PCREL_BRANCH9: /* Conditional branch. */
12398 newval = md_chars_to_number (buf, THUMB_SIZE);
12399 {
12400 addressT diff = (newval & 0xff) << 1;
12401 if (diff & 0x100)
12402 diff |= ~0xff;
12403
12404 value += diff;
12405 if ((value & ~0xff) && ((value & ~0xff) != ~0xff))
12406 as_bad_where (fixP->fx_file, fixP->fx_line,
12407 _("branch out of range"));
12408 newval = (newval & 0xff00) | ((value & 0x1ff) >> 1);
12409 }
12410 md_number_to_chars (buf, newval, THUMB_SIZE);
12411 break;
12412
12413 case BFD_RELOC_THUMB_PCREL_BRANCH12: /* Unconditional branch. */
12414 newval = md_chars_to_number (buf, THUMB_SIZE);
12415 {
12416 addressT diff = (newval & 0x7ff) << 1;
12417 if (diff & 0x800)
12418 diff |= ~0x7ff;
12419
12420 value += diff;
12421 if ((value & ~0x7ff) && ((value & ~0x7ff) != ~0x7ff))
12422 as_bad_where (fixP->fx_file, fixP->fx_line,
12423 _("branch out of range"));
12424 newval = (newval & 0xf800) | ((value & 0xfff) >> 1);
12425 }
12426 md_number_to_chars (buf, newval, THUMB_SIZE);
12427 break;
12428
12429 case BFD_RELOC_THUMB_PCREL_BLX:
12430 case BFD_RELOC_THUMB_PCREL_BRANCH23:
12431 {
12432 offsetT newval2;
12433 addressT diff;
12434
12435 newval = md_chars_to_number (buf, THUMB_SIZE);
12436 newval2 = md_chars_to_number (buf + THUMB_SIZE, THUMB_SIZE);
12437 diff = ((newval & 0x7ff) << 12) | ((newval2 & 0x7ff) << 1);
12438 if (diff & 0x400000)
12439 diff |= ~0x3fffff;
12440 #ifdef OBJ_ELF
12441 value = fixP->fx_offset;
12442 #endif
12443 value += diff;
12444
12445 if ((value & ~0x3fffff) && ((value & ~0x3fffff) != ~0x3fffff))
12446 as_bad_where (fixP->fx_file, fixP->fx_line,
12447 _("branch with link out of range"));
12448
12449 newval = (newval & 0xf800) | ((value & 0x7fffff) >> 12);
12450 newval2 = (newval2 & 0xf800) | ((value & 0xfff) >> 1);
12451 if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX)
12452 /* For a BLX instruction, make sure that the relocation is rounded up
12453 to a word boundary. This follows the semantics of the instruction
12454 which specifies that bit 1 of the target address will come from bit
12455 1 of the base address. */
12456 newval2 = (newval2 + 1) & ~ 1;
12457 md_number_to_chars (buf, newval, THUMB_SIZE);
12458 md_number_to_chars (buf + THUMB_SIZE, newval2, THUMB_SIZE);
12459 }
12460 break;
12461
12462 case BFD_RELOC_8:
12463 if (fixP->fx_done || fixP->fx_pcrel)
12464 md_number_to_chars (buf, value, 1);
12465 #ifdef OBJ_ELF
12466 else if (!target_oabi)
12467 {
12468 value = fixP->fx_offset;
12469 md_number_to_chars (buf, value, 1);
12470 }
12471 #endif
12472 break;
12473
12474 case BFD_RELOC_16:
12475 if (fixP->fx_done || fixP->fx_pcrel)
12476 md_number_to_chars (buf, value, 2);
12477 #ifdef OBJ_ELF
12478 else if (!target_oabi)
12479 {
12480 value = fixP->fx_offset;
12481 md_number_to_chars (buf, value, 2);
12482 }
12483 #endif
12484 break;
12485
12486 #ifdef OBJ_ELF
12487 case BFD_RELOC_ARM_GOT32:
12488 case BFD_RELOC_ARM_GOTOFF:
12489 md_number_to_chars (buf, 0, 4);
12490 break;
12491 #endif
12492
12493 case BFD_RELOC_RVA:
12494 case BFD_RELOC_32:
12495 if (fixP->fx_done || fixP->fx_pcrel)
12496 md_number_to_chars (buf, value, 4);
12497 #ifdef OBJ_ELF
12498 else if (!target_oabi)
12499 {
12500 value = fixP->fx_offset;
12501 md_number_to_chars (buf, value, 4);
12502 }
12503 #endif
12504 break;
12505
12506 #ifdef OBJ_ELF
12507 case BFD_RELOC_ARM_PLT32:
12508 /* It appears the instruction is fully prepared at this point. */
12509 break;
12510 #endif
12511
12512 case BFD_RELOC_ARM_CP_OFF_IMM:
12513 sign = value >= 0;
12514 if (value < -1023 || value > 1023 || (value & 3))
12515 as_bad_where (fixP->fx_file, fixP->fx_line,
12516 _("illegal value for co-processor offset"));
12517 if (value < 0)
12518 value = -value;
12519 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
12520 newval |= (value >> 2) | (sign ? INDEX_UP : 0);
12521 md_number_to_chars (buf, newval, INSN_SIZE);
12522 break;
12523
12524 case BFD_RELOC_ARM_CP_OFF_IMM_S2:
12525 sign = value >= 0;
12526 if (value < -255 || value > 255)
12527 as_bad_where (fixP->fx_file, fixP->fx_line,
12528 _("Illegal value for co-processor offset"));
12529 if (value < 0)
12530 value = -value;
12531 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
12532 newval |= value | (sign ? INDEX_UP : 0);
12533 md_number_to_chars (buf, newval , INSN_SIZE);
12534 break;
12535
12536 case BFD_RELOC_ARM_THUMB_OFFSET:
12537 newval = md_chars_to_number (buf, THUMB_SIZE);
12538 /* Exactly what ranges, and where the offset is inserted depends
12539 on the type of instruction, we can establish this from the
12540 top 4 bits. */
12541 switch (newval >> 12)
12542 {
12543 case 4: /* PC load. */
12544 /* Thumb PC loads are somewhat odd, bit 1 of the PC is
12545 forced to zero for these loads, so we will need to round
12546 up the offset if the instruction address is not word
12547 aligned (since the final address produced must be, and
12548 we can only describe word-aligned immediate offsets). */
12549
12550 if ((fixP->fx_frag->fr_address + fixP->fx_where + value) & 3)
12551 as_bad_where (fixP->fx_file, fixP->fx_line,
12552 _("invalid offset, target not word aligned (0x%08X)"),
12553 (unsigned int) (fixP->fx_frag->fr_address
12554 + fixP->fx_where + value));
12555
12556 if ((value + 2) & ~0x3fe)
12557 as_bad_where (fixP->fx_file, fixP->fx_line,
12558 _("invalid offset, value too big (0x%08lX)"),
12559 (long) value);
12560
12561 /* Round up, since pc will be rounded down. */
12562 newval |= (value + 2) >> 2;
12563 break;
12564
12565 case 9: /* SP load/store. */
12566 if (value & ~0x3fc)
12567 as_bad_where (fixP->fx_file, fixP->fx_line,
12568 _("invalid offset, value too big (0x%08lX)"),
12569 (long) value);
12570 newval |= value >> 2;
12571 break;
12572
12573 case 6: /* Word load/store. */
12574 if (value & ~0x7c)
12575 as_bad_where (fixP->fx_file, fixP->fx_line,
12576 _("invalid offset, value too big (0x%08lX)"),
12577 (long) value);
12578 newval |= value << 4; /* 6 - 2. */
12579 break;
12580
12581 case 7: /* Byte load/store. */
12582 if (value & ~0x1f)
12583 as_bad_where (fixP->fx_file, fixP->fx_line,
12584 _("invalid offset, value too big (0x%08lX)"),
12585 (long) value);
12586 newval |= value << 6;
12587 break;
12588
12589 case 8: /* Halfword load/store. */
12590 if (value & ~0x3e)
12591 as_bad_where (fixP->fx_file, fixP->fx_line,
12592 _("invalid offset, value too big (0x%08lX)"),
12593 (long) value);
12594 newval |= value << 5; /* 6 - 1. */
12595 break;
12596
12597 default:
12598 as_bad_where (fixP->fx_file, fixP->fx_line,
12599 "Unable to process relocation for thumb opcode: %lx",
12600 (unsigned long) newval);
12601 break;
12602 }
12603 md_number_to_chars (buf, newval, THUMB_SIZE);
12604 break;
12605
12606 case BFD_RELOC_ARM_THUMB_ADD:
12607 /* This is a complicated relocation, since we use it for all of
12608 the following immediate relocations:
12609
12610 3bit ADD/SUB
12611 8bit ADD/SUB
12612 9bit ADD/SUB SP word-aligned
12613 10bit ADD PC/SP word-aligned
12614
12615 The type of instruction being processed is encoded in the
12616 instruction field:
12617
12618 0x8000 SUB
12619 0x00F0 Rd
12620 0x000F Rs
12621 */
12622 newval = md_chars_to_number (buf, THUMB_SIZE);
12623 {
12624 int rd = (newval >> 4) & 0xf;
12625 int rs = newval & 0xf;
12626 int subtract = newval & 0x8000;
12627
12628 if (rd == REG_SP)
12629 {
12630 if (value & ~0x1fc)
12631 as_bad_where (fixP->fx_file, fixP->fx_line,
12632 _("invalid immediate for stack address calculation"));
12633 newval = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
12634 newval |= value >> 2;
12635 }
12636 else if (rs == REG_PC || rs == REG_SP)
12637 {
12638 if (subtract ||
12639 value & ~0x3fc)
12640 as_bad_where (fixP->fx_file, fixP->fx_line,
12641 _("invalid immediate for address calculation (value = 0x%08lX)"),
12642 (unsigned long) value);
12643 newval = (rs == REG_PC ? T_OPCODE_ADD_PC : T_OPCODE_ADD_SP);
12644 newval |= rd << 8;
12645 newval |= value >> 2;
12646 }
12647 else if (rs == rd)
12648 {
12649 if (value & ~0xff)
12650 as_bad_where (fixP->fx_file, fixP->fx_line,
12651 _("invalid 8bit immediate"));
12652 newval = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
12653 newval |= (rd << 8) | value;
12654 }
12655 else
12656 {
12657 if (value & ~0x7)
12658 as_bad_where (fixP->fx_file, fixP->fx_line,
12659 _("invalid 3bit immediate"));
12660 newval = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
12661 newval |= rd | (rs << 3) | (value << 6);
12662 }
12663 }
12664 md_number_to_chars (buf, newval, THUMB_SIZE);
12665 break;
12666
12667 case BFD_RELOC_ARM_THUMB_IMM:
12668 newval = md_chars_to_number (buf, THUMB_SIZE);
12669 switch (newval >> 11)
12670 {
12671 case 0x04: /* 8bit immediate MOV. */
12672 case 0x05: /* 8bit immediate CMP. */
12673 if (value < 0 || value > 255)
12674 as_bad_where (fixP->fx_file, fixP->fx_line,
12675 _("invalid immediate: %ld is too large"),
12676 (long) value);
12677 newval |= value;
12678 break;
12679
12680 default:
12681 abort ();
12682 }
12683 md_number_to_chars (buf, newval, THUMB_SIZE);
12684 break;
12685
12686 case BFD_RELOC_ARM_THUMB_SHIFT:
12687 /* 5bit shift value (0..31). */
12688 if (value < 0 || value > 31)
12689 as_bad_where (fixP->fx_file, fixP->fx_line,
12690 _("illegal Thumb shift value: %ld"), (long) value);
12691 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xf03f;
12692 newval |= value << 6;
12693 md_number_to_chars (buf, newval, THUMB_SIZE);
12694 break;
12695
12696 case BFD_RELOC_VTABLE_INHERIT:
12697 case BFD_RELOC_VTABLE_ENTRY:
12698 fixP->fx_done = 0;
12699 return;
12700
12701 case BFD_RELOC_NONE:
12702 default:
12703 as_bad_where (fixP->fx_file, fixP->fx_line,
12704 _("bad relocation fixup type (%d)"), fixP->fx_r_type);
12705 }
12706 }
12707
12708 /* Translate internal representation of relocation info to BFD target
12709 format. */
12710
12711 arelent *
12712 tc_gen_reloc (section, fixp)
12713 asection * section ATTRIBUTE_UNUSED;
12714 fixS * fixp;
12715 {
12716 arelent * reloc;
12717 bfd_reloc_code_real_type code;
12718
12719 reloc = (arelent *) xmalloc (sizeof (arelent));
12720
12721 reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
12722 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
12723 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
12724
12725 /* @@ Why fx_addnumber sometimes and fx_offset other times? */
12726 #ifndef OBJ_ELF
12727 if (fixp->fx_pcrel == 0)
12728 reloc->addend = fixp->fx_offset;
12729 else
12730 reloc->addend = fixp->fx_offset = reloc->address;
12731 #else /* OBJ_ELF */
12732 reloc->addend = fixp->fx_offset;
12733 #endif
12734
12735 switch (fixp->fx_r_type)
12736 {
12737 case BFD_RELOC_8:
12738 if (fixp->fx_pcrel)
12739 {
12740 code = BFD_RELOC_8_PCREL;
12741 break;
12742 }
12743
12744 case BFD_RELOC_16:
12745 if (fixp->fx_pcrel)
12746 {
12747 code = BFD_RELOC_16_PCREL;
12748 break;
12749 }
12750
12751 case BFD_RELOC_32:
12752 if (fixp->fx_pcrel)
12753 {
12754 code = BFD_RELOC_32_PCREL;
12755 break;
12756 }
12757
12758 case BFD_RELOC_ARM_PCREL_BRANCH:
12759 case BFD_RELOC_ARM_PCREL_BLX:
12760 case BFD_RELOC_RVA:
12761 case BFD_RELOC_THUMB_PCREL_BRANCH9:
12762 case BFD_RELOC_THUMB_PCREL_BRANCH12:
12763 case BFD_RELOC_THUMB_PCREL_BRANCH23:
12764 case BFD_RELOC_THUMB_PCREL_BLX:
12765 case BFD_RELOC_VTABLE_ENTRY:
12766 case BFD_RELOC_VTABLE_INHERIT:
12767 code = fixp->fx_r_type;
12768 break;
12769
12770 case BFD_RELOC_ARM_LITERAL:
12771 case BFD_RELOC_ARM_HWLITERAL:
12772 /* If this is called then the a literal has
12773 been referenced across a section boundary. */
12774 as_bad_where (fixp->fx_file, fixp->fx_line,
12775 _("literal referenced across section boundary"));
12776 return NULL;
12777
12778 #ifdef OBJ_ELF
12779 case BFD_RELOC_ARM_GOT32:
12780 case BFD_RELOC_ARM_GOTOFF:
12781 case BFD_RELOC_ARM_PLT32:
12782 code = fixp->fx_r_type;
12783 break;
12784 #endif
12785
12786 case BFD_RELOC_ARM_IMMEDIATE:
12787 as_bad_where (fixp->fx_file, fixp->fx_line,
12788 _("internal relocation (type: IMMEDIATE) not fixed up"));
12789 return NULL;
12790
12791 case BFD_RELOC_ARM_ADRL_IMMEDIATE:
12792 as_bad_where (fixp->fx_file, fixp->fx_line,
12793 _("ADRL used for a symbol not defined in the same file"));
12794 return NULL;
12795
12796 case BFD_RELOC_ARM_OFFSET_IMM:
12797 as_bad_where (fixp->fx_file, fixp->fx_line,
12798 _("internal_relocation (type: OFFSET_IMM) not fixed up"));
12799 return NULL;
12800
12801 default:
12802 {
12803 char * type;
12804
12805 switch (fixp->fx_r_type)
12806 {
12807 case BFD_RELOC_ARM_OFFSET_IMM8: type = "OFFSET_IMM8"; break;
12808 case BFD_RELOC_ARM_SHIFT_IMM: type = "SHIFT_IMM"; break;
12809 case BFD_RELOC_ARM_SWI: type = "SWI"; break;
12810 case BFD_RELOC_ARM_MULTI: type = "MULTI"; break;
12811 case BFD_RELOC_ARM_CP_OFF_IMM: type = "CP_OFF_IMM"; break;
12812 case BFD_RELOC_ARM_THUMB_ADD: type = "THUMB_ADD"; break;
12813 case BFD_RELOC_ARM_THUMB_SHIFT: type = "THUMB_SHIFT"; break;
12814 case BFD_RELOC_ARM_THUMB_IMM: type = "THUMB_IMM"; break;
12815 case BFD_RELOC_ARM_THUMB_OFFSET: type = "THUMB_OFFSET"; break;
12816 default: type = _("<unknown>"); break;
12817 }
12818 as_bad_where (fixp->fx_file, fixp->fx_line,
12819 _("cannot represent %s relocation in this object file format"),
12820 type);
12821 return NULL;
12822 }
12823 }
12824
12825 #ifdef OBJ_ELF
12826 if ((code == BFD_RELOC_32_PCREL || code == BFD_RELOC_32)
12827 && GOT_symbol
12828 && fixp->fx_addsy == GOT_symbol)
12829 {
12830 code = BFD_RELOC_ARM_GOTPC;
12831 reloc->addend = fixp->fx_offset = reloc->address;
12832 }
12833 #endif
12834
12835 reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
12836
12837 if (reloc->howto == NULL)
12838 {
12839 as_bad_where (fixp->fx_file, fixp->fx_line,
12840 _("cannot represent %s relocation in this object file format"),
12841 bfd_get_reloc_code_name (code));
12842 return NULL;
12843 }
12844
12845 /* HACK: Since arm ELF uses Rel instead of Rela, encode the
12846 vtable entry to be used in the relocation's section offset. */
12847 if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
12848 reloc->address = fixp->fx_offset;
12849
12850 return reloc;
12851 }
12852
12853 int
12854 md_estimate_size_before_relax (fragP, segtype)
12855 fragS * fragP ATTRIBUTE_UNUSED;
12856 segT segtype ATTRIBUTE_UNUSED;
12857 {
12858 as_fatal (_("md_estimate_size_before_relax\n"));
12859 return 1;
12860 }
12861
12862 static void
12863 output_inst (str)
12864 const char *str;
12865 {
12866 char * to = NULL;
12867
12868 if (inst.error)
12869 {
12870 as_bad ("%s -- `%s'", inst.error, str);
12871 return;
12872 }
12873
12874 to = frag_more (inst.size);
12875
12876 if (thumb_mode && (inst.size > THUMB_SIZE))
12877 {
12878 assert (inst.size == (2 * THUMB_SIZE));
12879 md_number_to_chars (to, inst.instruction >> 16, THUMB_SIZE);
12880 md_number_to_chars (to + THUMB_SIZE, inst.instruction, THUMB_SIZE);
12881 }
12882 else if (inst.size > INSN_SIZE)
12883 {
12884 assert (inst.size == (2 * INSN_SIZE));
12885 md_number_to_chars (to, inst.instruction, INSN_SIZE);
12886 md_number_to_chars (to + INSN_SIZE, inst.instruction, INSN_SIZE);
12887 }
12888 else
12889 md_number_to_chars (to, inst.instruction, inst.size);
12890
12891 if (inst.reloc.type != BFD_RELOC_NONE)
12892 fix_new_arm (frag_now, to - frag_now->fr_literal,
12893 inst.size, & inst.reloc.exp, inst.reloc.pc_rel,
12894 inst.reloc.type);
12895
12896 #ifdef OBJ_ELF
12897 dwarf2_emit_insn (inst.size);
12898 #endif
12899 }
12900
12901 void
12902 md_assemble (str)
12903 char * str;
12904 {
12905 char c;
12906 char *p;
12907 char *start;
12908
12909 /* Align the instruction.
12910 This may not be the right thing to do but ... */
12911 #if 0
12912 arm_align (2, 0);
12913 #endif
12914
12915 /* Align the previous label if needed. */
12916 if (last_label_seen != NULL)
12917 {
12918 symbol_set_frag (last_label_seen, frag_now);
12919 S_SET_VALUE (last_label_seen, (valueT) frag_now_fix ());
12920 S_SET_SEGMENT (last_label_seen, now_seg);
12921 }
12922
12923 memset (&inst, '\0', sizeof (inst));
12924 inst.reloc.type = BFD_RELOC_NONE;
12925
12926 skip_whitespace (str);
12927
12928 /* Scan up to the end of the op-code, which must end in white space or
12929 end of string. */
12930 for (start = p = str; *p != '\0'; p++)
12931 if (*p == ' ')
12932 break;
12933
12934 if (p == str)
12935 {
12936 as_bad (_("no operator -- statement `%s'\n"), str);
12937 return;
12938 }
12939
12940 if (thumb_mode)
12941 {
12942 const struct thumb_opcode * opcode;
12943
12944 c = *p;
12945 *p = '\0';
12946 opcode = (const struct thumb_opcode *) hash_find (arm_tops_hsh, str);
12947 *p = c;
12948
12949 if (opcode)
12950 {
12951 /* Check that this instruction is supported for this CPU. */
12952 if (thumb_mode == 1 && (opcode->variant & cpu_variant) == 0)
12953 {
12954 as_bad (_("selected processor does not support `%s'"), str);
12955 return;
12956 }
12957
12958 mapping_state (MAP_THUMB);
12959 inst.instruction = opcode->value;
12960 inst.size = opcode->size;
12961 (*opcode->parms) (p);
12962 output_inst (str);
12963 return;
12964 }
12965 }
12966 else
12967 {
12968 const struct asm_opcode * opcode;
12969
12970 c = *p;
12971 *p = '\0';
12972 opcode = (const struct asm_opcode *) hash_find (arm_ops_hsh, str);
12973 *p = c;
12974
12975 if (opcode)
12976 {
12977 /* Check that this instruction is supported for this CPU. */
12978 if ((opcode->variant & cpu_variant) == 0)
12979 {
12980 as_bad (_("selected processor does not support `%s'"), str);
12981 return;
12982 }
12983
12984 mapping_state (MAP_ARM);
12985 inst.instruction = opcode->value;
12986 inst.size = INSN_SIZE;
12987 (*opcode->parms) (p);
12988 output_inst (str);
12989 return;
12990 }
12991 }
12992
12993 /* It wasn't an instruction, but it might be a register alias of the form
12994 alias .req reg. */
12995 if (create_register_alias (str, p))
12996 return;
12997
12998 as_bad (_("bad instruction `%s'"), start);
12999 }
13000
13001 /* md_parse_option
13002 Invocation line includes a switch not recognized by the base assembler.
13003 See if it's a processor-specific option.
13004
13005 This routine is somewhat complicated by the need for backwards
13006 compatibility (since older releases of gcc can't be changed).
13007 The new options try to make the interface as compatible as
13008 possible with GCC.
13009
13010 New options (supported) are:
13011
13012 -mcpu=<cpu name> Assemble for selected processor
13013 -march=<architecture name> Assemble for selected architecture
13014 -mfpu=<fpu architecture> Assemble for selected FPU.
13015 -EB/-mbig-endian Big-endian
13016 -EL/-mlittle-endian Little-endian
13017 -k Generate PIC code
13018 -mthumb Start in Thumb mode
13019 -mthumb-interwork Code supports ARM/Thumb interworking
13020
13021 For now we will also provide support for:
13022
13023 -mapcs-32 32-bit Program counter
13024 -mapcs-26 26-bit Program counter
13025 -macps-float Floats passed in FP registers
13026 -mapcs-reentrant Reentrant code
13027 -matpcs
13028 (sometime these will probably be replaced with -mapcs=<list of options>
13029 and -matpcs=<list of options>)
13030
13031 The remaining options are only supported for back-wards compatibility.
13032 Cpu variants, the arm part is optional:
13033 -m[arm]1 Currently not supported.
13034 -m[arm]2, -m[arm]250 Arm 2 and Arm 250 processor
13035 -m[arm]3 Arm 3 processor
13036 -m[arm]6[xx], Arm 6 processors
13037 -m[arm]7[xx][t][[d]m] Arm 7 processors
13038 -m[arm]8[10] Arm 8 processors
13039 -m[arm]9[20][tdmi] Arm 9 processors
13040 -mstrongarm[110[0]] StrongARM processors
13041 -mxscale XScale processors
13042 -m[arm]v[2345[t[e]]] Arm architectures
13043 -mall All (except the ARM1)
13044 FP variants:
13045 -mfpa10, -mfpa11 FPA10 and 11 co-processor instructions
13046 -mfpe-old (No float load/store multiples)
13047 -mvfpxd VFP Single precision
13048 -mvfp All VFP
13049 -mno-fpu Disable all floating point instructions
13050
13051 The following CPU names are recognized:
13052 arm1, arm2, arm250, arm3, arm6, arm600, arm610, arm620,
13053 arm7, arm7m, arm7d, arm7dm, arm7di, arm7dmi, arm70, arm700,
13054 arm700i, arm710 arm710t, arm720, arm720t, arm740t, arm710c,
13055 arm7100, arm7500, arm7500fe, arm7tdmi, arm8, arm810, arm9,
13056 arm920, arm920t, arm940t, arm946, arm966, arm9tdmi, arm9e,
13057 arm10t arm10e, arm1020t, arm1020e, arm10200e,
13058 strongarm, strongarm110, strongarm1100, strongarm1110, xscale.
13059
13060 */
13061
13062 const char * md_shortopts = "m:k";
13063
13064 #ifdef ARM_BI_ENDIAN
13065 #define OPTION_EB (OPTION_MD_BASE + 0)
13066 #define OPTION_EL (OPTION_MD_BASE + 1)
13067 #else
13068 #if TARGET_BYTES_BIG_ENDIAN
13069 #define OPTION_EB (OPTION_MD_BASE + 0)
13070 #else
13071 #define OPTION_EL (OPTION_MD_BASE + 1)
13072 #endif
13073 #endif
13074
13075 struct option md_longopts[] =
13076 {
13077 #ifdef OPTION_EB
13078 {"EB", no_argument, NULL, OPTION_EB},
13079 #endif
13080 #ifdef OPTION_EL
13081 {"EL", no_argument, NULL, OPTION_EL},
13082 #endif
13083 {NULL, no_argument, NULL, 0}
13084 };
13085
13086 size_t md_longopts_size = sizeof (md_longopts);
13087
13088 struct arm_option_table
13089 {
13090 char *option; /* Option name to match. */
13091 char *help; /* Help information. */
13092 int *var; /* Variable to change. */
13093 int value; /* What to change it to. */
13094 char *deprecated; /* If non-null, print this message. */
13095 };
13096
13097 struct arm_option_table arm_opts[] =
13098 {
13099 {"k", N_("generate PIC code"), &pic_code, 1, NULL},
13100 {"mthumb", N_("assemble Thumb code"), &thumb_mode, 1, NULL},
13101 {"mthumb-interwork", N_("support ARM/Thumb interworking"),
13102 &support_interwork, 1, NULL},
13103 {"moabi", N_("use old ABI (ELF only)"), &target_oabi, 1, NULL},
13104 {"mapcs-32", N_("code uses 32-bit program counter"), &uses_apcs_26, 0, NULL},
13105 {"mapcs-26", N_("code uses 26-bit program counter"), &uses_apcs_26, 1, NULL},
13106 {"mapcs-float", N_("floating point args are in fp regs"), &uses_apcs_float,
13107 1, NULL},
13108 {"mapcs-reentrant", N_("re-entrant code"), &pic_code, 1, NULL},
13109 {"matpcs", N_("code is ATPCS conformant"), &atpcs, 1, NULL},
13110 {"mbig-endian", N_("assemble for big-endian"), &target_big_endian, 1, NULL},
13111 {"mlittle-endian", N_("assemble for little-endian"), &target_big_endian, 1,
13112 NULL},
13113
13114 /* These are recognized by the assembler, but have no affect on code. */
13115 {"mapcs-frame", N_("use frame pointer"), NULL, 0, NULL},
13116 {"mapcs-stack-check", N_("use stack size checking"), NULL, 0, NULL},
13117
13118 /* DON'T add any new processors to this list -- we want the whole list
13119 to go away... Add them to the processors table instead. */
13120 {"marm1", NULL, &legacy_cpu, ARM_ARCH_V1, N_("use -mcpu=arm1")},
13121 {"m1", NULL, &legacy_cpu, ARM_ARCH_V1, N_("use -mcpu=arm1")},
13122 {"marm2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -mcpu=arm2")},
13123 {"m2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -mcpu=arm2")},
13124 {"marm250", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm250")},
13125 {"m250", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm250")},
13126 {"marm3", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm3")},
13127 {"m3", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm3")},
13128 {"marm6", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm6")},
13129 {"m6", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm6")},
13130 {"marm600", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm600")},
13131 {"m600", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm600")},
13132 {"marm610", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm610")},
13133 {"m610", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm610")},
13134 {"marm620", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm620")},
13135 {"m620", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm620")},
13136 {"marm7", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7")},
13137 {"m7", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7")},
13138 {"marm70", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm70")},
13139 {"m70", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm70")},
13140 {"marm700", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700")},
13141 {"m700", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700")},
13142 {"marm700i", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700i")},
13143 {"m700i", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700i")},
13144 {"marm710", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710")},
13145 {"m710", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710")},
13146 {"marm710c", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710c")},
13147 {"m710c", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710c")},
13148 {"marm720", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm720")},
13149 {"m720", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm720")},
13150 {"marm7d", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7d")},
13151 {"m7d", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7d")},
13152 {"marm7di", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7di")},
13153 {"m7di", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7di")},
13154 {"marm7m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7m")},
13155 {"m7m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7m")},
13156 {"marm7dm", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dm")},
13157 {"m7dm", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dm")},
13158 {"marm7dmi", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dmi")},
13159 {"m7dmi", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dmi")},
13160 {"marm7100", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7100")},
13161 {"m7100", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7100")},
13162 {"marm7500", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500")},
13163 {"m7500", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500")},
13164 {"marm7500fe", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500fe")},
13165 {"m7500fe", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500fe")},
13166 {"marm7t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
13167 {"m7t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
13168 {"marm7tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
13169 {"m7tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
13170 {"marm710t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm710t")},
13171 {"m710t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm710t")},
13172 {"marm720t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm720t")},
13173 {"m720t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm720t")},
13174 {"marm740t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm740t")},
13175 {"m740t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm740t")},
13176 {"marm8", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm8")},
13177 {"m8", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm8")},
13178 {"marm810", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm810")},
13179 {"m810", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm810")},
13180 {"marm9", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9")},
13181 {"m9", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9")},
13182 {"marm9tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9tdmi")},
13183 {"m9tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9tdmi")},
13184 {"marm920", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm920")},
13185 {"m920", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm920")},
13186 {"marm940", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm940")},
13187 {"m940", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm940")},
13188 {"mstrongarm", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=strongarm")},
13189 {"mstrongarm110", NULL, &legacy_cpu, ARM_ARCH_V4,
13190 N_("use -mcpu=strongarm110")},
13191 {"mstrongarm1100", NULL, &legacy_cpu, ARM_ARCH_V4,
13192 N_("use -mcpu=strongarm1100")},
13193 {"mstrongarm1110", NULL, &legacy_cpu, ARM_ARCH_V4,
13194 N_("use -mcpu=strongarm1110")},
13195 {"mxscale", NULL, &legacy_cpu, ARM_ARCH_XSCALE, N_("use -mcpu=xscale")},
13196 {"miwmmxt", NULL, &legacy_cpu, ARM_ARCH_IWMMXT, N_("use -mcpu=iwmmxt")},
13197 {"mall", NULL, &legacy_cpu, ARM_ANY, N_("use -mcpu=all")},
13198
13199 /* Architecture variants -- don't add any more to this list either. */
13200 {"mv2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -march=armv2")},
13201 {"marmv2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -march=armv2")},
13202 {"mv2a", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -march=armv2a")},
13203 {"marmv2a", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -march=armv2a")},
13204 {"mv3", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -march=armv3")},
13205 {"marmv3", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -march=armv3")},
13206 {"mv3m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -march=armv3m")},
13207 {"marmv3m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -march=armv3m")},
13208 {"mv4", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -march=armv4")},
13209 {"marmv4", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -march=armv4")},
13210 {"mv4t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -march=armv4t")},
13211 {"marmv4t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -march=armv4t")},
13212 {"mv5", NULL, &legacy_cpu, ARM_ARCH_V5, N_("use -march=armv5")},
13213 {"marmv5", NULL, &legacy_cpu, ARM_ARCH_V5, N_("use -march=armv5")},
13214 {"mv5t", NULL, &legacy_cpu, ARM_ARCH_V5T, N_("use -march=armv5t")},
13215 {"marmv5t", NULL, &legacy_cpu, ARM_ARCH_V5T, N_("use -march=armv5t")},
13216 {"mv5e", NULL, &legacy_cpu, ARM_ARCH_V5TE, N_("use -march=armv5te")},
13217 {"marmv5e", NULL, &legacy_cpu, ARM_ARCH_V5TE, N_("use -march=armv5te")},
13218
13219 /* Floating point variants -- don't add any more to this list either. */
13220 {"mfpe-old", NULL, &legacy_fpu, FPU_ARCH_FPE, N_("use -mfpu=fpe")},
13221 {"mfpa10", NULL, &legacy_fpu, FPU_ARCH_FPA, N_("use -mfpu=fpa10")},
13222 {"mfpa11", NULL, &legacy_fpu, FPU_ARCH_FPA, N_("use -mfpu=fpa11")},
13223 {"mno-fpu", NULL, &legacy_fpu, 0,
13224 N_("use either -mfpu=softfpa or -mfpu=softvfp")},
13225
13226 {NULL, NULL, NULL, 0, NULL}
13227 };
13228
13229 struct arm_cpu_option_table
13230 {
13231 char *name;
13232 int value;
13233 /* For some CPUs we assume an FPU unless the user explicitly sets
13234 -mfpu=... */
13235 int default_fpu;
13236 };
13237
13238 /* This list should, at a minimum, contain all the cpu names
13239 recognized by GCC. */
13240 static struct arm_cpu_option_table arm_cpus[] =
13241 {
13242 {"all", ARM_ANY, FPU_ARCH_FPA},
13243 {"arm1", ARM_ARCH_V1, FPU_ARCH_FPA},
13244 {"arm2", ARM_ARCH_V2, FPU_ARCH_FPA},
13245 {"arm250", ARM_ARCH_V2S, FPU_ARCH_FPA},
13246 {"arm3", ARM_ARCH_V2S, FPU_ARCH_FPA},
13247 {"arm6", ARM_ARCH_V3, FPU_ARCH_FPA},
13248 {"arm60", ARM_ARCH_V3, FPU_ARCH_FPA},
13249 {"arm600", ARM_ARCH_V3, FPU_ARCH_FPA},
13250 {"arm610", ARM_ARCH_V3, FPU_ARCH_FPA},
13251 {"arm620", ARM_ARCH_V3, FPU_ARCH_FPA},
13252 {"arm7", ARM_ARCH_V3, FPU_ARCH_FPA},
13253 {"arm7m", ARM_ARCH_V3M, FPU_ARCH_FPA},
13254 {"arm7d", ARM_ARCH_V3, FPU_ARCH_FPA},
13255 {"arm7dm", ARM_ARCH_V3M, FPU_ARCH_FPA},
13256 {"arm7di", ARM_ARCH_V3, FPU_ARCH_FPA},
13257 {"arm7dmi", ARM_ARCH_V3M, FPU_ARCH_FPA},
13258 {"arm70", ARM_ARCH_V3, FPU_ARCH_FPA},
13259 {"arm700", ARM_ARCH_V3, FPU_ARCH_FPA},
13260 {"arm700i", ARM_ARCH_V3, FPU_ARCH_FPA},
13261 {"arm710", ARM_ARCH_V3, FPU_ARCH_FPA},
13262 {"arm710t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13263 {"arm720", ARM_ARCH_V3, FPU_ARCH_FPA},
13264 {"arm720t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13265 {"arm740t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13266 {"arm710c", ARM_ARCH_V3, FPU_ARCH_FPA},
13267 {"arm7100", ARM_ARCH_V3, FPU_ARCH_FPA},
13268 {"arm7500", ARM_ARCH_V3, FPU_ARCH_FPA},
13269 {"arm7500fe", ARM_ARCH_V3, FPU_ARCH_FPA},
13270 {"arm7t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13271 {"arm7tdmi", ARM_ARCH_V4T, FPU_ARCH_FPA},
13272 {"arm8", ARM_ARCH_V4, FPU_ARCH_FPA},
13273 {"arm810", ARM_ARCH_V4, FPU_ARCH_FPA},
13274 {"strongarm", ARM_ARCH_V4, FPU_ARCH_FPA},
13275 {"strongarm1", ARM_ARCH_V4, FPU_ARCH_FPA},
13276 {"strongarm110", ARM_ARCH_V4, FPU_ARCH_FPA},
13277 {"strongarm1100", ARM_ARCH_V4, FPU_ARCH_FPA},
13278 {"strongarm1110", ARM_ARCH_V4, FPU_ARCH_FPA},
13279 {"arm9", ARM_ARCH_V4T, FPU_ARCH_FPA},
13280 {"arm920", ARM_ARCH_V4T, FPU_ARCH_FPA},
13281 {"arm920t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13282 {"arm922t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13283 {"arm940t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13284 {"arm9tdmi", ARM_ARCH_V4T, FPU_ARCH_FPA},
13285 /* For V5 or later processors we default to using VFP; but the user
13286 should really set the FPU type explicitly. */
13287 {"arm9e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
13288 {"arm9e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13289 {"arm926ej", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
13290 {"arm946e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
13291 {"arm946e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13292 {"arm966e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
13293 {"arm966e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13294 {"arm10t", ARM_ARCH_V5T, FPU_ARCH_VFP_V1},
13295 {"arm10e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13296 {"arm1020", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13297 {"arm1020t", ARM_ARCH_V5T, FPU_ARCH_VFP_V1},
13298 {"arm1020e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13299 {"arm1136js", ARM_ARCH_V6, FPU_NONE},
13300 {"arm1136jfs", ARM_ARCH_V6, FPU_ARCH_VFP_V2},
13301 /* ??? XSCALE is really an architecture. */
13302 {"xscale", ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2},
13303 /* ??? iwmmxt is not a processor. */
13304 {"iwmmxt", ARM_ARCH_IWMMXT, FPU_ARCH_VFP_V2},
13305 {"i80200", ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2},
13306 /* Maverick */
13307 {"ep9312", ARM_ARCH_V4T | ARM_CEXT_MAVERICK, FPU_ARCH_MAVERICK},
13308 {NULL, 0, 0}
13309 };
13310
13311 struct arm_arch_option_table
13312 {
13313 char *name;
13314 int value;
13315 int default_fpu;
13316 };
13317
13318 /* This list should, at a minimum, contain all the architecture names
13319 recognized by GCC. */
13320 static struct arm_arch_option_table arm_archs[] =
13321 {
13322 {"all", ARM_ANY, FPU_ARCH_FPA},
13323 {"armv1", ARM_ARCH_V1, FPU_ARCH_FPA},
13324 {"armv2", ARM_ARCH_V2, FPU_ARCH_FPA},
13325 {"armv2a", ARM_ARCH_V2S, FPU_ARCH_FPA},
13326 {"armv2s", ARM_ARCH_V2S, FPU_ARCH_FPA},
13327 {"armv3", ARM_ARCH_V3, FPU_ARCH_FPA},
13328 {"armv3m", ARM_ARCH_V3M, FPU_ARCH_FPA},
13329 {"armv4", ARM_ARCH_V4, FPU_ARCH_FPA},
13330 {"armv4xm", ARM_ARCH_V4xM, FPU_ARCH_FPA},
13331 {"armv4t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13332 {"armv4txm", ARM_ARCH_V4TxM, FPU_ARCH_FPA},
13333 {"armv5", ARM_ARCH_V5, FPU_ARCH_VFP},
13334 {"armv5t", ARM_ARCH_V5T, FPU_ARCH_VFP},
13335 {"armv5txm", ARM_ARCH_V5TxM, FPU_ARCH_VFP},
13336 {"armv5te", ARM_ARCH_V5TE, FPU_ARCH_VFP},
13337 {"armv5texp", ARM_ARCH_V5TExP, FPU_ARCH_VFP},
13338 {"armv5tej", ARM_ARCH_V5TEJ, FPU_ARCH_VFP},
13339 {"armv6", ARM_ARCH_V6, FPU_ARCH_VFP},
13340 {"xscale", ARM_ARCH_XSCALE, FPU_ARCH_VFP},
13341 {"iwmmxt", ARM_ARCH_IWMMXT, FPU_ARCH_VFP},
13342 {NULL, 0, 0}
13343 };
13344
13345 /* ISA extensions in the co-processor space. */
13346 struct arm_arch_extension_table
13347 {
13348 char *name;
13349 int value;
13350 };
13351
13352 static struct arm_arch_extension_table arm_extensions[] =
13353 {
13354 {"maverick", ARM_CEXT_MAVERICK},
13355 {"xscale", ARM_CEXT_XSCALE},
13356 {"iwmmxt", ARM_CEXT_IWMMXT},
13357 {NULL, 0}
13358 };
13359
13360 struct arm_fpu_option_table
13361 {
13362 char *name;
13363 int value;
13364 };
13365
13366 /* This list should, at a minimum, contain all the fpu names
13367 recognized by GCC. */
13368 static struct arm_fpu_option_table arm_fpus[] =
13369 {
13370 {"softfpa", FPU_NONE},
13371 {"fpe", FPU_ARCH_FPE},
13372 {"fpe2", FPU_ARCH_FPE},
13373 {"fpe3", FPU_ARCH_FPA}, /* Third release supports LFM/SFM. */
13374 {"fpa", FPU_ARCH_FPA},
13375 {"fpa10", FPU_ARCH_FPA},
13376 {"fpa11", FPU_ARCH_FPA},
13377 {"arm7500fe", FPU_ARCH_FPA},
13378 {"softvfp", FPU_ARCH_VFP},
13379 {"softvfp+vfp", FPU_ARCH_VFP_V2},
13380 {"vfp", FPU_ARCH_VFP_V2},
13381 {"vfp9", FPU_ARCH_VFP_V2},
13382 {"vfp10", FPU_ARCH_VFP_V2},
13383 {"vfp10-r0", FPU_ARCH_VFP_V1},
13384 {"vfpxd", FPU_ARCH_VFP_V1xD},
13385 {"arm1020t", FPU_ARCH_VFP_V1},
13386 {"arm1020e", FPU_ARCH_VFP_V2},
13387 {"arm1136jfs", FPU_ARCH_VFP_V2},
13388 {"maverick", FPU_ARCH_MAVERICK},
13389 {NULL, 0}
13390 };
13391
13392 struct arm_float_abi_option_table
13393 {
13394 char *name;
13395 int value;
13396 };
13397
13398 static struct arm_float_abi_option_table arm_float_abis[] =
13399 {
13400 {"hard", ARM_FLOAT_ABI_HARD},
13401 {"softfp", ARM_FLOAT_ABI_SOFTFP},
13402 {"soft", ARM_FLOAT_ABI_SOFT},
13403 {NULL, 0}
13404 };
13405
13406 struct arm_long_option_table
13407 {
13408 char *option; /* Substring to match. */
13409 char *help; /* Help information. */
13410 int (*func) PARAMS ((char *subopt)); /* Function to decode sub-option. */
13411 char *deprecated; /* If non-null, print this message. */
13412 };
13413
13414 static int
13415 arm_parse_extension (str, opt_p)
13416 char *str;
13417 int *opt_p;
13418 {
13419 while (str != NULL && *str != 0)
13420 {
13421 struct arm_arch_extension_table *opt;
13422 char *ext;
13423 int optlen;
13424
13425 if (*str != '+')
13426 {
13427 as_bad (_("invalid architectural extension"));
13428 return 0;
13429 }
13430
13431 str++;
13432 ext = strchr (str, '+');
13433
13434 if (ext != NULL)
13435 optlen = ext - str;
13436 else
13437 optlen = strlen (str);
13438
13439 if (optlen == 0)
13440 {
13441 as_bad (_("missing architectural extension"));
13442 return 0;
13443 }
13444
13445 for (opt = arm_extensions; opt->name != NULL; opt++)
13446 if (strncmp (opt->name, str, optlen) == 0)
13447 {
13448 *opt_p |= opt->value;
13449 break;
13450 }
13451
13452 if (opt->name == NULL)
13453 {
13454 as_bad (_("unknown architectural extnsion `%s'"), str);
13455 return 0;
13456 }
13457
13458 str = ext;
13459 };
13460
13461 return 1;
13462 }
13463
13464 static int
13465 arm_parse_cpu (str)
13466 char *str;
13467 {
13468 struct arm_cpu_option_table *opt;
13469 char *ext = strchr (str, '+');
13470 int optlen;
13471
13472 if (ext != NULL)
13473 optlen = ext - str;
13474 else
13475 optlen = strlen (str);
13476
13477 if (optlen == 0)
13478 {
13479 as_bad (_("missing cpu name `%s'"), str);
13480 return 0;
13481 }
13482
13483 for (opt = arm_cpus; opt->name != NULL; opt++)
13484 if (strncmp (opt->name, str, optlen) == 0)
13485 {
13486 mcpu_cpu_opt = opt->value;
13487 mcpu_fpu_opt = opt->default_fpu;
13488
13489 if (ext != NULL)
13490 return arm_parse_extension (ext, &mcpu_cpu_opt);
13491
13492 return 1;
13493 }
13494
13495 as_bad (_("unknown cpu `%s'"), str);
13496 return 0;
13497 }
13498
13499 static int
13500 arm_parse_arch (str)
13501 char *str;
13502 {
13503 struct arm_arch_option_table *opt;
13504 char *ext = strchr (str, '+');
13505 int optlen;
13506
13507 if (ext != NULL)
13508 optlen = ext - str;
13509 else
13510 optlen = strlen (str);
13511
13512 if (optlen == 0)
13513 {
13514 as_bad (_("missing architecture name `%s'"), str);
13515 return 0;
13516 }
13517
13518
13519 for (opt = arm_archs; opt->name != NULL; opt++)
13520 if (strcmp (opt->name, str) == 0)
13521 {
13522 march_cpu_opt = opt->value;
13523 march_fpu_opt = opt->default_fpu;
13524
13525 if (ext != NULL)
13526 return arm_parse_extension (ext, &march_cpu_opt);
13527
13528 return 1;
13529 }
13530
13531 as_bad (_("unknown architecture `%s'\n"), str);
13532 return 0;
13533 }
13534
13535 static int
13536 arm_parse_fpu (str)
13537 char *str;
13538 {
13539 struct arm_fpu_option_table *opt;
13540
13541 for (opt = arm_fpus; opt->name != NULL; opt++)
13542 if (strcmp (opt->name, str) == 0)
13543 {
13544 mfpu_opt = opt->value;
13545 return 1;
13546 }
13547
13548 as_bad (_("unknown floating point format `%s'\n"), str);
13549 return 0;
13550 }
13551
13552 static int
13553 arm_parse_float_abi (str)
13554 char * str;
13555 {
13556 struct arm_float_abi_option_table *opt;
13557
13558 for (opt = arm_float_abis; opt->name != NULL; opt++)
13559 if (strcmp (opt->name, str) == 0)
13560 {
13561 mfloat_abi_opt = opt->value;
13562 return 1;
13563 }
13564
13565 as_bad (_("unknown floating point abi `%s'\n"), str);
13566 return 0;
13567 }
13568
13569 struct arm_long_option_table arm_long_opts[] =
13570 {
13571 {"mcpu=", N_("<cpu name>\t assemble for CPU <cpu name>"),
13572 arm_parse_cpu, NULL},
13573 {"march=", N_("<arch name>\t assemble for architecture <arch name>"),
13574 arm_parse_arch, NULL},
13575 {"mfpu=", N_("<fpu name>\t assemble for FPU architecture <fpu name>"),
13576 arm_parse_fpu, NULL},
13577 {"mfloat-abi=", N_("<abi>\t assemble for floating point ABI <abi>"),
13578 arm_parse_float_abi, NULL},
13579 {NULL, NULL, 0, NULL}
13580 };
13581
13582 int
13583 md_parse_option (c, arg)
13584 int c;
13585 char * arg;
13586 {
13587 struct arm_option_table *opt;
13588 struct arm_long_option_table *lopt;
13589
13590 switch (c)
13591 {
13592 #ifdef OPTION_EB
13593 case OPTION_EB:
13594 target_big_endian = 1;
13595 break;
13596 #endif
13597
13598 #ifdef OPTION_EL
13599 case OPTION_EL:
13600 target_big_endian = 0;
13601 break;
13602 #endif
13603
13604 case 'a':
13605 /* Listing option. Just ignore these, we don't support additional
13606 ones. */
13607 return 0;
13608
13609 default:
13610 for (opt = arm_opts; opt->option != NULL; opt++)
13611 {
13612 if (c == opt->option[0]
13613 && ((arg == NULL && opt->option[1] == 0)
13614 || strcmp (arg, opt->option + 1) == 0))
13615 {
13616 #if WARN_DEPRECATED
13617 /* If the option is deprecated, tell the user. */
13618 if (opt->deprecated != NULL)
13619 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c,
13620 arg ? arg : "", _(opt->deprecated));
13621 #endif
13622
13623 if (opt->var != NULL)
13624 *opt->var = opt->value;
13625
13626 return 1;
13627 }
13628 }
13629
13630 for (lopt = arm_long_opts; lopt->option != NULL; lopt++)
13631 {
13632 /* These options are expected to have an argument. */
13633 if (c == lopt->option[0]
13634 && arg != NULL
13635 && strncmp (arg, lopt->option + 1,
13636 strlen (lopt->option + 1)) == 0)
13637 {
13638 #if WARN_DEPRECATED
13639 /* If the option is deprecated, tell the user. */
13640 if (lopt->deprecated != NULL)
13641 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c, arg,
13642 _(lopt->deprecated));
13643 #endif
13644
13645 /* Call the sup-option parser. */
13646 return (*lopt->func)(arg + strlen (lopt->option) - 1);
13647 }
13648 }
13649
13650 as_bad (_("unrecognized option `-%c%s'"), c, arg ? arg : "");
13651 return 0;
13652 }
13653
13654 return 1;
13655 }
13656
13657 void
13658 md_show_usage (fp)
13659 FILE * fp;
13660 {
13661 struct arm_option_table *opt;
13662 struct arm_long_option_table *lopt;
13663
13664 fprintf (fp, _(" ARM-specific assembler options:\n"));
13665
13666 for (opt = arm_opts; opt->option != NULL; opt++)
13667 if (opt->help != NULL)
13668 fprintf (fp, " -%-23s%s\n", opt->option, _(opt->help));
13669
13670 for (lopt = arm_long_opts; lopt->option != NULL; lopt++)
13671 if (lopt->help != NULL)
13672 fprintf (fp, " -%s%s\n", lopt->option, _(lopt->help));
13673
13674 #ifdef OPTION_EB
13675 fprintf (fp, _("\
13676 -EB assemble code for a big-endian cpu\n"));
13677 #endif
13678
13679 #ifdef OPTION_EL
13680 fprintf (fp, _("\
13681 -EL assemble code for a little-endian cpu\n"));
13682 #endif
13683 }
13684
13685 /* We need to be able to fix up arbitrary expressions in some statements.
13686 This is so that we can handle symbols that are an arbitrary distance from
13687 the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
13688 which returns part of an address in a form which will be valid for
13689 a data instruction. We do this by pushing the expression into a symbol
13690 in the expr_section, and creating a fix for that. */
13691
13692 static void
13693 fix_new_arm (frag, where, size, exp, pc_rel, reloc)
13694 fragS * frag;
13695 int where;
13696 short int size;
13697 expressionS * exp;
13698 int pc_rel;
13699 int reloc;
13700 {
13701 fixS * new_fix;
13702 arm_fix_data * arm_data;
13703
13704 switch (exp->X_op)
13705 {
13706 case O_constant:
13707 case O_symbol:
13708 case O_add:
13709 case O_subtract:
13710 new_fix = fix_new_exp (frag, where, size, exp, pc_rel, reloc);
13711 break;
13712
13713 default:
13714 new_fix = fix_new (frag, where, size, make_expr_symbol (exp), 0,
13715 pc_rel, reloc);
13716 break;
13717 }
13718
13719 /* Mark whether the fix is to a THUMB instruction, or an ARM
13720 instruction. */
13721 arm_data = (arm_fix_data *) obstack_alloc (& notes, sizeof (arm_fix_data));
13722 new_fix->tc_fix_data = (PTR) arm_data;
13723 arm_data->thumb_mode = thumb_mode;
13724 }
13725
13726 /* This fix_new is called by cons via TC_CONS_FIX_NEW. */
13727
13728 void
13729 cons_fix_new_arm (frag, where, size, exp)
13730 fragS * frag;
13731 int where;
13732 int size;
13733 expressionS * exp;
13734 {
13735 bfd_reloc_code_real_type type;
13736 int pcrel = 0;
13737
13738 /* Pick a reloc.
13739 FIXME: @@ Should look at CPU word size. */
13740 switch (size)
13741 {
13742 case 1:
13743 type = BFD_RELOC_8;
13744 break;
13745 case 2:
13746 type = BFD_RELOC_16;
13747 break;
13748 case 4:
13749 default:
13750 type = BFD_RELOC_32;
13751 break;
13752 case 8:
13753 type = BFD_RELOC_64;
13754 break;
13755 }
13756
13757 fix_new_exp (frag, where, (int) size, exp, pcrel, type);
13758 }
13759
13760 /* A good place to do this, although this was probably not intended
13761 for this kind of use. We need to dump the literal pool before
13762 references are made to a null symbol pointer. */
13763
13764 void
13765 arm_cleanup ()
13766 {
13767 literal_pool * pool;
13768
13769 for (pool = list_of_pools; pool; pool = pool->next)
13770 {
13771 /* Put it at the end of the relevent section. */
13772 subseg_set (pool->section, pool->sub_section);
13773 s_ltorg (0);
13774 }
13775 }
13776
13777 void
13778 arm_start_line_hook ()
13779 {
13780 last_label_seen = NULL;
13781 }
13782
13783 void
13784 arm_frob_label (sym)
13785 symbolS * sym;
13786 {
13787 last_label_seen = sym;
13788
13789 ARM_SET_THUMB (sym, thumb_mode);
13790
13791 #if defined OBJ_COFF || defined OBJ_ELF
13792 ARM_SET_INTERWORK (sym, support_interwork);
13793 #endif
13794
13795 /* Note - do not allow local symbols (.Lxxx) to be labeled
13796 as Thumb functions. This is because these labels, whilst
13797 they exist inside Thumb code, are not the entry points for
13798 possible ARM->Thumb calls. Also, these labels can be used
13799 as part of a computed goto or switch statement. eg gcc
13800 can generate code that looks like this:
13801
13802 ldr r2, [pc, .Laaa]
13803 lsl r3, r3, #2
13804 ldr r2, [r3, r2]
13805 mov pc, r2
13806
13807 .Lbbb: .word .Lxxx
13808 .Lccc: .word .Lyyy
13809 ..etc...
13810 .Laaa: .word Lbbb
13811
13812 The first instruction loads the address of the jump table.
13813 The second instruction converts a table index into a byte offset.
13814 The third instruction gets the jump address out of the table.
13815 The fourth instruction performs the jump.
13816
13817 If the address stored at .Laaa is that of a symbol which has the
13818 Thumb_Func bit set, then the linker will arrange for this address
13819 to have the bottom bit set, which in turn would mean that the
13820 address computation performed by the third instruction would end
13821 up with the bottom bit set. Since the ARM is capable of unaligned
13822 word loads, the instruction would then load the incorrect address
13823 out of the jump table, and chaos would ensue. */
13824 if (label_is_thumb_function_name
13825 && (S_GET_NAME (sym)[0] != '.' || S_GET_NAME (sym)[1] != 'L')
13826 && (bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
13827 {
13828 /* When the address of a Thumb function is taken the bottom
13829 bit of that address should be set. This will allow
13830 interworking between Arm and Thumb functions to work
13831 correctly. */
13832
13833 THUMB_SET_FUNC (sym, 1);
13834
13835 label_is_thumb_function_name = FALSE;
13836 }
13837 }
13838
13839 /* Adjust the symbol table. This marks Thumb symbols as distinct from
13840 ARM ones. */
13841
13842 void
13843 arm_adjust_symtab ()
13844 {
13845 #ifdef OBJ_COFF
13846 symbolS * sym;
13847
13848 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
13849 {
13850 if (ARM_IS_THUMB (sym))
13851 {
13852 if (THUMB_IS_FUNC (sym))
13853 {
13854 /* Mark the symbol as a Thumb function. */
13855 if ( S_GET_STORAGE_CLASS (sym) == C_STAT
13856 || S_GET_STORAGE_CLASS (sym) == C_LABEL) /* This can happen! */
13857 S_SET_STORAGE_CLASS (sym, C_THUMBSTATFUNC);
13858
13859 else if (S_GET_STORAGE_CLASS (sym) == C_EXT)
13860 S_SET_STORAGE_CLASS (sym, C_THUMBEXTFUNC);
13861 else
13862 as_bad (_("%s: unexpected function type: %d"),
13863 S_GET_NAME (sym), S_GET_STORAGE_CLASS (sym));
13864 }
13865 else switch (S_GET_STORAGE_CLASS (sym))
13866 {
13867 case C_EXT:
13868 S_SET_STORAGE_CLASS (sym, C_THUMBEXT);
13869 break;
13870 case C_STAT:
13871 S_SET_STORAGE_CLASS (sym, C_THUMBSTAT);
13872 break;
13873 case C_LABEL:
13874 S_SET_STORAGE_CLASS (sym, C_THUMBLABEL);
13875 break;
13876 default:
13877 /* Do nothing. */
13878 break;
13879 }
13880 }
13881
13882 if (ARM_IS_INTERWORK (sym))
13883 coffsymbol (symbol_get_bfdsym (sym))->native->u.syment.n_flags = 0xFF;
13884 }
13885 #endif
13886 #ifdef OBJ_ELF
13887 symbolS * sym;
13888 char bind;
13889
13890 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
13891 {
13892 if (ARM_IS_THUMB (sym))
13893 {
13894 elf_symbol_type * elf_sym;
13895
13896 elf_sym = elf_symbol (symbol_get_bfdsym (sym));
13897 bind = ELF_ST_BIND (elf_sym);
13898
13899 /* If it's a .thumb_func, declare it as so,
13900 otherwise tag label as .code 16. */
13901 if (THUMB_IS_FUNC (sym))
13902 elf_sym->internal_elf_sym.st_info =
13903 ELF_ST_INFO (bind, STT_ARM_TFUNC);
13904 else
13905 elf_sym->internal_elf_sym.st_info =
13906 ELF_ST_INFO (bind, STT_ARM_16BIT);
13907 }
13908 }
13909 #endif
13910 }
13911
13912 int
13913 arm_data_in_code ()
13914 {
13915 if (thumb_mode && ! strncmp (input_line_pointer + 1, "data:", 5))
13916 {
13917 *input_line_pointer = '/';
13918 input_line_pointer += 5;
13919 *input_line_pointer = 0;
13920 return 1;
13921 }
13922
13923 return 0;
13924 }
13925
13926 char *
13927 arm_canonicalize_symbol_name (name)
13928 char * name;
13929 {
13930 int len;
13931
13932 if (thumb_mode && (len = strlen (name)) > 5
13933 && streq (name + len - 5, "/data"))
13934 *(name + len - 5) = 0;
13935
13936 return name;
13937 }
13938
13939 #if defined OBJ_COFF || defined OBJ_ELF
13940 void
13941 arm_validate_fix (fixP)
13942 fixS * fixP;
13943 {
13944 /* If the destination of the branch is a defined symbol which does not have
13945 the THUMB_FUNC attribute, then we must be calling a function which has
13946 the (interfacearm) attribute. We look for the Thumb entry point to that
13947 function and change the branch to refer to that function instead. */
13948 if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23
13949 && fixP->fx_addsy != NULL
13950 && S_IS_DEFINED (fixP->fx_addsy)
13951 && ! THUMB_IS_FUNC (fixP->fx_addsy))
13952 {
13953 fixP->fx_addsy = find_real_start (fixP->fx_addsy);
13954 }
13955 }
13956 #endif
13957
13958 int
13959 arm_force_relocation (fixp)
13960 struct fix * fixp;
13961 {
13962 #if defined (OBJ_COFF) && defined (TE_PE)
13963 if (fixp->fx_r_type == BFD_RELOC_RVA)
13964 return 1;
13965 #endif
13966 #ifdef OBJ_ELF
13967 if (fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH
13968 || fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BLX
13969 || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX
13970 || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23)
13971 return 1;
13972 #endif
13973
13974 /* Resolve these relocations even if the symbol is extern or weak. */
13975 if (fixp->fx_r_type == BFD_RELOC_ARM_IMMEDIATE
13976 || fixp->fx_r_type == BFD_RELOC_ARM_OFFSET_IMM
13977 || fixp->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE)
13978 return 0;
13979
13980 return generic_force_reloc (fixp);
13981 }
13982
13983 #ifdef OBJ_COFF
13984 /* This is a little hack to help the gas/arm/adrl.s test. It prevents
13985 local labels from being added to the output symbol table when they
13986 are used with the ADRL pseudo op. The ADRL relocation should always
13987 be resolved before the binbary is emitted, so it is safe to say that
13988 it is adjustable. */
13989
13990 bfd_boolean
13991 arm_fix_adjustable (fixP)
13992 fixS * fixP;
13993 {
13994 if (fixP->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE)
13995 return 1;
13996 return 0;
13997 }
13998 #endif
13999
14000 #ifdef OBJ_ELF
14001 /* Relocations against Thumb function names must be left unadjusted,
14002 so that the linker can use this information to correctly set the
14003 bottom bit of their addresses. The MIPS version of this function
14004 also prevents relocations that are mips-16 specific, but I do not
14005 know why it does this.
14006
14007 FIXME:
14008 There is one other problem that ought to be addressed here, but
14009 which currently is not: Taking the address of a label (rather
14010 than a function) and then later jumping to that address. Such
14011 addresses also ought to have their bottom bit set (assuming that
14012 they reside in Thumb code), but at the moment they will not. */
14013
14014 bfd_boolean
14015 arm_fix_adjustable (fixP)
14016 fixS * fixP;
14017 {
14018 if (fixP->fx_addsy == NULL)
14019 return 1;
14020
14021 if (THUMB_IS_FUNC (fixP->fx_addsy)
14022 && fixP->fx_subsy == NULL)
14023 return 0;
14024
14025 /* We need the symbol name for the VTABLE entries. */
14026 if ( fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
14027 || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
14028 return 0;
14029
14030 /* Don't allow symbols to be discarded on GOT related relocs. */
14031 if (fixP->fx_r_type == BFD_RELOC_ARM_PLT32
14032 || fixP->fx_r_type == BFD_RELOC_ARM_GOT32
14033 || fixP->fx_r_type == BFD_RELOC_ARM_GOTOFF)
14034 return 0;
14035
14036 return 1;
14037 }
14038
14039 const char *
14040 elf32_arm_target_format ()
14041 {
14042 if (target_big_endian)
14043 {
14044 if (target_oabi)
14045 return "elf32-bigarm-oabi";
14046 else
14047 return "elf32-bigarm";
14048 }
14049 else
14050 {
14051 if (target_oabi)
14052 return "elf32-littlearm-oabi";
14053 else
14054 return "elf32-littlearm";
14055 }
14056 }
14057
14058 void
14059 armelf_frob_symbol (symp, puntp)
14060 symbolS * symp;
14061 int * puntp;
14062 {
14063 elf_frob_symbol (symp, puntp);
14064 }
14065
14066 static bfd_reloc_code_real_type
14067 arm_parse_reloc ()
14068 {
14069 char id [16];
14070 char * ip;
14071 unsigned int i;
14072 static struct
14073 {
14074 char * str;
14075 int len;
14076 bfd_reloc_code_real_type reloc;
14077 }
14078 reloc_map[] =
14079 {
14080 #define MAP(str,reloc) { str, sizeof (str) - 1, reloc }
14081 MAP ("(got)", BFD_RELOC_ARM_GOT32),
14082 MAP ("(gotoff)", BFD_RELOC_ARM_GOTOFF),
14083 /* ScottB: Jan 30, 1998 - Added support for parsing "var(PLT)"
14084 branch instructions generated by GCC for PLT relocs. */
14085 MAP ("(plt)", BFD_RELOC_ARM_PLT32),
14086 { NULL, 0, BFD_RELOC_UNUSED }
14087 #undef MAP
14088 };
14089
14090 for (i = 0, ip = input_line_pointer;
14091 i < sizeof (id) && (ISALNUM (*ip) || ISPUNCT (*ip));
14092 i++, ip++)
14093 id[i] = TOLOWER (*ip);
14094
14095 for (i = 0; reloc_map[i].str; i++)
14096 if (strncmp (id, reloc_map[i].str, reloc_map[i].len) == 0)
14097 break;
14098
14099 input_line_pointer += reloc_map[i].len;
14100
14101 return reloc_map[i].reloc;
14102 }
14103
14104 static void
14105 s_arm_elf_cons (nbytes)
14106 int nbytes;
14107 {
14108 expressionS exp;
14109
14110 #ifdef md_flush_pending_output
14111 md_flush_pending_output ();
14112 #endif
14113
14114 if (is_it_end_of_statement ())
14115 {
14116 demand_empty_rest_of_line ();
14117 return;
14118 }
14119
14120 #ifdef md_cons_align
14121 md_cons_align (nbytes);
14122 #endif
14123
14124 mapping_state (MAP_DATA);
14125 do
14126 {
14127 bfd_reloc_code_real_type reloc;
14128
14129 expression (& exp);
14130
14131 if (exp.X_op == O_symbol
14132 && * input_line_pointer == '('
14133 && (reloc = arm_parse_reloc ()) != BFD_RELOC_UNUSED)
14134 {
14135 reloc_howto_type *howto = bfd_reloc_type_lookup (stdoutput, reloc);
14136 int size = bfd_get_reloc_size (howto);
14137
14138 if (size > nbytes)
14139 as_bad ("%s relocations do not fit in %d bytes",
14140 howto->name, nbytes);
14141 else
14142 {
14143 register char *p = frag_more ((int) nbytes);
14144 int offset = nbytes - size;
14145
14146 fix_new_exp (frag_now, p - frag_now->fr_literal + offset, size,
14147 &exp, 0, reloc);
14148 }
14149 }
14150 else
14151 emit_expr (&exp, (unsigned int) nbytes);
14152 }
14153 while (*input_line_pointer++ == ',');
14154
14155 /* Put terminator back into stream. */
14156 input_line_pointer --;
14157 demand_empty_rest_of_line ();
14158 }
14159
14160 #endif /* OBJ_ELF */
14161
14162 /* This is called from HANDLE_ALIGN in write.c. Fill in the contents
14163 of an rs_align_code fragment. */
14164
14165 void
14166 arm_handle_align (fragP)
14167 fragS *fragP;
14168 {
14169 static char const arm_noop[4] = { 0x00, 0x00, 0xa0, 0xe1 };
14170 static char const thumb_noop[2] = { 0xc0, 0x46 };
14171 static char const arm_bigend_noop[4] = { 0xe1, 0xa0, 0x00, 0x00 };
14172 static char const thumb_bigend_noop[2] = { 0x46, 0xc0 };
14173
14174 int bytes, fix, noop_size;
14175 char * p;
14176 const char * noop;
14177
14178 if (fragP->fr_type != rs_align_code)
14179 return;
14180
14181 bytes = fragP->fr_next->fr_address - fragP->fr_address - fragP->fr_fix;
14182 p = fragP->fr_literal + fragP->fr_fix;
14183 fix = 0;
14184
14185 if (bytes > MAX_MEM_FOR_RS_ALIGN_CODE)
14186 bytes &= MAX_MEM_FOR_RS_ALIGN_CODE;
14187
14188 if (fragP->tc_frag_data)
14189 {
14190 if (target_big_endian)
14191 noop = thumb_bigend_noop;
14192 else
14193 noop = thumb_noop;
14194 noop_size = sizeof (thumb_noop);
14195 }
14196 else
14197 {
14198 if (target_big_endian)
14199 noop = arm_bigend_noop;
14200 else
14201 noop = arm_noop;
14202 noop_size = sizeof (arm_noop);
14203 }
14204
14205 if (bytes & (noop_size - 1))
14206 {
14207 fix = bytes & (noop_size - 1);
14208 memset (p, 0, fix);
14209 p += fix;
14210 bytes -= fix;
14211 }
14212
14213 while (bytes >= noop_size)
14214 {
14215 memcpy (p, noop, noop_size);
14216 p += noop_size;
14217 bytes -= noop_size;
14218 fix += noop_size;
14219 }
14220
14221 fragP->fr_fix += fix;
14222 fragP->fr_var = noop_size;
14223 }
14224
14225 /* Called from md_do_align. Used to create an alignment
14226 frag in a code section. */
14227
14228 void
14229 arm_frag_align_code (n, max)
14230 int n;
14231 int max;
14232 {
14233 char * p;
14234
14235 /* We assume that there will never be a requirement
14236 to support alignments greater than 32 bytes. */
14237 if (max > MAX_MEM_FOR_RS_ALIGN_CODE)
14238 as_fatal (_("alignments greater than 32 bytes not supported in .text sections."));
14239
14240 p = frag_var (rs_align_code,
14241 MAX_MEM_FOR_RS_ALIGN_CODE,
14242 1,
14243 (relax_substateT) max,
14244 (symbolS *) NULL,
14245 (offsetT) n,
14246 (char *) NULL);
14247 *p = 0;
14248
14249 }
14250
14251 /* Perform target specific initialisation of a frag. */
14252
14253 void
14254 arm_init_frag (fragP)
14255 fragS *fragP;
14256 {
14257 /* Record whether this frag is in an ARM or a THUMB area. */
14258 fragP->tc_frag_data = thumb_mode;
14259 }
This page took 0.45928 seconds and 4 git commands to generate.