2003-09-26 Matt Thomas <matt@3am-software.com>
[deliverable/binutils-gdb.git] / gas / config / tc-arm.c
1 /* tc-arm.c -- Assemble for the ARM
2 Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
3 Free Software Foundation, Inc.
4 Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org)
5 Modified by David Taylor (dtaylor@armltd.co.uk)
6 Cirrus coprocessor mods by Aldy Hernandez (aldyh@redhat.com)
7
8 This file is part of GAS, the GNU Assembler.
9
10 GAS is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2, or (at your option)
13 any later version.
14
15 GAS is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with GAS; see the file COPYING. If not, write to the Free
22 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
23 02111-1307, USA. */
24
25 #include <string.h>
26 #define NO_RELOC 0
27 #include "as.h"
28 #include "safe-ctype.h"
29
30 /* Need TARGET_CPU. */
31 #include "config.h"
32 #include "subsegs.h"
33 #include "obstack.h"
34 #include "symbols.h"
35 #include "listing.h"
36
37 #ifdef OBJ_ELF
38 #include "elf/arm.h"
39 #include "dwarf2dbg.h"
40 #endif
41
42 /* XXX Set this to 1 after the next binutils release */
43 #define WARN_DEPRECATED 0
44
45 /* The following bitmasks control CPU extensions: */
46 #define ARM_EXT_V1 0x00000001 /* All processors (core set). */
47 #define ARM_EXT_V2 0x00000002 /* Multiply instructions. */
48 #define ARM_EXT_V2S 0x00000004 /* SWP instructions. */
49 #define ARM_EXT_V3 0x00000008 /* MSR MRS. */
50 #define ARM_EXT_V3M 0x00000010 /* Allow long multiplies. */
51 #define ARM_EXT_V4 0x00000020 /* Allow half word loads. */
52 #define ARM_EXT_V4T 0x00000040 /* Thumb v1. */
53 #define ARM_EXT_V5 0x00000080 /* Allow CLZ, etc. */
54 #define ARM_EXT_V5T 0x00000100 /* Thumb v2. */
55 #define ARM_EXT_V5ExP 0x00000200 /* DSP core set. */
56 #define ARM_EXT_V5E 0x00000400 /* DSP Double transfers. */
57 #define ARM_EXT_V5J 0x00000800 /* Jazelle extension. */
58
59 /* Co-processor space extensions. */
60 #define ARM_CEXT_XSCALE 0x00800000 /* Allow MIA etc. */
61 #define ARM_CEXT_MAVERICK 0x00400000 /* Use Cirrus/DSP coprocessor. */
62 #define ARM_CEXT_IWMMXT 0x00200000 /* Intel Wireless MMX technology coprocessor. */
63
64 /* Architectures are the sum of the base and extensions. The ARM ARM (rev E)
65 defines the following: ARMv3, ARMv3M, ARMv4xM, ARMv4, ARMv4TxM, ARMv4T,
66 ARMv5xM, ARMv5, ARMv5TxM, ARMv5T, ARMv5TExP, ARMv5TE. To these we add
67 three more to cover cores prior to ARM6. Finally, there are cores which
68 implement further extensions in the co-processor space. */
69 #define ARM_ARCH_V1 ARM_EXT_V1
70 #define ARM_ARCH_V2 (ARM_ARCH_V1 | ARM_EXT_V2)
71 #define ARM_ARCH_V2S (ARM_ARCH_V2 | ARM_EXT_V2S)
72 #define ARM_ARCH_V3 (ARM_ARCH_V2S | ARM_EXT_V3)
73 #define ARM_ARCH_V3M (ARM_ARCH_V3 | ARM_EXT_V3M)
74 #define ARM_ARCH_V4xM (ARM_ARCH_V3 | ARM_EXT_V4)
75 #define ARM_ARCH_V4 (ARM_ARCH_V3M | ARM_EXT_V4)
76 #define ARM_ARCH_V4TxM (ARM_ARCH_V4xM | ARM_EXT_V4T)
77 #define ARM_ARCH_V4T (ARM_ARCH_V4 | ARM_EXT_V4T)
78 #define ARM_ARCH_V5xM (ARM_ARCH_V4xM | ARM_EXT_V5)
79 #define ARM_ARCH_V5 (ARM_ARCH_V4 | ARM_EXT_V5)
80 #define ARM_ARCH_V5TxM (ARM_ARCH_V5xM | ARM_EXT_V4T | ARM_EXT_V5T)
81 #define ARM_ARCH_V5T (ARM_ARCH_V5 | ARM_EXT_V4T | ARM_EXT_V5T)
82 #define ARM_ARCH_V5TExP (ARM_ARCH_V5T | ARM_EXT_V5ExP)
83 #define ARM_ARCH_V5TE (ARM_ARCH_V5TExP | ARM_EXT_V5E)
84 #define ARM_ARCH_V5TEJ (ARM_ARCH_V5TE | ARM_EXT_V5J)
85
86 /* Processors with specific extensions in the co-processor space. */
87 #define ARM_ARCH_XSCALE (ARM_ARCH_V5TE | ARM_CEXT_XSCALE)
88 #define ARM_ARCH_IWMMXT (ARM_ARCH_XSCALE | ARM_CEXT_IWMMXT)
89
90 /* Some useful combinations: */
91 #define ARM_ANY 0x0000ffff /* Any basic core. */
92 #define ARM_ALL 0x00ffffff /* Any core + co-processor */
93 #define CPROC_ANY 0x00ff0000 /* Any co-processor */
94 #define FPU_ANY 0xff000000 /* Note this is ~ARM_ALL. */
95
96
97 #define FPU_FPA_EXT_V1 0x80000000 /* Base FPA instruction set. */
98 #define FPU_FPA_EXT_V2 0x40000000 /* LFM/SFM. */
99 #define FPU_VFP_EXT_NONE 0x20000000 /* Use VFP word-ordering. */
100 #define FPU_VFP_EXT_V1xD 0x10000000 /* Base VFP instruction set. */
101 #define FPU_VFP_EXT_V1 0x08000000 /* Double-precision insns. */
102 #define FPU_VFP_EXT_V2 0x04000000 /* ARM10E VFPr1. */
103 #define FPU_NONE 0
104
105 #define FPU_ARCH_FPE FPU_FPA_EXT_V1
106 #define FPU_ARCH_FPA (FPU_ARCH_FPE | FPU_FPA_EXT_V2)
107
108 #define FPU_ARCH_VFP FPU_VFP_EXT_NONE
109 #define FPU_ARCH_VFP_V1xD (FPU_VFP_EXT_V1xD | FPU_VFP_EXT_NONE)
110 #define FPU_ARCH_VFP_V1 (FPU_ARCH_VFP_V1xD | FPU_VFP_EXT_V1)
111 #define FPU_ARCH_VFP_V2 (FPU_ARCH_VFP_V1 | FPU_VFP_EXT_V2)
112
113 /* Types of processor to assemble for. */
114 #define ARM_1 ARM_ARCH_V1
115 #define ARM_2 ARM_ARCH_V2
116 #define ARM_3 ARM_ARCH_V2S
117 #define ARM_250 ARM_ARCH_V2S
118 #define ARM_6 ARM_ARCH_V3
119 #define ARM_7 ARM_ARCH_V3
120 #define ARM_8 ARM_ARCH_V4
121 #define ARM_9 ARM_ARCH_V4T
122 #define ARM_STRONG ARM_ARCH_V4
123 #define ARM_CPU_MASK 0x0000000f /* XXX? */
124
125 #ifndef CPU_DEFAULT
126 #if defined __XSCALE__
127 #define CPU_DEFAULT (ARM_ARCH_XSCALE)
128 #else
129 #if defined __thumb__
130 #define CPU_DEFAULT (ARM_ARCH_V5T)
131 #else
132 #define CPU_DEFAULT ARM_ANY
133 #endif
134 #endif
135 #endif
136
137 #ifdef TE_LINUX
138 #define FPU_DEFAULT FPU_ARCH_FPA
139 #endif
140
141 #ifdef TE_NetBSD
142 #ifdef OBJ_ELF
143 #define FPU_DEFAULT FPU_ARCH_VFP /* Soft-float, but VFP order. */
144 #else
145 /* Legacy a.out format. */
146 #define FPU_DEFAULT FPU_ARCH_FPA /* Soft-float, but FPA order. */
147 #endif
148 #endif
149
150 /* For backwards compatibility we default to the FPA. */
151 #ifndef FPU_DEFAULT
152 #define FPU_DEFAULT FPU_ARCH_FPA
153 #endif
154
155 #define streq(a, b) (strcmp (a, b) == 0)
156 #define skip_whitespace(str) while (*(str) == ' ') ++(str)
157
158 static unsigned long cpu_variant;
159 static int target_oabi = 0;
160
161 /* Flags stored in private area of BFD structure. */
162 static int uses_apcs_26 = FALSE;
163 static int atpcs = FALSE;
164 static int support_interwork = FALSE;
165 static int uses_apcs_float = FALSE;
166 static int pic_code = FALSE;
167
168 /* Variables that we set while parsing command-line options. Once all
169 options have been read we re-process these values to set the real
170 assembly flags. */
171 static int legacy_cpu = -1;
172 static int legacy_fpu = -1;
173
174 static int mcpu_cpu_opt = -1;
175 static int mcpu_fpu_opt = -1;
176 static int march_cpu_opt = -1;
177 static int march_fpu_opt = -1;
178 static int mfpu_opt = -1;
179
180 /* This array holds the chars that always start a comment. If the
181 pre-processor is disabled, these aren't very useful. */
182 const char comment_chars[] = "@";
183
184 /* This array holds the chars that only start a comment at the beginning of
185 a line. If the line seems to have the form '# 123 filename'
186 .line and .file directives will appear in the pre-processed output. */
187 /* Note that input_file.c hand checks for '#' at the beginning of the
188 first line of the input file. This is because the compiler outputs
189 #NO_APP at the beginning of its output. */
190 /* Also note that comments like this one will always work. */
191 const char line_comment_chars[] = "#";
192
193 const char line_separator_chars[] = ";";
194
195 /* Chars that can be used to separate mant
196 from exp in floating point numbers. */
197 const char EXP_CHARS[] = "eE";
198
199 /* Chars that mean this number is a floating point constant. */
200 /* As in 0f12.456 */
201 /* or 0d1.2345e12 */
202
203 const char FLT_CHARS[] = "rRsSfFdDxXeEpP";
204
205 /* Prefix characters that indicate the start of an immediate
206 value. */
207 #define is_immediate_prefix(C) ((C) == '#' || (C) == '$')
208
209 #ifdef OBJ_ELF
210 /* Pre-defined "_GLOBAL_OFFSET_TABLE_" */
211 symbolS * GOT_symbol;
212 #endif
213
214 /* Size of relocation record. */
215 const int md_reloc_size = 8;
216
217 /* 0: assemble for ARM,
218 1: assemble for Thumb,
219 2: assemble for Thumb even though target CPU does not support thumb
220 instructions. */
221 static int thumb_mode = 0;
222
223 typedef struct arm_fix
224 {
225 int thumb_mode;
226 } arm_fix_data;
227
228 struct arm_it
229 {
230 const char * error;
231 unsigned long instruction;
232 int size;
233 struct
234 {
235 bfd_reloc_code_real_type type;
236 expressionS exp;
237 int pc_rel;
238 } reloc;
239 };
240
241 struct arm_it inst;
242
243 enum asm_shift_index
244 {
245 SHIFT_LSL = 0,
246 SHIFT_LSR,
247 SHIFT_ASR,
248 SHIFT_ROR,
249 SHIFT_RRX
250 };
251
252 struct asm_shift_properties
253 {
254 enum asm_shift_index index;
255 unsigned long bit_field;
256 unsigned int allows_0 : 1;
257 unsigned int allows_32 : 1;
258 };
259
260 static const struct asm_shift_properties shift_properties [] =
261 {
262 { SHIFT_LSL, 0, 1, 0},
263 { SHIFT_LSR, 0x20, 0, 1},
264 { SHIFT_ASR, 0x40, 0, 1},
265 { SHIFT_ROR, 0x60, 0, 0},
266 { SHIFT_RRX, 0x60, 0, 0}
267 };
268
269 struct asm_shift_name
270 {
271 const char * name;
272 const struct asm_shift_properties * properties;
273 };
274
275 static const struct asm_shift_name shift_names [] =
276 {
277 { "asl", shift_properties + SHIFT_LSL },
278 { "lsl", shift_properties + SHIFT_LSL },
279 { "lsr", shift_properties + SHIFT_LSR },
280 { "asr", shift_properties + SHIFT_ASR },
281 { "ror", shift_properties + SHIFT_ROR },
282 { "rrx", shift_properties + SHIFT_RRX },
283 { "ASL", shift_properties + SHIFT_LSL },
284 { "LSL", shift_properties + SHIFT_LSL },
285 { "LSR", shift_properties + SHIFT_LSR },
286 { "ASR", shift_properties + SHIFT_ASR },
287 { "ROR", shift_properties + SHIFT_ROR },
288 { "RRX", shift_properties + SHIFT_RRX }
289 };
290
291 #define NO_SHIFT_RESTRICT 1
292 #define SHIFT_RESTRICT 0
293
294 #define NUM_FLOAT_VALS 8
295
296 const char * fp_const[] =
297 {
298 "0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0", 0
299 };
300
301 /* Number of littlenums required to hold an extended precision number. */
302 #define MAX_LITTLENUMS 6
303
304 LITTLENUM_TYPE fp_values[NUM_FLOAT_VALS][MAX_LITTLENUMS];
305
306 #define FAIL (-1)
307 #define SUCCESS (0)
308
309 /* Whether a Co-processor load/store operation accepts write-back forms. */
310 #define CP_WB_OK 1
311 #define CP_NO_WB 0
312
313 #define SUFF_S 1
314 #define SUFF_D 2
315 #define SUFF_E 3
316 #define SUFF_P 4
317
318 #define CP_T_X 0x00008000
319 #define CP_T_Y 0x00400000
320 #define CP_T_Pre 0x01000000
321 #define CP_T_UD 0x00800000
322 #define CP_T_WB 0x00200000
323
324 #define CONDS_BIT 0x00100000
325 #define LOAD_BIT 0x00100000
326
327 #define DOUBLE_LOAD_FLAG 0x00000001
328
329 struct asm_cond
330 {
331 const char * template;
332 unsigned long value;
333 };
334
335 #define COND_ALWAYS 0xe0000000
336 #define COND_MASK 0xf0000000
337
338 static const struct asm_cond conds[] =
339 {
340 {"eq", 0x00000000},
341 {"ne", 0x10000000},
342 {"cs", 0x20000000}, {"hs", 0x20000000},
343 {"cc", 0x30000000}, {"ul", 0x30000000}, {"lo", 0x30000000},
344 {"mi", 0x40000000},
345 {"pl", 0x50000000},
346 {"vs", 0x60000000},
347 {"vc", 0x70000000},
348 {"hi", 0x80000000},
349 {"ls", 0x90000000},
350 {"ge", 0xa0000000},
351 {"lt", 0xb0000000},
352 {"gt", 0xc0000000},
353 {"le", 0xd0000000},
354 {"al", 0xe0000000},
355 {"nv", 0xf0000000}
356 };
357
358 struct asm_psr
359 {
360 const char *template;
361 bfd_boolean cpsr;
362 unsigned long field;
363 };
364
365 /* The bit that distnguishes CPSR and SPSR. */
366 #define SPSR_BIT (1 << 22)
367
368 /* How many bits to shift the PSR_xxx bits up by. */
369 #define PSR_SHIFT 16
370
371 #define PSR_c (1 << 0)
372 #define PSR_x (1 << 1)
373 #define PSR_s (1 << 2)
374 #define PSR_f (1 << 3)
375
376 static const struct asm_psr psrs[] =
377 {
378 {"CPSR", TRUE, PSR_c | PSR_f},
379 {"CPSR_all", TRUE, PSR_c | PSR_f},
380 {"SPSR", FALSE, PSR_c | PSR_f},
381 {"SPSR_all", FALSE, PSR_c | PSR_f},
382 {"CPSR_flg", TRUE, PSR_f},
383 {"CPSR_f", TRUE, PSR_f},
384 {"SPSR_flg", FALSE, PSR_f},
385 {"SPSR_f", FALSE, PSR_f},
386 {"CPSR_c", TRUE, PSR_c},
387 {"CPSR_ctl", TRUE, PSR_c},
388 {"SPSR_c", FALSE, PSR_c},
389 {"SPSR_ctl", FALSE, PSR_c},
390 {"CPSR_x", TRUE, PSR_x},
391 {"CPSR_s", TRUE, PSR_s},
392 {"SPSR_x", FALSE, PSR_x},
393 {"SPSR_s", FALSE, PSR_s},
394 /* Combinations of flags. */
395 {"CPSR_fs", TRUE, PSR_f | PSR_s},
396 {"CPSR_fx", TRUE, PSR_f | PSR_x},
397 {"CPSR_fc", TRUE, PSR_f | PSR_c},
398 {"CPSR_sf", TRUE, PSR_s | PSR_f},
399 {"CPSR_sx", TRUE, PSR_s | PSR_x},
400 {"CPSR_sc", TRUE, PSR_s | PSR_c},
401 {"CPSR_xf", TRUE, PSR_x | PSR_f},
402 {"CPSR_xs", TRUE, PSR_x | PSR_s},
403 {"CPSR_xc", TRUE, PSR_x | PSR_c},
404 {"CPSR_cf", TRUE, PSR_c | PSR_f},
405 {"CPSR_cs", TRUE, PSR_c | PSR_s},
406 {"CPSR_cx", TRUE, PSR_c | PSR_x},
407 {"CPSR_fsx", TRUE, PSR_f | PSR_s | PSR_x},
408 {"CPSR_fsc", TRUE, PSR_f | PSR_s | PSR_c},
409 {"CPSR_fxs", TRUE, PSR_f | PSR_x | PSR_s},
410 {"CPSR_fxc", TRUE, PSR_f | PSR_x | PSR_c},
411 {"CPSR_fcs", TRUE, PSR_f | PSR_c | PSR_s},
412 {"CPSR_fcx", TRUE, PSR_f | PSR_c | PSR_x},
413 {"CPSR_sfx", TRUE, PSR_s | PSR_f | PSR_x},
414 {"CPSR_sfc", TRUE, PSR_s | PSR_f | PSR_c},
415 {"CPSR_sxf", TRUE, PSR_s | PSR_x | PSR_f},
416 {"CPSR_sxc", TRUE, PSR_s | PSR_x | PSR_c},
417 {"CPSR_scf", TRUE, PSR_s | PSR_c | PSR_f},
418 {"CPSR_scx", TRUE, PSR_s | PSR_c | PSR_x},
419 {"CPSR_xfs", TRUE, PSR_x | PSR_f | PSR_s},
420 {"CPSR_xfc", TRUE, PSR_x | PSR_f | PSR_c},
421 {"CPSR_xsf", TRUE, PSR_x | PSR_s | PSR_f},
422 {"CPSR_xsc", TRUE, PSR_x | PSR_s | PSR_c},
423 {"CPSR_xcf", TRUE, PSR_x | PSR_c | PSR_f},
424 {"CPSR_xcs", TRUE, PSR_x | PSR_c | PSR_s},
425 {"CPSR_cfs", TRUE, PSR_c | PSR_f | PSR_s},
426 {"CPSR_cfx", TRUE, PSR_c | PSR_f | PSR_x},
427 {"CPSR_csf", TRUE, PSR_c | PSR_s | PSR_f},
428 {"CPSR_csx", TRUE, PSR_c | PSR_s | PSR_x},
429 {"CPSR_cxf", TRUE, PSR_c | PSR_x | PSR_f},
430 {"CPSR_cxs", TRUE, PSR_c | PSR_x | PSR_s},
431 {"CPSR_fsxc", TRUE, PSR_f | PSR_s | PSR_x | PSR_c},
432 {"CPSR_fscx", TRUE, PSR_f | PSR_s | PSR_c | PSR_x},
433 {"CPSR_fxsc", TRUE, PSR_f | PSR_x | PSR_s | PSR_c},
434 {"CPSR_fxcs", TRUE, PSR_f | PSR_x | PSR_c | PSR_s},
435 {"CPSR_fcsx", TRUE, PSR_f | PSR_c | PSR_s | PSR_x},
436 {"CPSR_fcxs", TRUE, PSR_f | PSR_c | PSR_x | PSR_s},
437 {"CPSR_sfxc", TRUE, PSR_s | PSR_f | PSR_x | PSR_c},
438 {"CPSR_sfcx", TRUE, PSR_s | PSR_f | PSR_c | PSR_x},
439 {"CPSR_sxfc", TRUE, PSR_s | PSR_x | PSR_f | PSR_c},
440 {"CPSR_sxcf", TRUE, PSR_s | PSR_x | PSR_c | PSR_f},
441 {"CPSR_scfx", TRUE, PSR_s | PSR_c | PSR_f | PSR_x},
442 {"CPSR_scxf", TRUE, PSR_s | PSR_c | PSR_x | PSR_f},
443 {"CPSR_xfsc", TRUE, PSR_x | PSR_f | PSR_s | PSR_c},
444 {"CPSR_xfcs", TRUE, PSR_x | PSR_f | PSR_c | PSR_s},
445 {"CPSR_xsfc", TRUE, PSR_x | PSR_s | PSR_f | PSR_c},
446 {"CPSR_xscf", TRUE, PSR_x | PSR_s | PSR_c | PSR_f},
447 {"CPSR_xcfs", TRUE, PSR_x | PSR_c | PSR_f | PSR_s},
448 {"CPSR_xcsf", TRUE, PSR_x | PSR_c | PSR_s | PSR_f},
449 {"CPSR_cfsx", TRUE, PSR_c | PSR_f | PSR_s | PSR_x},
450 {"CPSR_cfxs", TRUE, PSR_c | PSR_f | PSR_x | PSR_s},
451 {"CPSR_csfx", TRUE, PSR_c | PSR_s | PSR_f | PSR_x},
452 {"CPSR_csxf", TRUE, PSR_c | PSR_s | PSR_x | PSR_f},
453 {"CPSR_cxfs", TRUE, PSR_c | PSR_x | PSR_f | PSR_s},
454 {"CPSR_cxsf", TRUE, PSR_c | PSR_x | PSR_s | PSR_f},
455 {"SPSR_fs", FALSE, PSR_f | PSR_s},
456 {"SPSR_fx", FALSE, PSR_f | PSR_x},
457 {"SPSR_fc", FALSE, PSR_f | PSR_c},
458 {"SPSR_sf", FALSE, PSR_s | PSR_f},
459 {"SPSR_sx", FALSE, PSR_s | PSR_x},
460 {"SPSR_sc", FALSE, PSR_s | PSR_c},
461 {"SPSR_xf", FALSE, PSR_x | PSR_f},
462 {"SPSR_xs", FALSE, PSR_x | PSR_s},
463 {"SPSR_xc", FALSE, PSR_x | PSR_c},
464 {"SPSR_cf", FALSE, PSR_c | PSR_f},
465 {"SPSR_cs", FALSE, PSR_c | PSR_s},
466 {"SPSR_cx", FALSE, PSR_c | PSR_x},
467 {"SPSR_fsx", FALSE, PSR_f | PSR_s | PSR_x},
468 {"SPSR_fsc", FALSE, PSR_f | PSR_s | PSR_c},
469 {"SPSR_fxs", FALSE, PSR_f | PSR_x | PSR_s},
470 {"SPSR_fxc", FALSE, PSR_f | PSR_x | PSR_c},
471 {"SPSR_fcs", FALSE, PSR_f | PSR_c | PSR_s},
472 {"SPSR_fcx", FALSE, PSR_f | PSR_c | PSR_x},
473 {"SPSR_sfx", FALSE, PSR_s | PSR_f | PSR_x},
474 {"SPSR_sfc", FALSE, PSR_s | PSR_f | PSR_c},
475 {"SPSR_sxf", FALSE, PSR_s | PSR_x | PSR_f},
476 {"SPSR_sxc", FALSE, PSR_s | PSR_x | PSR_c},
477 {"SPSR_scf", FALSE, PSR_s | PSR_c | PSR_f},
478 {"SPSR_scx", FALSE, PSR_s | PSR_c | PSR_x},
479 {"SPSR_xfs", FALSE, PSR_x | PSR_f | PSR_s},
480 {"SPSR_xfc", FALSE, PSR_x | PSR_f | PSR_c},
481 {"SPSR_xsf", FALSE, PSR_x | PSR_s | PSR_f},
482 {"SPSR_xsc", FALSE, PSR_x | PSR_s | PSR_c},
483 {"SPSR_xcf", FALSE, PSR_x | PSR_c | PSR_f},
484 {"SPSR_xcs", FALSE, PSR_x | PSR_c | PSR_s},
485 {"SPSR_cfs", FALSE, PSR_c | PSR_f | PSR_s},
486 {"SPSR_cfx", FALSE, PSR_c | PSR_f | PSR_x},
487 {"SPSR_csf", FALSE, PSR_c | PSR_s | PSR_f},
488 {"SPSR_csx", FALSE, PSR_c | PSR_s | PSR_x},
489 {"SPSR_cxf", FALSE, PSR_c | PSR_x | PSR_f},
490 {"SPSR_cxs", FALSE, PSR_c | PSR_x | PSR_s},
491 {"SPSR_fsxc", FALSE, PSR_f | PSR_s | PSR_x | PSR_c},
492 {"SPSR_fscx", FALSE, PSR_f | PSR_s | PSR_c | PSR_x},
493 {"SPSR_fxsc", FALSE, PSR_f | PSR_x | PSR_s | PSR_c},
494 {"SPSR_fxcs", FALSE, PSR_f | PSR_x | PSR_c | PSR_s},
495 {"SPSR_fcsx", FALSE, PSR_f | PSR_c | PSR_s | PSR_x},
496 {"SPSR_fcxs", FALSE, PSR_f | PSR_c | PSR_x | PSR_s},
497 {"SPSR_sfxc", FALSE, PSR_s | PSR_f | PSR_x | PSR_c},
498 {"SPSR_sfcx", FALSE, PSR_s | PSR_f | PSR_c | PSR_x},
499 {"SPSR_sxfc", FALSE, PSR_s | PSR_x | PSR_f | PSR_c},
500 {"SPSR_sxcf", FALSE, PSR_s | PSR_x | PSR_c | PSR_f},
501 {"SPSR_scfx", FALSE, PSR_s | PSR_c | PSR_f | PSR_x},
502 {"SPSR_scxf", FALSE, PSR_s | PSR_c | PSR_x | PSR_f},
503 {"SPSR_xfsc", FALSE, PSR_x | PSR_f | PSR_s | PSR_c},
504 {"SPSR_xfcs", FALSE, PSR_x | PSR_f | PSR_c | PSR_s},
505 {"SPSR_xsfc", FALSE, PSR_x | PSR_s | PSR_f | PSR_c},
506 {"SPSR_xscf", FALSE, PSR_x | PSR_s | PSR_c | PSR_f},
507 {"SPSR_xcfs", FALSE, PSR_x | PSR_c | PSR_f | PSR_s},
508 {"SPSR_xcsf", FALSE, PSR_x | PSR_c | PSR_s | PSR_f},
509 {"SPSR_cfsx", FALSE, PSR_c | PSR_f | PSR_s | PSR_x},
510 {"SPSR_cfxs", FALSE, PSR_c | PSR_f | PSR_x | PSR_s},
511 {"SPSR_csfx", FALSE, PSR_c | PSR_s | PSR_f | PSR_x},
512 {"SPSR_csxf", FALSE, PSR_c | PSR_s | PSR_x | PSR_f},
513 {"SPSR_cxfs", FALSE, PSR_c | PSR_x | PSR_f | PSR_s},
514 {"SPSR_cxsf", FALSE, PSR_c | PSR_x | PSR_s | PSR_f},
515 };
516
517 enum wreg_type
518 {
519 IWMMXT_REG_WR = 0,
520 IWMMXT_REG_WC = 1,
521 IWMMXT_REG_WR_OR_WC = 2,
522 IWMMXT_REG_WCG
523 };
524
525 enum iwmmxt_insn_type
526 {
527 check_rd,
528 check_wr,
529 check_wrwr,
530 check_wrwrwr,
531 check_wrwrwcg,
532 check_tbcst,
533 check_tmovmsk,
534 check_tmia,
535 check_tmcrr,
536 check_tmrrc,
537 check_tmcr,
538 check_tmrc,
539 check_tinsr,
540 check_textrc,
541 check_waligni,
542 check_textrm,
543 check_wshufh
544 };
545
546 enum vfp_dp_reg_pos
547 {
548 VFP_REG_Dd, VFP_REG_Dm, VFP_REG_Dn
549 };
550
551 enum vfp_sp_reg_pos
552 {
553 VFP_REG_Sd, VFP_REG_Sm, VFP_REG_Sn
554 };
555
556 enum vfp_ldstm_type
557 {
558 VFP_LDSTMIA, VFP_LDSTMDB, VFP_LDSTMIAX, VFP_LDSTMDBX
559 };
560
561 /* VFP system registers. */
562 struct vfp_reg
563 {
564 const char *name;
565 unsigned long regno;
566 };
567
568 static const struct vfp_reg vfp_regs[] =
569 {
570 {"fpsid", 0x00000000},
571 {"FPSID", 0x00000000},
572 {"fpscr", 0x00010000},
573 {"FPSCR", 0x00010000},
574 {"fpexc", 0x00080000},
575 {"FPEXC", 0x00080000}
576 };
577
578 /* Structure for a hash table entry for a register. */
579 struct reg_entry
580 {
581 const char * name;
582 int number;
583 };
584
585 /* Some well known registers that we refer to directly elsewhere. */
586 #define REG_SP 13
587 #define REG_LR 14
588 #define REG_PC 15
589
590 #define wr_register(reg) ((reg ^ WR_PREFIX) >= 0 && (reg ^ WR_PREFIX) <= 15)
591 #define wc_register(reg) ((reg ^ WC_PREFIX) >= 0 && (reg ^ WC_PREFIX) <= 15)
592 #define wcg_register(reg) ((reg ^ WC_PREFIX) >= 8 && (reg ^ WC_PREFIX) <= 11)
593
594 /* These are the standard names. Users can add aliases with .req. */
595 /* Integer Register Numbers. */
596 static const struct reg_entry rn_table[] =
597 {
598 {"r0", 0}, {"r1", 1}, {"r2", 2}, {"r3", 3},
599 {"r4", 4}, {"r5", 5}, {"r6", 6}, {"r7", 7},
600 {"r8", 8}, {"r9", 9}, {"r10", 10}, {"r11", 11},
601 {"r12", 12}, {"r13", REG_SP}, {"r14", REG_LR}, {"r15", REG_PC},
602 /* ATPCS Synonyms. */
603 {"a1", 0}, {"a2", 1}, {"a3", 2}, {"a4", 3},
604 {"v1", 4}, {"v2", 5}, {"v3", 6}, {"v4", 7},
605 {"v5", 8}, {"v6", 9}, {"v7", 10}, {"v8", 11},
606 /* Well-known aliases. */
607 {"wr", 7},
608 {"sb", 9}, {"sl", 10}, {"fp", 11},
609 {"ip", 12}, {"sp", REG_SP}, {"lr", REG_LR}, {"pc", REG_PC},
610 {NULL, 0}
611 };
612
613 #define WR_PREFIX 0x200
614 #define WC_PREFIX 0x400
615
616 static const struct reg_entry iwmmxt_table[] =
617 {
618 /* Intel Wireless MMX technology register names. */
619 { "wr0", 0x0 | WR_PREFIX}, {"wr1", 0x1 | WR_PREFIX},
620 { "wr2", 0x2 | WR_PREFIX}, {"wr3", 0x3 | WR_PREFIX},
621 { "wr4", 0x4 | WR_PREFIX}, {"wr5", 0x5 | WR_PREFIX},
622 { "wr6", 0x6 | WR_PREFIX}, {"wr7", 0x7 | WR_PREFIX},
623 { "wr8", 0x8 | WR_PREFIX}, {"wr9", 0x9 | WR_PREFIX},
624 { "wr10", 0xa | WR_PREFIX}, {"wr11", 0xb | WR_PREFIX},
625 { "wr12", 0xc | WR_PREFIX}, {"wr13", 0xd | WR_PREFIX},
626 { "wr14", 0xe | WR_PREFIX}, {"wr15", 0xf | WR_PREFIX},
627 { "wcid", 0x0 | WC_PREFIX}, {"wcon", 0x1 | WC_PREFIX},
628 {"wcssf", 0x2 | WC_PREFIX}, {"wcasf", 0x3 | WC_PREFIX},
629 {"wcgr0", 0x8 | WC_PREFIX}, {"wcgr1", 0x9 | WC_PREFIX},
630 {"wcgr2", 0xa | WC_PREFIX}, {"wcgr3", 0xb | WC_PREFIX},
631
632 { "wR0", 0x0 | WR_PREFIX}, {"wR1", 0x1 | WR_PREFIX},
633 { "wR2", 0x2 | WR_PREFIX}, {"wR3", 0x3 | WR_PREFIX},
634 { "wR4", 0x4 | WR_PREFIX}, {"wR5", 0x5 | WR_PREFIX},
635 { "wR6", 0x6 | WR_PREFIX}, {"wR7", 0x7 | WR_PREFIX},
636 { "wR8", 0x8 | WR_PREFIX}, {"wR9", 0x9 | WR_PREFIX},
637 { "wR10", 0xa | WR_PREFIX}, {"wR11", 0xb | WR_PREFIX},
638 { "wR12", 0xc | WR_PREFIX}, {"wR13", 0xd | WR_PREFIX},
639 { "wR14", 0xe | WR_PREFIX}, {"wR15", 0xf | WR_PREFIX},
640 { "wCID", 0x0 | WC_PREFIX}, {"wCon", 0x1 | WC_PREFIX},
641 {"wCSSF", 0x2 | WC_PREFIX}, {"wCASF", 0x3 | WC_PREFIX},
642 {"wCGR0", 0x8 | WC_PREFIX}, {"wCGR1", 0x9 | WC_PREFIX},
643 {"wCGR2", 0xa | WC_PREFIX}, {"wCGR3", 0xb | WC_PREFIX},
644 {NULL, 0}
645 };
646
647 /* Co-processor Numbers. */
648 static const struct reg_entry cp_table[] =
649 {
650 {"p0", 0}, {"p1", 1}, {"p2", 2}, {"p3", 3},
651 {"p4", 4}, {"p5", 5}, {"p6", 6}, {"p7", 7},
652 {"p8", 8}, {"p9", 9}, {"p10", 10}, {"p11", 11},
653 {"p12", 12}, {"p13", 13}, {"p14", 14}, {"p15", 15},
654 {NULL, 0}
655 };
656
657 /* Co-processor Register Numbers. */
658 static const struct reg_entry cn_table[] =
659 {
660 {"c0", 0}, {"c1", 1}, {"c2", 2}, {"c3", 3},
661 {"c4", 4}, {"c5", 5}, {"c6", 6}, {"c7", 7},
662 {"c8", 8}, {"c9", 9}, {"c10", 10}, {"c11", 11},
663 {"c12", 12}, {"c13", 13}, {"c14", 14}, {"c15", 15},
664 /* Not really valid, but kept for back-wards compatibility. */
665 {"cr0", 0}, {"cr1", 1}, {"cr2", 2}, {"cr3", 3},
666 {"cr4", 4}, {"cr5", 5}, {"cr6", 6}, {"cr7", 7},
667 {"cr8", 8}, {"cr9", 9}, {"cr10", 10}, {"cr11", 11},
668 {"cr12", 12}, {"cr13", 13}, {"cr14", 14}, {"cr15", 15},
669 {NULL, 0}
670 };
671
672 /* FPA Registers. */
673 static const struct reg_entry fn_table[] =
674 {
675 {"f0", 0}, {"f1", 1}, {"f2", 2}, {"f3", 3},
676 {"f4", 4}, {"f5", 5}, {"f6", 6}, {"f7", 7},
677 {NULL, 0}
678 };
679
680 /* VFP SP Registers. */
681 static const struct reg_entry sn_table[] =
682 {
683 {"s0", 0}, {"s1", 1}, {"s2", 2}, {"s3", 3},
684 {"s4", 4}, {"s5", 5}, {"s6", 6}, {"s7", 7},
685 {"s8", 8}, {"s9", 9}, {"s10", 10}, {"s11", 11},
686 {"s12", 12}, {"s13", 13}, {"s14", 14}, {"s15", 15},
687 {"s16", 16}, {"s17", 17}, {"s18", 18}, {"s19", 19},
688 {"s20", 20}, {"s21", 21}, {"s22", 22}, {"s23", 23},
689 {"s24", 24}, {"s25", 25}, {"s26", 26}, {"s27", 27},
690 {"s28", 28}, {"s29", 29}, {"s30", 30}, {"s31", 31},
691 {NULL, 0}
692 };
693
694 /* VFP DP Registers. */
695 static const struct reg_entry dn_table[] =
696 {
697 {"d0", 0}, {"d1", 1}, {"d2", 2}, {"d3", 3},
698 {"d4", 4}, {"d5", 5}, {"d6", 6}, {"d7", 7},
699 {"d8", 8}, {"d9", 9}, {"d10", 10}, {"d11", 11},
700 {"d12", 12}, {"d13", 13}, {"d14", 14}, {"d15", 15},
701 {NULL, 0}
702 };
703
704 /* Maverick DSP coprocessor registers. */
705 static const struct reg_entry mav_mvf_table[] =
706 {
707 {"mvf0", 0}, {"mvf1", 1}, {"mvf2", 2}, {"mvf3", 3},
708 {"mvf4", 4}, {"mvf5", 5}, {"mvf6", 6}, {"mvf7", 7},
709 {"mvf8", 8}, {"mvf9", 9}, {"mvf10", 10}, {"mvf11", 11},
710 {"mvf12", 12}, {"mvf13", 13}, {"mvf14", 14}, {"mvf15", 15},
711 {NULL, 0}
712 };
713
714 static const struct reg_entry mav_mvd_table[] =
715 {
716 {"mvd0", 0}, {"mvd1", 1}, {"mvd2", 2}, {"mvd3", 3},
717 {"mvd4", 4}, {"mvd5", 5}, {"mvd6", 6}, {"mvd7", 7},
718 {"mvd8", 8}, {"mvd9", 9}, {"mvd10", 10}, {"mvd11", 11},
719 {"mvd12", 12}, {"mvd13", 13}, {"mvd14", 14}, {"mvd15", 15},
720 {NULL, 0}
721 };
722
723 static const struct reg_entry mav_mvfx_table[] =
724 {
725 {"mvfx0", 0}, {"mvfx1", 1}, {"mvfx2", 2}, {"mvfx3", 3},
726 {"mvfx4", 4}, {"mvfx5", 5}, {"mvfx6", 6}, {"mvfx7", 7},
727 {"mvfx8", 8}, {"mvfx9", 9}, {"mvfx10", 10}, {"mvfx11", 11},
728 {"mvfx12", 12}, {"mvfx13", 13}, {"mvfx14", 14}, {"mvfx15", 15},
729 {NULL, 0}
730 };
731
732 static const struct reg_entry mav_mvdx_table[] =
733 {
734 {"mvdx0", 0}, {"mvdx1", 1}, {"mvdx2", 2}, {"mvdx3", 3},
735 {"mvdx4", 4}, {"mvdx5", 5}, {"mvdx6", 6}, {"mvdx7", 7},
736 {"mvdx8", 8}, {"mvdx9", 9}, {"mvdx10", 10}, {"mvdx11", 11},
737 {"mvdx12", 12}, {"mvdx13", 13}, {"mvdx14", 14}, {"mvdx15", 15},
738 {NULL, 0}
739 };
740
741 static const struct reg_entry mav_mvax_table[] =
742 {
743 {"mvax0", 0}, {"mvax1", 1}, {"mvax2", 2}, {"mvax3", 3},
744 {NULL, 0}
745 };
746
747 static const struct reg_entry mav_dspsc_table[] =
748 {
749 {"dspsc", 0},
750 {NULL, 0}
751 };
752
753 struct reg_map
754 {
755 const struct reg_entry *names;
756 int max_regno;
757 struct hash_control *htab;
758 const char *expected;
759 };
760
761 struct reg_map all_reg_maps[] =
762 {
763 {rn_table, 15, NULL, N_("ARM register expected")},
764 {cp_table, 15, NULL, N_("bad or missing co-processor number")},
765 {cn_table, 15, NULL, N_("co-processor register expected")},
766 {fn_table, 7, NULL, N_("FPA register expected")},
767 {sn_table, 31, NULL, N_("VFP single precision register expected")},
768 {dn_table, 15, NULL, N_("VFP double precision register expected")},
769 {mav_mvf_table, 15, NULL, N_("Maverick MVF register expected")},
770 {mav_mvd_table, 15, NULL, N_("Maverick MVD register expected")},
771 {mav_mvfx_table, 15, NULL, N_("Maverick MVFX register expected")},
772 {mav_mvdx_table, 15, NULL, N_("Maverick MVFX register expected")},
773 {mav_mvax_table, 3, NULL, N_("Maverick MVAX register expected")},
774 {mav_dspsc_table, 0, NULL, N_("Maverick DSPSC register expected")},
775 {iwmmxt_table, 23, NULL, N_("Intel Wireless MMX technology register expected")},
776 };
777
778 /* Enumeration matching entries in table above. */
779 enum arm_reg_type
780 {
781 REG_TYPE_RN = 0,
782 #define REG_TYPE_FIRST REG_TYPE_RN
783 REG_TYPE_CP = 1,
784 REG_TYPE_CN = 2,
785 REG_TYPE_FN = 3,
786 REG_TYPE_SN = 4,
787 REG_TYPE_DN = 5,
788 REG_TYPE_MVF = 6,
789 REG_TYPE_MVD = 7,
790 REG_TYPE_MVFX = 8,
791 REG_TYPE_MVDX = 9,
792 REG_TYPE_MVAX = 10,
793 REG_TYPE_DSPSC = 11,
794 REG_TYPE_IWMMXT = 12,
795
796 REG_TYPE_MAX = 13
797 };
798
799 /* Functions called by parser. */
800 /* ARM instructions. */
801 static void do_arit PARAMS ((char *));
802 static void do_cmp PARAMS ((char *));
803 static void do_mov PARAMS ((char *));
804 static void do_ldst PARAMS ((char *));
805 static void do_ldstt PARAMS ((char *));
806 static void do_ldmstm PARAMS ((char *));
807 static void do_branch PARAMS ((char *));
808 static void do_swi PARAMS ((char *));
809
810 /* Pseudo Op codes. */
811 static void do_adr PARAMS ((char *));
812 static void do_adrl PARAMS ((char *));
813 static void do_empty PARAMS ((char *));
814
815 /* ARM v2. */
816 static void do_mul PARAMS ((char *));
817 static void do_mla PARAMS ((char *));
818
819 /* ARM v2S. */
820 static void do_swap PARAMS ((char *));
821
822 /* ARM v3. */
823 static void do_msr PARAMS ((char *));
824 static void do_mrs PARAMS ((char *));
825
826 /* ARM v3M. */
827 static void do_mull PARAMS ((char *));
828
829 /* ARM v4. */
830 static void do_ldstv4 PARAMS ((char *));
831
832 /* ARM v4T. */
833 static void do_bx PARAMS ((char *));
834
835 /* ARM v5T. */
836 static void do_blx PARAMS ((char *));
837 static void do_bkpt PARAMS ((char *));
838 static void do_clz PARAMS ((char *));
839 static void do_lstc2 PARAMS ((char *));
840 static void do_cdp2 PARAMS ((char *));
841 static void do_co_reg2 PARAMS ((char *));
842
843 /* ARM v5TExP. */
844 static void do_smla PARAMS ((char *));
845 static void do_smlal PARAMS ((char *));
846 static void do_smul PARAMS ((char *));
847 static void do_qadd PARAMS ((char *));
848
849 /* ARM v5TE. */
850 static void do_pld PARAMS ((char *));
851 static void do_ldrd PARAMS ((char *));
852 static void do_co_reg2c PARAMS ((char *));
853
854 /* ARM v5TEJ. */
855 static void do_bxj PARAMS ((char *));
856
857 /* Coprocessor Instructions. */
858 static void do_cdp PARAMS ((char *));
859 static void do_lstc PARAMS ((char *));
860 static void do_co_reg PARAMS ((char *));
861
862 /* FPA instructions. */
863 static void do_fpa_ctrl PARAMS ((char *));
864 static void do_fpa_ldst PARAMS ((char *));
865 static void do_fpa_ldmstm PARAMS ((char *));
866 static void do_fpa_dyadic PARAMS ((char *));
867 static void do_fpa_monadic PARAMS ((char *));
868 static void do_fpa_cmp PARAMS ((char *));
869 static void do_fpa_from_reg PARAMS ((char *));
870 static void do_fpa_to_reg PARAMS ((char *));
871
872 /* VFP instructions. */
873 static void do_vfp_sp_monadic PARAMS ((char *));
874 static void do_vfp_dp_monadic PARAMS ((char *));
875 static void do_vfp_sp_dyadic PARAMS ((char *));
876 static void do_vfp_dp_dyadic PARAMS ((char *));
877 static void do_vfp_reg_from_sp PARAMS ((char *));
878 static void do_vfp_sp_from_reg PARAMS ((char *));
879 static void do_vfp_sp_reg2 PARAMS ((char *));
880 static void do_vfp_reg_from_dp PARAMS ((char *));
881 static void do_vfp_reg2_from_dp PARAMS ((char *));
882 static void do_vfp_dp_from_reg PARAMS ((char *));
883 static void do_vfp_dp_from_reg2 PARAMS ((char *));
884 static void do_vfp_reg_from_ctrl PARAMS ((char *));
885 static void do_vfp_ctrl_from_reg PARAMS ((char *));
886 static void do_vfp_sp_ldst PARAMS ((char *));
887 static void do_vfp_dp_ldst PARAMS ((char *));
888 static void do_vfp_sp_ldstmia PARAMS ((char *));
889 static void do_vfp_sp_ldstmdb PARAMS ((char *));
890 static void do_vfp_dp_ldstmia PARAMS ((char *));
891 static void do_vfp_dp_ldstmdb PARAMS ((char *));
892 static void do_vfp_xp_ldstmia PARAMS ((char *));
893 static void do_vfp_xp_ldstmdb PARAMS ((char *));
894 static void do_vfp_sp_compare_z PARAMS ((char *));
895 static void do_vfp_dp_compare_z PARAMS ((char *));
896 static void do_vfp_dp_sp_cvt PARAMS ((char *));
897 static void do_vfp_sp_dp_cvt PARAMS ((char *));
898
899 /* XScale. */
900 static void do_xsc_mia PARAMS ((char *));
901 static void do_xsc_mar PARAMS ((char *));
902 static void do_xsc_mra PARAMS ((char *));
903
904 /* Maverick. */
905 static void do_mav_binops PARAMS ((char *, int, enum arm_reg_type,
906 enum arm_reg_type));
907 static void do_mav_binops_1a PARAMS ((char *));
908 static void do_mav_binops_1b PARAMS ((char *));
909 static void do_mav_binops_1c PARAMS ((char *));
910 static void do_mav_binops_1d PARAMS ((char *));
911 static void do_mav_binops_1e PARAMS ((char *));
912 static void do_mav_binops_1f PARAMS ((char *));
913 static void do_mav_binops_1g PARAMS ((char *));
914 static void do_mav_binops_1h PARAMS ((char *));
915 static void do_mav_binops_1i PARAMS ((char *));
916 static void do_mav_binops_1j PARAMS ((char *));
917 static void do_mav_binops_1k PARAMS ((char *));
918 static void do_mav_binops_1l PARAMS ((char *));
919 static void do_mav_binops_1m PARAMS ((char *));
920 static void do_mav_binops_1n PARAMS ((char *));
921 static void do_mav_binops_1o PARAMS ((char *));
922 static void do_mav_binops_2a PARAMS ((char *));
923 static void do_mav_binops_2b PARAMS ((char *));
924 static void do_mav_binops_2c PARAMS ((char *));
925 static void do_mav_binops_3a PARAMS ((char *));
926 static void do_mav_binops_3b PARAMS ((char *));
927 static void do_mav_binops_3c PARAMS ((char *));
928 static void do_mav_binops_3d PARAMS ((char *));
929 static void do_mav_triple PARAMS ((char *, int, enum arm_reg_type,
930 enum arm_reg_type,
931 enum arm_reg_type));
932 static void do_mav_triple_4a PARAMS ((char *));
933 static void do_mav_triple_4b PARAMS ((char *));
934 static void do_mav_triple_5a PARAMS ((char *));
935 static void do_mav_triple_5b PARAMS ((char *));
936 static void do_mav_triple_5c PARAMS ((char *));
937 static void do_mav_triple_5d PARAMS ((char *));
938 static void do_mav_triple_5e PARAMS ((char *));
939 static void do_mav_triple_5f PARAMS ((char *));
940 static void do_mav_triple_5g PARAMS ((char *));
941 static void do_mav_triple_5h PARAMS ((char *));
942 static void do_mav_quad PARAMS ((char *, int, enum arm_reg_type,
943 enum arm_reg_type,
944 enum arm_reg_type,
945 enum arm_reg_type));
946 static void do_mav_quad_6a PARAMS ((char *));
947 static void do_mav_quad_6b PARAMS ((char *));
948 static void do_mav_dspsc_1 PARAMS ((char *));
949 static void do_mav_dspsc_2 PARAMS ((char *));
950 static void do_mav_shift PARAMS ((char *, enum arm_reg_type,
951 enum arm_reg_type));
952 static void do_mav_shift_1 PARAMS ((char *));
953 static void do_mav_shift_2 PARAMS ((char *));
954 static void do_mav_ldst PARAMS ((char *, enum arm_reg_type));
955 static void do_mav_ldst_1 PARAMS ((char *));
956 static void do_mav_ldst_2 PARAMS ((char *));
957 static void do_mav_ldst_3 PARAMS ((char *));
958 static void do_mav_ldst_4 PARAMS ((char *));
959
960 static int mav_reg_required_here PARAMS ((char **, int,
961 enum arm_reg_type));
962 static int mav_parse_offset PARAMS ((char **, int *));
963
964 static void fix_new_arm PARAMS ((fragS *, int, short, expressionS *,
965 int, int));
966 static int arm_reg_parse PARAMS ((char **, struct hash_control *));
967 static enum arm_reg_type arm_reg_parse_any PARAMS ((char *));
968 static const struct asm_psr * arm_psr_parse PARAMS ((char **));
969 static void symbol_locate PARAMS ((symbolS *, const char *, segT, valueT,
970 fragS *));
971 static int add_to_lit_pool PARAMS ((void));
972 static unsigned validate_immediate PARAMS ((unsigned));
973 static unsigned validate_immediate_twopart PARAMS ((unsigned int,
974 unsigned int *));
975 static int validate_offset_imm PARAMS ((unsigned int, int));
976 static void opcode_select PARAMS ((int));
977 static void end_of_line PARAMS ((char *));
978 static int reg_required_here PARAMS ((char **, int));
979 static int psr_required_here PARAMS ((char **));
980 static int co_proc_number PARAMS ((char **));
981 static int cp_opc_expr PARAMS ((char **, int, int));
982 static int cp_reg_required_here PARAMS ((char **, int));
983 static int fp_reg_required_here PARAMS ((char **, int));
984 static int vfp_sp_reg_required_here PARAMS ((char **, enum vfp_sp_reg_pos));
985 static int vfp_dp_reg_required_here PARAMS ((char **, enum vfp_dp_reg_pos));
986 static void vfp_sp_ldstm PARAMS ((char *, enum vfp_ldstm_type));
987 static void vfp_dp_ldstm PARAMS ((char *, enum vfp_ldstm_type));
988 static long vfp_sp_reg_list PARAMS ((char **, enum vfp_sp_reg_pos));
989 static long vfp_dp_reg_list PARAMS ((char **));
990 static int vfp_psr_required_here PARAMS ((char **str));
991 static const struct vfp_reg *vfp_psr_parse PARAMS ((char **str));
992 static int cp_address_offset PARAMS ((char **));
993 static int cp_address_required_here PARAMS ((char **, int));
994 static int my_get_float_expression PARAMS ((char **));
995 static int skip_past_comma PARAMS ((char **));
996 static int walk_no_bignums PARAMS ((symbolS *));
997 static int negate_data_op PARAMS ((unsigned long *, unsigned long));
998 static int data_op2 PARAMS ((char **));
999 static int fp_op2 PARAMS ((char **));
1000 static long reg_list PARAMS ((char **));
1001 static void thumb_load_store PARAMS ((char *, int, int));
1002 static int decode_shift PARAMS ((char **, int));
1003 static int ldst_extend PARAMS ((char **));
1004 static int ldst_extend_v4 PARAMS ((char **));
1005 static void thumb_add_sub PARAMS ((char *, int));
1006 static void insert_reg PARAMS ((const struct reg_entry *,
1007 struct hash_control *));
1008 static void thumb_shift PARAMS ((char *, int));
1009 static void thumb_mov_compare PARAMS ((char *, int));
1010 static void build_arm_ops_hsh PARAMS ((void));
1011 static void set_constant_flonums PARAMS ((void));
1012 static valueT md_chars_to_number PARAMS ((char *, int));
1013 static void build_reg_hsh PARAMS ((struct reg_map *));
1014 static void insert_reg_alias PARAMS ((char *, int, struct hash_control *));
1015 static int create_register_alias PARAMS ((char *, char *));
1016 static void output_inst PARAMS ((const char *));
1017 static int accum0_required_here PARAMS ((char **));
1018 static int ld_mode_required_here PARAMS ((char **));
1019 static void do_branch25 PARAMS ((char *));
1020 static symbolS * find_real_start PARAMS ((symbolS *));
1021 #ifdef OBJ_ELF
1022 static bfd_reloc_code_real_type arm_parse_reloc PARAMS ((void));
1023 #endif
1024
1025 static int wreg_required_here PARAMS ((char **, int, enum wreg_type));
1026 static void do_iwmmxt_byte_addr PARAMS ((char *));
1027 static void do_iwmmxt_tandc PARAMS ((char *));
1028 static void do_iwmmxt_tbcst PARAMS ((char *));
1029 static void do_iwmmxt_textrc PARAMS ((char *));
1030 static void do_iwmmxt_textrm PARAMS ((char *));
1031 static void do_iwmmxt_tinsr PARAMS ((char *));
1032 static void do_iwmmxt_tmcr PARAMS ((char *));
1033 static void do_iwmmxt_tmcrr PARAMS ((char *));
1034 static void do_iwmmxt_tmia PARAMS ((char *));
1035 static void do_iwmmxt_tmovmsk PARAMS ((char *));
1036 static void do_iwmmxt_tmrc PARAMS ((char *));
1037 static void do_iwmmxt_tmrrc PARAMS ((char *));
1038 static void do_iwmmxt_torc PARAMS ((char *));
1039 static void do_iwmmxt_waligni PARAMS ((char *));
1040 static void do_iwmmxt_wmov PARAMS ((char *));
1041 static void do_iwmmxt_word_addr PARAMS ((char *));
1042 static void do_iwmmxt_wrwr PARAMS ((char *));
1043 static void do_iwmmxt_wrwrwcg PARAMS ((char *));
1044 static void do_iwmmxt_wrwrwr PARAMS ((char *));
1045 static void do_iwmmxt_wshufh PARAMS ((char *));
1046 static void do_iwmmxt_wzero PARAMS ((char *));
1047 static int cp_byte_address_offset PARAMS ((char **));
1048 static int cp_byte_address_required_here PARAMS ((char **));
1049
1050 /* ARM instructions take 4bytes in the object file, Thumb instructions
1051 take 2: */
1052 #define INSN_SIZE 4
1053
1054 /* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
1055 #define MAV_MODE1 0x100c
1056
1057 /* "INSN<cond> X,Y" where X:bit16, Y:bit12. */
1058 #define MAV_MODE2 0x0c10
1059
1060 /* "INSN<cond> X,Y" where X:0, Y:bit16. */
1061 #define MAV_MODE3 0x1000
1062
1063 /* "INSN<cond> X,Y,Z" where X:16, Y:0, Z:12. */
1064 #define MAV_MODE4 0x0c0010
1065
1066 /* "INSN<cond> X,Y,Z" where X:12, Y:16, Z:0. */
1067 #define MAV_MODE5 0x00100c
1068
1069 /* "INSN<cond> W,X,Y,Z" where W:5, X:12, Y:16, Z:0. */
1070 #define MAV_MODE6 0x00100c05
1071
1072 struct asm_opcode
1073 {
1074 /* Basic string to match. */
1075 const char * template;
1076
1077 /* Basic instruction code. */
1078 unsigned long value;
1079
1080 /* Offset into the template where the condition code (if any) will be.
1081 If zero, then the instruction is never conditional. */
1082 unsigned cond_offset;
1083
1084 /* Which architecture variant provides this instruction. */
1085 unsigned long variant;
1086
1087 /* Function to call to parse args. */
1088 void (* parms) PARAMS ((char *));
1089 };
1090
1091 static const struct asm_opcode insns[] =
1092 {
1093 /* Core ARM Instructions. */
1094 {"and", 0xe0000000, 3, ARM_EXT_V1, do_arit},
1095 {"ands", 0xe0100000, 3, ARM_EXT_V1, do_arit},
1096 {"eor", 0xe0200000, 3, ARM_EXT_V1, do_arit},
1097 {"eors", 0xe0300000, 3, ARM_EXT_V1, do_arit},
1098 {"sub", 0xe0400000, 3, ARM_EXT_V1, do_arit},
1099 {"subs", 0xe0500000, 3, ARM_EXT_V1, do_arit},
1100 {"rsb", 0xe0600000, 3, ARM_EXT_V1, do_arit},
1101 {"rsbs", 0xe0700000, 3, ARM_EXT_V1, do_arit},
1102 {"add", 0xe0800000, 3, ARM_EXT_V1, do_arit},
1103 {"adds", 0xe0900000, 3, ARM_EXT_V1, do_arit},
1104 {"adc", 0xe0a00000, 3, ARM_EXT_V1, do_arit},
1105 {"adcs", 0xe0b00000, 3, ARM_EXT_V1, do_arit},
1106 {"sbc", 0xe0c00000, 3, ARM_EXT_V1, do_arit},
1107 {"sbcs", 0xe0d00000, 3, ARM_EXT_V1, do_arit},
1108 {"rsc", 0xe0e00000, 3, ARM_EXT_V1, do_arit},
1109 {"rscs", 0xe0f00000, 3, ARM_EXT_V1, do_arit},
1110 {"orr", 0xe1800000, 3, ARM_EXT_V1, do_arit},
1111 {"orrs", 0xe1900000, 3, ARM_EXT_V1, do_arit},
1112 {"bic", 0xe1c00000, 3, ARM_EXT_V1, do_arit},
1113 {"bics", 0xe1d00000, 3, ARM_EXT_V1, do_arit},
1114
1115 {"tst", 0xe1100000, 3, ARM_EXT_V1, do_cmp},
1116 {"tsts", 0xe1100000, 3, ARM_EXT_V1, do_cmp},
1117 {"tstp", 0xe110f000, 3, ARM_EXT_V1, do_cmp},
1118 {"teq", 0xe1300000, 3, ARM_EXT_V1, do_cmp},
1119 {"teqs", 0xe1300000, 3, ARM_EXT_V1, do_cmp},
1120 {"teqp", 0xe130f000, 3, ARM_EXT_V1, do_cmp},
1121 {"cmp", 0xe1500000, 3, ARM_EXT_V1, do_cmp},
1122 {"cmps", 0xe1500000, 3, ARM_EXT_V1, do_cmp},
1123 {"cmpp", 0xe150f000, 3, ARM_EXT_V1, do_cmp},
1124 {"cmn", 0xe1700000, 3, ARM_EXT_V1, do_cmp},
1125 {"cmns", 0xe1700000, 3, ARM_EXT_V1, do_cmp},
1126 {"cmnp", 0xe170f000, 3, ARM_EXT_V1, do_cmp},
1127
1128 {"mov", 0xe1a00000, 3, ARM_EXT_V1, do_mov},
1129 {"movs", 0xe1b00000, 3, ARM_EXT_V1, do_mov},
1130 {"mvn", 0xe1e00000, 3, ARM_EXT_V1, do_mov},
1131 {"mvns", 0xe1f00000, 3, ARM_EXT_V1, do_mov},
1132
1133 {"ldr", 0xe4100000, 3, ARM_EXT_V1, do_ldst},
1134 {"ldrb", 0xe4500000, 3, ARM_EXT_V1, do_ldst},
1135 {"ldrt", 0xe4300000, 3, ARM_EXT_V1, do_ldstt},
1136 {"ldrbt", 0xe4700000, 3, ARM_EXT_V1, do_ldstt},
1137 {"str", 0xe4000000, 3, ARM_EXT_V1, do_ldst},
1138 {"strb", 0xe4400000, 3, ARM_EXT_V1, do_ldst},
1139 {"strt", 0xe4200000, 3, ARM_EXT_V1, do_ldstt},
1140 {"strbt", 0xe4600000, 3, ARM_EXT_V1, do_ldstt},
1141
1142 {"stmia", 0xe8800000, 3, ARM_EXT_V1, do_ldmstm},
1143 {"stmib", 0xe9800000, 3, ARM_EXT_V1, do_ldmstm},
1144 {"stmda", 0xe8000000, 3, ARM_EXT_V1, do_ldmstm},
1145 {"stmdb", 0xe9000000, 3, ARM_EXT_V1, do_ldmstm},
1146 {"stmfd", 0xe9000000, 3, ARM_EXT_V1, do_ldmstm},
1147 {"stmfa", 0xe9800000, 3, ARM_EXT_V1, do_ldmstm},
1148 {"stmea", 0xe8800000, 3, ARM_EXT_V1, do_ldmstm},
1149 {"stmed", 0xe8000000, 3, ARM_EXT_V1, do_ldmstm},
1150
1151 {"ldmia", 0xe8900000, 3, ARM_EXT_V1, do_ldmstm},
1152 {"ldmib", 0xe9900000, 3, ARM_EXT_V1, do_ldmstm},
1153 {"ldmda", 0xe8100000, 3, ARM_EXT_V1, do_ldmstm},
1154 {"ldmdb", 0xe9100000, 3, ARM_EXT_V1, do_ldmstm},
1155 {"ldmfd", 0xe8900000, 3, ARM_EXT_V1, do_ldmstm},
1156 {"ldmfa", 0xe8100000, 3, ARM_EXT_V1, do_ldmstm},
1157 {"ldmea", 0xe9100000, 3, ARM_EXT_V1, do_ldmstm},
1158 {"ldmed", 0xe9900000, 3, ARM_EXT_V1, do_ldmstm},
1159
1160 {"swi", 0xef000000, 3, ARM_EXT_V1, do_swi},
1161 #ifdef TE_WINCE
1162 /* XXX This is the wrong place to do this. Think multi-arch. */
1163 {"bl", 0xeb000000, 2, ARM_EXT_V1, do_branch},
1164 {"b", 0xea000000, 1, ARM_EXT_V1, do_branch},
1165 #else
1166 {"bl", 0xebfffffe, 2, ARM_EXT_V1, do_branch},
1167 {"b", 0xeafffffe, 1, ARM_EXT_V1, do_branch},
1168 #endif
1169
1170 /* Pseudo ops. */
1171 {"adr", 0xe28f0000, 3, ARM_EXT_V1, do_adr},
1172 {"adrl", 0xe28f0000, 3, ARM_EXT_V1, do_adrl},
1173 {"nop", 0xe1a00000, 3, ARM_EXT_V1, do_empty},
1174
1175 /* ARM 2 multiplies. */
1176 {"mul", 0xe0000090, 3, ARM_EXT_V2, do_mul},
1177 {"muls", 0xe0100090, 3, ARM_EXT_V2, do_mul},
1178 {"mla", 0xe0200090, 3, ARM_EXT_V2, do_mla},
1179 {"mlas", 0xe0300090, 3, ARM_EXT_V2, do_mla},
1180
1181 /* Generic copressor instructions. */
1182 {"cdp", 0xee000000, 3, ARM_EXT_V2, do_cdp},
1183 {"ldc", 0xec100000, 3, ARM_EXT_V2, do_lstc},
1184 {"ldcl", 0xec500000, 3, ARM_EXT_V2, do_lstc},
1185 {"stc", 0xec000000, 3, ARM_EXT_V2, do_lstc},
1186 {"stcl", 0xec400000, 3, ARM_EXT_V2, do_lstc},
1187 {"mcr", 0xee000010, 3, ARM_EXT_V2, do_co_reg},
1188 {"mrc", 0xee100010, 3, ARM_EXT_V2, do_co_reg},
1189
1190 /* ARM 3 - swp instructions. */
1191 {"swp", 0xe1000090, 3, ARM_EXT_V2S, do_swap},
1192 {"swpb", 0xe1400090, 3, ARM_EXT_V2S, do_swap},
1193
1194 /* ARM 6 Status register instructions. */
1195 {"mrs", 0xe10f0000, 3, ARM_EXT_V3, do_mrs},
1196 {"msr", 0xe120f000, 3, ARM_EXT_V3, do_msr},
1197 /* ScottB: our code uses 0xe128f000 for msr.
1198 NickC: but this is wrong because the bits 16 through 19 are
1199 handled by the PSR_xxx defines above. */
1200
1201 /* ARM 7M long multiplies. */
1202 {"smull", 0xe0c00090, 5, ARM_EXT_V3M, do_mull},
1203 {"smulls", 0xe0d00090, 5, ARM_EXT_V3M, do_mull},
1204 {"umull", 0xe0800090, 5, ARM_EXT_V3M, do_mull},
1205 {"umulls", 0xe0900090, 5, ARM_EXT_V3M, do_mull},
1206 {"smlal", 0xe0e00090, 5, ARM_EXT_V3M, do_mull},
1207 {"smlals", 0xe0f00090, 5, ARM_EXT_V3M, do_mull},
1208 {"umlal", 0xe0a00090, 5, ARM_EXT_V3M, do_mull},
1209 {"umlals", 0xe0b00090, 5, ARM_EXT_V3M, do_mull},
1210
1211 /* ARM Architecture 4. */
1212 {"ldrh", 0xe01000b0, 3, ARM_EXT_V4, do_ldstv4},
1213 {"ldrsh", 0xe01000f0, 3, ARM_EXT_V4, do_ldstv4},
1214 {"ldrsb", 0xe01000d0, 3, ARM_EXT_V4, do_ldstv4},
1215 {"strh", 0xe00000b0, 3, ARM_EXT_V4, do_ldstv4},
1216
1217 /* ARM Architecture 4T. */
1218 /* Note: bx (and blx) are required on V5, even if the processor does
1219 not support Thumb. */
1220 {"bx", 0xe12fff10, 2, ARM_EXT_V4T | ARM_EXT_V5, do_bx},
1221
1222 /* ARM Architecture 5T. */
1223 /* Note: blx has 2 variants, so the .value is set dynamically.
1224 Only one of the variants has conditional execution. */
1225 {"blx", 0xe0000000, 3, ARM_EXT_V5, do_blx},
1226 {"clz", 0xe16f0f10, 3, ARM_EXT_V5, do_clz},
1227 {"bkpt", 0xe1200070, 0, ARM_EXT_V5, do_bkpt},
1228 {"ldc2", 0xfc100000, 0, ARM_EXT_V5, do_lstc2},
1229 {"ldc2l", 0xfc500000, 0, ARM_EXT_V5, do_lstc2},
1230 {"stc2", 0xfc000000, 0, ARM_EXT_V5, do_lstc2},
1231 {"stc2l", 0xfc400000, 0, ARM_EXT_V5, do_lstc2},
1232 {"cdp2", 0xfe000000, 0, ARM_EXT_V5, do_cdp2},
1233 {"mcr2", 0xfe000010, 0, ARM_EXT_V5, do_co_reg2},
1234 {"mrc2", 0xfe100010, 0, ARM_EXT_V5, do_co_reg2},
1235
1236 /* ARM Architecture 5TExP. */
1237 {"smlabb", 0xe1000080, 6, ARM_EXT_V5ExP, do_smla},
1238 {"smlatb", 0xe10000a0, 6, ARM_EXT_V5ExP, do_smla},
1239 {"smlabt", 0xe10000c0, 6, ARM_EXT_V5ExP, do_smla},
1240 {"smlatt", 0xe10000e0, 6, ARM_EXT_V5ExP, do_smla},
1241
1242 {"smlawb", 0xe1200080, 6, ARM_EXT_V5ExP, do_smla},
1243 {"smlawt", 0xe12000c0, 6, ARM_EXT_V5ExP, do_smla},
1244
1245 {"smlalbb", 0xe1400080, 7, ARM_EXT_V5ExP, do_smlal},
1246 {"smlaltb", 0xe14000a0, 7, ARM_EXT_V5ExP, do_smlal},
1247 {"smlalbt", 0xe14000c0, 7, ARM_EXT_V5ExP, do_smlal},
1248 {"smlaltt", 0xe14000e0, 7, ARM_EXT_V5ExP, do_smlal},
1249
1250 {"smulbb", 0xe1600080, 6, ARM_EXT_V5ExP, do_smul},
1251 {"smultb", 0xe16000a0, 6, ARM_EXT_V5ExP, do_smul},
1252 {"smulbt", 0xe16000c0, 6, ARM_EXT_V5ExP, do_smul},
1253 {"smultt", 0xe16000e0, 6, ARM_EXT_V5ExP, do_smul},
1254
1255 {"smulwb", 0xe12000a0, 6, ARM_EXT_V5ExP, do_smul},
1256 {"smulwt", 0xe12000e0, 6, ARM_EXT_V5ExP, do_smul},
1257
1258 {"qadd", 0xe1000050, 4, ARM_EXT_V5ExP, do_qadd},
1259 {"qdadd", 0xe1400050, 5, ARM_EXT_V5ExP, do_qadd},
1260 {"qsub", 0xe1200050, 4, ARM_EXT_V5ExP, do_qadd},
1261 {"qdsub", 0xe1600050, 5, ARM_EXT_V5ExP, do_qadd},
1262
1263 /* ARM Architecture 5TE. */
1264 {"pld", 0xf450f000, 0, ARM_EXT_V5E, do_pld},
1265 {"ldrd", 0xe00000d0, 3, ARM_EXT_V5E, do_ldrd},
1266 {"strd", 0xe00000f0, 3, ARM_EXT_V5E, do_ldrd},
1267
1268 {"mcrr", 0xec400000, 4, ARM_EXT_V5E, do_co_reg2c},
1269 {"mrrc", 0xec500000, 4, ARM_EXT_V5E, do_co_reg2c},
1270
1271 /* ARM Architecture 5TEJ. */
1272 {"bxj", 0xe12fff20, 3, ARM_EXT_V5J, do_bxj},
1273
1274 /* Core FPA instruction set (V1). */
1275 {"wfs", 0xee200110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
1276 {"rfs", 0xee300110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
1277 {"wfc", 0xee400110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
1278 {"rfc", 0xee500110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
1279
1280 {"ldfs", 0xec100100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1281 {"ldfd", 0xec108100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1282 {"ldfe", 0xec500100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1283 {"ldfp", 0xec508100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1284
1285 {"stfs", 0xec000100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1286 {"stfd", 0xec008100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1287 {"stfe", 0xec400100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1288 {"stfp", 0xec408100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1289
1290 {"mvfs", 0xee008100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1291 {"mvfsp", 0xee008120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1292 {"mvfsm", 0xee008140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1293 {"mvfsz", 0xee008160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1294 {"mvfd", 0xee008180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1295 {"mvfdp", 0xee0081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1296 {"mvfdm", 0xee0081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1297 {"mvfdz", 0xee0081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1298 {"mvfe", 0xee088100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1299 {"mvfep", 0xee088120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1300 {"mvfem", 0xee088140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1301 {"mvfez", 0xee088160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1302
1303 {"mnfs", 0xee108100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1304 {"mnfsp", 0xee108120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1305 {"mnfsm", 0xee108140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1306 {"mnfsz", 0xee108160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1307 {"mnfd", 0xee108180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1308 {"mnfdp", 0xee1081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1309 {"mnfdm", 0xee1081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1310 {"mnfdz", 0xee1081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1311 {"mnfe", 0xee188100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1312 {"mnfep", 0xee188120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1313 {"mnfem", 0xee188140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1314 {"mnfez", 0xee188160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1315
1316 {"abss", 0xee208100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1317 {"abssp", 0xee208120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1318 {"abssm", 0xee208140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1319 {"abssz", 0xee208160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1320 {"absd", 0xee208180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1321 {"absdp", 0xee2081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1322 {"absdm", 0xee2081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1323 {"absdz", 0xee2081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1324 {"abse", 0xee288100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1325 {"absep", 0xee288120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1326 {"absem", 0xee288140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1327 {"absez", 0xee288160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1328
1329 {"rnds", 0xee308100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1330 {"rndsp", 0xee308120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1331 {"rndsm", 0xee308140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1332 {"rndsz", 0xee308160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1333 {"rndd", 0xee308180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1334 {"rnddp", 0xee3081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1335 {"rnddm", 0xee3081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1336 {"rnddz", 0xee3081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1337 {"rnde", 0xee388100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1338 {"rndep", 0xee388120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1339 {"rndem", 0xee388140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1340 {"rndez", 0xee388160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1341
1342 {"sqts", 0xee408100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1343 {"sqtsp", 0xee408120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1344 {"sqtsm", 0xee408140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1345 {"sqtsz", 0xee408160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1346 {"sqtd", 0xee408180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1347 {"sqtdp", 0xee4081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1348 {"sqtdm", 0xee4081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1349 {"sqtdz", 0xee4081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1350 {"sqte", 0xee488100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1351 {"sqtep", 0xee488120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1352 {"sqtem", 0xee488140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1353 {"sqtez", 0xee488160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1354
1355 {"logs", 0xee508100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1356 {"logsp", 0xee508120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1357 {"logsm", 0xee508140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1358 {"logsz", 0xee508160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1359 {"logd", 0xee508180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1360 {"logdp", 0xee5081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1361 {"logdm", 0xee5081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1362 {"logdz", 0xee5081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1363 {"loge", 0xee588100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1364 {"logep", 0xee588120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1365 {"logem", 0xee588140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1366 {"logez", 0xee588160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1367
1368 {"lgns", 0xee608100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1369 {"lgnsp", 0xee608120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1370 {"lgnsm", 0xee608140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1371 {"lgnsz", 0xee608160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1372 {"lgnd", 0xee608180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1373 {"lgndp", 0xee6081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1374 {"lgndm", 0xee6081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1375 {"lgndz", 0xee6081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1376 {"lgne", 0xee688100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1377 {"lgnep", 0xee688120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1378 {"lgnem", 0xee688140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1379 {"lgnez", 0xee688160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1380
1381 {"exps", 0xee708100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1382 {"expsp", 0xee708120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1383 {"expsm", 0xee708140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1384 {"expsz", 0xee708160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1385 {"expd", 0xee708180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1386 {"expdp", 0xee7081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1387 {"expdm", 0xee7081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1388 {"expdz", 0xee7081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1389 {"expe", 0xee788100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1390 {"expep", 0xee788120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1391 {"expem", 0xee788140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1392 {"expdz", 0xee788160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1393
1394 {"sins", 0xee808100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1395 {"sinsp", 0xee808120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1396 {"sinsm", 0xee808140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1397 {"sinsz", 0xee808160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1398 {"sind", 0xee808180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1399 {"sindp", 0xee8081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1400 {"sindm", 0xee8081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1401 {"sindz", 0xee8081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1402 {"sine", 0xee888100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1403 {"sinep", 0xee888120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1404 {"sinem", 0xee888140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1405 {"sinez", 0xee888160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1406
1407 {"coss", 0xee908100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1408 {"cossp", 0xee908120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1409 {"cossm", 0xee908140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1410 {"cossz", 0xee908160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1411 {"cosd", 0xee908180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1412 {"cosdp", 0xee9081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1413 {"cosdm", 0xee9081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1414 {"cosdz", 0xee9081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1415 {"cose", 0xee988100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1416 {"cosep", 0xee988120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1417 {"cosem", 0xee988140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1418 {"cosez", 0xee988160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1419
1420 {"tans", 0xeea08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1421 {"tansp", 0xeea08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1422 {"tansm", 0xeea08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1423 {"tansz", 0xeea08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1424 {"tand", 0xeea08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1425 {"tandp", 0xeea081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1426 {"tandm", 0xeea081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1427 {"tandz", 0xeea081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1428 {"tane", 0xeea88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1429 {"tanep", 0xeea88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1430 {"tanem", 0xeea88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1431 {"tanez", 0xeea88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1432
1433 {"asns", 0xeeb08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1434 {"asnsp", 0xeeb08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1435 {"asnsm", 0xeeb08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1436 {"asnsz", 0xeeb08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1437 {"asnd", 0xeeb08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1438 {"asndp", 0xeeb081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1439 {"asndm", 0xeeb081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1440 {"asndz", 0xeeb081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1441 {"asne", 0xeeb88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1442 {"asnep", 0xeeb88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1443 {"asnem", 0xeeb88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1444 {"asnez", 0xeeb88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1445
1446 {"acss", 0xeec08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1447 {"acssp", 0xeec08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1448 {"acssm", 0xeec08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1449 {"acssz", 0xeec08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1450 {"acsd", 0xeec08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1451 {"acsdp", 0xeec081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1452 {"acsdm", 0xeec081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1453 {"acsdz", 0xeec081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1454 {"acse", 0xeec88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1455 {"acsep", 0xeec88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1456 {"acsem", 0xeec88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1457 {"acsez", 0xeec88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1458
1459 {"atns", 0xeed08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1460 {"atnsp", 0xeed08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1461 {"atnsm", 0xeed08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1462 {"atnsz", 0xeed08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1463 {"atnd", 0xeed08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1464 {"atndp", 0xeed081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1465 {"atndm", 0xeed081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1466 {"atndz", 0xeed081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1467 {"atne", 0xeed88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1468 {"atnep", 0xeed88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1469 {"atnem", 0xeed88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1470 {"atnez", 0xeed88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1471
1472 {"urds", 0xeee08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1473 {"urdsp", 0xeee08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1474 {"urdsm", 0xeee08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1475 {"urdsz", 0xeee08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1476 {"urdd", 0xeee08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1477 {"urddp", 0xeee081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1478 {"urddm", 0xeee081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1479 {"urddz", 0xeee081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1480 {"urde", 0xeee88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1481 {"urdep", 0xeee88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1482 {"urdem", 0xeee88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1483 {"urdez", 0xeee88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1484
1485 {"nrms", 0xeef08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1486 {"nrmsp", 0xeef08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1487 {"nrmsm", 0xeef08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1488 {"nrmsz", 0xeef08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1489 {"nrmd", 0xeef08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1490 {"nrmdp", 0xeef081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1491 {"nrmdm", 0xeef081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1492 {"nrmdz", 0xeef081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1493 {"nrme", 0xeef88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1494 {"nrmep", 0xeef88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1495 {"nrmem", 0xeef88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1496 {"nrmez", 0xeef88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1497
1498 {"adfs", 0xee000100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1499 {"adfsp", 0xee000120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1500 {"adfsm", 0xee000140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1501 {"adfsz", 0xee000160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1502 {"adfd", 0xee000180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1503 {"adfdp", 0xee0001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1504 {"adfdm", 0xee0001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1505 {"adfdz", 0xee0001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1506 {"adfe", 0xee080100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1507 {"adfep", 0xee080120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1508 {"adfem", 0xee080140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1509 {"adfez", 0xee080160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1510
1511 {"sufs", 0xee200100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1512 {"sufsp", 0xee200120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1513 {"sufsm", 0xee200140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1514 {"sufsz", 0xee200160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1515 {"sufd", 0xee200180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1516 {"sufdp", 0xee2001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1517 {"sufdm", 0xee2001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1518 {"sufdz", 0xee2001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1519 {"sufe", 0xee280100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1520 {"sufep", 0xee280120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1521 {"sufem", 0xee280140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1522 {"sufez", 0xee280160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1523
1524 {"rsfs", 0xee300100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1525 {"rsfsp", 0xee300120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1526 {"rsfsm", 0xee300140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1527 {"rsfsz", 0xee300160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1528 {"rsfd", 0xee300180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1529 {"rsfdp", 0xee3001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1530 {"rsfdm", 0xee3001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1531 {"rsfdz", 0xee3001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1532 {"rsfe", 0xee380100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1533 {"rsfep", 0xee380120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1534 {"rsfem", 0xee380140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1535 {"rsfez", 0xee380160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1536
1537 {"mufs", 0xee100100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1538 {"mufsp", 0xee100120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1539 {"mufsm", 0xee100140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1540 {"mufsz", 0xee100160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1541 {"mufd", 0xee100180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1542 {"mufdp", 0xee1001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1543 {"mufdm", 0xee1001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1544 {"mufdz", 0xee1001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1545 {"mufe", 0xee180100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1546 {"mufep", 0xee180120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1547 {"mufem", 0xee180140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1548 {"mufez", 0xee180160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1549
1550 {"dvfs", 0xee400100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1551 {"dvfsp", 0xee400120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1552 {"dvfsm", 0xee400140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1553 {"dvfsz", 0xee400160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1554 {"dvfd", 0xee400180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1555 {"dvfdp", 0xee4001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1556 {"dvfdm", 0xee4001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1557 {"dvfdz", 0xee4001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1558 {"dvfe", 0xee480100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1559 {"dvfep", 0xee480120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1560 {"dvfem", 0xee480140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1561 {"dvfez", 0xee480160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1562
1563 {"rdfs", 0xee500100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1564 {"rdfsp", 0xee500120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1565 {"rdfsm", 0xee500140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1566 {"rdfsz", 0xee500160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1567 {"rdfd", 0xee500180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1568 {"rdfdp", 0xee5001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1569 {"rdfdm", 0xee5001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1570 {"rdfdz", 0xee5001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1571 {"rdfe", 0xee580100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1572 {"rdfep", 0xee580120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1573 {"rdfem", 0xee580140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1574 {"rdfez", 0xee580160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1575
1576 {"pows", 0xee600100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1577 {"powsp", 0xee600120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1578 {"powsm", 0xee600140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1579 {"powsz", 0xee600160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1580 {"powd", 0xee600180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1581 {"powdp", 0xee6001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1582 {"powdm", 0xee6001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1583 {"powdz", 0xee6001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1584 {"powe", 0xee680100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1585 {"powep", 0xee680120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1586 {"powem", 0xee680140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1587 {"powez", 0xee680160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1588
1589 {"rpws", 0xee700100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1590 {"rpwsp", 0xee700120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1591 {"rpwsm", 0xee700140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1592 {"rpwsz", 0xee700160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1593 {"rpwd", 0xee700180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1594 {"rpwdp", 0xee7001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1595 {"rpwdm", 0xee7001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1596 {"rpwdz", 0xee7001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1597 {"rpwe", 0xee780100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1598 {"rpwep", 0xee780120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1599 {"rpwem", 0xee780140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1600 {"rpwez", 0xee780160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1601
1602 {"rmfs", 0xee800100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1603 {"rmfsp", 0xee800120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1604 {"rmfsm", 0xee800140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1605 {"rmfsz", 0xee800160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1606 {"rmfd", 0xee800180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1607 {"rmfdp", 0xee8001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1608 {"rmfdm", 0xee8001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1609 {"rmfdz", 0xee8001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1610 {"rmfe", 0xee880100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1611 {"rmfep", 0xee880120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1612 {"rmfem", 0xee880140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1613 {"rmfez", 0xee880160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1614
1615 {"fmls", 0xee900100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1616 {"fmlsp", 0xee900120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1617 {"fmlsm", 0xee900140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1618 {"fmlsz", 0xee900160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1619 {"fmld", 0xee900180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1620 {"fmldp", 0xee9001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1621 {"fmldm", 0xee9001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1622 {"fmldz", 0xee9001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1623 {"fmle", 0xee980100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1624 {"fmlep", 0xee980120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1625 {"fmlem", 0xee980140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1626 {"fmlez", 0xee980160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1627
1628 {"fdvs", 0xeea00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1629 {"fdvsp", 0xeea00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1630 {"fdvsm", 0xeea00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1631 {"fdvsz", 0xeea00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1632 {"fdvd", 0xeea00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1633 {"fdvdp", 0xeea001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1634 {"fdvdm", 0xeea001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1635 {"fdvdz", 0xeea001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1636 {"fdve", 0xeea80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1637 {"fdvep", 0xeea80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1638 {"fdvem", 0xeea80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1639 {"fdvez", 0xeea80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1640
1641 {"frds", 0xeeb00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1642 {"frdsp", 0xeeb00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1643 {"frdsm", 0xeeb00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1644 {"frdsz", 0xeeb00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1645 {"frdd", 0xeeb00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1646 {"frddp", 0xeeb001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1647 {"frddm", 0xeeb001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1648 {"frddz", 0xeeb001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1649 {"frde", 0xeeb80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1650 {"frdep", 0xeeb80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1651 {"frdem", 0xeeb80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1652 {"frdez", 0xeeb80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1653
1654 {"pols", 0xeec00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1655 {"polsp", 0xeec00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1656 {"polsm", 0xeec00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1657 {"polsz", 0xeec00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1658 {"pold", 0xeec00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1659 {"poldp", 0xeec001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1660 {"poldm", 0xeec001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1661 {"poldz", 0xeec001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1662 {"pole", 0xeec80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1663 {"polep", 0xeec80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1664 {"polem", 0xeec80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1665 {"polez", 0xeec80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1666
1667 {"cmf", 0xee90f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
1668 {"cmfe", 0xeed0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
1669 {"cnf", 0xeeb0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
1670 {"cnfe", 0xeef0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
1671 /* The FPA10 data sheet suggests that the 'E' of cmfe/cnfe should
1672 not be an optional suffix, but part of the instruction. To be
1673 compatible, we accept either. */
1674 {"cmfe", 0xeed0f110, 4, FPU_FPA_EXT_V1, do_fpa_cmp},
1675 {"cnfe", 0xeef0f110, 4, FPU_FPA_EXT_V1, do_fpa_cmp},
1676
1677 {"flts", 0xee000110, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1678 {"fltsp", 0xee000130, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1679 {"fltsm", 0xee000150, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1680 {"fltsz", 0xee000170, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1681 {"fltd", 0xee000190, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1682 {"fltdp", 0xee0001b0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1683 {"fltdm", 0xee0001d0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1684 {"fltdz", 0xee0001f0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1685 {"flte", 0xee080110, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1686 {"fltep", 0xee080130, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1687 {"fltem", 0xee080150, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1688 {"fltez", 0xee080170, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1689
1690 /* The implementation of the FIX instruction is broken on some
1691 assemblers, in that it accepts a precision specifier as well as a
1692 rounding specifier, despite the fact that this is meaningless.
1693 To be more compatible, we accept it as well, though of course it
1694 does not set any bits. */
1695 {"fix", 0xee100110, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1696 {"fixp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1697 {"fixm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1698 {"fixz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1699 {"fixsp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1700 {"fixsm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1701 {"fixsz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1702 {"fixdp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1703 {"fixdm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1704 {"fixdz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1705 {"fixep", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1706 {"fixem", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1707 {"fixez", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1708
1709 /* Instructions that were new with the real FPA, call them V2. */
1710 {"lfm", 0xec100200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1711 {"lfmfd", 0xec900200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1712 {"lfmea", 0xed100200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1713 {"sfm", 0xec000200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1714 {"sfmfd", 0xed000200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1715 {"sfmea", 0xec800200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1716
1717 /* VFP V1xD (single precision). */
1718 /* Moves and type conversions. */
1719 {"fcpys", 0xeeb00a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1720 {"fmrs", 0xee100a10, 4, FPU_VFP_EXT_V1xD, do_vfp_reg_from_sp},
1721 {"fmsr", 0xee000a10, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_from_reg},
1722 {"fmstat", 0xeef1fa10, 6, FPU_VFP_EXT_V1xD, do_empty},
1723 {"fsitos", 0xeeb80ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1724 {"fuitos", 0xeeb80a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1725 {"ftosis", 0xeebd0a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1726 {"ftosizs", 0xeebd0ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1727 {"ftouis", 0xeebc0a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1728 {"ftouizs", 0xeebc0ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1729 {"fmrx", 0xeef00a10, 4, FPU_VFP_EXT_V1xD, do_vfp_reg_from_ctrl},
1730 {"fmxr", 0xeee00a10, 4, FPU_VFP_EXT_V1xD, do_vfp_ctrl_from_reg},
1731
1732 /* Memory operations. */
1733 {"flds", 0xed100a00, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_ldst},
1734 {"fsts", 0xed000a00, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_ldst},
1735 {"fldmias", 0xec900a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
1736 {"fldmfds", 0xec900a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
1737 {"fldmdbs", 0xed300a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
1738 {"fldmeas", 0xed300a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
1739 {"fldmiax", 0xec900b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
1740 {"fldmfdx", 0xec900b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
1741 {"fldmdbx", 0xed300b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
1742 {"fldmeax", 0xed300b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
1743 {"fstmias", 0xec800a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
1744 {"fstmeas", 0xec800a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
1745 {"fstmdbs", 0xed200a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
1746 {"fstmfds", 0xed200a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
1747 {"fstmiax", 0xec800b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
1748 {"fstmeax", 0xec800b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
1749 {"fstmdbx", 0xed200b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
1750 {"fstmfdx", 0xed200b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
1751
1752 /* Monadic operations. */
1753 {"fabss", 0xeeb00ac0, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1754 {"fnegs", 0xeeb10a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1755 {"fsqrts", 0xeeb10ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1756
1757 /* Dyadic operations. */
1758 {"fadds", 0xee300a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1759 {"fsubs", 0xee300a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1760 {"fmuls", 0xee200a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1761 {"fdivs", 0xee800a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1762 {"fmacs", 0xee000a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1763 {"fmscs", 0xee100a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1764 {"fnmuls", 0xee200a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1765 {"fnmacs", 0xee000a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1766 {"fnmscs", 0xee100a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1767
1768 /* Comparisons. */
1769 {"fcmps", 0xeeb40a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1770 {"fcmpzs", 0xeeb50a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_compare_z},
1771 {"fcmpes", 0xeeb40ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1772 {"fcmpezs", 0xeeb50ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_compare_z},
1773
1774 /* VFP V1 (Double precision). */
1775 /* Moves and type conversions. */
1776 {"fcpyd", 0xeeb00b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1777 {"fcvtds", 0xeeb70ac0, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
1778 {"fcvtsd", 0xeeb70bc0, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
1779 {"fmdhr", 0xee200b10, 5, FPU_VFP_EXT_V1, do_vfp_dp_from_reg},
1780 {"fmdlr", 0xee000b10, 5, FPU_VFP_EXT_V1, do_vfp_dp_from_reg},
1781 {"fmrdh", 0xee300b10, 5, FPU_VFP_EXT_V1, do_vfp_reg_from_dp},
1782 {"fmrdl", 0xee100b10, 5, FPU_VFP_EXT_V1, do_vfp_reg_from_dp},
1783 {"fsitod", 0xeeb80bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
1784 {"fuitod", 0xeeb80b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
1785 {"ftosid", 0xeebd0b40, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
1786 {"ftosizd", 0xeebd0bc0, 7, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
1787 {"ftouid", 0xeebc0b40, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
1788 {"ftouizd", 0xeebc0bc0, 7, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
1789
1790 /* Memory operations. */
1791 {"fldd", 0xed100b00, 4, FPU_VFP_EXT_V1, do_vfp_dp_ldst},
1792 {"fstd", 0xed000b00, 4, FPU_VFP_EXT_V1, do_vfp_dp_ldst},
1793 {"fldmiad", 0xec900b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
1794 {"fldmfdd", 0xec900b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
1795 {"fldmdbd", 0xed300b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
1796 {"fldmead", 0xed300b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
1797 {"fstmiad", 0xec800b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
1798 {"fstmead", 0xec800b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
1799 {"fstmdbd", 0xed200b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
1800 {"fstmfdd", 0xed200b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
1801
1802 /* Monadic operations. */
1803 {"fabsd", 0xeeb00bc0, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1804 {"fnegd", 0xeeb10b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1805 {"fsqrtd", 0xeeb10bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1806
1807 /* Dyadic operations. */
1808 {"faddd", 0xee300b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1809 {"fsubd", 0xee300b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1810 {"fmuld", 0xee200b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1811 {"fdivd", 0xee800b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1812 {"fmacd", 0xee000b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1813 {"fmscd", 0xee100b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1814 {"fnmuld", 0xee200b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1815 {"fnmacd", 0xee000b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1816 {"fnmscd", 0xee100b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1817
1818 /* Comparisons. */
1819 {"fcmpd", 0xeeb40b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1820 {"fcmpzd", 0xeeb50b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_compare_z},
1821 {"fcmped", 0xeeb40bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1822 {"fcmpezd", 0xeeb50bc0, 7, FPU_VFP_EXT_V1, do_vfp_dp_compare_z},
1823
1824 /* VFP V2. */
1825 {"fmsrr", 0xec400a10, 5, FPU_VFP_EXT_V2, do_vfp_sp_reg2},
1826 {"fmrrs", 0xec500a10, 5, FPU_VFP_EXT_V2, do_vfp_sp_reg2},
1827 {"fmdrr", 0xec400b10, 5, FPU_VFP_EXT_V2, do_vfp_dp_from_reg2},
1828 {"fmrrd", 0xec500b10, 5, FPU_VFP_EXT_V2, do_vfp_reg2_from_dp},
1829
1830 /* Intel XScale extensions to ARM V5 ISA. (All use CP0). */
1831 {"mia", 0xee200010, 3, ARM_CEXT_XSCALE, do_xsc_mia},
1832 {"miaph", 0xee280010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
1833 {"miabb", 0xee2c0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
1834 {"miabt", 0xee2d0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
1835 {"miatb", 0xee2e0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
1836 {"miatt", 0xee2f0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
1837 {"mar", 0xec400000, 3, ARM_CEXT_XSCALE, do_xsc_mar},
1838 {"mra", 0xec500000, 3, ARM_CEXT_XSCALE, do_xsc_mra},
1839
1840 /* Intel Wireless MMX technology instructions. */
1841 {"tandcb", 0xee130130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
1842 {"tandch", 0xee530130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
1843 {"tandcw", 0xee930130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
1844 {"tbcstb", 0xee400010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
1845 {"tbcsth", 0xee400050, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
1846 {"tbcstw", 0xee400090, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
1847 {"textrcb", 0xee130170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
1848 {"textrch", 0xee530170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
1849 {"textrcw", 0xee930170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
1850 {"textrmub", 0xee100070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
1851 {"textrmuh", 0xee500070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
1852 {"textrmuw", 0xee900070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
1853 {"textrmsb", 0xee100078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
1854 {"textrmsh", 0xee500078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
1855 {"textrmsw", 0xee900078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
1856 {"tinsrb", 0xee600010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
1857 {"tinsrh", 0xee600050, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
1858 {"tinsrw", 0xee600090, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
1859 {"tmcr", 0xee000110, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmcr},
1860 {"tmcrr", 0xec400000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_tmcrr},
1861 {"tmia", 0xee200010, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
1862 {"tmiaph", 0xee280010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
1863 {"tmiabb", 0xee2c0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
1864 {"tmiabt", 0xee2d0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
1865 {"tmiatb", 0xee2e0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
1866 {"tmiatt", 0xee2f0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
1867 {"tmovmskb", 0xee100030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
1868 {"tmovmskh", 0xee500030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
1869 {"tmovmskw", 0xee900030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
1870 {"tmrc", 0xee100110, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmrc},
1871 {"tmrrc", 0xec500000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_tmrrc},
1872 {"torcb", 0xee130150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
1873 {"torch", 0xee530150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
1874 {"torcw", 0xee930150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
1875 {"waccb", 0xee0001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
1876 {"wacch", 0xee4001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
1877 {"waccw", 0xee8001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
1878 {"waddbss", 0xee300180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1879 {"waddb", 0xee000180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1880 {"waddbus", 0xee100180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1881 {"waddhss", 0xee700180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1882 {"waddh", 0xee400180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1883 {"waddhus", 0xee500180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1884 {"waddwss", 0xeeb00180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1885 {"waddw", 0xee800180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1886 {"waddwus", 0xee900180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1887 {"waligni", 0xee000020, 7, ARM_CEXT_IWMMXT, do_iwmmxt_waligni},
1888 {"walignr0", 0xee800020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1889 {"walignr1", 0xee900020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1890 {"walignr2", 0xeea00020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1891 {"walignr3", 0xeeb00020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1892 {"wand", 0xee200000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1893 {"wandn", 0xee300000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1894 {"wavg2b", 0xee800000, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1895 {"wavg2br", 0xee900000, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1896 {"wavg2h", 0xeec00000, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1897 {"wavg2hr", 0xeed00000, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1898 {"wcmpeqb", 0xee000060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1899 {"wcmpeqh", 0xee400060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1900 {"wcmpeqw", 0xee800060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1901 {"wcmpgtub", 0xee100060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1902 {"wcmpgtuh", 0xee500060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1903 {"wcmpgtuw", 0xee900060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1904 {"wcmpgtsb", 0xee300060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1905 {"wcmpgtsh", 0xee700060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1906 {"wcmpgtsw", 0xeeb00060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1907 {"wldrb", 0xec100000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
1908 {"wldrh", 0xec100100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
1909 {"wldrw", 0xec100200, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
1910 {"wldrd", 0xec100300, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
1911 {"wmacs", 0xee600100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1912 {"wmacsz", 0xee700100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1913 {"wmacu", 0xee400100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1914 {"wmacuz", 0xee500100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1915 {"wmadds", 0xeea00100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1916 {"wmaddu", 0xee800100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1917 {"wmaxsb", 0xee200160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1918 {"wmaxsh", 0xee600160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1919 {"wmaxsw", 0xeea00160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1920 {"wmaxub", 0xee000160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1921 {"wmaxuh", 0xee400160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1922 {"wmaxuw", 0xee800160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1923 {"wminsb", 0xee300160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1924 {"wminsh", 0xee700160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1925 {"wminsw", 0xeeb00160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1926 {"wminub", 0xee100160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1927 {"wminuh", 0xee500160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1928 {"wminuw", 0xee900160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1929 {"wmov", 0xee000000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wmov},
1930 {"wmulsm", 0xee300100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1931 {"wmulsl", 0xee200100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1932 {"wmulum", 0xee100100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1933 {"wmulul", 0xee000100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1934 {"wor", 0xee000000, 3, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1935 {"wpackhss", 0xee700080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1936 {"wpackhus", 0xee500080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1937 {"wpackwss", 0xeeb00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1938 {"wpackwus", 0xee900080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1939 {"wpackdss", 0xeef00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1940 {"wpackdus", 0xeed00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1941 {"wrorh", 0xee700040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1942 {"wrorhg", 0xee700148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
1943 {"wrorw", 0xeeb00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1944 {"wrorwg", 0xeeb00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
1945 {"wrord", 0xeef00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1946 {"wrordg", 0xeef00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
1947 {"wsadb", 0xee000120, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1948 {"wsadbz", 0xee100120, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1949 {"wsadh", 0xee400120, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1950 {"wsadhz", 0xee500120, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1951 {"wshufh", 0xee0001e0, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wshufh},
1952 {"wsllh", 0xee500040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1953 {"wsllhg", 0xee500148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
1954 {"wsllw", 0xee900040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1955 {"wsllwg", 0xee900148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
1956 {"wslld", 0xeed00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1957 {"wslldg", 0xeed00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
1958 {"wsrah", 0xee400040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1959 {"wsrahg", 0xee400148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
1960 {"wsraw", 0xee800040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1961 {"wsrawg", 0xee800148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
1962 {"wsrad", 0xeec00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1963 {"wsradg", 0xeec00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
1964 {"wsrlh", 0xee600040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1965 {"wsrlhg", 0xee600148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
1966 {"wsrlw", 0xeea00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1967 {"wsrlwg", 0xeea00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
1968 {"wsrld", 0xeee00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1969 {"wsrldg", 0xeee00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
1970 {"wstrb", 0xec000000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
1971 {"wstrh", 0xec000100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
1972 {"wstrw", 0xec000200, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
1973 {"wstrd", 0xec000300, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
1974 {"wsubbss", 0xee3001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1975 {"wsubb", 0xee0001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1976 {"wsubbus", 0xee1001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1977 {"wsubhss", 0xee7001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1978 {"wsubh", 0xee4001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1979 {"wsubhus", 0xee5001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1980 {"wsubwss", 0xeeb001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1981 {"wsubw", 0xee8001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1982 {"wsubwus", 0xee9001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1983 {"wunpckehub", 0xee0000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
1984 {"wunpckehuh", 0xee4000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
1985 {"wunpckehuw", 0xee8000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
1986 {"wunpckehsb", 0xee2000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
1987 {"wunpckehsh", 0xee6000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
1988 {"wunpckehsw", 0xeea000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
1989 {"wunpckihb", 0xee1000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1990 {"wunpckihh", 0xee5000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1991 {"wunpckihw", 0xee9000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1992 {"wunpckelub", 0xee0000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
1993 {"wunpckeluh", 0xee4000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
1994 {"wunpckeluw", 0xee8000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
1995 {"wunpckelsb", 0xee2000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
1996 {"wunpckelsh", 0xee6000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
1997 {"wunpckelsw", 0xeea000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
1998 {"wunpckilb", 0xee1000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1999 {"wunpckilh", 0xee5000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2000 {"wunpckilw", 0xee9000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2001 {"wxor", 0xee100000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2002 {"wzero", 0xee300000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wzero},
2003
2004 /* Cirrus Maverick instructions. */
2005 {"cfldrs", 0xec100400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_1},
2006 {"cfldrd", 0xec500400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_2},
2007 {"cfldr32", 0xec100500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_3},
2008 {"cfldr64", 0xec500500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_4},
2009 {"cfstrs", 0xec000400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_1},
2010 {"cfstrd", 0xec400400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_2},
2011 {"cfstr32", 0xec000500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_3},
2012 {"cfstr64", 0xec400500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_4},
2013 {"cfmvsr", 0xee000450, 6, ARM_CEXT_MAVERICK, do_mav_binops_2a},
2014 {"cfmvrs", 0xee100450, 6, ARM_CEXT_MAVERICK, do_mav_binops_1a},
2015 {"cfmvdlr", 0xee000410, 7, ARM_CEXT_MAVERICK, do_mav_binops_2b},
2016 {"cfmvrdl", 0xee100410, 7, ARM_CEXT_MAVERICK, do_mav_binops_1b},
2017 {"cfmvdhr", 0xee000430, 7, ARM_CEXT_MAVERICK, do_mav_binops_2b},
2018 {"cfmvrdh", 0xee100430, 7, ARM_CEXT_MAVERICK, do_mav_binops_1b},
2019 {"cfmv64lr", 0xee000510, 8, ARM_CEXT_MAVERICK, do_mav_binops_2c},
2020 {"cfmvr64l", 0xee100510, 8, ARM_CEXT_MAVERICK, do_mav_binops_1c},
2021 {"cfmv64hr", 0xee000530, 8, ARM_CEXT_MAVERICK, do_mav_binops_2c},
2022 {"cfmvr64h", 0xee100530, 8, ARM_CEXT_MAVERICK, do_mav_binops_1c},
2023 {"cfmval32", 0xee100610, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
2024 {"cfmv32al", 0xee000610, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
2025 {"cfmvam32", 0xee100630, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
2026 {"cfmv32am", 0xee000630, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
2027 {"cfmvah32", 0xee100650, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
2028 {"cfmv32ah", 0xee000650, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
2029 {"cfmva32", 0xee100670, 7, ARM_CEXT_MAVERICK, do_mav_binops_3a},
2030 {"cfmv32a", 0xee000670, 7, ARM_CEXT_MAVERICK, do_mav_binops_3b},
2031 {"cfmva64", 0xee100690, 7, ARM_CEXT_MAVERICK, do_mav_binops_3c},
2032 {"cfmv64a", 0xee000690, 7, ARM_CEXT_MAVERICK, do_mav_binops_3d},
2033 {"cfmvsc32", 0xee1006b0, 8, ARM_CEXT_MAVERICK, do_mav_dspsc_1},
2034 {"cfmv32sc", 0xee0006b0, 8, ARM_CEXT_MAVERICK, do_mav_dspsc_2},
2035 {"cfcpys", 0xee000400, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
2036 {"cfcpyd", 0xee000420, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
2037 {"cfcvtsd", 0xee000460, 7, ARM_CEXT_MAVERICK, do_mav_binops_1f},
2038 {"cfcvtds", 0xee000440, 7, ARM_CEXT_MAVERICK, do_mav_binops_1g},
2039 {"cfcvt32s", 0xee000480, 8, ARM_CEXT_MAVERICK, do_mav_binops_1h},
2040 {"cfcvt32d", 0xee0004a0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1i},
2041 {"cfcvt64s", 0xee0004c0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1j},
2042 {"cfcvt64d", 0xee0004e0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1k},
2043 {"cfcvts32", 0xee100580, 8, ARM_CEXT_MAVERICK, do_mav_binops_1l},
2044 {"cfcvtd32", 0xee1005a0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1m},
2045 {"cftruncs32", 0xee1005c0, 10, ARM_CEXT_MAVERICK, do_mav_binops_1l},
2046 {"cftruncd32", 0xee1005e0, 10, ARM_CEXT_MAVERICK, do_mav_binops_1m},
2047 {"cfrshl32", 0xee000550, 8, ARM_CEXT_MAVERICK, do_mav_triple_4a},
2048 {"cfrshl64", 0xee000570, 8, ARM_CEXT_MAVERICK, do_mav_triple_4b},
2049 {"cfsh32", 0xee000500, 6, ARM_CEXT_MAVERICK, do_mav_shift_1},
2050 {"cfsh64", 0xee200500, 6, ARM_CEXT_MAVERICK, do_mav_shift_2},
2051 {"cfcmps", 0xee100490, 6, ARM_CEXT_MAVERICK, do_mav_triple_5a},
2052 {"cfcmpd", 0xee1004b0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5b},
2053 {"cfcmp32", 0xee100590, 7, ARM_CEXT_MAVERICK, do_mav_triple_5c},
2054 {"cfcmp64", 0xee1005b0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5d},
2055 {"cfabss", 0xee300400, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
2056 {"cfabsd", 0xee300420, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
2057 {"cfnegs", 0xee300440, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
2058 {"cfnegd", 0xee300460, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
2059 {"cfadds", 0xee300480, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
2060 {"cfaddd", 0xee3004a0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
2061 {"cfsubs", 0xee3004c0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
2062 {"cfsubd", 0xee3004e0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
2063 {"cfmuls", 0xee100400, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
2064 {"cfmuld", 0xee100420, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
2065 {"cfabs32", 0xee300500, 7, ARM_CEXT_MAVERICK, do_mav_binops_1n},
2066 {"cfabs64", 0xee300520, 7, ARM_CEXT_MAVERICK, do_mav_binops_1o},
2067 {"cfneg32", 0xee300540, 7, ARM_CEXT_MAVERICK, do_mav_binops_1n},
2068 {"cfneg64", 0xee300560, 7, ARM_CEXT_MAVERICK, do_mav_binops_1o},
2069 {"cfadd32", 0xee300580, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
2070 {"cfadd64", 0xee3005a0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
2071 {"cfsub32", 0xee3005c0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
2072 {"cfsub64", 0xee3005e0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
2073 {"cfmul32", 0xee100500, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
2074 {"cfmul64", 0xee100520, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
2075 {"cfmac32", 0xee100540, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
2076 {"cfmsc32", 0xee100560, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
2077 {"cfmadd32", 0xee000600, 8, ARM_CEXT_MAVERICK, do_mav_quad_6a},
2078 {"cfmsub32", 0xee100600, 8, ARM_CEXT_MAVERICK, do_mav_quad_6a},
2079 {"cfmadda32", 0xee200600, 9, ARM_CEXT_MAVERICK, do_mav_quad_6b},
2080 {"cfmsuba32", 0xee300600, 9, ARM_CEXT_MAVERICK, do_mav_quad_6b},
2081 };
2082
2083 /* Defines for various bits that we will want to toggle. */
2084 #define INST_IMMEDIATE 0x02000000
2085 #define OFFSET_REG 0x02000000
2086 #define HWOFFSET_IMM 0x00400000
2087 #define SHIFT_BY_REG 0x00000010
2088 #define PRE_INDEX 0x01000000
2089 #define INDEX_UP 0x00800000
2090 #define WRITE_BACK 0x00200000
2091 #define LDM_TYPE_2_OR_3 0x00400000
2092
2093 #define LITERAL_MASK 0xf000f000
2094 #define OPCODE_MASK 0xfe1fffff
2095 #define V4_STR_BIT 0x00000020
2096
2097 #define DATA_OP_SHIFT 21
2098
2099 /* Codes to distinguish the arithmetic instructions. */
2100 #define OPCODE_AND 0
2101 #define OPCODE_EOR 1
2102 #define OPCODE_SUB 2
2103 #define OPCODE_RSB 3
2104 #define OPCODE_ADD 4
2105 #define OPCODE_ADC 5
2106 #define OPCODE_SBC 6
2107 #define OPCODE_RSC 7
2108 #define OPCODE_TST 8
2109 #define OPCODE_TEQ 9
2110 #define OPCODE_CMP 10
2111 #define OPCODE_CMN 11
2112 #define OPCODE_ORR 12
2113 #define OPCODE_MOV 13
2114 #define OPCODE_BIC 14
2115 #define OPCODE_MVN 15
2116
2117 /* Thumb v1 (ARMv4T). */
2118 static void do_t_nop PARAMS ((char *));
2119 static void do_t_arit PARAMS ((char *));
2120 static void do_t_add PARAMS ((char *));
2121 static void do_t_asr PARAMS ((char *));
2122 static void do_t_branch9 PARAMS ((char *));
2123 static void do_t_branch12 PARAMS ((char *));
2124 static void do_t_branch23 PARAMS ((char *));
2125 static void do_t_bx PARAMS ((char *));
2126 static void do_t_compare PARAMS ((char *));
2127 static void do_t_ldmstm PARAMS ((char *));
2128 static void do_t_ldr PARAMS ((char *));
2129 static void do_t_ldrb PARAMS ((char *));
2130 static void do_t_ldrh PARAMS ((char *));
2131 static void do_t_lds PARAMS ((char *));
2132 static void do_t_lsl PARAMS ((char *));
2133 static void do_t_lsr PARAMS ((char *));
2134 static void do_t_mov PARAMS ((char *));
2135 static void do_t_push_pop PARAMS ((char *));
2136 static void do_t_str PARAMS ((char *));
2137 static void do_t_strb PARAMS ((char *));
2138 static void do_t_strh PARAMS ((char *));
2139 static void do_t_sub PARAMS ((char *));
2140 static void do_t_swi PARAMS ((char *));
2141 static void do_t_adr PARAMS ((char *));
2142
2143 /* Thumb v2 (ARMv5T). */
2144 static void do_t_blx PARAMS ((char *));
2145 static void do_t_bkpt PARAMS ((char *));
2146
2147 #define T_OPCODE_MUL 0x4340
2148 #define T_OPCODE_TST 0x4200
2149 #define T_OPCODE_CMN 0x42c0
2150 #define T_OPCODE_NEG 0x4240
2151 #define T_OPCODE_MVN 0x43c0
2152
2153 #define T_OPCODE_ADD_R3 0x1800
2154 #define T_OPCODE_SUB_R3 0x1a00
2155 #define T_OPCODE_ADD_HI 0x4400
2156 #define T_OPCODE_ADD_ST 0xb000
2157 #define T_OPCODE_SUB_ST 0xb080
2158 #define T_OPCODE_ADD_SP 0xa800
2159 #define T_OPCODE_ADD_PC 0xa000
2160 #define T_OPCODE_ADD_I8 0x3000
2161 #define T_OPCODE_SUB_I8 0x3800
2162 #define T_OPCODE_ADD_I3 0x1c00
2163 #define T_OPCODE_SUB_I3 0x1e00
2164
2165 #define T_OPCODE_ASR_R 0x4100
2166 #define T_OPCODE_LSL_R 0x4080
2167 #define T_OPCODE_LSR_R 0x40c0
2168 #define T_OPCODE_ASR_I 0x1000
2169 #define T_OPCODE_LSL_I 0x0000
2170 #define T_OPCODE_LSR_I 0x0800
2171
2172 #define T_OPCODE_MOV_I8 0x2000
2173 #define T_OPCODE_CMP_I8 0x2800
2174 #define T_OPCODE_CMP_LR 0x4280
2175 #define T_OPCODE_MOV_HR 0x4600
2176 #define T_OPCODE_CMP_HR 0x4500
2177
2178 #define T_OPCODE_LDR_PC 0x4800
2179 #define T_OPCODE_LDR_SP 0x9800
2180 #define T_OPCODE_STR_SP 0x9000
2181 #define T_OPCODE_LDR_IW 0x6800
2182 #define T_OPCODE_STR_IW 0x6000
2183 #define T_OPCODE_LDR_IH 0x8800
2184 #define T_OPCODE_STR_IH 0x8000
2185 #define T_OPCODE_LDR_IB 0x7800
2186 #define T_OPCODE_STR_IB 0x7000
2187 #define T_OPCODE_LDR_RW 0x5800
2188 #define T_OPCODE_STR_RW 0x5000
2189 #define T_OPCODE_LDR_RH 0x5a00
2190 #define T_OPCODE_STR_RH 0x5200
2191 #define T_OPCODE_LDR_RB 0x5c00
2192 #define T_OPCODE_STR_RB 0x5400
2193
2194 #define T_OPCODE_PUSH 0xb400
2195 #define T_OPCODE_POP 0xbc00
2196
2197 #define T_OPCODE_BRANCH 0xe7fe
2198
2199 static int thumb_reg PARAMS ((char ** str, int hi_lo));
2200
2201 #define THUMB_SIZE 2 /* Size of thumb instruction. */
2202 #define THUMB_REG_LO 0x1
2203 #define THUMB_REG_HI 0x2
2204 #define THUMB_REG_ANY 0x3
2205
2206 #define THUMB_H1 0x0080
2207 #define THUMB_H2 0x0040
2208
2209 #define THUMB_ASR 0
2210 #define THUMB_LSL 1
2211 #define THUMB_LSR 2
2212
2213 #define THUMB_MOVE 0
2214 #define THUMB_COMPARE 1
2215
2216 #define THUMB_LOAD 0
2217 #define THUMB_STORE 1
2218
2219 #define THUMB_PP_PC_LR 0x0100
2220
2221 /* These three are used for immediate shifts, do not alter. */
2222 #define THUMB_WORD 2
2223 #define THUMB_HALFWORD 1
2224 #define THUMB_BYTE 0
2225
2226 struct thumb_opcode
2227 {
2228 /* Basic string to match. */
2229 const char * template;
2230
2231 /* Basic instruction code. */
2232 unsigned long value;
2233
2234 int size;
2235
2236 /* Which CPU variants this exists for. */
2237 unsigned long variant;
2238
2239 /* Function to call to parse args. */
2240 void (* parms) PARAMS ((char *));
2241 };
2242
2243 static const struct thumb_opcode tinsns[] =
2244 {
2245 /* Thumb v1 (ARMv4T). */
2246 {"adc", 0x4140, 2, ARM_EXT_V4T, do_t_arit},
2247 {"add", 0x0000, 2, ARM_EXT_V4T, do_t_add},
2248 {"and", 0x4000, 2, ARM_EXT_V4T, do_t_arit},
2249 {"asr", 0x0000, 2, ARM_EXT_V4T, do_t_asr},
2250 {"b", T_OPCODE_BRANCH, 2, ARM_EXT_V4T, do_t_branch12},
2251 {"beq", 0xd0fe, 2, ARM_EXT_V4T, do_t_branch9},
2252 {"bne", 0xd1fe, 2, ARM_EXT_V4T, do_t_branch9},
2253 {"bcs", 0xd2fe, 2, ARM_EXT_V4T, do_t_branch9},
2254 {"bhs", 0xd2fe, 2, ARM_EXT_V4T, do_t_branch9},
2255 {"bcc", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
2256 {"bul", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
2257 {"blo", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
2258 {"bmi", 0xd4fe, 2, ARM_EXT_V4T, do_t_branch9},
2259 {"bpl", 0xd5fe, 2, ARM_EXT_V4T, do_t_branch9},
2260 {"bvs", 0xd6fe, 2, ARM_EXT_V4T, do_t_branch9},
2261 {"bvc", 0xd7fe, 2, ARM_EXT_V4T, do_t_branch9},
2262 {"bhi", 0xd8fe, 2, ARM_EXT_V4T, do_t_branch9},
2263 {"bls", 0xd9fe, 2, ARM_EXT_V4T, do_t_branch9},
2264 {"bge", 0xdafe, 2, ARM_EXT_V4T, do_t_branch9},
2265 {"blt", 0xdbfe, 2, ARM_EXT_V4T, do_t_branch9},
2266 {"bgt", 0xdcfe, 2, ARM_EXT_V4T, do_t_branch9},
2267 {"ble", 0xddfe, 2, ARM_EXT_V4T, do_t_branch9},
2268 {"bal", 0xdefe, 2, ARM_EXT_V4T, do_t_branch9},
2269 {"bic", 0x4380, 2, ARM_EXT_V4T, do_t_arit},
2270 {"bl", 0xf7fffffe, 4, ARM_EXT_V4T, do_t_branch23},
2271 {"bx", 0x4700, 2, ARM_EXT_V4T, do_t_bx},
2272 {"cmn", T_OPCODE_CMN, 2, ARM_EXT_V4T, do_t_arit},
2273 {"cmp", 0x0000, 2, ARM_EXT_V4T, do_t_compare},
2274 {"eor", 0x4040, 2, ARM_EXT_V4T, do_t_arit},
2275 {"ldmia", 0xc800, 2, ARM_EXT_V4T, do_t_ldmstm},
2276 {"ldr", 0x0000, 2, ARM_EXT_V4T, do_t_ldr},
2277 {"ldrb", 0x0000, 2, ARM_EXT_V4T, do_t_ldrb},
2278 {"ldrh", 0x0000, 2, ARM_EXT_V4T, do_t_ldrh},
2279 {"ldrsb", 0x5600, 2, ARM_EXT_V4T, do_t_lds},
2280 {"ldrsh", 0x5e00, 2, ARM_EXT_V4T, do_t_lds},
2281 {"ldsb", 0x5600, 2, ARM_EXT_V4T, do_t_lds},
2282 {"ldsh", 0x5e00, 2, ARM_EXT_V4T, do_t_lds},
2283 {"lsl", 0x0000, 2, ARM_EXT_V4T, do_t_lsl},
2284 {"lsr", 0x0000, 2, ARM_EXT_V4T, do_t_lsr},
2285 {"mov", 0x0000, 2, ARM_EXT_V4T, do_t_mov},
2286 {"mul", T_OPCODE_MUL, 2, ARM_EXT_V4T, do_t_arit},
2287 {"mvn", T_OPCODE_MVN, 2, ARM_EXT_V4T, do_t_arit},
2288 {"neg", T_OPCODE_NEG, 2, ARM_EXT_V4T, do_t_arit},
2289 {"orr", 0x4300, 2, ARM_EXT_V4T, do_t_arit},
2290 {"pop", 0xbc00, 2, ARM_EXT_V4T, do_t_push_pop},
2291 {"push", 0xb400, 2, ARM_EXT_V4T, do_t_push_pop},
2292 {"ror", 0x41c0, 2, ARM_EXT_V4T, do_t_arit},
2293 {"sbc", 0x4180, 2, ARM_EXT_V4T, do_t_arit},
2294 {"stmia", 0xc000, 2, ARM_EXT_V4T, do_t_ldmstm},
2295 {"str", 0x0000, 2, ARM_EXT_V4T, do_t_str},
2296 {"strb", 0x0000, 2, ARM_EXT_V4T, do_t_strb},
2297 {"strh", 0x0000, 2, ARM_EXT_V4T, do_t_strh},
2298 {"swi", 0xdf00, 2, ARM_EXT_V4T, do_t_swi},
2299 {"sub", 0x0000, 2, ARM_EXT_V4T, do_t_sub},
2300 {"tst", T_OPCODE_TST, 2, ARM_EXT_V4T, do_t_arit},
2301 /* Pseudo ops: */
2302 {"adr", 0x0000, 2, ARM_EXT_V4T, do_t_adr},
2303 {"nop", 0x46C0, 2, ARM_EXT_V4T, do_t_nop}, /* mov r8,r8 */
2304 /* Thumb v2 (ARMv5T). */
2305 {"blx", 0, 0, ARM_EXT_V5T, do_t_blx},
2306 {"bkpt", 0xbe00, 2, ARM_EXT_V5T, do_t_bkpt},
2307 };
2308
2309 #define BAD_ARGS _("bad arguments to instruction")
2310 #define BAD_PC _("r15 not allowed here")
2311 #define BAD_COND _("instruction is not conditional")
2312 #define ERR_NO_ACCUM _("acc0 expected")
2313
2314 static struct hash_control * arm_ops_hsh = NULL;
2315 static struct hash_control * arm_tops_hsh = NULL;
2316 static struct hash_control * arm_cond_hsh = NULL;
2317 static struct hash_control * arm_shift_hsh = NULL;
2318 static struct hash_control * arm_psr_hsh = NULL;
2319
2320 /* This table describes all the machine specific pseudo-ops the assembler
2321 has to support. The fields are:
2322 pseudo-op name without dot
2323 function to call to execute this pseudo-op
2324 Integer arg to pass to the function. */
2325
2326 static void s_req PARAMS ((int));
2327 static void s_align PARAMS ((int));
2328 static void s_bss PARAMS ((int));
2329 static void s_even PARAMS ((int));
2330 static void s_ltorg PARAMS ((int));
2331 static void s_arm PARAMS ((int));
2332 static void s_thumb PARAMS ((int));
2333 static void s_code PARAMS ((int));
2334 static void s_force_thumb PARAMS ((int));
2335 static void s_thumb_func PARAMS ((int));
2336 static void s_thumb_set PARAMS ((int));
2337 #ifdef OBJ_ELF
2338 static void s_arm_elf_cons PARAMS ((int));
2339 #endif
2340
2341 static int my_get_expression PARAMS ((expressionS *, char **));
2342
2343 const pseudo_typeS md_pseudo_table[] =
2344 {
2345 /* Never called becasue '.req' does not start line. */
2346 { "req", s_req, 0 },
2347 { "bss", s_bss, 0 },
2348 { "align", s_align, 0 },
2349 { "arm", s_arm, 0 },
2350 { "thumb", s_thumb, 0 },
2351 { "code", s_code, 0 },
2352 { "force_thumb", s_force_thumb, 0 },
2353 { "thumb_func", s_thumb_func, 0 },
2354 { "thumb_set", s_thumb_set, 0 },
2355 { "even", s_even, 0 },
2356 { "ltorg", s_ltorg, 0 },
2357 { "pool", s_ltorg, 0 },
2358 #ifdef OBJ_ELF
2359 { "word", s_arm_elf_cons, 4 },
2360 { "long", s_arm_elf_cons, 4 },
2361 #else
2362 { "word", cons, 4},
2363 #endif
2364 { "extend", float_cons, 'x' },
2365 { "ldouble", float_cons, 'x' },
2366 { "packed", float_cons, 'p' },
2367 { 0, 0, 0 }
2368 };
2369
2370 /* Other internal functions. */
2371 static int arm_parse_extension PARAMS ((char *, int *));
2372 static int arm_parse_cpu PARAMS ((char *));
2373 static int arm_parse_arch PARAMS ((char *));
2374 static int arm_parse_fpu PARAMS ((char *));
2375 #if defined OBJ_COFF || defined OBJ_ELF
2376 static void arm_add_note PARAMS ((const char *, const char *, unsigned int));
2377 #endif
2378
2379 /* Stuff needed to resolve the label ambiguity
2380 As:
2381 ...
2382 label: <insn>
2383 may differ from:
2384 ...
2385 label:
2386 <insn>
2387 */
2388
2389 symbolS * last_label_seen;
2390 static int label_is_thumb_function_name = FALSE;
2391
2392 /* Literal Pool stuff. */
2393
2394 #define MAX_LITERAL_POOL_SIZE 1024
2395
2396 /* Literal pool structure. Held on a per-section
2397 and per-sub-section basis. */
2398 typedef struct literal_pool
2399 {
2400 expressionS literals [MAX_LITERAL_POOL_SIZE];
2401 unsigned int next_free_entry;
2402 unsigned int id;
2403 symbolS * symbol;
2404 segT section;
2405 subsegT sub_section;
2406 struct literal_pool * next;
2407 } literal_pool;
2408
2409 /* Pointer to a linked list of literal pools. */
2410 literal_pool * list_of_pools = NULL;
2411
2412 static literal_pool * find_literal_pool PARAMS ((void));
2413 static literal_pool * find_or_make_literal_pool PARAMS ((void));
2414
2415 static literal_pool *
2416 find_literal_pool ()
2417 {
2418 literal_pool * pool;
2419
2420 for (pool = list_of_pools; pool != NULL; pool = pool->next)
2421 {
2422 if (pool->section == now_seg
2423 && pool->sub_section == now_subseg)
2424 break;
2425 }
2426
2427 return pool;
2428 }
2429
2430 static literal_pool *
2431 find_or_make_literal_pool ()
2432 {
2433 /* Next literal pool ID number. */
2434 static unsigned int latest_pool_num = 1;
2435 literal_pool * pool;
2436
2437 pool = find_literal_pool ();
2438
2439 if (pool == NULL)
2440 {
2441 /* Create a new pool. */
2442 pool = (literal_pool *) xmalloc (sizeof (* pool));
2443 if (! pool)
2444 return NULL;
2445
2446 pool->next_free_entry = 0;
2447 pool->section = now_seg;
2448 pool->sub_section = now_subseg;
2449 pool->next = list_of_pools;
2450 pool->symbol = NULL;
2451
2452 /* Add it to the list. */
2453 list_of_pools = pool;
2454 }
2455
2456 /* New pools, and emptied pools, will have a NULL symbol. */
2457 if (pool->symbol == NULL)
2458 {
2459 pool->symbol = symbol_create (FAKE_LABEL_NAME, undefined_section,
2460 (valueT) 0, &zero_address_frag);
2461 pool->id = latest_pool_num ++;
2462 }
2463
2464 /* Done. */
2465 return pool;
2466 }
2467
2468 /* Add the literal in the global 'inst'
2469 structure to the relevent literal pool. */
2470 static int
2471 add_to_lit_pool ()
2472 {
2473 literal_pool * pool;
2474 unsigned int entry;
2475
2476 pool = find_or_make_literal_pool ();
2477
2478 /* Check if this literal value is already in the pool. */
2479 for (entry = 0; entry < pool->next_free_entry; entry ++)
2480 {
2481 if ((pool->literals[entry].X_op == inst.reloc.exp.X_op)
2482 && (inst.reloc.exp.X_op == O_constant)
2483 && (pool->literals[entry].X_add_number
2484 == inst.reloc.exp.X_add_number)
2485 && (pool->literals[entry].X_unsigned
2486 == inst.reloc.exp.X_unsigned))
2487 break;
2488
2489 if ((pool->literals[entry].X_op == inst.reloc.exp.X_op)
2490 && (inst.reloc.exp.X_op == O_symbol)
2491 && (pool->literals[entry].X_add_number
2492 == inst.reloc.exp.X_add_number)
2493 && (pool->literals[entry].X_add_symbol
2494 == inst.reloc.exp.X_add_symbol)
2495 && (pool->literals[entry].X_op_symbol
2496 == inst.reloc.exp.X_op_symbol))
2497 break;
2498 }
2499
2500 /* Do we need to create a new entry? */
2501 if (entry == pool->next_free_entry)
2502 {
2503 if (entry >= MAX_LITERAL_POOL_SIZE)
2504 {
2505 inst.error = _("literal pool overflow");
2506 return FAIL;
2507 }
2508
2509 pool->literals[entry] = inst.reloc.exp;
2510 pool->next_free_entry += 1;
2511 }
2512
2513 inst.reloc.exp.X_op = O_symbol;
2514 inst.reloc.exp.X_add_number = ((int) entry) * 4 - 8;
2515 inst.reloc.exp.X_add_symbol = pool->symbol;
2516
2517 return SUCCESS;
2518 }
2519
2520 /* Can't use symbol_new here, so have to create a symbol and then at
2521 a later date assign it a value. Thats what these functions do. */
2522
2523 static void
2524 symbol_locate (symbolP, name, segment, valu, frag)
2525 symbolS * symbolP;
2526 const char * name; /* It is copied, the caller can modify. */
2527 segT segment; /* Segment identifier (SEG_<something>). */
2528 valueT valu; /* Symbol value. */
2529 fragS * frag; /* Associated fragment. */
2530 {
2531 unsigned int name_length;
2532 char * preserved_copy_of_name;
2533
2534 name_length = strlen (name) + 1; /* +1 for \0. */
2535 obstack_grow (&notes, name, name_length);
2536 preserved_copy_of_name = obstack_finish (&notes);
2537 #ifdef STRIP_UNDERSCORE
2538 if (preserved_copy_of_name[0] == '_')
2539 preserved_copy_of_name++;
2540 #endif
2541
2542 #ifdef tc_canonicalize_symbol_name
2543 preserved_copy_of_name =
2544 tc_canonicalize_symbol_name (preserved_copy_of_name);
2545 #endif
2546
2547 S_SET_NAME (symbolP, preserved_copy_of_name);
2548
2549 S_SET_SEGMENT (symbolP, segment);
2550 S_SET_VALUE (symbolP, valu);
2551 symbol_clear_list_pointers (symbolP);
2552
2553 symbol_set_frag (symbolP, frag);
2554
2555 /* Link to end of symbol chain. */
2556 {
2557 extern int symbol_table_frozen;
2558 if (symbol_table_frozen)
2559 abort ();
2560 }
2561
2562 symbol_append (symbolP, symbol_lastP, & symbol_rootP, & symbol_lastP);
2563
2564 obj_symbol_new_hook (symbolP);
2565
2566 #ifdef tc_symbol_new_hook
2567 tc_symbol_new_hook (symbolP);
2568 #endif
2569
2570 #ifdef DEBUG_SYMS
2571 verify_symbol_chain (symbol_rootP, symbol_lastP);
2572 #endif /* DEBUG_SYMS */
2573 }
2574
2575 /* Check that an immediate is valid.
2576 If so, convert it to the right format. */
2577
2578 static unsigned int
2579 validate_immediate (val)
2580 unsigned int val;
2581 {
2582 unsigned int a;
2583 unsigned int i;
2584
2585 #define rotate_left(v, n) (v << n | v >> (32 - n))
2586
2587 for (i = 0; i < 32; i += 2)
2588 if ((a = rotate_left (val, i)) <= 0xff)
2589 return a | (i << 7); /* 12-bit pack: [shift-cnt,const]. */
2590
2591 return FAIL;
2592 }
2593
2594 /* Check to see if an immediate can be computed as two seperate immediate
2595 values, added together. We already know that this value cannot be
2596 computed by just one ARM instruction. */
2597
2598 static unsigned int
2599 validate_immediate_twopart (val, highpart)
2600 unsigned int val;
2601 unsigned int * highpart;
2602 {
2603 unsigned int a;
2604 unsigned int i;
2605
2606 for (i = 0; i < 32; i += 2)
2607 if (((a = rotate_left (val, i)) & 0xff) != 0)
2608 {
2609 if (a & 0xff00)
2610 {
2611 if (a & ~ 0xffff)
2612 continue;
2613 * highpart = (a >> 8) | ((i + 24) << 7);
2614 }
2615 else if (a & 0xff0000)
2616 {
2617 if (a & 0xff000000)
2618 continue;
2619 * highpart = (a >> 16) | ((i + 16) << 7);
2620 }
2621 else
2622 {
2623 assert (a & 0xff000000);
2624 * highpart = (a >> 24) | ((i + 8) << 7);
2625 }
2626
2627 return (a & 0xff) | (i << 7);
2628 }
2629
2630 return FAIL;
2631 }
2632
2633 static int
2634 validate_offset_imm (val, hwse)
2635 unsigned int val;
2636 int hwse;
2637 {
2638 if ((hwse && val > 255) || val > 4095)
2639 return FAIL;
2640 return val;
2641 }
2642
2643 static void
2644 s_req (a)
2645 int a ATTRIBUTE_UNUSED;
2646 {
2647 as_bad (_("invalid syntax for .req directive"));
2648 }
2649
2650 static void
2651 s_bss (ignore)
2652 int ignore ATTRIBUTE_UNUSED;
2653 {
2654 /* We don't support putting frags in the BSS segment, we fake it by
2655 marking in_bss, then looking at s_skip for clues. */
2656 subseg_set (bss_section, 0);
2657 demand_empty_rest_of_line ();
2658 }
2659
2660 static void
2661 s_even (ignore)
2662 int ignore ATTRIBUTE_UNUSED;
2663 {
2664 /* Never make frag if expect extra pass. */
2665 if (!need_pass_2)
2666 frag_align (1, 0, 0);
2667
2668 record_alignment (now_seg, 1);
2669
2670 demand_empty_rest_of_line ();
2671 }
2672
2673 static void
2674 s_ltorg (ignored)
2675 int ignored ATTRIBUTE_UNUSED;
2676 {
2677 unsigned int entry;
2678 literal_pool * pool;
2679 char sym_name[20];
2680
2681 pool = find_literal_pool ();
2682 if (pool == NULL
2683 || pool->symbol == NULL
2684 || pool->next_free_entry == 0)
2685 return;
2686
2687 /* Align pool as you have word accesses.
2688 Only make a frag if we have to. */
2689 if (!need_pass_2)
2690 frag_align (2, 0, 0);
2691
2692 record_alignment (now_seg, 2);
2693
2694 sprintf (sym_name, "$$lit_\002%x", pool->id);
2695
2696 symbol_locate (pool->symbol, sym_name, now_seg,
2697 (valueT) frag_now_fix (), frag_now);
2698 symbol_table_insert (pool->symbol);
2699
2700 ARM_SET_THUMB (pool->symbol, thumb_mode);
2701
2702 #if defined OBJ_COFF || defined OBJ_ELF
2703 ARM_SET_INTERWORK (pool->symbol, support_interwork);
2704 #endif
2705
2706 for (entry = 0; entry < pool->next_free_entry; entry ++)
2707 /* First output the expression in the instruction to the pool. */
2708 emit_expr (&(pool->literals[entry]), 4); /* .word */
2709
2710 /* Mark the pool as empty. */
2711 pool->next_free_entry = 0;
2712 pool->symbol = NULL;
2713 }
2714
2715 /* Same as s_align_ptwo but align 0 => align 2. */
2716
2717 static void
2718 s_align (unused)
2719 int unused ATTRIBUTE_UNUSED;
2720 {
2721 register int temp;
2722 register long temp_fill;
2723 long max_alignment = 15;
2724
2725 temp = get_absolute_expression ();
2726 if (temp > max_alignment)
2727 as_bad (_("alignment too large: %d assumed"), temp = max_alignment);
2728 else if (temp < 0)
2729 {
2730 as_bad (_("alignment negative. 0 assumed."));
2731 temp = 0;
2732 }
2733
2734 if (*input_line_pointer == ',')
2735 {
2736 input_line_pointer++;
2737 temp_fill = get_absolute_expression ();
2738 }
2739 else
2740 temp_fill = 0;
2741
2742 if (!temp)
2743 temp = 2;
2744
2745 /* Only make a frag if we HAVE to. */
2746 if (temp && !need_pass_2)
2747 frag_align (temp, (int) temp_fill, 0);
2748 demand_empty_rest_of_line ();
2749
2750 record_alignment (now_seg, temp);
2751 }
2752
2753 static void
2754 s_force_thumb (ignore)
2755 int ignore ATTRIBUTE_UNUSED;
2756 {
2757 /* If we are not already in thumb mode go into it, EVEN if
2758 the target processor does not support thumb instructions.
2759 This is used by gcc/config/arm/lib1funcs.asm for example
2760 to compile interworking support functions even if the
2761 target processor should not support interworking. */
2762 if (! thumb_mode)
2763 {
2764 thumb_mode = 2;
2765
2766 record_alignment (now_seg, 1);
2767 }
2768
2769 demand_empty_rest_of_line ();
2770 }
2771
2772 static void
2773 s_thumb_func (ignore)
2774 int ignore ATTRIBUTE_UNUSED;
2775 {
2776 if (! thumb_mode)
2777 opcode_select (16);
2778
2779 /* The following label is the name/address of the start of a Thumb function.
2780 We need to know this for the interworking support. */
2781 label_is_thumb_function_name = TRUE;
2782
2783 demand_empty_rest_of_line ();
2784 }
2785
2786 /* Perform a .set directive, but also mark the alias as
2787 being a thumb function. */
2788
2789 static void
2790 s_thumb_set (equiv)
2791 int equiv;
2792 {
2793 /* XXX the following is a duplicate of the code for s_set() in read.c
2794 We cannot just call that code as we need to get at the symbol that
2795 is created. */
2796 register char * name;
2797 register char delim;
2798 register char * end_name;
2799 register symbolS * symbolP;
2800
2801 /* Especial apologies for the random logic:
2802 This just grew, and could be parsed much more simply!
2803 Dean - in haste. */
2804 name = input_line_pointer;
2805 delim = get_symbol_end ();
2806 end_name = input_line_pointer;
2807 *end_name = delim;
2808
2809 SKIP_WHITESPACE ();
2810
2811 if (*input_line_pointer != ',')
2812 {
2813 *end_name = 0;
2814 as_bad (_("expected comma after name \"%s\""), name);
2815 *end_name = delim;
2816 ignore_rest_of_line ();
2817 return;
2818 }
2819
2820 input_line_pointer++;
2821 *end_name = 0;
2822
2823 if (name[0] == '.' && name[1] == '\0')
2824 {
2825 /* XXX - this should not happen to .thumb_set. */
2826 abort ();
2827 }
2828
2829 if ((symbolP = symbol_find (name)) == NULL
2830 && (symbolP = md_undefined_symbol (name)) == NULL)
2831 {
2832 #ifndef NO_LISTING
2833 /* When doing symbol listings, play games with dummy fragments living
2834 outside the normal fragment chain to record the file and line info
2835 for this symbol. */
2836 if (listing & LISTING_SYMBOLS)
2837 {
2838 extern struct list_info_struct * listing_tail;
2839 fragS * dummy_frag = (fragS *) xmalloc (sizeof (fragS));
2840
2841 memset (dummy_frag, 0, sizeof (fragS));
2842 dummy_frag->fr_type = rs_fill;
2843 dummy_frag->line = listing_tail;
2844 symbolP = symbol_new (name, undefined_section, 0, dummy_frag);
2845 dummy_frag->fr_symbol = symbolP;
2846 }
2847 else
2848 #endif
2849 symbolP = symbol_new (name, undefined_section, 0, &zero_address_frag);
2850
2851 #ifdef OBJ_COFF
2852 /* "set" symbols are local unless otherwise specified. */
2853 SF_SET_LOCAL (symbolP);
2854 #endif /* OBJ_COFF */
2855 } /* Make a new symbol. */
2856
2857 symbol_table_insert (symbolP);
2858
2859 * end_name = delim;
2860
2861 if (equiv
2862 && S_IS_DEFINED (symbolP)
2863 && S_GET_SEGMENT (symbolP) != reg_section)
2864 as_bad (_("symbol `%s' already defined"), S_GET_NAME (symbolP));
2865
2866 pseudo_set (symbolP);
2867
2868 demand_empty_rest_of_line ();
2869
2870 /* XXX Now we come to the Thumb specific bit of code. */
2871
2872 THUMB_SET_FUNC (symbolP, 1);
2873 ARM_SET_THUMB (symbolP, 1);
2874 #if defined OBJ_ELF || defined OBJ_COFF
2875 ARM_SET_INTERWORK (symbolP, support_interwork);
2876 #endif
2877 }
2878
2879 static void
2880 opcode_select (width)
2881 int width;
2882 {
2883 switch (width)
2884 {
2885 case 16:
2886 if (! thumb_mode)
2887 {
2888 if (! (cpu_variant & ARM_EXT_V4T))
2889 as_bad (_("selected processor does not support THUMB opcodes"));
2890
2891 thumb_mode = 1;
2892 /* No need to force the alignment, since we will have been
2893 coming from ARM mode, which is word-aligned. */
2894 record_alignment (now_seg, 1);
2895 }
2896 break;
2897
2898 case 32:
2899 if (thumb_mode)
2900 {
2901 if ((cpu_variant & ARM_ALL) == ARM_EXT_V4T)
2902 as_bad (_("selected processor does not support ARM opcodes"));
2903
2904 thumb_mode = 0;
2905
2906 if (!need_pass_2)
2907 frag_align (2, 0, 0);
2908
2909 record_alignment (now_seg, 1);
2910 }
2911 break;
2912
2913 default:
2914 as_bad (_("invalid instruction size selected (%d)"), width);
2915 }
2916 }
2917
2918 static void
2919 s_arm (ignore)
2920 int ignore ATTRIBUTE_UNUSED;
2921 {
2922 opcode_select (32);
2923 demand_empty_rest_of_line ();
2924 }
2925
2926 static void
2927 s_thumb (ignore)
2928 int ignore ATTRIBUTE_UNUSED;
2929 {
2930 opcode_select (16);
2931 demand_empty_rest_of_line ();
2932 }
2933
2934 static void
2935 s_code (unused)
2936 int unused ATTRIBUTE_UNUSED;
2937 {
2938 register int temp;
2939
2940 temp = get_absolute_expression ();
2941 switch (temp)
2942 {
2943 case 16:
2944 case 32:
2945 opcode_select (temp);
2946 break;
2947
2948 default:
2949 as_bad (_("invalid operand to .code directive (%d) (expecting 16 or 32)"), temp);
2950 }
2951 }
2952
2953 static void
2954 end_of_line (str)
2955 char *str;
2956 {
2957 skip_whitespace (str);
2958
2959 if (*str != '\0' && !inst.error)
2960 inst.error = _("garbage following instruction");
2961 }
2962
2963 static int
2964 skip_past_comma (str)
2965 char ** str;
2966 {
2967 char * p = * str, c;
2968 int comma = 0;
2969
2970 while ((c = *p) == ' ' || c == ',')
2971 {
2972 p++;
2973 if (c == ',' && comma++)
2974 return FAIL;
2975 }
2976
2977 if (c == '\0')
2978 return FAIL;
2979
2980 *str = p;
2981 return comma ? SUCCESS : FAIL;
2982 }
2983
2984 /* A standard register must be given at this point.
2985 SHIFT is the place to put it in inst.instruction.
2986 Restores input start point on error.
2987 Returns the reg#, or FAIL. */
2988
2989 static int
2990 reg_required_here (str, shift)
2991 char ** str;
2992 int shift;
2993 {
2994 static char buff [128]; /* XXX */
2995 int reg;
2996 char * start = * str;
2997
2998 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_RN].htab)) != FAIL)
2999 {
3000 if (shift >= 0)
3001 inst.instruction |= reg << shift;
3002 return reg;
3003 }
3004
3005 /* Restore the start point, we may have got a reg of the wrong class. */
3006 *str = start;
3007
3008 /* In the few cases where we might be able to accept something else
3009 this error can be overridden. */
3010 sprintf (buff, _("register expected, not '%.100s'"), start);
3011 inst.error = buff;
3012
3013 return FAIL;
3014 }
3015
3016 /* A Intel Wireless MMX technology register
3017 must be given at this point.
3018 Shift is the place to put it in inst.instruction.
3019 Restores input start point on err.
3020 Returns the reg#, or FAIL. */
3021
3022 static int
3023 wreg_required_here (str, shift, reg_type)
3024 char ** str;
3025 int shift;
3026 enum wreg_type reg_type;
3027 {
3028 static char buff [128];
3029 int reg;
3030 char * start = *str;
3031
3032 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_IWMMXT].htab)) != FAIL)
3033 {
3034 if (wr_register (reg)
3035 && (reg_type == IWMMXT_REG_WR || reg_type == IWMMXT_REG_WR_OR_WC))
3036 {
3037 if (shift >= 0)
3038 inst.instruction |= (reg ^ WR_PREFIX) << shift;
3039 return reg;
3040 }
3041 else if (wc_register (reg)
3042 && (reg_type == IWMMXT_REG_WC || reg_type == IWMMXT_REG_WR_OR_WC))
3043 {
3044 if (shift >= 0)
3045 inst.instruction |= (reg ^ WC_PREFIX) << shift;
3046 return reg;
3047 }
3048 else if ((wcg_register (reg) && reg_type == IWMMXT_REG_WCG))
3049 {
3050 if (shift >= 0)
3051 inst.instruction |= ((reg ^ WC_PREFIX) - 8) << shift;
3052 return reg;
3053 }
3054 }
3055
3056 /* Restore the start point, we may have got a reg of the wrong class. */
3057 *str = start;
3058
3059 /* In the few cases where we might be able to accept
3060 something else this error can be overridden. */
3061 sprintf (buff, _("Intel Wireless MMX technology register expected, not '%.100s'"), start);
3062 inst.error = buff;
3063
3064 return FAIL;
3065 }
3066
3067 static const struct asm_psr *
3068 arm_psr_parse (ccp)
3069 register char ** ccp;
3070 {
3071 char * start = * ccp;
3072 char c;
3073 char * p;
3074 const struct asm_psr * psr;
3075
3076 p = start;
3077
3078 /* Skip to the end of the next word in the input stream. */
3079 do
3080 {
3081 c = *p++;
3082 }
3083 while (ISALPHA (c) || c == '_');
3084
3085 /* Terminate the word. */
3086 *--p = 0;
3087
3088 /* CPSR's and SPSR's can now be lowercase. This is just a convenience
3089 feature for ease of use and backwards compatibility. */
3090 if (!strncmp (start, "cpsr", 4))
3091 strncpy (start, "CPSR", 4);
3092 else if (!strncmp (start, "spsr", 4))
3093 strncpy (start, "SPSR", 4);
3094
3095 /* Now locate the word in the psr hash table. */
3096 psr = (const struct asm_psr *) hash_find (arm_psr_hsh, start);
3097
3098 /* Restore the input stream. */
3099 *p = c;
3100
3101 /* If we found a valid match, advance the
3102 stream pointer past the end of the word. */
3103 *ccp = p;
3104
3105 return psr;
3106 }
3107
3108 /* Parse the input looking for a PSR flag. */
3109
3110 static int
3111 psr_required_here (str)
3112 char ** str;
3113 {
3114 char * start = * str;
3115 const struct asm_psr * psr;
3116
3117 psr = arm_psr_parse (str);
3118
3119 if (psr)
3120 {
3121 /* If this is the SPSR that is being modified, set the R bit. */
3122 if (! psr->cpsr)
3123 inst.instruction |= SPSR_BIT;
3124
3125 /* Set the psr flags in the MSR instruction. */
3126 inst.instruction |= psr->field << PSR_SHIFT;
3127
3128 return SUCCESS;
3129 }
3130
3131 /* In the few cases where we might be able to accept
3132 something else this error can be overridden. */
3133 inst.error = _("flag for {c}psr instruction expected");
3134
3135 /* Restore the start point. */
3136 *str = start;
3137 return FAIL;
3138 }
3139
3140 static int
3141 co_proc_number (str)
3142 char **str;
3143 {
3144 int processor, pchar;
3145 char *start;
3146
3147 skip_whitespace (*str);
3148 start = *str;
3149
3150 /* The data sheet seems to imply that just a number on its own is valid
3151 here, but the RISC iX assembler seems to accept a prefix 'p'. We will
3152 accept either. */
3153 if ((processor = arm_reg_parse (str, all_reg_maps[REG_TYPE_CP].htab))
3154 == FAIL)
3155 {
3156 *str = start;
3157
3158 pchar = *(*str)++;
3159 if (pchar >= '0' && pchar <= '9')
3160 {
3161 processor = pchar - '0';
3162 if (**str >= '0' && **str <= '9')
3163 {
3164 processor = processor * 10 + *(*str)++ - '0';
3165 if (processor > 15)
3166 {
3167 inst.error = _("illegal co-processor number");
3168 return FAIL;
3169 }
3170 }
3171 }
3172 else
3173 {
3174 inst.error = _("bad or missing co-processor number");
3175 return FAIL;
3176 }
3177 }
3178
3179 inst.instruction |= processor << 8;
3180 return SUCCESS;
3181 }
3182
3183 static int
3184 cp_opc_expr (str, where, length)
3185 char ** str;
3186 int where;
3187 int length;
3188 {
3189 expressionS expr;
3190
3191 skip_whitespace (* str);
3192
3193 memset (&expr, '\0', sizeof (expr));
3194
3195 if (my_get_expression (&expr, str))
3196 return FAIL;
3197 if (expr.X_op != O_constant)
3198 {
3199 inst.error = _("bad or missing expression");
3200 return FAIL;
3201 }
3202
3203 if ((expr.X_add_number & ((1 << length) - 1)) != expr.X_add_number)
3204 {
3205 inst.error = _("immediate co-processor expression too large");
3206 return FAIL;
3207 }
3208
3209 inst.instruction |= expr.X_add_number << where;
3210 return SUCCESS;
3211 }
3212
3213 static int
3214 cp_reg_required_here (str, where)
3215 char ** str;
3216 int where;
3217 {
3218 int reg;
3219 char * start = *str;
3220
3221 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_CN].htab)) != FAIL)
3222 {
3223 inst.instruction |= reg << where;
3224 return reg;
3225 }
3226
3227 /* In the few cases where we might be able to accept something else
3228 this error can be overridden. */
3229 inst.error = _("co-processor register expected");
3230
3231 /* Restore the start point. */
3232 *str = start;
3233 return FAIL;
3234 }
3235
3236 static int
3237 fp_reg_required_here (str, where)
3238 char ** str;
3239 int where;
3240 {
3241 int reg;
3242 char * start = * str;
3243
3244 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_FN].htab)) != FAIL)
3245 {
3246 inst.instruction |= reg << where;
3247 return reg;
3248 }
3249
3250 /* In the few cases where we might be able to accept something else
3251 this error can be overridden. */
3252 inst.error = _("floating point register expected");
3253
3254 /* Restore the start point. */
3255 *str = start;
3256 return FAIL;
3257 }
3258
3259 static int
3260 cp_address_offset (str)
3261 char ** str;
3262 {
3263 int offset;
3264
3265 skip_whitespace (* str);
3266
3267 if (! is_immediate_prefix (**str))
3268 {
3269 inst.error = _("immediate expression expected");
3270 return FAIL;
3271 }
3272
3273 (*str)++;
3274
3275 if (my_get_expression (& inst.reloc.exp, str))
3276 return FAIL;
3277
3278 if (inst.reloc.exp.X_op == O_constant)
3279 {
3280 offset = inst.reloc.exp.X_add_number;
3281
3282 if (offset & 3)
3283 {
3284 inst.error = _("co-processor address must be word aligned");
3285 return FAIL;
3286 }
3287
3288 if (offset > 1023 || offset < -1023)
3289 {
3290 inst.error = _("offset too large");
3291 return FAIL;
3292 }
3293
3294 if (offset >= 0)
3295 inst.instruction |= INDEX_UP;
3296 else
3297 offset = -offset;
3298
3299 inst.instruction |= offset >> 2;
3300 }
3301 else
3302 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
3303
3304 return SUCCESS;
3305 }
3306
3307 static int
3308 cp_address_required_here (str, wb_ok)
3309 char ** str;
3310 int wb_ok;
3311 {
3312 char * p = * str;
3313 int pre_inc = 0;
3314 int write_back = 0;
3315
3316 if (*p == '[')
3317 {
3318 int reg;
3319
3320 p++;
3321 skip_whitespace (p);
3322
3323 if ((reg = reg_required_here (& p, 16)) == FAIL)
3324 return FAIL;
3325
3326 skip_whitespace (p);
3327
3328 if (*p == ']')
3329 {
3330 p++;
3331
3332 skip_whitespace (p);
3333
3334 if (*p == '\0')
3335 {
3336 /* As an extension to the official ARM syntax we allow:
3337
3338 [Rn]
3339
3340 as a short hand for:
3341
3342 [Rn,#0] */
3343 inst.instruction |= PRE_INDEX | INDEX_UP;
3344 *str = p;
3345 return SUCCESS;
3346 }
3347
3348 if (skip_past_comma (& p) == FAIL)
3349 {
3350 inst.error = _("comma expected after closing square bracket");
3351 return FAIL;
3352 }
3353
3354 skip_whitespace (p);
3355
3356 if (*p == '#')
3357 {
3358 if (wb_ok)
3359 {
3360 /* [Rn], #expr */
3361 write_back = WRITE_BACK;
3362
3363 if (reg == REG_PC)
3364 {
3365 inst.error = _("pc may not be used in post-increment");
3366 return FAIL;
3367 }
3368
3369 if (cp_address_offset (& p) == FAIL)
3370 return FAIL;
3371 }
3372 else
3373 pre_inc = PRE_INDEX | INDEX_UP;
3374 }
3375 else if (*p == '{')
3376 {
3377 int option;
3378
3379 /* [Rn], {<expr>} */
3380 p++;
3381
3382 skip_whitespace (p);
3383
3384 if (my_get_expression (& inst.reloc.exp, & p))
3385 return FAIL;
3386
3387 if (inst.reloc.exp.X_op == O_constant)
3388 {
3389 option = inst.reloc.exp.X_add_number;
3390
3391 if (option > 255 || option < 0)
3392 {
3393 inst.error = _("'option' field too large");
3394 return FAIL;
3395 }
3396
3397 skip_whitespace (p);
3398
3399 if (*p != '}')
3400 {
3401 inst.error = _("'}' expected at end of 'option' field");
3402 return FAIL;
3403 }
3404 else
3405 {
3406 p++;
3407 inst.instruction |= option;
3408 inst.instruction |= INDEX_UP;
3409 }
3410 }
3411 else
3412 {
3413 inst.error = _("non-constant expressions for 'option' field not supported");
3414 return FAIL;
3415 }
3416 }
3417 else
3418 {
3419 inst.error = _("# or { expected after comma");
3420 return FAIL;
3421 }
3422 }
3423 else
3424 {
3425 /* '['Rn, #expr']'[!] */
3426
3427 if (skip_past_comma (& p) == FAIL)
3428 {
3429 inst.error = _("pre-indexed expression expected");
3430 return FAIL;
3431 }
3432
3433 pre_inc = PRE_INDEX;
3434
3435 if (cp_address_offset (& p) == FAIL)
3436 return FAIL;
3437
3438 skip_whitespace (p);
3439
3440 if (*p++ != ']')
3441 {
3442 inst.error = _("missing ]");
3443 return FAIL;
3444 }
3445
3446 skip_whitespace (p);
3447
3448 if (wb_ok && *p == '!')
3449 {
3450 if (reg == REG_PC)
3451 {
3452 inst.error = _("pc may not be used with write-back");
3453 return FAIL;
3454 }
3455
3456 p++;
3457 write_back = WRITE_BACK;
3458 }
3459 }
3460 }
3461 else
3462 {
3463 if (my_get_expression (&inst.reloc.exp, &p))
3464 return FAIL;
3465
3466 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
3467 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
3468 inst.reloc.pc_rel = 1;
3469 inst.instruction |= (REG_PC << 16);
3470 pre_inc = PRE_INDEX;
3471 }
3472
3473 inst.instruction |= write_back | pre_inc;
3474 *str = p;
3475 return SUCCESS;
3476 }
3477
3478 static int
3479 cp_byte_address_offset (str)
3480 char ** str;
3481 {
3482 int offset;
3483
3484 skip_whitespace (* str);
3485
3486 if (! is_immediate_prefix (**str))
3487 {
3488 inst.error = _("immediate expression expected");
3489 return FAIL;
3490 }
3491
3492 (*str)++;
3493
3494 if (my_get_expression (& inst.reloc.exp, str))
3495 return FAIL;
3496
3497 if (inst.reloc.exp.X_op == O_constant)
3498 {
3499 offset = inst.reloc.exp.X_add_number;
3500
3501 if (offset > 255 || offset < -255)
3502 {
3503 inst.error = _("offset too large");
3504 return FAIL;
3505 }
3506
3507 if (offset >= 0)
3508 inst.instruction |= INDEX_UP;
3509 else
3510 offset = -offset;
3511
3512 inst.instruction |= offset;
3513 }
3514 else
3515 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM_S2;
3516
3517 return SUCCESS;
3518 }
3519
3520 static int
3521 cp_byte_address_required_here (str)
3522 char ** str;
3523 {
3524 char * p = * str;
3525 int pre_inc = 0;
3526 int write_back = 0;
3527
3528 if (*p == '[')
3529 {
3530 int reg;
3531
3532 p++;
3533 skip_whitespace (p);
3534
3535 if ((reg = reg_required_here (& p, 16)) == FAIL)
3536 return FAIL;
3537
3538 skip_whitespace (p);
3539
3540 if (*p == ']')
3541 {
3542 p++;
3543
3544 if (skip_past_comma (& p) == SUCCESS)
3545 {
3546 /* [Rn], #expr */
3547 write_back = WRITE_BACK;
3548
3549 if (reg == REG_PC)
3550 {
3551 inst.error = _("pc may not be used in post-increment");
3552 return FAIL;
3553 }
3554
3555 if (cp_byte_address_offset (& p) == FAIL)
3556 return FAIL;
3557 }
3558 else
3559 pre_inc = PRE_INDEX | INDEX_UP;
3560 }
3561 else
3562 {
3563 /* '['Rn, #expr']'[!] */
3564
3565 if (skip_past_comma (& p) == FAIL)
3566 {
3567 inst.error = _("pre-indexed expression expected");
3568 return FAIL;
3569 }
3570
3571 pre_inc = PRE_INDEX;
3572
3573 if (cp_byte_address_offset (& p) == FAIL)
3574 return FAIL;
3575
3576 skip_whitespace (p);
3577
3578 if (*p++ != ']')
3579 {
3580 inst.error = _("missing ]");
3581 return FAIL;
3582 }
3583
3584 skip_whitespace (p);
3585
3586 if (*p == '!')
3587 {
3588 if (reg == REG_PC)
3589 {
3590 inst.error = _("pc may not be used with write-back");
3591 return FAIL;
3592 }
3593
3594 p++;
3595 write_back = WRITE_BACK;
3596 }
3597 }
3598 }
3599 else
3600 {
3601 if (my_get_expression (&inst.reloc.exp, &p))
3602 return FAIL;
3603
3604 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM_S2;
3605 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
3606 inst.reloc.pc_rel = 1;
3607 inst.instruction |= (REG_PC << 16);
3608 pre_inc = PRE_INDEX;
3609 }
3610
3611 inst.instruction |= write_back | pre_inc;
3612 *str = p;
3613 return SUCCESS;
3614 }
3615
3616 static void
3617 do_empty (str)
3618 char * str;
3619 {
3620 /* Do nothing really. */
3621 end_of_line (str);
3622 return;
3623 }
3624
3625 static void
3626 do_mrs (str)
3627 char *str;
3628 {
3629 int skip = 0;
3630
3631 /* Only one syntax. */
3632 skip_whitespace (str);
3633
3634 if (reg_required_here (&str, 12) == FAIL)
3635 {
3636 inst.error = BAD_ARGS;
3637 return;
3638 }
3639
3640 if (skip_past_comma (&str) == FAIL)
3641 {
3642 inst.error = _("comma expected after register name");
3643 return;
3644 }
3645
3646 skip_whitespace (str);
3647
3648 if ( strcmp (str, "CPSR") == 0
3649 || strcmp (str, "SPSR") == 0
3650 /* Lower case versions for backwards compatability. */
3651 || strcmp (str, "cpsr") == 0
3652 || strcmp (str, "spsr") == 0)
3653 skip = 4;
3654
3655 /* This is for backwards compatability with older toolchains. */
3656 else if ( strcmp (str, "cpsr_all") == 0
3657 || strcmp (str, "spsr_all") == 0)
3658 skip = 8;
3659 else
3660 {
3661 inst.error = _("CPSR or SPSR expected");
3662 return;
3663 }
3664
3665 if (* str == 's' || * str == 'S')
3666 inst.instruction |= SPSR_BIT;
3667 str += skip;
3668
3669 end_of_line (str);
3670 }
3671
3672 /* Two possible forms:
3673 "{C|S}PSR_<field>, Rm",
3674 "{C|S}PSR_f, #expression". */
3675
3676 static void
3677 do_msr (str)
3678 char * str;
3679 {
3680 skip_whitespace (str);
3681
3682 if (psr_required_here (& str) == FAIL)
3683 return;
3684
3685 if (skip_past_comma (& str) == FAIL)
3686 {
3687 inst.error = _("comma missing after psr flags");
3688 return;
3689 }
3690
3691 skip_whitespace (str);
3692
3693 if (reg_required_here (& str, 0) != FAIL)
3694 {
3695 inst.error = NULL;
3696 end_of_line (str);
3697 return;
3698 }
3699
3700 if (! is_immediate_prefix (* str))
3701 {
3702 inst.error =
3703 _("only a register or immediate value can follow a psr flag");
3704 return;
3705 }
3706
3707 str ++;
3708 inst.error = NULL;
3709
3710 if (my_get_expression (& inst.reloc.exp, & str))
3711 {
3712 inst.error =
3713 _("only a register or immediate value can follow a psr flag");
3714 return;
3715 }
3716
3717 #if 0 /* The first edition of the ARM architecture manual stated that
3718 writing anything other than the flags with an immediate operation
3719 had UNPREDICTABLE effects. This constraint was removed in the
3720 second edition of the specification. */
3721 if ((cpu_variant & ARM_EXT_V5) != ARM_EXT_V5
3722 && inst.instruction & ((PSR_c | PSR_x | PSR_s) << PSR_SHIFT))
3723 {
3724 inst.error = _("immediate value cannot be used to set this field");
3725 return;
3726 }
3727 #endif
3728
3729 inst.instruction |= INST_IMMEDIATE;
3730
3731 if (inst.reloc.exp.X_add_symbol)
3732 {
3733 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
3734 inst.reloc.pc_rel = 0;
3735 }
3736 else
3737 {
3738 unsigned value = validate_immediate (inst.reloc.exp.X_add_number);
3739
3740 if (value == (unsigned) FAIL)
3741 {
3742 inst.error = _("invalid constant");
3743 return;
3744 }
3745
3746 inst.instruction |= value;
3747 }
3748
3749 inst.error = NULL;
3750 end_of_line (str);
3751 }
3752
3753 /* Long Multiply Parser
3754 UMULL RdLo, RdHi, Rm, Rs
3755 SMULL RdLo, RdHi, Rm, Rs
3756 UMLAL RdLo, RdHi, Rm, Rs
3757 SMLAL RdLo, RdHi, Rm, Rs. */
3758
3759 static void
3760 do_mull (str)
3761 char * str;
3762 {
3763 int rdlo, rdhi, rm, rs;
3764
3765 /* Only one format "rdlo, rdhi, rm, rs". */
3766 skip_whitespace (str);
3767
3768 if ((rdlo = reg_required_here (&str, 12)) == FAIL)
3769 {
3770 inst.error = BAD_ARGS;
3771 return;
3772 }
3773
3774 if (skip_past_comma (&str) == FAIL
3775 || (rdhi = reg_required_here (&str, 16)) == FAIL)
3776 {
3777 inst.error = BAD_ARGS;
3778 return;
3779 }
3780
3781 if (skip_past_comma (&str) == FAIL
3782 || (rm = reg_required_here (&str, 0)) == FAIL)
3783 {
3784 inst.error = BAD_ARGS;
3785 return;
3786 }
3787
3788 /* rdhi, rdlo and rm must all be different. */
3789 if (rdlo == rdhi || rdlo == rm || rdhi == rm)
3790 as_tsktsk (_("rdhi, rdlo and rm must all be different"));
3791
3792 if (skip_past_comma (&str) == FAIL
3793 || (rs = reg_required_here (&str, 8)) == FAIL)
3794 {
3795 inst.error = BAD_ARGS;
3796 return;
3797 }
3798
3799 if (rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC)
3800 {
3801 inst.error = BAD_PC;
3802 return;
3803 }
3804
3805 end_of_line (str);
3806 return;
3807 }
3808
3809 static void
3810 do_mul (str)
3811 char * str;
3812 {
3813 int rd, rm;
3814
3815 /* Only one format "rd, rm, rs". */
3816 skip_whitespace (str);
3817
3818 if ((rd = reg_required_here (&str, 16)) == FAIL)
3819 {
3820 inst.error = BAD_ARGS;
3821 return;
3822 }
3823
3824 if (rd == REG_PC)
3825 {
3826 inst.error = BAD_PC;
3827 return;
3828 }
3829
3830 if (skip_past_comma (&str) == FAIL
3831 || (rm = reg_required_here (&str, 0)) == FAIL)
3832 {
3833 inst.error = BAD_ARGS;
3834 return;
3835 }
3836
3837 if (rm == REG_PC)
3838 {
3839 inst.error = BAD_PC;
3840 return;
3841 }
3842
3843 if (rm == rd)
3844 as_tsktsk (_("rd and rm should be different in mul"));
3845
3846 if (skip_past_comma (&str) == FAIL
3847 || (rm = reg_required_here (&str, 8)) == FAIL)
3848 {
3849 inst.error = BAD_ARGS;
3850 return;
3851 }
3852
3853 if (rm == REG_PC)
3854 {
3855 inst.error = BAD_PC;
3856 return;
3857 }
3858
3859 end_of_line (str);
3860 return;
3861 }
3862
3863 static void
3864 do_mla (str)
3865 char * str;
3866 {
3867 int rd, rm;
3868
3869 /* Only one format "rd, rm, rs, rn". */
3870 skip_whitespace (str);
3871
3872 if ((rd = reg_required_here (&str, 16)) == FAIL)
3873 {
3874 inst.error = BAD_ARGS;
3875 return;
3876 }
3877
3878 if (rd == REG_PC)
3879 {
3880 inst.error = BAD_PC;
3881 return;
3882 }
3883
3884 if (skip_past_comma (&str) == FAIL
3885 || (rm = reg_required_here (&str, 0)) == FAIL)
3886 {
3887 inst.error = BAD_ARGS;
3888 return;
3889 }
3890
3891 if (rm == REG_PC)
3892 {
3893 inst.error = BAD_PC;
3894 return;
3895 }
3896
3897 if (rm == rd)
3898 as_tsktsk (_("rd and rm should be different in mla"));
3899
3900 if (skip_past_comma (&str) == FAIL
3901 || (rd = reg_required_here (&str, 8)) == FAIL
3902 || skip_past_comma (&str) == FAIL
3903 || (rm = reg_required_here (&str, 12)) == FAIL)
3904 {
3905 inst.error = BAD_ARGS;
3906 return;
3907 }
3908
3909 if (rd == REG_PC || rm == REG_PC)
3910 {
3911 inst.error = BAD_PC;
3912 return;
3913 }
3914
3915 end_of_line (str);
3916 return;
3917 }
3918
3919 /* Expects *str -> the characters "acc0", possibly with leading blanks.
3920 Advances *str to the next non-alphanumeric.
3921 Returns 0, or else FAIL (in which case sets inst.error).
3922
3923 (In a future XScale, there may be accumulators other than zero.
3924 At that time this routine and its callers can be upgraded to suit.) */
3925
3926 static int
3927 accum0_required_here (str)
3928 char ** str;
3929 {
3930 static char buff [128]; /* Note the address is taken. Hence, static. */
3931 char * p = * str;
3932 char c;
3933 int result = 0; /* The accum number. */
3934
3935 skip_whitespace (p);
3936
3937 *str = p; /* Advance caller's string pointer too. */
3938 c = *p++;
3939 while (ISALNUM (c))
3940 c = *p++;
3941
3942 *--p = 0; /* Aap nul into input buffer at non-alnum. */
3943
3944 if (! ( streq (*str, "acc0") || streq (*str, "ACC0")))
3945 {
3946 sprintf (buff, _("acc0 expected, not '%.100s'"), *str);
3947 inst.error = buff;
3948 result = FAIL;
3949 }
3950
3951 *p = c; /* Unzap. */
3952 *str = p; /* Caller's string pointer to after match. */
3953 return result;
3954 }
3955
3956 /* Expects **str -> after a comma. May be leading blanks.
3957 Advances *str, recognizing a load mode, and setting inst.instruction.
3958 Returns rn, or else FAIL (in which case may set inst.error
3959 and not advance str)
3960
3961 Note: doesn't know Rd, so no err checks that require such knowledge. */
3962
3963 static int
3964 ld_mode_required_here (string)
3965 char ** string;
3966 {
3967 char * str = * string;
3968 int rn;
3969 int pre_inc = 0;
3970
3971 skip_whitespace (str);
3972
3973 if (* str == '[')
3974 {
3975 str++;
3976
3977 skip_whitespace (str);
3978
3979 if ((rn = reg_required_here (& str, 16)) == FAIL)
3980 return FAIL;
3981
3982 skip_whitespace (str);
3983
3984 if (* str == ']')
3985 {
3986 str ++;
3987
3988 if (skip_past_comma (& str) == SUCCESS)
3989 {
3990 /* [Rn],... (post inc) */
3991 if (ldst_extend_v4 (&str) == FAIL)
3992 return FAIL;
3993 }
3994 else /* [Rn] */
3995 {
3996 skip_whitespace (str);
3997
3998 if (* str == '!')
3999 {
4000 str ++;
4001 inst.instruction |= WRITE_BACK;
4002 }
4003
4004 inst.instruction |= INDEX_UP | HWOFFSET_IMM;
4005 pre_inc = 1;
4006 }
4007 }
4008 else /* [Rn,...] */
4009 {
4010 if (skip_past_comma (& str) == FAIL)
4011 {
4012 inst.error = _("pre-indexed expression expected");
4013 return FAIL;
4014 }
4015
4016 pre_inc = 1;
4017
4018 if (ldst_extend_v4 (&str) == FAIL)
4019 return FAIL;
4020
4021 skip_whitespace (str);
4022
4023 if (* str ++ != ']')
4024 {
4025 inst.error = _("missing ]");
4026 return FAIL;
4027 }
4028
4029 skip_whitespace (str);
4030
4031 if (* str == '!')
4032 {
4033 str ++;
4034 inst.instruction |= WRITE_BACK;
4035 }
4036 }
4037 }
4038 else if (* str == '=') /* ldr's "r,=label" syntax */
4039 /* We should never reach here, because <text> = <expression> is
4040 caught gas/read.c read_a_source_file() as a .set operation. */
4041 return FAIL;
4042 else /* PC +- 8 bit immediate offset. */
4043 {
4044 if (my_get_expression (& inst.reloc.exp, & str))
4045 return FAIL;
4046
4047 inst.instruction |= HWOFFSET_IMM; /* The I bit. */
4048 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
4049 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
4050 inst.reloc.pc_rel = 1;
4051 inst.instruction |= (REG_PC << 16);
4052
4053 rn = REG_PC;
4054 pre_inc = 1;
4055 }
4056
4057 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
4058 * string = str;
4059
4060 return rn;
4061 }
4062
4063 /* ARM V5E (El Segundo) signed-multiply-accumulate (argument parse)
4064 SMLAxy{cond} Rd,Rm,Rs,Rn
4065 SMLAWy{cond} Rd,Rm,Rs,Rn
4066 Error if any register is R15. */
4067
4068 static void
4069 do_smla (str)
4070 char * str;
4071 {
4072 int rd, rm, rs, rn;
4073
4074 skip_whitespace (str);
4075
4076 if ((rd = reg_required_here (& str, 16)) == FAIL
4077 || skip_past_comma (& str) == FAIL
4078 || (rm = reg_required_here (& str, 0)) == FAIL
4079 || skip_past_comma (& str) == FAIL
4080 || (rs = reg_required_here (& str, 8)) == FAIL
4081 || skip_past_comma (& str) == FAIL
4082 || (rn = reg_required_here (& str, 12)) == FAIL)
4083 inst.error = BAD_ARGS;
4084
4085 else if (rd == REG_PC || rm == REG_PC || rs == REG_PC || rn == REG_PC)
4086 inst.error = BAD_PC;
4087
4088 else
4089 end_of_line (str);
4090 }
4091
4092 /* ARM V5E (El Segundo) signed-multiply-accumulate-long (argument parse)
4093 SMLALxy{cond} Rdlo,Rdhi,Rm,Rs
4094 Error if any register is R15.
4095 Warning if Rdlo == Rdhi. */
4096
4097 static void
4098 do_smlal (str)
4099 char * str;
4100 {
4101 int rdlo, rdhi, rm, rs;
4102
4103 skip_whitespace (str);
4104
4105 if ((rdlo = reg_required_here (& str, 12)) == FAIL
4106 || skip_past_comma (& str) == FAIL
4107 || (rdhi = reg_required_here (& str, 16)) == FAIL
4108 || skip_past_comma (& str) == FAIL
4109 || (rm = reg_required_here (& str, 0)) == FAIL
4110 || skip_past_comma (& str) == FAIL
4111 || (rs = reg_required_here (& str, 8)) == FAIL)
4112 {
4113 inst.error = BAD_ARGS;
4114 return;
4115 }
4116
4117 if (rdlo == REG_PC || rdhi == REG_PC || rm == REG_PC || rs == REG_PC)
4118 {
4119 inst.error = BAD_PC;
4120 return;
4121 }
4122
4123 if (rdlo == rdhi)
4124 as_tsktsk (_("rdhi and rdlo must be different"));
4125
4126 end_of_line (str);
4127 }
4128
4129 /* ARM V5E (El Segundo) signed-multiply (argument parse)
4130 SMULxy{cond} Rd,Rm,Rs
4131 Error if any register is R15. */
4132
4133 static void
4134 do_smul (str)
4135 char * str;
4136 {
4137 int rd, rm, rs;
4138
4139 skip_whitespace (str);
4140
4141 if ((rd = reg_required_here (& str, 16)) == FAIL
4142 || skip_past_comma (& str) == FAIL
4143 || (rm = reg_required_here (& str, 0)) == FAIL
4144 || skip_past_comma (& str) == FAIL
4145 || (rs = reg_required_here (& str, 8)) == FAIL)
4146 inst.error = BAD_ARGS;
4147
4148 else if (rd == REG_PC || rm == REG_PC || rs == REG_PC)
4149 inst.error = BAD_PC;
4150
4151 else
4152 end_of_line (str);
4153 }
4154
4155 /* ARM V5E (El Segundo) saturating-add/subtract (argument parse)
4156 Q[D]{ADD,SUB}{cond} Rd,Rm,Rn
4157 Error if any register is R15. */
4158
4159 static void
4160 do_qadd (str)
4161 char * str;
4162 {
4163 int rd, rm, rn;
4164
4165 skip_whitespace (str);
4166
4167 if ((rd = reg_required_here (& str, 12)) == FAIL
4168 || skip_past_comma (& str) == FAIL
4169 || (rm = reg_required_here (& str, 0)) == FAIL
4170 || skip_past_comma (& str) == FAIL
4171 || (rn = reg_required_here (& str, 16)) == FAIL)
4172 inst.error = BAD_ARGS;
4173
4174 else if (rd == REG_PC || rm == REG_PC || rn == REG_PC)
4175 inst.error = BAD_PC;
4176
4177 else
4178 end_of_line (str);
4179 }
4180
4181 /* ARM V5E (el Segundo)
4182 MCRRcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
4183 MRRCcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
4184
4185 These are equivalent to the XScale instructions MAR and MRA,
4186 respectively, when coproc == 0, opcode == 0, and CRm == 0.
4187
4188 Result unpredicatable if Rd or Rn is R15. */
4189
4190 static void
4191 do_co_reg2c (str)
4192 char * str;
4193 {
4194 int rd, rn;
4195
4196 skip_whitespace (str);
4197
4198 if (co_proc_number (& str) == FAIL)
4199 {
4200 if (!inst.error)
4201 inst.error = BAD_ARGS;
4202 return;
4203 }
4204
4205 if (skip_past_comma (& str) == FAIL
4206 || cp_opc_expr (& str, 4, 4) == FAIL)
4207 {
4208 if (!inst.error)
4209 inst.error = BAD_ARGS;
4210 return;
4211 }
4212
4213 if (skip_past_comma (& str) == FAIL
4214 || (rd = reg_required_here (& str, 12)) == FAIL)
4215 {
4216 if (!inst.error)
4217 inst.error = BAD_ARGS;
4218 return;
4219 }
4220
4221 if (skip_past_comma (& str) == FAIL
4222 || (rn = reg_required_here (& str, 16)) == FAIL)
4223 {
4224 if (!inst.error)
4225 inst.error = BAD_ARGS;
4226 return;
4227 }
4228
4229 /* Unpredictable result if rd or rn is R15. */
4230 if (rd == REG_PC || rn == REG_PC)
4231 as_tsktsk
4232 (_("Warning: instruction unpredictable when using r15"));
4233
4234 if (skip_past_comma (& str) == FAIL
4235 || cp_reg_required_here (& str, 0) == FAIL)
4236 {
4237 if (!inst.error)
4238 inst.error = BAD_ARGS;
4239 return;
4240 }
4241
4242 end_of_line (str);
4243 }
4244
4245 /* ARM V5 count-leading-zeroes instruction (argument parse)
4246 CLZ{<cond>} <Rd>, <Rm>
4247 Condition defaults to COND_ALWAYS.
4248 Error if Rd or Rm are R15. */
4249
4250 static void
4251 do_clz (str)
4252 char * str;
4253 {
4254 int rd, rm;
4255
4256 skip_whitespace (str);
4257
4258 if (((rd = reg_required_here (& str, 12)) == FAIL)
4259 || (skip_past_comma (& str) == FAIL)
4260 || ((rm = reg_required_here (& str, 0)) == FAIL))
4261 inst.error = BAD_ARGS;
4262
4263 else if (rd == REG_PC || rm == REG_PC )
4264 inst.error = BAD_PC;
4265
4266 else
4267 end_of_line (str);
4268 }
4269
4270 /* ARM V5 (argument parse)
4271 LDC2{L} <coproc>, <CRd>, <addressing mode>
4272 STC2{L} <coproc>, <CRd>, <addressing mode>
4273 Instruction is not conditional, and has 0xf in the codition field.
4274 Otherwise, it's the same as LDC/STC. */
4275
4276 static void
4277 do_lstc2 (str)
4278 char * str;
4279 {
4280 skip_whitespace (str);
4281
4282 if (co_proc_number (& str) == FAIL)
4283 {
4284 if (!inst.error)
4285 inst.error = BAD_ARGS;
4286 }
4287 else if (skip_past_comma (& str) == FAIL
4288 || cp_reg_required_here (& str, 12) == FAIL)
4289 {
4290 if (!inst.error)
4291 inst.error = BAD_ARGS;
4292 }
4293 else if (skip_past_comma (& str) == FAIL
4294 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
4295 {
4296 if (! inst.error)
4297 inst.error = BAD_ARGS;
4298 }
4299 else
4300 end_of_line (str);
4301 }
4302
4303 /* ARM V5 (argument parse)
4304 CDP2 <coproc>, <opcode_1>, <CRd>, <CRn>, <CRm>, <opcode_2>
4305 Instruction is not conditional, and has 0xf in the condition field.
4306 Otherwise, it's the same as CDP. */
4307
4308 static void
4309 do_cdp2 (str)
4310 char * str;
4311 {
4312 skip_whitespace (str);
4313
4314 if (co_proc_number (& str) == FAIL)
4315 {
4316 if (!inst.error)
4317 inst.error = BAD_ARGS;
4318 return;
4319 }
4320
4321 if (skip_past_comma (& str) == FAIL
4322 || cp_opc_expr (& str, 20,4) == FAIL)
4323 {
4324 if (!inst.error)
4325 inst.error = BAD_ARGS;
4326 return;
4327 }
4328
4329 if (skip_past_comma (& str) == FAIL
4330 || cp_reg_required_here (& str, 12) == FAIL)
4331 {
4332 if (!inst.error)
4333 inst.error = BAD_ARGS;
4334 return;
4335 }
4336
4337 if (skip_past_comma (& str) == FAIL
4338 || cp_reg_required_here (& str, 16) == FAIL)
4339 {
4340 if (!inst.error)
4341 inst.error = BAD_ARGS;
4342 return;
4343 }
4344
4345 if (skip_past_comma (& str) == FAIL
4346 || cp_reg_required_here (& str, 0) == FAIL)
4347 {
4348 if (!inst.error)
4349 inst.error = BAD_ARGS;
4350 return;
4351 }
4352
4353 if (skip_past_comma (& str) == SUCCESS)
4354 {
4355 if (cp_opc_expr (& str, 5, 3) == FAIL)
4356 {
4357 if (!inst.error)
4358 inst.error = BAD_ARGS;
4359 return;
4360 }
4361 }
4362
4363 end_of_line (str);
4364 }
4365
4366 /* ARM V5 (argument parse)
4367 MCR2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
4368 MRC2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
4369 Instruction is not conditional, and has 0xf in the condition field.
4370 Otherwise, it's the same as MCR/MRC. */
4371
4372 static void
4373 do_co_reg2 (str)
4374 char * str;
4375 {
4376 skip_whitespace (str);
4377
4378 if (co_proc_number (& str) == FAIL)
4379 {
4380 if (!inst.error)
4381 inst.error = BAD_ARGS;
4382 return;
4383 }
4384
4385 if (skip_past_comma (& str) == FAIL
4386 || cp_opc_expr (& str, 21, 3) == FAIL)
4387 {
4388 if (!inst.error)
4389 inst.error = BAD_ARGS;
4390 return;
4391 }
4392
4393 if (skip_past_comma (& str) == FAIL
4394 || reg_required_here (& str, 12) == FAIL)
4395 {
4396 if (!inst.error)
4397 inst.error = BAD_ARGS;
4398 return;
4399 }
4400
4401 if (skip_past_comma (& str) == FAIL
4402 || cp_reg_required_here (& str, 16) == FAIL)
4403 {
4404 if (!inst.error)
4405 inst.error = BAD_ARGS;
4406 return;
4407 }
4408
4409 if (skip_past_comma (& str) == FAIL
4410 || cp_reg_required_here (& str, 0) == FAIL)
4411 {
4412 if (!inst.error)
4413 inst.error = BAD_ARGS;
4414 return;
4415 }
4416
4417 if (skip_past_comma (& str) == SUCCESS)
4418 {
4419 if (cp_opc_expr (& str, 5, 3) == FAIL)
4420 {
4421 if (!inst.error)
4422 inst.error = BAD_ARGS;
4423 return;
4424 }
4425 }
4426
4427 end_of_line (str);
4428 }
4429
4430 /* ARM v5TEJ. Jump to Jazelle code. */
4431 static void
4432 do_bxj (str)
4433 char * str;
4434 {
4435 int reg;
4436
4437 skip_whitespace (str);
4438
4439 if ((reg = reg_required_here (&str, 0)) == FAIL)
4440 {
4441 inst.error = BAD_ARGS;
4442 return;
4443 }
4444
4445 /* Note - it is not illegal to do a "bxj pc". Useless, but not illegal. */
4446 if (reg == REG_PC)
4447 as_tsktsk (_("use of r15 in bxj is not really useful"));
4448
4449 end_of_line (str);
4450 }
4451
4452 /* THUMB V5 breakpoint instruction (argument parse)
4453 BKPT <immed_8>. */
4454
4455 static void
4456 do_t_bkpt (str)
4457 char * str;
4458 {
4459 expressionS expr;
4460 unsigned long number;
4461
4462 skip_whitespace (str);
4463
4464 /* Allow optional leading '#'. */
4465 if (is_immediate_prefix (*str))
4466 str ++;
4467
4468 memset (& expr, '\0', sizeof (expr));
4469 if (my_get_expression (& expr, & str)
4470 || (expr.X_op != O_constant
4471 /* As a convenience we allow 'bkpt' without an operand. */
4472 && expr.X_op != O_absent))
4473 {
4474 inst.error = _("bad expression");
4475 return;
4476 }
4477
4478 number = expr.X_add_number;
4479
4480 /* Check it fits an 8 bit unsigned. */
4481 if (number != (number & 0xff))
4482 {
4483 inst.error = _("immediate value out of range");
4484 return;
4485 }
4486
4487 inst.instruction |= number;
4488
4489 end_of_line (str);
4490 }
4491
4492 /* ARM V5 branch-link-exchange (argument parse) for BLX(1) only.
4493 Expects inst.instruction is set for BLX(1).
4494 Note: this is cloned from do_branch, and the reloc changed to be a
4495 new one that can cope with setting one extra bit (the H bit). */
4496
4497 static void
4498 do_branch25 (str)
4499 char * str;
4500 {
4501 if (my_get_expression (& inst.reloc.exp, & str))
4502 return;
4503
4504 #ifdef OBJ_ELF
4505 {
4506 char * save_in;
4507
4508 /* ScottB: February 5, 1998 */
4509 /* Check to see of PLT32 reloc required for the instruction. */
4510
4511 /* arm_parse_reloc() works on input_line_pointer.
4512 We actually want to parse the operands to the branch instruction
4513 passed in 'str'. Save the input pointer and restore it later. */
4514 save_in = input_line_pointer;
4515 input_line_pointer = str;
4516
4517 if (inst.reloc.exp.X_op == O_symbol
4518 && *str == '('
4519 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
4520 {
4521 inst.reloc.type = BFD_RELOC_ARM_PLT32;
4522 inst.reloc.pc_rel = 0;
4523 /* Modify str to point to after parsed operands, otherwise
4524 end_of_line() will complain about the (PLT) left in str. */
4525 str = input_line_pointer;
4526 }
4527 else
4528 {
4529 inst.reloc.type = BFD_RELOC_ARM_PCREL_BLX;
4530 inst.reloc.pc_rel = 1;
4531 }
4532
4533 input_line_pointer = save_in;
4534 }
4535 #else
4536 inst.reloc.type = BFD_RELOC_ARM_PCREL_BLX;
4537 inst.reloc.pc_rel = 1;
4538 #endif /* OBJ_ELF */
4539
4540 end_of_line (str);
4541 }
4542
4543 /* ARM V5 branch-link-exchange instruction (argument parse)
4544 BLX <target_addr> ie BLX(1)
4545 BLX{<condition>} <Rm> ie BLX(2)
4546 Unfortunately, there are two different opcodes for this mnemonic.
4547 So, the insns[].value is not used, and the code here zaps values
4548 into inst.instruction.
4549 Also, the <target_addr> can be 25 bits, hence has its own reloc. */
4550
4551 static void
4552 do_blx (str)
4553 char * str;
4554 {
4555 char * mystr = str;
4556 int rm;
4557
4558 skip_whitespace (mystr);
4559 rm = reg_required_here (& mystr, 0);
4560
4561 /* The above may set inst.error. Ignore his opinion. */
4562 inst.error = 0;
4563
4564 if (rm != FAIL)
4565 {
4566 /* Arg is a register.
4567 Use the condition code our caller put in inst.instruction.
4568 Pass ourselves off as a BX with a funny opcode. */
4569 inst.instruction |= 0x012fff30;
4570 do_bx (str);
4571 }
4572 else
4573 {
4574 /* This must be is BLX <target address>, no condition allowed. */
4575 if (inst.instruction != COND_ALWAYS)
4576 {
4577 inst.error = BAD_COND;
4578 return;
4579 }
4580
4581 inst.instruction = 0xfafffffe;
4582
4583 /* Process like a B/BL, but with a different reloc.
4584 Note that B/BL expecte fffffe, not 0, offset in the opcode table. */
4585 do_branch25 (str);
4586 }
4587 }
4588
4589 /* ARM V5 Thumb BLX (argument parse)
4590 BLX <target_addr> which is BLX(1)
4591 BLX <Rm> which is BLX(2)
4592 Unfortunately, there are two different opcodes for this mnemonic.
4593 So, the tinsns[].value is not used, and the code here zaps values
4594 into inst.instruction. */
4595
4596 static void
4597 do_t_blx (str)
4598 char * str;
4599 {
4600 char * mystr = str;
4601 int rm;
4602
4603 skip_whitespace (mystr);
4604 inst.instruction = 0x4780;
4605
4606 /* Note that this call is to the ARM register recognizer. BLX(2)
4607 uses the ARM register space, not the Thumb one, so a call to
4608 thumb_reg() would be wrong. */
4609 rm = reg_required_here (& mystr, 3);
4610 inst.error = 0;
4611
4612 if (rm != FAIL)
4613 {
4614 /* It's BLX(2). The .instruction was zapped with rm & is final. */
4615 inst.size = 2;
4616 }
4617 else
4618 {
4619 /* No ARM register. This must be BLX(1). Change the .instruction. */
4620 inst.instruction = 0xf7ffeffe;
4621 inst.size = 4;
4622
4623 if (my_get_expression (& inst.reloc.exp, & mystr))
4624 return;
4625
4626 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BLX;
4627 inst.reloc.pc_rel = 1;
4628 }
4629
4630 end_of_line (mystr);
4631 }
4632
4633 /* ARM V5 breakpoint instruction (argument parse)
4634 BKPT <16 bit unsigned immediate>
4635 Instruction is not conditional.
4636 The bit pattern given in insns[] has the COND_ALWAYS condition,
4637 and it is an error if the caller tried to override that. */
4638
4639 static void
4640 do_bkpt (str)
4641 char * str;
4642 {
4643 expressionS expr;
4644 unsigned long number;
4645
4646 skip_whitespace (str);
4647
4648 /* Allow optional leading '#'. */
4649 if (is_immediate_prefix (* str))
4650 str++;
4651
4652 memset (& expr, '\0', sizeof (expr));
4653
4654 if (my_get_expression (& expr, & str)
4655 || (expr.X_op != O_constant
4656 /* As a convenience we allow 'bkpt' without an operand. */
4657 && expr.X_op != O_absent))
4658 {
4659 inst.error = _("bad expression");
4660 return;
4661 }
4662
4663 number = expr.X_add_number;
4664
4665 /* Check it fits a 16 bit unsigned. */
4666 if (number != (number & 0xffff))
4667 {
4668 inst.error = _("immediate value out of range");
4669 return;
4670 }
4671
4672 /* Top 12 of 16 bits to bits 19:8. */
4673 inst.instruction |= (number & 0xfff0) << 4;
4674
4675 /* Bottom 4 of 16 bits to bits 3:0. */
4676 inst.instruction |= number & 0xf;
4677
4678 end_of_line (str);
4679 }
4680
4681 static unsigned long check_iwmmxt_insn PARAMS ((char *, enum iwmmxt_insn_type, int));
4682
4683 /* Parse INSN_TYPE insn STR having a possible IMMEDIATE_SIZE immediate. */
4684
4685 static unsigned long
4686 check_iwmmxt_insn (str, insn_type, immediate_size)
4687 char * str;
4688 enum iwmmxt_insn_type insn_type;
4689 int immediate_size;
4690 {
4691 int reg = 0;
4692 const char * inst_error;
4693 expressionS expr;
4694 unsigned long number;
4695
4696 inst_error = inst.error;
4697 if (!inst.error)
4698 inst.error = BAD_ARGS;
4699 skip_whitespace (str);
4700
4701 switch (insn_type)
4702 {
4703 case check_rd:
4704 if ((reg = reg_required_here (&str, 12)) == FAIL)
4705 return FAIL;
4706 break;
4707
4708 case check_wr:
4709 if ((wreg_required_here (&str, 0, IWMMXT_REG_WR)) == FAIL)
4710 return FAIL;
4711 break;
4712
4713 case check_wrwr:
4714 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
4715 || skip_past_comma (&str) == FAIL
4716 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL))
4717 return FAIL;
4718 break;
4719
4720 case check_wrwrwr:
4721 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
4722 || skip_past_comma (&str) == FAIL
4723 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
4724 || skip_past_comma (&str) == FAIL
4725 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL))
4726 return FAIL;
4727 break;
4728
4729 case check_wrwrwcg:
4730 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
4731 || skip_past_comma (&str) == FAIL
4732 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
4733 || skip_past_comma (&str) == FAIL
4734 || wreg_required_here (&str, 0, IWMMXT_REG_WCG) == FAIL))
4735 return FAIL;
4736 break;
4737
4738 case check_tbcst:
4739 if ((wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
4740 || skip_past_comma (&str) == FAIL
4741 || reg_required_here (&str, 12) == FAIL))
4742 return FAIL;
4743 break;
4744
4745 case check_tmovmsk:
4746 if ((reg_required_here (&str, 12) == FAIL
4747 || skip_past_comma (&str) == FAIL
4748 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL))
4749 return FAIL;
4750 break;
4751
4752 case check_tmia:
4753 if ((wreg_required_here (&str, 5, IWMMXT_REG_WR) == FAIL
4754 || skip_past_comma (&str) == FAIL
4755 || reg_required_here (&str, 0) == FAIL
4756 || skip_past_comma (&str) == FAIL
4757 || reg_required_here (&str, 12) == FAIL))
4758 return FAIL;
4759 break;
4760
4761 case check_tmcrr:
4762 if ((wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL
4763 || skip_past_comma (&str) == FAIL
4764 || reg_required_here (&str, 12) == FAIL
4765 || skip_past_comma (&str) == FAIL
4766 || reg_required_here (&str, 16) == FAIL))
4767 return FAIL;
4768 break;
4769
4770 case check_tmrrc:
4771 if ((reg_required_here (&str, 12) == FAIL
4772 || skip_past_comma (&str) == FAIL
4773 || reg_required_here (&str, 16) == FAIL
4774 || skip_past_comma (&str) == FAIL
4775 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL))
4776 return FAIL;
4777 break;
4778
4779 case check_tmcr:
4780 if ((wreg_required_here (&str, 16, IWMMXT_REG_WC) == FAIL
4781 || skip_past_comma (&str) == FAIL
4782 || reg_required_here (&str, 12) == FAIL))
4783 return FAIL;
4784 break;
4785
4786 case check_tmrc:
4787 if ((reg_required_here (&str, 12) == FAIL
4788 || skip_past_comma (&str) == FAIL
4789 || wreg_required_here (&str, 16, IWMMXT_REG_WC) == FAIL))
4790 return FAIL;
4791 break;
4792
4793 case check_tinsr:
4794 if ((wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
4795 || skip_past_comma (&str) == FAIL
4796 || reg_required_here (&str, 12) == FAIL
4797 || skip_past_comma (&str) == FAIL))
4798 return FAIL;
4799 break;
4800
4801 case check_textrc:
4802 if ((reg_required_here (&str, 12) == FAIL
4803 || skip_past_comma (&str) == FAIL))
4804 return FAIL;
4805 break;
4806
4807 case check_waligni:
4808 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
4809 || skip_past_comma (&str) == FAIL
4810 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
4811 || skip_past_comma (&str) == FAIL
4812 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL
4813 || skip_past_comma (&str) == FAIL))
4814 return FAIL;
4815 break;
4816
4817 case check_textrm:
4818 if ((reg_required_here (&str, 12) == FAIL
4819 || skip_past_comma (&str) == FAIL
4820 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
4821 || skip_past_comma (&str) == FAIL))
4822 return FAIL;
4823 break;
4824
4825 case check_wshufh:
4826 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
4827 || skip_past_comma (&str) == FAIL
4828 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
4829 || skip_past_comma (&str) == FAIL))
4830 return FAIL;
4831 break;
4832 }
4833
4834 if (immediate_size == 0)
4835 {
4836 end_of_line (str);
4837 inst.error = inst_error;
4838 return reg;
4839 }
4840 else
4841 {
4842 skip_whitespace (str);
4843
4844 /* Allow optional leading '#'. */
4845 if (is_immediate_prefix (* str))
4846 str++;
4847
4848 memset (& expr, '\0', sizeof (expr));
4849
4850 if (my_get_expression (& expr, & str) || (expr.X_op != O_constant))
4851 {
4852 inst.error = _("bad or missing expression");
4853 return FAIL;
4854 }
4855
4856 number = expr.X_add_number;
4857
4858 if (number != (number & immediate_size))
4859 {
4860 inst.error = _("immediate value out of range");
4861 return FAIL;
4862 }
4863 end_of_line (str);
4864 inst.error = inst_error;
4865 return number;
4866 }
4867 }
4868
4869 static void
4870 do_iwmmxt_byte_addr (str)
4871 char * str;
4872 {
4873 int op = (inst.instruction & 0x300) >> 8;
4874 int reg;
4875
4876 inst.instruction &= ~0x300;
4877 inst.instruction |= (op & 1) << 22 | (op & 2) << 7;
4878
4879 skip_whitespace (str);
4880
4881 if ((reg = wreg_required_here (&str, 12, IWMMXT_REG_WR_OR_WC)) == FAIL
4882 || skip_past_comma (& str) == FAIL
4883 || cp_byte_address_required_here (&str) == FAIL)
4884 {
4885 if (! inst.error)
4886 inst.error = BAD_ARGS;
4887 }
4888 else
4889 end_of_line (str);
4890
4891 if (wc_register (reg))
4892 {
4893 inst.instruction |= 0xf0000100;
4894 inst.instruction &= ~0x00400000;
4895 }
4896 }
4897
4898 static void
4899 do_iwmmxt_tandc (str)
4900 char * str;
4901 {
4902 int reg;
4903
4904 reg = check_iwmmxt_insn (str, check_rd, 0);
4905
4906 if (reg != REG_PC && !inst.error)
4907 inst.error = _("only r15 allowed here");
4908 return;
4909 }
4910
4911 static void
4912 do_iwmmxt_tbcst (str)
4913 char * str;
4914 {
4915 check_iwmmxt_insn (str, check_tbcst, 0);
4916
4917 return;
4918 }
4919
4920 static void
4921 do_iwmmxt_textrc (str)
4922 char * str;
4923 {
4924 unsigned long number;
4925
4926 if ((number = check_iwmmxt_insn (str, check_textrc, 7)) == (unsigned long) FAIL)
4927 return;
4928
4929 inst.instruction |= number & 0x7;
4930 return;
4931 }
4932
4933 static void
4934 do_iwmmxt_textrm (str)
4935 char * str;
4936 {
4937 unsigned long number;
4938
4939 if ((number = check_iwmmxt_insn (str, check_textrm, 7)) == (unsigned long) FAIL)
4940 return;
4941
4942 inst.instruction |= number & 0x7;
4943 }
4944
4945 static void
4946 do_iwmmxt_tinsr (str)
4947 char * str;
4948 {
4949 unsigned long number;
4950
4951 if ((number = check_iwmmxt_insn (str, check_tinsr, 7)) == (unsigned long) FAIL)
4952 return;
4953
4954 inst.instruction |= number & 0x7;
4955 return;
4956 }
4957
4958 static void
4959 do_iwmmxt_tmcr (str)
4960 char * str;
4961 {
4962 check_iwmmxt_insn (str, check_tmcr, 0);
4963
4964 return;
4965 }
4966
4967 static void
4968 do_iwmmxt_tmcrr (str)
4969 char * str;
4970 {
4971 check_iwmmxt_insn (str, check_tmcrr, 0);
4972
4973 return;
4974 }
4975
4976 static void
4977 do_iwmmxt_tmia (str)
4978 char * str;
4979 {
4980 check_iwmmxt_insn (str, check_tmia, 0);
4981
4982 return;
4983 }
4984
4985 static void
4986 do_iwmmxt_tmovmsk (str)
4987 char * str;
4988 {
4989 check_iwmmxt_insn (str, check_tmovmsk, 0);
4990
4991 return;
4992 }
4993
4994 static void
4995 do_iwmmxt_tmrc (str)
4996 char * str;
4997 {
4998 check_iwmmxt_insn (str, check_tmrc, 0);
4999
5000 return;
5001 }
5002
5003 static void
5004 do_iwmmxt_tmrrc (str)
5005 char * str;
5006 {
5007 check_iwmmxt_insn (str, check_tmrrc, 0);
5008
5009 return;
5010 }
5011
5012 static void
5013 do_iwmmxt_torc (str)
5014 char * str;
5015 {
5016 check_iwmmxt_insn (str, check_rd, 0);
5017 return;
5018 }
5019
5020 static void
5021 do_iwmmxt_waligni (str)
5022 char * str;
5023 {
5024 unsigned long number;
5025
5026 if ((number = check_iwmmxt_insn (str, check_waligni, 7)) == (unsigned long) FAIL)
5027 return;
5028
5029 inst.instruction |= ((number & 0x7) << 20);
5030 return;
5031 }
5032
5033 static void
5034 do_iwmmxt_wmov (str)
5035 char * str;
5036 {
5037 if (check_iwmmxt_insn (str, check_wrwr, 0) == (unsigned long) FAIL)
5038 return;
5039
5040 inst.instruction |= ((inst.instruction >> 16) & 0xf);
5041 return;
5042 }
5043
5044 static void
5045 do_iwmmxt_word_addr (str)
5046 char * str;
5047 {
5048 int op = (inst.instruction & 0x300) >> 8;
5049 int reg;
5050
5051 inst.instruction &= ~0x300;
5052 inst.instruction |= (op & 1) << 22 | (op & 2) << 7;
5053
5054 skip_whitespace (str);
5055
5056 if ((reg = wreg_required_here (&str, 12, IWMMXT_REG_WR_OR_WC)) == FAIL
5057 || skip_past_comma (& str) == FAIL
5058 || cp_address_required_here (& str, CP_WB_OK) == FAIL)
5059 {
5060 if (! inst.error)
5061 inst.error = BAD_ARGS;
5062 }
5063 else
5064 end_of_line (str);
5065
5066 if (wc_register (reg))
5067 {
5068 inst.instruction |= 0xf0000100;
5069 inst.instruction &= ~0x00400000;
5070 }
5071 }
5072
5073 static void
5074 do_iwmmxt_wrwr (str)
5075 char * str;
5076 {
5077 check_iwmmxt_insn (str, check_wrwr, 0);
5078
5079 return;
5080 }
5081
5082 static void
5083 do_iwmmxt_wrwrwcg (str)
5084 char * str;
5085 {
5086 check_iwmmxt_insn (str, check_wrwrwcg, 0);
5087
5088 return;
5089 }
5090
5091 static void
5092 do_iwmmxt_wrwrwr (str)
5093 char * str;
5094 {
5095 check_iwmmxt_insn (str, check_wrwrwr, 0);
5096
5097 return;
5098 }
5099
5100 static void
5101 do_iwmmxt_wshufh (str)
5102 char * str;
5103 {
5104 unsigned long number;
5105
5106 if ((number = check_iwmmxt_insn (str, check_wshufh, 0xff)) == (unsigned long) FAIL)
5107 return;
5108
5109 inst.instruction |= ((number & 0xf0) << 16) | (number & 0xf);
5110 return;
5111 }
5112
5113 static void
5114 do_iwmmxt_wzero (str)
5115 char * str;
5116 {
5117 if (check_iwmmxt_insn (str, check_wr, 0) == (unsigned long) FAIL)
5118 return;
5119
5120 inst.instruction |= ((inst.instruction & 0xf) << 12) | ((inst.instruction & 0xf) << 16);
5121 return;
5122 }
5123
5124 /* Xscale multiply-accumulate (argument parse)
5125 MIAcc acc0,Rm,Rs
5126 MIAPHcc acc0,Rm,Rs
5127 MIAxycc acc0,Rm,Rs. */
5128
5129 static void
5130 do_xsc_mia (str)
5131 char * str;
5132 {
5133 int rs;
5134 int rm;
5135
5136 if (accum0_required_here (& str) == FAIL)
5137 inst.error = ERR_NO_ACCUM;
5138
5139 else if (skip_past_comma (& str) == FAIL
5140 || (rm = reg_required_here (& str, 0)) == FAIL)
5141 inst.error = BAD_ARGS;
5142
5143 else if (skip_past_comma (& str) == FAIL
5144 || (rs = reg_required_here (& str, 12)) == FAIL)
5145 inst.error = BAD_ARGS;
5146
5147 /* inst.instruction has now been zapped with both rm and rs. */
5148 else if (rm == REG_PC || rs == REG_PC)
5149 inst.error = BAD_PC; /* Undefined result if rm or rs is R15. */
5150
5151 else
5152 end_of_line (str);
5153 }
5154
5155 /* Xscale move-accumulator-register (argument parse)
5156
5157 MARcc acc0,RdLo,RdHi. */
5158
5159 static void
5160 do_xsc_mar (str)
5161 char * str;
5162 {
5163 int rdlo, rdhi;
5164
5165 if (accum0_required_here (& str) == FAIL)
5166 inst.error = ERR_NO_ACCUM;
5167
5168 else if (skip_past_comma (& str) == FAIL
5169 || (rdlo = reg_required_here (& str, 12)) == FAIL)
5170 inst.error = BAD_ARGS;
5171
5172 else if (skip_past_comma (& str) == FAIL
5173 || (rdhi = reg_required_here (& str, 16)) == FAIL)
5174 inst.error = BAD_ARGS;
5175
5176 /* inst.instruction has now been zapped with both rdlo and rdhi. */
5177 else if (rdlo == REG_PC || rdhi == REG_PC)
5178 inst.error = BAD_PC; /* Undefined result if rdlo or rdhi is R15. */
5179
5180 else
5181 end_of_line (str);
5182 }
5183
5184 /* Xscale move-register-accumulator (argument parse)
5185
5186 MRAcc RdLo,RdHi,acc0. */
5187
5188 static void
5189 do_xsc_mra (str)
5190 char * str;
5191 {
5192 int rdlo;
5193 int rdhi;
5194
5195 skip_whitespace (str);
5196
5197 if ((rdlo = reg_required_here (& str, 12)) == FAIL)
5198 inst.error = BAD_ARGS;
5199
5200 else if (skip_past_comma (& str) == FAIL
5201 || (rdhi = reg_required_here (& str, 16)) == FAIL)
5202 inst.error = BAD_ARGS;
5203
5204 else if (skip_past_comma (& str) == FAIL
5205 || accum0_required_here (& str) == FAIL)
5206 inst.error = ERR_NO_ACCUM;
5207
5208 /* inst.instruction has now been zapped with both rdlo and rdhi. */
5209 else if (rdlo == rdhi)
5210 inst.error = BAD_ARGS; /* Undefined result if 2 writes to same reg. */
5211
5212 else if (rdlo == REG_PC || rdhi == REG_PC)
5213 inst.error = BAD_PC; /* Undefined result if rdlo or rdhi is R15. */
5214 else
5215 end_of_line (str);
5216 }
5217
5218 /* ARMv5TE: Preload-Cache
5219
5220 PLD <addr_mode>
5221
5222 Syntactically, like LDR with B=1, W=0, L=1. */
5223
5224 static void
5225 do_pld (str)
5226 char * str;
5227 {
5228 int rd;
5229
5230 skip_whitespace (str);
5231
5232 if (* str != '[')
5233 {
5234 inst.error = _("'[' expected after PLD mnemonic");
5235 return;
5236 }
5237
5238 ++str;
5239 skip_whitespace (str);
5240
5241 if ((rd = reg_required_here (& str, 16)) == FAIL)
5242 return;
5243
5244 skip_whitespace (str);
5245
5246 if (*str == ']')
5247 {
5248 /* [Rn], ... ? */
5249 ++str;
5250 skip_whitespace (str);
5251
5252 /* Post-indexed addressing is not allowed with PLD. */
5253 if (skip_past_comma (&str) == SUCCESS)
5254 {
5255 inst.error
5256 = _("post-indexed expression used in preload instruction");
5257 return;
5258 }
5259 else if (*str == '!') /* [Rn]! */
5260 {
5261 inst.error = _("writeback used in preload instruction");
5262 ++str;
5263 }
5264 else /* [Rn] */
5265 inst.instruction |= INDEX_UP | PRE_INDEX;
5266 }
5267 else /* [Rn, ...] */
5268 {
5269 if (skip_past_comma (& str) == FAIL)
5270 {
5271 inst.error = _("pre-indexed expression expected");
5272 return;
5273 }
5274
5275 if (ldst_extend (&str) == FAIL)
5276 return;
5277
5278 skip_whitespace (str);
5279
5280 if (* str != ']')
5281 {
5282 inst.error = _("missing ]");
5283 return;
5284 }
5285
5286 ++ str;
5287 skip_whitespace (str);
5288
5289 if (* str == '!') /* [Rn]! */
5290 {
5291 inst.error = _("writeback used in preload instruction");
5292 ++ str;
5293 }
5294
5295 inst.instruction |= PRE_INDEX;
5296 }
5297
5298 end_of_line (str);
5299 }
5300
5301 /* ARMv5TE load-consecutive (argument parse)
5302 Mode is like LDRH.
5303
5304 LDRccD R, mode
5305 STRccD R, mode. */
5306
5307 static void
5308 do_ldrd (str)
5309 char * str;
5310 {
5311 int rd;
5312 int rn;
5313
5314 skip_whitespace (str);
5315
5316 if ((rd = reg_required_here (& str, 12)) == FAIL)
5317 {
5318 inst.error = BAD_ARGS;
5319 return;
5320 }
5321
5322 if (skip_past_comma (& str) == FAIL
5323 || (rn = ld_mode_required_here (& str)) == FAIL)
5324 {
5325 if (!inst.error)
5326 inst.error = BAD_ARGS;
5327 return;
5328 }
5329
5330 /* inst.instruction has now been zapped with Rd and the addressing mode. */
5331 if (rd & 1) /* Unpredictable result if Rd is odd. */
5332 {
5333 inst.error = _("destination register must be even");
5334 return;
5335 }
5336
5337 if (rd == REG_LR)
5338 {
5339 inst.error = _("r14 not allowed here");
5340 return;
5341 }
5342
5343 if (((rd == rn) || (rd + 1 == rn))
5344 && ((inst.instruction & WRITE_BACK)
5345 || (!(inst.instruction & PRE_INDEX))))
5346 as_warn (_("pre/post-indexing used when modified address register is destination"));
5347
5348 /* For an index-register load, the index register must not overlap the
5349 destination (even if not write-back). */
5350 if ((inst.instruction & V4_STR_BIT) == 0
5351 && (inst.instruction & HWOFFSET_IMM) == 0)
5352 {
5353 int rm = inst.instruction & 0x0000000f;
5354
5355 if (rm == rd || (rm == rd + 1))
5356 as_warn (_("ldrd destination registers must not overlap index register"));
5357 }
5358
5359 end_of_line (str);
5360 }
5361
5362 /* Returns the index into fp_values of a floating point number,
5363 or -1 if not in the table. */
5364
5365 static int
5366 my_get_float_expression (str)
5367 char ** str;
5368 {
5369 LITTLENUM_TYPE words[MAX_LITTLENUMS];
5370 char * save_in;
5371 expressionS exp;
5372 int i;
5373 int j;
5374
5375 memset (words, 0, MAX_LITTLENUMS * sizeof (LITTLENUM_TYPE));
5376
5377 /* Look for a raw floating point number. */
5378 if ((save_in = atof_ieee (*str, 'x', words)) != NULL
5379 && is_end_of_line[(unsigned char) *save_in])
5380 {
5381 for (i = 0; i < NUM_FLOAT_VALS; i++)
5382 {
5383 for (j = 0; j < MAX_LITTLENUMS; j++)
5384 {
5385 if (words[j] != fp_values[i][j])
5386 break;
5387 }
5388
5389 if (j == MAX_LITTLENUMS)
5390 {
5391 *str = save_in;
5392 return i;
5393 }
5394 }
5395 }
5396
5397 /* Try and parse a more complex expression, this will probably fail
5398 unless the code uses a floating point prefix (eg "0f"). */
5399 save_in = input_line_pointer;
5400 input_line_pointer = *str;
5401 if (expression (&exp) == absolute_section
5402 && exp.X_op == O_big
5403 && exp.X_add_number < 0)
5404 {
5405 /* FIXME: 5 = X_PRECISION, should be #define'd where we can use it.
5406 Ditto for 15. */
5407 if (gen_to_words (words, 5, (long) 15) == 0)
5408 {
5409 for (i = 0; i < NUM_FLOAT_VALS; i++)
5410 {
5411 for (j = 0; j < MAX_LITTLENUMS; j++)
5412 {
5413 if (words[j] != fp_values[i][j])
5414 break;
5415 }
5416
5417 if (j == MAX_LITTLENUMS)
5418 {
5419 *str = input_line_pointer;
5420 input_line_pointer = save_in;
5421 return i;
5422 }
5423 }
5424 }
5425 }
5426
5427 *str = input_line_pointer;
5428 input_line_pointer = save_in;
5429 return -1;
5430 }
5431
5432 /* Return TRUE if anything in the expression is a bignum. */
5433
5434 static int
5435 walk_no_bignums (sp)
5436 symbolS * sp;
5437 {
5438 if (symbol_get_value_expression (sp)->X_op == O_big)
5439 return 1;
5440
5441 if (symbol_get_value_expression (sp)->X_add_symbol)
5442 {
5443 return (walk_no_bignums (symbol_get_value_expression (sp)->X_add_symbol)
5444 || (symbol_get_value_expression (sp)->X_op_symbol
5445 && walk_no_bignums (symbol_get_value_expression (sp)->X_op_symbol)));
5446 }
5447
5448 return 0;
5449 }
5450
5451 static int in_my_get_expression = 0;
5452
5453 static int
5454 my_get_expression (ep, str)
5455 expressionS * ep;
5456 char ** str;
5457 {
5458 char * save_in;
5459 segT seg;
5460
5461 save_in = input_line_pointer;
5462 input_line_pointer = *str;
5463 in_my_get_expression = 1;
5464 seg = expression (ep);
5465 in_my_get_expression = 0;
5466
5467 if (ep->X_op == O_illegal)
5468 {
5469 /* We found a bad expression in md_operand(). */
5470 *str = input_line_pointer;
5471 input_line_pointer = save_in;
5472 return 1;
5473 }
5474
5475 #ifdef OBJ_AOUT
5476 if (seg != absolute_section
5477 && seg != text_section
5478 && seg != data_section
5479 && seg != bss_section
5480 && seg != undefined_section)
5481 {
5482 inst.error = _("bad_segment");
5483 *str = input_line_pointer;
5484 input_line_pointer = save_in;
5485 return 1;
5486 }
5487 #endif
5488
5489 /* Get rid of any bignums now, so that we don't generate an error for which
5490 we can't establish a line number later on. Big numbers are never valid
5491 in instructions, which is where this routine is always called. */
5492 if (ep->X_op == O_big
5493 || (ep->X_add_symbol
5494 && (walk_no_bignums (ep->X_add_symbol)
5495 || (ep->X_op_symbol
5496 && walk_no_bignums (ep->X_op_symbol)))))
5497 {
5498 inst.error = _("invalid constant");
5499 *str = input_line_pointer;
5500 input_line_pointer = save_in;
5501 return 1;
5502 }
5503
5504 *str = input_line_pointer;
5505 input_line_pointer = save_in;
5506 return 0;
5507 }
5508
5509 /* We handle all bad expressions here, so that we can report the faulty
5510 instruction in the error message. */
5511 void
5512 md_operand (expr)
5513 expressionS *expr;
5514 {
5515 if (in_my_get_expression)
5516 {
5517 expr->X_op = O_illegal;
5518 if (inst.error == NULL)
5519 inst.error = _("bad expression");
5520 }
5521 }
5522
5523 /* UNRESTRICT should be one if <shift> <register> is permitted for this
5524 instruction. */
5525
5526 static int
5527 decode_shift (str, unrestrict)
5528 char ** str;
5529 int unrestrict;
5530 {
5531 const struct asm_shift_name * shift;
5532 char * p;
5533 char c;
5534
5535 skip_whitespace (* str);
5536
5537 for (p = * str; ISALPHA (* p); p ++)
5538 ;
5539
5540 if (p == * str)
5541 {
5542 inst.error = _("shift expression expected");
5543 return FAIL;
5544 }
5545
5546 c = * p;
5547 * p = '\0';
5548 shift = (const struct asm_shift_name *) hash_find (arm_shift_hsh, * str);
5549 * p = c;
5550
5551 if (shift == NULL)
5552 {
5553 inst.error = _("shift expression expected");
5554 return FAIL;
5555 }
5556
5557 assert (shift->properties->index == shift_properties[shift->properties->index].index);
5558
5559 if (shift->properties->index == SHIFT_RRX)
5560 {
5561 * str = p;
5562 inst.instruction |= shift->properties->bit_field;
5563 return SUCCESS;
5564 }
5565
5566 skip_whitespace (p);
5567
5568 if (unrestrict && reg_required_here (& p, 8) != FAIL)
5569 {
5570 inst.instruction |= shift->properties->bit_field | SHIFT_BY_REG;
5571 * str = p;
5572 return SUCCESS;
5573 }
5574 else if (! is_immediate_prefix (* p))
5575 {
5576 inst.error = (unrestrict
5577 ? _("shift requires register or #expression")
5578 : _("shift requires #expression"));
5579 * str = p;
5580 return FAIL;
5581 }
5582
5583 inst.error = NULL;
5584 p ++;
5585
5586 if (my_get_expression (& inst.reloc.exp, & p))
5587 return FAIL;
5588
5589 /* Validate some simple #expressions. */
5590 if (inst.reloc.exp.X_op == O_constant)
5591 {
5592 unsigned num = inst.reloc.exp.X_add_number;
5593
5594 /* Reject operations greater than 32. */
5595 if (num > 32
5596 /* Reject a shift of 0 unless the mode allows it. */
5597 || (num == 0 && shift->properties->allows_0 == 0)
5598 /* Reject a shift of 32 unless the mode allows it. */
5599 || (num == 32 && shift->properties->allows_32 == 0)
5600 )
5601 {
5602 /* As a special case we allow a shift of zero for
5603 modes that do not support it to be recoded as an
5604 logical shift left of zero (ie nothing). We warn
5605 about this though. */
5606 if (num == 0)
5607 {
5608 as_warn (_("shift of 0 ignored."));
5609 shift = & shift_names[0];
5610 assert (shift->properties->index == SHIFT_LSL);
5611 }
5612 else
5613 {
5614 inst.error = _("invalid immediate shift");
5615 return FAIL;
5616 }
5617 }
5618
5619 /* Shifts of 32 are encoded as 0, for those shifts that
5620 support it. */
5621 if (num == 32)
5622 num = 0;
5623
5624 inst.instruction |= (num << 7) | shift->properties->bit_field;
5625 }
5626 else
5627 {
5628 inst.reloc.type = BFD_RELOC_ARM_SHIFT_IMM;
5629 inst.reloc.pc_rel = 0;
5630 inst.instruction |= shift->properties->bit_field;
5631 }
5632
5633 * str = p;
5634 return SUCCESS;
5635 }
5636
5637 /* Do those data_ops which can take a negative immediate constant
5638 by altering the instuction. A bit of a hack really.
5639 MOV <-> MVN
5640 AND <-> BIC
5641 ADC <-> SBC
5642 by inverting the second operand, and
5643 ADD <-> SUB
5644 CMP <-> CMN
5645 by negating the second operand. */
5646
5647 static int
5648 negate_data_op (instruction, value)
5649 unsigned long * instruction;
5650 unsigned long value;
5651 {
5652 int op, new_inst;
5653 unsigned long negated, inverted;
5654
5655 negated = validate_immediate (-value);
5656 inverted = validate_immediate (~value);
5657
5658 op = (*instruction >> DATA_OP_SHIFT) & 0xf;
5659 switch (op)
5660 {
5661 /* First negates. */
5662 case OPCODE_SUB: /* ADD <-> SUB */
5663 new_inst = OPCODE_ADD;
5664 value = negated;
5665 break;
5666
5667 case OPCODE_ADD:
5668 new_inst = OPCODE_SUB;
5669 value = negated;
5670 break;
5671
5672 case OPCODE_CMP: /* CMP <-> CMN */
5673 new_inst = OPCODE_CMN;
5674 value = negated;
5675 break;
5676
5677 case OPCODE_CMN:
5678 new_inst = OPCODE_CMP;
5679 value = negated;
5680 break;
5681
5682 /* Now Inverted ops. */
5683 case OPCODE_MOV: /* MOV <-> MVN */
5684 new_inst = OPCODE_MVN;
5685 value = inverted;
5686 break;
5687
5688 case OPCODE_MVN:
5689 new_inst = OPCODE_MOV;
5690 value = inverted;
5691 break;
5692
5693 case OPCODE_AND: /* AND <-> BIC */
5694 new_inst = OPCODE_BIC;
5695 value = inverted;
5696 break;
5697
5698 case OPCODE_BIC:
5699 new_inst = OPCODE_AND;
5700 value = inverted;
5701 break;
5702
5703 case OPCODE_ADC: /* ADC <-> SBC */
5704 new_inst = OPCODE_SBC;
5705 value = inverted;
5706 break;
5707
5708 case OPCODE_SBC:
5709 new_inst = OPCODE_ADC;
5710 value = inverted;
5711 break;
5712
5713 /* We cannot do anything. */
5714 default:
5715 return FAIL;
5716 }
5717
5718 if (value == (unsigned) FAIL)
5719 return FAIL;
5720
5721 *instruction &= OPCODE_MASK;
5722 *instruction |= new_inst << DATA_OP_SHIFT;
5723 return value;
5724 }
5725
5726 static int
5727 data_op2 (str)
5728 char ** str;
5729 {
5730 int value;
5731 expressionS expr;
5732
5733 skip_whitespace (* str);
5734
5735 if (reg_required_here (str, 0) != FAIL)
5736 {
5737 if (skip_past_comma (str) == SUCCESS)
5738 /* Shift operation on register. */
5739 return decode_shift (str, NO_SHIFT_RESTRICT);
5740
5741 return SUCCESS;
5742 }
5743 else
5744 {
5745 /* Immediate expression. */
5746 if (is_immediate_prefix (**str))
5747 {
5748 (*str)++;
5749 inst.error = NULL;
5750
5751 if (my_get_expression (&inst.reloc.exp, str))
5752 return FAIL;
5753
5754 if (inst.reloc.exp.X_add_symbol)
5755 {
5756 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
5757 inst.reloc.pc_rel = 0;
5758 }
5759 else
5760 {
5761 if (skip_past_comma (str) == SUCCESS)
5762 {
5763 /* #x, y -- ie explicit rotation by Y. */
5764 if (my_get_expression (&expr, str))
5765 return FAIL;
5766
5767 if (expr.X_op != O_constant)
5768 {
5769 inst.error = _("constant expression expected");
5770 return FAIL;
5771 }
5772
5773 /* Rotate must be a multiple of 2. */
5774 if (((unsigned) expr.X_add_number) > 30
5775 || (expr.X_add_number & 1) != 0
5776 || ((unsigned) inst.reloc.exp.X_add_number) > 255)
5777 {
5778 inst.error = _("invalid constant");
5779 return FAIL;
5780 }
5781 inst.instruction |= INST_IMMEDIATE;
5782 inst.instruction |= inst.reloc.exp.X_add_number;
5783 inst.instruction |= expr.X_add_number << 7;
5784 return SUCCESS;
5785 }
5786
5787 /* Implicit rotation, select a suitable one. */
5788 value = validate_immediate (inst.reloc.exp.X_add_number);
5789
5790 if (value == FAIL)
5791 {
5792 /* Can't be done. Perhaps the code reads something like
5793 "add Rd, Rn, #-n", where "sub Rd, Rn, #n" would be OK. */
5794 if ((value = negate_data_op (&inst.instruction,
5795 inst.reloc.exp.X_add_number))
5796 == FAIL)
5797 {
5798 inst.error = _("invalid constant");
5799 return FAIL;
5800 }
5801 }
5802
5803 inst.instruction |= value;
5804 }
5805
5806 inst.instruction |= INST_IMMEDIATE;
5807 return SUCCESS;
5808 }
5809
5810 (*str)++;
5811 inst.error = _("register or shift expression expected");
5812 return FAIL;
5813 }
5814 }
5815
5816 static int
5817 fp_op2 (str)
5818 char ** str;
5819 {
5820 skip_whitespace (* str);
5821
5822 if (fp_reg_required_here (str, 0) != FAIL)
5823 return SUCCESS;
5824 else
5825 {
5826 /* Immediate expression. */
5827 if (*((*str)++) == '#')
5828 {
5829 int i;
5830
5831 inst.error = NULL;
5832
5833 skip_whitespace (* str);
5834
5835 /* First try and match exact strings, this is to guarantee
5836 that some formats will work even for cross assembly. */
5837
5838 for (i = 0; fp_const[i]; i++)
5839 {
5840 if (strncmp (*str, fp_const[i], strlen (fp_const[i])) == 0)
5841 {
5842 char *start = *str;
5843
5844 *str += strlen (fp_const[i]);
5845 if (is_end_of_line[(unsigned char) **str])
5846 {
5847 inst.instruction |= i + 8;
5848 return SUCCESS;
5849 }
5850 *str = start;
5851 }
5852 }
5853
5854 /* Just because we didn't get a match doesn't mean that the
5855 constant isn't valid, just that it is in a format that we
5856 don't automatically recognize. Try parsing it with
5857 the standard expression routines. */
5858 if ((i = my_get_float_expression (str)) >= 0)
5859 {
5860 inst.instruction |= i + 8;
5861 return SUCCESS;
5862 }
5863
5864 inst.error = _("invalid floating point immediate expression");
5865 return FAIL;
5866 }
5867 inst.error =
5868 _("floating point register or immediate expression expected");
5869 return FAIL;
5870 }
5871 }
5872
5873 static void
5874 do_arit (str)
5875 char * str;
5876 {
5877 skip_whitespace (str);
5878
5879 if (reg_required_here (&str, 12) == FAIL
5880 || skip_past_comma (&str) == FAIL
5881 || reg_required_here (&str, 16) == FAIL
5882 || skip_past_comma (&str) == FAIL
5883 || data_op2 (&str) == FAIL)
5884 {
5885 if (!inst.error)
5886 inst.error = BAD_ARGS;
5887 return;
5888 }
5889
5890 end_of_line (str);
5891 return;
5892 }
5893
5894 static void
5895 do_adr (str)
5896 char * str;
5897 {
5898 /* This is a pseudo-op of the form "adr rd, label" to be converted
5899 into a relative address of the form "add rd, pc, #label-.-8". */
5900 skip_whitespace (str);
5901
5902 if (reg_required_here (&str, 12) == FAIL
5903 || skip_past_comma (&str) == FAIL
5904 || my_get_expression (&inst.reloc.exp, &str))
5905 {
5906 if (!inst.error)
5907 inst.error = BAD_ARGS;
5908 return;
5909 }
5910
5911 /* Frag hacking will turn this into a sub instruction if the offset turns
5912 out to be negative. */
5913 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
5914 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust. */
5915 inst.reloc.pc_rel = 1;
5916
5917 end_of_line (str);
5918 }
5919
5920 static void
5921 do_adrl (str)
5922 char * str;
5923 {
5924 /* This is a pseudo-op of the form "adrl rd, label" to be converted
5925 into a relative address of the form:
5926 add rd, pc, #low(label-.-8)"
5927 add rd, rd, #high(label-.-8)" */
5928
5929 skip_whitespace (str);
5930
5931 if (reg_required_here (&str, 12) == FAIL
5932 || skip_past_comma (&str) == FAIL
5933 || my_get_expression (&inst.reloc.exp, &str))
5934 {
5935 if (!inst.error)
5936 inst.error = BAD_ARGS;
5937
5938 return;
5939 }
5940
5941 end_of_line (str);
5942 /* Frag hacking will turn this into a sub instruction if the offset turns
5943 out to be negative. */
5944 inst.reloc.type = BFD_RELOC_ARM_ADRL_IMMEDIATE;
5945 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust */
5946 inst.reloc.pc_rel = 1;
5947 inst.size = INSN_SIZE * 2;
5948
5949 return;
5950 }
5951
5952 static void
5953 do_cmp (str)
5954 char * str;
5955 {
5956 skip_whitespace (str);
5957
5958 if (reg_required_here (&str, 16) == FAIL)
5959 {
5960 if (!inst.error)
5961 inst.error = BAD_ARGS;
5962 return;
5963 }
5964
5965 if (skip_past_comma (&str) == FAIL
5966 || data_op2 (&str) == FAIL)
5967 {
5968 if (!inst.error)
5969 inst.error = BAD_ARGS;
5970 return;
5971 }
5972
5973 end_of_line (str);
5974 return;
5975 }
5976
5977 static void
5978 do_mov (str)
5979 char * str;
5980 {
5981 skip_whitespace (str);
5982
5983 if (reg_required_here (&str, 12) == FAIL)
5984 {
5985 if (!inst.error)
5986 inst.error = BAD_ARGS;
5987 return;
5988 }
5989
5990 if (skip_past_comma (&str) == FAIL
5991 || data_op2 (&str) == FAIL)
5992 {
5993 if (!inst.error)
5994 inst.error = BAD_ARGS;
5995 return;
5996 }
5997
5998 end_of_line (str);
5999 return;
6000 }
6001
6002 static int
6003 ldst_extend (str)
6004 char ** str;
6005 {
6006 int add = INDEX_UP;
6007
6008 switch (**str)
6009 {
6010 case '#':
6011 case '$':
6012 (*str)++;
6013 if (my_get_expression (& inst.reloc.exp, str))
6014 return FAIL;
6015
6016 if (inst.reloc.exp.X_op == O_constant)
6017 {
6018 int value = inst.reloc.exp.X_add_number;
6019
6020 if (value < -4095 || value > 4095)
6021 {
6022 inst.error = _("address offset too large");
6023 return FAIL;
6024 }
6025
6026 if (value < 0)
6027 {
6028 value = -value;
6029 add = 0;
6030 }
6031
6032 inst.instruction |= add | value;
6033 }
6034 else
6035 {
6036 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
6037 inst.reloc.pc_rel = 0;
6038 }
6039 return SUCCESS;
6040
6041 case '-':
6042 add = 0;
6043 /* Fall through. */
6044
6045 case '+':
6046 (*str)++;
6047 /* Fall through. */
6048
6049 default:
6050 if (reg_required_here (str, 0) == FAIL)
6051 return FAIL;
6052
6053 inst.instruction |= add | OFFSET_REG;
6054 if (skip_past_comma (str) == SUCCESS)
6055 return decode_shift (str, SHIFT_RESTRICT);
6056
6057 return SUCCESS;
6058 }
6059 }
6060
6061 static void
6062 do_ldst (str)
6063 char * str;
6064 {
6065 int pre_inc = 0;
6066 int conflict_reg;
6067 int value;
6068
6069 skip_whitespace (str);
6070
6071 if ((conflict_reg = reg_required_here (&str, 12)) == FAIL)
6072 {
6073 if (!inst.error)
6074 inst.error = BAD_ARGS;
6075 return;
6076 }
6077
6078 if (skip_past_comma (&str) == FAIL)
6079 {
6080 inst.error = _("address expected");
6081 return;
6082 }
6083
6084 if (*str == '[')
6085 {
6086 int reg;
6087
6088 str++;
6089
6090 skip_whitespace (str);
6091
6092 if ((reg = reg_required_here (&str, 16)) == FAIL)
6093 return;
6094
6095 /* Conflicts can occur on stores as well as loads. */
6096 conflict_reg = (conflict_reg == reg);
6097
6098 skip_whitespace (str);
6099
6100 if (*str == ']')
6101 {
6102 str ++;
6103
6104 if (skip_past_comma (&str) == SUCCESS)
6105 {
6106 /* [Rn],... (post inc) */
6107 if (ldst_extend (&str) == FAIL)
6108 return;
6109 if (conflict_reg)
6110 as_warn (_("%s register same as write-back base"),
6111 ((inst.instruction & LOAD_BIT)
6112 ? _("destination") : _("source")));
6113 }
6114 else
6115 {
6116 /* [Rn] */
6117 skip_whitespace (str);
6118
6119 if (*str == '!')
6120 {
6121 if (conflict_reg)
6122 as_warn (_("%s register same as write-back base"),
6123 ((inst.instruction & LOAD_BIT)
6124 ? _("destination") : _("source")));
6125 str++;
6126 inst.instruction |= WRITE_BACK;
6127 }
6128
6129 inst.instruction |= INDEX_UP;
6130 pre_inc = 1;
6131 }
6132 }
6133 else
6134 {
6135 /* [Rn,...] */
6136 if (skip_past_comma (&str) == FAIL)
6137 {
6138 inst.error = _("pre-indexed expression expected");
6139 return;
6140 }
6141
6142 pre_inc = 1;
6143 if (ldst_extend (&str) == FAIL)
6144 return;
6145
6146 skip_whitespace (str);
6147
6148 if (*str++ != ']')
6149 {
6150 inst.error = _("missing ]");
6151 return;
6152 }
6153
6154 skip_whitespace (str);
6155
6156 if (*str == '!')
6157 {
6158 if (conflict_reg)
6159 as_warn (_("%s register same as write-back base"),
6160 ((inst.instruction & LOAD_BIT)
6161 ? _("destination") : _("source")));
6162 str++;
6163 inst.instruction |= WRITE_BACK;
6164 }
6165 }
6166 }
6167 else if (*str == '=')
6168 {
6169 if ((inst.instruction & LOAD_BIT) == 0)
6170 {
6171 inst.error = _("invalid pseudo operation");
6172 return;
6173 }
6174
6175 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
6176 str++;
6177
6178 skip_whitespace (str);
6179
6180 if (my_get_expression (&inst.reloc.exp, &str))
6181 return;
6182
6183 if (inst.reloc.exp.X_op != O_constant
6184 && inst.reloc.exp.X_op != O_symbol)
6185 {
6186 inst.error = _("constant expression expected");
6187 return;
6188 }
6189
6190 if (inst.reloc.exp.X_op == O_constant)
6191 {
6192 value = validate_immediate (inst.reloc.exp.X_add_number);
6193
6194 if (value != FAIL)
6195 {
6196 /* This can be done with a mov instruction. */
6197 inst.instruction &= LITERAL_MASK;
6198 inst.instruction |= (INST_IMMEDIATE
6199 | (OPCODE_MOV << DATA_OP_SHIFT));
6200 inst.instruction |= value & 0xfff;
6201 end_of_line (str);
6202 return;
6203 }
6204
6205 value = validate_immediate (~inst.reloc.exp.X_add_number);
6206
6207 if (value != FAIL)
6208 {
6209 /* This can be done with a mvn instruction. */
6210 inst.instruction &= LITERAL_MASK;
6211 inst.instruction |= (INST_IMMEDIATE
6212 | (OPCODE_MVN << DATA_OP_SHIFT));
6213 inst.instruction |= value & 0xfff;
6214 end_of_line (str);
6215 return;
6216 }
6217 }
6218
6219 /* Insert into literal pool. */
6220 if (add_to_lit_pool () == FAIL)
6221 {
6222 if (!inst.error)
6223 inst.error = _("literal pool insertion failed");
6224 return;
6225 }
6226
6227 /* Change the instruction exp to point to the pool. */
6228 inst.reloc.type = BFD_RELOC_ARM_LITERAL;
6229 inst.reloc.pc_rel = 1;
6230 inst.instruction |= (REG_PC << 16);
6231 pre_inc = 1;
6232 }
6233 else
6234 {
6235 if (my_get_expression (&inst.reloc.exp, &str))
6236 return;
6237
6238 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
6239 #ifndef TE_WINCE
6240 /* PC rel adjust. */
6241 inst.reloc.exp.X_add_number -= 8;
6242 #endif
6243 inst.reloc.pc_rel = 1;
6244 inst.instruction |= (REG_PC << 16);
6245 pre_inc = 1;
6246 }
6247
6248 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
6249 end_of_line (str);
6250 return;
6251 }
6252
6253 static void
6254 do_ldstt (str)
6255 char * str;
6256 {
6257 int conflict_reg;
6258
6259 skip_whitespace (str);
6260
6261 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
6262 {
6263 if (!inst.error)
6264 inst.error = BAD_ARGS;
6265 return;
6266 }
6267
6268 if (skip_past_comma (& str) == FAIL)
6269 {
6270 inst.error = _("address expected");
6271 return;
6272 }
6273
6274 if (*str == '[')
6275 {
6276 int reg;
6277
6278 str++;
6279
6280 skip_whitespace (str);
6281
6282 if ((reg = reg_required_here (&str, 16)) == FAIL)
6283 return;
6284
6285 /* ldrt/strt always use post-indexed addressing, so if the base is
6286 the same as Rd, we warn. */
6287 if (conflict_reg == reg)
6288 as_warn (_("%s register same as write-back base"),
6289 ((inst.instruction & LOAD_BIT)
6290 ? _("destination") : _("source")));
6291
6292 skip_whitespace (str);
6293
6294 if (*str == ']')
6295 {
6296 str ++;
6297
6298 if (skip_past_comma (&str) == SUCCESS)
6299 {
6300 /* [Rn],... (post inc) */
6301 if (ldst_extend (&str) == FAIL)
6302 return;
6303 }
6304 else
6305 {
6306 /* [Rn] */
6307 skip_whitespace (str);
6308
6309 /* Skip a write-back '!'. */
6310 if (*str == '!')
6311 str++;
6312
6313 inst.instruction |= INDEX_UP;
6314 }
6315 }
6316 else
6317 {
6318 inst.error = _("post-indexed expression expected");
6319 return;
6320 }
6321 }
6322 else
6323 {
6324 inst.error = _("post-indexed expression expected");
6325 return;
6326 }
6327
6328 end_of_line (str);
6329 return;
6330 }
6331
6332 static int
6333 ldst_extend_v4 (str)
6334 char ** str;
6335 {
6336 int add = INDEX_UP;
6337
6338 switch (**str)
6339 {
6340 case '#':
6341 case '$':
6342 (*str)++;
6343 if (my_get_expression (& inst.reloc.exp, str))
6344 return FAIL;
6345
6346 if (inst.reloc.exp.X_op == O_constant)
6347 {
6348 int value = inst.reloc.exp.X_add_number;
6349
6350 if (value < -255 || value > 255)
6351 {
6352 inst.error = _("address offset too large");
6353 return FAIL;
6354 }
6355
6356 if (value < 0)
6357 {
6358 value = -value;
6359 add = 0;
6360 }
6361
6362 /* Halfword and signextension instructions have the
6363 immediate value split across bits 11..8 and bits 3..0. */
6364 inst.instruction |= (add | HWOFFSET_IMM
6365 | ((value >> 4) << 8) | (value & 0xF));
6366 }
6367 else
6368 {
6369 inst.instruction |= HWOFFSET_IMM;
6370 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
6371 inst.reloc.pc_rel = 0;
6372 }
6373 return SUCCESS;
6374
6375 case '-':
6376 add = 0;
6377 /* Fall through. */
6378
6379 case '+':
6380 (*str)++;
6381 /* Fall through. */
6382
6383 default:
6384 if (reg_required_here (str, 0) == FAIL)
6385 return FAIL;
6386
6387 inst.instruction |= add;
6388 return SUCCESS;
6389 }
6390 }
6391
6392 /* Halfword and signed-byte load/store operations. */
6393 static void
6394 do_ldstv4 (str)
6395 char * str;
6396 {
6397 int pre_inc = 0;
6398 int conflict_reg;
6399 int value;
6400
6401 skip_whitespace (str);
6402
6403 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
6404 {
6405 if (!inst.error)
6406 inst.error = BAD_ARGS;
6407 return;
6408 }
6409
6410 if (skip_past_comma (& str) == FAIL)
6411 {
6412 inst.error = _("address expected");
6413 return;
6414 }
6415
6416 if (*str == '[')
6417 {
6418 int reg;
6419
6420 str++;
6421
6422 skip_whitespace (str);
6423
6424 if ((reg = reg_required_here (&str, 16)) == FAIL)
6425 return;
6426
6427 /* Conflicts can occur on stores as well as loads. */
6428 conflict_reg = (conflict_reg == reg);
6429
6430 skip_whitespace (str);
6431
6432 if (*str == ']')
6433 {
6434 str ++;
6435
6436 if (skip_past_comma (&str) == SUCCESS)
6437 {
6438 /* [Rn],... (post inc) */
6439 if (ldst_extend_v4 (&str) == FAIL)
6440 return;
6441 if (conflict_reg)
6442 as_warn (_("%s register same as write-back base"),
6443 ((inst.instruction & LOAD_BIT)
6444 ? _("destination") : _("source")));
6445 }
6446 else
6447 {
6448 /* [Rn] */
6449 inst.instruction |= HWOFFSET_IMM;
6450
6451 skip_whitespace (str);
6452
6453 if (*str == '!')
6454 {
6455 if (conflict_reg)
6456 as_warn (_("%s register same as write-back base"),
6457 ((inst.instruction & LOAD_BIT)
6458 ? _("destination") : _("source")));
6459 str++;
6460 inst.instruction |= WRITE_BACK;
6461 }
6462
6463 inst.instruction |= INDEX_UP;
6464 pre_inc = 1;
6465 }
6466 }
6467 else
6468 {
6469 /* [Rn,...] */
6470 if (skip_past_comma (&str) == FAIL)
6471 {
6472 inst.error = _("pre-indexed expression expected");
6473 return;
6474 }
6475
6476 pre_inc = 1;
6477 if (ldst_extend_v4 (&str) == FAIL)
6478 return;
6479
6480 skip_whitespace (str);
6481
6482 if (*str++ != ']')
6483 {
6484 inst.error = _("missing ]");
6485 return;
6486 }
6487
6488 skip_whitespace (str);
6489
6490 if (*str == '!')
6491 {
6492 if (conflict_reg)
6493 as_warn (_("%s register same as write-back base"),
6494 ((inst.instruction & LOAD_BIT)
6495 ? _("destination") : _("source")));
6496 str++;
6497 inst.instruction |= WRITE_BACK;
6498 }
6499 }
6500 }
6501 else if (*str == '=')
6502 {
6503 if ((inst.instruction & LOAD_BIT) == 0)
6504 {
6505 inst.error = _("invalid pseudo operation");
6506 return;
6507 }
6508
6509 /* XXX Does this work correctly for half-word/byte ops? */
6510 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
6511 str++;
6512
6513 skip_whitespace (str);
6514
6515 if (my_get_expression (&inst.reloc.exp, &str))
6516 return;
6517
6518 if (inst.reloc.exp.X_op != O_constant
6519 && inst.reloc.exp.X_op != O_symbol)
6520 {
6521 inst.error = _("constant expression expected");
6522 return;
6523 }
6524
6525 if (inst.reloc.exp.X_op == O_constant)
6526 {
6527 value = validate_immediate (inst.reloc.exp.X_add_number);
6528
6529 if (value != FAIL)
6530 {
6531 /* This can be done with a mov instruction. */
6532 inst.instruction &= LITERAL_MASK;
6533 inst.instruction |= INST_IMMEDIATE | (OPCODE_MOV << DATA_OP_SHIFT);
6534 inst.instruction |= value & 0xfff;
6535 end_of_line (str);
6536 return;
6537 }
6538
6539 value = validate_immediate (~ inst.reloc.exp.X_add_number);
6540
6541 if (value != FAIL)
6542 {
6543 /* This can be done with a mvn instruction. */
6544 inst.instruction &= LITERAL_MASK;
6545 inst.instruction |= INST_IMMEDIATE | (OPCODE_MVN << DATA_OP_SHIFT);
6546 inst.instruction |= value & 0xfff;
6547 end_of_line (str);
6548 return;
6549 }
6550 }
6551
6552 /* Insert into literal pool. */
6553 if (add_to_lit_pool () == FAIL)
6554 {
6555 if (!inst.error)
6556 inst.error = _("literal pool insertion failed");
6557 return;
6558 }
6559
6560 /* Change the instruction exp to point to the pool. */
6561 inst.instruction |= HWOFFSET_IMM;
6562 inst.reloc.type = BFD_RELOC_ARM_HWLITERAL;
6563 inst.reloc.pc_rel = 1;
6564 inst.instruction |= (REG_PC << 16);
6565 pre_inc = 1;
6566 }
6567 else
6568 {
6569 if (my_get_expression (&inst.reloc.exp, &str))
6570 return;
6571
6572 inst.instruction |= HWOFFSET_IMM;
6573 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
6574 #ifndef TE_WINCE
6575 /* PC rel adjust. */
6576 inst.reloc.exp.X_add_number -= 8;
6577 #endif
6578 inst.reloc.pc_rel = 1;
6579 inst.instruction |= (REG_PC << 16);
6580 pre_inc = 1;
6581 }
6582
6583 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
6584 end_of_line (str);
6585 return;
6586 }
6587
6588 static long
6589 reg_list (strp)
6590 char ** strp;
6591 {
6592 char * str = * strp;
6593 long range = 0;
6594 int another_range;
6595
6596 /* We come back here if we get ranges concatenated by '+' or '|'. */
6597 do
6598 {
6599 another_range = 0;
6600
6601 if (*str == '{')
6602 {
6603 int in_range = 0;
6604 int cur_reg = -1;
6605
6606 str++;
6607 do
6608 {
6609 int reg;
6610
6611 skip_whitespace (str);
6612
6613 if ((reg = reg_required_here (& str, -1)) == FAIL)
6614 return FAIL;
6615
6616 if (in_range)
6617 {
6618 int i;
6619
6620 if (reg <= cur_reg)
6621 {
6622 inst.error = _("bad range in register list");
6623 return FAIL;
6624 }
6625
6626 for (i = cur_reg + 1; i < reg; i++)
6627 {
6628 if (range & (1 << i))
6629 as_tsktsk
6630 (_("Warning: duplicated register (r%d) in register list"),
6631 i);
6632 else
6633 range |= 1 << i;
6634 }
6635 in_range = 0;
6636 }
6637
6638 if (range & (1 << reg))
6639 as_tsktsk (_("Warning: duplicated register (r%d) in register list"),
6640 reg);
6641 else if (reg <= cur_reg)
6642 as_tsktsk (_("Warning: register range not in ascending order"));
6643
6644 range |= 1 << reg;
6645 cur_reg = reg;
6646 }
6647 while (skip_past_comma (&str) != FAIL
6648 || (in_range = 1, *str++ == '-'));
6649 str--;
6650 skip_whitespace (str);
6651
6652 if (*str++ != '}')
6653 {
6654 inst.error = _("missing `}'");
6655 return FAIL;
6656 }
6657 }
6658 else
6659 {
6660 expressionS expr;
6661
6662 if (my_get_expression (&expr, &str))
6663 return FAIL;
6664
6665 if (expr.X_op == O_constant)
6666 {
6667 if (expr.X_add_number
6668 != (expr.X_add_number & 0x0000ffff))
6669 {
6670 inst.error = _("invalid register mask");
6671 return FAIL;
6672 }
6673
6674 if ((range & expr.X_add_number) != 0)
6675 {
6676 int regno = range & expr.X_add_number;
6677
6678 regno &= -regno;
6679 regno = (1 << regno) - 1;
6680 as_tsktsk
6681 (_("Warning: duplicated register (r%d) in register list"),
6682 regno);
6683 }
6684
6685 range |= expr.X_add_number;
6686 }
6687 else
6688 {
6689 if (inst.reloc.type != 0)
6690 {
6691 inst.error = _("expression too complex");
6692 return FAIL;
6693 }
6694
6695 memcpy (&inst.reloc.exp, &expr, sizeof (expressionS));
6696 inst.reloc.type = BFD_RELOC_ARM_MULTI;
6697 inst.reloc.pc_rel = 0;
6698 }
6699 }
6700
6701 skip_whitespace (str);
6702
6703 if (*str == '|' || *str == '+')
6704 {
6705 str++;
6706 another_range = 1;
6707 }
6708 }
6709 while (another_range);
6710
6711 *strp = str;
6712 return range;
6713 }
6714
6715 static void
6716 do_ldmstm (str)
6717 char * str;
6718 {
6719 int base_reg;
6720 long range;
6721
6722 skip_whitespace (str);
6723
6724 if ((base_reg = reg_required_here (&str, 16)) == FAIL)
6725 return;
6726
6727 if (base_reg == REG_PC)
6728 {
6729 inst.error = _("r15 not allowed as base register");
6730 return;
6731 }
6732
6733 skip_whitespace (str);
6734
6735 if (*str == '!')
6736 {
6737 inst.instruction |= WRITE_BACK;
6738 str++;
6739 }
6740
6741 if (skip_past_comma (&str) == FAIL
6742 || (range = reg_list (&str)) == FAIL)
6743 {
6744 if (! inst.error)
6745 inst.error = BAD_ARGS;
6746 return;
6747 }
6748
6749 if (*str == '^')
6750 {
6751 str++;
6752 inst.instruction |= LDM_TYPE_2_OR_3;
6753 }
6754
6755 if (inst.instruction & WRITE_BACK)
6756 {
6757 /* Check for unpredictable uses of writeback. */
6758 if (inst.instruction & LOAD_BIT)
6759 {
6760 /* Not allowed in LDM type 2. */
6761 if ((inst.instruction & LDM_TYPE_2_OR_3)
6762 && ((range & (1 << REG_PC)) == 0))
6763 as_warn (_("writeback of base register is UNPREDICTABLE"));
6764 /* Only allowed if base reg not in list for other types. */
6765 else if (range & (1 << base_reg))
6766 as_warn (_("writeback of base register when in register list is UNPREDICTABLE"));
6767 }
6768 else /* STM. */
6769 {
6770 /* Not allowed for type 2. */
6771 if (inst.instruction & LDM_TYPE_2_OR_3)
6772 as_warn (_("writeback of base register is UNPREDICTABLE"));
6773 /* Only allowed if base reg not in list, or first in list. */
6774 else if ((range & (1 << base_reg))
6775 && (range & ((1 << base_reg) - 1)))
6776 as_warn (_("if writeback register is in list, it must be the lowest reg in the list"));
6777 }
6778 }
6779
6780 inst.instruction |= range;
6781 end_of_line (str);
6782 return;
6783 }
6784
6785 static void
6786 do_swi (str)
6787 char * str;
6788 {
6789 skip_whitespace (str);
6790
6791 /* Allow optional leading '#'. */
6792 if (is_immediate_prefix (*str))
6793 str++;
6794
6795 if (my_get_expression (& inst.reloc.exp, & str))
6796 return;
6797
6798 inst.reloc.type = BFD_RELOC_ARM_SWI;
6799 inst.reloc.pc_rel = 0;
6800 end_of_line (str);
6801
6802 return;
6803 }
6804
6805 static void
6806 do_swap (str)
6807 char * str;
6808 {
6809 int reg;
6810
6811 skip_whitespace (str);
6812
6813 if ((reg = reg_required_here (&str, 12)) == FAIL)
6814 return;
6815
6816 if (reg == REG_PC)
6817 {
6818 inst.error = _("r15 not allowed in swap");
6819 return;
6820 }
6821
6822 if (skip_past_comma (&str) == FAIL
6823 || (reg = reg_required_here (&str, 0)) == FAIL)
6824 {
6825 if (!inst.error)
6826 inst.error = BAD_ARGS;
6827 return;
6828 }
6829
6830 if (reg == REG_PC)
6831 {
6832 inst.error = _("r15 not allowed in swap");
6833 return;
6834 }
6835
6836 if (skip_past_comma (&str) == FAIL
6837 || *str++ != '[')
6838 {
6839 inst.error = BAD_ARGS;
6840 return;
6841 }
6842
6843 skip_whitespace (str);
6844
6845 if ((reg = reg_required_here (&str, 16)) == FAIL)
6846 return;
6847
6848 if (reg == REG_PC)
6849 {
6850 inst.error = BAD_PC;
6851 return;
6852 }
6853
6854 skip_whitespace (str);
6855
6856 if (*str++ != ']')
6857 {
6858 inst.error = _("missing ]");
6859 return;
6860 }
6861
6862 end_of_line (str);
6863 return;
6864 }
6865
6866 static void
6867 do_branch (str)
6868 char * str;
6869 {
6870 if (my_get_expression (&inst.reloc.exp, &str))
6871 return;
6872
6873 #ifdef OBJ_ELF
6874 {
6875 char * save_in;
6876
6877 /* ScottB: February 5, 1998 - Check to see of PLT32 reloc
6878 required for the instruction. */
6879
6880 /* arm_parse_reloc () works on input_line_pointer.
6881 We actually want to parse the operands to the branch instruction
6882 passed in 'str'. Save the input pointer and restore it later. */
6883 save_in = input_line_pointer;
6884 input_line_pointer = str;
6885 if (inst.reloc.exp.X_op == O_symbol
6886 && *str == '('
6887 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
6888 {
6889 inst.reloc.type = BFD_RELOC_ARM_PLT32;
6890 inst.reloc.pc_rel = 0;
6891 /* Modify str to point to after parsed operands, otherwise
6892 end_of_line() will complain about the (PLT) left in str. */
6893 str = input_line_pointer;
6894 }
6895 else
6896 {
6897 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
6898 inst.reloc.pc_rel = 1;
6899 }
6900 input_line_pointer = save_in;
6901 }
6902 #else
6903 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
6904 inst.reloc.pc_rel = 1;
6905 #endif /* OBJ_ELF */
6906
6907 end_of_line (str);
6908 return;
6909 }
6910
6911 static void
6912 do_bx (str)
6913 char * str;
6914 {
6915 int reg;
6916
6917 skip_whitespace (str);
6918
6919 if ((reg = reg_required_here (&str, 0)) == FAIL)
6920 {
6921 inst.error = BAD_ARGS;
6922 return;
6923 }
6924
6925 /* Note - it is not illegal to do a "bx pc". Useless, but not illegal. */
6926 if (reg == REG_PC)
6927 as_tsktsk (_("use of r15 in bx in ARM mode is not really useful"));
6928
6929 end_of_line (str);
6930 }
6931
6932 static void
6933 do_cdp (str)
6934 char * str;
6935 {
6936 /* Co-processor data operation.
6937 Format: CDP{cond} CP#,<expr>,CRd,CRn,CRm{,<expr>} */
6938 skip_whitespace (str);
6939
6940 if (co_proc_number (&str) == FAIL)
6941 {
6942 if (!inst.error)
6943 inst.error = BAD_ARGS;
6944 return;
6945 }
6946
6947 if (skip_past_comma (&str) == FAIL
6948 || cp_opc_expr (&str, 20,4) == FAIL)
6949 {
6950 if (!inst.error)
6951 inst.error = BAD_ARGS;
6952 return;
6953 }
6954
6955 if (skip_past_comma (&str) == FAIL
6956 || cp_reg_required_here (&str, 12) == FAIL)
6957 {
6958 if (!inst.error)
6959 inst.error = BAD_ARGS;
6960 return;
6961 }
6962
6963 if (skip_past_comma (&str) == FAIL
6964 || cp_reg_required_here (&str, 16) == FAIL)
6965 {
6966 if (!inst.error)
6967 inst.error = BAD_ARGS;
6968 return;
6969 }
6970
6971 if (skip_past_comma (&str) == FAIL
6972 || cp_reg_required_here (&str, 0) == FAIL)
6973 {
6974 if (!inst.error)
6975 inst.error = BAD_ARGS;
6976 return;
6977 }
6978
6979 if (skip_past_comma (&str) == SUCCESS)
6980 {
6981 if (cp_opc_expr (&str, 5, 3) == FAIL)
6982 {
6983 if (!inst.error)
6984 inst.error = BAD_ARGS;
6985 return;
6986 }
6987 }
6988
6989 end_of_line (str);
6990 return;
6991 }
6992
6993 static void
6994 do_lstc (str)
6995 char * str;
6996 {
6997 /* Co-processor register load/store.
6998 Format: <LDC|STC{cond}[L] CP#,CRd,<address> */
6999
7000 skip_whitespace (str);
7001
7002 if (co_proc_number (&str) == FAIL)
7003 {
7004 if (!inst.error)
7005 inst.error = BAD_ARGS;
7006 return;
7007 }
7008
7009 if (skip_past_comma (&str) == FAIL
7010 || cp_reg_required_here (&str, 12) == FAIL)
7011 {
7012 if (!inst.error)
7013 inst.error = BAD_ARGS;
7014 return;
7015 }
7016
7017 if (skip_past_comma (&str) == FAIL
7018 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
7019 {
7020 if (! inst.error)
7021 inst.error = BAD_ARGS;
7022 return;
7023 }
7024
7025 end_of_line (str);
7026 return;
7027 }
7028
7029 static void
7030 do_co_reg (str)
7031 char * str;
7032 {
7033 /* Co-processor register transfer.
7034 Format: <MCR|MRC>{cond} CP#,<expr1>,Rd,CRn,CRm{,<expr2>} */
7035
7036 skip_whitespace (str);
7037
7038 if (co_proc_number (&str) == FAIL)
7039 {
7040 if (!inst.error)
7041 inst.error = BAD_ARGS;
7042 return;
7043 }
7044
7045 if (skip_past_comma (&str) == FAIL
7046 || cp_opc_expr (&str, 21, 3) == FAIL)
7047 {
7048 if (!inst.error)
7049 inst.error = BAD_ARGS;
7050 return;
7051 }
7052
7053 if (skip_past_comma (&str) == FAIL
7054 || reg_required_here (&str, 12) == FAIL)
7055 {
7056 if (!inst.error)
7057 inst.error = BAD_ARGS;
7058 return;
7059 }
7060
7061 if (skip_past_comma (&str) == FAIL
7062 || cp_reg_required_here (&str, 16) == FAIL)
7063 {
7064 if (!inst.error)
7065 inst.error = BAD_ARGS;
7066 return;
7067 }
7068
7069 if (skip_past_comma (&str) == FAIL
7070 || cp_reg_required_here (&str, 0) == FAIL)
7071 {
7072 if (!inst.error)
7073 inst.error = BAD_ARGS;
7074 return;
7075 }
7076
7077 if (skip_past_comma (&str) == SUCCESS)
7078 {
7079 if (cp_opc_expr (&str, 5, 3) == FAIL)
7080 {
7081 if (!inst.error)
7082 inst.error = BAD_ARGS;
7083 return;
7084 }
7085 }
7086
7087 end_of_line (str);
7088 return;
7089 }
7090
7091 static void
7092 do_fpa_ctrl (str)
7093 char * str;
7094 {
7095 /* FP control registers.
7096 Format: <WFS|RFS|WFC|RFC>{cond} Rn */
7097
7098 skip_whitespace (str);
7099
7100 if (reg_required_here (&str, 12) == FAIL)
7101 {
7102 if (!inst.error)
7103 inst.error = BAD_ARGS;
7104 return;
7105 }
7106
7107 end_of_line (str);
7108 return;
7109 }
7110
7111 static void
7112 do_fpa_ldst (str)
7113 char * str;
7114 {
7115 skip_whitespace (str);
7116
7117 if (fp_reg_required_here (&str, 12) == FAIL)
7118 {
7119 if (!inst.error)
7120 inst.error = BAD_ARGS;
7121 return;
7122 }
7123
7124 if (skip_past_comma (&str) == FAIL
7125 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
7126 {
7127 if (!inst.error)
7128 inst.error = BAD_ARGS;
7129 return;
7130 }
7131
7132 end_of_line (str);
7133 }
7134
7135 static void
7136 do_fpa_ldmstm (str)
7137 char * str;
7138 {
7139 int num_regs;
7140
7141 skip_whitespace (str);
7142
7143 if (fp_reg_required_here (&str, 12) == FAIL)
7144 {
7145 if (! inst.error)
7146 inst.error = BAD_ARGS;
7147 return;
7148 }
7149
7150 /* Get Number of registers to transfer. */
7151 if (skip_past_comma (&str) == FAIL
7152 || my_get_expression (&inst.reloc.exp, &str))
7153 {
7154 if (! inst.error)
7155 inst.error = _("constant expression expected");
7156 return;
7157 }
7158
7159 if (inst.reloc.exp.X_op != O_constant)
7160 {
7161 inst.error = _("constant value required for number of registers");
7162 return;
7163 }
7164
7165 num_regs = inst.reloc.exp.X_add_number;
7166
7167 if (num_regs < 1 || num_regs > 4)
7168 {
7169 inst.error = _("number of registers must be in the range [1:4]");
7170 return;
7171 }
7172
7173 switch (num_regs)
7174 {
7175 case 1:
7176 inst.instruction |= CP_T_X;
7177 break;
7178 case 2:
7179 inst.instruction |= CP_T_Y;
7180 break;
7181 case 3:
7182 inst.instruction |= CP_T_Y | CP_T_X;
7183 break;
7184 case 4:
7185 break;
7186 default:
7187 abort ();
7188 }
7189
7190 if (inst.instruction & (CP_T_Pre | CP_T_UD)) /* ea/fd format. */
7191 {
7192 int reg;
7193 int write_back;
7194 int offset;
7195
7196 /* The instruction specified "ea" or "fd", so we can only accept
7197 [Rn]{!}. The instruction does not really support stacking or
7198 unstacking, so we have to emulate these by setting appropriate
7199 bits and offsets. */
7200 if (skip_past_comma (&str) == FAIL
7201 || *str != '[')
7202 {
7203 if (! inst.error)
7204 inst.error = BAD_ARGS;
7205 return;
7206 }
7207
7208 str++;
7209 skip_whitespace (str);
7210
7211 if ((reg = reg_required_here (&str, 16)) == FAIL)
7212 return;
7213
7214 skip_whitespace (str);
7215
7216 if (*str != ']')
7217 {
7218 inst.error = BAD_ARGS;
7219 return;
7220 }
7221
7222 str++;
7223 if (*str == '!')
7224 {
7225 write_back = 1;
7226 str++;
7227 if (reg == REG_PC)
7228 {
7229 inst.error =
7230 _("r15 not allowed as base register with write-back");
7231 return;
7232 }
7233 }
7234 else
7235 write_back = 0;
7236
7237 if (inst.instruction & CP_T_Pre)
7238 {
7239 /* Pre-decrement. */
7240 offset = 3 * num_regs;
7241 if (write_back)
7242 inst.instruction |= CP_T_WB;
7243 }
7244 else
7245 {
7246 /* Post-increment. */
7247 if (write_back)
7248 {
7249 inst.instruction |= CP_T_WB;
7250 offset = 3 * num_regs;
7251 }
7252 else
7253 {
7254 /* No write-back, so convert this into a standard pre-increment
7255 instruction -- aesthetically more pleasing. */
7256 inst.instruction |= CP_T_Pre | CP_T_UD;
7257 offset = 0;
7258 }
7259 }
7260
7261 inst.instruction |= offset;
7262 }
7263 else if (skip_past_comma (&str) == FAIL
7264 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
7265 {
7266 if (! inst.error)
7267 inst.error = BAD_ARGS;
7268 return;
7269 }
7270
7271 end_of_line (str);
7272 }
7273
7274 static void
7275 do_fpa_dyadic (str)
7276 char * str;
7277 {
7278 skip_whitespace (str);
7279
7280 if (fp_reg_required_here (&str, 12) == FAIL)
7281 {
7282 if (! inst.error)
7283 inst.error = BAD_ARGS;
7284 return;
7285 }
7286
7287 if (skip_past_comma (&str) == FAIL
7288 || fp_reg_required_here (&str, 16) == FAIL)
7289 {
7290 if (! inst.error)
7291 inst.error = BAD_ARGS;
7292 return;
7293 }
7294
7295 if (skip_past_comma (&str) == FAIL
7296 || fp_op2 (&str) == FAIL)
7297 {
7298 if (! inst.error)
7299 inst.error = BAD_ARGS;
7300 return;
7301 }
7302
7303 end_of_line (str);
7304 return;
7305 }
7306
7307 static void
7308 do_fpa_monadic (str)
7309 char * str;
7310 {
7311 skip_whitespace (str);
7312
7313 if (fp_reg_required_here (&str, 12) == FAIL)
7314 {
7315 if (! inst.error)
7316 inst.error = BAD_ARGS;
7317 return;
7318 }
7319
7320 if (skip_past_comma (&str) == FAIL
7321 || fp_op2 (&str) == FAIL)
7322 {
7323 if (! inst.error)
7324 inst.error = BAD_ARGS;
7325 return;
7326 }
7327
7328 end_of_line (str);
7329 return;
7330 }
7331
7332 static void
7333 do_fpa_cmp (str)
7334 char * str;
7335 {
7336 skip_whitespace (str);
7337
7338 if (fp_reg_required_here (&str, 16) == FAIL)
7339 {
7340 if (! inst.error)
7341 inst.error = BAD_ARGS;
7342 return;
7343 }
7344
7345 if (skip_past_comma (&str) == FAIL
7346 || fp_op2 (&str) == FAIL)
7347 {
7348 if (! inst.error)
7349 inst.error = BAD_ARGS;
7350 return;
7351 }
7352
7353 end_of_line (str);
7354 return;
7355 }
7356
7357 static void
7358 do_fpa_from_reg (str)
7359 char * str;
7360 {
7361 skip_whitespace (str);
7362
7363 if (fp_reg_required_here (&str, 16) == FAIL)
7364 {
7365 if (! inst.error)
7366 inst.error = BAD_ARGS;
7367 return;
7368 }
7369
7370 if (skip_past_comma (&str) == FAIL
7371 || reg_required_here (&str, 12) == FAIL)
7372 {
7373 if (! inst.error)
7374 inst.error = BAD_ARGS;
7375 return;
7376 }
7377
7378 end_of_line (str);
7379 return;
7380 }
7381
7382 static void
7383 do_fpa_to_reg (str)
7384 char * str;
7385 {
7386 skip_whitespace (str);
7387
7388 if (reg_required_here (&str, 12) == FAIL)
7389 return;
7390
7391 if (skip_past_comma (&str) == FAIL
7392 || fp_reg_required_here (&str, 0) == FAIL)
7393 {
7394 if (! inst.error)
7395 inst.error = BAD_ARGS;
7396 return;
7397 }
7398
7399 end_of_line (str);
7400 return;
7401 }
7402
7403 static int
7404 vfp_sp_reg_required_here (str, pos)
7405 char **str;
7406 enum vfp_sp_reg_pos pos;
7407 {
7408 int reg;
7409 char *start = *str;
7410
7411 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_SN].htab)) != FAIL)
7412 {
7413 switch (pos)
7414 {
7415 case VFP_REG_Sd:
7416 inst.instruction |= ((reg >> 1) << 12) | ((reg & 1) << 22);
7417 break;
7418
7419 case VFP_REG_Sn:
7420 inst.instruction |= ((reg >> 1) << 16) | ((reg & 1) << 7);
7421 break;
7422
7423 case VFP_REG_Sm:
7424 inst.instruction |= ((reg >> 1) << 0) | ((reg & 1) << 5);
7425 break;
7426
7427 default:
7428 abort ();
7429 }
7430 return reg;
7431 }
7432
7433 /* In the few cases where we might be able to accept something else
7434 this error can be overridden. */
7435 inst.error = _(all_reg_maps[REG_TYPE_SN].expected);
7436
7437 /* Restore the start point. */
7438 *str = start;
7439 return FAIL;
7440 }
7441
7442 static int
7443 vfp_dp_reg_required_here (str, pos)
7444 char **str;
7445 enum vfp_dp_reg_pos pos;
7446 {
7447 int reg;
7448 char *start = *str;
7449
7450 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_DN].htab)) != FAIL)
7451 {
7452 switch (pos)
7453 {
7454 case VFP_REG_Dd:
7455 inst.instruction |= reg << 12;
7456 break;
7457
7458 case VFP_REG_Dn:
7459 inst.instruction |= reg << 16;
7460 break;
7461
7462 case VFP_REG_Dm:
7463 inst.instruction |= reg << 0;
7464 break;
7465
7466 default:
7467 abort ();
7468 }
7469 return reg;
7470 }
7471
7472 /* In the few cases where we might be able to accept something else
7473 this error can be overridden. */
7474 inst.error = _(all_reg_maps[REG_TYPE_DN].expected);
7475
7476 /* Restore the start point. */
7477 *str = start;
7478 return FAIL;
7479 }
7480
7481 static void
7482 do_vfp_sp_monadic (str)
7483 char *str;
7484 {
7485 skip_whitespace (str);
7486
7487 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
7488 return;
7489
7490 if (skip_past_comma (&str) == FAIL
7491 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
7492 {
7493 if (! inst.error)
7494 inst.error = BAD_ARGS;
7495 return;
7496 }
7497
7498 end_of_line (str);
7499 return;
7500 }
7501
7502 static void
7503 do_vfp_dp_monadic (str)
7504 char *str;
7505 {
7506 skip_whitespace (str);
7507
7508 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
7509 return;
7510
7511 if (skip_past_comma (&str) == FAIL
7512 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
7513 {
7514 if (! inst.error)
7515 inst.error = BAD_ARGS;
7516 return;
7517 }
7518
7519 end_of_line (str);
7520 return;
7521 }
7522
7523 static void
7524 do_vfp_sp_dyadic (str)
7525 char *str;
7526 {
7527 skip_whitespace (str);
7528
7529 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
7530 return;
7531
7532 if (skip_past_comma (&str) == FAIL
7533 || vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL
7534 || skip_past_comma (&str) == FAIL
7535 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
7536 {
7537 if (! inst.error)
7538 inst.error = BAD_ARGS;
7539 return;
7540 }
7541
7542 end_of_line (str);
7543 return;
7544 }
7545
7546 static void
7547 do_vfp_dp_dyadic (str)
7548 char *str;
7549 {
7550 skip_whitespace (str);
7551
7552 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
7553 return;
7554
7555 if (skip_past_comma (&str) == FAIL
7556 || vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL
7557 || skip_past_comma (&str) == FAIL
7558 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
7559 {
7560 if (! inst.error)
7561 inst.error = BAD_ARGS;
7562 return;
7563 }
7564
7565 end_of_line (str);
7566 return;
7567 }
7568
7569 static void
7570 do_vfp_reg_from_sp (str)
7571 char *str;
7572 {
7573 skip_whitespace (str);
7574
7575 if (reg_required_here (&str, 12) == FAIL)
7576 return;
7577
7578 if (skip_past_comma (&str) == FAIL
7579 || vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL)
7580 {
7581 if (! inst.error)
7582 inst.error = BAD_ARGS;
7583 return;
7584 }
7585
7586 end_of_line (str);
7587 return;
7588 }
7589
7590 static void
7591 do_vfp_sp_reg2 (str)
7592 char *str;
7593 {
7594 skip_whitespace (str);
7595
7596 if (reg_required_here (&str, 12) == FAIL)
7597 return;
7598
7599 if (skip_past_comma (&str) == FAIL
7600 || reg_required_here (&str, 16) == FAIL
7601 || skip_past_comma (&str) == FAIL)
7602 {
7603 if (! inst.error)
7604 inst.error = BAD_ARGS;
7605 return;
7606 }
7607
7608 /* We require exactly two consecutive SP registers. */
7609 if (vfp_sp_reg_list (&str, VFP_REG_Sm) != 2)
7610 {
7611 if (! inst.error)
7612 inst.error = _("only two consecutive VFP SP registers allowed here");
7613 }
7614
7615 end_of_line (str);
7616 return;
7617 }
7618
7619 static void
7620 do_vfp_sp_from_reg (str)
7621 char *str;
7622 {
7623 skip_whitespace (str);
7624
7625 if (vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL)
7626 return;
7627
7628 if (skip_past_comma (&str) == FAIL
7629 || reg_required_here (&str, 12) == FAIL)
7630 {
7631 if (! inst.error)
7632 inst.error = BAD_ARGS;
7633 return;
7634 }
7635
7636 end_of_line (str);
7637 return;
7638 }
7639
7640 static void
7641 do_vfp_reg_from_dp (str)
7642 char *str;
7643 {
7644 skip_whitespace (str);
7645
7646 if (reg_required_here (&str, 12) == FAIL)
7647 return;
7648
7649 if (skip_past_comma (&str) == FAIL
7650 || vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL)
7651 {
7652 if (! inst.error)
7653 inst.error = BAD_ARGS;
7654 return;
7655 }
7656
7657 end_of_line (str);
7658 return;
7659 }
7660
7661 static void
7662 do_vfp_reg2_from_dp (str)
7663 char *str;
7664 {
7665 skip_whitespace (str);
7666
7667 if (reg_required_here (&str, 12) == FAIL)
7668 return;
7669
7670 if (skip_past_comma (&str) == FAIL
7671 || reg_required_here (&str, 16) == FAIL
7672 || skip_past_comma (&str) == FAIL
7673 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
7674 {
7675 if (! inst.error)
7676 inst.error = BAD_ARGS;
7677 return;
7678 }
7679
7680 end_of_line (str);
7681 return;
7682 }
7683
7684 static void
7685 do_vfp_dp_from_reg (str)
7686 char *str;
7687 {
7688 skip_whitespace (str);
7689
7690 if (vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL)
7691 return;
7692
7693 if (skip_past_comma (&str) == FAIL
7694 || reg_required_here (&str, 12) == FAIL)
7695 {
7696 if (! inst.error)
7697 inst.error = BAD_ARGS;
7698 return;
7699 }
7700
7701 end_of_line (str);
7702 return;
7703 }
7704
7705 static void
7706 do_vfp_dp_from_reg2 (str)
7707 char *str;
7708 {
7709 skip_whitespace (str);
7710
7711 if (vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
7712 return;
7713
7714 if (skip_past_comma (&str) == FAIL
7715 || reg_required_here (&str, 12) == FAIL
7716 || skip_past_comma (&str) == FAIL
7717 || reg_required_here (&str, 16))
7718 {
7719 if (! inst.error)
7720 inst.error = BAD_ARGS;
7721 return;
7722 }
7723
7724 end_of_line (str);
7725 return;
7726 }
7727
7728 static const struct vfp_reg *
7729 vfp_psr_parse (str)
7730 char **str;
7731 {
7732 char *start = *str;
7733 char c;
7734 char *p;
7735 const struct vfp_reg *vreg;
7736
7737 p = start;
7738
7739 /* Find the end of the current token. */
7740 do
7741 {
7742 c = *p++;
7743 }
7744 while (ISALPHA (c));
7745
7746 /* Mark it. */
7747 *--p = 0;
7748
7749 for (vreg = vfp_regs + 0;
7750 vreg < vfp_regs + sizeof (vfp_regs) / sizeof (struct vfp_reg);
7751 vreg++)
7752 {
7753 if (strcmp (start, vreg->name) == 0)
7754 {
7755 *p = c;
7756 *str = p;
7757 return vreg;
7758 }
7759 }
7760
7761 *p = c;
7762 return NULL;
7763 }
7764
7765 static int
7766 vfp_psr_required_here (str)
7767 char **str;
7768 {
7769 char *start = *str;
7770 const struct vfp_reg *vreg;
7771
7772 vreg = vfp_psr_parse (str);
7773
7774 if (vreg)
7775 {
7776 inst.instruction |= vreg->regno;
7777 return SUCCESS;
7778 }
7779
7780 inst.error = _("VFP system register expected");
7781
7782 *str = start;
7783 return FAIL;
7784 }
7785
7786 static void
7787 do_vfp_reg_from_ctrl (str)
7788 char *str;
7789 {
7790 skip_whitespace (str);
7791
7792 if (reg_required_here (&str, 12) == FAIL)
7793 return;
7794
7795 if (skip_past_comma (&str) == FAIL
7796 || vfp_psr_required_here (&str) == FAIL)
7797 {
7798 if (! inst.error)
7799 inst.error = BAD_ARGS;
7800 return;
7801 }
7802
7803 end_of_line (str);
7804 return;
7805 }
7806
7807 static void
7808 do_vfp_ctrl_from_reg (str)
7809 char *str;
7810 {
7811 skip_whitespace (str);
7812
7813 if (vfp_psr_required_here (&str) == FAIL)
7814 return;
7815
7816 if (skip_past_comma (&str) == FAIL
7817 || reg_required_here (&str, 12) == FAIL)
7818 {
7819 if (! inst.error)
7820 inst.error = BAD_ARGS;
7821 return;
7822 }
7823
7824 end_of_line (str);
7825 return;
7826 }
7827
7828 static void
7829 do_vfp_sp_ldst (str)
7830 char *str;
7831 {
7832 skip_whitespace (str);
7833
7834 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
7835 {
7836 if (!inst.error)
7837 inst.error = BAD_ARGS;
7838 return;
7839 }
7840
7841 if (skip_past_comma (&str) == FAIL
7842 || cp_address_required_here (&str, CP_NO_WB) == FAIL)
7843 {
7844 if (!inst.error)
7845 inst.error = BAD_ARGS;
7846 return;
7847 }
7848
7849 end_of_line (str);
7850 return;
7851 }
7852
7853 static void
7854 do_vfp_dp_ldst (str)
7855 char *str;
7856 {
7857 skip_whitespace (str);
7858
7859 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
7860 {
7861 if (!inst.error)
7862 inst.error = BAD_ARGS;
7863 return;
7864 }
7865
7866 if (skip_past_comma (&str) == FAIL
7867 || cp_address_required_here (&str, CP_NO_WB) == FAIL)
7868 {
7869 if (!inst.error)
7870 inst.error = BAD_ARGS;
7871 return;
7872 }
7873
7874 end_of_line (str);
7875 return;
7876 }
7877
7878 /* Parse and encode a VFP SP register list, storing the initial
7879 register in position POS and returning the range as the result. If
7880 the string is invalid return FAIL (an invalid range). */
7881 static long
7882 vfp_sp_reg_list (str, pos)
7883 char **str;
7884 enum vfp_sp_reg_pos pos;
7885 {
7886 long range = 0;
7887 int base_reg = 0;
7888 int new_base;
7889 long base_bits = 0;
7890 int count = 0;
7891 long tempinst;
7892 unsigned long mask = 0;
7893 int warned = 0;
7894
7895 if (**str != '{')
7896 return FAIL;
7897
7898 (*str)++;
7899 skip_whitespace (*str);
7900
7901 tempinst = inst.instruction;
7902
7903 do
7904 {
7905 inst.instruction = 0;
7906
7907 if ((new_base = vfp_sp_reg_required_here (str, pos)) == FAIL)
7908 return FAIL;
7909
7910 if (count == 0 || base_reg > new_base)
7911 {
7912 base_reg = new_base;
7913 base_bits = inst.instruction;
7914 }
7915
7916 if (mask & (1 << new_base))
7917 {
7918 inst.error = _("invalid register list");
7919 return FAIL;
7920 }
7921
7922 if ((mask >> new_base) != 0 && ! warned)
7923 {
7924 as_tsktsk (_("register list not in ascending order"));
7925 warned = 1;
7926 }
7927
7928 mask |= 1 << new_base;
7929 count++;
7930
7931 skip_whitespace (*str);
7932
7933 if (**str == '-') /* We have the start of a range expression */
7934 {
7935 int high_range;
7936
7937 (*str)++;
7938
7939 if ((high_range
7940 = arm_reg_parse (str, all_reg_maps[REG_TYPE_SN].htab))
7941 == FAIL)
7942 {
7943 inst.error = _(all_reg_maps[REG_TYPE_SN].expected);
7944 return FAIL;
7945 }
7946
7947 if (high_range <= new_base)
7948 {
7949 inst.error = _("register range not in ascending order");
7950 return FAIL;
7951 }
7952
7953 for (new_base++; new_base <= high_range; new_base++)
7954 {
7955 if (mask & (1 << new_base))
7956 {
7957 inst.error = _("invalid register list");
7958 return FAIL;
7959 }
7960
7961 mask |= 1 << new_base;
7962 count++;
7963 }
7964 }
7965 }
7966 while (skip_past_comma (str) != FAIL);
7967
7968 if (**str != '}')
7969 {
7970 inst.error = _("invalid register list");
7971 return FAIL;
7972 }
7973
7974 (*str)++;
7975
7976 range = count;
7977
7978 /* Sanity check -- should have raised a parse error above. */
7979 if (count == 0 || count > 32)
7980 abort ();
7981
7982 /* Final test -- the registers must be consecutive. */
7983 while (count--)
7984 {
7985 if ((mask & (1 << base_reg++)) == 0)
7986 {
7987 inst.error = _("non-contiguous register range");
7988 return FAIL;
7989 }
7990 }
7991
7992 inst.instruction = tempinst | base_bits;
7993 return range;
7994 }
7995
7996 static long
7997 vfp_dp_reg_list (str)
7998 char **str;
7999 {
8000 long range = 0;
8001 int base_reg = 0;
8002 int new_base;
8003 int count = 0;
8004 long tempinst;
8005 unsigned long mask = 0;
8006 int warned = 0;
8007
8008 if (**str != '{')
8009 return FAIL;
8010
8011 (*str)++;
8012 skip_whitespace (*str);
8013
8014 tempinst = inst.instruction;
8015
8016 do
8017 {
8018 inst.instruction = 0;
8019
8020 if ((new_base = vfp_dp_reg_required_here (str, VFP_REG_Dd)) == FAIL)
8021 return FAIL;
8022
8023 if (count == 0 || base_reg > new_base)
8024 {
8025 base_reg = new_base;
8026 range = inst.instruction;
8027 }
8028
8029 if (mask & (1 << new_base))
8030 {
8031 inst.error = _("invalid register list");
8032 return FAIL;
8033 }
8034
8035 if ((mask >> new_base) != 0 && ! warned)
8036 {
8037 as_tsktsk (_("register list not in ascending order"));
8038 warned = 1;
8039 }
8040
8041 mask |= 1 << new_base;
8042 count++;
8043
8044 skip_whitespace (*str);
8045
8046 if (**str == '-') /* We have the start of a range expression */
8047 {
8048 int high_range;
8049
8050 (*str)++;
8051
8052 if ((high_range
8053 = arm_reg_parse (str, all_reg_maps[REG_TYPE_DN].htab))
8054 == FAIL)
8055 {
8056 inst.error = _(all_reg_maps[REG_TYPE_DN].expected);
8057 return FAIL;
8058 }
8059
8060 if (high_range <= new_base)
8061 {
8062 inst.error = _("register range not in ascending order");
8063 return FAIL;
8064 }
8065
8066 for (new_base++; new_base <= high_range; new_base++)
8067 {
8068 if (mask & (1 << new_base))
8069 {
8070 inst.error = _("invalid register list");
8071 return FAIL;
8072 }
8073
8074 mask |= 1 << new_base;
8075 count++;
8076 }
8077 }
8078 }
8079 while (skip_past_comma (str) != FAIL);
8080
8081 if (**str != '}')
8082 {
8083 inst.error = _("invalid register list");
8084 return FAIL;
8085 }
8086
8087 (*str)++;
8088
8089 range |= 2 * count;
8090
8091 /* Sanity check -- should have raised a parse error above. */
8092 if (count == 0 || count > 16)
8093 abort ();
8094
8095 /* Final test -- the registers must be consecutive. */
8096 while (count--)
8097 {
8098 if ((mask & (1 << base_reg++)) == 0)
8099 {
8100 inst.error = _("non-contiguous register range");
8101 return FAIL;
8102 }
8103 }
8104
8105 inst.instruction = tempinst;
8106 return range;
8107 }
8108
8109 static void
8110 vfp_sp_ldstm (str, ldstm_type)
8111 char *str;
8112 enum vfp_ldstm_type ldstm_type;
8113 {
8114 long range;
8115
8116 skip_whitespace (str);
8117
8118 if (reg_required_here (&str, 16) == FAIL)
8119 return;
8120
8121 skip_whitespace (str);
8122
8123 if (*str == '!')
8124 {
8125 inst.instruction |= WRITE_BACK;
8126 str++;
8127 }
8128 else if (ldstm_type != VFP_LDSTMIA)
8129 {
8130 inst.error = _("this addressing mode requires base-register writeback");
8131 return;
8132 }
8133
8134 if (skip_past_comma (&str) == FAIL
8135 || (range = vfp_sp_reg_list (&str, VFP_REG_Sd)) == FAIL)
8136 {
8137 if (!inst.error)
8138 inst.error = BAD_ARGS;
8139 return;
8140 }
8141
8142 inst.instruction |= range;
8143 end_of_line (str);
8144 }
8145
8146 static void
8147 vfp_dp_ldstm (str, ldstm_type)
8148 char *str;
8149 enum vfp_ldstm_type ldstm_type;
8150 {
8151 long range;
8152
8153 skip_whitespace (str);
8154
8155 if (reg_required_here (&str, 16) == FAIL)
8156 return;
8157
8158 skip_whitespace (str);
8159
8160 if (*str == '!')
8161 {
8162 inst.instruction |= WRITE_BACK;
8163 str++;
8164 }
8165 else if (ldstm_type != VFP_LDSTMIA && ldstm_type != VFP_LDSTMIAX)
8166 {
8167 inst.error = _("this addressing mode requires base-register writeback");
8168 return;
8169 }
8170
8171 if (skip_past_comma (&str) == FAIL
8172 || (range = vfp_dp_reg_list (&str)) == FAIL)
8173 {
8174 if (!inst.error)
8175 inst.error = BAD_ARGS;
8176 return;
8177 }
8178
8179 if (ldstm_type == VFP_LDSTMIAX || ldstm_type == VFP_LDSTMDBX)
8180 range += 1;
8181
8182 inst.instruction |= range;
8183 end_of_line (str);
8184 }
8185
8186 static void
8187 do_vfp_sp_ldstmia (str)
8188 char *str;
8189 {
8190 vfp_sp_ldstm (str, VFP_LDSTMIA);
8191 }
8192
8193 static void
8194 do_vfp_sp_ldstmdb (str)
8195 char *str;
8196 {
8197 vfp_sp_ldstm (str, VFP_LDSTMDB);
8198 }
8199
8200 static void
8201 do_vfp_dp_ldstmia (str)
8202 char *str;
8203 {
8204 vfp_dp_ldstm (str, VFP_LDSTMIA);
8205 }
8206
8207 static void
8208 do_vfp_dp_ldstmdb (str)
8209 char *str;
8210 {
8211 vfp_dp_ldstm (str, VFP_LDSTMDB);
8212 }
8213
8214 static void
8215 do_vfp_xp_ldstmia (str)
8216 char *str;
8217 {
8218 vfp_dp_ldstm (str, VFP_LDSTMIAX);
8219 }
8220
8221 static void
8222 do_vfp_xp_ldstmdb (str)
8223 char *str;
8224 {
8225 vfp_dp_ldstm (str, VFP_LDSTMDBX);
8226 }
8227
8228 static void
8229 do_vfp_sp_compare_z (str)
8230 char *str;
8231 {
8232 skip_whitespace (str);
8233
8234 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
8235 {
8236 if (!inst.error)
8237 inst.error = BAD_ARGS;
8238 return;
8239 }
8240
8241 end_of_line (str);
8242 return;
8243 }
8244
8245 static void
8246 do_vfp_dp_compare_z (str)
8247 char *str;
8248 {
8249 skip_whitespace (str);
8250
8251 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
8252 {
8253 if (!inst.error)
8254 inst.error = BAD_ARGS;
8255 return;
8256 }
8257
8258 end_of_line (str);
8259 return;
8260 }
8261
8262 static void
8263 do_vfp_dp_sp_cvt (str)
8264 char *str;
8265 {
8266 skip_whitespace (str);
8267
8268 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
8269 return;
8270
8271 if (skip_past_comma (&str) == FAIL
8272 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
8273 {
8274 if (! inst.error)
8275 inst.error = BAD_ARGS;
8276 return;
8277 }
8278
8279 end_of_line (str);
8280 return;
8281 }
8282
8283 static void
8284 do_vfp_sp_dp_cvt (str)
8285 char *str;
8286 {
8287 skip_whitespace (str);
8288
8289 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
8290 return;
8291
8292 if (skip_past_comma (&str) == FAIL
8293 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
8294 {
8295 if (! inst.error)
8296 inst.error = BAD_ARGS;
8297 return;
8298 }
8299
8300 end_of_line (str);
8301 return;
8302 }
8303
8304 /* Thumb specific routines. */
8305
8306 /* Parse and validate that a register is of the right form, this saves
8307 repeated checking of this information in many similar cases.
8308 Unlike the 32-bit case we do not insert the register into the opcode
8309 here, since the position is often unknown until the full instruction
8310 has been parsed. */
8311
8312 static int
8313 thumb_reg (strp, hi_lo)
8314 char ** strp;
8315 int hi_lo;
8316 {
8317 int reg;
8318
8319 if ((reg = reg_required_here (strp, -1)) == FAIL)
8320 return FAIL;
8321
8322 switch (hi_lo)
8323 {
8324 case THUMB_REG_LO:
8325 if (reg > 7)
8326 {
8327 inst.error = _("lo register required");
8328 return FAIL;
8329 }
8330 break;
8331
8332 case THUMB_REG_HI:
8333 if (reg < 8)
8334 {
8335 inst.error = _("hi register required");
8336 return FAIL;
8337 }
8338 break;
8339
8340 default:
8341 break;
8342 }
8343
8344 return reg;
8345 }
8346
8347 /* Parse an add or subtract instruction, SUBTRACT is non-zero if the opcode
8348 was SUB. */
8349
8350 static void
8351 thumb_add_sub (str, subtract)
8352 char * str;
8353 int subtract;
8354 {
8355 int Rd, Rs, Rn = FAIL;
8356
8357 skip_whitespace (str);
8358
8359 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
8360 || skip_past_comma (&str) == FAIL)
8361 {
8362 if (! inst.error)
8363 inst.error = BAD_ARGS;
8364 return;
8365 }
8366
8367 if (is_immediate_prefix (*str))
8368 {
8369 Rs = Rd;
8370 str++;
8371 if (my_get_expression (&inst.reloc.exp, &str))
8372 return;
8373 }
8374 else
8375 {
8376 if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
8377 return;
8378
8379 if (skip_past_comma (&str) == FAIL)
8380 {
8381 /* Two operand format, shuffle the registers
8382 and pretend there are 3. */
8383 Rn = Rs;
8384 Rs = Rd;
8385 }
8386 else if (is_immediate_prefix (*str))
8387 {
8388 str++;
8389 if (my_get_expression (&inst.reloc.exp, &str))
8390 return;
8391 }
8392 else if ((Rn = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
8393 return;
8394 }
8395
8396 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
8397 for the latter case, EXPR contains the immediate that was found. */
8398 if (Rn != FAIL)
8399 {
8400 /* All register format. */
8401 if (Rd > 7 || Rs > 7 || Rn > 7)
8402 {
8403 if (Rs != Rd)
8404 {
8405 inst.error = _("dest and source1 must be the same register");
8406 return;
8407 }
8408
8409 /* Can't do this for SUB. */
8410 if (subtract)
8411 {
8412 inst.error = _("subtract valid only on lo regs");
8413 return;
8414 }
8415
8416 inst.instruction = (T_OPCODE_ADD_HI
8417 | (Rd > 7 ? THUMB_H1 : 0)
8418 | (Rn > 7 ? THUMB_H2 : 0));
8419 inst.instruction |= (Rd & 7) | ((Rn & 7) << 3);
8420 }
8421 else
8422 {
8423 inst.instruction = subtract ? T_OPCODE_SUB_R3 : T_OPCODE_ADD_R3;
8424 inst.instruction |= Rd | (Rs << 3) | (Rn << 6);
8425 }
8426 }
8427 else
8428 {
8429 /* Immediate expression, now things start to get nasty. */
8430
8431 /* First deal with HI regs, only very restricted cases allowed:
8432 Adjusting SP, and using PC or SP to get an address. */
8433 if ((Rd > 7 && (Rd != REG_SP || Rs != REG_SP))
8434 || (Rs > 7 && Rs != REG_SP && Rs != REG_PC))
8435 {
8436 inst.error = _("invalid Hi register with immediate");
8437 return;
8438 }
8439
8440 if (inst.reloc.exp.X_op != O_constant)
8441 {
8442 /* Value isn't known yet, all we can do is store all the fragments
8443 we know about in the instruction and let the reloc hacking
8444 work it all out. */
8445 inst.instruction = (subtract ? 0x8000 : 0) | (Rd << 4) | Rs;
8446 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
8447 }
8448 else
8449 {
8450 int offset = inst.reloc.exp.X_add_number;
8451
8452 if (subtract)
8453 offset = - offset;
8454
8455 if (offset < 0)
8456 {
8457 offset = - offset;
8458 subtract = 1;
8459
8460 /* Quick check, in case offset is MIN_INT. */
8461 if (offset < 0)
8462 {
8463 inst.error = _("immediate value out of range");
8464 return;
8465 }
8466 }
8467 /* Note - you cannot convert a subtract of 0 into an
8468 add of 0 because the carry flag is set differently. */
8469 else if (offset > 0)
8470 subtract = 0;
8471
8472 if (Rd == REG_SP)
8473 {
8474 if (offset & ~0x1fc)
8475 {
8476 inst.error = _("invalid immediate value for stack adjust");
8477 return;
8478 }
8479 inst.instruction = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
8480 inst.instruction |= offset >> 2;
8481 }
8482 else if (Rs == REG_PC || Rs == REG_SP)
8483 {
8484 if (subtract
8485 || (offset & ~0x3fc))
8486 {
8487 inst.error = _("invalid immediate for address calculation");
8488 return;
8489 }
8490 inst.instruction = (Rs == REG_PC ? T_OPCODE_ADD_PC
8491 : T_OPCODE_ADD_SP);
8492 inst.instruction |= (Rd << 8) | (offset >> 2);
8493 }
8494 else if (Rs == Rd)
8495 {
8496 if (offset & ~0xff)
8497 {
8498 inst.error = _("immediate value out of range");
8499 return;
8500 }
8501 inst.instruction = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
8502 inst.instruction |= (Rd << 8) | offset;
8503 }
8504 else
8505 {
8506 if (offset & ~0x7)
8507 {
8508 inst.error = _("immediate value out of range");
8509 return;
8510 }
8511 inst.instruction = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
8512 inst.instruction |= Rd | (Rs << 3) | (offset << 6);
8513 }
8514 }
8515 }
8516
8517 end_of_line (str);
8518 }
8519
8520 static void
8521 thumb_shift (str, shift)
8522 char * str;
8523 int shift;
8524 {
8525 int Rd, Rs, Rn = FAIL;
8526
8527 skip_whitespace (str);
8528
8529 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
8530 || skip_past_comma (&str) == FAIL)
8531 {
8532 if (! inst.error)
8533 inst.error = BAD_ARGS;
8534 return;
8535 }
8536
8537 if (is_immediate_prefix (*str))
8538 {
8539 /* Two operand immediate format, set Rs to Rd. */
8540 Rs = Rd;
8541 str ++;
8542 if (my_get_expression (&inst.reloc.exp, &str))
8543 return;
8544 }
8545 else
8546 {
8547 if ((Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
8548 return;
8549
8550 if (skip_past_comma (&str) == FAIL)
8551 {
8552 /* Two operand format, shuffle the registers
8553 and pretend there are 3. */
8554 Rn = Rs;
8555 Rs = Rd;
8556 }
8557 else if (is_immediate_prefix (*str))
8558 {
8559 str++;
8560 if (my_get_expression (&inst.reloc.exp, &str))
8561 return;
8562 }
8563 else if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
8564 return;
8565 }
8566
8567 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
8568 for the latter case, EXPR contains the immediate that was found. */
8569
8570 if (Rn != FAIL)
8571 {
8572 if (Rs != Rd)
8573 {
8574 inst.error = _("source1 and dest must be same register");
8575 return;
8576 }
8577
8578 switch (shift)
8579 {
8580 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_R; break;
8581 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_R; break;
8582 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_R; break;
8583 }
8584
8585 inst.instruction |= Rd | (Rn << 3);
8586 }
8587 else
8588 {
8589 switch (shift)
8590 {
8591 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_I; break;
8592 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_I; break;
8593 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_I; break;
8594 }
8595
8596 if (inst.reloc.exp.X_op != O_constant)
8597 {
8598 /* Value isn't known yet, create a dummy reloc and let reloc
8599 hacking fix it up. */
8600 inst.reloc.type = BFD_RELOC_ARM_THUMB_SHIFT;
8601 }
8602 else
8603 {
8604 unsigned shift_value = inst.reloc.exp.X_add_number;
8605
8606 if (shift_value > 32 || (shift_value == 32 && shift == THUMB_LSL))
8607 {
8608 inst.error = _("invalid immediate for shift");
8609 return;
8610 }
8611
8612 /* Shifts of zero are handled by converting to LSL. */
8613 if (shift_value == 0)
8614 inst.instruction = T_OPCODE_LSL_I;
8615
8616 /* Shifts of 32 are encoded as a shift of zero. */
8617 if (shift_value == 32)
8618 shift_value = 0;
8619
8620 inst.instruction |= shift_value << 6;
8621 }
8622
8623 inst.instruction |= Rd | (Rs << 3);
8624 }
8625
8626 end_of_line (str);
8627 }
8628
8629 static void
8630 thumb_mov_compare (str, move)
8631 char * str;
8632 int move;
8633 {
8634 int Rd, Rs = FAIL;
8635
8636 skip_whitespace (str);
8637
8638 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
8639 || skip_past_comma (&str) == FAIL)
8640 {
8641 if (! inst.error)
8642 inst.error = BAD_ARGS;
8643 return;
8644 }
8645
8646 if (is_immediate_prefix (*str))
8647 {
8648 str++;
8649 if (my_get_expression (&inst.reloc.exp, &str))
8650 return;
8651 }
8652 else if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
8653 return;
8654
8655 if (Rs != FAIL)
8656 {
8657 if (Rs < 8 && Rd < 8)
8658 {
8659 if (move == THUMB_MOVE)
8660 /* A move of two lowregs is encoded as ADD Rd, Rs, #0
8661 since a MOV instruction produces unpredictable results. */
8662 inst.instruction = T_OPCODE_ADD_I3;
8663 else
8664 inst.instruction = T_OPCODE_CMP_LR;
8665 inst.instruction |= Rd | (Rs << 3);
8666 }
8667 else
8668 {
8669 if (move == THUMB_MOVE)
8670 inst.instruction = T_OPCODE_MOV_HR;
8671 else
8672 inst.instruction = T_OPCODE_CMP_HR;
8673
8674 if (Rd > 7)
8675 inst.instruction |= THUMB_H1;
8676
8677 if (Rs > 7)
8678 inst.instruction |= THUMB_H2;
8679
8680 inst.instruction |= (Rd & 7) | ((Rs & 7) << 3);
8681 }
8682 }
8683 else
8684 {
8685 if (Rd > 7)
8686 {
8687 inst.error = _("only lo regs allowed with immediate");
8688 return;
8689 }
8690
8691 if (move == THUMB_MOVE)
8692 inst.instruction = T_OPCODE_MOV_I8;
8693 else
8694 inst.instruction = T_OPCODE_CMP_I8;
8695
8696 inst.instruction |= Rd << 8;
8697
8698 if (inst.reloc.exp.X_op != O_constant)
8699 inst.reloc.type = BFD_RELOC_ARM_THUMB_IMM;
8700 else
8701 {
8702 unsigned value = inst.reloc.exp.X_add_number;
8703
8704 if (value > 255)
8705 {
8706 inst.error = _("invalid immediate");
8707 return;
8708 }
8709
8710 inst.instruction |= value;
8711 }
8712 }
8713
8714 end_of_line (str);
8715 }
8716
8717 static void
8718 thumb_load_store (str, load_store, size)
8719 char * str;
8720 int load_store;
8721 int size;
8722 {
8723 int Rd, Rb, Ro = FAIL;
8724
8725 skip_whitespace (str);
8726
8727 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
8728 || skip_past_comma (&str) == FAIL)
8729 {
8730 if (! inst.error)
8731 inst.error = BAD_ARGS;
8732 return;
8733 }
8734
8735 if (*str == '[')
8736 {
8737 str++;
8738 if ((Rb = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
8739 return;
8740
8741 if (skip_past_comma (&str) != FAIL)
8742 {
8743 if (is_immediate_prefix (*str))
8744 {
8745 str++;
8746 if (my_get_expression (&inst.reloc.exp, &str))
8747 return;
8748 }
8749 else if ((Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
8750 return;
8751 }
8752 else
8753 {
8754 inst.reloc.exp.X_op = O_constant;
8755 inst.reloc.exp.X_add_number = 0;
8756 }
8757
8758 if (*str != ']')
8759 {
8760 inst.error = _("expected ']'");
8761 return;
8762 }
8763 str++;
8764 }
8765 else if (*str == '=')
8766 {
8767 if (load_store != THUMB_LOAD)
8768 {
8769 inst.error = _("invalid pseudo operation");
8770 return;
8771 }
8772
8773 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
8774 str++;
8775
8776 skip_whitespace (str);
8777
8778 if (my_get_expression (& inst.reloc.exp, & str))
8779 return;
8780
8781 end_of_line (str);
8782
8783 if ( inst.reloc.exp.X_op != O_constant
8784 && inst.reloc.exp.X_op != O_symbol)
8785 {
8786 inst.error = "Constant expression expected";
8787 return;
8788 }
8789
8790 if (inst.reloc.exp.X_op == O_constant
8791 && ((inst.reloc.exp.X_add_number & ~0xFF) == 0))
8792 {
8793 /* This can be done with a mov instruction. */
8794
8795 inst.instruction = T_OPCODE_MOV_I8 | (Rd << 8);
8796 inst.instruction |= inst.reloc.exp.X_add_number;
8797 return;
8798 }
8799
8800 /* Insert into literal pool. */
8801 if (add_to_lit_pool () == FAIL)
8802 {
8803 if (!inst.error)
8804 inst.error = "literal pool insertion failed";
8805 return;
8806 }
8807
8808 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
8809 inst.reloc.pc_rel = 1;
8810 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
8811 /* Adjust ARM pipeline offset to Thumb. */
8812 inst.reloc.exp.X_add_number += 4;
8813
8814 return;
8815 }
8816 else
8817 {
8818 if (my_get_expression (&inst.reloc.exp, &str))
8819 return;
8820
8821 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
8822 inst.reloc.pc_rel = 1;
8823 inst.reloc.exp.X_add_number -= 4; /* Pipeline offset. */
8824 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
8825 end_of_line (str);
8826 return;
8827 }
8828
8829 if (Rb == REG_PC || Rb == REG_SP)
8830 {
8831 if (size != THUMB_WORD)
8832 {
8833 inst.error = _("byte or halfword not valid for base register");
8834 return;
8835 }
8836 else if (Rb == REG_PC && load_store != THUMB_LOAD)
8837 {
8838 inst.error = _("r15 based store not allowed");
8839 return;
8840 }
8841 else if (Ro != FAIL)
8842 {
8843 inst.error = _("invalid base register for register offset");
8844 return;
8845 }
8846
8847 if (Rb == REG_PC)
8848 inst.instruction = T_OPCODE_LDR_PC;
8849 else if (load_store == THUMB_LOAD)
8850 inst.instruction = T_OPCODE_LDR_SP;
8851 else
8852 inst.instruction = T_OPCODE_STR_SP;
8853
8854 inst.instruction |= Rd << 8;
8855 if (inst.reloc.exp.X_op == O_constant)
8856 {
8857 unsigned offset = inst.reloc.exp.X_add_number;
8858
8859 if (offset & ~0x3fc)
8860 {
8861 inst.error = _("invalid offset");
8862 return;
8863 }
8864
8865 inst.instruction |= offset >> 2;
8866 }
8867 else
8868 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
8869 }
8870 else if (Rb > 7)
8871 {
8872 inst.error = _("invalid base register in load/store");
8873 return;
8874 }
8875 else if (Ro == FAIL)
8876 {
8877 /* Immediate offset. */
8878 if (size == THUMB_WORD)
8879 inst.instruction = (load_store == THUMB_LOAD
8880 ? T_OPCODE_LDR_IW : T_OPCODE_STR_IW);
8881 else if (size == THUMB_HALFWORD)
8882 inst.instruction = (load_store == THUMB_LOAD
8883 ? T_OPCODE_LDR_IH : T_OPCODE_STR_IH);
8884 else
8885 inst.instruction = (load_store == THUMB_LOAD
8886 ? T_OPCODE_LDR_IB : T_OPCODE_STR_IB);
8887
8888 inst.instruction |= Rd | (Rb << 3);
8889
8890 if (inst.reloc.exp.X_op == O_constant)
8891 {
8892 unsigned offset = inst.reloc.exp.X_add_number;
8893
8894 if (offset & ~(0x1f << size))
8895 {
8896 inst.error = _("invalid offset");
8897 return;
8898 }
8899 inst.instruction |= (offset >> size) << 6;
8900 }
8901 else
8902 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
8903 }
8904 else
8905 {
8906 /* Register offset. */
8907 if (size == THUMB_WORD)
8908 inst.instruction = (load_store == THUMB_LOAD
8909 ? T_OPCODE_LDR_RW : T_OPCODE_STR_RW);
8910 else if (size == THUMB_HALFWORD)
8911 inst.instruction = (load_store == THUMB_LOAD
8912 ? T_OPCODE_LDR_RH : T_OPCODE_STR_RH);
8913 else
8914 inst.instruction = (load_store == THUMB_LOAD
8915 ? T_OPCODE_LDR_RB : T_OPCODE_STR_RB);
8916
8917 inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
8918 }
8919
8920 end_of_line (str);
8921 }
8922
8923 /* A register must be given at this point.
8924
8925 Shift is the place to put it in inst.instruction.
8926
8927 Restores input start point on err.
8928 Returns the reg#, or FAIL. */
8929
8930 static int
8931 mav_reg_required_here (str, shift, regtype)
8932 char ** str;
8933 int shift;
8934 enum arm_reg_type regtype;
8935 {
8936 int reg;
8937 char *start = *str;
8938
8939 if ((reg = arm_reg_parse (str, all_reg_maps[regtype].htab)) != FAIL)
8940 {
8941 if (shift >= 0)
8942 inst.instruction |= reg << shift;
8943
8944 return reg;
8945 }
8946
8947 /* Restore the start point. */
8948 *str = start;
8949
8950 /* In the few cases where we might be able to accept something else
8951 this error can be overridden. */
8952 inst.error = _(all_reg_maps[regtype].expected);
8953
8954 return FAIL;
8955 }
8956
8957 /* Cirrus Maverick Instructions. */
8958
8959 /* Wrapper functions. */
8960
8961 static void
8962 do_mav_binops_1a (str)
8963 char * str;
8964 {
8965 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVF);
8966 }
8967
8968 static void
8969 do_mav_binops_1b (str)
8970 char * str;
8971 {
8972 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVD);
8973 }
8974
8975 static void
8976 do_mav_binops_1c (str)
8977 char * str;
8978 {
8979 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVDX);
8980 }
8981
8982 static void
8983 do_mav_binops_1d (str)
8984 char * str;
8985 {
8986 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVF);
8987 }
8988
8989 static void
8990 do_mav_binops_1e (str)
8991 char * str;
8992 {
8993 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVD);
8994 }
8995
8996 static void
8997 do_mav_binops_1f (str)
8998 char * str;
8999 {
9000 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVF);
9001 }
9002
9003 static void
9004 do_mav_binops_1g (str)
9005 char * str;
9006 {
9007 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVD);
9008 }
9009
9010 static void
9011 do_mav_binops_1h (str)
9012 char * str;
9013 {
9014 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVFX);
9015 }
9016
9017 static void
9018 do_mav_binops_1i (str)
9019 char * str;
9020 {
9021 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVFX);
9022 }
9023
9024 static void
9025 do_mav_binops_1j (str)
9026 char * str;
9027 {
9028 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVDX);
9029 }
9030
9031 static void
9032 do_mav_binops_1k (str)
9033 char * str;
9034 {
9035 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVDX);
9036 }
9037
9038 static void
9039 do_mav_binops_1l (str)
9040 char * str;
9041 {
9042 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVF);
9043 }
9044
9045 static void
9046 do_mav_binops_1m (str)
9047 char * str;
9048 {
9049 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVD);
9050 }
9051
9052 static void
9053 do_mav_binops_1n (str)
9054 char * str;
9055 {
9056 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVFX);
9057 }
9058
9059 static void
9060 do_mav_binops_1o (str)
9061 char * str;
9062 {
9063 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVDX, REG_TYPE_MVDX);
9064 }
9065
9066 static void
9067 do_mav_binops_2a (str)
9068 char * str;
9069 {
9070 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVF, REG_TYPE_RN);
9071 }
9072
9073 static void
9074 do_mav_binops_2b (str)
9075 char * str;
9076 {
9077 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVD, REG_TYPE_RN);
9078 }
9079
9080 static void
9081 do_mav_binops_2c (str)
9082 char * str;
9083 {
9084 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVDX, REG_TYPE_RN);
9085 }
9086
9087 static void
9088 do_mav_binops_3a (str)
9089 char * str;
9090 {
9091 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVAX, REG_TYPE_MVFX);
9092 }
9093
9094 static void
9095 do_mav_binops_3b (str)
9096 char * str;
9097 {
9098 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVFX, REG_TYPE_MVAX);
9099 }
9100
9101 static void
9102 do_mav_binops_3c (str)
9103 char * str;
9104 {
9105 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVAX, REG_TYPE_MVDX);
9106 }
9107
9108 static void
9109 do_mav_binops_3d (str)
9110 char * str;
9111 {
9112 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVDX, REG_TYPE_MVAX);
9113 }
9114
9115 static void
9116 do_mav_triple_4a (str)
9117 char * str;
9118 {
9119 do_mav_triple (str, MAV_MODE4, REG_TYPE_MVFX, REG_TYPE_MVFX, REG_TYPE_RN);
9120 }
9121
9122 static void
9123 do_mav_triple_4b (str)
9124 char * str;
9125 {
9126 do_mav_triple (str, MAV_MODE4, REG_TYPE_MVDX, REG_TYPE_MVDX, REG_TYPE_RN);
9127 }
9128
9129 static void
9130 do_mav_triple_5a (str)
9131 char * str;
9132 {
9133 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVF, REG_TYPE_MVF);
9134 }
9135
9136 static void
9137 do_mav_triple_5b (str)
9138 char * str;
9139 {
9140 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVD, REG_TYPE_MVD);
9141 }
9142
9143 static void
9144 do_mav_triple_5c (str)
9145 char * str;
9146 {
9147 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVFX, REG_TYPE_MVFX);
9148 }
9149
9150 static void
9151 do_mav_triple_5d (str)
9152 char * str;
9153 {
9154 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVDX, REG_TYPE_MVDX);
9155 }
9156
9157 static void
9158 do_mav_triple_5e (str)
9159 char * str;
9160 {
9161 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVF, REG_TYPE_MVF, REG_TYPE_MVF);
9162 }
9163
9164 static void
9165 do_mav_triple_5f (str)
9166 char * str;
9167 {
9168 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVD, REG_TYPE_MVD, REG_TYPE_MVD);
9169 }
9170
9171 static void
9172 do_mav_triple_5g (str)
9173 char * str;
9174 {
9175 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVFX, REG_TYPE_MVFX, REG_TYPE_MVFX);
9176 }
9177
9178 static void
9179 do_mav_triple_5h (str)
9180 char * str;
9181 {
9182 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVDX, REG_TYPE_MVDX, REG_TYPE_MVDX);
9183 }
9184
9185 static void
9186 do_mav_quad_6a (str)
9187 char * str;
9188 {
9189 do_mav_quad (str, MAV_MODE6, REG_TYPE_MVAX, REG_TYPE_MVFX, REG_TYPE_MVFX,
9190 REG_TYPE_MVFX);
9191 }
9192
9193 static void
9194 do_mav_quad_6b (str)
9195 char * str;
9196 {
9197 do_mav_quad (str, MAV_MODE6, REG_TYPE_MVAX, REG_TYPE_MVAX, REG_TYPE_MVFX,
9198 REG_TYPE_MVFX);
9199 }
9200
9201 /* cfmvsc32<cond> DSPSC,MVFX[15:0]. */
9202 static void
9203 do_mav_dspsc_1 (str)
9204 char * str;
9205 {
9206 skip_whitespace (str);
9207
9208 /* cfmvsc32. */
9209 if (mav_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL
9210 || skip_past_comma (&str) == FAIL
9211 || mav_reg_required_here (&str, 16, REG_TYPE_MVFX) == FAIL)
9212 {
9213 if (!inst.error)
9214 inst.error = BAD_ARGS;
9215
9216 return;
9217 }
9218
9219 end_of_line (str);
9220 }
9221
9222 /* cfmv32sc<cond> MVFX[15:0],DSPSC. */
9223 static void
9224 do_mav_dspsc_2 (str)
9225 char * str;
9226 {
9227 skip_whitespace (str);
9228
9229 /* cfmv32sc. */
9230 if (mav_reg_required_here (&str, 0, REG_TYPE_MVFX) == FAIL
9231 || skip_past_comma (&str) == FAIL
9232 || mav_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL)
9233 {
9234 if (!inst.error)
9235 inst.error = BAD_ARGS;
9236
9237 return;
9238 }
9239
9240 end_of_line (str);
9241 }
9242
9243 static void
9244 do_mav_shift_1 (str)
9245 char * str;
9246 {
9247 do_mav_shift (str, REG_TYPE_MVFX, REG_TYPE_MVFX);
9248 }
9249
9250 static void
9251 do_mav_shift_2 (str)
9252 char * str;
9253 {
9254 do_mav_shift (str, REG_TYPE_MVDX, REG_TYPE_MVDX);
9255 }
9256
9257 static void
9258 do_mav_ldst_1 (str)
9259 char * str;
9260 {
9261 do_mav_ldst (str, REG_TYPE_MVF);
9262 }
9263
9264 static void
9265 do_mav_ldst_2 (str)
9266 char * str;
9267 {
9268 do_mav_ldst (str, REG_TYPE_MVD);
9269 }
9270
9271 static void
9272 do_mav_ldst_3 (str)
9273 char * str;
9274 {
9275 do_mav_ldst (str, REG_TYPE_MVFX);
9276 }
9277
9278 static void
9279 do_mav_ldst_4 (str)
9280 char * str;
9281 {
9282 do_mav_ldst (str, REG_TYPE_MVDX);
9283 }
9284
9285 /* Isnsn like "foo X,Y". */
9286
9287 static void
9288 do_mav_binops (str, mode, reg0, reg1)
9289 char * str;
9290 int mode;
9291 enum arm_reg_type reg0;
9292 enum arm_reg_type reg1;
9293 {
9294 int shift0, shift1;
9295
9296 shift0 = mode & 0xff;
9297 shift1 = (mode >> 8) & 0xff;
9298
9299 skip_whitespace (str);
9300
9301 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
9302 || skip_past_comma (&str) == FAIL
9303 || mav_reg_required_here (&str, shift1, reg1) == FAIL)
9304 {
9305 if (!inst.error)
9306 inst.error = BAD_ARGS;
9307 }
9308 else
9309 end_of_line (str);
9310 }
9311
9312 /* Isnsn like "foo X,Y,Z". */
9313
9314 static void
9315 do_mav_triple (str, mode, reg0, reg1, reg2)
9316 char * str;
9317 int mode;
9318 enum arm_reg_type reg0;
9319 enum arm_reg_type reg1;
9320 enum arm_reg_type reg2;
9321 {
9322 int shift0, shift1, shift2;
9323
9324 shift0 = mode & 0xff;
9325 shift1 = (mode >> 8) & 0xff;
9326 shift2 = (mode >> 16) & 0xff;
9327
9328 skip_whitespace (str);
9329
9330 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
9331 || skip_past_comma (&str) == FAIL
9332 || mav_reg_required_here (&str, shift1, reg1) == FAIL
9333 || skip_past_comma (&str) == FAIL
9334 || mav_reg_required_here (&str, shift2, reg2) == FAIL)
9335 {
9336 if (!inst.error)
9337 inst.error = BAD_ARGS;
9338 }
9339 else
9340 end_of_line (str);
9341 }
9342
9343 /* Isnsn like "foo W,X,Y,Z".
9344 where W=MVAX[0:3] and X,Y,Z=MVFX[0:15]. */
9345
9346 static void
9347 do_mav_quad (str, mode, reg0, reg1, reg2, reg3)
9348 char * str;
9349 int mode;
9350 enum arm_reg_type reg0;
9351 enum arm_reg_type reg1;
9352 enum arm_reg_type reg2;
9353 enum arm_reg_type reg3;
9354 {
9355 int shift0, shift1, shift2, shift3;
9356
9357 shift0= mode & 0xff;
9358 shift1 = (mode >> 8) & 0xff;
9359 shift2 = (mode >> 16) & 0xff;
9360 shift3 = (mode >> 24) & 0xff;
9361
9362 skip_whitespace (str);
9363
9364 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
9365 || skip_past_comma (&str) == FAIL
9366 || mav_reg_required_here (&str, shift1, reg1) == FAIL
9367 || skip_past_comma (&str) == FAIL
9368 || mav_reg_required_here (&str, shift2, reg2) == FAIL
9369 || skip_past_comma (&str) == FAIL
9370 || mav_reg_required_here (&str, shift3, reg3) == FAIL)
9371 {
9372 if (!inst.error)
9373 inst.error = BAD_ARGS;
9374 }
9375 else
9376 end_of_line (str);
9377 }
9378
9379 /* Maverick shift immediate instructions.
9380 cfsh32<cond> MVFX[15:0],MVFX[15:0],Shift[6:0].
9381 cfsh64<cond> MVDX[15:0],MVDX[15:0],Shift[6:0]. */
9382
9383 static void
9384 do_mav_shift (str, reg0, reg1)
9385 char * str;
9386 enum arm_reg_type reg0;
9387 enum arm_reg_type reg1;
9388 {
9389 int error;
9390 int imm, neg = 0;
9391
9392 skip_whitespace (str);
9393
9394 error = 0;
9395
9396 if (mav_reg_required_here (&str, 12, reg0) == FAIL
9397 || skip_past_comma (&str) == FAIL
9398 || mav_reg_required_here (&str, 16, reg1) == FAIL
9399 || skip_past_comma (&str) == FAIL)
9400 {
9401 if (!inst.error)
9402 inst.error = BAD_ARGS;
9403 return;
9404 }
9405
9406 /* Calculate the immediate operand.
9407 The operand is a 7bit signed number. */
9408 skip_whitespace (str);
9409
9410 if (*str == '#')
9411 ++str;
9412
9413 if (!ISDIGIT (*str) && *str != '-')
9414 {
9415 inst.error = _("expecting immediate, 7bit operand");
9416 return;
9417 }
9418
9419 if (*str == '-')
9420 {
9421 neg = 1;
9422 ++str;
9423 }
9424
9425 for (imm = 0; *str && ISDIGIT (*str); ++str)
9426 imm = imm * 10 + *str - '0';
9427
9428 if (imm > 64)
9429 {
9430 inst.error = _("immediate out of range");
9431 return;
9432 }
9433
9434 /* Make negative imm's into 7bit signed numbers. */
9435 if (neg)
9436 {
9437 imm = -imm;
9438 imm &= 0x0000007f;
9439 }
9440
9441 /* Bits 0-3 of the insn should have bits 0-3 of the immediate.
9442 Bits 5-7 of the insn should have bits 4-6 of the immediate.
9443 Bit 4 should be 0. */
9444 imm = (imm & 0xf) | ((imm & 0x70) << 1);
9445
9446 inst.instruction |= imm;
9447 end_of_line (str);
9448 }
9449
9450 static int
9451 mav_parse_offset (str, negative)
9452 char ** str;
9453 int *negative;
9454 {
9455 char * p = *str;
9456 int offset;
9457
9458 *negative = 0;
9459
9460 skip_whitespace (p);
9461
9462 if (*p == '#')
9463 ++p;
9464
9465 if (*p == '-')
9466 {
9467 *negative = 1;
9468 ++p;
9469 }
9470
9471 if (!ISDIGIT (*p))
9472 {
9473 inst.error = _("offset expected");
9474 return 0;
9475 }
9476
9477 for (offset = 0; *p && ISDIGIT (*p); ++p)
9478 offset = offset * 10 + *p - '0';
9479
9480 if (offset > 0xff)
9481 {
9482 inst.error = _("offset out of range");
9483 return 0;
9484 }
9485
9486 *str = p;
9487
9488 return *negative ? -offset : offset;
9489 }
9490
9491 /* Maverick load/store instructions.
9492 <insn><cond> CRd,[Rn,<offset>]{!}.
9493 <insn><cond> CRd,[Rn],<offset>. */
9494
9495 static void
9496 do_mav_ldst (str, reg0)
9497 char * str;
9498 enum arm_reg_type reg0;
9499 {
9500 int offset, negative;
9501
9502 skip_whitespace (str);
9503
9504 if (mav_reg_required_here (&str, 12, reg0) == FAIL
9505 || skip_past_comma (&str) == FAIL
9506 || *str++ != '['
9507 || reg_required_here (&str, 16) == FAIL)
9508 goto fail_ldst;
9509
9510 if (skip_past_comma (&str) == SUCCESS)
9511 {
9512 /* You are here: "<offset>]{!}". */
9513 inst.instruction |= PRE_INDEX;
9514
9515 offset = mav_parse_offset (&str, &negative);
9516
9517 if (inst.error)
9518 return;
9519
9520 if (*str++ != ']')
9521 {
9522 inst.error = _("missing ]");
9523 return;
9524 }
9525
9526 if (*str == '!')
9527 {
9528 inst.instruction |= WRITE_BACK;
9529 ++str;
9530 }
9531 }
9532 else
9533 {
9534 /* You are here: "], <offset>". */
9535 if (*str++ != ']')
9536 {
9537 inst.error = _("missing ]");
9538 return;
9539 }
9540
9541 if (skip_past_comma (&str) == FAIL
9542 || (offset = mav_parse_offset (&str, &negative), inst.error))
9543 goto fail_ldst;
9544
9545 inst.instruction |= CP_T_WB; /* Post indexed, set bit W. */
9546 }
9547
9548 if (negative)
9549 offset = -offset;
9550 else
9551 inst.instruction |= CP_T_UD; /* Postive, so set bit U. */
9552
9553 inst.instruction |= offset >> 2;
9554 end_of_line (str);
9555 return;
9556
9557 fail_ldst:
9558 if (!inst.error)
9559 inst.error = BAD_ARGS;
9560 return;
9561 }
9562
9563 static void
9564 do_t_nop (str)
9565 char * str;
9566 {
9567 /* Do nothing. */
9568 end_of_line (str);
9569 return;
9570 }
9571
9572 /* Handle the Format 4 instructions that do not have equivalents in other
9573 formats. That is, ADC, AND, EOR, SBC, ROR, TST, NEG, CMN, ORR, MUL,
9574 BIC and MVN. */
9575
9576 static void
9577 do_t_arit (str)
9578 char * str;
9579 {
9580 int Rd, Rs, Rn;
9581
9582 skip_whitespace (str);
9583
9584 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9585 || skip_past_comma (&str) == FAIL
9586 || (Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9587 {
9588 inst.error = BAD_ARGS;
9589 return;
9590 }
9591
9592 if (skip_past_comma (&str) != FAIL)
9593 {
9594 /* Three operand format not allowed for TST, CMN, NEG and MVN.
9595 (It isn't allowed for CMP either, but that isn't handled by this
9596 function.) */
9597 if (inst.instruction == T_OPCODE_TST
9598 || inst.instruction == T_OPCODE_CMN
9599 || inst.instruction == T_OPCODE_NEG
9600 || inst.instruction == T_OPCODE_MVN)
9601 {
9602 inst.error = BAD_ARGS;
9603 return;
9604 }
9605
9606 if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9607 return;
9608
9609 if (Rs != Rd)
9610 {
9611 inst.error = _("dest and source1 must be the same register");
9612 return;
9613 }
9614 Rs = Rn;
9615 }
9616
9617 if (inst.instruction == T_OPCODE_MUL
9618 && Rs == Rd)
9619 as_tsktsk (_("Rs and Rd must be different in MUL"));
9620
9621 inst.instruction |= Rd | (Rs << 3);
9622 end_of_line (str);
9623 }
9624
9625 static void
9626 do_t_add (str)
9627 char * str;
9628 {
9629 thumb_add_sub (str, 0);
9630 }
9631
9632 static void
9633 do_t_asr (str)
9634 char * str;
9635 {
9636 thumb_shift (str, THUMB_ASR);
9637 }
9638
9639 static void
9640 do_t_branch9 (str)
9641 char * str;
9642 {
9643 if (my_get_expression (&inst.reloc.exp, &str))
9644 return;
9645 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH9;
9646 inst.reloc.pc_rel = 1;
9647 end_of_line (str);
9648 }
9649
9650 static void
9651 do_t_branch12 (str)
9652 char * str;
9653 {
9654 if (my_get_expression (&inst.reloc.exp, &str))
9655 return;
9656 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH12;
9657 inst.reloc.pc_rel = 1;
9658 end_of_line (str);
9659 }
9660
9661 /* Find the real, Thumb encoded start of a Thumb function. */
9662
9663 static symbolS *
9664 find_real_start (symbolP)
9665 symbolS * symbolP;
9666 {
9667 char * real_start;
9668 const char * name = S_GET_NAME (symbolP);
9669 symbolS * new_target;
9670
9671 /* This definiton must agree with the one in gcc/config/arm/thumb.c. */
9672 #define STUB_NAME ".real_start_of"
9673
9674 if (name == NULL)
9675 abort ();
9676
9677 /* Names that start with '.' are local labels, not function entry points.
9678 The compiler may generate BL instructions to these labels because it
9679 needs to perform a branch to a far away location. */
9680 if (name[0] == '.')
9681 return symbolP;
9682
9683 real_start = malloc (strlen (name) + strlen (STUB_NAME) + 1);
9684 sprintf (real_start, "%s%s", STUB_NAME, name);
9685
9686 new_target = symbol_find (real_start);
9687
9688 if (new_target == NULL)
9689 {
9690 as_warn ("Failed to find real start of function: %s\n", name);
9691 new_target = symbolP;
9692 }
9693
9694 free (real_start);
9695
9696 return new_target;
9697 }
9698
9699 static void
9700 do_t_branch23 (str)
9701 char * str;
9702 {
9703 if (my_get_expression (& inst.reloc.exp, & str))
9704 return;
9705
9706 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH23;
9707 inst.reloc.pc_rel = 1;
9708 end_of_line (str);
9709
9710 /* If the destination of the branch is a defined symbol which does not have
9711 the THUMB_FUNC attribute, then we must be calling a function which has
9712 the (interfacearm) attribute. We look for the Thumb entry point to that
9713 function and change the branch to refer to that function instead. */
9714 if ( inst.reloc.exp.X_op == O_symbol
9715 && inst.reloc.exp.X_add_symbol != NULL
9716 && S_IS_DEFINED (inst.reloc.exp.X_add_symbol)
9717 && ! THUMB_IS_FUNC (inst.reloc.exp.X_add_symbol))
9718 inst.reloc.exp.X_add_symbol =
9719 find_real_start (inst.reloc.exp.X_add_symbol);
9720 }
9721
9722 static void
9723 do_t_bx (str)
9724 char * str;
9725 {
9726 int reg;
9727
9728 skip_whitespace (str);
9729
9730 if ((reg = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
9731 return;
9732
9733 /* This sets THUMB_H2 from the top bit of reg. */
9734 inst.instruction |= reg << 3;
9735
9736 /* ??? FIXME: Should add a hacky reloc here if reg is REG_PC. The reloc
9737 should cause the alignment to be checked once it is known. This is
9738 because BX PC only works if the instruction is word aligned. */
9739
9740 end_of_line (str);
9741 }
9742
9743 static void
9744 do_t_compare (str)
9745 char * str;
9746 {
9747 thumb_mov_compare (str, THUMB_COMPARE);
9748 }
9749
9750 static void
9751 do_t_ldmstm (str)
9752 char * str;
9753 {
9754 int Rb;
9755 long range;
9756
9757 skip_whitespace (str);
9758
9759 if ((Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9760 return;
9761
9762 if (*str != '!')
9763 as_warn (_("inserted missing '!': load/store multiple always writes back base register"));
9764 else
9765 str++;
9766
9767 if (skip_past_comma (&str) == FAIL
9768 || (range = reg_list (&str)) == FAIL)
9769 {
9770 if (! inst.error)
9771 inst.error = BAD_ARGS;
9772 return;
9773 }
9774
9775 if (inst.reloc.type != BFD_RELOC_NONE)
9776 {
9777 /* This really doesn't seem worth it. */
9778 inst.reloc.type = BFD_RELOC_NONE;
9779 inst.error = _("expression too complex");
9780 return;
9781 }
9782
9783 if (range & ~0xff)
9784 {
9785 inst.error = _("only lo-regs valid in load/store multiple");
9786 return;
9787 }
9788
9789 inst.instruction |= (Rb << 8) | range;
9790 end_of_line (str);
9791 }
9792
9793 static void
9794 do_t_ldr (str)
9795 char * str;
9796 {
9797 thumb_load_store (str, THUMB_LOAD, THUMB_WORD);
9798 }
9799
9800 static void
9801 do_t_ldrb (str)
9802 char * str;
9803 {
9804 thumb_load_store (str, THUMB_LOAD, THUMB_BYTE);
9805 }
9806
9807 static void
9808 do_t_ldrh (str)
9809 char * str;
9810 {
9811 thumb_load_store (str, THUMB_LOAD, THUMB_HALFWORD);
9812 }
9813
9814 static void
9815 do_t_lds (str)
9816 char * str;
9817 {
9818 int Rd, Rb, Ro;
9819
9820 skip_whitespace (str);
9821
9822 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9823 || skip_past_comma (&str) == FAIL
9824 || *str++ != '['
9825 || (Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9826 || skip_past_comma (&str) == FAIL
9827 || (Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9828 || *str++ != ']')
9829 {
9830 if (! inst.error)
9831 inst.error = _("syntax: ldrs[b] Rd, [Rb, Ro]");
9832 return;
9833 }
9834
9835 inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
9836 end_of_line (str);
9837 }
9838
9839 static void
9840 do_t_lsl (str)
9841 char * str;
9842 {
9843 thumb_shift (str, THUMB_LSL);
9844 }
9845
9846 static void
9847 do_t_lsr (str)
9848 char * str;
9849 {
9850 thumb_shift (str, THUMB_LSR);
9851 }
9852
9853 static void
9854 do_t_mov (str)
9855 char * str;
9856 {
9857 thumb_mov_compare (str, THUMB_MOVE);
9858 }
9859
9860 static void
9861 do_t_push_pop (str)
9862 char * str;
9863 {
9864 long range;
9865
9866 skip_whitespace (str);
9867
9868 if ((range = reg_list (&str)) == FAIL)
9869 {
9870 if (! inst.error)
9871 inst.error = BAD_ARGS;
9872 return;
9873 }
9874
9875 if (inst.reloc.type != BFD_RELOC_NONE)
9876 {
9877 /* This really doesn't seem worth it. */
9878 inst.reloc.type = BFD_RELOC_NONE;
9879 inst.error = _("expression too complex");
9880 return;
9881 }
9882
9883 if (range & ~0xff)
9884 {
9885 if ((inst.instruction == T_OPCODE_PUSH
9886 && (range & ~0xff) == 1 << REG_LR)
9887 || (inst.instruction == T_OPCODE_POP
9888 && (range & ~0xff) == 1 << REG_PC))
9889 {
9890 inst.instruction |= THUMB_PP_PC_LR;
9891 range &= 0xff;
9892 }
9893 else
9894 {
9895 inst.error = _("invalid register list to push/pop instruction");
9896 return;
9897 }
9898 }
9899
9900 inst.instruction |= range;
9901 end_of_line (str);
9902 }
9903
9904 static void
9905 do_t_str (str)
9906 char * str;
9907 {
9908 thumb_load_store (str, THUMB_STORE, THUMB_WORD);
9909 }
9910
9911 static void
9912 do_t_strb (str)
9913 char * str;
9914 {
9915 thumb_load_store (str, THUMB_STORE, THUMB_BYTE);
9916 }
9917
9918 static void
9919 do_t_strh (str)
9920 char * str;
9921 {
9922 thumb_load_store (str, THUMB_STORE, THUMB_HALFWORD);
9923 }
9924
9925 static void
9926 do_t_sub (str)
9927 char * str;
9928 {
9929 thumb_add_sub (str, 1);
9930 }
9931
9932 static void
9933 do_t_swi (str)
9934 char * str;
9935 {
9936 skip_whitespace (str);
9937
9938 if (my_get_expression (&inst.reloc.exp, &str))
9939 return;
9940
9941 inst.reloc.type = BFD_RELOC_ARM_SWI;
9942 end_of_line (str);
9943 return;
9944 }
9945
9946 static void
9947 do_t_adr (str)
9948 char * str;
9949 {
9950 int reg;
9951
9952 /* This is a pseudo-op of the form "adr rd, label" to be converted
9953 into a relative address of the form "add rd, pc, #label-.-4". */
9954 skip_whitespace (str);
9955
9956 /* Store Rd in temporary location inside instruction. */
9957 if ((reg = reg_required_here (&str, 4)) == FAIL
9958 || (reg > 7) /* For Thumb reg must be r0..r7. */
9959 || skip_past_comma (&str) == FAIL
9960 || my_get_expression (&inst.reloc.exp, &str))
9961 {
9962 if (!inst.error)
9963 inst.error = BAD_ARGS;
9964 return;
9965 }
9966
9967 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
9968 inst.reloc.exp.X_add_number -= 4; /* PC relative adjust. */
9969 inst.reloc.pc_rel = 1;
9970 inst.instruction |= REG_PC; /* Rd is already placed into the instruction. */
9971
9972 end_of_line (str);
9973 }
9974
9975 static void
9976 insert_reg (r, htab)
9977 const struct reg_entry *r;
9978 struct hash_control *htab;
9979 {
9980 int len = strlen (r->name) + 2;
9981 char * buf = (char *) xmalloc (len);
9982 char * buf2 = (char *) xmalloc (len);
9983 int i = 0;
9984
9985 #ifdef REGISTER_PREFIX
9986 buf[i++] = REGISTER_PREFIX;
9987 #endif
9988
9989 strcpy (buf + i, r->name);
9990
9991 for (i = 0; buf[i]; i++)
9992 buf2[i] = TOUPPER (buf[i]);
9993
9994 buf2[i] = '\0';
9995
9996 hash_insert (htab, buf, (PTR) r);
9997 hash_insert (htab, buf2, (PTR) r);
9998 }
9999
10000 static void
10001 build_reg_hsh (map)
10002 struct reg_map *map;
10003 {
10004 const struct reg_entry *r;
10005
10006 if ((map->htab = hash_new ()) == NULL)
10007 as_fatal (_("virtual memory exhausted"));
10008
10009 for (r = map->names; r->name != NULL; r++)
10010 insert_reg (r, map->htab);
10011 }
10012
10013 static void
10014 insert_reg_alias (str, regnum, htab)
10015 char *str;
10016 int regnum;
10017 struct hash_control *htab;
10018 {
10019 struct reg_entry *new =
10020 (struct reg_entry *) xmalloc (sizeof (struct reg_entry));
10021 char *name = xmalloc (strlen (str) + 1);
10022 strcpy (name, str);
10023
10024 new->name = name;
10025 new->number = regnum;
10026
10027 hash_insert (htab, name, (PTR) new);
10028 }
10029
10030 /* Look for the .req directive. This is of the form:
10031
10032 newname .req existing_name
10033
10034 If we find one, or if it looks sufficiently like one that we want to
10035 handle any error here, return non-zero. Otherwise return zero. */
10036 static int
10037 create_register_alias (newname, p)
10038 char *newname;
10039 char *p;
10040 {
10041 char *q;
10042 char c;
10043
10044 q = p;
10045 skip_whitespace (q);
10046
10047 c = *p;
10048 *p = '\0';
10049
10050 if (*q && !strncmp (q, ".req ", 5))
10051 {
10052 char *copy_of_str;
10053 char *r;
10054
10055 #ifdef IGNORE_OPCODE_CASE
10056 newname = original_case_string;
10057 #endif
10058 copy_of_str = newname;
10059
10060 q += 4;
10061 skip_whitespace (q);
10062
10063 for (r = q; *r != '\0'; r++)
10064 if (*r == ' ')
10065 break;
10066
10067 if (r != q)
10068 {
10069 enum arm_reg_type new_type, old_type;
10070 int old_regno;
10071 char d = *r;
10072
10073 *r = '\0';
10074 old_type = arm_reg_parse_any (q);
10075 *r = d;
10076
10077 new_type = arm_reg_parse_any (newname);
10078
10079 if (new_type == REG_TYPE_MAX)
10080 {
10081 if (old_type != REG_TYPE_MAX)
10082 {
10083 old_regno = arm_reg_parse (&q, all_reg_maps[old_type].htab);
10084 insert_reg_alias (newname, old_regno,
10085 all_reg_maps[old_type].htab);
10086 }
10087 else
10088 as_warn (_("register '%s' does not exist\n"), q);
10089 }
10090 else if (old_type == REG_TYPE_MAX)
10091 {
10092 as_warn (_("ignoring redefinition of register alias '%s' to non-existant register '%s'"),
10093 copy_of_str, q);
10094 }
10095 else
10096 {
10097 /* Do not warn about redefinitions to the same alias. */
10098 if (new_type != old_type
10099 || (arm_reg_parse (&q, all_reg_maps[old_type].htab)
10100 != arm_reg_parse (&q, all_reg_maps[new_type].htab)))
10101 as_warn (_("ignoring redefinition of register alias '%s'"),
10102 copy_of_str);
10103
10104 }
10105 }
10106 else
10107 as_warn (_("ignoring incomplete .req pseuso op"));
10108
10109 *p = c;
10110 return 1;
10111 }
10112 *p = c;
10113 return 0;
10114 }
10115
10116 static void
10117 set_constant_flonums ()
10118 {
10119 int i;
10120
10121 for (i = 0; i < NUM_FLOAT_VALS; i++)
10122 if (atof_ieee ((char *) fp_const[i], 'x', fp_values[i]) == NULL)
10123 abort ();
10124 }
10125
10126 /* Iterate over the base tables to create the instruction patterns. */
10127 static void
10128 build_arm_ops_hsh ()
10129 {
10130 unsigned int i;
10131 unsigned int j;
10132 static struct obstack insn_obstack;
10133
10134 obstack_begin (&insn_obstack, 4000);
10135
10136 for (i = 0; i < sizeof (insns) / sizeof (struct asm_opcode); i++)
10137 {
10138 const struct asm_opcode *insn = insns + i;
10139
10140 if (insn->cond_offset != 0)
10141 {
10142 /* Insn supports conditional execution. Build the varaints
10143 and insert them in the hash table. */
10144 for (j = 0; j < sizeof (conds) / sizeof (struct asm_cond); j++)
10145 {
10146 unsigned len = strlen (insn->template);
10147 struct asm_opcode *new;
10148 char *template;
10149
10150 new = obstack_alloc (&insn_obstack, sizeof (struct asm_opcode));
10151 /* All condition codes are two characters. */
10152 template = obstack_alloc (&insn_obstack, len + 3);
10153
10154 strncpy (template, insn->template, insn->cond_offset);
10155 strcpy (template + insn->cond_offset, conds[j].template);
10156 if (len > insn->cond_offset)
10157 strcpy (template + insn->cond_offset + 2,
10158 insn->template + insn->cond_offset);
10159 new->template = template;
10160 new->cond_offset = 0;
10161 new->variant = insn->variant;
10162 new->parms = insn->parms;
10163 new->value = (insn->value & ~COND_MASK) | conds[j].value;
10164
10165 hash_insert (arm_ops_hsh, new->template, (PTR) new);
10166 }
10167 }
10168 /* Finally, insert the unconditional insn in the table directly;
10169 no need to build a copy. */
10170 hash_insert (arm_ops_hsh, insn->template, (PTR) insn);
10171 }
10172 }
10173
10174 #if defined OBJ_ELF || defined OBJ_COFF
10175
10176 #ifdef OBJ_ELF
10177 #define arm_Note Elf_External_Note
10178 #else
10179 typedef struct
10180 {
10181 unsigned char namesz[4]; /* Size of entry's owner string. */
10182 unsigned char descsz[4]; /* Size of the note descriptor. */
10183 unsigned char type[4]; /* Interpretation of the descriptor. */
10184 char name[1]; /* Start of the name+desc data. */
10185 } arm_Note;
10186 #endif
10187
10188 /* The description is kept to a fix sized in order to make updating
10189 it and merging it easier. */
10190 #define ARM_NOTE_DESCRIPTION_LENGTH 8
10191
10192 static void
10193 arm_add_note (name, description, type)
10194 const char * name;
10195 const char * description;
10196 unsigned int type;
10197 {
10198 arm_Note note ATTRIBUTE_UNUSED;
10199 char * p;
10200 unsigned int name_len;
10201
10202 name_len = (strlen (name) + 1 + 3) & ~3;
10203
10204 p = frag_more (sizeof (note.namesz));
10205 md_number_to_chars (p, (valueT) name_len, sizeof (note.namesz));
10206
10207 p = frag_more (sizeof (note.descsz));
10208 md_number_to_chars (p, (valueT) ARM_NOTE_DESCRIPTION_LENGTH, sizeof (note.descsz));
10209
10210 p = frag_more (sizeof (note.type));
10211 md_number_to_chars (p, (valueT) type, sizeof (note.type));
10212
10213 p = frag_more (name_len);
10214 strcpy (p, name);
10215
10216 p = frag_more (ARM_NOTE_DESCRIPTION_LENGTH);
10217 strncpy (p, description, ARM_NOTE_DESCRIPTION_LENGTH);
10218 frag_align (2, 0, 0);
10219 }
10220 #endif
10221
10222 void
10223 md_begin ()
10224 {
10225 unsigned mach;
10226 unsigned int i;
10227
10228 if ( (arm_ops_hsh = hash_new ()) == NULL
10229 || (arm_tops_hsh = hash_new ()) == NULL
10230 || (arm_cond_hsh = hash_new ()) == NULL
10231 || (arm_shift_hsh = hash_new ()) == NULL
10232 || (arm_psr_hsh = hash_new ()) == NULL)
10233 as_fatal (_("virtual memory exhausted"));
10234
10235 build_arm_ops_hsh ();
10236 for (i = 0; i < sizeof (tinsns) / sizeof (struct thumb_opcode); i++)
10237 hash_insert (arm_tops_hsh, tinsns[i].template, (PTR) (tinsns + i));
10238 for (i = 0; i < sizeof (conds) / sizeof (struct asm_cond); i++)
10239 hash_insert (arm_cond_hsh, conds[i].template, (PTR) (conds + i));
10240 for (i = 0; i < sizeof (shift_names) / sizeof (struct asm_shift_name); i++)
10241 hash_insert (arm_shift_hsh, shift_names[i].name, (PTR) (shift_names + i));
10242 for (i = 0; i < sizeof (psrs) / sizeof (struct asm_psr); i++)
10243 hash_insert (arm_psr_hsh, psrs[i].template, (PTR) (psrs + i));
10244
10245 for (i = (int) REG_TYPE_FIRST; i < (int) REG_TYPE_MAX; i++)
10246 build_reg_hsh (all_reg_maps + i);
10247
10248 set_constant_flonums ();
10249
10250 /* Set the cpu variant based on the command-line options. We prefer
10251 -mcpu= over -march= if both are set (as for GCC); and we prefer
10252 -mfpu= over any other way of setting the floating point unit.
10253 Use of legacy options with new options are faulted. */
10254 if (legacy_cpu != -1)
10255 {
10256 if (mcpu_cpu_opt != -1 || march_cpu_opt != -1)
10257 as_bad (_("use of old and new-style options to set CPU type"));
10258
10259 mcpu_cpu_opt = legacy_cpu;
10260 }
10261 else if (mcpu_cpu_opt == -1)
10262 mcpu_cpu_opt = march_cpu_opt;
10263
10264 if (legacy_fpu != -1)
10265 {
10266 if (mfpu_opt != -1)
10267 as_bad (_("use of old and new-style options to set FPU type"));
10268
10269 mfpu_opt = legacy_fpu;
10270 }
10271 else if (mfpu_opt == -1)
10272 {
10273 #if !(defined (TE_LINUX) || defined (TE_NetBSD))
10274 /* Some environments specify a default FPU. If they don't, infer it
10275 from the processor. */
10276 if (mcpu_fpu_opt != -1)
10277 mfpu_opt = mcpu_fpu_opt;
10278 else
10279 mfpu_opt = march_fpu_opt;
10280 #else
10281 mfpu_opt = FPU_DEFAULT;
10282 #endif
10283 }
10284
10285 if (mfpu_opt == -1)
10286 {
10287 if (mcpu_cpu_opt == -1)
10288 mfpu_opt = FPU_DEFAULT;
10289 else if (mcpu_cpu_opt & ARM_EXT_V5)
10290 mfpu_opt = FPU_ARCH_VFP_V2;
10291 else
10292 mfpu_opt = FPU_ARCH_FPA;
10293 }
10294
10295 if (mcpu_cpu_opt == -1)
10296 mcpu_cpu_opt = CPU_DEFAULT;
10297
10298 cpu_variant = mcpu_cpu_opt | mfpu_opt;
10299
10300 #if defined OBJ_COFF || defined OBJ_ELF
10301 {
10302 unsigned int flags = 0;
10303
10304 /* Set the flags in the private structure. */
10305 if (uses_apcs_26) flags |= F_APCS26;
10306 if (support_interwork) flags |= F_INTERWORK;
10307 if (uses_apcs_float) flags |= F_APCS_FLOAT;
10308 if (pic_code) flags |= F_PIC;
10309 if ((cpu_variant & FPU_ANY) == FPU_NONE
10310 || (cpu_variant & FPU_ANY) == FPU_ARCH_VFP) /* VFP layout only. */
10311 flags |= F_SOFT_FLOAT;
10312 /* Using VFP conventions (even if soft-float). */
10313 if (cpu_variant & FPU_VFP_EXT_NONE) flags |= F_VFP_FLOAT;
10314
10315 #if defined OBJ_ELF
10316 if (cpu_variant & ARM_CEXT_MAVERICK)
10317 {
10318 flags ^= F_SOFT_FLOAT;
10319 flags |= EF_ARM_MAVERICK_FLOAT;
10320 }
10321 #endif
10322
10323 bfd_set_private_flags (stdoutput, flags);
10324
10325 /* We have run out flags in the COFF header to encode the
10326 status of ATPCS support, so instead we create a dummy,
10327 empty, debug section called .arm.atpcs. */
10328 if (atpcs)
10329 {
10330 asection * sec;
10331
10332 sec = bfd_make_section (stdoutput, ".arm.atpcs");
10333
10334 if (sec != NULL)
10335 {
10336 bfd_set_section_flags
10337 (stdoutput, sec, SEC_READONLY | SEC_DEBUGGING /* | SEC_HAS_CONTENTS */);
10338 bfd_set_section_size (stdoutput, sec, 0);
10339 bfd_set_section_contents (stdoutput, sec, NULL, 0, 0);
10340 }
10341 }
10342 }
10343 #endif
10344
10345 /* Record the CPU type as well. */
10346 switch (cpu_variant & ARM_CPU_MASK)
10347 {
10348 case ARM_2:
10349 mach = bfd_mach_arm_2;
10350 break;
10351
10352 case ARM_3: /* Also ARM_250. */
10353 mach = bfd_mach_arm_2a;
10354 break;
10355
10356 case ARM_6: /* Also ARM_7. */
10357 mach = bfd_mach_arm_3;
10358 break;
10359
10360 default:
10361 mach = bfd_mach_arm_unknown;
10362 break;
10363 }
10364
10365 /* Catch special cases. */
10366 if (cpu_variant & ARM_CEXT_IWMMXT)
10367 mach = bfd_mach_arm_iWMMXt;
10368 else if (cpu_variant & ARM_CEXT_XSCALE)
10369 mach = bfd_mach_arm_XScale;
10370 else if (cpu_variant & ARM_CEXT_MAVERICK)
10371 mach = bfd_mach_arm_ep9312;
10372 else if (cpu_variant & ARM_EXT_V5E)
10373 mach = bfd_mach_arm_5TE;
10374 else if (cpu_variant & ARM_EXT_V5)
10375 {
10376 if (cpu_variant & ARM_EXT_V4T)
10377 mach = bfd_mach_arm_5T;
10378 else
10379 mach = bfd_mach_arm_5;
10380 }
10381 else if (cpu_variant & ARM_EXT_V4)
10382 {
10383 if (cpu_variant & ARM_EXT_V4T)
10384 mach = bfd_mach_arm_4T;
10385 else
10386 mach = bfd_mach_arm_4;
10387 }
10388 else if (cpu_variant & ARM_EXT_V3M)
10389 mach = bfd_mach_arm_3M;
10390
10391 #if 0 /* Suppressed - for now. */
10392 #if defined (OBJ_ELF) || defined (OBJ_COFF)
10393
10394 /* Create a .note section to fully identify this arm binary. */
10395
10396 #define NOTE_ARCH_STRING "arch: "
10397
10398 #if defined OBJ_COFF && ! defined NT_VERSION
10399 #define NT_VERSION 1
10400 #define NT_ARCH 2
10401 #endif
10402
10403 {
10404 segT current_seg = now_seg;
10405 subsegT current_subseg = now_subseg;
10406 asection * arm_arch;
10407 const char * arch_string;
10408
10409 arm_arch = bfd_make_section_old_way (stdoutput, ARM_NOTE_SECTION);
10410
10411 #ifdef OBJ_COFF
10412 bfd_set_section_flags (stdoutput, arm_arch,
10413 SEC_DATA | SEC_ALLOC | SEC_LOAD | SEC_LINK_ONCE \
10414 | SEC_HAS_CONTENTS);
10415 #endif
10416 arm_arch->output_section = arm_arch;
10417 subseg_set (arm_arch, 0);
10418
10419 switch (mach)
10420 {
10421 default:
10422 case bfd_mach_arm_unknown: arch_string = "unknown"; break;
10423 case bfd_mach_arm_2: arch_string = "armv2"; break;
10424 case bfd_mach_arm_2a: arch_string = "armv2a"; break;
10425 case bfd_mach_arm_3: arch_string = "armv3"; break;
10426 case bfd_mach_arm_3M: arch_string = "armv3M"; break;
10427 case bfd_mach_arm_4: arch_string = "armv4"; break;
10428 case bfd_mach_arm_4T: arch_string = "armv4t"; break;
10429 case bfd_mach_arm_5: arch_string = "armv5"; break;
10430 case bfd_mach_arm_5T: arch_string = "armv5t"; break;
10431 case bfd_mach_arm_5TE: arch_string = "armv5te"; break;
10432 case bfd_mach_arm_XScale: arch_string = "XScale"; break;
10433 case bfd_mach_arm_ep9312: arch_string = "ep9312"; break;
10434 case bfd_mach_arm_iWMMXt: arch_string = "iWMMXt"; break;
10435 }
10436
10437 arm_add_note (NOTE_ARCH_STRING, arch_string, NT_ARCH);
10438
10439 subseg_set (current_seg, current_subseg);
10440 }
10441 #endif
10442 #endif /* Suppressed code. */
10443
10444 bfd_set_arch_mach (stdoutput, TARGET_ARCH, mach);
10445 }
10446
10447 /* Turn an integer of n bytes (in val) into a stream of bytes appropriate
10448 for use in the a.out file, and stores them in the array pointed to by buf.
10449 This knows about the endian-ness of the target machine and does
10450 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
10451 2 (short) and 4 (long) Floating numbers are put out as a series of
10452 LITTLENUMS (shorts, here at least). */
10453
10454 void
10455 md_number_to_chars (buf, val, n)
10456 char * buf;
10457 valueT val;
10458 int n;
10459 {
10460 if (target_big_endian)
10461 number_to_chars_bigendian (buf, val, n);
10462 else
10463 number_to_chars_littleendian (buf, val, n);
10464 }
10465
10466 static valueT
10467 md_chars_to_number (buf, n)
10468 char * buf;
10469 int n;
10470 {
10471 valueT result = 0;
10472 unsigned char * where = (unsigned char *) buf;
10473
10474 if (target_big_endian)
10475 {
10476 while (n--)
10477 {
10478 result <<= 8;
10479 result |= (*where++ & 255);
10480 }
10481 }
10482 else
10483 {
10484 while (n--)
10485 {
10486 result <<= 8;
10487 result |= (where[n] & 255);
10488 }
10489 }
10490
10491 return result;
10492 }
10493
10494 /* Turn a string in input_line_pointer into a floating point constant
10495 of type TYPE, and store the appropriate bytes in *LITP. The number
10496 of LITTLENUMS emitted is stored in *SIZEP. An error message is
10497 returned, or NULL on OK.
10498
10499 Note that fp constants aren't represent in the normal way on the ARM.
10500 In big endian mode, things are as expected. However, in little endian
10501 mode fp constants are big-endian word-wise, and little-endian byte-wise
10502 within the words. For example, (double) 1.1 in big endian mode is
10503 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
10504 the byte sequence 99 99 f1 3f 9a 99 99 99.
10505
10506 ??? The format of 12 byte floats is uncertain according to gcc's arm.h. */
10507
10508 char *
10509 md_atof (type, litP, sizeP)
10510 char type;
10511 char * litP;
10512 int * sizeP;
10513 {
10514 int prec;
10515 LITTLENUM_TYPE words[MAX_LITTLENUMS];
10516 char *t;
10517 int i;
10518
10519 switch (type)
10520 {
10521 case 'f':
10522 case 'F':
10523 case 's':
10524 case 'S':
10525 prec = 2;
10526 break;
10527
10528 case 'd':
10529 case 'D':
10530 case 'r':
10531 case 'R':
10532 prec = 4;
10533 break;
10534
10535 case 'x':
10536 case 'X':
10537 prec = 6;
10538 break;
10539
10540 case 'p':
10541 case 'P':
10542 prec = 6;
10543 break;
10544
10545 default:
10546 *sizeP = 0;
10547 return _("bad call to MD_ATOF()");
10548 }
10549
10550 t = atof_ieee (input_line_pointer, type, words);
10551 if (t)
10552 input_line_pointer = t;
10553 *sizeP = prec * 2;
10554
10555 if (target_big_endian)
10556 {
10557 for (i = 0; i < prec; i++)
10558 {
10559 md_number_to_chars (litP, (valueT) words[i], 2);
10560 litP += 2;
10561 }
10562 }
10563 else
10564 {
10565 if (cpu_variant & FPU_ARCH_VFP)
10566 for (i = prec - 1; i >= 0; i--)
10567 {
10568 md_number_to_chars (litP, (valueT) words[i], 2);
10569 litP += 2;
10570 }
10571 else
10572 /* For a 4 byte float the order of elements in `words' is 1 0.
10573 For an 8 byte float the order is 1 0 3 2. */
10574 for (i = 0; i < prec; i += 2)
10575 {
10576 md_number_to_chars (litP, (valueT) words[i + 1], 2);
10577 md_number_to_chars (litP + 2, (valueT) words[i], 2);
10578 litP += 4;
10579 }
10580 }
10581
10582 return 0;
10583 }
10584
10585 /* The knowledge of the PC's pipeline offset is built into the insns
10586 themselves. */
10587
10588 long
10589 md_pcrel_from (fixP)
10590 fixS * fixP;
10591 {
10592 if (fixP->fx_addsy
10593 && S_GET_SEGMENT (fixP->fx_addsy) == undefined_section
10594 && fixP->fx_subsy == NULL)
10595 return 0;
10596
10597 if (fixP->fx_pcrel && (fixP->fx_r_type == BFD_RELOC_ARM_THUMB_ADD))
10598 {
10599 /* PC relative addressing on the Thumb is slightly odd
10600 as the bottom two bits of the PC are forced to zero
10601 for the calculation. */
10602 return (fixP->fx_where + fixP->fx_frag->fr_address) & ~3;
10603 }
10604
10605 #ifdef TE_WINCE
10606 /* The pattern was adjusted to accomodate CE's off-by-one fixups,
10607 so we un-adjust here to compensate for the accomodation. */
10608 return fixP->fx_where + fixP->fx_frag->fr_address + 8;
10609 #else
10610 return fixP->fx_where + fixP->fx_frag->fr_address;
10611 #endif
10612 }
10613
10614 /* Round up a section size to the appropriate boundary. */
10615
10616 valueT
10617 md_section_align (segment, size)
10618 segT segment ATTRIBUTE_UNUSED;
10619 valueT size;
10620 {
10621 #ifdef OBJ_ELF
10622 return size;
10623 #else
10624 /* Round all sects to multiple of 4. */
10625 return (size + 3) & ~3;
10626 #endif
10627 }
10628
10629 /* Under ELF we need to default _GLOBAL_OFFSET_TABLE.
10630 Otherwise we have no need to default values of symbols. */
10631
10632 symbolS *
10633 md_undefined_symbol (name)
10634 char * name ATTRIBUTE_UNUSED;
10635 {
10636 #ifdef OBJ_ELF
10637 if (name[0] == '_' && name[1] == 'G'
10638 && streq (name, GLOBAL_OFFSET_TABLE_NAME))
10639 {
10640 if (!GOT_symbol)
10641 {
10642 if (symbol_find (name))
10643 as_bad ("GOT already in the symbol table");
10644
10645 GOT_symbol = symbol_new (name, undefined_section,
10646 (valueT) 0, & zero_address_frag);
10647 }
10648
10649 return GOT_symbol;
10650 }
10651 #endif
10652
10653 return 0;
10654 }
10655
10656 /* arm_reg_parse () := if it looks like a register, return its token and
10657 advance the pointer. */
10658
10659 static int
10660 arm_reg_parse (ccp, htab)
10661 register char ** ccp;
10662 struct hash_control *htab;
10663 {
10664 char * start = * ccp;
10665 char c;
10666 char * p;
10667 struct reg_entry * reg;
10668
10669 #ifdef REGISTER_PREFIX
10670 if (*start != REGISTER_PREFIX)
10671 return FAIL;
10672 p = start + 1;
10673 #else
10674 p = start;
10675 #ifdef OPTIONAL_REGISTER_PREFIX
10676 if (*p == OPTIONAL_REGISTER_PREFIX)
10677 p++, start++;
10678 #endif
10679 #endif
10680 if (!ISALPHA (*p) || !is_name_beginner (*p))
10681 return FAIL;
10682
10683 c = *p++;
10684 while (ISALPHA (c) || ISDIGIT (c) || c == '_')
10685 c = *p++;
10686
10687 *--p = 0;
10688 reg = (struct reg_entry *) hash_find (htab, start);
10689 *p = c;
10690
10691 if (reg)
10692 {
10693 *ccp = p;
10694 return reg->number;
10695 }
10696
10697 return FAIL;
10698 }
10699
10700 /* Search for the following register name in each of the possible reg name
10701 tables. Return the classification if found, or REG_TYPE_MAX if not
10702 present. */
10703 static enum arm_reg_type
10704 arm_reg_parse_any (cp)
10705 char *cp;
10706 {
10707 int i;
10708
10709 for (i = (int) REG_TYPE_FIRST; i < (int) REG_TYPE_MAX; i++)
10710 if (arm_reg_parse (&cp, all_reg_maps[i].htab) != FAIL)
10711 return (enum arm_reg_type) i;
10712
10713 return REG_TYPE_MAX;
10714 }
10715
10716 void
10717 md_apply_fix3 (fixP, valP, seg)
10718 fixS * fixP;
10719 valueT * valP;
10720 segT seg;
10721 {
10722 offsetT value = * valP;
10723 offsetT newval;
10724 unsigned int newimm;
10725 unsigned long temp;
10726 int sign;
10727 char * buf = fixP->fx_where + fixP->fx_frag->fr_literal;
10728 arm_fix_data * arm_data = (arm_fix_data *) fixP->tc_fix_data;
10729
10730 assert (fixP->fx_r_type < BFD_RELOC_UNUSED);
10731
10732 /* Note whether this will delete the relocation. */
10733 #if 0
10734 /* Patch from REarnshaw to JDavis (disabled for the moment, since it
10735 doesn't work fully.) */
10736 if ((fixP->fx_addsy == 0 || symbol_constant_p (fixP->fx_addsy))
10737 && !fixP->fx_pcrel)
10738 #else
10739 if (fixP->fx_addsy == 0 && !fixP->fx_pcrel)
10740 #endif
10741 fixP->fx_done = 1;
10742
10743 /* If this symbol is in a different section then we need to leave it for
10744 the linker to deal with. Unfortunately, md_pcrel_from can't tell,
10745 so we have to undo it's effects here. */
10746 if (fixP->fx_pcrel)
10747 {
10748 if (fixP->fx_addsy != NULL
10749 && S_IS_DEFINED (fixP->fx_addsy)
10750 && S_GET_SEGMENT (fixP->fx_addsy) != seg)
10751 {
10752 if (target_oabi
10753 && (fixP->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH
10754 || fixP->fx_r_type == BFD_RELOC_ARM_PCREL_BLX
10755 ))
10756 value = 0;
10757 else
10758 value += md_pcrel_from (fixP);
10759 }
10760 }
10761
10762 /* Remember value for emit_reloc. */
10763 fixP->fx_addnumber = value;
10764
10765 switch (fixP->fx_r_type)
10766 {
10767 case BFD_RELOC_ARM_IMMEDIATE:
10768 newimm = validate_immediate (value);
10769 temp = md_chars_to_number (buf, INSN_SIZE);
10770
10771 /* If the instruction will fail, see if we can fix things up by
10772 changing the opcode. */
10773 if (newimm == (unsigned int) FAIL
10774 && (newimm = negate_data_op (&temp, value)) == (unsigned int) FAIL)
10775 {
10776 as_bad_where (fixP->fx_file, fixP->fx_line,
10777 _("invalid constant (%lx) after fixup"),
10778 (unsigned long) value);
10779 break;
10780 }
10781
10782 newimm |= (temp & 0xfffff000);
10783 md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
10784 fixP->fx_done = 1;
10785 break;
10786
10787 case BFD_RELOC_ARM_ADRL_IMMEDIATE:
10788 {
10789 unsigned int highpart = 0;
10790 unsigned int newinsn = 0xe1a00000; /* nop. */
10791
10792 newimm = validate_immediate (value);
10793 temp = md_chars_to_number (buf, INSN_SIZE);
10794
10795 /* If the instruction will fail, see if we can fix things up by
10796 changing the opcode. */
10797 if (newimm == (unsigned int) FAIL
10798 && (newimm = negate_data_op (& temp, value)) == (unsigned int) FAIL)
10799 {
10800 /* No ? OK - try using two ADD instructions to generate
10801 the value. */
10802 newimm = validate_immediate_twopart (value, & highpart);
10803
10804 /* Yes - then make sure that the second instruction is
10805 also an add. */
10806 if (newimm != (unsigned int) FAIL)
10807 newinsn = temp;
10808 /* Still No ? Try using a negated value. */
10809 else if ((newimm = validate_immediate_twopart (- value, & highpart)) != (unsigned int) FAIL)
10810 temp = newinsn = (temp & OPCODE_MASK) | OPCODE_SUB << DATA_OP_SHIFT;
10811 /* Otherwise - give up. */
10812 else
10813 {
10814 as_bad_where (fixP->fx_file, fixP->fx_line,
10815 _("unable to compute ADRL instructions for PC offset of 0x%lx"),
10816 (long) value);
10817 break;
10818 }
10819
10820 /* Replace the first operand in the 2nd instruction (which
10821 is the PC) with the destination register. We have
10822 already added in the PC in the first instruction and we
10823 do not want to do it again. */
10824 newinsn &= ~ 0xf0000;
10825 newinsn |= ((newinsn & 0x0f000) << 4);
10826 }
10827
10828 newimm |= (temp & 0xfffff000);
10829 md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
10830
10831 highpart |= (newinsn & 0xfffff000);
10832 md_number_to_chars (buf + INSN_SIZE, (valueT) highpart, INSN_SIZE);
10833 }
10834 break;
10835
10836 case BFD_RELOC_ARM_OFFSET_IMM:
10837 sign = value >= 0;
10838
10839 if (value < 0)
10840 value = - value;
10841
10842 if (validate_offset_imm (value, 0) == FAIL)
10843 {
10844 as_bad_where (fixP->fx_file, fixP->fx_line,
10845 _("bad immediate value for offset (%ld)"),
10846 (long) value);
10847 break;
10848 }
10849
10850 newval = md_chars_to_number (buf, INSN_SIZE);
10851 newval &= 0xff7ff000;
10852 newval |= value | (sign ? INDEX_UP : 0);
10853 md_number_to_chars (buf, newval, INSN_SIZE);
10854 break;
10855
10856 case BFD_RELOC_ARM_OFFSET_IMM8:
10857 case BFD_RELOC_ARM_HWLITERAL:
10858 sign = value >= 0;
10859
10860 if (value < 0)
10861 value = - value;
10862
10863 if (validate_offset_imm (value, 1) == FAIL)
10864 {
10865 if (fixP->fx_r_type == BFD_RELOC_ARM_HWLITERAL)
10866 as_bad_where (fixP->fx_file, fixP->fx_line,
10867 _("invalid literal constant: pool needs to be closer"));
10868 else
10869 as_bad (_("bad immediate value for half-word offset (%ld)"),
10870 (long) value);
10871 break;
10872 }
10873
10874 newval = md_chars_to_number (buf, INSN_SIZE);
10875 newval &= 0xff7ff0f0;
10876 newval |= ((value >> 4) << 8) | (value & 0xf) | (sign ? INDEX_UP : 0);
10877 md_number_to_chars (buf, newval, INSN_SIZE);
10878 break;
10879
10880 case BFD_RELOC_ARM_LITERAL:
10881 sign = value >= 0;
10882
10883 if (value < 0)
10884 value = - value;
10885
10886 if (validate_offset_imm (value, 0) == FAIL)
10887 {
10888 as_bad_where (fixP->fx_file, fixP->fx_line,
10889 _("invalid literal constant: pool needs to be closer"));
10890 break;
10891 }
10892
10893 newval = md_chars_to_number (buf, INSN_SIZE);
10894 newval &= 0xff7ff000;
10895 newval |= value | (sign ? INDEX_UP : 0);
10896 md_number_to_chars (buf, newval, INSN_SIZE);
10897 break;
10898
10899 case BFD_RELOC_ARM_SHIFT_IMM:
10900 newval = md_chars_to_number (buf, INSN_SIZE);
10901 if (((unsigned long) value) > 32
10902 || (value == 32
10903 && (((newval & 0x60) == 0) || (newval & 0x60) == 0x60)))
10904 {
10905 as_bad_where (fixP->fx_file, fixP->fx_line,
10906 _("shift expression is too large"));
10907 break;
10908 }
10909
10910 if (value == 0)
10911 /* Shifts of zero must be done as lsl. */
10912 newval &= ~0x60;
10913 else if (value == 32)
10914 value = 0;
10915 newval &= 0xfffff07f;
10916 newval |= (value & 0x1f) << 7;
10917 md_number_to_chars (buf, newval, INSN_SIZE);
10918 break;
10919
10920 case BFD_RELOC_ARM_SWI:
10921 if (arm_data->thumb_mode)
10922 {
10923 if (((unsigned long) value) > 0xff)
10924 as_bad_where (fixP->fx_file, fixP->fx_line,
10925 _("invalid swi expression"));
10926 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xff00;
10927 newval |= value;
10928 md_number_to_chars (buf, newval, THUMB_SIZE);
10929 }
10930 else
10931 {
10932 if (((unsigned long) value) > 0x00ffffff)
10933 as_bad_where (fixP->fx_file, fixP->fx_line,
10934 _("invalid swi expression"));
10935 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff000000;
10936 newval |= value;
10937 md_number_to_chars (buf, newval, INSN_SIZE);
10938 }
10939 break;
10940
10941 case BFD_RELOC_ARM_MULTI:
10942 if (((unsigned long) value) > 0xffff)
10943 as_bad_where (fixP->fx_file, fixP->fx_line,
10944 _("invalid expression in load/store multiple"));
10945 newval = value | md_chars_to_number (buf, INSN_SIZE);
10946 md_number_to_chars (buf, newval, INSN_SIZE);
10947 break;
10948
10949 case BFD_RELOC_ARM_PCREL_BRANCH:
10950 newval = md_chars_to_number (buf, INSN_SIZE);
10951
10952 /* Sign-extend a 24-bit number. */
10953 #define SEXT24(x) ((((x) & 0xffffff) ^ (~ 0x7fffff)) + 0x800000)
10954
10955 #ifdef OBJ_ELF
10956 if (! target_oabi)
10957 value = fixP->fx_offset;
10958 #endif
10959
10960 /* We are going to store value (shifted right by two) in the
10961 instruction, in a 24 bit, signed field. Thus we need to check
10962 that none of the top 8 bits of the shifted value (top 7 bits of
10963 the unshifted, unsigned value) are set, or that they are all set. */
10964 if ((value & ~ ((offsetT) 0x1ffffff)) != 0
10965 && ((value & ~ ((offsetT) 0x1ffffff)) != ~ ((offsetT) 0x1ffffff)))
10966 {
10967 #ifdef OBJ_ELF
10968 /* Normally we would be stuck at this point, since we cannot store
10969 the absolute address that is the destination of the branch in the
10970 24 bits of the branch instruction. If however, we happen to know
10971 that the destination of the branch is in the same section as the
10972 branch instruciton itself, then we can compute the relocation for
10973 ourselves and not have to bother the linker with it.
10974
10975 FIXME: The tests for OBJ_ELF and ! target_oabi are only here
10976 because I have not worked out how to do this for OBJ_COFF or
10977 target_oabi. */
10978 if (! target_oabi
10979 && fixP->fx_addsy != NULL
10980 && S_IS_DEFINED (fixP->fx_addsy)
10981 && S_GET_SEGMENT (fixP->fx_addsy) == seg)
10982 {
10983 /* Get pc relative value to go into the branch. */
10984 value = * valP;
10985
10986 /* Permit a backward branch provided that enough bits
10987 are set. Allow a forwards branch, provided that
10988 enough bits are clear. */
10989 if ( (value & ~ ((offsetT) 0x1ffffff)) == ~ ((offsetT) 0x1ffffff)
10990 || (value & ~ ((offsetT) 0x1ffffff)) == 0)
10991 fixP->fx_done = 1;
10992 }
10993
10994 if (! fixP->fx_done)
10995 #endif
10996 as_bad_where (fixP->fx_file, fixP->fx_line,
10997 _("GAS can't handle same-section branch dest >= 0x04000000"));
10998 }
10999
11000 value >>= 2;
11001 value += SEXT24 (newval);
11002
11003 if ( (value & ~ ((offsetT) 0xffffff)) != 0
11004 && ((value & ~ ((offsetT) 0xffffff)) != ~ ((offsetT) 0xffffff)))
11005 as_bad_where (fixP->fx_file, fixP->fx_line,
11006 _("out of range branch"));
11007
11008 newval = (value & 0x00ffffff) | (newval & 0xff000000);
11009 md_number_to_chars (buf, newval, INSN_SIZE);
11010 break;
11011
11012 case BFD_RELOC_ARM_PCREL_BLX:
11013 {
11014 offsetT hbit;
11015 newval = md_chars_to_number (buf, INSN_SIZE);
11016
11017 #ifdef OBJ_ELF
11018 if (! target_oabi)
11019 value = fixP->fx_offset;
11020 #endif
11021 hbit = (value >> 1) & 1;
11022 value = (value >> 2) & 0x00ffffff;
11023 value = (value + (newval & 0x00ffffff)) & 0x00ffffff;
11024 newval = value | (newval & 0xfe000000) | (hbit << 24);
11025 md_number_to_chars (buf, newval, INSN_SIZE);
11026 }
11027 break;
11028
11029 case BFD_RELOC_THUMB_PCREL_BRANCH9: /* Conditional branch. */
11030 newval = md_chars_to_number (buf, THUMB_SIZE);
11031 {
11032 addressT diff = (newval & 0xff) << 1;
11033 if (diff & 0x100)
11034 diff |= ~0xff;
11035
11036 value += diff;
11037 if ((value & ~0xff) && ((value & ~0xff) != ~0xff))
11038 as_bad_where (fixP->fx_file, fixP->fx_line,
11039 _("branch out of range"));
11040 newval = (newval & 0xff00) | ((value & 0x1ff) >> 1);
11041 }
11042 md_number_to_chars (buf, newval, THUMB_SIZE);
11043 break;
11044
11045 case BFD_RELOC_THUMB_PCREL_BRANCH12: /* Unconditional branch. */
11046 newval = md_chars_to_number (buf, THUMB_SIZE);
11047 {
11048 addressT diff = (newval & 0x7ff) << 1;
11049 if (diff & 0x800)
11050 diff |= ~0x7ff;
11051
11052 value += diff;
11053 if ((value & ~0x7ff) && ((value & ~0x7ff) != ~0x7ff))
11054 as_bad_where (fixP->fx_file, fixP->fx_line,
11055 _("branch out of range"));
11056 newval = (newval & 0xf800) | ((value & 0xfff) >> 1);
11057 }
11058 md_number_to_chars (buf, newval, THUMB_SIZE);
11059 break;
11060
11061 case BFD_RELOC_THUMB_PCREL_BLX:
11062 case BFD_RELOC_THUMB_PCREL_BRANCH23:
11063 {
11064 offsetT newval2;
11065 addressT diff;
11066
11067 newval = md_chars_to_number (buf, THUMB_SIZE);
11068 newval2 = md_chars_to_number (buf + THUMB_SIZE, THUMB_SIZE);
11069 diff = ((newval & 0x7ff) << 12) | ((newval2 & 0x7ff) << 1);
11070 if (diff & 0x400000)
11071 diff |= ~0x3fffff;
11072 #ifdef OBJ_ELF
11073 value = fixP->fx_offset;
11074 #endif
11075 value += diff;
11076
11077 if ((value & ~0x3fffff) && ((value & ~0x3fffff) != ~0x3fffff))
11078 as_bad_where (fixP->fx_file, fixP->fx_line,
11079 _("branch with link out of range"));
11080
11081 newval = (newval & 0xf800) | ((value & 0x7fffff) >> 12);
11082 newval2 = (newval2 & 0xf800) | ((value & 0xfff) >> 1);
11083 if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX)
11084 /* For a BLX instruction, make sure that the relocation is rounded up
11085 to a word boundary. This follows the semantics of the instruction
11086 which specifies that bit 1 of the target address will come from bit
11087 1 of the base address. */
11088 newval2 = (newval2 + 1) & ~ 1;
11089 md_number_to_chars (buf, newval, THUMB_SIZE);
11090 md_number_to_chars (buf + THUMB_SIZE, newval2, THUMB_SIZE);
11091 }
11092 break;
11093
11094 case BFD_RELOC_8:
11095 if (fixP->fx_done || fixP->fx_pcrel)
11096 md_number_to_chars (buf, value, 1);
11097 #ifdef OBJ_ELF
11098 else if (!target_oabi)
11099 {
11100 value = fixP->fx_offset;
11101 md_number_to_chars (buf, value, 1);
11102 }
11103 #endif
11104 break;
11105
11106 case BFD_RELOC_16:
11107 if (fixP->fx_done || fixP->fx_pcrel)
11108 md_number_to_chars (buf, value, 2);
11109 #ifdef OBJ_ELF
11110 else if (!target_oabi)
11111 {
11112 value = fixP->fx_offset;
11113 md_number_to_chars (buf, value, 2);
11114 }
11115 #endif
11116 break;
11117
11118 #ifdef OBJ_ELF
11119 case BFD_RELOC_ARM_GOT32:
11120 case BFD_RELOC_ARM_GOTOFF:
11121 md_number_to_chars (buf, 0, 4);
11122 break;
11123 #endif
11124
11125 case BFD_RELOC_RVA:
11126 case BFD_RELOC_32:
11127 if (fixP->fx_done || fixP->fx_pcrel)
11128 md_number_to_chars (buf, value, 4);
11129 #ifdef OBJ_ELF
11130 else if (!target_oabi)
11131 {
11132 value = fixP->fx_offset;
11133 md_number_to_chars (buf, value, 4);
11134 }
11135 #endif
11136 break;
11137
11138 #ifdef OBJ_ELF
11139 case BFD_RELOC_ARM_PLT32:
11140 /* It appears the instruction is fully prepared at this point. */
11141 break;
11142 #endif
11143
11144 case BFD_RELOC_ARM_CP_OFF_IMM:
11145 sign = value >= 0;
11146 if (value < -1023 || value > 1023 || (value & 3))
11147 as_bad_where (fixP->fx_file, fixP->fx_line,
11148 _("illegal value for co-processor offset"));
11149 if (value < 0)
11150 value = -value;
11151 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
11152 newval |= (value >> 2) | (sign ? INDEX_UP : 0);
11153 md_number_to_chars (buf, newval, INSN_SIZE);
11154 break;
11155
11156 case BFD_RELOC_ARM_CP_OFF_IMM_S2:
11157 sign = value >= 0;
11158 if (value < -255 || value > 255)
11159 as_bad_where (fixP->fx_file, fixP->fx_line,
11160 _("Illegal value for co-processor offset"));
11161 if (value < 0)
11162 value = -value;
11163 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
11164 newval |= value | (sign ? INDEX_UP : 0);
11165 md_number_to_chars (buf, newval , INSN_SIZE);
11166 break;
11167
11168 case BFD_RELOC_ARM_THUMB_OFFSET:
11169 newval = md_chars_to_number (buf, THUMB_SIZE);
11170 /* Exactly what ranges, and where the offset is inserted depends
11171 on the type of instruction, we can establish this from the
11172 top 4 bits. */
11173 switch (newval >> 12)
11174 {
11175 case 4: /* PC load. */
11176 /* Thumb PC loads are somewhat odd, bit 1 of the PC is
11177 forced to zero for these loads, so we will need to round
11178 up the offset if the instruction address is not word
11179 aligned (since the final address produced must be, and
11180 we can only describe word-aligned immediate offsets). */
11181
11182 if ((fixP->fx_frag->fr_address + fixP->fx_where + value) & 3)
11183 as_bad_where (fixP->fx_file, fixP->fx_line,
11184 _("invalid offset, target not word aligned (0x%08X)"),
11185 (unsigned int) (fixP->fx_frag->fr_address
11186 + fixP->fx_where + value));
11187
11188 if ((value + 2) & ~0x3fe)
11189 as_bad_where (fixP->fx_file, fixP->fx_line,
11190 _("invalid offset, value too big (0x%08lX)"),
11191 (long) value);
11192
11193 /* Round up, since pc will be rounded down. */
11194 newval |= (value + 2) >> 2;
11195 break;
11196
11197 case 9: /* SP load/store. */
11198 if (value & ~0x3fc)
11199 as_bad_where (fixP->fx_file, fixP->fx_line,
11200 _("invalid offset, value too big (0x%08lX)"),
11201 (long) value);
11202 newval |= value >> 2;
11203 break;
11204
11205 case 6: /* Word load/store. */
11206 if (value & ~0x7c)
11207 as_bad_where (fixP->fx_file, fixP->fx_line,
11208 _("invalid offset, value too big (0x%08lX)"),
11209 (long) value);
11210 newval |= value << 4; /* 6 - 2. */
11211 break;
11212
11213 case 7: /* Byte load/store. */
11214 if (value & ~0x1f)
11215 as_bad_where (fixP->fx_file, fixP->fx_line,
11216 _("invalid offset, value too big (0x%08lX)"),
11217 (long) value);
11218 newval |= value << 6;
11219 break;
11220
11221 case 8: /* Halfword load/store. */
11222 if (value & ~0x3e)
11223 as_bad_where (fixP->fx_file, fixP->fx_line,
11224 _("invalid offset, value too big (0x%08lX)"),
11225 (long) value);
11226 newval |= value << 5; /* 6 - 1. */
11227 break;
11228
11229 default:
11230 as_bad_where (fixP->fx_file, fixP->fx_line,
11231 "Unable to process relocation for thumb opcode: %lx",
11232 (unsigned long) newval);
11233 break;
11234 }
11235 md_number_to_chars (buf, newval, THUMB_SIZE);
11236 break;
11237
11238 case BFD_RELOC_ARM_THUMB_ADD:
11239 /* This is a complicated relocation, since we use it for all of
11240 the following immediate relocations:
11241
11242 3bit ADD/SUB
11243 8bit ADD/SUB
11244 9bit ADD/SUB SP word-aligned
11245 10bit ADD PC/SP word-aligned
11246
11247 The type of instruction being processed is encoded in the
11248 instruction field:
11249
11250 0x8000 SUB
11251 0x00F0 Rd
11252 0x000F Rs
11253 */
11254 newval = md_chars_to_number (buf, THUMB_SIZE);
11255 {
11256 int rd = (newval >> 4) & 0xf;
11257 int rs = newval & 0xf;
11258 int subtract = newval & 0x8000;
11259
11260 if (rd == REG_SP)
11261 {
11262 if (value & ~0x1fc)
11263 as_bad_where (fixP->fx_file, fixP->fx_line,
11264 _("invalid immediate for stack address calculation"));
11265 newval = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
11266 newval |= value >> 2;
11267 }
11268 else if (rs == REG_PC || rs == REG_SP)
11269 {
11270 if (subtract ||
11271 value & ~0x3fc)
11272 as_bad_where (fixP->fx_file, fixP->fx_line,
11273 _("invalid immediate for address calculation (value = 0x%08lX)"),
11274 (unsigned long) value);
11275 newval = (rs == REG_PC ? T_OPCODE_ADD_PC : T_OPCODE_ADD_SP);
11276 newval |= rd << 8;
11277 newval |= value >> 2;
11278 }
11279 else if (rs == rd)
11280 {
11281 if (value & ~0xff)
11282 as_bad_where (fixP->fx_file, fixP->fx_line,
11283 _("invalid 8bit immediate"));
11284 newval = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
11285 newval |= (rd << 8) | value;
11286 }
11287 else
11288 {
11289 if (value & ~0x7)
11290 as_bad_where (fixP->fx_file, fixP->fx_line,
11291 _("invalid 3bit immediate"));
11292 newval = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
11293 newval |= rd | (rs << 3) | (value << 6);
11294 }
11295 }
11296 md_number_to_chars (buf, newval, THUMB_SIZE);
11297 break;
11298
11299 case BFD_RELOC_ARM_THUMB_IMM:
11300 newval = md_chars_to_number (buf, THUMB_SIZE);
11301 switch (newval >> 11)
11302 {
11303 case 0x04: /* 8bit immediate MOV. */
11304 case 0x05: /* 8bit immediate CMP. */
11305 if (value < 0 || value > 255)
11306 as_bad_where (fixP->fx_file, fixP->fx_line,
11307 _("invalid immediate: %ld is too large"),
11308 (long) value);
11309 newval |= value;
11310 break;
11311
11312 default:
11313 abort ();
11314 }
11315 md_number_to_chars (buf, newval, THUMB_SIZE);
11316 break;
11317
11318 case BFD_RELOC_ARM_THUMB_SHIFT:
11319 /* 5bit shift value (0..31). */
11320 if (value < 0 || value > 31)
11321 as_bad_where (fixP->fx_file, fixP->fx_line,
11322 _("illegal Thumb shift value: %ld"), (long) value);
11323 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xf03f;
11324 newval |= value << 6;
11325 md_number_to_chars (buf, newval, THUMB_SIZE);
11326 break;
11327
11328 case BFD_RELOC_VTABLE_INHERIT:
11329 case BFD_RELOC_VTABLE_ENTRY:
11330 fixP->fx_done = 0;
11331 return;
11332
11333 case BFD_RELOC_NONE:
11334 default:
11335 as_bad_where (fixP->fx_file, fixP->fx_line,
11336 _("bad relocation fixup type (%d)"), fixP->fx_r_type);
11337 }
11338 }
11339
11340 /* Translate internal representation of relocation info to BFD target
11341 format. */
11342
11343 arelent *
11344 tc_gen_reloc (section, fixp)
11345 asection * section ATTRIBUTE_UNUSED;
11346 fixS * fixp;
11347 {
11348 arelent * reloc;
11349 bfd_reloc_code_real_type code;
11350
11351 reloc = (arelent *) xmalloc (sizeof (arelent));
11352
11353 reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
11354 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
11355 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
11356
11357 /* @@ Why fx_addnumber sometimes and fx_offset other times? */
11358 #ifndef OBJ_ELF
11359 if (fixp->fx_pcrel == 0)
11360 reloc->addend = fixp->fx_offset;
11361 else
11362 reloc->addend = fixp->fx_offset = reloc->address;
11363 #else /* OBJ_ELF */
11364 reloc->addend = fixp->fx_offset;
11365 #endif
11366
11367 switch (fixp->fx_r_type)
11368 {
11369 case BFD_RELOC_8:
11370 if (fixp->fx_pcrel)
11371 {
11372 code = BFD_RELOC_8_PCREL;
11373 break;
11374 }
11375
11376 case BFD_RELOC_16:
11377 if (fixp->fx_pcrel)
11378 {
11379 code = BFD_RELOC_16_PCREL;
11380 break;
11381 }
11382
11383 case BFD_RELOC_32:
11384 if (fixp->fx_pcrel)
11385 {
11386 code = BFD_RELOC_32_PCREL;
11387 break;
11388 }
11389
11390 case BFD_RELOC_ARM_PCREL_BRANCH:
11391 case BFD_RELOC_ARM_PCREL_BLX:
11392 case BFD_RELOC_RVA:
11393 case BFD_RELOC_THUMB_PCREL_BRANCH9:
11394 case BFD_RELOC_THUMB_PCREL_BRANCH12:
11395 case BFD_RELOC_THUMB_PCREL_BRANCH23:
11396 case BFD_RELOC_THUMB_PCREL_BLX:
11397 case BFD_RELOC_VTABLE_ENTRY:
11398 case BFD_RELOC_VTABLE_INHERIT:
11399 code = fixp->fx_r_type;
11400 break;
11401
11402 case BFD_RELOC_ARM_LITERAL:
11403 case BFD_RELOC_ARM_HWLITERAL:
11404 /* If this is called then the a literal has
11405 been referenced across a section boundary. */
11406 as_bad_where (fixp->fx_file, fixp->fx_line,
11407 _("literal referenced across section boundary"));
11408 return NULL;
11409
11410 #ifdef OBJ_ELF
11411 case BFD_RELOC_ARM_GOT32:
11412 case BFD_RELOC_ARM_GOTOFF:
11413 case BFD_RELOC_ARM_PLT32:
11414 code = fixp->fx_r_type;
11415 break;
11416 #endif
11417
11418 case BFD_RELOC_ARM_IMMEDIATE:
11419 as_bad_where (fixp->fx_file, fixp->fx_line,
11420 _("internal relocation (type: IMMEDIATE) not fixed up"));
11421 return NULL;
11422
11423 case BFD_RELOC_ARM_ADRL_IMMEDIATE:
11424 as_bad_where (fixp->fx_file, fixp->fx_line,
11425 _("ADRL used for a symbol not defined in the same file"));
11426 return NULL;
11427
11428 case BFD_RELOC_ARM_OFFSET_IMM:
11429 as_bad_where (fixp->fx_file, fixp->fx_line,
11430 _("internal_relocation (type: OFFSET_IMM) not fixed up"));
11431 return NULL;
11432
11433 default:
11434 {
11435 char * type;
11436
11437 switch (fixp->fx_r_type)
11438 {
11439 case BFD_RELOC_ARM_OFFSET_IMM8: type = "OFFSET_IMM8"; break;
11440 case BFD_RELOC_ARM_SHIFT_IMM: type = "SHIFT_IMM"; break;
11441 case BFD_RELOC_ARM_SWI: type = "SWI"; break;
11442 case BFD_RELOC_ARM_MULTI: type = "MULTI"; break;
11443 case BFD_RELOC_ARM_CP_OFF_IMM: type = "CP_OFF_IMM"; break;
11444 case BFD_RELOC_ARM_THUMB_ADD: type = "THUMB_ADD"; break;
11445 case BFD_RELOC_ARM_THUMB_SHIFT: type = "THUMB_SHIFT"; break;
11446 case BFD_RELOC_ARM_THUMB_IMM: type = "THUMB_IMM"; break;
11447 case BFD_RELOC_ARM_THUMB_OFFSET: type = "THUMB_OFFSET"; break;
11448 default: type = _("<unknown>"); break;
11449 }
11450 as_bad_where (fixp->fx_file, fixp->fx_line,
11451 _("cannot represent %s relocation in this object file format"),
11452 type);
11453 return NULL;
11454 }
11455 }
11456
11457 #ifdef OBJ_ELF
11458 if ((code == BFD_RELOC_32_PCREL || code == BFD_RELOC_32)
11459 && GOT_symbol
11460 && fixp->fx_addsy == GOT_symbol)
11461 {
11462 code = BFD_RELOC_ARM_GOTPC;
11463 reloc->addend = fixp->fx_offset = reloc->address;
11464 }
11465 #endif
11466
11467 reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
11468
11469 if (reloc->howto == NULL)
11470 {
11471 as_bad_where (fixp->fx_file, fixp->fx_line,
11472 _("cannot represent %s relocation in this object file format"),
11473 bfd_get_reloc_code_name (code));
11474 return NULL;
11475 }
11476
11477 /* HACK: Since arm ELF uses Rel instead of Rela, encode the
11478 vtable entry to be used in the relocation's section offset. */
11479 if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
11480 reloc->address = fixp->fx_offset;
11481
11482 return reloc;
11483 }
11484
11485 int
11486 md_estimate_size_before_relax (fragP, segtype)
11487 fragS * fragP ATTRIBUTE_UNUSED;
11488 segT segtype ATTRIBUTE_UNUSED;
11489 {
11490 as_fatal (_("md_estimate_size_before_relax\n"));
11491 return 1;
11492 }
11493
11494 static void
11495 output_inst (str)
11496 const char *str;
11497 {
11498 char * to = NULL;
11499
11500 if (inst.error)
11501 {
11502 as_bad ("%s -- `%s'", inst.error, str);
11503 return;
11504 }
11505
11506 to = frag_more (inst.size);
11507
11508 if (thumb_mode && (inst.size > THUMB_SIZE))
11509 {
11510 assert (inst.size == (2 * THUMB_SIZE));
11511 md_number_to_chars (to, inst.instruction >> 16, THUMB_SIZE);
11512 md_number_to_chars (to + THUMB_SIZE, inst.instruction, THUMB_SIZE);
11513 }
11514 else if (inst.size > INSN_SIZE)
11515 {
11516 assert (inst.size == (2 * INSN_SIZE));
11517 md_number_to_chars (to, inst.instruction, INSN_SIZE);
11518 md_number_to_chars (to + INSN_SIZE, inst.instruction, INSN_SIZE);
11519 }
11520 else
11521 md_number_to_chars (to, inst.instruction, inst.size);
11522
11523 if (inst.reloc.type != BFD_RELOC_NONE)
11524 fix_new_arm (frag_now, to - frag_now->fr_literal,
11525 inst.size, & inst.reloc.exp, inst.reloc.pc_rel,
11526 inst.reloc.type);
11527
11528 #ifdef OBJ_ELF
11529 dwarf2_emit_insn (inst.size);
11530 #endif
11531 }
11532
11533 void
11534 md_assemble (str)
11535 char * str;
11536 {
11537 char c;
11538 char *p;
11539 char *start;
11540
11541 /* Align the instruction.
11542 This may not be the right thing to do but ... */
11543 #if 0
11544 arm_align (2, 0);
11545 #endif
11546
11547 /* Align the previous label if needed. */
11548 if (last_label_seen != NULL)
11549 {
11550 symbol_set_frag (last_label_seen, frag_now);
11551 S_SET_VALUE (last_label_seen, (valueT) frag_now_fix ());
11552 S_SET_SEGMENT (last_label_seen, now_seg);
11553 }
11554
11555 memset (&inst, '\0', sizeof (inst));
11556 inst.reloc.type = BFD_RELOC_NONE;
11557
11558 skip_whitespace (str);
11559
11560 /* Scan up to the end of the op-code, which must end in white space or
11561 end of string. */
11562 for (start = p = str; *p != '\0'; p++)
11563 if (*p == ' ')
11564 break;
11565
11566 if (p == str)
11567 {
11568 as_bad (_("no operator -- statement `%s'\n"), str);
11569 return;
11570 }
11571
11572 if (thumb_mode)
11573 {
11574 const struct thumb_opcode * opcode;
11575
11576 c = *p;
11577 *p = '\0';
11578 opcode = (const struct thumb_opcode *) hash_find (arm_tops_hsh, str);
11579 *p = c;
11580
11581 if (opcode)
11582 {
11583 /* Check that this instruction is supported for this CPU. */
11584 if (thumb_mode == 1 && (opcode->variant & cpu_variant) == 0)
11585 {
11586 as_bad (_("selected processor does not support `%s'"), str);
11587 return;
11588 }
11589
11590 inst.instruction = opcode->value;
11591 inst.size = opcode->size;
11592 (*opcode->parms) (p);
11593 output_inst (str);
11594 return;
11595 }
11596 }
11597 else
11598 {
11599 const struct asm_opcode * opcode;
11600
11601 c = *p;
11602 *p = '\0';
11603 opcode = (const struct asm_opcode *) hash_find (arm_ops_hsh, str);
11604 *p = c;
11605
11606 if (opcode)
11607 {
11608 /* Check that this instruction is supported for this CPU. */
11609 if ((opcode->variant & cpu_variant) == 0)
11610 {
11611 as_bad (_("selected processor does not support `%s'"), str);
11612 return;
11613 }
11614
11615 inst.instruction = opcode->value;
11616 inst.size = INSN_SIZE;
11617 (*opcode->parms) (p);
11618 output_inst (str);
11619 return;
11620 }
11621 }
11622
11623 /* It wasn't an instruction, but it might be a register alias of the form
11624 alias .req reg. */
11625 if (create_register_alias (str, p))
11626 return;
11627
11628 as_bad (_("bad instruction `%s'"), start);
11629 }
11630
11631 /* md_parse_option
11632 Invocation line includes a switch not recognized by the base assembler.
11633 See if it's a processor-specific option.
11634
11635 This routine is somewhat complicated by the need for backwards
11636 compatibility (since older releases of gcc can't be changed).
11637 The new options try to make the interface as compatible as
11638 possible with GCC.
11639
11640 New options (supported) are:
11641
11642 -mcpu=<cpu name> Assemble for selected processor
11643 -march=<architecture name> Assemble for selected architecture
11644 -mfpu=<fpu architecture> Assemble for selected FPU.
11645 -EB/-mbig-endian Big-endian
11646 -EL/-mlittle-endian Little-endian
11647 -k Generate PIC code
11648 -mthumb Start in Thumb mode
11649 -mthumb-interwork Code supports ARM/Thumb interworking
11650
11651 For now we will also provide support for:
11652
11653 -mapcs-32 32-bit Program counter
11654 -mapcs-26 26-bit Program counter
11655 -macps-float Floats passed in FP registers
11656 -mapcs-reentrant Reentrant code
11657 -matpcs
11658 (sometime these will probably be replaced with -mapcs=<list of options>
11659 and -matpcs=<list of options>)
11660
11661 The remaining options are only supported for back-wards compatibility.
11662 Cpu variants, the arm part is optional:
11663 -m[arm]1 Currently not supported.
11664 -m[arm]2, -m[arm]250 Arm 2 and Arm 250 processor
11665 -m[arm]3 Arm 3 processor
11666 -m[arm]6[xx], Arm 6 processors
11667 -m[arm]7[xx][t][[d]m] Arm 7 processors
11668 -m[arm]8[10] Arm 8 processors
11669 -m[arm]9[20][tdmi] Arm 9 processors
11670 -mstrongarm[110[0]] StrongARM processors
11671 -mxscale XScale processors
11672 -m[arm]v[2345[t[e]]] Arm architectures
11673 -mall All (except the ARM1)
11674 FP variants:
11675 -mfpa10, -mfpa11 FPA10 and 11 co-processor instructions
11676 -mfpe-old (No float load/store multiples)
11677 -mvfpxd VFP Single precision
11678 -mvfp All VFP
11679 -mno-fpu Disable all floating point instructions
11680
11681 The following CPU names are recognized:
11682 arm1, arm2, arm250, arm3, arm6, arm600, arm610, arm620,
11683 arm7, arm7m, arm7d, arm7dm, arm7di, arm7dmi, arm70, arm700,
11684 arm700i, arm710 arm710t, arm720, arm720t, arm740t, arm710c,
11685 arm7100, arm7500, arm7500fe, arm7tdmi, arm8, arm810, arm9,
11686 arm920, arm920t, arm940t, arm946, arm966, arm9tdmi, arm9e,
11687 arm10t arm10e, arm1020t, arm1020e, arm10200e,
11688 strongarm, strongarm110, strongarm1100, strongarm1110, xscale.
11689
11690 */
11691
11692 const char * md_shortopts = "m:k";
11693
11694 #ifdef ARM_BI_ENDIAN
11695 #define OPTION_EB (OPTION_MD_BASE + 0)
11696 #define OPTION_EL (OPTION_MD_BASE + 1)
11697 #else
11698 #if TARGET_BYTES_BIG_ENDIAN
11699 #define OPTION_EB (OPTION_MD_BASE + 0)
11700 #else
11701 #define OPTION_EL (OPTION_MD_BASE + 1)
11702 #endif
11703 #endif
11704
11705 struct option md_longopts[] =
11706 {
11707 #ifdef OPTION_EB
11708 {"EB", no_argument, NULL, OPTION_EB},
11709 #endif
11710 #ifdef OPTION_EL
11711 {"EL", no_argument, NULL, OPTION_EL},
11712 #endif
11713 {NULL, no_argument, NULL, 0}
11714 };
11715
11716 size_t md_longopts_size = sizeof (md_longopts);
11717
11718 struct arm_option_table
11719 {
11720 char *option; /* Option name to match. */
11721 char *help; /* Help information. */
11722 int *var; /* Variable to change. */
11723 int value; /* What to change it to. */
11724 char *deprecated; /* If non-null, print this message. */
11725 };
11726
11727 struct arm_option_table arm_opts[] =
11728 {
11729 {"k", N_("generate PIC code"), &pic_code, 1, NULL},
11730 {"mthumb", N_("assemble Thumb code"), &thumb_mode, 1, NULL},
11731 {"mthumb-interwork", N_("support ARM/Thumb interworking"),
11732 &support_interwork, 1, NULL},
11733 {"moabi", N_("use old ABI (ELF only)"), &target_oabi, 1, NULL},
11734 {"mapcs-32", N_("code uses 32-bit program counter"), &uses_apcs_26, 0, NULL},
11735 {"mapcs-26", N_("code uses 26-bit program counter"), &uses_apcs_26, 1, NULL},
11736 {"mapcs-float", N_("floating point args are in fp regs"), &uses_apcs_float,
11737 1, NULL},
11738 {"mapcs-reentrant", N_("re-entrant code"), &pic_code, 1, NULL},
11739 {"matpcs", N_("code is ATPCS conformant"), &atpcs, 1, NULL},
11740 {"mbig-endian", N_("assemble for big-endian"), &target_big_endian, 1, NULL},
11741 {"mlittle-endian", N_("assemble for little-endian"), &target_big_endian, 1,
11742 NULL},
11743
11744 /* These are recognized by the assembler, but have no affect on code. */
11745 {"mapcs-frame", N_("use frame pointer"), NULL, 0, NULL},
11746 {"mapcs-stack-check", N_("use stack size checking"), NULL, 0, NULL},
11747
11748 /* DON'T add any new processors to this list -- we want the whole list
11749 to go away... Add them to the processors table instead. */
11750 {"marm1", NULL, &legacy_cpu, ARM_ARCH_V1, N_("use -mcpu=arm1")},
11751 {"m1", NULL, &legacy_cpu, ARM_ARCH_V1, N_("use -mcpu=arm1")},
11752 {"marm2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -mcpu=arm2")},
11753 {"m2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -mcpu=arm2")},
11754 {"marm250", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm250")},
11755 {"m250", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm250")},
11756 {"marm3", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm3")},
11757 {"m3", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm3")},
11758 {"marm6", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm6")},
11759 {"m6", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm6")},
11760 {"marm600", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm600")},
11761 {"m600", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm600")},
11762 {"marm610", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm610")},
11763 {"m610", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm610")},
11764 {"marm620", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm620")},
11765 {"m620", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm620")},
11766 {"marm7", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7")},
11767 {"m7", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7")},
11768 {"marm70", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm70")},
11769 {"m70", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm70")},
11770 {"marm700", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700")},
11771 {"m700", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700")},
11772 {"marm700i", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700i")},
11773 {"m700i", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700i")},
11774 {"marm710", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710")},
11775 {"m710", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710")},
11776 {"marm710c", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710c")},
11777 {"m710c", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710c")},
11778 {"marm720", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm720")},
11779 {"m720", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm720")},
11780 {"marm7d", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7d")},
11781 {"m7d", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7d")},
11782 {"marm7di", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7di")},
11783 {"m7di", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7di")},
11784 {"marm7m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7m")},
11785 {"m7m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7m")},
11786 {"marm7dm", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dm")},
11787 {"m7dm", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dm")},
11788 {"marm7dmi", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dmi")},
11789 {"m7dmi", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dmi")},
11790 {"marm7100", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7100")},
11791 {"m7100", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7100")},
11792 {"marm7500", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500")},
11793 {"m7500", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500")},
11794 {"marm7500fe", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500fe")},
11795 {"m7500fe", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500fe")},
11796 {"marm7t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
11797 {"m7t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
11798 {"marm7tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
11799 {"m7tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
11800 {"marm710t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm710t")},
11801 {"m710t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm710t")},
11802 {"marm720t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm720t")},
11803 {"m720t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm720t")},
11804 {"marm740t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm740t")},
11805 {"m740t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm740t")},
11806 {"marm8", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm8")},
11807 {"m8", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm8")},
11808 {"marm810", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm810")},
11809 {"m810", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm810")},
11810 {"marm9", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9")},
11811 {"m9", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9")},
11812 {"marm9tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9tdmi")},
11813 {"m9tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9tdmi")},
11814 {"marm920", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm920")},
11815 {"m920", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm920")},
11816 {"marm940", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm940")},
11817 {"m940", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm940")},
11818 {"mstrongarm", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=strongarm")},
11819 {"mstrongarm110", NULL, &legacy_cpu, ARM_ARCH_V4,
11820 N_("use -mcpu=strongarm110")},
11821 {"mstrongarm1100", NULL, &legacy_cpu, ARM_ARCH_V4,
11822 N_("use -mcpu=strongarm1100")},
11823 {"mstrongarm1110", NULL, &legacy_cpu, ARM_ARCH_V4,
11824 N_("use -mcpu=strongarm1110")},
11825 {"mxscale", NULL, &legacy_cpu, ARM_ARCH_XSCALE, N_("use -mcpu=xscale")},
11826 {"miwmmxt", NULL, &legacy_cpu, ARM_ARCH_IWMMXT, N_("use -mcpu=iwmmxt")},
11827 {"mall", NULL, &legacy_cpu, ARM_ANY, N_("use -mcpu=all")},
11828
11829 /* Architecture variants -- don't add any more to this list either. */
11830 {"mv2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -march=armv2")},
11831 {"marmv2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -march=armv2")},
11832 {"mv2a", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -march=armv2a")},
11833 {"marmv2a", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -march=armv2a")},
11834 {"mv3", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -march=armv3")},
11835 {"marmv3", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -march=armv3")},
11836 {"mv3m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -march=armv3m")},
11837 {"marmv3m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -march=armv3m")},
11838 {"mv4", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -march=armv4")},
11839 {"marmv4", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -march=armv4")},
11840 {"mv4t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -march=armv4t")},
11841 {"marmv4t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -march=armv4t")},
11842 {"mv5", NULL, &legacy_cpu, ARM_ARCH_V5, N_("use -march=armv5")},
11843 {"marmv5", NULL, &legacy_cpu, ARM_ARCH_V5, N_("use -march=armv5")},
11844 {"mv5t", NULL, &legacy_cpu, ARM_ARCH_V5T, N_("use -march=armv5t")},
11845 {"marmv5t", NULL, &legacy_cpu, ARM_ARCH_V5T, N_("use -march=armv5t")},
11846 {"mv5e", NULL, &legacy_cpu, ARM_ARCH_V5TE, N_("use -march=armv5te")},
11847 {"marmv5e", NULL, &legacy_cpu, ARM_ARCH_V5TE, N_("use -march=armv5te")},
11848
11849 /* Floating point variants -- don't add any more to this list either. */
11850 {"mfpe-old", NULL, &legacy_fpu, FPU_ARCH_FPE, N_("use -mfpu=fpe")},
11851 {"mfpa10", NULL, &legacy_fpu, FPU_ARCH_FPA, N_("use -mfpu=fpa10")},
11852 {"mfpa11", NULL, &legacy_fpu, FPU_ARCH_FPA, N_("use -mfpu=fpa11")},
11853 {"mno-fpu", NULL, &legacy_fpu, 0,
11854 N_("use either -mfpu=softfpa or -mfpu=softvfp")},
11855
11856 {NULL, NULL, NULL, 0, NULL}
11857 };
11858
11859 struct arm_cpu_option_table
11860 {
11861 char *name;
11862 int value;
11863 /* For some CPUs we assume an FPU unless the user explicitly sets
11864 -mfpu=... */
11865 int default_fpu;
11866 };
11867
11868 /* This list should, at a minimum, contain all the cpu names
11869 recognized by GCC. */
11870 static struct arm_cpu_option_table arm_cpus[] =
11871 {
11872 {"all", ARM_ANY, FPU_ARCH_FPA},
11873 {"arm1", ARM_ARCH_V1, FPU_ARCH_FPA},
11874 {"arm2", ARM_ARCH_V2, FPU_ARCH_FPA},
11875 {"arm250", ARM_ARCH_V2S, FPU_ARCH_FPA},
11876 {"arm3", ARM_ARCH_V2S, FPU_ARCH_FPA},
11877 {"arm6", ARM_ARCH_V3, FPU_ARCH_FPA},
11878 {"arm60", ARM_ARCH_V3, FPU_ARCH_FPA},
11879 {"arm600", ARM_ARCH_V3, FPU_ARCH_FPA},
11880 {"arm610", ARM_ARCH_V3, FPU_ARCH_FPA},
11881 {"arm620", ARM_ARCH_V3, FPU_ARCH_FPA},
11882 {"arm7", ARM_ARCH_V3, FPU_ARCH_FPA},
11883 {"arm7m", ARM_ARCH_V3M, FPU_ARCH_FPA},
11884 {"arm7d", ARM_ARCH_V3, FPU_ARCH_FPA},
11885 {"arm7dm", ARM_ARCH_V3M, FPU_ARCH_FPA},
11886 {"arm7di", ARM_ARCH_V3, FPU_ARCH_FPA},
11887 {"arm7dmi", ARM_ARCH_V3M, FPU_ARCH_FPA},
11888 {"arm70", ARM_ARCH_V3, FPU_ARCH_FPA},
11889 {"arm700", ARM_ARCH_V3, FPU_ARCH_FPA},
11890 {"arm700i", ARM_ARCH_V3, FPU_ARCH_FPA},
11891 {"arm710", ARM_ARCH_V3, FPU_ARCH_FPA},
11892 {"arm710t", ARM_ARCH_V4T, FPU_ARCH_FPA},
11893 {"arm720", ARM_ARCH_V3, FPU_ARCH_FPA},
11894 {"arm720t", ARM_ARCH_V4T, FPU_ARCH_FPA},
11895 {"arm740t", ARM_ARCH_V4T, FPU_ARCH_FPA},
11896 {"arm710c", ARM_ARCH_V3, FPU_ARCH_FPA},
11897 {"arm7100", ARM_ARCH_V3, FPU_ARCH_FPA},
11898 {"arm7500", ARM_ARCH_V3, FPU_ARCH_FPA},
11899 {"arm7500fe", ARM_ARCH_V3, FPU_ARCH_FPA},
11900 {"arm7t", ARM_ARCH_V4T, FPU_ARCH_FPA},
11901 {"arm7tdmi", ARM_ARCH_V4T, FPU_ARCH_FPA},
11902 {"arm8", ARM_ARCH_V4, FPU_ARCH_FPA},
11903 {"arm810", ARM_ARCH_V4, FPU_ARCH_FPA},
11904 {"strongarm", ARM_ARCH_V4, FPU_ARCH_FPA},
11905 {"strongarm1", ARM_ARCH_V4, FPU_ARCH_FPA},
11906 {"strongarm110", ARM_ARCH_V4, FPU_ARCH_FPA},
11907 {"strongarm1100", ARM_ARCH_V4, FPU_ARCH_FPA},
11908 {"strongarm1110", ARM_ARCH_V4, FPU_ARCH_FPA},
11909 {"arm9", ARM_ARCH_V4T, FPU_ARCH_FPA},
11910 {"arm920", ARM_ARCH_V4T, FPU_ARCH_FPA},
11911 {"arm920t", ARM_ARCH_V4T, FPU_ARCH_FPA},
11912 {"arm922t", ARM_ARCH_V4T, FPU_ARCH_FPA},
11913 {"arm940t", ARM_ARCH_V4T, FPU_ARCH_FPA},
11914 {"arm9tdmi", ARM_ARCH_V4T, FPU_ARCH_FPA},
11915 /* For V5 or later processors we default to using VFP; but the user
11916 should really set the FPU type explicitly. */
11917 {"arm9e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
11918 {"arm9e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
11919 {"arm926ej", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
11920 {"arm946e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
11921 {"arm946e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
11922 {"arm966e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
11923 {"arm966e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
11924 {"arm10t", ARM_ARCH_V5T, FPU_ARCH_VFP_V1},
11925 {"arm10e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
11926 {"arm1020", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
11927 {"arm1020t", ARM_ARCH_V5T, FPU_ARCH_VFP_V1},
11928 {"arm1020e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
11929 /* ??? XSCALE is really an architecture. */
11930 {"xscale", ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2},
11931 /* ??? iwmmxt is not a processor. */
11932 {"iwmmxt", ARM_ARCH_IWMMXT, FPU_ARCH_VFP_V2},
11933 {"i80200", ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2},
11934 /* Maverick */
11935 {"ep9312", ARM_ARCH_V4T | ARM_CEXT_MAVERICK, FPU_NONE},
11936 {NULL, 0, 0}
11937 };
11938
11939 struct arm_arch_option_table
11940 {
11941 char *name;
11942 int value;
11943 int default_fpu;
11944 };
11945
11946 /* This list should, at a minimum, contain all the architecture names
11947 recognized by GCC. */
11948 static struct arm_arch_option_table arm_archs[] =
11949 {
11950 {"all", ARM_ANY, FPU_ARCH_FPA},
11951 {"armv1", ARM_ARCH_V1, FPU_ARCH_FPA},
11952 {"armv2", ARM_ARCH_V2, FPU_ARCH_FPA},
11953 {"armv2a", ARM_ARCH_V2S, FPU_ARCH_FPA},
11954 {"armv2s", ARM_ARCH_V2S, FPU_ARCH_FPA},
11955 {"armv3", ARM_ARCH_V3, FPU_ARCH_FPA},
11956 {"armv3m", ARM_ARCH_V3M, FPU_ARCH_FPA},
11957 {"armv4", ARM_ARCH_V4, FPU_ARCH_FPA},
11958 {"armv4xm", ARM_ARCH_V4xM, FPU_ARCH_FPA},
11959 {"armv4t", ARM_ARCH_V4T, FPU_ARCH_FPA},
11960 {"armv4txm", ARM_ARCH_V4TxM, FPU_ARCH_FPA},
11961 {"armv5", ARM_ARCH_V5, FPU_ARCH_VFP},
11962 {"armv5t", ARM_ARCH_V5T, FPU_ARCH_VFP},
11963 {"armv5txm", ARM_ARCH_V5TxM, FPU_ARCH_VFP},
11964 {"armv5te", ARM_ARCH_V5TE, FPU_ARCH_VFP},
11965 {"armv5texp", ARM_ARCH_V5TExP, FPU_ARCH_VFP},
11966 {"armv5tej", ARM_ARCH_V5TEJ, FPU_ARCH_VFP},
11967 {"xscale", ARM_ARCH_XSCALE, FPU_ARCH_VFP},
11968 {"iwmmxt", ARM_ARCH_IWMMXT, FPU_ARCH_VFP},
11969 {NULL, 0, 0}
11970 };
11971
11972 /* ISA extensions in the co-processor space. */
11973 struct arm_arch_extension_table
11974 {
11975 char *name;
11976 int value;
11977 };
11978
11979 static struct arm_arch_extension_table arm_extensions[] =
11980 {
11981 {"maverick", ARM_CEXT_MAVERICK},
11982 {"xscale", ARM_CEXT_XSCALE},
11983 {"iwmmxt", ARM_CEXT_IWMMXT},
11984 {NULL, 0}
11985 };
11986
11987 struct arm_fpu_option_table
11988 {
11989 char *name;
11990 int value;
11991 };
11992
11993 /* This list should, at a minimum, contain all the fpu names
11994 recognized by GCC. */
11995 static struct arm_fpu_option_table arm_fpus[] =
11996 {
11997 {"softfpa", FPU_NONE},
11998 {"fpe", FPU_ARCH_FPE},
11999 {"fpe2", FPU_ARCH_FPE},
12000 {"fpe3", FPU_ARCH_FPA}, /* Third release supports LFM/SFM. */
12001 {"fpa", FPU_ARCH_FPA},
12002 {"fpa10", FPU_ARCH_FPA},
12003 {"fpa11", FPU_ARCH_FPA},
12004 {"arm7500fe", FPU_ARCH_FPA},
12005 {"softvfp", FPU_ARCH_VFP},
12006 {"softvfp+vfp", FPU_ARCH_VFP_V2},
12007 {"vfp", FPU_ARCH_VFP_V2},
12008 {"vfp9", FPU_ARCH_VFP_V2},
12009 {"vfp10", FPU_ARCH_VFP_V2},
12010 {"vfp10-r0", FPU_ARCH_VFP_V1},
12011 {"vfpxd", FPU_ARCH_VFP_V1xD},
12012 {"arm1020t", FPU_ARCH_VFP_V1},
12013 {"arm1020e", FPU_ARCH_VFP_V2},
12014 {NULL, 0}
12015 };
12016
12017 struct arm_long_option_table
12018 {
12019 char *option; /* Substring to match. */
12020 char *help; /* Help information. */
12021 int (*func) PARAMS ((char *subopt)); /* Function to decode sub-option. */
12022 char *deprecated; /* If non-null, print this message. */
12023 };
12024
12025 static int
12026 arm_parse_extension (str, opt_p)
12027 char *str;
12028 int *opt_p;
12029 {
12030 while (str != NULL && *str != 0)
12031 {
12032 struct arm_arch_extension_table *opt;
12033 char *ext;
12034 int optlen;
12035
12036 if (*str != '+')
12037 {
12038 as_bad (_("invalid architectural extension"));
12039 return 0;
12040 }
12041
12042 str++;
12043 ext = strchr (str, '+');
12044
12045 if (ext != NULL)
12046 optlen = ext - str;
12047 else
12048 optlen = strlen (str);
12049
12050 if (optlen == 0)
12051 {
12052 as_bad (_("missing architectural extension"));
12053 return 0;
12054 }
12055
12056 for (opt = arm_extensions; opt->name != NULL; opt++)
12057 if (strncmp (opt->name, str, optlen) == 0)
12058 {
12059 *opt_p |= opt->value;
12060 break;
12061 }
12062
12063 if (opt->name == NULL)
12064 {
12065 as_bad (_("unknown architectural extnsion `%s'"), str);
12066 return 0;
12067 }
12068
12069 str = ext;
12070 };
12071
12072 return 1;
12073 }
12074
12075 static int
12076 arm_parse_cpu (str)
12077 char *str;
12078 {
12079 struct arm_cpu_option_table *opt;
12080 char *ext = strchr (str, '+');
12081 int optlen;
12082
12083 if (ext != NULL)
12084 optlen = ext - str;
12085 else
12086 optlen = strlen (str);
12087
12088 if (optlen == 0)
12089 {
12090 as_bad (_("missing cpu name `%s'"), str);
12091 return 0;
12092 }
12093
12094 for (opt = arm_cpus; opt->name != NULL; opt++)
12095 if (strncmp (opt->name, str, optlen) == 0)
12096 {
12097 mcpu_cpu_opt = opt->value;
12098 mcpu_fpu_opt = opt->default_fpu;
12099
12100 if (ext != NULL)
12101 return arm_parse_extension (ext, &mcpu_cpu_opt);
12102
12103 return 1;
12104 }
12105
12106 as_bad (_("unknown cpu `%s'"), str);
12107 return 0;
12108 }
12109
12110 static int
12111 arm_parse_arch (str)
12112 char *str;
12113 {
12114 struct arm_arch_option_table *opt;
12115 char *ext = strchr (str, '+');
12116 int optlen;
12117
12118 if (ext != NULL)
12119 optlen = ext - str;
12120 else
12121 optlen = strlen (str);
12122
12123 if (optlen == 0)
12124 {
12125 as_bad (_("missing architecture name `%s'"), str);
12126 return 0;
12127 }
12128
12129
12130 for (opt = arm_archs; opt->name != NULL; opt++)
12131 if (strcmp (opt->name, str) == 0)
12132 {
12133 march_cpu_opt = opt->value;
12134 march_fpu_opt = opt->default_fpu;
12135
12136 if (ext != NULL)
12137 return arm_parse_extension (ext, &march_cpu_opt);
12138
12139 return 1;
12140 }
12141
12142 as_bad (_("unknown architecture `%s'\n"), str);
12143 return 0;
12144 }
12145
12146 static int
12147 arm_parse_fpu (str)
12148 char *str;
12149 {
12150 struct arm_fpu_option_table *opt;
12151
12152 for (opt = arm_fpus; opt->name != NULL; opt++)
12153 if (strcmp (opt->name, str) == 0)
12154 {
12155 mfpu_opt = opt->value;
12156 return 1;
12157 }
12158
12159 as_bad (_("unknown floating point format `%s'\n"), str);
12160 return 0;
12161 }
12162
12163 struct arm_long_option_table arm_long_opts[] =
12164 {
12165 {"mcpu=", N_("<cpu name>\t assemble for CPU <cpu name>"),
12166 arm_parse_cpu, NULL},
12167 {"march=", N_("<arch name>\t assemble for architecture <arch name>"),
12168 arm_parse_arch, NULL},
12169 {"mfpu=", N_("<fpu name>\t assemble for FPU architecture <fpu name>"),
12170 arm_parse_fpu, NULL},
12171 {NULL, NULL, 0, NULL}
12172 };
12173
12174 int
12175 md_parse_option (c, arg)
12176 int c;
12177 char * arg;
12178 {
12179 struct arm_option_table *opt;
12180 struct arm_long_option_table *lopt;
12181
12182 switch (c)
12183 {
12184 #ifdef OPTION_EB
12185 case OPTION_EB:
12186 target_big_endian = 1;
12187 break;
12188 #endif
12189
12190 #ifdef OPTION_EL
12191 case OPTION_EL:
12192 target_big_endian = 0;
12193 break;
12194 #endif
12195
12196 case 'a':
12197 /* Listing option. Just ignore these, we don't support additional
12198 ones. */
12199 return 0;
12200
12201 default:
12202 for (opt = arm_opts; opt->option != NULL; opt++)
12203 {
12204 if (c == opt->option[0]
12205 && ((arg == NULL && opt->option[1] == 0)
12206 || strcmp (arg, opt->option + 1) == 0))
12207 {
12208 #if WARN_DEPRECATED
12209 /* If the option is deprecated, tell the user. */
12210 if (opt->deprecated != NULL)
12211 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c,
12212 arg ? arg : "", _(opt->deprecated));
12213 #endif
12214
12215 if (opt->var != NULL)
12216 *opt->var = opt->value;
12217
12218 return 1;
12219 }
12220 }
12221
12222 for (lopt = arm_long_opts; lopt->option != NULL; lopt++)
12223 {
12224 /* These options are expected to have an argument. */
12225 if (c == lopt->option[0]
12226 && arg != NULL
12227 && strncmp (arg, lopt->option + 1,
12228 strlen (lopt->option + 1)) == 0)
12229 {
12230 #if WARN_DEPRECATED
12231 /* If the option is deprecated, tell the user. */
12232 if (lopt->deprecated != NULL)
12233 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c, arg,
12234 _(lopt->deprecated));
12235 #endif
12236
12237 /* Call the sup-option parser. */
12238 return (*lopt->func)(arg + strlen (lopt->option) - 1);
12239 }
12240 }
12241
12242 as_bad (_("unrecognized option `-%c%s'"), c, arg ? arg : "");
12243 return 0;
12244 }
12245
12246 return 1;
12247 }
12248
12249 void
12250 md_show_usage (fp)
12251 FILE * fp;
12252 {
12253 struct arm_option_table *opt;
12254 struct arm_long_option_table *lopt;
12255
12256 fprintf (fp, _(" ARM-specific assembler options:\n"));
12257
12258 for (opt = arm_opts; opt->option != NULL; opt++)
12259 if (opt->help != NULL)
12260 fprintf (fp, " -%-23s%s\n", opt->option, _(opt->help));
12261
12262 for (lopt = arm_long_opts; lopt->option != NULL; lopt++)
12263 if (lopt->help != NULL)
12264 fprintf (fp, " -%s%s\n", lopt->option, _(lopt->help));
12265
12266 #ifdef OPTION_EB
12267 fprintf (fp, _("\
12268 -EB assemble code for a big-endian cpu\n"));
12269 #endif
12270
12271 #ifdef OPTION_EL
12272 fprintf (fp, _("\
12273 -EL assemble code for a little-endian cpu\n"));
12274 #endif
12275 }
12276
12277 /* We need to be able to fix up arbitrary expressions in some statements.
12278 This is so that we can handle symbols that are an arbitrary distance from
12279 the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
12280 which returns part of an address in a form which will be valid for
12281 a data instruction. We do this by pushing the expression into a symbol
12282 in the expr_section, and creating a fix for that. */
12283
12284 static void
12285 fix_new_arm (frag, where, size, exp, pc_rel, reloc)
12286 fragS * frag;
12287 int where;
12288 short int size;
12289 expressionS * exp;
12290 int pc_rel;
12291 int reloc;
12292 {
12293 fixS * new_fix;
12294 arm_fix_data * arm_data;
12295
12296 switch (exp->X_op)
12297 {
12298 case O_constant:
12299 case O_symbol:
12300 case O_add:
12301 case O_subtract:
12302 new_fix = fix_new_exp (frag, where, size, exp, pc_rel, reloc);
12303 break;
12304
12305 default:
12306 new_fix = fix_new (frag, where, size, make_expr_symbol (exp), 0,
12307 pc_rel, reloc);
12308 break;
12309 }
12310
12311 /* Mark whether the fix is to a THUMB instruction, or an ARM
12312 instruction. */
12313 arm_data = (arm_fix_data *) obstack_alloc (& notes, sizeof (arm_fix_data));
12314 new_fix->tc_fix_data = (PTR) arm_data;
12315 arm_data->thumb_mode = thumb_mode;
12316
12317 return;
12318 }
12319
12320 /* This fix_new is called by cons via TC_CONS_FIX_NEW. */
12321
12322 void
12323 cons_fix_new_arm (frag, where, size, exp)
12324 fragS * frag;
12325 int where;
12326 int size;
12327 expressionS * exp;
12328 {
12329 bfd_reloc_code_real_type type;
12330 int pcrel = 0;
12331
12332 /* Pick a reloc.
12333 FIXME: @@ Should look at CPU word size. */
12334 switch (size)
12335 {
12336 case 1:
12337 type = BFD_RELOC_8;
12338 break;
12339 case 2:
12340 type = BFD_RELOC_16;
12341 break;
12342 case 4:
12343 default:
12344 type = BFD_RELOC_32;
12345 break;
12346 case 8:
12347 type = BFD_RELOC_64;
12348 break;
12349 }
12350
12351 fix_new_exp (frag, where, (int) size, exp, pcrel, type);
12352 }
12353
12354 /* A good place to do this, although this was probably not intended
12355 for this kind of use. We need to dump the literal pool before
12356 references are made to a null symbol pointer. */
12357
12358 void
12359 arm_cleanup ()
12360 {
12361 literal_pool * pool;
12362
12363 for (pool = list_of_pools; pool; pool = pool->next)
12364 {
12365 /* Put it at the end of the relevent section. */
12366 subseg_set (pool->section, pool->sub_section);
12367 s_ltorg (0);
12368 }
12369 }
12370
12371 void
12372 arm_start_line_hook ()
12373 {
12374 last_label_seen = NULL;
12375 }
12376
12377 void
12378 arm_frob_label (sym)
12379 symbolS * sym;
12380 {
12381 last_label_seen = sym;
12382
12383 ARM_SET_THUMB (sym, thumb_mode);
12384
12385 #if defined OBJ_COFF || defined OBJ_ELF
12386 ARM_SET_INTERWORK (sym, support_interwork);
12387 #endif
12388
12389 /* Note - do not allow local symbols (.Lxxx) to be labeled
12390 as Thumb functions. This is because these labels, whilst
12391 they exist inside Thumb code, are not the entry points for
12392 possible ARM->Thumb calls. Also, these labels can be used
12393 as part of a computed goto or switch statement. eg gcc
12394 can generate code that looks like this:
12395
12396 ldr r2, [pc, .Laaa]
12397 lsl r3, r3, #2
12398 ldr r2, [r3, r2]
12399 mov pc, r2
12400
12401 .Lbbb: .word .Lxxx
12402 .Lccc: .word .Lyyy
12403 ..etc...
12404 .Laaa: .word Lbbb
12405
12406 The first instruction loads the address of the jump table.
12407 The second instruction converts a table index into a byte offset.
12408 The third instruction gets the jump address out of the table.
12409 The fourth instruction performs the jump.
12410
12411 If the address stored at .Laaa is that of a symbol which has the
12412 Thumb_Func bit set, then the linker will arrange for this address
12413 to have the bottom bit set, which in turn would mean that the
12414 address computation performed by the third instruction would end
12415 up with the bottom bit set. Since the ARM is capable of unaligned
12416 word loads, the instruction would then load the incorrect address
12417 out of the jump table, and chaos would ensue. */
12418 if (label_is_thumb_function_name
12419 && (S_GET_NAME (sym)[0] != '.' || S_GET_NAME (sym)[1] != 'L')
12420 && (bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
12421 {
12422 /* When the address of a Thumb function is taken the bottom
12423 bit of that address should be set. This will allow
12424 interworking between Arm and Thumb functions to work
12425 correctly. */
12426
12427 THUMB_SET_FUNC (sym, 1);
12428
12429 label_is_thumb_function_name = FALSE;
12430 }
12431 }
12432
12433 /* Adjust the symbol table. This marks Thumb symbols as distinct from
12434 ARM ones. */
12435
12436 void
12437 arm_adjust_symtab ()
12438 {
12439 #ifdef OBJ_COFF
12440 symbolS * sym;
12441
12442 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
12443 {
12444 if (ARM_IS_THUMB (sym))
12445 {
12446 if (THUMB_IS_FUNC (sym))
12447 {
12448 /* Mark the symbol as a Thumb function. */
12449 if ( S_GET_STORAGE_CLASS (sym) == C_STAT
12450 || S_GET_STORAGE_CLASS (sym) == C_LABEL) /* This can happen! */
12451 S_SET_STORAGE_CLASS (sym, C_THUMBSTATFUNC);
12452
12453 else if (S_GET_STORAGE_CLASS (sym) == C_EXT)
12454 S_SET_STORAGE_CLASS (sym, C_THUMBEXTFUNC);
12455 else
12456 as_bad (_("%s: unexpected function type: %d"),
12457 S_GET_NAME (sym), S_GET_STORAGE_CLASS (sym));
12458 }
12459 else switch (S_GET_STORAGE_CLASS (sym))
12460 {
12461 case C_EXT:
12462 S_SET_STORAGE_CLASS (sym, C_THUMBEXT);
12463 break;
12464 case C_STAT:
12465 S_SET_STORAGE_CLASS (sym, C_THUMBSTAT);
12466 break;
12467 case C_LABEL:
12468 S_SET_STORAGE_CLASS (sym, C_THUMBLABEL);
12469 break;
12470 default:
12471 /* Do nothing. */
12472 break;
12473 }
12474 }
12475
12476 if (ARM_IS_INTERWORK (sym))
12477 coffsymbol (symbol_get_bfdsym (sym))->native->u.syment.n_flags = 0xFF;
12478 }
12479 #endif
12480 #ifdef OBJ_ELF
12481 symbolS * sym;
12482 char bind;
12483
12484 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
12485 {
12486 if (ARM_IS_THUMB (sym))
12487 {
12488 elf_symbol_type * elf_sym;
12489
12490 elf_sym = elf_symbol (symbol_get_bfdsym (sym));
12491 bind = ELF_ST_BIND (elf_sym);
12492
12493 /* If it's a .thumb_func, declare it as so,
12494 otherwise tag label as .code 16. */
12495 if (THUMB_IS_FUNC (sym))
12496 elf_sym->internal_elf_sym.st_info =
12497 ELF_ST_INFO (bind, STT_ARM_TFUNC);
12498 else
12499 elf_sym->internal_elf_sym.st_info =
12500 ELF_ST_INFO (bind, STT_ARM_16BIT);
12501 }
12502 }
12503 #endif
12504 }
12505
12506 int
12507 arm_data_in_code ()
12508 {
12509 if (thumb_mode && ! strncmp (input_line_pointer + 1, "data:", 5))
12510 {
12511 *input_line_pointer = '/';
12512 input_line_pointer += 5;
12513 *input_line_pointer = 0;
12514 return 1;
12515 }
12516
12517 return 0;
12518 }
12519
12520 char *
12521 arm_canonicalize_symbol_name (name)
12522 char * name;
12523 {
12524 int len;
12525
12526 if (thumb_mode && (len = strlen (name)) > 5
12527 && streq (name + len - 5, "/data"))
12528 *(name + len - 5) = 0;
12529
12530 return name;
12531 }
12532
12533 #if defined OBJ_COFF || defined OBJ_ELF
12534 void
12535 arm_validate_fix (fixP)
12536 fixS * fixP;
12537 {
12538 /* If the destination of the branch is a defined symbol which does not have
12539 the THUMB_FUNC attribute, then we must be calling a function which has
12540 the (interfacearm) attribute. We look for the Thumb entry point to that
12541 function and change the branch to refer to that function instead. */
12542 if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23
12543 && fixP->fx_addsy != NULL
12544 && S_IS_DEFINED (fixP->fx_addsy)
12545 && ! THUMB_IS_FUNC (fixP->fx_addsy))
12546 {
12547 fixP->fx_addsy = find_real_start (fixP->fx_addsy);
12548 }
12549 }
12550 #endif
12551
12552 int
12553 arm_force_relocation (fixp)
12554 struct fix * fixp;
12555 {
12556 #if defined (OBJ_COFF) && defined (TE_PE)
12557 if (fixp->fx_r_type == BFD_RELOC_RVA)
12558 return 1;
12559 #endif
12560 #ifdef OBJ_ELF
12561 if (fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH
12562 || fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BLX
12563 || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX
12564 || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23)
12565 return 1;
12566 #endif
12567
12568 /* Resolve these relocations even if the symbol is extern or weak. */
12569 if (fixp->fx_r_type == BFD_RELOC_ARM_IMMEDIATE
12570 || fixp->fx_r_type == BFD_RELOC_ARM_OFFSET_IMM
12571 || fixp->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE)
12572 return 0;
12573
12574 return generic_force_reloc (fixp);
12575 }
12576
12577 #ifdef OBJ_COFF
12578 /* This is a little hack to help the gas/arm/adrl.s test. It prevents
12579 local labels from being added to the output symbol table when they
12580 are used with the ADRL pseudo op. The ADRL relocation should always
12581 be resolved before the binbary is emitted, so it is safe to say that
12582 it is adjustable. */
12583
12584 bfd_boolean
12585 arm_fix_adjustable (fixP)
12586 fixS * fixP;
12587 {
12588 if (fixP->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE)
12589 return 1;
12590 return 0;
12591 }
12592 #endif
12593
12594 #ifdef OBJ_ELF
12595 /* Relocations against Thumb function names must be left unadjusted,
12596 so that the linker can use this information to correctly set the
12597 bottom bit of their addresses. The MIPS version of this function
12598 also prevents relocations that are mips-16 specific, but I do not
12599 know why it does this.
12600
12601 FIXME:
12602 There is one other problem that ought to be addressed here, but
12603 which currently is not: Taking the address of a label (rather
12604 than a function) and then later jumping to that address. Such
12605 addresses also ought to have their bottom bit set (assuming that
12606 they reside in Thumb code), but at the moment they will not. */
12607
12608 bfd_boolean
12609 arm_fix_adjustable (fixP)
12610 fixS * fixP;
12611 {
12612 if (fixP->fx_addsy == NULL)
12613 return 1;
12614
12615 if (THUMB_IS_FUNC (fixP->fx_addsy)
12616 && fixP->fx_subsy == NULL)
12617 return 0;
12618
12619 /* We need the symbol name for the VTABLE entries. */
12620 if ( fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
12621 || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
12622 return 0;
12623
12624 /* Don't allow symbols to be discarded on GOT related relocs. */
12625 if (fixP->fx_r_type == BFD_RELOC_ARM_PLT32
12626 || fixP->fx_r_type == BFD_RELOC_ARM_GOT32
12627 || fixP->fx_r_type == BFD_RELOC_ARM_GOTOFF)
12628 return 0;
12629
12630 return 1;
12631 }
12632
12633 const char *
12634 elf32_arm_target_format ()
12635 {
12636 if (target_big_endian)
12637 {
12638 if (target_oabi)
12639 return "elf32-bigarm-oabi";
12640 else
12641 return "elf32-bigarm";
12642 }
12643 else
12644 {
12645 if (target_oabi)
12646 return "elf32-littlearm-oabi";
12647 else
12648 return "elf32-littlearm";
12649 }
12650 }
12651
12652 void
12653 armelf_frob_symbol (symp, puntp)
12654 symbolS * symp;
12655 int * puntp;
12656 {
12657 elf_frob_symbol (symp, puntp);
12658 }
12659
12660 static bfd_reloc_code_real_type
12661 arm_parse_reloc ()
12662 {
12663 char id [16];
12664 char * ip;
12665 unsigned int i;
12666 static struct
12667 {
12668 char * str;
12669 int len;
12670 bfd_reloc_code_real_type reloc;
12671 }
12672 reloc_map[] =
12673 {
12674 #define MAP(str,reloc) { str, sizeof (str) - 1, reloc }
12675 MAP ("(got)", BFD_RELOC_ARM_GOT32),
12676 MAP ("(gotoff)", BFD_RELOC_ARM_GOTOFF),
12677 /* ScottB: Jan 30, 1998 - Added support for parsing "var(PLT)"
12678 branch instructions generated by GCC for PLT relocs. */
12679 MAP ("(plt)", BFD_RELOC_ARM_PLT32),
12680 { NULL, 0, BFD_RELOC_UNUSED }
12681 #undef MAP
12682 };
12683
12684 for (i = 0, ip = input_line_pointer;
12685 i < sizeof (id) && (ISALNUM (*ip) || ISPUNCT (*ip));
12686 i++, ip++)
12687 id[i] = TOLOWER (*ip);
12688
12689 for (i = 0; reloc_map[i].str; i++)
12690 if (strncmp (id, reloc_map[i].str, reloc_map[i].len) == 0)
12691 break;
12692
12693 input_line_pointer += reloc_map[i].len;
12694
12695 return reloc_map[i].reloc;
12696 }
12697
12698 static void
12699 s_arm_elf_cons (nbytes)
12700 int nbytes;
12701 {
12702 expressionS exp;
12703
12704 #ifdef md_flush_pending_output
12705 md_flush_pending_output ();
12706 #endif
12707
12708 if (is_it_end_of_statement ())
12709 {
12710 demand_empty_rest_of_line ();
12711 return;
12712 }
12713
12714 #ifdef md_cons_align
12715 md_cons_align (nbytes);
12716 #endif
12717
12718 do
12719 {
12720 bfd_reloc_code_real_type reloc;
12721
12722 expression (& exp);
12723
12724 if (exp.X_op == O_symbol
12725 && * input_line_pointer == '('
12726 && (reloc = arm_parse_reloc ()) != BFD_RELOC_UNUSED)
12727 {
12728 reloc_howto_type *howto = bfd_reloc_type_lookup (stdoutput, reloc);
12729 int size = bfd_get_reloc_size (howto);
12730
12731 if (size > nbytes)
12732 as_bad ("%s relocations do not fit in %d bytes",
12733 howto->name, nbytes);
12734 else
12735 {
12736 register char *p = frag_more ((int) nbytes);
12737 int offset = nbytes - size;
12738
12739 fix_new_exp (frag_now, p - frag_now->fr_literal + offset, size,
12740 &exp, 0, reloc);
12741 }
12742 }
12743 else
12744 emit_expr (&exp, (unsigned int) nbytes);
12745 }
12746 while (*input_line_pointer++ == ',');
12747
12748 /* Put terminator back into stream. */
12749 input_line_pointer --;
12750 demand_empty_rest_of_line ();
12751 }
12752
12753 #endif /* OBJ_ELF */
12754
12755 /* This is called from HANDLE_ALIGN in write.c. Fill in the contents
12756 of an rs_align_code fragment. */
12757
12758 void
12759 arm_handle_align (fragP)
12760 fragS *fragP;
12761 {
12762 static char const arm_noop[4] = { 0x00, 0x00, 0xa0, 0xe1 };
12763 static char const thumb_noop[2] = { 0xc0, 0x46 };
12764 static char const arm_bigend_noop[4] = { 0xe1, 0xa0, 0x00, 0x00 };
12765 static char const thumb_bigend_noop[2] = { 0x46, 0xc0 };
12766
12767 int bytes, fix, noop_size;
12768 char * p;
12769 const char * noop;
12770
12771 if (fragP->fr_type != rs_align_code)
12772 return;
12773
12774 bytes = fragP->fr_next->fr_address - fragP->fr_address - fragP->fr_fix;
12775 p = fragP->fr_literal + fragP->fr_fix;
12776 fix = 0;
12777
12778 if (bytes > MAX_MEM_FOR_RS_ALIGN_CODE)
12779 bytes &= MAX_MEM_FOR_RS_ALIGN_CODE;
12780
12781 if (fragP->tc_frag_data)
12782 {
12783 if (target_big_endian)
12784 noop = thumb_bigend_noop;
12785 else
12786 noop = thumb_noop;
12787 noop_size = sizeof (thumb_noop);
12788 }
12789 else
12790 {
12791 if (target_big_endian)
12792 noop = arm_bigend_noop;
12793 else
12794 noop = arm_noop;
12795 noop_size = sizeof (arm_noop);
12796 }
12797
12798 if (bytes & (noop_size - 1))
12799 {
12800 fix = bytes & (noop_size - 1);
12801 memset (p, 0, fix);
12802 p += fix;
12803 bytes -= fix;
12804 }
12805
12806 while (bytes >= noop_size)
12807 {
12808 memcpy (p, noop, noop_size);
12809 p += noop_size;
12810 bytes -= noop_size;
12811 fix += noop_size;
12812 }
12813
12814 fragP->fr_fix += fix;
12815 fragP->fr_var = noop_size;
12816 }
12817
12818 /* Called from md_do_align. Used to create an alignment
12819 frag in a code section. */
12820
12821 void
12822 arm_frag_align_code (n, max)
12823 int n;
12824 int max;
12825 {
12826 char * p;
12827
12828 /* We assume that there will never be a requirment
12829 to support alignments greater than 32 bytes. */
12830 if (max > MAX_MEM_FOR_RS_ALIGN_CODE)
12831 as_fatal (_("alignments greater than 32 bytes not supported in .text sections."));
12832
12833 p = frag_var (rs_align_code,
12834 MAX_MEM_FOR_RS_ALIGN_CODE,
12835 1,
12836 (relax_substateT) max,
12837 (symbolS *) NULL,
12838 (offsetT) n,
12839 (char *) NULL);
12840 *p = 0;
12841
12842 }
12843
12844 /* Perform target specific initialisation of a frag. */
12845
12846 void
12847 arm_init_frag (fragP)
12848 fragS *fragP;
12849 {
12850 /* Record whether this frag is in an ARM or a THUMB area. */
12851 fragP->tc_frag_data = thumb_mode;
12852 }
This page took 0.312189 seconds and 4 git commands to generate.