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