* tc-arm.c (FPU_DEFAULT, case TE_LINUX): Default to FPU_ARCH_FPA.
[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 if (wb_ok && skip_past_comma (& p) == SUCCESS)
3333 {
3334 /* [Rn], #expr */
3335 write_back = WRITE_BACK;
3336
3337 if (reg == REG_PC)
3338 {
3339 inst.error = _("pc may not be used in post-increment");
3340 return FAIL;
3341 }
3342
3343 if (cp_address_offset (& p) == FAIL)
3344 return FAIL;
3345 }
3346 else
3347 pre_inc = PRE_INDEX | INDEX_UP;
3348 }
3349 else
3350 {
3351 /* '['Rn, #expr']'[!] */
3352
3353 if (skip_past_comma (& p) == FAIL)
3354 {
3355 inst.error = _("pre-indexed expression expected");
3356 return FAIL;
3357 }
3358
3359 pre_inc = PRE_INDEX;
3360
3361 if (cp_address_offset (& p) == FAIL)
3362 return FAIL;
3363
3364 skip_whitespace (p);
3365
3366 if (*p++ != ']')
3367 {
3368 inst.error = _("missing ]");
3369 return FAIL;
3370 }
3371
3372 skip_whitespace (p);
3373
3374 if (wb_ok && *p == '!')
3375 {
3376 if (reg == REG_PC)
3377 {
3378 inst.error = _("pc may not be used with write-back");
3379 return FAIL;
3380 }
3381
3382 p++;
3383 write_back = WRITE_BACK;
3384 }
3385 }
3386 }
3387 else
3388 {
3389 if (my_get_expression (&inst.reloc.exp, &p))
3390 return FAIL;
3391
3392 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
3393 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
3394 inst.reloc.pc_rel = 1;
3395 inst.instruction |= (REG_PC << 16);
3396 pre_inc = PRE_INDEX;
3397 }
3398
3399 inst.instruction |= write_back | pre_inc;
3400 *str = p;
3401 return SUCCESS;
3402 }
3403
3404 static int
3405 cp_byte_address_offset (str)
3406 char ** str;
3407 {
3408 int offset;
3409
3410 skip_whitespace (* str);
3411
3412 if (! is_immediate_prefix (**str))
3413 {
3414 inst.error = _("immediate expression expected");
3415 return FAIL;
3416 }
3417
3418 (*str)++;
3419
3420 if (my_get_expression (& inst.reloc.exp, str))
3421 return FAIL;
3422
3423 if (inst.reloc.exp.X_op == O_constant)
3424 {
3425 offset = inst.reloc.exp.X_add_number;
3426
3427 if (offset > 255 || offset < -255)
3428 {
3429 inst.error = _("offset too large");
3430 return FAIL;
3431 }
3432
3433 if (offset >= 0)
3434 inst.instruction |= INDEX_UP;
3435 else
3436 offset = -offset;
3437
3438 inst.instruction |= offset;
3439 }
3440 else
3441 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM_S2;
3442
3443 return SUCCESS;
3444 }
3445
3446 static int
3447 cp_byte_address_required_here (str)
3448 char ** str;
3449 {
3450 char * p = * str;
3451 int pre_inc = 0;
3452 int write_back = 0;
3453
3454 if (*p == '[')
3455 {
3456 int reg;
3457
3458 p++;
3459 skip_whitespace (p);
3460
3461 if ((reg = reg_required_here (& p, 16)) == FAIL)
3462 return FAIL;
3463
3464 skip_whitespace (p);
3465
3466 if (*p == ']')
3467 {
3468 p++;
3469
3470 if (skip_past_comma (& p) == SUCCESS)
3471 {
3472 /* [Rn], #expr */
3473 write_back = WRITE_BACK;
3474
3475 if (reg == REG_PC)
3476 {
3477 inst.error = _("pc may not be used in post-increment");
3478 return FAIL;
3479 }
3480
3481 if (cp_byte_address_offset (& p) == FAIL)
3482 return FAIL;
3483 }
3484 else
3485 pre_inc = PRE_INDEX | INDEX_UP;
3486 }
3487 else
3488 {
3489 /* '['Rn, #expr']'[!] */
3490
3491 if (skip_past_comma (& p) == FAIL)
3492 {
3493 inst.error = _("pre-indexed expression expected");
3494 return FAIL;
3495 }
3496
3497 pre_inc = PRE_INDEX;
3498
3499 if (cp_byte_address_offset (& p) == FAIL)
3500 return FAIL;
3501
3502 skip_whitespace (p);
3503
3504 if (*p++ != ']')
3505 {
3506 inst.error = _("missing ]");
3507 return FAIL;
3508 }
3509
3510 skip_whitespace (p);
3511
3512 if (*p == '!')
3513 {
3514 if (reg == REG_PC)
3515 {
3516 inst.error = _("pc may not be used with write-back");
3517 return FAIL;
3518 }
3519
3520 p++;
3521 write_back = WRITE_BACK;
3522 }
3523 }
3524 }
3525 else
3526 {
3527 if (my_get_expression (&inst.reloc.exp, &p))
3528 return FAIL;
3529
3530 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM_S2;
3531 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
3532 inst.reloc.pc_rel = 1;
3533 inst.instruction |= (REG_PC << 16);
3534 pre_inc = PRE_INDEX;
3535 }
3536
3537 inst.instruction |= write_back | pre_inc;
3538 *str = p;
3539 return SUCCESS;
3540 }
3541
3542 static void
3543 do_empty (str)
3544 char * str;
3545 {
3546 /* Do nothing really. */
3547 end_of_line (str);
3548 return;
3549 }
3550
3551 static void
3552 do_mrs (str)
3553 char *str;
3554 {
3555 int skip = 0;
3556
3557 /* Only one syntax. */
3558 skip_whitespace (str);
3559
3560 if (reg_required_here (&str, 12) == FAIL)
3561 {
3562 inst.error = BAD_ARGS;
3563 return;
3564 }
3565
3566 if (skip_past_comma (&str) == FAIL)
3567 {
3568 inst.error = _("comma expected after register name");
3569 return;
3570 }
3571
3572 skip_whitespace (str);
3573
3574 if ( strcmp (str, "CPSR") == 0
3575 || strcmp (str, "SPSR") == 0
3576 /* Lower case versions for backwards compatability. */
3577 || strcmp (str, "cpsr") == 0
3578 || strcmp (str, "spsr") == 0)
3579 skip = 4;
3580
3581 /* This is for backwards compatability with older toolchains. */
3582 else if ( strcmp (str, "cpsr_all") == 0
3583 || strcmp (str, "spsr_all") == 0)
3584 skip = 8;
3585 else
3586 {
3587 inst.error = _("CPSR or SPSR expected");
3588 return;
3589 }
3590
3591 if (* str == 's' || * str == 'S')
3592 inst.instruction |= SPSR_BIT;
3593 str += skip;
3594
3595 end_of_line (str);
3596 }
3597
3598 /* Two possible forms:
3599 "{C|S}PSR_<field>, Rm",
3600 "{C|S}PSR_f, #expression". */
3601
3602 static void
3603 do_msr (str)
3604 char * str;
3605 {
3606 skip_whitespace (str);
3607
3608 if (psr_required_here (& str) == FAIL)
3609 return;
3610
3611 if (skip_past_comma (& str) == FAIL)
3612 {
3613 inst.error = _("comma missing after psr flags");
3614 return;
3615 }
3616
3617 skip_whitespace (str);
3618
3619 if (reg_required_here (& str, 0) != FAIL)
3620 {
3621 inst.error = NULL;
3622 end_of_line (str);
3623 return;
3624 }
3625
3626 if (! is_immediate_prefix (* str))
3627 {
3628 inst.error =
3629 _("only a register or immediate value can follow a psr flag");
3630 return;
3631 }
3632
3633 str ++;
3634 inst.error = NULL;
3635
3636 if (my_get_expression (& inst.reloc.exp, & str))
3637 {
3638 inst.error =
3639 _("only a register or immediate value can follow a psr flag");
3640 return;
3641 }
3642
3643 #if 0 /* The first edition of the ARM architecture manual stated that
3644 writing anything other than the flags with an immediate operation
3645 had UNPREDICTABLE effects. This constraint was removed in the
3646 second edition of the specification. */
3647 if ((cpu_variant & ARM_EXT_V5) != ARM_EXT_V5
3648 && inst.instruction & ((PSR_c | PSR_x | PSR_s) << PSR_SHIFT))
3649 {
3650 inst.error = _("immediate value cannot be used to set this field");
3651 return;
3652 }
3653 #endif
3654
3655 inst.instruction |= INST_IMMEDIATE;
3656
3657 if (inst.reloc.exp.X_add_symbol)
3658 {
3659 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
3660 inst.reloc.pc_rel = 0;
3661 }
3662 else
3663 {
3664 unsigned value = validate_immediate (inst.reloc.exp.X_add_number);
3665
3666 if (value == (unsigned) FAIL)
3667 {
3668 inst.error = _("invalid constant");
3669 return;
3670 }
3671
3672 inst.instruction |= value;
3673 }
3674
3675 inst.error = NULL;
3676 end_of_line (str);
3677 }
3678
3679 /* Long Multiply Parser
3680 UMULL RdLo, RdHi, Rm, Rs
3681 SMULL RdLo, RdHi, Rm, Rs
3682 UMLAL RdLo, RdHi, Rm, Rs
3683 SMLAL RdLo, RdHi, Rm, Rs. */
3684
3685 static void
3686 do_mull (str)
3687 char * str;
3688 {
3689 int rdlo, rdhi, rm, rs;
3690
3691 /* Only one format "rdlo, rdhi, rm, rs". */
3692 skip_whitespace (str);
3693
3694 if ((rdlo = reg_required_here (&str, 12)) == FAIL)
3695 {
3696 inst.error = BAD_ARGS;
3697 return;
3698 }
3699
3700 if (skip_past_comma (&str) == FAIL
3701 || (rdhi = reg_required_here (&str, 16)) == FAIL)
3702 {
3703 inst.error = BAD_ARGS;
3704 return;
3705 }
3706
3707 if (skip_past_comma (&str) == FAIL
3708 || (rm = reg_required_here (&str, 0)) == FAIL)
3709 {
3710 inst.error = BAD_ARGS;
3711 return;
3712 }
3713
3714 /* rdhi, rdlo and rm must all be different. */
3715 if (rdlo == rdhi || rdlo == rm || rdhi == rm)
3716 as_tsktsk (_("rdhi, rdlo and rm must all be different"));
3717
3718 if (skip_past_comma (&str) == FAIL
3719 || (rs = reg_required_here (&str, 8)) == FAIL)
3720 {
3721 inst.error = BAD_ARGS;
3722 return;
3723 }
3724
3725 if (rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC)
3726 {
3727 inst.error = BAD_PC;
3728 return;
3729 }
3730
3731 end_of_line (str);
3732 return;
3733 }
3734
3735 static void
3736 do_mul (str)
3737 char * str;
3738 {
3739 int rd, rm;
3740
3741 /* Only one format "rd, rm, rs". */
3742 skip_whitespace (str);
3743
3744 if ((rd = reg_required_here (&str, 16)) == FAIL)
3745 {
3746 inst.error = BAD_ARGS;
3747 return;
3748 }
3749
3750 if (rd == REG_PC)
3751 {
3752 inst.error = BAD_PC;
3753 return;
3754 }
3755
3756 if (skip_past_comma (&str) == FAIL
3757 || (rm = reg_required_here (&str, 0)) == FAIL)
3758 {
3759 inst.error = BAD_ARGS;
3760 return;
3761 }
3762
3763 if (rm == REG_PC)
3764 {
3765 inst.error = BAD_PC;
3766 return;
3767 }
3768
3769 if (rm == rd)
3770 as_tsktsk (_("rd and rm should be different in mul"));
3771
3772 if (skip_past_comma (&str) == FAIL
3773 || (rm = reg_required_here (&str, 8)) == FAIL)
3774 {
3775 inst.error = BAD_ARGS;
3776 return;
3777 }
3778
3779 if (rm == REG_PC)
3780 {
3781 inst.error = BAD_PC;
3782 return;
3783 }
3784
3785 end_of_line (str);
3786 return;
3787 }
3788
3789 static void
3790 do_mla (str)
3791 char * str;
3792 {
3793 int rd, rm;
3794
3795 /* Only one format "rd, rm, rs, rn". */
3796 skip_whitespace (str);
3797
3798 if ((rd = reg_required_here (&str, 16)) == FAIL)
3799 {
3800 inst.error = BAD_ARGS;
3801 return;
3802 }
3803
3804 if (rd == REG_PC)
3805 {
3806 inst.error = BAD_PC;
3807 return;
3808 }
3809
3810 if (skip_past_comma (&str) == FAIL
3811 || (rm = reg_required_here (&str, 0)) == FAIL)
3812 {
3813 inst.error = BAD_ARGS;
3814 return;
3815 }
3816
3817 if (rm == REG_PC)
3818 {
3819 inst.error = BAD_PC;
3820 return;
3821 }
3822
3823 if (rm == rd)
3824 as_tsktsk (_("rd and rm should be different in mla"));
3825
3826 if (skip_past_comma (&str) == FAIL
3827 || (rd = reg_required_here (&str, 8)) == FAIL
3828 || skip_past_comma (&str) == FAIL
3829 || (rm = reg_required_here (&str, 12)) == FAIL)
3830 {
3831 inst.error = BAD_ARGS;
3832 return;
3833 }
3834
3835 if (rd == REG_PC || rm == REG_PC)
3836 {
3837 inst.error = BAD_PC;
3838 return;
3839 }
3840
3841 end_of_line (str);
3842 return;
3843 }
3844
3845 /* Expects *str -> the characters "acc0", possibly with leading blanks.
3846 Advances *str to the next non-alphanumeric.
3847 Returns 0, or else FAIL (in which case sets inst.error).
3848
3849 (In a future XScale, there may be accumulators other than zero.
3850 At that time this routine and its callers can be upgraded to suit.) */
3851
3852 static int
3853 accum0_required_here (str)
3854 char ** str;
3855 {
3856 static char buff [128]; /* Note the address is taken. Hence, static. */
3857 char * p = * str;
3858 char c;
3859 int result = 0; /* The accum number. */
3860
3861 skip_whitespace (p);
3862
3863 *str = p; /* Advance caller's string pointer too. */
3864 c = *p++;
3865 while (ISALNUM (c))
3866 c = *p++;
3867
3868 *--p = 0; /* Aap nul into input buffer at non-alnum. */
3869
3870 if (! ( streq (*str, "acc0") || streq (*str, "ACC0")))
3871 {
3872 sprintf (buff, _("acc0 expected, not '%.100s'"), *str);
3873 inst.error = buff;
3874 result = FAIL;
3875 }
3876
3877 *p = c; /* Unzap. */
3878 *str = p; /* Caller's string pointer to after match. */
3879 return result;
3880 }
3881
3882 /* Expects **str -> after a comma. May be leading blanks.
3883 Advances *str, recognizing a load mode, and setting inst.instruction.
3884 Returns rn, or else FAIL (in which case may set inst.error
3885 and not advance str)
3886
3887 Note: doesn't know Rd, so no err checks that require such knowledge. */
3888
3889 static int
3890 ld_mode_required_here (string)
3891 char ** string;
3892 {
3893 char * str = * string;
3894 int rn;
3895 int pre_inc = 0;
3896
3897 skip_whitespace (str);
3898
3899 if (* str == '[')
3900 {
3901 str++;
3902
3903 skip_whitespace (str);
3904
3905 if ((rn = reg_required_here (& str, 16)) == FAIL)
3906 return FAIL;
3907
3908 skip_whitespace (str);
3909
3910 if (* str == ']')
3911 {
3912 str ++;
3913
3914 if (skip_past_comma (& str) == SUCCESS)
3915 {
3916 /* [Rn],... (post inc) */
3917 if (ldst_extend_v4 (&str) == FAIL)
3918 return FAIL;
3919 }
3920 else /* [Rn] */
3921 {
3922 skip_whitespace (str);
3923
3924 if (* str == '!')
3925 {
3926 str ++;
3927 inst.instruction |= WRITE_BACK;
3928 }
3929
3930 inst.instruction |= INDEX_UP | HWOFFSET_IMM;
3931 pre_inc = 1;
3932 }
3933 }
3934 else /* [Rn,...] */
3935 {
3936 if (skip_past_comma (& str) == FAIL)
3937 {
3938 inst.error = _("pre-indexed expression expected");
3939 return FAIL;
3940 }
3941
3942 pre_inc = 1;
3943
3944 if (ldst_extend_v4 (&str) == FAIL)
3945 return FAIL;
3946
3947 skip_whitespace (str);
3948
3949 if (* str ++ != ']')
3950 {
3951 inst.error = _("missing ]");
3952 return FAIL;
3953 }
3954
3955 skip_whitespace (str);
3956
3957 if (* str == '!')
3958 {
3959 str ++;
3960 inst.instruction |= WRITE_BACK;
3961 }
3962 }
3963 }
3964 else if (* str == '=') /* ldr's "r,=label" syntax */
3965 /* We should never reach here, because <text> = <expression> is
3966 caught gas/read.c read_a_source_file() as a .set operation. */
3967 return FAIL;
3968 else /* PC +- 8 bit immediate offset. */
3969 {
3970 if (my_get_expression (& inst.reloc.exp, & str))
3971 return FAIL;
3972
3973 inst.instruction |= HWOFFSET_IMM; /* The I bit. */
3974 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
3975 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
3976 inst.reloc.pc_rel = 1;
3977 inst.instruction |= (REG_PC << 16);
3978
3979 rn = REG_PC;
3980 pre_inc = 1;
3981 }
3982
3983 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
3984 * string = str;
3985
3986 return rn;
3987 }
3988
3989 /* ARM V5E (El Segundo) signed-multiply-accumulate (argument parse)
3990 SMLAxy{cond} Rd,Rm,Rs,Rn
3991 SMLAWy{cond} Rd,Rm,Rs,Rn
3992 Error if any register is R15. */
3993
3994 static void
3995 do_smla (str)
3996 char * str;
3997 {
3998 int rd, rm, rs, rn;
3999
4000 skip_whitespace (str);
4001
4002 if ((rd = reg_required_here (& str, 16)) == FAIL
4003 || skip_past_comma (& str) == FAIL
4004 || (rm = reg_required_here (& str, 0)) == FAIL
4005 || skip_past_comma (& str) == FAIL
4006 || (rs = reg_required_here (& str, 8)) == FAIL
4007 || skip_past_comma (& str) == FAIL
4008 || (rn = reg_required_here (& str, 12)) == FAIL)
4009 inst.error = BAD_ARGS;
4010
4011 else if (rd == REG_PC || rm == REG_PC || rs == REG_PC || rn == REG_PC)
4012 inst.error = BAD_PC;
4013
4014 else
4015 end_of_line (str);
4016 }
4017
4018 /* ARM V5E (El Segundo) signed-multiply-accumulate-long (argument parse)
4019 SMLALxy{cond} Rdlo,Rdhi,Rm,Rs
4020 Error if any register is R15.
4021 Warning if Rdlo == Rdhi. */
4022
4023 static void
4024 do_smlal (str)
4025 char * str;
4026 {
4027 int rdlo, rdhi, rm, rs;
4028
4029 skip_whitespace (str);
4030
4031 if ((rdlo = reg_required_here (& str, 12)) == FAIL
4032 || skip_past_comma (& str) == FAIL
4033 || (rdhi = reg_required_here (& str, 16)) == FAIL
4034 || skip_past_comma (& str) == FAIL
4035 || (rm = reg_required_here (& str, 0)) == FAIL
4036 || skip_past_comma (& str) == FAIL
4037 || (rs = reg_required_here (& str, 8)) == FAIL)
4038 {
4039 inst.error = BAD_ARGS;
4040 return;
4041 }
4042
4043 if (rdlo == REG_PC || rdhi == REG_PC || rm == REG_PC || rs == REG_PC)
4044 {
4045 inst.error = BAD_PC;
4046 return;
4047 }
4048
4049 if (rdlo == rdhi)
4050 as_tsktsk (_("rdhi and rdlo must be different"));
4051
4052 end_of_line (str);
4053 }
4054
4055 /* ARM V5E (El Segundo) signed-multiply (argument parse)
4056 SMULxy{cond} Rd,Rm,Rs
4057 Error if any register is R15. */
4058
4059 static void
4060 do_smul (str)
4061 char * str;
4062 {
4063 int rd, rm, rs;
4064
4065 skip_whitespace (str);
4066
4067 if ((rd = reg_required_here (& str, 16)) == FAIL
4068 || skip_past_comma (& str) == FAIL
4069 || (rm = reg_required_here (& str, 0)) == FAIL
4070 || skip_past_comma (& str) == FAIL
4071 || (rs = reg_required_here (& str, 8)) == FAIL)
4072 inst.error = BAD_ARGS;
4073
4074 else if (rd == REG_PC || rm == REG_PC || rs == REG_PC)
4075 inst.error = BAD_PC;
4076
4077 else
4078 end_of_line (str);
4079 }
4080
4081 /* ARM V5E (El Segundo) saturating-add/subtract (argument parse)
4082 Q[D]{ADD,SUB}{cond} Rd,Rm,Rn
4083 Error if any register is R15. */
4084
4085 static void
4086 do_qadd (str)
4087 char * str;
4088 {
4089 int rd, rm, rn;
4090
4091 skip_whitespace (str);
4092
4093 if ((rd = reg_required_here (& str, 12)) == FAIL
4094 || skip_past_comma (& str) == FAIL
4095 || (rm = reg_required_here (& str, 0)) == FAIL
4096 || skip_past_comma (& str) == FAIL
4097 || (rn = reg_required_here (& str, 16)) == FAIL)
4098 inst.error = BAD_ARGS;
4099
4100 else if (rd == REG_PC || rm == REG_PC || rn == REG_PC)
4101 inst.error = BAD_PC;
4102
4103 else
4104 end_of_line (str);
4105 }
4106
4107 /* ARM V5E (el Segundo)
4108 MCRRcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
4109 MRRCcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
4110
4111 These are equivalent to the XScale instructions MAR and MRA,
4112 respectively, when coproc == 0, opcode == 0, and CRm == 0.
4113
4114 Result unpredicatable if Rd or Rn is R15. */
4115
4116 static void
4117 do_co_reg2c (str)
4118 char * str;
4119 {
4120 int rd, rn;
4121
4122 skip_whitespace (str);
4123
4124 if (co_proc_number (& str) == FAIL)
4125 {
4126 if (!inst.error)
4127 inst.error = BAD_ARGS;
4128 return;
4129 }
4130
4131 if (skip_past_comma (& str) == FAIL
4132 || cp_opc_expr (& str, 4, 4) == FAIL)
4133 {
4134 if (!inst.error)
4135 inst.error = BAD_ARGS;
4136 return;
4137 }
4138
4139 if (skip_past_comma (& str) == FAIL
4140 || (rd = reg_required_here (& str, 12)) == FAIL)
4141 {
4142 if (!inst.error)
4143 inst.error = BAD_ARGS;
4144 return;
4145 }
4146
4147 if (skip_past_comma (& str) == FAIL
4148 || (rn = reg_required_here (& str, 16)) == FAIL)
4149 {
4150 if (!inst.error)
4151 inst.error = BAD_ARGS;
4152 return;
4153 }
4154
4155 /* Unpredictable result if rd or rn is R15. */
4156 if (rd == REG_PC || rn == REG_PC)
4157 as_tsktsk
4158 (_("Warning: instruction unpredictable when using r15"));
4159
4160 if (skip_past_comma (& str) == FAIL
4161 || cp_reg_required_here (& str, 0) == FAIL)
4162 {
4163 if (!inst.error)
4164 inst.error = BAD_ARGS;
4165 return;
4166 }
4167
4168 end_of_line (str);
4169 }
4170
4171 /* ARM V5 count-leading-zeroes instruction (argument parse)
4172 CLZ{<cond>} <Rd>, <Rm>
4173 Condition defaults to COND_ALWAYS.
4174 Error if Rd or Rm are R15. */
4175
4176 static void
4177 do_clz (str)
4178 char * str;
4179 {
4180 int rd, rm;
4181
4182 skip_whitespace (str);
4183
4184 if (((rd = reg_required_here (& str, 12)) == FAIL)
4185 || (skip_past_comma (& str) == FAIL)
4186 || ((rm = reg_required_here (& str, 0)) == FAIL))
4187 inst.error = BAD_ARGS;
4188
4189 else if (rd == REG_PC || rm == REG_PC )
4190 inst.error = BAD_PC;
4191
4192 else
4193 end_of_line (str);
4194 }
4195
4196 /* ARM V5 (argument parse)
4197 LDC2{L} <coproc>, <CRd>, <addressing mode>
4198 STC2{L} <coproc>, <CRd>, <addressing mode>
4199 Instruction is not conditional, and has 0xf in the codition field.
4200 Otherwise, it's the same as LDC/STC. */
4201
4202 static void
4203 do_lstc2 (str)
4204 char * str;
4205 {
4206 skip_whitespace (str);
4207
4208 if (co_proc_number (& str) == FAIL)
4209 {
4210 if (!inst.error)
4211 inst.error = BAD_ARGS;
4212 }
4213 else if (skip_past_comma (& str) == FAIL
4214 || cp_reg_required_here (& str, 12) == FAIL)
4215 {
4216 if (!inst.error)
4217 inst.error = BAD_ARGS;
4218 }
4219 else if (skip_past_comma (& str) == FAIL
4220 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
4221 {
4222 if (! inst.error)
4223 inst.error = BAD_ARGS;
4224 }
4225 else
4226 end_of_line (str);
4227 }
4228
4229 /* ARM V5 (argument parse)
4230 CDP2 <coproc>, <opcode_1>, <CRd>, <CRn>, <CRm>, <opcode_2>
4231 Instruction is not conditional, and has 0xf in the condition field.
4232 Otherwise, it's the same as CDP. */
4233
4234 static void
4235 do_cdp2 (str)
4236 char * str;
4237 {
4238 skip_whitespace (str);
4239
4240 if (co_proc_number (& str) == FAIL)
4241 {
4242 if (!inst.error)
4243 inst.error = BAD_ARGS;
4244 return;
4245 }
4246
4247 if (skip_past_comma (& str) == FAIL
4248 || cp_opc_expr (& str, 20,4) == FAIL)
4249 {
4250 if (!inst.error)
4251 inst.error = BAD_ARGS;
4252 return;
4253 }
4254
4255 if (skip_past_comma (& str) == FAIL
4256 || cp_reg_required_here (& str, 12) == FAIL)
4257 {
4258 if (!inst.error)
4259 inst.error = BAD_ARGS;
4260 return;
4261 }
4262
4263 if (skip_past_comma (& str) == FAIL
4264 || cp_reg_required_here (& str, 16) == FAIL)
4265 {
4266 if (!inst.error)
4267 inst.error = BAD_ARGS;
4268 return;
4269 }
4270
4271 if (skip_past_comma (& str) == FAIL
4272 || cp_reg_required_here (& str, 0) == FAIL)
4273 {
4274 if (!inst.error)
4275 inst.error = BAD_ARGS;
4276 return;
4277 }
4278
4279 if (skip_past_comma (& str) == SUCCESS)
4280 {
4281 if (cp_opc_expr (& str, 5, 3) == FAIL)
4282 {
4283 if (!inst.error)
4284 inst.error = BAD_ARGS;
4285 return;
4286 }
4287 }
4288
4289 end_of_line (str);
4290 }
4291
4292 /* ARM V5 (argument parse)
4293 MCR2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
4294 MRC2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
4295 Instruction is not conditional, and has 0xf in the condition field.
4296 Otherwise, it's the same as MCR/MRC. */
4297
4298 static void
4299 do_co_reg2 (str)
4300 char * str;
4301 {
4302 skip_whitespace (str);
4303
4304 if (co_proc_number (& str) == FAIL)
4305 {
4306 if (!inst.error)
4307 inst.error = BAD_ARGS;
4308 return;
4309 }
4310
4311 if (skip_past_comma (& str) == FAIL
4312 || cp_opc_expr (& str, 21, 3) == FAIL)
4313 {
4314 if (!inst.error)
4315 inst.error = BAD_ARGS;
4316 return;
4317 }
4318
4319 if (skip_past_comma (& str) == FAIL
4320 || reg_required_here (& str, 12) == FAIL)
4321 {
4322 if (!inst.error)
4323 inst.error = BAD_ARGS;
4324 return;
4325 }
4326
4327 if (skip_past_comma (& str) == FAIL
4328 || cp_reg_required_here (& str, 16) == FAIL)
4329 {
4330 if (!inst.error)
4331 inst.error = BAD_ARGS;
4332 return;
4333 }
4334
4335 if (skip_past_comma (& str) == FAIL
4336 || cp_reg_required_here (& str, 0) == FAIL)
4337 {
4338 if (!inst.error)
4339 inst.error = BAD_ARGS;
4340 return;
4341 }
4342
4343 if (skip_past_comma (& str) == SUCCESS)
4344 {
4345 if (cp_opc_expr (& str, 5, 3) == FAIL)
4346 {
4347 if (!inst.error)
4348 inst.error = BAD_ARGS;
4349 return;
4350 }
4351 }
4352
4353 end_of_line (str);
4354 }
4355
4356 /* ARM v5TEJ. Jump to Jazelle code. */
4357 static void
4358 do_bxj (str)
4359 char * str;
4360 {
4361 int reg;
4362
4363 skip_whitespace (str);
4364
4365 if ((reg = reg_required_here (&str, 0)) == FAIL)
4366 {
4367 inst.error = BAD_ARGS;
4368 return;
4369 }
4370
4371 /* Note - it is not illegal to do a "bxj pc". Useless, but not illegal. */
4372 if (reg == REG_PC)
4373 as_tsktsk (_("use of r15 in bxj is not really useful"));
4374
4375 end_of_line (str);
4376 }
4377
4378 /* THUMB V5 breakpoint instruction (argument parse)
4379 BKPT <immed_8>. */
4380
4381 static void
4382 do_t_bkpt (str)
4383 char * str;
4384 {
4385 expressionS expr;
4386 unsigned long number;
4387
4388 skip_whitespace (str);
4389
4390 /* Allow optional leading '#'. */
4391 if (is_immediate_prefix (*str))
4392 str ++;
4393
4394 memset (& expr, '\0', sizeof (expr));
4395 if (my_get_expression (& expr, & str)
4396 || (expr.X_op != O_constant
4397 /* As a convenience we allow 'bkpt' without an operand. */
4398 && expr.X_op != O_absent))
4399 {
4400 inst.error = _("bad expression");
4401 return;
4402 }
4403
4404 number = expr.X_add_number;
4405
4406 /* Check it fits an 8 bit unsigned. */
4407 if (number != (number & 0xff))
4408 {
4409 inst.error = _("immediate value out of range");
4410 return;
4411 }
4412
4413 inst.instruction |= number;
4414
4415 end_of_line (str);
4416 }
4417
4418 /* ARM V5 branch-link-exchange (argument parse) for BLX(1) only.
4419 Expects inst.instruction is set for BLX(1).
4420 Note: this is cloned from do_branch, and the reloc changed to be a
4421 new one that can cope with setting one extra bit (the H bit). */
4422
4423 static void
4424 do_branch25 (str)
4425 char * str;
4426 {
4427 if (my_get_expression (& inst.reloc.exp, & str))
4428 return;
4429
4430 #ifdef OBJ_ELF
4431 {
4432 char * save_in;
4433
4434 /* ScottB: February 5, 1998 */
4435 /* Check to see of PLT32 reloc required for the instruction. */
4436
4437 /* arm_parse_reloc() works on input_line_pointer.
4438 We actually want to parse the operands to the branch instruction
4439 passed in 'str'. Save the input pointer and restore it later. */
4440 save_in = input_line_pointer;
4441 input_line_pointer = str;
4442
4443 if (inst.reloc.exp.X_op == O_symbol
4444 && *str == '('
4445 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
4446 {
4447 inst.reloc.type = BFD_RELOC_ARM_PLT32;
4448 inst.reloc.pc_rel = 0;
4449 /* Modify str to point to after parsed operands, otherwise
4450 end_of_line() will complain about the (PLT) left in str. */
4451 str = input_line_pointer;
4452 }
4453 else
4454 {
4455 inst.reloc.type = BFD_RELOC_ARM_PCREL_BLX;
4456 inst.reloc.pc_rel = 1;
4457 }
4458
4459 input_line_pointer = save_in;
4460 }
4461 #else
4462 inst.reloc.type = BFD_RELOC_ARM_PCREL_BLX;
4463 inst.reloc.pc_rel = 1;
4464 #endif /* OBJ_ELF */
4465
4466 end_of_line (str);
4467 }
4468
4469 /* ARM V5 branch-link-exchange instruction (argument parse)
4470 BLX <target_addr> ie BLX(1)
4471 BLX{<condition>} <Rm> ie BLX(2)
4472 Unfortunately, there are two different opcodes for this mnemonic.
4473 So, the insns[].value is not used, and the code here zaps values
4474 into inst.instruction.
4475 Also, the <target_addr> can be 25 bits, hence has its own reloc. */
4476
4477 static void
4478 do_blx (str)
4479 char * str;
4480 {
4481 char * mystr = str;
4482 int rm;
4483
4484 skip_whitespace (mystr);
4485 rm = reg_required_here (& mystr, 0);
4486
4487 /* The above may set inst.error. Ignore his opinion. */
4488 inst.error = 0;
4489
4490 if (rm != FAIL)
4491 {
4492 /* Arg is a register.
4493 Use the condition code our caller put in inst.instruction.
4494 Pass ourselves off as a BX with a funny opcode. */
4495 inst.instruction |= 0x012fff30;
4496 do_bx (str);
4497 }
4498 else
4499 {
4500 /* This must be is BLX <target address>, no condition allowed. */
4501 if (inst.instruction != COND_ALWAYS)
4502 {
4503 inst.error = BAD_COND;
4504 return;
4505 }
4506
4507 inst.instruction = 0xfafffffe;
4508
4509 /* Process like a B/BL, but with a different reloc.
4510 Note that B/BL expecte fffffe, not 0, offset in the opcode table. */
4511 do_branch25 (str);
4512 }
4513 }
4514
4515 /* ARM V5 Thumb BLX (argument parse)
4516 BLX <target_addr> which is BLX(1)
4517 BLX <Rm> which is BLX(2)
4518 Unfortunately, there are two different opcodes for this mnemonic.
4519 So, the tinsns[].value is not used, and the code here zaps values
4520 into inst.instruction. */
4521
4522 static void
4523 do_t_blx (str)
4524 char * str;
4525 {
4526 char * mystr = str;
4527 int rm;
4528
4529 skip_whitespace (mystr);
4530 inst.instruction = 0x4780;
4531
4532 /* Note that this call is to the ARM register recognizer. BLX(2)
4533 uses the ARM register space, not the Thumb one, so a call to
4534 thumb_reg() would be wrong. */
4535 rm = reg_required_here (& mystr, 3);
4536 inst.error = 0;
4537
4538 if (rm != FAIL)
4539 {
4540 /* It's BLX(2). The .instruction was zapped with rm & is final. */
4541 inst.size = 2;
4542 }
4543 else
4544 {
4545 /* No ARM register. This must be BLX(1). Change the .instruction. */
4546 inst.instruction = 0xf7ffeffe;
4547 inst.size = 4;
4548
4549 if (my_get_expression (& inst.reloc.exp, & mystr))
4550 return;
4551
4552 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BLX;
4553 inst.reloc.pc_rel = 1;
4554 }
4555
4556 end_of_line (mystr);
4557 }
4558
4559 /* ARM V5 breakpoint instruction (argument parse)
4560 BKPT <16 bit unsigned immediate>
4561 Instruction is not conditional.
4562 The bit pattern given in insns[] has the COND_ALWAYS condition,
4563 and it is an error if the caller tried to override that. */
4564
4565 static void
4566 do_bkpt (str)
4567 char * str;
4568 {
4569 expressionS expr;
4570 unsigned long number;
4571
4572 skip_whitespace (str);
4573
4574 /* Allow optional leading '#'. */
4575 if (is_immediate_prefix (* str))
4576 str++;
4577
4578 memset (& expr, '\0', sizeof (expr));
4579
4580 if (my_get_expression (& expr, & str)
4581 || (expr.X_op != O_constant
4582 /* As a convenience we allow 'bkpt' without an operand. */
4583 && expr.X_op != O_absent))
4584 {
4585 inst.error = _("bad expression");
4586 return;
4587 }
4588
4589 number = expr.X_add_number;
4590
4591 /* Check it fits a 16 bit unsigned. */
4592 if (number != (number & 0xffff))
4593 {
4594 inst.error = _("immediate value out of range");
4595 return;
4596 }
4597
4598 /* Top 12 of 16 bits to bits 19:8. */
4599 inst.instruction |= (number & 0xfff0) << 4;
4600
4601 /* Bottom 4 of 16 bits to bits 3:0. */
4602 inst.instruction |= number & 0xf;
4603
4604 end_of_line (str);
4605 }
4606
4607 static unsigned long check_iwmmxt_insn PARAMS ((char *, enum iwmmxt_insn_type, int));
4608
4609 /* Parse INSN_TYPE insn STR having a possible IMMEDIATE_SIZE immediate. */
4610
4611 static unsigned long
4612 check_iwmmxt_insn (str, insn_type, immediate_size)
4613 char * str;
4614 enum iwmmxt_insn_type insn_type;
4615 int immediate_size;
4616 {
4617 int reg = 0;
4618 const char * inst_error;
4619 expressionS expr;
4620 unsigned long number;
4621
4622 inst_error = inst.error;
4623 if (!inst.error)
4624 inst.error = BAD_ARGS;
4625 skip_whitespace (str);
4626
4627 switch (insn_type)
4628 {
4629 case check_rd:
4630 if ((reg = reg_required_here (&str, 12)) == FAIL)
4631 return FAIL;
4632 break;
4633
4634 case check_wr:
4635 if ((wreg_required_here (&str, 0, IWMMXT_REG_WR)) == FAIL)
4636 return FAIL;
4637 break;
4638
4639 case check_wrwr:
4640 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
4641 || skip_past_comma (&str) == FAIL
4642 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL))
4643 return FAIL;
4644 break;
4645
4646 case check_wrwrwr:
4647 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
4648 || skip_past_comma (&str) == FAIL
4649 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
4650 || skip_past_comma (&str) == FAIL
4651 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL))
4652 return FAIL;
4653 break;
4654
4655 case check_wrwrwcg:
4656 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
4657 || skip_past_comma (&str) == FAIL
4658 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
4659 || skip_past_comma (&str) == FAIL
4660 || wreg_required_here (&str, 0, IWMMXT_REG_WCG) == FAIL))
4661 return FAIL;
4662 break;
4663
4664 case check_tbcst:
4665 if ((wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
4666 || skip_past_comma (&str) == FAIL
4667 || reg_required_here (&str, 12) == FAIL))
4668 return FAIL;
4669 break;
4670
4671 case check_tmovmsk:
4672 if ((reg_required_here (&str, 12) == FAIL
4673 || skip_past_comma (&str) == FAIL
4674 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL))
4675 return FAIL;
4676 break;
4677
4678 case check_tmia:
4679 if ((wreg_required_here (&str, 5, IWMMXT_REG_WR) == FAIL
4680 || skip_past_comma (&str) == FAIL
4681 || reg_required_here (&str, 0) == FAIL
4682 || skip_past_comma (&str) == FAIL
4683 || reg_required_here (&str, 12) == FAIL))
4684 return FAIL;
4685 break;
4686
4687 case check_tmcrr:
4688 if ((wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL
4689 || skip_past_comma (&str) == FAIL
4690 || reg_required_here (&str, 12) == FAIL
4691 || skip_past_comma (&str) == FAIL
4692 || reg_required_here (&str, 16) == FAIL))
4693 return FAIL;
4694 break;
4695
4696 case check_tmrrc:
4697 if ((reg_required_here (&str, 12) == FAIL
4698 || skip_past_comma (&str) == FAIL
4699 || reg_required_here (&str, 16) == FAIL
4700 || skip_past_comma (&str) == FAIL
4701 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL))
4702 return FAIL;
4703 break;
4704
4705 case check_tmcr:
4706 if ((wreg_required_here (&str, 16, IWMMXT_REG_WC) == FAIL
4707 || skip_past_comma (&str) == FAIL
4708 || reg_required_here (&str, 12) == FAIL))
4709 return FAIL;
4710 break;
4711
4712 case check_tmrc:
4713 if ((reg_required_here (&str, 12) == FAIL
4714 || skip_past_comma (&str) == FAIL
4715 || wreg_required_here (&str, 16, IWMMXT_REG_WC) == FAIL))
4716 return FAIL;
4717 break;
4718
4719 case check_tinsr:
4720 if ((wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
4721 || skip_past_comma (&str) == FAIL
4722 || reg_required_here (&str, 12) == FAIL
4723 || skip_past_comma (&str) == FAIL))
4724 return FAIL;
4725 break;
4726
4727 case check_textrc:
4728 if ((reg_required_here (&str, 12) == FAIL
4729 || skip_past_comma (&str) == FAIL))
4730 return FAIL;
4731 break;
4732
4733 case check_waligni:
4734 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
4735 || skip_past_comma (&str) == FAIL
4736 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
4737 || skip_past_comma (&str) == FAIL
4738 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL
4739 || skip_past_comma (&str) == FAIL))
4740 return FAIL;
4741 break;
4742
4743 case check_textrm:
4744 if ((reg_required_here (&str, 12) == FAIL
4745 || skip_past_comma (&str) == FAIL
4746 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
4747 || skip_past_comma (&str) == FAIL))
4748 return FAIL;
4749 break;
4750
4751 case check_wshufh:
4752 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
4753 || skip_past_comma (&str) == FAIL
4754 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
4755 || skip_past_comma (&str) == FAIL))
4756 return FAIL;
4757 break;
4758 }
4759
4760 if (immediate_size == 0)
4761 {
4762 end_of_line (str);
4763 inst.error = inst_error;
4764 return reg;
4765 }
4766 else
4767 {
4768 skip_whitespace (str);
4769
4770 /* Allow optional leading '#'. */
4771 if (is_immediate_prefix (* str))
4772 str++;
4773
4774 memset (& expr, '\0', sizeof (expr));
4775
4776 if (my_get_expression (& expr, & str) || (expr.X_op != O_constant))
4777 {
4778 inst.error = _("bad or missing expression");
4779 return FAIL;
4780 }
4781
4782 number = expr.X_add_number;
4783
4784 if (number != (number & immediate_size))
4785 {
4786 inst.error = _("immediate value out of range");
4787 return FAIL;
4788 }
4789 end_of_line (str);
4790 inst.error = inst_error;
4791 return number;
4792 }
4793 }
4794
4795 static void
4796 do_iwmmxt_byte_addr (str)
4797 char * str;
4798 {
4799 int op = (inst.instruction & 0x300) >> 8;
4800 int reg;
4801
4802 inst.instruction &= ~0x300;
4803 inst.instruction |= (op & 1) << 22 | (op & 2) << 7;
4804
4805 skip_whitespace (str);
4806
4807 if ((reg = wreg_required_here (&str, 12, IWMMXT_REG_WR_OR_WC)) == FAIL
4808 || skip_past_comma (& str) == FAIL
4809 || cp_byte_address_required_here (&str) == FAIL)
4810 {
4811 if (! inst.error)
4812 inst.error = BAD_ARGS;
4813 }
4814 else
4815 end_of_line (str);
4816
4817 if (wc_register (reg))
4818 {
4819 inst.instruction |= 0xf0000100;
4820 inst.instruction &= ~0x00400000;
4821 }
4822 }
4823
4824 static void
4825 do_iwmmxt_tandc (str)
4826 char * str;
4827 {
4828 int reg;
4829
4830 reg = check_iwmmxt_insn (str, check_rd, 0);
4831
4832 if (reg != REG_PC && !inst.error)
4833 inst.error = _("only r15 allowed here");
4834 return;
4835 }
4836
4837 static void
4838 do_iwmmxt_tbcst (str)
4839 char * str;
4840 {
4841 check_iwmmxt_insn (str, check_tbcst, 0);
4842
4843 return;
4844 }
4845
4846 static void
4847 do_iwmmxt_textrc (str)
4848 char * str;
4849 {
4850 unsigned long number;
4851
4852 if ((number = check_iwmmxt_insn (str, check_textrc, 7)) == (unsigned long) FAIL)
4853 return;
4854
4855 inst.instruction |= number & 0x7;
4856 return;
4857 }
4858
4859 static void
4860 do_iwmmxt_textrm (str)
4861 char * str;
4862 {
4863 unsigned long number;
4864
4865 if ((number = check_iwmmxt_insn (str, check_textrm, 7)) == (unsigned long) FAIL)
4866 return;
4867
4868 inst.instruction |= number & 0x7;
4869 }
4870
4871 static void
4872 do_iwmmxt_tinsr (str)
4873 char * str;
4874 {
4875 unsigned long number;
4876
4877 if ((number = check_iwmmxt_insn (str, check_tinsr, 7)) == (unsigned long) FAIL)
4878 return;
4879
4880 inst.instruction |= number & 0x7;
4881 return;
4882 }
4883
4884 static void
4885 do_iwmmxt_tmcr (str)
4886 char * str;
4887 {
4888 check_iwmmxt_insn (str, check_tmcr, 0);
4889
4890 return;
4891 }
4892
4893 static void
4894 do_iwmmxt_tmcrr (str)
4895 char * str;
4896 {
4897 check_iwmmxt_insn (str, check_tmcrr, 0);
4898
4899 return;
4900 }
4901
4902 static void
4903 do_iwmmxt_tmia (str)
4904 char * str;
4905 {
4906 check_iwmmxt_insn (str, check_tmia, 0);
4907
4908 return;
4909 }
4910
4911 static void
4912 do_iwmmxt_tmovmsk (str)
4913 char * str;
4914 {
4915 check_iwmmxt_insn (str, check_tmovmsk, 0);
4916
4917 return;
4918 }
4919
4920 static void
4921 do_iwmmxt_tmrc (str)
4922 char * str;
4923 {
4924 check_iwmmxt_insn (str, check_tmrc, 0);
4925
4926 return;
4927 }
4928
4929 static void
4930 do_iwmmxt_tmrrc (str)
4931 char * str;
4932 {
4933 check_iwmmxt_insn (str, check_tmrrc, 0);
4934
4935 return;
4936 }
4937
4938 static void
4939 do_iwmmxt_torc (str)
4940 char * str;
4941 {
4942 check_iwmmxt_insn (str, check_rd, 0);
4943 return;
4944 }
4945
4946 static void
4947 do_iwmmxt_waligni (str)
4948 char * str;
4949 {
4950 unsigned long number;
4951
4952 if ((number = check_iwmmxt_insn (str, check_waligni, 7)) == (unsigned long) FAIL)
4953 return;
4954
4955 inst.instruction |= ((number & 0x7) << 20);
4956 return;
4957 }
4958
4959 static void
4960 do_iwmmxt_wmov (str)
4961 char * str;
4962 {
4963 if (check_iwmmxt_insn (str, check_wrwr, 0) == (unsigned long) FAIL)
4964 return;
4965
4966 inst.instruction |= ((inst.instruction >> 16) & 0xf);
4967 return;
4968 }
4969
4970 static void
4971 do_iwmmxt_word_addr (str)
4972 char * str;
4973 {
4974 int op = (inst.instruction & 0x300) >> 8;
4975 int reg;
4976
4977 inst.instruction &= ~0x300;
4978 inst.instruction |= (op & 1) << 22 | (op & 2) << 7;
4979
4980 skip_whitespace (str);
4981
4982 if ((reg = wreg_required_here (&str, 12, IWMMXT_REG_WR_OR_WC)) == FAIL
4983 || skip_past_comma (& str) == FAIL
4984 || cp_address_required_here (& str, CP_WB_OK) == FAIL)
4985 {
4986 if (! inst.error)
4987 inst.error = BAD_ARGS;
4988 }
4989 else
4990 end_of_line (str);
4991
4992 if (wc_register (reg))
4993 {
4994 inst.instruction |= 0xf0000100;
4995 inst.instruction &= ~0x00400000;
4996 }
4997 }
4998
4999 static void
5000 do_iwmmxt_wrwr (str)
5001 char * str;
5002 {
5003 check_iwmmxt_insn (str, check_wrwr, 0);
5004
5005 return;
5006 }
5007
5008 static void
5009 do_iwmmxt_wrwrwcg (str)
5010 char * str;
5011 {
5012 check_iwmmxt_insn (str, check_wrwrwcg, 0);
5013
5014 return;
5015 }
5016
5017 static void
5018 do_iwmmxt_wrwrwr (str)
5019 char * str;
5020 {
5021 check_iwmmxt_insn (str, check_wrwrwr, 0);
5022
5023 return;
5024 }
5025
5026 static void
5027 do_iwmmxt_wshufh (str)
5028 char * str;
5029 {
5030 unsigned long number;
5031
5032 if ((number = check_iwmmxt_insn (str, check_wshufh, 0xff)) == (unsigned long) FAIL)
5033 return;
5034
5035 inst.instruction |= ((number & 0xf0) << 16) | (number & 0xf);
5036 return;
5037 }
5038
5039 static void
5040 do_iwmmxt_wzero (str)
5041 char * str;
5042 {
5043 if (check_iwmmxt_insn (str, check_wr, 0) == (unsigned long) FAIL)
5044 return;
5045
5046 inst.instruction |= ((inst.instruction & 0xf) << 12) | ((inst.instruction & 0xf) << 16);
5047 return;
5048 }
5049
5050 /* Xscale multiply-accumulate (argument parse)
5051 MIAcc acc0,Rm,Rs
5052 MIAPHcc acc0,Rm,Rs
5053 MIAxycc acc0,Rm,Rs. */
5054
5055 static void
5056 do_xsc_mia (str)
5057 char * str;
5058 {
5059 int rs;
5060 int rm;
5061
5062 if (accum0_required_here (& str) == FAIL)
5063 inst.error = ERR_NO_ACCUM;
5064
5065 else if (skip_past_comma (& str) == FAIL
5066 || (rm = reg_required_here (& str, 0)) == FAIL)
5067 inst.error = BAD_ARGS;
5068
5069 else if (skip_past_comma (& str) == FAIL
5070 || (rs = reg_required_here (& str, 12)) == FAIL)
5071 inst.error = BAD_ARGS;
5072
5073 /* inst.instruction has now been zapped with both rm and rs. */
5074 else if (rm == REG_PC || rs == REG_PC)
5075 inst.error = BAD_PC; /* Undefined result if rm or rs is R15. */
5076
5077 else
5078 end_of_line (str);
5079 }
5080
5081 /* Xscale move-accumulator-register (argument parse)
5082
5083 MARcc acc0,RdLo,RdHi. */
5084
5085 static void
5086 do_xsc_mar (str)
5087 char * str;
5088 {
5089 int rdlo, rdhi;
5090
5091 if (accum0_required_here (& str) == FAIL)
5092 inst.error = ERR_NO_ACCUM;
5093
5094 else if (skip_past_comma (& str) == FAIL
5095 || (rdlo = reg_required_here (& str, 12)) == FAIL)
5096 inst.error = BAD_ARGS;
5097
5098 else if (skip_past_comma (& str) == FAIL
5099 || (rdhi = reg_required_here (& str, 16)) == FAIL)
5100 inst.error = BAD_ARGS;
5101
5102 /* inst.instruction has now been zapped with both rdlo and rdhi. */
5103 else if (rdlo == REG_PC || rdhi == REG_PC)
5104 inst.error = BAD_PC; /* Undefined result if rdlo or rdhi is R15. */
5105
5106 else
5107 end_of_line (str);
5108 }
5109
5110 /* Xscale move-register-accumulator (argument parse)
5111
5112 MRAcc RdLo,RdHi,acc0. */
5113
5114 static void
5115 do_xsc_mra (str)
5116 char * str;
5117 {
5118 int rdlo;
5119 int rdhi;
5120
5121 skip_whitespace (str);
5122
5123 if ((rdlo = reg_required_here (& str, 12)) == FAIL)
5124 inst.error = BAD_ARGS;
5125
5126 else if (skip_past_comma (& str) == FAIL
5127 || (rdhi = reg_required_here (& str, 16)) == FAIL)
5128 inst.error = BAD_ARGS;
5129
5130 else if (skip_past_comma (& str) == FAIL
5131 || accum0_required_here (& str) == FAIL)
5132 inst.error = ERR_NO_ACCUM;
5133
5134 /* inst.instruction has now been zapped with both rdlo and rdhi. */
5135 else if (rdlo == rdhi)
5136 inst.error = BAD_ARGS; /* Undefined result if 2 writes to same reg. */
5137
5138 else if (rdlo == REG_PC || rdhi == REG_PC)
5139 inst.error = BAD_PC; /* Undefined result if rdlo or rdhi is R15. */
5140 else
5141 end_of_line (str);
5142 }
5143
5144 /* ARMv5TE: Preload-Cache
5145
5146 PLD <addr_mode>
5147
5148 Syntactically, like LDR with B=1, W=0, L=1. */
5149
5150 static void
5151 do_pld (str)
5152 char * str;
5153 {
5154 int rd;
5155
5156 skip_whitespace (str);
5157
5158 if (* str != '[')
5159 {
5160 inst.error = _("'[' expected after PLD mnemonic");
5161 return;
5162 }
5163
5164 ++str;
5165 skip_whitespace (str);
5166
5167 if ((rd = reg_required_here (& str, 16)) == FAIL)
5168 return;
5169
5170 skip_whitespace (str);
5171
5172 if (*str == ']')
5173 {
5174 /* [Rn], ... ? */
5175 ++str;
5176 skip_whitespace (str);
5177
5178 /* Post-indexed addressing is not allowed with PLD. */
5179 if (skip_past_comma (&str) == SUCCESS)
5180 {
5181 inst.error
5182 = _("post-indexed expression used in preload instruction");
5183 return;
5184 }
5185 else if (*str == '!') /* [Rn]! */
5186 {
5187 inst.error = _("writeback used in preload instruction");
5188 ++str;
5189 }
5190 else /* [Rn] */
5191 inst.instruction |= INDEX_UP | PRE_INDEX;
5192 }
5193 else /* [Rn, ...] */
5194 {
5195 if (skip_past_comma (& str) == FAIL)
5196 {
5197 inst.error = _("pre-indexed expression expected");
5198 return;
5199 }
5200
5201 if (ldst_extend (&str) == FAIL)
5202 return;
5203
5204 skip_whitespace (str);
5205
5206 if (* str != ']')
5207 {
5208 inst.error = _("missing ]");
5209 return;
5210 }
5211
5212 ++ str;
5213 skip_whitespace (str);
5214
5215 if (* str == '!') /* [Rn]! */
5216 {
5217 inst.error = _("writeback used in preload instruction");
5218 ++ str;
5219 }
5220
5221 inst.instruction |= PRE_INDEX;
5222 }
5223
5224 end_of_line (str);
5225 }
5226
5227 /* ARMv5TE load-consecutive (argument parse)
5228 Mode is like LDRH.
5229
5230 LDRccD R, mode
5231 STRccD R, mode. */
5232
5233 static void
5234 do_ldrd (str)
5235 char * str;
5236 {
5237 int rd;
5238 int rn;
5239
5240 skip_whitespace (str);
5241
5242 if ((rd = reg_required_here (& str, 12)) == FAIL)
5243 {
5244 inst.error = BAD_ARGS;
5245 return;
5246 }
5247
5248 if (skip_past_comma (& str) == FAIL
5249 || (rn = ld_mode_required_here (& str)) == FAIL)
5250 {
5251 if (!inst.error)
5252 inst.error = BAD_ARGS;
5253 return;
5254 }
5255
5256 /* inst.instruction has now been zapped with Rd and the addressing mode. */
5257 if (rd & 1) /* Unpredictable result if Rd is odd. */
5258 {
5259 inst.error = _("destination register must be even");
5260 return;
5261 }
5262
5263 if (rd == REG_LR)
5264 {
5265 inst.error = _("r14 not allowed here");
5266 return;
5267 }
5268
5269 if (((rd == rn) || (rd + 1 == rn))
5270 && ((inst.instruction & WRITE_BACK)
5271 || (!(inst.instruction & PRE_INDEX))))
5272 as_warn (_("pre/post-indexing used when modified address register is destination"));
5273
5274 /* For an index-register load, the index register must not overlap the
5275 destination (even if not write-back). */
5276 if ((inst.instruction & V4_STR_BIT) == 0
5277 && (inst.instruction & HWOFFSET_IMM) == 0)
5278 {
5279 int rm = inst.instruction & 0x0000000f;
5280
5281 if (rm == rd || (rm == rd + 1))
5282 as_warn (_("ldrd destination registers must not overlap index register"));
5283 }
5284
5285 end_of_line (str);
5286 }
5287
5288 /* Returns the index into fp_values of a floating point number,
5289 or -1 if not in the table. */
5290
5291 static int
5292 my_get_float_expression (str)
5293 char ** str;
5294 {
5295 LITTLENUM_TYPE words[MAX_LITTLENUMS];
5296 char * save_in;
5297 expressionS exp;
5298 int i;
5299 int j;
5300
5301 memset (words, 0, MAX_LITTLENUMS * sizeof (LITTLENUM_TYPE));
5302
5303 /* Look for a raw floating point number. */
5304 if ((save_in = atof_ieee (*str, 'x', words)) != NULL
5305 && is_end_of_line[(unsigned char) *save_in])
5306 {
5307 for (i = 0; i < NUM_FLOAT_VALS; i++)
5308 {
5309 for (j = 0; j < MAX_LITTLENUMS; j++)
5310 {
5311 if (words[j] != fp_values[i][j])
5312 break;
5313 }
5314
5315 if (j == MAX_LITTLENUMS)
5316 {
5317 *str = save_in;
5318 return i;
5319 }
5320 }
5321 }
5322
5323 /* Try and parse a more complex expression, this will probably fail
5324 unless the code uses a floating point prefix (eg "0f"). */
5325 save_in = input_line_pointer;
5326 input_line_pointer = *str;
5327 if (expression (&exp) == absolute_section
5328 && exp.X_op == O_big
5329 && exp.X_add_number < 0)
5330 {
5331 /* FIXME: 5 = X_PRECISION, should be #define'd where we can use it.
5332 Ditto for 15. */
5333 if (gen_to_words (words, 5, (long) 15) == 0)
5334 {
5335 for (i = 0; i < NUM_FLOAT_VALS; i++)
5336 {
5337 for (j = 0; j < MAX_LITTLENUMS; j++)
5338 {
5339 if (words[j] != fp_values[i][j])
5340 break;
5341 }
5342
5343 if (j == MAX_LITTLENUMS)
5344 {
5345 *str = input_line_pointer;
5346 input_line_pointer = save_in;
5347 return i;
5348 }
5349 }
5350 }
5351 }
5352
5353 *str = input_line_pointer;
5354 input_line_pointer = save_in;
5355 return -1;
5356 }
5357
5358 /* Return TRUE if anything in the expression is a bignum. */
5359
5360 static int
5361 walk_no_bignums (sp)
5362 symbolS * sp;
5363 {
5364 if (symbol_get_value_expression (sp)->X_op == O_big)
5365 return 1;
5366
5367 if (symbol_get_value_expression (sp)->X_add_symbol)
5368 {
5369 return (walk_no_bignums (symbol_get_value_expression (sp)->X_add_symbol)
5370 || (symbol_get_value_expression (sp)->X_op_symbol
5371 && walk_no_bignums (symbol_get_value_expression (sp)->X_op_symbol)));
5372 }
5373
5374 return 0;
5375 }
5376
5377 static int in_my_get_expression = 0;
5378
5379 static int
5380 my_get_expression (ep, str)
5381 expressionS * ep;
5382 char ** str;
5383 {
5384 char * save_in;
5385 segT seg;
5386
5387 save_in = input_line_pointer;
5388 input_line_pointer = *str;
5389 in_my_get_expression = 1;
5390 seg = expression (ep);
5391 in_my_get_expression = 0;
5392
5393 if (ep->X_op == O_illegal)
5394 {
5395 /* We found a bad expression in md_operand(). */
5396 *str = input_line_pointer;
5397 input_line_pointer = save_in;
5398 return 1;
5399 }
5400
5401 #ifdef OBJ_AOUT
5402 if (seg != absolute_section
5403 && seg != text_section
5404 && seg != data_section
5405 && seg != bss_section
5406 && seg != undefined_section)
5407 {
5408 inst.error = _("bad_segment");
5409 *str = input_line_pointer;
5410 input_line_pointer = save_in;
5411 return 1;
5412 }
5413 #endif
5414
5415 /* Get rid of any bignums now, so that we don't generate an error for which
5416 we can't establish a line number later on. Big numbers are never valid
5417 in instructions, which is where this routine is always called. */
5418 if (ep->X_op == O_big
5419 || (ep->X_add_symbol
5420 && (walk_no_bignums (ep->X_add_symbol)
5421 || (ep->X_op_symbol
5422 && walk_no_bignums (ep->X_op_symbol)))))
5423 {
5424 inst.error = _("invalid constant");
5425 *str = input_line_pointer;
5426 input_line_pointer = save_in;
5427 return 1;
5428 }
5429
5430 *str = input_line_pointer;
5431 input_line_pointer = save_in;
5432 return 0;
5433 }
5434
5435 /* We handle all bad expressions here, so that we can report the faulty
5436 instruction in the error message. */
5437 void
5438 md_operand (expr)
5439 expressionS *expr;
5440 {
5441 if (in_my_get_expression)
5442 {
5443 expr->X_op = O_illegal;
5444 if (inst.error == NULL)
5445 inst.error = _("bad expression");
5446 }
5447 }
5448
5449 /* UNRESTRICT should be one if <shift> <register> is permitted for this
5450 instruction. */
5451
5452 static int
5453 decode_shift (str, unrestrict)
5454 char ** str;
5455 int unrestrict;
5456 {
5457 const struct asm_shift_name * shift;
5458 char * p;
5459 char c;
5460
5461 skip_whitespace (* str);
5462
5463 for (p = * str; ISALPHA (* p); p ++)
5464 ;
5465
5466 if (p == * str)
5467 {
5468 inst.error = _("shift expression expected");
5469 return FAIL;
5470 }
5471
5472 c = * p;
5473 * p = '\0';
5474 shift = (const struct asm_shift_name *) hash_find (arm_shift_hsh, * str);
5475 * p = c;
5476
5477 if (shift == NULL)
5478 {
5479 inst.error = _("shift expression expected");
5480 return FAIL;
5481 }
5482
5483 assert (shift->properties->index == shift_properties[shift->properties->index].index);
5484
5485 if (shift->properties->index == SHIFT_RRX)
5486 {
5487 * str = p;
5488 inst.instruction |= shift->properties->bit_field;
5489 return SUCCESS;
5490 }
5491
5492 skip_whitespace (p);
5493
5494 if (unrestrict && reg_required_here (& p, 8) != FAIL)
5495 {
5496 inst.instruction |= shift->properties->bit_field | SHIFT_BY_REG;
5497 * str = p;
5498 return SUCCESS;
5499 }
5500 else if (! is_immediate_prefix (* p))
5501 {
5502 inst.error = (unrestrict
5503 ? _("shift requires register or #expression")
5504 : _("shift requires #expression"));
5505 * str = p;
5506 return FAIL;
5507 }
5508
5509 inst.error = NULL;
5510 p ++;
5511
5512 if (my_get_expression (& inst.reloc.exp, & p))
5513 return FAIL;
5514
5515 /* Validate some simple #expressions. */
5516 if (inst.reloc.exp.X_op == O_constant)
5517 {
5518 unsigned num = inst.reloc.exp.X_add_number;
5519
5520 /* Reject operations greater than 32. */
5521 if (num > 32
5522 /* Reject a shift of 0 unless the mode allows it. */
5523 || (num == 0 && shift->properties->allows_0 == 0)
5524 /* Reject a shift of 32 unless the mode allows it. */
5525 || (num == 32 && shift->properties->allows_32 == 0)
5526 )
5527 {
5528 /* As a special case we allow a shift of zero for
5529 modes that do not support it to be recoded as an
5530 logical shift left of zero (ie nothing). We warn
5531 about this though. */
5532 if (num == 0)
5533 {
5534 as_warn (_("shift of 0 ignored."));
5535 shift = & shift_names[0];
5536 assert (shift->properties->index == SHIFT_LSL);
5537 }
5538 else
5539 {
5540 inst.error = _("invalid immediate shift");
5541 return FAIL;
5542 }
5543 }
5544
5545 /* Shifts of 32 are encoded as 0, for those shifts that
5546 support it. */
5547 if (num == 32)
5548 num = 0;
5549
5550 inst.instruction |= (num << 7) | shift->properties->bit_field;
5551 }
5552 else
5553 {
5554 inst.reloc.type = BFD_RELOC_ARM_SHIFT_IMM;
5555 inst.reloc.pc_rel = 0;
5556 inst.instruction |= shift->properties->bit_field;
5557 }
5558
5559 * str = p;
5560 return SUCCESS;
5561 }
5562
5563 /* Do those data_ops which can take a negative immediate constant
5564 by altering the instuction. A bit of a hack really.
5565 MOV <-> MVN
5566 AND <-> BIC
5567 ADC <-> SBC
5568 by inverting the second operand, and
5569 ADD <-> SUB
5570 CMP <-> CMN
5571 by negating the second operand. */
5572
5573 static int
5574 negate_data_op (instruction, value)
5575 unsigned long * instruction;
5576 unsigned long value;
5577 {
5578 int op, new_inst;
5579 unsigned long negated, inverted;
5580
5581 negated = validate_immediate (-value);
5582 inverted = validate_immediate (~value);
5583
5584 op = (*instruction >> DATA_OP_SHIFT) & 0xf;
5585 switch (op)
5586 {
5587 /* First negates. */
5588 case OPCODE_SUB: /* ADD <-> SUB */
5589 new_inst = OPCODE_ADD;
5590 value = negated;
5591 break;
5592
5593 case OPCODE_ADD:
5594 new_inst = OPCODE_SUB;
5595 value = negated;
5596 break;
5597
5598 case OPCODE_CMP: /* CMP <-> CMN */
5599 new_inst = OPCODE_CMN;
5600 value = negated;
5601 break;
5602
5603 case OPCODE_CMN:
5604 new_inst = OPCODE_CMP;
5605 value = negated;
5606 break;
5607
5608 /* Now Inverted ops. */
5609 case OPCODE_MOV: /* MOV <-> MVN */
5610 new_inst = OPCODE_MVN;
5611 value = inverted;
5612 break;
5613
5614 case OPCODE_MVN:
5615 new_inst = OPCODE_MOV;
5616 value = inverted;
5617 break;
5618
5619 case OPCODE_AND: /* AND <-> BIC */
5620 new_inst = OPCODE_BIC;
5621 value = inverted;
5622 break;
5623
5624 case OPCODE_BIC:
5625 new_inst = OPCODE_AND;
5626 value = inverted;
5627 break;
5628
5629 case OPCODE_ADC: /* ADC <-> SBC */
5630 new_inst = OPCODE_SBC;
5631 value = inverted;
5632 break;
5633
5634 case OPCODE_SBC:
5635 new_inst = OPCODE_ADC;
5636 value = inverted;
5637 break;
5638
5639 /* We cannot do anything. */
5640 default:
5641 return FAIL;
5642 }
5643
5644 if (value == (unsigned) FAIL)
5645 return FAIL;
5646
5647 *instruction &= OPCODE_MASK;
5648 *instruction |= new_inst << DATA_OP_SHIFT;
5649 return value;
5650 }
5651
5652 static int
5653 data_op2 (str)
5654 char ** str;
5655 {
5656 int value;
5657 expressionS expr;
5658
5659 skip_whitespace (* str);
5660
5661 if (reg_required_here (str, 0) != FAIL)
5662 {
5663 if (skip_past_comma (str) == SUCCESS)
5664 /* Shift operation on register. */
5665 return decode_shift (str, NO_SHIFT_RESTRICT);
5666
5667 return SUCCESS;
5668 }
5669 else
5670 {
5671 /* Immediate expression. */
5672 if (is_immediate_prefix (**str))
5673 {
5674 (*str)++;
5675 inst.error = NULL;
5676
5677 if (my_get_expression (&inst.reloc.exp, str))
5678 return FAIL;
5679
5680 if (inst.reloc.exp.X_add_symbol)
5681 {
5682 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
5683 inst.reloc.pc_rel = 0;
5684 }
5685 else
5686 {
5687 if (skip_past_comma (str) == SUCCESS)
5688 {
5689 /* #x, y -- ie explicit rotation by Y. */
5690 if (my_get_expression (&expr, str))
5691 return FAIL;
5692
5693 if (expr.X_op != O_constant)
5694 {
5695 inst.error = _("constant expression expected");
5696 return FAIL;
5697 }
5698
5699 /* Rotate must be a multiple of 2. */
5700 if (((unsigned) expr.X_add_number) > 30
5701 || (expr.X_add_number & 1) != 0
5702 || ((unsigned) inst.reloc.exp.X_add_number) > 255)
5703 {
5704 inst.error = _("invalid constant");
5705 return FAIL;
5706 }
5707 inst.instruction |= INST_IMMEDIATE;
5708 inst.instruction |= inst.reloc.exp.X_add_number;
5709 inst.instruction |= expr.X_add_number << 7;
5710 return SUCCESS;
5711 }
5712
5713 /* Implicit rotation, select a suitable one. */
5714 value = validate_immediate (inst.reloc.exp.X_add_number);
5715
5716 if (value == FAIL)
5717 {
5718 /* Can't be done. Perhaps the code reads something like
5719 "add Rd, Rn, #-n", where "sub Rd, Rn, #n" would be OK. */
5720 if ((value = negate_data_op (&inst.instruction,
5721 inst.reloc.exp.X_add_number))
5722 == FAIL)
5723 {
5724 inst.error = _("invalid constant");
5725 return FAIL;
5726 }
5727 }
5728
5729 inst.instruction |= value;
5730 }
5731
5732 inst.instruction |= INST_IMMEDIATE;
5733 return SUCCESS;
5734 }
5735
5736 (*str)++;
5737 inst.error = _("register or shift expression expected");
5738 return FAIL;
5739 }
5740 }
5741
5742 static int
5743 fp_op2 (str)
5744 char ** str;
5745 {
5746 skip_whitespace (* str);
5747
5748 if (fp_reg_required_here (str, 0) != FAIL)
5749 return SUCCESS;
5750 else
5751 {
5752 /* Immediate expression. */
5753 if (*((*str)++) == '#')
5754 {
5755 int i;
5756
5757 inst.error = NULL;
5758
5759 skip_whitespace (* str);
5760
5761 /* First try and match exact strings, this is to guarantee
5762 that some formats will work even for cross assembly. */
5763
5764 for (i = 0; fp_const[i]; i++)
5765 {
5766 if (strncmp (*str, fp_const[i], strlen (fp_const[i])) == 0)
5767 {
5768 char *start = *str;
5769
5770 *str += strlen (fp_const[i]);
5771 if (is_end_of_line[(unsigned char) **str])
5772 {
5773 inst.instruction |= i + 8;
5774 return SUCCESS;
5775 }
5776 *str = start;
5777 }
5778 }
5779
5780 /* Just because we didn't get a match doesn't mean that the
5781 constant isn't valid, just that it is in a format that we
5782 don't automatically recognize. Try parsing it with
5783 the standard expression routines. */
5784 if ((i = my_get_float_expression (str)) >= 0)
5785 {
5786 inst.instruction |= i + 8;
5787 return SUCCESS;
5788 }
5789
5790 inst.error = _("invalid floating point immediate expression");
5791 return FAIL;
5792 }
5793 inst.error =
5794 _("floating point register or immediate expression expected");
5795 return FAIL;
5796 }
5797 }
5798
5799 static void
5800 do_arit (str)
5801 char * str;
5802 {
5803 skip_whitespace (str);
5804
5805 if (reg_required_here (&str, 12) == FAIL
5806 || skip_past_comma (&str) == FAIL
5807 || reg_required_here (&str, 16) == FAIL
5808 || skip_past_comma (&str) == FAIL
5809 || data_op2 (&str) == FAIL)
5810 {
5811 if (!inst.error)
5812 inst.error = BAD_ARGS;
5813 return;
5814 }
5815
5816 end_of_line (str);
5817 return;
5818 }
5819
5820 static void
5821 do_adr (str)
5822 char * str;
5823 {
5824 /* This is a pseudo-op of the form "adr rd, label" to be converted
5825 into a relative address of the form "add rd, pc, #label-.-8". */
5826 skip_whitespace (str);
5827
5828 if (reg_required_here (&str, 12) == FAIL
5829 || skip_past_comma (&str) == FAIL
5830 || my_get_expression (&inst.reloc.exp, &str))
5831 {
5832 if (!inst.error)
5833 inst.error = BAD_ARGS;
5834 return;
5835 }
5836
5837 /* Frag hacking will turn this into a sub instruction if the offset turns
5838 out to be negative. */
5839 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
5840 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust. */
5841 inst.reloc.pc_rel = 1;
5842
5843 end_of_line (str);
5844 }
5845
5846 static void
5847 do_adrl (str)
5848 char * str;
5849 {
5850 /* This is a pseudo-op of the form "adrl rd, label" to be converted
5851 into a relative address of the form:
5852 add rd, pc, #low(label-.-8)"
5853 add rd, rd, #high(label-.-8)" */
5854
5855 skip_whitespace (str);
5856
5857 if (reg_required_here (&str, 12) == FAIL
5858 || skip_past_comma (&str) == FAIL
5859 || my_get_expression (&inst.reloc.exp, &str))
5860 {
5861 if (!inst.error)
5862 inst.error = BAD_ARGS;
5863
5864 return;
5865 }
5866
5867 end_of_line (str);
5868 /* Frag hacking will turn this into a sub instruction if the offset turns
5869 out to be negative. */
5870 inst.reloc.type = BFD_RELOC_ARM_ADRL_IMMEDIATE;
5871 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust */
5872 inst.reloc.pc_rel = 1;
5873 inst.size = INSN_SIZE * 2;
5874
5875 return;
5876 }
5877
5878 static void
5879 do_cmp (str)
5880 char * str;
5881 {
5882 skip_whitespace (str);
5883
5884 if (reg_required_here (&str, 16) == FAIL)
5885 {
5886 if (!inst.error)
5887 inst.error = BAD_ARGS;
5888 return;
5889 }
5890
5891 if (skip_past_comma (&str) == FAIL
5892 || data_op2 (&str) == FAIL)
5893 {
5894 if (!inst.error)
5895 inst.error = BAD_ARGS;
5896 return;
5897 }
5898
5899 end_of_line (str);
5900 return;
5901 }
5902
5903 static void
5904 do_mov (str)
5905 char * str;
5906 {
5907 skip_whitespace (str);
5908
5909 if (reg_required_here (&str, 12) == FAIL)
5910 {
5911 if (!inst.error)
5912 inst.error = BAD_ARGS;
5913 return;
5914 }
5915
5916 if (skip_past_comma (&str) == FAIL
5917 || data_op2 (&str) == FAIL)
5918 {
5919 if (!inst.error)
5920 inst.error = BAD_ARGS;
5921 return;
5922 }
5923
5924 end_of_line (str);
5925 return;
5926 }
5927
5928 static int
5929 ldst_extend (str)
5930 char ** str;
5931 {
5932 int add = INDEX_UP;
5933
5934 switch (**str)
5935 {
5936 case '#':
5937 case '$':
5938 (*str)++;
5939 if (my_get_expression (& inst.reloc.exp, str))
5940 return FAIL;
5941
5942 if (inst.reloc.exp.X_op == O_constant)
5943 {
5944 int value = inst.reloc.exp.X_add_number;
5945
5946 if (value < -4095 || value > 4095)
5947 {
5948 inst.error = _("address offset too large");
5949 return FAIL;
5950 }
5951
5952 if (value < 0)
5953 {
5954 value = -value;
5955 add = 0;
5956 }
5957
5958 inst.instruction |= add | value;
5959 }
5960 else
5961 {
5962 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
5963 inst.reloc.pc_rel = 0;
5964 }
5965 return SUCCESS;
5966
5967 case '-':
5968 add = 0;
5969 /* Fall through. */
5970
5971 case '+':
5972 (*str)++;
5973 /* Fall through. */
5974
5975 default:
5976 if (reg_required_here (str, 0) == FAIL)
5977 return FAIL;
5978
5979 inst.instruction |= add | OFFSET_REG;
5980 if (skip_past_comma (str) == SUCCESS)
5981 return decode_shift (str, SHIFT_RESTRICT);
5982
5983 return SUCCESS;
5984 }
5985 }
5986
5987 static void
5988 do_ldst (str)
5989 char * str;
5990 {
5991 int pre_inc = 0;
5992 int conflict_reg;
5993 int value;
5994
5995 skip_whitespace (str);
5996
5997 if ((conflict_reg = reg_required_here (&str, 12)) == FAIL)
5998 {
5999 if (!inst.error)
6000 inst.error = BAD_ARGS;
6001 return;
6002 }
6003
6004 if (skip_past_comma (&str) == FAIL)
6005 {
6006 inst.error = _("address expected");
6007 return;
6008 }
6009
6010 if (*str == '[')
6011 {
6012 int reg;
6013
6014 str++;
6015
6016 skip_whitespace (str);
6017
6018 if ((reg = reg_required_here (&str, 16)) == FAIL)
6019 return;
6020
6021 /* Conflicts can occur on stores as well as loads. */
6022 conflict_reg = (conflict_reg == reg);
6023
6024 skip_whitespace (str);
6025
6026 if (*str == ']')
6027 {
6028 str ++;
6029
6030 if (skip_past_comma (&str) == SUCCESS)
6031 {
6032 /* [Rn],... (post inc) */
6033 if (ldst_extend (&str) == FAIL)
6034 return;
6035 if (conflict_reg)
6036 as_warn (_("%s register same as write-back base"),
6037 ((inst.instruction & LOAD_BIT)
6038 ? _("destination") : _("source")));
6039 }
6040 else
6041 {
6042 /* [Rn] */
6043 skip_whitespace (str);
6044
6045 if (*str == '!')
6046 {
6047 if (conflict_reg)
6048 as_warn (_("%s register same as write-back base"),
6049 ((inst.instruction & LOAD_BIT)
6050 ? _("destination") : _("source")));
6051 str++;
6052 inst.instruction |= WRITE_BACK;
6053 }
6054
6055 inst.instruction |= INDEX_UP;
6056 pre_inc = 1;
6057 }
6058 }
6059 else
6060 {
6061 /* [Rn,...] */
6062 if (skip_past_comma (&str) == FAIL)
6063 {
6064 inst.error = _("pre-indexed expression expected");
6065 return;
6066 }
6067
6068 pre_inc = 1;
6069 if (ldst_extend (&str) == FAIL)
6070 return;
6071
6072 skip_whitespace (str);
6073
6074 if (*str++ != ']')
6075 {
6076 inst.error = _("missing ]");
6077 return;
6078 }
6079
6080 skip_whitespace (str);
6081
6082 if (*str == '!')
6083 {
6084 if (conflict_reg)
6085 as_warn (_("%s register same as write-back base"),
6086 ((inst.instruction & LOAD_BIT)
6087 ? _("destination") : _("source")));
6088 str++;
6089 inst.instruction |= WRITE_BACK;
6090 }
6091 }
6092 }
6093 else if (*str == '=')
6094 {
6095 if ((inst.instruction & LOAD_BIT) == 0)
6096 {
6097 inst.error = _("invalid pseudo operation");
6098 return;
6099 }
6100
6101 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
6102 str++;
6103
6104 skip_whitespace (str);
6105
6106 if (my_get_expression (&inst.reloc.exp, &str))
6107 return;
6108
6109 if (inst.reloc.exp.X_op != O_constant
6110 && inst.reloc.exp.X_op != O_symbol)
6111 {
6112 inst.error = _("constant expression expected");
6113 return;
6114 }
6115
6116 if (inst.reloc.exp.X_op == O_constant)
6117 {
6118 value = validate_immediate (inst.reloc.exp.X_add_number);
6119
6120 if (value != FAIL)
6121 {
6122 /* This can be done with a mov instruction. */
6123 inst.instruction &= LITERAL_MASK;
6124 inst.instruction |= (INST_IMMEDIATE
6125 | (OPCODE_MOV << DATA_OP_SHIFT));
6126 inst.instruction |= value & 0xfff;
6127 end_of_line (str);
6128 return;
6129 }
6130
6131 value = validate_immediate (~inst.reloc.exp.X_add_number);
6132
6133 if (value != FAIL)
6134 {
6135 /* This can be done with a mvn instruction. */
6136 inst.instruction &= LITERAL_MASK;
6137 inst.instruction |= (INST_IMMEDIATE
6138 | (OPCODE_MVN << DATA_OP_SHIFT));
6139 inst.instruction |= value & 0xfff;
6140 end_of_line (str);
6141 return;
6142 }
6143 }
6144
6145 /* Insert into literal pool. */
6146 if (add_to_lit_pool () == FAIL)
6147 {
6148 if (!inst.error)
6149 inst.error = _("literal pool insertion failed");
6150 return;
6151 }
6152
6153 /* Change the instruction exp to point to the pool. */
6154 inst.reloc.type = BFD_RELOC_ARM_LITERAL;
6155 inst.reloc.pc_rel = 1;
6156 inst.instruction |= (REG_PC << 16);
6157 pre_inc = 1;
6158 }
6159 else
6160 {
6161 if (my_get_expression (&inst.reloc.exp, &str))
6162 return;
6163
6164 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
6165 #ifndef TE_WINCE
6166 /* PC rel adjust. */
6167 inst.reloc.exp.X_add_number -= 8;
6168 #endif
6169 inst.reloc.pc_rel = 1;
6170 inst.instruction |= (REG_PC << 16);
6171 pre_inc = 1;
6172 }
6173
6174 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
6175 end_of_line (str);
6176 return;
6177 }
6178
6179 static void
6180 do_ldstt (str)
6181 char * str;
6182 {
6183 int conflict_reg;
6184
6185 skip_whitespace (str);
6186
6187 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
6188 {
6189 if (!inst.error)
6190 inst.error = BAD_ARGS;
6191 return;
6192 }
6193
6194 if (skip_past_comma (& str) == FAIL)
6195 {
6196 inst.error = _("address expected");
6197 return;
6198 }
6199
6200 if (*str == '[')
6201 {
6202 int reg;
6203
6204 str++;
6205
6206 skip_whitespace (str);
6207
6208 if ((reg = reg_required_here (&str, 16)) == FAIL)
6209 return;
6210
6211 /* ldrt/strt always use post-indexed addressing, so if the base is
6212 the same as Rd, we warn. */
6213 if (conflict_reg == reg)
6214 as_warn (_("%s register same as write-back base"),
6215 ((inst.instruction & LOAD_BIT)
6216 ? _("destination") : _("source")));
6217
6218 skip_whitespace (str);
6219
6220 if (*str == ']')
6221 {
6222 str ++;
6223
6224 if (skip_past_comma (&str) == SUCCESS)
6225 {
6226 /* [Rn],... (post inc) */
6227 if (ldst_extend (&str) == FAIL)
6228 return;
6229 }
6230 else
6231 {
6232 /* [Rn] */
6233 skip_whitespace (str);
6234
6235 /* Skip a write-back '!'. */
6236 if (*str == '!')
6237 str++;
6238
6239 inst.instruction |= INDEX_UP;
6240 }
6241 }
6242 else
6243 {
6244 inst.error = _("post-indexed expression expected");
6245 return;
6246 }
6247 }
6248 else
6249 {
6250 inst.error = _("post-indexed expression expected");
6251 return;
6252 }
6253
6254 end_of_line (str);
6255 return;
6256 }
6257
6258 static int
6259 ldst_extend_v4 (str)
6260 char ** str;
6261 {
6262 int add = INDEX_UP;
6263
6264 switch (**str)
6265 {
6266 case '#':
6267 case '$':
6268 (*str)++;
6269 if (my_get_expression (& inst.reloc.exp, str))
6270 return FAIL;
6271
6272 if (inst.reloc.exp.X_op == O_constant)
6273 {
6274 int value = inst.reloc.exp.X_add_number;
6275
6276 if (value < -255 || value > 255)
6277 {
6278 inst.error = _("address offset too large");
6279 return FAIL;
6280 }
6281
6282 if (value < 0)
6283 {
6284 value = -value;
6285 add = 0;
6286 }
6287
6288 /* Halfword and signextension instructions have the
6289 immediate value split across bits 11..8 and bits 3..0. */
6290 inst.instruction |= (add | HWOFFSET_IMM
6291 | ((value >> 4) << 8) | (value & 0xF));
6292 }
6293 else
6294 {
6295 inst.instruction |= HWOFFSET_IMM;
6296 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
6297 inst.reloc.pc_rel = 0;
6298 }
6299 return SUCCESS;
6300
6301 case '-':
6302 add = 0;
6303 /* Fall through. */
6304
6305 case '+':
6306 (*str)++;
6307 /* Fall through. */
6308
6309 default:
6310 if (reg_required_here (str, 0) == FAIL)
6311 return FAIL;
6312
6313 inst.instruction |= add;
6314 return SUCCESS;
6315 }
6316 }
6317
6318 /* Halfword and signed-byte load/store operations. */
6319 static void
6320 do_ldstv4 (str)
6321 char * str;
6322 {
6323 int pre_inc = 0;
6324 int conflict_reg;
6325 int value;
6326
6327 skip_whitespace (str);
6328
6329 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
6330 {
6331 if (!inst.error)
6332 inst.error = BAD_ARGS;
6333 return;
6334 }
6335
6336 if (skip_past_comma (& str) == FAIL)
6337 {
6338 inst.error = _("address expected");
6339 return;
6340 }
6341
6342 if (*str == '[')
6343 {
6344 int reg;
6345
6346 str++;
6347
6348 skip_whitespace (str);
6349
6350 if ((reg = reg_required_here (&str, 16)) == FAIL)
6351 return;
6352
6353 /* Conflicts can occur on stores as well as loads. */
6354 conflict_reg = (conflict_reg == reg);
6355
6356 skip_whitespace (str);
6357
6358 if (*str == ']')
6359 {
6360 str ++;
6361
6362 if (skip_past_comma (&str) == SUCCESS)
6363 {
6364 /* [Rn],... (post inc) */
6365 if (ldst_extend_v4 (&str) == FAIL)
6366 return;
6367 if (conflict_reg)
6368 as_warn (_("%s register same as write-back base"),
6369 ((inst.instruction & LOAD_BIT)
6370 ? _("destination") : _("source")));
6371 }
6372 else
6373 {
6374 /* [Rn] */
6375 inst.instruction |= HWOFFSET_IMM;
6376
6377 skip_whitespace (str);
6378
6379 if (*str == '!')
6380 {
6381 if (conflict_reg)
6382 as_warn (_("%s register same as write-back base"),
6383 ((inst.instruction & LOAD_BIT)
6384 ? _("destination") : _("source")));
6385 str++;
6386 inst.instruction |= WRITE_BACK;
6387 }
6388
6389 inst.instruction |= INDEX_UP;
6390 pre_inc = 1;
6391 }
6392 }
6393 else
6394 {
6395 /* [Rn,...] */
6396 if (skip_past_comma (&str) == FAIL)
6397 {
6398 inst.error = _("pre-indexed expression expected");
6399 return;
6400 }
6401
6402 pre_inc = 1;
6403 if (ldst_extend_v4 (&str) == FAIL)
6404 return;
6405
6406 skip_whitespace (str);
6407
6408 if (*str++ != ']')
6409 {
6410 inst.error = _("missing ]");
6411 return;
6412 }
6413
6414 skip_whitespace (str);
6415
6416 if (*str == '!')
6417 {
6418 if (conflict_reg)
6419 as_warn (_("%s register same as write-back base"),
6420 ((inst.instruction & LOAD_BIT)
6421 ? _("destination") : _("source")));
6422 str++;
6423 inst.instruction |= WRITE_BACK;
6424 }
6425 }
6426 }
6427 else if (*str == '=')
6428 {
6429 if ((inst.instruction & LOAD_BIT) == 0)
6430 {
6431 inst.error = _("invalid pseudo operation");
6432 return;
6433 }
6434
6435 /* XXX Does this work correctly for half-word/byte ops? */
6436 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
6437 str++;
6438
6439 skip_whitespace (str);
6440
6441 if (my_get_expression (&inst.reloc.exp, &str))
6442 return;
6443
6444 if (inst.reloc.exp.X_op != O_constant
6445 && inst.reloc.exp.X_op != O_symbol)
6446 {
6447 inst.error = _("constant expression expected");
6448 return;
6449 }
6450
6451 if (inst.reloc.exp.X_op == O_constant)
6452 {
6453 value = validate_immediate (inst.reloc.exp.X_add_number);
6454
6455 if (value != FAIL)
6456 {
6457 /* This can be done with a mov instruction. */
6458 inst.instruction &= LITERAL_MASK;
6459 inst.instruction |= INST_IMMEDIATE | (OPCODE_MOV << DATA_OP_SHIFT);
6460 inst.instruction |= value & 0xfff;
6461 end_of_line (str);
6462 return;
6463 }
6464
6465 value = validate_immediate (~ inst.reloc.exp.X_add_number);
6466
6467 if (value != FAIL)
6468 {
6469 /* This can be done with a mvn instruction. */
6470 inst.instruction &= LITERAL_MASK;
6471 inst.instruction |= INST_IMMEDIATE | (OPCODE_MVN << DATA_OP_SHIFT);
6472 inst.instruction |= value & 0xfff;
6473 end_of_line (str);
6474 return;
6475 }
6476 }
6477
6478 /* Insert into literal pool. */
6479 if (add_to_lit_pool () == FAIL)
6480 {
6481 if (!inst.error)
6482 inst.error = _("literal pool insertion failed");
6483 return;
6484 }
6485
6486 /* Change the instruction exp to point to the pool. */
6487 inst.instruction |= HWOFFSET_IMM;
6488 inst.reloc.type = BFD_RELOC_ARM_HWLITERAL;
6489 inst.reloc.pc_rel = 1;
6490 inst.instruction |= (REG_PC << 16);
6491 pre_inc = 1;
6492 }
6493 else
6494 {
6495 if (my_get_expression (&inst.reloc.exp, &str))
6496 return;
6497
6498 inst.instruction |= HWOFFSET_IMM;
6499 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
6500 #ifndef TE_WINCE
6501 /* PC rel adjust. */
6502 inst.reloc.exp.X_add_number -= 8;
6503 #endif
6504 inst.reloc.pc_rel = 1;
6505 inst.instruction |= (REG_PC << 16);
6506 pre_inc = 1;
6507 }
6508
6509 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
6510 end_of_line (str);
6511 return;
6512 }
6513
6514 static long
6515 reg_list (strp)
6516 char ** strp;
6517 {
6518 char * str = * strp;
6519 long range = 0;
6520 int another_range;
6521
6522 /* We come back here if we get ranges concatenated by '+' or '|'. */
6523 do
6524 {
6525 another_range = 0;
6526
6527 if (*str == '{')
6528 {
6529 int in_range = 0;
6530 int cur_reg = -1;
6531
6532 str++;
6533 do
6534 {
6535 int reg;
6536
6537 skip_whitespace (str);
6538
6539 if ((reg = reg_required_here (& str, -1)) == FAIL)
6540 return FAIL;
6541
6542 if (in_range)
6543 {
6544 int i;
6545
6546 if (reg <= cur_reg)
6547 {
6548 inst.error = _("bad range in register list");
6549 return FAIL;
6550 }
6551
6552 for (i = cur_reg + 1; i < reg; i++)
6553 {
6554 if (range & (1 << i))
6555 as_tsktsk
6556 (_("Warning: duplicated register (r%d) in register list"),
6557 i);
6558 else
6559 range |= 1 << i;
6560 }
6561 in_range = 0;
6562 }
6563
6564 if (range & (1 << reg))
6565 as_tsktsk (_("Warning: duplicated register (r%d) in register list"),
6566 reg);
6567 else if (reg <= cur_reg)
6568 as_tsktsk (_("Warning: register range not in ascending order"));
6569
6570 range |= 1 << reg;
6571 cur_reg = reg;
6572 }
6573 while (skip_past_comma (&str) != FAIL
6574 || (in_range = 1, *str++ == '-'));
6575 str--;
6576 skip_whitespace (str);
6577
6578 if (*str++ != '}')
6579 {
6580 inst.error = _("missing `}'");
6581 return FAIL;
6582 }
6583 }
6584 else
6585 {
6586 expressionS expr;
6587
6588 if (my_get_expression (&expr, &str))
6589 return FAIL;
6590
6591 if (expr.X_op == O_constant)
6592 {
6593 if (expr.X_add_number
6594 != (expr.X_add_number & 0x0000ffff))
6595 {
6596 inst.error = _("invalid register mask");
6597 return FAIL;
6598 }
6599
6600 if ((range & expr.X_add_number) != 0)
6601 {
6602 int regno = range & expr.X_add_number;
6603
6604 regno &= -regno;
6605 regno = (1 << regno) - 1;
6606 as_tsktsk
6607 (_("Warning: duplicated register (r%d) in register list"),
6608 regno);
6609 }
6610
6611 range |= expr.X_add_number;
6612 }
6613 else
6614 {
6615 if (inst.reloc.type != 0)
6616 {
6617 inst.error = _("expression too complex");
6618 return FAIL;
6619 }
6620
6621 memcpy (&inst.reloc.exp, &expr, sizeof (expressionS));
6622 inst.reloc.type = BFD_RELOC_ARM_MULTI;
6623 inst.reloc.pc_rel = 0;
6624 }
6625 }
6626
6627 skip_whitespace (str);
6628
6629 if (*str == '|' || *str == '+')
6630 {
6631 str++;
6632 another_range = 1;
6633 }
6634 }
6635 while (another_range);
6636
6637 *strp = str;
6638 return range;
6639 }
6640
6641 static void
6642 do_ldmstm (str)
6643 char * str;
6644 {
6645 int base_reg;
6646 long range;
6647
6648 skip_whitespace (str);
6649
6650 if ((base_reg = reg_required_here (&str, 16)) == FAIL)
6651 return;
6652
6653 if (base_reg == REG_PC)
6654 {
6655 inst.error = _("r15 not allowed as base register");
6656 return;
6657 }
6658
6659 skip_whitespace (str);
6660
6661 if (*str == '!')
6662 {
6663 inst.instruction |= WRITE_BACK;
6664 str++;
6665 }
6666
6667 if (skip_past_comma (&str) == FAIL
6668 || (range = reg_list (&str)) == FAIL)
6669 {
6670 if (! inst.error)
6671 inst.error = BAD_ARGS;
6672 return;
6673 }
6674
6675 if (*str == '^')
6676 {
6677 str++;
6678 inst.instruction |= LDM_TYPE_2_OR_3;
6679 }
6680
6681 if (inst.instruction & WRITE_BACK)
6682 {
6683 /* Check for unpredictable uses of writeback. */
6684 if (inst.instruction & LOAD_BIT)
6685 {
6686 /* Not allowed in LDM type 2. */
6687 if ((inst.instruction & LDM_TYPE_2_OR_3)
6688 && ((range & (1 << REG_PC)) == 0))
6689 as_warn (_("writeback of base register is UNPREDICTABLE"));
6690 /* Only allowed if base reg not in list for other types. */
6691 else if (range & (1 << base_reg))
6692 as_warn (_("writeback of base register when in register list is UNPREDICTABLE"));
6693 }
6694 else /* STM. */
6695 {
6696 /* Not allowed for type 2. */
6697 if (inst.instruction & LDM_TYPE_2_OR_3)
6698 as_warn (_("writeback of base register is UNPREDICTABLE"));
6699 /* Only allowed if base reg not in list, or first in list. */
6700 else if ((range & (1 << base_reg))
6701 && (range & ((1 << base_reg) - 1)))
6702 as_warn (_("if writeback register is in list, it must be the lowest reg in the list"));
6703 }
6704 }
6705
6706 inst.instruction |= range;
6707 end_of_line (str);
6708 return;
6709 }
6710
6711 static void
6712 do_swi (str)
6713 char * str;
6714 {
6715 skip_whitespace (str);
6716
6717 /* Allow optional leading '#'. */
6718 if (is_immediate_prefix (*str))
6719 str++;
6720
6721 if (my_get_expression (& inst.reloc.exp, & str))
6722 return;
6723
6724 inst.reloc.type = BFD_RELOC_ARM_SWI;
6725 inst.reloc.pc_rel = 0;
6726 end_of_line (str);
6727
6728 return;
6729 }
6730
6731 static void
6732 do_swap (str)
6733 char * str;
6734 {
6735 int reg;
6736
6737 skip_whitespace (str);
6738
6739 if ((reg = reg_required_here (&str, 12)) == FAIL)
6740 return;
6741
6742 if (reg == REG_PC)
6743 {
6744 inst.error = _("r15 not allowed in swap");
6745 return;
6746 }
6747
6748 if (skip_past_comma (&str) == FAIL
6749 || (reg = reg_required_here (&str, 0)) == FAIL)
6750 {
6751 if (!inst.error)
6752 inst.error = BAD_ARGS;
6753 return;
6754 }
6755
6756 if (reg == REG_PC)
6757 {
6758 inst.error = _("r15 not allowed in swap");
6759 return;
6760 }
6761
6762 if (skip_past_comma (&str) == FAIL
6763 || *str++ != '[')
6764 {
6765 inst.error = BAD_ARGS;
6766 return;
6767 }
6768
6769 skip_whitespace (str);
6770
6771 if ((reg = reg_required_here (&str, 16)) == FAIL)
6772 return;
6773
6774 if (reg == REG_PC)
6775 {
6776 inst.error = BAD_PC;
6777 return;
6778 }
6779
6780 skip_whitespace (str);
6781
6782 if (*str++ != ']')
6783 {
6784 inst.error = _("missing ]");
6785 return;
6786 }
6787
6788 end_of_line (str);
6789 return;
6790 }
6791
6792 static void
6793 do_branch (str)
6794 char * str;
6795 {
6796 if (my_get_expression (&inst.reloc.exp, &str))
6797 return;
6798
6799 #ifdef OBJ_ELF
6800 {
6801 char * save_in;
6802
6803 /* ScottB: February 5, 1998 - Check to see of PLT32 reloc
6804 required for the instruction. */
6805
6806 /* arm_parse_reloc () works on input_line_pointer.
6807 We actually want to parse the operands to the branch instruction
6808 passed in 'str'. Save the input pointer and restore it later. */
6809 save_in = input_line_pointer;
6810 input_line_pointer = str;
6811 if (inst.reloc.exp.X_op == O_symbol
6812 && *str == '('
6813 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
6814 {
6815 inst.reloc.type = BFD_RELOC_ARM_PLT32;
6816 inst.reloc.pc_rel = 0;
6817 /* Modify str to point to after parsed operands, otherwise
6818 end_of_line() will complain about the (PLT) left in str. */
6819 str = input_line_pointer;
6820 }
6821 else
6822 {
6823 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
6824 inst.reloc.pc_rel = 1;
6825 }
6826 input_line_pointer = save_in;
6827 }
6828 #else
6829 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
6830 inst.reloc.pc_rel = 1;
6831 #endif /* OBJ_ELF */
6832
6833 end_of_line (str);
6834 return;
6835 }
6836
6837 static void
6838 do_bx (str)
6839 char * str;
6840 {
6841 int reg;
6842
6843 skip_whitespace (str);
6844
6845 if ((reg = reg_required_here (&str, 0)) == FAIL)
6846 {
6847 inst.error = BAD_ARGS;
6848 return;
6849 }
6850
6851 /* Note - it is not illegal to do a "bx pc". Useless, but not illegal. */
6852 if (reg == REG_PC)
6853 as_tsktsk (_("use of r15 in bx in ARM mode is not really useful"));
6854
6855 end_of_line (str);
6856 }
6857
6858 static void
6859 do_cdp (str)
6860 char * str;
6861 {
6862 /* Co-processor data operation.
6863 Format: CDP{cond} CP#,<expr>,CRd,CRn,CRm{,<expr>} */
6864 skip_whitespace (str);
6865
6866 if (co_proc_number (&str) == FAIL)
6867 {
6868 if (!inst.error)
6869 inst.error = BAD_ARGS;
6870 return;
6871 }
6872
6873 if (skip_past_comma (&str) == FAIL
6874 || cp_opc_expr (&str, 20,4) == FAIL)
6875 {
6876 if (!inst.error)
6877 inst.error = BAD_ARGS;
6878 return;
6879 }
6880
6881 if (skip_past_comma (&str) == FAIL
6882 || cp_reg_required_here (&str, 12) == FAIL)
6883 {
6884 if (!inst.error)
6885 inst.error = BAD_ARGS;
6886 return;
6887 }
6888
6889 if (skip_past_comma (&str) == FAIL
6890 || cp_reg_required_here (&str, 16) == FAIL)
6891 {
6892 if (!inst.error)
6893 inst.error = BAD_ARGS;
6894 return;
6895 }
6896
6897 if (skip_past_comma (&str) == FAIL
6898 || cp_reg_required_here (&str, 0) == FAIL)
6899 {
6900 if (!inst.error)
6901 inst.error = BAD_ARGS;
6902 return;
6903 }
6904
6905 if (skip_past_comma (&str) == SUCCESS)
6906 {
6907 if (cp_opc_expr (&str, 5, 3) == FAIL)
6908 {
6909 if (!inst.error)
6910 inst.error = BAD_ARGS;
6911 return;
6912 }
6913 }
6914
6915 end_of_line (str);
6916 return;
6917 }
6918
6919 static void
6920 do_lstc (str)
6921 char * str;
6922 {
6923 /* Co-processor register load/store.
6924 Format: <LDC|STC{cond}[L] CP#,CRd,<address> */
6925
6926 skip_whitespace (str);
6927
6928 if (co_proc_number (&str) == FAIL)
6929 {
6930 if (!inst.error)
6931 inst.error = BAD_ARGS;
6932 return;
6933 }
6934
6935 if (skip_past_comma (&str) == FAIL
6936 || cp_reg_required_here (&str, 12) == FAIL)
6937 {
6938 if (!inst.error)
6939 inst.error = BAD_ARGS;
6940 return;
6941 }
6942
6943 if (skip_past_comma (&str) == FAIL
6944 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
6945 {
6946 if (! inst.error)
6947 inst.error = BAD_ARGS;
6948 return;
6949 }
6950
6951 end_of_line (str);
6952 return;
6953 }
6954
6955 static void
6956 do_co_reg (str)
6957 char * str;
6958 {
6959 /* Co-processor register transfer.
6960 Format: <MCR|MRC>{cond} CP#,<expr1>,Rd,CRn,CRm{,<expr2>} */
6961
6962 skip_whitespace (str);
6963
6964 if (co_proc_number (&str) == FAIL)
6965 {
6966 if (!inst.error)
6967 inst.error = BAD_ARGS;
6968 return;
6969 }
6970
6971 if (skip_past_comma (&str) == FAIL
6972 || cp_opc_expr (&str, 21, 3) == FAIL)
6973 {
6974 if (!inst.error)
6975 inst.error = BAD_ARGS;
6976 return;
6977 }
6978
6979 if (skip_past_comma (&str) == FAIL
6980 || reg_required_here (&str, 12) == FAIL)
6981 {
6982 if (!inst.error)
6983 inst.error = BAD_ARGS;
6984 return;
6985 }
6986
6987 if (skip_past_comma (&str) == FAIL
6988 || cp_reg_required_here (&str, 16) == FAIL)
6989 {
6990 if (!inst.error)
6991 inst.error = BAD_ARGS;
6992 return;
6993 }
6994
6995 if (skip_past_comma (&str) == FAIL
6996 || cp_reg_required_here (&str, 0) == FAIL)
6997 {
6998 if (!inst.error)
6999 inst.error = BAD_ARGS;
7000 return;
7001 }
7002
7003 if (skip_past_comma (&str) == SUCCESS)
7004 {
7005 if (cp_opc_expr (&str, 5, 3) == FAIL)
7006 {
7007 if (!inst.error)
7008 inst.error = BAD_ARGS;
7009 return;
7010 }
7011 }
7012
7013 end_of_line (str);
7014 return;
7015 }
7016
7017 static void
7018 do_fpa_ctrl (str)
7019 char * str;
7020 {
7021 /* FP control registers.
7022 Format: <WFS|RFS|WFC|RFC>{cond} Rn */
7023
7024 skip_whitespace (str);
7025
7026 if (reg_required_here (&str, 12) == FAIL)
7027 {
7028 if (!inst.error)
7029 inst.error = BAD_ARGS;
7030 return;
7031 }
7032
7033 end_of_line (str);
7034 return;
7035 }
7036
7037 static void
7038 do_fpa_ldst (str)
7039 char * str;
7040 {
7041 skip_whitespace (str);
7042
7043 if (fp_reg_required_here (&str, 12) == FAIL)
7044 {
7045 if (!inst.error)
7046 inst.error = BAD_ARGS;
7047 return;
7048 }
7049
7050 if (skip_past_comma (&str) == FAIL
7051 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
7052 {
7053 if (!inst.error)
7054 inst.error = BAD_ARGS;
7055 return;
7056 }
7057
7058 end_of_line (str);
7059 }
7060
7061 static void
7062 do_fpa_ldmstm (str)
7063 char * str;
7064 {
7065 int num_regs;
7066
7067 skip_whitespace (str);
7068
7069 if (fp_reg_required_here (&str, 12) == FAIL)
7070 {
7071 if (! inst.error)
7072 inst.error = BAD_ARGS;
7073 return;
7074 }
7075
7076 /* Get Number of registers to transfer. */
7077 if (skip_past_comma (&str) == FAIL
7078 || my_get_expression (&inst.reloc.exp, &str))
7079 {
7080 if (! inst.error)
7081 inst.error = _("constant expression expected");
7082 return;
7083 }
7084
7085 if (inst.reloc.exp.X_op != O_constant)
7086 {
7087 inst.error = _("constant value required for number of registers");
7088 return;
7089 }
7090
7091 num_regs = inst.reloc.exp.X_add_number;
7092
7093 if (num_regs < 1 || num_regs > 4)
7094 {
7095 inst.error = _("number of registers must be in the range [1:4]");
7096 return;
7097 }
7098
7099 switch (num_regs)
7100 {
7101 case 1:
7102 inst.instruction |= CP_T_X;
7103 break;
7104 case 2:
7105 inst.instruction |= CP_T_Y;
7106 break;
7107 case 3:
7108 inst.instruction |= CP_T_Y | CP_T_X;
7109 break;
7110 case 4:
7111 break;
7112 default:
7113 abort ();
7114 }
7115
7116 if (inst.instruction & (CP_T_Pre | CP_T_UD)) /* ea/fd format. */
7117 {
7118 int reg;
7119 int write_back;
7120 int offset;
7121
7122 /* The instruction specified "ea" or "fd", so we can only accept
7123 [Rn]{!}. The instruction does not really support stacking or
7124 unstacking, so we have to emulate these by setting appropriate
7125 bits and offsets. */
7126 if (skip_past_comma (&str) == FAIL
7127 || *str != '[')
7128 {
7129 if (! inst.error)
7130 inst.error = BAD_ARGS;
7131 return;
7132 }
7133
7134 str++;
7135 skip_whitespace (str);
7136
7137 if ((reg = reg_required_here (&str, 16)) == FAIL)
7138 return;
7139
7140 skip_whitespace (str);
7141
7142 if (*str != ']')
7143 {
7144 inst.error = BAD_ARGS;
7145 return;
7146 }
7147
7148 str++;
7149 if (*str == '!')
7150 {
7151 write_back = 1;
7152 str++;
7153 if (reg == REG_PC)
7154 {
7155 inst.error =
7156 _("r15 not allowed as base register with write-back");
7157 return;
7158 }
7159 }
7160 else
7161 write_back = 0;
7162
7163 if (inst.instruction & CP_T_Pre)
7164 {
7165 /* Pre-decrement. */
7166 offset = 3 * num_regs;
7167 if (write_back)
7168 inst.instruction |= CP_T_WB;
7169 }
7170 else
7171 {
7172 /* Post-increment. */
7173 if (write_back)
7174 {
7175 inst.instruction |= CP_T_WB;
7176 offset = 3 * num_regs;
7177 }
7178 else
7179 {
7180 /* No write-back, so convert this into a standard pre-increment
7181 instruction -- aesthetically more pleasing. */
7182 inst.instruction |= CP_T_Pre | CP_T_UD;
7183 offset = 0;
7184 }
7185 }
7186
7187 inst.instruction |= offset;
7188 }
7189 else if (skip_past_comma (&str) == FAIL
7190 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
7191 {
7192 if (! inst.error)
7193 inst.error = BAD_ARGS;
7194 return;
7195 }
7196
7197 end_of_line (str);
7198 }
7199
7200 static void
7201 do_fpa_dyadic (str)
7202 char * str;
7203 {
7204 skip_whitespace (str);
7205
7206 if (fp_reg_required_here (&str, 12) == FAIL)
7207 {
7208 if (! inst.error)
7209 inst.error = BAD_ARGS;
7210 return;
7211 }
7212
7213 if (skip_past_comma (&str) == FAIL
7214 || fp_reg_required_here (&str, 16) == FAIL)
7215 {
7216 if (! inst.error)
7217 inst.error = BAD_ARGS;
7218 return;
7219 }
7220
7221 if (skip_past_comma (&str) == FAIL
7222 || fp_op2 (&str) == FAIL)
7223 {
7224 if (! inst.error)
7225 inst.error = BAD_ARGS;
7226 return;
7227 }
7228
7229 end_of_line (str);
7230 return;
7231 }
7232
7233 static void
7234 do_fpa_monadic (str)
7235 char * str;
7236 {
7237 skip_whitespace (str);
7238
7239 if (fp_reg_required_here (&str, 12) == FAIL)
7240 {
7241 if (! inst.error)
7242 inst.error = BAD_ARGS;
7243 return;
7244 }
7245
7246 if (skip_past_comma (&str) == FAIL
7247 || fp_op2 (&str) == FAIL)
7248 {
7249 if (! inst.error)
7250 inst.error = BAD_ARGS;
7251 return;
7252 }
7253
7254 end_of_line (str);
7255 return;
7256 }
7257
7258 static void
7259 do_fpa_cmp (str)
7260 char * str;
7261 {
7262 skip_whitespace (str);
7263
7264 if (fp_reg_required_here (&str, 16) == FAIL)
7265 {
7266 if (! inst.error)
7267 inst.error = BAD_ARGS;
7268 return;
7269 }
7270
7271 if (skip_past_comma (&str) == FAIL
7272 || fp_op2 (&str) == FAIL)
7273 {
7274 if (! inst.error)
7275 inst.error = BAD_ARGS;
7276 return;
7277 }
7278
7279 end_of_line (str);
7280 return;
7281 }
7282
7283 static void
7284 do_fpa_from_reg (str)
7285 char * str;
7286 {
7287 skip_whitespace (str);
7288
7289 if (fp_reg_required_here (&str, 16) == FAIL)
7290 {
7291 if (! inst.error)
7292 inst.error = BAD_ARGS;
7293 return;
7294 }
7295
7296 if (skip_past_comma (&str) == FAIL
7297 || reg_required_here (&str, 12) == FAIL)
7298 {
7299 if (! inst.error)
7300 inst.error = BAD_ARGS;
7301 return;
7302 }
7303
7304 end_of_line (str);
7305 return;
7306 }
7307
7308 static void
7309 do_fpa_to_reg (str)
7310 char * str;
7311 {
7312 skip_whitespace (str);
7313
7314 if (reg_required_here (&str, 12) == FAIL)
7315 return;
7316
7317 if (skip_past_comma (&str) == FAIL
7318 || fp_reg_required_here (&str, 0) == FAIL)
7319 {
7320 if (! inst.error)
7321 inst.error = BAD_ARGS;
7322 return;
7323 }
7324
7325 end_of_line (str);
7326 return;
7327 }
7328
7329 static int
7330 vfp_sp_reg_required_here (str, pos)
7331 char **str;
7332 enum vfp_sp_reg_pos pos;
7333 {
7334 int reg;
7335 char *start = *str;
7336
7337 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_SN].htab)) != FAIL)
7338 {
7339 switch (pos)
7340 {
7341 case VFP_REG_Sd:
7342 inst.instruction |= ((reg >> 1) << 12) | ((reg & 1) << 22);
7343 break;
7344
7345 case VFP_REG_Sn:
7346 inst.instruction |= ((reg >> 1) << 16) | ((reg & 1) << 7);
7347 break;
7348
7349 case VFP_REG_Sm:
7350 inst.instruction |= ((reg >> 1) << 0) | ((reg & 1) << 5);
7351 break;
7352
7353 default:
7354 abort ();
7355 }
7356 return reg;
7357 }
7358
7359 /* In the few cases where we might be able to accept something else
7360 this error can be overridden. */
7361 inst.error = _(all_reg_maps[REG_TYPE_SN].expected);
7362
7363 /* Restore the start point. */
7364 *str = start;
7365 return FAIL;
7366 }
7367
7368 static int
7369 vfp_dp_reg_required_here (str, pos)
7370 char **str;
7371 enum vfp_dp_reg_pos pos;
7372 {
7373 int reg;
7374 char *start = *str;
7375
7376 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_DN].htab)) != FAIL)
7377 {
7378 switch (pos)
7379 {
7380 case VFP_REG_Dd:
7381 inst.instruction |= reg << 12;
7382 break;
7383
7384 case VFP_REG_Dn:
7385 inst.instruction |= reg << 16;
7386 break;
7387
7388 case VFP_REG_Dm:
7389 inst.instruction |= reg << 0;
7390 break;
7391
7392 default:
7393 abort ();
7394 }
7395 return reg;
7396 }
7397
7398 /* In the few cases where we might be able to accept something else
7399 this error can be overridden. */
7400 inst.error = _(all_reg_maps[REG_TYPE_DN].expected);
7401
7402 /* Restore the start point. */
7403 *str = start;
7404 return FAIL;
7405 }
7406
7407 static void
7408 do_vfp_sp_monadic (str)
7409 char *str;
7410 {
7411 skip_whitespace (str);
7412
7413 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
7414 return;
7415
7416 if (skip_past_comma (&str) == FAIL
7417 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
7418 {
7419 if (! inst.error)
7420 inst.error = BAD_ARGS;
7421 return;
7422 }
7423
7424 end_of_line (str);
7425 return;
7426 }
7427
7428 static void
7429 do_vfp_dp_monadic (str)
7430 char *str;
7431 {
7432 skip_whitespace (str);
7433
7434 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
7435 return;
7436
7437 if (skip_past_comma (&str) == FAIL
7438 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
7439 {
7440 if (! inst.error)
7441 inst.error = BAD_ARGS;
7442 return;
7443 }
7444
7445 end_of_line (str);
7446 return;
7447 }
7448
7449 static void
7450 do_vfp_sp_dyadic (str)
7451 char *str;
7452 {
7453 skip_whitespace (str);
7454
7455 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
7456 return;
7457
7458 if (skip_past_comma (&str) == FAIL
7459 || vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL
7460 || skip_past_comma (&str) == FAIL
7461 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
7462 {
7463 if (! inst.error)
7464 inst.error = BAD_ARGS;
7465 return;
7466 }
7467
7468 end_of_line (str);
7469 return;
7470 }
7471
7472 static void
7473 do_vfp_dp_dyadic (str)
7474 char *str;
7475 {
7476 skip_whitespace (str);
7477
7478 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
7479 return;
7480
7481 if (skip_past_comma (&str) == FAIL
7482 || vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL
7483 || skip_past_comma (&str) == FAIL
7484 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
7485 {
7486 if (! inst.error)
7487 inst.error = BAD_ARGS;
7488 return;
7489 }
7490
7491 end_of_line (str);
7492 return;
7493 }
7494
7495 static void
7496 do_vfp_reg_from_sp (str)
7497 char *str;
7498 {
7499 skip_whitespace (str);
7500
7501 if (reg_required_here (&str, 12) == FAIL)
7502 return;
7503
7504 if (skip_past_comma (&str) == FAIL
7505 || vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL)
7506 {
7507 if (! inst.error)
7508 inst.error = BAD_ARGS;
7509 return;
7510 }
7511
7512 end_of_line (str);
7513 return;
7514 }
7515
7516 static void
7517 do_vfp_sp_reg2 (str)
7518 char *str;
7519 {
7520 skip_whitespace (str);
7521
7522 if (reg_required_here (&str, 12) == FAIL)
7523 return;
7524
7525 if (skip_past_comma (&str) == FAIL
7526 || reg_required_here (&str, 16) == FAIL
7527 || skip_past_comma (&str) == FAIL)
7528 {
7529 if (! inst.error)
7530 inst.error = BAD_ARGS;
7531 return;
7532 }
7533
7534 /* We require exactly two consecutive SP registers. */
7535 if (vfp_sp_reg_list (&str, VFP_REG_Sm) != 2)
7536 {
7537 if (! inst.error)
7538 inst.error = _("only two consecutive VFP SP registers allowed here");
7539 }
7540
7541 end_of_line (str);
7542 return;
7543 }
7544
7545 static void
7546 do_vfp_sp_from_reg (str)
7547 char *str;
7548 {
7549 skip_whitespace (str);
7550
7551 if (vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL)
7552 return;
7553
7554 if (skip_past_comma (&str) == FAIL
7555 || reg_required_here (&str, 12) == FAIL)
7556 {
7557 if (! inst.error)
7558 inst.error = BAD_ARGS;
7559 return;
7560 }
7561
7562 end_of_line (str);
7563 return;
7564 }
7565
7566 static void
7567 do_vfp_reg_from_dp (str)
7568 char *str;
7569 {
7570 skip_whitespace (str);
7571
7572 if (reg_required_here (&str, 12) == FAIL)
7573 return;
7574
7575 if (skip_past_comma (&str) == FAIL
7576 || vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL)
7577 {
7578 if (! inst.error)
7579 inst.error = BAD_ARGS;
7580 return;
7581 }
7582
7583 end_of_line (str);
7584 return;
7585 }
7586
7587 static void
7588 do_vfp_reg2_from_dp (str)
7589 char *str;
7590 {
7591 skip_whitespace (str);
7592
7593 if (reg_required_here (&str, 12) == FAIL)
7594 return;
7595
7596 if (skip_past_comma (&str) == FAIL
7597 || reg_required_here (&str, 16) == FAIL
7598 || skip_past_comma (&str) == FAIL
7599 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
7600 {
7601 if (! inst.error)
7602 inst.error = BAD_ARGS;
7603 return;
7604 }
7605
7606 end_of_line (str);
7607 return;
7608 }
7609
7610 static void
7611 do_vfp_dp_from_reg (str)
7612 char *str;
7613 {
7614 skip_whitespace (str);
7615
7616 if (vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL)
7617 return;
7618
7619 if (skip_past_comma (&str) == FAIL
7620 || reg_required_here (&str, 12) == FAIL)
7621 {
7622 if (! inst.error)
7623 inst.error = BAD_ARGS;
7624 return;
7625 }
7626
7627 end_of_line (str);
7628 return;
7629 }
7630
7631 static void
7632 do_vfp_dp_from_reg2 (str)
7633 char *str;
7634 {
7635 skip_whitespace (str);
7636
7637 if (vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
7638 return;
7639
7640 if (skip_past_comma (&str) == FAIL
7641 || reg_required_here (&str, 12) == FAIL
7642 || skip_past_comma (&str) == FAIL
7643 || reg_required_here (&str, 16))
7644 {
7645 if (! inst.error)
7646 inst.error = BAD_ARGS;
7647 return;
7648 }
7649
7650 end_of_line (str);
7651 return;
7652 }
7653
7654 static const struct vfp_reg *
7655 vfp_psr_parse (str)
7656 char **str;
7657 {
7658 char *start = *str;
7659 char c;
7660 char *p;
7661 const struct vfp_reg *vreg;
7662
7663 p = start;
7664
7665 /* Find the end of the current token. */
7666 do
7667 {
7668 c = *p++;
7669 }
7670 while (ISALPHA (c));
7671
7672 /* Mark it. */
7673 *--p = 0;
7674
7675 for (vreg = vfp_regs + 0;
7676 vreg < vfp_regs + sizeof (vfp_regs) / sizeof (struct vfp_reg);
7677 vreg++)
7678 {
7679 if (strcmp (start, vreg->name) == 0)
7680 {
7681 *p = c;
7682 *str = p;
7683 return vreg;
7684 }
7685 }
7686
7687 *p = c;
7688 return NULL;
7689 }
7690
7691 static int
7692 vfp_psr_required_here (str)
7693 char **str;
7694 {
7695 char *start = *str;
7696 const struct vfp_reg *vreg;
7697
7698 vreg = vfp_psr_parse (str);
7699
7700 if (vreg)
7701 {
7702 inst.instruction |= vreg->regno;
7703 return SUCCESS;
7704 }
7705
7706 inst.error = _("VFP system register expected");
7707
7708 *str = start;
7709 return FAIL;
7710 }
7711
7712 static void
7713 do_vfp_reg_from_ctrl (str)
7714 char *str;
7715 {
7716 skip_whitespace (str);
7717
7718 if (reg_required_here (&str, 12) == FAIL)
7719 return;
7720
7721 if (skip_past_comma (&str) == FAIL
7722 || vfp_psr_required_here (&str) == FAIL)
7723 {
7724 if (! inst.error)
7725 inst.error = BAD_ARGS;
7726 return;
7727 }
7728
7729 end_of_line (str);
7730 return;
7731 }
7732
7733 static void
7734 do_vfp_ctrl_from_reg (str)
7735 char *str;
7736 {
7737 skip_whitespace (str);
7738
7739 if (vfp_psr_required_here (&str) == FAIL)
7740 return;
7741
7742 if (skip_past_comma (&str) == FAIL
7743 || reg_required_here (&str, 12) == FAIL)
7744 {
7745 if (! inst.error)
7746 inst.error = BAD_ARGS;
7747 return;
7748 }
7749
7750 end_of_line (str);
7751 return;
7752 }
7753
7754 static void
7755 do_vfp_sp_ldst (str)
7756 char *str;
7757 {
7758 skip_whitespace (str);
7759
7760 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
7761 {
7762 if (!inst.error)
7763 inst.error = BAD_ARGS;
7764 return;
7765 }
7766
7767 if (skip_past_comma (&str) == FAIL
7768 || cp_address_required_here (&str, CP_NO_WB) == FAIL)
7769 {
7770 if (!inst.error)
7771 inst.error = BAD_ARGS;
7772 return;
7773 }
7774
7775 end_of_line (str);
7776 return;
7777 }
7778
7779 static void
7780 do_vfp_dp_ldst (str)
7781 char *str;
7782 {
7783 skip_whitespace (str);
7784
7785 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
7786 {
7787 if (!inst.error)
7788 inst.error = BAD_ARGS;
7789 return;
7790 }
7791
7792 if (skip_past_comma (&str) == FAIL
7793 || cp_address_required_here (&str, CP_NO_WB) == FAIL)
7794 {
7795 if (!inst.error)
7796 inst.error = BAD_ARGS;
7797 return;
7798 }
7799
7800 end_of_line (str);
7801 return;
7802 }
7803
7804 /* Parse and encode a VFP SP register list, storing the initial
7805 register in position POS and returning the range as the result. If
7806 the string is invalid return FAIL (an invalid range). */
7807 static long
7808 vfp_sp_reg_list (str, pos)
7809 char **str;
7810 enum vfp_sp_reg_pos pos;
7811 {
7812 long range = 0;
7813 int base_reg = 0;
7814 int new_base;
7815 long base_bits = 0;
7816 int count = 0;
7817 long tempinst;
7818 unsigned long mask = 0;
7819 int warned = 0;
7820
7821 if (**str != '{')
7822 return FAIL;
7823
7824 (*str)++;
7825 skip_whitespace (*str);
7826
7827 tempinst = inst.instruction;
7828
7829 do
7830 {
7831 inst.instruction = 0;
7832
7833 if ((new_base = vfp_sp_reg_required_here (str, pos)) == FAIL)
7834 return FAIL;
7835
7836 if (count == 0 || base_reg > new_base)
7837 {
7838 base_reg = new_base;
7839 base_bits = inst.instruction;
7840 }
7841
7842 if (mask & (1 << new_base))
7843 {
7844 inst.error = _("invalid register list");
7845 return FAIL;
7846 }
7847
7848 if ((mask >> new_base) != 0 && ! warned)
7849 {
7850 as_tsktsk (_("register list not in ascending order"));
7851 warned = 1;
7852 }
7853
7854 mask |= 1 << new_base;
7855 count++;
7856
7857 skip_whitespace (*str);
7858
7859 if (**str == '-') /* We have the start of a range expression */
7860 {
7861 int high_range;
7862
7863 (*str)++;
7864
7865 if ((high_range
7866 = arm_reg_parse (str, all_reg_maps[REG_TYPE_SN].htab))
7867 == FAIL)
7868 {
7869 inst.error = _(all_reg_maps[REG_TYPE_SN].expected);
7870 return FAIL;
7871 }
7872
7873 if (high_range <= new_base)
7874 {
7875 inst.error = _("register range not in ascending order");
7876 return FAIL;
7877 }
7878
7879 for (new_base++; new_base <= high_range; new_base++)
7880 {
7881 if (mask & (1 << new_base))
7882 {
7883 inst.error = _("invalid register list");
7884 return FAIL;
7885 }
7886
7887 mask |= 1 << new_base;
7888 count++;
7889 }
7890 }
7891 }
7892 while (skip_past_comma (str) != FAIL);
7893
7894 if (**str != '}')
7895 {
7896 inst.error = _("invalid register list");
7897 return FAIL;
7898 }
7899
7900 (*str)++;
7901
7902 range = count;
7903
7904 /* Sanity check -- should have raised a parse error above. */
7905 if (count == 0 || count > 32)
7906 abort ();
7907
7908 /* Final test -- the registers must be consecutive. */
7909 while (count--)
7910 {
7911 if ((mask & (1 << base_reg++)) == 0)
7912 {
7913 inst.error = _("non-contiguous register range");
7914 return FAIL;
7915 }
7916 }
7917
7918 inst.instruction = tempinst | base_bits;
7919 return range;
7920 }
7921
7922 static long
7923 vfp_dp_reg_list (str)
7924 char **str;
7925 {
7926 long range = 0;
7927 int base_reg = 0;
7928 int new_base;
7929 int count = 0;
7930 long tempinst;
7931 unsigned long mask = 0;
7932 int warned = 0;
7933
7934 if (**str != '{')
7935 return FAIL;
7936
7937 (*str)++;
7938 skip_whitespace (*str);
7939
7940 tempinst = inst.instruction;
7941
7942 do
7943 {
7944 inst.instruction = 0;
7945
7946 if ((new_base = vfp_dp_reg_required_here (str, VFP_REG_Dd)) == FAIL)
7947 return FAIL;
7948
7949 if (count == 0 || base_reg > new_base)
7950 {
7951 base_reg = new_base;
7952 range = inst.instruction;
7953 }
7954
7955 if (mask & (1 << new_base))
7956 {
7957 inst.error = _("invalid register list");
7958 return FAIL;
7959 }
7960
7961 if ((mask >> new_base) != 0 && ! warned)
7962 {
7963 as_tsktsk (_("register list not in ascending order"));
7964 warned = 1;
7965 }
7966
7967 mask |= 1 << new_base;
7968 count++;
7969
7970 skip_whitespace (*str);
7971
7972 if (**str == '-') /* We have the start of a range expression */
7973 {
7974 int high_range;
7975
7976 (*str)++;
7977
7978 if ((high_range
7979 = arm_reg_parse (str, all_reg_maps[REG_TYPE_DN].htab))
7980 == FAIL)
7981 {
7982 inst.error = _(all_reg_maps[REG_TYPE_DN].expected);
7983 return FAIL;
7984 }
7985
7986 if (high_range <= new_base)
7987 {
7988 inst.error = _("register range not in ascending order");
7989 return FAIL;
7990 }
7991
7992 for (new_base++; new_base <= high_range; new_base++)
7993 {
7994 if (mask & (1 << new_base))
7995 {
7996 inst.error = _("invalid register list");
7997 return FAIL;
7998 }
7999
8000 mask |= 1 << new_base;
8001 count++;
8002 }
8003 }
8004 }
8005 while (skip_past_comma (str) != FAIL);
8006
8007 if (**str != '}')
8008 {
8009 inst.error = _("invalid register list");
8010 return FAIL;
8011 }
8012
8013 (*str)++;
8014
8015 range |= 2 * count;
8016
8017 /* Sanity check -- should have raised a parse error above. */
8018 if (count == 0 || count > 16)
8019 abort ();
8020
8021 /* Final test -- the registers must be consecutive. */
8022 while (count--)
8023 {
8024 if ((mask & (1 << base_reg++)) == 0)
8025 {
8026 inst.error = _("non-contiguous register range");
8027 return FAIL;
8028 }
8029 }
8030
8031 inst.instruction = tempinst;
8032 return range;
8033 }
8034
8035 static void
8036 vfp_sp_ldstm (str, ldstm_type)
8037 char *str;
8038 enum vfp_ldstm_type ldstm_type;
8039 {
8040 long range;
8041
8042 skip_whitespace (str);
8043
8044 if (reg_required_here (&str, 16) == FAIL)
8045 return;
8046
8047 skip_whitespace (str);
8048
8049 if (*str == '!')
8050 {
8051 inst.instruction |= WRITE_BACK;
8052 str++;
8053 }
8054 else if (ldstm_type != VFP_LDSTMIA)
8055 {
8056 inst.error = _("this addressing mode requires base-register writeback");
8057 return;
8058 }
8059
8060 if (skip_past_comma (&str) == FAIL
8061 || (range = vfp_sp_reg_list (&str, VFP_REG_Sd)) == FAIL)
8062 {
8063 if (!inst.error)
8064 inst.error = BAD_ARGS;
8065 return;
8066 }
8067
8068 inst.instruction |= range;
8069 end_of_line (str);
8070 }
8071
8072 static void
8073 vfp_dp_ldstm (str, ldstm_type)
8074 char *str;
8075 enum vfp_ldstm_type ldstm_type;
8076 {
8077 long range;
8078
8079 skip_whitespace (str);
8080
8081 if (reg_required_here (&str, 16) == FAIL)
8082 return;
8083
8084 skip_whitespace (str);
8085
8086 if (*str == '!')
8087 {
8088 inst.instruction |= WRITE_BACK;
8089 str++;
8090 }
8091 else if (ldstm_type != VFP_LDSTMIA && ldstm_type != VFP_LDSTMIAX)
8092 {
8093 inst.error = _("this addressing mode requires base-register writeback");
8094 return;
8095 }
8096
8097 if (skip_past_comma (&str) == FAIL
8098 || (range = vfp_dp_reg_list (&str)) == FAIL)
8099 {
8100 if (!inst.error)
8101 inst.error = BAD_ARGS;
8102 return;
8103 }
8104
8105 if (ldstm_type == VFP_LDSTMIAX || ldstm_type == VFP_LDSTMDBX)
8106 range += 1;
8107
8108 inst.instruction |= range;
8109 end_of_line (str);
8110 }
8111
8112 static void
8113 do_vfp_sp_ldstmia (str)
8114 char *str;
8115 {
8116 vfp_sp_ldstm (str, VFP_LDSTMIA);
8117 }
8118
8119 static void
8120 do_vfp_sp_ldstmdb (str)
8121 char *str;
8122 {
8123 vfp_sp_ldstm (str, VFP_LDSTMDB);
8124 }
8125
8126 static void
8127 do_vfp_dp_ldstmia (str)
8128 char *str;
8129 {
8130 vfp_dp_ldstm (str, VFP_LDSTMIA);
8131 }
8132
8133 static void
8134 do_vfp_dp_ldstmdb (str)
8135 char *str;
8136 {
8137 vfp_dp_ldstm (str, VFP_LDSTMDB);
8138 }
8139
8140 static void
8141 do_vfp_xp_ldstmia (str)
8142 char *str;
8143 {
8144 vfp_dp_ldstm (str, VFP_LDSTMIAX);
8145 }
8146
8147 static void
8148 do_vfp_xp_ldstmdb (str)
8149 char *str;
8150 {
8151 vfp_dp_ldstm (str, VFP_LDSTMDBX);
8152 }
8153
8154 static void
8155 do_vfp_sp_compare_z (str)
8156 char *str;
8157 {
8158 skip_whitespace (str);
8159
8160 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
8161 {
8162 if (!inst.error)
8163 inst.error = BAD_ARGS;
8164 return;
8165 }
8166
8167 end_of_line (str);
8168 return;
8169 }
8170
8171 static void
8172 do_vfp_dp_compare_z (str)
8173 char *str;
8174 {
8175 skip_whitespace (str);
8176
8177 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
8178 {
8179 if (!inst.error)
8180 inst.error = BAD_ARGS;
8181 return;
8182 }
8183
8184 end_of_line (str);
8185 return;
8186 }
8187
8188 static void
8189 do_vfp_dp_sp_cvt (str)
8190 char *str;
8191 {
8192 skip_whitespace (str);
8193
8194 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
8195 return;
8196
8197 if (skip_past_comma (&str) == FAIL
8198 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
8199 {
8200 if (! inst.error)
8201 inst.error = BAD_ARGS;
8202 return;
8203 }
8204
8205 end_of_line (str);
8206 return;
8207 }
8208
8209 static void
8210 do_vfp_sp_dp_cvt (str)
8211 char *str;
8212 {
8213 skip_whitespace (str);
8214
8215 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
8216 return;
8217
8218 if (skip_past_comma (&str) == FAIL
8219 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
8220 {
8221 if (! inst.error)
8222 inst.error = BAD_ARGS;
8223 return;
8224 }
8225
8226 end_of_line (str);
8227 return;
8228 }
8229
8230 /* Thumb specific routines. */
8231
8232 /* Parse and validate that a register is of the right form, this saves
8233 repeated checking of this information in many similar cases.
8234 Unlike the 32-bit case we do not insert the register into the opcode
8235 here, since the position is often unknown until the full instruction
8236 has been parsed. */
8237
8238 static int
8239 thumb_reg (strp, hi_lo)
8240 char ** strp;
8241 int hi_lo;
8242 {
8243 int reg;
8244
8245 if ((reg = reg_required_here (strp, -1)) == FAIL)
8246 return FAIL;
8247
8248 switch (hi_lo)
8249 {
8250 case THUMB_REG_LO:
8251 if (reg > 7)
8252 {
8253 inst.error = _("lo register required");
8254 return FAIL;
8255 }
8256 break;
8257
8258 case THUMB_REG_HI:
8259 if (reg < 8)
8260 {
8261 inst.error = _("hi register required");
8262 return FAIL;
8263 }
8264 break;
8265
8266 default:
8267 break;
8268 }
8269
8270 return reg;
8271 }
8272
8273 /* Parse an add or subtract instruction, SUBTRACT is non-zero if the opcode
8274 was SUB. */
8275
8276 static void
8277 thumb_add_sub (str, subtract)
8278 char * str;
8279 int subtract;
8280 {
8281 int Rd, Rs, Rn = FAIL;
8282
8283 skip_whitespace (str);
8284
8285 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
8286 || skip_past_comma (&str) == FAIL)
8287 {
8288 if (! inst.error)
8289 inst.error = BAD_ARGS;
8290 return;
8291 }
8292
8293 if (is_immediate_prefix (*str))
8294 {
8295 Rs = Rd;
8296 str++;
8297 if (my_get_expression (&inst.reloc.exp, &str))
8298 return;
8299 }
8300 else
8301 {
8302 if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
8303 return;
8304
8305 if (skip_past_comma (&str) == FAIL)
8306 {
8307 /* Two operand format, shuffle the registers
8308 and pretend there are 3. */
8309 Rn = Rs;
8310 Rs = Rd;
8311 }
8312 else if (is_immediate_prefix (*str))
8313 {
8314 str++;
8315 if (my_get_expression (&inst.reloc.exp, &str))
8316 return;
8317 }
8318 else if ((Rn = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
8319 return;
8320 }
8321
8322 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
8323 for the latter case, EXPR contains the immediate that was found. */
8324 if (Rn != FAIL)
8325 {
8326 /* All register format. */
8327 if (Rd > 7 || Rs > 7 || Rn > 7)
8328 {
8329 if (Rs != Rd)
8330 {
8331 inst.error = _("dest and source1 must be the same register");
8332 return;
8333 }
8334
8335 /* Can't do this for SUB. */
8336 if (subtract)
8337 {
8338 inst.error = _("subtract valid only on lo regs");
8339 return;
8340 }
8341
8342 inst.instruction = (T_OPCODE_ADD_HI
8343 | (Rd > 7 ? THUMB_H1 : 0)
8344 | (Rn > 7 ? THUMB_H2 : 0));
8345 inst.instruction |= (Rd & 7) | ((Rn & 7) << 3);
8346 }
8347 else
8348 {
8349 inst.instruction = subtract ? T_OPCODE_SUB_R3 : T_OPCODE_ADD_R3;
8350 inst.instruction |= Rd | (Rs << 3) | (Rn << 6);
8351 }
8352 }
8353 else
8354 {
8355 /* Immediate expression, now things start to get nasty. */
8356
8357 /* First deal with HI regs, only very restricted cases allowed:
8358 Adjusting SP, and using PC or SP to get an address. */
8359 if ((Rd > 7 && (Rd != REG_SP || Rs != REG_SP))
8360 || (Rs > 7 && Rs != REG_SP && Rs != REG_PC))
8361 {
8362 inst.error = _("invalid Hi register with immediate");
8363 return;
8364 }
8365
8366 if (inst.reloc.exp.X_op != O_constant)
8367 {
8368 /* Value isn't known yet, all we can do is store all the fragments
8369 we know about in the instruction and let the reloc hacking
8370 work it all out. */
8371 inst.instruction = (subtract ? 0x8000 : 0) | (Rd << 4) | Rs;
8372 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
8373 }
8374 else
8375 {
8376 int offset = inst.reloc.exp.X_add_number;
8377
8378 if (subtract)
8379 offset = - offset;
8380
8381 if (offset < 0)
8382 {
8383 offset = - offset;
8384 subtract = 1;
8385
8386 /* Quick check, in case offset is MIN_INT. */
8387 if (offset < 0)
8388 {
8389 inst.error = _("immediate value out of range");
8390 return;
8391 }
8392 }
8393 /* Note - you cannot convert a subtract of 0 into an
8394 add of 0 because the carry flag is set differently. */
8395 else if (offset > 0)
8396 subtract = 0;
8397
8398 if (Rd == REG_SP)
8399 {
8400 if (offset & ~0x1fc)
8401 {
8402 inst.error = _("invalid immediate value for stack adjust");
8403 return;
8404 }
8405 inst.instruction = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
8406 inst.instruction |= offset >> 2;
8407 }
8408 else if (Rs == REG_PC || Rs == REG_SP)
8409 {
8410 if (subtract
8411 || (offset & ~0x3fc))
8412 {
8413 inst.error = _("invalid immediate for address calculation");
8414 return;
8415 }
8416 inst.instruction = (Rs == REG_PC ? T_OPCODE_ADD_PC
8417 : T_OPCODE_ADD_SP);
8418 inst.instruction |= (Rd << 8) | (offset >> 2);
8419 }
8420 else if (Rs == Rd)
8421 {
8422 if (offset & ~0xff)
8423 {
8424 inst.error = _("immediate value out of range");
8425 return;
8426 }
8427 inst.instruction = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
8428 inst.instruction |= (Rd << 8) | offset;
8429 }
8430 else
8431 {
8432 if (offset & ~0x7)
8433 {
8434 inst.error = _("immediate value out of range");
8435 return;
8436 }
8437 inst.instruction = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
8438 inst.instruction |= Rd | (Rs << 3) | (offset << 6);
8439 }
8440 }
8441 }
8442
8443 end_of_line (str);
8444 }
8445
8446 static void
8447 thumb_shift (str, shift)
8448 char * str;
8449 int shift;
8450 {
8451 int Rd, Rs, Rn = FAIL;
8452
8453 skip_whitespace (str);
8454
8455 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
8456 || skip_past_comma (&str) == FAIL)
8457 {
8458 if (! inst.error)
8459 inst.error = BAD_ARGS;
8460 return;
8461 }
8462
8463 if (is_immediate_prefix (*str))
8464 {
8465 /* Two operand immediate format, set Rs to Rd. */
8466 Rs = Rd;
8467 str ++;
8468 if (my_get_expression (&inst.reloc.exp, &str))
8469 return;
8470 }
8471 else
8472 {
8473 if ((Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
8474 return;
8475
8476 if (skip_past_comma (&str) == FAIL)
8477 {
8478 /* Two operand format, shuffle the registers
8479 and pretend there are 3. */
8480 Rn = Rs;
8481 Rs = Rd;
8482 }
8483 else if (is_immediate_prefix (*str))
8484 {
8485 str++;
8486 if (my_get_expression (&inst.reloc.exp, &str))
8487 return;
8488 }
8489 else if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
8490 return;
8491 }
8492
8493 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
8494 for the latter case, EXPR contains the immediate that was found. */
8495
8496 if (Rn != FAIL)
8497 {
8498 if (Rs != Rd)
8499 {
8500 inst.error = _("source1 and dest must be same register");
8501 return;
8502 }
8503
8504 switch (shift)
8505 {
8506 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_R; break;
8507 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_R; break;
8508 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_R; break;
8509 }
8510
8511 inst.instruction |= Rd | (Rn << 3);
8512 }
8513 else
8514 {
8515 switch (shift)
8516 {
8517 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_I; break;
8518 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_I; break;
8519 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_I; break;
8520 }
8521
8522 if (inst.reloc.exp.X_op != O_constant)
8523 {
8524 /* Value isn't known yet, create a dummy reloc and let reloc
8525 hacking fix it up. */
8526 inst.reloc.type = BFD_RELOC_ARM_THUMB_SHIFT;
8527 }
8528 else
8529 {
8530 unsigned shift_value = inst.reloc.exp.X_add_number;
8531
8532 if (shift_value > 32 || (shift_value == 32 && shift == THUMB_LSL))
8533 {
8534 inst.error = _("invalid immediate for shift");
8535 return;
8536 }
8537
8538 /* Shifts of zero are handled by converting to LSL. */
8539 if (shift_value == 0)
8540 inst.instruction = T_OPCODE_LSL_I;
8541
8542 /* Shifts of 32 are encoded as a shift of zero. */
8543 if (shift_value == 32)
8544 shift_value = 0;
8545
8546 inst.instruction |= shift_value << 6;
8547 }
8548
8549 inst.instruction |= Rd | (Rs << 3);
8550 }
8551
8552 end_of_line (str);
8553 }
8554
8555 static void
8556 thumb_mov_compare (str, move)
8557 char * str;
8558 int move;
8559 {
8560 int Rd, Rs = FAIL;
8561
8562 skip_whitespace (str);
8563
8564 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
8565 || skip_past_comma (&str) == FAIL)
8566 {
8567 if (! inst.error)
8568 inst.error = BAD_ARGS;
8569 return;
8570 }
8571
8572 if (is_immediate_prefix (*str))
8573 {
8574 str++;
8575 if (my_get_expression (&inst.reloc.exp, &str))
8576 return;
8577 }
8578 else if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
8579 return;
8580
8581 if (Rs != FAIL)
8582 {
8583 if (Rs < 8 && Rd < 8)
8584 {
8585 if (move == THUMB_MOVE)
8586 /* A move of two lowregs is encoded as ADD Rd, Rs, #0
8587 since a MOV instruction produces unpredictable results. */
8588 inst.instruction = T_OPCODE_ADD_I3;
8589 else
8590 inst.instruction = T_OPCODE_CMP_LR;
8591 inst.instruction |= Rd | (Rs << 3);
8592 }
8593 else
8594 {
8595 if (move == THUMB_MOVE)
8596 inst.instruction = T_OPCODE_MOV_HR;
8597 else
8598 inst.instruction = T_OPCODE_CMP_HR;
8599
8600 if (Rd > 7)
8601 inst.instruction |= THUMB_H1;
8602
8603 if (Rs > 7)
8604 inst.instruction |= THUMB_H2;
8605
8606 inst.instruction |= (Rd & 7) | ((Rs & 7) << 3);
8607 }
8608 }
8609 else
8610 {
8611 if (Rd > 7)
8612 {
8613 inst.error = _("only lo regs allowed with immediate");
8614 return;
8615 }
8616
8617 if (move == THUMB_MOVE)
8618 inst.instruction = T_OPCODE_MOV_I8;
8619 else
8620 inst.instruction = T_OPCODE_CMP_I8;
8621
8622 inst.instruction |= Rd << 8;
8623
8624 if (inst.reloc.exp.X_op != O_constant)
8625 inst.reloc.type = BFD_RELOC_ARM_THUMB_IMM;
8626 else
8627 {
8628 unsigned value = inst.reloc.exp.X_add_number;
8629
8630 if (value > 255)
8631 {
8632 inst.error = _("invalid immediate");
8633 return;
8634 }
8635
8636 inst.instruction |= value;
8637 }
8638 }
8639
8640 end_of_line (str);
8641 }
8642
8643 static void
8644 thumb_load_store (str, load_store, size)
8645 char * str;
8646 int load_store;
8647 int size;
8648 {
8649 int Rd, Rb, Ro = FAIL;
8650
8651 skip_whitespace (str);
8652
8653 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
8654 || skip_past_comma (&str) == FAIL)
8655 {
8656 if (! inst.error)
8657 inst.error = BAD_ARGS;
8658 return;
8659 }
8660
8661 if (*str == '[')
8662 {
8663 str++;
8664 if ((Rb = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
8665 return;
8666
8667 if (skip_past_comma (&str) != FAIL)
8668 {
8669 if (is_immediate_prefix (*str))
8670 {
8671 str++;
8672 if (my_get_expression (&inst.reloc.exp, &str))
8673 return;
8674 }
8675 else if ((Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
8676 return;
8677 }
8678 else
8679 {
8680 inst.reloc.exp.X_op = O_constant;
8681 inst.reloc.exp.X_add_number = 0;
8682 }
8683
8684 if (*str != ']')
8685 {
8686 inst.error = _("expected ']'");
8687 return;
8688 }
8689 str++;
8690 }
8691 else if (*str == '=')
8692 {
8693 if (load_store != THUMB_LOAD)
8694 {
8695 inst.error = _("invalid pseudo operation");
8696 return;
8697 }
8698
8699 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
8700 str++;
8701
8702 skip_whitespace (str);
8703
8704 if (my_get_expression (& inst.reloc.exp, & str))
8705 return;
8706
8707 end_of_line (str);
8708
8709 if ( inst.reloc.exp.X_op != O_constant
8710 && inst.reloc.exp.X_op != O_symbol)
8711 {
8712 inst.error = "Constant expression expected";
8713 return;
8714 }
8715
8716 if (inst.reloc.exp.X_op == O_constant
8717 && ((inst.reloc.exp.X_add_number & ~0xFF) == 0))
8718 {
8719 /* This can be done with a mov instruction. */
8720
8721 inst.instruction = T_OPCODE_MOV_I8 | (Rd << 8);
8722 inst.instruction |= inst.reloc.exp.X_add_number;
8723 return;
8724 }
8725
8726 /* Insert into literal pool. */
8727 if (add_to_lit_pool () == FAIL)
8728 {
8729 if (!inst.error)
8730 inst.error = "literal pool insertion failed";
8731 return;
8732 }
8733
8734 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
8735 inst.reloc.pc_rel = 1;
8736 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
8737 /* Adjust ARM pipeline offset to Thumb. */
8738 inst.reloc.exp.X_add_number += 4;
8739
8740 return;
8741 }
8742 else
8743 {
8744 if (my_get_expression (&inst.reloc.exp, &str))
8745 return;
8746
8747 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
8748 inst.reloc.pc_rel = 1;
8749 inst.reloc.exp.X_add_number -= 4; /* Pipeline offset. */
8750 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
8751 end_of_line (str);
8752 return;
8753 }
8754
8755 if (Rb == REG_PC || Rb == REG_SP)
8756 {
8757 if (size != THUMB_WORD)
8758 {
8759 inst.error = _("byte or halfword not valid for base register");
8760 return;
8761 }
8762 else if (Rb == REG_PC && load_store != THUMB_LOAD)
8763 {
8764 inst.error = _("r15 based store not allowed");
8765 return;
8766 }
8767 else if (Ro != FAIL)
8768 {
8769 inst.error = _("invalid base register for register offset");
8770 return;
8771 }
8772
8773 if (Rb == REG_PC)
8774 inst.instruction = T_OPCODE_LDR_PC;
8775 else if (load_store == THUMB_LOAD)
8776 inst.instruction = T_OPCODE_LDR_SP;
8777 else
8778 inst.instruction = T_OPCODE_STR_SP;
8779
8780 inst.instruction |= Rd << 8;
8781 if (inst.reloc.exp.X_op == O_constant)
8782 {
8783 unsigned offset = inst.reloc.exp.X_add_number;
8784
8785 if (offset & ~0x3fc)
8786 {
8787 inst.error = _("invalid offset");
8788 return;
8789 }
8790
8791 inst.instruction |= offset >> 2;
8792 }
8793 else
8794 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
8795 }
8796 else if (Rb > 7)
8797 {
8798 inst.error = _("invalid base register in load/store");
8799 return;
8800 }
8801 else if (Ro == FAIL)
8802 {
8803 /* Immediate offset. */
8804 if (size == THUMB_WORD)
8805 inst.instruction = (load_store == THUMB_LOAD
8806 ? T_OPCODE_LDR_IW : T_OPCODE_STR_IW);
8807 else if (size == THUMB_HALFWORD)
8808 inst.instruction = (load_store == THUMB_LOAD
8809 ? T_OPCODE_LDR_IH : T_OPCODE_STR_IH);
8810 else
8811 inst.instruction = (load_store == THUMB_LOAD
8812 ? T_OPCODE_LDR_IB : T_OPCODE_STR_IB);
8813
8814 inst.instruction |= Rd | (Rb << 3);
8815
8816 if (inst.reloc.exp.X_op == O_constant)
8817 {
8818 unsigned offset = inst.reloc.exp.X_add_number;
8819
8820 if (offset & ~(0x1f << size))
8821 {
8822 inst.error = _("invalid offset");
8823 return;
8824 }
8825 inst.instruction |= (offset >> size) << 6;
8826 }
8827 else
8828 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
8829 }
8830 else
8831 {
8832 /* Register offset. */
8833 if (size == THUMB_WORD)
8834 inst.instruction = (load_store == THUMB_LOAD
8835 ? T_OPCODE_LDR_RW : T_OPCODE_STR_RW);
8836 else if (size == THUMB_HALFWORD)
8837 inst.instruction = (load_store == THUMB_LOAD
8838 ? T_OPCODE_LDR_RH : T_OPCODE_STR_RH);
8839 else
8840 inst.instruction = (load_store == THUMB_LOAD
8841 ? T_OPCODE_LDR_RB : T_OPCODE_STR_RB);
8842
8843 inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
8844 }
8845
8846 end_of_line (str);
8847 }
8848
8849 /* A register must be given at this point.
8850
8851 Shift is the place to put it in inst.instruction.
8852
8853 Restores input start point on err.
8854 Returns the reg#, or FAIL. */
8855
8856 static int
8857 mav_reg_required_here (str, shift, regtype)
8858 char ** str;
8859 int shift;
8860 enum arm_reg_type regtype;
8861 {
8862 int reg;
8863 char *start = *str;
8864
8865 if ((reg = arm_reg_parse (str, all_reg_maps[regtype].htab)) != FAIL)
8866 {
8867 if (shift >= 0)
8868 inst.instruction |= reg << shift;
8869
8870 return reg;
8871 }
8872
8873 /* Restore the start point. */
8874 *str = start;
8875
8876 /* In the few cases where we might be able to accept something else
8877 this error can be overridden. */
8878 inst.error = _(all_reg_maps[regtype].expected);
8879
8880 return FAIL;
8881 }
8882
8883 /* Cirrus Maverick Instructions. */
8884
8885 /* Wrapper functions. */
8886
8887 static void
8888 do_mav_binops_1a (str)
8889 char * str;
8890 {
8891 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVF);
8892 }
8893
8894 static void
8895 do_mav_binops_1b (str)
8896 char * str;
8897 {
8898 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVD);
8899 }
8900
8901 static void
8902 do_mav_binops_1c (str)
8903 char * str;
8904 {
8905 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVDX);
8906 }
8907
8908 static void
8909 do_mav_binops_1d (str)
8910 char * str;
8911 {
8912 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVF);
8913 }
8914
8915 static void
8916 do_mav_binops_1e (str)
8917 char * str;
8918 {
8919 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVD);
8920 }
8921
8922 static void
8923 do_mav_binops_1f (str)
8924 char * str;
8925 {
8926 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVF);
8927 }
8928
8929 static void
8930 do_mav_binops_1g (str)
8931 char * str;
8932 {
8933 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVD);
8934 }
8935
8936 static void
8937 do_mav_binops_1h (str)
8938 char * str;
8939 {
8940 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVFX);
8941 }
8942
8943 static void
8944 do_mav_binops_1i (str)
8945 char * str;
8946 {
8947 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVFX);
8948 }
8949
8950 static void
8951 do_mav_binops_1j (str)
8952 char * str;
8953 {
8954 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVDX);
8955 }
8956
8957 static void
8958 do_mav_binops_1k (str)
8959 char * str;
8960 {
8961 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVDX);
8962 }
8963
8964 static void
8965 do_mav_binops_1l (str)
8966 char * str;
8967 {
8968 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVF);
8969 }
8970
8971 static void
8972 do_mav_binops_1m (str)
8973 char * str;
8974 {
8975 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVD);
8976 }
8977
8978 static void
8979 do_mav_binops_1n (str)
8980 char * str;
8981 {
8982 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVFX);
8983 }
8984
8985 static void
8986 do_mav_binops_1o (str)
8987 char * str;
8988 {
8989 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVDX, REG_TYPE_MVDX);
8990 }
8991
8992 static void
8993 do_mav_binops_2a (str)
8994 char * str;
8995 {
8996 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVF, REG_TYPE_RN);
8997 }
8998
8999 static void
9000 do_mav_binops_2b (str)
9001 char * str;
9002 {
9003 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVD, REG_TYPE_RN);
9004 }
9005
9006 static void
9007 do_mav_binops_2c (str)
9008 char * str;
9009 {
9010 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVDX, REG_TYPE_RN);
9011 }
9012
9013 static void
9014 do_mav_binops_3a (str)
9015 char * str;
9016 {
9017 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVAX, REG_TYPE_MVFX);
9018 }
9019
9020 static void
9021 do_mav_binops_3b (str)
9022 char * str;
9023 {
9024 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVFX, REG_TYPE_MVAX);
9025 }
9026
9027 static void
9028 do_mav_binops_3c (str)
9029 char * str;
9030 {
9031 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVAX, REG_TYPE_MVDX);
9032 }
9033
9034 static void
9035 do_mav_binops_3d (str)
9036 char * str;
9037 {
9038 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVDX, REG_TYPE_MVAX);
9039 }
9040
9041 static void
9042 do_mav_triple_4a (str)
9043 char * str;
9044 {
9045 do_mav_triple (str, MAV_MODE4, REG_TYPE_MVFX, REG_TYPE_MVFX, REG_TYPE_RN);
9046 }
9047
9048 static void
9049 do_mav_triple_4b (str)
9050 char * str;
9051 {
9052 do_mav_triple (str, MAV_MODE4, REG_TYPE_MVDX, REG_TYPE_MVDX, REG_TYPE_RN);
9053 }
9054
9055 static void
9056 do_mav_triple_5a (str)
9057 char * str;
9058 {
9059 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVF, REG_TYPE_MVF);
9060 }
9061
9062 static void
9063 do_mav_triple_5b (str)
9064 char * str;
9065 {
9066 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVD, REG_TYPE_MVD);
9067 }
9068
9069 static void
9070 do_mav_triple_5c (str)
9071 char * str;
9072 {
9073 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVFX, REG_TYPE_MVFX);
9074 }
9075
9076 static void
9077 do_mav_triple_5d (str)
9078 char * str;
9079 {
9080 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVDX, REG_TYPE_MVDX);
9081 }
9082
9083 static void
9084 do_mav_triple_5e (str)
9085 char * str;
9086 {
9087 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVF, REG_TYPE_MVF, REG_TYPE_MVF);
9088 }
9089
9090 static void
9091 do_mav_triple_5f (str)
9092 char * str;
9093 {
9094 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVD, REG_TYPE_MVD, REG_TYPE_MVD);
9095 }
9096
9097 static void
9098 do_mav_triple_5g (str)
9099 char * str;
9100 {
9101 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVFX, REG_TYPE_MVFX, REG_TYPE_MVFX);
9102 }
9103
9104 static void
9105 do_mav_triple_5h (str)
9106 char * str;
9107 {
9108 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVDX, REG_TYPE_MVDX, REG_TYPE_MVDX);
9109 }
9110
9111 static void
9112 do_mav_quad_6a (str)
9113 char * str;
9114 {
9115 do_mav_quad (str, MAV_MODE6, REG_TYPE_MVAX, REG_TYPE_MVFX, REG_TYPE_MVFX,
9116 REG_TYPE_MVFX);
9117 }
9118
9119 static void
9120 do_mav_quad_6b (str)
9121 char * str;
9122 {
9123 do_mav_quad (str, MAV_MODE6, REG_TYPE_MVAX, REG_TYPE_MVAX, REG_TYPE_MVFX,
9124 REG_TYPE_MVFX);
9125 }
9126
9127 /* cfmvsc32<cond> DSPSC,MVFX[15:0]. */
9128 static void
9129 do_mav_dspsc_1 (str)
9130 char * str;
9131 {
9132 skip_whitespace (str);
9133
9134 /* cfmvsc32. */
9135 if (mav_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL
9136 || skip_past_comma (&str) == FAIL
9137 || mav_reg_required_here (&str, 16, REG_TYPE_MVFX) == FAIL)
9138 {
9139 if (!inst.error)
9140 inst.error = BAD_ARGS;
9141
9142 return;
9143 }
9144
9145 end_of_line (str);
9146 }
9147
9148 /* cfmv32sc<cond> MVFX[15:0],DSPSC. */
9149 static void
9150 do_mav_dspsc_2 (str)
9151 char * str;
9152 {
9153 skip_whitespace (str);
9154
9155 /* cfmv32sc. */
9156 if (mav_reg_required_here (&str, 0, REG_TYPE_MVFX) == FAIL
9157 || skip_past_comma (&str) == FAIL
9158 || mav_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL)
9159 {
9160 if (!inst.error)
9161 inst.error = BAD_ARGS;
9162
9163 return;
9164 }
9165
9166 end_of_line (str);
9167 }
9168
9169 static void
9170 do_mav_shift_1 (str)
9171 char * str;
9172 {
9173 do_mav_shift (str, REG_TYPE_MVFX, REG_TYPE_MVFX);
9174 }
9175
9176 static void
9177 do_mav_shift_2 (str)
9178 char * str;
9179 {
9180 do_mav_shift (str, REG_TYPE_MVDX, REG_TYPE_MVDX);
9181 }
9182
9183 static void
9184 do_mav_ldst_1 (str)
9185 char * str;
9186 {
9187 do_mav_ldst (str, REG_TYPE_MVF);
9188 }
9189
9190 static void
9191 do_mav_ldst_2 (str)
9192 char * str;
9193 {
9194 do_mav_ldst (str, REG_TYPE_MVD);
9195 }
9196
9197 static void
9198 do_mav_ldst_3 (str)
9199 char * str;
9200 {
9201 do_mav_ldst (str, REG_TYPE_MVFX);
9202 }
9203
9204 static void
9205 do_mav_ldst_4 (str)
9206 char * str;
9207 {
9208 do_mav_ldst (str, REG_TYPE_MVDX);
9209 }
9210
9211 /* Isnsn like "foo X,Y". */
9212
9213 static void
9214 do_mav_binops (str, mode, reg0, reg1)
9215 char * str;
9216 int mode;
9217 enum arm_reg_type reg0;
9218 enum arm_reg_type reg1;
9219 {
9220 int shift0, shift1;
9221
9222 shift0 = mode & 0xff;
9223 shift1 = (mode >> 8) & 0xff;
9224
9225 skip_whitespace (str);
9226
9227 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
9228 || skip_past_comma (&str) == FAIL
9229 || mav_reg_required_here (&str, shift1, reg1) == FAIL)
9230 {
9231 if (!inst.error)
9232 inst.error = BAD_ARGS;
9233 }
9234 else
9235 end_of_line (str);
9236 }
9237
9238 /* Isnsn like "foo X,Y,Z". */
9239
9240 static void
9241 do_mav_triple (str, mode, reg0, reg1, reg2)
9242 char * str;
9243 int mode;
9244 enum arm_reg_type reg0;
9245 enum arm_reg_type reg1;
9246 enum arm_reg_type reg2;
9247 {
9248 int shift0, shift1, shift2;
9249
9250 shift0 = mode & 0xff;
9251 shift1 = (mode >> 8) & 0xff;
9252 shift2 = (mode >> 16) & 0xff;
9253
9254 skip_whitespace (str);
9255
9256 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
9257 || skip_past_comma (&str) == FAIL
9258 || mav_reg_required_here (&str, shift1, reg1) == FAIL
9259 || skip_past_comma (&str) == FAIL
9260 || mav_reg_required_here (&str, shift2, reg2) == FAIL)
9261 {
9262 if (!inst.error)
9263 inst.error = BAD_ARGS;
9264 }
9265 else
9266 end_of_line (str);
9267 }
9268
9269 /* Isnsn like "foo W,X,Y,Z".
9270 where W=MVAX[0:3] and X,Y,Z=MVFX[0:15]. */
9271
9272 static void
9273 do_mav_quad (str, mode, reg0, reg1, reg2, reg3)
9274 char * str;
9275 int mode;
9276 enum arm_reg_type reg0;
9277 enum arm_reg_type reg1;
9278 enum arm_reg_type reg2;
9279 enum arm_reg_type reg3;
9280 {
9281 int shift0, shift1, shift2, shift3;
9282
9283 shift0= mode & 0xff;
9284 shift1 = (mode >> 8) & 0xff;
9285 shift2 = (mode >> 16) & 0xff;
9286 shift3 = (mode >> 24) & 0xff;
9287
9288 skip_whitespace (str);
9289
9290 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
9291 || skip_past_comma (&str) == FAIL
9292 || mav_reg_required_here (&str, shift1, reg1) == FAIL
9293 || skip_past_comma (&str) == FAIL
9294 || mav_reg_required_here (&str, shift2, reg2) == FAIL
9295 || skip_past_comma (&str) == FAIL
9296 || mav_reg_required_here (&str, shift3, reg3) == FAIL)
9297 {
9298 if (!inst.error)
9299 inst.error = BAD_ARGS;
9300 }
9301 else
9302 end_of_line (str);
9303 }
9304
9305 /* Maverick shift immediate instructions.
9306 cfsh32<cond> MVFX[15:0],MVFX[15:0],Shift[6:0].
9307 cfsh64<cond> MVDX[15:0],MVDX[15:0],Shift[6:0]. */
9308
9309 static void
9310 do_mav_shift (str, reg0, reg1)
9311 char * str;
9312 enum arm_reg_type reg0;
9313 enum arm_reg_type reg1;
9314 {
9315 int error;
9316 int imm, neg = 0;
9317
9318 skip_whitespace (str);
9319
9320 error = 0;
9321
9322 if (mav_reg_required_here (&str, 12, reg0) == FAIL
9323 || skip_past_comma (&str) == FAIL
9324 || mav_reg_required_here (&str, 16, reg1) == FAIL
9325 || skip_past_comma (&str) == FAIL)
9326 {
9327 if (!inst.error)
9328 inst.error = BAD_ARGS;
9329 return;
9330 }
9331
9332 /* Calculate the immediate operand.
9333 The operand is a 7bit signed number. */
9334 skip_whitespace (str);
9335
9336 if (*str == '#')
9337 ++str;
9338
9339 if (!ISDIGIT (*str) && *str != '-')
9340 {
9341 inst.error = _("expecting immediate, 7bit operand");
9342 return;
9343 }
9344
9345 if (*str == '-')
9346 {
9347 neg = 1;
9348 ++str;
9349 }
9350
9351 for (imm = 0; *str && ISDIGIT (*str); ++str)
9352 imm = imm * 10 + *str - '0';
9353
9354 if (imm > 64)
9355 {
9356 inst.error = _("immediate out of range");
9357 return;
9358 }
9359
9360 /* Make negative imm's into 7bit signed numbers. */
9361 if (neg)
9362 {
9363 imm = -imm;
9364 imm &= 0x0000007f;
9365 }
9366
9367 /* Bits 0-3 of the insn should have bits 0-3 of the immediate.
9368 Bits 5-7 of the insn should have bits 4-6 of the immediate.
9369 Bit 4 should be 0. */
9370 imm = (imm & 0xf) | ((imm & 0x70) << 1);
9371
9372 inst.instruction |= imm;
9373 end_of_line (str);
9374 }
9375
9376 static int
9377 mav_parse_offset (str, negative)
9378 char ** str;
9379 int *negative;
9380 {
9381 char * p = *str;
9382 int offset;
9383
9384 *negative = 0;
9385
9386 skip_whitespace (p);
9387
9388 if (*p == '#')
9389 ++p;
9390
9391 if (*p == '-')
9392 {
9393 *negative = 1;
9394 ++p;
9395 }
9396
9397 if (!ISDIGIT (*p))
9398 {
9399 inst.error = _("offset expected");
9400 return 0;
9401 }
9402
9403 for (offset = 0; *p && ISDIGIT (*p); ++p)
9404 offset = offset * 10 + *p - '0';
9405
9406 if (offset > 0xff)
9407 {
9408 inst.error = _("offset out of range");
9409 return 0;
9410 }
9411
9412 *str = p;
9413
9414 return *negative ? -offset : offset;
9415 }
9416
9417 /* Maverick load/store instructions.
9418 <insn><cond> CRd,[Rn,<offset>]{!}.
9419 <insn><cond> CRd,[Rn],<offset>. */
9420
9421 static void
9422 do_mav_ldst (str, reg0)
9423 char * str;
9424 enum arm_reg_type reg0;
9425 {
9426 int offset, negative;
9427
9428 skip_whitespace (str);
9429
9430 if (mav_reg_required_here (&str, 12, reg0) == FAIL
9431 || skip_past_comma (&str) == FAIL
9432 || *str++ != '['
9433 || reg_required_here (&str, 16) == FAIL)
9434 goto fail_ldst;
9435
9436 if (skip_past_comma (&str) == SUCCESS)
9437 {
9438 /* You are here: "<offset>]{!}". */
9439 inst.instruction |= PRE_INDEX;
9440
9441 offset = mav_parse_offset (&str, &negative);
9442
9443 if (inst.error)
9444 return;
9445
9446 if (*str++ != ']')
9447 {
9448 inst.error = _("missing ]");
9449 return;
9450 }
9451
9452 if (*str == '!')
9453 {
9454 inst.instruction |= WRITE_BACK;
9455 ++str;
9456 }
9457 }
9458 else
9459 {
9460 /* You are here: "], <offset>". */
9461 if (*str++ != ']')
9462 {
9463 inst.error = _("missing ]");
9464 return;
9465 }
9466
9467 if (skip_past_comma (&str) == FAIL
9468 || (offset = mav_parse_offset (&str, &negative), inst.error))
9469 goto fail_ldst;
9470
9471 inst.instruction |= CP_T_WB; /* Post indexed, set bit W. */
9472 }
9473
9474 if (negative)
9475 offset = -offset;
9476 else
9477 inst.instruction |= CP_T_UD; /* Postive, so set bit U. */
9478
9479 inst.instruction |= offset >> 2;
9480 end_of_line (str);
9481 return;
9482
9483 fail_ldst:
9484 if (!inst.error)
9485 inst.error = BAD_ARGS;
9486 return;
9487 }
9488
9489 static void
9490 do_t_nop (str)
9491 char * str;
9492 {
9493 /* Do nothing. */
9494 end_of_line (str);
9495 return;
9496 }
9497
9498 /* Handle the Format 4 instructions that do not have equivalents in other
9499 formats. That is, ADC, AND, EOR, SBC, ROR, TST, NEG, CMN, ORR, MUL,
9500 BIC and MVN. */
9501
9502 static void
9503 do_t_arit (str)
9504 char * str;
9505 {
9506 int Rd, Rs, Rn;
9507
9508 skip_whitespace (str);
9509
9510 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9511 || skip_past_comma (&str) == FAIL
9512 || (Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9513 {
9514 inst.error = BAD_ARGS;
9515 return;
9516 }
9517
9518 if (skip_past_comma (&str) != FAIL)
9519 {
9520 /* Three operand format not allowed for TST, CMN, NEG and MVN.
9521 (It isn't allowed for CMP either, but that isn't handled by this
9522 function.) */
9523 if (inst.instruction == T_OPCODE_TST
9524 || inst.instruction == T_OPCODE_CMN
9525 || inst.instruction == T_OPCODE_NEG
9526 || inst.instruction == T_OPCODE_MVN)
9527 {
9528 inst.error = BAD_ARGS;
9529 return;
9530 }
9531
9532 if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9533 return;
9534
9535 if (Rs != Rd)
9536 {
9537 inst.error = _("dest and source1 must be the same register");
9538 return;
9539 }
9540 Rs = Rn;
9541 }
9542
9543 if (inst.instruction == T_OPCODE_MUL
9544 && Rs == Rd)
9545 as_tsktsk (_("Rs and Rd must be different in MUL"));
9546
9547 inst.instruction |= Rd | (Rs << 3);
9548 end_of_line (str);
9549 }
9550
9551 static void
9552 do_t_add (str)
9553 char * str;
9554 {
9555 thumb_add_sub (str, 0);
9556 }
9557
9558 static void
9559 do_t_asr (str)
9560 char * str;
9561 {
9562 thumb_shift (str, THUMB_ASR);
9563 }
9564
9565 static void
9566 do_t_branch9 (str)
9567 char * str;
9568 {
9569 if (my_get_expression (&inst.reloc.exp, &str))
9570 return;
9571 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH9;
9572 inst.reloc.pc_rel = 1;
9573 end_of_line (str);
9574 }
9575
9576 static void
9577 do_t_branch12 (str)
9578 char * str;
9579 {
9580 if (my_get_expression (&inst.reloc.exp, &str))
9581 return;
9582 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH12;
9583 inst.reloc.pc_rel = 1;
9584 end_of_line (str);
9585 }
9586
9587 /* Find the real, Thumb encoded start of a Thumb function. */
9588
9589 static symbolS *
9590 find_real_start (symbolP)
9591 symbolS * symbolP;
9592 {
9593 char * real_start;
9594 const char * name = S_GET_NAME (symbolP);
9595 symbolS * new_target;
9596
9597 /* This definiton must agree with the one in gcc/config/arm/thumb.c. */
9598 #define STUB_NAME ".real_start_of"
9599
9600 if (name == NULL)
9601 abort ();
9602
9603 /* Names that start with '.' are local labels, not function entry points.
9604 The compiler may generate BL instructions to these labels because it
9605 needs to perform a branch to a far away location. */
9606 if (name[0] == '.')
9607 return symbolP;
9608
9609 real_start = malloc (strlen (name) + strlen (STUB_NAME) + 1);
9610 sprintf (real_start, "%s%s", STUB_NAME, name);
9611
9612 new_target = symbol_find (real_start);
9613
9614 if (new_target == NULL)
9615 {
9616 as_warn ("Failed to find real start of function: %s\n", name);
9617 new_target = symbolP;
9618 }
9619
9620 free (real_start);
9621
9622 return new_target;
9623 }
9624
9625 static void
9626 do_t_branch23 (str)
9627 char * str;
9628 {
9629 if (my_get_expression (& inst.reloc.exp, & str))
9630 return;
9631
9632 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH23;
9633 inst.reloc.pc_rel = 1;
9634 end_of_line (str);
9635
9636 /* If the destination of the branch is a defined symbol which does not have
9637 the THUMB_FUNC attribute, then we must be calling a function which has
9638 the (interfacearm) attribute. We look for the Thumb entry point to that
9639 function and change the branch to refer to that function instead. */
9640 if ( inst.reloc.exp.X_op == O_symbol
9641 && inst.reloc.exp.X_add_symbol != NULL
9642 && S_IS_DEFINED (inst.reloc.exp.X_add_symbol)
9643 && ! THUMB_IS_FUNC (inst.reloc.exp.X_add_symbol))
9644 inst.reloc.exp.X_add_symbol =
9645 find_real_start (inst.reloc.exp.X_add_symbol);
9646 }
9647
9648 static void
9649 do_t_bx (str)
9650 char * str;
9651 {
9652 int reg;
9653
9654 skip_whitespace (str);
9655
9656 if ((reg = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
9657 return;
9658
9659 /* This sets THUMB_H2 from the top bit of reg. */
9660 inst.instruction |= reg << 3;
9661
9662 /* ??? FIXME: Should add a hacky reloc here if reg is REG_PC. The reloc
9663 should cause the alignment to be checked once it is known. This is
9664 because BX PC only works if the instruction is word aligned. */
9665
9666 end_of_line (str);
9667 }
9668
9669 static void
9670 do_t_compare (str)
9671 char * str;
9672 {
9673 thumb_mov_compare (str, THUMB_COMPARE);
9674 }
9675
9676 static void
9677 do_t_ldmstm (str)
9678 char * str;
9679 {
9680 int Rb;
9681 long range;
9682
9683 skip_whitespace (str);
9684
9685 if ((Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9686 return;
9687
9688 if (*str != '!')
9689 as_warn (_("inserted missing '!': load/store multiple always writes back base register"));
9690 else
9691 str++;
9692
9693 if (skip_past_comma (&str) == FAIL
9694 || (range = reg_list (&str)) == FAIL)
9695 {
9696 if (! inst.error)
9697 inst.error = BAD_ARGS;
9698 return;
9699 }
9700
9701 if (inst.reloc.type != BFD_RELOC_NONE)
9702 {
9703 /* This really doesn't seem worth it. */
9704 inst.reloc.type = BFD_RELOC_NONE;
9705 inst.error = _("expression too complex");
9706 return;
9707 }
9708
9709 if (range & ~0xff)
9710 {
9711 inst.error = _("only lo-regs valid in load/store multiple");
9712 return;
9713 }
9714
9715 inst.instruction |= (Rb << 8) | range;
9716 end_of_line (str);
9717 }
9718
9719 static void
9720 do_t_ldr (str)
9721 char * str;
9722 {
9723 thumb_load_store (str, THUMB_LOAD, THUMB_WORD);
9724 }
9725
9726 static void
9727 do_t_ldrb (str)
9728 char * str;
9729 {
9730 thumb_load_store (str, THUMB_LOAD, THUMB_BYTE);
9731 }
9732
9733 static void
9734 do_t_ldrh (str)
9735 char * str;
9736 {
9737 thumb_load_store (str, THUMB_LOAD, THUMB_HALFWORD);
9738 }
9739
9740 static void
9741 do_t_lds (str)
9742 char * str;
9743 {
9744 int Rd, Rb, Ro;
9745
9746 skip_whitespace (str);
9747
9748 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9749 || skip_past_comma (&str) == FAIL
9750 || *str++ != '['
9751 || (Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9752 || skip_past_comma (&str) == FAIL
9753 || (Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9754 || *str++ != ']')
9755 {
9756 if (! inst.error)
9757 inst.error = _("syntax: ldrs[b] Rd, [Rb, Ro]");
9758 return;
9759 }
9760
9761 inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
9762 end_of_line (str);
9763 }
9764
9765 static void
9766 do_t_lsl (str)
9767 char * str;
9768 {
9769 thumb_shift (str, THUMB_LSL);
9770 }
9771
9772 static void
9773 do_t_lsr (str)
9774 char * str;
9775 {
9776 thumb_shift (str, THUMB_LSR);
9777 }
9778
9779 static void
9780 do_t_mov (str)
9781 char * str;
9782 {
9783 thumb_mov_compare (str, THUMB_MOVE);
9784 }
9785
9786 static void
9787 do_t_push_pop (str)
9788 char * str;
9789 {
9790 long range;
9791
9792 skip_whitespace (str);
9793
9794 if ((range = reg_list (&str)) == FAIL)
9795 {
9796 if (! inst.error)
9797 inst.error = BAD_ARGS;
9798 return;
9799 }
9800
9801 if (inst.reloc.type != BFD_RELOC_NONE)
9802 {
9803 /* This really doesn't seem worth it. */
9804 inst.reloc.type = BFD_RELOC_NONE;
9805 inst.error = _("expression too complex");
9806 return;
9807 }
9808
9809 if (range & ~0xff)
9810 {
9811 if ((inst.instruction == T_OPCODE_PUSH
9812 && (range & ~0xff) == 1 << REG_LR)
9813 || (inst.instruction == T_OPCODE_POP
9814 && (range & ~0xff) == 1 << REG_PC))
9815 {
9816 inst.instruction |= THUMB_PP_PC_LR;
9817 range &= 0xff;
9818 }
9819 else
9820 {
9821 inst.error = _("invalid register list to push/pop instruction");
9822 return;
9823 }
9824 }
9825
9826 inst.instruction |= range;
9827 end_of_line (str);
9828 }
9829
9830 static void
9831 do_t_str (str)
9832 char * str;
9833 {
9834 thumb_load_store (str, THUMB_STORE, THUMB_WORD);
9835 }
9836
9837 static void
9838 do_t_strb (str)
9839 char * str;
9840 {
9841 thumb_load_store (str, THUMB_STORE, THUMB_BYTE);
9842 }
9843
9844 static void
9845 do_t_strh (str)
9846 char * str;
9847 {
9848 thumb_load_store (str, THUMB_STORE, THUMB_HALFWORD);
9849 }
9850
9851 static void
9852 do_t_sub (str)
9853 char * str;
9854 {
9855 thumb_add_sub (str, 1);
9856 }
9857
9858 static void
9859 do_t_swi (str)
9860 char * str;
9861 {
9862 skip_whitespace (str);
9863
9864 if (my_get_expression (&inst.reloc.exp, &str))
9865 return;
9866
9867 inst.reloc.type = BFD_RELOC_ARM_SWI;
9868 end_of_line (str);
9869 return;
9870 }
9871
9872 static void
9873 do_t_adr (str)
9874 char * str;
9875 {
9876 int reg;
9877
9878 /* This is a pseudo-op of the form "adr rd, label" to be converted
9879 into a relative address of the form "add rd, pc, #label-.-4". */
9880 skip_whitespace (str);
9881
9882 /* Store Rd in temporary location inside instruction. */
9883 if ((reg = reg_required_here (&str, 4)) == FAIL
9884 || (reg > 7) /* For Thumb reg must be r0..r7. */
9885 || skip_past_comma (&str) == FAIL
9886 || my_get_expression (&inst.reloc.exp, &str))
9887 {
9888 if (!inst.error)
9889 inst.error = BAD_ARGS;
9890 return;
9891 }
9892
9893 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
9894 inst.reloc.exp.X_add_number -= 4; /* PC relative adjust. */
9895 inst.reloc.pc_rel = 1;
9896 inst.instruction |= REG_PC; /* Rd is already placed into the instruction. */
9897
9898 end_of_line (str);
9899 }
9900
9901 static void
9902 insert_reg (r, htab)
9903 const struct reg_entry *r;
9904 struct hash_control *htab;
9905 {
9906 int len = strlen (r->name) + 2;
9907 char * buf = (char *) xmalloc (len);
9908 char * buf2 = (char *) xmalloc (len);
9909 int i = 0;
9910
9911 #ifdef REGISTER_PREFIX
9912 buf[i++] = REGISTER_PREFIX;
9913 #endif
9914
9915 strcpy (buf + i, r->name);
9916
9917 for (i = 0; buf[i]; i++)
9918 buf2[i] = TOUPPER (buf[i]);
9919
9920 buf2[i] = '\0';
9921
9922 hash_insert (htab, buf, (PTR) r);
9923 hash_insert (htab, buf2, (PTR) r);
9924 }
9925
9926 static void
9927 build_reg_hsh (map)
9928 struct reg_map *map;
9929 {
9930 const struct reg_entry *r;
9931
9932 if ((map->htab = hash_new ()) == NULL)
9933 as_fatal (_("virtual memory exhausted"));
9934
9935 for (r = map->names; r->name != NULL; r++)
9936 insert_reg (r, map->htab);
9937 }
9938
9939 static void
9940 insert_reg_alias (str, regnum, htab)
9941 char *str;
9942 int regnum;
9943 struct hash_control *htab;
9944 {
9945 struct reg_entry *new =
9946 (struct reg_entry *) xmalloc (sizeof (struct reg_entry));
9947 char *name = xmalloc (strlen (str) + 1);
9948 strcpy (name, str);
9949
9950 new->name = name;
9951 new->number = regnum;
9952
9953 hash_insert (htab, name, (PTR) new);
9954 }
9955
9956 /* Look for the .req directive. This is of the form:
9957
9958 newname .req existing_name
9959
9960 If we find one, or if it looks sufficiently like one that we want to
9961 handle any error here, return non-zero. Otherwise return zero. */
9962 static int
9963 create_register_alias (newname, p)
9964 char *newname;
9965 char *p;
9966 {
9967 char *q;
9968 char c;
9969
9970 q = p;
9971 skip_whitespace (q);
9972
9973 c = *p;
9974 *p = '\0';
9975
9976 if (*q && !strncmp (q, ".req ", 5))
9977 {
9978 char *copy_of_str;
9979 char *r;
9980
9981 #ifdef IGNORE_OPCODE_CASE
9982 newname = original_case_string;
9983 #endif
9984 copy_of_str = newname;
9985
9986 q += 4;
9987 skip_whitespace (q);
9988
9989 for (r = q; *r != '\0'; r++)
9990 if (*r == ' ')
9991 break;
9992
9993 if (r != q)
9994 {
9995 enum arm_reg_type new_type, old_type;
9996 int old_regno;
9997 char d = *r;
9998
9999 *r = '\0';
10000 old_type = arm_reg_parse_any (q);
10001 *r = d;
10002
10003 new_type = arm_reg_parse_any (newname);
10004
10005 if (new_type == REG_TYPE_MAX)
10006 {
10007 if (old_type != REG_TYPE_MAX)
10008 {
10009 old_regno = arm_reg_parse (&q, all_reg_maps[old_type].htab);
10010 insert_reg_alias (newname, old_regno,
10011 all_reg_maps[old_type].htab);
10012 }
10013 else
10014 as_warn (_("register '%s' does not exist\n"), q);
10015 }
10016 else if (old_type == REG_TYPE_MAX)
10017 {
10018 as_warn (_("ignoring redefinition of register alias '%s' to non-existant register '%s'"),
10019 copy_of_str, q);
10020 }
10021 else
10022 {
10023 /* Do not warn about redefinitions to the same alias. */
10024 if (new_type != old_type
10025 || (arm_reg_parse (&q, all_reg_maps[old_type].htab)
10026 != arm_reg_parse (&q, all_reg_maps[new_type].htab)))
10027 as_warn (_("ignoring redefinition of register alias '%s'"),
10028 copy_of_str);
10029
10030 }
10031 }
10032 else
10033 as_warn (_("ignoring incomplete .req pseuso op"));
10034
10035 *p = c;
10036 return 1;
10037 }
10038 *p = c;
10039 return 0;
10040 }
10041
10042 static void
10043 set_constant_flonums ()
10044 {
10045 int i;
10046
10047 for (i = 0; i < NUM_FLOAT_VALS; i++)
10048 if (atof_ieee ((char *) fp_const[i], 'x', fp_values[i]) == NULL)
10049 abort ();
10050 }
10051
10052 /* Iterate over the base tables to create the instruction patterns. */
10053 static void
10054 build_arm_ops_hsh ()
10055 {
10056 unsigned int i;
10057 unsigned int j;
10058 static struct obstack insn_obstack;
10059
10060 obstack_begin (&insn_obstack, 4000);
10061
10062 for (i = 0; i < sizeof (insns) / sizeof (struct asm_opcode); i++)
10063 {
10064 const struct asm_opcode *insn = insns + i;
10065
10066 if (insn->cond_offset != 0)
10067 {
10068 /* Insn supports conditional execution. Build the varaints
10069 and insert them in the hash table. */
10070 for (j = 0; j < sizeof (conds) / sizeof (struct asm_cond); j++)
10071 {
10072 unsigned len = strlen (insn->template);
10073 struct asm_opcode *new;
10074 char *template;
10075
10076 new = obstack_alloc (&insn_obstack, sizeof (struct asm_opcode));
10077 /* All condition codes are two characters. */
10078 template = obstack_alloc (&insn_obstack, len + 3);
10079
10080 strncpy (template, insn->template, insn->cond_offset);
10081 strcpy (template + insn->cond_offset, conds[j].template);
10082 if (len > insn->cond_offset)
10083 strcpy (template + insn->cond_offset + 2,
10084 insn->template + insn->cond_offset);
10085 new->template = template;
10086 new->cond_offset = 0;
10087 new->variant = insn->variant;
10088 new->parms = insn->parms;
10089 new->value = (insn->value & ~COND_MASK) | conds[j].value;
10090
10091 hash_insert (arm_ops_hsh, new->template, (PTR) new);
10092 }
10093 }
10094 /* Finally, insert the unconditional insn in the table directly;
10095 no need to build a copy. */
10096 hash_insert (arm_ops_hsh, insn->template, (PTR) insn);
10097 }
10098 }
10099
10100 #if defined OBJ_ELF || defined OBJ_COFF
10101
10102 #ifdef OBJ_ELF
10103 #define arm_Note Elf_External_Note
10104 #else
10105 typedef struct
10106 {
10107 unsigned char namesz[4]; /* Size of entry's owner string. */
10108 unsigned char descsz[4]; /* Size of the note descriptor. */
10109 unsigned char type[4]; /* Interpretation of the descriptor. */
10110 char name[1]; /* Start of the name+desc data. */
10111 } arm_Note;
10112 #endif
10113
10114 /* The description is kept to a fix sized in order to make updating
10115 it and merging it easier. */
10116 #define ARM_NOTE_DESCRIPTION_LENGTH 8
10117
10118 static void
10119 arm_add_note (name, description, type)
10120 const char * name;
10121 const char * description;
10122 unsigned int type;
10123 {
10124 arm_Note note ATTRIBUTE_UNUSED;
10125 char * p;
10126 unsigned int name_len;
10127
10128 name_len = (strlen (name) + 1 + 3) & ~3;
10129
10130 p = frag_more (sizeof (note.namesz));
10131 md_number_to_chars (p, (valueT) name_len, sizeof (note.namesz));
10132
10133 p = frag_more (sizeof (note.descsz));
10134 md_number_to_chars (p, (valueT) ARM_NOTE_DESCRIPTION_LENGTH, sizeof (note.descsz));
10135
10136 p = frag_more (sizeof (note.type));
10137 md_number_to_chars (p, (valueT) type, sizeof (note.type));
10138
10139 p = frag_more (name_len);
10140 strcpy (p, name);
10141
10142 p = frag_more (ARM_NOTE_DESCRIPTION_LENGTH);
10143 strncpy (p, description, ARM_NOTE_DESCRIPTION_LENGTH);
10144 frag_align (2, 0, 0);
10145 }
10146 #endif
10147
10148 void
10149 md_begin ()
10150 {
10151 unsigned mach;
10152 unsigned int i;
10153
10154 if ( (arm_ops_hsh = hash_new ()) == NULL
10155 || (arm_tops_hsh = hash_new ()) == NULL
10156 || (arm_cond_hsh = hash_new ()) == NULL
10157 || (arm_shift_hsh = hash_new ()) == NULL
10158 || (arm_psr_hsh = hash_new ()) == NULL)
10159 as_fatal (_("virtual memory exhausted"));
10160
10161 build_arm_ops_hsh ();
10162 for (i = 0; i < sizeof (tinsns) / sizeof (struct thumb_opcode); i++)
10163 hash_insert (arm_tops_hsh, tinsns[i].template, (PTR) (tinsns + i));
10164 for (i = 0; i < sizeof (conds) / sizeof (struct asm_cond); i++)
10165 hash_insert (arm_cond_hsh, conds[i].template, (PTR) (conds + i));
10166 for (i = 0; i < sizeof (shift_names) / sizeof (struct asm_shift_name); i++)
10167 hash_insert (arm_shift_hsh, shift_names[i].name, (PTR) (shift_names + i));
10168 for (i = 0; i < sizeof (psrs) / sizeof (struct asm_psr); i++)
10169 hash_insert (arm_psr_hsh, psrs[i].template, (PTR) (psrs + i));
10170
10171 for (i = (int) REG_TYPE_FIRST; i < (int) REG_TYPE_MAX; i++)
10172 build_reg_hsh (all_reg_maps + i);
10173
10174 set_constant_flonums ();
10175
10176 /* Set the cpu variant based on the command-line options. We prefer
10177 -mcpu= over -march= if both are set (as for GCC); and we prefer
10178 -mfpu= over any other way of setting the floating point unit.
10179 Use of legacy options with new options are faulted. */
10180 if (legacy_cpu != -1)
10181 {
10182 if (mcpu_cpu_opt != -1 || march_cpu_opt != -1)
10183 as_bad (_("use of old and new-style options to set CPU type"));
10184
10185 mcpu_cpu_opt = legacy_cpu;
10186 }
10187 else if (mcpu_cpu_opt == -1)
10188 mcpu_cpu_opt = march_cpu_opt;
10189
10190 if (legacy_fpu != -1)
10191 {
10192 if (mfpu_opt != -1)
10193 as_bad (_("use of old and new-style options to set FPU type"));
10194
10195 mfpu_opt = legacy_fpu;
10196 }
10197 else if (mfpu_opt == -1)
10198 {
10199 #if !(defined (TE_LINUX) || defined (TE_NetBSD))
10200 /* Some environments specify a default FPU. If they don't, infer it
10201 from the processor. */
10202 if (mcpu_fpu_opt != -1)
10203 mfpu_opt = mcpu_fpu_opt;
10204 else
10205 mfpu_opt = march_fpu_opt;
10206 #else
10207 mfpu_opt = FPU_DEFAULT;
10208 #endif
10209 }
10210
10211 if (mfpu_opt == -1)
10212 {
10213 if (mcpu_cpu_opt == -1)
10214 mfpu_opt = FPU_DEFAULT;
10215 else if (mcpu_cpu_opt & ARM_EXT_V5)
10216 mfpu_opt = FPU_ARCH_VFP_V2;
10217 else
10218 mfpu_opt = FPU_ARCH_FPA;
10219 }
10220
10221 if (mcpu_cpu_opt == -1)
10222 mcpu_cpu_opt = CPU_DEFAULT;
10223
10224 cpu_variant = mcpu_cpu_opt | mfpu_opt;
10225
10226 #if defined OBJ_COFF || defined OBJ_ELF
10227 {
10228 unsigned int flags = 0;
10229
10230 /* Set the flags in the private structure. */
10231 if (uses_apcs_26) flags |= F_APCS26;
10232 if (support_interwork) flags |= F_INTERWORK;
10233 if (uses_apcs_float) flags |= F_APCS_FLOAT;
10234 if (pic_code) flags |= F_PIC;
10235 if ((cpu_variant & FPU_ANY) == FPU_NONE
10236 || (cpu_variant & FPU_ANY) == FPU_ARCH_VFP) /* VFP layout only. */
10237 flags |= F_SOFT_FLOAT;
10238 /* Using VFP conventions (even if soft-float). */
10239 if (cpu_variant & FPU_VFP_EXT_NONE) flags |= F_VFP_FLOAT;
10240
10241 #if defined OBJ_ELF
10242 if (cpu_variant & ARM_CEXT_MAVERICK)
10243 {
10244 flags ^= F_SOFT_FLOAT;
10245 flags |= EF_ARM_MAVERICK_FLOAT;
10246 }
10247 #endif
10248
10249 bfd_set_private_flags (stdoutput, flags);
10250
10251 /* We have run out flags in the COFF header to encode the
10252 status of ATPCS support, so instead we create a dummy,
10253 empty, debug section called .arm.atpcs. */
10254 if (atpcs)
10255 {
10256 asection * sec;
10257
10258 sec = bfd_make_section (stdoutput, ".arm.atpcs");
10259
10260 if (sec != NULL)
10261 {
10262 bfd_set_section_flags
10263 (stdoutput, sec, SEC_READONLY | SEC_DEBUGGING /* | SEC_HAS_CONTENTS */);
10264 bfd_set_section_size (stdoutput, sec, 0);
10265 bfd_set_section_contents (stdoutput, sec, NULL, 0, 0);
10266 }
10267 }
10268 }
10269 #endif
10270
10271 /* Record the CPU type as well. */
10272 switch (cpu_variant & ARM_CPU_MASK)
10273 {
10274 case ARM_2:
10275 mach = bfd_mach_arm_2;
10276 break;
10277
10278 case ARM_3: /* Also ARM_250. */
10279 mach = bfd_mach_arm_2a;
10280 break;
10281
10282 case ARM_6: /* Also ARM_7. */
10283 mach = bfd_mach_arm_3;
10284 break;
10285
10286 default:
10287 mach = bfd_mach_arm_unknown;
10288 break;
10289 }
10290
10291 /* Catch special cases. */
10292 if (cpu_variant & ARM_CEXT_IWMMXT)
10293 mach = bfd_mach_arm_iWMMXt;
10294 else if (cpu_variant & ARM_CEXT_XSCALE)
10295 mach = bfd_mach_arm_XScale;
10296 else if (cpu_variant & ARM_CEXT_MAVERICK)
10297 mach = bfd_mach_arm_ep9312;
10298 else if (cpu_variant & ARM_EXT_V5E)
10299 mach = bfd_mach_arm_5TE;
10300 else if (cpu_variant & ARM_EXT_V5)
10301 {
10302 if (cpu_variant & ARM_EXT_V4T)
10303 mach = bfd_mach_arm_5T;
10304 else
10305 mach = bfd_mach_arm_5;
10306 }
10307 else if (cpu_variant & ARM_EXT_V4)
10308 {
10309 if (cpu_variant & ARM_EXT_V4T)
10310 mach = bfd_mach_arm_4T;
10311 else
10312 mach = bfd_mach_arm_4;
10313 }
10314 else if (cpu_variant & ARM_EXT_V3M)
10315 mach = bfd_mach_arm_3M;
10316
10317 #if 0 /* Suppressed - for now. */
10318 #if defined (OBJ_ELF) || defined (OBJ_COFF)
10319
10320 /* Create a .note section to fully identify this arm binary. */
10321
10322 #define NOTE_ARCH_STRING "arch: "
10323
10324 #if defined OBJ_COFF && ! defined NT_VERSION
10325 #define NT_VERSION 1
10326 #define NT_ARCH 2
10327 #endif
10328
10329 {
10330 segT current_seg = now_seg;
10331 subsegT current_subseg = now_subseg;
10332 asection * arm_arch;
10333 const char * arch_string;
10334
10335 arm_arch = bfd_make_section_old_way (stdoutput, ARM_NOTE_SECTION);
10336
10337 #ifdef OBJ_COFF
10338 bfd_set_section_flags (stdoutput, arm_arch,
10339 SEC_DATA | SEC_ALLOC | SEC_LOAD | SEC_LINK_ONCE \
10340 | SEC_HAS_CONTENTS);
10341 #endif
10342 arm_arch->output_section = arm_arch;
10343 subseg_set (arm_arch, 0);
10344
10345 switch (mach)
10346 {
10347 default:
10348 case bfd_mach_arm_unknown: arch_string = "unknown"; break;
10349 case bfd_mach_arm_2: arch_string = "armv2"; break;
10350 case bfd_mach_arm_2a: arch_string = "armv2a"; break;
10351 case bfd_mach_arm_3: arch_string = "armv3"; break;
10352 case bfd_mach_arm_3M: arch_string = "armv3M"; break;
10353 case bfd_mach_arm_4: arch_string = "armv4"; break;
10354 case bfd_mach_arm_4T: arch_string = "armv4t"; break;
10355 case bfd_mach_arm_5: arch_string = "armv5"; break;
10356 case bfd_mach_arm_5T: arch_string = "armv5t"; break;
10357 case bfd_mach_arm_5TE: arch_string = "armv5te"; break;
10358 case bfd_mach_arm_XScale: arch_string = "XScale"; break;
10359 case bfd_mach_arm_ep9312: arch_string = "ep9312"; break;
10360 case bfd_mach_arm_iWMMXt: arch_string = "iWMMXt"; break;
10361 }
10362
10363 arm_add_note (NOTE_ARCH_STRING, arch_string, NT_ARCH);
10364
10365 subseg_set (current_seg, current_subseg);
10366 }
10367 #endif
10368 #endif /* Suppressed code. */
10369
10370 bfd_set_arch_mach (stdoutput, TARGET_ARCH, mach);
10371 }
10372
10373 /* Turn an integer of n bytes (in val) into a stream of bytes appropriate
10374 for use in the a.out file, and stores them in the array pointed to by buf.
10375 This knows about the endian-ness of the target machine and does
10376 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
10377 2 (short) and 4 (long) Floating numbers are put out as a series of
10378 LITTLENUMS (shorts, here at least). */
10379
10380 void
10381 md_number_to_chars (buf, val, n)
10382 char * buf;
10383 valueT val;
10384 int n;
10385 {
10386 if (target_big_endian)
10387 number_to_chars_bigendian (buf, val, n);
10388 else
10389 number_to_chars_littleendian (buf, val, n);
10390 }
10391
10392 static valueT
10393 md_chars_to_number (buf, n)
10394 char * buf;
10395 int n;
10396 {
10397 valueT result = 0;
10398 unsigned char * where = (unsigned char *) buf;
10399
10400 if (target_big_endian)
10401 {
10402 while (n--)
10403 {
10404 result <<= 8;
10405 result |= (*where++ & 255);
10406 }
10407 }
10408 else
10409 {
10410 while (n--)
10411 {
10412 result <<= 8;
10413 result |= (where[n] & 255);
10414 }
10415 }
10416
10417 return result;
10418 }
10419
10420 /* Turn a string in input_line_pointer into a floating point constant
10421 of type TYPE, and store the appropriate bytes in *LITP. The number
10422 of LITTLENUMS emitted is stored in *SIZEP. An error message is
10423 returned, or NULL on OK.
10424
10425 Note that fp constants aren't represent in the normal way on the ARM.
10426 In big endian mode, things are as expected. However, in little endian
10427 mode fp constants are big-endian word-wise, and little-endian byte-wise
10428 within the words. For example, (double) 1.1 in big endian mode is
10429 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
10430 the byte sequence 99 99 f1 3f 9a 99 99 99.
10431
10432 ??? The format of 12 byte floats is uncertain according to gcc's arm.h. */
10433
10434 char *
10435 md_atof (type, litP, sizeP)
10436 char type;
10437 char * litP;
10438 int * sizeP;
10439 {
10440 int prec;
10441 LITTLENUM_TYPE words[MAX_LITTLENUMS];
10442 char *t;
10443 int i;
10444
10445 switch (type)
10446 {
10447 case 'f':
10448 case 'F':
10449 case 's':
10450 case 'S':
10451 prec = 2;
10452 break;
10453
10454 case 'd':
10455 case 'D':
10456 case 'r':
10457 case 'R':
10458 prec = 4;
10459 break;
10460
10461 case 'x':
10462 case 'X':
10463 prec = 6;
10464 break;
10465
10466 case 'p':
10467 case 'P':
10468 prec = 6;
10469 break;
10470
10471 default:
10472 *sizeP = 0;
10473 return _("bad call to MD_ATOF()");
10474 }
10475
10476 t = atof_ieee (input_line_pointer, type, words);
10477 if (t)
10478 input_line_pointer = t;
10479 *sizeP = prec * 2;
10480
10481 if (target_big_endian)
10482 {
10483 for (i = 0; i < prec; i++)
10484 {
10485 md_number_to_chars (litP, (valueT) words[i], 2);
10486 litP += 2;
10487 }
10488 }
10489 else
10490 {
10491 if (cpu_variant & FPU_ARCH_VFP)
10492 for (i = prec - 1; i >= 0; i--)
10493 {
10494 md_number_to_chars (litP, (valueT) words[i], 2);
10495 litP += 2;
10496 }
10497 else
10498 /* For a 4 byte float the order of elements in `words' is 1 0.
10499 For an 8 byte float the order is 1 0 3 2. */
10500 for (i = 0; i < prec; i += 2)
10501 {
10502 md_number_to_chars (litP, (valueT) words[i + 1], 2);
10503 md_number_to_chars (litP + 2, (valueT) words[i], 2);
10504 litP += 4;
10505 }
10506 }
10507
10508 return 0;
10509 }
10510
10511 /* The knowledge of the PC's pipeline offset is built into the insns
10512 themselves. */
10513
10514 long
10515 md_pcrel_from (fixP)
10516 fixS * fixP;
10517 {
10518 if (fixP->fx_addsy
10519 && S_GET_SEGMENT (fixP->fx_addsy) == undefined_section
10520 && fixP->fx_subsy == NULL)
10521 return 0;
10522
10523 if (fixP->fx_pcrel && (fixP->fx_r_type == BFD_RELOC_ARM_THUMB_ADD))
10524 {
10525 /* PC relative addressing on the Thumb is slightly odd
10526 as the bottom two bits of the PC are forced to zero
10527 for the calculation. */
10528 return (fixP->fx_where + fixP->fx_frag->fr_address) & ~3;
10529 }
10530
10531 #ifdef TE_WINCE
10532 /* The pattern was adjusted to accomodate CE's off-by-one fixups,
10533 so we un-adjust here to compensate for the accomodation. */
10534 return fixP->fx_where + fixP->fx_frag->fr_address + 8;
10535 #else
10536 return fixP->fx_where + fixP->fx_frag->fr_address;
10537 #endif
10538 }
10539
10540 /* Round up a section size to the appropriate boundary. */
10541
10542 valueT
10543 md_section_align (segment, size)
10544 segT segment ATTRIBUTE_UNUSED;
10545 valueT size;
10546 {
10547 #ifdef OBJ_ELF
10548 return size;
10549 #else
10550 /* Round all sects to multiple of 4. */
10551 return (size + 3) & ~3;
10552 #endif
10553 }
10554
10555 /* Under ELF we need to default _GLOBAL_OFFSET_TABLE.
10556 Otherwise we have no need to default values of symbols. */
10557
10558 symbolS *
10559 md_undefined_symbol (name)
10560 char * name ATTRIBUTE_UNUSED;
10561 {
10562 #ifdef OBJ_ELF
10563 if (name[0] == '_' && name[1] == 'G'
10564 && streq (name, GLOBAL_OFFSET_TABLE_NAME))
10565 {
10566 if (!GOT_symbol)
10567 {
10568 if (symbol_find (name))
10569 as_bad ("GOT already in the symbol table");
10570
10571 GOT_symbol = symbol_new (name, undefined_section,
10572 (valueT) 0, & zero_address_frag);
10573 }
10574
10575 return GOT_symbol;
10576 }
10577 #endif
10578
10579 return 0;
10580 }
10581
10582 /* arm_reg_parse () := if it looks like a register, return its token and
10583 advance the pointer. */
10584
10585 static int
10586 arm_reg_parse (ccp, htab)
10587 register char ** ccp;
10588 struct hash_control *htab;
10589 {
10590 char * start = * ccp;
10591 char c;
10592 char * p;
10593 struct reg_entry * reg;
10594
10595 #ifdef REGISTER_PREFIX
10596 if (*start != REGISTER_PREFIX)
10597 return FAIL;
10598 p = start + 1;
10599 #else
10600 p = start;
10601 #ifdef OPTIONAL_REGISTER_PREFIX
10602 if (*p == OPTIONAL_REGISTER_PREFIX)
10603 p++, start++;
10604 #endif
10605 #endif
10606 if (!ISALPHA (*p) || !is_name_beginner (*p))
10607 return FAIL;
10608
10609 c = *p++;
10610 while (ISALPHA (c) || ISDIGIT (c) || c == '_')
10611 c = *p++;
10612
10613 *--p = 0;
10614 reg = (struct reg_entry *) hash_find (htab, start);
10615 *p = c;
10616
10617 if (reg)
10618 {
10619 *ccp = p;
10620 return reg->number;
10621 }
10622
10623 return FAIL;
10624 }
10625
10626 /* Search for the following register name in each of the possible reg name
10627 tables. Return the classification if found, or REG_TYPE_MAX if not
10628 present. */
10629 static enum arm_reg_type
10630 arm_reg_parse_any (cp)
10631 char *cp;
10632 {
10633 int i;
10634
10635 for (i = (int) REG_TYPE_FIRST; i < (int) REG_TYPE_MAX; i++)
10636 if (arm_reg_parse (&cp, all_reg_maps[i].htab) != FAIL)
10637 return (enum arm_reg_type) i;
10638
10639 return REG_TYPE_MAX;
10640 }
10641
10642 void
10643 md_apply_fix3 (fixP, valP, seg)
10644 fixS * fixP;
10645 valueT * valP;
10646 segT seg;
10647 {
10648 offsetT value = * valP;
10649 offsetT newval;
10650 unsigned int newimm;
10651 unsigned long temp;
10652 int sign;
10653 char * buf = fixP->fx_where + fixP->fx_frag->fr_literal;
10654 arm_fix_data * arm_data = (arm_fix_data *) fixP->tc_fix_data;
10655
10656 assert (fixP->fx_r_type < BFD_RELOC_UNUSED);
10657
10658 /* Note whether this will delete the relocation. */
10659 #if 0
10660 /* Patch from REarnshaw to JDavis (disabled for the moment, since it
10661 doesn't work fully.) */
10662 if ((fixP->fx_addsy == 0 || symbol_constant_p (fixP->fx_addsy))
10663 && !fixP->fx_pcrel)
10664 #else
10665 if (fixP->fx_addsy == 0 && !fixP->fx_pcrel)
10666 #endif
10667 fixP->fx_done = 1;
10668
10669 /* If this symbol is in a different section then we need to leave it for
10670 the linker to deal with. Unfortunately, md_pcrel_from can't tell,
10671 so we have to undo it's effects here. */
10672 if (fixP->fx_pcrel)
10673 {
10674 if (fixP->fx_addsy != NULL
10675 && S_IS_DEFINED (fixP->fx_addsy)
10676 && S_GET_SEGMENT (fixP->fx_addsy) != seg)
10677 {
10678 if (target_oabi
10679 && (fixP->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH
10680 || fixP->fx_r_type == BFD_RELOC_ARM_PCREL_BLX
10681 ))
10682 value = 0;
10683 else
10684 value += md_pcrel_from (fixP);
10685 }
10686 }
10687
10688 /* Remember value for emit_reloc. */
10689 fixP->fx_addnumber = value;
10690
10691 switch (fixP->fx_r_type)
10692 {
10693 case BFD_RELOC_ARM_IMMEDIATE:
10694 newimm = validate_immediate (value);
10695 temp = md_chars_to_number (buf, INSN_SIZE);
10696
10697 /* If the instruction will fail, see if we can fix things up by
10698 changing the opcode. */
10699 if (newimm == (unsigned int) FAIL
10700 && (newimm = negate_data_op (&temp, value)) == (unsigned int) FAIL)
10701 {
10702 as_bad_where (fixP->fx_file, fixP->fx_line,
10703 _("invalid constant (%lx) after fixup"),
10704 (unsigned long) value);
10705 break;
10706 }
10707
10708 newimm |= (temp & 0xfffff000);
10709 md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
10710 fixP->fx_done = 1;
10711 break;
10712
10713 case BFD_RELOC_ARM_ADRL_IMMEDIATE:
10714 {
10715 unsigned int highpart = 0;
10716 unsigned int newinsn = 0xe1a00000; /* nop. */
10717
10718 newimm = validate_immediate (value);
10719 temp = md_chars_to_number (buf, INSN_SIZE);
10720
10721 /* If the instruction will fail, see if we can fix things up by
10722 changing the opcode. */
10723 if (newimm == (unsigned int) FAIL
10724 && (newimm = negate_data_op (& temp, value)) == (unsigned int) FAIL)
10725 {
10726 /* No ? OK - try using two ADD instructions to generate
10727 the value. */
10728 newimm = validate_immediate_twopart (value, & highpart);
10729
10730 /* Yes - then make sure that the second instruction is
10731 also an add. */
10732 if (newimm != (unsigned int) FAIL)
10733 newinsn = temp;
10734 /* Still No ? Try using a negated value. */
10735 else if ((newimm = validate_immediate_twopart (- value, & highpart)) != (unsigned int) FAIL)
10736 temp = newinsn = (temp & OPCODE_MASK) | OPCODE_SUB << DATA_OP_SHIFT;
10737 /* Otherwise - give up. */
10738 else
10739 {
10740 as_bad_where (fixP->fx_file, fixP->fx_line,
10741 _("unable to compute ADRL instructions for PC offset of 0x%lx"),
10742 (long) value);
10743 break;
10744 }
10745
10746 /* Replace the first operand in the 2nd instruction (which
10747 is the PC) with the destination register. We have
10748 already added in the PC in the first instruction and we
10749 do not want to do it again. */
10750 newinsn &= ~ 0xf0000;
10751 newinsn |= ((newinsn & 0x0f000) << 4);
10752 }
10753
10754 newimm |= (temp & 0xfffff000);
10755 md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
10756
10757 highpart |= (newinsn & 0xfffff000);
10758 md_number_to_chars (buf + INSN_SIZE, (valueT) highpart, INSN_SIZE);
10759 }
10760 break;
10761
10762 case BFD_RELOC_ARM_OFFSET_IMM:
10763 sign = value >= 0;
10764
10765 if (value < 0)
10766 value = - value;
10767
10768 if (validate_offset_imm (value, 0) == FAIL)
10769 {
10770 as_bad_where (fixP->fx_file, fixP->fx_line,
10771 _("bad immediate value for offset (%ld)"),
10772 (long) value);
10773 break;
10774 }
10775
10776 newval = md_chars_to_number (buf, INSN_SIZE);
10777 newval &= 0xff7ff000;
10778 newval |= value | (sign ? INDEX_UP : 0);
10779 md_number_to_chars (buf, newval, INSN_SIZE);
10780 break;
10781
10782 case BFD_RELOC_ARM_OFFSET_IMM8:
10783 case BFD_RELOC_ARM_HWLITERAL:
10784 sign = value >= 0;
10785
10786 if (value < 0)
10787 value = - value;
10788
10789 if (validate_offset_imm (value, 1) == FAIL)
10790 {
10791 if (fixP->fx_r_type == BFD_RELOC_ARM_HWLITERAL)
10792 as_bad_where (fixP->fx_file, fixP->fx_line,
10793 _("invalid literal constant: pool needs to be closer"));
10794 else
10795 as_bad (_("bad immediate value for half-word offset (%ld)"),
10796 (long) value);
10797 break;
10798 }
10799
10800 newval = md_chars_to_number (buf, INSN_SIZE);
10801 newval &= 0xff7ff0f0;
10802 newval |= ((value >> 4) << 8) | (value & 0xf) | (sign ? INDEX_UP : 0);
10803 md_number_to_chars (buf, newval, INSN_SIZE);
10804 break;
10805
10806 case BFD_RELOC_ARM_LITERAL:
10807 sign = value >= 0;
10808
10809 if (value < 0)
10810 value = - value;
10811
10812 if (validate_offset_imm (value, 0) == FAIL)
10813 {
10814 as_bad_where (fixP->fx_file, fixP->fx_line,
10815 _("invalid literal constant: pool needs to be closer"));
10816 break;
10817 }
10818
10819 newval = md_chars_to_number (buf, INSN_SIZE);
10820 newval &= 0xff7ff000;
10821 newval |= value | (sign ? INDEX_UP : 0);
10822 md_number_to_chars (buf, newval, INSN_SIZE);
10823 break;
10824
10825 case BFD_RELOC_ARM_SHIFT_IMM:
10826 newval = md_chars_to_number (buf, INSN_SIZE);
10827 if (((unsigned long) value) > 32
10828 || (value == 32
10829 && (((newval & 0x60) == 0) || (newval & 0x60) == 0x60)))
10830 {
10831 as_bad_where (fixP->fx_file, fixP->fx_line,
10832 _("shift expression is too large"));
10833 break;
10834 }
10835
10836 if (value == 0)
10837 /* Shifts of zero must be done as lsl. */
10838 newval &= ~0x60;
10839 else if (value == 32)
10840 value = 0;
10841 newval &= 0xfffff07f;
10842 newval |= (value & 0x1f) << 7;
10843 md_number_to_chars (buf, newval, INSN_SIZE);
10844 break;
10845
10846 case BFD_RELOC_ARM_SWI:
10847 if (arm_data->thumb_mode)
10848 {
10849 if (((unsigned long) value) > 0xff)
10850 as_bad_where (fixP->fx_file, fixP->fx_line,
10851 _("invalid swi expression"));
10852 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xff00;
10853 newval |= value;
10854 md_number_to_chars (buf, newval, THUMB_SIZE);
10855 }
10856 else
10857 {
10858 if (((unsigned long) value) > 0x00ffffff)
10859 as_bad_where (fixP->fx_file, fixP->fx_line,
10860 _("invalid swi expression"));
10861 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff000000;
10862 newval |= value;
10863 md_number_to_chars (buf, newval, INSN_SIZE);
10864 }
10865 break;
10866
10867 case BFD_RELOC_ARM_MULTI:
10868 if (((unsigned long) value) > 0xffff)
10869 as_bad_where (fixP->fx_file, fixP->fx_line,
10870 _("invalid expression in load/store multiple"));
10871 newval = value | md_chars_to_number (buf, INSN_SIZE);
10872 md_number_to_chars (buf, newval, INSN_SIZE);
10873 break;
10874
10875 case BFD_RELOC_ARM_PCREL_BRANCH:
10876 newval = md_chars_to_number (buf, INSN_SIZE);
10877
10878 /* Sign-extend a 24-bit number. */
10879 #define SEXT24(x) ((((x) & 0xffffff) ^ (~ 0x7fffff)) + 0x800000)
10880
10881 #ifdef OBJ_ELF
10882 if (! target_oabi)
10883 value = fixP->fx_offset;
10884 #endif
10885
10886 /* We are going to store value (shifted right by two) in the
10887 instruction, in a 24 bit, signed field. Thus we need to check
10888 that none of the top 8 bits of the shifted value (top 7 bits of
10889 the unshifted, unsigned value) are set, or that they are all set. */
10890 if ((value & ~ ((offsetT) 0x1ffffff)) != 0
10891 && ((value & ~ ((offsetT) 0x1ffffff)) != ~ ((offsetT) 0x1ffffff)))
10892 {
10893 #ifdef OBJ_ELF
10894 /* Normally we would be stuck at this point, since we cannot store
10895 the absolute address that is the destination of the branch in the
10896 24 bits of the branch instruction. If however, we happen to know
10897 that the destination of the branch is in the same section as the
10898 branch instruciton itself, then we can compute the relocation for
10899 ourselves and not have to bother the linker with it.
10900
10901 FIXME: The tests for OBJ_ELF and ! target_oabi are only here
10902 because I have not worked out how to do this for OBJ_COFF or
10903 target_oabi. */
10904 if (! target_oabi
10905 && fixP->fx_addsy != NULL
10906 && S_IS_DEFINED (fixP->fx_addsy)
10907 && S_GET_SEGMENT (fixP->fx_addsy) == seg)
10908 {
10909 /* Get pc relative value to go into the branch. */
10910 value = * valP;
10911
10912 /* Permit a backward branch provided that enough bits
10913 are set. Allow a forwards branch, provided that
10914 enough bits are clear. */
10915 if ( (value & ~ ((offsetT) 0x1ffffff)) == ~ ((offsetT) 0x1ffffff)
10916 || (value & ~ ((offsetT) 0x1ffffff)) == 0)
10917 fixP->fx_done = 1;
10918 }
10919
10920 if (! fixP->fx_done)
10921 #endif
10922 as_bad_where (fixP->fx_file, fixP->fx_line,
10923 _("GAS can't handle same-section branch dest >= 0x04000000"));
10924 }
10925
10926 value >>= 2;
10927 value += SEXT24 (newval);
10928
10929 if ( (value & ~ ((offsetT) 0xffffff)) != 0
10930 && ((value & ~ ((offsetT) 0xffffff)) != ~ ((offsetT) 0xffffff)))
10931 as_bad_where (fixP->fx_file, fixP->fx_line,
10932 _("out of range branch"));
10933
10934 newval = (value & 0x00ffffff) | (newval & 0xff000000);
10935 md_number_to_chars (buf, newval, INSN_SIZE);
10936 break;
10937
10938 case BFD_RELOC_ARM_PCREL_BLX:
10939 {
10940 offsetT hbit;
10941 newval = md_chars_to_number (buf, INSN_SIZE);
10942
10943 #ifdef OBJ_ELF
10944 if (! target_oabi)
10945 value = fixP->fx_offset;
10946 #endif
10947 hbit = (value >> 1) & 1;
10948 value = (value >> 2) & 0x00ffffff;
10949 value = (value + (newval & 0x00ffffff)) & 0x00ffffff;
10950 newval = value | (newval & 0xfe000000) | (hbit << 24);
10951 md_number_to_chars (buf, newval, INSN_SIZE);
10952 }
10953 break;
10954
10955 case BFD_RELOC_THUMB_PCREL_BRANCH9: /* Conditional branch. */
10956 newval = md_chars_to_number (buf, THUMB_SIZE);
10957 {
10958 addressT diff = (newval & 0xff) << 1;
10959 if (diff & 0x100)
10960 diff |= ~0xff;
10961
10962 value += diff;
10963 if ((value & ~0xff) && ((value & ~0xff) != ~0xff))
10964 as_bad_where (fixP->fx_file, fixP->fx_line,
10965 _("branch out of range"));
10966 newval = (newval & 0xff00) | ((value & 0x1ff) >> 1);
10967 }
10968 md_number_to_chars (buf, newval, THUMB_SIZE);
10969 break;
10970
10971 case BFD_RELOC_THUMB_PCREL_BRANCH12: /* Unconditional branch. */
10972 newval = md_chars_to_number (buf, THUMB_SIZE);
10973 {
10974 addressT diff = (newval & 0x7ff) << 1;
10975 if (diff & 0x800)
10976 diff |= ~0x7ff;
10977
10978 value += diff;
10979 if ((value & ~0x7ff) && ((value & ~0x7ff) != ~0x7ff))
10980 as_bad_where (fixP->fx_file, fixP->fx_line,
10981 _("branch out of range"));
10982 newval = (newval & 0xf800) | ((value & 0xfff) >> 1);
10983 }
10984 md_number_to_chars (buf, newval, THUMB_SIZE);
10985 break;
10986
10987 case BFD_RELOC_THUMB_PCREL_BLX:
10988 case BFD_RELOC_THUMB_PCREL_BRANCH23:
10989 {
10990 offsetT newval2;
10991 addressT diff;
10992
10993 newval = md_chars_to_number (buf, THUMB_SIZE);
10994 newval2 = md_chars_to_number (buf + THUMB_SIZE, THUMB_SIZE);
10995 diff = ((newval & 0x7ff) << 12) | ((newval2 & 0x7ff) << 1);
10996 if (diff & 0x400000)
10997 diff |= ~0x3fffff;
10998 #ifdef OBJ_ELF
10999 value = fixP->fx_offset;
11000 #endif
11001 value += diff;
11002
11003 if ((value & ~0x3fffff) && ((value & ~0x3fffff) != ~0x3fffff))
11004 as_bad_where (fixP->fx_file, fixP->fx_line,
11005 _("branch with link out of range"));
11006
11007 newval = (newval & 0xf800) | ((value & 0x7fffff) >> 12);
11008 newval2 = (newval2 & 0xf800) | ((value & 0xfff) >> 1);
11009 if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX)
11010 /* For a BLX instruction, make sure that the relocation is rounded up
11011 to a word boundary. This follows the semantics of the instruction
11012 which specifies that bit 1 of the target address will come from bit
11013 1 of the base address. */
11014 newval2 = (newval2 + 1) & ~ 1;
11015 md_number_to_chars (buf, newval, THUMB_SIZE);
11016 md_number_to_chars (buf + THUMB_SIZE, newval2, THUMB_SIZE);
11017 }
11018 break;
11019
11020 case BFD_RELOC_8:
11021 if (fixP->fx_done || fixP->fx_pcrel)
11022 md_number_to_chars (buf, value, 1);
11023 #ifdef OBJ_ELF
11024 else if (!target_oabi)
11025 {
11026 value = fixP->fx_offset;
11027 md_number_to_chars (buf, value, 1);
11028 }
11029 #endif
11030 break;
11031
11032 case BFD_RELOC_16:
11033 if (fixP->fx_done || fixP->fx_pcrel)
11034 md_number_to_chars (buf, value, 2);
11035 #ifdef OBJ_ELF
11036 else if (!target_oabi)
11037 {
11038 value = fixP->fx_offset;
11039 md_number_to_chars (buf, value, 2);
11040 }
11041 #endif
11042 break;
11043
11044 #ifdef OBJ_ELF
11045 case BFD_RELOC_ARM_GOT32:
11046 case BFD_RELOC_ARM_GOTOFF:
11047 md_number_to_chars (buf, 0, 4);
11048 break;
11049 #endif
11050
11051 case BFD_RELOC_RVA:
11052 case BFD_RELOC_32:
11053 if (fixP->fx_done || fixP->fx_pcrel)
11054 md_number_to_chars (buf, value, 4);
11055 #ifdef OBJ_ELF
11056 else if (!target_oabi)
11057 {
11058 value = fixP->fx_offset;
11059 md_number_to_chars (buf, value, 4);
11060 }
11061 #endif
11062 break;
11063
11064 #ifdef OBJ_ELF
11065 case BFD_RELOC_ARM_PLT32:
11066 /* It appears the instruction is fully prepared at this point. */
11067 break;
11068 #endif
11069
11070 case BFD_RELOC_ARM_CP_OFF_IMM:
11071 sign = value >= 0;
11072 if (value < -1023 || value > 1023 || (value & 3))
11073 as_bad_where (fixP->fx_file, fixP->fx_line,
11074 _("illegal value for co-processor offset"));
11075 if (value < 0)
11076 value = -value;
11077 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
11078 newval |= (value >> 2) | (sign ? INDEX_UP : 0);
11079 md_number_to_chars (buf, newval, INSN_SIZE);
11080 break;
11081
11082 case BFD_RELOC_ARM_CP_OFF_IMM_S2:
11083 sign = value >= 0;
11084 if (value < -255 || value > 255)
11085 as_bad_where (fixP->fx_file, fixP->fx_line,
11086 _("Illegal value for co-processor offset"));
11087 if (value < 0)
11088 value = -value;
11089 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
11090 newval |= value | (sign ? INDEX_UP : 0);
11091 md_number_to_chars (buf, newval , INSN_SIZE);
11092 break;
11093
11094 case BFD_RELOC_ARM_THUMB_OFFSET:
11095 newval = md_chars_to_number (buf, THUMB_SIZE);
11096 /* Exactly what ranges, and where the offset is inserted depends
11097 on the type of instruction, we can establish this from the
11098 top 4 bits. */
11099 switch (newval >> 12)
11100 {
11101 case 4: /* PC load. */
11102 /* Thumb PC loads are somewhat odd, bit 1 of the PC is
11103 forced to zero for these loads, so we will need to round
11104 up the offset if the instruction address is not word
11105 aligned (since the final address produced must be, and
11106 we can only describe word-aligned immediate offsets). */
11107
11108 if ((fixP->fx_frag->fr_address + fixP->fx_where + value) & 3)
11109 as_bad_where (fixP->fx_file, fixP->fx_line,
11110 _("invalid offset, target not word aligned (0x%08X)"),
11111 (unsigned int) (fixP->fx_frag->fr_address
11112 + fixP->fx_where + value));
11113
11114 if ((value + 2) & ~0x3fe)
11115 as_bad_where (fixP->fx_file, fixP->fx_line,
11116 _("invalid offset, value too big (0x%08lX)"),
11117 (long) value);
11118
11119 /* Round up, since pc will be rounded down. */
11120 newval |= (value + 2) >> 2;
11121 break;
11122
11123 case 9: /* SP load/store. */
11124 if (value & ~0x3fc)
11125 as_bad_where (fixP->fx_file, fixP->fx_line,
11126 _("invalid offset, value too big (0x%08lX)"),
11127 (long) value);
11128 newval |= value >> 2;
11129 break;
11130
11131 case 6: /* Word load/store. */
11132 if (value & ~0x7c)
11133 as_bad_where (fixP->fx_file, fixP->fx_line,
11134 _("invalid offset, value too big (0x%08lX)"),
11135 (long) value);
11136 newval |= value << 4; /* 6 - 2. */
11137 break;
11138
11139 case 7: /* Byte load/store. */
11140 if (value & ~0x1f)
11141 as_bad_where (fixP->fx_file, fixP->fx_line,
11142 _("invalid offset, value too big (0x%08lX)"),
11143 (long) value);
11144 newval |= value << 6;
11145 break;
11146
11147 case 8: /* Halfword load/store. */
11148 if (value & ~0x3e)
11149 as_bad_where (fixP->fx_file, fixP->fx_line,
11150 _("invalid offset, value too big (0x%08lX)"),
11151 (long) value);
11152 newval |= value << 5; /* 6 - 1. */
11153 break;
11154
11155 default:
11156 as_bad_where (fixP->fx_file, fixP->fx_line,
11157 "Unable to process relocation for thumb opcode: %lx",
11158 (unsigned long) newval);
11159 break;
11160 }
11161 md_number_to_chars (buf, newval, THUMB_SIZE);
11162 break;
11163
11164 case BFD_RELOC_ARM_THUMB_ADD:
11165 /* This is a complicated relocation, since we use it for all of
11166 the following immediate relocations:
11167
11168 3bit ADD/SUB
11169 8bit ADD/SUB
11170 9bit ADD/SUB SP word-aligned
11171 10bit ADD PC/SP word-aligned
11172
11173 The type of instruction being processed is encoded in the
11174 instruction field:
11175
11176 0x8000 SUB
11177 0x00F0 Rd
11178 0x000F Rs
11179 */
11180 newval = md_chars_to_number (buf, THUMB_SIZE);
11181 {
11182 int rd = (newval >> 4) & 0xf;
11183 int rs = newval & 0xf;
11184 int subtract = newval & 0x8000;
11185
11186 if (rd == REG_SP)
11187 {
11188 if (value & ~0x1fc)
11189 as_bad_where (fixP->fx_file, fixP->fx_line,
11190 _("invalid immediate for stack address calculation"));
11191 newval = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
11192 newval |= value >> 2;
11193 }
11194 else if (rs == REG_PC || rs == REG_SP)
11195 {
11196 if (subtract ||
11197 value & ~0x3fc)
11198 as_bad_where (fixP->fx_file, fixP->fx_line,
11199 _("invalid immediate for address calculation (value = 0x%08lX)"),
11200 (unsigned long) value);
11201 newval = (rs == REG_PC ? T_OPCODE_ADD_PC : T_OPCODE_ADD_SP);
11202 newval |= rd << 8;
11203 newval |= value >> 2;
11204 }
11205 else if (rs == rd)
11206 {
11207 if (value & ~0xff)
11208 as_bad_where (fixP->fx_file, fixP->fx_line,
11209 _("invalid 8bit immediate"));
11210 newval = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
11211 newval |= (rd << 8) | value;
11212 }
11213 else
11214 {
11215 if (value & ~0x7)
11216 as_bad_where (fixP->fx_file, fixP->fx_line,
11217 _("invalid 3bit immediate"));
11218 newval = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
11219 newval |= rd | (rs << 3) | (value << 6);
11220 }
11221 }
11222 md_number_to_chars (buf, newval, THUMB_SIZE);
11223 break;
11224
11225 case BFD_RELOC_ARM_THUMB_IMM:
11226 newval = md_chars_to_number (buf, THUMB_SIZE);
11227 switch (newval >> 11)
11228 {
11229 case 0x04: /* 8bit immediate MOV. */
11230 case 0x05: /* 8bit immediate CMP. */
11231 if (value < 0 || value > 255)
11232 as_bad_where (fixP->fx_file, fixP->fx_line,
11233 _("invalid immediate: %ld is too large"),
11234 (long) value);
11235 newval |= value;
11236 break;
11237
11238 default:
11239 abort ();
11240 }
11241 md_number_to_chars (buf, newval, THUMB_SIZE);
11242 break;
11243
11244 case BFD_RELOC_ARM_THUMB_SHIFT:
11245 /* 5bit shift value (0..31). */
11246 if (value < 0 || value > 31)
11247 as_bad_where (fixP->fx_file, fixP->fx_line,
11248 _("illegal Thumb shift value: %ld"), (long) value);
11249 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xf03f;
11250 newval |= value << 6;
11251 md_number_to_chars (buf, newval, THUMB_SIZE);
11252 break;
11253
11254 case BFD_RELOC_VTABLE_INHERIT:
11255 case BFD_RELOC_VTABLE_ENTRY:
11256 fixP->fx_done = 0;
11257 return;
11258
11259 case BFD_RELOC_NONE:
11260 default:
11261 as_bad_where (fixP->fx_file, fixP->fx_line,
11262 _("bad relocation fixup type (%d)"), fixP->fx_r_type);
11263 }
11264 }
11265
11266 /* Translate internal representation of relocation info to BFD target
11267 format. */
11268
11269 arelent *
11270 tc_gen_reloc (section, fixp)
11271 asection * section ATTRIBUTE_UNUSED;
11272 fixS * fixp;
11273 {
11274 arelent * reloc;
11275 bfd_reloc_code_real_type code;
11276
11277 reloc = (arelent *) xmalloc (sizeof (arelent));
11278
11279 reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
11280 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
11281 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
11282
11283 /* @@ Why fx_addnumber sometimes and fx_offset other times? */
11284 #ifndef OBJ_ELF
11285 if (fixp->fx_pcrel == 0)
11286 reloc->addend = fixp->fx_offset;
11287 else
11288 reloc->addend = fixp->fx_offset = reloc->address;
11289 #else /* OBJ_ELF */
11290 reloc->addend = fixp->fx_offset;
11291 #endif
11292
11293 switch (fixp->fx_r_type)
11294 {
11295 case BFD_RELOC_8:
11296 if (fixp->fx_pcrel)
11297 {
11298 code = BFD_RELOC_8_PCREL;
11299 break;
11300 }
11301
11302 case BFD_RELOC_16:
11303 if (fixp->fx_pcrel)
11304 {
11305 code = BFD_RELOC_16_PCREL;
11306 break;
11307 }
11308
11309 case BFD_RELOC_32:
11310 if (fixp->fx_pcrel)
11311 {
11312 code = BFD_RELOC_32_PCREL;
11313 break;
11314 }
11315
11316 case BFD_RELOC_ARM_PCREL_BRANCH:
11317 case BFD_RELOC_ARM_PCREL_BLX:
11318 case BFD_RELOC_RVA:
11319 case BFD_RELOC_THUMB_PCREL_BRANCH9:
11320 case BFD_RELOC_THUMB_PCREL_BRANCH12:
11321 case BFD_RELOC_THUMB_PCREL_BRANCH23:
11322 case BFD_RELOC_THUMB_PCREL_BLX:
11323 case BFD_RELOC_VTABLE_ENTRY:
11324 case BFD_RELOC_VTABLE_INHERIT:
11325 code = fixp->fx_r_type;
11326 break;
11327
11328 case BFD_RELOC_ARM_LITERAL:
11329 case BFD_RELOC_ARM_HWLITERAL:
11330 /* If this is called then the a literal has
11331 been referenced across a section boundary. */
11332 as_bad_where (fixp->fx_file, fixp->fx_line,
11333 _("literal referenced across section boundary"));
11334 return NULL;
11335
11336 #ifdef OBJ_ELF
11337 case BFD_RELOC_ARM_GOT32:
11338 case BFD_RELOC_ARM_GOTOFF:
11339 case BFD_RELOC_ARM_PLT32:
11340 code = fixp->fx_r_type;
11341 break;
11342 #endif
11343
11344 case BFD_RELOC_ARM_IMMEDIATE:
11345 as_bad_where (fixp->fx_file, fixp->fx_line,
11346 _("internal relocation (type: IMMEDIATE) not fixed up"));
11347 return NULL;
11348
11349 case BFD_RELOC_ARM_ADRL_IMMEDIATE:
11350 as_bad_where (fixp->fx_file, fixp->fx_line,
11351 _("ADRL used for a symbol not defined in the same file"));
11352 return NULL;
11353
11354 case BFD_RELOC_ARM_OFFSET_IMM:
11355 as_bad_where (fixp->fx_file, fixp->fx_line,
11356 _("internal_relocation (type: OFFSET_IMM) not fixed up"));
11357 return NULL;
11358
11359 default:
11360 {
11361 char * type;
11362
11363 switch (fixp->fx_r_type)
11364 {
11365 case BFD_RELOC_ARM_OFFSET_IMM8: type = "OFFSET_IMM8"; break;
11366 case BFD_RELOC_ARM_SHIFT_IMM: type = "SHIFT_IMM"; break;
11367 case BFD_RELOC_ARM_SWI: type = "SWI"; break;
11368 case BFD_RELOC_ARM_MULTI: type = "MULTI"; break;
11369 case BFD_RELOC_ARM_CP_OFF_IMM: type = "CP_OFF_IMM"; break;
11370 case BFD_RELOC_ARM_THUMB_ADD: type = "THUMB_ADD"; break;
11371 case BFD_RELOC_ARM_THUMB_SHIFT: type = "THUMB_SHIFT"; break;
11372 case BFD_RELOC_ARM_THUMB_IMM: type = "THUMB_IMM"; break;
11373 case BFD_RELOC_ARM_THUMB_OFFSET: type = "THUMB_OFFSET"; break;
11374 default: type = _("<unknown>"); break;
11375 }
11376 as_bad_where (fixp->fx_file, fixp->fx_line,
11377 _("cannot represent %s relocation in this object file format"),
11378 type);
11379 return NULL;
11380 }
11381 }
11382
11383 #ifdef OBJ_ELF
11384 if ((code == BFD_RELOC_32_PCREL || code == BFD_RELOC_32)
11385 && GOT_symbol
11386 && fixp->fx_addsy == GOT_symbol)
11387 {
11388 code = BFD_RELOC_ARM_GOTPC;
11389 reloc->addend = fixp->fx_offset = reloc->address;
11390 }
11391 #endif
11392
11393 reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
11394
11395 if (reloc->howto == NULL)
11396 {
11397 as_bad_where (fixp->fx_file, fixp->fx_line,
11398 _("cannot represent %s relocation in this object file format"),
11399 bfd_get_reloc_code_name (code));
11400 return NULL;
11401 }
11402
11403 /* HACK: Since arm ELF uses Rel instead of Rela, encode the
11404 vtable entry to be used in the relocation's section offset. */
11405 if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
11406 reloc->address = fixp->fx_offset;
11407
11408 return reloc;
11409 }
11410
11411 int
11412 md_estimate_size_before_relax (fragP, segtype)
11413 fragS * fragP ATTRIBUTE_UNUSED;
11414 segT segtype ATTRIBUTE_UNUSED;
11415 {
11416 as_fatal (_("md_estimate_size_before_relax\n"));
11417 return 1;
11418 }
11419
11420 static void
11421 output_inst (str)
11422 const char *str;
11423 {
11424 char * to = NULL;
11425
11426 if (inst.error)
11427 {
11428 as_bad ("%s -- `%s'", inst.error, str);
11429 return;
11430 }
11431
11432 to = frag_more (inst.size);
11433
11434 if (thumb_mode && (inst.size > THUMB_SIZE))
11435 {
11436 assert (inst.size == (2 * THUMB_SIZE));
11437 md_number_to_chars (to, inst.instruction >> 16, THUMB_SIZE);
11438 md_number_to_chars (to + THUMB_SIZE, inst.instruction, THUMB_SIZE);
11439 }
11440 else if (inst.size > INSN_SIZE)
11441 {
11442 assert (inst.size == (2 * INSN_SIZE));
11443 md_number_to_chars (to, inst.instruction, INSN_SIZE);
11444 md_number_to_chars (to + INSN_SIZE, inst.instruction, INSN_SIZE);
11445 }
11446 else
11447 md_number_to_chars (to, inst.instruction, inst.size);
11448
11449 if (inst.reloc.type != BFD_RELOC_NONE)
11450 fix_new_arm (frag_now, to - frag_now->fr_literal,
11451 inst.size, & inst.reloc.exp, inst.reloc.pc_rel,
11452 inst.reloc.type);
11453
11454 #ifdef OBJ_ELF
11455 dwarf2_emit_insn (inst.size);
11456 #endif
11457 }
11458
11459 void
11460 md_assemble (str)
11461 char * str;
11462 {
11463 char c;
11464 char *p;
11465 char *start;
11466
11467 /* Align the instruction.
11468 This may not be the right thing to do but ... */
11469 #if 0
11470 arm_align (2, 0);
11471 #endif
11472
11473 /* Align the previous label if needed. */
11474 if (last_label_seen != NULL)
11475 {
11476 symbol_set_frag (last_label_seen, frag_now);
11477 S_SET_VALUE (last_label_seen, (valueT) frag_now_fix ());
11478 S_SET_SEGMENT (last_label_seen, now_seg);
11479 }
11480
11481 memset (&inst, '\0', sizeof (inst));
11482 inst.reloc.type = BFD_RELOC_NONE;
11483
11484 skip_whitespace (str);
11485
11486 /* Scan up to the end of the op-code, which must end in white space or
11487 end of string. */
11488 for (start = p = str; *p != '\0'; p++)
11489 if (*p == ' ')
11490 break;
11491
11492 if (p == str)
11493 {
11494 as_bad (_("no operator -- statement `%s'\n"), str);
11495 return;
11496 }
11497
11498 if (thumb_mode)
11499 {
11500 const struct thumb_opcode * opcode;
11501
11502 c = *p;
11503 *p = '\0';
11504 opcode = (const struct thumb_opcode *) hash_find (arm_tops_hsh, str);
11505 *p = c;
11506
11507 if (opcode)
11508 {
11509 /* Check that this instruction is supported for this CPU. */
11510 if (thumb_mode == 1 && (opcode->variant & cpu_variant) == 0)
11511 {
11512 as_bad (_("selected processor does not support `%s'"), str);
11513 return;
11514 }
11515
11516 inst.instruction = opcode->value;
11517 inst.size = opcode->size;
11518 (*opcode->parms) (p);
11519 output_inst (str);
11520 return;
11521 }
11522 }
11523 else
11524 {
11525 const struct asm_opcode * opcode;
11526
11527 c = *p;
11528 *p = '\0';
11529 opcode = (const struct asm_opcode *) hash_find (arm_ops_hsh, str);
11530 *p = c;
11531
11532 if (opcode)
11533 {
11534 /* Check that this instruction is supported for this CPU. */
11535 if ((opcode->variant & cpu_variant) == 0)
11536 {
11537 as_bad (_("selected processor does not support `%s'"), str);
11538 return;
11539 }
11540
11541 inst.instruction = opcode->value;
11542 inst.size = INSN_SIZE;
11543 (*opcode->parms) (p);
11544 output_inst (str);
11545 return;
11546 }
11547 }
11548
11549 /* It wasn't an instruction, but it might be a register alias of the form
11550 alias .req reg. */
11551 if (create_register_alias (str, p))
11552 return;
11553
11554 as_bad (_("bad instruction `%s'"), start);
11555 }
11556
11557 /* md_parse_option
11558 Invocation line includes a switch not recognized by the base assembler.
11559 See if it's a processor-specific option.
11560
11561 This routine is somewhat complicated by the need for backwards
11562 compatibility (since older releases of gcc can't be changed).
11563 The new options try to make the interface as compatible as
11564 possible with GCC.
11565
11566 New options (supported) are:
11567
11568 -mcpu=<cpu name> Assemble for selected processor
11569 -march=<architecture name> Assemble for selected architecture
11570 -mfpu=<fpu architecture> Assemble for selected FPU.
11571 -EB/-mbig-endian Big-endian
11572 -EL/-mlittle-endian Little-endian
11573 -k Generate PIC code
11574 -mthumb Start in Thumb mode
11575 -mthumb-interwork Code supports ARM/Thumb interworking
11576
11577 For now we will also provide support for:
11578
11579 -mapcs-32 32-bit Program counter
11580 -mapcs-26 26-bit Program counter
11581 -macps-float Floats passed in FP registers
11582 -mapcs-reentrant Reentrant code
11583 -matpcs
11584 (sometime these will probably be replaced with -mapcs=<list of options>
11585 and -matpcs=<list of options>)
11586
11587 The remaining options are only supported for back-wards compatibility.
11588 Cpu variants, the arm part is optional:
11589 -m[arm]1 Currently not supported.
11590 -m[arm]2, -m[arm]250 Arm 2 and Arm 250 processor
11591 -m[arm]3 Arm 3 processor
11592 -m[arm]6[xx], Arm 6 processors
11593 -m[arm]7[xx][t][[d]m] Arm 7 processors
11594 -m[arm]8[10] Arm 8 processors
11595 -m[arm]9[20][tdmi] Arm 9 processors
11596 -mstrongarm[110[0]] StrongARM processors
11597 -mxscale XScale processors
11598 -m[arm]v[2345[t[e]]] Arm architectures
11599 -mall All (except the ARM1)
11600 FP variants:
11601 -mfpa10, -mfpa11 FPA10 and 11 co-processor instructions
11602 -mfpe-old (No float load/store multiples)
11603 -mvfpxd VFP Single precision
11604 -mvfp All VFP
11605 -mno-fpu Disable all floating point instructions
11606
11607 The following CPU names are recognized:
11608 arm1, arm2, arm250, arm3, arm6, arm600, arm610, arm620,
11609 arm7, arm7m, arm7d, arm7dm, arm7di, arm7dmi, arm70, arm700,
11610 arm700i, arm710 arm710t, arm720, arm720t, arm740t, arm710c,
11611 arm7100, arm7500, arm7500fe, arm7tdmi, arm8, arm810, arm9,
11612 arm920, arm920t, arm940t, arm946, arm966, arm9tdmi, arm9e,
11613 arm10t arm10e, arm1020t, arm1020e, arm10200e,
11614 strongarm, strongarm110, strongarm1100, strongarm1110, xscale.
11615
11616 */
11617
11618 const char * md_shortopts = "m:k";
11619
11620 #ifdef ARM_BI_ENDIAN
11621 #define OPTION_EB (OPTION_MD_BASE + 0)
11622 #define OPTION_EL (OPTION_MD_BASE + 1)
11623 #else
11624 #if TARGET_BYTES_BIG_ENDIAN
11625 #define OPTION_EB (OPTION_MD_BASE + 0)
11626 #else
11627 #define OPTION_EL (OPTION_MD_BASE + 1)
11628 #endif
11629 #endif
11630
11631 struct option md_longopts[] =
11632 {
11633 #ifdef OPTION_EB
11634 {"EB", no_argument, NULL, OPTION_EB},
11635 #endif
11636 #ifdef OPTION_EL
11637 {"EL", no_argument, NULL, OPTION_EL},
11638 #endif
11639 {NULL, no_argument, NULL, 0}
11640 };
11641
11642 size_t md_longopts_size = sizeof (md_longopts);
11643
11644 struct arm_option_table
11645 {
11646 char *option; /* Option name to match. */
11647 char *help; /* Help information. */
11648 int *var; /* Variable to change. */
11649 int value; /* What to change it to. */
11650 char *deprecated; /* If non-null, print this message. */
11651 };
11652
11653 struct arm_option_table arm_opts[] =
11654 {
11655 {"k", N_("generate PIC code"), &pic_code, 1, NULL},
11656 {"mthumb", N_("assemble Thumb code"), &thumb_mode, 1, NULL},
11657 {"mthumb-interwork", N_("support ARM/Thumb interworking"),
11658 &support_interwork, 1, NULL},
11659 {"moabi", N_("use old ABI (ELF only)"), &target_oabi, 1, NULL},
11660 {"mapcs-32", N_("code uses 32-bit program counter"), &uses_apcs_26, 0, NULL},
11661 {"mapcs-26", N_("code uses 26-bit program counter"), &uses_apcs_26, 1, NULL},
11662 {"mapcs-float", N_("floating point args are in fp regs"), &uses_apcs_float,
11663 1, NULL},
11664 {"mapcs-reentrant", N_("re-entrant code"), &pic_code, 1, NULL},
11665 {"matpcs", N_("code is ATPCS conformant"), &atpcs, 1, NULL},
11666 {"mbig-endian", N_("assemble for big-endian"), &target_big_endian, 1, NULL},
11667 {"mlittle-endian", N_("assemble for little-endian"), &target_big_endian, 1,
11668 NULL},
11669
11670 /* These are recognized by the assembler, but have no affect on code. */
11671 {"mapcs-frame", N_("use frame pointer"), NULL, 0, NULL},
11672 {"mapcs-stack-check", N_("use stack size checking"), NULL, 0, NULL},
11673
11674 /* DON'T add any new processors to this list -- we want the whole list
11675 to go away... Add them to the processors table instead. */
11676 {"marm1", NULL, &legacy_cpu, ARM_ARCH_V1, N_("use -mcpu=arm1")},
11677 {"m1", NULL, &legacy_cpu, ARM_ARCH_V1, N_("use -mcpu=arm1")},
11678 {"marm2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -mcpu=arm2")},
11679 {"m2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -mcpu=arm2")},
11680 {"marm250", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm250")},
11681 {"m250", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm250")},
11682 {"marm3", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm3")},
11683 {"m3", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm3")},
11684 {"marm6", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm6")},
11685 {"m6", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm6")},
11686 {"marm600", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm600")},
11687 {"m600", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm600")},
11688 {"marm610", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm610")},
11689 {"m610", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm610")},
11690 {"marm620", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm620")},
11691 {"m620", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm620")},
11692 {"marm7", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7")},
11693 {"m7", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7")},
11694 {"marm70", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm70")},
11695 {"m70", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm70")},
11696 {"marm700", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700")},
11697 {"m700", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700")},
11698 {"marm700i", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700i")},
11699 {"m700i", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700i")},
11700 {"marm710", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710")},
11701 {"m710", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710")},
11702 {"marm710c", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710c")},
11703 {"m710c", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710c")},
11704 {"marm720", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm720")},
11705 {"m720", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm720")},
11706 {"marm7d", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7d")},
11707 {"m7d", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7d")},
11708 {"marm7di", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7di")},
11709 {"m7di", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7di")},
11710 {"marm7m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7m")},
11711 {"m7m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7m")},
11712 {"marm7dm", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dm")},
11713 {"m7dm", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dm")},
11714 {"marm7dmi", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dmi")},
11715 {"m7dmi", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dmi")},
11716 {"marm7100", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7100")},
11717 {"m7100", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7100")},
11718 {"marm7500", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500")},
11719 {"m7500", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500")},
11720 {"marm7500fe", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500fe")},
11721 {"m7500fe", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500fe")},
11722 {"marm7t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
11723 {"m7t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
11724 {"marm7tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
11725 {"m7tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
11726 {"marm710t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm710t")},
11727 {"m710t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm710t")},
11728 {"marm720t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm720t")},
11729 {"m720t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm720t")},
11730 {"marm740t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm740t")},
11731 {"m740t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm740t")},
11732 {"marm8", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm8")},
11733 {"m8", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm8")},
11734 {"marm810", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm810")},
11735 {"m810", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm810")},
11736 {"marm9", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9")},
11737 {"m9", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9")},
11738 {"marm9tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9tdmi")},
11739 {"m9tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9tdmi")},
11740 {"marm920", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm920")},
11741 {"m920", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm920")},
11742 {"marm940", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm940")},
11743 {"m940", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm940")},
11744 {"mstrongarm", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=strongarm")},
11745 {"mstrongarm110", NULL, &legacy_cpu, ARM_ARCH_V4,
11746 N_("use -mcpu=strongarm110")},
11747 {"mstrongarm1100", NULL, &legacy_cpu, ARM_ARCH_V4,
11748 N_("use -mcpu=strongarm1100")},
11749 {"mstrongarm1110", NULL, &legacy_cpu, ARM_ARCH_V4,
11750 N_("use -mcpu=strongarm1110")},
11751 {"mxscale", NULL, &legacy_cpu, ARM_ARCH_XSCALE, N_("use -mcpu=xscale")},
11752 {"miwmmxt", NULL, &legacy_cpu, ARM_ARCH_IWMMXT, N_("use -mcpu=iwmmxt")},
11753 {"mall", NULL, &legacy_cpu, ARM_ANY, N_("use -mcpu=all")},
11754
11755 /* Architecture variants -- don't add any more to this list either. */
11756 {"mv2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -march=armv2")},
11757 {"marmv2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -march=armv2")},
11758 {"mv2a", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -march=armv2a")},
11759 {"marmv2a", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -march=armv2a")},
11760 {"mv3", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -march=armv3")},
11761 {"marmv3", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -march=armv3")},
11762 {"mv3m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -march=armv3m")},
11763 {"marmv3m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -march=armv3m")},
11764 {"mv4", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -march=armv4")},
11765 {"marmv4", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -march=armv4")},
11766 {"mv4t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -march=armv4t")},
11767 {"marmv4t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -march=armv4t")},
11768 {"mv5", NULL, &legacy_cpu, ARM_ARCH_V5, N_("use -march=armv5")},
11769 {"marmv5", NULL, &legacy_cpu, ARM_ARCH_V5, N_("use -march=armv5")},
11770 {"mv5t", NULL, &legacy_cpu, ARM_ARCH_V5T, N_("use -march=armv5t")},
11771 {"marmv5t", NULL, &legacy_cpu, ARM_ARCH_V5T, N_("use -march=armv5t")},
11772 {"mv5e", NULL, &legacy_cpu, ARM_ARCH_V5TE, N_("use -march=armv5te")},
11773 {"marmv5e", NULL, &legacy_cpu, ARM_ARCH_V5TE, N_("use -march=armv5te")},
11774
11775 /* Floating point variants -- don't add any more to this list either. */
11776 {"mfpe-old", NULL, &legacy_fpu, FPU_ARCH_FPE, N_("use -mfpu=fpe")},
11777 {"mfpa10", NULL, &legacy_fpu, FPU_ARCH_FPA, N_("use -mfpu=fpa10")},
11778 {"mfpa11", NULL, &legacy_fpu, FPU_ARCH_FPA, N_("use -mfpu=fpa11")},
11779 {"mno-fpu", NULL, &legacy_fpu, 0,
11780 N_("use either -mfpu=softfpa or -mfpu=softvfp")},
11781
11782 {NULL, NULL, NULL, 0, NULL}
11783 };
11784
11785 struct arm_cpu_option_table
11786 {
11787 char *name;
11788 int value;
11789 /* For some CPUs we assume an FPU unless the user explicitly sets
11790 -mfpu=... */
11791 int default_fpu;
11792 };
11793
11794 /* This list should, at a minimum, contain all the cpu names
11795 recognized by GCC. */
11796 static struct arm_cpu_option_table arm_cpus[] =
11797 {
11798 {"all", ARM_ANY, FPU_ARCH_FPA},
11799 {"arm1", ARM_ARCH_V1, FPU_ARCH_FPA},
11800 {"arm2", ARM_ARCH_V2, FPU_ARCH_FPA},
11801 {"arm250", ARM_ARCH_V2S, FPU_ARCH_FPA},
11802 {"arm3", ARM_ARCH_V2S, FPU_ARCH_FPA},
11803 {"arm6", ARM_ARCH_V3, FPU_ARCH_FPA},
11804 {"arm60", ARM_ARCH_V3, FPU_ARCH_FPA},
11805 {"arm600", ARM_ARCH_V3, FPU_ARCH_FPA},
11806 {"arm610", ARM_ARCH_V3, FPU_ARCH_FPA},
11807 {"arm620", ARM_ARCH_V3, FPU_ARCH_FPA},
11808 {"arm7", ARM_ARCH_V3, FPU_ARCH_FPA},
11809 {"arm7m", ARM_ARCH_V3M, FPU_ARCH_FPA},
11810 {"arm7d", ARM_ARCH_V3, FPU_ARCH_FPA},
11811 {"arm7dm", ARM_ARCH_V3M, FPU_ARCH_FPA},
11812 {"arm7di", ARM_ARCH_V3, FPU_ARCH_FPA},
11813 {"arm7dmi", ARM_ARCH_V3M, FPU_ARCH_FPA},
11814 {"arm70", ARM_ARCH_V3, FPU_ARCH_FPA},
11815 {"arm700", ARM_ARCH_V3, FPU_ARCH_FPA},
11816 {"arm700i", ARM_ARCH_V3, FPU_ARCH_FPA},
11817 {"arm710", ARM_ARCH_V3, FPU_ARCH_FPA},
11818 {"arm710t", ARM_ARCH_V4T, FPU_ARCH_FPA},
11819 {"arm720", ARM_ARCH_V3, FPU_ARCH_FPA},
11820 {"arm720t", ARM_ARCH_V4T, FPU_ARCH_FPA},
11821 {"arm740t", ARM_ARCH_V4T, FPU_ARCH_FPA},
11822 {"arm710c", ARM_ARCH_V3, FPU_ARCH_FPA},
11823 {"arm7100", ARM_ARCH_V3, FPU_ARCH_FPA},
11824 {"arm7500", ARM_ARCH_V3, FPU_ARCH_FPA},
11825 {"arm7500fe", ARM_ARCH_V3, FPU_ARCH_FPA},
11826 {"arm7t", ARM_ARCH_V4T, FPU_ARCH_FPA},
11827 {"arm7tdmi", ARM_ARCH_V4T, FPU_ARCH_FPA},
11828 {"arm8", ARM_ARCH_V4, FPU_ARCH_FPA},
11829 {"arm810", ARM_ARCH_V4, FPU_ARCH_FPA},
11830 {"strongarm", ARM_ARCH_V4, FPU_ARCH_FPA},
11831 {"strongarm1", ARM_ARCH_V4, FPU_ARCH_FPA},
11832 {"strongarm110", ARM_ARCH_V4, FPU_ARCH_FPA},
11833 {"strongarm1100", ARM_ARCH_V4, FPU_ARCH_FPA},
11834 {"strongarm1110", ARM_ARCH_V4, FPU_ARCH_FPA},
11835 {"arm9", ARM_ARCH_V4T, FPU_ARCH_FPA},
11836 {"arm920", ARM_ARCH_V4T, FPU_ARCH_FPA},
11837 {"arm920t", ARM_ARCH_V4T, FPU_ARCH_FPA},
11838 {"arm922t", ARM_ARCH_V4T, FPU_ARCH_FPA},
11839 {"arm940t", ARM_ARCH_V4T, FPU_ARCH_FPA},
11840 {"arm9tdmi", ARM_ARCH_V4T, FPU_ARCH_FPA},
11841 /* For V5 or later processors we default to using VFP; but the user
11842 should really set the FPU type explicitly. */
11843 {"arm9e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
11844 {"arm9e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
11845 {"arm926ej", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
11846 {"arm946e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
11847 {"arm946e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
11848 {"arm966e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
11849 {"arm966e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
11850 {"arm10t", ARM_ARCH_V5T, FPU_ARCH_VFP_V1},
11851 {"arm10e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
11852 {"arm1020", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
11853 {"arm1020t", ARM_ARCH_V5T, FPU_ARCH_VFP_V1},
11854 {"arm1020e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
11855 /* ??? XSCALE is really an architecture. */
11856 {"xscale", ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2},
11857 /* ??? iwmmxt is not a processor. */
11858 {"iwmmxt", ARM_ARCH_IWMMXT, FPU_ARCH_VFP_V2},
11859 {"i80200", ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2},
11860 /* Maverick */
11861 {"ep9312", ARM_ARCH_V4T | ARM_CEXT_MAVERICK, FPU_NONE},
11862 {NULL, 0, 0}
11863 };
11864
11865 struct arm_arch_option_table
11866 {
11867 char *name;
11868 int value;
11869 int default_fpu;
11870 };
11871
11872 /* This list should, at a minimum, contain all the architecture names
11873 recognized by GCC. */
11874 static struct arm_arch_option_table arm_archs[] =
11875 {
11876 {"all", ARM_ANY, FPU_ARCH_FPA},
11877 {"armv1", ARM_ARCH_V1, FPU_ARCH_FPA},
11878 {"armv2", ARM_ARCH_V2, FPU_ARCH_FPA},
11879 {"armv2a", ARM_ARCH_V2S, FPU_ARCH_FPA},
11880 {"armv2s", ARM_ARCH_V2S, FPU_ARCH_FPA},
11881 {"armv3", ARM_ARCH_V3, FPU_ARCH_FPA},
11882 {"armv3m", ARM_ARCH_V3M, FPU_ARCH_FPA},
11883 {"armv4", ARM_ARCH_V4, FPU_ARCH_FPA},
11884 {"armv4xm", ARM_ARCH_V4xM, FPU_ARCH_FPA},
11885 {"armv4t", ARM_ARCH_V4T, FPU_ARCH_FPA},
11886 {"armv4txm", ARM_ARCH_V4TxM, FPU_ARCH_FPA},
11887 {"armv5", ARM_ARCH_V5, FPU_ARCH_VFP},
11888 {"armv5t", ARM_ARCH_V5T, FPU_ARCH_VFP},
11889 {"armv5txm", ARM_ARCH_V5TxM, FPU_ARCH_VFP},
11890 {"armv5te", ARM_ARCH_V5TE, FPU_ARCH_VFP},
11891 {"armv5texp", ARM_ARCH_V5TExP, FPU_ARCH_VFP},
11892 {"armv5tej", ARM_ARCH_V5TEJ, FPU_ARCH_VFP},
11893 {"xscale", ARM_ARCH_XSCALE, FPU_ARCH_VFP},
11894 {NULL, 0, 0}
11895 };
11896
11897 /* ISA extensions in the co-processor space. */
11898 struct arm_arch_extension_table
11899 {
11900 char *name;
11901 int value;
11902 };
11903
11904 static struct arm_arch_extension_table arm_extensions[] =
11905 {
11906 {"maverick", ARM_CEXT_MAVERICK},
11907 {"xscale", ARM_CEXT_XSCALE},
11908 {"iwmmxt", ARM_CEXT_IWMMXT},
11909 {NULL, 0}
11910 };
11911
11912 struct arm_fpu_option_table
11913 {
11914 char *name;
11915 int value;
11916 };
11917
11918 /* This list should, at a minimum, contain all the fpu names
11919 recognized by GCC. */
11920 static struct arm_fpu_option_table arm_fpus[] =
11921 {
11922 {"softfpa", FPU_NONE},
11923 {"fpe", FPU_ARCH_FPE},
11924 {"fpe2", FPU_ARCH_FPE},
11925 {"fpe3", FPU_ARCH_FPA}, /* Third release supports LFM/SFM. */
11926 {"fpa", FPU_ARCH_FPA},
11927 {"fpa10", FPU_ARCH_FPA},
11928 {"fpa11", FPU_ARCH_FPA},
11929 {"arm7500fe", FPU_ARCH_FPA},
11930 {"softvfp", FPU_ARCH_VFP},
11931 {"softvfp+vfp", FPU_ARCH_VFP_V2},
11932 {"vfp", FPU_ARCH_VFP_V2},
11933 {"vfp9", FPU_ARCH_VFP_V2},
11934 {"vfp10", FPU_ARCH_VFP_V2},
11935 {"vfp10-r0", FPU_ARCH_VFP_V1},
11936 {"vfpxd", FPU_ARCH_VFP_V1xD},
11937 {"arm1020t", FPU_ARCH_VFP_V1},
11938 {"arm1020e", FPU_ARCH_VFP_V2},
11939 {NULL, 0}
11940 };
11941
11942 struct arm_long_option_table
11943 {
11944 char *option; /* Substring to match. */
11945 char *help; /* Help information. */
11946 int (*func) PARAMS ((char *subopt)); /* Function to decode sub-option. */
11947 char *deprecated; /* If non-null, print this message. */
11948 };
11949
11950 static int
11951 arm_parse_extension (str, opt_p)
11952 char *str;
11953 int *opt_p;
11954 {
11955 while (str != NULL && *str != 0)
11956 {
11957 struct arm_arch_extension_table *opt;
11958 char *ext;
11959 int optlen;
11960
11961 if (*str != '+')
11962 {
11963 as_bad (_("invalid architectural extension"));
11964 return 0;
11965 }
11966
11967 str++;
11968 ext = strchr (str, '+');
11969
11970 if (ext != NULL)
11971 optlen = ext - str;
11972 else
11973 optlen = strlen (str);
11974
11975 if (optlen == 0)
11976 {
11977 as_bad (_("missing architectural extension"));
11978 return 0;
11979 }
11980
11981 for (opt = arm_extensions; opt->name != NULL; opt++)
11982 if (strncmp (opt->name, str, optlen) == 0)
11983 {
11984 *opt_p |= opt->value;
11985 break;
11986 }
11987
11988 if (opt->name == NULL)
11989 {
11990 as_bad (_("unknown architectural extnsion `%s'"), str);
11991 return 0;
11992 }
11993
11994 str = ext;
11995 };
11996
11997 return 1;
11998 }
11999
12000 static int
12001 arm_parse_cpu (str)
12002 char *str;
12003 {
12004 struct arm_cpu_option_table *opt;
12005 char *ext = strchr (str, '+');
12006 int optlen;
12007
12008 if (ext != NULL)
12009 optlen = ext - str;
12010 else
12011 optlen = strlen (str);
12012
12013 if (optlen == 0)
12014 {
12015 as_bad (_("missing cpu name `%s'"), str);
12016 return 0;
12017 }
12018
12019 for (opt = arm_cpus; opt->name != NULL; opt++)
12020 if (strncmp (opt->name, str, optlen) == 0)
12021 {
12022 mcpu_cpu_opt = opt->value;
12023 mcpu_fpu_opt = opt->default_fpu;
12024
12025 if (ext != NULL)
12026 return arm_parse_extension (ext, &mcpu_cpu_opt);
12027
12028 return 1;
12029 }
12030
12031 as_bad (_("unknown cpu `%s'"), str);
12032 return 0;
12033 }
12034
12035 static int
12036 arm_parse_arch (str)
12037 char *str;
12038 {
12039 struct arm_arch_option_table *opt;
12040 char *ext = strchr (str, '+');
12041 int optlen;
12042
12043 if (ext != NULL)
12044 optlen = ext - str;
12045 else
12046 optlen = strlen (str);
12047
12048 if (optlen == 0)
12049 {
12050 as_bad (_("missing architecture name `%s'"), str);
12051 return 0;
12052 }
12053
12054
12055 for (opt = arm_archs; opt->name != NULL; opt++)
12056 if (strcmp (opt->name, str) == 0)
12057 {
12058 march_cpu_opt = opt->value;
12059 march_fpu_opt = opt->default_fpu;
12060
12061 if (ext != NULL)
12062 return arm_parse_extension (ext, &march_cpu_opt);
12063
12064 return 1;
12065 }
12066
12067 as_bad (_("unknown architecture `%s'\n"), str);
12068 return 0;
12069 }
12070
12071 static int
12072 arm_parse_fpu (str)
12073 char *str;
12074 {
12075 struct arm_fpu_option_table *opt;
12076
12077 for (opt = arm_fpus; opt->name != NULL; opt++)
12078 if (strcmp (opt->name, str) == 0)
12079 {
12080 mfpu_opt = opt->value;
12081 return 1;
12082 }
12083
12084 as_bad (_("unknown floating point format `%s'\n"), str);
12085 return 0;
12086 }
12087
12088 struct arm_long_option_table arm_long_opts[] =
12089 {
12090 {"mcpu=", N_("<cpu name>\t assemble for CPU <cpu name>"),
12091 arm_parse_cpu, NULL},
12092 {"march=", N_("<arch name>\t assemble for architecture <arch name>"),
12093 arm_parse_arch, NULL},
12094 {"mfpu=", N_("<fpu name>\t assemble for FPU architecture <fpu name>"),
12095 arm_parse_fpu, NULL},
12096 {NULL, NULL, 0, NULL}
12097 };
12098
12099 int
12100 md_parse_option (c, arg)
12101 int c;
12102 char * arg;
12103 {
12104 struct arm_option_table *opt;
12105 struct arm_long_option_table *lopt;
12106
12107 switch (c)
12108 {
12109 #ifdef OPTION_EB
12110 case OPTION_EB:
12111 target_big_endian = 1;
12112 break;
12113 #endif
12114
12115 #ifdef OPTION_EL
12116 case OPTION_EL:
12117 target_big_endian = 0;
12118 break;
12119 #endif
12120
12121 case 'a':
12122 /* Listing option. Just ignore these, we don't support additional
12123 ones. */
12124 return 0;
12125
12126 default:
12127 for (opt = arm_opts; opt->option != NULL; opt++)
12128 {
12129 if (c == opt->option[0]
12130 && ((arg == NULL && opt->option[1] == 0)
12131 || strcmp (arg, opt->option + 1) == 0))
12132 {
12133 #if WARN_DEPRECATED
12134 /* If the option is deprecated, tell the user. */
12135 if (opt->deprecated != NULL)
12136 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c,
12137 arg ? arg : "", _(opt->deprecated));
12138 #endif
12139
12140 if (opt->var != NULL)
12141 *opt->var = opt->value;
12142
12143 return 1;
12144 }
12145 }
12146
12147 for (lopt = arm_long_opts; lopt->option != NULL; lopt++)
12148 {
12149 /* These options are expected to have an argument. */
12150 if (c == lopt->option[0]
12151 && arg != NULL
12152 && strncmp (arg, lopt->option + 1,
12153 strlen (lopt->option + 1)) == 0)
12154 {
12155 #if WARN_DEPRECATED
12156 /* If the option is deprecated, tell the user. */
12157 if (lopt->deprecated != NULL)
12158 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c, arg,
12159 _(lopt->deprecated));
12160 #endif
12161
12162 /* Call the sup-option parser. */
12163 return (*lopt->func)(arg + strlen (lopt->option) - 1);
12164 }
12165 }
12166
12167 as_bad (_("unrecognized option `-%c%s'"), c, arg ? arg : "");
12168 return 0;
12169 }
12170
12171 return 1;
12172 }
12173
12174 void
12175 md_show_usage (fp)
12176 FILE * fp;
12177 {
12178 struct arm_option_table *opt;
12179 struct arm_long_option_table *lopt;
12180
12181 fprintf (fp, _(" ARM-specific assembler options:\n"));
12182
12183 for (opt = arm_opts; opt->option != NULL; opt++)
12184 if (opt->help != NULL)
12185 fprintf (fp, " -%-23s%s\n", opt->option, _(opt->help));
12186
12187 for (lopt = arm_long_opts; lopt->option != NULL; lopt++)
12188 if (lopt->help != NULL)
12189 fprintf (fp, " -%s%s\n", lopt->option, _(lopt->help));
12190
12191 #ifdef OPTION_EB
12192 fprintf (fp, _("\
12193 -EB assemble code for a big-endian cpu\n"));
12194 #endif
12195
12196 #ifdef OPTION_EL
12197 fprintf (fp, _("\
12198 -EL assemble code for a little-endian cpu\n"));
12199 #endif
12200 }
12201
12202 /* We need to be able to fix up arbitrary expressions in some statements.
12203 This is so that we can handle symbols that are an arbitrary distance from
12204 the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
12205 which returns part of an address in a form which will be valid for
12206 a data instruction. We do this by pushing the expression into a symbol
12207 in the expr_section, and creating a fix for that. */
12208
12209 static void
12210 fix_new_arm (frag, where, size, exp, pc_rel, reloc)
12211 fragS * frag;
12212 int where;
12213 short int size;
12214 expressionS * exp;
12215 int pc_rel;
12216 int reloc;
12217 {
12218 fixS * new_fix;
12219 arm_fix_data * arm_data;
12220
12221 switch (exp->X_op)
12222 {
12223 case O_constant:
12224 case O_symbol:
12225 case O_add:
12226 case O_subtract:
12227 new_fix = fix_new_exp (frag, where, size, exp, pc_rel, reloc);
12228 break;
12229
12230 default:
12231 new_fix = fix_new (frag, where, size, make_expr_symbol (exp), 0,
12232 pc_rel, reloc);
12233 break;
12234 }
12235
12236 /* Mark whether the fix is to a THUMB instruction, or an ARM
12237 instruction. */
12238 arm_data = (arm_fix_data *) obstack_alloc (& notes, sizeof (arm_fix_data));
12239 new_fix->tc_fix_data = (PTR) arm_data;
12240 arm_data->thumb_mode = thumb_mode;
12241
12242 return;
12243 }
12244
12245 /* This fix_new is called by cons via TC_CONS_FIX_NEW. */
12246
12247 void
12248 cons_fix_new_arm (frag, where, size, exp)
12249 fragS * frag;
12250 int where;
12251 int size;
12252 expressionS * exp;
12253 {
12254 bfd_reloc_code_real_type type;
12255 int pcrel = 0;
12256
12257 /* Pick a reloc.
12258 FIXME: @@ Should look at CPU word size. */
12259 switch (size)
12260 {
12261 case 1:
12262 type = BFD_RELOC_8;
12263 break;
12264 case 2:
12265 type = BFD_RELOC_16;
12266 break;
12267 case 4:
12268 default:
12269 type = BFD_RELOC_32;
12270 break;
12271 case 8:
12272 type = BFD_RELOC_64;
12273 break;
12274 }
12275
12276 fix_new_exp (frag, where, (int) size, exp, pcrel, type);
12277 }
12278
12279 /* A good place to do this, although this was probably not intended
12280 for this kind of use. We need to dump the literal pool before
12281 references are made to a null symbol pointer. */
12282
12283 void
12284 arm_cleanup ()
12285 {
12286 literal_pool * pool;
12287
12288 for (pool = list_of_pools; pool; pool = pool->next)
12289 {
12290 /* Put it at the end of the relevent section. */
12291 subseg_set (pool->section, pool->sub_section);
12292 s_ltorg (0);
12293 }
12294 }
12295
12296 void
12297 arm_start_line_hook ()
12298 {
12299 last_label_seen = NULL;
12300 }
12301
12302 void
12303 arm_frob_label (sym)
12304 symbolS * sym;
12305 {
12306 last_label_seen = sym;
12307
12308 ARM_SET_THUMB (sym, thumb_mode);
12309
12310 #if defined OBJ_COFF || defined OBJ_ELF
12311 ARM_SET_INTERWORK (sym, support_interwork);
12312 #endif
12313
12314 /* Note - do not allow local symbols (.Lxxx) to be labeled
12315 as Thumb functions. This is because these labels, whilst
12316 they exist inside Thumb code, are not the entry points for
12317 possible ARM->Thumb calls. Also, these labels can be used
12318 as part of a computed goto or switch statement. eg gcc
12319 can generate code that looks like this:
12320
12321 ldr r2, [pc, .Laaa]
12322 lsl r3, r3, #2
12323 ldr r2, [r3, r2]
12324 mov pc, r2
12325
12326 .Lbbb: .word .Lxxx
12327 .Lccc: .word .Lyyy
12328 ..etc...
12329 .Laaa: .word Lbbb
12330
12331 The first instruction loads the address of the jump table.
12332 The second instruction converts a table index into a byte offset.
12333 The third instruction gets the jump address out of the table.
12334 The fourth instruction performs the jump.
12335
12336 If the address stored at .Laaa is that of a symbol which has the
12337 Thumb_Func bit set, then the linker will arrange for this address
12338 to have the bottom bit set, which in turn would mean that the
12339 address computation performed by the third instruction would end
12340 up with the bottom bit set. Since the ARM is capable of unaligned
12341 word loads, the instruction would then load the incorrect address
12342 out of the jump table, and chaos would ensue. */
12343 if (label_is_thumb_function_name
12344 && (S_GET_NAME (sym)[0] != '.' || S_GET_NAME (sym)[1] != 'L')
12345 && (bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
12346 {
12347 /* When the address of a Thumb function is taken the bottom
12348 bit of that address should be set. This will allow
12349 interworking between Arm and Thumb functions to work
12350 correctly. */
12351
12352 THUMB_SET_FUNC (sym, 1);
12353
12354 label_is_thumb_function_name = FALSE;
12355 }
12356 }
12357
12358 /* Adjust the symbol table. This marks Thumb symbols as distinct from
12359 ARM ones. */
12360
12361 void
12362 arm_adjust_symtab ()
12363 {
12364 #ifdef OBJ_COFF
12365 symbolS * sym;
12366
12367 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
12368 {
12369 if (ARM_IS_THUMB (sym))
12370 {
12371 if (THUMB_IS_FUNC (sym))
12372 {
12373 /* Mark the symbol as a Thumb function. */
12374 if ( S_GET_STORAGE_CLASS (sym) == C_STAT
12375 || S_GET_STORAGE_CLASS (sym) == C_LABEL) /* This can happen! */
12376 S_SET_STORAGE_CLASS (sym, C_THUMBSTATFUNC);
12377
12378 else if (S_GET_STORAGE_CLASS (sym) == C_EXT)
12379 S_SET_STORAGE_CLASS (sym, C_THUMBEXTFUNC);
12380 else
12381 as_bad (_("%s: unexpected function type: %d"),
12382 S_GET_NAME (sym), S_GET_STORAGE_CLASS (sym));
12383 }
12384 else switch (S_GET_STORAGE_CLASS (sym))
12385 {
12386 case C_EXT:
12387 S_SET_STORAGE_CLASS (sym, C_THUMBEXT);
12388 break;
12389 case C_STAT:
12390 S_SET_STORAGE_CLASS (sym, C_THUMBSTAT);
12391 break;
12392 case C_LABEL:
12393 S_SET_STORAGE_CLASS (sym, C_THUMBLABEL);
12394 break;
12395 default:
12396 /* Do nothing. */
12397 break;
12398 }
12399 }
12400
12401 if (ARM_IS_INTERWORK (sym))
12402 coffsymbol (symbol_get_bfdsym (sym))->native->u.syment.n_flags = 0xFF;
12403 }
12404 #endif
12405 #ifdef OBJ_ELF
12406 symbolS * sym;
12407 char bind;
12408
12409 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
12410 {
12411 if (ARM_IS_THUMB (sym))
12412 {
12413 elf_symbol_type * elf_sym;
12414
12415 elf_sym = elf_symbol (symbol_get_bfdsym (sym));
12416 bind = ELF_ST_BIND (elf_sym);
12417
12418 /* If it's a .thumb_func, declare it as so,
12419 otherwise tag label as .code 16. */
12420 if (THUMB_IS_FUNC (sym))
12421 elf_sym->internal_elf_sym.st_info =
12422 ELF_ST_INFO (bind, STT_ARM_TFUNC);
12423 else
12424 elf_sym->internal_elf_sym.st_info =
12425 ELF_ST_INFO (bind, STT_ARM_16BIT);
12426 }
12427 }
12428 #endif
12429 }
12430
12431 int
12432 arm_data_in_code ()
12433 {
12434 if (thumb_mode && ! strncmp (input_line_pointer + 1, "data:", 5))
12435 {
12436 *input_line_pointer = '/';
12437 input_line_pointer += 5;
12438 *input_line_pointer = 0;
12439 return 1;
12440 }
12441
12442 return 0;
12443 }
12444
12445 char *
12446 arm_canonicalize_symbol_name (name)
12447 char * name;
12448 {
12449 int len;
12450
12451 if (thumb_mode && (len = strlen (name)) > 5
12452 && streq (name + len - 5, "/data"))
12453 *(name + len - 5) = 0;
12454
12455 return name;
12456 }
12457
12458 #if defined OBJ_COFF || defined OBJ_ELF
12459 void
12460 arm_validate_fix (fixP)
12461 fixS * fixP;
12462 {
12463 /* If the destination of the branch is a defined symbol which does not have
12464 the THUMB_FUNC attribute, then we must be calling a function which has
12465 the (interfacearm) attribute. We look for the Thumb entry point to that
12466 function and change the branch to refer to that function instead. */
12467 if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23
12468 && fixP->fx_addsy != NULL
12469 && S_IS_DEFINED (fixP->fx_addsy)
12470 && ! THUMB_IS_FUNC (fixP->fx_addsy))
12471 {
12472 fixP->fx_addsy = find_real_start (fixP->fx_addsy);
12473 }
12474 }
12475 #endif
12476
12477 int
12478 arm_force_relocation (fixp)
12479 struct fix * fixp;
12480 {
12481 #if defined (OBJ_COFF) && defined (TE_PE)
12482 if (fixp->fx_r_type == BFD_RELOC_RVA)
12483 return 1;
12484 #endif
12485 #ifdef OBJ_ELF
12486 if (fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH
12487 || fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BLX
12488 || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX
12489 || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23)
12490 return 1;
12491 #endif
12492
12493 /* Resolve these relocations even if the symbol is extern or weak. */
12494 if (fixp->fx_r_type == BFD_RELOC_ARM_IMMEDIATE
12495 || fixp->fx_r_type == BFD_RELOC_ARM_OFFSET_IMM
12496 || fixp->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE)
12497 return 0;
12498
12499 return generic_force_reloc (fixp);
12500 }
12501
12502 #ifdef OBJ_COFF
12503 /* This is a little hack to help the gas/arm/adrl.s test. It prevents
12504 local labels from being added to the output symbol table when they
12505 are used with the ADRL pseudo op. The ADRL relocation should always
12506 be resolved before the binbary is emitted, so it is safe to say that
12507 it is adjustable. */
12508
12509 bfd_boolean
12510 arm_fix_adjustable (fixP)
12511 fixS * fixP;
12512 {
12513 if (fixP->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE)
12514 return 1;
12515 return 0;
12516 }
12517 #endif
12518
12519 #ifdef OBJ_ELF
12520 /* Relocations against Thumb function names must be left unadjusted,
12521 so that the linker can use this information to correctly set the
12522 bottom bit of their addresses. The MIPS version of this function
12523 also prevents relocations that are mips-16 specific, but I do not
12524 know why it does this.
12525
12526 FIXME:
12527 There is one other problem that ought to be addressed here, but
12528 which currently is not: Taking the address of a label (rather
12529 than a function) and then later jumping to that address. Such
12530 addresses also ought to have their bottom bit set (assuming that
12531 they reside in Thumb code), but at the moment they will not. */
12532
12533 bfd_boolean
12534 arm_fix_adjustable (fixP)
12535 fixS * fixP;
12536 {
12537 if (fixP->fx_addsy == NULL)
12538 return 1;
12539
12540 if (THUMB_IS_FUNC (fixP->fx_addsy)
12541 && fixP->fx_subsy == NULL)
12542 return 0;
12543
12544 /* We need the symbol name for the VTABLE entries. */
12545 if ( fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
12546 || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
12547 return 0;
12548
12549 /* Don't allow symbols to be discarded on GOT related relocs. */
12550 if (fixP->fx_r_type == BFD_RELOC_ARM_PLT32
12551 || fixP->fx_r_type == BFD_RELOC_ARM_GOT32
12552 || fixP->fx_r_type == BFD_RELOC_ARM_GOTOFF)
12553 return 0;
12554
12555 return 1;
12556 }
12557
12558 const char *
12559 elf32_arm_target_format ()
12560 {
12561 if (target_big_endian)
12562 {
12563 if (target_oabi)
12564 return "elf32-bigarm-oabi";
12565 else
12566 return "elf32-bigarm";
12567 }
12568 else
12569 {
12570 if (target_oabi)
12571 return "elf32-littlearm-oabi";
12572 else
12573 return "elf32-littlearm";
12574 }
12575 }
12576
12577 void
12578 armelf_frob_symbol (symp, puntp)
12579 symbolS * symp;
12580 int * puntp;
12581 {
12582 elf_frob_symbol (symp, puntp);
12583 }
12584
12585 static bfd_reloc_code_real_type
12586 arm_parse_reloc ()
12587 {
12588 char id [16];
12589 char * ip;
12590 unsigned int i;
12591 static struct
12592 {
12593 char * str;
12594 int len;
12595 bfd_reloc_code_real_type reloc;
12596 }
12597 reloc_map[] =
12598 {
12599 #define MAP(str,reloc) { str, sizeof (str) - 1, reloc }
12600 MAP ("(got)", BFD_RELOC_ARM_GOT32),
12601 MAP ("(gotoff)", BFD_RELOC_ARM_GOTOFF),
12602 /* ScottB: Jan 30, 1998 - Added support for parsing "var(PLT)"
12603 branch instructions generated by GCC for PLT relocs. */
12604 MAP ("(plt)", BFD_RELOC_ARM_PLT32),
12605 { NULL, 0, BFD_RELOC_UNUSED }
12606 #undef MAP
12607 };
12608
12609 for (i = 0, ip = input_line_pointer;
12610 i < sizeof (id) && (ISALNUM (*ip) || ISPUNCT (*ip));
12611 i++, ip++)
12612 id[i] = TOLOWER (*ip);
12613
12614 for (i = 0; reloc_map[i].str; i++)
12615 if (strncmp (id, reloc_map[i].str, reloc_map[i].len) == 0)
12616 break;
12617
12618 input_line_pointer += reloc_map[i].len;
12619
12620 return reloc_map[i].reloc;
12621 }
12622
12623 static void
12624 s_arm_elf_cons (nbytes)
12625 int nbytes;
12626 {
12627 expressionS exp;
12628
12629 #ifdef md_flush_pending_output
12630 md_flush_pending_output ();
12631 #endif
12632
12633 if (is_it_end_of_statement ())
12634 {
12635 demand_empty_rest_of_line ();
12636 return;
12637 }
12638
12639 #ifdef md_cons_align
12640 md_cons_align (nbytes);
12641 #endif
12642
12643 do
12644 {
12645 bfd_reloc_code_real_type reloc;
12646
12647 expression (& exp);
12648
12649 if (exp.X_op == O_symbol
12650 && * input_line_pointer == '('
12651 && (reloc = arm_parse_reloc ()) != BFD_RELOC_UNUSED)
12652 {
12653 reloc_howto_type *howto = bfd_reloc_type_lookup (stdoutput, reloc);
12654 int size = bfd_get_reloc_size (howto);
12655
12656 if (size > nbytes)
12657 as_bad ("%s relocations do not fit in %d bytes",
12658 howto->name, nbytes);
12659 else
12660 {
12661 register char *p = frag_more ((int) nbytes);
12662 int offset = nbytes - size;
12663
12664 fix_new_exp (frag_now, p - frag_now->fr_literal + offset, size,
12665 &exp, 0, reloc);
12666 }
12667 }
12668 else
12669 emit_expr (&exp, (unsigned int) nbytes);
12670 }
12671 while (*input_line_pointer++ == ',');
12672
12673 /* Put terminator back into stream. */
12674 input_line_pointer --;
12675 demand_empty_rest_of_line ();
12676 }
12677
12678 #endif /* OBJ_ELF */
12679
12680 /* This is called from HANDLE_ALIGN in write.c. Fill in the contents
12681 of an rs_align_code fragment. */
12682
12683 void
12684 arm_handle_align (fragP)
12685 fragS *fragP;
12686 {
12687 static char const arm_noop[4] = { 0x00, 0x00, 0xa0, 0xe1 };
12688 static char const thumb_noop[2] = { 0xc0, 0x46 };
12689 static char const arm_bigend_noop[4] = { 0xe1, 0xa0, 0x00, 0x00 };
12690 static char const thumb_bigend_noop[2] = { 0x46, 0xc0 };
12691
12692 int bytes, fix, noop_size;
12693 char * p;
12694 const char * noop;
12695
12696 if (fragP->fr_type != rs_align_code)
12697 return;
12698
12699 bytes = fragP->fr_next->fr_address - fragP->fr_address - fragP->fr_fix;
12700 p = fragP->fr_literal + fragP->fr_fix;
12701 fix = 0;
12702
12703 if (bytes > MAX_MEM_FOR_RS_ALIGN_CODE)
12704 bytes &= MAX_MEM_FOR_RS_ALIGN_CODE;
12705
12706 if (fragP->tc_frag_data)
12707 {
12708 if (target_big_endian)
12709 noop = thumb_bigend_noop;
12710 else
12711 noop = thumb_noop;
12712 noop_size = sizeof (thumb_noop);
12713 }
12714 else
12715 {
12716 if (target_big_endian)
12717 noop = arm_bigend_noop;
12718 else
12719 noop = arm_noop;
12720 noop_size = sizeof (arm_noop);
12721 }
12722
12723 if (bytes & (noop_size - 1))
12724 {
12725 fix = bytes & (noop_size - 1);
12726 memset (p, 0, fix);
12727 p += fix;
12728 bytes -= fix;
12729 }
12730
12731 while (bytes >= noop_size)
12732 {
12733 memcpy (p, noop, noop_size);
12734 p += noop_size;
12735 bytes -= noop_size;
12736 fix += noop_size;
12737 }
12738
12739 fragP->fr_fix += fix;
12740 fragP->fr_var = noop_size;
12741 }
12742
12743 /* Called from md_do_align. Used to create an alignment
12744 frag in a code section. */
12745
12746 void
12747 arm_frag_align_code (n, max)
12748 int n;
12749 int max;
12750 {
12751 char * p;
12752
12753 /* We assume that there will never be a requirment
12754 to support alignments greater than 32 bytes. */
12755 if (max > MAX_MEM_FOR_RS_ALIGN_CODE)
12756 as_fatal (_("alignments greater than 32 bytes not supported in .text sections."));
12757
12758 p = frag_var (rs_align_code,
12759 MAX_MEM_FOR_RS_ALIGN_CODE,
12760 1,
12761 (relax_substateT) max,
12762 (symbolS *) NULL,
12763 (offsetT) n,
12764 (char *) NULL);
12765 *p = 0;
12766
12767 }
12768
12769 /* Perform target specific initialisation of a frag. */
12770
12771 void
12772 arm_init_frag (fragP)
12773 fragS *fragP;
12774 {
12775 /* Record whether this frag is in an ARM or a THUMB area. */
12776 fragP->tc_frag_data = thumb_mode;
12777 }