1 /* tc-arm.c -- Assemble for the ARM
2 Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
3 Free Software Foundation, Inc.
4 Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org)
5 Modified by David Taylor (dtaylor@armltd.co.uk)
6 Cirrus coprocessor mods by Aldy Hernandez (aldyh@redhat.com)
7 Cirrus coprocessor fixes by Petko Manolov (petkan@nucleusys.com)
8 Cirrus coprocessor fixes by Vladimir Ivanov (vladitx@nucleusys.com)
9
10 This file is part of GAS, the GNU Assembler.
11
12 GAS is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2, or (at your option)
15 any later version.
16
17 GAS is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
21
22 You should have received a copy of the GNU General Public License
23 along with GAS; see the file COPYING. If not, write to the Free
24 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
25 02111-1307, USA. */
26
27 #include <string.h>
28 #define NO_RELOC 0
29 #include "as.h"
30 #include "safe-ctype.h"
31
32 /* Need TARGET_CPU. */
33 #include "config.h"
34 #include "subsegs.h"
35 #include "obstack.h"
36 #include "symbols.h"
37 #include "listing.h"
38
39 #ifdef OBJ_ELF
40 #include "elf/arm.h"
41 #include "dwarf2dbg.h"
42 #endif
43
44 /* XXX Set this to 1 after the next binutils release */
45 #define WARN_DEPRECATED 0
46
47 /* The following bitmasks control CPU extensions: */
48 #define ARM_EXT_V1 0x00000001 /* All processors (core set). */
49 #define ARM_EXT_V2 0x00000002 /* Multiply instructions. */
50 #define ARM_EXT_V2S 0x00000004 /* SWP instructions. */
51 #define ARM_EXT_V3 0x00000008 /* MSR MRS. */
52 #define ARM_EXT_V3M 0x00000010 /* Allow long multiplies. */
53 #define ARM_EXT_V4 0x00000020 /* Allow half word loads. */
54 #define ARM_EXT_V4T 0x00000040 /* Thumb v1. */
55 #define ARM_EXT_V5 0x00000080 /* Allow CLZ, etc. */
56 #define ARM_EXT_V5T 0x00000100 /* Thumb v2. */
57 #define ARM_EXT_V5ExP 0x00000200 /* DSP core set. */
58 #define ARM_EXT_V5E 0x00000400 /* DSP Double transfers. */
59 #define ARM_EXT_V5J 0x00000800 /* Jazelle extension. */
60 #define ARM_EXT_V6 0x00001000 /* ARM V6. */
61
62 /* Co-processor space extensions. */
63 #define ARM_CEXT_XSCALE 0x00800000 /* Allow MIA etc. */
64 #define ARM_CEXT_MAVERICK 0x00400000 /* Use Cirrus/DSP coprocessor. */
65 #define ARM_CEXT_IWMMXT 0x00200000 /* Intel Wireless MMX technology coprocessor. */
66
67 /* Architectures are the sum of the base and extensions. The ARM ARM (rev E)
68 defines the following: ARMv3, ARMv3M, ARMv4xM, ARMv4, ARMv4TxM, ARMv4T,
69 ARMv5xM, ARMv5, ARMv5TxM, ARMv5T, ARMv5TExP, ARMv5TE. To these we add
70 three more to cover cores prior to ARM6. Finally, there are cores which
71 implement further extensions in the co-processor space. */
72 #define ARM_ARCH_V1 ARM_EXT_V1
73 #define ARM_ARCH_V2 (ARM_ARCH_V1 | ARM_EXT_V2)
74 #define ARM_ARCH_V2S (ARM_ARCH_V2 | ARM_EXT_V2S)
75 #define ARM_ARCH_V3 (ARM_ARCH_V2S | ARM_EXT_V3)
76 #define ARM_ARCH_V3M (ARM_ARCH_V3 | ARM_EXT_V3M)
77 #define ARM_ARCH_V4xM (ARM_ARCH_V3 | ARM_EXT_V4)
78 #define ARM_ARCH_V4 (ARM_ARCH_V3M | ARM_EXT_V4)
79 #define ARM_ARCH_V4TxM (ARM_ARCH_V4xM | ARM_EXT_V4T)
80 #define ARM_ARCH_V4T (ARM_ARCH_V4 | ARM_EXT_V4T)
81 #define ARM_ARCH_V5xM (ARM_ARCH_V4xM | ARM_EXT_V5)
82 #define ARM_ARCH_V5 (ARM_ARCH_V4 | ARM_EXT_V5)
83 #define ARM_ARCH_V5TxM (ARM_ARCH_V5xM | ARM_EXT_V4T | ARM_EXT_V5T)
84 #define ARM_ARCH_V5T (ARM_ARCH_V5 | ARM_EXT_V4T | ARM_EXT_V5T)
85 #define ARM_ARCH_V5TExP (ARM_ARCH_V5T | ARM_EXT_V5ExP)
86 #define ARM_ARCH_V5TE (ARM_ARCH_V5TExP | ARM_EXT_V5E)
87 #define ARM_ARCH_V5TEJ (ARM_ARCH_V5TE | ARM_EXT_V5J)
88 #define ARM_ARCH_V6 (ARM_ARCH_V5TEJ | ARM_EXT_V6)
89
90 /* Processors with specific extensions in the co-processor space. */
91 #define ARM_ARCH_XSCALE (ARM_ARCH_V5TE | ARM_CEXT_XSCALE)
92 #define ARM_ARCH_IWMMXT (ARM_ARCH_XSCALE | ARM_CEXT_IWMMXT)
93
94 /* Some useful combinations: */
95 #define ARM_ANY 0x0000ffff /* Any basic core. */
96 #define ARM_ALL 0x00ffffff /* Any core + co-processor */
97 #define CPROC_ANY 0x00ff0000 /* Any co-processor */
98 #define FPU_ANY 0xff000000 /* Note this is ~ARM_ALL. */
99
100
101 #define FPU_FPA_EXT_V1 0x80000000 /* Base FPA instruction set. */
102 #define FPU_FPA_EXT_V2 0x40000000 /* LFM/SFM. */
103 #define FPU_VFP_EXT_NONE 0x20000000 /* Use VFP word-ordering. */
104 #define FPU_VFP_EXT_V1xD 0x10000000 /* Base VFP instruction set. */
105 #define FPU_VFP_EXT_V1 0x08000000 /* Double-precision insns. */
106 #define FPU_VFP_EXT_V2 0x04000000 /* ARM10E VFPr1. */
107 #define FPU_MAVERICK 0x02000000 /* Cirrus Maverick. */
108 #define FPU_NONE 0
109
110 #define FPU_ARCH_FPE FPU_FPA_EXT_V1
111 #define FPU_ARCH_FPA (FPU_ARCH_FPE | FPU_FPA_EXT_V2)
112
113 #define FPU_ARCH_VFP FPU_VFP_EXT_NONE
114 #define FPU_ARCH_VFP_V1xD (FPU_VFP_EXT_V1xD | FPU_VFP_EXT_NONE)
115 #define FPU_ARCH_VFP_V1 (FPU_ARCH_VFP_V1xD | FPU_VFP_EXT_V1)
116 #define FPU_ARCH_VFP_V2 (FPU_ARCH_VFP_V1 | FPU_VFP_EXT_V2)
117
118 #define FPU_ARCH_MAVERICK FPU_MAVERICK
119
120 enum arm_float_abi
121 {
122 ARM_FLOAT_ABI_HARD,
123 ARM_FLOAT_ABI_SOFTFP,
124 ARM_FLOAT_ABI_SOFT
125 };
126
127 /* Types of processor to assemble for. */
128 #define ARM_1 ARM_ARCH_V1
129 #define ARM_2 ARM_ARCH_V2
130 #define ARM_3 ARM_ARCH_V2S
131 #define ARM_250 ARM_ARCH_V2S
132 #define ARM_6 ARM_ARCH_V3
133 #define ARM_7 ARM_ARCH_V3
134 #define ARM_8 ARM_ARCH_V4
135 #define ARM_9 ARM_ARCH_V4T
136 #define ARM_STRONG ARM_ARCH_V4
137 #define ARM_CPU_MASK 0x0000000f /* XXX? */
138
139 #ifndef CPU_DEFAULT
140 #if defined __XSCALE__
141 #define CPU_DEFAULT (ARM_ARCH_XSCALE)
142 #else
143 #if defined __thumb__
144 #define CPU_DEFAULT (ARM_ARCH_V5T)
145 #else
146 #define CPU_DEFAULT ARM_ANY
147 #endif
148 #endif
149 #endif
150
151 #ifdef TE_LINUX
152 #define FPU_DEFAULT FPU_ARCH_FPA
153 #endif
154
155 #if defined(TE_NetBSD) || defined(TE_OpenBSD)
156 #ifdef OBJ_ELF
157 #define FPU_DEFAULT FPU_ARCH_VFP /* Soft-float, but VFP order. */
158 #else
159 /* Legacy a.out format. */
160 #define FPU_DEFAULT FPU_ARCH_FPA /* Soft-float, but FPA order. */
161 #endif
162 #endif
163
164 /* For backwards compatibility we default to the FPA. */
165 #ifndef FPU_DEFAULT
166 #define FPU_DEFAULT FPU_ARCH_FPA
167 #endif
168
169 #define streq(a, b) (strcmp (a, b) == 0)
170 #define skip_whitespace(str) while (*(str) == ' ') ++(str)
171
172 static unsigned long cpu_variant;
173 static int target_oabi = 0;
174
175 /* Flags stored in private area of BFD structure. */
176 static int uses_apcs_26 = FALSE;
177 static int atpcs = FALSE;
178 static int support_interwork = FALSE;
179 static int uses_apcs_float = FALSE;
180 static int pic_code = FALSE;
181
182 /* Variables that we set while parsing command-line options. Once all
183 options have been read we re-process these values to set the real
184 assembly flags. */
185 static int legacy_cpu = -1;
186 static int legacy_fpu = -1;
187
188 static int mcpu_cpu_opt = -1;
189 static int mcpu_fpu_opt = -1;
190 static int march_cpu_opt = -1;
191 static int march_fpu_opt = -1;
192 static int mfpu_opt = -1;
193 static int mfloat_abi_opt = -1;
194
195 /* This array holds the chars that always start a comment. If the
196 pre-processor is disabled, these aren't very useful. */
197 const char comment_chars[] = "@";
198
199 /* This array holds the chars that only start a comment at the beginning of
200 a line. If the line seems to have the form '# 123 filename'
201 .line and .file directives will appear in the pre-processed output. */
202 /* Note that input_file.c hand checks for '#' at the beginning of the
203 first line of the input file. This is because the compiler outputs
204 #NO_APP at the beginning of its output. */
205 /* Also note that comments like this one will always work. */
206 const char line_comment_chars[] = "#";
207
208 const char line_separator_chars[] = ";";
209
210 /* Chars that can be used to separate mant
211 from exp in floating point numbers. */
212 const char EXP_CHARS[] = "eE";
213
214 /* Chars that mean this number is a floating point constant. */
215 /* As in 0f12.456 */
216 /* or 0d1.2345e12 */
217
218 const char FLT_CHARS[] = "rRsSfFdDxXeEpP";
219
220 /* Prefix characters that indicate the start of an immediate
221 value. */
222 #define is_immediate_prefix(C) ((C) == '#' || (C) == '$')
223
224 #ifdef OBJ_ELF
225 /* Pre-defined "_GLOBAL_OFFSET_TABLE_" */
226 symbolS * GOT_symbol;
227 #endif
228
229 /* Size of relocation record. */
230 const int md_reloc_size = 8;
231
232 /* 0: assemble for ARM,
233 1: assemble for Thumb,
234 2: assemble for Thumb even though target CPU does not support thumb
235 instructions. */
236 static int thumb_mode = 0;
237
238 typedef struct arm_fix
239 {
240 int thumb_mode;
241 } arm_fix_data;
242
243 struct arm_it
244 {
245 const char * error;
246 unsigned long instruction;
247 int size;
248 struct
249 {
250 bfd_reloc_code_real_type type;
251 expressionS exp;
252 int pc_rel;
253 } reloc;
254 };
255
256 struct arm_it inst;
257
258 enum asm_shift_index
259 {
260 SHIFT_LSL = 0,
261 SHIFT_LSR,
262 SHIFT_ASR,
263 SHIFT_ROR,
264 SHIFT_RRX
265 };
266
267 struct asm_shift_properties
268 {
269 enum asm_shift_index index;
270 unsigned long bit_field;
271 unsigned int allows_0 : 1;
272 unsigned int allows_32 : 1;
273 };
274
275 static const struct asm_shift_properties shift_properties [] =
276 {
277 { SHIFT_LSL, 0, 1, 0},
278 { SHIFT_LSR, 0x20, 0, 1},
279 { SHIFT_ASR, 0x40, 0, 1},
280 { SHIFT_ROR, 0x60, 0, 0},
281 { SHIFT_RRX, 0x60, 0, 0}
282 };
283
284 struct asm_shift_name
285 {
286 const char * name;
287 const struct asm_shift_properties * properties;
288 };
289
290 static const struct asm_shift_name shift_names [] =
291 {
292 { "asl", shift_properties + SHIFT_LSL },
293 { "lsl", shift_properties + SHIFT_LSL },
294 { "lsr", shift_properties + SHIFT_LSR },
295 { "asr", shift_properties + SHIFT_ASR },
296 { "ror", shift_properties + SHIFT_ROR },
297 { "rrx", shift_properties + SHIFT_RRX },
298 { "ASL", shift_properties + SHIFT_LSL },
299 { "LSL", shift_properties + SHIFT_LSL },
300 { "LSR", shift_properties + SHIFT_LSR },
301 { "ASR", shift_properties + SHIFT_ASR },
302 { "ROR", shift_properties + SHIFT_ROR },
303 { "RRX", shift_properties + SHIFT_RRX }
304 };
305
306 /* Any kind of shift is accepted. */
307 #define NO_SHIFT_RESTRICT 1
308 /* The shift operand must be an immediate value, not a register. */
309 #define SHIFT_IMMEDIATE 0
310 /* The shift must be LSL or ASR and the operand must be an immediate. */
311 #define SHIFT_LSL_OR_ASR_IMMEDIATE 2
312 /* The shift must be ASR and the operand must be an immediate. */
313 #define SHIFT_ASR_IMMEDIATE 3
314 /* The shift must be LSL and the operand must be an immediate. */
315 #define SHIFT_LSL_IMMEDIATE 4
316
317 #define NUM_FLOAT_VALS 8
318
319 const char * fp_const[] =
320 {
321 "0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0", 0
322 };
323
324 /* Number of littlenums required to hold an extended precision number. */
325 #define MAX_LITTLENUMS 6
326
327 LITTLENUM_TYPE fp_values[NUM_FLOAT_VALS][MAX_LITTLENUMS];
328
329 #define FAIL (-1)
330 #define SUCCESS (0)
331
332 /* Whether a Co-processor load/store operation accepts write-back forms. */
333 #define CP_WB_OK 1
334 #define CP_NO_WB 0
335
336 #define SUFF_S 1
337 #define SUFF_D 2
338 #define SUFF_E 3
339 #define SUFF_P 4
340
341 #define CP_T_X 0x00008000
342 #define CP_T_Y 0x00400000
343 #define CP_T_Pre 0x01000000
344 #define CP_T_UD 0x00800000
345 #define CP_T_WB 0x00200000
346
347 #define CONDS_BIT 0x00100000
348 #define LOAD_BIT 0x00100000
349
350 #define DOUBLE_LOAD_FLAG 0x00000001
351
352 struct asm_cond
353 {
354 const char * template;
355 unsigned long value;
356 };
357
358 #define COND_ALWAYS 0xe0000000
359 #define COND_MASK 0xf0000000
360
361 static const struct asm_cond conds[] =
362 {
363 {"eq", 0x00000000},
364 {"ne", 0x10000000},
365 {"cs", 0x20000000}, {"hs", 0x20000000},
366 {"cc", 0x30000000}, {"ul", 0x30000000}, {"lo", 0x30000000},
367 {"mi", 0x40000000},
368 {"pl", 0x50000000},
369 {"vs", 0x60000000},
370 {"vc", 0x70000000},
371 {"hi", 0x80000000},
372 {"ls", 0x90000000},
373 {"ge", 0xa0000000},
374 {"lt", 0xb0000000},
375 {"gt", 0xc0000000},
376 {"le", 0xd0000000},
377 {"al", 0xe0000000},
378 {"nv", 0xf0000000}
379 };
380
381 struct asm_psr
382 {
383 const char *template;
384 bfd_boolean cpsr;
385 unsigned long field;
386 };
387
388 /* The bit that distinguishes CPSR and SPSR. */
389 #define SPSR_BIT (1 << 22)
390
391 /* How many bits to shift the PSR_xxx bits up by. */
392 #define PSR_SHIFT 16
393
394 #define PSR_c (1 << 0)
395 #define PSR_x (1 << 1)
396 #define PSR_s (1 << 2)
397 #define PSR_f (1 << 3)
398
399 static const struct asm_psr psrs[] =
400 {
401 {"CPSR", TRUE, PSR_c | PSR_f},
402 {"CPSR_all", TRUE, PSR_c | PSR_f},
403 {"SPSR", FALSE, PSR_c | PSR_f},
404 {"SPSR_all", FALSE, PSR_c | PSR_f},
405 {"CPSR_flg", TRUE, PSR_f},
406 {"CPSR_f", TRUE, PSR_f},
407 {"SPSR_flg", FALSE, PSR_f},
408 {"SPSR_f", FALSE, PSR_f},
409 {"CPSR_c", TRUE, PSR_c},
410 {"CPSR_ctl", TRUE, PSR_c},
411 {"SPSR_c", FALSE, PSR_c},
412 {"SPSR_ctl", FALSE, PSR_c},
413 {"CPSR_x", TRUE, PSR_x},
414 {"CPSR_s", TRUE, PSR_s},
415 {"SPSR_x", FALSE, PSR_x},
416 {"SPSR_s", FALSE, PSR_s},
417 /* Combinations of flags. */
418 {"CPSR_fs", TRUE, PSR_f | PSR_s},
419 {"CPSR_fx", TRUE, PSR_f | PSR_x},
420 {"CPSR_fc", TRUE, PSR_f | PSR_c},
421 {"CPSR_sf", TRUE, PSR_s | PSR_f},
422 {"CPSR_sx", TRUE, PSR_s | PSR_x},
423 {"CPSR_sc", TRUE, PSR_s | PSR_c},
424 {"CPSR_xf", TRUE, PSR_x | PSR_f},
425 {"CPSR_xs", TRUE, PSR_x | PSR_s},
426 {"CPSR_xc", TRUE, PSR_x | PSR_c},
427 {"CPSR_cf", TRUE, PSR_c | PSR_f},
428 {"CPSR_cs", TRUE, PSR_c | PSR_s},
429 {"CPSR_cx", TRUE, PSR_c | PSR_x},
430 {"CPSR_fsx", TRUE, PSR_f | PSR_s | PSR_x},
431 {"CPSR_fsc", TRUE, PSR_f | PSR_s | PSR_c},
432 {"CPSR_fxs", TRUE, PSR_f | PSR_x | PSR_s},
433 {"CPSR_fxc", TRUE, PSR_f | PSR_x | PSR_c},
434 {"CPSR_fcs", TRUE, PSR_f | PSR_c | PSR_s},
435 {"CPSR_fcx", TRUE, PSR_f | PSR_c | PSR_x},
436 {"CPSR_sfx", TRUE, PSR_s | PSR_f | PSR_x},
437 {"CPSR_sfc", TRUE, PSR_s | PSR_f | PSR_c},
438 {"CPSR_sxf", TRUE, PSR_s | PSR_x | PSR_f},
439 {"CPSR_sxc", TRUE, PSR_s | PSR_x | PSR_c},
440 {"CPSR_scf", TRUE, PSR_s | PSR_c | PSR_f},
441 {"CPSR_scx", TRUE, PSR_s | PSR_c | PSR_x},
442 {"CPSR_xfs", TRUE, PSR_x | PSR_f | PSR_s},
443 {"CPSR_xfc", TRUE, PSR_x | PSR_f | PSR_c},
444 {"CPSR_xsf", TRUE, PSR_x | PSR_s | PSR_f},
445 {"CPSR_xsc", TRUE, PSR_x | PSR_s | PSR_c},
446 {"CPSR_xcf", TRUE, PSR_x | PSR_c | PSR_f},
447 {"CPSR_xcs", TRUE, PSR_x | PSR_c | PSR_s},
448 {"CPSR_cfs", TRUE, PSR_c | PSR_f | PSR_s},
449 {"CPSR_cfx", TRUE, PSR_c | PSR_f | PSR_x},
450 {"CPSR_csf", TRUE, PSR_c | PSR_s | PSR_f},
451 {"CPSR_csx", TRUE, PSR_c | PSR_s | PSR_x},
452 {"CPSR_cxf", TRUE, PSR_c | PSR_x | PSR_f},
453 {"CPSR_cxs", TRUE, PSR_c | PSR_x | PSR_s},
454 {"CPSR_fsxc", TRUE, PSR_f | PSR_s | PSR_x | PSR_c},
455 {"CPSR_fscx", TRUE, PSR_f | PSR_s | PSR_c | PSR_x},
456 {"CPSR_fxsc", TRUE, PSR_f | PSR_x | PSR_s | PSR_c},
457 {"CPSR_fxcs", TRUE, PSR_f | PSR_x | PSR_c | PSR_s},
458 {"CPSR_fcsx", TRUE, PSR_f | PSR_c | PSR_s | PSR_x},
459 {"CPSR_fcxs", TRUE, PSR_f | PSR_c | PSR_x | PSR_s},
460 {"CPSR_sfxc", TRUE, PSR_s | PSR_f | PSR_x | PSR_c},
461 {"CPSR_sfcx", TRUE, PSR_s | PSR_f | PSR_c | PSR_x},
462 {"CPSR_sxfc", TRUE, PSR_s | PSR_x | PSR_f | PSR_c},
463 {"CPSR_sxcf", TRUE, PSR_s | PSR_x | PSR_c | PSR_f},
464 {"CPSR_scfx", TRUE, PSR_s | PSR_c | PSR_f | PSR_x},
465 {"CPSR_scxf", TRUE, PSR_s | PSR_c | PSR_x | PSR_f},
466 {"CPSR_xfsc", TRUE, PSR_x | PSR_f | PSR_s | PSR_c},
467 {"CPSR_xfcs", TRUE, PSR_x | PSR_f | PSR_c | PSR_s},
468 {"CPSR_xsfc", TRUE, PSR_x | PSR_s | PSR_f | PSR_c},
469 {"CPSR_xscf", TRUE, PSR_x | PSR_s | PSR_c | PSR_f},
470 {"CPSR_xcfs", TRUE, PSR_x | PSR_c | PSR_f | PSR_s},
471 {"CPSR_xcsf", TRUE, PSR_x | PSR_c | PSR_s | PSR_f},
472 {"CPSR_cfsx", TRUE, PSR_c | PSR_f | PSR_s | PSR_x},
473 {"CPSR_cfxs", TRUE, PSR_c | PSR_f | PSR_x | PSR_s},
474 {"CPSR_csfx", TRUE, PSR_c | PSR_s | PSR_f | PSR_x},
475 {"CPSR_csxf", TRUE, PSR_c | PSR_s | PSR_x | PSR_f},
476 {"CPSR_cxfs", TRUE, PSR_c | PSR_x | PSR_f | PSR_s},
477 {"CPSR_cxsf", TRUE, PSR_c | PSR_x | PSR_s | PSR_f},
478 {"SPSR_fs", FALSE, PSR_f | PSR_s},
479 {"SPSR_fx", FALSE, PSR_f | PSR_x},
480 {"SPSR_fc", FALSE, PSR_f | PSR_c},
481 {"SPSR_sf", FALSE, PSR_s | PSR_f},
482 {"SPSR_sx", FALSE, PSR_s | PSR_x},
483 {"SPSR_sc", FALSE, PSR_s | PSR_c},
484 {"SPSR_xf", FALSE, PSR_x | PSR_f},
485 {"SPSR_xs", FALSE, PSR_x | PSR_s},
486 {"SPSR_xc", FALSE, PSR_x | PSR_c},
487 {"SPSR_cf", FALSE, PSR_c | PSR_f},
488 {"SPSR_cs", FALSE, PSR_c | PSR_s},
489 {"SPSR_cx", FALSE, PSR_c | PSR_x},
490 {"SPSR_fsx", FALSE, PSR_f | PSR_s | PSR_x},
491 {"SPSR_fsc", FALSE, PSR_f | PSR_s | PSR_c},
492 {"SPSR_fxs", FALSE, PSR_f | PSR_x | PSR_s},
493 {"SPSR_fxc", FALSE, PSR_f | PSR_x | PSR_c},
494 {"SPSR_fcs", FALSE, PSR_f | PSR_c | PSR_s},
495 {"SPSR_fcx", FALSE, PSR_f | PSR_c | PSR_x},
496 {"SPSR_sfx", FALSE, PSR_s | PSR_f | PSR_x},
497 {"SPSR_sfc", FALSE, PSR_s | PSR_f | PSR_c},
498 {"SPSR_sxf", FALSE, PSR_s | PSR_x | PSR_f},
499 {"SPSR_sxc", FALSE, PSR_s | PSR_x | PSR_c},
500 {"SPSR_scf", FALSE, PSR_s | PSR_c | PSR_f},
501 {"SPSR_scx", FALSE, PSR_s | PSR_c | PSR_x},
502 {"SPSR_xfs", FALSE, PSR_x | PSR_f | PSR_s},
503 {"SPSR_xfc", FALSE, PSR_x | PSR_f | PSR_c},
504 {"SPSR_xsf", FALSE, PSR_x | PSR_s | PSR_f},
505 {"SPSR_xsc", FALSE, PSR_x | PSR_s | PSR_c},
506 {"SPSR_xcf", FALSE, PSR_x | PSR_c | PSR_f},
507 {"SPSR_xcs", FALSE, PSR_x | PSR_c | PSR_s},
508 {"SPSR_cfs", FALSE, PSR_c | PSR_f | PSR_s},
509 {"SPSR_cfx", FALSE, PSR_c | PSR_f | PSR_x},
510 {"SPSR_csf", FALSE, PSR_c | PSR_s | PSR_f},
511 {"SPSR_csx", FALSE, PSR_c | PSR_s | PSR_x},
512 {"SPSR_cxf", FALSE, PSR_c | PSR_x | PSR_f},
513 {"SPSR_cxs", FALSE, PSR_c | PSR_x | PSR_s},
514 {"SPSR_fsxc", FALSE, PSR_f | PSR_s | PSR_x | PSR_c},
515 {"SPSR_fscx", FALSE, PSR_f | PSR_s | PSR_c | PSR_x},
516 {"SPSR_fxsc", FALSE, PSR_f | PSR_x | PSR_s | PSR_c},
517 {"SPSR_fxcs", FALSE, PSR_f | PSR_x | PSR_c | PSR_s},
518 {"SPSR_fcsx", FALSE, PSR_f | PSR_c | PSR_s | PSR_x},
519 {"SPSR_fcxs", FALSE, PSR_f | PSR_c | PSR_x | PSR_s},
520 {"SPSR_sfxc", FALSE, PSR_s | PSR_f | PSR_x | PSR_c},
521 {"SPSR_sfcx", FALSE, PSR_s | PSR_f | PSR_c | PSR_x},
522 {"SPSR_sxfc", FALSE, PSR_s | PSR_x | PSR_f | PSR_c},
523 {"SPSR_sxcf", FALSE, PSR_s | PSR_x | PSR_c | PSR_f},
524 {"SPSR_scfx", FALSE, PSR_s | PSR_c | PSR_f | PSR_x},
525 {"SPSR_scxf", FALSE, PSR_s | PSR_c | PSR_x | PSR_f},
526 {"SPSR_xfsc", FALSE, PSR_x | PSR_f | PSR_s | PSR_c},
527 {"SPSR_xfcs", FALSE, PSR_x | PSR_f | PSR_c | PSR_s},
528 {"SPSR_xsfc", FALSE, PSR_x | PSR_s | PSR_f | PSR_c},
529 {"SPSR_xscf", FALSE, PSR_x | PSR_s | PSR_c | PSR_f},
530 {"SPSR_xcfs", FALSE, PSR_x | PSR_c | PSR_f | PSR_s},
531 {"SPSR_xcsf", FALSE, PSR_x | PSR_c | PSR_s | PSR_f},
532 {"SPSR_cfsx", FALSE, PSR_c | PSR_f | PSR_s | PSR_x},
533 {"SPSR_cfxs", FALSE, PSR_c | PSR_f | PSR_x | PSR_s},
534 {"SPSR_csfx", FALSE, PSR_c | PSR_s | PSR_f | PSR_x},
535 {"SPSR_csxf", FALSE, PSR_c | PSR_s | PSR_x | PSR_f},
536 {"SPSR_cxfs", FALSE, PSR_c | PSR_x | PSR_f | PSR_s},
537 {"SPSR_cxsf", FALSE, PSR_c | PSR_x | PSR_s | PSR_f},
538 };
539
540 enum wreg_type
541 {
542 IWMMXT_REG_WR = 0,
543 IWMMXT_REG_WC = 1,
544 IWMMXT_REG_WR_OR_WC = 2,
545 IWMMXT_REG_WCG
546 };
547
548 enum iwmmxt_insn_type
549 {
550 check_rd,
551 check_wr,
552 check_wrwr,
553 check_wrwrwr,
554 check_wrwrwcg,
555 check_tbcst,
556 check_tmovmsk,
557 check_tmia,
558 check_tmcrr,
559 check_tmrrc,
560 check_tmcr,
561 check_tmrc,
562 check_tinsr,
563 check_textrc,
564 check_waligni,
565 check_textrm,
566 check_wshufh
567 };
568
569 enum vfp_dp_reg_pos
570 {
571 VFP_REG_Dd, VFP_REG_Dm, VFP_REG_Dn
572 };
573
574 enum vfp_sp_reg_pos
575 {
576 VFP_REG_Sd, VFP_REG_Sm, VFP_REG_Sn
577 };
578
579 enum vfp_ldstm_type
580 {
581 VFP_LDSTMIA, VFP_LDSTMDB, VFP_LDSTMIAX, VFP_LDSTMDBX
582 };
583
584 /* VFP system registers. */
585 struct vfp_reg
586 {
587 const char *name;
588 unsigned long regno;
589 };
590
591 static const struct vfp_reg vfp_regs[] =
592 {
593 {"fpsid", 0x00000000},
594 {"FPSID", 0x00000000},
595 {"fpscr", 0x00010000},
596 {"FPSCR", 0x00010000},
597 {"fpexc", 0x00080000},
598 {"FPEXC", 0x00080000}
599 };
600
601 /* Structure for a hash table entry for a register. */
602 struct reg_entry
603 {
604 const char * name;
605 int number;
606 bfd_boolean builtin;
607 };
608
609 /* Some well known registers that we refer to directly elsewhere. */
610 #define REG_SP 13
611 #define REG_LR 14
612 #define REG_PC 15
613
614 #define wr_register(reg) ((reg ^ WR_PREFIX) >= 0 && (reg ^ WR_PREFIX) <= 15)
615 #define wc_register(reg) ((reg ^ WC_PREFIX) >= 0 && (reg ^ WC_PREFIX) <= 15)
616 #define wcg_register(reg) ((reg ^ WC_PREFIX) >= 8 && (reg ^ WC_PREFIX) <= 11)
617
618 /* These are the standard names. Users can add aliases with .req.
619 and delete them with .unreq. */
620
621 /* Integer Register Numbers. */
622 static const struct reg_entry rn_table[] =
623 {
624 {"r0", 0, TRUE}, {"r1", 1, TRUE}, {"r2", 2, TRUE}, {"r3", 3, TRUE},
625 {"r4", 4, TRUE}, {"r5", 5, TRUE}, {"r6", 6, TRUE}, {"r7", 7, TRUE},
626 {"r8", 8, TRUE}, {"r9", 9, TRUE}, {"r10", 10, TRUE}, {"r11", 11, TRUE},
627 {"r12", 12, TRUE}, {"r13", REG_SP, TRUE}, {"r14", REG_LR, TRUE}, {"r15", REG_PC, TRUE},
628 /* ATPCS Synonyms. */
629 {"a1", 0, TRUE}, {"a2", 1, TRUE}, {"a3", 2, TRUE}, {"a4", 3, TRUE},
630 {"v1", 4, TRUE}, {"v2", 5, TRUE}, {"v3", 6, TRUE}, {"v4", 7, TRUE},
631 {"v5", 8, TRUE}, {"v6", 9, TRUE}, {"v7", 10, TRUE}, {"v8", 11, TRUE},
632 /* Well-known aliases. */
633 {"wr", 7, TRUE}, {"sb", 9, TRUE}, {"sl", 10, TRUE}, {"fp", 11, TRUE},
634 {"ip", 12, TRUE}, {"sp", REG_SP, TRUE}, {"lr", REG_LR, TRUE}, {"pc", REG_PC, TRUE},
635 {NULL, 0, TRUE}
636 };
637
638 #define WR_PREFIX 0x200
639 #define WC_PREFIX 0x400
640
641 static const struct reg_entry iwmmxt_table[] =
642 {
643 /* Intel Wireless MMX technology register names. */
644 { "wr0", 0x0 | WR_PREFIX, TRUE}, {"wr1", 0x1 | WR_PREFIX, TRUE},
645 { "wr2", 0x2 | WR_PREFIX, TRUE}, {"wr3", 0x3 | WR_PREFIX, TRUE},
646 { "wr4", 0x4 | WR_PREFIX, TRUE}, {"wr5", 0x5 | WR_PREFIX, TRUE},
647 { "wr6", 0x6 | WR_PREFIX, TRUE}, {"wr7", 0x7 | WR_PREFIX, TRUE},
648 { "wr8", 0x8 | WR_PREFIX, TRUE}, {"wr9", 0x9 | WR_PREFIX, TRUE},
649 { "wr10", 0xa | WR_PREFIX, TRUE}, {"wr11", 0xb | WR_PREFIX, TRUE},
650 { "wr12", 0xc | WR_PREFIX, TRUE}, {"wr13", 0xd | WR_PREFIX, TRUE},
651 { "wr14", 0xe | WR_PREFIX, TRUE}, {"wr15", 0xf | WR_PREFIX, TRUE},
652 { "wcid", 0x0 | WC_PREFIX, TRUE}, {"wcon", 0x1 | WC_PREFIX, TRUE},
653 {"wcssf", 0x2 | WC_PREFIX, TRUE}, {"wcasf", 0x3 | WC_PREFIX, TRUE},
654 {"wcgr0", 0x8 | WC_PREFIX, TRUE}, {"wcgr1", 0x9 | WC_PREFIX, TRUE},
655 {"wcgr2", 0xa | WC_PREFIX, TRUE}, {"wcgr3", 0xb | WC_PREFIX, TRUE},
656
657 { "wR0", 0x0 | WR_PREFIX, TRUE}, {"wR1", 0x1 | WR_PREFIX, TRUE},
658 { "wR2", 0x2 | WR_PREFIX, TRUE}, {"wR3", 0x3 | WR_PREFIX, TRUE},
659 { "wR4", 0x4 | WR_PREFIX, TRUE}, {"wR5", 0x5 | WR_PREFIX, TRUE},
660 { "wR6", 0x6 | WR_PREFIX, TRUE}, {"wR7", 0x7 | WR_PREFIX, TRUE},
661 { "wR8", 0x8 | WR_PREFIX, TRUE}, {"wR9", 0x9 | WR_PREFIX, TRUE},
662 { "wR10", 0xa | WR_PREFIX, TRUE}, {"wR11", 0xb | WR_PREFIX, TRUE},
663 { "wR12", 0xc | WR_PREFIX, TRUE}, {"wR13", 0xd | WR_PREFIX, TRUE},
664 { "wR14", 0xe | WR_PREFIX, TRUE}, {"wR15", 0xf | WR_PREFIX, TRUE},
665 { "wCID", 0x0 | WC_PREFIX, TRUE}, {"wCon", 0x1 | WC_PREFIX, TRUE},
666 {"wCSSF", 0x2 | WC_PREFIX, TRUE}, {"wCASF", 0x3 | WC_PREFIX, TRUE},
667 {"wCGR0", 0x8 | WC_PREFIX, TRUE}, {"wCGR1", 0x9 | WC_PREFIX, TRUE},
668 {"wCGR2", 0xa | WC_PREFIX, TRUE}, {"wCGR3", 0xb | WC_PREFIX, TRUE},
669 {NULL, 0, TRUE}
670 };
671
672 /* Co-processor Numbers. */
673 static const struct reg_entry cp_table[] =
674 {
675 {"p0", 0, TRUE}, {"p1", 1, TRUE}, {"p2", 2, TRUE}, {"p3", 3, TRUE},
676 {"p4", 4, TRUE}, {"p5", 5, TRUE}, {"p6", 6, TRUE}, {"p7", 7, TRUE},
677 {"p8", 8, TRUE}, {"p9", 9, TRUE}, {"p10", 10, TRUE}, {"p11", 11, TRUE},
678 {"p12", 12, TRUE}, {"p13", 13, TRUE}, {"p14", 14, TRUE}, {"p15", 15, TRUE},
679 {NULL, 0, TRUE}
680 };
681
682 /* Co-processor Register Numbers. */
683 static const struct reg_entry cn_table[] =
684 {
685 {"c0", 0, TRUE}, {"c1", 1, TRUE}, {"c2", 2, TRUE}, {"c3", 3, TRUE},
686 {"c4", 4, TRUE}, {"c5", 5, TRUE}, {"c6", 6, TRUE}, {"c7", 7, TRUE},
687 {"c8", 8, TRUE}, {"c9", 9, TRUE}, {"c10", 10, TRUE}, {"c11", 11, TRUE},
688 {"c12", 12, TRUE}, {"c13", 13, TRUE}, {"c14", 14, TRUE}, {"c15", 15, TRUE},
689 /* Not really valid, but kept for back-wards compatibility. */
690 {"cr0", 0, TRUE}, {"cr1", 1, TRUE}, {"cr2", 2, TRUE}, {"cr3", 3, TRUE},
691 {"cr4", 4, TRUE}, {"cr5", 5, TRUE}, {"cr6", 6, TRUE}, {"cr7", 7, TRUE},
692 {"cr8", 8, TRUE}, {"cr9", 9, TRUE}, {"cr10", 10, TRUE}, {"cr11", 11, TRUE},
693 {"cr12", 12, TRUE}, {"cr13", 13, TRUE}, {"cr14", 14, TRUE}, {"cr15", 15, TRUE},
694 {NULL, 0, TRUE}
695 };
696
697 /* FPA Registers. */
698 static const struct reg_entry fn_table[] =
699 {
700 {"f0", 0, TRUE}, {"f1", 1, TRUE}, {"f2", 2, TRUE}, {"f3", 3, TRUE},
701 {"f4", 4, TRUE}, {"f5", 5, TRUE}, {"f6", 6, TRUE}, {"f7", 7, TRUE},
702 {NULL, 0, TRUE}
703 };
704
705 /* VFP SP Registers. */
706 static const struct reg_entry sn_table[] =
707 {
708 {"s0", 0, TRUE}, {"s1", 1, TRUE}, {"s2", 2, TRUE}, {"s3", 3, TRUE},
709 {"s4", 4, TRUE}, {"s5", 5, TRUE}, {"s6", 6, TRUE}, {"s7", 7, TRUE},
710 {"s8", 8, TRUE}, {"s9", 9, TRUE}, {"s10", 10, TRUE}, {"s11", 11, TRUE},
711 {"s12", 12, TRUE}, {"s13", 13, TRUE}, {"s14", 14, TRUE}, {"s15", 15, TRUE},
712 {"s16", 16, TRUE}, {"s17", 17, TRUE}, {"s18", 18, TRUE}, {"s19", 19, TRUE},
713 {"s20", 20, TRUE}, {"s21", 21, TRUE}, {"s22", 22, TRUE}, {"s23", 23, TRUE},
714 {"s24", 24, TRUE}, {"s25", 25, TRUE}, {"s26", 26, TRUE}, {"s27", 27, TRUE},
715 {"s28", 28, TRUE}, {"s29", 29, TRUE}, {"s30", 30, TRUE}, {"s31", 31, TRUE},
716 {NULL, 0, TRUE}
717 };
718
719 /* VFP DP Registers. */
720 static const struct reg_entry dn_table[] =
721 {
722 {"d0", 0, TRUE}, {"d1", 1, TRUE}, {"d2", 2, TRUE}, {"d3", 3, TRUE},
723 {"d4", 4, TRUE}, {"d5", 5, TRUE}, {"d6", 6, TRUE}, {"d7", 7, TRUE},
724 {"d8", 8, TRUE}, {"d9", 9, TRUE}, {"d10", 10, TRUE}, {"d11", 11, TRUE},
725 {"d12", 12, TRUE}, {"d13", 13, TRUE}, {"d14", 14, TRUE}, {"d15", 15, TRUE},
726 {NULL, 0, TRUE}
727 };
728
729 /* Maverick DSP coprocessor registers. */
730 static const struct reg_entry mav_mvf_table[] =
731 {
732 {"mvf0", 0, TRUE}, {"mvf1", 1, TRUE}, {"mvf2", 2, TRUE}, {"mvf3", 3, TRUE},
733 {"mvf4", 4, TRUE}, {"mvf5", 5, TRUE}, {"mvf6", 6, TRUE}, {"mvf7", 7, TRUE},
734 {"mvf8", 8, TRUE}, {"mvf9", 9, TRUE}, {"mvf10", 10, TRUE}, {"mvf11", 11, TRUE},
735 {"mvf12", 12, TRUE}, {"mvf13", 13, TRUE}, {"mvf14", 14, TRUE}, {"mvf15", 15, TRUE},
736 {NULL, 0, TRUE}
737 };
738
739 static const struct reg_entry mav_mvd_table[] =
740 {
741 {"mvd0", 0, TRUE}, {"mvd1", 1, TRUE}, {"mvd2", 2, TRUE}, {"mvd3", 3, TRUE},
742 {"mvd4", 4, TRUE}, {"mvd5", 5, TRUE}, {"mvd6", 6, TRUE}, {"mvd7", 7, TRUE},
743 {"mvd8", 8, TRUE}, {"mvd9", 9, TRUE}, {"mvd10", 10, TRUE}, {"mvd11", 11, TRUE},
744 {"mvd12", 12, TRUE}, {"mvd13", 13, TRUE}, {"mvd14", 14, TRUE}, {"mvd15", 15, TRUE},
745 {NULL, 0, TRUE}
746 };
747
748 static const struct reg_entry mav_mvfx_table[] =
749 {
750 {"mvfx0", 0, TRUE}, {"mvfx1", 1, TRUE}, {"mvfx2", 2, TRUE}, {"mvfx3", 3, TRUE},
751 {"mvfx4", 4, TRUE}, {"mvfx5", 5, TRUE}, {"mvfx6", 6, TRUE}, {"mvfx7", 7, TRUE},
752 {"mvfx8", 8, TRUE}, {"mvfx9", 9, TRUE}, {"mvfx10", 10, TRUE}, {"mvfx11", 11, TRUE},
753 {"mvfx12", 12, TRUE}, {"mvfx13", 13, TRUE}, {"mvfx14", 14, TRUE}, {"mvfx15", 15, TRUE},
754 {NULL, 0, TRUE}
755 };
756
757 static const struct reg_entry mav_mvdx_table[] =
758 {
759 {"mvdx0", 0, TRUE}, {"mvdx1", 1, TRUE}, {"mvdx2", 2, TRUE}, {"mvdx3", 3, TRUE},
760 {"mvdx4", 4, TRUE}, {"mvdx5", 5, TRUE}, {"mvdx6", 6, TRUE}, {"mvdx7", 7, TRUE},
761 {"mvdx8", 8, TRUE}, {"mvdx9", 9, TRUE}, {"mvdx10", 10, TRUE}, {"mvdx11", 11, TRUE},
762 {"mvdx12", 12, TRUE}, {"mvdx13", 13, TRUE}, {"mvdx14", 14, TRUE}, {"mvdx15", 15, TRUE},
763 {NULL, 0, TRUE}
764 };
765
766 static const struct reg_entry mav_mvax_table[] =
767 {
768 {"mvax0", 0, TRUE}, {"mvax1", 1, TRUE}, {"mvax2", 2, TRUE}, {"mvax3", 3, TRUE},
769 {NULL, 0, TRUE}
770 };
771
772 static const struct reg_entry mav_dspsc_table[] =
773 {
774 {"dspsc", 0, TRUE},
775 {NULL, 0, TRUE}
776 };
777
778 struct reg_map
779 {
780 const struct reg_entry *names;
781 int max_regno;
782 struct hash_control *htab;
783 const char *expected;
784 };
785
786 struct reg_map all_reg_maps[] =
787 {
788 {rn_table, 15, NULL, N_("ARM register expected")},
789 {cp_table, 15, NULL, N_("bad or missing co-processor number")},
790 {cn_table, 15, NULL, N_("co-processor register expected")},
791 {fn_table, 7, NULL, N_("FPA register expected")},
792 {sn_table, 31, NULL, N_("VFP single precision register expected")},
793 {dn_table, 15, NULL, N_("VFP double precision register expected")},
794 {mav_mvf_table, 15, NULL, N_("Maverick MVF register expected")},
795 {mav_mvd_table, 15, NULL, N_("Maverick MVD register expected")},
796 {mav_mvfx_table, 15, NULL, N_("Maverick MVFX register expected")},
797 {mav_mvdx_table, 15, NULL, N_("Maverick MVDX register expected")},
798 {mav_mvax_table, 3, NULL, N_("Maverick MVAX register expected")},
799 {mav_dspsc_table, 0, NULL, N_("Maverick DSPSC register expected")},
800 {iwmmxt_table, 23, NULL, N_("Intel Wireless MMX technology register expected")},
801 };
802
803 /* Enumeration matching entries in table above. */
804 enum arm_reg_type
805 {
806 REG_TYPE_RN = 0,
807 #define REG_TYPE_FIRST REG_TYPE_RN
808 REG_TYPE_CP = 1,
809 REG_TYPE_CN = 2,
810 REG_TYPE_FN = 3,
811 REG_TYPE_SN = 4,
812 REG_TYPE_DN = 5,
813 REG_TYPE_MVF = 6,
814 REG_TYPE_MVD = 7,
815 REG_TYPE_MVFX = 8,
816 REG_TYPE_MVDX = 9,
817 REG_TYPE_MVAX = 10,
818 REG_TYPE_DSPSC = 11,
819 REG_TYPE_IWMMXT = 12,
820
821 REG_TYPE_MAX = 13
822 };
823
824 /* Functions called by parser. */
825 /* ARM instructions. */
826 static void do_arit PARAMS ((char *));
827 static void do_cmp PARAMS ((char *));
828 static void do_mov PARAMS ((char *));
829 static void do_ldst PARAMS ((char *));
830 static void do_ldstt PARAMS ((char *));
831 static void do_ldmstm PARAMS ((char *));
832 static void do_branch PARAMS ((char *));
833 static void do_swi PARAMS ((char *));
834
835 /* Pseudo Op codes. */
836 static void do_adr PARAMS ((char *));
837 static void do_adrl PARAMS ((char *));
838 static void do_empty PARAMS ((char *));
839
840 /* ARM v2. */
841 static void do_mul PARAMS ((char *));
842 static void do_mla PARAMS ((char *));
843
844 /* ARM v2S. */
845 static void do_swap PARAMS ((char *));
846
847 /* ARM v3. */
848 static void do_msr PARAMS ((char *));
849 static void do_mrs PARAMS ((char *));
850
851 /* ARM v3M. */
852 static void do_mull PARAMS ((char *));
853
854 /* ARM v4. */
855 static void do_ldstv4 PARAMS ((char *));
856
857 /* ARM v4T. */
858 static void do_bx PARAMS ((char *));
859
860 /* ARM v5T. */
861 static void do_blx PARAMS ((char *));
862 static void do_bkpt PARAMS ((char *));
863 static void do_clz PARAMS ((char *));
864 static void do_lstc2 PARAMS ((char *));
865 static void do_cdp2 PARAMS ((char *));
866 static void do_co_reg2 PARAMS ((char *));
867
868 /* ARM v5TExP. */
869 static void do_smla PARAMS ((char *));
870 static void do_smlal PARAMS ((char *));
871 static void do_smul PARAMS ((char *));
872 static void do_qadd PARAMS ((char *));
873
874 /* ARM v5TE. */
875 static void do_pld PARAMS ((char *));
876 static void do_ldrd PARAMS ((char *));
877 static void do_co_reg2c PARAMS ((char *));
878
879 /* ARM v5TEJ. */
880 static void do_bxj PARAMS ((char *));
881
882 /* ARM V6. */
883 static void do_cps PARAMS ((char *));
884 static void do_cpsi PARAMS ((char *));
885 static void do_ldrex PARAMS ((char *));
886 static void do_pkhbt PARAMS ((char *));
887 static void do_pkhtb PARAMS ((char *));
888 static void do_qadd16 PARAMS ((char *));
889 static void do_rev PARAMS ((char *));
890 static void do_rfe PARAMS ((char *));
891 static void do_sxtah PARAMS ((char *));
892 static void do_sxth PARAMS ((char *));
893 static void do_setend PARAMS ((char *));
894 static void do_smlad PARAMS ((char *));
895 static void do_smlald PARAMS ((char *));
896 static void do_smmul PARAMS ((char *));
897 static void do_ssat PARAMS ((char *));
898 static void do_usat PARAMS ((char *));
899 static void do_srs PARAMS ((char *));
900 static void do_ssat16 PARAMS ((char *));
901 static void do_usat16 PARAMS ((char *));
902 static void do_strex PARAMS ((char *));
903 static void do_umaal PARAMS ((char *));
904
905 static void do_cps_mode PARAMS ((char **));
906 static void do_cps_flags PARAMS ((char **, int));
907 static int do_endian_specifier PARAMS ((char *));
908 static void do_pkh_core PARAMS ((char *, int));
909 static void do_sat PARAMS ((char **, int));
910 static void do_sat16 PARAMS ((char **, int));
911
912 /* Coprocessor Instructions. */
913 static void do_cdp PARAMS ((char *));
914 static void do_lstc PARAMS ((char *));
915 static void do_co_reg PARAMS ((char *));
916
917 /* FPA instructions. */
918 static void do_fpa_ctrl PARAMS ((char *));
919 static void do_fpa_ldst PARAMS ((char *));
920 static void do_fpa_ldmstm PARAMS ((char *));
921 static void do_fpa_dyadic PARAMS ((char *));
922 static void do_fpa_monadic PARAMS ((char *));
923 static void do_fpa_cmp PARAMS ((char *));
924 static void do_fpa_from_reg PARAMS ((char *));
925 static void do_fpa_to_reg PARAMS ((char *));
926
927 /* VFP instructions. */
928 static void do_vfp_sp_monadic PARAMS ((char *));
929 static void do_vfp_dp_monadic PARAMS ((char *));
930 static void do_vfp_sp_dyadic PARAMS ((char *));
931 static void do_vfp_dp_dyadic PARAMS ((char *));
932 static void do_vfp_reg_from_sp PARAMS ((char *));
933 static void do_vfp_sp_from_reg PARAMS ((char *));
934 static void do_vfp_reg2_from_sp2 PARAMS ((char *));
935 static void do_vfp_sp2_from_reg2 PARAMS ((char *));
936 static void do_vfp_reg_from_dp PARAMS ((char *));
937 static void do_vfp_reg2_from_dp PARAMS ((char *));
938 static void do_vfp_dp_from_reg PARAMS ((char *));
939 static void do_vfp_dp_from_reg2 PARAMS ((char *));
940 static void do_vfp_reg_from_ctrl PARAMS ((char *));
941 static void do_vfp_ctrl_from_reg PARAMS ((char *));
942 static void do_vfp_sp_ldst PARAMS ((char *));
943 static void do_vfp_dp_ldst PARAMS ((char *));
944 static void do_vfp_sp_ldstmia PARAMS ((char *));
945 static void do_vfp_sp_ldstmdb PARAMS ((char *));
946 static void do_vfp_dp_ldstmia PARAMS ((char *));
947 static void do_vfp_dp_ldstmdb PARAMS ((char *));
948 static void do_vfp_xp_ldstmia PARAMS ((char *));
949 static void do_vfp_xp_ldstmdb PARAMS ((char *));
950 static void do_vfp_sp_compare_z PARAMS ((char *));
951 static void do_vfp_dp_compare_z PARAMS ((char *));
952 static void do_vfp_dp_sp_cvt PARAMS ((char *));
953 static void do_vfp_sp_dp_cvt PARAMS ((char *));
954
955 /* XScale. */
956 static void do_xsc_mia PARAMS ((char *));
957 static void do_xsc_mar PARAMS ((char *));
958 static void do_xsc_mra PARAMS ((char *));
959
960 /* Maverick. */
961 static void do_mav_binops PARAMS ((char *, int, enum arm_reg_type,
962 enum arm_reg_type));
963 static void do_mav_binops_1a PARAMS ((char *));
964 static void do_mav_binops_1b PARAMS ((char *));
965 static void do_mav_binops_1c PARAMS ((char *));
966 static void do_mav_binops_1d PARAMS ((char *));
967 static void do_mav_binops_1e PARAMS ((char *));
968 static void do_mav_binops_1f PARAMS ((char *));
969 static void do_mav_binops_1g PARAMS ((char *));
970 static void do_mav_binops_1h PARAMS ((char *));
971 static void do_mav_binops_1i PARAMS ((char *));
972 static void do_mav_binops_1j PARAMS ((char *));
973 static void do_mav_binops_1k PARAMS ((char *));
974 static void do_mav_binops_1l PARAMS ((char *));
975 static void do_mav_binops_1m PARAMS ((char *));
976 static void do_mav_binops_1n PARAMS ((char *));
977 static void do_mav_binops_1o PARAMS ((char *));
978 static void do_mav_binops_2a PARAMS ((char *));
979 static void do_mav_binops_2b PARAMS ((char *));
980 static void do_mav_binops_2c PARAMS ((char *));
981 static void do_mav_binops_3a PARAMS ((char *));
982 static void do_mav_binops_3b PARAMS ((char *));
983 static void do_mav_binops_3c PARAMS ((char *));
984 static void do_mav_binops_3d PARAMS ((char *));
985 static void do_mav_triple PARAMS ((char *, int, enum arm_reg_type,
986 enum arm_reg_type,
987 enum arm_reg_type));
988 static void do_mav_triple_4a PARAMS ((char *));
989 static void do_mav_triple_4b PARAMS ((char *));
990 static void do_mav_triple_5a PARAMS ((char *));
991 static void do_mav_triple_5b PARAMS ((char *));
992 static void do_mav_triple_5c PARAMS ((char *));
993 static void do_mav_triple_5d PARAMS ((char *));
994 static void do_mav_triple_5e PARAMS ((char *));
995 static void do_mav_triple_5f PARAMS ((char *));
996 static void do_mav_triple_5g PARAMS ((char *));
997 static void do_mav_triple_5h PARAMS ((char *));
998 static void do_mav_quad PARAMS ((char *, int, enum arm_reg_type,
999 enum arm_reg_type,
1000 enum arm_reg_type,
1001 enum arm_reg_type));
1002 static void do_mav_quad_6a PARAMS ((char *));
1003 static void do_mav_quad_6b PARAMS ((char *));
1004 static void do_mav_dspsc_1 PARAMS ((char *));
1005 static void do_mav_dspsc_2 PARAMS ((char *));
1006 static void do_mav_shift PARAMS ((char *, enum arm_reg_type,
1007 enum arm_reg_type));
1008 static void do_mav_shift_1 PARAMS ((char *));
1009 static void do_mav_shift_2 PARAMS ((char *));
1010 static void do_mav_ldst PARAMS ((char *, enum arm_reg_type));
1011 static void do_mav_ldst_1 PARAMS ((char *));
1012 static void do_mav_ldst_2 PARAMS ((char *));
1013 static void do_mav_ldst_3 PARAMS ((char *));
1014 static void do_mav_ldst_4 PARAMS ((char *));
1015
1016 static int mav_reg_required_here PARAMS ((char **, int,
1017 enum arm_reg_type));
1018 static int mav_parse_offset PARAMS ((char **, int *));
1019
1020 static void fix_new_arm PARAMS ((fragS *, int, short, expressionS *,
1021 int, int));
1022 static int arm_reg_parse PARAMS ((char **, struct hash_control *));
1023 static enum arm_reg_type arm_reg_parse_any PARAMS ((char *));
1024 static const struct asm_psr * arm_psr_parse PARAMS ((char **));
1025 static void symbol_locate PARAMS ((symbolS *, const char *, segT, valueT,
1026 fragS *));
1027 static int add_to_lit_pool PARAMS ((void));
1028 static unsigned validate_immediate PARAMS ((unsigned));
1029 static unsigned validate_immediate_twopart PARAMS ((unsigned int,
1030 unsigned int *));
1031 static int validate_offset_imm PARAMS ((unsigned int, int));
1032 static void opcode_select PARAMS ((int));
1033 static void end_of_line PARAMS ((char *));
1034 static int reg_required_here PARAMS ((char **, int));
1035 static int psr_required_here PARAMS ((char **));
1036 static int co_proc_number PARAMS ((char **));
1037 static int cp_opc_expr PARAMS ((char **, int, int));
1038 static int cp_reg_required_here PARAMS ((char **, int));
1039 static int fp_reg_required_here PARAMS ((char **, int));
1040 static int vfp_sp_reg_required_here PARAMS ((char **, enum vfp_sp_reg_pos));
1041 static int vfp_dp_reg_required_here PARAMS ((char **, enum vfp_dp_reg_pos));
1042 static void vfp_sp_ldstm PARAMS ((char *, enum vfp_ldstm_type));
1043 static void vfp_dp_ldstm PARAMS ((char *, enum vfp_ldstm_type));
1044 static long vfp_sp_reg_list PARAMS ((char **, enum vfp_sp_reg_pos));
1045 static long vfp_dp_reg_list PARAMS ((char **));
1046 static int vfp_psr_required_here PARAMS ((char **str));
1047 static const struct vfp_reg *vfp_psr_parse PARAMS ((char **str));
1048 static int cp_address_offset PARAMS ((char **));
1049 static int cp_address_required_here PARAMS ((char **, int));
1050 static int my_get_float_expression PARAMS ((char **));
1051 static int skip_past_comma PARAMS ((char **));
1052 static int walk_no_bignums PARAMS ((symbolS *));
1053 static int negate_data_op PARAMS ((unsigned long *, unsigned long));
1054 static int data_op2 PARAMS ((char **));
1055 static int fp_op2 PARAMS ((char **));
1056 static long reg_list PARAMS ((char **));
1057 static void thumb_load_store PARAMS ((char *, int, int));
1058 static int decode_shift PARAMS ((char **, int));
1059 static int ldst_extend PARAMS ((char **));
1060 static int ldst_extend_v4 PARAMS ((char **));
1061 static void thumb_add_sub PARAMS ((char *, int));
1062 static void insert_reg PARAMS ((const struct reg_entry *,
1063 struct hash_control *));
1064 static void thumb_shift PARAMS ((char *, int));
1065 static void thumb_mov_compare PARAMS ((char *, int));
1066 static void build_arm_ops_hsh PARAMS ((void));
1067 static void set_constant_flonums PARAMS ((void));
1068 static valueT md_chars_to_number PARAMS ((char *, int));
1069 static void build_reg_hsh PARAMS ((struct reg_map *));
1070 static void insert_reg_alias PARAMS ((char *, int, struct hash_control *));
1071 static int create_register_alias PARAMS ((char *, char *));
1072 static void output_inst PARAMS ((const char *));
1073 static int accum0_required_here PARAMS ((char **));
1074 static int ld_mode_required_here PARAMS ((char **));
1075 static void do_branch25 PARAMS ((char *));
1076 static symbolS * find_real_start PARAMS ((symbolS *));
1077 #ifdef OBJ_ELF
1078 static bfd_reloc_code_real_type arm_parse_reloc PARAMS ((void));
1079 #endif
1080
1081 static int wreg_required_here PARAMS ((char **, int, enum wreg_type));
1082 static void do_iwmmxt_byte_addr PARAMS ((char *));
1083 static void do_iwmmxt_tandc PARAMS ((char *));
1084 static void do_iwmmxt_tbcst PARAMS ((char *));
1085 static void do_iwmmxt_textrc PARAMS ((char *));
1086 static void do_iwmmxt_textrm PARAMS ((char *));
1087 static void do_iwmmxt_tinsr PARAMS ((char *));
1088 static void do_iwmmxt_tmcr PARAMS ((char *));
1089 static void do_iwmmxt_tmcrr PARAMS ((char *));
1090 static void do_iwmmxt_tmia PARAMS ((char *));
1091 static void do_iwmmxt_tmovmsk PARAMS ((char *));
1092 static void do_iwmmxt_tmrc PARAMS ((char *));
1093 static void do_iwmmxt_tmrrc PARAMS ((char *));
1094 static void do_iwmmxt_torc PARAMS ((char *));
1095 static void do_iwmmxt_waligni PARAMS ((char *));
1096 static void do_iwmmxt_wmov PARAMS ((char *));
1097 static void do_iwmmxt_word_addr PARAMS ((char *));
1098 static void do_iwmmxt_wrwr PARAMS ((char *));
1099 static void do_iwmmxt_wrwrwcg PARAMS ((char *));
1100 static void do_iwmmxt_wrwrwr PARAMS ((char *));
1101 static void do_iwmmxt_wshufh PARAMS ((char *));
1102 static void do_iwmmxt_wzero PARAMS ((char *));
1103 static int cp_byte_address_offset PARAMS ((char **));
1104 static int cp_byte_address_required_here PARAMS ((char **));
1105
1106 /* ARM instructions take 4bytes in the object file, Thumb instructions
1107 take 2: */
1108 #define INSN_SIZE 4
1109
1110 /* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
1111 #define MAV_MODE1 0x100c
1112
1113 /* "INSN<cond> X,Y" where X:bit16, Y:bit12. */
1114 #define MAV_MODE2 0x0c10
1115
1116 /* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
1117 #define MAV_MODE3 0x100c
1118
1119 /* "INSN<cond> X,Y,Z" where X:16, Y:0, Z:12. */
1120 #define MAV_MODE4 0x0c0010
1121
1122 /* "INSN<cond> X,Y,Z" where X:12, Y:16, Z:0. */
1123 #define MAV_MODE5 0x00100c
1124
1125 /* "INSN<cond> W,X,Y,Z" where W:5, X:12, Y:16, Z:0. */
1126 #define MAV_MODE6 0x00100c05
1127
1128 struct asm_opcode
1129 {
1130 /* Basic string to match. */
1131 const char * template;
1132
1133 /* Basic instruction code. */
1134 unsigned long value;
1135
1136 /* Offset into the template where the condition code (if any) will be.
1137 If zero, then the instruction is never conditional. */
1138 unsigned cond_offset;
1139
1140 /* Which architecture variant provides this instruction. */
1141 unsigned long variant;
1142
1143 /* Function to call to parse args. */
1144 void (* parms) PARAMS ((char *));
1145 };
1146
1147 static const struct asm_opcode insns[] =
1148 {
1149 /* Core ARM Instructions. */
1150 {"and", 0xe0000000, 3, ARM_EXT_V1, do_arit},
1151 {"ands", 0xe0100000, 3, ARM_EXT_V1, do_arit},
1152 {"eor", 0xe0200000, 3, ARM_EXT_V1, do_arit},
1153 {"eors", 0xe0300000, 3, ARM_EXT_V1, do_arit},
1154 {"sub", 0xe0400000, 3, ARM_EXT_V1, do_arit},
1155 {"subs", 0xe0500000, 3, ARM_EXT_V1, do_arit},
1156 {"rsb", 0xe0600000, 3, ARM_EXT_V1, do_arit},
1157 {"rsbs", 0xe0700000, 3, ARM_EXT_V1, do_arit},
1158 {"add", 0xe0800000, 3, ARM_EXT_V1, do_arit},
1159 {"adds", 0xe0900000, 3, ARM_EXT_V1, do_arit},
1160 {"adc", 0xe0a00000, 3, ARM_EXT_V1, do_arit},
1161 {"adcs", 0xe0b00000, 3, ARM_EXT_V1, do_arit},
1162 {"sbc", 0xe0c00000, 3, ARM_EXT_V1, do_arit},
1163 {"sbcs", 0xe0d00000, 3, ARM_EXT_V1, do_arit},
1164 {"rsc", 0xe0e00000, 3, ARM_EXT_V1, do_arit},
1165 {"rscs", 0xe0f00000, 3, ARM_EXT_V1, do_arit},
1166 {"orr", 0xe1800000, 3, ARM_EXT_V1, do_arit},
1167 {"orrs", 0xe1900000, 3, ARM_EXT_V1, do_arit},
1168 {"bic", 0xe1c00000, 3, ARM_EXT_V1, do_arit},
1169 {"bics", 0xe1d00000, 3, ARM_EXT_V1, do_arit},
1170
1171 {"tst", 0xe1100000, 3, ARM_EXT_V1, do_cmp},
1172 {"tsts", 0xe1100000, 3, ARM_EXT_V1, do_cmp},
1173 {"tstp", 0xe110f000, 3, ARM_EXT_V1, do_cmp},
1174 {"teq", 0xe1300000, 3, ARM_EXT_V1, do_cmp},
1175 {"teqs", 0xe1300000, 3, ARM_EXT_V1, do_cmp},
1176 {"teqp", 0xe130f000, 3, ARM_EXT_V1, do_cmp},
1177 {"cmp", 0xe1500000, 3, ARM_EXT_V1, do_cmp},
1178 {"cmps", 0xe1500000, 3, ARM_EXT_V1, do_cmp},
1179 {"cmpp", 0xe150f000, 3, ARM_EXT_V1, do_cmp},
1180 {"cmn", 0xe1700000, 3, ARM_EXT_V1, do_cmp},
1181 {"cmns", 0xe1700000, 3, ARM_EXT_V1, do_cmp},
1182 {"cmnp", 0xe170f000, 3, ARM_EXT_V1, do_cmp},
1183
1184 {"mov", 0xe1a00000, 3, ARM_EXT_V1, do_mov},
1185 {"movs", 0xe1b00000, 3, ARM_EXT_V1, do_mov},
1186 {"mvn", 0xe1e00000, 3, ARM_EXT_V1, do_mov},
1187 {"mvns", 0xe1f00000, 3, ARM_EXT_V1, do_mov},
1188
1189 {"ldr", 0xe4100000, 3, ARM_EXT_V1, do_ldst},
1190 {"ldrb", 0xe4500000, 3, ARM_EXT_V1, do_ldst},
1191 {"ldrt", 0xe4300000, 3, ARM_EXT_V1, do_ldstt},
1192 {"ldrbt", 0xe4700000, 3, ARM_EXT_V1, do_ldstt},
1193 {"str", 0xe4000000, 3, ARM_EXT_V1, do_ldst},
1194 {"strb", 0xe4400000, 3, ARM_EXT_V1, do_ldst},
1195 {"strt", 0xe4200000, 3, ARM_EXT_V1, do_ldstt},
1196 {"strbt", 0xe4600000, 3, ARM_EXT_V1, do_ldstt},
1197
1198 {"stmia", 0xe8800000, 3, ARM_EXT_V1, do_ldmstm},
1199 {"stmib", 0xe9800000, 3, ARM_EXT_V1, do_ldmstm},
1200 {"stmda", 0xe8000000, 3, ARM_EXT_V1, do_ldmstm},
1201 {"stmdb", 0xe9000000, 3, ARM_EXT_V1, do_ldmstm},
1202 {"stmfd", 0xe9000000, 3, ARM_EXT_V1, do_ldmstm},
1203 {"stmfa", 0xe9800000, 3, ARM_EXT_V1, do_ldmstm},
1204 {"stmea", 0xe8800000, 3, ARM_EXT_V1, do_ldmstm},
1205 {"stmed", 0xe8000000, 3, ARM_EXT_V1, do_ldmstm},
1206
1207 {"ldmia", 0xe8900000, 3, ARM_EXT_V1, do_ldmstm},
1208 {"ldmib", 0xe9900000, 3, ARM_EXT_V1, do_ldmstm},
1209 {"ldmda", 0xe8100000, 3, ARM_EXT_V1, do_ldmstm},
1210 {"ldmdb", 0xe9100000, 3, ARM_EXT_V1, do_ldmstm},
1211 {"ldmfd", 0xe8900000, 3, ARM_EXT_V1, do_ldmstm},
1212 {"ldmfa", 0xe8100000, 3, ARM_EXT_V1, do_ldmstm},
1213 {"ldmea", 0xe9100000, 3, ARM_EXT_V1, do_ldmstm},
1214 {"ldmed", 0xe9900000, 3, ARM_EXT_V1, do_ldmstm},
1215
1216 {"swi", 0xef000000, 3, ARM_EXT_V1, do_swi},
1217 #ifdef TE_WINCE
1218 /* XXX This is the wrong place to do this. Think multi-arch. */
1219 {"bl", 0xeb000000, 2, ARM_EXT_V1, do_branch},
1220 {"b", 0xea000000, 1, ARM_EXT_V1, do_branch},
1221 #else
1222 {"bl", 0xebfffffe, 2, ARM_EXT_V1, do_branch},
1223 {"b", 0xeafffffe, 1, ARM_EXT_V1, do_branch},
1224 #endif
1225
1226 /* Pseudo ops. */
1227 {"adr", 0xe28f0000, 3, ARM_EXT_V1, do_adr},
1228 {"adrl", 0xe28f0000, 3, ARM_EXT_V1, do_adrl},
1229 {"nop", 0xe1a00000, 3, ARM_EXT_V1, do_empty},
1230
1231 /* ARM 2 multiplies. */
1232 {"mul", 0xe0000090, 3, ARM_EXT_V2, do_mul},
1233 {"muls", 0xe0100090, 3, ARM_EXT_V2, do_mul},
1234 {"mla", 0xe0200090, 3, ARM_EXT_V2, do_mla},
1235 {"mlas", 0xe0300090, 3, ARM_EXT_V2, do_mla},
1236
1237 /* Generic coprocessor instructions. */
1238 {"cdp", 0xee000000, 3, ARM_EXT_V2, do_cdp},
1239 {"ldc", 0xec100000, 3, ARM_EXT_V2, do_lstc},
1240 {"ldcl", 0xec500000, 3, ARM_EXT_V2, do_lstc},
1241 {"stc", 0xec000000, 3, ARM_EXT_V2, do_lstc},
1242 {"stcl", 0xec400000, 3, ARM_EXT_V2, do_lstc},
1243 {"mcr", 0xee000010, 3, ARM_EXT_V2, do_co_reg},
1244 {"mrc", 0xee100010, 3, ARM_EXT_V2, do_co_reg},
1245
1246 /* ARM 3 - swp instructions. */
1247 {"swp", 0xe1000090, 3, ARM_EXT_V2S, do_swap},
1248 {"swpb", 0xe1400090, 3, ARM_EXT_V2S, do_swap},
1249
1250 /* ARM 6 Status register instructions. */
1251 {"mrs", 0xe10f0000, 3, ARM_EXT_V3, do_mrs},
1252 {"msr", 0xe120f000, 3, ARM_EXT_V3, do_msr},
1253 /* ScottB: our code uses 0xe128f000 for msr.
1254 NickC: but this is wrong because the bits 16 through 19 are
1255 handled by the PSR_xxx defines above. */
1256
1257 /* ARM 7M long multiplies. */
1258 {"smull", 0xe0c00090, 5, ARM_EXT_V3M, do_mull},
1259 {"smulls", 0xe0d00090, 5, ARM_EXT_V3M, do_mull},
1260 {"umull", 0xe0800090, 5, ARM_EXT_V3M, do_mull},
1261 {"umulls", 0xe0900090, 5, ARM_EXT_V3M, do_mull},
1262 {"smlal", 0xe0e00090, 5, ARM_EXT_V3M, do_mull},
1263 {"smlals", 0xe0f00090, 5, ARM_EXT_V3M, do_mull},
1264 {"umlal", 0xe0a00090, 5, ARM_EXT_V3M, do_mull},
1265 {"umlals", 0xe0b00090, 5, ARM_EXT_V3M, do_mull},
1266
1267 /* ARM Architecture 4. */
1268 {"ldrh", 0xe01000b0, 3, ARM_EXT_V4, do_ldstv4},
1269 {"ldrsh", 0xe01000f0, 3, ARM_EXT_V4, do_ldstv4},
1270 {"ldrsb", 0xe01000d0, 3, ARM_EXT_V4, do_ldstv4},
1271 {"strh", 0xe00000b0, 3, ARM_EXT_V4, do_ldstv4},
1272
1273 /* ARM Architecture 4T. */
1274 /* Note: bx (and blx) are required on V5, even if the processor does
1275 not support Thumb. */
1276 {"bx", 0xe12fff10, 2, ARM_EXT_V4T | ARM_EXT_V5, do_bx},
1277
1278 /* ARM Architecture 5T. */
1279 /* Note: blx has 2 variants, so the .value is set dynamically.
1280 Only one of the variants has conditional execution. */
1281 {"blx", 0xe0000000, 3, ARM_EXT_V5, do_blx},
1282 {"clz", 0xe16f0f10, 3, ARM_EXT_V5, do_clz},
1283 {"bkpt", 0xe1200070, 0, ARM_EXT_V5, do_bkpt},
1284 {"ldc2", 0xfc100000, 0, ARM_EXT_V5, do_lstc2},
1285 {"ldc2l", 0xfc500000, 0, ARM_EXT_V5, do_lstc2},
1286 {"stc2", 0xfc000000, 0, ARM_EXT_V5, do_lstc2},
1287 {"stc2l", 0xfc400000, 0, ARM_EXT_V5, do_lstc2},
1288 {"cdp2", 0xfe000000, 0, ARM_EXT_V5, do_cdp2},
1289 {"mcr2", 0xfe000010, 0, ARM_EXT_V5, do_co_reg2},
1290 {"mrc2", 0xfe100010, 0, ARM_EXT_V5, do_co_reg2},
1291
1292 /* ARM Architecture 5TExP. */
1293 {"smlabb", 0xe1000080, 6, ARM_EXT_V5ExP, do_smla},
1294 {"smlatb", 0xe10000a0, 6, ARM_EXT_V5ExP, do_smla},
1295 {"smlabt", 0xe10000c0, 6, ARM_EXT_V5ExP, do_smla},
1296 {"smlatt", 0xe10000e0, 6, ARM_EXT_V5ExP, do_smla},
1297
1298 {"smlawb", 0xe1200080, 6, ARM_EXT_V5ExP, do_smla},
1299 {"smlawt", 0xe12000c0, 6, ARM_EXT_V5ExP, do_smla},
1300
1301 {"smlalbb", 0xe1400080, 7, ARM_EXT_V5ExP, do_smlal},
1302 {"smlaltb", 0xe14000a0, 7, ARM_EXT_V5ExP, do_smlal},
1303 {"smlalbt", 0xe14000c0, 7, ARM_EXT_V5ExP, do_smlal},
1304 {"smlaltt", 0xe14000e0, 7, ARM_EXT_V5ExP, do_smlal},
1305
1306 {"smulbb", 0xe1600080, 6, ARM_EXT_V5ExP, do_smul},
1307 {"smultb", 0xe16000a0, 6, ARM_EXT_V5ExP, do_smul},
1308 {"smulbt", 0xe16000c0, 6, ARM_EXT_V5ExP, do_smul},
1309 {"smultt", 0xe16000e0, 6, ARM_EXT_V5ExP, do_smul},
1310
1311 {"smulwb", 0xe12000a0, 6, ARM_EXT_V5ExP, do_smul},
1312 {"smulwt", 0xe12000e0, 6, ARM_EXT_V5ExP, do_smul},
1313
1314 {"qadd", 0xe1000050, 4, ARM_EXT_V5ExP, do_qadd},
1315 {"qdadd", 0xe1400050, 5, ARM_EXT_V5ExP, do_qadd},
1316 {"qsub", 0xe1200050, 4, ARM_EXT_V5ExP, do_qadd},
1317 {"qdsub", 0xe1600050, 5, ARM_EXT_V5ExP, do_qadd},
1318
1319 /* ARM Architecture 5TE. */
1320 {"pld", 0xf450f000, 0, ARM_EXT_V5E, do_pld},
1321 {"ldrd", 0xe00000d0, 3, ARM_EXT_V5E, do_ldrd},
1322 {"strd", 0xe00000f0, 3, ARM_EXT_V5E, do_ldrd},
1323
1324 {"mcrr", 0xec400000, 4, ARM_EXT_V5E, do_co_reg2c},
1325 {"mrrc", 0xec500000, 4, ARM_EXT_V5E, do_co_reg2c},
1326
1327 /* ARM Architecture 5TEJ. */
1328 {"bxj", 0xe12fff20, 3, ARM_EXT_V5J, do_bxj},
1329
1330 /* ARM V6. */
1331 { "cps", 0xf1020000, 0, ARM_EXT_V6, do_cps},
1332 { "cpsie", 0xf1080000, 0, ARM_EXT_V6, do_cpsi},
1333 { "cpsid", 0xf10C0000, 0, ARM_EXT_V6, do_cpsi},
1334 { "ldrex", 0xe1900f9f, 5, ARM_EXT_V6, do_ldrex},
1335 { "mcrr2", 0xfc400000, 0, ARM_EXT_V6, do_co_reg2c},
1336 { "mrrc2", 0xfc500000, 0, ARM_EXT_V6, do_co_reg2c},
1337 { "pkhbt", 0xe6800010, 5, ARM_EXT_V6, do_pkhbt},
1338 { "pkhtb", 0xe6800050, 5, ARM_EXT_V6, do_pkhtb},
1339 { "qadd16", 0xe6200f10, 6, ARM_EXT_V6, do_qadd16},
1340 { "qadd8", 0xe6200f90, 5, ARM_EXT_V6, do_qadd16},
1341 { "qaddsubx", 0xe6200f30, 8, ARM_EXT_V6, do_qadd16},
1342 { "qsub16", 0xe6200f70, 6, ARM_EXT_V6, do_qadd16},
1343 { "qsub8", 0xe6200ff0, 5, ARM_EXT_V6, do_qadd16},
1344 { "qsubaddx", 0xe6200f50, 8, ARM_EXT_V6, do_qadd16},
1345 { "sadd16", 0xe6100f10, 6, ARM_EXT_V6, do_qadd16},
1346 { "sadd8", 0xe6100f90, 5, ARM_EXT_V6, do_qadd16},
1347 { "saddsubx", 0xe6100f30, 8, ARM_EXT_V6, do_qadd16},
1348 { "shadd16", 0xe6300f10, 7, ARM_EXT_V6, do_qadd16},
1349 { "shadd8", 0xe6300f90, 6, ARM_EXT_V6, do_qadd16},
1350 { "shaddsubx", 0xe6300f30, 9, ARM_EXT_V6, do_qadd16},
1351 { "shsub16", 0xe6300f70, 7, ARM_EXT_V6, do_qadd16},
1352 { "shsub8", 0xe6300ff0, 6, ARM_EXT_V6, do_qadd16},
1353 { "shsubaddx", 0xe6300f50, 9, ARM_EXT_V6, do_qadd16},
1354 { "ssub16", 0xe6100f70, 6, ARM_EXT_V6, do_qadd16},
1355 { "ssub8", 0xe6100ff0, 5, ARM_EXT_V6, do_qadd16},
1356 { "ssubaddx", 0xe6100f50, 8, ARM_EXT_V6, do_qadd16},
1357 { "uadd16", 0xe6500f10, 6, ARM_EXT_V6, do_qadd16},
1358 { "uadd8", 0xe6500f90, 5, ARM_EXT_V6, do_qadd16},
1359 { "uaddsubx", 0xe6500f30, 8, ARM_EXT_V6, do_qadd16},
1360 { "uhadd16", 0xe6700f10, 7, ARM_EXT_V6, do_qadd16},
1361 { "uhadd8", 0xe6700f90, 6, ARM_EXT_V6, do_qadd16},
1362 { "uhaddsubx", 0xe6700f30, 9, ARM_EXT_V6, do_qadd16},
1363 { "uhsub16", 0xe6700f70, 7, ARM_EXT_V6, do_qadd16},
1364 { "uhsub8", 0xe6700ff0, 6, ARM_EXT_V6, do_qadd16},
1365 { "uhsubaddx", 0xe6700f50, 9, ARM_EXT_V6, do_qadd16},
1366 { "uqadd16", 0xe6600f10, 7, ARM_EXT_V6, do_qadd16},
1367 { "uqadd8", 0xe6600f90, 6, ARM_EXT_V6, do_qadd16},
1368 { "uqaddsubx", 0xe6600f30, 9, ARM_EXT_V6, do_qadd16},
1369 { "uqsub16", 0xe6600f70, 7, ARM_EXT_V6, do_qadd16},
1370 { "uqsub8", 0xe6600ff0, 6, ARM_EXT_V6, do_qadd16},
1371 { "uqsubaddx", 0xe6600f50, 9, ARM_EXT_V6, do_qadd16},
1372 { "usub16", 0xe6500f70, 6, ARM_EXT_V6, do_qadd16},
1373 { "usub8", 0xe6500ff0, 5, ARM_EXT_V6, do_qadd16},
1374 { "usubaddx", 0xe6500f50, 8, ARM_EXT_V6, do_qadd16},
1375 { "rev", 0xe6bf0f30, 3, ARM_EXT_V6, do_rev},
1376 { "rev16", 0xe6bf0fb0, 5, ARM_EXT_V6, do_rev},
1377 { "revsh", 0xe6ff0fb0, 5, ARM_EXT_V6, do_rev},
1378 { "rfeia", 0xf8900a00, 0, ARM_EXT_V6, do_rfe},
1379 { "rfeib", 0xf9900a00, 0, ARM_EXT_V6, do_rfe},
1380 { "rfeda", 0xf8100a00, 0, ARM_EXT_V6, do_rfe},
1381 { "rfedb", 0xf9100a00, 0, ARM_EXT_V6, do_rfe},
1382 { "rfefd", 0xf8900a00, 0, ARM_EXT_V6, do_rfe},
1383 { "rfefa", 0xf9900a00, 0, ARM_EXT_V6, do_rfe},
1384 { "rfeea", 0xf8100a00, 0, ARM_EXT_V6, do_rfe},
1385 { "rfeed", 0xf9100a00, 0, ARM_EXT_V6, do_rfe},
1386 { "sxtah", 0xe6b00070, 5, ARM_EXT_V6, do_sxtah},
1387 { "sxtab16", 0xe6800070, 7, ARM_EXT_V6, do_sxtah},
1388 { "sxtab", 0xe6a00070, 5, ARM_EXT_V6, do_sxtah},
1389 { "sxth", 0xe6bf0070, 4, ARM_EXT_V6, do_sxth},
1390 { "sxtb16", 0xe68f0070, 6, ARM_EXT_V6, do_sxth},
1391 { "sxtb", 0xe6af0070, 4, ARM_EXT_V6, do_sxth},
1392 { "uxtah", 0xe6f00070, 5, ARM_EXT_V6, do_sxtah},
1393 { "uxtab16", 0xe6c00070, 7, ARM_EXT_V6, do_sxtah},
1394 { "uxtab", 0xe6e00070, 5, ARM_EXT_V6, do_sxtah},
1395 { "uxth", 0xe6ff0070, 4, ARM_EXT_V6, do_sxth},
1396 { "uxtb16", 0xe6cf0070, 6, ARM_EXT_V6, do_sxth},
1397 { "uxtb", 0xe6ef0070, 4, ARM_EXT_V6, do_sxth},
1398 { "sel", 0xe68000b0, 3, ARM_EXT_V6, do_qadd16},
1399 { "setend", 0xf1010000, 0, ARM_EXT_V6, do_setend},
1400 { "smlad", 0xe7000010, 5, ARM_EXT_V6, do_smlad},
1401 { "smladx", 0xe7000030, 6, ARM_EXT_V6, do_smlad},
1402 { "smlald", 0xe7400010, 6, ARM_EXT_V6, do_smlald},
1403 { "smlaldx", 0xe7400030, 7, ARM_EXT_V6, do_smlald},
1404 { "smlsd", 0xe7000050, 5, ARM_EXT_V6, do_smlad},
1405 { "smlsdx", 0xe7000070, 6, ARM_EXT_V6, do_smlad},
1406 { "smlsld", 0xe7400050, 6, ARM_EXT_V6, do_smlald},
1407 { "smlsldx", 0xe7400070, 7, ARM_EXT_V6, do_smlald},
1408 { "smmla", 0xe7500010, 5, ARM_EXT_V6, do_smlad},
1409 { "smmlar", 0xe7500030, 6, ARM_EXT_V6, do_smlad},
1410 { "smmls", 0xe75000d0, 5, ARM_EXT_V6, do_smlad},
1411 { "smmlsr", 0xe75000f0, 6, ARM_EXT_V6, do_smlad},
1412 { "smmul", 0xe750f010, 5, ARM_EXT_V6, do_smmul},
1413 { "smmulr", 0xe750f030, 6, ARM_EXT_V6, do_smmul},
1414 { "smuad", 0xe700f010, 5, ARM_EXT_V6, do_smmul},
1415 { "smuadx", 0xe700f030, 6, ARM_EXT_V6, do_smmul},
1416 { "smusd", 0xe700f050, 5, ARM_EXT_V6, do_smmul},
1417 { "smusdx", 0xe700f070, 6, ARM_EXT_V6, do_smmul},
1418 { "srsia", 0xf8cd0500, 0, ARM_EXT_V6, do_srs},
1419 { "srsib", 0xf9cd0500, 0, ARM_EXT_V6, do_srs},
1420 { "srsda", 0xf84d0500, 0, ARM_EXT_V6, do_srs},
1421 { "srsdb", 0xf94d0500, 0, ARM_EXT_V6, do_srs},
1422 { "ssat", 0xe6a00010, 4, ARM_EXT_V6, do_ssat},
1423 { "ssat16", 0xe6a00f30, 6, ARM_EXT_V6, do_ssat16},
1424 { "strex", 0xe1800f90, 5, ARM_EXT_V6, do_strex},
1425 { "umaal", 0xe0400090, 5, ARM_EXT_V6, do_umaal},
1426 { "usad8", 0xe780f010, 5, ARM_EXT_V6, do_smmul},
1427 { "usada8", 0xe7800010, 6, ARM_EXT_V6, do_smlad},
1428 { "usat", 0xe6e00010, 4, ARM_EXT_V6, do_usat},
1429 { "usat16", 0xe6e00f30, 6, ARM_EXT_V6, do_usat16},
1430
1431 /* Core FPA instruction set (V1). */
1432 {"wfs", 0xee200110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
1433 {"rfs", 0xee300110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
1434 {"wfc", 0xee400110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
1435 {"rfc", 0xee500110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
1436
1437 {"ldfs", 0xec100100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1438 {"ldfd", 0xec108100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1439 {"ldfe", 0xec500100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1440 {"ldfp", 0xec508100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1441
1442 {"stfs", 0xec000100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1443 {"stfd", 0xec008100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1444 {"stfe", 0xec400100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1445 {"stfp", 0xec408100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1446
1447 {"mvfs", 0xee008100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1448 {"mvfsp", 0xee008120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1449 {"mvfsm", 0xee008140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1450 {"mvfsz", 0xee008160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1451 {"mvfd", 0xee008180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1452 {"mvfdp", 0xee0081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1453 {"mvfdm", 0xee0081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1454 {"mvfdz", 0xee0081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1455 {"mvfe", 0xee088100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1456 {"mvfep", 0xee088120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1457 {"mvfem", 0xee088140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1458 {"mvfez", 0xee088160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1459
1460 {"mnfs", 0xee108100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1461 {"mnfsp", 0xee108120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1462 {"mnfsm", 0xee108140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1463 {"mnfsz", 0xee108160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1464 {"mnfd", 0xee108180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1465 {"mnfdp", 0xee1081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1466 {"mnfdm", 0xee1081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1467 {"mnfdz", 0xee1081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1468 {"mnfe", 0xee188100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1469 {"mnfep", 0xee188120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1470 {"mnfem", 0xee188140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1471 {"mnfez", 0xee188160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1472
1473 {"abss", 0xee208100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1474 {"abssp", 0xee208120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1475 {"abssm", 0xee208140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1476 {"abssz", 0xee208160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1477 {"absd", 0xee208180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1478 {"absdp", 0xee2081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1479 {"absdm", 0xee2081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1480 {"absdz", 0xee2081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1481 {"abse", 0xee288100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1482 {"absep", 0xee288120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1483 {"absem", 0xee288140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1484 {"absez", 0xee288160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1485
1486 {"rnds", 0xee308100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1487 {"rndsp", 0xee308120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1488 {"rndsm", 0xee308140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1489 {"rndsz", 0xee308160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1490 {"rndd", 0xee308180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1491 {"rnddp", 0xee3081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1492 {"rnddm", 0xee3081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1493 {"rnddz", 0xee3081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1494 {"rnde", 0xee388100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1495 {"rndep", 0xee388120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1496 {"rndem", 0xee388140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1497 {"rndez", 0xee388160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1498
1499 {"sqts", 0xee408100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1500 {"sqtsp", 0xee408120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1501 {"sqtsm", 0xee408140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1502 {"sqtsz", 0xee408160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1503 {"sqtd", 0xee408180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1504 {"sqtdp", 0xee4081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1505 {"sqtdm", 0xee4081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1506 {"sqtdz", 0xee4081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1507 {"sqte", 0xee488100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1508 {"sqtep", 0xee488120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1509 {"sqtem", 0xee488140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1510 {"sqtez", 0xee488160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1511
1512 {"logs", 0xee508100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1513 {"logsp", 0xee508120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1514 {"logsm", 0xee508140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1515 {"logsz", 0xee508160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1516 {"logd", 0xee508180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1517 {"logdp", 0xee5081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1518 {"logdm", 0xee5081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1519 {"logdz", 0xee5081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1520 {"loge", 0xee588100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1521 {"logep", 0xee588120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1522 {"logem", 0xee588140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1523 {"logez", 0xee588160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1524
1525 {"lgns", 0xee608100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1526 {"lgnsp", 0xee608120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1527 {"lgnsm", 0xee608140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1528 {"lgnsz", 0xee608160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1529 {"lgnd", 0xee608180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1530 {"lgndp", 0xee6081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1531 {"lgndm", 0xee6081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1532 {"lgndz", 0xee6081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1533 {"lgne", 0xee688100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1534 {"lgnep", 0xee688120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1535 {"lgnem", 0xee688140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1536 {"lgnez", 0xee688160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1537
1538 {"exps", 0xee708100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1539 {"expsp", 0xee708120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1540 {"expsm", 0xee708140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1541 {"expsz", 0xee708160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1542 {"expd", 0xee708180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1543 {"expdp", 0xee7081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1544 {"expdm", 0xee7081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1545 {"expdz", 0xee7081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1546 {"expe", 0xee788100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1547 {"expep", 0xee788120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1548 {"expem", 0xee788140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1549 {"expdz", 0xee788160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1550
1551 {"sins", 0xee808100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1552 {"sinsp", 0xee808120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1553 {"sinsm", 0xee808140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1554 {"sinsz", 0xee808160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1555 {"sind", 0xee808180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1556 {"sindp", 0xee8081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1557 {"sindm", 0xee8081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1558 {"sindz", 0xee8081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1559 {"sine", 0xee888100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1560 {"sinep", 0xee888120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1561 {"sinem", 0xee888140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1562 {"sinez", 0xee888160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1563
1564 {"coss", 0xee908100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1565 {"cossp", 0xee908120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1566 {"cossm", 0xee908140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1567 {"cossz", 0xee908160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1568 {"cosd", 0xee908180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1569 {"cosdp", 0xee9081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1570 {"cosdm", 0xee9081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1571 {"cosdz", 0xee9081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1572 {"cose", 0xee988100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1573 {"cosep", 0xee988120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1574 {"cosem", 0xee988140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1575 {"cosez", 0xee988160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1576
1577 {"tans", 0xeea08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1578 {"tansp", 0xeea08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1579 {"tansm", 0xeea08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1580 {"tansz", 0xeea08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1581 {"tand", 0xeea08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1582 {"tandp", 0xeea081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1583 {"tandm", 0xeea081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1584 {"tandz", 0xeea081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1585 {"tane", 0xeea88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1586 {"tanep", 0xeea88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1587 {"tanem", 0xeea88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1588 {"tanez", 0xeea88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1589
1590 {"asns", 0xeeb08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1591 {"asnsp", 0xeeb08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1592 {"asnsm", 0xeeb08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1593 {"asnsz", 0xeeb08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1594 {"asnd", 0xeeb08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1595 {"asndp", 0xeeb081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1596 {"asndm", 0xeeb081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1597 {"asndz", 0xeeb081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1598 {"asne", 0xeeb88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1599 {"asnep", 0xeeb88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1600 {"asnem", 0xeeb88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1601 {"asnez", 0xeeb88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1602
1603 {"acss", 0xeec08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1604 {"acssp", 0xeec08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1605 {"acssm", 0xeec08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1606 {"acssz", 0xeec08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1607 {"acsd", 0xeec08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1608 {"acsdp", 0xeec081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1609 {"acsdm", 0xeec081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1610 {"acsdz", 0xeec081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1611 {"acse", 0xeec88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1612 {"acsep", 0xeec88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1613 {"acsem", 0xeec88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1614 {"acsez", 0xeec88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1615
1616 {"atns", 0xeed08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1617 {"atnsp", 0xeed08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1618 {"atnsm", 0xeed08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1619 {"atnsz", 0xeed08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1620 {"atnd", 0xeed08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1621 {"atndp", 0xeed081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1622 {"atndm", 0xeed081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1623 {"atndz", 0xeed081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1624 {"atne", 0xeed88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1625 {"atnep", 0xeed88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1626 {"atnem", 0xeed88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1627 {"atnez", 0xeed88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1628
1629 {"urds", 0xeee08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1630 {"urdsp", 0xeee08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1631 {"urdsm", 0xeee08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1632 {"urdsz", 0xeee08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1633 {"urdd", 0xeee08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1634 {"urddp", 0xeee081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1635 {"urddm", 0xeee081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1636 {"urddz", 0xeee081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1637 {"urde", 0xeee88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1638 {"urdep", 0xeee88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1639 {"urdem", 0xeee88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1640 {"urdez", 0xeee88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1641
1642 {"nrms", 0xeef08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1643 {"nrmsp", 0xeef08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1644 {"nrmsm", 0xeef08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1645 {"nrmsz", 0xeef08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1646 {"nrmd", 0xeef08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1647 {"nrmdp", 0xeef081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1648 {"nrmdm", 0xeef081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1649 {"nrmdz", 0xeef081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1650 {"nrme", 0xeef88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1651 {"nrmep", 0xeef88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1652 {"nrmem", 0xeef88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1653 {"nrmez", 0xeef88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1654
1655 {"adfs", 0xee000100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1656 {"adfsp", 0xee000120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1657 {"adfsm", 0xee000140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1658 {"adfsz", 0xee000160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1659 {"adfd", 0xee000180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1660 {"adfdp", 0xee0001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1661 {"adfdm", 0xee0001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1662 {"adfdz", 0xee0001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1663 {"adfe", 0xee080100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1664 {"adfep", 0xee080120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1665 {"adfem", 0xee080140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1666 {"adfez", 0xee080160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1667
1668 {"sufs", 0xee200100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1669 {"sufsp", 0xee200120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1670 {"sufsm", 0xee200140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1671 {"sufsz", 0xee200160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1672 {"sufd", 0xee200180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1673 {"sufdp", 0xee2001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1674 {"sufdm", 0xee2001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1675 {"sufdz", 0xee2001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1676 {"sufe", 0xee280100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1677 {"sufep", 0xee280120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1678 {"sufem", 0xee280140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1679 {"sufez", 0xee280160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1680
1681 {"rsfs", 0xee300100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1682 {"rsfsp", 0xee300120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1683 {"rsfsm", 0xee300140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1684 {"rsfsz", 0xee300160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1685 {"rsfd", 0xee300180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1686 {"rsfdp", 0xee3001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1687 {"rsfdm", 0xee3001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1688 {"rsfdz", 0xee3001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1689 {"rsfe", 0xee380100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1690 {"rsfep", 0xee380120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1691 {"rsfem", 0xee380140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1692 {"rsfez", 0xee380160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1693
1694 {"mufs", 0xee100100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1695 {"mufsp", 0xee100120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1696 {"mufsm", 0xee100140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1697 {"mufsz", 0xee100160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1698 {"mufd", 0xee100180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1699 {"mufdp", 0xee1001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1700 {"mufdm", 0xee1001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1701 {"mufdz", 0xee1001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1702 {"mufe", 0xee180100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1703 {"mufep", 0xee180120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1704 {"mufem", 0xee180140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1705 {"mufez", 0xee180160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1706
1707 {"dvfs", 0xee400100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1708 {"dvfsp", 0xee400120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1709 {"dvfsm", 0xee400140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1710 {"dvfsz", 0xee400160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1711 {"dvfd", 0xee400180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1712 {"dvfdp", 0xee4001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1713 {"dvfdm", 0xee4001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1714 {"dvfdz", 0xee4001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1715 {"dvfe", 0xee480100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1716 {"dvfep", 0xee480120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1717 {"dvfem", 0xee480140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1718 {"dvfez", 0xee480160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1719
1720 {"rdfs", 0xee500100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1721 {"rdfsp", 0xee500120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1722 {"rdfsm", 0xee500140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1723 {"rdfsz", 0xee500160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1724 {"rdfd", 0xee500180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1725 {"rdfdp", 0xee5001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1726 {"rdfdm", 0xee5001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1727 {"rdfdz", 0xee5001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1728 {"rdfe", 0xee580100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1729 {"rdfep", 0xee580120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1730 {"rdfem", 0xee580140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1731 {"rdfez", 0xee580160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1732
1733 {"pows", 0xee600100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1734 {"powsp", 0xee600120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1735 {"powsm", 0xee600140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1736 {"powsz", 0xee600160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1737 {"powd", 0xee600180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1738 {"powdp", 0xee6001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1739 {"powdm", 0xee6001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1740 {"powdz", 0xee6001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1741 {"powe", 0xee680100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1742 {"powep", 0xee680120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1743 {"powem", 0xee680140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1744 {"powez", 0xee680160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1745
1746 {"rpws", 0xee700100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1747 {"rpwsp", 0xee700120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1748 {"rpwsm", 0xee700140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1749 {"rpwsz", 0xee700160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1750 {"rpwd", 0xee700180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1751 {"rpwdp", 0xee7001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1752 {"rpwdm", 0xee7001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1753 {"rpwdz", 0xee7001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1754 {"rpwe", 0xee780100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1755 {"rpwep", 0xee780120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1756 {"rpwem", 0xee780140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1757 {"rpwez", 0xee780160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1758
1759 {"rmfs", 0xee800100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1760 {"rmfsp", 0xee800120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1761 {"rmfsm", 0xee800140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1762 {"rmfsz", 0xee800160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1763 {"rmfd", 0xee800180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1764 {"rmfdp", 0xee8001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1765 {"rmfdm", 0xee8001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1766 {"rmfdz", 0xee8001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1767 {"rmfe", 0xee880100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1768 {"rmfep", 0xee880120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1769 {"rmfem", 0xee880140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1770 {"rmfez", 0xee880160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1771
1772 {"fmls", 0xee900100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1773 {"fmlsp", 0xee900120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1774 {"fmlsm", 0xee900140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1775 {"fmlsz", 0xee900160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1776 {"fmld", 0xee900180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1777 {"fmldp", 0xee9001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1778 {"fmldm", 0xee9001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1779 {"fmldz", 0xee9001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1780 {"fmle", 0xee980100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1781 {"fmlep", 0xee980120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1782 {"fmlem", 0xee980140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1783 {"fmlez", 0xee980160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1784
1785 {"fdvs", 0xeea00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1786 {"fdvsp", 0xeea00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1787 {"fdvsm", 0xeea00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1788 {"fdvsz", 0xeea00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1789 {"fdvd", 0xeea00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1790 {"fdvdp", 0xeea001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1791 {"fdvdm", 0xeea001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1792 {"fdvdz", 0xeea001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1793 {"fdve", 0xeea80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1794 {"fdvep", 0xeea80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1795 {"fdvem", 0xeea80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1796 {"fdvez", 0xeea80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1797
1798 {"frds", 0xeeb00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1799 {"frdsp", 0xeeb00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1800 {"frdsm", 0xeeb00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1801 {"frdsz", 0xeeb00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1802 {"frdd", 0xeeb00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1803 {"frddp", 0xeeb001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1804 {"frddm", 0xeeb001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1805 {"frddz", 0xeeb001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1806 {"frde", 0xeeb80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1807 {"frdep", 0xeeb80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1808 {"frdem", 0xeeb80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1809 {"frdez", 0xeeb80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1810
1811 {"pols", 0xeec00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1812 {"polsp", 0xeec00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1813 {"polsm", 0xeec00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1814 {"polsz", 0xeec00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1815 {"pold", 0xeec00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1816 {"poldp", 0xeec001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1817 {"poldm", 0xeec001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1818 {"poldz", 0xeec001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1819 {"pole", 0xeec80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1820 {"polep", 0xeec80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1821 {"polem", 0xeec80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1822 {"polez", 0xeec80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1823
1824 {"cmf", 0xee90f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
1825 {"cmfe", 0xeed0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
1826 {"cnf", 0xeeb0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
1827 {"cnfe", 0xeef0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
1828 /* The FPA10 data sheet suggests that the 'E' of cmfe/cnfe should
1829 not be an optional suffix, but part of the instruction. To be
1830 compatible, we accept either. */
1831 {"cmfe", 0xeed0f110, 4, FPU_FPA_EXT_V1, do_fpa_cmp},
1832 {"cnfe", 0xeef0f110, 4, FPU_FPA_EXT_V1, do_fpa_cmp},
1833
1834 {"flts", 0xee000110, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1835 {"fltsp", 0xee000130, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1836 {"fltsm", 0xee000150, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1837 {"fltsz", 0xee000170, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1838 {"fltd", 0xee000190, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1839 {"fltdp", 0xee0001b0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1840 {"fltdm", 0xee0001d0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1841 {"fltdz", 0xee0001f0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1842 {"flte", 0xee080110, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1843 {"fltep", 0xee080130, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1844 {"fltem", 0xee080150, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1845 {"fltez", 0xee080170, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1846
1847 /* The implementation of the FIX instruction is broken on some
1848 assemblers, in that it accepts a precision specifier as well as a
1849 rounding specifier, despite the fact that this is meaningless.
1850 To be more compatible, we accept it as well, though of course it
1851 does not set any bits. */
1852 {"fix", 0xee100110, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1853 {"fixp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1854 {"fixm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1855 {"fixz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1856 {"fixsp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1857 {"fixsm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1858 {"fixsz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1859 {"fixdp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1860 {"fixdm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1861 {"fixdz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1862 {"fixep", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1863 {"fixem", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1864 {"fixez", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1865
1866 /* Instructions that were new with the real FPA, call them V2. */
1867 {"lfm", 0xec100200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1868 {"lfmfd", 0xec900200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1869 {"lfmea", 0xed100200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1870 {"sfm", 0xec000200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1871 {"sfmfd", 0xed000200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1872 {"sfmea", 0xec800200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1873
1874 /* VFP V1xD (single precision). */
1875 /* Moves and type conversions. */
1876 {"fcpys", 0xeeb00a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1877 {"fmrs", 0xee100a10, 4, FPU_VFP_EXT_V1xD, do_vfp_reg_from_sp},
1878 {"fmsr", 0xee000a10, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_from_reg},
1879 {"fmstat", 0xeef1fa10, 6, FPU_VFP_EXT_V1xD, do_empty},
1880 {"fsitos", 0xeeb80ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1881 {"fuitos", 0xeeb80a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1882 {"ftosis", 0xeebd0a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1883 {"ftosizs", 0xeebd0ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1884 {"ftouis", 0xeebc0a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1885 {"ftouizs", 0xeebc0ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1886 {"fmrx", 0xeef00a10, 4, FPU_VFP_EXT_V1xD, do_vfp_reg_from_ctrl},
1887 {"fmxr", 0xeee00a10, 4, FPU_VFP_EXT_V1xD, do_vfp_ctrl_from_reg},
1888
1889 /* Memory operations. */
1890 {"flds", 0xed100a00, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_ldst},
1891 {"fsts", 0xed000a00, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_ldst},
1892 {"fldmias", 0xec900a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
1893 {"fldmfds", 0xec900a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
1894 {"fldmdbs", 0xed300a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
1895 {"fldmeas", 0xed300a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
1896 {"fldmiax", 0xec900b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
1897 {"fldmfdx", 0xec900b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
1898 {"fldmdbx", 0xed300b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
1899 {"fldmeax", 0xed300b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
1900 {"fstmias", 0xec800a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
1901 {"fstmeas", 0xec800a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
1902 {"fstmdbs", 0xed200a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
1903 {"fstmfds", 0xed200a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
1904 {"fstmiax", 0xec800b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
1905 {"fstmeax", 0xec800b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
1906 {"fstmdbx", 0xed200b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
1907 {"fstmfdx", 0xed200b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
1908
1909 /* Monadic operations. */
1910 {"fabss", 0xeeb00ac0, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1911 {"fnegs", 0xeeb10a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1912 {"fsqrts", 0xeeb10ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1913
1914 /* Dyadic operations. */
1915 {"fadds", 0xee300a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1916 {"fsubs", 0xee300a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1917 {"fmuls", 0xee200a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1918 {"fdivs", 0xee800a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1919 {"fmacs", 0xee000a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1920 {"fmscs", 0xee100a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1921 {"fnmuls", 0xee200a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1922 {"fnmacs", 0xee000a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1923 {"fnmscs", 0xee100a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1924
1925 /* Comparisons. */
1926 {"fcmps", 0xeeb40a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1927 {"fcmpzs", 0xeeb50a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_compare_z},
1928 {"fcmpes", 0xeeb40ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1929 {"fcmpezs", 0xeeb50ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_compare_z},
1930
1931 /* VFP V1 (Double precision). */
1932 /* Moves and type conversions. */
1933 {"fcpyd", 0xeeb00b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1934 {"fcvtds", 0xeeb70ac0, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
1935 {"fcvtsd", 0xeeb70bc0, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
1936 {"fmdhr", 0xee200b10, 5, FPU_VFP_EXT_V1, do_vfp_dp_from_reg},
1937 {"fmdlr", 0xee000b10, 5, FPU_VFP_EXT_V1, do_vfp_dp_from_reg},
1938 {"fmrdh", 0xee300b10, 5, FPU_VFP_EXT_V1, do_vfp_reg_from_dp},
1939 {"fmrdl", 0xee100b10, 5, FPU_VFP_EXT_V1, do_vfp_reg_from_dp},
1940 {"fsitod", 0xeeb80bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
1941 {"fuitod", 0xeeb80b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
1942 {"ftosid", 0xeebd0b40, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
1943 {"ftosizd", 0xeebd0bc0, 7, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
1944 {"ftouid", 0xeebc0b40, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
1945 {"ftouizd", 0xeebc0bc0, 7, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
1946
1947 /* Memory operations. */
1948 {"fldd", 0xed100b00, 4, FPU_VFP_EXT_V1, do_vfp_dp_ldst},
1949 {"fstd", 0xed000b00, 4, FPU_VFP_EXT_V1, do_vfp_dp_ldst},
1950 {"fldmiad", 0xec900b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
1951 {"fldmfdd", 0xec900b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
1952 {"fldmdbd", 0xed300b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
1953 {"fldmead", 0xed300b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
1954 {"fstmiad", 0xec800b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
1955 {"fstmead", 0xec800b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
1956 {"fstmdbd", 0xed200b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
1957 {"fstmfdd", 0xed200b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
1958
1959 /* Monadic operations. */
1960 {"fabsd", 0xeeb00bc0, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1961 {"fnegd", 0xeeb10b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1962 {"fsqrtd", 0xeeb10bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1963
1964 /* Dyadic operations. */
1965 {"faddd", 0xee300b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1966 {"fsubd", 0xee300b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1967 {"fmuld", 0xee200b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1968 {"fdivd", 0xee800b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1969 {"fmacd", 0xee000b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1970 {"fmscd", 0xee100b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1971 {"fnmuld", 0xee200b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1972 {"fnmacd", 0xee000b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1973 {"fnmscd", 0xee100b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1974
1975 /* Comparisons. */
1976 {"fcmpd", 0xeeb40b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1977 {"fcmpzd", 0xeeb50b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_compare_z},
1978 {"fcmped", 0xeeb40bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1979 {"fcmpezd", 0xeeb50bc0, 7, FPU_VFP_EXT_V1, do_vfp_dp_compare_z},
1980
1981 /* VFP V2. */
1982 {"fmsrr", 0xec400a10, 5, FPU_VFP_EXT_V2, do_vfp_sp2_from_reg2},
1983 {"fmrrs", 0xec500a10, 5, FPU_VFP_EXT_V2, do_vfp_reg2_from_sp2},
1984 {"fmdrr", 0xec400b10, 5, FPU_VFP_EXT_V2, do_vfp_dp_from_reg2},
1985 {"fmrrd", 0xec500b10, 5, FPU_VFP_EXT_V2, do_vfp_reg2_from_dp},
1986
1987 /* Intel XScale extensions to ARM V5 ISA. (All use CP0). */
1988 {"mia", 0xee200010, 3, ARM_CEXT_XSCALE, do_xsc_mia},
1989 {"miaph", 0xee280010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
1990 {"miabb", 0xee2c0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
1991 {"miabt", 0xee2d0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
1992 {"miatb", 0xee2e0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
1993 {"miatt", 0xee2f0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
1994 {"mar", 0xec400000, 3, ARM_CEXT_XSCALE, do_xsc_mar},
1995 {"mra", 0xec500000, 3, ARM_CEXT_XSCALE, do_xsc_mra},
1996
1997 /* Intel Wireless MMX technology instructions. */
1998 {"tandcb", 0xee130130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
1999 {"tandch", 0xee530130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
2000 {"tandcw", 0xee930130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
2001 {"tbcstb", 0xee400010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
2002 {"tbcsth", 0xee400050, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
2003 {"tbcstw", 0xee400090, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
2004 {"textrcb", 0xee130170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
2005 {"textrch", 0xee530170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
2006 {"textrcw", 0xee930170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
2007 {"textrmub", 0xee100070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
2008 {"textrmuh", 0xee500070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
2009 {"textrmuw", 0xee900070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
2010 {"textrmsb", 0xee100078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
2011 {"textrmsh", 0xee500078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
2012 {"textrmsw", 0xee900078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
2013 {"tinsrb", 0xee600010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
2014 {"tinsrh", 0xee600050, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
2015 {"tinsrw", 0xee600090, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
2016 {"tmcr", 0xee000110, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmcr},
2017 {"tmcrr", 0xec400000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_tmcrr},
2018 {"tmia", 0xee200010, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
2019 {"tmiaph", 0xee280010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
2020 {"tmiabb", 0xee2c0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
2021 {"tmiabt", 0xee2d0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
2022 {"tmiatb", 0xee2e0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
2023 {"tmiatt", 0xee2f0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
2024 {"tmovmskb", 0xee100030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
2025 {"tmovmskh", 0xee500030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
2026 {"tmovmskw", 0xee900030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
2027 {"tmrc", 0xee100110, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmrc},
2028 {"tmrrc", 0xec500000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_tmrrc},
2029 {"torcb", 0xee130150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
2030 {"torch", 0xee530150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
2031 {"torcw", 0xee930150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
2032 {"waccb", 0xee0001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2033 {"wacch", 0xee4001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2034 {"waccw", 0xee8001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2035 {"waddbss", 0xee300180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2036 {"waddb", 0xee000180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2037 {"waddbus", 0xee100180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2038 {"waddhss", 0xee700180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2039 {"waddh", 0xee400180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2040 {"waddhus", 0xee500180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2041 {"waddwss", 0xeeb00180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2042 {"waddw", 0xee800180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2043 {"waddwus", 0xee900180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2044 {"waligni", 0xee000020, 7, ARM_CEXT_IWMMXT, do_iwmmxt_waligni},
2045 {"walignr0", 0xee800020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2046 {"walignr1", 0xee900020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2047 {"walignr2", 0xeea00020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2048 {"walignr3", 0xeeb00020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2049 {"wand", 0xee200000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2050 {"wandn", 0xee300000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2051 {"wavg2b", 0xee800000, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2052 {"wavg2br", 0xee900000, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2053 {"wavg2h", 0xeec00000, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2054 {"wavg2hr", 0xeed00000, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2055 {"wcmpeqb", 0xee000060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2056 {"wcmpeqh", 0xee400060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2057 {"wcmpeqw", 0xee800060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2058 {"wcmpgtub", 0xee100060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2059 {"wcmpgtuh", 0xee500060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2060 {"wcmpgtuw", 0xee900060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2061 {"wcmpgtsb", 0xee300060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2062 {"wcmpgtsh", 0xee700060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2063 {"wcmpgtsw", 0xeeb00060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2064 {"wldrb", 0xec100000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
2065 {"wldrh", 0xec100100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
2066 {"wldrw", 0xec100200, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
2067 {"wldrd", 0xec100300, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
2068 {"wmacs", 0xee600100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2069 {"wmacsz", 0xee700100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2070 {"wmacu", 0xee400100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2071 {"wmacuz", 0xee500100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2072 {"wmadds", 0xeea00100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2073 {"wmaddu", 0xee800100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2074 {"wmaxsb", 0xee200160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2075 {"wmaxsh", 0xee600160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2076 {"wmaxsw", 0xeea00160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2077 {"wmaxub", 0xee000160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2078 {"wmaxuh", 0xee400160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2079 {"wmaxuw", 0xee800160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2080 {"wminsb", 0xee300160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2081 {"wminsh", 0xee700160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2082 {"wminsw", 0xeeb00160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2083 {"wminub", 0xee100160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2084 {"wminuh", 0xee500160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2085 {"wminuw", 0xee900160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2086 {"wmov", 0xee000000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wmov},
2087 {"wmulsm", 0xee300100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2088 {"wmulsl", 0xee200100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2089 {"wmulum", 0xee100100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2090 {"wmulul", 0xee000100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2091 {"wor", 0xee000000, 3, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2092 {"wpackhss", 0xee700080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2093 {"wpackhus", 0xee500080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2094 {"wpackwss", 0xeeb00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2095 {"wpackwus", 0xee900080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2096 {"wpackdss", 0xeef00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2097 {"wpackdus", 0xeed00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2098 {"wrorh", 0xee700040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2099 {"wrorhg", 0xee700148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2100 {"wrorw", 0xeeb00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2101 {"wrorwg", 0xeeb00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2102 {"wrord", 0xeef00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2103 {"wrordg", 0xeef00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2104 {"wsadb", 0xee000120, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2105 {"wsadbz", 0xee100120, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2106 {"wsadh", 0xee400120, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2107 {"wsadhz", 0xee500120, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2108 {"wshufh", 0xee0001e0, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wshufh},
2109 {"wsllh", 0xee500040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2110 {"wsllhg", 0xee500148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2111 {"wsllw", 0xee900040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2112 {"wsllwg", 0xee900148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2113 {"wslld", 0xeed00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2114 {"wslldg", 0xeed00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2115 {"wsrah", 0xee400040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2116 {"wsrahg", 0xee400148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2117 {"wsraw", 0xee800040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2118 {"wsrawg", 0xee800148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2119 {"wsrad", 0xeec00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2120 {"wsradg", 0xeec00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2121 {"wsrlh", 0xee600040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2122 {"wsrlhg", 0xee600148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2123 {"wsrlw", 0xeea00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2124 {"wsrlwg", 0xeea00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2125 {"wsrld", 0xeee00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2126 {"wsrldg", 0xeee00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2127 {"wstrb", 0xec000000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
2128 {"wstrh", 0xec000100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
2129 {"wstrw", 0xec000200, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
2130 {"wstrd", 0xec000300, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
2131 {"wsubbss", 0xee3001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2132 {"wsubb", 0xee0001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2133 {"wsubbus", 0xee1001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2134 {"wsubhss", 0xee7001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2135 {"wsubh", 0xee4001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2136 {"wsubhus", 0xee5001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2137 {"wsubwss", 0xeeb001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2138 {"wsubw", 0xee8001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2139 {"wsubwus", 0xee9001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2140 {"wunpckehub", 0xee0000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2141 {"wunpckehuh", 0xee4000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2142 {"wunpckehuw", 0xee8000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2143 {"wunpckehsb", 0xee2000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2144 {"wunpckehsh", 0xee6000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2145 {"wunpckehsw", 0xeea000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2146 {"wunpckihb", 0xee1000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2147 {"wunpckihh", 0xee5000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2148 {"wunpckihw", 0xee9000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2149 {"wunpckelub", 0xee0000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2150 {"wunpckeluh", 0xee4000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2151 {"wunpckeluw", 0xee8000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2152 {"wunpckelsb", 0xee2000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2153 {"wunpckelsh", 0xee6000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2154 {"wunpckelsw", 0xeea000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2155 {"wunpckilb", 0xee1000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2156 {"wunpckilh", 0xee5000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2157 {"wunpckilw", 0xee9000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2158 {"wxor", 0xee100000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2159 {"wzero", 0xee300000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wzero},
2160
2161 /* Cirrus Maverick instructions. */
2162 {"cfldrs", 0xec100400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_1},
2163 {"cfldrd", 0xec500400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_2},
2164 {"cfldr32", 0xec100500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_3},
2165 {"cfldr64", 0xec500500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_4},
2166 {"cfstrs", 0xec000400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_1},
2167 {"cfstrd", 0xec400400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_2},
2168 {"cfstr32", 0xec000500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_3},
2169 {"cfstr64", 0xec400500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_4},
2170 {"cfmvsr", 0xee000450, 6, ARM_CEXT_MAVERICK, do_mav_binops_2a},
2171 {"cfmvrs", 0xee100450, 6, ARM_CEXT_MAVERICK, do_mav_binops_1a},
2172 {"cfmvdlr", 0xee000410, 7, ARM_CEXT_MAVERICK, do_mav_binops_2b},
2173 {"cfmvrdl", 0xee100410, 7, ARM_CEXT_MAVERICK, do_mav_binops_1b},
2174 {"cfmvdhr", 0xee000430, 7, ARM_CEXT_MAVERICK, do_mav_binops_2b},
2175 {"cfmvrdh", 0xee100430, 7, ARM_CEXT_MAVERICK, do_mav_binops_1b},
2176 {"cfmv64lr", 0xee000510, 8, ARM_CEXT_MAVERICK, do_mav_binops_2c},
2177 {"cfmvr64l", 0xee100510, 8, ARM_CEXT_MAVERICK, do_mav_binops_1c},
2178 {"cfmv64hr", 0xee000530, 8, ARM_CEXT_MAVERICK, do_mav_binops_2c},
2179 {"cfmvr64h", 0xee100530, 8, ARM_CEXT_MAVERICK, do_mav_binops_1c},
2180 {"cfmval32", 0xee200440, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
2181 {"cfmv32al", 0xee100440, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
2182 {"cfmvam32", 0xee200460, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
2183 {"cfmv32am", 0xee100460, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
2184 {"cfmvah32", 0xee200480, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
2185 {"cfmv32ah", 0xee100480, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
2186 {"cfmva32", 0xee2004a0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3a},
2187 {"cfmv32a", 0xee1004a0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3b},
2188 {"cfmva64", 0xee2004c0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3c},
2189 {"cfmv64a", 0xee1004c0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3d},
2190 {"cfmvsc32", 0xee2004e0, 8, ARM_CEXT_MAVERICK, do_mav_dspsc_1},
2191 {"cfmv32sc", 0xee1004e0, 8, ARM_CEXT_MAVERICK, do_mav_dspsc_2},
2192 {"cfcpys", 0xee000400, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
2193 {"cfcpyd", 0xee000420, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
2194 {"cfcvtsd", 0xee000460, 7, ARM_CEXT_MAVERICK, do_mav_binops_1f},
2195 {"cfcvtds", 0xee000440, 7, ARM_CEXT_MAVERICK, do_mav_binops_1g},
2196 {"cfcvt32s", 0xee000480, 8, ARM_CEXT_MAVERICK, do_mav_binops_1h},
2197 {"cfcvt32d", 0xee0004a0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1i},
2198 {"cfcvt64s", 0xee0004c0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1j},
2199 {"cfcvt64d", 0xee0004e0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1k},
2200 {"cfcvts32", 0xee100580, 8, ARM_CEXT_MAVERICK, do_mav_binops_1l},
2201 {"cfcvtd32", 0xee1005a0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1m},
2202 {"cftruncs32", 0xee1005c0, 10, ARM_CEXT_MAVERICK, do_mav_binops_1l},
2203 {"cftruncd32", 0xee1005e0, 10, ARM_CEXT_MAVERICK, do_mav_binops_1m},
2204 {"cfrshl32", 0xee000550, 8, ARM_CEXT_MAVERICK, do_mav_triple_4a},
2205 {"cfrshl64", 0xee000570, 8, ARM_CEXT_MAVERICK, do_mav_triple_4b},
2206 {"cfsh32", 0xee000500, 6, ARM_CEXT_MAVERICK, do_mav_shift_1},
2207 {"cfsh64", 0xee200500, 6, ARM_CEXT_MAVERICK, do_mav_shift_2},
2208 {"cfcmps", 0xee100490, 6, ARM_CEXT_MAVERICK, do_mav_triple_5a},
2209 {"cfcmpd", 0xee1004b0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5b},
2210 {"cfcmp32", 0xee100590, 7, ARM_CEXT_MAVERICK, do_mav_triple_5c},
2211 {"cfcmp64", 0xee1005b0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5d},
2212 {"cfabss", 0xee300400, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
2213 {"cfabsd", 0xee300420, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
2214 {"cfnegs", 0xee300440, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
2215 {"cfnegd", 0xee300460, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
2216 {"cfadds", 0xee300480, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
2217 {"cfaddd", 0xee3004a0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
2218 {"cfsubs", 0xee3004c0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
2219 {"cfsubd", 0xee3004e0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
2220 {"cfmuls", 0xee100400, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
2221 {"cfmuld", 0xee100420, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
2222 {"cfabs32", 0xee300500, 7, ARM_CEXT_MAVERICK, do_mav_binops_1n},
2223 {"cfabs64", 0xee300520, 7, ARM_CEXT_MAVERICK, do_mav_binops_1o},
2224 {"cfneg32", 0xee300540, 7, ARM_CEXT_MAVERICK, do_mav_binops_1n},
2225 {"cfneg64", 0xee300560, 7, ARM_CEXT_MAVERICK, do_mav_binops_1o},
2226 {"cfadd32", 0xee300580, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
2227 {"cfadd64", 0xee3005a0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
2228 {"cfsub32", 0xee3005c0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
2229 {"cfsub64", 0xee3005e0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
2230 {"cfmul32", 0xee100500, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
2231 {"cfmul64", 0xee100520, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
2232 {"cfmac32", 0xee100540, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
2233 {"cfmsc32", 0xee100560, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
2234 {"cfmadd32", 0xee000600, 8, ARM_CEXT_MAVERICK, do_mav_quad_6a},
2235 {"cfmsub32", 0xee100600, 8, ARM_CEXT_MAVERICK, do_mav_quad_6a},
2236 {"cfmadda32", 0xee200600, 9, ARM_CEXT_MAVERICK, do_mav_quad_6b},
2237 {"cfmsuba32", 0xee300600, 9, ARM_CEXT_MAVERICK, do_mav_quad_6b},
2238 };
2239
2240 /* Defines for various bits that we will want to toggle. */
2241 #define INST_IMMEDIATE 0x02000000
2242 #define OFFSET_REG 0x02000000
2243 #define HWOFFSET_IMM 0x00400000
2244 #define SHIFT_BY_REG 0x00000010
2245 #define PRE_INDEX 0x01000000
2246 #define INDEX_UP 0x00800000
2247 #define WRITE_BACK 0x00200000
2248 #define LDM_TYPE_2_OR_3 0x00400000
2249
2250 #define LITERAL_MASK 0xf000f000
2251 #define OPCODE_MASK 0xfe1fffff
2252 #define V4_STR_BIT 0x00000020
2253
2254 #define DATA_OP_SHIFT 21
2255
2256 /* Codes to distinguish the arithmetic instructions. */
2257 #define OPCODE_AND 0
2258 #define OPCODE_EOR 1
2259 #define OPCODE_SUB 2
2260 #define OPCODE_RSB 3
2261 #define OPCODE_ADD 4
2262 #define OPCODE_ADC 5
2263 #define OPCODE_SBC 6
2264 #define OPCODE_RSC 7
2265 #define OPCODE_TST 8
2266 #define OPCODE_TEQ 9
2267 #define OPCODE_CMP 10
2268 #define OPCODE_CMN 11
2269 #define OPCODE_ORR 12
2270 #define OPCODE_MOV 13
2271 #define OPCODE_BIC 14
2272 #define OPCODE_MVN 15
2273
2274 /* Thumb v1 (ARMv4T). */
2275 static void do_t_nop PARAMS ((char *));
2276 static void do_t_arit PARAMS ((char *));
2277 static void do_t_add PARAMS ((char *));
2278 static void do_t_asr PARAMS ((char *));
2279 static void do_t_branch9 PARAMS ((char *));
2280 static void do_t_branch12 PARAMS ((char *));
2281 static void do_t_branch23 PARAMS ((char *));
2282 static void do_t_bx PARAMS ((char *));
2283 static void do_t_compare PARAMS ((char *));
2284 static void do_t_ldmstm PARAMS ((char *));
2285 static void do_t_ldr PARAMS ((char *));
2286 static void do_t_ldrb PARAMS ((char *));
2287 static void do_t_ldrh PARAMS ((char *));
2288 static void do_t_lds PARAMS ((char *));
2289 static void do_t_lsl PARAMS ((char *));
2290 static void do_t_lsr PARAMS ((char *));
2291 static void do_t_mov PARAMS ((char *));
2292 static void do_t_push_pop PARAMS ((char *));
2293 static void do_t_str PARAMS ((char *));
2294 static void do_t_strb PARAMS ((char *));
2295 static void do_t_strh PARAMS ((char *));
2296 static void do_t_sub PARAMS ((char *));
2297 static void do_t_swi PARAMS ((char *));
2298 static void do_t_adr PARAMS ((char *));
2299
2300 /* Thumb v2 (ARMv5T). */
2301 static void do_t_blx PARAMS ((char *));
2302 static void do_t_bkpt PARAMS ((char *));
2303
2304 /* ARM V6. */
2305 static void do_t_cps PARAMS ((char *));
2306 static void do_t_cpy PARAMS ((char *));
2307 static void do_t_setend PARAMS ((char *));;
2308
2309 #define T_OPCODE_MUL 0x4340
2310 #define T_OPCODE_TST 0x4200
2311 #define T_OPCODE_CMN 0x42c0
2312 #define T_OPCODE_NEG 0x4240
2313 #define T_OPCODE_MVN 0x43c0
2314
2315 #define T_OPCODE_ADD_R3 0x1800
2316 #define T_OPCODE_SUB_R3 0x1a00
2317 #define T_OPCODE_ADD_HI 0x4400
2318 #define T_OPCODE_ADD_ST 0xb000
2319 #define T_OPCODE_SUB_ST 0xb080
2320 #define T_OPCODE_ADD_SP 0xa800
2321 #define T_OPCODE_ADD_PC 0xa000
2322 #define T_OPCODE_ADD_I8 0x3000
2323 #define T_OPCODE_SUB_I8 0x3800
2324 #define T_OPCODE_ADD_I3 0x1c00
2325 #define T_OPCODE_SUB_I3 0x1e00
2326
2327 #define T_OPCODE_ASR_R 0x4100
2328 #define T_OPCODE_LSL_R 0x4080
2329 #define T_OPCODE_LSR_R 0x40c0
2330 #define T_OPCODE_ASR_I 0x1000
2331 #define T_OPCODE_LSL_I 0x0000
2332 #define T_OPCODE_LSR_I 0x0800
2333
2334 #define T_OPCODE_MOV_I8 0x2000
2335 #define T_OPCODE_CMP_I8 0x2800
2336 #define T_OPCODE_CMP_LR 0x4280
2337 #define T_OPCODE_MOV_HR 0x4600
2338 #define T_OPCODE_CMP_HR 0x4500
2339
2340 #define T_OPCODE_LDR_PC 0x4800
2341 #define T_OPCODE_LDR_SP 0x9800
2342 #define T_OPCODE_STR_SP 0x9000
2343 #define T_OPCODE_LDR_IW 0x6800
2344 #define T_OPCODE_STR_IW 0x6000
2345 #define T_OPCODE_LDR_IH 0x8800
2346 #define T_OPCODE_STR_IH 0x8000
2347 #define T_OPCODE_LDR_IB 0x7800
2348 #define T_OPCODE_STR_IB 0x7000
2349 #define T_OPCODE_LDR_RW 0x5800
2350 #define T_OPCODE_STR_RW 0x5000
2351 #define T_OPCODE_LDR_RH 0x5a00
2352 #define T_OPCODE_STR_RH 0x5200
2353 #define T_OPCODE_LDR_RB 0x5c00
2354 #define T_OPCODE_STR_RB 0x5400
2355
2356 #define T_OPCODE_PUSH 0xb400
2357 #define T_OPCODE_POP 0xbc00
2358
2359 #define T_OPCODE_BRANCH 0xe7fe
2360
2361 static int thumb_reg PARAMS ((char ** str, int hi_lo));
2362
2363 #define THUMB_SIZE 2 /* Size of thumb instruction. */
2364 #define THUMB_REG_LO 0x1
2365 #define THUMB_REG_HI 0x2
2366 #define THUMB_REG_ANY 0x3
2367
2368 #define THUMB_H1 0x0080
2369 #define THUMB_H2 0x0040
2370
2371 #define THUMB_ASR 0
2372 #define THUMB_LSL 1
2373 #define THUMB_LSR 2
2374
2375 #define THUMB_MOVE 0
2376 #define THUMB_COMPARE 1
2377 #define THUMB_CPY 2
2378
2379 #define THUMB_LOAD 0
2380 #define THUMB_STORE 1
2381
2382 #define THUMB_PP_PC_LR 0x0100
2383
2384 /* These three are used for immediate shifts, do not alter. */
2385 #define THUMB_WORD 2
2386 #define THUMB_HALFWORD 1
2387 #define THUMB_BYTE 0
2388
2389 struct thumb_opcode
2390 {
2391 /* Basic string to match. */
2392 const char * template;
2393
2394 /* Basic instruction code. */
2395 unsigned long value;
2396
2397 int size;
2398
2399 /* Which CPU variants this exists for. */
2400 unsigned long variant;
2401
2402 /* Function to call to parse args. */
2403 void (* parms) PARAMS ((char *));
2404 };
2405
2406 static const struct thumb_opcode tinsns[] =
2407 {
2408 /* Thumb v1 (ARMv4T). */
2409 {"adc", 0x4140, 2, ARM_EXT_V4T, do_t_arit},
2410 {"add", 0x0000, 2, ARM_EXT_V4T, do_t_add},
2411 {"and", 0x4000, 2, ARM_EXT_V4T, do_t_arit},
2412 {"asr", 0x0000, 2, ARM_EXT_V4T, do_t_asr},
2413 {"b", T_OPCODE_BRANCH, 2, ARM_EXT_V4T, do_t_branch12},
2414 {"beq", 0xd0fe, 2, ARM_EXT_V4T, do_t_branch9},
2415 {"bne", 0xd1fe, 2, ARM_EXT_V4T, do_t_branch9},
2416 {"bcs", 0xd2fe, 2, ARM_EXT_V4T, do_t_branch9},
2417 {"bhs", 0xd2fe, 2, ARM_EXT_V4T, do_t_branch9},
2418 {"bcc", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
2419 {"bul", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
2420 {"blo", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
2421 {"bmi", 0xd4fe, 2, ARM_EXT_V4T, do_t_branch9},
2422 {"bpl", 0xd5fe, 2, ARM_EXT_V4T, do_t_branch9},
2423 {"bvs", 0xd6fe, 2, ARM_EXT_V4T, do_t_branch9},
2424 {"bvc", 0xd7fe, 2, ARM_EXT_V4T, do_t_branch9},
2425 {"bhi", 0xd8fe, 2, ARM_EXT_V4T, do_t_branch9},
2426 {"bls", 0xd9fe, 2, ARM_EXT_V4T, do_t_branch9},
2427 {"bge", 0xdafe, 2, ARM_EXT_V4T, do_t_branch9},
2428 {"blt", 0xdbfe, 2, ARM_EXT_V4T, do_t_branch9},
2429 {"bgt", 0xdcfe, 2, ARM_EXT_V4T, do_t_branch9},
2430 {"ble", 0xddfe, 2, ARM_EXT_V4T, do_t_branch9},
2431 {"bal", 0xdefe, 2, ARM_EXT_V4T, do_t_branch9},
2432 {"bic", 0x4380, 2, ARM_EXT_V4T, do_t_arit},
2433 {"bl", 0xf7fffffe, 4, ARM_EXT_V4T, do_t_branch23},
2434 {"bx", 0x4700, 2, ARM_EXT_V4T, do_t_bx},
2435 {"cmn", T_OPCODE_CMN, 2, ARM_EXT_V4T, do_t_arit},
2436 {"cmp", 0x0000, 2, ARM_EXT_V4T, do_t_compare},
2437 {"eor", 0x4040, 2, ARM_EXT_V4T, do_t_arit},
2438 {"ldmia", 0xc800, 2, ARM_EXT_V4T, do_t_ldmstm},
2439 {"ldr", 0x0000, 2, ARM_EXT_V4T, do_t_ldr},
2440 {"ldrb", 0x0000, 2, ARM_EXT_V4T, do_t_ldrb},
2441 {"ldrh", 0x0000, 2, ARM_EXT_V4T, do_t_ldrh},
2442 {"ldrsb", 0x5600, 2, ARM_EXT_V4T, do_t_lds},
2443 {"ldrsh", 0x5e00, 2, ARM_EXT_V4T, do_t_lds},
2444 {"ldsb", 0x5600, 2, ARM_EXT_V4T, do_t_lds},
2445 {"ldsh", 0x5e00, 2, ARM_EXT_V4T, do_t_lds},
2446 {"lsl", 0x0000, 2, ARM_EXT_V4T, do_t_lsl},
2447 {"lsr", 0x0000, 2, ARM_EXT_V4T, do_t_lsr},
2448 {"mov", 0x0000, 2, ARM_EXT_V4T, do_t_mov},
2449 {"mul", T_OPCODE_MUL, 2, ARM_EXT_V4T, do_t_arit},
2450 {"mvn", T_OPCODE_MVN, 2, ARM_EXT_V4T, do_t_arit},
2451 {"neg", T_OPCODE_NEG, 2, ARM_EXT_V4T, do_t_arit},
2452 {"orr", 0x4300, 2, ARM_EXT_V4T, do_t_arit},
2453 {"pop", 0xbc00, 2, ARM_EXT_V4T, do_t_push_pop},
2454 {"push", 0xb400, 2, ARM_EXT_V4T, do_t_push_pop},
2455 {"ror", 0x41c0, 2, ARM_EXT_V4T, do_t_arit},
2456 {"sbc", 0x4180, 2, ARM_EXT_V4T, do_t_arit},
2457 {"stmia", 0xc000, 2, ARM_EXT_V4T, do_t_ldmstm},
2458 {"str", 0x0000, 2, ARM_EXT_V4T, do_t_str},
2459 {"strb", 0x0000, 2, ARM_EXT_V4T, do_t_strb},
2460 {"strh", 0x0000, 2, ARM_EXT_V4T, do_t_strh},
2461 {"swi", 0xdf00, 2, ARM_EXT_V4T, do_t_swi},
2462 {"sub", 0x0000, 2, ARM_EXT_V4T, do_t_sub},
2463 {"tst", T_OPCODE_TST, 2, ARM_EXT_V4T, do_t_arit},
2464 /* Pseudo ops: */
2465 {"adr", 0x0000, 2, ARM_EXT_V4T, do_t_adr},
2466 {"nop", 0x46C0, 2, ARM_EXT_V4T, do_t_nop}, /* mov r8,r8 */
2467 /* Thumb v2 (ARMv5T). */
2468 {"blx", 0, 0, ARM_EXT_V5T, do_t_blx},
2469 {"bkpt", 0xbe00, 2, ARM_EXT_V5T, do_t_bkpt},
2470
2471 /* ARM V6. */
2472 {"cpsie", 0xb660, 2, ARM_EXT_V6, do_t_cps},
2473 {"cpsid", 0xb670, 2, ARM_EXT_V6, do_t_cps},
2474 {"cpy", 0x4600, 2, ARM_EXT_V6, do_t_cpy},
2475 {"rev", 0xba00, 2, ARM_EXT_V6, do_t_arit},
2476 {"rev16", 0xba40, 2, ARM_EXT_V6, do_t_arit},
2477 {"revsh", 0xbac0, 2, ARM_EXT_V6, do_t_arit},
2478 {"setend", 0xb650, 2, ARM_EXT_V6, do_t_setend},
2479 {"sxth", 0xb200, 2, ARM_EXT_V6, do_t_arit},
2480 {"sxtb", 0xb240, 2, ARM_EXT_V6, do_t_arit},
2481 {"uxth", 0xb280, 2, ARM_EXT_V6, do_t_arit},
2482 {"uxtb", 0xb2c0, 2, ARM_EXT_V6, do_t_arit},
2483 };
2484
2485 #define BAD_ARGS _("bad arguments to instruction")
2486 #define BAD_PC _("r15 not allowed here")
2487 #define BAD_COND _("instruction is not conditional")
2488 #define ERR_NO_ACCUM _("acc0 expected")
2489
2490 static struct hash_control * arm_ops_hsh = NULL;
2491 static struct hash_control * arm_tops_hsh = NULL;
2492 static struct hash_control * arm_cond_hsh = NULL;
2493 static struct hash_control * arm_shift_hsh = NULL;
2494 static struct hash_control * arm_psr_hsh = NULL;
2495
2496 /* This table describes all the machine specific pseudo-ops the assembler
2497 has to support. The fields are:
2498 pseudo-op name without dot
2499 function to call to execute this pseudo-op
2500 Integer arg to pass to the function. */
2501
2502 static void s_req PARAMS ((int));
2503 static void s_unreq PARAMS ((int));
2504 static void s_align PARAMS ((int));
2505 static void s_bss PARAMS ((int));
2506 static void s_even PARAMS ((int));
2507 static void s_ltorg PARAMS ((int));
2508 static void s_arm PARAMS ((int));
2509 static void s_thumb PARAMS ((int));
2510 static void s_code PARAMS ((int));
2511 static void s_force_thumb PARAMS ((int));
2512 static void s_thumb_func PARAMS ((int));
2513 static void s_thumb_set PARAMS ((int));
2514 #ifdef OBJ_ELF
2515 static void s_arm_elf_cons PARAMS ((int));
2516 #endif
2517
2518 static int my_get_expression PARAMS ((expressionS *, char **));
2519
2520 const pseudo_typeS md_pseudo_table[] =
2521 {
2522 /* Never called because '.req' does not start a line. */
2523 { "req", s_req, 0 },
2524 { "unreq", s_unreq, 0 },
2525 { "bss", s_bss, 0 },
2526 { "align", s_align, 0 },
2527 { "arm", s_arm, 0 },
2528 { "thumb", s_thumb, 0 },
2529 { "code", s_code, 0 },
2530 { "force_thumb", s_force_thumb, 0 },
2531 { "thumb_func", s_thumb_func, 0 },
2532 { "thumb_set", s_thumb_set, 0 },
2533 { "even", s_even, 0 },
2534 { "ltorg", s_ltorg, 0 },
2535 { "pool", s_ltorg, 0 },
2536 #ifdef OBJ_ELF
2537 { "word", s_arm_elf_cons, 4 },
2538 { "long", s_arm_elf_cons, 4 },
2539 #else
2540 { "word", cons, 4},
2541 #endif
2542 { "extend", float_cons, 'x' },
2543 { "ldouble", float_cons, 'x' },
2544 { "packed", float_cons, 'p' },
2545 { 0, 0, 0 }
2546 };
2547
2548 /* Other internal functions. */
2549 static int arm_parse_extension PARAMS ((char *, int *));
2550 static int arm_parse_cpu PARAMS ((char *));
2551 static int arm_parse_arch PARAMS ((char *));
2552 static int arm_parse_fpu PARAMS ((char *));
2553 static int arm_parse_float_abi PARAMS ((char *));
2554 #if 0 /* Suppressed - for now. */
2555 #if defined OBJ_COFF || defined OBJ_ELF
2556 static void arm_add_note PARAMS ((const char *, const char *, unsigned int));
2557 #endif
2558 #endif
2559
2560 /* Stuff needed to resolve the label ambiguity
2561 As:
2562 ...
2563 label: <insn>
2564 may differ from:
2565 ...
2566 label:
2567 <insn>
2568 */
2569
2570 symbolS * last_label_seen;
2571 static int label_is_thumb_function_name = FALSE;
2572
2573 /* Literal Pool stuff. */
2574
2575 #define MAX_LITERAL_POOL_SIZE 1024
2576
2577 /* Literal pool structure. Held on a per-section
2578 and per-sub-section basis. */
2579 typedef struct literal_pool
2580 {
2581 expressionS literals [MAX_LITERAL_POOL_SIZE];
2582 unsigned int next_free_entry;
2583 unsigned int id;
2584 symbolS * symbol;
2585 segT section;
2586 subsegT sub_section;
2587 struct literal_pool * next;
2588 } literal_pool;
2589
2590 /* Pointer to a linked list of literal pools. */
2591 literal_pool * list_of_pools = NULL;
2592
2593 static literal_pool * find_literal_pool PARAMS ((void));
2594 static literal_pool * find_or_make_literal_pool PARAMS ((void));
2595
2596 static literal_pool *
find_literal_pool()2597 find_literal_pool ()
2598 {
2599 literal_pool * pool;
2600
2601 for (pool = list_of_pools; pool != NULL; pool = pool->next)
2602 {
2603 if (pool->section == now_seg
2604 && pool->sub_section == now_subseg)
2605 break;
2606 }
2607
2608 return pool;
2609 }
2610
2611 static literal_pool *
find_or_make_literal_pool()2612 find_or_make_literal_pool ()
2613 {
2614 /* Next literal pool ID number. */
2615 static unsigned int latest_pool_num = 1;
2616 literal_pool * pool;
2617
2618 pool = find_literal_pool ();
2619
2620 if (pool == NULL)
2621 {
2622 /* Create a new pool. */
2623 pool = (literal_pool *) xmalloc (sizeof (* pool));
2624 if (! pool)
2625 return NULL;
2626
2627 pool->next_free_entry = 0;
2628 pool->section = now_seg;
2629 pool->sub_section = now_subseg;
2630 pool->next = list_of_pools;
2631 pool->symbol = NULL;
2632
2633 /* Add it to the list. */
2634 list_of_pools = pool;
2635 }
2636
2637 /* New pools, and emptied pools, will have a NULL symbol. */
2638 if (pool->symbol == NULL)
2639 {
2640 pool->symbol = symbol_create (FAKE_LABEL_NAME, undefined_section,
2641 (valueT) 0, &zero_address_frag);
2642 pool->id = latest_pool_num ++;
2643 }
2644
2645 /* Done. */
2646 return pool;
2647 }
2648
2649 /* Add the literal in the global 'inst'
2650 structure to the relevent literal pool. */
2651 static int
add_to_lit_pool()2652 add_to_lit_pool ()
2653 {
2654 literal_pool * pool;
2655 unsigned int entry;
2656
2657 pool = find_or_make_literal_pool ();
2658
2659 /* Check if this literal value is already in the pool. */
2660 for (entry = 0; entry < pool->next_free_entry; entry ++)
2661 {
2662 if ((pool->literals[entry].X_op == inst.reloc.exp.X_op)
2663 && (inst.reloc.exp.X_op == O_constant)
2664 && (pool->literals[entry].X_add_number
2665 == inst.reloc.exp.X_add_number)
2666 && (pool->literals[entry].X_unsigned
2667 == inst.reloc.exp.X_unsigned))
2668 break;
2669
2670 if ((pool->literals[entry].X_op == inst.reloc.exp.X_op)
2671 && (inst.reloc.exp.X_op == O_symbol)
2672 && (pool->literals[entry].X_add_number
2673 == inst.reloc.exp.X_add_number)
2674 && (pool->literals[entry].X_add_symbol
2675 == inst.reloc.exp.X_add_symbol)
2676 && (pool->literals[entry].X_op_symbol
2677 == inst.reloc.exp.X_op_symbol))
2678 break;
2679 }
2680
2681 /* Do we need to create a new entry? */
2682 if (entry == pool->next_free_entry)
2683 {
2684 if (entry >= MAX_LITERAL_POOL_SIZE)
2685 {
2686 inst.error = _("literal pool overflow");
2687 return FAIL;
2688 }
2689
2690 pool->literals[entry] = inst.reloc.exp;
2691 pool->next_free_entry += 1;
2692 }
2693
2694 inst.reloc.exp.X_op = O_symbol;
2695 inst.reloc.exp.X_add_number = ((int) entry) * 4 - 8;
2696 inst.reloc.exp.X_add_symbol = pool->symbol;
2697
2698 return SUCCESS;
2699 }
2700
2701 /* Can't use symbol_new here, so have to create a symbol and then at
2702 a later date assign it a value. Thats what these functions do. */
2703
2704 static void
symbol_locate(symbolP,name,segment,valu,frag)2705 symbol_locate (symbolP, name, segment, valu, frag)
2706 symbolS * symbolP;
2707 const char * name; /* It is copied, the caller can modify. */
2708 segT segment; /* Segment identifier (SEG_<something>). */
2709 valueT valu; /* Symbol value. */
2710 fragS * frag; /* Associated fragment. */
2711 {
2712 unsigned int name_length;
2713 char * preserved_copy_of_name;
2714
2715 name_length = strlen (name) + 1; /* +1 for \0. */
2716 obstack_grow (¬es, name, name_length);
2717 preserved_copy_of_name = obstack_finish (¬es);
2718 #ifdef STRIP_UNDERSCORE
2719 if (preserved_copy_of_name[0] == '_')
2720 preserved_copy_of_name++;
2721 #endif
2722
2723 #ifdef tc_canonicalize_symbol_name
2724 preserved_copy_of_name =
2725 tc_canonicalize_symbol_name (preserved_copy_of_name);
2726 #endif
2727
2728 S_SET_NAME (symbolP, preserved_copy_of_name);
2729
2730 S_SET_SEGMENT (symbolP, segment);
2731 S_SET_VALUE (symbolP, valu);
2732 symbol_clear_list_pointers (symbolP);
2733
2734 symbol_set_frag (symbolP, frag);
2735
2736 /* Link to end of symbol chain. */
2737 {
2738 extern int symbol_table_frozen;
2739 if (symbol_table_frozen)
2740 abort ();
2741 }
2742
2743 symbol_append (symbolP, symbol_lastP, & symbol_rootP, & symbol_lastP);
2744
2745 obj_symbol_new_hook (symbolP);
2746
2747 #ifdef tc_symbol_new_hook
2748 tc_symbol_new_hook (symbolP);
2749 #endif
2750
2751 #ifdef DEBUG_SYMS
2752 verify_symbol_chain (symbol_rootP, symbol_lastP);
2753 #endif /* DEBUG_SYMS */
2754 }
2755
2756 /* Check that an immediate is valid.
2757 If so, convert it to the right format. */
2758
2759 static unsigned int
validate_immediate(val)2760 validate_immediate (val)
2761 unsigned int val;
2762 {
2763 unsigned int a;
2764 unsigned int i;
2765
2766 #define rotate_left(v, n) (v << n | v >> (32 - n))
2767
2768 for (i = 0; i < 32; i += 2)
2769 if ((a = rotate_left (val, i)) <= 0xff)
2770 return a | (i << 7); /* 12-bit pack: [shift-cnt,const]. */
2771
2772 return FAIL;
2773 }
2774
2775 /* Check to see if an immediate can be computed as two separate immediate
2776 values, added together. We already know that this value cannot be
2777 computed by just one ARM instruction. */
2778
2779 static unsigned int
validate_immediate_twopart(val,highpart)2780 validate_immediate_twopart (val, highpart)
2781 unsigned int val;
2782 unsigned int * highpart;
2783 {
2784 unsigned int a;
2785 unsigned int i;
2786
2787 for (i = 0; i < 32; i += 2)
2788 if (((a = rotate_left (val, i)) & 0xff) != 0)
2789 {
2790 if (a & 0xff00)
2791 {
2792 if (a & ~ 0xffff)
2793 continue;
2794 * highpart = (a >> 8) | ((i + 24) << 7);
2795 }
2796 else if (a & 0xff0000)
2797 {
2798 if (a & 0xff000000)
2799 continue;
2800 * highpart = (a >> 16) | ((i + 16) << 7);
2801 }
2802 else
2803 {
2804 assert (a & 0xff000000);
2805 * highpart = (a >> 24) | ((i + 8) << 7);
2806 }
2807
2808 return (a & 0xff) | (i << 7);
2809 }
2810
2811 return FAIL;
2812 }
2813
2814 static int
validate_offset_imm(val,hwse)2815 validate_offset_imm (val, hwse)
2816 unsigned int val;
2817 int hwse;
2818 {
2819 if ((hwse && val > 255) || val > 4095)
2820 return FAIL;
2821 return val;
2822 }
2823
2824
2825 #ifdef OBJ_ELF
2826 /* This code is to handle mapping symbols as defined in the ARM ELF spec.
2827 (This text is taken from version B-02 of the spec):
2828
2829 4.4.7 Mapping and tagging symbols
2830
2831 A section of an ARM ELF file can contain a mixture of ARM code,
2832 Thumb code, and data. There are inline transitions between code
2833 and data at literal pool boundaries. There can also be inline
2834 transitions between ARM code and Thumb code, for example in
2835 ARM-Thumb inter-working veneers. Linkers, machine-level
2836 debuggers, profiling tools, and disassembly tools need to map
2837 images accurately. For example, setting an ARM breakpoint on a
2838 Thumb location, or in a literal pool, can crash the program
2839 being debugged, ruining the debugging session.
2840
2841 ARM ELF entities are mapped (see section 4.4.7.1 below) and
2842 tagged (see section 4.4.7.2 below) using local symbols (with
2843 binding STB_LOCAL). To assist consumers, mapping and tagging
2844 symbols should be collated first in the symbol table, before
2845 other symbols with binding STB_LOCAL.
2846
2847 To allow properly collated mapping and tagging symbols to be
2848 skipped by consumers that have no interest in them, the first
2849 such symbol should have the name $m and its st_value field equal
2850 to the total number of mapping and tagging symbols (including
2851 the $m) in the symbol table.
2852
2853 4.4.7.1 Mapping symbols
2854
2855 $a Labels the first byte of a sequence of ARM instructions.
2856 Its type is STT_FUNC.
2857
2858 $d Labels the first byte of a sequence of data items.
2859 Its type is STT_OBJECT.
2860
2861 $t Labels the first byte of a sequence of Thumb instructions.
2862 Its type is STT_FUNC.
2863
2864 This list of mapping symbols may be extended in the future.
2865
2866 Section-relative mapping symbols
2867
2868 Mapping symbols defined in a section define a sequence of
2869 half-open address intervals that cover the address range of the
2870 section. Each interval starts at the address defined by a
2871 mapping symbol, and continues up to, but not including, the
2872 address defined by the next (in address order) mapping symbol or
2873 the end of the section. A corollary is that there must be a
2874 mapping symbol defined at the beginning of each section.
2875 Consumers can ignore the size of a section-relative mapping
2876 symbol. Producers can set it to 0.
2877
2878 Absolute mapping symbols
2879
2880 Because of the need to crystallize a Thumb address with the
2881 Thumb-bit set, absolute symbol of type STT_FUNC (symbols of type
2882 STT_FUNC defined in section SHN_ABS) need to be mapped with $a
2883 or $t.
2884
2885 The extent of a mapping symbol defined in SHN_ABS is [st_value,
2886 st_value + st_size), or [st_value, st_value + 1) if st_size = 0,
2887 where [x, y) denotes the half-open address range from x,
2888 inclusive, to y, exclusive.
2889
2890 In the absence of a mapping symbol, a consumer can interpret a
2891 function symbol with an odd value as the Thumb code address
2892 obtained by clearing the least significant bit of the
2893 value. This interpretation is deprecated, and it may not work in
2894 the future.
2895
2896 Note - the Tagging symbols ($b, $f, $p $m) have been dropped from
2897 the EABI (which is still under development), so they are not
2898 implemented here. */
2899
2900 static enum mstate mapstate = MAP_UNDEFINED;
2901
2902 static void
mapping_state(enum mstate state)2903 mapping_state (enum mstate state)
2904 {
2905 symbolS * symbolP;
2906 const char * symname;
2907 int type;
2908
2909 if (mapstate == state)
2910 /* The mapping symbol has already been emitted.
2911 There is nothing else to do. */
2912 return;
2913
2914 mapstate = state;
2915
2916 switch (state)
2917 {
2918 case MAP_DATA:
2919 symname = "$d";
2920 type = BSF_OBJECT;
2921 break;
2922 case MAP_ARM:
2923 symname = "$a";
2924 type = BSF_FUNCTION;
2925 break;
2926 case MAP_THUMB:
2927 symname = "$t";
2928 type = BSF_FUNCTION;
2929 break;
2930 case MAP_UNDEFINED:
2931 return;
2932 default:
2933 abort ();
2934 }
2935
2936 seg_info (now_seg)->tc_segment_info_data = state;
2937
2938 symbolP = symbol_new (symname, now_seg, (valueT) frag_now_fix (), frag_now);
2939 symbol_table_insert (symbolP);
2940 symbol_get_bfdsym (symbolP)->flags |= type | BSF_LOCAL;
2941
2942 switch (state)
2943 {
2944 case MAP_ARM:
2945 THUMB_SET_FUNC (symbolP, 0);
2946 ARM_SET_THUMB (symbolP, 0);
2947 ARM_SET_INTERWORK (symbolP, support_interwork);
2948 break;
2949
2950 case MAP_THUMB:
2951 THUMB_SET_FUNC (symbolP, 1);
2952 ARM_SET_THUMB (symbolP, 1);
2953 ARM_SET_INTERWORK (symbolP, support_interwork);
2954 break;
2955
2956 case MAP_DATA:
2957 default:
2958 return;
2959 }
2960 }
2961
2962 /* When we change sections we need to issue a new mapping symbol. */
2963
2964 void
arm_elf_change_section(void)2965 arm_elf_change_section (void)
2966 {
2967 flagword flags;
2968
2969 if (!SEG_NORMAL (now_seg))
2970 return;
2971
2972 flags = bfd_get_section_flags (stdoutput, now_seg);
2973
2974 /* We can ignore sections that only contain debug info. */
2975 if ((flags & SEC_ALLOC) == 0)
2976 return;
2977
2978 mapstate = seg_info (now_seg)->tc_segment_info_data;
2979 }
2980 #else
2981 #define mapping_state(a)
2982 #endif /* OBJ_ELF */
2983
2984
2985 static void
s_req(a)2986 s_req (a)
2987 int a ATTRIBUTE_UNUSED;
2988 {
2989 as_bad (_("invalid syntax for .req directive"));
2990 }
2991
2992 /* The .unreq directive deletes an alias which was previously defined
2993 by .req. For example:
2994
2995 my_alias .req r11
2996 .unreq my_alias */
2997
2998 static void
s_unreq(int a ATTRIBUTE_UNUSED)2999 s_unreq (int a ATTRIBUTE_UNUSED)
3000 {
3001 char *name;
3002 char saved_char;
3003
3004 skip_whitespace (input_line_pointer);
3005 name = input_line_pointer;
3006
3007 while (*input_line_pointer != 0
3008 && *input_line_pointer != ' '
3009 && *input_line_pointer != '\n')
3010 ++input_line_pointer;
3011
3012 saved_char = *input_line_pointer;
3013 *input_line_pointer = 0;
3014
3015 if (*name)
3016 {
3017 enum arm_reg_type req_type = arm_reg_parse_any (name);
3018
3019 if (req_type != REG_TYPE_MAX)
3020 {
3021 char *temp_name = name;
3022 int req_no = arm_reg_parse (&temp_name, all_reg_maps[req_type].htab);
3023
3024 if (req_no != FAIL)
3025 {
3026 struct reg_entry *req_entry;
3027
3028 /* Check to see if this alias is a builtin one. */
3029 req_entry = hash_delete (all_reg_maps[req_type].htab, name);
3030
3031 if (!req_entry)
3032 as_bad (_("unreq: missing hash entry for \"%s\""), name);
3033 else if (req_entry->builtin)
3034 /* FIXME: We are deleting a built in register alias which
3035 points to a const data structure, so we only need to
3036 free up the memory used by the key in the hash table.
3037 Unfortunately we have not recorded this value, so this
3038 is a memory leak. */
3039 /* FIXME: Should we issue a warning message ? */
3040 ;
3041 else
3042 {
3043 /* Deleting a user defined alias. We need to free the
3044 key and the value, but fortunately the key is the same
3045 as the value->name field. */
3046 free ((char *) req_entry->name);
3047 free (req_entry);
3048 }
3049 }
3050 else
3051 as_bad (_(".unreq: unrecognized symbol \"%s\""), name);
3052 }
3053 else
3054 as_bad (_(".unreq: unrecognized symbol \"%s\""), name);
3055 }
3056 else
3057 as_bad (_("invalid syntax for .unreq directive"));
3058
3059 *input_line_pointer = saved_char;
3060 demand_empty_rest_of_line ();
3061 }
3062
3063 static void
s_bss(ignore)3064 s_bss (ignore)
3065 int ignore ATTRIBUTE_UNUSED;
3066 {
3067 /* We don't support putting frags in the BSS segment, we fake it by
3068 marking in_bss, then looking at s_skip for clues. */
3069 subseg_set (bss_section, 0);
3070 demand_empty_rest_of_line ();
3071 mapping_state (MAP_DATA);
3072 }
3073
3074 static void
s_even(ignore)3075 s_even (ignore)
3076 int ignore ATTRIBUTE_UNUSED;
3077 {
3078 /* Never make frag if expect extra pass. */
3079 if (!need_pass_2)
3080 frag_align (1, 0, 0);
3081
3082 record_alignment (now_seg, 1);
3083
3084 demand_empty_rest_of_line ();
3085 }
3086
3087 static void
s_ltorg(ignored)3088 s_ltorg (ignored)
3089 int ignored ATTRIBUTE_UNUSED;
3090 {
3091 unsigned int entry;
3092 literal_pool * pool;
3093 char sym_name[20];
3094
3095 pool = find_literal_pool ();
3096 if (pool == NULL
3097 || pool->symbol == NULL
3098 || pool->next_free_entry == 0)
3099 return;
3100
3101 mapping_state (MAP_DATA);
3102
3103 /* Align pool as you have word accesses.
3104 Only make a frag if we have to. */
3105 if (!need_pass_2)
3106 frag_align (2, 0, 0);
3107
3108 record_alignment (now_seg, 2);
3109
3110 sprintf (sym_name, "$$lit_\002%x", pool->id);
3111
3112 symbol_locate (pool->symbol, sym_name, now_seg,
3113 (valueT) frag_now_fix (), frag_now);
3114 symbol_table_insert (pool->symbol);
3115
3116 ARM_SET_THUMB (pool->symbol, thumb_mode);
3117
3118 #if defined OBJ_COFF || defined OBJ_ELF
3119 ARM_SET_INTERWORK (pool->symbol, support_interwork);
3120 #endif
3121
3122 for (entry = 0; entry < pool->next_free_entry; entry ++)
3123 /* First output the expression in the instruction to the pool. */
3124 emit_expr (&(pool->literals[entry]), 4); /* .word */
3125
3126 /* Mark the pool as empty. */
3127 pool->next_free_entry = 0;
3128 pool->symbol = NULL;
3129 }
3130
3131 /* Same as s_align_ptwo but align 0 => align 2. */
3132
3133 static void
s_align(unused)3134 s_align (unused)
3135 int unused ATTRIBUTE_UNUSED;
3136 {
3137 register int temp;
3138 register long temp_fill;
3139 long max_alignment = 15;
3140
3141 temp = get_absolute_expression ();
3142 if (temp > max_alignment)
3143 as_bad (_("alignment too large: %d assumed"), temp = max_alignment);
3144 else if (temp < 0)
3145 {
3146 as_bad (_("alignment negative. 0 assumed."));
3147 temp = 0;
3148 }
3149
3150 if (*input_line_pointer == ',')
3151 {
3152 input_line_pointer++;
3153 temp_fill = get_absolute_expression ();
3154 }
3155 else
3156 temp_fill = 0;
3157
3158 if (!temp)
3159 temp = 2;
3160
3161 /* Only make a frag if we HAVE to. */
3162 if (temp && !need_pass_2)
3163 frag_align (temp, (int) temp_fill, 0);
3164 demand_empty_rest_of_line ();
3165
3166 record_alignment (now_seg, temp);
3167 }
3168
3169 static void
s_force_thumb(ignore)3170 s_force_thumb (ignore)
3171 int ignore ATTRIBUTE_UNUSED;
3172 {
3173 /* If we are not already in thumb mode go into it, EVEN if
3174 the target processor does not support thumb instructions.
3175 This is used by gcc/config/arm/lib1funcs.asm for example
3176 to compile interworking support functions even if the
3177 target processor should not support interworking. */
3178 if (! thumb_mode)
3179 {
3180 thumb_mode = 2;
3181
3182 record_alignment (now_seg, 1);
3183 }
3184
3185 demand_empty_rest_of_line ();
3186 }
3187
3188 static void
s_thumb_func(ignore)3189 s_thumb_func (ignore)
3190 int ignore ATTRIBUTE_UNUSED;
3191 {
3192 if (! thumb_mode)
3193 opcode_select (16);
3194
3195 /* The following label is the name/address of the start of a Thumb function.
3196 We need to know this for the interworking support. */
3197 label_is_thumb_function_name = TRUE;
3198
3199 demand_empty_rest_of_line ();
3200 }
3201
3202 /* Perform a .set directive, but also mark the alias as
3203 being a thumb function. */
3204
3205 static void
s_thumb_set(equiv)3206 s_thumb_set (equiv)
3207 int equiv;
3208 {
3209 /* XXX the following is a duplicate of the code for s_set() in read.c
3210 We cannot just call that code as we need to get at the symbol that
3211 is created. */
3212 register char * name;
3213 register char delim;
3214 register char * end_name;
3215 register symbolS * symbolP;
3216
3217 /* Especial apologies for the random logic:
3218 This just grew, and could be parsed much more simply!
3219 Dean - in haste. */
3220 name = input_line_pointer;
3221 delim = get_symbol_end ();
3222 end_name = input_line_pointer;
3223 *end_name = delim;
3224
3225 SKIP_WHITESPACE ();
3226
3227 if (*input_line_pointer != ',')
3228 {
3229 *end_name = 0;
3230 as_bad (_("expected comma after name \"%s\""), name);
3231 *end_name = delim;
3232 ignore_rest_of_line ();
3233 return;
3234 }
3235
3236 input_line_pointer++;
3237 *end_name = 0;
3238
3239 if (name[0] == '.' && name[1] == '\0')
3240 {
3241 /* XXX - this should not happen to .thumb_set. */
3242 abort ();
3243 }
3244
3245 if ((symbolP = symbol_find (name)) == NULL
3246 && (symbolP = md_undefined_symbol (name)) == NULL)
3247 {
3248 #ifndef NO_LISTING
3249 /* When doing symbol listings, play games with dummy fragments living
3250 outside the normal fragment chain to record the file and line info
3251 for this symbol. */
3252 if (listing & LISTING_SYMBOLS)
3253 {
3254 extern struct list_info_struct * listing_tail;
3255 fragS * dummy_frag = (fragS *) xmalloc (sizeof (fragS));
3256
3257 memset (dummy_frag, 0, sizeof (fragS));
3258 dummy_frag->fr_type = rs_fill;
3259 dummy_frag->line = listing_tail;
3260 symbolP = symbol_new (name, undefined_section, 0, dummy_frag);
3261 dummy_frag->fr_symbol = symbolP;
3262 }
3263 else
3264 #endif
3265 symbolP = symbol_new (name, undefined_section, 0, &zero_address_frag);
3266
3267 #ifdef OBJ_COFF
3268 /* "set" symbols are local unless otherwise specified. */
3269 SF_SET_LOCAL (symbolP);
3270 #endif /* OBJ_COFF */
3271 } /* Make a new symbol. */
3272
3273 symbol_table_insert (symbolP);
3274
3275 * end_name = delim;
3276
3277 if (equiv
3278 && S_IS_DEFINED (symbolP)
3279 && S_GET_SEGMENT (symbolP) != reg_section)
3280 as_bad (_("symbol `%s' already defined"), S_GET_NAME (symbolP));
3281
3282 pseudo_set (symbolP);
3283
3284 demand_empty_rest_of_line ();
3285
3286 /* XXX Now we come to the Thumb specific bit of code. */
3287
3288 THUMB_SET_FUNC (symbolP, 1);
3289 ARM_SET_THUMB (symbolP, 1);
3290 #if defined OBJ_ELF || defined OBJ_COFF
3291 ARM_SET_INTERWORK (symbolP, support_interwork);
3292 #endif
3293 }
3294
3295 static void
opcode_select(width)3296 opcode_select (width)
3297 int width;
3298 {
3299 switch (width)
3300 {
3301 case 16:
3302 if (! thumb_mode)
3303 {
3304 if (! (cpu_variant & ARM_EXT_V4T))
3305 as_bad (_("selected processor does not support THUMB opcodes"));
3306
3307 thumb_mode = 1;
3308 /* No need to force the alignment, since we will have been
3309 coming from ARM mode, which is word-aligned. */
3310 record_alignment (now_seg, 1);
3311 }
3312 mapping_state (MAP_THUMB);
3313 break;
3314
3315 case 32:
3316 if (thumb_mode)
3317 {
3318 if ((cpu_variant & ARM_ALL) == ARM_EXT_V4T)
3319 as_bad (_("selected processor does not support ARM opcodes"));
3320
3321 thumb_mode = 0;
3322
3323 if (!need_pass_2)
3324 frag_align (2, 0, 0);
3325
3326 record_alignment (now_seg, 1);
3327 }
3328 mapping_state (MAP_ARM);
3329 break;
3330
3331 default:
3332 as_bad (_("invalid instruction size selected (%d)"), width);
3333 }
3334 }
3335
3336 static void
s_arm(ignore)3337 s_arm (ignore)
3338 int ignore ATTRIBUTE_UNUSED;
3339 {
3340 opcode_select (32);
3341 demand_empty_rest_of_line ();
3342 }
3343
3344 static void
s_thumb(ignore)3345 s_thumb (ignore)
3346 int ignore ATTRIBUTE_UNUSED;
3347 {
3348 opcode_select (16);
3349 demand_empty_rest_of_line ();
3350 }
3351
3352 static void
s_code(unused)3353 s_code (unused)
3354 int unused ATTRIBUTE_UNUSED;
3355 {
3356 register int temp;
3357
3358 temp = get_absolute_expression ();
3359 switch (temp)
3360 {
3361 case 16:
3362 case 32:
3363 opcode_select (temp);
3364 break;
3365
3366 default:
3367 as_bad (_("invalid operand to .code directive (%d) (expecting 16 or 32)"), temp);
3368 }
3369 }
3370
3371 static void
end_of_line(str)3372 end_of_line (str)
3373 char *str;
3374 {
3375 skip_whitespace (str);
3376
3377 if (*str != '\0' && !inst.error)
3378 inst.error = _("garbage following instruction");
3379 }
3380
3381 static int
skip_past_comma(str)3382 skip_past_comma (str)
3383 char ** str;
3384 {
3385 char * p = * str, c;
3386 int comma = 0;
3387
3388 while ((c = *p) == ' ' || c == ',')
3389 {
3390 p++;
3391 if (c == ',' && comma++)
3392 return FAIL;
3393 }
3394
3395 if (c == '\0')
3396 return FAIL;
3397
3398 *str = p;
3399 return comma ? SUCCESS : FAIL;
3400 }
3401
3402 /* A standard register must be given at this point.
3403 SHIFT is the place to put it in inst.instruction.
3404 Restores input start point on error.
3405 Returns the reg#, or FAIL. */
3406
3407 static int
reg_required_here(str,shift)3408 reg_required_here (str, shift)
3409 char ** str;
3410 int shift;
3411 {
3412 static char buff [128]; /* XXX */
3413 int reg;
3414 char * start = * str;
3415
3416 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_RN].htab)) != FAIL)
3417 {
3418 if (shift >= 0)
3419 inst.instruction |= reg << shift;
3420 return reg;
3421 }
3422
3423 /* Restore the start point, we may have got a reg of the wrong class. */
3424 *str = start;
3425
3426 /* In the few cases where we might be able to accept something else
3427 this error can be overridden. */
3428 sprintf (buff, _("register expected, not '%.100s'"), start);
3429 inst.error = buff;
3430
3431 return FAIL;
3432 }
3433
3434 /* A Intel Wireless MMX technology register
3435 must be given at this point.
3436 Shift is the place to put it in inst.instruction.
3437 Restores input start point on err.
3438 Returns the reg#, or FAIL. */
3439
3440 static int
wreg_required_here(str,shift,reg_type)3441 wreg_required_here (str, shift, reg_type)
3442 char ** str;
3443 int shift;
3444 enum wreg_type reg_type;
3445 {
3446 static char buff [128];
3447 int reg;
3448 char * start = *str;
3449
3450 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_IWMMXT].htab)) != FAIL)
3451 {
3452 if (wr_register (reg)
3453 && (reg_type == IWMMXT_REG_WR || reg_type == IWMMXT_REG_WR_OR_WC))
3454 {
3455 if (shift >= 0)
3456 inst.instruction |= (reg ^ WR_PREFIX) << shift;
3457 return reg;
3458 }
3459 else if (wc_register (reg)
3460 && (reg_type == IWMMXT_REG_WC || reg_type == IWMMXT_REG_WR_OR_WC))
3461 {
3462 if (shift >= 0)
3463 inst.instruction |= (reg ^ WC_PREFIX) << shift;
3464 return reg;
3465 }
3466 else if ((wcg_register (reg) && reg_type == IWMMXT_REG_WCG))
3467 {
3468 if (shift >= 0)
3469 inst.instruction |= ((reg ^ WC_PREFIX) - 8) << shift;
3470 return reg;
3471 }
3472 }
3473
3474 /* Restore the start point, we may have got a reg of the wrong class. */
3475 *str = start;
3476
3477 /* In the few cases where we might be able to accept
3478 something else this error can be overridden. */
3479 sprintf (buff, _("Intel Wireless MMX technology register expected, not '%.100s'"), start);
3480 inst.error = buff;
3481
3482 return FAIL;
3483 }
3484
3485 static const struct asm_psr *
arm_psr_parse(ccp)3486 arm_psr_parse (ccp)
3487 register char ** ccp;
3488 {
3489 char * start = * ccp;
3490 char c;
3491 char * p;
3492 const struct asm_psr * psr;
3493
3494 p = start;
3495
3496 /* Skip to the end of the next word in the input stream. */
3497 do
3498 {
3499 c = *p++;
3500 }
3501 while (ISALPHA (c) || c == '_');
3502
3503 /* Terminate the word. */
3504 *--p = 0;
3505
3506 /* CPSR's and SPSR's can now be lowercase. This is just a convenience
3507 feature for ease of use and backwards compatibility. */
3508 if (!strncmp (start, "cpsr", 4))
3509 strncpy (start, "CPSR", 4);
3510 else if (!strncmp (start, "spsr", 4))
3511 strncpy (start, "SPSR", 4);
3512
3513 /* Now locate the word in the psr hash table. */
3514 psr = (const struct asm_psr *) hash_find (arm_psr_hsh, start);
3515
3516 /* Restore the input stream. */
3517 *p = c;
3518
3519 /* If we found a valid match, advance the
3520 stream pointer past the end of the word. */
3521 *ccp = p;
3522
3523 return psr;
3524 }
3525
3526 /* Parse the input looking for a PSR flag. */
3527
3528 static int
psr_required_here(str)3529 psr_required_here (str)
3530 char ** str;
3531 {
3532 char * start = * str;
3533 const struct asm_psr * psr;
3534
3535 psr = arm_psr_parse (str);
3536
3537 if (psr)
3538 {
3539 /* If this is the SPSR that is being modified, set the R bit. */
3540 if (! psr->cpsr)
3541 inst.instruction |= SPSR_BIT;
3542
3543 /* Set the psr flags in the MSR instruction. */
3544 inst.instruction |= psr->field << PSR_SHIFT;
3545
3546 return SUCCESS;
3547 }
3548
3549 /* In the few cases where we might be able to accept
3550 something else this error can be overridden. */
3551 inst.error = _("flag for {c}psr instruction expected");
3552
3553 /* Restore the start point. */
3554 *str = start;
3555 return FAIL;
3556 }
3557
3558 static int
co_proc_number(str)3559 co_proc_number (str)
3560 char **str;
3561 {
3562 int processor, pchar;
3563 char *start;
3564
3565 skip_whitespace (*str);
3566 start = *str;
3567
3568 /* The data sheet seems to imply that just a number on its own is valid
3569 here, but the RISC iX assembler seems to accept a prefix 'p'. We will
3570 accept either. */
3571 if ((processor = arm_reg_parse (str, all_reg_maps[REG_TYPE_CP].htab))
3572 == FAIL)
3573 {
3574 *str = start;
3575
3576 pchar = *(*str)++;
3577 if (pchar >= '0' && pchar <= '9')
3578 {
3579 processor = pchar - '0';
3580 if (**str >= '0' && **str <= '9')
3581 {
3582 processor = processor * 10 + *(*str)++ - '0';
3583 if (processor > 15)
3584 {
3585 inst.error = _("illegal co-processor number");
3586 return FAIL;
3587 }
3588 }
3589 }
3590 else
3591 {
3592 inst.error = _("bad or missing co-processor number");
3593 return FAIL;
3594 }
3595 }
3596
3597 inst.instruction |= processor << 8;
3598 return SUCCESS;
3599 }
3600
3601 static int
cp_opc_expr(str,where,length)3602 cp_opc_expr (str, where, length)
3603 char ** str;
3604 int where;
3605 int length;
3606 {
3607 expressionS expr;
3608
3609 skip_whitespace (* str);
3610
3611 memset (&expr, '\0', sizeof (expr));
3612
3613 if (my_get_expression (&expr, str))
3614 return FAIL;
3615 if (expr.X_op != O_constant)
3616 {
3617 inst.error = _("bad or missing expression");
3618 return FAIL;
3619 }
3620
3621 if ((expr.X_add_number & ((1 << length) - 1)) != expr.X_add_number)
3622 {
3623 inst.error = _("immediate co-processor expression too large");
3624 return FAIL;
3625 }
3626
3627 inst.instruction |= expr.X_add_number << where;
3628 return SUCCESS;
3629 }
3630
3631 static int
cp_reg_required_here(str,where)3632 cp_reg_required_here (str, where)
3633 char ** str;
3634 int where;
3635 {
3636 int reg;
3637 char * start = *str;
3638
3639 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_CN].htab)) != FAIL)
3640 {
3641 inst.instruction |= reg << where;
3642 return reg;
3643 }
3644
3645 /* In the few cases where we might be able to accept something else
3646 this error can be overridden. */
3647 inst.error = _("co-processor register expected");
3648
3649 /* Restore the start point. */
3650 *str = start;
3651 return FAIL;
3652 }
3653
3654 static int
fp_reg_required_here(str,where)3655 fp_reg_required_here (str, where)
3656 char ** str;
3657 int where;
3658 {
3659 int reg;
3660 char * start = * str;
3661
3662 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_FN].htab)) != FAIL)
3663 {
3664 inst.instruction |= reg << where;
3665 return reg;
3666 }
3667
3668 /* In the few cases where we might be able to accept something else
3669 this error can be overridden. */
3670 inst.error = _("floating point register expected");
3671
3672 /* Restore the start point. */
3673 *str = start;
3674 return FAIL;
3675 }
3676
3677 static int
cp_address_offset(str)3678 cp_address_offset (str)
3679 char ** str;
3680 {
3681 int offset;
3682
3683 skip_whitespace (* str);
3684
3685 if (! is_immediate_prefix (**str))
3686 {
3687 inst.error = _("immediate expression expected");
3688 return FAIL;
3689 }
3690
3691 (*str)++;
3692
3693 if (my_get_expression (& inst.reloc.exp, str))
3694 return FAIL;
3695
3696 if (inst.reloc.exp.X_op == O_constant)
3697 {
3698 offset = inst.reloc.exp.X_add_number;
3699
3700 if (offset & 3)
3701 {
3702 inst.error = _("co-processor address must be word aligned");
3703 return FAIL;
3704 }
3705
3706 if (offset > 1023 || offset < -1023)
3707 {
3708 inst.error = _("offset too large");
3709 return FAIL;
3710 }
3711
3712 if (offset >= 0)
3713 inst.instruction |= INDEX_UP;
3714 else
3715 offset = -offset;
3716
3717 inst.instruction |= offset >> 2;
3718 }
3719 else
3720 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
3721
3722 return SUCCESS;
3723 }
3724
3725 static int
cp_address_required_here(str,wb_ok)3726 cp_address_required_here (str, wb_ok)
3727 char ** str;
3728 int wb_ok;
3729 {
3730 char * p = * str;
3731 int pre_inc = 0;
3732 int write_back = 0;
3733
3734 if (*p == '[')
3735 {
3736 int reg;
3737
3738 p++;
3739 skip_whitespace (p);
3740
3741 if ((reg = reg_required_here (& p, 16)) == FAIL)
3742 return FAIL;
3743
3744 skip_whitespace (p);
3745
3746 if (*p == ']')
3747 {
3748 p++;
3749
3750 skip_whitespace (p);
3751
3752 if (*p == '\0')
3753 {
3754 /* As an extension to the official ARM syntax we allow:
3755
3756 [Rn]
3757
3758 as a short hand for:
3759
3760 [Rn,#0] */
3761 inst.instruction |= PRE_INDEX | INDEX_UP;
3762 *str = p;
3763 return SUCCESS;
3764 }
3765
3766 if (skip_past_comma (& p) == FAIL)
3767 {
3768 inst.error = _("comma expected after closing square bracket");
3769 return FAIL;
3770 }
3771
3772 skip_whitespace (p);
3773
3774 if (*p == '#')
3775 {
3776 if (wb_ok)
3777 {
3778 /* [Rn], #expr */
3779 write_back = WRITE_BACK;
3780
3781 if (reg == REG_PC)
3782 {
3783 inst.error = _("pc may not be used in post-increment");
3784 return FAIL;
3785 }
3786
3787 if (cp_address_offset (& p) == FAIL)
3788 return FAIL;
3789 }
3790 else
3791 pre_inc = PRE_INDEX | INDEX_UP;
3792 }
3793 else if (*p == '{')
3794 {
3795 int option;
3796
3797 /* [Rn], {<expr>} */
3798 p++;
3799
3800 skip_whitespace (p);
3801
3802 if (my_get_expression (& inst.reloc.exp, & p))
3803 return FAIL;
3804
3805 if (inst.reloc.exp.X_op == O_constant)
3806 {
3807 option = inst.reloc.exp.X_add_number;
3808
3809 if (option > 255 || option < 0)
3810 {
3811 inst.error = _("'option' field too large");
3812 return FAIL;
3813 }
3814
3815 skip_whitespace (p);
3816
3817 if (*p != '}')
3818 {
3819 inst.error = _("'}' expected at end of 'option' field");
3820 return FAIL;
3821 }
3822 else
3823 {
3824 p++;
3825 inst.instruction |= option;
3826 inst.instruction |= INDEX_UP;
3827 }
3828 }
3829 else
3830 {
3831 inst.error = _("non-constant expressions for 'option' field not supported");
3832 return FAIL;
3833 }
3834 }
3835 else
3836 {
3837 inst.error = _("# or { expected after comma");
3838 return FAIL;
3839 }
3840 }
3841 else
3842 {
3843 /* '['Rn, #expr']'[!] */
3844
3845 if (skip_past_comma (& p) == FAIL)
3846 {
3847 inst.error = _("pre-indexed expression expected");
3848 return FAIL;
3849 }
3850
3851 pre_inc = PRE_INDEX;
3852
3853 if (cp_address_offset (& p) == FAIL)
3854 return FAIL;
3855
3856 skip_whitespace (p);
3857
3858 if (*p++ != ']')
3859 {
3860 inst.error = _("missing ]");
3861 return FAIL;
3862 }
3863
3864 skip_whitespace (p);
3865
3866 if (wb_ok && *p == '!')
3867 {
3868 if (reg == REG_PC)
3869 {
3870 inst.error = _("pc may not be used with write-back");
3871 return FAIL;
3872 }
3873
3874 p++;
3875 write_back = WRITE_BACK;
3876 }
3877 }
3878 }
3879 else
3880 {
3881 if (my_get_expression (&inst.reloc.exp, &p))
3882 return FAIL;
3883
3884 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
3885 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
3886 inst.reloc.pc_rel = 1;
3887 inst.instruction |= (REG_PC << 16);
3888 pre_inc = PRE_INDEX;
3889 }
3890
3891 inst.instruction |= write_back | pre_inc;
3892 *str = p;
3893 return SUCCESS;
3894 }
3895
3896 static int
cp_byte_address_offset(str)3897 cp_byte_address_offset (str)
3898 char ** str;
3899 {
3900 int offset;
3901
3902 skip_whitespace (* str);
3903
3904 if (! is_immediate_prefix (**str))
3905 {
3906 inst.error = _("immediate expression expected");
3907 return FAIL;
3908 }
3909
3910 (*str)++;
3911
3912 if (my_get_expression (& inst.reloc.exp, str))
3913 return FAIL;
3914
3915 if (inst.reloc.exp.X_op == O_constant)
3916 {
3917 offset = inst.reloc.exp.X_add_number;
3918
3919 if (offset > 255 || offset < -255)
3920 {
3921 inst.error = _("offset too large");
3922 return FAIL;
3923 }
3924
3925 if (offset >= 0)
3926 inst.instruction |= INDEX_UP;
3927 else
3928 offset = -offset;
3929
3930 inst.instruction |= offset;
3931 }
3932 else
3933 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM_S2;
3934
3935 return SUCCESS;
3936 }
3937
3938 static int
cp_byte_address_required_here(str)3939 cp_byte_address_required_here (str)
3940 char ** str;
3941 {
3942 char * p = * str;
3943 int pre_inc = 0;
3944 int write_back = 0;
3945
3946 if (*p == '[')
3947 {
3948 int reg;
3949
3950 p++;
3951 skip_whitespace (p);
3952
3953 if ((reg = reg_required_here (& p, 16)) == FAIL)
3954 return FAIL;
3955
3956 skip_whitespace (p);
3957
3958 if (*p == ']')
3959 {
3960 p++;
3961
3962 if (skip_past_comma (& p) == SUCCESS)
3963 {
3964 /* [Rn], #expr */
3965 write_back = WRITE_BACK;
3966
3967 if (reg == REG_PC)
3968 {
3969 inst.error = _("pc may not be used in post-increment");
3970 return FAIL;
3971 }
3972
3973 if (cp_byte_address_offset (& p) == FAIL)
3974 return FAIL;
3975 }
3976 else
3977 pre_inc = PRE_INDEX | INDEX_UP;
3978 }
3979 else
3980 {
3981 /* '['Rn, #expr']'[!] */
3982
3983 if (skip_past_comma (& p) == FAIL)
3984 {
3985 inst.error = _("pre-indexed expression expected");
3986 return FAIL;
3987 }
3988
3989 pre_inc = PRE_INDEX;
3990
3991 if (cp_byte_address_offset (& p) == FAIL)
3992 return FAIL;
3993
3994 skip_whitespace (p);
3995
3996 if (*p++ != ']')
3997 {
3998 inst.error = _("missing ]");
3999 return FAIL;
4000 }
4001
4002 skip_whitespace (p);
4003
4004 if (*p == '!')
4005 {
4006 if (reg == REG_PC)
4007 {
4008 inst.error = _("pc may not be used with write-back");
4009 return FAIL;
4010 }
4011
4012 p++;
4013 write_back = WRITE_BACK;
4014 }
4015 }
4016 }
4017 else
4018 {
4019 if (my_get_expression (&inst.reloc.exp, &p))
4020 return FAIL;
4021
4022 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM_S2;
4023 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
4024 inst.reloc.pc_rel = 1;
4025 inst.instruction |= (REG_PC << 16);
4026 pre_inc = PRE_INDEX;
4027 }
4028
4029 inst.instruction |= write_back | pre_inc;
4030 *str = p;
4031 return SUCCESS;
4032 }
4033
4034 static void
do_empty(str)4035 do_empty (str)
4036 char * str;
4037 {
4038 /* Do nothing really. */
4039 end_of_line (str);
4040 }
4041
4042 static void
do_mrs(str)4043 do_mrs (str)
4044 char *str;
4045 {
4046 int skip = 0;
4047
4048 /* Only one syntax. */
4049 skip_whitespace (str);
4050
4051 if (reg_required_here (&str, 12) == FAIL)
4052 {
4053 inst.error = BAD_ARGS;
4054 return;
4055 }
4056
4057 if (skip_past_comma (&str) == FAIL)
4058 {
4059 inst.error = _("comma expected after register name");
4060 return;
4061 }
4062
4063 skip_whitespace (str);
4064
4065 if ( strcmp (str, "CPSR") == 0
4066 || strcmp (str, "SPSR") == 0
4067 /* Lower case versions for backwards compatibility. */
4068 || strcmp (str, "cpsr") == 0
4069 || strcmp (str, "spsr") == 0)
4070 skip = 4;
4071
4072 /* This is for backwards compatibility with older toolchains. */
4073 else if ( strcmp (str, "cpsr_all") == 0
4074 || strcmp (str, "spsr_all") == 0)
4075 skip = 8;
4076 else
4077 {
4078 inst.error = _("CPSR or SPSR expected");
4079 return;
4080 }
4081
4082 if (* str == 's' || * str == 'S')
4083 inst.instruction |= SPSR_BIT;
4084 str += skip;
4085
4086 end_of_line (str);
4087 }
4088
4089 /* Two possible forms:
4090 "{C|S}PSR_<field>, Rm",
4091 "{C|S}PSR_f, #expression". */
4092
4093 static void
do_msr(str)4094 do_msr (str)
4095 char * str;
4096 {
4097 skip_whitespace (str);
4098
4099 if (psr_required_here (& str) == FAIL)
4100 return;
4101
4102 if (skip_past_comma (& str) == FAIL)
4103 {
4104 inst.error = _("comma missing after psr flags");
4105 return;
4106 }
4107
4108 skip_whitespace (str);
4109
4110 if (reg_required_here (& str, 0) != FAIL)
4111 {
4112 inst.error = NULL;
4113 end_of_line (str);
4114 return;
4115 }
4116
4117 if (! is_immediate_prefix (* str))
4118 {
4119 inst.error =
4120 _("only a register or immediate value can follow a psr flag");
4121 return;
4122 }
4123
4124 str ++;
4125 inst.error = NULL;
4126
4127 if (my_get_expression (& inst.reloc.exp, & str))
4128 {
4129 inst.error =
4130 _("only a register or immediate value can follow a psr flag");
4131 return;
4132 }
4133
4134 #if 0 /* The first edition of the ARM architecture manual stated that
4135 writing anything other than the flags with an immediate operation
4136 had UNPREDICTABLE effects. This constraint was removed in the
4137 second edition of the specification. */
4138 if ((cpu_variant & ARM_EXT_V5) != ARM_EXT_V5
4139 && inst.instruction & ((PSR_c | PSR_x | PSR_s) << PSR_SHIFT))
4140 {
4141 inst.error = _("immediate value cannot be used to set this field");
4142 return;
4143 }
4144 #endif
4145
4146 inst.instruction |= INST_IMMEDIATE;
4147
4148 if (inst.reloc.exp.X_add_symbol)
4149 {
4150 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
4151 inst.reloc.pc_rel = 0;
4152 }
4153 else
4154 {
4155 unsigned value = validate_immediate (inst.reloc.exp.X_add_number);
4156
4157 if (value == (unsigned) FAIL)
4158 {
4159 inst.error = _("invalid constant");
4160 return;
4161 }
4162
4163 inst.instruction |= value;
4164 }
4165
4166 inst.error = NULL;
4167 end_of_line (str);
4168 }
4169
4170 /* Long Multiply Parser
4171 UMULL RdLo, RdHi, Rm, Rs
4172 SMULL RdLo, RdHi, Rm, Rs
4173 UMLAL RdLo, RdHi, Rm, Rs
4174 SMLAL RdLo, RdHi, Rm, Rs. */
4175
4176 static void
do_mull(str)4177 do_mull (str)
4178 char * str;
4179 {
4180 int rdlo, rdhi, rm, rs;
4181
4182 /* Only one format "rdlo, rdhi, rm, rs". */
4183 skip_whitespace (str);
4184
4185 if ((rdlo = reg_required_here (&str, 12)) == FAIL)
4186 {
4187 inst.error = BAD_ARGS;
4188 return;
4189 }
4190
4191 if (skip_past_comma (&str) == FAIL
4192 || (rdhi = reg_required_here (&str, 16)) == FAIL)
4193 {
4194 inst.error = BAD_ARGS;
4195 return;
4196 }
4197
4198 if (skip_past_comma (&str) == FAIL
4199 || (rm = reg_required_here (&str, 0)) == FAIL)
4200 {
4201 inst.error = BAD_ARGS;
4202 return;
4203 }
4204
4205 /* rdhi, rdlo and rm must all be different. */
4206 if (rdlo == rdhi || rdlo == rm || rdhi == rm)
4207 as_tsktsk (_("rdhi, rdlo and rm must all be different"));
4208
4209 if (skip_past_comma (&str) == FAIL
4210 || (rs = reg_required_here (&str, 8)) == FAIL)
4211 {
4212 inst.error = BAD_ARGS;
4213 return;
4214 }
4215
4216 if (rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC)
4217 {
4218 inst.error = BAD_PC;
4219 return;
4220 }
4221
4222 end_of_line (str);
4223 }
4224
4225 static void
do_mul(str)4226 do_mul (str)
4227 char * str;
4228 {
4229 int rd, rm;
4230
4231 /* Only one format "rd, rm, rs". */
4232 skip_whitespace (str);
4233
4234 if ((rd = reg_required_here (&str, 16)) == FAIL)
4235 {
4236 inst.error = BAD_ARGS;
4237 return;
4238 }
4239
4240 if (rd == REG_PC)
4241 {
4242 inst.error = BAD_PC;
4243 return;
4244 }
4245
4246 if (skip_past_comma (&str) == FAIL
4247 || (rm = reg_required_here (&str, 0)) == FAIL)
4248 {
4249 inst.error = BAD_ARGS;
4250 return;
4251 }
4252
4253 if (rm == REG_PC)
4254 {
4255 inst.error = BAD_PC;
4256 return;
4257 }
4258
4259 if (rm == rd)
4260 as_tsktsk (_("rd and rm should be different in mul"));
4261
4262 if (skip_past_comma (&str) == FAIL
4263 || (rm = reg_required_here (&str, 8)) == FAIL)
4264 {
4265 inst.error = BAD_ARGS;
4266 return;
4267 }
4268
4269 if (rm == REG_PC)
4270 {
4271 inst.error = BAD_PC;
4272 return;
4273 }
4274
4275 end_of_line (str);
4276 }
4277
4278 static void
do_mla(str)4279 do_mla (str)
4280 char * str;
4281 {
4282 int rd, rm;
4283
4284 /* Only one format "rd, rm, rs, rn". */
4285 skip_whitespace (str);
4286
4287 if ((rd = reg_required_here (&str, 16)) == FAIL)
4288 {
4289 inst.error = BAD_ARGS;
4290 return;
4291 }
4292
4293 if (rd == REG_PC)
4294 {
4295 inst.error = BAD_PC;
4296 return;
4297 }
4298
4299 if (skip_past_comma (&str) == FAIL
4300 || (rm = reg_required_here (&str, 0)) == FAIL)
4301 {
4302 inst.error = BAD_ARGS;
4303 return;
4304 }
4305
4306 if (rm == REG_PC)
4307 {
4308 inst.error = BAD_PC;
4309 return;
4310 }
4311
4312 if (rm == rd)
4313 as_tsktsk (_("rd and rm should be different in mla"));
4314
4315 if (skip_past_comma (&str) == FAIL
4316 || (rd = reg_required_here (&str, 8)) == FAIL
4317 || skip_past_comma (&str) == FAIL
4318 || (rm = reg_required_here (&str, 12)) == FAIL)
4319 {
4320 inst.error = BAD_ARGS;
4321 return;
4322 }
4323
4324 if (rd == REG_PC || rm == REG_PC)
4325 {
4326 inst.error = BAD_PC;
4327 return;
4328 }
4329
4330 end_of_line (str);
4331 }
4332
4333 /* Expects *str -> the characters "acc0", possibly with leading blanks.
4334 Advances *str to the next non-alphanumeric.
4335 Returns 0, or else FAIL (in which case sets inst.error).
4336
4337 (In a future XScale, there may be accumulators other than zero.
4338 At that time this routine and its callers can be upgraded to suit.) */
4339
4340 static int
accum0_required_here(str)4341 accum0_required_here (str)
4342 char ** str;
4343 {
4344 static char buff [128]; /* Note the address is taken. Hence, static. */
4345 char * p = * str;
4346 char c;
4347 int result = 0; /* The accum number. */
4348
4349 skip_whitespace (p);
4350
4351 *str = p; /* Advance caller's string pointer too. */
4352 c = *p++;
4353 while (ISALNUM (c))
4354 c = *p++;
4355
4356 *--p = 0; /* Aap nul into input buffer at non-alnum. */
4357
4358 if (! ( streq (*str, "acc0") || streq (*str, "ACC0")))
4359 {
4360 sprintf (buff, _("acc0 expected, not '%.100s'"), *str);
4361 inst.error = buff;
4362 result = FAIL;
4363 }
4364
4365 *p = c; /* Unzap. */
4366 *str = p; /* Caller's string pointer to after match. */
4367 return result;
4368 }
4369
4370 /* Expects **str -> after a comma. May be leading blanks.
4371 Advances *str, recognizing a load mode, and setting inst.instruction.
4372 Returns rn, or else FAIL (in which case may set inst.error
4373 and not advance str)
4374
4375 Note: doesn't know Rd, so no err checks that require such knowledge. */
4376
4377 static int
ld_mode_required_here(string)4378 ld_mode_required_here (string)
4379 char ** string;
4380 {
4381 char * str = * string;
4382 int rn;
4383 int pre_inc = 0;
4384
4385 skip_whitespace (str);
4386
4387 if (* str == '[')
4388 {
4389 str++;
4390
4391 skip_whitespace (str);
4392
4393 if ((rn = reg_required_here (& str, 16)) == FAIL)
4394 return FAIL;
4395
4396 skip_whitespace (str);
4397
4398 if (* str == ']')
4399 {
4400 str ++;
4401
4402 if (skip_past_comma (& str) == SUCCESS)
4403 {
4404 /* [Rn],... (post inc) */
4405 if (ldst_extend_v4 (&str) == FAIL)
4406 return FAIL;
4407 }
4408 else /* [Rn] */
4409 {
4410 skip_whitespace (str);
4411
4412 if (* str == '!')
4413 {
4414 str ++;
4415 inst.instruction |= WRITE_BACK;
4416 }
4417
4418 inst.instruction |= INDEX_UP | HWOFFSET_IMM;
4419 pre_inc = 1;
4420 }
4421 }
4422 else /* [Rn,...] */
4423 {
4424 if (skip_past_comma (& str) == FAIL)
4425 {
4426 inst.error = _("pre-indexed expression expected");
4427 return FAIL;
4428 }
4429
4430 pre_inc = 1;
4431
4432 if (ldst_extend_v4 (&str) == FAIL)
4433 return FAIL;
4434
4435 skip_whitespace (str);
4436
4437 if (* str ++ != ']')
4438 {
4439 inst.error = _("missing ]");
4440 return FAIL;
4441 }
4442
4443 skip_whitespace (str);
4444
4445 if (* str == '!')
4446 {
4447 str ++;
4448 inst.instruction |= WRITE_BACK;
4449 }
4450 }
4451 }
4452 else if (* str == '=') /* ldr's "r,=label" syntax */
4453 /* We should never reach here, because <text> = <expression> is
4454 caught gas/read.c read_a_source_file() as a .set operation. */
4455 return FAIL;
4456 else /* PC +- 8 bit immediate offset. */
4457 {
4458 if (my_get_expression (& inst.reloc.exp, & str))
4459 return FAIL;
4460
4461 inst.instruction |= HWOFFSET_IMM; /* The I bit. */
4462 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
4463 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
4464 inst.reloc.pc_rel = 1;
4465 inst.instruction |= (REG_PC << 16);
4466
4467 rn = REG_PC;
4468 pre_inc = 1;
4469 }
4470
4471 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
4472 * string = str;
4473
4474 return rn;
4475 }
4476
4477 /* ARM V5E (El Segundo) signed-multiply-accumulate (argument parse)
4478 SMLAxy{cond} Rd,Rm,Rs,Rn
4479 SMLAWy{cond} Rd,Rm,Rs,Rn
4480 Error if any register is R15. */
4481
4482 static void
do_smla(str)4483 do_smla (str)
4484 char * str;
4485 {
4486 int rd, rm, rs, rn;
4487
4488 skip_whitespace (str);
4489
4490 if ((rd = reg_required_here (& str, 16)) == FAIL
4491 || skip_past_comma (& str) == FAIL
4492 || (rm = reg_required_here (& str, 0)) == FAIL
4493 || skip_past_comma (& str) == FAIL
4494 || (rs = reg_required_here (& str, 8)) == FAIL
4495 || skip_past_comma (& str) == FAIL
4496 || (rn = reg_required_here (& str, 12)) == FAIL)
4497 inst.error = BAD_ARGS;
4498
4499 else if (rd == REG_PC || rm == REG_PC || rs == REG_PC || rn == REG_PC)
4500 inst.error = BAD_PC;
4501
4502 else
4503 end_of_line (str);
4504 }
4505
4506 /* ARM V5E (El Segundo) signed-multiply-accumulate-long (argument parse)
4507 SMLALxy{cond} Rdlo,Rdhi,Rm,Rs
4508 Error if any register is R15.
4509 Warning if Rdlo == Rdhi. */
4510
4511 static void
do_smlal(str)4512 do_smlal (str)
4513 char * str;
4514 {
4515 int rdlo, rdhi, rm, rs;
4516
4517 skip_whitespace (str);
4518
4519 if ((rdlo = reg_required_here (& str, 12)) == FAIL
4520 || skip_past_comma (& str) == FAIL
4521 || (rdhi = reg_required_here (& str, 16)) == FAIL
4522 || skip_past_comma (& str) == FAIL
4523 || (rm = reg_required_here (& str, 0)) == FAIL
4524 || skip_past_comma (& str) == FAIL
4525 || (rs = reg_required_here (& str, 8)) == FAIL)
4526 {
4527 inst.error = BAD_ARGS;
4528 return;
4529 }
4530
4531 if (rdlo == REG_PC || rdhi == REG_PC || rm == REG_PC || rs == REG_PC)
4532 {
4533 inst.error = BAD_PC;
4534 return;
4535 }
4536
4537 if (rdlo == rdhi)
4538 as_tsktsk (_("rdhi and rdlo must be different"));
4539
4540 end_of_line (str);
4541 }
4542
4543 /* ARM V5E (El Segundo) signed-multiply (argument parse)
4544 SMULxy{cond} Rd,Rm,Rs
4545 Error if any register is R15. */
4546
4547 static void
do_smul(str)4548 do_smul (str)
4549 char * str;
4550 {
4551 int rd, rm, rs;
4552
4553 skip_whitespace (str);
4554
4555 if ((rd = reg_required_here (& str, 16)) == FAIL
4556 || skip_past_comma (& str) == FAIL
4557 || (rm = reg_required_here (& str, 0)) == FAIL
4558 || skip_past_comma (& str) == FAIL
4559 || (rs = reg_required_here (& str, 8)) == FAIL)
4560 inst.error = BAD_ARGS;
4561
4562 else if (rd == REG_PC || rm == REG_PC || rs == REG_PC)
4563 inst.error = BAD_PC;
4564
4565 else
4566 end_of_line (str);
4567 }
4568
4569 /* ARM V5E (El Segundo) saturating-add/subtract (argument parse)
4570 Q[D]{ADD,SUB}{cond} Rd,Rm,Rn
4571 Error if any register is R15. */
4572
4573 static void
do_qadd(str)4574 do_qadd (str)
4575 char * str;
4576 {
4577 int rd, rm, rn;
4578
4579 skip_whitespace (str);
4580
4581 if ((rd = reg_required_here (& str, 12)) == FAIL
4582 || skip_past_comma (& str) == FAIL
4583 || (rm = reg_required_here (& str, 0)) == FAIL
4584 || skip_past_comma (& str) == FAIL
4585 || (rn = reg_required_here (& str, 16)) == FAIL)
4586 inst.error = BAD_ARGS;
4587
4588 else if (rd == REG_PC || rm == REG_PC || rn == REG_PC)
4589 inst.error = BAD_PC;
4590
4591 else
4592 end_of_line (str);
4593 }
4594
4595 /* ARM V5E (el Segundo)
4596 MCRRcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
4597 MRRCcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
4598
4599 These are equivalent to the XScale instructions MAR and MRA,
4600 respectively, when coproc == 0, opcode == 0, and CRm == 0.
4601
4602 Result unpredicatable if Rd or Rn is R15. */
4603
4604 static void
do_co_reg2c(str)4605 do_co_reg2c (str)
4606 char * str;
4607 {
4608 int rd, rn;
4609
4610 skip_whitespace (str);
4611
4612 if (co_proc_number (& str) == FAIL)
4613 {
4614 if (!inst.error)
4615 inst.error = BAD_ARGS;
4616 return;
4617 }
4618
4619 if (skip_past_comma (& str) == FAIL
4620 || cp_opc_expr (& str, 4, 4) == FAIL)
4621 {
4622 if (!inst.error)
4623 inst.error = BAD_ARGS;
4624 return;
4625 }
4626
4627 if (skip_past_comma (& str) == FAIL
4628 || (rd = reg_required_here (& str, 12)) == FAIL)
4629 {
4630 if (!inst.error)
4631 inst.error = BAD_ARGS;
4632 return;
4633 }
4634
4635 if (skip_past_comma (& str) == FAIL
4636 || (rn = reg_required_here (& str, 16)) == FAIL)
4637 {
4638 if (!inst.error)
4639 inst.error = BAD_ARGS;
4640 return;
4641 }
4642
4643 /* Unpredictable result if rd or rn is R15. */
4644 if (rd == REG_PC || rn == REG_PC)
4645 as_tsktsk
4646 (_("Warning: instruction unpredictable when using r15"));
4647
4648 if (skip_past_comma (& str) == FAIL
4649 || cp_reg_required_here (& str, 0) == FAIL)
4650 {
4651 if (!inst.error)
4652 inst.error = BAD_ARGS;
4653 return;
4654 }
4655
4656 end_of_line (str);
4657 }
4658
4659 /* ARM V5 count-leading-zeroes instruction (argument parse)
4660 CLZ{<cond>} <Rd>, <Rm>
4661 Condition defaults to COND_ALWAYS.
4662 Error if Rd or Rm are R15. */
4663
4664 static void
do_clz(str)4665 do_clz (str)
4666 char * str;
4667 {
4668 int rd, rm;
4669
4670 skip_whitespace (str);
4671
4672 if (((rd = reg_required_here (& str, 12)) == FAIL)
4673 || (skip_past_comma (& str) == FAIL)
4674 || ((rm = reg_required_here (& str, 0)) == FAIL))
4675 inst.error = BAD_ARGS;
4676
4677 else if (rd == REG_PC || rm == REG_PC )
4678 inst.error = BAD_PC;
4679
4680 else
4681 end_of_line (str);
4682 }
4683
4684 /* ARM V5 (argument parse)
4685 LDC2{L} <coproc>, <CRd>, <addressing mode>
4686 STC2{L} <coproc>, <CRd>, <addressing mode>
4687 Instruction is not conditional, and has 0xf in the condition field.
4688 Otherwise, it's the same as LDC/STC. */
4689
4690 static void
do_lstc2(str)4691 do_lstc2 (str)
4692 char * str;
4693 {
4694 skip_whitespace (str);
4695
4696 if (co_proc_number (& str) == FAIL)
4697 {
4698 if (!inst.error)
4699 inst.error = BAD_ARGS;
4700 }
4701 else if (skip_past_comma (& str) == FAIL
4702 || cp_reg_required_here (& str, 12) == FAIL)
4703 {
4704 if (!inst.error)
4705 inst.error = BAD_ARGS;
4706 }
4707 else if (skip_past_comma (& str) == FAIL
4708 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
4709 {
4710 if (! inst.error)
4711 inst.error = BAD_ARGS;
4712 }
4713 else
4714 end_of_line (str);
4715 }
4716
4717 /* ARM V5 (argument parse)
4718 CDP2 <coproc>, <opcode_1>, <CRd>, <CRn>, <CRm>, <opcode_2>
4719 Instruction is not conditional, and has 0xf in the condition field.
4720 Otherwise, it's the same as CDP. */
4721
4722 static void
do_cdp2(str)4723 do_cdp2 (str)
4724 char * str;
4725 {
4726 skip_whitespace (str);
4727
4728 if (co_proc_number (& str) == FAIL)
4729 {
4730 if (!inst.error)
4731 inst.error = BAD_ARGS;
4732 return;
4733 }
4734
4735 if (skip_past_comma (& str) == FAIL
4736 || cp_opc_expr (& str, 20,4) == FAIL)
4737 {
4738 if (!inst.error)
4739 inst.error = BAD_ARGS;
4740 return;
4741 }
4742
4743 if (skip_past_comma (& str) == FAIL
4744 || cp_reg_required_here (& str, 12) == FAIL)
4745 {
4746 if (!inst.error)
4747 inst.error = BAD_ARGS;
4748 return;
4749 }
4750
4751 if (skip_past_comma (& str) == FAIL
4752 || cp_reg_required_here (& str, 16) == FAIL)
4753 {
4754 if (!inst.error)
4755 inst.error = BAD_ARGS;
4756 return;
4757 }
4758
4759 if (skip_past_comma (& str) == FAIL
4760 || cp_reg_required_here (& str, 0) == FAIL)
4761 {
4762 if (!inst.error)
4763 inst.error = BAD_ARGS;
4764 return;
4765 }
4766
4767 if (skip_past_comma (& str) == SUCCESS)
4768 {
4769 if (cp_opc_expr (& str, 5, 3) == FAIL)
4770 {
4771 if (!inst.error)
4772 inst.error = BAD_ARGS;
4773 return;
4774 }
4775 }
4776
4777 end_of_line (str);
4778 }
4779
4780 /* ARM V5 (argument parse)
4781 MCR2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
4782 MRC2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
4783 Instruction is not conditional, and has 0xf in the condition field.
4784 Otherwise, it's the same as MCR/MRC. */
4785
4786 static void
do_co_reg2(str)4787 do_co_reg2 (str)
4788 char * str;
4789 {
4790 skip_whitespace (str);
4791
4792 if (co_proc_number (& str) == FAIL)
4793 {
4794 if (!inst.error)
4795 inst.error = BAD_ARGS;
4796 return;
4797 }
4798
4799 if (skip_past_comma (& str) == FAIL
4800 || cp_opc_expr (& str, 21, 3) == FAIL)
4801 {
4802 if (!inst.error)
4803 inst.error = BAD_ARGS;
4804 return;
4805 }
4806
4807 if (skip_past_comma (& str) == FAIL
4808 || reg_required_here (& str, 12) == FAIL)
4809 {
4810 if (!inst.error)
4811 inst.error = BAD_ARGS;
4812 return;
4813 }
4814
4815 if (skip_past_comma (& str) == FAIL
4816 || cp_reg_required_here (& str, 16) == FAIL)
4817 {
4818 if (!inst.error)
4819 inst.error = BAD_ARGS;
4820 return;
4821 }
4822
4823 if (skip_past_comma (& str) == FAIL
4824 || cp_reg_required_here (& str, 0) == FAIL)
4825 {
4826 if (!inst.error)
4827 inst.error = BAD_ARGS;
4828 return;
4829 }
4830
4831 if (skip_past_comma (& str) == SUCCESS)
4832 {
4833 if (cp_opc_expr (& str, 5, 3) == FAIL)
4834 {
4835 if (!inst.error)
4836 inst.error = BAD_ARGS;
4837 return;
4838 }
4839 }
4840
4841 end_of_line (str);
4842 }
4843
4844 /* ARM v5TEJ. Jump to Jazelle code. */
4845 static void
do_bxj(str)4846 do_bxj (str)
4847 char * str;
4848 {
4849 int reg;
4850
4851 skip_whitespace (str);
4852
4853 if ((reg = reg_required_here (&str, 0)) == FAIL)
4854 {
4855 inst.error = BAD_ARGS;
4856 return;
4857 }
4858
4859 /* Note - it is not illegal to do a "bxj pc". Useless, but not illegal. */
4860 if (reg == REG_PC)
4861 as_tsktsk (_("use of r15 in bxj is not really useful"));
4862
4863 end_of_line (str);
4864 }
4865
4866 /* ARM V6 umaal (argument parse). */
4867
4868 static void
do_umaal(str)4869 do_umaal (str)
4870 char *str;
4871 {
4872
4873 int rdlo, rdhi, rm, rs;
4874
4875 skip_whitespace (str);
4876 if ((rdlo = reg_required_here (& str, 12)) == FAIL
4877 || skip_past_comma (& str) == FAIL
4878 || (rdhi = reg_required_here (& str, 16)) == FAIL
4879 || skip_past_comma (& str) == FAIL
4880 || (rm = reg_required_here (& str, 0)) == FAIL
4881 || skip_past_comma (& str) == FAIL
4882 || (rs = reg_required_here (& str, 8)) == FAIL)
4883 {
4884 inst.error = BAD_ARGS;
4885 return;
4886 }
4887
4888 if (rdlo == REG_PC || rdhi == REG_PC || rm == REG_PC || rs == REG_PC)
4889 {
4890 inst.error = BAD_PC;
4891 return;
4892 }
4893
4894 end_of_line (str);
4895 }
4896
4897 /* ARM V6 strex (argument parse). */
4898
4899 static void
do_strex(str)4900 do_strex (str)
4901 char *str;
4902 {
4903 int rd, rm, rn;
4904
4905 /* Parse Rd, Rm,. */
4906 skip_whitespace (str);
4907 if ((rd = reg_required_here (& str, 12)) == FAIL
4908 || skip_past_comma (& str) == FAIL
4909 || (rm = reg_required_here (& str, 0)) == FAIL
4910 || skip_past_comma (& str) == FAIL)
4911 {
4912 inst.error = BAD_ARGS;
4913 return;
4914 }
4915 if (rd == REG_PC || rm == REG_PC)
4916 {
4917 inst.error = BAD_PC;
4918 return;
4919 }
4920 if (rd == rm)
4921 {
4922 inst.error = _("Rd equal to Rm or Rn yields unpredictable results");
4923 return;
4924 }
4925
4926 /* Skip past '['. */
4927 if ((strlen (str) >= 1)
4928 && strncmp (str, "[", 1) == 0)
4929 str+=1;
4930 skip_whitespace (str);
4931
4932 /* Parse Rn. */
4933 if ((rn = reg_required_here (& str, 16)) == FAIL)
4934 {
4935 inst.error = BAD_ARGS;
4936 return;
4937 }
4938 else if (rn == REG_PC)
4939 {
4940 inst.error = BAD_PC;
4941 return;
4942 }
4943 if (rd == rn)
4944 {
4945 inst.error = _("Rd equal to Rm or Rn yields unpredictable results");
4946 return;
4947 }
4948 skip_whitespace (str);
4949
4950 /* Skip past ']'. */
4951 if ((strlen (str) >= 1)
4952 && strncmp (str, "]", 1) == 0)
4953 str+=1;
4954
4955 end_of_line (str);
4956 }
4957
4958 /* ARM V6 ssat (argument parse). */
4959
4960 static void
do_ssat(str)4961 do_ssat (str)
4962 char* str;
4963 {
4964 do_sat (&str, /*bias=*/-1);
4965 end_of_line (str);
4966 }
4967
4968 /* ARM V6 usat (argument parse). */
4969
4970 static void
do_usat(str)4971 do_usat (str)
4972 char* str;
4973 {
4974 do_sat (&str, /*bias=*/0);
4975 end_of_line (str);
4976 }
4977
4978 static void
do_sat(str,bias)4979 do_sat (str, bias)
4980 char **str;
4981 int bias;
4982 {
4983 int rd, rm;
4984 expressionS expr;
4985
4986 skip_whitespace (*str);
4987
4988 /* Parse <Rd>, field. */
4989 if ((rd = reg_required_here (str, 12)) == FAIL
4990 || skip_past_comma (str) == FAIL)
4991 {
4992 inst.error = BAD_ARGS;
4993 return;
4994 }
4995 if (rd == REG_PC)
4996 {
4997 inst.error = BAD_PC;
4998 return;
4999 }
5000
5001 /* Parse #<immed>, field. */
5002 if (is_immediate_prefix (**str))
5003 (*str)++;
5004 else
5005 {
5006 inst.error = _("immediate expression expected");
5007 return;
5008 }
5009 if (my_get_expression (&expr, str))
5010 {
5011 inst.error = _("bad expression");
5012 return;
5013 }
5014 if (expr.X_op != O_constant)
5015 {
5016 inst.error = _("constant expression expected");
5017 return;
5018 }
5019 if (expr.X_add_number + bias < 0
5020 || expr.X_add_number + bias > 31)
5021 {
5022 inst.error = _("immediate value out of range");
5023 return;
5024 }
5025 inst.instruction |= (expr.X_add_number + bias) << 16;
5026 if (skip_past_comma (str) == FAIL)
5027 {
5028 inst.error = BAD_ARGS;
5029 return;
5030 }
5031
5032 /* Parse <Rm> field. */
5033 if ((rm = reg_required_here (str, 0)) == FAIL)
5034 {
5035 inst.error = BAD_ARGS;
5036 return;
5037 }
5038 if (rm == REG_PC)
5039 {
5040 inst.error = BAD_PC;
5041 return;
5042 }
5043
5044 if (skip_past_comma (str) == SUCCESS)
5045 decode_shift (str, SHIFT_LSL_OR_ASR_IMMEDIATE);
5046 }
5047
5048 /* ARM V6 ssat16 (argument parse). */
5049
5050 static void
do_ssat16(str)5051 do_ssat16 (str)
5052 char *str;
5053 {
5054 do_sat16 (&str, /*bias=*/-1);
5055 end_of_line (str);
5056 }
5057
5058 static void
do_usat16(str)5059 do_usat16 (str)
5060 char *str;
5061 {
5062 do_sat16 (&str, /*bias=*/0);
5063 end_of_line (str);
5064 }
5065
5066 static void
do_sat16(str,bias)5067 do_sat16 (str, bias)
5068 char **str;
5069 int bias;
5070 {
5071 int rd, rm;
5072 expressionS expr;
5073
5074 skip_whitespace (*str);
5075
5076 /* Parse the <Rd> field. */
5077 if ((rd = reg_required_here (str, 12)) == FAIL
5078 || skip_past_comma (str) == FAIL)
5079 {
5080 inst.error = BAD_ARGS;
5081 return;
5082 }
5083 if (rd == REG_PC)
5084 {
5085 inst.error = BAD_PC;
5086 return;
5087 }
5088
5089 /* Parse #<immed>, field. */
5090 if (is_immediate_prefix (**str))
5091 (*str)++;
5092 else
5093 {
5094 inst.error = _("immediate expression expected");
5095 return;
5096 }
5097 if (my_get_expression (&expr, str))
5098 {
5099 inst.error = _("bad expression");
5100 return;
5101 }
5102 if (expr.X_op != O_constant)
5103 {
5104 inst.error = _("constant expression expected");
5105 return;
5106 }
5107 if (expr.X_add_number + bias < 0
5108 || expr.X_add_number + bias > 15)
5109 {
5110 inst.error = _("immediate value out of range");
5111 return;
5112 }
5113 inst.instruction |= (expr.X_add_number + bias) << 16;
5114 if (skip_past_comma (str) == FAIL)
5115 {
5116 inst.error = BAD_ARGS;
5117 return;
5118 }
5119
5120 /* Parse <Rm> field. */
5121 if ((rm = reg_required_here (str, 0)) == FAIL)
5122 {
5123 inst.error = BAD_ARGS;
5124 return;
5125 }
5126 if (rm == REG_PC)
5127 {
5128 inst.error = BAD_PC;
5129 return;
5130 }
5131 }
5132
5133 /* ARM V6 srs (argument parse). */
5134
5135 static void
do_srs(str)5136 do_srs (str)
5137 char* str;
5138 {
5139 char *exclam;
5140 skip_whitespace (str);
5141 exclam = strchr (str, '!');
5142 if (exclam)
5143 *exclam = '\0';
5144 do_cps_mode (&str);
5145 if (exclam)
5146 *exclam = '!';
5147 if (*str == '!')
5148 {
5149 inst.instruction |= WRITE_BACK;
5150 str++;
5151 }
5152 end_of_line (str);
5153 }
5154
5155 /* ARM V6 SMMUL (argument parse). */
5156
5157 static void
do_smmul(str)5158 do_smmul (str)
5159 char* str;
5160 {
5161 int rd, rm, rs;
5162
5163 skip_whitespace (str);
5164 if ((rd = reg_required_here (&str, 16)) == FAIL
5165 || skip_past_comma (&str) == FAIL
5166 || (rm = reg_required_here (&str, 0)) == FAIL
5167 || skip_past_comma (&str) == FAIL
5168 || (rs = reg_required_here (&str, 8)) == FAIL)
5169 {
5170 inst.error = BAD_ARGS;
5171 return;
5172 }
5173
5174 if (rd == REG_PC
5175 || rm == REG_PC
5176 || rs == REG_PC)
5177 {
5178 inst.error = BAD_PC;
5179 return;
5180 }
5181
5182 end_of_line (str);
5183
5184 }
5185
5186 /* ARM V6 SMLALD (argument parse). */
5187
5188 static void
do_smlald(str)5189 do_smlald (str)
5190 char* str;
5191 {
5192 int rdlo, rdhi, rm, rs;
5193 skip_whitespace (str);
5194 if ((rdlo = reg_required_here (&str, 12)) == FAIL
5195 || skip_past_comma (&str) == FAIL
5196 || (rdhi = reg_required_here (&str, 16)) == FAIL
5197 || skip_past_comma (&str) == FAIL
5198 || (rm = reg_required_here (&str, 0)) == FAIL
5199 || skip_past_comma (&str) == FAIL
5200 || (rs = reg_required_here (&str, 8)) == FAIL)
5201 {
5202 inst.error = BAD_ARGS;
5203 return;
5204 }
5205
5206 if (rdlo == REG_PC
5207 || rdhi == REG_PC
5208 || rm == REG_PC
5209 || rs == REG_PC)
5210 {
5211 inst.error = BAD_PC;
5212 return;
5213 }
5214
5215 end_of_line (str);
5216 }
5217
5218 /* ARM V6 SMLAD (argument parse). Signed multiply accumulate dual.
5219 smlad{x}{<cond>} Rd, Rm, Rs, Rn */
5220
5221 static void
do_smlad(str)5222 do_smlad (str)
5223 char *str;
5224 {
5225 int rd, rm, rs, rn;
5226
5227 skip_whitespace (str);
5228 if ((rd = reg_required_here (&str, 16)) == FAIL
5229 || skip_past_comma (&str) == FAIL
5230 || (rm = reg_required_here (&str, 0)) == FAIL
5231 || skip_past_comma (&str) == FAIL
5232 || (rs = reg_required_here (&str, 8)) == FAIL
5233 || skip_past_comma (&str) == FAIL
5234 || (rn = reg_required_here (&str, 12)) == FAIL)
5235 {
5236 inst.error = BAD_ARGS;
5237 return;
5238 }
5239
5240 if (rd == REG_PC
5241 || rn == REG_PC
5242 || rs == REG_PC
5243 || rm == REG_PC)
5244 {
5245 inst.error = BAD_PC;
5246 return;
5247 }
5248
5249 end_of_line (str);
5250 }
5251
5252 /* ARM V6 SETEND (argument parse). Sets the E bit in the CPSR while
5253 preserving the other bits.
5254
5255 setend <endian_specifier>, where <endian_specifier> is either
5256 BE or LE. */
5257
5258 static void
do_setend(str)5259 do_setend (str)
5260 char *str;
5261 {
5262 if (do_endian_specifier (str))
5263 inst.instruction |= 0x200;
5264 }
5265
5266 /* Returns true if the endian-specifier indicates big-endianness. */
5267
5268 static int
do_endian_specifier(str)5269 do_endian_specifier (str)
5270 char *str;
5271 {
5272 int big_endian = 0;
5273
5274 skip_whitespace (str);
5275 if (strlen (str) < 2)
5276 inst.error = _("missing endian specifier");
5277 else if (strncasecmp (str, "BE", 2) == 0)
5278 {
5279 str += 2;
5280 big_endian = 1;
5281 }
5282 else if (strncasecmp (str, "LE", 2) == 0)
5283 str += 2;
5284 else
5285 inst.error = _("valid endian specifiers are be or le");
5286
5287 end_of_line (str);
5288
5289 return big_endian;
5290 }
5291
5292 /* ARM V6 SXTH.
5293
5294 SXTH {<cond>} <Rd>, <Rm>{, <rotation>}
5295 Condition defaults to COND_ALWAYS.
5296 Error if any register uses R15. */
5297
5298 static void
do_sxth(str)5299 do_sxth (str)
5300 char *str;
5301 {
5302 int rd, rm;
5303 expressionS expr;
5304 int rotation_clear_mask = 0xfffff3ff;
5305 int rotation_eight_mask = 0x00000400;
5306 int rotation_sixteen_mask = 0x00000800;
5307 int rotation_twenty_four_mask = 0x00000c00;
5308
5309 skip_whitespace (str);
5310 if ((rd = reg_required_here (&str, 12)) == FAIL
5311 || skip_past_comma (&str) == FAIL
5312 || (rm = reg_required_here (&str, 0)) == FAIL)
5313 {
5314 inst.error = BAD_ARGS;
5315 return;
5316 }
5317
5318 else if (rd == REG_PC || rm == REG_PC)
5319 {
5320 inst.error = BAD_PC;
5321 return;
5322 }
5323
5324 /* Zero out the rotation field. */
5325 inst.instruction &= rotation_clear_mask;
5326
5327 /* Check for lack of optional rotation field. */
5328 if (skip_past_comma (&str) == FAIL)
5329 {
5330 end_of_line (str);
5331 return;
5332 }
5333
5334 /* Move past 'ROR'. */
5335 skip_whitespace (str);
5336 if (strncasecmp (str, "ROR", 3) == 0)
5337 str+=3;
5338 else
5339 {
5340 inst.error = _("missing rotation field after comma");
5341 return;
5342 }
5343
5344 /* Get the immediate constant. */
5345 skip_whitespace (str);
5346 if (is_immediate_prefix (* str))
5347 str++;
5348 else
5349 {
5350 inst.error = _("immediate expression expected");
5351 return;
5352 }
5353
5354 if (my_get_expression (&expr, &str))
5355 {
5356 inst.error = _("bad expression");
5357 return;
5358 }
5359
5360 if (expr.X_op != O_constant)
5361 {
5362 inst.error = _("constant expression expected");
5363 return;
5364 }
5365
5366 switch (expr.X_add_number)
5367 {
5368 case 0:
5369 /* Rotation field has already been zeroed. */
5370 break;
5371 case 8:
5372 inst.instruction |= rotation_eight_mask;
5373 break;
5374
5375 case 16:
5376 inst.instruction |= rotation_sixteen_mask;
5377 break;
5378
5379 case 24:
5380 inst.instruction |= rotation_twenty_four_mask;
5381 break;
5382
5383 default:
5384 inst.error = _("rotation can be 8, 16, 24 or 0 when field is ommited");
5385 break;
5386 }
5387
5388 end_of_line (str);
5389
5390 }
5391
5392 /* ARM V6 SXTAH extracts a 16-bit value from a register, sign
5393 extends it to 32-bits, and adds the result to a value in another
5394 register. You can specify a rotation by 0, 8, 16, or 24 bits
5395 before extracting the 16-bit value.
5396 SXTAH{<cond>} <Rd>, <Rn>, <Rm>{, <rotation>}
5397 Condition defaults to COND_ALWAYS.
5398 Error if any register uses R15. */
5399
5400 static void
do_sxtah(str)5401 do_sxtah (str)
5402 char *str;
5403 {
5404 int rd, rn, rm;
5405 expressionS expr;
5406 int rotation_clear_mask = 0xfffff3ff;
5407 int rotation_eight_mask = 0x00000400;
5408 int rotation_sixteen_mask = 0x00000800;
5409 int rotation_twenty_four_mask = 0x00000c00;
5410
5411 skip_whitespace (str);
5412 if ((rd = reg_required_here (&str, 12)) == FAIL
5413 || skip_past_comma (&str) == FAIL
5414 || (rn = reg_required_here (&str, 16)) == FAIL
5415 || skip_past_comma (&str) == FAIL
5416 || (rm = reg_required_here (&str, 0)) == FAIL)
5417 {
5418 inst.error = BAD_ARGS;
5419 return;
5420 }
5421
5422 else if (rd == REG_PC || rn == REG_PC || rm == REG_PC)
5423 {
5424 inst.error = BAD_PC;
5425 return;
5426 }
5427
5428 /* Zero out the rotation field. */
5429 inst.instruction &= rotation_clear_mask;
5430
5431 /* Check for lack of optional rotation field. */
5432 if (skip_past_comma (&str) == FAIL)
5433 {
5434 end_of_line (str);
5435 return;
5436 }
5437
5438 /* Move past 'ROR'. */
5439 skip_whitespace (str);
5440 if (strncasecmp (str, "ROR", 3) == 0)
5441 str+=3;
5442 else
5443 {
5444 inst.error = _("missing rotation field after comma");
5445 return;
5446 }
5447
5448 /* Get the immediate constant. */
5449 skip_whitespace (str);
5450 if (is_immediate_prefix (* str))
5451 str++;
5452 else
5453 {
5454 inst.error = _("immediate expression expected");
5455 return;
5456 }
5457
5458 if (my_get_expression (&expr, &str))
5459 {
5460 inst.error = _("bad expression");
5461 return;
5462 }
5463
5464 if (expr.X_op != O_constant)
5465 {
5466 inst.error = _("constant expression expected");
5467 return;
5468 }
5469
5470 switch (expr.X_add_number)
5471 {
5472 case 0:
5473 /* Rotation field has already been zeroed. */
5474 break;
5475
5476 case 8:
5477 inst.instruction |= rotation_eight_mask;
5478 break;
5479
5480 case 16:
5481 inst.instruction |= rotation_sixteen_mask;
5482 break;
5483
5484 case 24:
5485 inst.instruction |= rotation_twenty_four_mask;
5486 break;
5487
5488 default:
5489 inst.error = _("rotation can be 8, 16, 24 or 0 when field is ommited");
5490 break;
5491 }
5492
5493 end_of_line (str);
5494
5495 }
5496
5497
5498 /* ARM V6 RFE (Return from Exception) loads the PC and CPSR from the
5499 word at the specified address and the following word
5500 respectively.
5501 Unconditionally executed.
5502 Error if Rn is R15.
5503 */
5504
5505 static void
do_rfe(str)5506 do_rfe (str)
5507 char *str;
5508 {
5509 int rn;
5510
5511 skip_whitespace (str);
5512
5513 if ((rn = reg_required_here (&str, 16)) == FAIL)
5514 return;
5515
5516 if (rn == REG_PC)
5517 {
5518 inst.error = BAD_PC;
5519 return;
5520 }
5521
5522 skip_whitespace (str);
5523
5524 if (*str == '!')
5525 {
5526 inst.instruction |= WRITE_BACK;
5527 str++;
5528 }
5529 end_of_line (str);
5530 }
5531
5532 /* ARM V6 REV (Byte Reverse Word) reverses the byte order in a 32-bit
5533 register (argument parse).
5534 REV{<cond>} Rd, Rm.
5535 Condition defaults to COND_ALWAYS.
5536 Error if Rd or Rm are R15. */
5537
5538 static void
do_rev(str)5539 do_rev (str)
5540 char* str;
5541 {
5542 int rd, rm;
5543
5544 skip_whitespace (str);
5545
5546 if ((rd = reg_required_here (&str, 12)) == FAIL
5547 || skip_past_comma (&str) == FAIL
5548 || (rm = reg_required_here (&str, 0)) == FAIL)
5549 inst.error = BAD_ARGS;
5550
5551 else if (rd == REG_PC || rm == REG_PC)
5552 inst.error = BAD_PC;
5553
5554 else
5555 end_of_line (str);
5556 }
5557
5558 /* ARM V6 Perform Two Sixteen Bit Integer Additions. (argument parse).
5559 QADD16{<cond>} <Rd>, <Rn>, <Rm>
5560 Condition defaults to COND_ALWAYS.
5561 Error if Rd, Rn or Rm are R15. */
5562
5563 static void
do_qadd16(str)5564 do_qadd16 (str)
5565 char* str;
5566 {
5567 int rd, rm, rn;
5568
5569 skip_whitespace (str);
5570
5571 if ((rd = reg_required_here (&str, 12)) == FAIL
5572 || skip_past_comma (&str) == FAIL
5573 || (rn = reg_required_here (&str, 16)) == FAIL
5574 || skip_past_comma (&str) == FAIL
5575 || (rm = reg_required_here (&str, 0)) == FAIL)
5576 inst.error = BAD_ARGS;
5577
5578 else if (rd == REG_PC || rm == REG_PC || rn == REG_PC)
5579 inst.error = BAD_PC;
5580
5581 else
5582 end_of_line (str);
5583 }
5584
5585 /* ARM V6 Pack Halfword Bottom Top instruction (argument parse).
5586 PKHBT {<cond>} <Rd>, <Rn>, <Rm> {, LSL #<shift_imm>}
5587 Condition defaults to COND_ALWAYS.
5588 Error if Rd, Rn or Rm are R15. */
5589
5590 static void
do_pkhbt(str)5591 do_pkhbt (str)
5592 char* str;
5593 {
5594 do_pkh_core (str, SHIFT_LSL_IMMEDIATE);
5595 }
5596
5597 /* ARM V6 PKHTB (Argument Parse). */
5598
5599 static void
do_pkhtb(str)5600 do_pkhtb (str)
5601 char* str;
5602 {
5603 do_pkh_core (str, SHIFT_ASR_IMMEDIATE);
5604 }
5605
5606 static void
do_pkh_core(str,shift)5607 do_pkh_core (str, shift)
5608 char* str;
5609 int shift;
5610 {
5611 int rd, rn, rm;
5612
5613 skip_whitespace (str);
5614 if (((rd = reg_required_here (&str, 12)) == FAIL)
5615 || (skip_past_comma (&str) == FAIL)
5616 || ((rn = reg_required_here (&str, 16)) == FAIL)
5617 || (skip_past_comma (&str) == FAIL)
5618 || ((rm = reg_required_here (&str, 0)) == FAIL))
5619 {
5620 inst.error = BAD_ARGS;
5621 return;
5622 }
5623
5624 else if (rd == REG_PC || rn == REG_PC || rm == REG_PC)
5625 {
5626 inst.error = BAD_PC;
5627 return;
5628 }
5629
5630 /* Check for optional shift immediate constant. */
5631 if (skip_past_comma (&str) == FAIL)
5632 {
5633 if (shift == SHIFT_ASR_IMMEDIATE)
5634 {
5635 /* If the shift specifier is ommited, turn the instruction
5636 into pkhbt rd, rm, rn. First, switch the instruction
5637 code, and clear the rn and rm fields. */
5638 inst.instruction &= 0xfff0f010;
5639 /* Now, re-encode the registers. */
5640 inst.instruction |= (rm << 16) | rn;
5641 }
5642 return;
5643 }
5644
5645 decode_shift (&str, shift);
5646 }
5647
5648 /* ARM V6 Load Register Exclusive instruction (argument parse).
5649 LDREX{<cond>} <Rd, [<Rn>]
5650 Condition defaults to COND_ALWAYS.
5651 Error if Rd or Rn are R15.
5652 See ARMARMv6 A4.1.27: LDREX. */
5653
5654
5655 static void
do_ldrex(str)5656 do_ldrex (str)
5657 char * str;
5658 {
5659 int rd, rn;
5660
5661 skip_whitespace (str);
5662
5663 /* Parse Rd. */
5664 if (((rd = reg_required_here (&str, 12)) == FAIL)
5665 || (skip_past_comma (&str) == FAIL))
5666 {
5667 inst.error = BAD_ARGS;
5668 return;
5669 }
5670 else if (rd == REG_PC)
5671 {
5672 inst.error = BAD_PC;
5673 return;
5674 }
5675 skip_whitespace (str);
5676
5677 /* Skip past '['. */
5678 if ((strlen (str) >= 1)
5679 &&strncmp (str, "[", 1) == 0)
5680 str+=1;
5681 skip_whitespace (str);
5682
5683 /* Parse Rn. */
5684 if ((rn = reg_required_here (&str, 16)) == FAIL)
5685 {
5686 inst.error = BAD_ARGS;
5687 return;
5688 }
5689 else if (rn == REG_PC)
5690 {
5691 inst.error = BAD_PC;
5692 return;
5693 }
5694 skip_whitespace (str);
5695
5696 /* Skip past ']'. */
5697 if ((strlen (str) >= 1)
5698 && strncmp (str, "]", 1) == 0)
5699 str+=1;
5700
5701 end_of_line (str);
5702 }
5703
5704 /* ARM V6 change processor state instruction (argument parse)
5705 CPS, CPSIE, CSPID . */
5706
5707 static void
do_cps(str)5708 do_cps (str)
5709 char * str;
5710 {
5711 do_cps_mode (&str);
5712 end_of_line (str);
5713 }
5714
5715 static void
do_cpsi(str)5716 do_cpsi (str)
5717 char * str;
5718 {
5719 do_cps_flags (&str, /*thumb_p=*/0);
5720
5721 if (skip_past_comma (&str) == SUCCESS)
5722 {
5723 skip_whitespace (str);
5724 do_cps_mode (&str);
5725 }
5726 end_of_line (str);
5727 }
5728
5729 static void
do_cps_mode(str)5730 do_cps_mode (str)
5731 char **str;
5732 {
5733 expressionS expr;
5734
5735 skip_whitespace (*str);
5736
5737 if (! is_immediate_prefix (**str))
5738 {
5739 inst.error = _("immediate expression expected");
5740 return;
5741 }
5742
5743 (*str)++; /* Strip off the immediate signifier. */
5744 if (my_get_expression (&expr, str))
5745 {
5746 inst.error = _("bad expression");
5747 return;
5748 }
5749
5750 if (expr.X_op != O_constant)
5751 {
5752 inst.error = _("constant expression expected");
5753 return;
5754 }
5755
5756 /* The mode is a 5 bit field. Valid values are 0-31. */
5757 if (((unsigned) expr.X_add_number) > 31
5758 || (inst.reloc.exp.X_add_number) < 0)
5759 {
5760 inst.error = _("invalid constant");
5761 return;
5762 }
5763
5764 inst.instruction |= expr.X_add_number;
5765 }
5766
5767 static void
do_cps_flags(str,thumb_p)5768 do_cps_flags (str, thumb_p)
5769 char **str;
5770 int thumb_p;
5771 {
5772 struct cps_flag {
5773 char character;
5774 unsigned long arm_value;
5775 unsigned long thumb_value;
5776 };
5777 static struct cps_flag flag_table[] = {
5778 {'a', 0x100, 0x4 },
5779 {'i', 0x080, 0x2 },
5780 {'f', 0x040, 0x1 }
5781 };
5782
5783 int saw_a_flag = 0;
5784
5785 skip_whitespace (*str);
5786
5787 /* Get the a, f and i flags. */
5788 while (**str && **str != ',')
5789 {
5790 struct cps_flag *p;
5791 struct cps_flag *q = flag_table + sizeof (flag_table)/sizeof (*p);
5792 for (p = flag_table; p < q; ++p)
5793 if (strncasecmp (*str, &p->character, 1) == 0)
5794 {
5795 inst.instruction |= (thumb_p ? p->thumb_value : p->arm_value);
5796 saw_a_flag = 1;
5797 break;
5798 }
5799 if (p == q)
5800 {
5801 inst.error = _("unrecognized flag");
5802 return;
5803 }
5804 (*str)++;
5805 }
5806 if (!saw_a_flag)
5807 inst.error = _("no 'a', 'i', or 'f' flags for 'cps'");
5808 }
5809
5810 /* THUMB V5 breakpoint instruction (argument parse)
5811 BKPT <immed_8>. */
5812
5813 static void
do_t_bkpt(str)5814 do_t_bkpt (str)
5815 char * str;
5816 {
5817 expressionS expr;
5818 unsigned long number;
5819
5820 skip_whitespace (str);
5821
5822 /* Allow optional leading '#'. */
5823 if (is_immediate_prefix (*str))
5824 str ++;
5825
5826 memset (& expr, '\0', sizeof (expr));
5827 if (my_get_expression (& expr, & str)
5828 || (expr.X_op != O_constant
5829 /* As a convenience we allow 'bkpt' without an operand. */
5830 && expr.X_op != O_absent))
5831 {
5832 inst.error = _("bad expression");
5833 return;
5834 }
5835
5836 number = expr.X_add_number;
5837
5838 /* Check it fits an 8 bit unsigned. */
5839 if (number != (number & 0xff))
5840 {
5841 inst.error = _("immediate value out of range");
5842 return;
5843 }
5844
5845 inst.instruction |= number;
5846
5847 end_of_line (str);
5848 }
5849
5850 /* ARM V5 branch-link-exchange (argument parse) for BLX(1) only.
5851 Expects inst.instruction is set for BLX(1).
5852 Note: this is cloned from do_branch, and the reloc changed to be a
5853 new one that can cope with setting one extra bit (the H bit). */
5854
5855 static void
do_branch25(str)5856 do_branch25 (str)
5857 char * str;
5858 {
5859 if (my_get_expression (& inst.reloc.exp, & str))
5860 return;
5861
5862 #ifdef OBJ_ELF
5863 {
5864 char * save_in;
5865
5866 /* ScottB: February 5, 1998 */
5867 /* Check to see of PLT32 reloc required for the instruction. */
5868
5869 /* arm_parse_reloc() works on input_line_pointer.
5870 We actually want to parse the operands to the branch instruction
5871 passed in 'str'. Save the input pointer and restore it later. */
5872 save_in = input_line_pointer;
5873 input_line_pointer = str;
5874
5875 if (inst.reloc.exp.X_op == O_symbol
5876 && *str == '('
5877 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
5878 {
5879 inst.reloc.type = BFD_RELOC_ARM_PLT32;
5880 inst.reloc.pc_rel = 0;
5881 /* Modify str to point to after parsed operands, otherwise
5882 end_of_line() will complain about the (PLT) left in str. */
5883 str = input_line_pointer;
5884 }
5885 else
5886 {
5887 inst.reloc.type = BFD_RELOC_ARM_PCREL_BLX;
5888 inst.reloc.pc_rel = 1;
5889 }
5890
5891 input_line_pointer = save_in;
5892 }
5893 #else
5894 inst.reloc.type = BFD_RELOC_ARM_PCREL_BLX;
5895 inst.reloc.pc_rel = 1;
5896 #endif /* OBJ_ELF */
5897
5898 end_of_line (str);
5899 }
5900
5901 /* ARM V5 branch-link-exchange instruction (argument parse)
5902 BLX <target_addr> ie BLX(1)
5903 BLX{<condition>} <Rm> ie BLX(2)
5904 Unfortunately, there are two different opcodes for this mnemonic.
5905 So, the insns[].value is not used, and the code here zaps values
5906 into inst.instruction.
5907 Also, the <target_addr> can be 25 bits, hence has its own reloc. */
5908
5909 static void
do_blx(str)5910 do_blx (str)
5911 char * str;
5912 {
5913 char * mystr = str;
5914 int rm;
5915
5916 skip_whitespace (mystr);
5917 rm = reg_required_here (& mystr, 0);
5918
5919 /* The above may set inst.error. Ignore his opinion. */
5920 inst.error = 0;
5921
5922 if (rm != FAIL)
5923 {
5924 /* Arg is a register.
5925 Use the condition code our caller put in inst.instruction.
5926 Pass ourselves off as a BX with a funny opcode. */
5927 inst.instruction |= 0x012fff30;
5928 do_bx (str);
5929 }
5930 else
5931 {
5932 /* This must be is BLX <target address>, no condition allowed. */
5933 if (inst.instruction != COND_ALWAYS)
5934 {
5935 inst.error = BAD_COND;
5936 return;
5937 }
5938
5939 inst.instruction = 0xfafffffe;
5940
5941 /* Process like a B/BL, but with a different reloc.
5942 Note that B/BL expecte fffffe, not 0, offset in the opcode table. */
5943 do_branch25 (str);
5944 }
5945 }
5946
5947 /* ARM V5 Thumb BLX (argument parse)
5948 BLX <target_addr> which is BLX(1)
5949 BLX <Rm> which is BLX(2)
5950 Unfortunately, there are two different opcodes for this mnemonic.
5951 So, the tinsns[].value is not used, and the code here zaps values
5952 into inst.instruction. */
5953
5954 static void
do_t_blx(str)5955 do_t_blx (str)
5956 char * str;
5957 {
5958 char * mystr = str;
5959 int rm;
5960
5961 skip_whitespace (mystr);
5962 inst.instruction = 0x4780;
5963
5964 /* Note that this call is to the ARM register recognizer. BLX(2)
5965 uses the ARM register space, not the Thumb one, so a call to
5966 thumb_reg() would be wrong. */
5967 rm = reg_required_here (& mystr, 3);
5968 inst.error = 0;
5969
5970 if (rm != FAIL)
5971 {
5972 /* It's BLX(2). The .instruction was zapped with rm & is final. */
5973 inst.size = 2;
5974 }
5975 else
5976 {
5977 /* No ARM register. This must be BLX(1). Change the .instruction. */
5978 inst.instruction = 0xf7ffeffe;
5979 inst.size = 4;
5980
5981 if (my_get_expression (& inst.reloc.exp, & mystr))
5982 return;
5983
5984 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BLX;
5985 inst.reloc.pc_rel = 1;
5986 }
5987
5988 end_of_line (mystr);
5989 }
5990
5991 /* ARM V5 breakpoint instruction (argument parse)
5992 BKPT <16 bit unsigned immediate>
5993 Instruction is not conditional.
5994 The bit pattern given in insns[] has the COND_ALWAYS condition,
5995 and it is an error if the caller tried to override that. */
5996
5997 static void
do_bkpt(str)5998 do_bkpt (str)
5999 char * str;
6000 {
6001 expressionS expr;
6002 unsigned long number;
6003
6004 skip_whitespace (str);
6005
6006 /* Allow optional leading '#'. */
6007 if (is_immediate_prefix (* str))
6008 str++;
6009
6010 memset (& expr, '\0', sizeof (expr));
6011
6012 if (my_get_expression (& expr, & str)
6013 || (expr.X_op != O_constant
6014 /* As a convenience we allow 'bkpt' without an operand. */
6015 && expr.X_op != O_absent))
6016 {
6017 inst.error = _("bad expression");
6018 return;
6019 }
6020
6021 number = expr.X_add_number;
6022
6023 /* Check it fits a 16 bit unsigned. */
6024 if (number != (number & 0xffff))
6025 {
6026 inst.error = _("immediate value out of range");
6027 return;
6028 }
6029
6030 /* Top 12 of 16 bits to bits 19:8. */
6031 inst.instruction |= (number & 0xfff0) << 4;
6032
6033 /* Bottom 4 of 16 bits to bits 3:0. */
6034 inst.instruction |= number & 0xf;
6035
6036 end_of_line (str);
6037 }
6038
6039 /* THUMB CPS instruction (argument parse). */
6040
6041 static void
do_t_cps(str)6042 do_t_cps (str)
6043 char *str;
6044 {
6045 do_cps_flags (&str, /*thumb_p=*/1);
6046 end_of_line (str);
6047 }
6048
6049 /* THUMB CPY instruction (argument parse). */
6050
6051 static void
do_t_cpy(str)6052 do_t_cpy (str)
6053 char *str;
6054 {
6055 thumb_mov_compare (str, THUMB_CPY);
6056 }
6057
6058 /* THUMB SETEND instruction (argument parse). */
6059
6060 static void
do_t_setend(str)6061 do_t_setend (str)
6062 char *str;
6063 {
6064 if (do_endian_specifier (str))
6065 inst.instruction |= 0x8;
6066 }
6067
6068 static unsigned long check_iwmmxt_insn PARAMS ((char *, enum iwmmxt_insn_type, int));
6069
6070 /* Parse INSN_TYPE insn STR having a possible IMMEDIATE_SIZE immediate. */
6071
6072 static unsigned long
check_iwmmxt_insn(str,insn_type,immediate_size)6073 check_iwmmxt_insn (str, insn_type, immediate_size)
6074 char * str;
6075 enum iwmmxt_insn_type insn_type;
6076 int immediate_size;
6077 {
6078 int reg = 0;
6079 const char * inst_error;
6080 expressionS expr;
6081 unsigned long number;
6082
6083 inst_error = inst.error;
6084 if (!inst.error)
6085 inst.error = BAD_ARGS;
6086 skip_whitespace (str);
6087
6088 switch (insn_type)
6089 {
6090 case check_rd:
6091 if ((reg = reg_required_here (&str, 12)) == FAIL)
6092 return FAIL;
6093 break;
6094
6095 case check_wr:
6096 if ((wreg_required_here (&str, 0, IWMMXT_REG_WR)) == FAIL)
6097 return FAIL;
6098 break;
6099
6100 case check_wrwr:
6101 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
6102 || skip_past_comma (&str) == FAIL
6103 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL))
6104 return FAIL;
6105 break;
6106
6107 case check_wrwrwr:
6108 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
6109 || skip_past_comma (&str) == FAIL
6110 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6111 || skip_past_comma (&str) == FAIL
6112 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL))
6113 return FAIL;
6114 break;
6115
6116 case check_wrwrwcg:
6117 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
6118 || skip_past_comma (&str) == FAIL
6119 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6120 || skip_past_comma (&str) == FAIL
6121 || wreg_required_here (&str, 0, IWMMXT_REG_WCG) == FAIL))
6122 return FAIL;
6123 break;
6124
6125 case check_tbcst:
6126 if ((wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6127 || skip_past_comma (&str) == FAIL
6128 || reg_required_here (&str, 12) == FAIL))
6129 return FAIL;
6130 break;
6131
6132 case check_tmovmsk:
6133 if ((reg_required_here (&str, 12) == FAIL
6134 || skip_past_comma (&str) == FAIL
6135 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL))
6136 return FAIL;
6137 break;
6138
6139 case check_tmia:
6140 if ((wreg_required_here (&str, 5, IWMMXT_REG_WR) == FAIL
6141 || skip_past_comma (&str) == FAIL
6142 || reg_required_here (&str, 0) == FAIL
6143 || skip_past_comma (&str) == FAIL
6144 || reg_required_here (&str, 12) == FAIL))
6145 return FAIL;
6146 break;
6147
6148 case check_tmcrr:
6149 if ((wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL
6150 || skip_past_comma (&str) == FAIL
6151 || reg_required_here (&str, 12) == FAIL
6152 || skip_past_comma (&str) == FAIL
6153 || reg_required_here (&str, 16) == FAIL))
6154 return FAIL;
6155 break;
6156
6157 case check_tmrrc:
6158 if ((reg_required_here (&str, 12) == FAIL
6159 || skip_past_comma (&str) == FAIL
6160 || reg_required_here (&str, 16) == FAIL
6161 || skip_past_comma (&str) == FAIL
6162 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL))
6163 return FAIL;
6164 break;
6165
6166 case check_tmcr:
6167 if ((wreg_required_here (&str, 16, IWMMXT_REG_WC) == FAIL
6168 || skip_past_comma (&str) == FAIL
6169 || reg_required_here (&str, 12) == FAIL))
6170 return FAIL;
6171 break;
6172
6173 case check_tmrc:
6174 if ((reg_required_here (&str, 12) == FAIL
6175 || skip_past_comma (&str) == FAIL
6176 || wreg_required_here (&str, 16, IWMMXT_REG_WC) == FAIL))
6177 return FAIL;
6178 break;
6179
6180 case check_tinsr:
6181 if ((wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6182 || skip_past_comma (&str) == FAIL
6183 || reg_required_here (&str, 12) == FAIL
6184 || skip_past_comma (&str) == FAIL))
6185 return FAIL;
6186 break;
6187
6188 case check_textrc:
6189 if ((reg_required_here (&str, 12) == FAIL
6190 || skip_past_comma (&str) == FAIL))
6191 return FAIL;
6192 break;
6193
6194 case check_waligni:
6195 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
6196 || skip_past_comma (&str) == FAIL
6197 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6198 || skip_past_comma (&str) == FAIL
6199 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL
6200 || skip_past_comma (&str) == FAIL))
6201 return FAIL;
6202 break;
6203
6204 case check_textrm:
6205 if ((reg_required_here (&str, 12) == FAIL
6206 || skip_past_comma (&str) == FAIL
6207 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6208 || skip_past_comma (&str) == FAIL))
6209 return FAIL;
6210 break;
6211
6212 case check_wshufh:
6213 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
6214 || skip_past_comma (&str) == FAIL
6215 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6216 || skip_past_comma (&str) == FAIL))
6217 return FAIL;
6218 break;
6219 }
6220
6221 if (immediate_size == 0)
6222 {
6223 end_of_line (str);
6224 inst.error = inst_error;
6225 return reg;
6226 }
6227 else
6228 {
6229 skip_whitespace (str);
6230
6231 /* Allow optional leading '#'. */
6232 if (is_immediate_prefix (* str))
6233 str++;
6234
6235 memset (& expr, '\0', sizeof (expr));
6236
6237 if (my_get_expression (& expr, & str) || (expr.X_op != O_constant))
6238 {
6239 inst.error = _("bad or missing expression");
6240 return FAIL;
6241 }
6242
6243 number = expr.X_add_number;
6244
6245 if (number != (number & immediate_size))
6246 {
6247 inst.error = _("immediate value out of range");
6248 return FAIL;
6249 }
6250 end_of_line (str);
6251 inst.error = inst_error;
6252 return number;
6253 }
6254 }
6255
6256 static void
do_iwmmxt_byte_addr(str)6257 do_iwmmxt_byte_addr (str)
6258 char * str;
6259 {
6260 int op = (inst.instruction & 0x300) >> 8;
6261 int reg;
6262
6263 inst.instruction &= ~0x300;
6264 inst.instruction |= (op & 1) << 22 | (op & 2) << 7;
6265
6266 skip_whitespace (str);
6267
6268 if ((reg = wreg_required_here (&str, 12, IWMMXT_REG_WR_OR_WC)) == FAIL
6269 || skip_past_comma (& str) == FAIL
6270 || cp_byte_address_required_here (&str) == FAIL)
6271 {
6272 if (! inst.error)
6273 inst.error = BAD_ARGS;
6274 }
6275 else
6276 end_of_line (str);
6277
6278 if (wc_register (reg))
6279 {
6280 as_bad (_("non-word size not supported with control register"));
6281 inst.instruction |= 0xf0000100;
6282 inst.instruction &= ~0x00400000;
6283 }
6284 }
6285
6286 static void
do_iwmmxt_tandc(str)6287 do_iwmmxt_tandc (str)
6288 char * str;
6289 {
6290 int reg;
6291
6292 reg = check_iwmmxt_insn (str, check_rd, 0);
6293
6294 if (reg != REG_PC && !inst.error)
6295 inst.error = _("only r15 allowed here");
6296 }
6297
6298 static void
do_iwmmxt_tbcst(str)6299 do_iwmmxt_tbcst (str)
6300 char * str;
6301 {
6302 check_iwmmxt_insn (str, check_tbcst, 0);
6303 }
6304
6305 static void
do_iwmmxt_textrc(str)6306 do_iwmmxt_textrc (str)
6307 char * str;
6308 {
6309 unsigned long number;
6310
6311 if ((number = check_iwmmxt_insn (str, check_textrc, 7)) == (unsigned long) FAIL)
6312 return;
6313
6314 inst.instruction |= number & 0x7;
6315 }
6316
6317 static void
do_iwmmxt_textrm(str)6318 do_iwmmxt_textrm (str)
6319 char * str;
6320 {
6321 unsigned long number;
6322
6323 if ((number = check_iwmmxt_insn (str, check_textrm, 7)) == (unsigned long) FAIL)
6324 return;
6325
6326 inst.instruction |= number & 0x7;
6327 }
6328
6329 static void
do_iwmmxt_tinsr(str)6330 do_iwmmxt_tinsr (str)
6331 char * str;
6332 {
6333 unsigned long number;
6334
6335 if ((number = check_iwmmxt_insn (str, check_tinsr, 7)) == (unsigned long) FAIL)
6336 return;
6337
6338 inst.instruction |= number & 0x7;
6339 }
6340
6341 static void
do_iwmmxt_tmcr(str)6342 do_iwmmxt_tmcr (str)
6343 char * str;
6344 {
6345 check_iwmmxt_insn (str, check_tmcr, 0);
6346 }
6347
6348 static void
do_iwmmxt_tmcrr(str)6349 do_iwmmxt_tmcrr (str)
6350 char * str;
6351 {
6352 check_iwmmxt_insn (str, check_tmcrr, 0);
6353 }
6354
6355 static void
do_iwmmxt_tmia(str)6356 do_iwmmxt_tmia (str)
6357 char * str;
6358 {
6359 check_iwmmxt_insn (str, check_tmia, 0);
6360 }
6361
6362 static void
do_iwmmxt_tmovmsk(str)6363 do_iwmmxt_tmovmsk (str)
6364 char * str;
6365 {
6366 check_iwmmxt_insn (str, check_tmovmsk, 0);
6367 }
6368
6369 static void
do_iwmmxt_tmrc(str)6370 do_iwmmxt_tmrc (str)
6371 char * str;
6372 {
6373 check_iwmmxt_insn (str, check_tmrc, 0);
6374 }
6375
6376 static void
do_iwmmxt_tmrrc(str)6377 do_iwmmxt_tmrrc (str)
6378 char * str;
6379 {
6380 check_iwmmxt_insn (str, check_tmrrc, 0);
6381 }
6382
6383 static void
do_iwmmxt_torc(str)6384 do_iwmmxt_torc (str)
6385 char * str;
6386 {
6387 check_iwmmxt_insn (str, check_rd, 0);
6388 }
6389
6390 static void
do_iwmmxt_waligni(str)6391 do_iwmmxt_waligni (str)
6392 char * str;
6393 {
6394 unsigned long number;
6395
6396 if ((number = check_iwmmxt_insn (str, check_waligni, 7)) == (unsigned long) FAIL)
6397 return;
6398
6399 inst.instruction |= ((number & 0x7) << 20);
6400 }
6401
6402 static void
do_iwmmxt_wmov(str)6403 do_iwmmxt_wmov (str)
6404 char * str;
6405 {
6406 if (check_iwmmxt_insn (str, check_wrwr, 0) == (unsigned long) FAIL)
6407 return;
6408
6409 inst.instruction |= ((inst.instruction >> 16) & 0xf);
6410 }
6411
6412 static void
do_iwmmxt_word_addr(str)6413 do_iwmmxt_word_addr (str)
6414 char * str;
6415 {
6416 int op = (inst.instruction & 0x300) >> 8;
6417 int reg;
6418
6419 inst.instruction &= ~0x300;
6420 inst.instruction |= (op & 1) << 22 | (op & 2) << 7;
6421
6422 skip_whitespace (str);
6423
6424 if ((reg = wreg_required_here (&str, 12, IWMMXT_REG_WR_OR_WC)) == FAIL
6425 || skip_past_comma (& str) == FAIL
6426 || cp_address_required_here (& str, CP_WB_OK) == FAIL)
6427 {
6428 if (! inst.error)
6429 inst.error = BAD_ARGS;
6430 }
6431 else
6432 end_of_line (str);
6433
6434 if (wc_register (reg))
6435 {
6436 if ((inst.instruction & COND_MASK) != COND_ALWAYS)
6437 as_bad (_("conditional execution not supported with control register"));
6438 if (op != 2)
6439 as_bad (_("non-word size not supported with control register"));
6440 inst.instruction |= 0xf0000100;
6441 inst.instruction &= ~0x00400000;
6442 }
6443 }
6444
6445 static void
do_iwmmxt_wrwr(str)6446 do_iwmmxt_wrwr (str)
6447 char * str;
6448 {
6449 check_iwmmxt_insn (str, check_wrwr, 0);
6450 }
6451
6452 static void
do_iwmmxt_wrwrwcg(str)6453 do_iwmmxt_wrwrwcg (str)
6454 char * str;
6455 {
6456 check_iwmmxt_insn (str, check_wrwrwcg, 0);
6457 }
6458
6459 static void
do_iwmmxt_wrwrwr(str)6460 do_iwmmxt_wrwrwr (str)
6461 char * str;
6462 {
6463 check_iwmmxt_insn (str, check_wrwrwr, 0);
6464 }
6465
6466 static void
do_iwmmxt_wshufh(str)6467 do_iwmmxt_wshufh (str)
6468 char * str;
6469 {
6470 unsigned long number;
6471
6472 if ((number = check_iwmmxt_insn (str, check_wshufh, 0xff)) == (unsigned long) FAIL)
6473 return;
6474
6475 inst.instruction |= ((number & 0xf0) << 16) | (number & 0xf);
6476 }
6477
6478 static void
do_iwmmxt_wzero(str)6479 do_iwmmxt_wzero (str)
6480 char * str;
6481 {
6482 if (check_iwmmxt_insn (str, check_wr, 0) == (unsigned long) FAIL)
6483 return;
6484
6485 inst.instruction |= ((inst.instruction & 0xf) << 12) | ((inst.instruction & 0xf) << 16);
6486 }
6487
6488 /* Xscale multiply-accumulate (argument parse)
6489 MIAcc acc0,Rm,Rs
6490 MIAPHcc acc0,Rm,Rs
6491 MIAxycc acc0,Rm,Rs. */
6492
6493 static void
do_xsc_mia(str)6494 do_xsc_mia (str)
6495 char * str;
6496 {
6497 int rs;
6498 int rm;
6499
6500 if (accum0_required_here (& str) == FAIL)
6501 inst.error = ERR_NO_ACCUM;
6502
6503 else if (skip_past_comma (& str) == FAIL
6504 || (rm = reg_required_here (& str, 0)) == FAIL)
6505 inst.error = BAD_ARGS;
6506
6507 else if (skip_past_comma (& str) == FAIL
6508 || (rs = reg_required_here (& str, 12)) == FAIL)
6509 inst.error = BAD_ARGS;
6510
6511 /* inst.instruction has now been zapped with both rm and rs. */
6512 else if (rm == REG_PC || rs == REG_PC)
6513 inst.error = BAD_PC; /* Undefined result if rm or rs is R15. */
6514
6515 else
6516 end_of_line (str);
6517 }
6518
6519 /* Xscale move-accumulator-register (argument parse)
6520
6521 MARcc acc0,RdLo,RdHi. */
6522
6523 static void
do_xsc_mar(str)6524 do_xsc_mar (str)
6525 char * str;
6526 {
6527 int rdlo, rdhi;
6528
6529 if (accum0_required_here (& str) == FAIL)
6530 inst.error = ERR_NO_ACCUM;
6531
6532 else if (skip_past_comma (& str) == FAIL
6533 || (rdlo = reg_required_here (& str, 12)) == FAIL)
6534 inst.error = BAD_ARGS;
6535
6536 else if (skip_past_comma (& str) == FAIL
6537 || (rdhi = reg_required_here (& str, 16)) == FAIL)
6538 inst.error = BAD_ARGS;
6539
6540 /* inst.instruction has now been zapped with both rdlo and rdhi. */
6541 else if (rdlo == REG_PC || rdhi == REG_PC)
6542 inst.error = BAD_PC; /* Undefined result if rdlo or rdhi is R15. */
6543
6544 else
6545 end_of_line (str);
6546 }
6547
6548 /* Xscale move-register-accumulator (argument parse)
6549
6550 MRAcc RdLo,RdHi,acc0. */
6551
6552 static void
do_xsc_mra(str)6553 do_xsc_mra (str)
6554 char * str;
6555 {
6556 int rdlo;
6557 int rdhi;
6558
6559 skip_whitespace (str);
6560
6561 if ((rdlo = reg_required_here (& str, 12)) == FAIL)
6562 inst.error = BAD_ARGS;
6563
6564 else if (skip_past_comma (& str) == FAIL
6565 || (rdhi = reg_required_here (& str, 16)) == FAIL)
6566 inst.error = BAD_ARGS;
6567
6568 else if (skip_past_comma (& str) == FAIL
6569 || accum0_required_here (& str) == FAIL)
6570 inst.error = ERR_NO_ACCUM;
6571
6572 /* inst.instruction has now been zapped with both rdlo and rdhi. */
6573 else if (rdlo == rdhi)
6574 inst.error = BAD_ARGS; /* Undefined result if 2 writes to same reg. */
6575
6576 else if (rdlo == REG_PC || rdhi == REG_PC)
6577 inst.error = BAD_PC; /* Undefined result if rdlo or rdhi is R15. */
6578 else
6579 end_of_line (str);
6580 }
6581
6582 /* ARMv5TE: Preload-Cache
6583
6584 PLD <addr_mode>
6585
6586 Syntactically, like LDR with B=1, W=0, L=1. */
6587
6588 static void
do_pld(str)6589 do_pld (str)
6590 char * str;
6591 {
6592 int rd;
6593
6594 skip_whitespace (str);
6595
6596 if (* str != '[')
6597 {
6598 inst.error = _("'[' expected after PLD mnemonic");
6599 return;
6600 }
6601
6602 ++str;
6603 skip_whitespace (str);
6604
6605 if ((rd = reg_required_here (& str, 16)) == FAIL)
6606 return;
6607
6608 skip_whitespace (str);
6609
6610 if (*str == ']')
6611 {
6612 /* [Rn], ... ? */
6613 ++str;
6614 skip_whitespace (str);
6615
6616 /* Post-indexed addressing is not allowed with PLD. */
6617 if (skip_past_comma (&str) == SUCCESS)
6618 {
6619 inst.error
6620 = _("post-indexed expression used in preload instruction");
6621 return;
6622 }
6623 else if (*str == '!') /* [Rn]! */
6624 {
6625 inst.error = _("writeback used in preload instruction");
6626 ++str;
6627 }
6628 else /* [Rn] */
6629 inst.instruction |= INDEX_UP | PRE_INDEX;
6630 }
6631 else /* [Rn, ...] */
6632 {
6633 if (skip_past_comma (& str) == FAIL)
6634 {
6635 inst.error = _("pre-indexed expression expected");
6636 return;
6637 }
6638
6639 if (ldst_extend (&str) == FAIL)
6640 return;
6641
6642 skip_whitespace (str);
6643
6644 if (* str != ']')
6645 {
6646 inst.error = _("missing ]");
6647 return;
6648 }
6649
6650 ++ str;
6651 skip_whitespace (str);
6652
6653 if (* str == '!') /* [Rn]! */
6654 {
6655 inst.error = _("writeback used in preload instruction");
6656 ++ str;
6657 }
6658
6659 inst.instruction |= PRE_INDEX;
6660 }
6661
6662 end_of_line (str);
6663 }
6664
6665 /* ARMv5TE load-consecutive (argument parse)
6666 Mode is like LDRH.
6667
6668 LDRccD R, mode
6669 STRccD R, mode. */
6670
6671 static void
do_ldrd(str)6672 do_ldrd (str)
6673 char * str;
6674 {
6675 int rd;
6676 int rn;
6677
6678 skip_whitespace (str);
6679
6680 if ((rd = reg_required_here (& str, 12)) == FAIL)
6681 {
6682 inst.error = BAD_ARGS;
6683 return;
6684 }
6685
6686 if (skip_past_comma (& str) == FAIL
6687 || (rn = ld_mode_required_here (& str)) == FAIL)
6688 {
6689 if (!inst.error)
6690 inst.error = BAD_ARGS;
6691 return;
6692 }
6693
6694 /* inst.instruction has now been zapped with Rd and the addressing mode. */
6695 if (rd & 1) /* Unpredictable result if Rd is odd. */
6696 {
6697 inst.error = _("destination register must be even");
6698 return;
6699 }
6700
6701 if (rd == REG_LR)
6702 {
6703 inst.error = _("r14 not allowed here");
6704 return;
6705 }
6706
6707 if (((rd == rn) || (rd + 1 == rn))
6708 && ((inst.instruction & WRITE_BACK)
6709 || (!(inst.instruction & PRE_INDEX))))
6710 as_warn (_("pre/post-indexing used when modified address register is destination"));
6711
6712 /* For an index-register load, the index register must not overlap the
6713 destination (even if not write-back). */
6714 if ((inst.instruction & V4_STR_BIT) == 0
6715 && (inst.instruction & HWOFFSET_IMM) == 0)
6716 {
6717 int rm = inst.instruction & 0x0000000f;
6718
6719 if (rm == rd || (rm == rd + 1))
6720 as_warn (_("ldrd destination registers must not overlap index register"));
6721 }
6722
6723 end_of_line (str);
6724 }
6725
6726 /* Returns the index into fp_values of a floating point number,
6727 or -1 if not in the table. */
6728
6729 static int
my_get_float_expression(str)6730 my_get_float_expression (str)
6731 char ** str;
6732 {
6733 LITTLENUM_TYPE words[MAX_LITTLENUMS];
6734 char * save_in;
6735 expressionS exp;
6736 int i;
6737 int j;
6738
6739 memset (words, 0, MAX_LITTLENUMS * sizeof (LITTLENUM_TYPE));
6740
6741 /* Look for a raw floating point number. */
6742 if ((save_in = atof_ieee (*str, 'x', words)) != NULL
6743 && is_end_of_line[(unsigned char) *save_in])
6744 {
6745 for (i = 0; i < NUM_FLOAT_VALS; i++)
6746 {
6747 for (j = 0; j < MAX_LITTLENUMS; j++)
6748 {
6749 if (words[j] != fp_values[i][j])
6750 break;
6751 }
6752
6753 if (j == MAX_LITTLENUMS)
6754 {
6755 *str = save_in;
6756 return i;
6757 }
6758 }
6759 }
6760
6761 /* Try and parse a more complex expression, this will probably fail
6762 unless the code uses a floating point prefix (eg "0f"). */
6763 save_in = input_line_pointer;
6764 input_line_pointer = *str;
6765 if (expression (&exp) == absolute_section
6766 && exp.X_op == O_big
6767 && exp.X_add_number < 0)
6768 {
6769 /* FIXME: 5 = X_PRECISION, should be #define'd where we can use it.
6770 Ditto for 15. */
6771 if (gen_to_words (words, 5, (long) 15) == 0)
6772 {
6773 for (i = 0; i < NUM_FLOAT_VALS; i++)
6774 {
6775 for (j = 0; j < MAX_LITTLENUMS; j++)
6776 {
6777 if (words[j] != fp_values[i][j])
6778 break;
6779 }
6780
6781 if (j == MAX_LITTLENUMS)
6782 {
6783 *str = input_line_pointer;
6784 input_line_pointer = save_in;
6785 return i;
6786 }
6787 }
6788 }
6789 }
6790
6791 *str = input_line_pointer;
6792 input_line_pointer = save_in;
6793 return -1;
6794 }
6795
6796 /* Return TRUE if anything in the expression is a bignum. */
6797
6798 static int
walk_no_bignums(sp)6799 walk_no_bignums (sp)
6800 symbolS * sp;
6801 {
6802 if (symbol_get_value_expression (sp)->X_op == O_big)
6803 return 1;
6804
6805 if (symbol_get_value_expression (sp)->X_add_symbol)
6806 {
6807 return (walk_no_bignums (symbol_get_value_expression (sp)->X_add_symbol)
6808 || (symbol_get_value_expression (sp)->X_op_symbol
6809 && walk_no_bignums (symbol_get_value_expression (sp)->X_op_symbol)));
6810 }
6811
6812 return 0;
6813 }
6814
6815 static int in_my_get_expression = 0;
6816
6817 static int
my_get_expression(ep,str)6818 my_get_expression (ep, str)
6819 expressionS * ep;
6820 char ** str;
6821 {
6822 char * save_in;
6823 segT seg;
6824
6825 save_in = input_line_pointer;
6826 input_line_pointer = *str;
6827 in_my_get_expression = 1;
6828 seg = expression (ep);
6829 in_my_get_expression = 0;
6830
6831 if (ep->X_op == O_illegal)
6832 {
6833 /* We found a bad expression in md_operand(). */
6834 *str = input_line_pointer;
6835 input_line_pointer = save_in;
6836 return 1;
6837 }
6838
6839 #ifdef OBJ_AOUT
6840 if (seg != absolute_section
6841 && seg != text_section
6842 && seg != data_section
6843 && seg != bss_section
6844 && seg != undefined_section)
6845 {
6846 inst.error = _("bad_segment");
6847 *str = input_line_pointer;
6848 input_line_pointer = save_in;
6849 return 1;
6850 }
6851 #endif
6852
6853 /* Get rid of any bignums now, so that we don't generate an error for which
6854 we can't establish a line number later on. Big numbers are never valid
6855 in instructions, which is where this routine is always called. */
6856 if (ep->X_op == O_big
6857 || (ep->X_add_symbol
6858 && (walk_no_bignums (ep->X_add_symbol)
6859 || (ep->X_op_symbol
6860 && walk_no_bignums (ep->X_op_symbol)))))
6861 {
6862 inst.error = _("invalid constant");
6863 *str = input_line_pointer;
6864 input_line_pointer = save_in;
6865 return 1;
6866 }
6867
6868 *str = input_line_pointer;
6869 input_line_pointer = save_in;
6870 return 0;
6871 }
6872
6873 /* We handle all bad expressions here, so that we can report the faulty
6874 instruction in the error message. */
6875 void
md_operand(expr)6876 md_operand (expr)
6877 expressionS *expr;
6878 {
6879 if (in_my_get_expression)
6880 {
6881 expr->X_op = O_illegal;
6882 if (inst.error == NULL)
6883 inst.error = _("bad expression");
6884 }
6885 }
6886
6887 /* KIND indicates what kind of shifts are accepted. */
6888
6889 static int
decode_shift(str,kind)6890 decode_shift (str, kind)
6891 char ** str;
6892 int kind;
6893 {
6894 const struct asm_shift_name * shift;
6895 char * p;
6896 char c;
6897
6898 skip_whitespace (* str);
6899
6900 for (p = * str; ISALPHA (* p); p ++)
6901 ;
6902
6903 if (p == * str)
6904 {
6905 inst.error = _("shift expression expected");
6906 return FAIL;
6907 }
6908
6909 c = * p;
6910 * p = '\0';
6911 shift = (const struct asm_shift_name *) hash_find (arm_shift_hsh, * str);
6912 * p = c;
6913
6914 if (shift == NULL)
6915 {
6916 inst.error = _("shift expression expected");
6917 return FAIL;
6918 }
6919
6920 assert (shift->properties->index == shift_properties[shift->properties->index].index);
6921
6922 if (kind == SHIFT_LSL_OR_ASR_IMMEDIATE
6923 && shift->properties->index != SHIFT_LSL
6924 && shift->properties->index != SHIFT_ASR)
6925 {
6926 inst.error = _("'LSL' or 'ASR' required");
6927 return FAIL;
6928 }
6929 else if (kind == SHIFT_LSL_IMMEDIATE
6930 && shift->properties->index != SHIFT_LSL)
6931 {
6932 inst.error = _("'LSL' required");
6933 return FAIL;
6934 }
6935 else if (kind == SHIFT_ASR_IMMEDIATE
6936 && shift->properties->index != SHIFT_ASR)
6937 {
6938 inst.error = _("'ASR' required");
6939 return FAIL;
6940 }
6941
6942 if (shift->properties->index == SHIFT_RRX)
6943 {
6944 * str = p;
6945 inst.instruction |= shift->properties->bit_field;
6946 return SUCCESS;
6947 }
6948
6949 skip_whitespace (p);
6950
6951 if (kind == NO_SHIFT_RESTRICT && reg_required_here (& p, 8) != FAIL)
6952 {
6953 inst.instruction |= shift->properties->bit_field | SHIFT_BY_REG;
6954 * str = p;
6955 return SUCCESS;
6956 }
6957 else if (! is_immediate_prefix (* p))
6958 {
6959 inst.error = (NO_SHIFT_RESTRICT
6960 ? _("shift requires register or #expression")
6961 : _("shift requires #expression"));
6962 * str = p;
6963 return FAIL;
6964 }
6965
6966 inst.error = NULL;
6967 p ++;
6968
6969 if (my_get_expression (& inst.reloc.exp, & p))
6970 return FAIL;
6971
6972 /* Validate some simple #expressions. */
6973 if (inst.reloc.exp.X_op == O_constant)
6974 {
6975 unsigned num = inst.reloc.exp.X_add_number;
6976
6977 /* Reject operations greater than 32. */
6978 if (num > 32
6979 /* Reject a shift of 0 unless the mode allows it. */
6980 || (num == 0 && shift->properties->allows_0 == 0)
6981 /* Reject a shift of 32 unless the mode allows it. */
6982 || (num == 32 && shift->properties->allows_32 == 0)
6983 )
6984 {
6985 /* As a special case we allow a shift of zero for
6986 modes that do not support it to be recoded as an
6987 logical shift left of zero (ie nothing). We warn
6988 about this though. */
6989 if (num == 0)
6990 {
6991 as_warn (_("shift of 0 ignored."));
6992 shift = & shift_names[0];
6993 assert (shift->properties->index == SHIFT_LSL);
6994 }
6995 else
6996 {
6997 inst.error = _("invalid immediate shift");
6998 return FAIL;
6999 }
7000 }
7001
7002 /* Shifts of 32 are encoded as 0, for those shifts that
7003 support it. */
7004 if (num == 32)
7005 num = 0;
7006
7007 inst.instruction |= (num << 7) | shift->properties->bit_field;
7008 }
7009 else
7010 {
7011 inst.reloc.type = BFD_RELOC_ARM_SHIFT_IMM;
7012 inst.reloc.pc_rel = 0;
7013 inst.instruction |= shift->properties->bit_field;
7014 }
7015
7016 * str = p;
7017 return SUCCESS;
7018 }
7019
7020 /* Do those data_ops which can take a negative immediate constant
7021 by altering the instruction. A bit of a hack really.
7022 MOV <-> MVN
7023 AND <-> BIC
7024 ADC <-> SBC
7025 by inverting the second operand, and
7026 ADD <-> SUB
7027 CMP <-> CMN
7028 by negating the second operand. */
7029
7030 static int
negate_data_op(instruction,value)7031 negate_data_op (instruction, value)
7032 unsigned long * instruction;
7033 unsigned long value;
7034 {
7035 int op, new_inst;
7036 unsigned long negated, inverted;
7037
7038 negated = validate_immediate (-value);
7039 inverted = validate_immediate (~value);
7040
7041 op = (*instruction >> DATA_OP_SHIFT) & 0xf;
7042 switch (op)
7043 {
7044 /* First negates. */
7045 case OPCODE_SUB: /* ADD <-> SUB */
7046 new_inst = OPCODE_ADD;
7047 value = negated;
7048 break;
7049
7050 case OPCODE_ADD:
7051 new_inst = OPCODE_SUB;
7052 value = negated;
7053 break;
7054
7055 case OPCODE_CMP: /* CMP <-> CMN */
7056 new_inst = OPCODE_CMN;
7057 value = negated;
7058 break;
7059
7060 case OPCODE_CMN:
7061 new_inst = OPCODE_CMP;
7062 value = negated;
7063 break;
7064
7065 /* Now Inverted ops. */
7066 case OPCODE_MOV: /* MOV <-> MVN */
7067 new_inst = OPCODE_MVN;
7068 value = inverted;
7069 break;
7070
7071 case OPCODE_MVN:
7072 new_inst = OPCODE_MOV;
7073 value = inverted;
7074 break;
7075
7076 case OPCODE_AND: /* AND <-> BIC */
7077 new_inst = OPCODE_BIC;
7078 value = inverted;
7079 break;
7080
7081 case OPCODE_BIC:
7082 new_inst = OPCODE_AND;
7083 value = inverted;
7084 break;
7085
7086 case OPCODE_ADC: /* ADC <-> SBC */
7087 new_inst = OPCODE_SBC;
7088 value = inverted;
7089 break;
7090
7091 case OPCODE_SBC:
7092 new_inst = OPCODE_ADC;
7093 value = inverted;
7094 break;
7095
7096 /* We cannot do anything. */
7097 default:
7098 return FAIL;
7099 }
7100
7101 if (value == (unsigned) FAIL)
7102 return FAIL;
7103
7104 *instruction &= OPCODE_MASK;
7105 *instruction |= new_inst << DATA_OP_SHIFT;
7106 return value;
7107 }
7108
7109 static int
data_op2(str)7110 data_op2 (str)
7111 char ** str;
7112 {
7113 int value;
7114 expressionS expr;
7115
7116 skip_whitespace (* str);
7117
7118 if (reg_required_here (str, 0) != FAIL)
7119 {
7120 if (skip_past_comma (str) == SUCCESS)
7121 /* Shift operation on register. */
7122 return decode_shift (str, NO_SHIFT_RESTRICT);
7123
7124 return SUCCESS;
7125 }
7126 else
7127 {
7128 /* Immediate expression. */
7129 if (is_immediate_prefix (**str))
7130 {
7131 (*str)++;
7132 inst.error = NULL;
7133
7134 if (my_get_expression (&inst.reloc.exp, str))
7135 return FAIL;
7136
7137 if (inst.reloc.exp.X_add_symbol)
7138 {
7139 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
7140 inst.reloc.pc_rel = 0;
7141 }
7142 else
7143 {
7144 if (skip_past_comma (str) == SUCCESS)
7145 {
7146 /* #x, y -- ie explicit rotation by Y. */
7147 if (my_get_expression (&expr, str))
7148 return FAIL;
7149
7150 if (expr.X_op != O_constant)
7151 {
7152 inst.error = _("constant expression expected");
7153 return FAIL;
7154 }
7155
7156 /* Rotate must be a multiple of 2. */
7157 if (((unsigned) expr.X_add_number) > 30
7158 || (expr.X_add_number & 1) != 0
7159 || ((unsigned) inst.reloc.exp.X_add_number) > 255)
7160 {
7161 inst.error = _("invalid constant");
7162 return FAIL;
7163 }
7164 inst.instruction |= INST_IMMEDIATE;
7165 inst.instruction |= inst.reloc.exp.X_add_number;
7166 inst.instruction |= expr.X_add_number << 7;
7167 return SUCCESS;
7168 }
7169
7170 /* Implicit rotation, select a suitable one. */
7171 value = validate_immediate (inst.reloc.exp.X_add_number);
7172
7173 if (value == FAIL)
7174 {
7175 /* Can't be done. Perhaps the code reads something like
7176 "add Rd, Rn, #-n", where "sub Rd, Rn, #n" would be OK. */
7177 if ((value = negate_data_op (&inst.instruction,
7178 inst.reloc.exp.X_add_number))
7179 == FAIL)
7180 {
7181 inst.error = _("invalid constant");
7182 return FAIL;
7183 }
7184 }
7185
7186 inst.instruction |= value;
7187 }
7188
7189 inst.instruction |= INST_IMMEDIATE;
7190 return SUCCESS;
7191 }
7192
7193 (*str)++;
7194 inst.error = _("register or shift expression expected");
7195 return FAIL;
7196 }
7197 }
7198
7199 static int
fp_op2(str)7200 fp_op2 (str)
7201 char ** str;
7202 {
7203 skip_whitespace (* str);
7204
7205 if (fp_reg_required_here (str, 0) != FAIL)
7206 return SUCCESS;
7207 else
7208 {
7209 /* Immediate expression. */
7210 if (*((*str)++) == '#')
7211 {
7212 int i;
7213
7214 inst.error = NULL;
7215
7216 skip_whitespace (* str);
7217
7218 /* First try and match exact strings, this is to guarantee
7219 that some formats will work even for cross assembly. */
7220
7221 for (i = 0; fp_const[i]; i++)
7222 {
7223 if (strncmp (*str, fp_const[i], strlen (fp_const[i])) == 0)
7224 {
7225 char *start = *str;
7226
7227 *str += strlen (fp_const[i]);
7228 if (is_end_of_line[(unsigned char) **str])
7229 {
7230 inst.instruction |= i + 8;
7231 return SUCCESS;
7232 }
7233 *str = start;
7234 }
7235 }
7236
7237 /* Just because we didn't get a match doesn't mean that the
7238 constant isn't valid, just that it is in a format that we
7239 don't automatically recognize. Try parsing it with
7240 the standard expression routines. */
7241 if ((i = my_get_float_expression (str)) >= 0)
7242 {
7243 inst.instruction |= i + 8;
7244 return SUCCESS;
7245 }
7246
7247 inst.error = _("invalid floating point immediate expression");
7248 return FAIL;
7249 }
7250 inst.error =
7251 _("floating point register or immediate expression expected");
7252 return FAIL;
7253 }
7254 }
7255
7256 static void
do_arit(str)7257 do_arit (str)
7258 char * str;
7259 {
7260 skip_whitespace (str);
7261
7262 if (reg_required_here (&str, 12) == FAIL
7263 || skip_past_comma (&str) == FAIL
7264 || reg_required_here (&str, 16) == FAIL
7265 || skip_past_comma (&str) == FAIL
7266 || data_op2 (&str) == FAIL)
7267 {
7268 if (!inst.error)
7269 inst.error = BAD_ARGS;
7270 return;
7271 }
7272
7273 end_of_line (str);
7274 }
7275
7276 static void
do_adr(str)7277 do_adr (str)
7278 char * str;
7279 {
7280 /* This is a pseudo-op of the form "adr rd, label" to be converted
7281 into a relative address of the form "add rd, pc, #label-.-8". */
7282 skip_whitespace (str);
7283
7284 if (reg_required_here (&str, 12) == FAIL
7285 || skip_past_comma (&str) == FAIL
7286 || my_get_expression (&inst.reloc.exp, &str))
7287 {
7288 if (!inst.error)
7289 inst.error = BAD_ARGS;
7290 return;
7291 }
7292
7293 /* Frag hacking will turn this into a sub instruction if the offset turns
7294 out to be negative. */
7295 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
7296 #ifndef TE_WINCE
7297 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust. */
7298 #endif
7299 inst.reloc.pc_rel = 1;
7300
7301 end_of_line (str);
7302 }
7303
7304 static void
do_adrl(str)7305 do_adrl (str)
7306 char * str;
7307 {
7308 /* This is a pseudo-op of the form "adrl rd, label" to be converted
7309 into a relative address of the form:
7310 add rd, pc, #low(label-.-8)"
7311 add rd, rd, #high(label-.-8)" */
7312
7313 skip_whitespace (str);
7314
7315 if (reg_required_here (&str, 12) == FAIL
7316 || skip_past_comma (&str) == FAIL
7317 || my_get_expression (&inst.reloc.exp, &str))
7318 {
7319 if (!inst.error)
7320 inst.error = BAD_ARGS;
7321
7322 return;
7323 }
7324
7325 end_of_line (str);
7326 /* Frag hacking will turn this into a sub instruction if the offset turns
7327 out to be negative. */
7328 inst.reloc.type = BFD_RELOC_ARM_ADRL_IMMEDIATE;
7329 #ifndef TE_WINCE
7330 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust */
7331 #endif
7332 inst.reloc.pc_rel = 1;
7333 inst.size = INSN_SIZE * 2;
7334 }
7335
7336 static void
do_cmp(str)7337 do_cmp (str)
7338 char * str;
7339 {
7340 skip_whitespace (str);
7341
7342 if (reg_required_here (&str, 16) == FAIL)
7343 {
7344 if (!inst.error)
7345 inst.error = BAD_ARGS;
7346 return;
7347 }
7348
7349 if (skip_past_comma (&str) == FAIL
7350 || data_op2 (&str) == FAIL)
7351 {
7352 if (!inst.error)
7353 inst.error = BAD_ARGS;
7354 return;
7355 }
7356
7357 end_of_line (str);
7358 }
7359
7360 static void
do_mov(str)7361 do_mov (str)
7362 char * str;
7363 {
7364 skip_whitespace (str);
7365
7366 if (reg_required_here (&str, 12) == FAIL)
7367 {
7368 if (!inst.error)
7369 inst.error = BAD_ARGS;
7370 return;
7371 }
7372
7373 if (skip_past_comma (&str) == FAIL
7374 || data_op2 (&str) == FAIL)
7375 {
7376 if (!inst.error)
7377 inst.error = BAD_ARGS;
7378 return;
7379 }
7380
7381 end_of_line (str);
7382 }
7383
7384 static int
ldst_extend(str)7385 ldst_extend (str)
7386 char ** str;
7387 {
7388 int add = INDEX_UP;
7389
7390 switch (**str)
7391 {
7392 case '#':
7393 case '$':
7394 (*str)++;
7395 if (my_get_expression (& inst.reloc.exp, str))
7396 return FAIL;
7397
7398 if (inst.reloc.exp.X_op == O_constant)
7399 {
7400 int value = inst.reloc.exp.X_add_number;
7401
7402 if (value < -4095 || value > 4095)
7403 {
7404 inst.error = _("address offset too large");
7405 return FAIL;
7406 }
7407
7408 if (value < 0)
7409 {
7410 value = -value;
7411 add = 0;
7412 }
7413
7414 inst.instruction |= add | value;
7415 }
7416 else
7417 {
7418 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
7419 inst.reloc.pc_rel = 0;
7420 }
7421 return SUCCESS;
7422
7423 case '-':
7424 add = 0;
7425 /* Fall through. */
7426
7427 case '+':
7428 (*str)++;
7429 /* Fall through. */
7430
7431 default:
7432 if (reg_required_here (str, 0) == FAIL)
7433 return FAIL;
7434
7435 inst.instruction |= add | OFFSET_REG;
7436 if (skip_past_comma (str) == SUCCESS)
7437 return decode_shift (str, SHIFT_IMMEDIATE);
7438
7439 return SUCCESS;
7440 }
7441 }
7442
7443 static void
do_ldst(str)7444 do_ldst (str)
7445 char * str;
7446 {
7447 int pre_inc = 0;
7448 int conflict_reg;
7449 int value;
7450
7451 skip_whitespace (str);
7452
7453 if ((conflict_reg = reg_required_here (&str, 12)) == FAIL)
7454 {
7455 if (!inst.error)
7456 inst.error = BAD_ARGS;
7457 return;
7458 }
7459
7460 if (skip_past_comma (&str) == FAIL)
7461 {
7462 inst.error = _("address expected");
7463 return;
7464 }
7465
7466 if (*str == '[')
7467 {
7468 int reg;
7469
7470 str++;
7471
7472 skip_whitespace (str);
7473
7474 if ((reg = reg_required_here (&str, 16)) == FAIL)
7475 return;
7476
7477 /* Conflicts can occur on stores as well as loads. */
7478 conflict_reg = (conflict_reg == reg);
7479
7480 skip_whitespace (str);
7481
7482 if (*str == ']')
7483 {
7484 str ++;
7485
7486 if (skip_past_comma (&str) == SUCCESS)
7487 {
7488 /* [Rn],... (post inc) */
7489 if (ldst_extend (&str) == FAIL)
7490 return;
7491 if (conflict_reg)
7492 as_warn (_("%s register same as write-back base"),
7493 ((inst.instruction & LOAD_BIT)
7494 ? _("destination") : _("source")));
7495 }
7496 else
7497 {
7498 /* [Rn] */
7499 skip_whitespace (str);
7500
7501 if (*str == '!')
7502 {
7503 if (conflict_reg)
7504 as_warn (_("%s register same as write-back base"),
7505 ((inst.instruction & LOAD_BIT)
7506 ? _("destination") : _("source")));
7507 str++;
7508 inst.instruction |= WRITE_BACK;
7509 }
7510
7511 inst.instruction |= INDEX_UP;
7512 pre_inc = 1;
7513 }
7514 }
7515 else
7516 {
7517 /* [Rn,...] */
7518 if (skip_past_comma (&str) == FAIL)
7519 {
7520 inst.error = _("pre-indexed expression expected");
7521 return;
7522 }
7523
7524 pre_inc = 1;
7525 if (ldst_extend (&str) == FAIL)
7526 return;
7527
7528 skip_whitespace (str);
7529
7530 if (*str++ != ']')
7531 {
7532 inst.error = _("missing ]");
7533 return;
7534 }
7535
7536 skip_whitespace (str);
7537
7538 if (*str == '!')
7539 {
7540 if (conflict_reg)
7541 as_warn (_("%s register same as write-back base"),
7542 ((inst.instruction & LOAD_BIT)
7543 ? _("destination") : _("source")));
7544 str++;
7545 inst.instruction |= WRITE_BACK;
7546 }
7547 }
7548 }
7549 else if (*str == '=')
7550 {
7551 if ((inst.instruction & LOAD_BIT) == 0)
7552 {
7553 inst.error = _("invalid pseudo operation");
7554 return;
7555 }
7556
7557 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
7558 str++;
7559
7560 skip_whitespace (str);
7561
7562 if (my_get_expression (&inst.reloc.exp, &str))
7563 return;
7564
7565 if (inst.reloc.exp.X_op != O_constant
7566 && inst.reloc.exp.X_op != O_symbol)
7567 {
7568 inst.error = _("constant expression expected");
7569 return;
7570 }
7571
7572 if (inst.reloc.exp.X_op == O_constant)
7573 {
7574 value = validate_immediate (inst.reloc.exp.X_add_number);
7575
7576 if (value != FAIL)
7577 {
7578 /* This can be done with a mov instruction. */
7579 inst.instruction &= LITERAL_MASK;
7580 inst.instruction |= (INST_IMMEDIATE
7581 | (OPCODE_MOV << DATA_OP_SHIFT));
7582 inst.instruction |= value & 0xfff;
7583 end_of_line (str);
7584 return;
7585 }
7586
7587 value = validate_immediate (~inst.reloc.exp.X_add_number);
7588
7589 if (value != FAIL)
7590 {
7591 /* This can be done with a mvn instruction. */
7592 inst.instruction &= LITERAL_MASK;
7593 inst.instruction |= (INST_IMMEDIATE
7594 | (OPCODE_MVN << DATA_OP_SHIFT));
7595 inst.instruction |= value & 0xfff;
7596 end_of_line (str);
7597 return;
7598 }
7599 }
7600
7601 /* Insert into literal pool. */
7602 if (add_to_lit_pool () == FAIL)
7603 {
7604 if (!inst.error)
7605 inst.error = _("literal pool insertion failed");
7606 return;
7607 }
7608
7609 /* Change the instruction exp to point to the pool. */
7610 inst.reloc.type = BFD_RELOC_ARM_LITERAL;
7611 inst.reloc.pc_rel = 1;
7612 inst.instruction |= (REG_PC << 16);
7613 pre_inc = 1;
7614 }
7615 else
7616 {
7617 if (my_get_expression (&inst.reloc.exp, &str))
7618 return;
7619
7620 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
7621 #ifndef TE_WINCE
7622 /* PC rel adjust. */
7623 inst.reloc.exp.X_add_number -= 8;
7624 #endif
7625 inst.reloc.pc_rel = 1;
7626 inst.instruction |= (REG_PC << 16);
7627 pre_inc = 1;
7628 }
7629
7630 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
7631 end_of_line (str);
7632 }
7633
7634 static void
do_ldstt(str)7635 do_ldstt (str)
7636 char * str;
7637 {
7638 int conflict_reg;
7639
7640 skip_whitespace (str);
7641
7642 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
7643 {
7644 if (!inst.error)
7645 inst.error = BAD_ARGS;
7646 return;
7647 }
7648
7649 if (skip_past_comma (& str) == FAIL)
7650 {
7651 inst.error = _("address expected");
7652 return;
7653 }
7654
7655 if (*str == '[')
7656 {
7657 int reg;
7658
7659 str++;
7660
7661 skip_whitespace (str);
7662
7663 if ((reg = reg_required_here (&str, 16)) == FAIL)
7664 return;
7665
7666 /* ldrt/strt always use post-indexed addressing, so if the base is
7667 the same as Rd, we warn. */
7668 if (conflict_reg == reg)
7669 as_warn (_("%s register same as write-back base"),
7670 ((inst.instruction & LOAD_BIT)
7671 ? _("destination") : _("source")));
7672
7673 skip_whitespace (str);
7674
7675 if (*str == ']')
7676 {
7677 str ++;
7678
7679 if (skip_past_comma (&str) == SUCCESS)
7680 {
7681 /* [Rn],... (post inc) */
7682 if (ldst_extend (&str) == FAIL)
7683 return;
7684 }
7685 else
7686 {
7687 /* [Rn] */
7688 skip_whitespace (str);
7689
7690 /* Skip a write-back '!'. */
7691 if (*str == '!')
7692 str++;
7693
7694 inst.instruction |= INDEX_UP;
7695 }
7696 }
7697 else
7698 {
7699 inst.error = _("post-indexed expression expected");
7700 return;
7701 }
7702 }
7703 else
7704 {
7705 inst.error = _("post-indexed expression expected");
7706 return;
7707 }
7708
7709 end_of_line (str);
7710 }
7711
7712 static int
ldst_extend_v4(str)7713 ldst_extend_v4 (str)
7714 char ** str;
7715 {
7716 int add = INDEX_UP;
7717
7718 switch (**str)
7719 {
7720 case '#':
7721 case '$':
7722 (*str)++;
7723 if (my_get_expression (& inst.reloc.exp, str))
7724 return FAIL;
7725
7726 if (inst.reloc.exp.X_op == O_constant)
7727 {
7728 int value = inst.reloc.exp.X_add_number;
7729
7730 if (value < -255 || value > 255)
7731 {
7732 inst.error = _("address offset too large");
7733 return FAIL;
7734 }
7735
7736 if (value < 0)
7737 {
7738 value = -value;
7739 add = 0;
7740 }
7741
7742 /* Halfword and signextension instructions have the
7743 immediate value split across bits 11..8 and bits 3..0. */
7744 inst.instruction |= (add | HWOFFSET_IMM
7745 | ((value >> 4) << 8) | (value & 0xF));
7746 }
7747 else
7748 {
7749 inst.instruction |= HWOFFSET_IMM;
7750 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
7751 inst.reloc.pc_rel = 0;
7752 }
7753 return SUCCESS;
7754
7755 case '-':
7756 add = 0;
7757 /* Fall through. */
7758
7759 case '+':
7760 (*str)++;
7761 /* Fall through. */
7762
7763 default:
7764 if (reg_required_here (str, 0) == FAIL)
7765 return FAIL;
7766
7767 inst.instruction |= add;
7768 return SUCCESS;
7769 }
7770 }
7771
7772 /* Halfword and signed-byte load/store operations. */
7773 static void
do_ldstv4(str)7774 do_ldstv4 (str)
7775 char * str;
7776 {
7777 int pre_inc = 0;
7778 int conflict_reg;
7779 int value;
7780
7781 skip_whitespace (str);
7782
7783 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
7784 {
7785 if (!inst.error)
7786 inst.error = BAD_ARGS;
7787 return;
7788 }
7789
7790 if (skip_past_comma (& str) == FAIL)
7791 {
7792 inst.error = _("address expected");
7793 return;
7794 }
7795
7796 if (*str == '[')
7797 {
7798 int reg;
7799
7800 str++;
7801
7802 skip_whitespace (str);
7803
7804 if ((reg = reg_required_here (&str, 16)) == FAIL)
7805 return;
7806
7807 /* Conflicts can occur on stores as well as loads. */
7808 conflict_reg = (conflict_reg == reg);
7809
7810 skip_whitespace (str);
7811
7812 if (*str == ']')
7813 {
7814 str ++;
7815
7816 if (skip_past_comma (&str) == SUCCESS)
7817 {
7818 /* [Rn],... (post inc) */
7819 if (ldst_extend_v4 (&str) == FAIL)
7820 return;
7821 if (conflict_reg)
7822 as_warn (_("%s register same as write-back base"),
7823 ((inst.instruction & LOAD_BIT)
7824 ? _("destination") : _("source")));
7825 }
7826 else
7827 {
7828 /* [Rn] */
7829 inst.instruction |= HWOFFSET_IMM;
7830
7831 skip_whitespace (str);
7832
7833 if (*str == '!')
7834 {
7835 if (conflict_reg)
7836 as_warn (_("%s register same as write-back base"),
7837 ((inst.instruction & LOAD_BIT)
7838 ? _("destination") : _("source")));
7839 str++;
7840 inst.instruction |= WRITE_BACK;
7841 }
7842
7843 inst.instruction |= INDEX_UP;
7844 pre_inc = 1;
7845 }
7846 }
7847 else
7848 {
7849 /* [Rn,...] */
7850 if (skip_past_comma (&str) == FAIL)
7851 {
7852 inst.error = _("pre-indexed expression expected");
7853 return;
7854 }
7855
7856 pre_inc = 1;
7857 if (ldst_extend_v4 (&str) == FAIL)
7858 return;
7859
7860 skip_whitespace (str);
7861
7862 if (*str++ != ']')
7863 {
7864 inst.error = _("missing ]");
7865 return;
7866 }
7867
7868 skip_whitespace (str);
7869
7870 if (*str == '!')
7871 {
7872 if (conflict_reg)
7873 as_warn (_("%s register same as write-back base"),
7874 ((inst.instruction & LOAD_BIT)
7875 ? _("destination") : _("source")));
7876 str++;
7877 inst.instruction |= WRITE_BACK;
7878 }
7879 }
7880 }
7881 else if (*str == '=')
7882 {
7883 if ((inst.instruction & LOAD_BIT) == 0)
7884 {
7885 inst.error = _("invalid pseudo operation");
7886 return;
7887 }
7888
7889 /* XXX Does this work correctly for half-word/byte ops? */
7890 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
7891 str++;
7892
7893 skip_whitespace (str);
7894
7895 if (my_get_expression (&inst.reloc.exp, &str))
7896 return;
7897
7898 if (inst.reloc.exp.X_op != O_constant
7899 && inst.reloc.exp.X_op != O_symbol)
7900 {
7901 inst.error = _("constant expression expected");
7902 return;
7903 }
7904
7905 if (inst.reloc.exp.X_op == O_constant)
7906 {
7907 value = validate_immediate (inst.reloc.exp.X_add_number);
7908
7909 if (value != FAIL)
7910 {
7911 /* This can be done with a mov instruction. */
7912 inst.instruction &= LITERAL_MASK;
7913 inst.instruction |= INST_IMMEDIATE | (OPCODE_MOV << DATA_OP_SHIFT);
7914 inst.instruction |= value & 0xfff;
7915 end_of_line (str);
7916 return;
7917 }
7918
7919 value = validate_immediate (~ inst.reloc.exp.X_add_number);
7920
7921 if (value != FAIL)
7922 {
7923 /* This can be done with a mvn instruction. */
7924 inst.instruction &= LITERAL_MASK;
7925 inst.instruction |= INST_IMMEDIATE | (OPCODE_MVN << DATA_OP_SHIFT);
7926 inst.instruction |= value & 0xfff;
7927 end_of_line (str);
7928 return;
7929 }
7930 }
7931
7932 /* Insert into literal pool. */
7933 if (add_to_lit_pool () == FAIL)
7934 {
7935 if (!inst.error)
7936 inst.error = _("literal pool insertion failed");
7937 return;
7938 }
7939
7940 /* Change the instruction exp to point to the pool. */
7941 inst.instruction |= HWOFFSET_IMM;
7942 inst.reloc.type = BFD_RELOC_ARM_HWLITERAL;
7943 inst.reloc.pc_rel = 1;
7944 inst.instruction |= (REG_PC << 16);
7945 pre_inc = 1;
7946 }
7947 else
7948 {
7949 if (my_get_expression (&inst.reloc.exp, &str))
7950 return;
7951
7952 inst.instruction |= HWOFFSET_IMM;
7953 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
7954 #ifndef TE_WINCE
7955 /* PC rel adjust. */
7956 inst.reloc.exp.X_add_number -= 8;
7957 #endif
7958 inst.reloc.pc_rel = 1;
7959 inst.instruction |= (REG_PC << 16);
7960 pre_inc = 1;
7961 }
7962
7963 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
7964 end_of_line (str);
7965 }
7966
7967 static long
reg_list(strp)7968 reg_list (strp)
7969 char ** strp;
7970 {
7971 char * str = * strp;
7972 long range = 0;
7973 int another_range;
7974
7975 /* We come back here if we get ranges concatenated by '+' or '|'. */
7976 do
7977 {
7978 another_range = 0;
7979
7980 if (*str == '{')
7981 {
7982 int in_range = 0;
7983 int cur_reg = -1;
7984
7985 str++;
7986 do
7987 {
7988 int reg;
7989
7990 skip_whitespace (str);
7991
7992 if ((reg = reg_required_here (& str, -1)) == FAIL)
7993 return FAIL;
7994
7995 if (in_range)
7996 {
7997 int i;
7998
7999 if (reg <= cur_reg)
8000 {
8001 inst.error = _("bad range in register list");
8002 return FAIL;
8003 }
8004
8005 for (i = cur_reg + 1; i < reg; i++)
8006 {
8007 if (range & (1 << i))
8008 as_tsktsk
8009 (_("Warning: duplicated register (r%d) in register list"),
8010 i);
8011 else
8012 range |= 1 << i;
8013 }
8014 in_range = 0;
8015 }
8016
8017 if (range & (1 << reg))
8018 as_tsktsk (_("Warning: duplicated register (r%d) in register list"),
8019 reg);
8020 else if (reg <= cur_reg)
8021 as_tsktsk (_("Warning: register range not in ascending order"));
8022
8023 range |= 1 << reg;
8024 cur_reg = reg;
8025 }
8026 while (skip_past_comma (&str) != FAIL
8027 || (in_range = 1, *str++ == '-'));
8028 str--;
8029 skip_whitespace (str);
8030
8031 if (*str++ != '}')
8032 {
8033 inst.error = _("missing `}'");
8034 return FAIL;
8035 }
8036 }
8037 else
8038 {
8039 expressionS expr;
8040
8041 if (my_get_expression (&expr, &str))
8042 return FAIL;
8043
8044 if (expr.X_op == O_constant)
8045 {
8046 if (expr.X_add_number
8047 != (expr.X_add_number & 0x0000ffff))
8048 {
8049 inst.error = _("invalid register mask");
8050 return FAIL;
8051 }
8052
8053 if ((range & expr.X_add_number) != 0)
8054 {
8055 int regno = range & expr.X_add_number;
8056
8057 regno &= -regno;
8058 regno = (1 << regno) - 1;
8059 as_tsktsk
8060 (_("Warning: duplicated register (r%d) in register list"),
8061 regno);
8062 }
8063
8064 range |= expr.X_add_number;
8065 }
8066 else
8067 {
8068 if (inst.reloc.type != 0)
8069 {
8070 inst.error = _("expression too complex");
8071 return FAIL;
8072 }
8073
8074 memcpy (&inst.reloc.exp, &expr, sizeof (expressionS));
8075 inst.reloc.type = BFD_RELOC_ARM_MULTI;
8076 inst.reloc.pc_rel = 0;
8077 }
8078 }
8079
8080 skip_whitespace (str);
8081
8082 if (*str == '|' || *str == '+')
8083 {
8084 str++;
8085 another_range = 1;
8086 }
8087 }
8088 while (another_range);
8089
8090 *strp = str;
8091 return range;
8092 }
8093
8094 static void
do_ldmstm(str)8095 do_ldmstm (str)
8096 char * str;
8097 {
8098 int base_reg;
8099 long range;
8100
8101 skip_whitespace (str);
8102
8103 if ((base_reg = reg_required_here (&str, 16)) == FAIL)
8104 return;
8105
8106 if (base_reg == REG_PC)
8107 {
8108 inst.error = _("r15 not allowed as base register");
8109 return;
8110 }
8111
8112 skip_whitespace (str);
8113
8114 if (*str == '!')
8115 {
8116 inst.instruction |= WRITE_BACK;
8117 str++;
8118 }
8119
8120 if (skip_past_comma (&str) == FAIL
8121 || (range = reg_list (&str)) == FAIL)
8122 {
8123 if (! inst.error)
8124 inst.error = BAD_ARGS;
8125 return;
8126 }
8127
8128 if (*str == '^')
8129 {
8130 str++;
8131 inst.instruction |= LDM_TYPE_2_OR_3;
8132 }
8133
8134 if (inst.instruction & WRITE_BACK)
8135 {
8136 /* Check for unpredictable uses of writeback. */
8137 if (inst.instruction & LOAD_BIT)
8138 {
8139 /* Not allowed in LDM type 2. */
8140 if ((inst.instruction & LDM_TYPE_2_OR_3)
8141 && ((range & (1 << REG_PC)) == 0))
8142 as_warn (_("writeback of base register is UNPREDICTABLE"));
8143 /* Only allowed if base reg not in list for other types. */
8144 else if (range & (1 << base_reg))
8145 as_warn (_("writeback of base register when in register list is UNPREDICTABLE"));
8146 }
8147 else /* STM. */
8148 {
8149 /* Not allowed for type 2. */
8150 if (inst.instruction & LDM_TYPE_2_OR_3)
8151 as_warn (_("writeback of base register is UNPREDICTABLE"));
8152 /* Only allowed if base reg not in list, or first in list. */
8153 else if ((range & (1 << base_reg))
8154 && (range & ((1 << base_reg) - 1)))
8155 as_warn (_("if writeback register is in list, it must be the lowest reg in the list"));
8156 }
8157 }
8158
8159 inst.instruction |= range;
8160 end_of_line (str);
8161 }
8162
8163 static void
do_swi(str)8164 do_swi (str)
8165 char * str;
8166 {
8167 skip_whitespace (str);
8168
8169 /* Allow optional leading '#'. */
8170 if (is_immediate_prefix (*str))
8171 str++;
8172
8173 if (my_get_expression (& inst.reloc.exp, & str))
8174 return;
8175
8176 inst.reloc.type = BFD_RELOC_ARM_SWI;
8177 inst.reloc.pc_rel = 0;
8178 end_of_line (str);
8179 }
8180
8181 static void
do_swap(str)8182 do_swap (str)
8183 char * str;
8184 {
8185 int reg;
8186
8187 skip_whitespace (str);
8188
8189 if ((reg = reg_required_here (&str, 12)) == FAIL)
8190 return;
8191
8192 if (reg == REG_PC)
8193 {
8194 inst.error = _("r15 not allowed in swap");
8195 return;
8196 }
8197
8198 if (skip_past_comma (&str) == FAIL
8199 || (reg = reg_required_here (&str, 0)) == FAIL)
8200 {
8201 if (!inst.error)
8202 inst.error = BAD_ARGS;
8203 return;
8204 }
8205
8206 if (reg == REG_PC)
8207 {
8208 inst.error = _("r15 not allowed in swap");
8209 return;
8210 }
8211
8212 if (skip_past_comma (&str) == FAIL
8213 || *str++ != '[')
8214 {
8215 inst.error = BAD_ARGS;
8216 return;
8217 }
8218
8219 skip_whitespace (str);
8220
8221 if ((reg = reg_required_here (&str, 16)) == FAIL)
8222 return;
8223
8224 if (reg == REG_PC)
8225 {
8226 inst.error = BAD_PC;
8227 return;
8228 }
8229
8230 skip_whitespace (str);
8231
8232 if (*str++ != ']')
8233 {
8234 inst.error = _("missing ]");
8235 return;
8236 }
8237
8238 end_of_line (str);
8239 }
8240
8241 static void
do_branch(str)8242 do_branch (str)
8243 char * str;
8244 {
8245 if (my_get_expression (&inst.reloc.exp, &str))
8246 return;
8247
8248 #ifdef OBJ_ELF
8249 {
8250 char * save_in;
8251
8252 /* ScottB: February 5, 1998 - Check to see of PLT32 reloc
8253 required for the instruction. */
8254
8255 /* arm_parse_reloc () works on input_line_pointer.
8256 We actually want to parse the operands to the branch instruction
8257 passed in 'str'. Save the input pointer and restore it later. */
8258 save_in = input_line_pointer;
8259 input_line_pointer = str;
8260 if (inst.reloc.exp.X_op == O_symbol
8261 && *str == '('
8262 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
8263 {
8264 inst.reloc.type = BFD_RELOC_ARM_PLT32;
8265 inst.reloc.pc_rel = 0;
8266 /* Modify str to point to after parsed operands, otherwise
8267 end_of_line() will complain about the (PLT) left in str. */
8268 str = input_line_pointer;
8269 }
8270 else
8271 {
8272 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
8273 inst.reloc.pc_rel = 1;
8274 }
8275 input_line_pointer = save_in;
8276 }
8277 #else
8278 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
8279 inst.reloc.pc_rel = 1;
8280 #endif /* OBJ_ELF */
8281
8282 end_of_line (str);
8283 }
8284
8285 static void
do_bx(str)8286 do_bx (str)
8287 char * str;
8288 {
8289 int reg;
8290
8291 skip_whitespace (str);
8292
8293 if ((reg = reg_required_here (&str, 0)) == FAIL)
8294 {
8295 inst.error = BAD_ARGS;
8296 return;
8297 }
8298
8299 /* Note - it is not illegal to do a "bx pc". Useless, but not illegal. */
8300 if (reg == REG_PC)
8301 as_tsktsk (_("use of r15 in bx in ARM mode is not really useful"));
8302
8303 end_of_line (str);
8304 }
8305
8306 static void
do_cdp(str)8307 do_cdp (str)
8308 char * str;
8309 {
8310 /* Co-processor data operation.
8311 Format: CDP{cond} CP#,<expr>,CRd,CRn,CRm{,<expr>} */
8312 skip_whitespace (str);
8313
8314 if (co_proc_number (&str) == FAIL)
8315 {
8316 if (!inst.error)
8317 inst.error = BAD_ARGS;
8318 return;
8319 }
8320
8321 if (skip_past_comma (&str) == FAIL
8322 || cp_opc_expr (&str, 20,4) == FAIL)
8323 {
8324 if (!inst.error)
8325 inst.error = BAD_ARGS;
8326 return;
8327 }
8328
8329 if (skip_past_comma (&str) == FAIL
8330 || cp_reg_required_here (&str, 12) == FAIL)
8331 {
8332 if (!inst.error)
8333 inst.error = BAD_ARGS;
8334 return;
8335 }
8336
8337 if (skip_past_comma (&str) == FAIL
8338 || cp_reg_required_here (&str, 16) == FAIL)
8339 {
8340 if (!inst.error)
8341 inst.error = BAD_ARGS;
8342 return;
8343 }
8344
8345 if (skip_past_comma (&str) == FAIL
8346 || cp_reg_required_here (&str, 0) == FAIL)
8347 {
8348 if (!inst.error)
8349 inst.error = BAD_ARGS;
8350 return;
8351 }
8352
8353 if (skip_past_comma (&str) == SUCCESS)
8354 {
8355 if (cp_opc_expr (&str, 5, 3) == FAIL)
8356 {
8357 if (!inst.error)
8358 inst.error = BAD_ARGS;
8359 return;
8360 }
8361 }
8362
8363 end_of_line (str);
8364 }
8365
8366 static void
do_lstc(str)8367 do_lstc (str)
8368 char * str;
8369 {
8370 /* Co-processor register load/store.
8371 Format: <LDC|STC{cond}[L] CP#,CRd,<address> */
8372
8373 skip_whitespace (str);
8374
8375 if (co_proc_number (&str) == FAIL)
8376 {
8377 if (!inst.error)
8378 inst.error = BAD_ARGS;
8379 return;
8380 }
8381
8382 if (skip_past_comma (&str) == FAIL
8383 || cp_reg_required_here (&str, 12) == FAIL)
8384 {
8385 if (!inst.error)
8386 inst.error = BAD_ARGS;
8387 return;
8388 }
8389
8390 if (skip_past_comma (&str) == FAIL
8391 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
8392 {
8393 if (! inst.error)
8394 inst.error = BAD_ARGS;
8395 return;
8396 }
8397
8398 end_of_line (str);
8399 }
8400
8401 static void
do_co_reg(str)8402 do_co_reg (str)
8403 char * str;
8404 {
8405 /* Co-processor register transfer.
8406 Format: <MCR|MRC>{cond} CP#,<expr1>,Rd,CRn,CRm{,<expr2>} */
8407
8408 skip_whitespace (str);
8409
8410 if (co_proc_number (&str) == FAIL)
8411 {
8412 if (!inst.error)
8413 inst.error = BAD_ARGS;
8414 return;
8415 }
8416
8417 if (skip_past_comma (&str) == FAIL
8418 || cp_opc_expr (&str, 21, 3) == FAIL)
8419 {
8420 if (!inst.error)
8421 inst.error = BAD_ARGS;
8422 return;
8423 }
8424
8425 if (skip_past_comma (&str) == FAIL
8426 || reg_required_here (&str, 12) == FAIL)
8427 {
8428 if (!inst.error)
8429 inst.error = BAD_ARGS;
8430 return;
8431 }
8432
8433 if (skip_past_comma (&str) == FAIL
8434 || cp_reg_required_here (&str, 16) == FAIL)
8435 {
8436 if (!inst.error)
8437 inst.error = BAD_ARGS;
8438 return;
8439 }
8440
8441 if (skip_past_comma (&str) == FAIL
8442 || cp_reg_required_here (&str, 0) == FAIL)
8443 {
8444 if (!inst.error)
8445 inst.error = BAD_ARGS;
8446 return;
8447 }
8448
8449 if (skip_past_comma (&str) == SUCCESS)
8450 {
8451 if (cp_opc_expr (&str, 5, 3) == FAIL)
8452 {
8453 if (!inst.error)
8454 inst.error = BAD_ARGS;
8455 return;
8456 }
8457 }
8458
8459 end_of_line (str);
8460 }
8461
8462 static void
do_fpa_ctrl(str)8463 do_fpa_ctrl (str)
8464 char * str;
8465 {
8466 /* FP control registers.
8467 Format: <WFS|RFS|WFC|RFC>{cond} Rn */
8468
8469 skip_whitespace (str);
8470
8471 if (reg_required_here (&str, 12) == FAIL)
8472 {
8473 if (!inst.error)
8474 inst.error = BAD_ARGS;
8475 return;
8476 }
8477
8478 end_of_line (str);
8479 }
8480
8481 static void
do_fpa_ldst(str)8482 do_fpa_ldst (str)
8483 char * str;
8484 {
8485 skip_whitespace (str);
8486
8487 if (fp_reg_required_here (&str, 12) == FAIL)
8488 {
8489 if (!inst.error)
8490 inst.error = BAD_ARGS;
8491 return;
8492 }
8493
8494 if (skip_past_comma (&str) == FAIL
8495 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
8496 {
8497 if (!inst.error)
8498 inst.error = BAD_ARGS;
8499 return;
8500 }
8501
8502 end_of_line (str);
8503 }
8504
8505 static void
do_fpa_ldmstm(str)8506 do_fpa_ldmstm (str)
8507 char * str;
8508 {
8509 int num_regs;
8510
8511 skip_whitespace (str);
8512
8513 if (fp_reg_required_here (&str, 12) == FAIL)
8514 {
8515 if (! inst.error)
8516 inst.error = BAD_ARGS;
8517 return;
8518 }
8519
8520 /* Get Number of registers to transfer. */
8521 if (skip_past_comma (&str) == FAIL
8522 || my_get_expression (&inst.reloc.exp, &str))
8523 {
8524 if (! inst.error)
8525 inst.error = _("constant expression expected");
8526 return;
8527 }
8528
8529 if (inst.reloc.exp.X_op != O_constant)
8530 {
8531 inst.error = _("constant value required for number of registers");
8532 return;
8533 }
8534
8535 num_regs = inst.reloc.exp.X_add_number;
8536
8537 if (num_regs < 1 || num_regs > 4)
8538 {
8539 inst.error = _("number of registers must be in the range [1:4]");
8540 return;
8541 }
8542
8543 switch (num_regs)
8544 {
8545 case 1:
8546 inst.instruction |= CP_T_X;
8547 break;
8548 case 2:
8549 inst.instruction |= CP_T_Y;
8550 break;
8551 case 3:
8552 inst.instruction |= CP_T_Y | CP_T_X;
8553 break;
8554 case 4:
8555 break;
8556 default:
8557 abort ();
8558 }
8559
8560 if (inst.instruction & (CP_T_Pre | CP_T_UD)) /* ea/fd format. */
8561 {
8562 int reg;
8563 int write_back;
8564 int offset;
8565
8566 /* The instruction specified "ea" or "fd", so we can only accept
8567 [Rn]{!}. The instruction does not really support stacking or
8568 unstacking, so we have to emulate these by setting appropriate
8569 bits and offsets. */
8570 if (skip_past_comma (&str) == FAIL
8571 || *str != '[')
8572 {
8573 if (! inst.error)
8574 inst.error = BAD_ARGS;
8575 return;
8576 }
8577
8578 str++;
8579 skip_whitespace (str);
8580
8581 if ((reg = reg_required_here (&str, 16)) == FAIL)
8582 return;
8583
8584 skip_whitespace (str);
8585
8586 if (*str != ']')
8587 {
8588 inst.error = BAD_ARGS;
8589 return;
8590 }
8591
8592 str++;
8593 if (*str == '!')
8594 {
8595 write_back = 1;
8596 str++;
8597 if (reg == REG_PC)
8598 {
8599 inst.error =
8600 _("r15 not allowed as base register with write-back");
8601 return;
8602 }
8603 }
8604 else
8605 write_back = 0;
8606
8607 if (inst.instruction & CP_T_Pre)
8608 {
8609 /* Pre-decrement. */
8610 offset = 3 * num_regs;
8611 if (write_back)
8612 inst.instruction |= CP_T_WB;
8613 }
8614 else
8615 {
8616 /* Post-increment. */
8617 if (write_back)
8618 {
8619 inst.instruction |= CP_T_WB;
8620 offset = 3 * num_regs;
8621 }
8622 else
8623 {
8624 /* No write-back, so convert this into a standard pre-increment
8625 instruction -- aesthetically more pleasing. */
8626 inst.instruction |= CP_T_Pre | CP_T_UD;
8627 offset = 0;
8628 }
8629 }
8630
8631 inst.instruction |= offset;
8632 }
8633 else if (skip_past_comma (&str) == FAIL
8634 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
8635 {
8636 if (! inst.error)
8637 inst.error = BAD_ARGS;
8638 return;
8639 }
8640
8641 end_of_line (str);
8642 }
8643
8644 static void
do_fpa_dyadic(str)8645 do_fpa_dyadic (str)
8646 char * str;
8647 {
8648 skip_whitespace (str);
8649
8650 if (fp_reg_required_here (&str, 12) == FAIL)
8651 {
8652 if (! inst.error)
8653 inst.error = BAD_ARGS;
8654 return;
8655 }
8656
8657 if (skip_past_comma (&str) == FAIL
8658 || fp_reg_required_here (&str, 16) == FAIL)
8659 {
8660 if (! inst.error)
8661 inst.error = BAD_ARGS;
8662 return;
8663 }
8664
8665 if (skip_past_comma (&str) == FAIL
8666 || fp_op2 (&str) == FAIL)
8667 {
8668 if (! inst.error)
8669 inst.error = BAD_ARGS;
8670 return;
8671 }
8672
8673 end_of_line (str);
8674 }
8675
8676 static void
do_fpa_monadic(str)8677 do_fpa_monadic (str)
8678 char * str;
8679 {
8680 skip_whitespace (str);
8681
8682 if (fp_reg_required_here (&str, 12) == FAIL)
8683 {
8684 if (! inst.error)
8685 inst.error = BAD_ARGS;
8686 return;
8687 }
8688
8689 if (skip_past_comma (&str) == FAIL
8690 || fp_op2 (&str) == FAIL)
8691 {
8692 if (! inst.error)
8693 inst.error = BAD_ARGS;
8694 return;
8695 }
8696
8697 end_of_line (str);
8698 }
8699
8700 static void
do_fpa_cmp(str)8701 do_fpa_cmp (str)
8702 char * str;
8703 {
8704 skip_whitespace (str);
8705
8706 if (fp_reg_required_here (&str, 16) == FAIL)
8707 {
8708 if (! inst.error)
8709 inst.error = BAD_ARGS;
8710 return;
8711 }
8712
8713 if (skip_past_comma (&str) == FAIL
8714 || fp_op2 (&str) == FAIL)
8715 {
8716 if (! inst.error)
8717 inst.error = BAD_ARGS;
8718 return;
8719 }
8720
8721 end_of_line (str);
8722 }
8723
8724 static void
do_fpa_from_reg(str)8725 do_fpa_from_reg (str)
8726 char * str;
8727 {
8728 skip_whitespace (str);
8729
8730 if (fp_reg_required_here (&str, 16) == FAIL)
8731 {
8732 if (! inst.error)
8733 inst.error = BAD_ARGS;
8734 return;
8735 }
8736
8737 if (skip_past_comma (&str) == FAIL
8738 || reg_required_here (&str, 12) == FAIL)
8739 {
8740 if (! inst.error)
8741 inst.error = BAD_ARGS;
8742 return;
8743 }
8744
8745 end_of_line (str);
8746 }
8747
8748 static void
do_fpa_to_reg(str)8749 do_fpa_to_reg (str)
8750 char * str;
8751 {
8752 skip_whitespace (str);
8753
8754 if (reg_required_here (&str, 12) == FAIL)
8755 return;
8756
8757 if (skip_past_comma (&str) == FAIL
8758 || fp_reg_required_here (&str, 0) == FAIL)
8759 {
8760 if (! inst.error)
8761 inst.error = BAD_ARGS;
8762 return;
8763 }
8764
8765 end_of_line (str);
8766 }
8767
8768 static int
vfp_sp_reg_required_here(str,pos)8769 vfp_sp_reg_required_here (str, pos)
8770 char **str;
8771 enum vfp_sp_reg_pos pos;
8772 {
8773 int reg;
8774 char *start = *str;
8775
8776 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_SN].htab)) != FAIL)
8777 {
8778 switch (pos)
8779 {
8780 case VFP_REG_Sd:
8781 inst.instruction |= ((reg >> 1) << 12) | ((reg & 1) << 22);
8782 break;
8783
8784 case VFP_REG_Sn:
8785 inst.instruction |= ((reg >> 1) << 16) | ((reg & 1) << 7);
8786 break;
8787
8788 case VFP_REG_Sm:
8789 inst.instruction |= ((reg >> 1) << 0) | ((reg & 1) << 5);
8790 break;
8791
8792 default:
8793 abort ();
8794 }
8795 return reg;
8796 }
8797
8798 /* In the few cases where we might be able to accept something else
8799 this error can be overridden. */
8800 inst.error = _(all_reg_maps[REG_TYPE_SN].expected);
8801
8802 /* Restore the start point. */
8803 *str = start;
8804 return FAIL;
8805 }
8806
8807 static int
vfp_dp_reg_required_here(str,pos)8808 vfp_dp_reg_required_here (str, pos)
8809 char **str;
8810 enum vfp_dp_reg_pos pos;
8811 {
8812 int reg;
8813 char *start = *str;
8814
8815 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_DN].htab)) != FAIL)
8816 {
8817 switch (pos)
8818 {
8819 case VFP_REG_Dd:
8820 inst.instruction |= reg << 12;
8821 break;
8822
8823 case VFP_REG_Dn:
8824 inst.instruction |= reg << 16;
8825 break;
8826
8827 case VFP_REG_Dm:
8828 inst.instruction |= reg << 0;
8829 break;
8830
8831 default:
8832 abort ();
8833 }
8834 return reg;
8835 }
8836
8837 /* In the few cases where we might be able to accept something else
8838 this error can be overridden. */
8839 inst.error = _(all_reg_maps[REG_TYPE_DN].expected);
8840
8841 /* Restore the start point. */
8842 *str = start;
8843 return FAIL;
8844 }
8845
8846 static void
do_vfp_sp_monadic(str)8847 do_vfp_sp_monadic (str)
8848 char *str;
8849 {
8850 skip_whitespace (str);
8851
8852 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
8853 return;
8854
8855 if (skip_past_comma (&str) == FAIL
8856 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
8857 {
8858 if (! inst.error)
8859 inst.error = BAD_ARGS;
8860 return;
8861 }
8862
8863 end_of_line (str);
8864 }
8865
8866 static void
do_vfp_dp_monadic(str)8867 do_vfp_dp_monadic (str)
8868 char *str;
8869 {
8870 skip_whitespace (str);
8871
8872 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
8873 return;
8874
8875 if (skip_past_comma (&str) == FAIL
8876 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
8877 {
8878 if (! inst.error)
8879 inst.error = BAD_ARGS;
8880 return;
8881 }
8882
8883 end_of_line (str);
8884 }
8885
8886 static void
do_vfp_sp_dyadic(str)8887 do_vfp_sp_dyadic (str)
8888 char *str;
8889 {
8890 skip_whitespace (str);
8891
8892 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
8893 return;
8894
8895 if (skip_past_comma (&str) == FAIL
8896 || vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL
8897 || skip_past_comma (&str) == FAIL
8898 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
8899 {
8900 if (! inst.error)
8901 inst.error = BAD_ARGS;
8902 return;
8903 }
8904
8905 end_of_line (str);
8906 }
8907
8908 static void
do_vfp_dp_dyadic(str)8909 do_vfp_dp_dyadic (str)
8910 char *str;
8911 {
8912 skip_whitespace (str);
8913
8914 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
8915 return;
8916
8917 if (skip_past_comma (&str) == FAIL
8918 || vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL
8919 || skip_past_comma (&str) == FAIL
8920 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
8921 {
8922 if (! inst.error)
8923 inst.error = BAD_ARGS;
8924 return;
8925 }
8926
8927 end_of_line (str);
8928 }
8929
8930 static void
do_vfp_reg_from_sp(str)8931 do_vfp_reg_from_sp (str)
8932 char *str;
8933 {
8934 skip_whitespace (str);
8935
8936 if (reg_required_here (&str, 12) == FAIL)
8937 return;
8938
8939 if (skip_past_comma (&str) == FAIL
8940 || vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL)
8941 {
8942 if (! inst.error)
8943 inst.error = BAD_ARGS;
8944 return;
8945 }
8946
8947 end_of_line (str);
8948 }
8949
8950 static void
do_vfp_reg2_from_sp2(str)8951 do_vfp_reg2_from_sp2 (str)
8952 char *str;
8953 {
8954 skip_whitespace (str);
8955
8956 if (reg_required_here (&str, 12) == FAIL
8957 || skip_past_comma (&str) == FAIL
8958 || reg_required_here (&str, 16) == FAIL
8959 || skip_past_comma (&str) == FAIL)
8960 {
8961 if (! inst.error)
8962 inst.error = BAD_ARGS;
8963 return;
8964 }
8965
8966 /* We require exactly two consecutive SP registers. */
8967 if (vfp_sp_reg_list (&str, VFP_REG_Sm) != 2)
8968 {
8969 if (! inst.error)
8970 inst.error = _("only two consecutive VFP SP registers allowed here");
8971 }
8972
8973 end_of_line (str);
8974 }
8975
8976 static void
do_vfp_sp_from_reg(str)8977 do_vfp_sp_from_reg (str)
8978 char *str;
8979 {
8980 skip_whitespace (str);
8981
8982 if (vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL)
8983 return;
8984
8985 if (skip_past_comma (&str) == FAIL
8986 || reg_required_here (&str, 12) == FAIL)
8987 {
8988 if (! inst.error)
8989 inst.error = BAD_ARGS;
8990 return;
8991 }
8992
8993 end_of_line (str);
8994 }
8995
8996 static void
do_vfp_sp2_from_reg2(str)8997 do_vfp_sp2_from_reg2 (str)
8998 char *str;
8999 {
9000 skip_whitespace (str);
9001
9002 /* We require exactly two consecutive SP registers. */
9003 if (vfp_sp_reg_list (&str, VFP_REG_Sm) != 2)
9004 {
9005 if (! inst.error)
9006 inst.error = _("only two consecutive VFP SP registers allowed here");
9007 }
9008
9009 if (skip_past_comma (&str) == FAIL
9010 || reg_required_here (&str, 12) == FAIL
9011 || skip_past_comma (&str) == FAIL
9012 || reg_required_here (&str, 16) == FAIL)
9013 {
9014 if (! inst.error)
9015 inst.error = BAD_ARGS;
9016 return;
9017 }
9018
9019 end_of_line (str);
9020 }
9021
9022 static void
do_vfp_reg_from_dp(str)9023 do_vfp_reg_from_dp (str)
9024 char *str;
9025 {
9026 skip_whitespace (str);
9027
9028 if (reg_required_here (&str, 12) == FAIL)
9029 return;
9030
9031 if (skip_past_comma (&str) == FAIL
9032 || vfp_dp_reg_required_here (&str, VFP_REG_Dn) == 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
do_vfp_reg2_from_dp(str)9043 do_vfp_reg2_from_dp (str)
9044 char *str;
9045 {
9046 skip_whitespace (str);
9047
9048 if (reg_required_here (&str, 12) == FAIL)
9049 return;
9050
9051 if (skip_past_comma (&str) == FAIL
9052 || reg_required_here (&str, 16) == FAIL
9053 || skip_past_comma (&str) == FAIL
9054 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
9055 {
9056 if (! inst.error)
9057 inst.error = BAD_ARGS;
9058 return;
9059 }
9060
9061 end_of_line (str);
9062 }
9063
9064 static void
do_vfp_dp_from_reg(str)9065 do_vfp_dp_from_reg (str)
9066 char *str;
9067 {
9068 skip_whitespace (str);
9069
9070 if (vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL)
9071 return;
9072
9073 if (skip_past_comma (&str) == FAIL
9074 || reg_required_here (&str, 12) == FAIL)
9075 {
9076 if (! inst.error)
9077 inst.error = BAD_ARGS;
9078 return;
9079 }
9080
9081 end_of_line (str);
9082 }
9083
9084 static void
do_vfp_dp_from_reg2(str)9085 do_vfp_dp_from_reg2 (str)
9086 char *str;
9087 {
9088 skip_whitespace (str);
9089
9090 if (vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
9091 return;
9092
9093 if (skip_past_comma (&str) == FAIL
9094 || reg_required_here (&str, 12) == FAIL
9095 || skip_past_comma (&str) == FAIL
9096 || reg_required_here (&str, 16) == FAIL)
9097 {
9098 if (! inst.error)
9099 inst.error = BAD_ARGS;
9100 return;
9101 }
9102
9103 end_of_line (str);
9104 }
9105
9106 static const struct vfp_reg *
vfp_psr_parse(str)9107 vfp_psr_parse (str)
9108 char **str;
9109 {
9110 char *start = *str;
9111 char c;
9112 char *p;
9113 const struct vfp_reg *vreg;
9114
9115 p = start;
9116
9117 /* Find the end of the current token. */
9118 do
9119 {
9120 c = *p++;
9121 }
9122 while (ISALPHA (c));
9123
9124 /* Mark it. */
9125 *--p = 0;
9126
9127 for (vreg = vfp_regs + 0;
9128 vreg < vfp_regs + sizeof (vfp_regs) / sizeof (struct vfp_reg);
9129 vreg++)
9130 {
9131 if (strcmp (start, vreg->name) == 0)
9132 {
9133 *p = c;
9134 *str = p;
9135 return vreg;
9136 }
9137 }
9138
9139 *p = c;
9140 return NULL;
9141 }
9142
9143 static int
vfp_psr_required_here(str)9144 vfp_psr_required_here (str)
9145 char **str;
9146 {
9147 char *start = *str;
9148 const struct vfp_reg *vreg;
9149
9150 vreg = vfp_psr_parse (str);
9151
9152 if (vreg)
9153 {
9154 inst.instruction |= vreg->regno;
9155 return SUCCESS;
9156 }
9157
9158 inst.error = _("VFP system register expected");
9159
9160 *str = start;
9161 return FAIL;
9162 }
9163
9164 static void
do_vfp_reg_from_ctrl(str)9165 do_vfp_reg_from_ctrl (str)
9166 char *str;
9167 {
9168 skip_whitespace (str);
9169
9170 if (reg_required_here (&str, 12) == FAIL)
9171 return;
9172
9173 if (skip_past_comma (&str) == FAIL
9174 || vfp_psr_required_here (&str) == FAIL)
9175 {
9176 if (! inst.error)
9177 inst.error = BAD_ARGS;
9178 return;
9179 }
9180
9181 end_of_line (str);
9182 }
9183
9184 static void
do_vfp_ctrl_from_reg(str)9185 do_vfp_ctrl_from_reg (str)
9186 char *str;
9187 {
9188 skip_whitespace (str);
9189
9190 if (vfp_psr_required_here (&str) == FAIL)
9191 return;
9192
9193 if (skip_past_comma (&str) == FAIL
9194 || reg_required_here (&str, 12) == FAIL)
9195 {
9196 if (! inst.error)
9197 inst.error = BAD_ARGS;
9198 return;
9199 }
9200
9201 end_of_line (str);
9202 }
9203
9204 static void
do_vfp_sp_ldst(str)9205 do_vfp_sp_ldst (str)
9206 char *str;
9207 {
9208 skip_whitespace (str);
9209
9210 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
9211 {
9212 if (!inst.error)
9213 inst.error = BAD_ARGS;
9214 return;
9215 }
9216
9217 if (skip_past_comma (&str) == FAIL
9218 || cp_address_required_here (&str, CP_NO_WB) == FAIL)
9219 {
9220 if (!inst.error)
9221 inst.error = BAD_ARGS;
9222 return;
9223 }
9224
9225 end_of_line (str);
9226 }
9227
9228 static void
do_vfp_dp_ldst(str)9229 do_vfp_dp_ldst (str)
9230 char *str;
9231 {
9232 skip_whitespace (str);
9233
9234 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
9235 {
9236 if (!inst.error)
9237 inst.error = BAD_ARGS;
9238 return;
9239 }
9240
9241 if (skip_past_comma (&str) == FAIL
9242 || cp_address_required_here (&str, CP_NO_WB) == FAIL)
9243 {
9244 if (!inst.error)
9245 inst.error = BAD_ARGS;
9246 return;
9247 }
9248
9249 end_of_line (str);
9250 }
9251
9252 /* Parse and encode a VFP SP register list, storing the initial
9253 register in position POS and returning the range as the result. If
9254 the string is invalid return FAIL (an invalid range). */
9255 static long
vfp_sp_reg_list(str,pos)9256 vfp_sp_reg_list (str, pos)
9257 char **str;
9258 enum vfp_sp_reg_pos pos;
9259 {
9260 long range = 0;
9261 int base_reg = 0;
9262 int new_base;
9263 long base_bits = 0;
9264 int count = 0;
9265 long tempinst;
9266 unsigned long mask = 0;
9267 int warned = 0;
9268
9269 if (**str != '{')
9270 return FAIL;
9271
9272 (*str)++;
9273 skip_whitespace (*str);
9274
9275 tempinst = inst.instruction;
9276
9277 do
9278 {
9279 inst.instruction = 0;
9280
9281 if ((new_base = vfp_sp_reg_required_here (str, pos)) == FAIL)
9282 return FAIL;
9283
9284 if (count == 0 || base_reg > new_base)
9285 {
9286 base_reg = new_base;
9287 base_bits = inst.instruction;
9288 }
9289
9290 if (mask & (1 << new_base))
9291 {
9292 inst.error = _("invalid register list");
9293 return FAIL;
9294 }
9295
9296 if ((mask >> new_base) != 0 && ! warned)
9297 {
9298 as_tsktsk (_("register list not in ascending order"));
9299 warned = 1;
9300 }
9301
9302 mask |= 1 << new_base;
9303 count++;
9304
9305 skip_whitespace (*str);
9306
9307 if (**str == '-') /* We have the start of a range expression */
9308 {
9309 int high_range;
9310
9311 (*str)++;
9312
9313 if ((high_range
9314 = arm_reg_parse (str, all_reg_maps[REG_TYPE_SN].htab))
9315 == FAIL)
9316 {
9317 inst.error = _(all_reg_maps[REG_TYPE_SN].expected);
9318 return FAIL;
9319 }
9320
9321 if (high_range <= new_base)
9322 {
9323 inst.error = _("register range not in ascending order");
9324 return FAIL;
9325 }
9326
9327 for (new_base++; new_base <= high_range; new_base++)
9328 {
9329 if (mask & (1 << new_base))
9330 {
9331 inst.error = _("invalid register list");
9332 return FAIL;
9333 }
9334
9335 mask |= 1 << new_base;
9336 count++;
9337 }
9338 }
9339 }
9340 while (skip_past_comma (str) != FAIL);
9341
9342 if (**str != '}')
9343 {
9344 inst.error = _("invalid register list");
9345 return FAIL;
9346 }
9347
9348 (*str)++;
9349
9350 range = count;
9351
9352 /* Sanity check -- should have raised a parse error above. */
9353 if (count == 0 || count > 32)
9354 abort ();
9355
9356 /* Final test -- the registers must be consecutive. */
9357 while (count--)
9358 {
9359 if ((mask & (1 << base_reg++)) == 0)
9360 {
9361 inst.error = _("non-contiguous register range");
9362 return FAIL;
9363 }
9364 }
9365
9366 inst.instruction = tempinst | base_bits;
9367 return range;
9368 }
9369
9370 static long
vfp_dp_reg_list(str)9371 vfp_dp_reg_list (str)
9372 char **str;
9373 {
9374 long range = 0;
9375 int base_reg = 0;
9376 int new_base;
9377 int count = 0;
9378 long tempinst;
9379 unsigned long mask = 0;
9380 int warned = 0;
9381
9382 if (**str != '{')
9383 return FAIL;
9384
9385 (*str)++;
9386 skip_whitespace (*str);
9387
9388 tempinst = inst.instruction;
9389
9390 do
9391 {
9392 inst.instruction = 0;
9393
9394 if ((new_base = vfp_dp_reg_required_here (str, VFP_REG_Dd)) == FAIL)
9395 return FAIL;
9396
9397 if (count == 0 || base_reg > new_base)
9398 {
9399 base_reg = new_base;
9400 range = inst.instruction;
9401 }
9402
9403 if (mask & (1 << new_base))
9404 {
9405 inst.error = _("invalid register list");
9406 return FAIL;
9407 }
9408
9409 if ((mask >> new_base) != 0 && ! warned)
9410 {
9411 as_tsktsk (_("register list not in ascending order"));
9412 warned = 1;
9413 }
9414
9415 mask |= 1 << new_base;
9416 count++;
9417
9418 skip_whitespace (*str);
9419
9420 if (**str == '-') /* We have the start of a range expression */
9421 {
9422 int high_range;
9423
9424 (*str)++;
9425
9426 if ((high_range
9427 = arm_reg_parse (str, all_reg_maps[REG_TYPE_DN].htab))
9428 == FAIL)
9429 {
9430 inst.error = _(all_reg_maps[REG_TYPE_DN].expected);
9431 return FAIL;
9432 }
9433
9434 if (high_range <= new_base)
9435 {
9436 inst.error = _("register range not in ascending order");
9437 return FAIL;
9438 }
9439
9440 for (new_base++; new_base <= high_range; new_base++)
9441 {
9442 if (mask & (1 << new_base))
9443 {
9444 inst.error = _("invalid register list");
9445 return FAIL;
9446 }
9447
9448 mask |= 1 << new_base;
9449 count++;
9450 }
9451 }
9452 }
9453 while (skip_past_comma (str) != FAIL);
9454
9455 if (**str != '}')
9456 {
9457 inst.error = _("invalid register list");
9458 return FAIL;
9459 }
9460
9461 (*str)++;
9462
9463 range |= 2 * count;
9464
9465 /* Sanity check -- should have raised a parse error above. */
9466 if (count == 0 || count > 16)
9467 abort ();
9468
9469 /* Final test -- the registers must be consecutive. */
9470 while (count--)
9471 {
9472 if ((mask & (1 << base_reg++)) == 0)
9473 {
9474 inst.error = _("non-contiguous register range");
9475 return FAIL;
9476 }
9477 }
9478
9479 inst.instruction = tempinst;
9480 return range;
9481 }
9482
9483 static void
vfp_sp_ldstm(str,ldstm_type)9484 vfp_sp_ldstm (str, ldstm_type)
9485 char *str;
9486 enum vfp_ldstm_type ldstm_type;
9487 {
9488 long range;
9489
9490 skip_whitespace (str);
9491
9492 if (reg_required_here (&str, 16) == FAIL)
9493 return;
9494
9495 skip_whitespace (str);
9496
9497 if (*str == '!')
9498 {
9499 inst.instruction |= WRITE_BACK;
9500 str++;
9501 }
9502 else if (ldstm_type != VFP_LDSTMIA)
9503 {
9504 inst.error = _("this addressing mode requires base-register writeback");
9505 return;
9506 }
9507
9508 if (skip_past_comma (&str) == FAIL
9509 || (range = vfp_sp_reg_list (&str, VFP_REG_Sd)) == FAIL)
9510 {
9511 if (!inst.error)
9512 inst.error = BAD_ARGS;
9513 return;
9514 }
9515
9516 inst.instruction |= range;
9517 end_of_line (str);
9518 }
9519
9520 static void
vfp_dp_ldstm(str,ldstm_type)9521 vfp_dp_ldstm (str, ldstm_type)
9522 char *str;
9523 enum vfp_ldstm_type ldstm_type;
9524 {
9525 long range;
9526
9527 skip_whitespace (str);
9528
9529 if (reg_required_here (&str, 16) == FAIL)
9530 return;
9531
9532 skip_whitespace (str);
9533
9534 if (*str == '!')
9535 {
9536 inst.instruction |= WRITE_BACK;
9537 str++;
9538 }
9539 else if (ldstm_type != VFP_LDSTMIA && ldstm_type != VFP_LDSTMIAX)
9540 {
9541 inst.error = _("this addressing mode requires base-register writeback");
9542 return;
9543 }
9544
9545 if (skip_past_comma (&str) == FAIL
9546 || (range = vfp_dp_reg_list (&str)) == FAIL)
9547 {
9548 if (!inst.error)
9549 inst.error = BAD_ARGS;
9550 return;
9551 }
9552
9553 if (ldstm_type == VFP_LDSTMIAX || ldstm_type == VFP_LDSTMDBX)
9554 range += 1;
9555
9556 inst.instruction |= range;
9557 end_of_line (str);
9558 }
9559
9560 static void
do_vfp_sp_ldstmia(str)9561 do_vfp_sp_ldstmia (str)
9562 char *str;
9563 {
9564 vfp_sp_ldstm (str, VFP_LDSTMIA);
9565 }
9566
9567 static void
do_vfp_sp_ldstmdb(str)9568 do_vfp_sp_ldstmdb (str)
9569 char *str;
9570 {
9571 vfp_sp_ldstm (str, VFP_LDSTMDB);
9572 }
9573
9574 static void
do_vfp_dp_ldstmia(str)9575 do_vfp_dp_ldstmia (str)
9576 char *str;
9577 {
9578 vfp_dp_ldstm (str, VFP_LDSTMIA);
9579 }
9580
9581 static void
do_vfp_dp_ldstmdb(str)9582 do_vfp_dp_ldstmdb (str)
9583 char *str;
9584 {
9585 vfp_dp_ldstm (str, VFP_LDSTMDB);
9586 }
9587
9588 static void
do_vfp_xp_ldstmia(str)9589 do_vfp_xp_ldstmia (str)
9590 char *str;
9591 {
9592 vfp_dp_ldstm (str, VFP_LDSTMIAX);
9593 }
9594
9595 static void
do_vfp_xp_ldstmdb(str)9596 do_vfp_xp_ldstmdb (str)
9597 char *str;
9598 {
9599 vfp_dp_ldstm (str, VFP_LDSTMDBX);
9600 }
9601
9602 static void
do_vfp_sp_compare_z(str)9603 do_vfp_sp_compare_z (str)
9604 char *str;
9605 {
9606 skip_whitespace (str);
9607
9608 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
9609 {
9610 if (!inst.error)
9611 inst.error = BAD_ARGS;
9612 return;
9613 }
9614
9615 end_of_line (str);
9616 }
9617
9618 static void
do_vfp_dp_compare_z(str)9619 do_vfp_dp_compare_z (str)
9620 char *str;
9621 {
9622 skip_whitespace (str);
9623
9624 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
9625 {
9626 if (!inst.error)
9627 inst.error = BAD_ARGS;
9628 return;
9629 }
9630
9631 end_of_line (str);
9632 }
9633
9634 static void
do_vfp_dp_sp_cvt(str)9635 do_vfp_dp_sp_cvt (str)
9636 char *str;
9637 {
9638 skip_whitespace (str);
9639
9640 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
9641 return;
9642
9643 if (skip_past_comma (&str) == FAIL
9644 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
9645 {
9646 if (! inst.error)
9647 inst.error = BAD_ARGS;
9648 return;
9649 }
9650
9651 end_of_line (str);
9652 }
9653
9654 static void
do_vfp_sp_dp_cvt(str)9655 do_vfp_sp_dp_cvt (str)
9656 char *str;
9657 {
9658 skip_whitespace (str);
9659
9660 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
9661 return;
9662
9663 if (skip_past_comma (&str) == FAIL
9664 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
9665 {
9666 if (! inst.error)
9667 inst.error = BAD_ARGS;
9668 return;
9669 }
9670
9671 end_of_line (str);
9672 }
9673
9674 /* Thumb specific routines. */
9675
9676 /* Parse and validate that a register is of the right form, this saves
9677 repeated checking of this information in many similar cases.
9678 Unlike the 32-bit case we do not insert the register into the opcode
9679 here, since the position is often unknown until the full instruction
9680 has been parsed. */
9681
9682 static int
thumb_reg(strp,hi_lo)9683 thumb_reg (strp, hi_lo)
9684 char ** strp;
9685 int hi_lo;
9686 {
9687 int reg;
9688
9689 if ((reg = reg_required_here (strp, -1)) == FAIL)
9690 return FAIL;
9691
9692 switch (hi_lo)
9693 {
9694 case THUMB_REG_LO:
9695 if (reg > 7)
9696 {
9697 inst.error = _("lo register required");
9698 return FAIL;
9699 }
9700 break;
9701
9702 case THUMB_REG_HI:
9703 if (reg < 8)
9704 {
9705 inst.error = _("hi register required");
9706 return FAIL;
9707 }
9708 break;
9709
9710 default:
9711 break;
9712 }
9713
9714 return reg;
9715 }
9716
9717 /* Parse an add or subtract instruction, SUBTRACT is non-zero if the opcode
9718 was SUB. */
9719
9720 static void
thumb_add_sub(str,subtract)9721 thumb_add_sub (str, subtract)
9722 char * str;
9723 int subtract;
9724 {
9725 int Rd, Rs, Rn = FAIL;
9726
9727 skip_whitespace (str);
9728
9729 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
9730 || skip_past_comma (&str) == FAIL)
9731 {
9732 if (! inst.error)
9733 inst.error = BAD_ARGS;
9734 return;
9735 }
9736
9737 if (is_immediate_prefix (*str))
9738 {
9739 Rs = Rd;
9740 str++;
9741 if (my_get_expression (&inst.reloc.exp, &str))
9742 return;
9743 }
9744 else
9745 {
9746 if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
9747 return;
9748
9749 if (skip_past_comma (&str) == FAIL)
9750 {
9751 /* Two operand format, shuffle the registers
9752 and pretend there are 3. */
9753 Rn = Rs;
9754 Rs = Rd;
9755 }
9756 else if (is_immediate_prefix (*str))
9757 {
9758 str++;
9759 if (my_get_expression (&inst.reloc.exp, &str))
9760 return;
9761 }
9762 else if ((Rn = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
9763 return;
9764 }
9765
9766 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
9767 for the latter case, EXPR contains the immediate that was found. */
9768 if (Rn != FAIL)
9769 {
9770 /* All register format. */
9771 if (Rd > 7 || Rs > 7 || Rn > 7)
9772 {
9773 if (Rs != Rd)
9774 {
9775 inst.error = _("dest and source1 must be the same register");
9776 return;
9777 }
9778
9779 /* Can't do this for SUB. */
9780 if (subtract)
9781 {
9782 inst.error = _("subtract valid only on lo regs");
9783 return;
9784 }
9785
9786 inst.instruction = (T_OPCODE_ADD_HI
9787 | (Rd > 7 ? THUMB_H1 : 0)
9788 | (Rn > 7 ? THUMB_H2 : 0));
9789 inst.instruction |= (Rd & 7) | ((Rn & 7) << 3);
9790 }
9791 else
9792 {
9793 inst.instruction = subtract ? T_OPCODE_SUB_R3 : T_OPCODE_ADD_R3;
9794 inst.instruction |= Rd | (Rs << 3) | (Rn << 6);
9795 }
9796 }
9797 else
9798 {
9799 /* Immediate expression, now things start to get nasty. */
9800
9801 /* First deal with HI regs, only very restricted cases allowed:
9802 Adjusting SP, and using PC or SP to get an address. */
9803 if ((Rd > 7 && (Rd != REG_SP || Rs != REG_SP))
9804 || (Rs > 7 && Rs != REG_SP && Rs != REG_PC))
9805 {
9806 inst.error = _("invalid Hi register with immediate");
9807 return;
9808 }
9809
9810 if (inst.reloc.exp.X_op != O_constant)
9811 {
9812 /* Value isn't known yet, all we can do is store all the fragments
9813 we know about in the instruction and let the reloc hacking
9814 work it all out. */
9815 inst.instruction = (subtract ? 0x8000 : 0) | (Rd << 4) | Rs;
9816 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
9817 }
9818 else
9819 {
9820 int offset = inst.reloc.exp.X_add_number;
9821
9822 if (subtract)
9823 offset = - offset;
9824
9825 if (offset < 0)
9826 {
9827 offset = - offset;
9828 subtract = 1;
9829
9830 /* Quick check, in case offset is MIN_INT. */
9831 if (offset < 0)
9832 {
9833 inst.error = _("immediate value out of range");
9834 return;
9835 }
9836 }
9837 /* Note - you cannot convert a subtract of 0 into an
9838 add of 0 because the carry flag is set differently. */
9839 else if (offset > 0)
9840 subtract = 0;
9841
9842 if (Rd == REG_SP)
9843 {
9844 if (offset & ~0x1fc)
9845 {
9846 inst.error = _("invalid immediate value for stack adjust");
9847 return;
9848 }
9849 inst.instruction = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
9850 inst.instruction |= offset >> 2;
9851 }
9852 else if (Rs == REG_PC || Rs == REG_SP)
9853 {
9854 if (subtract
9855 || (offset & ~0x3fc))
9856 {
9857 inst.error = _("invalid immediate for address calculation");
9858 return;
9859 }
9860 inst.instruction = (Rs == REG_PC ? T_OPCODE_ADD_PC
9861 : T_OPCODE_ADD_SP);
9862 inst.instruction |= (Rd << 8) | (offset >> 2);
9863 }
9864 else if (Rs == Rd)
9865 {
9866 if (offset & ~0xff)
9867 {
9868 inst.error = _("immediate value out of range");
9869 return;
9870 }
9871 inst.instruction = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
9872 inst.instruction |= (Rd << 8) | offset;
9873 }
9874 else
9875 {
9876 if (offset & ~0x7)
9877 {
9878 inst.error = _("immediate value out of range");
9879 return;
9880 }
9881 inst.instruction = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
9882 inst.instruction |= Rd | (Rs << 3) | (offset << 6);
9883 }
9884 }
9885 }
9886
9887 end_of_line (str);
9888 }
9889
9890 static void
thumb_shift(str,shift)9891 thumb_shift (str, shift)
9892 char * str;
9893 int shift;
9894 {
9895 int Rd, Rs, Rn = FAIL;
9896
9897 skip_whitespace (str);
9898
9899 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9900 || skip_past_comma (&str) == FAIL)
9901 {
9902 if (! inst.error)
9903 inst.error = BAD_ARGS;
9904 return;
9905 }
9906
9907 if (is_immediate_prefix (*str))
9908 {
9909 /* Two operand immediate format, set Rs to Rd. */
9910 Rs = Rd;
9911 str ++;
9912 if (my_get_expression (&inst.reloc.exp, &str))
9913 return;
9914 }
9915 else
9916 {
9917 if ((Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9918 return;
9919
9920 if (skip_past_comma (&str) == FAIL)
9921 {
9922 /* Two operand format, shuffle the registers
9923 and pretend there are 3. */
9924 Rn = Rs;
9925 Rs = Rd;
9926 }
9927 else if (is_immediate_prefix (*str))
9928 {
9929 str++;
9930 if (my_get_expression (&inst.reloc.exp, &str))
9931 return;
9932 }
9933 else if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9934 return;
9935 }
9936
9937 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
9938 for the latter case, EXPR contains the immediate that was found. */
9939
9940 if (Rn != FAIL)
9941 {
9942 if (Rs != Rd)
9943 {
9944 inst.error = _("source1 and dest must be same register");
9945 return;
9946 }
9947
9948 switch (shift)
9949 {
9950 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_R; break;
9951 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_R; break;
9952 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_R; break;
9953 }
9954
9955 inst.instruction |= Rd | (Rn << 3);
9956 }
9957 else
9958 {
9959 switch (shift)
9960 {
9961 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_I; break;
9962 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_I; break;
9963 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_I; break;
9964 }
9965
9966 if (inst.reloc.exp.X_op != O_constant)
9967 {
9968 /* Value isn't known yet, create a dummy reloc and let reloc
9969 hacking fix it up. */
9970 inst.reloc.type = BFD_RELOC_ARM_THUMB_SHIFT;
9971 }
9972 else
9973 {
9974 unsigned shift_value = inst.reloc.exp.X_add_number;
9975
9976 if (shift_value > 32 || (shift_value == 32 && shift == THUMB_LSL))
9977 {
9978 inst.error = _("invalid immediate for shift");
9979 return;
9980 }
9981
9982 /* Shifts of zero are handled by converting to LSL. */
9983 if (shift_value == 0)
9984 inst.instruction = T_OPCODE_LSL_I;
9985
9986 /* Shifts of 32 are encoded as a shift of zero. */
9987 if (shift_value == 32)
9988 shift_value = 0;
9989
9990 inst.instruction |= shift_value << 6;
9991 }
9992
9993 inst.instruction |= Rd | (Rs << 3);
9994 }
9995
9996 end_of_line (str);
9997 }
9998
9999 static void
thumb_mov_compare(str,move)10000 thumb_mov_compare (str, move)
10001 char * str;
10002 int move;
10003 {
10004 int Rd, Rs = FAIL;
10005
10006 skip_whitespace (str);
10007
10008 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
10009 || skip_past_comma (&str) == FAIL)
10010 {
10011 if (! inst.error)
10012 inst.error = BAD_ARGS;
10013 return;
10014 }
10015
10016 if (move != THUMB_CPY && is_immediate_prefix (*str))
10017 {
10018 str++;
10019 if (my_get_expression (&inst.reloc.exp, &str))
10020 return;
10021 }
10022 else if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
10023 return;
10024
10025 if (Rs != FAIL)
10026 {
10027 if (move != THUMB_CPY && Rs < 8 && Rd < 8)
10028 {
10029 if (move == THUMB_MOVE)
10030 /* A move of two lowregs is encoded as ADD Rd, Rs, #0
10031 since a MOV instruction produces unpredictable results. */
10032 inst.instruction = T_OPCODE_ADD_I3;
10033 else
10034 inst.instruction = T_OPCODE_CMP_LR;
10035 inst.instruction |= Rd | (Rs << 3);
10036 }
10037 else
10038 {
10039 if (move == THUMB_MOVE)
10040 inst.instruction = T_OPCODE_MOV_HR;
10041 else if (move != THUMB_CPY)
10042 inst.instruction = T_OPCODE_CMP_HR;
10043
10044 if (Rd > 7)
10045 inst.instruction |= THUMB_H1;
10046
10047 if (Rs > 7)
10048 inst.instruction |= THUMB_H2;
10049
10050 inst.instruction |= (Rd & 7) | ((Rs & 7) << 3);
10051 }
10052 }
10053 else
10054 {
10055 if (Rd > 7)
10056 {
10057 inst.error = _("only lo regs allowed with immediate");
10058 return;
10059 }
10060
10061 if (move == THUMB_MOVE)
10062 inst.instruction = T_OPCODE_MOV_I8;
10063 else
10064 inst.instruction = T_OPCODE_CMP_I8;
10065
10066 inst.instruction |= Rd << 8;
10067
10068 if (inst.reloc.exp.X_op != O_constant)
10069 inst.reloc.type = BFD_RELOC_ARM_THUMB_IMM;
10070 else
10071 {
10072 unsigned value = inst.reloc.exp.X_add_number;
10073
10074 if (value > 255)
10075 {
10076 inst.error = _("invalid immediate");
10077 return;
10078 }
10079
10080 inst.instruction |= value;
10081 }
10082 }
10083
10084 end_of_line (str);
10085 }
10086
10087 static void
thumb_load_store(str,load_store,size)10088 thumb_load_store (str, load_store, size)
10089 char * str;
10090 int load_store;
10091 int size;
10092 {
10093 int Rd, Rb, Ro = FAIL;
10094
10095 skip_whitespace (str);
10096
10097 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
10098 || skip_past_comma (&str) == FAIL)
10099 {
10100 if (! inst.error)
10101 inst.error = BAD_ARGS;
10102 return;
10103 }
10104
10105 if (*str == '[')
10106 {
10107 str++;
10108 if ((Rb = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
10109 return;
10110
10111 if (skip_past_comma (&str) != FAIL)
10112 {
10113 if (is_immediate_prefix (*str))
10114 {
10115 str++;
10116 if (my_get_expression (&inst.reloc.exp, &str))
10117 return;
10118 }
10119 else if ((Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
10120 return;
10121 }
10122 else
10123 {
10124 inst.reloc.exp.X_op = O_constant;
10125 inst.reloc.exp.X_add_number = 0;
10126 }
10127
10128 if (*str != ']')
10129 {
10130 inst.error = _("expected ']'");
10131 return;
10132 }
10133 str++;
10134 }
10135 else if (*str == '=')
10136 {
10137 if (load_store != THUMB_LOAD)
10138 {
10139 inst.error = _("invalid pseudo operation");
10140 return;
10141 }
10142
10143 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
10144 str++;
10145
10146 skip_whitespace (str);
10147
10148 if (my_get_expression (& inst.reloc.exp, & str))
10149 return;
10150
10151 end_of_line (str);
10152
10153 if ( inst.reloc.exp.X_op != O_constant
10154 && inst.reloc.exp.X_op != O_symbol)
10155 {
10156 inst.error = "Constant expression expected";
10157 return;
10158 }
10159
10160 if (inst.reloc.exp.X_op == O_constant
10161 && ((inst.reloc.exp.X_add_number & ~0xFF) == 0))
10162 {
10163 /* This can be done with a mov instruction. */
10164
10165 inst.instruction = T_OPCODE_MOV_I8 | (Rd << 8);
10166 inst.instruction |= inst.reloc.exp.X_add_number;
10167 return;
10168 }
10169
10170 /* Insert into literal pool. */
10171 if (add_to_lit_pool () == FAIL)
10172 {
10173 if (!inst.error)
10174 inst.error = "literal pool insertion failed";
10175 return;
10176 }
10177
10178 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
10179 inst.reloc.pc_rel = 1;
10180 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
10181 /* Adjust ARM pipeline offset to Thumb. */
10182 inst.reloc.exp.X_add_number += 4;
10183
10184 return;
10185 }
10186 else
10187 {
10188 if (my_get_expression (&inst.reloc.exp, &str))
10189 return;
10190
10191 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
10192 inst.reloc.pc_rel = 1;
10193 inst.reloc.exp.X_add_number -= 4; /* Pipeline offset. */
10194 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
10195 end_of_line (str);
10196 return;
10197 }
10198
10199 if (Rb == REG_PC || Rb == REG_SP)
10200 {
10201 if (size != THUMB_WORD)
10202 {
10203 inst.error = _("byte or halfword not valid for base register");
10204 return;
10205 }
10206 else if (Rb == REG_PC && load_store != THUMB_LOAD)
10207 {
10208 inst.error = _("r15 based store not allowed");
10209 return;
10210 }
10211 else if (Ro != FAIL)
10212 {
10213 inst.error = _("invalid base register for register offset");
10214 return;
10215 }
10216
10217 if (Rb == REG_PC)
10218 inst.instruction = T_OPCODE_LDR_PC;
10219 else if (load_store == THUMB_LOAD)
10220 inst.instruction = T_OPCODE_LDR_SP;
10221 else
10222 inst.instruction = T_OPCODE_STR_SP;
10223
10224 inst.instruction |= Rd << 8;
10225 if (inst.reloc.exp.X_op == O_constant)
10226 {
10227 unsigned offset = inst.reloc.exp.X_add_number;
10228
10229 if (offset & ~0x3fc)
10230 {
10231 inst.error = _("invalid offset");
10232 return;
10233 }
10234
10235 inst.instruction |= offset >> 2;
10236 }
10237 else
10238 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
10239 }
10240 else if (Rb > 7)
10241 {
10242 inst.error = _("invalid base register in load/store");
10243 return;
10244 }
10245 else if (Ro == FAIL)
10246 {
10247 /* Immediate offset. */
10248 if (size == THUMB_WORD)
10249 inst.instruction = (load_store == THUMB_LOAD
10250 ? T_OPCODE_LDR_IW : T_OPCODE_STR_IW);
10251 else if (size == THUMB_HALFWORD)
10252 inst.instruction = (load_store == THUMB_LOAD
10253 ? T_OPCODE_LDR_IH : T_OPCODE_STR_IH);
10254 else
10255 inst.instruction = (load_store == THUMB_LOAD
10256 ? T_OPCODE_LDR_IB : T_OPCODE_STR_IB);
10257
10258 inst.instruction |= Rd | (Rb << 3);
10259
10260 if (inst.reloc.exp.X_op == O_constant)
10261 {
10262 unsigned offset = inst.reloc.exp.X_add_number;
10263
10264 if (offset & ~(0x1f << size))
10265 {
10266 inst.error = _("invalid offset");
10267 return;
10268 }
10269 inst.instruction |= (offset >> size) << 6;
10270 }
10271 else
10272 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
10273 }
10274 else
10275 {
10276 /* Register offset. */
10277 if (size == THUMB_WORD)
10278 inst.instruction = (load_store == THUMB_LOAD
10279 ? T_OPCODE_LDR_RW : T_OPCODE_STR_RW);
10280 else if (size == THUMB_HALFWORD)
10281 inst.instruction = (load_store == THUMB_LOAD
10282 ? T_OPCODE_LDR_RH : T_OPCODE_STR_RH);
10283 else
10284 inst.instruction = (load_store == THUMB_LOAD
10285 ? T_OPCODE_LDR_RB : T_OPCODE_STR_RB);
10286
10287 inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
10288 }
10289
10290 end_of_line (str);
10291 }
10292
10293 /* A register must be given at this point.
10294
10295 Shift is the place to put it in inst.instruction.
10296
10297 Restores input start point on err.
10298 Returns the reg#, or FAIL. */
10299
10300 static int
mav_reg_required_here(str,shift,regtype)10301 mav_reg_required_here (str, shift, regtype)
10302 char ** str;
10303 int shift;
10304 enum arm_reg_type regtype;
10305 {
10306 int reg;
10307 char *start = *str;
10308
10309 if ((reg = arm_reg_parse (str, all_reg_maps[regtype].htab)) != FAIL)
10310 {
10311 if (shift >= 0)
10312 inst.instruction |= reg << shift;
10313
10314 return reg;
10315 }
10316
10317 /* Restore the start point. */
10318 *str = start;
10319
10320 /* In the few cases where we might be able to accept something else
10321 this error can be overridden. */
10322 inst.error = _(all_reg_maps[regtype].expected);
10323
10324 return FAIL;
10325 }
10326
10327 /* Cirrus Maverick Instructions. */
10328
10329 /* Wrapper functions. */
10330
10331 static void
do_mav_binops_1a(str)10332 do_mav_binops_1a (str)
10333 char * str;
10334 {
10335 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVF);
10336 }
10337
10338 static void
do_mav_binops_1b(str)10339 do_mav_binops_1b (str)
10340 char * str;
10341 {
10342 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVD);
10343 }
10344
10345 static void
do_mav_binops_1c(str)10346 do_mav_binops_1c (str)
10347 char * str;
10348 {
10349 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVDX);
10350 }
10351
10352 static void
do_mav_binops_1d(str)10353 do_mav_binops_1d (str)
10354 char * str;
10355 {
10356 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVF);
10357 }
10358
10359 static void
do_mav_binops_1e(str)10360 do_mav_binops_1e (str)
10361 char * str;
10362 {
10363 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVD);
10364 }
10365
10366 static void
do_mav_binops_1f(str)10367 do_mav_binops_1f (str)
10368 char * str;
10369 {
10370 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVF);
10371 }
10372
10373 static void
do_mav_binops_1g(str)10374 do_mav_binops_1g (str)
10375 char * str;
10376 {
10377 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVD);
10378 }
10379
10380 static void
do_mav_binops_1h(str)10381 do_mav_binops_1h (str)
10382 char * str;
10383 {
10384 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVFX);
10385 }
10386
10387 static void
do_mav_binops_1i(str)10388 do_mav_binops_1i (str)
10389 char * str;
10390 {
10391 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVFX);
10392 }
10393
10394 static void
do_mav_binops_1j(str)10395 do_mav_binops_1j (str)
10396 char * str;
10397 {
10398 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVDX);
10399 }
10400
10401 static void
do_mav_binops_1k(str)10402 do_mav_binops_1k (str)
10403 char * str;
10404 {
10405 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVDX);
10406 }
10407
10408 static void
do_mav_binops_1l(str)10409 do_mav_binops_1l (str)
10410 char * str;
10411 {
10412 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVF);
10413 }
10414
10415 static void
do_mav_binops_1m(str)10416 do_mav_binops_1m (str)
10417 char * str;
10418 {
10419 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVD);
10420 }
10421
10422 static void
do_mav_binops_1n(str)10423 do_mav_binops_1n (str)
10424 char * str;
10425 {
10426 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVFX);
10427 }
10428
10429 static void
do_mav_binops_1o(str)10430 do_mav_binops_1o (str)
10431 char * str;
10432 {
10433 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVDX, REG_TYPE_MVDX);
10434 }
10435
10436 static void
do_mav_binops_2a(str)10437 do_mav_binops_2a (str)
10438 char * str;
10439 {
10440 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVF, REG_TYPE_RN);
10441 }
10442
10443 static void
do_mav_binops_2b(str)10444 do_mav_binops_2b (str)
10445 char * str;
10446 {
10447 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVD, REG_TYPE_RN);
10448 }
10449
10450 static void
do_mav_binops_2c(str)10451 do_mav_binops_2c (str)
10452 char * str;
10453 {
10454 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVDX, REG_TYPE_RN);
10455 }
10456
10457 static void
do_mav_binops_3a(str)10458 do_mav_binops_3a (str)
10459 char * str;
10460 {
10461 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVAX, REG_TYPE_MVFX);
10462 }
10463
10464 static void
do_mav_binops_3b(str)10465 do_mav_binops_3b (str)
10466 char * str;
10467 {
10468 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVFX, REG_TYPE_MVAX);
10469 }
10470
10471 static void
do_mav_binops_3c(str)10472 do_mav_binops_3c (str)
10473 char * str;
10474 {
10475 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVAX, REG_TYPE_MVDX);
10476 }
10477
10478 static void
do_mav_binops_3d(str)10479 do_mav_binops_3d (str)
10480 char * str;
10481 {
10482 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVDX, REG_TYPE_MVAX);
10483 }
10484
10485 static void
do_mav_triple_4a(str)10486 do_mav_triple_4a (str)
10487 char * str;
10488 {
10489 do_mav_triple (str, MAV_MODE4, REG_TYPE_MVFX, REG_TYPE_MVFX, REG_TYPE_RN);
10490 }
10491
10492 static void
do_mav_triple_4b(str)10493 do_mav_triple_4b (str)
10494 char * str;
10495 {
10496 do_mav_triple (str, MAV_MODE4, REG_TYPE_MVDX, REG_TYPE_MVDX, REG_TYPE_RN);
10497 }
10498
10499 static void
do_mav_triple_5a(str)10500 do_mav_triple_5a (str)
10501 char * str;
10502 {
10503 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVF, REG_TYPE_MVF);
10504 }
10505
10506 static void
do_mav_triple_5b(str)10507 do_mav_triple_5b (str)
10508 char * str;
10509 {
10510 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVD, REG_TYPE_MVD);
10511 }
10512
10513 static void
do_mav_triple_5c(str)10514 do_mav_triple_5c (str)
10515 char * str;
10516 {
10517 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVFX, REG_TYPE_MVFX);
10518 }
10519
10520 static void
do_mav_triple_5d(str)10521 do_mav_triple_5d (str)
10522 char * str;
10523 {
10524 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVDX, REG_TYPE_MVDX);
10525 }
10526
10527 static void
do_mav_triple_5e(str)10528 do_mav_triple_5e (str)
10529 char * str;
10530 {
10531 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVF, REG_TYPE_MVF, REG_TYPE_MVF);
10532 }
10533
10534 static void
do_mav_triple_5f(str)10535 do_mav_triple_5f (str)
10536 char * str;
10537 {
10538 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVD, REG_TYPE_MVD, REG_TYPE_MVD);
10539 }
10540
10541 static void
do_mav_triple_5g(str)10542 do_mav_triple_5g (str)
10543 char * str;
10544 {
10545 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVFX, REG_TYPE_MVFX, REG_TYPE_MVFX);
10546 }
10547
10548 static void
do_mav_triple_5h(str)10549 do_mav_triple_5h (str)
10550 char * str;
10551 {
10552 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVDX, REG_TYPE_MVDX, REG_TYPE_MVDX);
10553 }
10554
10555 static void
do_mav_quad_6a(str)10556 do_mav_quad_6a (str)
10557 char * str;
10558 {
10559 do_mav_quad (str, MAV_MODE6, REG_TYPE_MVAX, REG_TYPE_MVFX, REG_TYPE_MVFX,
10560 REG_TYPE_MVFX);
10561 }
10562
10563 static void
do_mav_quad_6b(str)10564 do_mav_quad_6b (str)
10565 char * str;
10566 {
10567 do_mav_quad (str, MAV_MODE6, REG_TYPE_MVAX, REG_TYPE_MVAX, REG_TYPE_MVFX,
10568 REG_TYPE_MVFX);
10569 }
10570
10571 /* cfmvsc32<cond> DSPSC,MVDX[15:0]. */
10572 static void
do_mav_dspsc_1(str)10573 do_mav_dspsc_1 (str)
10574 char * str;
10575 {
10576 skip_whitespace (str);
10577
10578 /* cfmvsc32. */
10579 if (mav_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL
10580 || skip_past_comma (&str) == FAIL
10581 || mav_reg_required_here (&str, 12, REG_TYPE_MVDX) == FAIL)
10582 {
10583 if (!inst.error)
10584 inst.error = BAD_ARGS;
10585
10586 return;
10587 }
10588
10589 end_of_line (str);
10590 }
10591
10592 /* cfmv32sc<cond> MVDX[15:0],DSPSC. */
10593 static void
do_mav_dspsc_2(str)10594 do_mav_dspsc_2 (str)
10595 char * str;
10596 {
10597 skip_whitespace (str);
10598
10599 /* cfmv32sc. */
10600 if (mav_reg_required_here (&str, 12, REG_TYPE_MVDX) == FAIL
10601 || skip_past_comma (&str) == FAIL
10602 || mav_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL)
10603 {
10604 if (!inst.error)
10605 inst.error = BAD_ARGS;
10606
10607 return;
10608 }
10609
10610 end_of_line (str);
10611 }
10612
10613 static void
do_mav_shift_1(str)10614 do_mav_shift_1 (str)
10615 char * str;
10616 {
10617 do_mav_shift (str, REG_TYPE_MVFX, REG_TYPE_MVFX);
10618 }
10619
10620 static void
do_mav_shift_2(str)10621 do_mav_shift_2 (str)
10622 char * str;
10623 {
10624 do_mav_shift (str, REG_TYPE_MVDX, REG_TYPE_MVDX);
10625 }
10626
10627 static void
do_mav_ldst_1(str)10628 do_mav_ldst_1 (str)
10629 char * str;
10630 {
10631 do_mav_ldst (str, REG_TYPE_MVF);
10632 }
10633
10634 static void
do_mav_ldst_2(str)10635 do_mav_ldst_2 (str)
10636 char * str;
10637 {
10638 do_mav_ldst (str, REG_TYPE_MVD);
10639 }
10640
10641 static void
do_mav_ldst_3(str)10642 do_mav_ldst_3 (str)
10643 char * str;
10644 {
10645 do_mav_ldst (str, REG_TYPE_MVFX);
10646 }
10647
10648 static void
do_mav_ldst_4(str)10649 do_mav_ldst_4 (str)
10650 char * str;
10651 {
10652 do_mav_ldst (str, REG_TYPE_MVDX);
10653 }
10654
10655 /* Isnsn like "foo X,Y". */
10656
10657 static void
do_mav_binops(str,mode,reg0,reg1)10658 do_mav_binops (str, mode, reg0, reg1)
10659 char * str;
10660 int mode;
10661 enum arm_reg_type reg0;
10662 enum arm_reg_type reg1;
10663 {
10664 int shift0, shift1;
10665
10666 shift0 = mode & 0xff;
10667 shift1 = (mode >> 8) & 0xff;
10668
10669 skip_whitespace (str);
10670
10671 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
10672 || skip_past_comma (&str) == FAIL
10673 || mav_reg_required_here (&str, shift1, reg1) == FAIL)
10674 {
10675 if (!inst.error)
10676 inst.error = BAD_ARGS;
10677 }
10678 else
10679 end_of_line (str);
10680 }
10681
10682 /* Isnsn like "foo X,Y,Z". */
10683
10684 static void
do_mav_triple(str,mode,reg0,reg1,reg2)10685 do_mav_triple (str, mode, reg0, reg1, reg2)
10686 char * str;
10687 int mode;
10688 enum arm_reg_type reg0;
10689 enum arm_reg_type reg1;
10690 enum arm_reg_type reg2;
10691 {
10692 int shift0, shift1, shift2;
10693
10694 shift0 = mode & 0xff;
10695 shift1 = (mode >> 8) & 0xff;
10696 shift2 = (mode >> 16) & 0xff;
10697
10698 skip_whitespace (str);
10699
10700 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
10701 || skip_past_comma (&str) == FAIL
10702 || mav_reg_required_here (&str, shift1, reg1) == FAIL
10703 || skip_past_comma (&str) == FAIL
10704 || mav_reg_required_here (&str, shift2, reg2) == FAIL)
10705 {
10706 if (!inst.error)
10707 inst.error = BAD_ARGS;
10708 }
10709 else
10710 end_of_line (str);
10711 }
10712
10713 /* Isnsn like "foo W,X,Y,Z".
10714 where W=MVAX[0:3] and X,Y,Z=MVFX[0:15]. */
10715
10716 static void
do_mav_quad(str,mode,reg0,reg1,reg2,reg3)10717 do_mav_quad (str, mode, reg0, reg1, reg2, reg3)
10718 char * str;
10719 int mode;
10720 enum arm_reg_type reg0;
10721 enum arm_reg_type reg1;
10722 enum arm_reg_type reg2;
10723 enum arm_reg_type reg3;
10724 {
10725 int shift0, shift1, shift2, shift3;
10726
10727 shift0= mode & 0xff;
10728 shift1 = (mode >> 8) & 0xff;
10729 shift2 = (mode >> 16) & 0xff;
10730 shift3 = (mode >> 24) & 0xff;
10731
10732 skip_whitespace (str);
10733
10734 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
10735 || skip_past_comma (&str) == FAIL
10736 || mav_reg_required_here (&str, shift1, reg1) == FAIL
10737 || skip_past_comma (&str) == FAIL
10738 || mav_reg_required_here (&str, shift2, reg2) == FAIL
10739 || skip_past_comma (&str) == FAIL
10740 || mav_reg_required_here (&str, shift3, reg3) == FAIL)
10741 {
10742 if (!inst.error)
10743 inst.error = BAD_ARGS;
10744 }
10745 else
10746 end_of_line (str);
10747 }
10748
10749 /* Maverick shift immediate instructions.
10750 cfsh32<cond> MVFX[15:0],MVFX[15:0],Shift[6:0].
10751 cfsh64<cond> MVDX[15:0],MVDX[15:0],Shift[6:0]. */
10752
10753 static void
do_mav_shift(str,reg0,reg1)10754 do_mav_shift (str, reg0, reg1)
10755 char * str;
10756 enum arm_reg_type reg0;
10757 enum arm_reg_type reg1;
10758 {
10759 int error;
10760 int imm, neg = 0;
10761
10762 skip_whitespace (str);
10763
10764 error = 0;
10765
10766 if (mav_reg_required_here (&str, 12, reg0) == FAIL
10767 || skip_past_comma (&str) == FAIL
10768 || mav_reg_required_here (&str, 16, reg1) == FAIL
10769 || skip_past_comma (&str) == FAIL)
10770 {
10771 if (!inst.error)
10772 inst.error = BAD_ARGS;
10773 return;
10774 }
10775
10776 /* Calculate the immediate operand.
10777 The operand is a 7bit signed number. */
10778 skip_whitespace (str);
10779
10780 if (*str == '#')
10781 ++str;
10782
10783 if (!ISDIGIT (*str) && *str != '-')
10784 {
10785 inst.error = _("expecting immediate, 7bit operand");
10786 return;
10787 }
10788
10789 if (*str == '-')
10790 {
10791 neg = 1;
10792 ++str;
10793 }
10794
10795 for (imm = 0; *str && ISDIGIT (*str); ++str)
10796 imm = imm * 10 + *str - '0';
10797
10798 if (imm > 64)
10799 {
10800 inst.error = _("immediate out of range");
10801 return;
10802 }
10803
10804 /* Make negative imm's into 7bit signed numbers. */
10805 if (neg)
10806 {
10807 imm = -imm;
10808 imm &= 0x0000007f;
10809 }
10810
10811 /* Bits 0-3 of the insn should have bits 0-3 of the immediate.
10812 Bits 5-7 of the insn should have bits 4-6 of the immediate.
10813 Bit 4 should be 0. */
10814 imm = (imm & 0xf) | ((imm & 0x70) << 1);
10815
10816 inst.instruction |= imm;
10817 end_of_line (str);
10818 }
10819
10820 static int
mav_parse_offset(str,negative)10821 mav_parse_offset (str, negative)
10822 char ** str;
10823 int *negative;
10824 {
10825 char * p = *str;
10826 int offset;
10827
10828 *negative = 0;
10829
10830 skip_whitespace (p);
10831
10832 if (*p == '#')
10833 ++p;
10834
10835 if (*p == '-')
10836 {
10837 *negative = 1;
10838 ++p;
10839 }
10840
10841 if (!ISDIGIT (*p))
10842 {
10843 inst.error = _("offset expected");
10844 return 0;
10845 }
10846
10847 for (offset = 0; *p && ISDIGIT (*p); ++p)
10848 offset = offset * 10 + *p - '0';
10849
10850 if (offset > 0xff)
10851 {
10852 inst.error = _("offset out of range");
10853 return 0;
10854 }
10855
10856 *str = p;
10857
10858 return *negative ? -offset : offset;
10859 }
10860
10861 /* Maverick load/store instructions.
10862 <insn><cond> CRd,[Rn,<offset>]{!}.
10863 <insn><cond> CRd,[Rn],<offset>. */
10864
10865 static void
do_mav_ldst(str,reg0)10866 do_mav_ldst (str, reg0)
10867 char * str;
10868 enum arm_reg_type reg0;
10869 {
10870 int offset, negative;
10871
10872 skip_whitespace (str);
10873
10874 if (mav_reg_required_here (&str, 12, reg0) == FAIL
10875 || skip_past_comma (&str) == FAIL
10876 || *str++ != '['
10877 || reg_required_here (&str, 16) == FAIL)
10878 goto fail_ldst;
10879
10880 if (skip_past_comma (&str) == SUCCESS)
10881 {
10882 /* You are here: "<offset>]{!}". */
10883 inst.instruction |= PRE_INDEX;
10884
10885 offset = mav_parse_offset (&str, &negative);
10886
10887 if (inst.error)
10888 return;
10889
10890 if (*str++ != ']')
10891 {
10892 inst.error = _("missing ]");
10893 return;
10894 }
10895
10896 if (*str == '!')
10897 {
10898 inst.instruction |= WRITE_BACK;
10899 ++str;
10900 }
10901 }
10902 else
10903 {
10904 /* You are here: "], <offset>". */
10905 if (*str++ != ']')
10906 {
10907 inst.error = _("missing ]");
10908 return;
10909 }
10910
10911 if (skip_past_comma (&str) == FAIL
10912 || (offset = mav_parse_offset (&str, &negative), inst.error))
10913 goto fail_ldst;
10914
10915 inst.instruction |= CP_T_WB; /* Post indexed, set bit W. */
10916 }
10917
10918 if (negative)
10919 offset = -offset;
10920 else
10921 inst.instruction |= CP_T_UD; /* Positive, so set bit U. */
10922
10923 inst.instruction |= offset >> 2;
10924 end_of_line (str);
10925 return;
10926
10927 fail_ldst:
10928 if (!inst.error)
10929 inst.error = BAD_ARGS;
10930 }
10931
10932 static void
do_t_nop(str)10933 do_t_nop (str)
10934 char * str;
10935 {
10936 /* Do nothing. */
10937 end_of_line (str);
10938 }
10939
10940 /* Handle the Format 4 instructions that do not have equivalents in other
10941 formats. That is, ADC, AND, EOR, SBC, ROR, TST, NEG, CMN, ORR, MUL,
10942 BIC and MVN. */
10943
10944 static void
do_t_arit(str)10945 do_t_arit (str)
10946 char * str;
10947 {
10948 int Rd, Rs, Rn;
10949
10950 skip_whitespace (str);
10951
10952 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
10953 || skip_past_comma (&str) == FAIL
10954 || (Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
10955 {
10956 inst.error = BAD_ARGS;
10957 return;
10958 }
10959
10960 if (skip_past_comma (&str) != FAIL)
10961 {
10962 /* Three operand format not allowed for TST, CMN, NEG and MVN.
10963 (It isn't allowed for CMP either, but that isn't handled by this
10964 function.) */
10965 if (inst.instruction == T_OPCODE_TST
10966 || inst.instruction == T_OPCODE_CMN
10967 || inst.instruction == T_OPCODE_NEG
10968 || inst.instruction == T_OPCODE_MVN)
10969 {
10970 inst.error = BAD_ARGS;
10971 return;
10972 }
10973
10974 if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
10975 return;
10976
10977 if (Rs != Rd)
10978 {
10979 inst.error = _("dest and source1 must be the same register");
10980 return;
10981 }
10982 Rs = Rn;
10983 }
10984
10985 if (inst.instruction == T_OPCODE_MUL
10986 && Rs == Rd)
10987 as_tsktsk (_("Rs and Rd must be different in MUL"));
10988
10989 inst.instruction |= Rd | (Rs << 3);
10990 end_of_line (str);
10991 }
10992
10993 static void
do_t_add(str)10994 do_t_add (str)
10995 char * str;
10996 {
10997 thumb_add_sub (str, 0);
10998 }
10999
11000 static void
do_t_asr(str)11001 do_t_asr (str)
11002 char * str;
11003 {
11004 thumb_shift (str, THUMB_ASR);
11005 }
11006
11007 static void
do_t_branch9(str)11008 do_t_branch9 (str)
11009 char * str;
11010 {
11011 if (my_get_expression (&inst.reloc.exp, &str))
11012 return;
11013 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH9;
11014 inst.reloc.pc_rel = 1;
11015 end_of_line (str);
11016 }
11017
11018 static void
do_t_branch12(str)11019 do_t_branch12 (str)
11020 char * str;
11021 {
11022 if (my_get_expression (&inst.reloc.exp, &str))
11023 return;
11024 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH12;
11025 inst.reloc.pc_rel = 1;
11026 end_of_line (str);
11027 }
11028
11029 /* Find the real, Thumb encoded start of a Thumb function. */
11030
11031 static symbolS *
find_real_start(symbolP)11032 find_real_start (symbolP)
11033 symbolS * symbolP;
11034 {
11035 char * real_start;
11036 const char * name = S_GET_NAME (symbolP);
11037 symbolS * new_target;
11038
11039 /* This definition must agree with the one in gcc/config/arm/thumb.c. */
11040 #define STUB_NAME ".real_start_of"
11041
11042 if (name == NULL)
11043 abort ();
11044
11045 /* Names that start with '.' are local labels, not function entry points.
11046 The compiler may generate BL instructions to these labels because it
11047 needs to perform a branch to a far away location. */
11048 if (name[0] == '.')
11049 return symbolP;
11050
11051 real_start = malloc (strlen (name) + strlen (STUB_NAME) + 1);
11052 sprintf (real_start, "%s%s", STUB_NAME, name);
11053
11054 new_target = symbol_find (real_start);
11055
11056 if (new_target == NULL)
11057 {
11058 as_warn ("Failed to find real start of function: %s\n", name);
11059 new_target = symbolP;
11060 }
11061
11062 free (real_start);
11063
11064 return new_target;
11065 }
11066
11067 static void
do_t_branch23(str)11068 do_t_branch23 (str)
11069 char * str;
11070 {
11071 if (my_get_expression (& inst.reloc.exp, & str))
11072 return;
11073
11074 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH23;
11075 inst.reloc.pc_rel = 1;
11076 end_of_line (str);
11077
11078 /* If the destination of the branch is a defined symbol which does not have
11079 the THUMB_FUNC attribute, then we must be calling a function which has
11080 the (interfacearm) attribute. We look for the Thumb entry point to that
11081 function and change the branch to refer to that function instead. */
11082 if ( inst.reloc.exp.X_op == O_symbol
11083 && inst.reloc.exp.X_add_symbol != NULL
11084 && S_IS_DEFINED (inst.reloc.exp.X_add_symbol)
11085 && ! THUMB_IS_FUNC (inst.reloc.exp.X_add_symbol))
11086 inst.reloc.exp.X_add_symbol =
11087 find_real_start (inst.reloc.exp.X_add_symbol);
11088 }
11089
11090 static void
do_t_bx(str)11091 do_t_bx (str)
11092 char * str;
11093 {
11094 int reg;
11095
11096 skip_whitespace (str);
11097
11098 if ((reg = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
11099 return;
11100
11101 /* This sets THUMB_H2 from the top bit of reg. */
11102 inst.instruction |= reg << 3;
11103
11104 /* ??? FIXME: Should add a hacky reloc here if reg is REG_PC. The reloc
11105 should cause the alignment to be checked once it is known. This is
11106 because BX PC only works if the instruction is word aligned. */
11107
11108 end_of_line (str);
11109 }
11110
11111 static void
do_t_compare(str)11112 do_t_compare (str)
11113 char * str;
11114 {
11115 thumb_mov_compare (str, THUMB_COMPARE);
11116 }
11117
11118 static void
do_t_ldmstm(str)11119 do_t_ldmstm (str)
11120 char * str;
11121 {
11122 int Rb;
11123 long range;
11124
11125 skip_whitespace (str);
11126
11127 if ((Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
11128 return;
11129
11130 if (*str != '!')
11131 as_warn (_("inserted missing '!': load/store multiple always writes back base register"));
11132 else
11133 str++;
11134
11135 if (skip_past_comma (&str) == FAIL
11136 || (range = reg_list (&str)) == FAIL)
11137 {
11138 if (! inst.error)
11139 inst.error = BAD_ARGS;
11140 return;
11141 }
11142
11143 if (inst.reloc.type != BFD_RELOC_NONE)
11144 {
11145 /* This really doesn't seem worth it. */
11146 inst.reloc.type = BFD_RELOC_NONE;
11147 inst.error = _("expression too complex");
11148 return;
11149 }
11150
11151 if (range & ~0xff)
11152 {
11153 inst.error = _("only lo-regs valid in load/store multiple");
11154 return;
11155 }
11156
11157 inst.instruction |= (Rb << 8) | range;
11158 end_of_line (str);
11159 }
11160
11161 static void
do_t_ldr(str)11162 do_t_ldr (str)
11163 char * str;
11164 {
11165 thumb_load_store (str, THUMB_LOAD, THUMB_WORD);
11166 }
11167
11168 static void
do_t_ldrb(str)11169 do_t_ldrb (str)
11170 char * str;
11171 {
11172 thumb_load_store (str, THUMB_LOAD, THUMB_BYTE);
11173 }
11174
11175 static void
do_t_ldrh(str)11176 do_t_ldrh (str)
11177 char * str;
11178 {
11179 thumb_load_store (str, THUMB_LOAD, THUMB_HALFWORD);
11180 }
11181
11182 static void
do_t_lds(str)11183 do_t_lds (str)
11184 char * str;
11185 {
11186 int Rd, Rb, Ro;
11187
11188 skip_whitespace (str);
11189
11190 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
11191 || skip_past_comma (&str) == FAIL
11192 || *str++ != '['
11193 || (Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL
11194 || skip_past_comma (&str) == FAIL
11195 || (Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL
11196 || *str++ != ']')
11197 {
11198 if (! inst.error)
11199 inst.error = _("syntax: ldrs[b] Rd, [Rb, Ro]");
11200 return;
11201 }
11202
11203 inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
11204 end_of_line (str);
11205 }
11206
11207 static void
do_t_lsl(str)11208 do_t_lsl (str)
11209 char * str;
11210 {
11211 thumb_shift (str, THUMB_LSL);
11212 }
11213
11214 static void
do_t_lsr(str)11215 do_t_lsr (str)
11216 char * str;
11217 {
11218 thumb_shift (str, THUMB_LSR);
11219 }
11220
11221 static void
do_t_mov(str)11222 do_t_mov (str)
11223 char * str;
11224 {
11225 thumb_mov_compare (str, THUMB_MOVE);
11226 }
11227
11228 static void
do_t_push_pop(str)11229 do_t_push_pop (str)
11230 char * str;
11231 {
11232 long range;
11233
11234 skip_whitespace (str);
11235
11236 if ((range = reg_list (&str)) == FAIL)
11237 {
11238 if (! inst.error)
11239 inst.error = BAD_ARGS;
11240 return;
11241 }
11242
11243 if (inst.reloc.type != BFD_RELOC_NONE)
11244 {
11245 /* This really doesn't seem worth it. */
11246 inst.reloc.type = BFD_RELOC_NONE;
11247 inst.error = _("expression too complex");
11248 return;
11249 }
11250
11251 if (range & ~0xff)
11252 {
11253 if ((inst.instruction == T_OPCODE_PUSH
11254 && (range & ~0xff) == 1 << REG_LR)
11255 || (inst.instruction == T_OPCODE_POP
11256 && (range & ~0xff) == 1 << REG_PC))
11257 {
11258 inst.instruction |= THUMB_PP_PC_LR;
11259 range &= 0xff;
11260 }
11261 else
11262 {
11263 inst.error = _("invalid register list to push/pop instruction");
11264 return;
11265 }
11266 }
11267
11268 inst.instruction |= range;
11269 end_of_line (str);
11270 }
11271
11272 static void
do_t_str(str)11273 do_t_str (str)
11274 char * str;
11275 {
11276 thumb_load_store (str, THUMB_STORE, THUMB_WORD);
11277 }
11278
11279 static void
do_t_strb(str)11280 do_t_strb (str)
11281 char * str;
11282 {
11283 thumb_load_store (str, THUMB_STORE, THUMB_BYTE);
11284 }
11285
11286 static void
do_t_strh(str)11287 do_t_strh (str)
11288 char * str;
11289 {
11290 thumb_load_store (str, THUMB_STORE, THUMB_HALFWORD);
11291 }
11292
11293 static void
do_t_sub(str)11294 do_t_sub (str)
11295 char * str;
11296 {
11297 thumb_add_sub (str, 1);
11298 }
11299
11300 static void
do_t_swi(str)11301 do_t_swi (str)
11302 char * str;
11303 {
11304 skip_whitespace (str);
11305
11306 if (my_get_expression (&inst.reloc.exp, &str))
11307 return;
11308
11309 inst.reloc.type = BFD_RELOC_ARM_SWI;
11310 end_of_line (str);
11311 }
11312
11313 static void
do_t_adr(str)11314 do_t_adr (str)
11315 char * str;
11316 {
11317 int reg;
11318
11319 /* This is a pseudo-op of the form "adr rd, label" to be converted
11320 into a relative address of the form "add rd, pc, #label-.-4". */
11321 skip_whitespace (str);
11322
11323 /* Store Rd in temporary location inside instruction. */
11324 if ((reg = reg_required_here (&str, 4)) == FAIL
11325 || (reg > 7) /* For Thumb reg must be r0..r7. */
11326 || skip_past_comma (&str) == FAIL
11327 || my_get_expression (&inst.reloc.exp, &str))
11328 {
11329 if (!inst.error)
11330 inst.error = BAD_ARGS;
11331 return;
11332 }
11333
11334 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
11335 inst.reloc.exp.X_add_number -= 4; /* PC relative adjust. */
11336 inst.reloc.pc_rel = 1;
11337 inst.instruction |= REG_PC; /* Rd is already placed into the instruction. */
11338
11339 end_of_line (str);
11340 }
11341
11342 static void
insert_reg(r,htab)11343 insert_reg (r, htab)
11344 const struct reg_entry *r;
11345 struct hash_control *htab;
11346 {
11347 int len = strlen (r->name) + 2;
11348 char * buf = (char *) xmalloc (len);
11349 char * buf2 = (char *) xmalloc (len);
11350 int i = 0;
11351
11352 #ifdef REGISTER_PREFIX
11353 buf[i++] = REGISTER_PREFIX;
11354 #endif
11355
11356 strcpy (buf + i, r->name);
11357
11358 for (i = 0; buf[i]; i++)
11359 buf2[i] = TOUPPER (buf[i]);
11360
11361 buf2[i] = '\0';
11362
11363 hash_insert (htab, buf, (PTR) r);
11364 hash_insert (htab, buf2, (PTR) r);
11365 }
11366
11367 static void
build_reg_hsh(map)11368 build_reg_hsh (map)
11369 struct reg_map *map;
11370 {
11371 const struct reg_entry *r;
11372
11373 if ((map->htab = hash_new ()) == NULL)
11374 as_fatal (_("virtual memory exhausted"));
11375
11376 for (r = map->names; r->name != NULL; r++)
11377 insert_reg (r, map->htab);
11378 }
11379
11380 static void
insert_reg_alias(str,regnum,htab)11381 insert_reg_alias (str, regnum, htab)
11382 char *str;
11383 int regnum;
11384 struct hash_control *htab;
11385 {
11386 const char *error;
11387 struct reg_entry *new = xmalloc (sizeof (struct reg_entry));
11388 const char *name = xmalloc (strlen (str) + 1);
11389
11390 strcpy ((char *) name, str);
11391
11392 new->name = name;
11393 new->number = regnum;
11394 new->builtin = FALSE;
11395
11396 error = hash_insert (htab, name, (PTR) new);
11397 if (error)
11398 {
11399 as_bad (_("failed to create an alias for %s, reason: %s"),
11400 str, error);
11401 free ((char *) name);
11402 free (new);
11403 }
11404 }
11405
11406 /* Look for the .req directive. This is of the form:
11407
11408 new_register_name .req existing_register_name
11409
11410 If we find one, or if it looks sufficiently like one that we want to
11411 handle any error here, return non-zero. Otherwise return zero. */
11412 static int
create_register_alias(newname,p)11413 create_register_alias (newname, p)
11414 char *newname;
11415 char *p;
11416 {
11417 char *q;
11418 char c;
11419
11420 q = p;
11421 skip_whitespace (q);
11422
11423 c = *p;
11424 *p = '\0';
11425
11426 if (*q && !strncmp (q, ".req ", 5))
11427 {
11428 char *copy_of_str;
11429 char *r;
11430
11431 #ifdef IGNORE_OPCODE_CASE
11432 newname = original_case_string;
11433 #endif
11434 copy_of_str = newname;
11435
11436 q += 4;
11437 skip_whitespace (q);
11438
11439 for (r = q; *r != '\0'; r++)
11440 if (*r == ' ')
11441 break;
11442
11443 if (r != q)
11444 {
11445 enum arm_reg_type new_type, old_type;
11446 int old_regno;
11447 char d = *r;
11448
11449 *r = '\0';
11450 old_type = arm_reg_parse_any (q);
11451 *r = d;
11452
11453 new_type = arm_reg_parse_any (newname);
11454
11455 if (new_type == REG_TYPE_MAX)
11456 {
11457 if (old_type != REG_TYPE_MAX)
11458 {
11459 old_regno = arm_reg_parse (&q, all_reg_maps[old_type].htab);
11460 insert_reg_alias (newname, old_regno,
11461 all_reg_maps[old_type].htab);
11462 }
11463 else
11464 as_warn (_("register '%s' does not exist\n"), q);
11465 }
11466 else if (old_type == REG_TYPE_MAX)
11467 {
11468 as_warn (_("ignoring redefinition of register alias '%s' to non-existant register '%s'"),
11469 copy_of_str, q);
11470 }
11471 else
11472 {
11473 /* Do not warn about redefinitions to the same alias. */
11474 if (new_type != old_type
11475 || (arm_reg_parse (&q, all_reg_maps[old_type].htab)
11476 != arm_reg_parse (&q, all_reg_maps[new_type].htab)))
11477 as_warn (_("ignoring redefinition of register alias '%s'"),
11478 copy_of_str);
11479
11480 }
11481 }
11482 else
11483 as_warn (_("ignoring incomplete .req pseuso op"));
11484
11485 *p = c;
11486 return 1;
11487 }
11488
11489 *p = c;
11490 return 0;
11491 }
11492
11493 static void
set_constant_flonums()11494 set_constant_flonums ()
11495 {
11496 int i;
11497
11498 for (i = 0; i < NUM_FLOAT_VALS; i++)
11499 if (atof_ieee ((char *) fp_const[i], 'x', fp_values[i]) == NULL)
11500 abort ();
11501 }
11502
11503 /* Iterate over the base tables to create the instruction patterns. */
11504 static void
build_arm_ops_hsh()11505 build_arm_ops_hsh ()
11506 {
11507 unsigned int i;
11508 unsigned int j;
11509 static struct obstack insn_obstack;
11510
11511 obstack_begin (&insn_obstack, 4000);
11512
11513 for (i = 0; i < sizeof (insns) / sizeof (struct asm_opcode); i++)
11514 {
11515 const struct asm_opcode *insn = insns + i;
11516
11517 if (insn->cond_offset != 0)
11518 {
11519 /* Insn supports conditional execution. Build the varaints
11520 and insert them in the hash table. */
11521 for (j = 0; j < sizeof (conds) / sizeof (struct asm_cond); j++)
11522 {
11523 unsigned len = strlen (insn->template);
11524 struct asm_opcode *new;
11525 char *template;
11526
11527 new = obstack_alloc (&insn_obstack, sizeof (struct asm_opcode));
11528 /* All condition codes are two characters. */
11529 template = obstack_alloc (&insn_obstack, len + 3);
11530
11531 strncpy (template, insn->template, insn->cond_offset);
11532 strcpy (template + insn->cond_offset, conds[j].template);
11533 if (len > insn->cond_offset)
11534 strcpy (template + insn->cond_offset + 2,
11535 insn->template + insn->cond_offset);
11536 new->template = template;
11537 new->cond_offset = 0;
11538 new->variant = insn->variant;
11539 new->parms = insn->parms;
11540 new->value = (insn->value & ~COND_MASK) | conds[j].value;
11541
11542 hash_insert (arm_ops_hsh, new->template, (PTR) new);
11543 }
11544 }
11545 /* Finally, insert the unconditional insn in the table directly;
11546 no need to build a copy. */
11547 hash_insert (arm_ops_hsh, insn->template, (PTR) insn);
11548 }
11549 }
11550
11551 #if 0 /* Suppressed - for now. */
11552 #if defined OBJ_ELF || defined OBJ_COFF
11553
11554 #ifdef OBJ_ELF
11555 #define arm_Note Elf_External_Note
11556 #else
11557 typedef struct
11558 {
11559 unsigned char namesz[4]; /* Size of entry's owner string. */
11560 unsigned char descsz[4]; /* Size of the note descriptor. */
11561 unsigned char type[4]; /* Interpretation of the descriptor. */
11562 char name[1]; /* Start of the name+desc data. */
11563 } arm_Note;
11564 #endif
11565
11566 /* The description is kept to a fix sized in order to make updating
11567 it and merging it easier. */
11568 #define ARM_NOTE_DESCRIPTION_LENGTH 8
11569
11570 static void
11571 arm_add_note (name, description, type)
11572 const char * name;
11573 const char * description;
11574 unsigned int type;
11575 {
11576 arm_Note note ATTRIBUTE_UNUSED;
11577 char * p;
11578 unsigned int name_len;
11579
11580 name_len = (strlen (name) + 1 + 3) & ~3;
11581
11582 p = frag_more (sizeof (note.namesz));
11583 md_number_to_chars (p, (valueT) name_len, sizeof (note.namesz));
11584
11585 p = frag_more (sizeof (note.descsz));
11586 md_number_to_chars (p, (valueT) ARM_NOTE_DESCRIPTION_LENGTH, sizeof (note.descsz));
11587
11588 p = frag_more (sizeof (note.type));
11589 md_number_to_chars (p, (valueT) type, sizeof (note.type));
11590
11591 p = frag_more (name_len);
11592 strcpy (p, name);
11593
11594 p = frag_more (ARM_NOTE_DESCRIPTION_LENGTH);
11595 strncpy (p, description, ARM_NOTE_DESCRIPTION_LENGTH);
11596 frag_align (2, 0, 0);
11597 }
11598 #endif
11599 #endif
11600
11601 void
md_begin()11602 md_begin ()
11603 {
11604 unsigned mach;
11605 unsigned int i;
11606
11607 if ( (arm_ops_hsh = hash_new ()) == NULL
11608 || (arm_tops_hsh = hash_new ()) == NULL
11609 || (arm_cond_hsh = hash_new ()) == NULL
11610 || (arm_shift_hsh = hash_new ()) == NULL
11611 || (arm_psr_hsh = hash_new ()) == NULL)
11612 as_fatal (_("virtual memory exhausted"));
11613
11614 build_arm_ops_hsh ();
11615 for (i = 0; i < sizeof (tinsns) / sizeof (struct thumb_opcode); i++)
11616 hash_insert (arm_tops_hsh, tinsns[i].template, (PTR) (tinsns + i));
11617 for (i = 0; i < sizeof (conds) / sizeof (struct asm_cond); i++)
11618 hash_insert (arm_cond_hsh, conds[i].template, (PTR) (conds + i));
11619 for (i = 0; i < sizeof (shift_names) / sizeof (struct asm_shift_name); i++)
11620 hash_insert (arm_shift_hsh, shift_names[i].name, (PTR) (shift_names + i));
11621 for (i = 0; i < sizeof (psrs) / sizeof (struct asm_psr); i++)
11622 hash_insert (arm_psr_hsh, psrs[i].template, (PTR) (psrs + i));
11623
11624 for (i = (int) REG_TYPE_FIRST; i < (int) REG_TYPE_MAX; i++)
11625 build_reg_hsh (all_reg_maps + i);
11626
11627 set_constant_flonums ();
11628
11629 /* Set the cpu variant based on the command-line options. We prefer
11630 -mcpu= over -march= if both are set (as for GCC); and we prefer
11631 -mfpu= over any other way of setting the floating point unit.
11632 Use of legacy options with new options are faulted. */
11633 if (legacy_cpu != -1)
11634 {
11635 if (mcpu_cpu_opt != -1 || march_cpu_opt != -1)
11636 as_bad (_("use of old and new-style options to set CPU type"));
11637
11638 mcpu_cpu_opt = legacy_cpu;
11639 }
11640 else if (mcpu_cpu_opt == -1)
11641 mcpu_cpu_opt = march_cpu_opt;
11642
11643 if (legacy_fpu != -1)
11644 {
11645 if (mfpu_opt != -1)
11646 as_bad (_("use of old and new-style options to set FPU type"));
11647
11648 mfpu_opt = legacy_fpu;
11649 }
11650 else if (mfpu_opt == -1)
11651 {
11652 #if !(defined (TE_LINUX) || defined (TE_NetBSD) || defined(TE_OpenBSD))
11653 /* Some environments specify a default FPU. If they don't, infer it
11654 from the processor. */
11655 if (mcpu_fpu_opt != -1)
11656 mfpu_opt = mcpu_fpu_opt;
11657 else
11658 mfpu_opt = march_fpu_opt;
11659 #else
11660 mfpu_opt = FPU_DEFAULT;
11661 #endif
11662 }
11663
11664 if (mfpu_opt == -1)
11665 {
11666 if (mcpu_cpu_opt == -1)
11667 mfpu_opt = FPU_DEFAULT;
11668 else if (mcpu_cpu_opt & ARM_EXT_V5)
11669 mfpu_opt = FPU_ARCH_VFP_V2;
11670 else
11671 mfpu_opt = FPU_ARCH_FPA;
11672 }
11673
11674 if (mcpu_cpu_opt == -1)
11675 mcpu_cpu_opt = CPU_DEFAULT;
11676
11677 cpu_variant = mcpu_cpu_opt | mfpu_opt;
11678
11679 #if defined OBJ_COFF || defined OBJ_ELF
11680 {
11681 unsigned int flags = 0;
11682
11683 /* Set the flags in the private structure. */
11684 if (uses_apcs_26) flags |= F_APCS26;
11685 if (support_interwork) flags |= F_INTERWORK;
11686 if (uses_apcs_float) flags |= F_APCS_FLOAT;
11687 if (pic_code) flags |= F_PIC;
11688 if ((cpu_variant & FPU_ANY) == FPU_NONE
11689 || (cpu_variant & FPU_ANY) == FPU_ARCH_VFP) /* VFP layout only. */
11690 {
11691 flags |= F_SOFT_FLOAT;
11692 }
11693 switch (mfloat_abi_opt)
11694 {
11695 case ARM_FLOAT_ABI_SOFT:
11696 case ARM_FLOAT_ABI_SOFTFP:
11697 flags |= F_SOFT_FLOAT;
11698 break;
11699
11700 case ARM_FLOAT_ABI_HARD:
11701 if (flags & F_SOFT_FLOAT)
11702 as_bad (_("hard-float conflicts with specified fpu"));
11703 break;
11704 }
11705 /* Using VFP conventions (even if soft-float). */
11706 if (cpu_variant & FPU_VFP_EXT_NONE) flags |= F_VFP_FLOAT;
11707
11708 #if defined OBJ_ELF
11709 if (cpu_variant & FPU_ARCH_MAVERICK)
11710 flags |= EF_ARM_MAVERICK_FLOAT;
11711 #endif
11712
11713 bfd_set_private_flags (stdoutput, flags);
11714
11715 /* We have run out flags in the COFF header to encode the
11716 status of ATPCS support, so instead we create a dummy,
11717 empty, debug section called .arm.atpcs. */
11718 if (atpcs)
11719 {
11720 asection * sec;
11721
11722 sec = bfd_make_section (stdoutput, ".arm.atpcs");
11723
11724 if (sec != NULL)
11725 {
11726 bfd_set_section_flags
11727 (stdoutput, sec, SEC_READONLY | SEC_DEBUGGING /* | SEC_HAS_CONTENTS */);
11728 bfd_set_section_size (stdoutput, sec, 0);
11729 bfd_set_section_contents (stdoutput, sec, NULL, 0, 0);
11730 }
11731 }
11732 }
11733 #endif
11734
11735 /* Record the CPU type as well. */
11736 switch (cpu_variant & ARM_CPU_MASK)
11737 {
11738 case ARM_2:
11739 mach = bfd_mach_arm_2;
11740 break;
11741
11742 case ARM_3: /* Also ARM_250. */
11743 mach = bfd_mach_arm_2a;
11744 break;
11745
11746 case ARM_6: /* Also ARM_7. */
11747 mach = bfd_mach_arm_3;
11748 break;
11749
11750 default:
11751 mach = bfd_mach_arm_unknown;
11752 break;
11753 }
11754
11755 /* Catch special cases. */
11756 if (cpu_variant & ARM_CEXT_IWMMXT)
11757 mach = bfd_mach_arm_iWMMXt;
11758 else if (cpu_variant & ARM_CEXT_XSCALE)
11759 mach = bfd_mach_arm_XScale;
11760 else if (cpu_variant & ARM_CEXT_MAVERICK)
11761 mach = bfd_mach_arm_ep9312;
11762 else if (cpu_variant & ARM_EXT_V5E)
11763 mach = bfd_mach_arm_5TE;
11764 else if (cpu_variant & ARM_EXT_V5)
11765 {
11766 if (cpu_variant & ARM_EXT_V4T)
11767 mach = bfd_mach_arm_5T;
11768 else
11769 mach = bfd_mach_arm_5;
11770 }
11771 else if (cpu_variant & ARM_EXT_V4)
11772 {
11773 if (cpu_variant & ARM_EXT_V4T)
11774 mach = bfd_mach_arm_4T;
11775 else
11776 mach = bfd_mach_arm_4;
11777 }
11778 else if (cpu_variant & ARM_EXT_V3M)
11779 mach = bfd_mach_arm_3M;
11780
11781 #if 0 /* Suppressed - for now. */
11782 #if defined (OBJ_ELF) || defined (OBJ_COFF)
11783
11784 /* Create a .note section to fully identify this arm binary. */
11785
11786 #define NOTE_ARCH_STRING "arch: "
11787
11788 #if defined OBJ_COFF && ! defined NT_VERSION
11789 #define NT_VERSION 1
11790 #define NT_ARCH 2
11791 #endif
11792
11793 {
11794 segT current_seg = now_seg;
11795 subsegT current_subseg = now_subseg;
11796 asection * arm_arch;
11797 const char * arch_string;
11798
11799 arm_arch = bfd_make_section_old_way (stdoutput, ARM_NOTE_SECTION);
11800
11801 #ifdef OBJ_COFF
11802 bfd_set_section_flags (stdoutput, arm_arch,
11803 SEC_DATA | SEC_ALLOC | SEC_LOAD | SEC_LINK_ONCE \
11804 | SEC_HAS_CONTENTS);
11805 #else
11806 bfd_set_section_flags (stdoutput, arm_arch,
11807 SEC_READONLY | SEC_HAS_CONTENTS);
11808 #endif
11809 arm_arch->output_section = arm_arch;
11810 subseg_set (arm_arch, 0);
11811
11812 switch (mach)
11813 {
11814 default:
11815 case bfd_mach_arm_unknown: arch_string = "unknown"; break;
11816 case bfd_mach_arm_2: arch_string = "armv2"; break;
11817 case bfd_mach_arm_2a: arch_string = "armv2a"; break;
11818 case bfd_mach_arm_3: arch_string = "armv3"; break;
11819 case bfd_mach_arm_3M: arch_string = "armv3M"; break;
11820 case bfd_mach_arm_4: arch_string = "armv4"; break;
11821 case bfd_mach_arm_4T: arch_string = "armv4t"; break;
11822 case bfd_mach_arm_5: arch_string = "armv5"; break;
11823 case bfd_mach_arm_5T: arch_string = "armv5t"; break;
11824 case bfd_mach_arm_5TE: arch_string = "armv5te"; break;
11825 case bfd_mach_arm_XScale: arch_string = "XScale"; break;
11826 case bfd_mach_arm_ep9312: arch_string = "ep9312"; break;
11827 case bfd_mach_arm_iWMMXt: arch_string = "iWMMXt"; break;
11828 }
11829
11830 arm_add_note (NOTE_ARCH_STRING, arch_string, NT_ARCH);
11831
11832 subseg_set (current_seg, current_subseg);
11833 }
11834 #endif
11835 #endif /* Suppressed code. */
11836
11837 bfd_set_arch_mach (stdoutput, TARGET_ARCH, mach);
11838 }
11839
11840 /* Turn an integer of n bytes (in val) into a stream of bytes appropriate
11841 for use in the a.out file, and stores them in the array pointed to by buf.
11842 This knows about the endian-ness of the target machine and does
11843 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
11844 2 (short) and 4 (long) Floating numbers are put out as a series of
11845 LITTLENUMS (shorts, here at least). */
11846
11847 void
md_number_to_chars(buf,val,n)11848 md_number_to_chars (buf, val, n)
11849 char * buf;
11850 valueT val;
11851 int n;
11852 {
11853 if (target_big_endian)
11854 number_to_chars_bigendian (buf, val, n);
11855 else
11856 number_to_chars_littleendian (buf, val, n);
11857 }
11858
11859 static valueT
md_chars_to_number(buf,n)11860 md_chars_to_number (buf, n)
11861 char * buf;
11862 int n;
11863 {
11864 valueT result = 0;
11865 unsigned char * where = (unsigned char *) buf;
11866
11867 if (target_big_endian)
11868 {
11869 while (n--)
11870 {
11871 result <<= 8;
11872 result |= (*where++ & 255);
11873 }
11874 }
11875 else
11876 {
11877 while (n--)
11878 {
11879 result <<= 8;
11880 result |= (where[n] & 255);
11881 }
11882 }
11883
11884 return result;
11885 }
11886
11887 /* Turn a string in input_line_pointer into a floating point constant
11888 of type TYPE, and store the appropriate bytes in *LITP. The number
11889 of LITTLENUMS emitted is stored in *SIZEP. An error message is
11890 returned, or NULL on OK.
11891
11892 Note that fp constants aren't represent in the normal way on the ARM.
11893 In big endian mode, things are as expected. However, in little endian
11894 mode fp constants are big-endian word-wise, and little-endian byte-wise
11895 within the words. For example, (double) 1.1 in big endian mode is
11896 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
11897 the byte sequence 99 99 f1 3f 9a 99 99 99.
11898
11899 ??? The format of 12 byte floats is uncertain according to gcc's arm.h. */
11900
11901 char *
md_atof(type,litP,sizeP)11902 md_atof (type, litP, sizeP)
11903 char type;
11904 char * litP;
11905 int * sizeP;
11906 {
11907 int prec;
11908 LITTLENUM_TYPE words[MAX_LITTLENUMS];
11909 char *t;
11910 int i;
11911
11912 switch (type)
11913 {
11914 case 'f':
11915 case 'F':
11916 case 's':
11917 case 'S':
11918 prec = 2;
11919 break;
11920
11921 case 'd':
11922 case 'D':
11923 case 'r':
11924 case 'R':
11925 prec = 4;
11926 break;
11927
11928 case 'x':
11929 case 'X':
11930 prec = 6;
11931 break;
11932
11933 case 'p':
11934 case 'P':
11935 prec = 6;
11936 break;
11937
11938 default:
11939 *sizeP = 0;
11940 return _("bad call to MD_ATOF()");
11941 }
11942
11943 t = atof_ieee (input_line_pointer, type, words);
11944 if (t)
11945 input_line_pointer = t;
11946 *sizeP = prec * 2;
11947
11948 if (target_big_endian)
11949 {
11950 for (i = 0; i < prec; i++)
11951 {
11952 md_number_to_chars (litP, (valueT) words[i], 2);
11953 litP += 2;
11954 }
11955 }
11956 else
11957 {
11958 if (cpu_variant & FPU_ARCH_VFP)
11959 for (i = prec - 1; i >= 0; i--)
11960 {
11961 md_number_to_chars (litP, (valueT) words[i], 2);
11962 litP += 2;
11963 }
11964 else
11965 /* For a 4 byte float the order of elements in `words' is 1 0.
11966 For an 8 byte float the order is 1 0 3 2. */
11967 for (i = 0; i < prec; i += 2)
11968 {
11969 md_number_to_chars (litP, (valueT) words[i + 1], 2);
11970 md_number_to_chars (litP + 2, (valueT) words[i], 2);
11971 litP += 4;
11972 }
11973 }
11974
11975 return 0;
11976 }
11977
11978 /* The knowledge of the PC's pipeline offset is built into the insns
11979 themselves. */
11980
11981 long
md_pcrel_from(fixP)11982 md_pcrel_from (fixP)
11983 fixS * fixP;
11984 {
11985 if (fixP->fx_addsy
11986 && S_GET_SEGMENT (fixP->fx_addsy) == undefined_section
11987 && fixP->fx_subsy == NULL)
11988 return 0;
11989
11990 if (fixP->fx_pcrel && (fixP->fx_r_type == BFD_RELOC_ARM_THUMB_ADD))
11991 {
11992 /* PC relative addressing on the Thumb is slightly odd
11993 as the bottom two bits of the PC are forced to zero
11994 for the calculation. */
11995 return (fixP->fx_where + fixP->fx_frag->fr_address) & ~3;
11996 }
11997
11998 #ifdef TE_WINCE
11999 /* The pattern was adjusted to accommodate CE's off-by-one fixups,
12000 so we un-adjust here to compensate for the accommodation. */
12001 return fixP->fx_where + fixP->fx_frag->fr_address + 8;
12002 #else
12003 return fixP->fx_where + fixP->fx_frag->fr_address;
12004 #endif
12005 }
12006
12007 /* Round up a section size to the appropriate boundary. */
12008
12009 valueT
md_section_align(segment,size)12010 md_section_align (segment, size)
12011 segT segment ATTRIBUTE_UNUSED;
12012 valueT size;
12013 {
12014 #ifdef OBJ_ELF
12015 return size;
12016 #else
12017 /* Round all sects to multiple of 4. */
12018 return (size + 3) & ~3;
12019 #endif
12020 }
12021
12022 /* Under ELF we need to default _GLOBAL_OFFSET_TABLE.
12023 Otherwise we have no need to default values of symbols. */
12024
12025 symbolS *
md_undefined_symbol(name)12026 md_undefined_symbol (name)
12027 char * name ATTRIBUTE_UNUSED;
12028 {
12029 #ifdef OBJ_ELF
12030 if (name[0] == '_' && name[1] == 'G'
12031 && streq (name, GLOBAL_OFFSET_TABLE_NAME))
12032 {
12033 if (!GOT_symbol)
12034 {
12035 if (symbol_find (name))
12036 as_bad ("GOT already in the symbol table");
12037
12038 GOT_symbol = symbol_new (name, undefined_section,
12039 (valueT) 0, & zero_address_frag);
12040 }
12041
12042 return GOT_symbol;
12043 }
12044 #endif
12045
12046 return 0;
12047 }
12048
12049 /* arm_reg_parse () := if it looks like a register, return its token and
12050 advance the pointer. */
12051
12052 static int
arm_reg_parse(ccp,htab)12053 arm_reg_parse (ccp, htab)
12054 register char ** ccp;
12055 struct hash_control *htab;
12056 {
12057 char * start = * ccp;
12058 char c;
12059 char * p;
12060 struct reg_entry * reg;
12061
12062 #ifdef REGISTER_PREFIX
12063 if (*start != REGISTER_PREFIX)
12064 return FAIL;
12065 p = start + 1;
12066 #else
12067 p = start;
12068 #ifdef OPTIONAL_REGISTER_PREFIX
12069 if (*p == OPTIONAL_REGISTER_PREFIX)
12070 p++, start++;
12071 #endif
12072 #endif
12073 if (!ISALPHA (*p) || !is_name_beginner (*p))
12074 return FAIL;
12075
12076 c = *p++;
12077 while (ISALPHA (c) || ISDIGIT (c) || c == '_')
12078 c = *p++;
12079
12080 *--p = 0;
12081 reg = (struct reg_entry *) hash_find (htab, start);
12082 *p = c;
12083
12084 if (reg)
12085 {
12086 *ccp = p;
12087 return reg->number;
12088 }
12089
12090 return FAIL;
12091 }
12092
12093 /* Search for the following register name in each of the possible reg name
12094 tables. Return the classification if found, or REG_TYPE_MAX if not
12095 present. */
12096 static enum arm_reg_type
arm_reg_parse_any(cp)12097 arm_reg_parse_any (cp)
12098 char *cp;
12099 {
12100 int i;
12101
12102 for (i = (int) REG_TYPE_FIRST; i < (int) REG_TYPE_MAX; i++)
12103 if (arm_reg_parse (&cp, all_reg_maps[i].htab) != FAIL)
12104 return (enum arm_reg_type) i;
12105
12106 return REG_TYPE_MAX;
12107 }
12108
12109 void
md_apply_fix3(fixP,valP,seg)12110 md_apply_fix3 (fixP, valP, seg)
12111 fixS * fixP;
12112 valueT * valP;
12113 segT seg;
12114 {
12115 offsetT value = * valP;
12116 offsetT newval;
12117 unsigned int newimm;
12118 unsigned long temp;
12119 int sign;
12120 char * buf = fixP->fx_where + fixP->fx_frag->fr_literal;
12121 arm_fix_data * arm_data = (arm_fix_data *) fixP->tc_fix_data;
12122
12123 assert (fixP->fx_r_type < BFD_RELOC_UNUSED);
12124
12125 /* Note whether this will delete the relocation. */
12126 #if 0
12127 /* Patch from REarnshaw to JDavis (disabled for the moment, since it
12128 doesn't work fully.) */
12129 if ((fixP->fx_addsy == 0 || symbol_constant_p (fixP->fx_addsy))
12130 && !fixP->fx_pcrel)
12131 #else
12132 if (fixP->fx_addsy == 0 && !fixP->fx_pcrel)
12133 #endif
12134 fixP->fx_done = 1;
12135
12136 /* If this symbol is in a different section then we need to leave it for
12137 the linker to deal with. Unfortunately, md_pcrel_from can't tell,
12138 so we have to undo it's effects here. */
12139 if (fixP->fx_pcrel)
12140 {
12141 if (fixP->fx_addsy != NULL
12142 && S_IS_DEFINED (fixP->fx_addsy)
12143 && S_GET_SEGMENT (fixP->fx_addsy) != seg)
12144 {
12145 if (target_oabi
12146 && (fixP->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH
12147 || fixP->fx_r_type == BFD_RELOC_ARM_PCREL_BLX
12148 ))
12149 value = 0;
12150 else
12151 value += md_pcrel_from (fixP);
12152 }
12153 }
12154
12155 /* Remember value for emit_reloc. */
12156 fixP->fx_addnumber = value;
12157
12158 switch (fixP->fx_r_type)
12159 {
12160 case BFD_RELOC_ARM_IMMEDIATE:
12161 newimm = validate_immediate (value);
12162 temp = md_chars_to_number (buf, INSN_SIZE);
12163
12164 /* If the instruction will fail, see if we can fix things up by
12165 changing the opcode. */
12166 if (newimm == (unsigned int) FAIL
12167 && (newimm = negate_data_op (&temp, value)) == (unsigned int) FAIL)
12168 {
12169 as_bad_where (fixP->fx_file, fixP->fx_line,
12170 _("invalid constant (%lx) after fixup"),
12171 (unsigned long) value);
12172 break;
12173 }
12174
12175 newimm |= (temp & 0xfffff000);
12176 md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
12177 fixP->fx_done = 1;
12178 break;
12179
12180 case BFD_RELOC_ARM_ADRL_IMMEDIATE:
12181 {
12182 unsigned int highpart = 0;
12183 unsigned int newinsn = 0xe1a00000; /* nop. */
12184
12185 newimm = validate_immediate (value);
12186 temp = md_chars_to_number (buf, INSN_SIZE);
12187
12188 /* If the instruction will fail, see if we can fix things up by
12189 changing the opcode. */
12190 if (newimm == (unsigned int) FAIL
12191 && (newimm = negate_data_op (& temp, value)) == (unsigned int) FAIL)
12192 {
12193 /* No ? OK - try using two ADD instructions to generate
12194 the value. */
12195 newimm = validate_immediate_twopart (value, & highpart);
12196
12197 /* Yes - then make sure that the second instruction is
12198 also an add. */
12199 if (newimm != (unsigned int) FAIL)
12200 newinsn = temp;
12201 /* Still No ? Try using a negated value. */
12202 else if ((newimm = validate_immediate_twopart (- value, & highpart)) != (unsigned int) FAIL)
12203 temp = newinsn = (temp & OPCODE_MASK) | OPCODE_SUB << DATA_OP_SHIFT;
12204 /* Otherwise - give up. */
12205 else
12206 {
12207 as_bad_where (fixP->fx_file, fixP->fx_line,
12208 _("unable to compute ADRL instructions for PC offset of 0x%lx"),
12209 (long) value);
12210 break;
12211 }
12212
12213 /* Replace the first operand in the 2nd instruction (which
12214 is the PC) with the destination register. We have
12215 already added in the PC in the first instruction and we
12216 do not want to do it again. */
12217 newinsn &= ~ 0xf0000;
12218 newinsn |= ((newinsn & 0x0f000) << 4);
12219 }
12220
12221 newimm |= (temp & 0xfffff000);
12222 md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
12223
12224 highpart |= (newinsn & 0xfffff000);
12225 md_number_to_chars (buf + INSN_SIZE, (valueT) highpart, INSN_SIZE);
12226 }
12227 break;
12228
12229 case BFD_RELOC_ARM_OFFSET_IMM:
12230 sign = value >= 0;
12231
12232 if (value < 0)
12233 value = - value;
12234
12235 if (validate_offset_imm (value, 0) == FAIL)
12236 {
12237 as_bad_where (fixP->fx_file, fixP->fx_line,
12238 _("bad immediate value for offset (%ld)"),
12239 (long) value);
12240 break;
12241 }
12242
12243 newval = md_chars_to_number (buf, INSN_SIZE);
12244 newval &= 0xff7ff000;
12245 newval |= value | (sign ? INDEX_UP : 0);
12246 md_number_to_chars (buf, newval, INSN_SIZE);
12247 break;
12248
12249 case BFD_RELOC_ARM_OFFSET_IMM8:
12250 case BFD_RELOC_ARM_HWLITERAL:
12251 sign = value >= 0;
12252
12253 if (value < 0)
12254 value = - value;
12255
12256 if (validate_offset_imm (value, 1) == FAIL)
12257 {
12258 if (fixP->fx_r_type == BFD_RELOC_ARM_HWLITERAL)
12259 as_bad_where (fixP->fx_file, fixP->fx_line,
12260 _("invalid literal constant: pool needs to be closer"));
12261 else
12262 as_bad (_("bad immediate value for half-word offset (%ld)"),
12263 (long) value);
12264 break;
12265 }
12266
12267 newval = md_chars_to_number (buf, INSN_SIZE);
12268 newval &= 0xff7ff0f0;
12269 newval |= ((value >> 4) << 8) | (value & 0xf) | (sign ? INDEX_UP : 0);
12270 md_number_to_chars (buf, newval, INSN_SIZE);
12271 break;
12272
12273 case BFD_RELOC_ARM_LITERAL:
12274 sign = value >= 0;
12275
12276 if (value < 0)
12277 value = - value;
12278
12279 if (validate_offset_imm (value, 0) == FAIL)
12280 {
12281 as_bad_where (fixP->fx_file, fixP->fx_line,
12282 _("invalid literal constant: pool needs to be closer"));
12283 break;
12284 }
12285
12286 newval = md_chars_to_number (buf, INSN_SIZE);
12287 newval &= 0xff7ff000;
12288 newval |= value | (sign ? INDEX_UP : 0);
12289 md_number_to_chars (buf, newval, INSN_SIZE);
12290 break;
12291
12292 case BFD_RELOC_ARM_SHIFT_IMM:
12293 newval = md_chars_to_number (buf, INSN_SIZE);
12294 if (((unsigned long) value) > 32
12295 || (value == 32
12296 && (((newval & 0x60) == 0) || (newval & 0x60) == 0x60)))
12297 {
12298 as_bad_where (fixP->fx_file, fixP->fx_line,
12299 _("shift expression is too large"));
12300 break;
12301 }
12302
12303 if (value == 0)
12304 /* Shifts of zero must be done as lsl. */
12305 newval &= ~0x60;
12306 else if (value == 32)
12307 value = 0;
12308 newval &= 0xfffff07f;
12309 newval |= (value & 0x1f) << 7;
12310 md_number_to_chars (buf, newval, INSN_SIZE);
12311 break;
12312
12313 case BFD_RELOC_ARM_SWI:
12314 if (arm_data->thumb_mode)
12315 {
12316 if (((unsigned long) value) > 0xff)
12317 as_bad_where (fixP->fx_file, fixP->fx_line,
12318 _("invalid swi expression"));
12319 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xff00;
12320 newval |= value;
12321 md_number_to_chars (buf, newval, THUMB_SIZE);
12322 }
12323 else
12324 {
12325 if (((unsigned long) value) > 0x00ffffff)
12326 as_bad_where (fixP->fx_file, fixP->fx_line,
12327 _("invalid swi expression"));
12328 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff000000;
12329 newval |= value;
12330 md_number_to_chars (buf, newval, INSN_SIZE);
12331 }
12332 break;
12333
12334 case BFD_RELOC_ARM_MULTI:
12335 if (((unsigned long) value) > 0xffff)
12336 as_bad_where (fixP->fx_file, fixP->fx_line,
12337 _("invalid expression in load/store multiple"));
12338 newval = value | md_chars_to_number (buf, INSN_SIZE);
12339 md_number_to_chars (buf, newval, INSN_SIZE);
12340 break;
12341
12342 case BFD_RELOC_ARM_PCREL_BRANCH:
12343 newval = md_chars_to_number (buf, INSN_SIZE);
12344
12345 /* Sign-extend a 24-bit number. */
12346 #define SEXT24(x) ((((x) & 0xffffff) ^ (~ 0x7fffff)) + 0x800000)
12347
12348 #ifdef OBJ_ELF
12349 if (! target_oabi)
12350 value = fixP->fx_offset;
12351 #endif
12352
12353 /* We are going to store value (shifted right by two) in the
12354 instruction, in a 24 bit, signed field. Thus we need to check
12355 that none of the top 8 bits of the shifted value (top 7 bits of
12356 the unshifted, unsigned value) are set, or that they are all set. */
12357 if ((value & ~ ((offsetT) 0x1ffffff)) != 0
12358 && ((value & ~ ((offsetT) 0x1ffffff)) != ~ ((offsetT) 0x1ffffff)))
12359 {
12360 #ifdef OBJ_ELF
12361 /* Normally we would be stuck at this point, since we cannot store
12362 the absolute address that is the destination of the branch in the
12363 24 bits of the branch instruction. If however, we happen to know
12364 that the destination of the branch is in the same section as the
12365 branch instruction itself, then we can compute the relocation for
12366 ourselves and not have to bother the linker with it.
12367
12368 FIXME: The tests for OBJ_ELF and ! target_oabi are only here
12369 because I have not worked out how to do this for OBJ_COFF or
12370 target_oabi. */
12371 if (! target_oabi
12372 && fixP->fx_addsy != NULL
12373 && S_IS_DEFINED (fixP->fx_addsy)
12374 && S_GET_SEGMENT (fixP->fx_addsy) == seg)
12375 {
12376 /* Get pc relative value to go into the branch. */
12377 value = * valP;
12378
12379 /* Permit a backward branch provided that enough bits
12380 are set. Allow a forwards branch, provided that
12381 enough bits are clear. */
12382 if ( (value & ~ ((offsetT) 0x1ffffff)) == ~ ((offsetT) 0x1ffffff)
12383 || (value & ~ ((offsetT) 0x1ffffff)) == 0)
12384 fixP->fx_done = 1;
12385 }
12386
12387 if (! fixP->fx_done)
12388 #endif
12389 as_bad_where (fixP->fx_file, fixP->fx_line,
12390 _("GAS can't handle same-section branch dest >= 0x04000000"));
12391 }
12392
12393 value >>= 2;
12394 value += SEXT24 (newval);
12395
12396 if ( (value & ~ ((offsetT) 0xffffff)) != 0
12397 && ((value & ~ ((offsetT) 0xffffff)) != ~ ((offsetT) 0xffffff)))
12398 as_bad_where (fixP->fx_file, fixP->fx_line,
12399 _("out of range branch"));
12400
12401 newval = (value & 0x00ffffff) | (newval & 0xff000000);
12402 md_number_to_chars (buf, newval, INSN_SIZE);
12403 break;
12404
12405 case BFD_RELOC_ARM_PCREL_BLX:
12406 {
12407 offsetT hbit;
12408 newval = md_chars_to_number (buf, INSN_SIZE);
12409
12410 #ifdef OBJ_ELF
12411 if (! target_oabi)
12412 value = fixP->fx_offset;
12413 #endif
12414 hbit = (value >> 1) & 1;
12415 value = (value >> 2) & 0x00ffffff;
12416 value = (value + (newval & 0x00ffffff)) & 0x00ffffff;
12417 newval = value | (newval & 0xfe000000) | (hbit << 24);
12418 md_number_to_chars (buf, newval, INSN_SIZE);
12419 }
12420 break;
12421
12422 case BFD_RELOC_THUMB_PCREL_BRANCH9: /* Conditional branch. */
12423 newval = md_chars_to_number (buf, THUMB_SIZE);
12424 {
12425 addressT diff = (newval & 0xff) << 1;
12426 if (diff & 0x100)
12427 diff |= ~0xff;
12428
12429 value += diff;
12430 if ((value & ~0xff) && ((value & ~0xff) != ~0xff))
12431 as_bad_where (fixP->fx_file, fixP->fx_line,
12432 _("branch out of range"));
12433 newval = (newval & 0xff00) | ((value & 0x1ff) >> 1);
12434 }
12435 md_number_to_chars (buf, newval, THUMB_SIZE);
12436 break;
12437
12438 case BFD_RELOC_THUMB_PCREL_BRANCH12: /* Unconditional branch. */
12439 newval = md_chars_to_number (buf, THUMB_SIZE);
12440 {
12441 addressT diff = (newval & 0x7ff) << 1;
12442 if (diff & 0x800)
12443 diff |= ~0x7ff;
12444
12445 value += diff;
12446 if ((value & ~0x7ff) && ((value & ~0x7ff) != ~0x7ff))
12447 as_bad_where (fixP->fx_file, fixP->fx_line,
12448 _("branch out of range"));
12449 newval = (newval & 0xf800) | ((value & 0xfff) >> 1);
12450 }
12451 md_number_to_chars (buf, newval, THUMB_SIZE);
12452 break;
12453
12454 case BFD_RELOC_THUMB_PCREL_BLX:
12455 case BFD_RELOC_THUMB_PCREL_BRANCH23:
12456 {
12457 offsetT newval2;
12458 addressT diff;
12459
12460 newval = md_chars_to_number (buf, THUMB_SIZE);
12461 newval2 = md_chars_to_number (buf + THUMB_SIZE, THUMB_SIZE);
12462 diff = ((newval & 0x7ff) << 12) | ((newval2 & 0x7ff) << 1);
12463 if (diff & 0x400000)
12464 diff |= ~0x3fffff;
12465 #ifdef OBJ_ELF
12466 value = fixP->fx_offset;
12467 #endif
12468 value += diff;
12469
12470 if ((value & ~0x3fffff) && ((value & ~0x3fffff) != ~0x3fffff))
12471 as_bad_where (fixP->fx_file, fixP->fx_line,
12472 _("branch with link out of range"));
12473
12474 newval = (newval & 0xf800) | ((value & 0x7fffff) >> 12);
12475 newval2 = (newval2 & 0xf800) | ((value & 0xfff) >> 1);
12476 if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX)
12477 /* For a BLX instruction, make sure that the relocation is rounded up
12478 to a word boundary. This follows the semantics of the instruction
12479 which specifies that bit 1 of the target address will come from bit
12480 1 of the base address. */
12481 newval2 = (newval2 + 1) & ~ 1;
12482 md_number_to_chars (buf, newval, THUMB_SIZE);
12483 md_number_to_chars (buf + THUMB_SIZE, newval2, THUMB_SIZE);
12484 }
12485 break;
12486
12487 case BFD_RELOC_8:
12488 if (fixP->fx_done || fixP->fx_pcrel)
12489 md_number_to_chars (buf, value, 1);
12490 #ifdef OBJ_ELF
12491 else if (!target_oabi)
12492 {
12493 value = fixP->fx_offset;
12494 md_number_to_chars (buf, value, 1);
12495 }
12496 #endif
12497 break;
12498
12499 case BFD_RELOC_16:
12500 if (fixP->fx_done || fixP->fx_pcrel)
12501 md_number_to_chars (buf, value, 2);
12502 #ifdef OBJ_ELF
12503 else if (!target_oabi)
12504 {
12505 value = fixP->fx_offset;
12506 md_number_to_chars (buf, value, 2);
12507 }
12508 #endif
12509 break;
12510
12511 #ifdef OBJ_ELF
12512 case BFD_RELOC_ARM_GOT32:
12513 case BFD_RELOC_ARM_GOTOFF:
12514 md_number_to_chars (buf, 0, 4);
12515 break;
12516 #endif
12517
12518 case BFD_RELOC_RVA:
12519 case BFD_RELOC_32:
12520 if (fixP->fx_done || fixP->fx_pcrel)
12521 md_number_to_chars (buf, value, 4);
12522 #ifdef OBJ_ELF
12523 else if (!target_oabi)
12524 {
12525 value = fixP->fx_offset;
12526 md_number_to_chars (buf, value, 4);
12527 }
12528 #endif
12529 break;
12530
12531 #ifdef OBJ_ELF
12532 case BFD_RELOC_ARM_PLT32:
12533 /* It appears the instruction is fully prepared at this point. */
12534 break;
12535 #endif
12536
12537 case BFD_RELOC_ARM_CP_OFF_IMM:
12538 sign = value >= 0;
12539 if (value < -1023 || value > 1023 || (value & 3))
12540 as_bad_where (fixP->fx_file, fixP->fx_line,
12541 _("illegal value for co-processor offset"));
12542 if (value < 0)
12543 value = -value;
12544 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
12545 newval |= (value >> 2) | (sign ? INDEX_UP : 0);
12546 md_number_to_chars (buf, newval, INSN_SIZE);
12547 break;
12548
12549 case BFD_RELOC_ARM_CP_OFF_IMM_S2:
12550 sign = value >= 0;
12551 if (value < -255 || value > 255)
12552 as_bad_where (fixP->fx_file, fixP->fx_line,
12553 _("Illegal value for co-processor offset"));
12554 if (value < 0)
12555 value = -value;
12556 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
12557 newval |= value | (sign ? INDEX_UP : 0);
12558 md_number_to_chars (buf, newval , INSN_SIZE);
12559 break;
12560
12561 case BFD_RELOC_ARM_THUMB_OFFSET:
12562 newval = md_chars_to_number (buf, THUMB_SIZE);
12563 /* Exactly what ranges, and where the offset is inserted depends
12564 on the type of instruction, we can establish this from the
12565 top 4 bits. */
12566 switch (newval >> 12)
12567 {
12568 case 4: /* PC load. */
12569 /* Thumb PC loads are somewhat odd, bit 1 of the PC is
12570 forced to zero for these loads, so we will need to round
12571 up the offset if the instruction address is not word
12572 aligned (since the final address produced must be, and
12573 we can only describe word-aligned immediate offsets). */
12574
12575 if ((fixP->fx_frag->fr_address + fixP->fx_where + value) & 3)
12576 as_bad_where (fixP->fx_file, fixP->fx_line,
12577 _("invalid offset, target not word aligned (0x%08X)"),
12578 (unsigned int) (fixP->fx_frag->fr_address
12579 + fixP->fx_where + value));
12580
12581 if ((value + 2) & ~0x3fe)
12582 as_bad_where (fixP->fx_file, fixP->fx_line,
12583 _("invalid offset, value too big (0x%08lX)"),
12584 (long) value);
12585
12586 /* Round up, since pc will be rounded down. */
12587 newval |= (value + 2) >> 2;
12588 break;
12589
12590 case 9: /* SP load/store. */
12591 if (value & ~0x3fc)
12592 as_bad_where (fixP->fx_file, fixP->fx_line,
12593 _("invalid offset, value too big (0x%08lX)"),
12594 (long) value);
12595 newval |= value >> 2;
12596 break;
12597
12598 case 6: /* Word load/store. */
12599 if (value & ~0x7c)
12600 as_bad_where (fixP->fx_file, fixP->fx_line,
12601 _("invalid offset, value too big (0x%08lX)"),
12602 (long) value);
12603 newval |= value << 4; /* 6 - 2. */
12604 break;
12605
12606 case 7: /* Byte load/store. */
12607 if (value & ~0x1f)
12608 as_bad_where (fixP->fx_file, fixP->fx_line,
12609 _("invalid offset, value too big (0x%08lX)"),
12610 (long) value);
12611 newval |= value << 6;
12612 break;
12613
12614 case 8: /* Halfword load/store. */
12615 if (value & ~0x3e)
12616 as_bad_where (fixP->fx_file, fixP->fx_line,
12617 _("invalid offset, value too big (0x%08lX)"),
12618 (long) value);
12619 newval |= value << 5; /* 6 - 1. */
12620 break;
12621
12622 default:
12623 as_bad_where (fixP->fx_file, fixP->fx_line,
12624 "Unable to process relocation for thumb opcode: %lx",
12625 (unsigned long) newval);
12626 break;
12627 }
12628 md_number_to_chars (buf, newval, THUMB_SIZE);
12629 break;
12630
12631 case BFD_RELOC_ARM_THUMB_ADD:
12632 /* This is a complicated relocation, since we use it for all of
12633 the following immediate relocations:
12634
12635 3bit ADD/SUB
12636 8bit ADD/SUB
12637 9bit ADD/SUB SP word-aligned
12638 10bit ADD PC/SP word-aligned
12639
12640 The type of instruction being processed is encoded in the
12641 instruction field:
12642
12643 0x8000 SUB
12644 0x00F0 Rd
12645 0x000F Rs
12646 */
12647 newval = md_chars_to_number (buf, THUMB_SIZE);
12648 {
12649 int rd = (newval >> 4) & 0xf;
12650 int rs = newval & 0xf;
12651 int subtract = newval & 0x8000;
12652
12653 if (rd == REG_SP)
12654 {
12655 if (value & ~0x1fc)
12656 as_bad_where (fixP->fx_file, fixP->fx_line,
12657 _("invalid immediate for stack address calculation"));
12658 newval = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
12659 newval |= value >> 2;
12660 }
12661 else if (rs == REG_PC || rs == REG_SP)
12662 {
12663 if (subtract ||
12664 value & ~0x3fc)
12665 as_bad_where (fixP->fx_file, fixP->fx_line,
12666 _("invalid immediate for address calculation (value = 0x%08lX)"),
12667 (unsigned long) value);
12668 newval = (rs == REG_PC ? T_OPCODE_ADD_PC : T_OPCODE_ADD_SP);
12669 newval |= rd << 8;
12670 newval |= value >> 2;
12671 }
12672 else if (rs == rd)
12673 {
12674 if (value & ~0xff)
12675 as_bad_where (fixP->fx_file, fixP->fx_line,
12676 _("invalid 8bit immediate"));
12677 newval = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
12678 newval |= (rd << 8) | value;
12679 }
12680 else
12681 {
12682 if (value & ~0x7)
12683 as_bad_where (fixP->fx_file, fixP->fx_line,
12684 _("invalid 3bit immediate"));
12685 newval = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
12686 newval |= rd | (rs << 3) | (value << 6);
12687 }
12688 }
12689 md_number_to_chars (buf, newval, THUMB_SIZE);
12690 break;
12691
12692 case BFD_RELOC_ARM_THUMB_IMM:
12693 newval = md_chars_to_number (buf, THUMB_SIZE);
12694 switch (newval >> 11)
12695 {
12696 case 0x04: /* 8bit immediate MOV. */
12697 case 0x05: /* 8bit immediate CMP. */
12698 if (value < 0 || value > 255)
12699 as_bad_where (fixP->fx_file, fixP->fx_line,
12700 _("invalid immediate: %ld is too large"),
12701 (long) value);
12702 newval |= value;
12703 break;
12704
12705 default:
12706 abort ();
12707 }
12708 md_number_to_chars (buf, newval, THUMB_SIZE);
12709 break;
12710
12711 case BFD_RELOC_ARM_THUMB_SHIFT:
12712 /* 5bit shift value (0..31). */
12713 if (value < 0 || value > 31)
12714 as_bad_where (fixP->fx_file, fixP->fx_line,
12715 _("illegal Thumb shift value: %ld"), (long) value);
12716 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xf03f;
12717 newval |= value << 6;
12718 md_number_to_chars (buf, newval, THUMB_SIZE);
12719 break;
12720
12721 case BFD_RELOC_VTABLE_INHERIT:
12722 case BFD_RELOC_VTABLE_ENTRY:
12723 fixP->fx_done = 0;
12724 return;
12725
12726 case BFD_RELOC_NONE:
12727 default:
12728 as_bad_where (fixP->fx_file, fixP->fx_line,
12729 _("bad relocation fixup type (%d)"), fixP->fx_r_type);
12730 }
12731 }
12732
12733 /* Translate internal representation of relocation info to BFD target
12734 format. */
12735
12736 arelent *
tc_gen_reloc(section,fixp)12737 tc_gen_reloc (section, fixp)
12738 asection * section ATTRIBUTE_UNUSED;
12739 fixS * fixp;
12740 {
12741 arelent * reloc;
12742 bfd_reloc_code_real_type code;
12743
12744 reloc = (arelent *) xmalloc (sizeof (arelent));
12745
12746 reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
12747 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
12748 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
12749
12750 /* @@ Why fx_addnumber sometimes and fx_offset other times? */
12751 #ifndef OBJ_ELF
12752 if (fixp->fx_pcrel == 0)
12753 reloc->addend = fixp->fx_offset;
12754 else
12755 reloc->addend = fixp->fx_offset = reloc->address;
12756 #else /* OBJ_ELF */
12757 reloc->addend = fixp->fx_offset;
12758 #endif
12759
12760 switch (fixp->fx_r_type)
12761 {
12762 case BFD_RELOC_8:
12763 if (fixp->fx_pcrel)
12764 {
12765 code = BFD_RELOC_8_PCREL;
12766 break;
12767 }
12768
12769 case BFD_RELOC_16:
12770 if (fixp->fx_pcrel)
12771 {
12772 code = BFD_RELOC_16_PCREL;
12773 break;
12774 }
12775
12776 case BFD_RELOC_32:
12777 if (fixp->fx_pcrel)
12778 {
12779 code = BFD_RELOC_32_PCREL;
12780 break;
12781 }
12782
12783 case BFD_RELOC_ARM_PCREL_BRANCH:
12784 case BFD_RELOC_ARM_PCREL_BLX:
12785 case BFD_RELOC_RVA:
12786 case BFD_RELOC_THUMB_PCREL_BRANCH9:
12787 case BFD_RELOC_THUMB_PCREL_BRANCH12:
12788 case BFD_RELOC_THUMB_PCREL_BRANCH23:
12789 case BFD_RELOC_THUMB_PCREL_BLX:
12790 case BFD_RELOC_VTABLE_ENTRY:
12791 case BFD_RELOC_VTABLE_INHERIT:
12792 code = fixp->fx_r_type;
12793 break;
12794
12795 case BFD_RELOC_ARM_LITERAL:
12796 case BFD_RELOC_ARM_HWLITERAL:
12797 /* If this is called then the a literal has
12798 been referenced across a section boundary. */
12799 as_bad_where (fixp->fx_file, fixp->fx_line,
12800 _("literal referenced across section boundary"));
12801 return NULL;
12802
12803 #ifdef OBJ_ELF
12804 case BFD_RELOC_ARM_GOT32:
12805 case BFD_RELOC_ARM_GOTOFF:
12806 case BFD_RELOC_ARM_PLT32:
12807 code = fixp->fx_r_type;
12808 break;
12809 #endif
12810
12811 case BFD_RELOC_ARM_IMMEDIATE:
12812 as_bad_where (fixp->fx_file, fixp->fx_line,
12813 _("internal relocation (type: IMMEDIATE) not fixed up"));
12814 return NULL;
12815
12816 case BFD_RELOC_ARM_ADRL_IMMEDIATE:
12817 as_bad_where (fixp->fx_file, fixp->fx_line,
12818 _("ADRL used for a symbol not defined in the same file"));
12819 return NULL;
12820
12821 case BFD_RELOC_ARM_OFFSET_IMM:
12822 if (fixp->fx_addsy != NULL
12823 && !S_IS_DEFINED (fixp->fx_addsy)
12824 && S_IS_LOCAL (fixp->fx_addsy))
12825 {
12826 as_bad_where (fixp->fx_file, fixp->fx_line,
12827 _("undefined local label `%s'"),
12828 S_GET_NAME (fixp->fx_addsy));
12829 return NULL;
12830 }
12831
12832 as_bad_where (fixp->fx_file, fixp->fx_line,
12833 _("internal_relocation (type: OFFSET_IMM) not fixed up"));
12834 return NULL;
12835
12836 default:
12837 {
12838 char * type;
12839
12840 switch (fixp->fx_r_type)
12841 {
12842 case BFD_RELOC_ARM_OFFSET_IMM8: type = "OFFSET_IMM8"; break;
12843 case BFD_RELOC_ARM_SHIFT_IMM: type = "SHIFT_IMM"; break;
12844 case BFD_RELOC_ARM_SWI: type = "SWI"; break;
12845 case BFD_RELOC_ARM_MULTI: type = "MULTI"; break;
12846 case BFD_RELOC_ARM_CP_OFF_IMM: type = "CP_OFF_IMM"; break;
12847 case BFD_RELOC_ARM_THUMB_ADD: type = "THUMB_ADD"; break;
12848 case BFD_RELOC_ARM_THUMB_SHIFT: type = "THUMB_SHIFT"; break;
12849 case BFD_RELOC_ARM_THUMB_IMM: type = "THUMB_IMM"; break;
12850 case BFD_RELOC_ARM_THUMB_OFFSET: type = "THUMB_OFFSET"; break;
12851 default: type = _("<unknown>"); break;
12852 }
12853 as_bad_where (fixp->fx_file, fixp->fx_line,
12854 _("cannot represent %s relocation in this object file format"),
12855 type);
12856 return NULL;
12857 }
12858 }
12859
12860 #ifdef OBJ_ELF
12861 if ((code == BFD_RELOC_32_PCREL || code == BFD_RELOC_32)
12862 && GOT_symbol
12863 && fixp->fx_addsy == GOT_symbol)
12864 {
12865 code = BFD_RELOC_ARM_GOTPC;
12866 reloc->addend = fixp->fx_offset = reloc->address;
12867 }
12868 #endif
12869
12870 reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
12871
12872 if (reloc->howto == NULL)
12873 {
12874 as_bad_where (fixp->fx_file, fixp->fx_line,
12875 _("cannot represent %s relocation in this object file format"),
12876 bfd_get_reloc_code_name (code));
12877 return NULL;
12878 }
12879
12880 /* HACK: Since arm ELF uses Rel instead of Rela, encode the
12881 vtable entry to be used in the relocation's section offset. */
12882 if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
12883 reloc->address = fixp->fx_offset;
12884
12885 return reloc;
12886 }
12887
12888 int
md_estimate_size_before_relax(fragP,segtype)12889 md_estimate_size_before_relax (fragP, segtype)
12890 fragS * fragP ATTRIBUTE_UNUSED;
12891 segT segtype ATTRIBUTE_UNUSED;
12892 {
12893 as_fatal (_("md_estimate_size_before_relax\n"));
12894 return 1;
12895 }
12896
12897 static void
output_inst(str)12898 output_inst (str)
12899 const char *str;
12900 {
12901 char * to = NULL;
12902
12903 if (inst.error)
12904 {
12905 as_bad ("%s -- `%s'", inst.error, str);
12906 return;
12907 }
12908
12909 to = frag_more (inst.size);
12910
12911 if (thumb_mode && (inst.size > THUMB_SIZE))
12912 {
12913 assert (inst.size == (2 * THUMB_SIZE));
12914 md_number_to_chars (to, inst.instruction >> 16, THUMB_SIZE);
12915 md_number_to_chars (to + THUMB_SIZE, inst.instruction, THUMB_SIZE);
12916 }
12917 else if (inst.size > INSN_SIZE)
12918 {
12919 assert (inst.size == (2 * INSN_SIZE));
12920 md_number_to_chars (to, inst.instruction, INSN_SIZE);
12921 md_number_to_chars (to + INSN_SIZE, inst.instruction, INSN_SIZE);
12922 }
12923 else
12924 md_number_to_chars (to, inst.instruction, inst.size);
12925
12926 if (inst.reloc.type != BFD_RELOC_NONE)
12927 fix_new_arm (frag_now, to - frag_now->fr_literal,
12928 inst.size, & inst.reloc.exp, inst.reloc.pc_rel,
12929 inst.reloc.type);
12930
12931 #ifdef OBJ_ELF
12932 dwarf2_emit_insn (inst.size);
12933 #endif
12934 }
12935
12936 void
md_assemble(str)12937 md_assemble (str)
12938 char * str;
12939 {
12940 char c;
12941 char *p;
12942 char *start;
12943
12944 /* Align the instruction.
12945 This may not be the right thing to do but ... */
12946 #if 0
12947 arm_align (2, 0);
12948 #endif
12949
12950 /* Align the previous label if needed. */
12951 if (last_label_seen != NULL)
12952 {
12953 symbol_set_frag (last_label_seen, frag_now);
12954 S_SET_VALUE (last_label_seen, (valueT) frag_now_fix ());
12955 S_SET_SEGMENT (last_label_seen, now_seg);
12956 }
12957
12958 memset (&inst, '\0', sizeof (inst));
12959 inst.reloc.type = BFD_RELOC_NONE;
12960
12961 skip_whitespace (str);
12962
12963 /* Scan up to the end of the op-code, which must end in white space or
12964 end of string. */
12965 for (start = p = str; *p != '\0'; p++)
12966 if (*p == ' ')
12967 break;
12968
12969 if (p == str)
12970 {
12971 as_bad (_("no operator -- statement `%s'\n"), str);
12972 return;
12973 }
12974
12975 if (thumb_mode)
12976 {
12977 const struct thumb_opcode * opcode;
12978
12979 c = *p;
12980 *p = '\0';
12981 opcode = (const struct thumb_opcode *) hash_find (arm_tops_hsh, str);
12982 *p = c;
12983
12984 if (opcode)
12985 {
12986 /* Check that this instruction is supported for this CPU. */
12987 if (thumb_mode == 1 && (opcode->variant & cpu_variant) == 0)
12988 {
12989 as_bad (_("selected processor does not support `%s'"), str);
12990 return;
12991 }
12992
12993 mapping_state (MAP_THUMB);
12994 inst.instruction = opcode->value;
12995 inst.size = opcode->size;
12996 (*opcode->parms) (p);
12997 output_inst (str);
12998 return;
12999 }
13000 }
13001 else
13002 {
13003 const struct asm_opcode * opcode;
13004
13005 c = *p;
13006 *p = '\0';
13007 opcode = (const struct asm_opcode *) hash_find (arm_ops_hsh, str);
13008 *p = c;
13009
13010 if (opcode)
13011 {
13012 /* Check that this instruction is supported for this CPU. */
13013 if ((opcode->variant & cpu_variant) == 0)
13014 {
13015 as_bad (_("selected processor does not support `%s'"), str);
13016 return;
13017 }
13018
13019 mapping_state (MAP_ARM);
13020 inst.instruction = opcode->value;
13021 inst.size = INSN_SIZE;
13022 (*opcode->parms) (p);
13023 output_inst (str);
13024 return;
13025 }
13026 }
13027
13028 /* It wasn't an instruction, but it might be a register alias of the form
13029 alias .req reg. */
13030 if (create_register_alias (str, p))
13031 return;
13032
13033 as_bad (_("bad instruction `%s'"), start);
13034 }
13035
13036 /* md_parse_option
13037 Invocation line includes a switch not recognized by the base assembler.
13038 See if it's a processor-specific option.
13039
13040 This routine is somewhat complicated by the need for backwards
13041 compatibility (since older releases of gcc can't be changed).
13042 The new options try to make the interface as compatible as
13043 possible with GCC.
13044
13045 New options (supported) are:
13046
13047 -mcpu=<cpu name> Assemble for selected processor
13048 -march=<architecture name> Assemble for selected architecture
13049 -mfpu=<fpu architecture> Assemble for selected FPU.
13050 -EB/-mbig-endian Big-endian
13051 -EL/-mlittle-endian Little-endian
13052 -k Generate PIC code
13053 -mthumb Start in Thumb mode
13054 -mthumb-interwork Code supports ARM/Thumb interworking
13055
13056 For now we will also provide support for:
13057
13058 -mapcs-32 32-bit Program counter
13059 -mapcs-26 26-bit Program counter
13060 -macps-float Floats passed in FP registers
13061 -mapcs-reentrant Reentrant code
13062 -matpcs
13063 (sometime these will probably be replaced with -mapcs=<list of options>
13064 and -matpcs=<list of options>)
13065
13066 The remaining options are only supported for back-wards compatibility.
13067 Cpu variants, the arm part is optional:
13068 -m[arm]1 Currently not supported.
13069 -m[arm]2, -m[arm]250 Arm 2 and Arm 250 processor
13070 -m[arm]3 Arm 3 processor
13071 -m[arm]6[xx], Arm 6 processors
13072 -m[arm]7[xx][t][[d]m] Arm 7 processors
13073 -m[arm]8[10] Arm 8 processors
13074 -m[arm]9[20][tdmi] Arm 9 processors
13075 -mstrongarm[110[0]] StrongARM processors
13076 -mxscale XScale processors
13077 -m[arm]v[2345[t[e]]] Arm architectures
13078 -mall All (except the ARM1)
13079 FP variants:
13080 -mfpa10, -mfpa11 FPA10 and 11 co-processor instructions
13081 -mfpe-old (No float load/store multiples)
13082 -mvfpxd VFP Single precision
13083 -mvfp All VFP
13084 -mno-fpu Disable all floating point instructions
13085
13086 The following CPU names are recognized:
13087 arm1, arm2, arm250, arm3, arm6, arm600, arm610, arm620,
13088 arm7, arm7m, arm7d, arm7dm, arm7di, arm7dmi, arm70, arm700,
13089 arm700i, arm710 arm710t, arm720, arm720t, arm740t, arm710c,
13090 arm7100, arm7500, arm7500fe, arm7tdmi, arm8, arm810, arm9,
13091 arm920, arm920t, arm940t, arm946, arm966, arm9tdmi, arm9e,
13092 arm10t arm10e, arm1020t, arm1020e, arm10200e,
13093 strongarm, strongarm110, strongarm1100, strongarm1110, xscale.
13094
13095 */
13096
13097 const char * md_shortopts = "m:k";
13098
13099 #ifdef ARM_BI_ENDIAN
13100 #define OPTION_EB (OPTION_MD_BASE + 0)
13101 #define OPTION_EL (OPTION_MD_BASE + 1)
13102 #else
13103 #if TARGET_BYTES_BIG_ENDIAN
13104 #define OPTION_EB (OPTION_MD_BASE + 0)
13105 #else
13106 #define OPTION_EL (OPTION_MD_BASE + 1)
13107 #endif
13108 #endif
13109
13110 struct option md_longopts[] =
13111 {
13112 #ifdef OPTION_EB
13113 {"EB", no_argument, NULL, OPTION_EB},
13114 #endif
13115 #ifdef OPTION_EL
13116 {"EL", no_argument, NULL, OPTION_EL},
13117 #endif
13118 {NULL, no_argument, NULL, 0}
13119 };
13120
13121 size_t md_longopts_size = sizeof (md_longopts);
13122
13123 struct arm_option_table
13124 {
13125 char *option; /* Option name to match. */
13126 char *help; /* Help information. */
13127 int *var; /* Variable to change. */
13128 int value; /* What to change it to. */
13129 char *deprecated; /* If non-null, print this message. */
13130 };
13131
13132 struct arm_option_table arm_opts[] =
13133 {
13134 {"k", N_("generate PIC code"), &pic_code, 1, NULL},
13135 {"mthumb", N_("assemble Thumb code"), &thumb_mode, 1, NULL},
13136 {"mthumb-interwork", N_("support ARM/Thumb interworking"),
13137 &support_interwork, 1, NULL},
13138 {"moabi", N_("use old ABI (ELF only)"), &target_oabi, 1, NULL},
13139 {"mapcs-32", N_("code uses 32-bit program counter"), &uses_apcs_26, 0, NULL},
13140 {"mapcs-26", N_("code uses 26-bit program counter"), &uses_apcs_26, 1, NULL},
13141 {"mapcs-float", N_("floating point args are in fp regs"), &uses_apcs_float,
13142 1, NULL},
13143 {"mapcs-reentrant", N_("re-entrant code"), &pic_code, 1, NULL},
13144 {"matpcs", N_("code is ATPCS conformant"), &atpcs, 1, NULL},
13145 {"mbig-endian", N_("assemble for big-endian"), &target_big_endian, 1, NULL},
13146 {"mlittle-endian", N_("assemble for little-endian"), &target_big_endian, 1,
13147 NULL},
13148
13149 /* These are recognized by the assembler, but have no affect on code. */
13150 {"mapcs-frame", N_("use frame pointer"), NULL, 0, NULL},
13151 {"mapcs-stack-check", N_("use stack size checking"), NULL, 0, NULL},
13152
13153 /* DON'T add any new processors to this list -- we want the whole list
13154 to go away... Add them to the processors table instead. */
13155 {"marm1", NULL, &legacy_cpu, ARM_ARCH_V1, N_("use -mcpu=arm1")},
13156 {"m1", NULL, &legacy_cpu, ARM_ARCH_V1, N_("use -mcpu=arm1")},
13157 {"marm2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -mcpu=arm2")},
13158 {"m2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -mcpu=arm2")},
13159 {"marm250", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm250")},
13160 {"m250", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm250")},
13161 {"marm3", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm3")},
13162 {"m3", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm3")},
13163 {"marm6", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm6")},
13164 {"m6", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm6")},
13165 {"marm600", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm600")},
13166 {"m600", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm600")},
13167 {"marm610", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm610")},
13168 {"m610", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm610")},
13169 {"marm620", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm620")},
13170 {"m620", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm620")},
13171 {"marm7", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7")},
13172 {"m7", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7")},
13173 {"marm70", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm70")},
13174 {"m70", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm70")},
13175 {"marm700", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700")},
13176 {"m700", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700")},
13177 {"marm700i", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700i")},
13178 {"m700i", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700i")},
13179 {"marm710", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710")},
13180 {"m710", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710")},
13181 {"marm710c", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710c")},
13182 {"m710c", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710c")},
13183 {"marm720", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm720")},
13184 {"m720", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm720")},
13185 {"marm7d", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7d")},
13186 {"m7d", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7d")},
13187 {"marm7di", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7di")},
13188 {"m7di", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7di")},
13189 {"marm7m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7m")},
13190 {"m7m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7m")},
13191 {"marm7dm", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dm")},
13192 {"m7dm", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dm")},
13193 {"marm7dmi", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dmi")},
13194 {"m7dmi", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dmi")},
13195 {"marm7100", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7100")},
13196 {"m7100", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7100")},
13197 {"marm7500", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500")},
13198 {"m7500", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500")},
13199 {"marm7500fe", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500fe")},
13200 {"m7500fe", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500fe")},
13201 {"marm7t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
13202 {"m7t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
13203 {"marm7tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
13204 {"m7tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
13205 {"marm710t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm710t")},
13206 {"m710t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm710t")},
13207 {"marm720t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm720t")},
13208 {"m720t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm720t")},
13209 {"marm740t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm740t")},
13210 {"m740t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm740t")},
13211 {"marm8", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm8")},
13212 {"m8", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm8")},
13213 {"marm810", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm810")},
13214 {"m810", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm810")},
13215 {"marm9", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9")},
13216 {"m9", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9")},
13217 {"marm9tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9tdmi")},
13218 {"m9tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9tdmi")},
13219 {"marm920", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm920")},
13220 {"m920", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm920")},
13221 {"marm940", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm940")},
13222 {"m940", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm940")},
13223 {"mstrongarm", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=strongarm")},
13224 {"mstrongarm110", NULL, &legacy_cpu, ARM_ARCH_V4,
13225 N_("use -mcpu=strongarm110")},
13226 {"mstrongarm1100", NULL, &legacy_cpu, ARM_ARCH_V4,
13227 N_("use -mcpu=strongarm1100")},
13228 {"mstrongarm1110", NULL, &legacy_cpu, ARM_ARCH_V4,
13229 N_("use -mcpu=strongarm1110")},
13230 {"mxscale", NULL, &legacy_cpu, ARM_ARCH_XSCALE, N_("use -mcpu=xscale")},
13231 {"miwmmxt", NULL, &legacy_cpu, ARM_ARCH_IWMMXT, N_("use -mcpu=iwmmxt")},
13232 {"mall", NULL, &legacy_cpu, ARM_ANY, N_("use -mcpu=all")},
13233
13234 /* Architecture variants -- don't add any more to this list either. */
13235 {"mv2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -march=armv2")},
13236 {"marmv2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -march=armv2")},
13237 {"mv2a", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -march=armv2a")},
13238 {"marmv2a", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -march=armv2a")},
13239 {"mv3", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -march=armv3")},
13240 {"marmv3", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -march=armv3")},
13241 {"mv3m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -march=armv3m")},
13242 {"marmv3m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -march=armv3m")},
13243 {"mv4", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -march=armv4")},
13244 {"marmv4", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -march=armv4")},
13245 {"mv4t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -march=armv4t")},
13246 {"marmv4t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -march=armv4t")},
13247 {"mv5", NULL, &legacy_cpu, ARM_ARCH_V5, N_("use -march=armv5")},
13248 {"marmv5", NULL, &legacy_cpu, ARM_ARCH_V5, N_("use -march=armv5")},
13249 {"mv5t", NULL, &legacy_cpu, ARM_ARCH_V5T, N_("use -march=armv5t")},
13250 {"marmv5t", NULL, &legacy_cpu, ARM_ARCH_V5T, N_("use -march=armv5t")},
13251 {"mv5e", NULL, &legacy_cpu, ARM_ARCH_V5TE, N_("use -march=armv5te")},
13252 {"marmv5e", NULL, &legacy_cpu, ARM_ARCH_V5TE, N_("use -march=armv5te")},
13253
13254 /* Floating point variants -- don't add any more to this list either. */
13255 {"mfpe-old", NULL, &legacy_fpu, FPU_ARCH_FPE, N_("use -mfpu=fpe")},
13256 {"mfpa10", NULL, &legacy_fpu, FPU_ARCH_FPA, N_("use -mfpu=fpa10")},
13257 {"mfpa11", NULL, &legacy_fpu, FPU_ARCH_FPA, N_("use -mfpu=fpa11")},
13258 {"mno-fpu", NULL, &legacy_fpu, 0,
13259 N_("use either -mfpu=softfpa or -mfpu=softvfp")},
13260
13261 {NULL, NULL, NULL, 0, NULL}
13262 };
13263
13264 struct arm_cpu_option_table
13265 {
13266 char *name;
13267 int value;
13268 /* For some CPUs we assume an FPU unless the user explicitly sets
13269 -mfpu=... */
13270 int default_fpu;
13271 };
13272
13273 /* This list should, at a minimum, contain all the cpu names
13274 recognized by GCC. */
13275 static struct arm_cpu_option_table arm_cpus[] =
13276 {
13277 {"all", ARM_ANY, FPU_ARCH_FPA},
13278 {"arm1", ARM_ARCH_V1, FPU_ARCH_FPA},
13279 {"arm2", ARM_ARCH_V2, FPU_ARCH_FPA},
13280 {"arm250", ARM_ARCH_V2S, FPU_ARCH_FPA},
13281 {"arm3", ARM_ARCH_V2S, FPU_ARCH_FPA},
13282 {"arm6", ARM_ARCH_V3, FPU_ARCH_FPA},
13283 {"arm60", ARM_ARCH_V3, FPU_ARCH_FPA},
13284 {"arm600", ARM_ARCH_V3, FPU_ARCH_FPA},
13285 {"arm610", ARM_ARCH_V3, FPU_ARCH_FPA},
13286 {"arm620", ARM_ARCH_V3, FPU_ARCH_FPA},
13287 {"arm7", ARM_ARCH_V3, FPU_ARCH_FPA},
13288 {"arm7m", ARM_ARCH_V3M, FPU_ARCH_FPA},
13289 {"arm7d", ARM_ARCH_V3, FPU_ARCH_FPA},
13290 {"arm7dm", ARM_ARCH_V3M, FPU_ARCH_FPA},
13291 {"arm7di", ARM_ARCH_V3, FPU_ARCH_FPA},
13292 {"arm7dmi", ARM_ARCH_V3M, FPU_ARCH_FPA},
13293 {"arm70", ARM_ARCH_V3, FPU_ARCH_FPA},
13294 {"arm700", ARM_ARCH_V3, FPU_ARCH_FPA},
13295 {"arm700i", ARM_ARCH_V3, FPU_ARCH_FPA},
13296 {"arm710", ARM_ARCH_V3, FPU_ARCH_FPA},
13297 {"arm710t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13298 {"arm720", ARM_ARCH_V3, FPU_ARCH_FPA},
13299 {"arm720t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13300 {"arm740t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13301 {"arm710c", ARM_ARCH_V3, FPU_ARCH_FPA},
13302 {"arm7100", ARM_ARCH_V3, FPU_ARCH_FPA},
13303 {"arm7500", ARM_ARCH_V3, FPU_ARCH_FPA},
13304 {"arm7500fe", ARM_ARCH_V3, FPU_ARCH_FPA},
13305 {"arm7t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13306 {"arm7tdmi", ARM_ARCH_V4T, FPU_ARCH_FPA},
13307 {"arm8", ARM_ARCH_V4, FPU_ARCH_FPA},
13308 {"arm810", ARM_ARCH_V4, FPU_ARCH_FPA},
13309 {"strongarm", ARM_ARCH_V4, FPU_ARCH_FPA},
13310 {"strongarm1", ARM_ARCH_V4, FPU_ARCH_FPA},
13311 {"strongarm110", ARM_ARCH_V4, FPU_ARCH_FPA},
13312 {"strongarm1100", ARM_ARCH_V4, FPU_ARCH_FPA},
13313 {"strongarm1110", ARM_ARCH_V4, FPU_ARCH_FPA},
13314 {"arm9", ARM_ARCH_V4T, FPU_ARCH_FPA},
13315 {"arm920", ARM_ARCH_V4T, FPU_ARCH_FPA},
13316 {"arm920t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13317 {"arm922t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13318 {"arm940t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13319 {"arm9tdmi", ARM_ARCH_V4T, FPU_ARCH_FPA},
13320 /* For V5 or later processors we default to using VFP; but the user
13321 should really set the FPU type explicitly. */
13322 {"arm9e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
13323 {"arm9e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13324 {"arm926ej", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
13325 {"arm926ejs", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
13326 {"arm946e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
13327 {"arm946e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13328 {"arm966e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
13329 {"arm966e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13330 {"arm10t", ARM_ARCH_V5T, FPU_ARCH_VFP_V1},
13331 {"arm10e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13332 {"arm1020", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13333 {"arm1020t", ARM_ARCH_V5T, FPU_ARCH_VFP_V1},
13334 {"arm1020e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13335 {"arm1026ejs", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13336 {"arm1136js", ARM_ARCH_V6, FPU_NONE},
13337 {"arm1136jfs", ARM_ARCH_V6, FPU_ARCH_VFP_V2},
13338 /* ??? XSCALE is really an architecture. */
13339 {"xscale", ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2},
13340 /* ??? iwmmxt is not a processor. */
13341 {"iwmmxt", ARM_ARCH_IWMMXT, FPU_ARCH_VFP_V2},
13342 {"i80200", ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2},
13343 /* Maverick */
13344 {"ep9312", ARM_ARCH_V4T | ARM_CEXT_MAVERICK, FPU_ARCH_MAVERICK},
13345 {NULL, 0, 0}
13346 };
13347
13348 struct arm_arch_option_table
13349 {
13350 char *name;
13351 int value;
13352 int default_fpu;
13353 };
13354
13355 /* This list should, at a minimum, contain all the architecture names
13356 recognized by GCC. */
13357 static struct arm_arch_option_table arm_archs[] =
13358 {
13359 {"all", ARM_ANY, FPU_ARCH_FPA},
13360 {"armv1", ARM_ARCH_V1, FPU_ARCH_FPA},
13361 {"armv2", ARM_ARCH_V2, FPU_ARCH_FPA},
13362 {"armv2a", ARM_ARCH_V2S, FPU_ARCH_FPA},
13363 {"armv2s", ARM_ARCH_V2S, FPU_ARCH_FPA},
13364 {"armv3", ARM_ARCH_V3, FPU_ARCH_FPA},
13365 {"armv3m", ARM_ARCH_V3M, FPU_ARCH_FPA},
13366 {"armv4", ARM_ARCH_V4, FPU_ARCH_FPA},
13367 {"armv4xm", ARM_ARCH_V4xM, FPU_ARCH_FPA},
13368 {"armv4t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13369 {"armv4txm", ARM_ARCH_V4TxM, FPU_ARCH_FPA},
13370 {"armv5", ARM_ARCH_V5, FPU_ARCH_VFP},
13371 {"armv5t", ARM_ARCH_V5T, FPU_ARCH_VFP},
13372 {"armv5txm", ARM_ARCH_V5TxM, FPU_ARCH_VFP},
13373 {"armv5te", ARM_ARCH_V5TE, FPU_ARCH_VFP},
13374 {"armv5texp", ARM_ARCH_V5TExP, FPU_ARCH_VFP},
13375 {"armv5tej", ARM_ARCH_V5TEJ, FPU_ARCH_VFP},
13376 {"armv6", ARM_ARCH_V6, FPU_ARCH_VFP},
13377 {"armv6j", ARM_ARCH_V6, FPU_ARCH_VFP},
13378 {"xscale", ARM_ARCH_XSCALE, FPU_ARCH_VFP},
13379 {"iwmmxt", ARM_ARCH_IWMMXT, FPU_ARCH_VFP},
13380 {NULL, 0, 0}
13381 };
13382
13383 /* ISA extensions in the co-processor space. */
13384 struct arm_arch_extension_table
13385 {
13386 char *name;
13387 int value;
13388 };
13389
13390 static struct arm_arch_extension_table arm_extensions[] =
13391 {
13392 {"maverick", ARM_CEXT_MAVERICK},
13393 {"xscale", ARM_CEXT_XSCALE},
13394 {"iwmmxt", ARM_CEXT_IWMMXT},
13395 {NULL, 0}
13396 };
13397
13398 struct arm_fpu_option_table
13399 {
13400 char *name;
13401 int value;
13402 };
13403
13404 /* This list should, at a minimum, contain all the fpu names
13405 recognized by GCC. */
13406 static struct arm_fpu_option_table arm_fpus[] =
13407 {
13408 {"softfpa", FPU_NONE},
13409 {"fpe", FPU_ARCH_FPE},
13410 {"fpe2", FPU_ARCH_FPE},
13411 {"fpe3", FPU_ARCH_FPA}, /* Third release supports LFM/SFM. */
13412 {"fpa", FPU_ARCH_FPA},
13413 {"fpa10", FPU_ARCH_FPA},
13414 {"fpa11", FPU_ARCH_FPA},
13415 {"arm7500fe", FPU_ARCH_FPA},
13416 {"softvfp", FPU_ARCH_VFP},
13417 {"softvfp+vfp", FPU_ARCH_VFP_V2},
13418 {"vfp", FPU_ARCH_VFP_V2},
13419 {"vfp9", FPU_ARCH_VFP_V2},
13420 {"vfp10", FPU_ARCH_VFP_V2},
13421 {"vfp10-r0", FPU_ARCH_VFP_V1},
13422 {"vfpxd", FPU_ARCH_VFP_V1xD},
13423 {"arm1020t", FPU_ARCH_VFP_V1},
13424 {"arm1020e", FPU_ARCH_VFP_V2},
13425 {"arm1136jfs", FPU_ARCH_VFP_V2},
13426 {"maverick", FPU_ARCH_MAVERICK},
13427 {NULL, 0}
13428 };
13429
13430 struct arm_float_abi_option_table
13431 {
13432 char *name;
13433 int value;
13434 };
13435
13436 static struct arm_float_abi_option_table arm_float_abis[] =
13437 {
13438 {"hard", ARM_FLOAT_ABI_HARD},
13439 {"softfp", ARM_FLOAT_ABI_SOFTFP},
13440 {"soft", ARM_FLOAT_ABI_SOFT},
13441 {NULL, 0}
13442 };
13443
13444 struct arm_long_option_table
13445 {
13446 char *option; /* Substring to match. */
13447 char *help; /* Help information. */
13448 int (*func) PARAMS ((char *subopt)); /* Function to decode sub-option. */
13449 char *deprecated; /* If non-null, print this message. */
13450 };
13451
13452 static int
arm_parse_extension(str,opt_p)13453 arm_parse_extension (str, opt_p)
13454 char *str;
13455 int *opt_p;
13456 {
13457 while (str != NULL && *str != 0)
13458 {
13459 struct arm_arch_extension_table *opt;
13460 char *ext;
13461 int optlen;
13462
13463 if (*str != '+')
13464 {
13465 as_bad (_("invalid architectural extension"));
13466 return 0;
13467 }
13468
13469 str++;
13470 ext = strchr (str, '+');
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 architectural extension"));
13480 return 0;
13481 }
13482
13483 for (opt = arm_extensions; opt->name != NULL; opt++)
13484 if (strncmp (opt->name, str, optlen) == 0)
13485 {
13486 *opt_p |= opt->value;
13487 break;
13488 }
13489
13490 if (opt->name == NULL)
13491 {
13492 as_bad (_("unknown architectural extnsion `%s'"), str);
13493 return 0;
13494 }
13495
13496 str = ext;
13497 };
13498
13499 return 1;
13500 }
13501
13502 static int
arm_parse_cpu(str)13503 arm_parse_cpu (str)
13504 char *str;
13505 {
13506 struct arm_cpu_option_table *opt;
13507 char *ext = strchr (str, '+');
13508 int optlen;
13509
13510 if (ext != NULL)
13511 optlen = ext - str;
13512 else
13513 optlen = strlen (str);
13514
13515 if (optlen == 0)
13516 {
13517 as_bad (_("missing cpu name `%s'"), str);
13518 return 0;
13519 }
13520
13521 for (opt = arm_cpus; opt->name != NULL; opt++)
13522 if (strncmp (opt->name, str, optlen) == 0)
13523 {
13524 mcpu_cpu_opt = opt->value;
13525 mcpu_fpu_opt = opt->default_fpu;
13526
13527 if (ext != NULL)
13528 return arm_parse_extension (ext, &mcpu_cpu_opt);
13529
13530 return 1;
13531 }
13532
13533 as_bad (_("unknown cpu `%s'"), str);
13534 return 0;
13535 }
13536
13537 static int
arm_parse_arch(str)13538 arm_parse_arch (str)
13539 char *str;
13540 {
13541 struct arm_arch_option_table *opt;
13542 char *ext = strchr (str, '+');
13543 int optlen;
13544
13545 if (ext != NULL)
13546 optlen = ext - str;
13547 else
13548 optlen = strlen (str);
13549
13550 if (optlen == 0)
13551 {
13552 as_bad (_("missing architecture name `%s'"), str);
13553 return 0;
13554 }
13555
13556
13557 for (opt = arm_archs; opt->name != NULL; opt++)
13558 if (strcmp (opt->name, str) == 0)
13559 {
13560 march_cpu_opt = opt->value;
13561 march_fpu_opt = opt->default_fpu;
13562
13563 if (ext != NULL)
13564 return arm_parse_extension (ext, &march_cpu_opt);
13565
13566 return 1;
13567 }
13568
13569 as_bad (_("unknown architecture `%s'\n"), str);
13570 return 0;
13571 }
13572
13573 static int
arm_parse_fpu(str)13574 arm_parse_fpu (str)
13575 char *str;
13576 {
13577 struct arm_fpu_option_table *opt;
13578
13579 for (opt = arm_fpus; opt->name != NULL; opt++)
13580 if (strcmp (opt->name, str) == 0)
13581 {
13582 mfpu_opt = opt->value;
13583 return 1;
13584 }
13585
13586 as_bad (_("unknown floating point format `%s'\n"), str);
13587 return 0;
13588 }
13589
13590 static int
arm_parse_float_abi(str)13591 arm_parse_float_abi (str)
13592 char * str;
13593 {
13594 struct arm_float_abi_option_table *opt;
13595
13596 for (opt = arm_float_abis; opt->name != NULL; opt++)
13597 if (strcmp (opt->name, str) == 0)
13598 {
13599 mfloat_abi_opt = opt->value;
13600 return 1;
13601 }
13602
13603 as_bad (_("unknown floating point abi `%s'\n"), str);
13604 return 0;
13605 }
13606
13607 struct arm_long_option_table arm_long_opts[] =
13608 {
13609 {"mcpu=", N_("<cpu name>\t assemble for CPU <cpu name>"),
13610 arm_parse_cpu, NULL},
13611 {"march=", N_("<arch name>\t assemble for architecture <arch name>"),
13612 arm_parse_arch, NULL},
13613 {"mfpu=", N_("<fpu name>\t assemble for FPU architecture <fpu name>"),
13614 arm_parse_fpu, NULL},
13615 {"mfloat-abi=", N_("<abi>\t assemble for floating point ABI <abi>"),
13616 arm_parse_float_abi, NULL},
13617 {NULL, NULL, 0, NULL}
13618 };
13619
13620 int
md_parse_option(c,arg)13621 md_parse_option (c, arg)
13622 int c;
13623 char * arg;
13624 {
13625 struct arm_option_table *opt;
13626 struct arm_long_option_table *lopt;
13627
13628 switch (c)
13629 {
13630 #ifdef OPTION_EB
13631 case OPTION_EB:
13632 target_big_endian = 1;
13633 break;
13634 #endif
13635
13636 #ifdef OPTION_EL
13637 case OPTION_EL:
13638 target_big_endian = 0;
13639 break;
13640 #endif
13641
13642 case 'a':
13643 /* Listing option. Just ignore these, we don't support additional
13644 ones. */
13645 return 0;
13646
13647 default:
13648 for (opt = arm_opts; opt->option != NULL; opt++)
13649 {
13650 if (c == opt->option[0]
13651 && ((arg == NULL && opt->option[1] == 0)
13652 || strcmp (arg, opt->option + 1) == 0))
13653 {
13654 #if WARN_DEPRECATED
13655 /* If the option is deprecated, tell the user. */
13656 if (opt->deprecated != NULL)
13657 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c,
13658 arg ? arg : "", _(opt->deprecated));
13659 #endif
13660
13661 if (opt->var != NULL)
13662 *opt->var = opt->value;
13663
13664 return 1;
13665 }
13666 }
13667
13668 for (lopt = arm_long_opts; lopt->option != NULL; lopt++)
13669 {
13670 /* These options are expected to have an argument. */
13671 if (c == lopt->option[0]
13672 && arg != NULL
13673 && strncmp (arg, lopt->option + 1,
13674 strlen (lopt->option + 1)) == 0)
13675 {
13676 #if WARN_DEPRECATED
13677 /* If the option is deprecated, tell the user. */
13678 if (lopt->deprecated != NULL)
13679 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c, arg,
13680 _(lopt->deprecated));
13681 #endif
13682
13683 /* Call the sup-option parser. */
13684 return (*lopt->func)(arg + strlen (lopt->option) - 1);
13685 }
13686 }
13687
13688 as_bad (_("unrecognized option `-%c%s'"), c, arg ? arg : "");
13689 return 0;
13690 }
13691
13692 return 1;
13693 }
13694
13695 void
md_show_usage(fp)13696 md_show_usage (fp)
13697 FILE * fp;
13698 {
13699 struct arm_option_table *opt;
13700 struct arm_long_option_table *lopt;
13701
13702 fprintf (fp, _(" ARM-specific assembler options:\n"));
13703
13704 for (opt = arm_opts; opt->option != NULL; opt++)
13705 if (opt->help != NULL)
13706 fprintf (fp, " -%-23s%s\n", opt->option, _(opt->help));
13707
13708 for (lopt = arm_long_opts; lopt->option != NULL; lopt++)
13709 if (lopt->help != NULL)
13710 fprintf (fp, " -%s%s\n", lopt->option, _(lopt->help));
13711
13712 #ifdef OPTION_EB
13713 fprintf (fp, _("\
13714 -EB assemble code for a big-endian cpu\n"));
13715 #endif
13716
13717 #ifdef OPTION_EL
13718 fprintf (fp, _("\
13719 -EL assemble code for a little-endian cpu\n"));
13720 #endif
13721 }
13722
13723 /* We need to be able to fix up arbitrary expressions in some statements.
13724 This is so that we can handle symbols that are an arbitrary distance from
13725 the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
13726 which returns part of an address in a form which will be valid for
13727 a data instruction. We do this by pushing the expression into a symbol
13728 in the expr_section, and creating a fix for that. */
13729
13730 static void
fix_new_arm(frag,where,size,exp,pc_rel,reloc)13731 fix_new_arm (frag, where, size, exp, pc_rel, reloc)
13732 fragS * frag;
13733 int where;
13734 short int size;
13735 expressionS * exp;
13736 int pc_rel;
13737 int reloc;
13738 {
13739 fixS * new_fix;
13740 arm_fix_data * arm_data;
13741
13742 switch (exp->X_op)
13743 {
13744 case O_constant:
13745 case O_symbol:
13746 case O_add:
13747 case O_subtract:
13748 new_fix = fix_new_exp (frag, where, size, exp, pc_rel, reloc);
13749 break;
13750
13751 default:
13752 new_fix = fix_new (frag, where, size, make_expr_symbol (exp), 0,
13753 pc_rel, reloc);
13754 break;
13755 }
13756
13757 /* Mark whether the fix is to a THUMB instruction, or an ARM
13758 instruction. */
13759 arm_data = (arm_fix_data *) obstack_alloc (& notes, sizeof (arm_fix_data));
13760 new_fix->tc_fix_data = (PTR) arm_data;
13761 arm_data->thumb_mode = thumb_mode;
13762 }
13763
13764 /* This fix_new is called by cons via TC_CONS_FIX_NEW. */
13765
13766 void
cons_fix_new_arm(frag,where,size,exp)13767 cons_fix_new_arm (frag, where, size, exp)
13768 fragS * frag;
13769 int where;
13770 int size;
13771 expressionS * exp;
13772 {
13773 bfd_reloc_code_real_type type;
13774 int pcrel = 0;
13775
13776 /* Pick a reloc.
13777 FIXME: @@ Should look at CPU word size. */
13778 switch (size)
13779 {
13780 case 1:
13781 type = BFD_RELOC_8;
13782 break;
13783 case 2:
13784 type = BFD_RELOC_16;
13785 break;
13786 case 4:
13787 default:
13788 type = BFD_RELOC_32;
13789 break;
13790 case 8:
13791 type = BFD_RELOC_64;
13792 break;
13793 }
13794
13795 fix_new_exp (frag, where, (int) size, exp, pcrel, type);
13796 }
13797
13798 /* A good place to do this, although this was probably not intended
13799 for this kind of use. We need to dump the literal pool before
13800 references are made to a null symbol pointer. */
13801
13802 void
arm_cleanup()13803 arm_cleanup ()
13804 {
13805 literal_pool * pool;
13806
13807 for (pool = list_of_pools; pool; pool = pool->next)
13808 {
13809 /* Put it at the end of the relevent section. */
13810 subseg_set (pool->section, pool->sub_section);
13811 #ifdef OBJ_ELF
13812 arm_elf_change_section ();
13813 #endif
13814 s_ltorg (0);
13815 }
13816 }
13817
13818 void
arm_start_line_hook()13819 arm_start_line_hook ()
13820 {
13821 last_label_seen = NULL;
13822 }
13823
13824 void
arm_frob_label(sym)13825 arm_frob_label (sym)
13826 symbolS * sym;
13827 {
13828 last_label_seen = sym;
13829
13830 ARM_SET_THUMB (sym, thumb_mode);
13831
13832 #if defined OBJ_COFF || defined OBJ_ELF
13833 ARM_SET_INTERWORK (sym, support_interwork);
13834 #endif
13835
13836 /* Note - do not allow local symbols (.Lxxx) to be labeled
13837 as Thumb functions. This is because these labels, whilst
13838 they exist inside Thumb code, are not the entry points for
13839 possible ARM->Thumb calls. Also, these labels can be used
13840 as part of a computed goto or switch statement. eg gcc
13841 can generate code that looks like this:
13842
13843 ldr r2, [pc, .Laaa]
13844 lsl r3, r3, #2
13845 ldr r2, [r3, r2]
13846 mov pc, r2
13847
13848 .Lbbb: .word .Lxxx
13849 .Lccc: .word .Lyyy
13850 ..etc...
13851 .Laaa: .word Lbbb
13852
13853 The first instruction loads the address of the jump table.
13854 The second instruction converts a table index into a byte offset.
13855 The third instruction gets the jump address out of the table.
13856 The fourth instruction performs the jump.
13857
13858 If the address stored at .Laaa is that of a symbol which has the
13859 Thumb_Func bit set, then the linker will arrange for this address
13860 to have the bottom bit set, which in turn would mean that the
13861 address computation performed by the third instruction would end
13862 up with the bottom bit set. Since the ARM is capable of unaligned
13863 word loads, the instruction would then load the incorrect address
13864 out of the jump table, and chaos would ensue. */
13865 if (label_is_thumb_function_name
13866 && (S_GET_NAME (sym)[0] != '.' || S_GET_NAME (sym)[1] != 'L')
13867 && (bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
13868 {
13869 /* When the address of a Thumb function is taken the bottom
13870 bit of that address should be set. This will allow
13871 interworking between Arm and Thumb functions to work
13872 correctly. */
13873
13874 THUMB_SET_FUNC (sym, 1);
13875
13876 label_is_thumb_function_name = FALSE;
13877 }
13878 }
13879
13880 /* Adjust the symbol table. This marks Thumb symbols as distinct from
13881 ARM ones. */
13882
13883 void
arm_adjust_symtab()13884 arm_adjust_symtab ()
13885 {
13886 #ifdef OBJ_COFF
13887 symbolS * sym;
13888
13889 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
13890 {
13891 if (ARM_IS_THUMB (sym))
13892 {
13893 if (THUMB_IS_FUNC (sym))
13894 {
13895 /* Mark the symbol as a Thumb function. */
13896 if ( S_GET_STORAGE_CLASS (sym) == C_STAT
13897 || S_GET_STORAGE_CLASS (sym) == C_LABEL) /* This can happen! */
13898 S_SET_STORAGE_CLASS (sym, C_THUMBSTATFUNC);
13899
13900 else if (S_GET_STORAGE_CLASS (sym) == C_EXT)
13901 S_SET_STORAGE_CLASS (sym, C_THUMBEXTFUNC);
13902 else
13903 as_bad (_("%s: unexpected function type: %d"),
13904 S_GET_NAME (sym), S_GET_STORAGE_CLASS (sym));
13905 }
13906 else switch (S_GET_STORAGE_CLASS (sym))
13907 {
13908 case C_EXT:
13909 S_SET_STORAGE_CLASS (sym, C_THUMBEXT);
13910 break;
13911 case C_STAT:
13912 S_SET_STORAGE_CLASS (sym, C_THUMBSTAT);
13913 break;
13914 case C_LABEL:
13915 S_SET_STORAGE_CLASS (sym, C_THUMBLABEL);
13916 break;
13917 default:
13918 /* Do nothing. */
13919 break;
13920 }
13921 }
13922
13923 if (ARM_IS_INTERWORK (sym))
13924 coffsymbol (symbol_get_bfdsym (sym))->native->u.syment.n_flags = 0xFF;
13925 }
13926 #endif
13927 #ifdef OBJ_ELF
13928 symbolS * sym;
13929 char bind;
13930
13931 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
13932 {
13933 if (ARM_IS_THUMB (sym))
13934 {
13935 elf_symbol_type * elf_sym;
13936
13937 elf_sym = elf_symbol (symbol_get_bfdsym (sym));
13938 bind = ELF_ST_BIND (elf_sym);
13939
13940 /* If it's a .thumb_func, declare it as so,
13941 otherwise tag label as .code 16. */
13942 if (THUMB_IS_FUNC (sym))
13943 elf_sym->internal_elf_sym.st_info =
13944 ELF_ST_INFO (bind, STT_ARM_TFUNC);
13945 else
13946 elf_sym->internal_elf_sym.st_info =
13947 ELF_ST_INFO (bind, STT_ARM_16BIT);
13948 }
13949 }
13950 #endif
13951 }
13952
13953 int
arm_data_in_code()13954 arm_data_in_code ()
13955 {
13956 if (thumb_mode && ! strncmp (input_line_pointer + 1, "data:", 5))
13957 {
13958 *input_line_pointer = '/';
13959 input_line_pointer += 5;
13960 *input_line_pointer = 0;
13961 return 1;
13962 }
13963
13964 return 0;
13965 }
13966
13967 char *
arm_canonicalize_symbol_name(name)13968 arm_canonicalize_symbol_name (name)
13969 char * name;
13970 {
13971 int len;
13972
13973 if (thumb_mode && (len = strlen (name)) > 5
13974 && streq (name + len - 5, "/data"))
13975 *(name + len - 5) = 0;
13976
13977 return name;
13978 }
13979
13980 #if defined OBJ_COFF || defined OBJ_ELF
13981 void
arm_validate_fix(fixP)13982 arm_validate_fix (fixP)
13983 fixS * fixP;
13984 {
13985 /* If the destination of the branch is a defined symbol which does not have
13986 the THUMB_FUNC attribute, then we must be calling a function which has
13987 the (interfacearm) attribute. We look for the Thumb entry point to that
13988 function and change the branch to refer to that function instead. */
13989 if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23
13990 && fixP->fx_addsy != NULL
13991 && S_IS_DEFINED (fixP->fx_addsy)
13992 && ! THUMB_IS_FUNC (fixP->fx_addsy))
13993 {
13994 fixP->fx_addsy = find_real_start (fixP->fx_addsy);
13995 }
13996 }
13997 #endif
13998
13999 int
arm_force_relocation(fixp)14000 arm_force_relocation (fixp)
14001 struct fix * fixp;
14002 {
14003 #if defined (OBJ_COFF) && defined (TE_PE)
14004 if (fixp->fx_r_type == BFD_RELOC_RVA)
14005 return 1;
14006 #endif
14007 #ifdef OBJ_ELF
14008 if (fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH
14009 || fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BLX
14010 || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX
14011 || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23)
14012 return 1;
14013 #endif
14014
14015 /* Resolve these relocations even if the symbol is extern or weak. */
14016 if (fixp->fx_r_type == BFD_RELOC_ARM_IMMEDIATE
14017 || fixp->fx_r_type == BFD_RELOC_ARM_OFFSET_IMM
14018 || fixp->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE)
14019 return 0;
14020
14021 return generic_force_reloc (fixp);
14022 }
14023
14024 #ifdef OBJ_COFF
14025 /* This is a little hack to help the gas/arm/adrl.s test. It prevents
14026 local labels from being added to the output symbol table when they
14027 are used with the ADRL pseudo op. The ADRL relocation should always
14028 be resolved before the binbary is emitted, so it is safe to say that
14029 it is adjustable. */
14030
14031 bfd_boolean
arm_fix_adjustable(fixP)14032 arm_fix_adjustable (fixP)
14033 fixS * fixP;
14034 {
14035 if (fixP->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE)
14036 return 1;
14037 return 0;
14038 }
14039 #endif
14040
14041 #ifdef OBJ_ELF
14042 /* Relocations against Thumb function names must be left unadjusted,
14043 so that the linker can use this information to correctly set the
14044 bottom bit of their addresses. The MIPS version of this function
14045 also prevents relocations that are mips-16 specific, but I do not
14046 know why it does this.
14047
14048 FIXME:
14049 There is one other problem that ought to be addressed here, but
14050 which currently is not: Taking the address of a label (rather
14051 than a function) and then later jumping to that address. Such
14052 addresses also ought to have their bottom bit set (assuming that
14053 they reside in Thumb code), but at the moment they will not. */
14054
14055 bfd_boolean
arm_fix_adjustable(fixP)14056 arm_fix_adjustable (fixP)
14057 fixS * fixP;
14058 {
14059 if (fixP->fx_addsy == NULL)
14060 return 1;
14061
14062 if (THUMB_IS_FUNC (fixP->fx_addsy)
14063 && fixP->fx_subsy == NULL)
14064 return 0;
14065
14066 /* We need the symbol name for the VTABLE entries. */
14067 if ( fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
14068 || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
14069 return 0;
14070
14071 /* Don't allow symbols to be discarded on GOT related relocs. */
14072 if (fixP->fx_r_type == BFD_RELOC_ARM_PLT32
14073 || fixP->fx_r_type == BFD_RELOC_ARM_GOT32
14074 || fixP->fx_r_type == BFD_RELOC_ARM_GOTOFF)
14075 return 0;
14076
14077 return 1;
14078 }
14079
14080 const char *
elf32_arm_target_format()14081 elf32_arm_target_format ()
14082 {
14083 if (target_big_endian)
14084 {
14085 if (target_oabi)
14086 return "elf32-bigarm-oabi";
14087 else
14088 return "elf32-bigarm";
14089 }
14090 else
14091 {
14092 if (target_oabi)
14093 return "elf32-littlearm-oabi";
14094 else
14095 return "elf32-littlearm";
14096 }
14097 }
14098
14099 void
armelf_frob_symbol(symp,puntp)14100 armelf_frob_symbol (symp, puntp)
14101 symbolS * symp;
14102 int * puntp;
14103 {
14104 elf_frob_symbol (symp, puntp);
14105 }
14106
14107 static bfd_reloc_code_real_type
arm_parse_reloc()14108 arm_parse_reloc ()
14109 {
14110 char id [16];
14111 char * ip;
14112 unsigned int i;
14113 static struct
14114 {
14115 char * str;
14116 int len;
14117 bfd_reloc_code_real_type reloc;
14118 }
14119 reloc_map[] =
14120 {
14121 #define MAP(str,reloc) { str, sizeof (str) - 1, reloc }
14122 MAP ("(got)", BFD_RELOC_ARM_GOT32),
14123 MAP ("(gotoff)", BFD_RELOC_ARM_GOTOFF),
14124 /* ScottB: Jan 30, 1998 - Added support for parsing "var(PLT)"
14125 branch instructions generated by GCC for PLT relocs. */
14126 MAP ("(plt)", BFD_RELOC_ARM_PLT32),
14127 { NULL, 0, BFD_RELOC_UNUSED }
14128 #undef MAP
14129 };
14130
14131 for (i = 0, ip = input_line_pointer;
14132 i < sizeof (id) && (ISALNUM (*ip) || ISPUNCT (*ip));
14133 i++, ip++)
14134 id[i] = TOLOWER (*ip);
14135
14136 for (i = 0; reloc_map[i].str; i++)
14137 if (strncmp (id, reloc_map[i].str, reloc_map[i].len) == 0)
14138 break;
14139
14140 input_line_pointer += reloc_map[i].len;
14141
14142 return reloc_map[i].reloc;
14143 }
14144
14145 static void
s_arm_elf_cons(nbytes)14146 s_arm_elf_cons (nbytes)
14147 int nbytes;
14148 {
14149 expressionS exp;
14150
14151 #ifdef md_flush_pending_output
14152 md_flush_pending_output ();
14153 #endif
14154
14155 if (is_it_end_of_statement ())
14156 {
14157 demand_empty_rest_of_line ();
14158 return;
14159 }
14160
14161 #ifdef md_cons_align
14162 md_cons_align (nbytes);
14163 #endif
14164
14165 mapping_state (MAP_DATA);
14166 do
14167 {
14168 bfd_reloc_code_real_type reloc;
14169
14170 expression (& exp);
14171
14172 if (exp.X_op == O_symbol
14173 && * input_line_pointer == '('
14174 && (reloc = arm_parse_reloc ()) != BFD_RELOC_UNUSED)
14175 {
14176 reloc_howto_type *howto = bfd_reloc_type_lookup (stdoutput, reloc);
14177 int size = bfd_get_reloc_size (howto);
14178
14179 if (size > nbytes)
14180 as_bad ("%s relocations do not fit in %d bytes",
14181 howto->name, nbytes);
14182 else
14183 {
14184 register char *p = frag_more ((int) nbytes);
14185 int offset = nbytes - size;
14186
14187 fix_new_exp (frag_now, p - frag_now->fr_literal + offset, size,
14188 &exp, 0, reloc);
14189 }
14190 }
14191 else
14192 emit_expr (&exp, (unsigned int) nbytes);
14193 }
14194 while (*input_line_pointer++ == ',');
14195
14196 /* Put terminator back into stream. */
14197 input_line_pointer --;
14198 demand_empty_rest_of_line ();
14199 }
14200
14201 #endif /* OBJ_ELF */
14202
14203 /* This is called from HANDLE_ALIGN in write.c. Fill in the contents
14204 of an rs_align_code fragment. */
14205
14206 void
arm_handle_align(fragP)14207 arm_handle_align (fragP)
14208 fragS *fragP;
14209 {
14210 static char const arm_noop[4] = { 0x00, 0x00, 0xa0, 0xe1 };
14211 static char const thumb_noop[2] = { 0xc0, 0x46 };
14212 static char const arm_bigend_noop[4] = { 0xe1, 0xa0, 0x00, 0x00 };
14213 static char const thumb_bigend_noop[2] = { 0x46, 0xc0 };
14214
14215 int bytes, fix, noop_size;
14216 char * p;
14217 const char * noop;
14218
14219 if (fragP->fr_type != rs_align_code)
14220 return;
14221
14222 bytes = fragP->fr_next->fr_address - fragP->fr_address - fragP->fr_fix;
14223 p = fragP->fr_literal + fragP->fr_fix;
14224 fix = 0;
14225
14226 if (bytes > MAX_MEM_FOR_RS_ALIGN_CODE)
14227 bytes &= MAX_MEM_FOR_RS_ALIGN_CODE;
14228
14229 if (fragP->tc_frag_data)
14230 {
14231 if (target_big_endian)
14232 noop = thumb_bigend_noop;
14233 else
14234 noop = thumb_noop;
14235 noop_size = sizeof (thumb_noop);
14236 }
14237 else
14238 {
14239 if (target_big_endian)
14240 noop = arm_bigend_noop;
14241 else
14242 noop = arm_noop;
14243 noop_size = sizeof (arm_noop);
14244 }
14245
14246 if (bytes & (noop_size - 1))
14247 {
14248 fix = bytes & (noop_size - 1);
14249 memset (p, 0, fix);
14250 p += fix;
14251 bytes -= fix;
14252 }
14253
14254 while (bytes >= noop_size)
14255 {
14256 memcpy (p, noop, noop_size);
14257 p += noop_size;
14258 bytes -= noop_size;
14259 fix += noop_size;
14260 }
14261
14262 fragP->fr_fix += fix;
14263 fragP->fr_var = noop_size;
14264 }
14265
14266 /* Called from md_do_align. Used to create an alignment
14267 frag in a code section. */
14268
14269 void
arm_frag_align_code(n,max)14270 arm_frag_align_code (n, max)
14271 int n;
14272 int max;
14273 {
14274 char * p;
14275
14276 /* We assume that there will never be a requirement
14277 to support alignments greater than 32 bytes. */
14278 if (max > MAX_MEM_FOR_RS_ALIGN_CODE)
14279 as_fatal (_("alignments greater than 32 bytes not supported in .text sections."));
14280
14281 p = frag_var (rs_align_code,
14282 MAX_MEM_FOR_RS_ALIGN_CODE,
14283 1,
14284 (relax_substateT) max,
14285 (symbolS *) NULL,
14286 (offsetT) n,
14287 (char *) NULL);
14288 *p = 0;
14289
14290 }
14291
14292 /* Perform target specific initialisation of a frag. */
14293
14294 void
arm_init_frag(fragP)14295 arm_init_frag (fragP)
14296 fragS *fragP;
14297 {
14298 /* Record whether this frag is in an ARM or a THUMB area. */
14299 fragP->tc_frag_data = thumb_mode;
14300 }
14301