* tc.h (struct relax_type, relax_typeS): Move from here..
[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 2004, 2005
4 Free Software Foundation, Inc.
5 Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org)
6 Modified by David Taylor (dtaylor@armltd.co.uk)
7 Cirrus coprocessor mods by Aldy Hernandez (aldyh@redhat.com)
8 Cirrus coprocessor fixes by Petko Manolov (petkan@nucleusys.com)
9 Cirrus coprocessor fixes by Vladimir Ivanov (vladitx@nucleusys.com)
10
11 This file is part of GAS, the GNU Assembler.
12
13 GAS is free software; you can redistribute it and/or modify
14 it under the terms of the GNU General Public License as published by
15 the Free Software Foundation; either version 2, or (at your option)
16 any later version.
17
18 GAS is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with GAS; see the file COPYING. If not, write to the Free
25 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
26 02111-1307, USA. */
27
28 #include <string.h>
29 #define NO_RELOC 0
30 #include "as.h"
31 #include "safe-ctype.h"
32
33 /* Need TARGET_CPU. */
34 #include "config.h"
35 #include "subsegs.h"
36 #include "obstack.h"
37 #include "symbols.h"
38 #include "listing.h"
39
40 #include "opcode/arm.h"
41
42 #ifdef OBJ_ELF
43 #include "elf/arm.h"
44 #include "dwarf2dbg.h"
45 #include "dw2gencfi.h"
46 #endif
47
48 /* XXX Set this to 1 after the next binutils release. */
49 #define WARN_DEPRECATED 0
50
51 #ifdef OBJ_ELF
52 /* Must be at least the size of the largest unwind opcode (currently two). */
53 #define ARM_OPCODE_CHUNK_SIZE 8
54
55 /* This structure holds the unwinding state. */
56
57 static struct
58 {
59 symbolS * proc_start;
60 symbolS * table_entry;
61 symbolS * personality_routine;
62 int personality_index;
63 /* The segment containing the function. */
64 segT saved_seg;
65 subsegT saved_subseg;
66 /* Opcodes generated from this function. */
67 unsigned char * opcodes;
68 int opcode_count;
69 int opcode_alloc;
70 /* The number of bytes pushed to the stack. */
71 offsetT frame_size;
72 /* We don't add stack adjustment opcodes immediately so that we can merge
73 multiple adjustments. We can also omit the final adjustment
74 when using a frame pointer. */
75 offsetT pending_offset;
76 /* These two fields are set by both unwind_movsp and unwind_setfp. They
77 hold the reg+offset to use when restoring sp from a frame pointer. */
78 offsetT fp_offset;
79 int fp_reg;
80 /* Nonzero if an unwind_setfp directive has been seen. */
81 unsigned fp_used:1;
82 /* Nonzero if the last opcode restores sp from fp_reg. */
83 unsigned sp_restored:1;
84 } unwind;
85
86 #endif /* OBJ_ELF */
87
88 enum arm_float_abi
89 {
90 ARM_FLOAT_ABI_HARD,
91 ARM_FLOAT_ABI_SOFTFP,
92 ARM_FLOAT_ABI_SOFT
93 };
94
95 /* Types of processor to assemble for. */
96 #define ARM_1 ARM_ARCH_V1
97 #define ARM_2 ARM_ARCH_V2
98 #define ARM_3 ARM_ARCH_V2S
99 #define ARM_250 ARM_ARCH_V2S
100 #define ARM_6 ARM_ARCH_V3
101 #define ARM_7 ARM_ARCH_V3
102 #define ARM_8 ARM_ARCH_V4
103 #define ARM_9 ARM_ARCH_V4T
104 #define ARM_STRONG ARM_ARCH_V4
105 #define ARM_CPU_MASK 0x0000000f /* XXX? */
106
107 #ifndef CPU_DEFAULT
108 #if defined __XSCALE__
109 #define CPU_DEFAULT (ARM_ARCH_XSCALE)
110 #else
111 #if defined __thumb__
112 #define CPU_DEFAULT (ARM_ARCH_V5T)
113 #else
114 #define CPU_DEFAULT ARM_ANY
115 #endif
116 #endif
117 #endif
118
119 #ifndef FPU_DEFAULT
120 # ifdef TE_LINUX
121 # define FPU_DEFAULT FPU_ARCH_FPA
122 # elif defined (TE_NetBSD)
123 # ifdef OBJ_ELF
124 # define FPU_DEFAULT FPU_ARCH_VFP /* Soft-float, but VFP order. */
125 # else
126 /* Legacy a.out format. */
127 # define FPU_DEFAULT FPU_ARCH_FPA /* Soft-float, but FPA order. */
128 # endif
129 # elif defined (TE_VXWORKS)
130 # define FPU_DEFAULT FPU_ARCH_VFP /* Soft-float, VFP order. */
131 # else
132 /* For backwards compatibility, default to FPA. */
133 # define FPU_DEFAULT FPU_ARCH_FPA
134 # endif
135 #endif /* ifndef FPU_DEFAULT */
136
137 #define streq(a, b) (strcmp (a, b) == 0)
138 #define skip_whitespace(str) while (*(str) == ' ') ++(str)
139
140 static unsigned long cpu_variant;
141
142 /* Flags stored in private area of BFD structure. */
143 static int uses_apcs_26 = FALSE;
144 static int atpcs = FALSE;
145 static int support_interwork = FALSE;
146 static int uses_apcs_float = FALSE;
147 static int pic_code = FALSE;
148
149 /* Variables that we set while parsing command-line options. Once all
150 options have been read we re-process these values to set the real
151 assembly flags. */
152 static int legacy_cpu = -1;
153 static int legacy_fpu = -1;
154
155 static int mcpu_cpu_opt = -1;
156 static int mcpu_fpu_opt = -1;
157 static int march_cpu_opt = -1;
158 static int march_fpu_opt = -1;
159 static int mfpu_opt = -1;
160 static int mfloat_abi_opt = -1;
161 #ifdef OBJ_ELF
162 static int meabi_flags = EF_ARM_EABI_UNKNOWN;
163 #endif
164
165 /* This array holds the chars that always start a comment. If the
166 pre-processor is disabled, these aren't very useful. */
167 const char comment_chars[] = "@";
168
169 /* This array holds the chars that only start a comment at the beginning of
170 a line. If the line seems to have the form '# 123 filename'
171 .line and .file directives will appear in the pre-processed output. */
172 /* Note that input_file.c hand checks for '#' at the beginning of the
173 first line of the input file. This is because the compiler outputs
174 #NO_APP at the beginning of its output. */
175 /* Also note that comments like this one will always work. */
176 const char line_comment_chars[] = "#";
177
178 const char line_separator_chars[] = ";";
179
180 /* Chars that can be used to separate mant
181 from exp in floating point numbers. */
182 const char EXP_CHARS[] = "eE";
183
184 /* Chars that mean this number is a floating point constant. */
185 /* As in 0f12.456 */
186 /* or 0d1.2345e12 */
187
188 const char FLT_CHARS[] = "rRsSfFdDxXeEpP";
189
190 /* Prefix characters that indicate the start of an immediate
191 value. */
192 #define is_immediate_prefix(C) ((C) == '#' || (C) == '$')
193
194 #ifdef OBJ_ELF
195 /* Pre-defined "_GLOBAL_OFFSET_TABLE_" */
196 symbolS * GOT_symbol;
197 #endif
198
199 /* Size of relocation record. */
200 const int md_reloc_size = 8;
201
202 /* 0: assemble for ARM,
203 1: assemble for Thumb,
204 2: assemble for Thumb even though target CPU does not support thumb
205 instructions. */
206 static int thumb_mode = 0;
207
208 typedef struct arm_fix
209 {
210 int thumb_mode;
211 } arm_fix_data;
212
213 struct arm_it
214 {
215 const char * error;
216 unsigned long instruction;
217 int size;
218 struct
219 {
220 bfd_reloc_code_real_type type;
221 expressionS exp;
222 int pc_rel;
223 } reloc;
224 };
225
226 struct arm_it inst;
227
228 enum asm_shift_index
229 {
230 SHIFT_LSL = 0,
231 SHIFT_LSR,
232 SHIFT_ASR,
233 SHIFT_ROR,
234 SHIFT_RRX
235 };
236
237 struct asm_shift_properties
238 {
239 enum asm_shift_index index;
240 unsigned long bit_field;
241 unsigned int allows_0 : 1;
242 unsigned int allows_32 : 1;
243 };
244
245 static const struct asm_shift_properties shift_properties [] =
246 {
247 { SHIFT_LSL, 0, 1, 0},
248 { SHIFT_LSR, 0x20, 0, 1},
249 { SHIFT_ASR, 0x40, 0, 1},
250 { SHIFT_ROR, 0x60, 0, 0},
251 { SHIFT_RRX, 0x60, 0, 0}
252 };
253
254 struct asm_shift_name
255 {
256 const char * name;
257 const struct asm_shift_properties * properties;
258 };
259
260 static const struct asm_shift_name shift_names [] =
261 {
262 { "asl", shift_properties + SHIFT_LSL },
263 { "lsl", shift_properties + SHIFT_LSL },
264 { "lsr", shift_properties + SHIFT_LSR },
265 { "asr", shift_properties + SHIFT_ASR },
266 { "ror", shift_properties + SHIFT_ROR },
267 { "rrx", shift_properties + SHIFT_RRX },
268 { "ASL", shift_properties + SHIFT_LSL },
269 { "LSL", shift_properties + SHIFT_LSL },
270 { "LSR", shift_properties + SHIFT_LSR },
271 { "ASR", shift_properties + SHIFT_ASR },
272 { "ROR", shift_properties + SHIFT_ROR },
273 { "RRX", shift_properties + SHIFT_RRX }
274 };
275
276 /* Any kind of shift is accepted. */
277 #define NO_SHIFT_RESTRICT 1
278 /* The shift operand must be an immediate value, not a register. */
279 #define SHIFT_IMMEDIATE 0
280 /* The shift must be LSL or ASR and the operand must be an immediate. */
281 #define SHIFT_LSL_OR_ASR_IMMEDIATE 2
282 /* The shift must be ASR and the operand must be an immediate. */
283 #define SHIFT_ASR_IMMEDIATE 3
284 /* The shift must be LSL and the operand must be an immediate. */
285 #define SHIFT_LSL_IMMEDIATE 4
286
287 #define NUM_FLOAT_VALS 8
288
289 const char * fp_const[] =
290 {
291 "0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0", 0
292 };
293
294 /* Number of littlenums required to hold an extended precision number. */
295 #define MAX_LITTLENUMS 6
296
297 LITTLENUM_TYPE fp_values[NUM_FLOAT_VALS][MAX_LITTLENUMS];
298
299 #define FAIL (-1)
300 #define SUCCESS (0)
301
302 /* Whether a Co-processor load/store operation accepts write-back forms. */
303 #define CP_WB_OK 1
304 #define CP_NO_WB 0
305
306 #define SUFF_S 1
307 #define SUFF_D 2
308 #define SUFF_E 3
309 #define SUFF_P 4
310
311 #define CP_T_X 0x00008000
312 #define CP_T_Y 0x00400000
313 #define CP_T_Pre 0x01000000
314 #define CP_T_UD 0x00800000
315 #define CP_T_WB 0x00200000
316
317 #define CONDS_BIT 0x00100000
318 #define LOAD_BIT 0x00100000
319
320 #define DOUBLE_LOAD_FLAG 0x00000001
321
322 struct asm_cond
323 {
324 const char * template;
325 unsigned long value;
326 };
327
328 #define COND_ALWAYS 0xe0000000
329 #define COND_MASK 0xf0000000
330
331 static const struct asm_cond conds[] =
332 {
333 {"eq", 0x00000000},
334 {"ne", 0x10000000},
335 {"cs", 0x20000000}, {"hs", 0x20000000},
336 {"cc", 0x30000000}, {"ul", 0x30000000}, {"lo", 0x30000000},
337 {"mi", 0x40000000},
338 {"pl", 0x50000000},
339 {"vs", 0x60000000},
340 {"vc", 0x70000000},
341 {"hi", 0x80000000},
342 {"ls", 0x90000000},
343 {"ge", 0xa0000000},
344 {"lt", 0xb0000000},
345 {"gt", 0xc0000000},
346 {"le", 0xd0000000},
347 {"al", 0xe0000000},
348 {"nv", 0xf0000000}
349 };
350
351 struct asm_psr
352 {
353 const char *template;
354 bfd_boolean cpsr;
355 unsigned long field;
356 };
357
358 /* The bit that distinguishes CPSR and SPSR. */
359 #define SPSR_BIT (1 << 22)
360
361 /* How many bits to shift the PSR_xxx bits up by. */
362 #define PSR_SHIFT 16
363
364 #define PSR_c (1 << 0)
365 #define PSR_x (1 << 1)
366 #define PSR_s (1 << 2)
367 #define PSR_f (1 << 3)
368
369 static const struct asm_psr psrs[] =
370 {
371 {"CPSR", TRUE, PSR_c | PSR_f},
372 {"CPSR_all", TRUE, PSR_c | PSR_f},
373 {"SPSR", FALSE, PSR_c | PSR_f},
374 {"SPSR_all", FALSE, PSR_c | PSR_f},
375 {"CPSR_flg", TRUE, PSR_f},
376 {"CPSR_f", TRUE, PSR_f},
377 {"SPSR_flg", FALSE, PSR_f},
378 {"SPSR_f", FALSE, PSR_f},
379 {"CPSR_c", TRUE, PSR_c},
380 {"CPSR_ctl", TRUE, PSR_c},
381 {"SPSR_c", FALSE, PSR_c},
382 {"SPSR_ctl", FALSE, PSR_c},
383 {"CPSR_x", TRUE, PSR_x},
384 {"CPSR_s", TRUE, PSR_s},
385 {"SPSR_x", FALSE, PSR_x},
386 {"SPSR_s", FALSE, PSR_s},
387 /* Combinations of flags. */
388 {"CPSR_fs", TRUE, PSR_f | PSR_s},
389 {"CPSR_fx", TRUE, PSR_f | PSR_x},
390 {"CPSR_fc", TRUE, PSR_f | PSR_c},
391 {"CPSR_sf", TRUE, PSR_s | PSR_f},
392 {"CPSR_sx", TRUE, PSR_s | PSR_x},
393 {"CPSR_sc", TRUE, PSR_s | PSR_c},
394 {"CPSR_xf", TRUE, PSR_x | PSR_f},
395 {"CPSR_xs", TRUE, PSR_x | PSR_s},
396 {"CPSR_xc", TRUE, PSR_x | PSR_c},
397 {"CPSR_cf", TRUE, PSR_c | PSR_f},
398 {"CPSR_cs", TRUE, PSR_c | PSR_s},
399 {"CPSR_cx", TRUE, PSR_c | PSR_x},
400 {"CPSR_fsx", TRUE, PSR_f | PSR_s | PSR_x},
401 {"CPSR_fsc", TRUE, PSR_f | PSR_s | PSR_c},
402 {"CPSR_fxs", TRUE, PSR_f | PSR_x | PSR_s},
403 {"CPSR_fxc", TRUE, PSR_f | PSR_x | PSR_c},
404 {"CPSR_fcs", TRUE, PSR_f | PSR_c | PSR_s},
405 {"CPSR_fcx", TRUE, PSR_f | PSR_c | PSR_x},
406 {"CPSR_sfx", TRUE, PSR_s | PSR_f | PSR_x},
407 {"CPSR_sfc", TRUE, PSR_s | PSR_f | PSR_c},
408 {"CPSR_sxf", TRUE, PSR_s | PSR_x | PSR_f},
409 {"CPSR_sxc", TRUE, PSR_s | PSR_x | PSR_c},
410 {"CPSR_scf", TRUE, PSR_s | PSR_c | PSR_f},
411 {"CPSR_scx", TRUE, PSR_s | PSR_c | PSR_x},
412 {"CPSR_xfs", TRUE, PSR_x | PSR_f | PSR_s},
413 {"CPSR_xfc", TRUE, PSR_x | PSR_f | PSR_c},
414 {"CPSR_xsf", TRUE, PSR_x | PSR_s | PSR_f},
415 {"CPSR_xsc", TRUE, PSR_x | PSR_s | PSR_c},
416 {"CPSR_xcf", TRUE, PSR_x | PSR_c | PSR_f},
417 {"CPSR_xcs", TRUE, PSR_x | PSR_c | PSR_s},
418 {"CPSR_cfs", TRUE, PSR_c | PSR_f | PSR_s},
419 {"CPSR_cfx", TRUE, PSR_c | PSR_f | PSR_x},
420 {"CPSR_csf", TRUE, PSR_c | PSR_s | PSR_f},
421 {"CPSR_csx", TRUE, PSR_c | PSR_s | PSR_x},
422 {"CPSR_cxf", TRUE, PSR_c | PSR_x | PSR_f},
423 {"CPSR_cxs", TRUE, PSR_c | PSR_x | PSR_s},
424 {"CPSR_fsxc", TRUE, PSR_f | PSR_s | PSR_x | PSR_c},
425 {"CPSR_fscx", TRUE, PSR_f | PSR_s | PSR_c | PSR_x},
426 {"CPSR_fxsc", TRUE, PSR_f | PSR_x | PSR_s | PSR_c},
427 {"CPSR_fxcs", TRUE, PSR_f | PSR_x | PSR_c | PSR_s},
428 {"CPSR_fcsx", TRUE, PSR_f | PSR_c | PSR_s | PSR_x},
429 {"CPSR_fcxs", TRUE, PSR_f | PSR_c | PSR_x | PSR_s},
430 {"CPSR_sfxc", TRUE, PSR_s | PSR_f | PSR_x | PSR_c},
431 {"CPSR_sfcx", TRUE, PSR_s | PSR_f | PSR_c | PSR_x},
432 {"CPSR_sxfc", TRUE, PSR_s | PSR_x | PSR_f | PSR_c},
433 {"CPSR_sxcf", TRUE, PSR_s | PSR_x | PSR_c | PSR_f},
434 {"CPSR_scfx", TRUE, PSR_s | PSR_c | PSR_f | PSR_x},
435 {"CPSR_scxf", TRUE, PSR_s | PSR_c | PSR_x | PSR_f},
436 {"CPSR_xfsc", TRUE, PSR_x | PSR_f | PSR_s | PSR_c},
437 {"CPSR_xfcs", TRUE, PSR_x | PSR_f | PSR_c | PSR_s},
438 {"CPSR_xsfc", TRUE, PSR_x | PSR_s | PSR_f | PSR_c},
439 {"CPSR_xscf", TRUE, PSR_x | PSR_s | PSR_c | PSR_f},
440 {"CPSR_xcfs", TRUE, PSR_x | PSR_c | PSR_f | PSR_s},
441 {"CPSR_xcsf", TRUE, PSR_x | PSR_c | PSR_s | PSR_f},
442 {"CPSR_cfsx", TRUE, PSR_c | PSR_f | PSR_s | PSR_x},
443 {"CPSR_cfxs", TRUE, PSR_c | PSR_f | PSR_x | PSR_s},
444 {"CPSR_csfx", TRUE, PSR_c | PSR_s | PSR_f | PSR_x},
445 {"CPSR_csxf", TRUE, PSR_c | PSR_s | PSR_x | PSR_f},
446 {"CPSR_cxfs", TRUE, PSR_c | PSR_x | PSR_f | PSR_s},
447 {"CPSR_cxsf", TRUE, PSR_c | PSR_x | PSR_s | PSR_f},
448 {"SPSR_fs", FALSE, PSR_f | PSR_s},
449 {"SPSR_fx", FALSE, PSR_f | PSR_x},
450 {"SPSR_fc", FALSE, PSR_f | PSR_c},
451 {"SPSR_sf", FALSE, PSR_s | PSR_f},
452 {"SPSR_sx", FALSE, PSR_s | PSR_x},
453 {"SPSR_sc", FALSE, PSR_s | PSR_c},
454 {"SPSR_xf", FALSE, PSR_x | PSR_f},
455 {"SPSR_xs", FALSE, PSR_x | PSR_s},
456 {"SPSR_xc", FALSE, PSR_x | PSR_c},
457 {"SPSR_cf", FALSE, PSR_c | PSR_f},
458 {"SPSR_cs", FALSE, PSR_c | PSR_s},
459 {"SPSR_cx", FALSE, PSR_c | PSR_x},
460 {"SPSR_fsx", FALSE, PSR_f | PSR_s | PSR_x},
461 {"SPSR_fsc", FALSE, PSR_f | PSR_s | PSR_c},
462 {"SPSR_fxs", FALSE, PSR_f | PSR_x | PSR_s},
463 {"SPSR_fxc", FALSE, PSR_f | PSR_x | PSR_c},
464 {"SPSR_fcs", FALSE, PSR_f | PSR_c | PSR_s},
465 {"SPSR_fcx", FALSE, PSR_f | PSR_c | PSR_x},
466 {"SPSR_sfx", FALSE, PSR_s | PSR_f | PSR_x},
467 {"SPSR_sfc", FALSE, PSR_s | PSR_f | PSR_c},
468 {"SPSR_sxf", FALSE, PSR_s | PSR_x | PSR_f},
469 {"SPSR_sxc", FALSE, PSR_s | PSR_x | PSR_c},
470 {"SPSR_scf", FALSE, PSR_s | PSR_c | PSR_f},
471 {"SPSR_scx", FALSE, PSR_s | PSR_c | PSR_x},
472 {"SPSR_xfs", FALSE, PSR_x | PSR_f | PSR_s},
473 {"SPSR_xfc", FALSE, PSR_x | PSR_f | PSR_c},
474 {"SPSR_xsf", FALSE, PSR_x | PSR_s | PSR_f},
475 {"SPSR_xsc", FALSE, PSR_x | PSR_s | PSR_c},
476 {"SPSR_xcf", FALSE, PSR_x | PSR_c | PSR_f},
477 {"SPSR_xcs", FALSE, PSR_x | PSR_c | PSR_s},
478 {"SPSR_cfs", FALSE, PSR_c | PSR_f | PSR_s},
479 {"SPSR_cfx", FALSE, PSR_c | PSR_f | PSR_x},
480 {"SPSR_csf", FALSE, PSR_c | PSR_s | PSR_f},
481 {"SPSR_csx", FALSE, PSR_c | PSR_s | PSR_x},
482 {"SPSR_cxf", FALSE, PSR_c | PSR_x | PSR_f},
483 {"SPSR_cxs", FALSE, PSR_c | PSR_x | PSR_s},
484 {"SPSR_fsxc", FALSE, PSR_f | PSR_s | PSR_x | PSR_c},
485 {"SPSR_fscx", FALSE, PSR_f | PSR_s | PSR_c | PSR_x},
486 {"SPSR_fxsc", FALSE, PSR_f | PSR_x | PSR_s | PSR_c},
487 {"SPSR_fxcs", FALSE, PSR_f | PSR_x | PSR_c | PSR_s},
488 {"SPSR_fcsx", FALSE, PSR_f | PSR_c | PSR_s | PSR_x},
489 {"SPSR_fcxs", FALSE, PSR_f | PSR_c | PSR_x | PSR_s},
490 {"SPSR_sfxc", FALSE, PSR_s | PSR_f | PSR_x | PSR_c},
491 {"SPSR_sfcx", FALSE, PSR_s | PSR_f | PSR_c | PSR_x},
492 {"SPSR_sxfc", FALSE, PSR_s | PSR_x | PSR_f | PSR_c},
493 {"SPSR_sxcf", FALSE, PSR_s | PSR_x | PSR_c | PSR_f},
494 {"SPSR_scfx", FALSE, PSR_s | PSR_c | PSR_f | PSR_x},
495 {"SPSR_scxf", FALSE, PSR_s | PSR_c | PSR_x | PSR_f},
496 {"SPSR_xfsc", FALSE, PSR_x | PSR_f | PSR_s | PSR_c},
497 {"SPSR_xfcs", FALSE, PSR_x | PSR_f | PSR_c | PSR_s},
498 {"SPSR_xsfc", FALSE, PSR_x | PSR_s | PSR_f | PSR_c},
499 {"SPSR_xscf", FALSE, PSR_x | PSR_s | PSR_c | PSR_f},
500 {"SPSR_xcfs", FALSE, PSR_x | PSR_c | PSR_f | PSR_s},
501 {"SPSR_xcsf", FALSE, PSR_x | PSR_c | PSR_s | PSR_f},
502 {"SPSR_cfsx", FALSE, PSR_c | PSR_f | PSR_s | PSR_x},
503 {"SPSR_cfxs", FALSE, PSR_c | PSR_f | PSR_x | PSR_s},
504 {"SPSR_csfx", FALSE, PSR_c | PSR_s | PSR_f | PSR_x},
505 {"SPSR_csxf", FALSE, PSR_c | PSR_s | PSR_x | PSR_f},
506 {"SPSR_cxfs", FALSE, PSR_c | PSR_x | PSR_f | PSR_s},
507 {"SPSR_cxsf", FALSE, PSR_c | PSR_x | PSR_s | PSR_f},
508 };
509
510 enum wreg_type
511 {
512 IWMMXT_REG_WR = 0,
513 IWMMXT_REG_WC = 1,
514 IWMMXT_REG_WR_OR_WC = 2,
515 IWMMXT_REG_WCG
516 };
517
518 enum iwmmxt_insn_type
519 {
520 check_rd,
521 check_wr,
522 check_wrwr,
523 check_wrwrwr,
524 check_wrwrwcg,
525 check_tbcst,
526 check_tmovmsk,
527 check_tmia,
528 check_tmcrr,
529 check_tmrrc,
530 check_tmcr,
531 check_tmrc,
532 check_tinsr,
533 check_textrc,
534 check_waligni,
535 check_textrm,
536 check_wshufh
537 };
538
539 enum vfp_dp_reg_pos
540 {
541 VFP_REG_Dd, VFP_REG_Dm, VFP_REG_Dn
542 };
543
544 enum vfp_sp_reg_pos
545 {
546 VFP_REG_Sd, VFP_REG_Sm, VFP_REG_Sn
547 };
548
549 enum vfp_ldstm_type
550 {
551 VFP_LDSTMIA, VFP_LDSTMDB, VFP_LDSTMIAX, VFP_LDSTMDBX
552 };
553
554 /* VFP system registers. */
555 struct vfp_reg
556 {
557 const char *name;
558 unsigned long regno;
559 };
560
561 static const struct vfp_reg vfp_regs[] =
562 {
563 {"fpsid", 0x00000000},
564 {"FPSID", 0x00000000},
565 {"fpscr", 0x00010000},
566 {"FPSCR", 0x00010000},
567 {"fpexc", 0x00080000},
568 {"FPEXC", 0x00080000}
569 };
570
571 /* Structure for a hash table entry for a register. */
572 struct reg_entry
573 {
574 const char * name;
575 int number;
576 bfd_boolean builtin;
577 };
578
579 /* Some well known registers that we refer to directly elsewhere. */
580 #define REG_SP 13
581 #define REG_LR 14
582 #define REG_PC 15
583
584 #define wr_register(reg) ((reg ^ WR_PREFIX) >= 0 && (reg ^ WR_PREFIX) <= 15)
585 #define wc_register(reg) ((reg ^ WC_PREFIX) >= 0 && (reg ^ WC_PREFIX) <= 15)
586 #define wcg_register(reg) ((reg ^ WC_PREFIX) >= 8 && (reg ^ WC_PREFIX) <= 11)
587
588 /* These are the standard names. Users can add aliases with .req.
589 and delete them with .unreq. */
590
591 /* Integer Register Numbers. */
592 static const struct reg_entry rn_table[] =
593 {
594 {"r0", 0, TRUE}, {"r1", 1, TRUE}, {"r2", 2, TRUE}, {"r3", 3, TRUE},
595 {"r4", 4, TRUE}, {"r5", 5, TRUE}, {"r6", 6, TRUE}, {"r7", 7, TRUE},
596 {"r8", 8, TRUE}, {"r9", 9, TRUE}, {"r10", 10, TRUE}, {"r11", 11, TRUE},
597 {"r12", 12, TRUE}, {"r13", REG_SP, TRUE}, {"r14", REG_LR, TRUE}, {"r15", REG_PC, TRUE},
598 /* ATPCS Synonyms. */
599 {"a1", 0, TRUE}, {"a2", 1, TRUE}, {"a3", 2, TRUE}, {"a4", 3, TRUE},
600 {"v1", 4, TRUE}, {"v2", 5, TRUE}, {"v3", 6, TRUE}, {"v4", 7, TRUE},
601 {"v5", 8, TRUE}, {"v6", 9, TRUE}, {"v7", 10, TRUE}, {"v8", 11, TRUE},
602 /* Well-known aliases. */
603 {"wr", 7, TRUE}, {"sb", 9, TRUE}, {"sl", 10, TRUE}, {"fp", 11, TRUE},
604 {"ip", 12, TRUE}, {"sp", REG_SP, TRUE}, {"lr", REG_LR, TRUE}, {"pc", REG_PC, TRUE},
605 {NULL, 0, TRUE}
606 };
607
608 #define WR_PREFIX 0x200
609 #define WC_PREFIX 0x400
610
611 static const struct reg_entry iwmmxt_table[] =
612 {
613 /* Intel Wireless MMX technology register names. */
614 { "wr0", 0x0 | WR_PREFIX, TRUE}, {"wr1", 0x1 | WR_PREFIX, TRUE},
615 { "wr2", 0x2 | WR_PREFIX, TRUE}, {"wr3", 0x3 | WR_PREFIX, TRUE},
616 { "wr4", 0x4 | WR_PREFIX, TRUE}, {"wr5", 0x5 | WR_PREFIX, TRUE},
617 { "wr6", 0x6 | WR_PREFIX, TRUE}, {"wr7", 0x7 | WR_PREFIX, TRUE},
618 { "wr8", 0x8 | WR_PREFIX, TRUE}, {"wr9", 0x9 | WR_PREFIX, TRUE},
619 { "wr10", 0xa | WR_PREFIX, TRUE}, {"wr11", 0xb | WR_PREFIX, TRUE},
620 { "wr12", 0xc | WR_PREFIX, TRUE}, {"wr13", 0xd | WR_PREFIX, TRUE},
621 { "wr14", 0xe | WR_PREFIX, TRUE}, {"wr15", 0xf | WR_PREFIX, TRUE},
622 { "wcid", 0x0 | WC_PREFIX, TRUE}, {"wcon", 0x1 | WC_PREFIX, TRUE},
623 {"wcssf", 0x2 | WC_PREFIX, TRUE}, {"wcasf", 0x3 | WC_PREFIX, TRUE},
624 {"wcgr0", 0x8 | WC_PREFIX, TRUE}, {"wcgr1", 0x9 | WC_PREFIX, TRUE},
625 {"wcgr2", 0xa | WC_PREFIX, TRUE}, {"wcgr3", 0xb | WC_PREFIX, TRUE},
626
627 { "wR0", 0x0 | WR_PREFIX, TRUE}, {"wR1", 0x1 | WR_PREFIX, TRUE},
628 { "wR2", 0x2 | WR_PREFIX, TRUE}, {"wR3", 0x3 | WR_PREFIX, TRUE},
629 { "wR4", 0x4 | WR_PREFIX, TRUE}, {"wR5", 0x5 | WR_PREFIX, TRUE},
630 { "wR6", 0x6 | WR_PREFIX, TRUE}, {"wR7", 0x7 | WR_PREFIX, TRUE},
631 { "wR8", 0x8 | WR_PREFIX, TRUE}, {"wR9", 0x9 | WR_PREFIX, TRUE},
632 { "wR10", 0xa | WR_PREFIX, TRUE}, {"wR11", 0xb | WR_PREFIX, TRUE},
633 { "wR12", 0xc | WR_PREFIX, TRUE}, {"wR13", 0xd | WR_PREFIX, TRUE},
634 { "wR14", 0xe | WR_PREFIX, TRUE}, {"wR15", 0xf | WR_PREFIX, TRUE},
635 { "wCID", 0x0 | WC_PREFIX, TRUE}, {"wCon", 0x1 | WC_PREFIX, TRUE},
636 {"wCSSF", 0x2 | WC_PREFIX, TRUE}, {"wCASF", 0x3 | WC_PREFIX, TRUE},
637 {"wCGR0", 0x8 | WC_PREFIX, TRUE}, {"wCGR1", 0x9 | WC_PREFIX, TRUE},
638 {"wCGR2", 0xa | WC_PREFIX, TRUE}, {"wCGR3", 0xb | WC_PREFIX, TRUE},
639 {NULL, 0, TRUE}
640 };
641
642 /* Co-processor Numbers. */
643 static const struct reg_entry cp_table[] =
644 {
645 {"p0", 0, TRUE}, {"p1", 1, TRUE}, {"p2", 2, TRUE}, {"p3", 3, TRUE},
646 {"p4", 4, TRUE}, {"p5", 5, TRUE}, {"p6", 6, TRUE}, {"p7", 7, TRUE},
647 {"p8", 8, TRUE}, {"p9", 9, TRUE}, {"p10", 10, TRUE}, {"p11", 11, TRUE},
648 {"p12", 12, TRUE}, {"p13", 13, TRUE}, {"p14", 14, TRUE}, {"p15", 15, TRUE},
649 {NULL, 0, TRUE}
650 };
651
652 /* Co-processor Register Numbers. */
653 static const struct reg_entry cn_table[] =
654 {
655 {"c0", 0, TRUE}, {"c1", 1, TRUE}, {"c2", 2, TRUE}, {"c3", 3, TRUE},
656 {"c4", 4, TRUE}, {"c5", 5, TRUE}, {"c6", 6, TRUE}, {"c7", 7, TRUE},
657 {"c8", 8, TRUE}, {"c9", 9, TRUE}, {"c10", 10, TRUE}, {"c11", 11, TRUE},
658 {"c12", 12, TRUE}, {"c13", 13, TRUE}, {"c14", 14, TRUE}, {"c15", 15, TRUE},
659 /* Not really valid, but kept for back-wards compatibility. */
660 {"cr0", 0, TRUE}, {"cr1", 1, TRUE}, {"cr2", 2, TRUE}, {"cr3", 3, TRUE},
661 {"cr4", 4, TRUE}, {"cr5", 5, TRUE}, {"cr6", 6, TRUE}, {"cr7", 7, TRUE},
662 {"cr8", 8, TRUE}, {"cr9", 9, TRUE}, {"cr10", 10, TRUE}, {"cr11", 11, TRUE},
663 {"cr12", 12, TRUE}, {"cr13", 13, TRUE}, {"cr14", 14, TRUE}, {"cr15", 15, TRUE},
664 {NULL, 0, TRUE}
665 };
666
667 /* FPA Registers. */
668 static const struct reg_entry fn_table[] =
669 {
670 {"f0", 0, TRUE}, {"f1", 1, TRUE}, {"f2", 2, TRUE}, {"f3", 3, TRUE},
671 {"f4", 4, TRUE}, {"f5", 5, TRUE}, {"f6", 6, TRUE}, {"f7", 7, TRUE},
672 {NULL, 0, TRUE}
673 };
674
675 /* VFP SP Registers. */
676 static const struct reg_entry sn_table[] =
677 {
678 {"s0", 0, TRUE}, {"s1", 1, TRUE}, {"s2", 2, TRUE}, {"s3", 3, TRUE},
679 {"s4", 4, TRUE}, {"s5", 5, TRUE}, {"s6", 6, TRUE}, {"s7", 7, TRUE},
680 {"s8", 8, TRUE}, {"s9", 9, TRUE}, {"s10", 10, TRUE}, {"s11", 11, TRUE},
681 {"s12", 12, TRUE}, {"s13", 13, TRUE}, {"s14", 14, TRUE}, {"s15", 15, TRUE},
682 {"s16", 16, TRUE}, {"s17", 17, TRUE}, {"s18", 18, TRUE}, {"s19", 19, TRUE},
683 {"s20", 20, TRUE}, {"s21", 21, TRUE}, {"s22", 22, TRUE}, {"s23", 23, TRUE},
684 {"s24", 24, TRUE}, {"s25", 25, TRUE}, {"s26", 26, TRUE}, {"s27", 27, TRUE},
685 {"s28", 28, TRUE}, {"s29", 29, TRUE}, {"s30", 30, TRUE}, {"s31", 31, TRUE},
686 {NULL, 0, TRUE}
687 };
688
689 /* VFP DP Registers. */
690 static const struct reg_entry dn_table[] =
691 {
692 {"d0", 0, TRUE}, {"d1", 1, TRUE}, {"d2", 2, TRUE}, {"d3", 3, TRUE},
693 {"d4", 4, TRUE}, {"d5", 5, TRUE}, {"d6", 6, TRUE}, {"d7", 7, TRUE},
694 {"d8", 8, TRUE}, {"d9", 9, TRUE}, {"d10", 10, TRUE}, {"d11", 11, TRUE},
695 {"d12", 12, TRUE}, {"d13", 13, TRUE}, {"d14", 14, TRUE}, {"d15", 15, TRUE},
696 {NULL, 0, TRUE}
697 };
698
699 /* Maverick DSP coprocessor registers. */
700 static const struct reg_entry mav_mvf_table[] =
701 {
702 {"mvf0", 0, TRUE}, {"mvf1", 1, TRUE}, {"mvf2", 2, TRUE}, {"mvf3", 3, TRUE},
703 {"mvf4", 4, TRUE}, {"mvf5", 5, TRUE}, {"mvf6", 6, TRUE}, {"mvf7", 7, TRUE},
704 {"mvf8", 8, TRUE}, {"mvf9", 9, TRUE}, {"mvf10", 10, TRUE}, {"mvf11", 11, TRUE},
705 {"mvf12", 12, TRUE}, {"mvf13", 13, TRUE}, {"mvf14", 14, TRUE}, {"mvf15", 15, TRUE},
706 {NULL, 0, TRUE}
707 };
708
709 static const struct reg_entry mav_mvd_table[] =
710 {
711 {"mvd0", 0, TRUE}, {"mvd1", 1, TRUE}, {"mvd2", 2, TRUE}, {"mvd3", 3, TRUE},
712 {"mvd4", 4, TRUE}, {"mvd5", 5, TRUE}, {"mvd6", 6, TRUE}, {"mvd7", 7, TRUE},
713 {"mvd8", 8, TRUE}, {"mvd9", 9, TRUE}, {"mvd10", 10, TRUE}, {"mvd11", 11, TRUE},
714 {"mvd12", 12, TRUE}, {"mvd13", 13, TRUE}, {"mvd14", 14, TRUE}, {"mvd15", 15, TRUE},
715 {NULL, 0, TRUE}
716 };
717
718 static const struct reg_entry mav_mvfx_table[] =
719 {
720 {"mvfx0", 0, TRUE}, {"mvfx1", 1, TRUE}, {"mvfx2", 2, TRUE}, {"mvfx3", 3, TRUE},
721 {"mvfx4", 4, TRUE}, {"mvfx5", 5, TRUE}, {"mvfx6", 6, TRUE}, {"mvfx7", 7, TRUE},
722 {"mvfx8", 8, TRUE}, {"mvfx9", 9, TRUE}, {"mvfx10", 10, TRUE}, {"mvfx11", 11, TRUE},
723 {"mvfx12", 12, TRUE}, {"mvfx13", 13, TRUE}, {"mvfx14", 14, TRUE}, {"mvfx15", 15, TRUE},
724 {NULL, 0, TRUE}
725 };
726
727 static const struct reg_entry mav_mvdx_table[] =
728 {
729 {"mvdx0", 0, TRUE}, {"mvdx1", 1, TRUE}, {"mvdx2", 2, TRUE}, {"mvdx3", 3, TRUE},
730 {"mvdx4", 4, TRUE}, {"mvdx5", 5, TRUE}, {"mvdx6", 6, TRUE}, {"mvdx7", 7, TRUE},
731 {"mvdx8", 8, TRUE}, {"mvdx9", 9, TRUE}, {"mvdx10", 10, TRUE}, {"mvdx11", 11, TRUE},
732 {"mvdx12", 12, TRUE}, {"mvdx13", 13, TRUE}, {"mvdx14", 14, TRUE}, {"mvdx15", 15, TRUE},
733 {NULL, 0, TRUE}
734 };
735
736 static const struct reg_entry mav_mvax_table[] =
737 {
738 {"mvax0", 0, TRUE}, {"mvax1", 1, TRUE}, {"mvax2", 2, TRUE}, {"mvax3", 3, TRUE},
739 {NULL, 0, TRUE}
740 };
741
742 static const struct reg_entry mav_dspsc_table[] =
743 {
744 {"dspsc", 0, TRUE},
745 {NULL, 0, TRUE}
746 };
747
748 struct reg_map
749 {
750 const struct reg_entry * names;
751 int max_regno;
752 struct hash_control * htab;
753 const char * expected;
754 };
755
756 struct reg_map all_reg_maps[] =
757 {
758 {rn_table, 15, NULL, N_("ARM register expected")},
759 {cp_table, 15, NULL, N_("bad or missing co-processor number")},
760 {cn_table, 15, NULL, N_("co-processor register expected")},
761 {fn_table, 7, NULL, N_("FPA register expected")},
762 {sn_table, 31, NULL, N_("VFP single precision register expected")},
763 {dn_table, 15, NULL, N_("VFP double precision register expected")},
764 {mav_mvf_table, 15, NULL, N_("Maverick MVF register expected")},
765 {mav_mvd_table, 15, NULL, N_("Maverick MVD register expected")},
766 {mav_mvfx_table, 15, NULL, N_("Maverick MVFX register expected")},
767 {mav_mvdx_table, 15, NULL, N_("Maverick MVDX register expected")},
768 {mav_mvax_table, 3, NULL, N_("Maverick MVAX register expected")},
769 {mav_dspsc_table, 0, NULL, N_("Maverick DSPSC register expected")},
770 {iwmmxt_table, 23, NULL, N_("Intel Wireless MMX technology register expected")},
771 };
772
773 /* Enumeration matching entries in table above. */
774 enum arm_reg_type
775 {
776 REG_TYPE_RN = 0,
777 #define REG_TYPE_FIRST REG_TYPE_RN
778 REG_TYPE_CP = 1,
779 REG_TYPE_CN = 2,
780 REG_TYPE_FN = 3,
781 REG_TYPE_SN = 4,
782 REG_TYPE_DN = 5,
783 REG_TYPE_MVF = 6,
784 REG_TYPE_MVD = 7,
785 REG_TYPE_MVFX = 8,
786 REG_TYPE_MVDX = 9,
787 REG_TYPE_MVAX = 10,
788 REG_TYPE_DSPSC = 11,
789 REG_TYPE_IWMMXT = 12,
790
791 REG_TYPE_MAX = 13
792 };
793
794 /* ARM instructions take 4bytes in the object file, Thumb instructions
795 take 2: */
796 #define INSN_SIZE 4
797
798 /* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
799 #define MAV_MODE1 0x100c
800
801 /* "INSN<cond> X,Y" where X:bit16, Y:bit12. */
802 #define MAV_MODE2 0x0c10
803
804 /* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
805 #define MAV_MODE3 0x100c
806
807 /* "INSN<cond> X,Y,Z" where X:16, Y:0, Z:12. */
808 #define MAV_MODE4 0x0c0010
809
810 /* "INSN<cond> X,Y,Z" where X:12, Y:16, Z:0. */
811 #define MAV_MODE5 0x00100c
812
813 /* "INSN<cond> W,X,Y,Z" where W:5, X:12, Y:16, Z:0. */
814 #define MAV_MODE6 0x00100c05
815
816 struct asm_opcode
817 {
818 /* Basic string to match. */
819 const char * template;
820
821 /* Basic instruction code. */
822 unsigned long value;
823
824 /* Offset into the template where the condition code (if any) will be.
825 If zero, then the instruction is never conditional. */
826 unsigned cond_offset;
827
828 /* Which architecture variant provides this instruction. */
829 unsigned long variant;
830
831 /* Function to call to parse args. */
832 void (* parms) (char *);
833 };
834
835 /* Defines for various bits that we will want to toggle. */
836 #define INST_IMMEDIATE 0x02000000
837 #define OFFSET_REG 0x02000000
838 #define HWOFFSET_IMM 0x00400000
839 #define SHIFT_BY_REG 0x00000010
840 #define PRE_INDEX 0x01000000
841 #define INDEX_UP 0x00800000
842 #define WRITE_BACK 0x00200000
843 #define LDM_TYPE_2_OR_3 0x00400000
844
845 #define LITERAL_MASK 0xf000f000
846 #define OPCODE_MASK 0xfe1fffff
847 #define V4_STR_BIT 0x00000020
848
849 #define DATA_OP_SHIFT 21
850
851 /* Codes to distinguish the arithmetic instructions. */
852 #define OPCODE_AND 0
853 #define OPCODE_EOR 1
854 #define OPCODE_SUB 2
855 #define OPCODE_RSB 3
856 #define OPCODE_ADD 4
857 #define OPCODE_ADC 5
858 #define OPCODE_SBC 6
859 #define OPCODE_RSC 7
860 #define OPCODE_TST 8
861 #define OPCODE_TEQ 9
862 #define OPCODE_CMP 10
863 #define OPCODE_CMN 11
864 #define OPCODE_ORR 12
865 #define OPCODE_MOV 13
866 #define OPCODE_BIC 14
867 #define OPCODE_MVN 15
868
869 #define T_OPCODE_MUL 0x4340
870 #define T_OPCODE_TST 0x4200
871 #define T_OPCODE_CMN 0x42c0
872 #define T_OPCODE_NEG 0x4240
873 #define T_OPCODE_MVN 0x43c0
874
875 #define T_OPCODE_ADD_R3 0x1800
876 #define T_OPCODE_SUB_R3 0x1a00
877 #define T_OPCODE_ADD_HI 0x4400
878 #define T_OPCODE_ADD_ST 0xb000
879 #define T_OPCODE_SUB_ST 0xb080
880 #define T_OPCODE_ADD_SP 0xa800
881 #define T_OPCODE_ADD_PC 0xa000
882 #define T_OPCODE_ADD_I8 0x3000
883 #define T_OPCODE_SUB_I8 0x3800
884 #define T_OPCODE_ADD_I3 0x1c00
885 #define T_OPCODE_SUB_I3 0x1e00
886
887 #define T_OPCODE_ASR_R 0x4100
888 #define T_OPCODE_LSL_R 0x4080
889 #define T_OPCODE_LSR_R 0x40c0
890 #define T_OPCODE_ASR_I 0x1000
891 #define T_OPCODE_LSL_I 0x0000
892 #define T_OPCODE_LSR_I 0x0800
893
894 #define T_OPCODE_MOV_I8 0x2000
895 #define T_OPCODE_CMP_I8 0x2800
896 #define T_OPCODE_CMP_LR 0x4280
897 #define T_OPCODE_MOV_HR 0x4600
898 #define T_OPCODE_CMP_HR 0x4500
899
900 #define T_OPCODE_LDR_PC 0x4800
901 #define T_OPCODE_LDR_SP 0x9800
902 #define T_OPCODE_STR_SP 0x9000
903 #define T_OPCODE_LDR_IW 0x6800
904 #define T_OPCODE_STR_IW 0x6000
905 #define T_OPCODE_LDR_IH 0x8800
906 #define T_OPCODE_STR_IH 0x8000
907 #define T_OPCODE_LDR_IB 0x7800
908 #define T_OPCODE_STR_IB 0x7000
909 #define T_OPCODE_LDR_RW 0x5800
910 #define T_OPCODE_STR_RW 0x5000
911 #define T_OPCODE_LDR_RH 0x5a00
912 #define T_OPCODE_STR_RH 0x5200
913 #define T_OPCODE_LDR_RB 0x5c00
914 #define T_OPCODE_STR_RB 0x5400
915
916 #define T_OPCODE_PUSH 0xb400
917 #define T_OPCODE_POP 0xbc00
918
919 #define T_OPCODE_BRANCH 0xe7fe
920
921 #define THUMB_SIZE 2 /* Size of thumb instruction. */
922 #define THUMB_REG_LO 0x1
923 #define THUMB_REG_HI 0x2
924 #define THUMB_REG_ANY 0x3
925
926 #define THUMB_H1 0x0080
927 #define THUMB_H2 0x0040
928
929 #define THUMB_ASR 0
930 #define THUMB_LSL 1
931 #define THUMB_LSR 2
932
933 #define THUMB_MOVE 0
934 #define THUMB_COMPARE 1
935 #define THUMB_CPY 2
936
937 #define THUMB_LOAD 0
938 #define THUMB_STORE 1
939
940 #define THUMB_PP_PC_LR 0x0100
941
942 /* These three are used for immediate shifts, do not alter. */
943 #define THUMB_WORD 2
944 #define THUMB_HALFWORD 1
945 #define THUMB_BYTE 0
946
947 struct thumb_opcode
948 {
949 /* Basic string to match. */
950 const char * template;
951
952 /* Basic instruction code. */
953 unsigned long value;
954
955 int size;
956
957 /* Which CPU variants this exists for. */
958 unsigned long variant;
959
960 /* Function to call to parse args. */
961 void (* parms) (char *);
962 };
963
964 #define BAD_ARGS _("bad arguments to instruction")
965 #define BAD_PC _("r15 not allowed here")
966 #define BAD_COND _("instruction is not conditional")
967 #define ERR_NO_ACCUM _("acc0 expected")
968
969 static struct hash_control * arm_ops_hsh = NULL;
970 static struct hash_control * arm_tops_hsh = NULL;
971 static struct hash_control * arm_cond_hsh = NULL;
972 static struct hash_control * arm_shift_hsh = NULL;
973 static struct hash_control * arm_psr_hsh = NULL;
974
975 /* Stuff needed to resolve the label ambiguity
976 As:
977 ...
978 label: <insn>
979 may differ from:
980 ...
981 label:
982 <insn>
983 */
984
985 symbolS * last_label_seen;
986 static int label_is_thumb_function_name = FALSE;
987 \f
988 /* Literal Pool stuff. */
989
990 #define MAX_LITERAL_POOL_SIZE 1024
991
992 /* Literal pool structure. Held on a per-section
993 and per-sub-section basis. */
994
995 typedef struct literal_pool
996 {
997 expressionS literals [MAX_LITERAL_POOL_SIZE];
998 unsigned int next_free_entry;
999 unsigned int id;
1000 symbolS * symbol;
1001 segT section;
1002 subsegT sub_section;
1003 struct literal_pool * next;
1004 } literal_pool;
1005
1006 /* Pointer to a linked list of literal pools. */
1007 literal_pool * list_of_pools = NULL;
1008
1009 static literal_pool *
1010 find_literal_pool (void)
1011 {
1012 literal_pool * pool;
1013
1014 for (pool = list_of_pools; pool != NULL; pool = pool->next)
1015 {
1016 if (pool->section == now_seg
1017 && pool->sub_section == now_subseg)
1018 break;
1019 }
1020
1021 return pool;
1022 }
1023
1024 static literal_pool *
1025 find_or_make_literal_pool (void)
1026 {
1027 /* Next literal pool ID number. */
1028 static unsigned int latest_pool_num = 1;
1029 literal_pool * pool;
1030
1031 pool = find_literal_pool ();
1032
1033 if (pool == NULL)
1034 {
1035 /* Create a new pool. */
1036 pool = xmalloc (sizeof (* pool));
1037 if (! pool)
1038 return NULL;
1039
1040 pool->next_free_entry = 0;
1041 pool->section = now_seg;
1042 pool->sub_section = now_subseg;
1043 pool->next = list_of_pools;
1044 pool->symbol = NULL;
1045
1046 /* Add it to the list. */
1047 list_of_pools = pool;
1048 }
1049
1050 /* New pools, and emptied pools, will have a NULL symbol. */
1051 if (pool->symbol == NULL)
1052 {
1053 pool->symbol = symbol_create (FAKE_LABEL_NAME, undefined_section,
1054 (valueT) 0, &zero_address_frag);
1055 pool->id = latest_pool_num ++;
1056 }
1057
1058 /* Done. */
1059 return pool;
1060 }
1061
1062 /* Add the literal in the global 'inst'
1063 structure to the relevent literal pool. */
1064
1065 static int
1066 add_to_lit_pool (void)
1067 {
1068 literal_pool * pool;
1069 unsigned int entry;
1070
1071 pool = find_or_make_literal_pool ();
1072
1073 /* Check if this literal value is already in the pool. */
1074 for (entry = 0; entry < pool->next_free_entry; entry ++)
1075 {
1076 if ((pool->literals[entry].X_op == inst.reloc.exp.X_op)
1077 && (inst.reloc.exp.X_op == O_constant)
1078 && (pool->literals[entry].X_add_number
1079 == inst.reloc.exp.X_add_number)
1080 && (pool->literals[entry].X_unsigned
1081 == inst.reloc.exp.X_unsigned))
1082 break;
1083
1084 if ((pool->literals[entry].X_op == inst.reloc.exp.X_op)
1085 && (inst.reloc.exp.X_op == O_symbol)
1086 && (pool->literals[entry].X_add_number
1087 == inst.reloc.exp.X_add_number)
1088 && (pool->literals[entry].X_add_symbol
1089 == inst.reloc.exp.X_add_symbol)
1090 && (pool->literals[entry].X_op_symbol
1091 == inst.reloc.exp.X_op_symbol))
1092 break;
1093 }
1094
1095 /* Do we need to create a new entry? */
1096 if (entry == pool->next_free_entry)
1097 {
1098 if (entry >= MAX_LITERAL_POOL_SIZE)
1099 {
1100 inst.error = _("literal pool overflow");
1101 return FAIL;
1102 }
1103
1104 pool->literals[entry] = inst.reloc.exp;
1105 pool->next_free_entry += 1;
1106 }
1107
1108 inst.reloc.exp.X_op = O_symbol;
1109 inst.reloc.exp.X_add_number = ((int) entry) * 4 - 8;
1110 inst.reloc.exp.X_add_symbol = pool->symbol;
1111
1112 return SUCCESS;
1113 }
1114
1115 /* Can't use symbol_new here, so have to create a symbol and then at
1116 a later date assign it a value. Thats what these functions do. */
1117
1118 static void
1119 symbol_locate (symbolS * symbolP,
1120 const char * name, /* It is copied, the caller can modify. */
1121 segT segment, /* Segment identifier (SEG_<something>). */
1122 valueT valu, /* Symbol value. */
1123 fragS * frag) /* Associated fragment. */
1124 {
1125 unsigned int name_length;
1126 char * preserved_copy_of_name;
1127
1128 name_length = strlen (name) + 1; /* +1 for \0. */
1129 obstack_grow (&notes, name, name_length);
1130 preserved_copy_of_name = obstack_finish (&notes);
1131 #ifdef STRIP_UNDERSCORE
1132 if (preserved_copy_of_name[0] == '_')
1133 preserved_copy_of_name++;
1134 #endif
1135
1136 #ifdef tc_canonicalize_symbol_name
1137 preserved_copy_of_name =
1138 tc_canonicalize_symbol_name (preserved_copy_of_name);
1139 #endif
1140
1141 S_SET_NAME (symbolP, preserved_copy_of_name);
1142
1143 S_SET_SEGMENT (symbolP, segment);
1144 S_SET_VALUE (symbolP, valu);
1145 symbol_clear_list_pointers (symbolP);
1146
1147 symbol_set_frag (symbolP, frag);
1148
1149 /* Link to end of symbol chain. */
1150 {
1151 extern int symbol_table_frozen;
1152
1153 if (symbol_table_frozen)
1154 abort ();
1155 }
1156
1157 symbol_append (symbolP, symbol_lastP, & symbol_rootP, & symbol_lastP);
1158
1159 obj_symbol_new_hook (symbolP);
1160
1161 #ifdef tc_symbol_new_hook
1162 tc_symbol_new_hook (symbolP);
1163 #endif
1164
1165 #ifdef DEBUG_SYMS
1166 verify_symbol_chain (symbol_rootP, symbol_lastP);
1167 #endif /* DEBUG_SYMS */
1168 }
1169
1170 /* Check that an immediate is valid.
1171 If so, convert it to the right format. */
1172
1173 static unsigned int
1174 validate_immediate (unsigned int val)
1175 {
1176 unsigned int a;
1177 unsigned int i;
1178
1179 #define rotate_left(v, n) (v << n | v >> (32 - n))
1180
1181 for (i = 0; i < 32; i += 2)
1182 if ((a = rotate_left (val, i)) <= 0xff)
1183 return a | (i << 7); /* 12-bit pack: [shift-cnt,const]. */
1184
1185 return FAIL;
1186 }
1187
1188 /* Check to see if an immediate can be computed as two separate immediate
1189 values, added together. We already know that this value cannot be
1190 computed by just one ARM instruction. */
1191
1192 static unsigned int
1193 validate_immediate_twopart (unsigned int val,
1194 unsigned int * highpart)
1195 {
1196 unsigned int a;
1197 unsigned int i;
1198
1199 for (i = 0; i < 32; i += 2)
1200 if (((a = rotate_left (val, i)) & 0xff) != 0)
1201 {
1202 if (a & 0xff00)
1203 {
1204 if (a & ~ 0xffff)
1205 continue;
1206 * highpart = (a >> 8) | ((i + 24) << 7);
1207 }
1208 else if (a & 0xff0000)
1209 {
1210 if (a & 0xff000000)
1211 continue;
1212 * highpart = (a >> 16) | ((i + 16) << 7);
1213 }
1214 else
1215 {
1216 assert (a & 0xff000000);
1217 * highpart = (a >> 24) | ((i + 8) << 7);
1218 }
1219
1220 return (a & 0xff) | (i << 7);
1221 }
1222
1223 return FAIL;
1224 }
1225
1226 static int
1227 validate_offset_imm (unsigned int val, int hwse)
1228 {
1229 if ((hwse && val > 255) || val > 4095)
1230 return FAIL;
1231 return val;
1232 }
1233
1234 \f
1235 #ifdef OBJ_ELF
1236 /* This code is to handle mapping symbols as defined in the ARM ELF spec.
1237 (This text is taken from version B-02 of the spec):
1238
1239 4.4.7 Mapping and tagging symbols
1240
1241 A section of an ARM ELF file can contain a mixture of ARM code,
1242 Thumb code, and data. There are inline transitions between code
1243 and data at literal pool boundaries. There can also be inline
1244 transitions between ARM code and Thumb code, for example in
1245 ARM-Thumb inter-working veneers. Linkers, machine-level
1246 debuggers, profiling tools, and disassembly tools need to map
1247 images accurately. For example, setting an ARM breakpoint on a
1248 Thumb location, or in a literal pool, can crash the program
1249 being debugged, ruining the debugging session.
1250
1251 ARM ELF entities are mapped (see section 4.4.7.1 below) and
1252 tagged (see section 4.4.7.2 below) using local symbols (with
1253 binding STB_LOCAL). To assist consumers, mapping and tagging
1254 symbols should be collated first in the symbol table, before
1255 other symbols with binding STB_LOCAL.
1256
1257 To allow properly collated mapping and tagging symbols to be
1258 skipped by consumers that have no interest in them, the first
1259 such symbol should have the name $m and its st_value field equal
1260 to the total number of mapping and tagging symbols (including
1261 the $m) in the symbol table.
1262
1263 4.4.7.1 Mapping symbols
1264
1265 $a Labels the first byte of a sequence of ARM instructions.
1266 Its type is STT_FUNC.
1267
1268 $d Labels the first byte of a sequence of data items.
1269 Its type is STT_OBJECT.
1270
1271 $t Labels the first byte of a sequence of Thumb instructions.
1272 Its type is STT_FUNC.
1273
1274 This list of mapping symbols may be extended in the future.
1275
1276 Section-relative mapping symbols
1277
1278 Mapping symbols defined in a section define a sequence of
1279 half-open address intervals that cover the address range of the
1280 section. Each interval starts at the address defined by a
1281 mapping symbol, and continues up to, but not including, the
1282 address defined by the next (in address order) mapping symbol or
1283 the end of the section. A corollary is that there must be a
1284 mapping symbol defined at the beginning of each section.
1285 Consumers can ignore the size of a section-relative mapping
1286 symbol. Producers can set it to 0.
1287
1288 Absolute mapping symbols
1289
1290 Because of the need to crystallize a Thumb address with the
1291 Thumb-bit set, absolute symbol of type STT_FUNC (symbols of type
1292 STT_FUNC defined in section SHN_ABS) need to be mapped with $a
1293 or $t.
1294
1295 The extent of a mapping symbol defined in SHN_ABS is [st_value,
1296 st_value + st_size), or [st_value, st_value + 1) if st_size = 0,
1297 where [x, y) denotes the half-open address range from x,
1298 inclusive, to y, exclusive.
1299
1300 In the absence of a mapping symbol, a consumer can interpret a
1301 function symbol with an odd value as the Thumb code address
1302 obtained by clearing the least significant bit of the
1303 value. This interpretation is deprecated, and it may not work in
1304 the future.
1305
1306 Note - the Tagging symbols ($b, $f, $p $m) have been dropped from
1307 the EABI (which is still under development), so they are not
1308 implemented here. */
1309
1310 static enum mstate mapstate = MAP_UNDEFINED;
1311
1312 static void
1313 mapping_state (enum mstate state)
1314 {
1315 symbolS * symbolP;
1316 const char * symname;
1317 int type;
1318
1319 if (mapstate == state)
1320 /* The mapping symbol has already been emitted.
1321 There is nothing else to do. */
1322 return;
1323
1324 mapstate = state;
1325
1326 switch (state)
1327 {
1328 case MAP_DATA:
1329 symname = "$d";
1330 type = BSF_OBJECT;
1331 break;
1332 case MAP_ARM:
1333 symname = "$a";
1334 type = BSF_FUNCTION;
1335 break;
1336 case MAP_THUMB:
1337 symname = "$t";
1338 type = BSF_FUNCTION;
1339 break;
1340 case MAP_UNDEFINED:
1341 return;
1342 default:
1343 abort ();
1344 }
1345
1346 seg_info (now_seg)->tc_segment_info_data = state;
1347
1348 symbolP = symbol_new (symname, now_seg, (valueT) frag_now_fix (), frag_now);
1349 symbol_table_insert (symbolP);
1350 symbol_get_bfdsym (symbolP)->flags |= type | BSF_LOCAL;
1351
1352 switch (state)
1353 {
1354 case MAP_ARM:
1355 THUMB_SET_FUNC (symbolP, 0);
1356 ARM_SET_THUMB (symbolP, 0);
1357 ARM_SET_INTERWORK (symbolP, support_interwork);
1358 break;
1359
1360 case MAP_THUMB:
1361 THUMB_SET_FUNC (symbolP, 1);
1362 ARM_SET_THUMB (symbolP, 1);
1363 ARM_SET_INTERWORK (symbolP, support_interwork);
1364 break;
1365
1366 case MAP_DATA:
1367 default:
1368 return;
1369 }
1370 }
1371
1372 /* When we change sections we need to issue a new mapping symbol. */
1373
1374 void
1375 arm_elf_change_section (void)
1376 {
1377 flagword flags;
1378
1379 /* Link an unlinked unwind index table section to the .text section. */
1380 if (elf_section_type (now_seg) == SHT_ARM_EXIDX
1381 && elf_linked_to_section (now_seg) == NULL)
1382 elf_linked_to_section (now_seg) = text_section;
1383
1384 if (!SEG_NORMAL (now_seg))
1385 return;
1386
1387 flags = bfd_get_section_flags (stdoutput, now_seg);
1388
1389 /* We can ignore sections that only contain debug info. */
1390 if ((flags & SEC_ALLOC) == 0)
1391 return;
1392
1393 mapstate = seg_info (now_seg)->tc_segment_info_data;
1394 }
1395
1396 int
1397 arm_elf_section_type (const char * str, size_t len)
1398 {
1399 if (len == 5 && strncmp (str, "exidx", 5) == 0)
1400 return SHT_ARM_EXIDX;
1401
1402 return -1;
1403 }
1404 #else
1405 #define mapping_state(a)
1406 #endif /* OBJ_ELF */
1407 \f
1408 /* arm_reg_parse () := if it looks like a register, return its token and
1409 advance the pointer. */
1410
1411 static int
1412 arm_reg_parse (char ** ccp, struct hash_control * htab)
1413 {
1414 char * start = * ccp;
1415 char c;
1416 char * p;
1417 struct reg_entry * reg;
1418
1419 #ifdef REGISTER_PREFIX
1420 if (*start != REGISTER_PREFIX)
1421 return FAIL;
1422 p = start + 1;
1423 #else
1424 p = start;
1425 #ifdef OPTIONAL_REGISTER_PREFIX
1426 if (*p == OPTIONAL_REGISTER_PREFIX)
1427 p++, start++;
1428 #endif
1429 #endif
1430 if (!ISALPHA (*p) || !is_name_beginner (*p))
1431 return FAIL;
1432
1433 c = *p++;
1434 while (ISALPHA (c) || ISDIGIT (c) || c == '_')
1435 c = *p++;
1436
1437 *--p = 0;
1438 reg = (struct reg_entry *) hash_find (htab, start);
1439 *p = c;
1440
1441 if (reg)
1442 {
1443 *ccp = p;
1444 return reg->number;
1445 }
1446
1447 return FAIL;
1448 }
1449
1450 /* Search for the following register name in each of the possible reg name
1451 tables. Return the classification if found, or REG_TYPE_MAX if not
1452 present. */
1453
1454 static enum arm_reg_type
1455 arm_reg_parse_any (char *cp)
1456 {
1457 int i;
1458
1459 for (i = (int) REG_TYPE_FIRST; i < (int) REG_TYPE_MAX; i++)
1460 if (arm_reg_parse (&cp, all_reg_maps[i].htab) != FAIL)
1461 return (enum arm_reg_type) i;
1462
1463 return REG_TYPE_MAX;
1464 }
1465
1466 static void
1467 opcode_select (int width)
1468 {
1469 switch (width)
1470 {
1471 case 16:
1472 if (! thumb_mode)
1473 {
1474 if (! (cpu_variant & ARM_EXT_V4T))
1475 as_bad (_("selected processor does not support THUMB opcodes"));
1476
1477 thumb_mode = 1;
1478 /* No need to force the alignment, since we will have been
1479 coming from ARM mode, which is word-aligned. */
1480 record_alignment (now_seg, 1);
1481 }
1482 mapping_state (MAP_THUMB);
1483 break;
1484
1485 case 32:
1486 if (thumb_mode)
1487 {
1488 if ((cpu_variant & ARM_ALL) == ARM_EXT_V4T)
1489 as_bad (_("selected processor does not support ARM opcodes"));
1490
1491 thumb_mode = 0;
1492
1493 if (!need_pass_2)
1494 frag_align (2, 0, 0);
1495
1496 record_alignment (now_seg, 1);
1497 }
1498 mapping_state (MAP_ARM);
1499 break;
1500
1501 default:
1502 as_bad (_("invalid instruction size selected (%d)"), width);
1503 }
1504 }
1505
1506 static void
1507 s_req (int a ATTRIBUTE_UNUSED)
1508 {
1509 as_bad (_("invalid syntax for .req directive"));
1510 }
1511
1512 /* The .unreq directive deletes an alias which was previously defined
1513 by .req. For example:
1514
1515 my_alias .req r11
1516 .unreq my_alias */
1517
1518 static void
1519 s_unreq (int a ATTRIBUTE_UNUSED)
1520 {
1521 char * name;
1522 char saved_char;
1523
1524 skip_whitespace (input_line_pointer);
1525 name = input_line_pointer;
1526
1527 while (*input_line_pointer != 0
1528 && *input_line_pointer != ' '
1529 && *input_line_pointer != '\n')
1530 ++input_line_pointer;
1531
1532 saved_char = *input_line_pointer;
1533 *input_line_pointer = 0;
1534
1535 if (*name)
1536 {
1537 enum arm_reg_type req_type = arm_reg_parse_any (name);
1538
1539 if (req_type != REG_TYPE_MAX)
1540 {
1541 char *temp_name = name;
1542 int req_no = arm_reg_parse (&temp_name, all_reg_maps[req_type].htab);
1543
1544 if (req_no != FAIL)
1545 {
1546 struct reg_entry *req_entry;
1547
1548 /* Check to see if this alias is a builtin one. */
1549 req_entry = hash_delete (all_reg_maps[req_type].htab, name);
1550
1551 if (!req_entry)
1552 as_bad (_("unreq: missing hash entry for \"%s\""), name);
1553 else if (req_entry->builtin)
1554 /* FIXME: We are deleting a built in register alias which
1555 points to a const data structure, so we only need to
1556 free up the memory used by the key in the hash table.
1557 Unfortunately we have not recorded this value, so this
1558 is a memory leak. */
1559 /* FIXME: Should we issue a warning message ? */
1560 ;
1561 else
1562 {
1563 /* Deleting a user defined alias. We need to free the
1564 key and the value, but fortunately the key is the same
1565 as the value->name field. */
1566 free ((char *) req_entry->name);
1567 free (req_entry);
1568 }
1569 }
1570 else
1571 as_bad (_(".unreq: unrecognized symbol \"%s\""), name);
1572 }
1573 else
1574 as_bad (_(".unreq: unrecognized symbol \"%s\""), name);
1575 }
1576 else
1577 as_bad (_("invalid syntax for .unreq directive"));
1578
1579 *input_line_pointer = saved_char;
1580 demand_empty_rest_of_line ();
1581 }
1582
1583 static void
1584 s_bss (int ignore ATTRIBUTE_UNUSED)
1585 {
1586 /* We don't support putting frags in the BSS segment, we fake it by
1587 marking in_bss, then looking at s_skip for clues. */
1588 subseg_set (bss_section, 0);
1589 demand_empty_rest_of_line ();
1590 mapping_state (MAP_DATA);
1591 }
1592
1593 static void
1594 s_even (int ignore ATTRIBUTE_UNUSED)
1595 {
1596 /* Never make frag if expect extra pass. */
1597 if (!need_pass_2)
1598 frag_align (1, 0, 0);
1599
1600 record_alignment (now_seg, 1);
1601
1602 demand_empty_rest_of_line ();
1603 }
1604
1605 static void
1606 s_ltorg (int ignored ATTRIBUTE_UNUSED)
1607 {
1608 unsigned int entry;
1609 literal_pool * pool;
1610 char sym_name[20];
1611
1612 pool = find_literal_pool ();
1613 if (pool == NULL
1614 || pool->symbol == NULL
1615 || pool->next_free_entry == 0)
1616 return;
1617
1618 mapping_state (MAP_DATA);
1619
1620 /* Align pool as you have word accesses.
1621 Only make a frag if we have to. */
1622 if (!need_pass_2)
1623 frag_align (2, 0, 0);
1624
1625 record_alignment (now_seg, 2);
1626
1627 sprintf (sym_name, "$$lit_\002%x", pool->id);
1628
1629 symbol_locate (pool->symbol, sym_name, now_seg,
1630 (valueT) frag_now_fix (), frag_now);
1631 symbol_table_insert (pool->symbol);
1632
1633 ARM_SET_THUMB (pool->symbol, thumb_mode);
1634
1635 #if defined OBJ_COFF || defined OBJ_ELF
1636 ARM_SET_INTERWORK (pool->symbol, support_interwork);
1637 #endif
1638
1639 for (entry = 0; entry < pool->next_free_entry; entry ++)
1640 /* First output the expression in the instruction to the pool. */
1641 emit_expr (&(pool->literals[entry]), 4); /* .word */
1642
1643 /* Mark the pool as empty. */
1644 pool->next_free_entry = 0;
1645 pool->symbol = NULL;
1646 }
1647
1648 /* Same as s_align_ptwo but align 0 => align 2. */
1649
1650 static void
1651 s_align (int unused ATTRIBUTE_UNUSED)
1652 {
1653 int temp;
1654 long temp_fill;
1655 long max_alignment = 15;
1656
1657 temp = get_absolute_expression ();
1658 if (temp > max_alignment)
1659 as_bad (_("alignment too large: %d assumed"), temp = max_alignment);
1660 else if (temp < 0)
1661 {
1662 as_bad (_("alignment negative. 0 assumed."));
1663 temp = 0;
1664 }
1665
1666 if (*input_line_pointer == ',')
1667 {
1668 input_line_pointer++;
1669 temp_fill = get_absolute_expression ();
1670 }
1671 else
1672 temp_fill = 0;
1673
1674 if (!temp)
1675 temp = 2;
1676
1677 /* Only make a frag if we HAVE to. */
1678 if (temp && !need_pass_2)
1679 frag_align (temp, (int) temp_fill, 0);
1680 demand_empty_rest_of_line ();
1681
1682 record_alignment (now_seg, temp);
1683 }
1684
1685 static void
1686 s_force_thumb (int ignore ATTRIBUTE_UNUSED)
1687 {
1688 /* If we are not already in thumb mode go into it, EVEN if
1689 the target processor does not support thumb instructions.
1690 This is used by gcc/config/arm/lib1funcs.asm for example
1691 to compile interworking support functions even if the
1692 target processor should not support interworking. */
1693 if (! thumb_mode)
1694 {
1695 thumb_mode = 2;
1696
1697 record_alignment (now_seg, 1);
1698 }
1699
1700 demand_empty_rest_of_line ();
1701 }
1702
1703 static void
1704 s_thumb_func (int ignore ATTRIBUTE_UNUSED)
1705 {
1706 if (! thumb_mode)
1707 opcode_select (16);
1708
1709 /* The following label is the name/address of the start of a Thumb function.
1710 We need to know this for the interworking support. */
1711 label_is_thumb_function_name = TRUE;
1712
1713 demand_empty_rest_of_line ();
1714 }
1715
1716 /* Perform a .set directive, but also mark the alias as
1717 being a thumb function. */
1718
1719 static void
1720 s_thumb_set (int equiv)
1721 {
1722 /* XXX the following is a duplicate of the code for s_set() in read.c
1723 We cannot just call that code as we need to get at the symbol that
1724 is created. */
1725 char * name;
1726 char delim;
1727 char * end_name;
1728 symbolS * symbolP;
1729
1730 /* Especial apologies for the random logic:
1731 This just grew, and could be parsed much more simply!
1732 Dean - in haste. */
1733 name = input_line_pointer;
1734 delim = get_symbol_end ();
1735 end_name = input_line_pointer;
1736 *end_name = delim;
1737
1738 SKIP_WHITESPACE ();
1739
1740 if (*input_line_pointer != ',')
1741 {
1742 *end_name = 0;
1743 as_bad (_("expected comma after name \"%s\""), name);
1744 *end_name = delim;
1745 ignore_rest_of_line ();
1746 return;
1747 }
1748
1749 input_line_pointer++;
1750 *end_name = 0;
1751
1752 if (name[0] == '.' && name[1] == '\0')
1753 {
1754 /* XXX - this should not happen to .thumb_set. */
1755 abort ();
1756 }
1757
1758 if ((symbolP = symbol_find (name)) == NULL
1759 && (symbolP = md_undefined_symbol (name)) == NULL)
1760 {
1761 #ifndef NO_LISTING
1762 /* When doing symbol listings, play games with dummy fragments living
1763 outside the normal fragment chain to record the file and line info
1764 for this symbol. */
1765 if (listing & LISTING_SYMBOLS)
1766 {
1767 extern struct list_info_struct * listing_tail;
1768 fragS * dummy_frag = xmalloc (sizeof (fragS));
1769
1770 memset (dummy_frag, 0, sizeof (fragS));
1771 dummy_frag->fr_type = rs_fill;
1772 dummy_frag->line = listing_tail;
1773 symbolP = symbol_new (name, undefined_section, 0, dummy_frag);
1774 dummy_frag->fr_symbol = symbolP;
1775 }
1776 else
1777 #endif
1778 symbolP = symbol_new (name, undefined_section, 0, &zero_address_frag);
1779
1780 #ifdef OBJ_COFF
1781 /* "set" symbols are local unless otherwise specified. */
1782 SF_SET_LOCAL (symbolP);
1783 #endif /* OBJ_COFF */
1784 } /* Make a new symbol. */
1785
1786 symbol_table_insert (symbolP);
1787
1788 * end_name = delim;
1789
1790 if (equiv
1791 && S_IS_DEFINED (symbolP)
1792 && S_GET_SEGMENT (symbolP) != reg_section)
1793 as_bad (_("symbol `%s' already defined"), S_GET_NAME (symbolP));
1794
1795 pseudo_set (symbolP);
1796
1797 demand_empty_rest_of_line ();
1798
1799 /* XXX Now we come to the Thumb specific bit of code. */
1800
1801 THUMB_SET_FUNC (symbolP, 1);
1802 ARM_SET_THUMB (symbolP, 1);
1803 #if defined OBJ_ELF || defined OBJ_COFF
1804 ARM_SET_INTERWORK (symbolP, support_interwork);
1805 #endif
1806 }
1807
1808 static void
1809 s_arm (int ignore ATTRIBUTE_UNUSED)
1810 {
1811 opcode_select (32);
1812 demand_empty_rest_of_line ();
1813 }
1814
1815 static void
1816 s_thumb (int ignore ATTRIBUTE_UNUSED)
1817 {
1818 opcode_select (16);
1819 demand_empty_rest_of_line ();
1820 }
1821
1822 static void
1823 s_code (int unused ATTRIBUTE_UNUSED)
1824 {
1825 int temp;
1826
1827 temp = get_absolute_expression ();
1828 switch (temp)
1829 {
1830 case 16:
1831 case 32:
1832 opcode_select (temp);
1833 break;
1834
1835 default:
1836 as_bad (_("invalid operand to .code directive (%d) (expecting 16 or 32)"), temp);
1837 }
1838 }
1839
1840 static void
1841 end_of_line (char * str)
1842 {
1843 skip_whitespace (str);
1844
1845 if (*str != '\0' && !inst.error)
1846 inst.error = _("garbage following instruction");
1847 }
1848
1849 static int
1850 skip_past_comma (char ** str)
1851 {
1852 char * p = * str, c;
1853 int comma = 0;
1854
1855 while ((c = *p) == ' ' || c == ',')
1856 {
1857 p++;
1858 if (c == ',' && comma++)
1859 return FAIL;
1860 }
1861
1862 if (c == '\0')
1863 return FAIL;
1864
1865 *str = p;
1866 return comma ? SUCCESS : FAIL;
1867 }
1868
1869 /* Return TRUE if anything in the expression is a bignum. */
1870
1871 static int
1872 walk_no_bignums (symbolS * sp)
1873 {
1874 if (symbol_get_value_expression (sp)->X_op == O_big)
1875 return 1;
1876
1877 if (symbol_get_value_expression (sp)->X_add_symbol)
1878 {
1879 return (walk_no_bignums (symbol_get_value_expression (sp)->X_add_symbol)
1880 || (symbol_get_value_expression (sp)->X_op_symbol
1881 && walk_no_bignums (symbol_get_value_expression (sp)->X_op_symbol)));
1882 }
1883
1884 return 0;
1885 }
1886
1887 static int in_my_get_expression = 0;
1888
1889 static int
1890 my_get_expression (expressionS * ep, char ** str)
1891 {
1892 char * save_in;
1893 segT seg;
1894
1895 save_in = input_line_pointer;
1896 input_line_pointer = *str;
1897 in_my_get_expression = 1;
1898 seg = expression (ep);
1899 in_my_get_expression = 0;
1900
1901 if (ep->X_op == O_illegal)
1902 {
1903 /* We found a bad expression in md_operand(). */
1904 *str = input_line_pointer;
1905 input_line_pointer = save_in;
1906 return 1;
1907 }
1908
1909 #ifdef OBJ_AOUT
1910 if (seg != absolute_section
1911 && seg != text_section
1912 && seg != data_section
1913 && seg != bss_section
1914 && seg != undefined_section)
1915 {
1916 inst.error = _("bad_segment");
1917 *str = input_line_pointer;
1918 input_line_pointer = save_in;
1919 return 1;
1920 }
1921 #endif
1922
1923 /* Get rid of any bignums now, so that we don't generate an error for which
1924 we can't establish a line number later on. Big numbers are never valid
1925 in instructions, which is where this routine is always called. */
1926 if (ep->X_op == O_big
1927 || (ep->X_add_symbol
1928 && (walk_no_bignums (ep->X_add_symbol)
1929 || (ep->X_op_symbol
1930 && walk_no_bignums (ep->X_op_symbol)))))
1931 {
1932 inst.error = _("invalid constant");
1933 *str = input_line_pointer;
1934 input_line_pointer = save_in;
1935 return 1;
1936 }
1937
1938 *str = input_line_pointer;
1939 input_line_pointer = save_in;
1940 return 0;
1941 }
1942
1943 /* A standard register must be given at this point.
1944 SHIFT is the place to put it in inst.instruction.
1945 Restores input start point on error.
1946 Returns the reg#, or FAIL. */
1947
1948 static int
1949 reg_required_here (char ** str, int shift)
1950 {
1951 static char buff [128]; /* XXX */
1952 int reg;
1953 char * start = * str;
1954
1955 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_RN].htab)) != FAIL)
1956 {
1957 if (shift >= 0)
1958 inst.instruction |= reg << shift;
1959 return reg;
1960 }
1961
1962 /* Restore the start point, we may have got a reg of the wrong class. */
1963 *str = start;
1964
1965 /* In the few cases where we might be able to accept something else
1966 this error can be overridden. */
1967 sprintf (buff, _("register expected, not '%.100s'"), start);
1968 inst.error = buff;
1969
1970 return FAIL;
1971 }
1972
1973 /* A Intel Wireless MMX technology register
1974 must be given at this point.
1975 Shift is the place to put it in inst.instruction.
1976 Restores input start point on err.
1977 Returns the reg#, or FAIL. */
1978
1979 static int
1980 wreg_required_here (char ** str,
1981 int shift,
1982 enum wreg_type reg_type)
1983 {
1984 static char buff [128];
1985 int reg;
1986 char * start = *str;
1987
1988 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_IWMMXT].htab)) != FAIL)
1989 {
1990 if (wr_register (reg)
1991 && (reg_type == IWMMXT_REG_WR || reg_type == IWMMXT_REG_WR_OR_WC))
1992 {
1993 if (shift >= 0)
1994 inst.instruction |= (reg ^ WR_PREFIX) << shift;
1995 return reg;
1996 }
1997 else if (wc_register (reg)
1998 && (reg_type == IWMMXT_REG_WC || reg_type == IWMMXT_REG_WR_OR_WC))
1999 {
2000 if (shift >= 0)
2001 inst.instruction |= (reg ^ WC_PREFIX) << shift;
2002 return reg;
2003 }
2004 else if ((wcg_register (reg) && reg_type == IWMMXT_REG_WCG))
2005 {
2006 if (shift >= 0)
2007 inst.instruction |= ((reg ^ WC_PREFIX) - 8) << shift;
2008 return reg;
2009 }
2010 }
2011
2012 /* Restore the start point, we may have got a reg of the wrong class. */
2013 *str = start;
2014
2015 /* In the few cases where we might be able to accept
2016 something else this error can be overridden. */
2017 sprintf (buff, _("Intel Wireless MMX technology register expected, not '%.100s'"), start);
2018 inst.error = buff;
2019
2020 return FAIL;
2021 }
2022
2023 static const struct asm_psr *
2024 arm_psr_parse (char ** ccp)
2025 {
2026 char * start = * ccp;
2027 char c;
2028 char * p;
2029 const struct asm_psr * psr;
2030
2031 p = start;
2032
2033 /* Skip to the end of the next word in the input stream. */
2034 do
2035 {
2036 c = *p++;
2037 }
2038 while (ISALPHA (c) || c == '_');
2039
2040 /* Terminate the word. */
2041 *--p = 0;
2042
2043 /* CPSR's and SPSR's can now be lowercase. This is just a convenience
2044 feature for ease of use and backwards compatibility. */
2045 if (!strncmp (start, "cpsr", 4))
2046 strncpy (start, "CPSR", 4);
2047 else if (!strncmp (start, "spsr", 4))
2048 strncpy (start, "SPSR", 4);
2049
2050 /* Now locate the word in the psr hash table. */
2051 psr = (const struct asm_psr *) hash_find (arm_psr_hsh, start);
2052
2053 /* Restore the input stream. */
2054 *p = c;
2055
2056 /* If we found a valid match, advance the
2057 stream pointer past the end of the word. */
2058 *ccp = p;
2059
2060 return psr;
2061 }
2062
2063 /* Parse the input looking for a PSR flag. */
2064
2065 static int
2066 psr_required_here (char ** str)
2067 {
2068 char * start = * str;
2069 const struct asm_psr * psr;
2070
2071 psr = arm_psr_parse (str);
2072
2073 if (psr)
2074 {
2075 /* If this is the SPSR that is being modified, set the R bit. */
2076 if (! psr->cpsr)
2077 inst.instruction |= SPSR_BIT;
2078
2079 /* Set the psr flags in the MSR instruction. */
2080 inst.instruction |= psr->field << PSR_SHIFT;
2081
2082 return SUCCESS;
2083 }
2084
2085 /* In the few cases where we might be able to accept
2086 something else this error can be overridden. */
2087 inst.error = _("flag for {c}psr instruction expected");
2088
2089 /* Restore the start point. */
2090 *str = start;
2091 return FAIL;
2092 }
2093
2094 static int
2095 co_proc_number (char ** str)
2096 {
2097 int processor, pchar;
2098 char *start;
2099
2100 skip_whitespace (*str);
2101 start = *str;
2102
2103 /* The data sheet seems to imply that just a number on its own is valid
2104 here, but the RISC iX assembler seems to accept a prefix 'p'. We will
2105 accept either. */
2106 if ((processor = arm_reg_parse (str, all_reg_maps[REG_TYPE_CP].htab))
2107 == FAIL)
2108 {
2109 *str = start;
2110
2111 pchar = *(*str)++;
2112 if (pchar >= '0' && pchar <= '9')
2113 {
2114 processor = pchar - '0';
2115 if (**str >= '0' && **str <= '9')
2116 {
2117 processor = processor * 10 + *(*str)++ - '0';
2118 if (processor > 15)
2119 {
2120 inst.error = _("illegal co-processor number");
2121 return FAIL;
2122 }
2123 }
2124 }
2125 else
2126 {
2127 inst.error = all_reg_maps[REG_TYPE_CP].expected;
2128 return FAIL;
2129 }
2130 }
2131
2132 inst.instruction |= processor << 8;
2133 return SUCCESS;
2134 }
2135
2136 static int
2137 cp_opc_expr (char ** str, int where, int length)
2138 {
2139 expressionS expr;
2140
2141 skip_whitespace (* str);
2142
2143 memset (&expr, '\0', sizeof (expr));
2144
2145 if (my_get_expression (&expr, str))
2146 return FAIL;
2147 if (expr.X_op != O_constant)
2148 {
2149 inst.error = _("bad or missing expression");
2150 return FAIL;
2151 }
2152
2153 if ((expr.X_add_number & ((1 << length) - 1)) != expr.X_add_number)
2154 {
2155 inst.error = _("immediate co-processor expression too large");
2156 return FAIL;
2157 }
2158
2159 inst.instruction |= expr.X_add_number << where;
2160 return SUCCESS;
2161 }
2162
2163 static int
2164 cp_reg_required_here (char ** str, int where)
2165 {
2166 int reg;
2167 char * start = *str;
2168
2169 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_CN].htab)) != FAIL)
2170 {
2171 inst.instruction |= reg << where;
2172 return reg;
2173 }
2174
2175 /* In the few cases where we might be able to accept something else
2176 this error can be overridden. */
2177 inst.error = all_reg_maps[REG_TYPE_CN].expected;
2178
2179 /* Restore the start point. */
2180 *str = start;
2181 return FAIL;
2182 }
2183
2184 static int
2185 fp_reg_required_here (char ** str, int where)
2186 {
2187 int reg;
2188 char * start = * str;
2189
2190 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_FN].htab)) != FAIL)
2191 {
2192 inst.instruction |= reg << where;
2193 return reg;
2194 }
2195
2196 /* In the few cases where we might be able to accept something else
2197 this error can be overridden. */
2198 inst.error = all_reg_maps[REG_TYPE_FN].expected;
2199
2200 /* Restore the start point. */
2201 *str = start;
2202 return FAIL;
2203 }
2204
2205 static int
2206 cp_address_offset (char ** str)
2207 {
2208 int offset;
2209
2210 skip_whitespace (* str);
2211
2212 if (! is_immediate_prefix (**str))
2213 {
2214 inst.error = _("immediate expression expected");
2215 return FAIL;
2216 }
2217
2218 (*str)++;
2219
2220 if (my_get_expression (& inst.reloc.exp, str))
2221 return FAIL;
2222
2223 if (inst.reloc.exp.X_op == O_constant)
2224 {
2225 offset = inst.reloc.exp.X_add_number;
2226
2227 if (offset & 3)
2228 {
2229 inst.error = _("co-processor address must be word aligned");
2230 return FAIL;
2231 }
2232
2233 if (offset > 1023 || offset < -1023)
2234 {
2235 inst.error = _("offset too large");
2236 return FAIL;
2237 }
2238
2239 if (offset >= 0)
2240 inst.instruction |= INDEX_UP;
2241 else
2242 offset = -offset;
2243
2244 inst.instruction |= offset >> 2;
2245 }
2246 else
2247 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
2248
2249 return SUCCESS;
2250 }
2251
2252 static int
2253 cp_address_required_here (char ** str, int wb_ok)
2254 {
2255 char * p = * str;
2256 int pre_inc = 0;
2257 int write_back = 0;
2258
2259 if (*p == '[')
2260 {
2261 int reg;
2262
2263 p++;
2264 skip_whitespace (p);
2265
2266 if ((reg = reg_required_here (& p, 16)) == FAIL)
2267 return FAIL;
2268
2269 skip_whitespace (p);
2270
2271 if (*p == ']')
2272 {
2273 p++;
2274
2275 skip_whitespace (p);
2276
2277 if (*p == '\0')
2278 {
2279 /* As an extension to the official ARM syntax we allow:
2280 [Rn]
2281 as a short hand for:
2282 [Rn,#0] */
2283 inst.instruction |= PRE_INDEX | INDEX_UP;
2284 *str = p;
2285 return SUCCESS;
2286 }
2287
2288 if (skip_past_comma (& p) == FAIL)
2289 {
2290 inst.error = _("comma expected after closing square bracket");
2291 return FAIL;
2292 }
2293
2294 skip_whitespace (p);
2295
2296 if (*p == '#')
2297 {
2298 if (wb_ok)
2299 {
2300 /* [Rn], #expr */
2301 write_back = WRITE_BACK;
2302
2303 if (reg == REG_PC)
2304 {
2305 inst.error = _("pc may not be used in post-increment");
2306 return FAIL;
2307 }
2308
2309 if (cp_address_offset (& p) == FAIL)
2310 return FAIL;
2311 }
2312 else
2313 pre_inc = PRE_INDEX | INDEX_UP;
2314 }
2315 else if (*p == '{')
2316 {
2317 int option;
2318
2319 /* [Rn], {<expr>} */
2320 p++;
2321
2322 skip_whitespace (p);
2323
2324 if (my_get_expression (& inst.reloc.exp, & p))
2325 return FAIL;
2326
2327 if (inst.reloc.exp.X_op == O_constant)
2328 {
2329 option = inst.reloc.exp.X_add_number;
2330
2331 if (option > 255 || option < 0)
2332 {
2333 inst.error = _("'option' field too large");
2334 return FAIL;
2335 }
2336
2337 skip_whitespace (p);
2338
2339 if (*p != '}')
2340 {
2341 inst.error = _("'}' expected at end of 'option' field");
2342 return FAIL;
2343 }
2344 else
2345 {
2346 p++;
2347 inst.instruction |= option;
2348 inst.instruction |= INDEX_UP;
2349 }
2350 }
2351 else
2352 {
2353 inst.error = _("non-constant expressions for 'option' field not supported");
2354 return FAIL;
2355 }
2356 }
2357 else
2358 {
2359 inst.error = _("# or { expected after comma");
2360 return FAIL;
2361 }
2362 }
2363 else
2364 {
2365 /* '['Rn, #expr']'[!] */
2366
2367 if (skip_past_comma (& p) == FAIL)
2368 {
2369 inst.error = _("pre-indexed expression expected");
2370 return FAIL;
2371 }
2372
2373 pre_inc = PRE_INDEX;
2374
2375 if (cp_address_offset (& p) == FAIL)
2376 return FAIL;
2377
2378 skip_whitespace (p);
2379
2380 if (*p++ != ']')
2381 {
2382 inst.error = _("missing ]");
2383 return FAIL;
2384 }
2385
2386 skip_whitespace (p);
2387
2388 if (wb_ok && *p == '!')
2389 {
2390 if (reg == REG_PC)
2391 {
2392 inst.error = _("pc may not be used with write-back");
2393 return FAIL;
2394 }
2395
2396 p++;
2397 write_back = WRITE_BACK;
2398 }
2399 }
2400 }
2401 else
2402 {
2403 if (my_get_expression (&inst.reloc.exp, &p))
2404 return FAIL;
2405
2406 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
2407 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
2408 inst.reloc.pc_rel = 1;
2409 inst.instruction |= (REG_PC << 16);
2410 pre_inc = PRE_INDEX;
2411 }
2412
2413 inst.instruction |= write_back | pre_inc;
2414 *str = p;
2415 return SUCCESS;
2416 }
2417
2418 static int
2419 cp_byte_address_offset (char ** str)
2420 {
2421 int offset;
2422
2423 skip_whitespace (* str);
2424
2425 if (! is_immediate_prefix (**str))
2426 {
2427 inst.error = _("immediate expression expected");
2428 return FAIL;
2429 }
2430
2431 (*str)++;
2432
2433 if (my_get_expression (& inst.reloc.exp, str))
2434 return FAIL;
2435
2436 if (inst.reloc.exp.X_op == O_constant)
2437 {
2438 offset = inst.reloc.exp.X_add_number;
2439
2440 if (offset > 255 || offset < -255)
2441 {
2442 inst.error = _("offset too large");
2443 return FAIL;
2444 }
2445
2446 if (offset >= 0)
2447 inst.instruction |= INDEX_UP;
2448 else
2449 offset = -offset;
2450
2451 inst.instruction |= offset;
2452 }
2453 else
2454 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM_S2;
2455
2456 return SUCCESS;
2457 }
2458
2459 static int
2460 cp_byte_address_required_here (char ** str)
2461 {
2462 char * p = * str;
2463 int pre_inc = 0;
2464 int write_back = 0;
2465
2466 if (*p == '[')
2467 {
2468 int reg;
2469
2470 p++;
2471 skip_whitespace (p);
2472
2473 if ((reg = reg_required_here (& p, 16)) == FAIL)
2474 return FAIL;
2475
2476 skip_whitespace (p);
2477
2478 if (*p == ']')
2479 {
2480 p++;
2481
2482 if (skip_past_comma (& p) == SUCCESS)
2483 {
2484 /* [Rn], #expr */
2485 write_back = WRITE_BACK;
2486
2487 if (reg == REG_PC)
2488 {
2489 inst.error = _("pc may not be used in post-increment");
2490 return FAIL;
2491 }
2492
2493 if (cp_byte_address_offset (& p) == FAIL)
2494 return FAIL;
2495 }
2496 else
2497 pre_inc = PRE_INDEX | INDEX_UP;
2498 }
2499 else
2500 {
2501 /* '['Rn, #expr']'[!] */
2502
2503 if (skip_past_comma (& p) == FAIL)
2504 {
2505 inst.error = _("pre-indexed expression expected");
2506 return FAIL;
2507 }
2508
2509 pre_inc = PRE_INDEX;
2510
2511 if (cp_byte_address_offset (& p) == FAIL)
2512 return FAIL;
2513
2514 skip_whitespace (p);
2515
2516 if (*p++ != ']')
2517 {
2518 inst.error = _("missing ]");
2519 return FAIL;
2520 }
2521
2522 skip_whitespace (p);
2523
2524 if (*p == '!')
2525 {
2526 if (reg == REG_PC)
2527 {
2528 inst.error = _("pc may not be used with write-back");
2529 return FAIL;
2530 }
2531
2532 p++;
2533 write_back = WRITE_BACK;
2534 }
2535 }
2536 }
2537 else
2538 {
2539 if (my_get_expression (&inst.reloc.exp, &p))
2540 return FAIL;
2541
2542 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM_S2;
2543 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
2544 inst.reloc.pc_rel = 1;
2545 inst.instruction |= (REG_PC << 16);
2546 pre_inc = PRE_INDEX;
2547 }
2548
2549 inst.instruction |= write_back | pre_inc;
2550 *str = p;
2551 return SUCCESS;
2552 }
2553
2554 static void
2555 do_nop (char * str)
2556 {
2557 skip_whitespace (str);
2558 if (*str == '{')
2559 {
2560 str++;
2561
2562 if (my_get_expression (&inst.reloc.exp, &str))
2563 inst.reloc.exp.X_op = O_illegal;
2564 else
2565 {
2566 skip_whitespace (str);
2567 if (*str == '}')
2568 str++;
2569 else
2570 inst.reloc.exp.X_op = O_illegal;
2571 }
2572
2573 if (inst.reloc.exp.X_op != O_constant
2574 || inst.reloc.exp.X_add_number > 255
2575 || inst.reloc.exp.X_add_number < 0)
2576 {
2577 inst.error = _("Invalid NOP hint");
2578 return;
2579 }
2580
2581 /* Arcitectural NOP hints are CPSR sets with no bits selected. */
2582 inst.instruction &= 0xf0000000;
2583 inst.instruction |= 0x0320f000 + inst.reloc.exp.X_add_number;
2584 }
2585
2586 end_of_line (str);
2587 }
2588
2589 static void
2590 do_empty (char * str)
2591 {
2592 /* Do nothing really. */
2593 end_of_line (str);
2594 }
2595
2596 static void
2597 do_mrs (char * str)
2598 {
2599 int skip = 0;
2600
2601 /* Only one syntax. */
2602 skip_whitespace (str);
2603
2604 if (reg_required_here (&str, 12) == FAIL)
2605 {
2606 inst.error = BAD_ARGS;
2607 return;
2608 }
2609
2610 if (skip_past_comma (&str) == FAIL)
2611 {
2612 inst.error = _("comma expected after register name");
2613 return;
2614 }
2615
2616 skip_whitespace (str);
2617
2618 if ( streq (str, "CPSR")
2619 || streq (str, "SPSR")
2620 /* Lower case versions for backwards compatibility. */
2621 || streq (str, "cpsr")
2622 || streq (str, "spsr"))
2623 skip = 4;
2624
2625 /* This is for backwards compatibility with older toolchains. */
2626 else if ( streq (str, "cpsr_all")
2627 || streq (str, "spsr_all"))
2628 skip = 8;
2629 else
2630 {
2631 inst.error = _("CPSR or SPSR expected");
2632 return;
2633 }
2634
2635 if (* str == 's' || * str == 'S')
2636 inst.instruction |= SPSR_BIT;
2637 str += skip;
2638
2639 end_of_line (str);
2640 }
2641
2642 /* Two possible forms:
2643 "{C|S}PSR_<field>, Rm",
2644 "{C|S}PSR_f, #expression". */
2645
2646 static void
2647 do_msr (char * str)
2648 {
2649 skip_whitespace (str);
2650
2651 if (psr_required_here (& str) == FAIL)
2652 return;
2653
2654 if (skip_past_comma (& str) == FAIL)
2655 {
2656 inst.error = _("comma missing after psr flags");
2657 return;
2658 }
2659
2660 skip_whitespace (str);
2661
2662 if (reg_required_here (& str, 0) != FAIL)
2663 {
2664 inst.error = NULL;
2665 end_of_line (str);
2666 return;
2667 }
2668
2669 if (! is_immediate_prefix (* str))
2670 {
2671 inst.error =
2672 _("only a register or immediate value can follow a psr flag");
2673 return;
2674 }
2675
2676 str ++;
2677 inst.error = NULL;
2678
2679 if (my_get_expression (& inst.reloc.exp, & str))
2680 {
2681 inst.error =
2682 _("only a register or immediate value can follow a psr flag");
2683 return;
2684 }
2685
2686 inst.instruction |= INST_IMMEDIATE;
2687
2688 if (inst.reloc.exp.X_add_symbol)
2689 {
2690 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
2691 inst.reloc.pc_rel = 0;
2692 }
2693 else
2694 {
2695 unsigned value = validate_immediate (inst.reloc.exp.X_add_number);
2696
2697 if (value == (unsigned) FAIL)
2698 {
2699 inst.error = _("invalid constant");
2700 return;
2701 }
2702
2703 inst.instruction |= value;
2704 }
2705
2706 inst.error = NULL;
2707 end_of_line (str);
2708 }
2709
2710 /* Long Multiply Parser
2711 UMULL RdLo, RdHi, Rm, Rs
2712 SMULL RdLo, RdHi, Rm, Rs
2713 UMLAL RdLo, RdHi, Rm, Rs
2714 SMLAL RdLo, RdHi, Rm, Rs. */
2715
2716 static void
2717 do_mull (char * str)
2718 {
2719 int rdlo, rdhi, rm, rs;
2720
2721 /* Only one format "rdlo, rdhi, rm, rs". */
2722 skip_whitespace (str);
2723
2724 if ((rdlo = reg_required_here (&str, 12)) == FAIL)
2725 {
2726 inst.error = BAD_ARGS;
2727 return;
2728 }
2729
2730 if (skip_past_comma (&str) == FAIL
2731 || (rdhi = reg_required_here (&str, 16)) == FAIL)
2732 {
2733 inst.error = BAD_ARGS;
2734 return;
2735 }
2736
2737 if (skip_past_comma (&str) == FAIL
2738 || (rm = reg_required_here (&str, 0)) == FAIL)
2739 {
2740 inst.error = BAD_ARGS;
2741 return;
2742 }
2743
2744 /* rdhi, rdlo and rm must all be different. */
2745 if (rdlo == rdhi || rdlo == rm || rdhi == rm)
2746 as_tsktsk (_("rdhi, rdlo and rm must all be different"));
2747
2748 if (skip_past_comma (&str) == FAIL
2749 || (rs = reg_required_here (&str, 8)) == FAIL)
2750 {
2751 inst.error = BAD_ARGS;
2752 return;
2753 }
2754
2755 if (rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC)
2756 {
2757 inst.error = BAD_PC;
2758 return;
2759 }
2760
2761 end_of_line (str);
2762 }
2763
2764 static void
2765 do_mul (char * str)
2766 {
2767 int rd, rm;
2768
2769 /* Only one format "rd, rm, rs". */
2770 skip_whitespace (str);
2771
2772 if ((rd = reg_required_here (&str, 16)) == FAIL)
2773 {
2774 inst.error = BAD_ARGS;
2775 return;
2776 }
2777
2778 if (rd == REG_PC)
2779 {
2780 inst.error = BAD_PC;
2781 return;
2782 }
2783
2784 if (skip_past_comma (&str) == FAIL
2785 || (rm = reg_required_here (&str, 0)) == FAIL)
2786 {
2787 inst.error = BAD_ARGS;
2788 return;
2789 }
2790
2791 if (rm == REG_PC)
2792 {
2793 inst.error = BAD_PC;
2794 return;
2795 }
2796
2797 if (rm == rd)
2798 as_tsktsk (_("rd and rm should be different in mul"));
2799
2800 if (skip_past_comma (&str) == FAIL
2801 || (rm = reg_required_here (&str, 8)) == FAIL)
2802 {
2803 inst.error = BAD_ARGS;
2804 return;
2805 }
2806
2807 if (rm == REG_PC)
2808 {
2809 inst.error = BAD_PC;
2810 return;
2811 }
2812
2813 end_of_line (str);
2814 }
2815
2816 static void
2817 do_mla (char * str)
2818 {
2819 int rd, rm;
2820
2821 /* Only one format "rd, rm, rs, rn". */
2822 skip_whitespace (str);
2823
2824 if ((rd = reg_required_here (&str, 16)) == FAIL)
2825 {
2826 inst.error = BAD_ARGS;
2827 return;
2828 }
2829
2830 if (rd == REG_PC)
2831 {
2832 inst.error = BAD_PC;
2833 return;
2834 }
2835
2836 if (skip_past_comma (&str) == FAIL
2837 || (rm = reg_required_here (&str, 0)) == FAIL)
2838 {
2839 inst.error = BAD_ARGS;
2840 return;
2841 }
2842
2843 if (rm == REG_PC)
2844 {
2845 inst.error = BAD_PC;
2846 return;
2847 }
2848
2849 if (rm == rd)
2850 as_tsktsk (_("rd and rm should be different in mla"));
2851
2852 if (skip_past_comma (&str) == FAIL
2853 || (rd = reg_required_here (&str, 8)) == FAIL
2854 || skip_past_comma (&str) == FAIL
2855 || (rm = reg_required_here (&str, 12)) == FAIL)
2856 {
2857 inst.error = BAD_ARGS;
2858 return;
2859 }
2860
2861 if (rd == REG_PC || rm == REG_PC)
2862 {
2863 inst.error = BAD_PC;
2864 return;
2865 }
2866
2867 end_of_line (str);
2868 }
2869
2870 /* Expects *str -> the characters "acc0", possibly with leading blanks.
2871 Advances *str to the next non-alphanumeric.
2872 Returns 0, or else FAIL (in which case sets inst.error).
2873
2874 (In a future XScale, there may be accumulators other than zero.
2875 At that time this routine and its callers can be upgraded to suit.) */
2876
2877 static int
2878 accum0_required_here (char ** str)
2879 {
2880 static char buff [128]; /* Note the address is taken. Hence, static. */
2881 char * p = * str;
2882 char c;
2883 int result = 0; /* The accum number. */
2884
2885 skip_whitespace (p);
2886
2887 *str = p; /* Advance caller's string pointer too. */
2888 c = *p++;
2889 while (ISALNUM (c))
2890 c = *p++;
2891
2892 *--p = 0; /* Aap nul into input buffer at non-alnum. */
2893
2894 if (! ( streq (*str, "acc0") || streq (*str, "ACC0")))
2895 {
2896 sprintf (buff, _("acc0 expected, not '%.100s'"), *str);
2897 inst.error = buff;
2898 result = FAIL;
2899 }
2900
2901 *p = c; /* Unzap. */
2902 *str = p; /* Caller's string pointer to after match. */
2903 return result;
2904 }
2905
2906 static int
2907 ldst_extend_v4 (char ** str)
2908 {
2909 int add = INDEX_UP;
2910
2911 switch (**str)
2912 {
2913 case '#':
2914 case '$':
2915 (*str)++;
2916 if (my_get_expression (& inst.reloc.exp, str))
2917 return FAIL;
2918
2919 if (inst.reloc.exp.X_op == O_constant)
2920 {
2921 int value = inst.reloc.exp.X_add_number;
2922
2923 if (value < -255 || value > 255)
2924 {
2925 inst.error = _("address offset too large");
2926 return FAIL;
2927 }
2928
2929 if (value < 0)
2930 {
2931 value = -value;
2932 add = 0;
2933 }
2934
2935 /* Halfword and signextension instructions have the
2936 immediate value split across bits 11..8 and bits 3..0. */
2937 inst.instruction |= (add | HWOFFSET_IMM
2938 | ((value >> 4) << 8) | (value & 0xF));
2939 }
2940 else
2941 {
2942 inst.instruction |= HWOFFSET_IMM;
2943 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
2944 inst.reloc.pc_rel = 0;
2945 }
2946 return SUCCESS;
2947
2948 case '-':
2949 add = 0;
2950 /* Fall through. */
2951
2952 case '+':
2953 (*str)++;
2954 /* Fall through. */
2955
2956 default:
2957 if (reg_required_here (str, 0) == FAIL)
2958 return FAIL;
2959
2960 inst.instruction |= add;
2961 return SUCCESS;
2962 }
2963 }
2964
2965 /* Expects **str -> after a comma. May be leading blanks.
2966 Advances *str, recognizing a load mode, and setting inst.instruction.
2967 Returns rn, or else FAIL (in which case may set inst.error
2968 and not advance str)
2969
2970 Note: doesn't know Rd, so no err checks that require such knowledge. */
2971
2972 static int
2973 ld_mode_required_here (char ** string)
2974 {
2975 char * str = * string;
2976 int rn;
2977 int pre_inc = 0;
2978
2979 skip_whitespace (str);
2980
2981 if (* str == '[')
2982 {
2983 str++;
2984
2985 skip_whitespace (str);
2986
2987 if ((rn = reg_required_here (& str, 16)) == FAIL)
2988 return FAIL;
2989
2990 skip_whitespace (str);
2991
2992 if (* str == ']')
2993 {
2994 str ++;
2995
2996 if (skip_past_comma (& str) == SUCCESS)
2997 {
2998 /* [Rn],... (post inc) */
2999 if (ldst_extend_v4 (&str) == FAIL)
3000 return FAIL;
3001 }
3002 else /* [Rn] */
3003 {
3004 skip_whitespace (str);
3005
3006 if (* str == '!')
3007 {
3008 str ++;
3009 inst.instruction |= WRITE_BACK;
3010 }
3011
3012 inst.instruction |= INDEX_UP | HWOFFSET_IMM;
3013 pre_inc = 1;
3014 }
3015 }
3016 else /* [Rn,...] */
3017 {
3018 if (skip_past_comma (& str) == FAIL)
3019 {
3020 inst.error = _("pre-indexed expression expected");
3021 return FAIL;
3022 }
3023
3024 pre_inc = 1;
3025
3026 if (ldst_extend_v4 (&str) == FAIL)
3027 return FAIL;
3028
3029 skip_whitespace (str);
3030
3031 if (* str ++ != ']')
3032 {
3033 inst.error = _("missing ]");
3034 return FAIL;
3035 }
3036
3037 skip_whitespace (str);
3038
3039 if (* str == '!')
3040 {
3041 str ++;
3042 inst.instruction |= WRITE_BACK;
3043 }
3044 }
3045 }
3046 else if (* str == '=') /* ldr's "r,=label" syntax */
3047 /* We should never reach here, because <text> = <expression> is
3048 caught gas/read.c read_a_source_file() as a .set operation. */
3049 return FAIL;
3050 else /* PC +- 8 bit immediate offset. */
3051 {
3052 if (my_get_expression (& inst.reloc.exp, & str))
3053 return FAIL;
3054
3055 inst.instruction |= HWOFFSET_IMM; /* The I bit. */
3056 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
3057 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
3058 inst.reloc.pc_rel = 1;
3059 inst.instruction |= (REG_PC << 16);
3060
3061 rn = REG_PC;
3062 pre_inc = 1;
3063 }
3064
3065 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
3066 * string = str;
3067
3068 return rn;
3069 }
3070
3071 /* ARM V5E (El Segundo) signed-multiply-accumulate (argument parse)
3072 SMLAxy{cond} Rd,Rm,Rs,Rn
3073 SMLAWy{cond} Rd,Rm,Rs,Rn
3074 Error if any register is R15. */
3075
3076 static void
3077 do_smla (char * str)
3078 {
3079 int rd, rm, rs, rn;
3080
3081 skip_whitespace (str);
3082
3083 if ((rd = reg_required_here (& str, 16)) == FAIL
3084 || skip_past_comma (& str) == FAIL
3085 || (rm = reg_required_here (& str, 0)) == FAIL
3086 || skip_past_comma (& str) == FAIL
3087 || (rs = reg_required_here (& str, 8)) == FAIL
3088 || skip_past_comma (& str) == FAIL
3089 || (rn = reg_required_here (& str, 12)) == FAIL)
3090 inst.error = BAD_ARGS;
3091
3092 else if (rd == REG_PC || rm == REG_PC || rs == REG_PC || rn == REG_PC)
3093 inst.error = BAD_PC;
3094
3095 else
3096 end_of_line (str);
3097 }
3098
3099 /* ARM V5E (El Segundo) signed-multiply-accumulate-long (argument parse)
3100 SMLALxy{cond} Rdlo,Rdhi,Rm,Rs
3101 Error if any register is R15.
3102 Warning if Rdlo == Rdhi. */
3103
3104 static void
3105 do_smlal (char * str)
3106 {
3107 int rdlo, rdhi, rm, rs;
3108
3109 skip_whitespace (str);
3110
3111 if ((rdlo = reg_required_here (& str, 12)) == FAIL
3112 || skip_past_comma (& str) == FAIL
3113 || (rdhi = reg_required_here (& str, 16)) == FAIL
3114 || skip_past_comma (& str) == FAIL
3115 || (rm = reg_required_here (& str, 0)) == FAIL
3116 || skip_past_comma (& str) == FAIL
3117 || (rs = reg_required_here (& str, 8)) == FAIL)
3118 {
3119 inst.error = BAD_ARGS;
3120 return;
3121 }
3122
3123 if (rdlo == REG_PC || rdhi == REG_PC || rm == REG_PC || rs == REG_PC)
3124 {
3125 inst.error = BAD_PC;
3126 return;
3127 }
3128
3129 if (rdlo == rdhi)
3130 as_tsktsk (_("rdhi and rdlo must be different"));
3131
3132 end_of_line (str);
3133 }
3134
3135 /* ARM V5E (El Segundo) signed-multiply (argument parse)
3136 SMULxy{cond} Rd,Rm,Rs
3137 Error if any register is R15. */
3138
3139 static void
3140 do_smul (char * str)
3141 {
3142 int rd, rm, rs;
3143
3144 skip_whitespace (str);
3145
3146 if ((rd = reg_required_here (& str, 16)) == FAIL
3147 || skip_past_comma (& str) == FAIL
3148 || (rm = reg_required_here (& str, 0)) == FAIL
3149 || skip_past_comma (& str) == FAIL
3150 || (rs = reg_required_here (& str, 8)) == FAIL)
3151 inst.error = BAD_ARGS;
3152
3153 else if (rd == REG_PC || rm == REG_PC || rs == REG_PC)
3154 inst.error = BAD_PC;
3155
3156 else
3157 end_of_line (str);
3158 }
3159
3160 /* ARM V5E (El Segundo) saturating-add/subtract (argument parse)
3161 Q[D]{ADD,SUB}{cond} Rd,Rm,Rn
3162 Error if any register is R15. */
3163
3164 static void
3165 do_qadd (char * str)
3166 {
3167 int rd, rm, rn;
3168
3169 skip_whitespace (str);
3170
3171 if ((rd = reg_required_here (& str, 12)) == FAIL
3172 || skip_past_comma (& str) == FAIL
3173 || (rm = reg_required_here (& str, 0)) == FAIL
3174 || skip_past_comma (& str) == FAIL
3175 || (rn = reg_required_here (& str, 16)) == FAIL)
3176 inst.error = BAD_ARGS;
3177
3178 else if (rd == REG_PC || rm == REG_PC || rn == REG_PC)
3179 inst.error = BAD_PC;
3180
3181 else
3182 end_of_line (str);
3183 }
3184
3185 /* ARM V5E (el Segundo)
3186 MCRRcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
3187 MRRCcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
3188
3189 These are equivalent to the XScale instructions MAR and MRA,
3190 respectively, when coproc == 0, opcode == 0, and CRm == 0.
3191
3192 Result unpredicatable if Rd or Rn is R15. */
3193
3194 static void
3195 do_co_reg2c (char * str)
3196 {
3197 int rd, rn;
3198
3199 skip_whitespace (str);
3200
3201 if (co_proc_number (& str) == FAIL)
3202 {
3203 if (!inst.error)
3204 inst.error = BAD_ARGS;
3205 return;
3206 }
3207
3208 if (skip_past_comma (& str) == FAIL
3209 || cp_opc_expr (& str, 4, 4) == FAIL)
3210 {
3211 if (!inst.error)
3212 inst.error = BAD_ARGS;
3213 return;
3214 }
3215
3216 if (skip_past_comma (& str) == FAIL
3217 || (rd = reg_required_here (& str, 12)) == FAIL)
3218 {
3219 if (!inst.error)
3220 inst.error = BAD_ARGS;
3221 return;
3222 }
3223
3224 if (skip_past_comma (& str) == FAIL
3225 || (rn = reg_required_here (& str, 16)) == FAIL)
3226 {
3227 if (!inst.error)
3228 inst.error = BAD_ARGS;
3229 return;
3230 }
3231
3232 /* Unpredictable result if rd or rn is R15. */
3233 if (rd == REG_PC || rn == REG_PC)
3234 as_tsktsk
3235 (_("Warning: instruction unpredictable when using r15"));
3236
3237 if (skip_past_comma (& str) == FAIL
3238 || cp_reg_required_here (& str, 0) == FAIL)
3239 {
3240 if (!inst.error)
3241 inst.error = BAD_ARGS;
3242 return;
3243 }
3244
3245 end_of_line (str);
3246 }
3247
3248 /* ARM V5 count-leading-zeroes instruction (argument parse)
3249 CLZ{<cond>} <Rd>, <Rm>
3250 Condition defaults to COND_ALWAYS.
3251 Error if Rd or Rm are R15. */
3252
3253 static void
3254 do_clz (char * str)
3255 {
3256 int rd, rm;
3257
3258 skip_whitespace (str);
3259
3260 if (((rd = reg_required_here (& str, 12)) == FAIL)
3261 || (skip_past_comma (& str) == FAIL)
3262 || ((rm = reg_required_here (& str, 0)) == FAIL))
3263 inst.error = BAD_ARGS;
3264
3265 else if (rd == REG_PC || rm == REG_PC )
3266 inst.error = BAD_PC;
3267
3268 else
3269 end_of_line (str);
3270 }
3271
3272 /* ARM V5 (argument parse)
3273 LDC2{L} <coproc>, <CRd>, <addressing mode>
3274 STC2{L} <coproc>, <CRd>, <addressing mode>
3275 Instruction is not conditional, and has 0xf in the condition field.
3276 Otherwise, it's the same as LDC/STC. */
3277
3278 static void
3279 do_lstc2 (char * str)
3280 {
3281 skip_whitespace (str);
3282
3283 if (co_proc_number (& str) == FAIL)
3284 {
3285 if (!inst.error)
3286 inst.error = BAD_ARGS;
3287 }
3288 else if (skip_past_comma (& str) == FAIL
3289 || cp_reg_required_here (& str, 12) == FAIL)
3290 {
3291 if (!inst.error)
3292 inst.error = BAD_ARGS;
3293 }
3294 else if (skip_past_comma (& str) == FAIL
3295 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
3296 {
3297 if (! inst.error)
3298 inst.error = BAD_ARGS;
3299 }
3300 else
3301 end_of_line (str);
3302 }
3303
3304 /* ARM V5 (argument parse)
3305 CDP2 <coproc>, <opcode_1>, <CRd>, <CRn>, <CRm>, <opcode_2>
3306 Instruction is not conditional, and has 0xf in the condition field.
3307 Otherwise, it's the same as CDP. */
3308
3309 static void
3310 do_cdp2 (char * str)
3311 {
3312 skip_whitespace (str);
3313
3314 if (co_proc_number (& str) == FAIL)
3315 {
3316 if (!inst.error)
3317 inst.error = BAD_ARGS;
3318 return;
3319 }
3320
3321 if (skip_past_comma (& str) == FAIL
3322 || cp_opc_expr (& str, 20,4) == FAIL)
3323 {
3324 if (!inst.error)
3325 inst.error = BAD_ARGS;
3326 return;
3327 }
3328
3329 if (skip_past_comma (& str) == FAIL
3330 || cp_reg_required_here (& str, 12) == FAIL)
3331 {
3332 if (!inst.error)
3333 inst.error = BAD_ARGS;
3334 return;
3335 }
3336
3337 if (skip_past_comma (& str) == FAIL
3338 || cp_reg_required_here (& str, 16) == FAIL)
3339 {
3340 if (!inst.error)
3341 inst.error = BAD_ARGS;
3342 return;
3343 }
3344
3345 if (skip_past_comma (& str) == FAIL
3346 || cp_reg_required_here (& str, 0) == FAIL)
3347 {
3348 if (!inst.error)
3349 inst.error = BAD_ARGS;
3350 return;
3351 }
3352
3353 if (skip_past_comma (& str) == SUCCESS)
3354 {
3355 if (cp_opc_expr (& str, 5, 3) == FAIL)
3356 {
3357 if (!inst.error)
3358 inst.error = BAD_ARGS;
3359 return;
3360 }
3361 }
3362
3363 end_of_line (str);
3364 }
3365
3366 /* ARM V5 (argument parse)
3367 MCR2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
3368 MRC2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
3369 Instruction is not conditional, and has 0xf in the condition field.
3370 Otherwise, it's the same as MCR/MRC. */
3371
3372 static void
3373 do_co_reg2 (char * str)
3374 {
3375 skip_whitespace (str);
3376
3377 if (co_proc_number (& str) == FAIL)
3378 {
3379 if (!inst.error)
3380 inst.error = BAD_ARGS;
3381 return;
3382 }
3383
3384 if (skip_past_comma (& str) == FAIL
3385 || cp_opc_expr (& str, 21, 3) == FAIL)
3386 {
3387 if (!inst.error)
3388 inst.error = BAD_ARGS;
3389 return;
3390 }
3391
3392 if (skip_past_comma (& str) == FAIL
3393 || reg_required_here (& str, 12) == FAIL)
3394 {
3395 if (!inst.error)
3396 inst.error = BAD_ARGS;
3397 return;
3398 }
3399
3400 if (skip_past_comma (& str) == FAIL
3401 || cp_reg_required_here (& str, 16) == FAIL)
3402 {
3403 if (!inst.error)
3404 inst.error = BAD_ARGS;
3405 return;
3406 }
3407
3408 if (skip_past_comma (& str) == FAIL
3409 || cp_reg_required_here (& str, 0) == FAIL)
3410 {
3411 if (!inst.error)
3412 inst.error = BAD_ARGS;
3413 return;
3414 }
3415
3416 if (skip_past_comma (& str) == SUCCESS)
3417 {
3418 if (cp_opc_expr (& str, 5, 3) == FAIL)
3419 {
3420 if (!inst.error)
3421 inst.error = BAD_ARGS;
3422 return;
3423 }
3424 }
3425
3426 end_of_line (str);
3427 }
3428
3429 static void
3430 do_bx (char * str)
3431 {
3432 int reg;
3433
3434 skip_whitespace (str);
3435
3436 if ((reg = reg_required_here (&str, 0)) == FAIL)
3437 {
3438 inst.error = BAD_ARGS;
3439 return;
3440 }
3441
3442 /* Note - it is not illegal to do a "bx pc". Useless, but not illegal. */
3443 if (reg == REG_PC)
3444 as_tsktsk (_("use of r15 in bx in ARM mode is not really useful"));
3445
3446 end_of_line (str);
3447 }
3448
3449 /* ARM v5TEJ. Jump to Jazelle code. */
3450
3451 static void
3452 do_bxj (char * str)
3453 {
3454 int reg;
3455
3456 skip_whitespace (str);
3457
3458 if ((reg = reg_required_here (&str, 0)) == FAIL)
3459 {
3460 inst.error = BAD_ARGS;
3461 return;
3462 }
3463
3464 /* Note - it is not illegal to do a "bxj pc". Useless, but not illegal. */
3465 if (reg == REG_PC)
3466 as_tsktsk (_("use of r15 in bxj is not really useful"));
3467
3468 end_of_line (str);
3469 }
3470
3471 /* ARM V6 umaal (argument parse). */
3472
3473 static void
3474 do_umaal (char * str)
3475 {
3476 int rdlo, rdhi, rm, rs;
3477
3478 skip_whitespace (str);
3479 if ((rdlo = reg_required_here (& str, 12)) == FAIL
3480 || skip_past_comma (& str) == FAIL
3481 || (rdhi = reg_required_here (& str, 16)) == FAIL
3482 || skip_past_comma (& str) == FAIL
3483 || (rm = reg_required_here (& str, 0)) == FAIL
3484 || skip_past_comma (& str) == FAIL
3485 || (rs = reg_required_here (& str, 8)) == FAIL)
3486 {
3487 inst.error = BAD_ARGS;
3488 return;
3489 }
3490
3491 if (rdlo == REG_PC || rdhi == REG_PC || rm == REG_PC || rs == REG_PC)
3492 {
3493 inst.error = BAD_PC;
3494 return;
3495 }
3496
3497 end_of_line (str);
3498 }
3499
3500 /* ARM V6 strex (argument parse). */
3501
3502 static void
3503 do_strex (char * str)
3504 {
3505 int rd, rm, rn;
3506
3507 /* Parse Rd, Rm,. */
3508 skip_whitespace (str);
3509 if ((rd = reg_required_here (& str, 12)) == FAIL
3510 || skip_past_comma (& str) == FAIL
3511 || (rm = reg_required_here (& str, 0)) == FAIL
3512 || skip_past_comma (& str) == FAIL)
3513 {
3514 inst.error = BAD_ARGS;
3515 return;
3516 }
3517 if (rd == REG_PC || rm == REG_PC)
3518 {
3519 inst.error = BAD_PC;
3520 return;
3521 }
3522 if (rd == rm)
3523 {
3524 inst.error = _("Rd equal to Rm or Rn yields unpredictable results");
3525 return;
3526 }
3527
3528 /* Skip past '['. */
3529 if ((strlen (str) >= 1)
3530 && strncmp (str, "[", 1) == 0)
3531 str += 1;
3532
3533 skip_whitespace (str);
3534
3535 /* Parse Rn. */
3536 if ((rn = reg_required_here (& str, 16)) == FAIL)
3537 {
3538 inst.error = BAD_ARGS;
3539 return;
3540 }
3541 else if (rn == REG_PC)
3542 {
3543 inst.error = BAD_PC;
3544 return;
3545 }
3546 if (rd == rn)
3547 {
3548 inst.error = _("Rd equal to Rm or Rn yields unpredictable results");
3549 return;
3550 }
3551 skip_whitespace (str);
3552
3553 /* Skip past ']'. */
3554 if ((strlen (str) >= 1)
3555 && strncmp (str, "]", 1) == 0)
3556 str += 1;
3557
3558 end_of_line (str);
3559 }
3560
3561 /* KIND indicates what kind of shifts are accepted. */
3562
3563 static int
3564 decode_shift (char ** str, int kind)
3565 {
3566 const struct asm_shift_name * shift;
3567 char * p;
3568 char c;
3569
3570 skip_whitespace (* str);
3571
3572 for (p = * str; ISALPHA (* p); p ++)
3573 ;
3574
3575 if (p == * str)
3576 {
3577 inst.error = _("shift expression expected");
3578 return FAIL;
3579 }
3580
3581 c = * p;
3582 * p = '\0';
3583 shift = (const struct asm_shift_name *) hash_find (arm_shift_hsh, * str);
3584 * p = c;
3585
3586 if (shift == NULL)
3587 {
3588 inst.error = _("shift expression expected");
3589 return FAIL;
3590 }
3591
3592 assert (shift->properties->index == shift_properties[shift->properties->index].index);
3593
3594 if (kind == SHIFT_LSL_OR_ASR_IMMEDIATE
3595 && shift->properties->index != SHIFT_LSL
3596 && shift->properties->index != SHIFT_ASR)
3597 {
3598 inst.error = _("'LSL' or 'ASR' required");
3599 return FAIL;
3600 }
3601 else if (kind == SHIFT_LSL_IMMEDIATE
3602 && shift->properties->index != SHIFT_LSL)
3603 {
3604 inst.error = _("'LSL' required");
3605 return FAIL;
3606 }
3607 else if (kind == SHIFT_ASR_IMMEDIATE
3608 && shift->properties->index != SHIFT_ASR)
3609 {
3610 inst.error = _("'ASR' required");
3611 return FAIL;
3612 }
3613
3614 if (shift->properties->index == SHIFT_RRX)
3615 {
3616 * str = p;
3617 inst.instruction |= shift->properties->bit_field;
3618 return SUCCESS;
3619 }
3620
3621 skip_whitespace (p);
3622
3623 if (kind == NO_SHIFT_RESTRICT && reg_required_here (& p, 8) != FAIL)
3624 {
3625 inst.instruction |= shift->properties->bit_field | SHIFT_BY_REG;
3626 * str = p;
3627 return SUCCESS;
3628 }
3629 else if (! is_immediate_prefix (* p))
3630 {
3631 inst.error = (NO_SHIFT_RESTRICT
3632 ? _("shift requires register or #expression")
3633 : _("shift requires #expression"));
3634 * str = p;
3635 return FAIL;
3636 }
3637
3638 inst.error = NULL;
3639 p ++;
3640
3641 if (my_get_expression (& inst.reloc.exp, & p))
3642 return FAIL;
3643
3644 /* Validate some simple #expressions. */
3645 if (inst.reloc.exp.X_op == O_constant)
3646 {
3647 unsigned num = inst.reloc.exp.X_add_number;
3648
3649 /* Reject operations greater than 32. */
3650 if (num > 32
3651 /* Reject a shift of 0 unless the mode allows it. */
3652 || (num == 0 && shift->properties->allows_0 == 0)
3653 /* Reject a shift of 32 unless the mode allows it. */
3654 || (num == 32 && shift->properties->allows_32 == 0)
3655 )
3656 {
3657 /* As a special case we allow a shift of zero for
3658 modes that do not support it to be recoded as an
3659 logical shift left of zero (ie nothing). We warn
3660 about this though. */
3661 if (num == 0)
3662 {
3663 as_warn (_("shift of 0 ignored."));
3664 shift = & shift_names[0];
3665 assert (shift->properties->index == SHIFT_LSL);
3666 }
3667 else
3668 {
3669 inst.error = _("invalid immediate shift");
3670 return FAIL;
3671 }
3672 }
3673
3674 /* Shifts of 32 are encoded as 0, for those shifts that
3675 support it. */
3676 if (num == 32)
3677 num = 0;
3678
3679 inst.instruction |= (num << 7) | shift->properties->bit_field;
3680 }
3681 else
3682 {
3683 inst.reloc.type = BFD_RELOC_ARM_SHIFT_IMM;
3684 inst.reloc.pc_rel = 0;
3685 inst.instruction |= shift->properties->bit_field;
3686 }
3687
3688 * str = p;
3689 return SUCCESS;
3690 }
3691
3692 static void
3693 do_sat (char ** str, int bias)
3694 {
3695 int rd, rm;
3696 expressionS expr;
3697
3698 skip_whitespace (*str);
3699
3700 /* Parse <Rd>, field. */
3701 if ((rd = reg_required_here (str, 12)) == FAIL
3702 || skip_past_comma (str) == FAIL)
3703 {
3704 inst.error = BAD_ARGS;
3705 return;
3706 }
3707 if (rd == REG_PC)
3708 {
3709 inst.error = BAD_PC;
3710 return;
3711 }
3712
3713 /* Parse #<immed>, field. */
3714 if (is_immediate_prefix (**str))
3715 (*str)++;
3716 else
3717 {
3718 inst.error = _("immediate expression expected");
3719 return;
3720 }
3721 if (my_get_expression (&expr, str))
3722 {
3723 inst.error = _("bad expression");
3724 return;
3725 }
3726 if (expr.X_op != O_constant)
3727 {
3728 inst.error = _("constant expression expected");
3729 return;
3730 }
3731 if (expr.X_add_number + bias < 0
3732 || expr.X_add_number + bias > 31)
3733 {
3734 inst.error = _("immediate value out of range");
3735 return;
3736 }
3737 inst.instruction |= (expr.X_add_number + bias) << 16;
3738 if (skip_past_comma (str) == FAIL)
3739 {
3740 inst.error = BAD_ARGS;
3741 return;
3742 }
3743
3744 /* Parse <Rm> field. */
3745 if ((rm = reg_required_here (str, 0)) == FAIL)
3746 {
3747 inst.error = BAD_ARGS;
3748 return;
3749 }
3750 if (rm == REG_PC)
3751 {
3752 inst.error = BAD_PC;
3753 return;
3754 }
3755
3756 if (skip_past_comma (str) == SUCCESS)
3757 decode_shift (str, SHIFT_LSL_OR_ASR_IMMEDIATE);
3758 }
3759
3760 /* ARM V6 ssat (argument parse). */
3761
3762 static void
3763 do_ssat (char * str)
3764 {
3765 do_sat (&str, /*bias=*/-1);
3766 end_of_line (str);
3767 }
3768
3769 /* ARM V6 usat (argument parse). */
3770
3771 static void
3772 do_usat (char * str)
3773 {
3774 do_sat (&str, /*bias=*/0);
3775 end_of_line (str);
3776 }
3777
3778 static void
3779 do_sat16 (char ** str, int bias)
3780 {
3781 int rd, rm;
3782 expressionS expr;
3783
3784 skip_whitespace (*str);
3785
3786 /* Parse the <Rd> field. */
3787 if ((rd = reg_required_here (str, 12)) == FAIL
3788 || skip_past_comma (str) == FAIL)
3789 {
3790 inst.error = BAD_ARGS;
3791 return;
3792 }
3793 if (rd == REG_PC)
3794 {
3795 inst.error = BAD_PC;
3796 return;
3797 }
3798
3799 /* Parse #<immed>, field. */
3800 if (is_immediate_prefix (**str))
3801 (*str)++;
3802 else
3803 {
3804 inst.error = _("immediate expression expected");
3805 return;
3806 }
3807 if (my_get_expression (&expr, str))
3808 {
3809 inst.error = _("bad expression");
3810 return;
3811 }
3812 if (expr.X_op != O_constant)
3813 {
3814 inst.error = _("constant expression expected");
3815 return;
3816 }
3817 if (expr.X_add_number + bias < 0
3818 || expr.X_add_number + bias > 15)
3819 {
3820 inst.error = _("immediate value out of range");
3821 return;
3822 }
3823 inst.instruction |= (expr.X_add_number + bias) << 16;
3824 if (skip_past_comma (str) == FAIL)
3825 {
3826 inst.error = BAD_ARGS;
3827 return;
3828 }
3829
3830 /* Parse <Rm> field. */
3831 if ((rm = reg_required_here (str, 0)) == FAIL)
3832 {
3833 inst.error = BAD_ARGS;
3834 return;
3835 }
3836 if (rm == REG_PC)
3837 {
3838 inst.error = BAD_PC;
3839 return;
3840 }
3841 }
3842
3843 /* ARM V6 ssat16 (argument parse). */
3844
3845 static void
3846 do_ssat16 (char * str)
3847 {
3848 do_sat16 (&str, /*bias=*/-1);
3849 end_of_line (str);
3850 }
3851
3852 static void
3853 do_usat16 (char * str)
3854 {
3855 do_sat16 (&str, /*bias=*/0);
3856 end_of_line (str);
3857 }
3858
3859 static void
3860 do_cps_mode (char ** str)
3861 {
3862 expressionS expr;
3863
3864 skip_whitespace (*str);
3865
3866 if (! is_immediate_prefix (**str))
3867 {
3868 inst.error = _("immediate expression expected");
3869 return;
3870 }
3871
3872 (*str)++; /* Strip off the immediate signifier. */
3873 if (my_get_expression (&expr, str))
3874 {
3875 inst.error = _("bad expression");
3876 return;
3877 }
3878
3879 if (expr.X_op != O_constant)
3880 {
3881 inst.error = _("constant expression expected");
3882 return;
3883 }
3884
3885 /* The mode is a 5 bit field. Valid values are 0-31. */
3886 if (((unsigned) expr.X_add_number) > 31
3887 || (inst.reloc.exp.X_add_number) < 0)
3888 {
3889 inst.error = _("invalid constant");
3890 return;
3891 }
3892
3893 inst.instruction |= expr.X_add_number;
3894 }
3895
3896 /* ARM V6 srs (argument parse). */
3897
3898 static void
3899 do_srs (char * str)
3900 {
3901 char *exclam;
3902 skip_whitespace (str);
3903 exclam = strchr (str, '!');
3904 if (exclam)
3905 *exclam = '\0';
3906 do_cps_mode (&str);
3907 if (exclam)
3908 *exclam = '!';
3909 if (*str == '!')
3910 {
3911 inst.instruction |= WRITE_BACK;
3912 str++;
3913 }
3914 end_of_line (str);
3915 }
3916
3917 /* ARM V6 SMMUL (argument parse). */
3918
3919 static void
3920 do_smmul (char * str)
3921 {
3922 int rd, rm, rs;
3923
3924 skip_whitespace (str);
3925 if ((rd = reg_required_here (&str, 16)) == FAIL
3926 || skip_past_comma (&str) == FAIL
3927 || (rm = reg_required_here (&str, 0)) == FAIL
3928 || skip_past_comma (&str) == FAIL
3929 || (rs = reg_required_here (&str, 8)) == FAIL)
3930 {
3931 inst.error = BAD_ARGS;
3932 return;
3933 }
3934
3935 if ( rd == REG_PC
3936 || rm == REG_PC
3937 || rs == REG_PC)
3938 {
3939 inst.error = BAD_PC;
3940 return;
3941 }
3942
3943 end_of_line (str);
3944 }
3945
3946 /* ARM V6 SMLALD (argument parse). */
3947
3948 static void
3949 do_smlald (char * str)
3950 {
3951 int rdlo, rdhi, rm, rs;
3952
3953 skip_whitespace (str);
3954 if ((rdlo = reg_required_here (&str, 12)) == FAIL
3955 || skip_past_comma (&str) == FAIL
3956 || (rdhi = reg_required_here (&str, 16)) == FAIL
3957 || skip_past_comma (&str) == FAIL
3958 || (rm = reg_required_here (&str, 0)) == FAIL
3959 || skip_past_comma (&str) == FAIL
3960 || (rs = reg_required_here (&str, 8)) == FAIL)
3961 {
3962 inst.error = BAD_ARGS;
3963 return;
3964 }
3965
3966 if ( rdlo == REG_PC
3967 || rdhi == REG_PC
3968 || rm == REG_PC
3969 || rs == REG_PC)
3970 {
3971 inst.error = BAD_PC;
3972 return;
3973 }
3974
3975 end_of_line (str);
3976 }
3977
3978 /* ARM V6 SMLAD (argument parse). Signed multiply accumulate dual.
3979 smlad{x}{<cond>} Rd, Rm, Rs, Rn */
3980
3981 static void
3982 do_smlad (char * str)
3983 {
3984 int rd, rm, rs, rn;
3985
3986 skip_whitespace (str);
3987 if ((rd = reg_required_here (&str, 16)) == FAIL
3988 || skip_past_comma (&str) == FAIL
3989 || (rm = reg_required_here (&str, 0)) == FAIL
3990 || skip_past_comma (&str) == FAIL
3991 || (rs = reg_required_here (&str, 8)) == FAIL
3992 || skip_past_comma (&str) == FAIL
3993 || (rn = reg_required_here (&str, 12)) == FAIL)
3994 {
3995 inst.error = BAD_ARGS;
3996 return;
3997 }
3998
3999 if ( rd == REG_PC
4000 || rn == REG_PC
4001 || rs == REG_PC
4002 || rm == REG_PC)
4003 {
4004 inst.error = BAD_PC;
4005 return;
4006 }
4007
4008 end_of_line (str);
4009 }
4010
4011 /* Returns true if the endian-specifier indicates big-endianness. */
4012
4013 static int
4014 do_endian_specifier (char * str)
4015 {
4016 int big_endian = 0;
4017
4018 skip_whitespace (str);
4019 if (strlen (str) < 2)
4020 inst.error = _("missing endian specifier");
4021 else if (strncasecmp (str, "BE", 2) == 0)
4022 {
4023 str += 2;
4024 big_endian = 1;
4025 }
4026 else if (strncasecmp (str, "LE", 2) == 0)
4027 str += 2;
4028 else
4029 inst.error = _("valid endian specifiers are be or le");
4030
4031 end_of_line (str);
4032
4033 return big_endian;
4034 }
4035
4036 /* ARM V6 SETEND (argument parse). Sets the E bit in the CPSR while
4037 preserving the other bits.
4038
4039 setend <endian_specifier>, where <endian_specifier> is either
4040 BE or LE. */
4041
4042 static void
4043 do_setend (char * str)
4044 {
4045 if (do_endian_specifier (str))
4046 inst.instruction |= 0x200;
4047 }
4048
4049 /* ARM V6 SXTH.
4050
4051 SXTH {<cond>} <Rd>, <Rm>{, <rotation>}
4052 Condition defaults to COND_ALWAYS.
4053 Error if any register uses R15. */
4054
4055 static void
4056 do_sxth (char * str)
4057 {
4058 int rd, rm;
4059 expressionS expr;
4060 int rotation_clear_mask = 0xfffff3ff;
4061 int rotation_eight_mask = 0x00000400;
4062 int rotation_sixteen_mask = 0x00000800;
4063 int rotation_twenty_four_mask = 0x00000c00;
4064
4065 skip_whitespace (str);
4066 if ((rd = reg_required_here (&str, 12)) == FAIL
4067 || skip_past_comma (&str) == FAIL
4068 || (rm = reg_required_here (&str, 0)) == FAIL)
4069 {
4070 inst.error = BAD_ARGS;
4071 return;
4072 }
4073
4074 else if (rd == REG_PC || rm == REG_PC)
4075 {
4076 inst.error = BAD_PC;
4077 return;
4078 }
4079
4080 /* Zero out the rotation field. */
4081 inst.instruction &= rotation_clear_mask;
4082
4083 /* Check for lack of optional rotation field. */
4084 if (skip_past_comma (&str) == FAIL)
4085 {
4086 end_of_line (str);
4087 return;
4088 }
4089
4090 /* Move past 'ROR'. */
4091 skip_whitespace (str);
4092 if (strncasecmp (str, "ROR", 3) == 0)
4093 str += 3;
4094 else
4095 {
4096 inst.error = _("missing rotation field after comma");
4097 return;
4098 }
4099
4100 /* Get the immediate constant. */
4101 skip_whitespace (str);
4102 if (is_immediate_prefix (* str))
4103 str++;
4104 else
4105 {
4106 inst.error = _("immediate expression expected");
4107 return;
4108 }
4109
4110 if (my_get_expression (&expr, &str))
4111 {
4112 inst.error = _("bad expression");
4113 return;
4114 }
4115
4116 if (expr.X_op != O_constant)
4117 {
4118 inst.error = _("constant expression expected");
4119 return;
4120 }
4121
4122 switch (expr.X_add_number)
4123 {
4124 case 0:
4125 /* Rotation field has already been zeroed. */
4126 break;
4127 case 8:
4128 inst.instruction |= rotation_eight_mask;
4129 break;
4130
4131 case 16:
4132 inst.instruction |= rotation_sixteen_mask;
4133 break;
4134
4135 case 24:
4136 inst.instruction |= rotation_twenty_four_mask;
4137 break;
4138
4139 default:
4140 inst.error = _("rotation can be 8, 16, 24 or 0 when field is ommited");
4141 break;
4142 }
4143
4144 end_of_line (str);
4145 }
4146
4147 /* ARM V6 SXTAH extracts a 16-bit value from a register, sign
4148 extends it to 32-bits, and adds the result to a value in another
4149 register. You can specify a rotation by 0, 8, 16, or 24 bits
4150 before extracting the 16-bit value.
4151 SXTAH{<cond>} <Rd>, <Rn>, <Rm>{, <rotation>}
4152 Condition defaults to COND_ALWAYS.
4153 Error if any register uses R15. */
4154
4155 static void
4156 do_sxtah (char * str)
4157 {
4158 int rd, rn, rm;
4159 expressionS expr;
4160 int rotation_clear_mask = 0xfffff3ff;
4161 int rotation_eight_mask = 0x00000400;
4162 int rotation_sixteen_mask = 0x00000800;
4163 int rotation_twenty_four_mask = 0x00000c00;
4164
4165 skip_whitespace (str);
4166 if ((rd = reg_required_here (&str, 12)) == FAIL
4167 || skip_past_comma (&str) == FAIL
4168 || (rn = reg_required_here (&str, 16)) == FAIL
4169 || skip_past_comma (&str) == FAIL
4170 || (rm = reg_required_here (&str, 0)) == FAIL)
4171 {
4172 inst.error = BAD_ARGS;
4173 return;
4174 }
4175
4176 else if (rd == REG_PC || rn == REG_PC || rm == REG_PC)
4177 {
4178 inst.error = BAD_PC;
4179 return;
4180 }
4181
4182 /* Zero out the rotation field. */
4183 inst.instruction &= rotation_clear_mask;
4184
4185 /* Check for lack of optional rotation field. */
4186 if (skip_past_comma (&str) == FAIL)
4187 {
4188 end_of_line (str);
4189 return;
4190 }
4191
4192 /* Move past 'ROR'. */
4193 skip_whitespace (str);
4194 if (strncasecmp (str, "ROR", 3) == 0)
4195 str += 3;
4196 else
4197 {
4198 inst.error = _("missing rotation field after comma");
4199 return;
4200 }
4201
4202 /* Get the immediate constant. */
4203 skip_whitespace (str);
4204 if (is_immediate_prefix (* str))
4205 str++;
4206 else
4207 {
4208 inst.error = _("immediate expression expected");
4209 return;
4210 }
4211
4212 if (my_get_expression (&expr, &str))
4213 {
4214 inst.error = _("bad expression");
4215 return;
4216 }
4217
4218 if (expr.X_op != O_constant)
4219 {
4220 inst.error = _("constant expression expected");
4221 return;
4222 }
4223
4224 switch (expr.X_add_number)
4225 {
4226 case 0:
4227 /* Rotation field has already been zeroed. */
4228 break;
4229
4230 case 8:
4231 inst.instruction |= rotation_eight_mask;
4232 break;
4233
4234 case 16:
4235 inst.instruction |= rotation_sixteen_mask;
4236 break;
4237
4238 case 24:
4239 inst.instruction |= rotation_twenty_four_mask;
4240 break;
4241
4242 default:
4243 inst.error = _("rotation can be 8, 16, 24 or 0 when field is ommited");
4244 break;
4245 }
4246
4247 end_of_line (str);
4248 }
4249
4250
4251 /* ARM V6 RFE (Return from Exception) loads the PC and CPSR from the
4252 word at the specified address and the following word
4253 respectively.
4254 Unconditionally executed.
4255 Error if Rn is R15. */
4256
4257 static void
4258 do_rfe (char * str)
4259 {
4260 int rn;
4261
4262 skip_whitespace (str);
4263
4264 if ((rn = reg_required_here (&str, 16)) == FAIL)
4265 return;
4266
4267 if (rn == REG_PC)
4268 {
4269 inst.error = BAD_PC;
4270 return;
4271 }
4272
4273 skip_whitespace (str);
4274
4275 if (*str == '!')
4276 {
4277 inst.instruction |= WRITE_BACK;
4278 str++;
4279 }
4280 end_of_line (str);
4281 }
4282
4283 /* ARM V6 REV (Byte Reverse Word) reverses the byte order in a 32-bit
4284 register (argument parse).
4285 REV{<cond>} Rd, Rm.
4286 Condition defaults to COND_ALWAYS.
4287 Error if Rd or Rm are R15. */
4288
4289 static void
4290 do_rev (char * str)
4291 {
4292 int rd, rm;
4293
4294 skip_whitespace (str);
4295
4296 if ((rd = reg_required_here (&str, 12)) == FAIL
4297 || skip_past_comma (&str) == FAIL
4298 || (rm = reg_required_here (&str, 0)) == FAIL)
4299 inst.error = BAD_ARGS;
4300
4301 else if (rd == REG_PC || rm == REG_PC)
4302 inst.error = BAD_PC;
4303
4304 else
4305 end_of_line (str);
4306 }
4307
4308 /* ARM V6 Perform Two Sixteen Bit Integer Additions. (argument parse).
4309 QADD16{<cond>} <Rd>, <Rn>, <Rm>
4310 Condition defaults to COND_ALWAYS.
4311 Error if Rd, Rn or Rm are R15. */
4312
4313 static void
4314 do_qadd16 (char * str)
4315 {
4316 int rd, rm, rn;
4317
4318 skip_whitespace (str);
4319
4320 if ((rd = reg_required_here (&str, 12)) == FAIL
4321 || skip_past_comma (&str) == FAIL
4322 || (rn = reg_required_here (&str, 16)) == FAIL
4323 || skip_past_comma (&str) == FAIL
4324 || (rm = reg_required_here (&str, 0)) == FAIL)
4325 inst.error = BAD_ARGS;
4326
4327 else if (rd == REG_PC || rm == REG_PC || rn == REG_PC)
4328 inst.error = BAD_PC;
4329
4330 else
4331 end_of_line (str);
4332 }
4333
4334 static void
4335 do_pkh_core (char * str, int shift)
4336 {
4337 int rd, rn, rm;
4338
4339 skip_whitespace (str);
4340 if (((rd = reg_required_here (&str, 12)) == FAIL)
4341 || (skip_past_comma (&str) == FAIL)
4342 || ((rn = reg_required_here (&str, 16)) == FAIL)
4343 || (skip_past_comma (&str) == FAIL)
4344 || ((rm = reg_required_here (&str, 0)) == FAIL))
4345 {
4346 inst.error = BAD_ARGS;
4347 return;
4348 }
4349
4350 else if (rd == REG_PC || rn == REG_PC || rm == REG_PC)
4351 {
4352 inst.error = BAD_PC;
4353 return;
4354 }
4355
4356 /* Check for optional shift immediate constant. */
4357 if (skip_past_comma (&str) == FAIL)
4358 {
4359 if (shift == SHIFT_ASR_IMMEDIATE)
4360 {
4361 /* If the shift specifier is ommited, turn the instruction
4362 into pkhbt rd, rm, rn. First, switch the instruction
4363 code, and clear the rn and rm fields. */
4364 inst.instruction &= 0xfff0f010;
4365 /* Now, re-encode the registers. */
4366 inst.instruction |= (rm << 16) | rn;
4367 }
4368 return;
4369 }
4370
4371 decode_shift (&str, shift);
4372 }
4373
4374 /* ARM V6 Pack Halfword Bottom Top instruction (argument parse).
4375 PKHBT {<cond>} <Rd>, <Rn>, <Rm> {, LSL #<shift_imm>}
4376 Condition defaults to COND_ALWAYS.
4377 Error if Rd, Rn or Rm are R15. */
4378
4379 static void
4380 do_pkhbt (char * str)
4381 {
4382 do_pkh_core (str, SHIFT_LSL_IMMEDIATE);
4383 }
4384
4385 /* ARM V6 PKHTB (Argument Parse). */
4386
4387 static void
4388 do_pkhtb (char * str)
4389 {
4390 do_pkh_core (str, SHIFT_ASR_IMMEDIATE);
4391 }
4392
4393 /* ARM V6 Load Register Exclusive instruction (argument parse).
4394 LDREX{,B,D,H}{<cond>} <Rd, [<Rn>]
4395 Condition defaults to COND_ALWAYS.
4396 Error if Rd or Rn are R15.
4397 See ARMARMv6 A4.1.27: LDREX. */
4398
4399 static void
4400 do_ldrex (char * str)
4401 {
4402 int rd, rn;
4403
4404 skip_whitespace (str);
4405
4406 /* Parse Rd. */
4407 if (((rd = reg_required_here (&str, 12)) == FAIL)
4408 || (skip_past_comma (&str) == FAIL))
4409 {
4410 inst.error = BAD_ARGS;
4411 return;
4412 }
4413 else if (rd == REG_PC)
4414 {
4415 inst.error = BAD_PC;
4416 return;
4417 }
4418 skip_whitespace (str);
4419
4420 /* Skip past '['. */
4421 if ((strlen (str) >= 1)
4422 &&strncmp (str, "[", 1) == 0)
4423 str += 1;
4424 skip_whitespace (str);
4425
4426 /* Parse Rn. */
4427 if ((rn = reg_required_here (&str, 16)) == FAIL)
4428 {
4429 inst.error = BAD_ARGS;
4430 return;
4431 }
4432 else if (rn == REG_PC)
4433 {
4434 inst.error = BAD_PC;
4435 return;
4436 }
4437 skip_whitespace (str);
4438
4439 /* Skip past ']'. */
4440 if ((strlen (str) >= 1)
4441 && strncmp (str, "]", 1) == 0)
4442 str += 1;
4443
4444 end_of_line (str);
4445 }
4446
4447 /* ARM V6 change processor state instruction (argument parse)
4448 CPS, CPSIE, CSPID . */
4449
4450 static void
4451 do_cps (char * str)
4452 {
4453 do_cps_mode (&str);
4454 end_of_line (str);
4455 }
4456
4457 static void
4458 do_cps_flags (char ** str, int thumb_p)
4459 {
4460 struct cps_flag
4461 {
4462 char character;
4463 unsigned long arm_value;
4464 unsigned long thumb_value;
4465 };
4466 static struct cps_flag flag_table[] =
4467 {
4468 {'a', 0x100, 0x4 },
4469 {'i', 0x080, 0x2 },
4470 {'f', 0x040, 0x1 }
4471 };
4472
4473 int saw_a_flag = 0;
4474
4475 skip_whitespace (*str);
4476
4477 /* Get the a, f and i flags. */
4478 while (**str && **str != ',')
4479 {
4480 struct cps_flag *p;
4481 struct cps_flag *q = flag_table + sizeof (flag_table)/sizeof (*p);
4482
4483 for (p = flag_table; p < q; ++p)
4484 if (strncasecmp (*str, &p->character, 1) == 0)
4485 {
4486 inst.instruction |= (thumb_p ? p->thumb_value : p->arm_value);
4487 saw_a_flag = 1;
4488 break;
4489 }
4490 if (p == q)
4491 {
4492 inst.error = _("unrecognized flag");
4493 return;
4494 }
4495 (*str)++;
4496 }
4497
4498 if (!saw_a_flag)
4499 inst.error = _("no 'a', 'i', or 'f' flags for 'cps'");
4500 }
4501
4502 static void
4503 do_cpsi (char * str)
4504 {
4505 do_cps_flags (&str, /*thumb_p=*/0);
4506
4507 if (skip_past_comma (&str) == SUCCESS)
4508 {
4509 skip_whitespace (str);
4510 do_cps_mode (&str);
4511 }
4512 end_of_line (str);
4513 }
4514
4515 /* THUMB V5 breakpoint instruction (argument parse)
4516 BKPT <immed_8>. */
4517
4518 static void
4519 do_t_bkpt (char * str)
4520 {
4521 expressionS expr;
4522 unsigned long number;
4523
4524 skip_whitespace (str);
4525
4526 /* Allow optional leading '#'. */
4527 if (is_immediate_prefix (*str))
4528 str ++;
4529
4530 memset (& expr, '\0', sizeof (expr));
4531 if (my_get_expression (& expr, & str)
4532 || (expr.X_op != O_constant
4533 /* As a convenience we allow 'bkpt' without an operand. */
4534 && expr.X_op != O_absent))
4535 {
4536 inst.error = _("bad expression");
4537 return;
4538 }
4539
4540 number = expr.X_add_number;
4541
4542 /* Check it fits an 8 bit unsigned. */
4543 if (number != (number & 0xff))
4544 {
4545 inst.error = _("immediate value out of range");
4546 return;
4547 }
4548
4549 inst.instruction |= number;
4550
4551 end_of_line (str);
4552 }
4553
4554 #ifdef OBJ_ELF
4555 static bfd_reloc_code_real_type
4556 arm_parse_reloc (void)
4557 {
4558 char id [16];
4559 char * ip;
4560 unsigned int i;
4561 static struct
4562 {
4563 char * str;
4564 int len;
4565 bfd_reloc_code_real_type reloc;
4566 }
4567 reloc_map[] =
4568 {
4569 #define MAP(str,reloc) { str, sizeof (str) - 1, reloc }
4570 MAP ("(got)", BFD_RELOC_ARM_GOT32),
4571 MAP ("(gotoff)", BFD_RELOC_ARM_GOTOFF),
4572 /* ScottB: Jan 30, 1998 - Added support for parsing "var(PLT)"
4573 branch instructions generated by GCC for PLT relocs. */
4574 MAP ("(plt)", BFD_RELOC_ARM_PLT32),
4575 MAP ("(target1)", BFD_RELOC_ARM_TARGET1),
4576 MAP ("(sbrel)", BFD_RELOC_ARM_SBREL32),
4577 MAP ("(target2)", BFD_RELOC_ARM_TARGET2),
4578 { NULL, 0, BFD_RELOC_UNUSED }
4579 #undef MAP
4580 };
4581
4582 for (i = 0, ip = input_line_pointer;
4583 i < sizeof (id) && (ISALNUM (*ip) || ISPUNCT (*ip));
4584 i++, ip++)
4585 id[i] = TOLOWER (*ip);
4586
4587 for (i = 0; reloc_map[i].str; i++)
4588 if (strncmp (id, reloc_map[i].str, reloc_map[i].len) == 0)
4589 break;
4590
4591 input_line_pointer += reloc_map[i].len;
4592
4593 return reloc_map[i].reloc;
4594 }
4595 #endif
4596
4597 /* ARM V5 branch-link-exchange (argument parse) for BLX(1) only.
4598 Expects inst.instruction is set for BLX(1).
4599 Note: this is cloned from do_branch, and the reloc changed to be a
4600 new one that can cope with setting one extra bit (the H bit). */
4601
4602 static void
4603 do_branch25 (char * str)
4604 {
4605 if (my_get_expression (& inst.reloc.exp, & str))
4606 return;
4607
4608 #ifdef OBJ_ELF
4609 {
4610 char * save_in;
4611
4612 /* ScottB: February 5, 1998 */
4613 /* Check to see of PLT32 reloc required for the instruction. */
4614
4615 /* arm_parse_reloc() works on input_line_pointer.
4616 We actually want to parse the operands to the branch instruction
4617 passed in 'str'. Save the input pointer and restore it later. */
4618 save_in = input_line_pointer;
4619 input_line_pointer = str;
4620
4621 if (inst.reloc.exp.X_op == O_symbol
4622 && *str == '('
4623 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
4624 {
4625 inst.reloc.type = BFD_RELOC_ARM_PLT32;
4626 inst.reloc.pc_rel = 0;
4627 /* Modify str to point to after parsed operands, otherwise
4628 end_of_line() will complain about the (PLT) left in str. */
4629 str = input_line_pointer;
4630 }
4631 else
4632 {
4633 inst.reloc.type = BFD_RELOC_ARM_PCREL_BLX;
4634 inst.reloc.pc_rel = 1;
4635 }
4636
4637 input_line_pointer = save_in;
4638 }
4639 #else
4640 inst.reloc.type = BFD_RELOC_ARM_PCREL_BLX;
4641 inst.reloc.pc_rel = 1;
4642 #endif /* OBJ_ELF */
4643
4644 end_of_line (str);
4645 }
4646
4647 /* ARM V5 branch-link-exchange instruction (argument parse)
4648 BLX <target_addr> ie BLX(1)
4649 BLX{<condition>} <Rm> ie BLX(2)
4650 Unfortunately, there are two different opcodes for this mnemonic.
4651 So, the insns[].value is not used, and the code here zaps values
4652 into inst.instruction.
4653 Also, the <target_addr> can be 25 bits, hence has its own reloc. */
4654
4655 static void
4656 do_blx (char * str)
4657 {
4658 char * mystr = str;
4659 int rm;
4660
4661 skip_whitespace (mystr);
4662 rm = reg_required_here (& mystr, 0);
4663
4664 /* The above may set inst.error. Ignore his opinion. */
4665 inst.error = 0;
4666
4667 if (rm != FAIL)
4668 {
4669 /* Arg is a register.
4670 Use the condition code our caller put in inst.instruction.
4671 Pass ourselves off as a BX with a funny opcode. */
4672 inst.instruction |= 0x012fff30;
4673 do_bx (str);
4674 }
4675 else
4676 {
4677 /* This must be is BLX <target address>, no condition allowed. */
4678 if (inst.instruction != COND_ALWAYS)
4679 {
4680 inst.error = BAD_COND;
4681 return;
4682 }
4683
4684 inst.instruction = 0xfafffffe;
4685
4686 /* Process like a B/BL, but with a different reloc.
4687 Note that B/BL expecte fffffe, not 0, offset in the opcode table. */
4688 do_branch25 (str);
4689 }
4690 }
4691
4692 /* ARM V5 Thumb BLX (argument parse)
4693 BLX <target_addr> which is BLX(1)
4694 BLX <Rm> which is BLX(2)
4695 Unfortunately, there are two different opcodes for this mnemonic.
4696 So, the tinsns[].value is not used, and the code here zaps values
4697 into inst.instruction. */
4698
4699 static void
4700 do_t_blx (char * str)
4701 {
4702 char * mystr = str;
4703 int rm;
4704
4705 skip_whitespace (mystr);
4706 inst.instruction = 0x4780;
4707
4708 /* Note that this call is to the ARM register recognizer. BLX(2)
4709 uses the ARM register space, not the Thumb one, so a call to
4710 thumb_reg() would be wrong. */
4711 rm = reg_required_here (& mystr, 3);
4712 inst.error = 0;
4713
4714 if (rm != FAIL)
4715 {
4716 /* It's BLX(2). The .instruction was zapped with rm & is final. */
4717 inst.size = 2;
4718 }
4719 else
4720 {
4721 /* No ARM register. This must be BLX(1). Change the .instruction. */
4722 inst.instruction = 0xf7ffeffe;
4723 inst.size = 4;
4724
4725 if (my_get_expression (& inst.reloc.exp, & mystr))
4726 return;
4727
4728 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BLX;
4729 inst.reloc.pc_rel = 1;
4730 }
4731
4732 end_of_line (mystr);
4733 }
4734
4735 /* ARM V5 breakpoint instruction (argument parse)
4736 BKPT <16 bit unsigned immediate>
4737 Instruction is not conditional.
4738 The bit pattern given in insns[] has the COND_ALWAYS condition,
4739 and it is an error if the caller tried to override that. */
4740
4741 static void
4742 do_bkpt (char * str)
4743 {
4744 expressionS expr;
4745 unsigned long number;
4746
4747 skip_whitespace (str);
4748
4749 /* Allow optional leading '#'. */
4750 if (is_immediate_prefix (* str))
4751 str++;
4752
4753 memset (& expr, '\0', sizeof (expr));
4754
4755 if (my_get_expression (& expr, & str)
4756 || (expr.X_op != O_constant
4757 /* As a convenience we allow 'bkpt' without an operand. */
4758 && expr.X_op != O_absent))
4759 {
4760 inst.error = _("bad expression");
4761 return;
4762 }
4763
4764 number = expr.X_add_number;
4765
4766 /* Check it fits a 16 bit unsigned. */
4767 if (number != (number & 0xffff))
4768 {
4769 inst.error = _("immediate value out of range");
4770 return;
4771 }
4772
4773 /* Top 12 of 16 bits to bits 19:8. */
4774 inst.instruction |= (number & 0xfff0) << 4;
4775
4776 /* Bottom 4 of 16 bits to bits 3:0. */
4777 inst.instruction |= number & 0xf;
4778
4779 end_of_line (str);
4780 }
4781
4782 /* THUMB CPS instruction (argument parse). */
4783
4784 static void
4785 do_t_cps (char * str)
4786 {
4787 do_cps_flags (&str, /*thumb_p=*/1);
4788 end_of_line (str);
4789 }
4790
4791 /* Parse and validate that a register is of the right form, this saves
4792 repeated checking of this information in many similar cases.
4793 Unlike the 32-bit case we do not insert the register into the opcode
4794 here, since the position is often unknown until the full instruction
4795 has been parsed. */
4796
4797 static int
4798 thumb_reg (char ** strp, int hi_lo)
4799 {
4800 int reg;
4801
4802 if ((reg = reg_required_here (strp, -1)) == FAIL)
4803 return FAIL;
4804
4805 switch (hi_lo)
4806 {
4807 case THUMB_REG_LO:
4808 if (reg > 7)
4809 {
4810 inst.error = _("lo register required");
4811 return FAIL;
4812 }
4813 break;
4814
4815 case THUMB_REG_HI:
4816 if (reg < 8)
4817 {
4818 inst.error = _("hi register required");
4819 return FAIL;
4820 }
4821 break;
4822
4823 default:
4824 break;
4825 }
4826
4827 return reg;
4828 }
4829
4830 static void
4831 thumb_mov_compare (char * str, int move)
4832 {
4833 int Rd, Rs = FAIL;
4834
4835 skip_whitespace (str);
4836
4837 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
4838 || skip_past_comma (&str) == FAIL)
4839 {
4840 if (! inst.error)
4841 inst.error = BAD_ARGS;
4842 return;
4843 }
4844
4845 if (move != THUMB_CPY && is_immediate_prefix (*str))
4846 {
4847 str++;
4848 if (my_get_expression (&inst.reloc.exp, &str))
4849 return;
4850 }
4851 else if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
4852 return;
4853
4854 if (Rs != FAIL)
4855 {
4856 if (move != THUMB_CPY && Rs < 8 && Rd < 8)
4857 {
4858 if (move == THUMB_MOVE)
4859 /* A move of two lowregs is encoded as ADD Rd, Rs, #0
4860 since a MOV instruction produces unpredictable results. */
4861 inst.instruction = T_OPCODE_ADD_I3;
4862 else
4863 inst.instruction = T_OPCODE_CMP_LR;
4864 inst.instruction |= Rd | (Rs << 3);
4865 }
4866 else
4867 {
4868 if (move == THUMB_MOVE)
4869 inst.instruction = T_OPCODE_MOV_HR;
4870 else if (move != THUMB_CPY)
4871 inst.instruction = T_OPCODE_CMP_HR;
4872
4873 if (Rd > 7)
4874 inst.instruction |= THUMB_H1;
4875
4876 if (Rs > 7)
4877 inst.instruction |= THUMB_H2;
4878
4879 inst.instruction |= (Rd & 7) | ((Rs & 7) << 3);
4880 }
4881 }
4882 else
4883 {
4884 if (Rd > 7)
4885 {
4886 inst.error = _("only lo regs allowed with immediate");
4887 return;
4888 }
4889
4890 if (move == THUMB_MOVE)
4891 inst.instruction = T_OPCODE_MOV_I8;
4892 else
4893 inst.instruction = T_OPCODE_CMP_I8;
4894
4895 inst.instruction |= Rd << 8;
4896
4897 if (inst.reloc.exp.X_op != O_constant)
4898 inst.reloc.type = BFD_RELOC_ARM_THUMB_IMM;
4899 else
4900 {
4901 unsigned value = inst.reloc.exp.X_add_number;
4902
4903 if (value > 255)
4904 {
4905 inst.error = _("invalid immediate");
4906 return;
4907 }
4908
4909 inst.instruction |= value;
4910 }
4911 }
4912
4913 end_of_line (str);
4914 }
4915
4916 /* THUMB CPY instruction (argument parse). */
4917
4918 static void
4919 do_t_cpy (char * str)
4920 {
4921 thumb_mov_compare (str, THUMB_CPY);
4922 }
4923
4924 /* THUMB SETEND instruction (argument parse). */
4925
4926 static void
4927 do_t_setend (char * str)
4928 {
4929 if (do_endian_specifier (str))
4930 inst.instruction |= 0x8;
4931 }
4932
4933 /* Parse INSN_TYPE insn STR having a possible IMMEDIATE_SIZE immediate. */
4934
4935 static unsigned long
4936 check_iwmmxt_insn (char * str,
4937 enum iwmmxt_insn_type insn_type,
4938 int immediate_size)
4939 {
4940 int reg = 0;
4941 const char * inst_error;
4942 expressionS expr;
4943 unsigned long number;
4944
4945 inst_error = inst.error;
4946 if (!inst.error)
4947 inst.error = BAD_ARGS;
4948 skip_whitespace (str);
4949
4950 switch (insn_type)
4951 {
4952 case check_rd:
4953 if ((reg = reg_required_here (&str, 12)) == FAIL)
4954 return FAIL;
4955 break;
4956
4957 case check_wr:
4958 if ((wreg_required_here (&str, 0, IWMMXT_REG_WR)) == FAIL)
4959 return FAIL;
4960 break;
4961
4962 case check_wrwr:
4963 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
4964 || skip_past_comma (&str) == FAIL
4965 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL))
4966 return FAIL;
4967 break;
4968
4969 case check_wrwrwr:
4970 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
4971 || skip_past_comma (&str) == FAIL
4972 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
4973 || skip_past_comma (&str) == FAIL
4974 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL))
4975 return FAIL;
4976 break;
4977
4978 case check_wrwrwcg:
4979 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
4980 || skip_past_comma (&str) == FAIL
4981 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
4982 || skip_past_comma (&str) == FAIL
4983 || wreg_required_here (&str, 0, IWMMXT_REG_WCG) == FAIL))
4984 return FAIL;
4985 break;
4986
4987 case check_tbcst:
4988 if ((wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
4989 || skip_past_comma (&str) == FAIL
4990 || reg_required_here (&str, 12) == FAIL))
4991 return FAIL;
4992 break;
4993
4994 case check_tmovmsk:
4995 if ((reg_required_here (&str, 12) == FAIL
4996 || skip_past_comma (&str) == FAIL
4997 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL))
4998 return FAIL;
4999 break;
5000
5001 case check_tmia:
5002 if ((wreg_required_here (&str, 5, IWMMXT_REG_WR) == FAIL
5003 || skip_past_comma (&str) == FAIL
5004 || reg_required_here (&str, 0) == FAIL
5005 || skip_past_comma (&str) == FAIL
5006 || reg_required_here (&str, 12) == FAIL))
5007 return FAIL;
5008 break;
5009
5010 case check_tmcrr:
5011 if ((wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL
5012 || skip_past_comma (&str) == FAIL
5013 || reg_required_here (&str, 12) == FAIL
5014 || skip_past_comma (&str) == FAIL
5015 || reg_required_here (&str, 16) == FAIL))
5016 return FAIL;
5017 break;
5018
5019 case check_tmrrc:
5020 if ((reg_required_here (&str, 12) == FAIL
5021 || skip_past_comma (&str) == FAIL
5022 || reg_required_here (&str, 16) == FAIL
5023 || skip_past_comma (&str) == FAIL
5024 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL))
5025 return FAIL;
5026 break;
5027
5028 case check_tmcr:
5029 if ((wreg_required_here (&str, 16, IWMMXT_REG_WC) == FAIL
5030 || skip_past_comma (&str) == FAIL
5031 || reg_required_here (&str, 12) == FAIL))
5032 return FAIL;
5033 break;
5034
5035 case check_tmrc:
5036 if ((reg_required_here (&str, 12) == FAIL
5037 || skip_past_comma (&str) == FAIL
5038 || wreg_required_here (&str, 16, IWMMXT_REG_WC) == FAIL))
5039 return FAIL;
5040 break;
5041
5042 case check_tinsr:
5043 if ((wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5044 || skip_past_comma (&str) == FAIL
5045 || reg_required_here (&str, 12) == FAIL
5046 || skip_past_comma (&str) == FAIL))
5047 return FAIL;
5048 break;
5049
5050 case check_textrc:
5051 if ((reg_required_here (&str, 12) == FAIL
5052 || skip_past_comma (&str) == FAIL))
5053 return FAIL;
5054 break;
5055
5056 case check_waligni:
5057 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
5058 || skip_past_comma (&str) == FAIL
5059 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5060 || skip_past_comma (&str) == FAIL
5061 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL
5062 || skip_past_comma (&str) == FAIL))
5063 return FAIL;
5064 break;
5065
5066 case check_textrm:
5067 if ((reg_required_here (&str, 12) == FAIL
5068 || skip_past_comma (&str) == FAIL
5069 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5070 || skip_past_comma (&str) == FAIL))
5071 return FAIL;
5072 break;
5073
5074 case check_wshufh:
5075 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
5076 || skip_past_comma (&str) == FAIL
5077 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5078 || skip_past_comma (&str) == FAIL))
5079 return FAIL;
5080 break;
5081 }
5082
5083 if (immediate_size == 0)
5084 {
5085 end_of_line (str);
5086 inst.error = inst_error;
5087 return reg;
5088 }
5089 else
5090 {
5091 skip_whitespace (str);
5092
5093 /* Allow optional leading '#'. */
5094 if (is_immediate_prefix (* str))
5095 str++;
5096
5097 memset (& expr, '\0', sizeof (expr));
5098
5099 if (my_get_expression (& expr, & str) || (expr.X_op != O_constant))
5100 {
5101 inst.error = _("bad or missing expression");
5102 return FAIL;
5103 }
5104
5105 number = expr.X_add_number;
5106
5107 if (number != (number & immediate_size))
5108 {
5109 inst.error = _("immediate value out of range");
5110 return FAIL;
5111 }
5112 end_of_line (str);
5113 inst.error = inst_error;
5114 return number;
5115 }
5116 }
5117
5118 static void
5119 do_iwmmxt_byte_addr (char * str)
5120 {
5121 int op = (inst.instruction & 0x300) >> 8;
5122 int reg;
5123
5124 inst.instruction &= ~0x300;
5125 inst.instruction |= (op & 1) << 22 | (op & 2) << 7;
5126
5127 skip_whitespace (str);
5128
5129 if ((reg = wreg_required_here (&str, 12, IWMMXT_REG_WR_OR_WC)) == FAIL
5130 || skip_past_comma (& str) == FAIL
5131 || cp_byte_address_required_here (&str) == FAIL)
5132 {
5133 if (! inst.error)
5134 inst.error = BAD_ARGS;
5135 }
5136 else
5137 end_of_line (str);
5138
5139 if (wc_register (reg))
5140 {
5141 as_bad (_("non-word size not supported with control register"));
5142 inst.instruction |= 0xf0000100;
5143 inst.instruction &= ~0x00400000;
5144 }
5145 }
5146
5147 static void
5148 do_iwmmxt_tandc (char * str)
5149 {
5150 int reg;
5151
5152 reg = check_iwmmxt_insn (str, check_rd, 0);
5153
5154 if (reg != REG_PC && !inst.error)
5155 inst.error = _("only r15 allowed here");
5156 }
5157
5158 static void
5159 do_iwmmxt_tbcst (char * str)
5160 {
5161 check_iwmmxt_insn (str, check_tbcst, 0);
5162 }
5163
5164 static void
5165 do_iwmmxt_textrc (char * str)
5166 {
5167 unsigned long number;
5168
5169 if ((number = check_iwmmxt_insn (str, check_textrc, 7)) == (unsigned long) FAIL)
5170 return;
5171
5172 inst.instruction |= number & 0x7;
5173 }
5174
5175 static void
5176 do_iwmmxt_textrm (char * str)
5177 {
5178 unsigned long number;
5179
5180 if ((number = check_iwmmxt_insn (str, check_textrm, 7)) == (unsigned long) FAIL)
5181 return;
5182
5183 inst.instruction |= number & 0x7;
5184 }
5185
5186 static void
5187 do_iwmmxt_tinsr (char * str)
5188 {
5189 unsigned long number;
5190
5191 if ((number = check_iwmmxt_insn (str, check_tinsr, 7)) == (unsigned long) FAIL)
5192 return;
5193
5194 inst.instruction |= number & 0x7;
5195 }
5196
5197 static void
5198 do_iwmmxt_tmcr (char * str)
5199 {
5200 check_iwmmxt_insn (str, check_tmcr, 0);
5201 }
5202
5203 static void
5204 do_iwmmxt_tmcrr (char * str)
5205 {
5206 check_iwmmxt_insn (str, check_tmcrr, 0);
5207 }
5208
5209 static void
5210 do_iwmmxt_tmia (char * str)
5211 {
5212 check_iwmmxt_insn (str, check_tmia, 0);
5213 }
5214
5215 static void
5216 do_iwmmxt_tmovmsk (char * str)
5217 {
5218 check_iwmmxt_insn (str, check_tmovmsk, 0);
5219 }
5220
5221 static void
5222 do_iwmmxt_tmrc (char * str)
5223 {
5224 check_iwmmxt_insn (str, check_tmrc, 0);
5225 }
5226
5227 static void
5228 do_iwmmxt_tmrrc (char * str)
5229 {
5230 check_iwmmxt_insn (str, check_tmrrc, 0);
5231 }
5232
5233 static void
5234 do_iwmmxt_torc (char * str)
5235 {
5236 check_iwmmxt_insn (str, check_rd, 0);
5237 }
5238
5239 static void
5240 do_iwmmxt_waligni (char * str)
5241 {
5242 unsigned long number;
5243
5244 if ((number = check_iwmmxt_insn (str, check_waligni, 7)) == (unsigned long) FAIL)
5245 return;
5246
5247 inst.instruction |= ((number & 0x7) << 20);
5248 }
5249
5250 static void
5251 do_iwmmxt_wmov (char * str)
5252 {
5253 if (check_iwmmxt_insn (str, check_wrwr, 0) == (unsigned long) FAIL)
5254 return;
5255
5256 inst.instruction |= ((inst.instruction >> 16) & 0xf);
5257 }
5258
5259 static void
5260 do_iwmmxt_word_addr (char * str)
5261 {
5262 int op = (inst.instruction & 0x300) >> 8;
5263 int reg;
5264
5265 inst.instruction &= ~0x300;
5266 inst.instruction |= (op & 1) << 22 | (op & 2) << 7;
5267
5268 skip_whitespace (str);
5269
5270 if ((reg = wreg_required_here (&str, 12, IWMMXT_REG_WR_OR_WC)) == FAIL
5271 || skip_past_comma (& str) == FAIL
5272 || cp_address_required_here (& str, CP_WB_OK) == FAIL)
5273 {
5274 if (! inst.error)
5275 inst.error = BAD_ARGS;
5276 }
5277 else
5278 end_of_line (str);
5279
5280 if (wc_register (reg))
5281 {
5282 if ((inst.instruction & COND_MASK) != COND_ALWAYS)
5283 as_bad (_("conditional execution not supported with control register"));
5284 if (op != 2)
5285 as_bad (_("non-word size not supported with control register"));
5286 inst.instruction |= 0xf0000100;
5287 inst.instruction &= ~0x00400000;
5288 }
5289 }
5290
5291 static void
5292 do_iwmmxt_wrwr (char * str)
5293 {
5294 check_iwmmxt_insn (str, check_wrwr, 0);
5295 }
5296
5297 static void
5298 do_iwmmxt_wrwrwcg (char * str)
5299 {
5300 check_iwmmxt_insn (str, check_wrwrwcg, 0);
5301 }
5302
5303 static void
5304 do_iwmmxt_wrwrwr (char * str)
5305 {
5306 check_iwmmxt_insn (str, check_wrwrwr, 0);
5307 }
5308
5309 static void
5310 do_iwmmxt_wshufh (char * str)
5311 {
5312 unsigned long number;
5313
5314 if ((number = check_iwmmxt_insn (str, check_wshufh, 0xff)) == (unsigned long) FAIL)
5315 return;
5316
5317 inst.instruction |= ((number & 0xf0) << 16) | (number & 0xf);
5318 }
5319
5320 static void
5321 do_iwmmxt_wzero (char * str)
5322 {
5323 if (check_iwmmxt_insn (str, check_wr, 0) == (unsigned long) FAIL)
5324 return;
5325
5326 inst.instruction |= ((inst.instruction & 0xf) << 12) | ((inst.instruction & 0xf) << 16);
5327 }
5328
5329 /* Xscale multiply-accumulate (argument parse)
5330 MIAcc acc0,Rm,Rs
5331 MIAPHcc acc0,Rm,Rs
5332 MIAxycc acc0,Rm,Rs. */
5333
5334 static void
5335 do_xsc_mia (char * str)
5336 {
5337 int rs;
5338 int rm;
5339
5340 if (accum0_required_here (& str) == FAIL)
5341 inst.error = ERR_NO_ACCUM;
5342
5343 else if (skip_past_comma (& str) == FAIL
5344 || (rm = reg_required_here (& str, 0)) == FAIL)
5345 inst.error = BAD_ARGS;
5346
5347 else if (skip_past_comma (& str) == FAIL
5348 || (rs = reg_required_here (& str, 12)) == FAIL)
5349 inst.error = BAD_ARGS;
5350
5351 /* inst.instruction has now been zapped with both rm and rs. */
5352 else if (rm == REG_PC || rs == REG_PC)
5353 inst.error = BAD_PC; /* Undefined result if rm or rs is R15. */
5354
5355 else
5356 end_of_line (str);
5357 }
5358
5359 /* Xscale move-accumulator-register (argument parse)
5360
5361 MARcc acc0,RdLo,RdHi. */
5362
5363 static void
5364 do_xsc_mar (char * str)
5365 {
5366 int rdlo, rdhi;
5367
5368 if (accum0_required_here (& str) == FAIL)
5369 inst.error = ERR_NO_ACCUM;
5370
5371 else if (skip_past_comma (& str) == FAIL
5372 || (rdlo = reg_required_here (& str, 12)) == FAIL)
5373 inst.error = BAD_ARGS;
5374
5375 else if (skip_past_comma (& str) == FAIL
5376 || (rdhi = reg_required_here (& str, 16)) == FAIL)
5377 inst.error = BAD_ARGS;
5378
5379 /* inst.instruction has now been zapped with both rdlo and rdhi. */
5380 else if (rdlo == REG_PC || rdhi == REG_PC)
5381 inst.error = BAD_PC; /* Undefined result if rdlo or rdhi is R15. */
5382
5383 else
5384 end_of_line (str);
5385 }
5386
5387 /* Xscale move-register-accumulator (argument parse)
5388
5389 MRAcc RdLo,RdHi,acc0. */
5390
5391 static void
5392 do_xsc_mra (char * str)
5393 {
5394 int rdlo;
5395 int rdhi;
5396
5397 skip_whitespace (str);
5398
5399 if ((rdlo = reg_required_here (& str, 12)) == FAIL)
5400 inst.error = BAD_ARGS;
5401
5402 else if (skip_past_comma (& str) == FAIL
5403 || (rdhi = reg_required_here (& str, 16)) == FAIL)
5404 inst.error = BAD_ARGS;
5405
5406 else if (skip_past_comma (& str) == FAIL
5407 || accum0_required_here (& str) == FAIL)
5408 inst.error = ERR_NO_ACCUM;
5409
5410 /* inst.instruction has now been zapped with both rdlo and rdhi. */
5411 else if (rdlo == rdhi)
5412 inst.error = BAD_ARGS; /* Undefined result if 2 writes to same reg. */
5413
5414 else if (rdlo == REG_PC || rdhi == REG_PC)
5415 inst.error = BAD_PC; /* Undefined result if rdlo or rdhi is R15. */
5416 else
5417 end_of_line (str);
5418 }
5419
5420 static int
5421 ldst_extend (char ** str)
5422 {
5423 int add = INDEX_UP;
5424
5425 switch (**str)
5426 {
5427 case '#':
5428 case '$':
5429 (*str)++;
5430 if (my_get_expression (& inst.reloc.exp, str))
5431 return FAIL;
5432
5433 if (inst.reloc.exp.X_op == O_constant)
5434 {
5435 int value = inst.reloc.exp.X_add_number;
5436
5437 if (value < -4095 || value > 4095)
5438 {
5439 inst.error = _("address offset too large");
5440 return FAIL;
5441 }
5442
5443 if (value < 0)
5444 {
5445 value = -value;
5446 add = 0;
5447 }
5448
5449 inst.instruction |= add | value;
5450 }
5451 else
5452 {
5453 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
5454 inst.reloc.pc_rel = 0;
5455 }
5456 return SUCCESS;
5457
5458 case '-':
5459 add = 0;
5460 /* Fall through. */
5461
5462 case '+':
5463 (*str)++;
5464 /* Fall through. */
5465
5466 default:
5467 if (reg_required_here (str, 0) == FAIL)
5468 return FAIL;
5469
5470 inst.instruction |= add | OFFSET_REG;
5471 if (skip_past_comma (str) == SUCCESS)
5472 return decode_shift (str, SHIFT_IMMEDIATE);
5473
5474 return SUCCESS;
5475 }
5476 }
5477
5478 /* ARMv5TE: Preload-Cache
5479
5480 PLD <addr_mode>
5481
5482 Syntactically, like LDR with B=1, W=0, L=1. */
5483
5484 static void
5485 do_pld (char * str)
5486 {
5487 int rd;
5488
5489 skip_whitespace (str);
5490
5491 if (* str != '[')
5492 {
5493 inst.error = _("'[' expected after PLD mnemonic");
5494 return;
5495 }
5496
5497 ++str;
5498 skip_whitespace (str);
5499
5500 if ((rd = reg_required_here (& str, 16)) == FAIL)
5501 return;
5502
5503 skip_whitespace (str);
5504
5505 if (*str == ']')
5506 {
5507 /* [Rn], ... ? */
5508 ++str;
5509 skip_whitespace (str);
5510
5511 /* Post-indexed addressing is not allowed with PLD. */
5512 if (skip_past_comma (&str) == SUCCESS)
5513 {
5514 inst.error
5515 = _("post-indexed expression used in preload instruction");
5516 return;
5517 }
5518 else if (*str == '!') /* [Rn]! */
5519 {
5520 inst.error = _("writeback used in preload instruction");
5521 ++str;
5522 }
5523 else /* [Rn] */
5524 inst.instruction |= INDEX_UP | PRE_INDEX;
5525 }
5526 else /* [Rn, ...] */
5527 {
5528 if (skip_past_comma (& str) == FAIL)
5529 {
5530 inst.error = _("pre-indexed expression expected");
5531 return;
5532 }
5533
5534 if (ldst_extend (&str) == FAIL)
5535 return;
5536
5537 skip_whitespace (str);
5538
5539 if (* str != ']')
5540 {
5541 inst.error = _("missing ]");
5542 return;
5543 }
5544
5545 ++ str;
5546 skip_whitespace (str);
5547
5548 if (* str == '!') /* [Rn]! */
5549 {
5550 inst.error = _("writeback used in preload instruction");
5551 ++ str;
5552 }
5553
5554 inst.instruction |= PRE_INDEX;
5555 }
5556
5557 end_of_line (str);
5558 }
5559
5560 /* ARMv5TE load-consecutive (argument parse)
5561 Mode is like LDRH.
5562
5563 LDRccD R, mode
5564 STRccD R, mode. */
5565
5566 static void
5567 do_ldrd (char * str)
5568 {
5569 int rd;
5570 int rn;
5571
5572 skip_whitespace (str);
5573
5574 if ((rd = reg_required_here (& str, 12)) == FAIL)
5575 {
5576 inst.error = BAD_ARGS;
5577 return;
5578 }
5579
5580 if (skip_past_comma (& str) == FAIL
5581 || (rn = ld_mode_required_here (& str)) == FAIL)
5582 {
5583 if (!inst.error)
5584 inst.error = BAD_ARGS;
5585 return;
5586 }
5587
5588 /* inst.instruction has now been zapped with Rd and the addressing mode. */
5589 if (rd & 1) /* Unpredictable result if Rd is odd. */
5590 {
5591 inst.error = _("destination register must be even");
5592 return;
5593 }
5594
5595 if (rd == REG_LR)
5596 {
5597 inst.error = _("r14 not allowed here");
5598 return;
5599 }
5600
5601 if (((rd == rn) || (rd + 1 == rn))
5602 && ((inst.instruction & WRITE_BACK)
5603 || (!(inst.instruction & PRE_INDEX))))
5604 as_warn (_("pre/post-indexing used when modified address register is destination"));
5605
5606 /* For an index-register load, the index register must not overlap the
5607 destination (even if not write-back). */
5608 if ((inst.instruction & V4_STR_BIT) == 0
5609 && (inst.instruction & HWOFFSET_IMM) == 0)
5610 {
5611 int rm = inst.instruction & 0x0000000f;
5612
5613 if (rm == rd || (rm == rd + 1))
5614 as_warn (_("ldrd destination registers must not overlap index register"));
5615 }
5616
5617 end_of_line (str);
5618 }
5619
5620 /* Returns the index into fp_values of a floating point number,
5621 or -1 if not in the table. */
5622
5623 static int
5624 my_get_float_expression (char ** str)
5625 {
5626 LITTLENUM_TYPE words[MAX_LITTLENUMS];
5627 char * save_in;
5628 expressionS exp;
5629 int i;
5630 int j;
5631
5632 memset (words, 0, MAX_LITTLENUMS * sizeof (LITTLENUM_TYPE));
5633
5634 /* Look for a raw floating point number. */
5635 if ((save_in = atof_ieee (*str, 'x', words)) != NULL
5636 && is_end_of_line[(unsigned char) *save_in])
5637 {
5638 for (i = 0; i < NUM_FLOAT_VALS; i++)
5639 {
5640 for (j = 0; j < MAX_LITTLENUMS; j++)
5641 {
5642 if (words[j] != fp_values[i][j])
5643 break;
5644 }
5645
5646 if (j == MAX_LITTLENUMS)
5647 {
5648 *str = save_in;
5649 return i;
5650 }
5651 }
5652 }
5653
5654 /* Try and parse a more complex expression, this will probably fail
5655 unless the code uses a floating point prefix (eg "0f"). */
5656 save_in = input_line_pointer;
5657 input_line_pointer = *str;
5658 if (expression (&exp) == absolute_section
5659 && exp.X_op == O_big
5660 && exp.X_add_number < 0)
5661 {
5662 /* FIXME: 5 = X_PRECISION, should be #define'd where we can use it.
5663 Ditto for 15. */
5664 if (gen_to_words (words, 5, (long) 15) == 0)
5665 {
5666 for (i = 0; i < NUM_FLOAT_VALS; i++)
5667 {
5668 for (j = 0; j < MAX_LITTLENUMS; j++)
5669 {
5670 if (words[j] != fp_values[i][j])
5671 break;
5672 }
5673
5674 if (j == MAX_LITTLENUMS)
5675 {
5676 *str = input_line_pointer;
5677 input_line_pointer = save_in;
5678 return i;
5679 }
5680 }
5681 }
5682 }
5683
5684 *str = input_line_pointer;
5685 input_line_pointer = save_in;
5686 return -1;
5687 }
5688
5689 /* We handle all bad expressions here, so that we can report the faulty
5690 instruction in the error message. */
5691 void
5692 md_operand (expressionS * expr)
5693 {
5694 if (in_my_get_expression)
5695 {
5696 expr->X_op = O_illegal;
5697 if (inst.error == NULL)
5698 inst.error = _("bad expression");
5699 }
5700 }
5701
5702 /* Do those data_ops which can take a negative immediate constant
5703 by altering the instruction. A bit of a hack really.
5704 MOV <-> MVN
5705 AND <-> BIC
5706 ADC <-> SBC
5707 by inverting the second operand, and
5708 ADD <-> SUB
5709 CMP <-> CMN
5710 by negating the second operand. */
5711
5712 static int
5713 negate_data_op (unsigned long * instruction,
5714 unsigned long value)
5715 {
5716 int op, new_inst;
5717 unsigned long negated, inverted;
5718
5719 negated = validate_immediate (-value);
5720 inverted = validate_immediate (~value);
5721
5722 op = (*instruction >> DATA_OP_SHIFT) & 0xf;
5723 switch (op)
5724 {
5725 /* First negates. */
5726 case OPCODE_SUB: /* ADD <-> SUB */
5727 new_inst = OPCODE_ADD;
5728 value = negated;
5729 break;
5730
5731 case OPCODE_ADD:
5732 new_inst = OPCODE_SUB;
5733 value = negated;
5734 break;
5735
5736 case OPCODE_CMP: /* CMP <-> CMN */
5737 new_inst = OPCODE_CMN;
5738 value = negated;
5739 break;
5740
5741 case OPCODE_CMN:
5742 new_inst = OPCODE_CMP;
5743 value = negated;
5744 break;
5745
5746 /* Now Inverted ops. */
5747 case OPCODE_MOV: /* MOV <-> MVN */
5748 new_inst = OPCODE_MVN;
5749 value = inverted;
5750 break;
5751
5752 case OPCODE_MVN:
5753 new_inst = OPCODE_MOV;
5754 value = inverted;
5755 break;
5756
5757 case OPCODE_AND: /* AND <-> BIC */
5758 new_inst = OPCODE_BIC;
5759 value = inverted;
5760 break;
5761
5762 case OPCODE_BIC:
5763 new_inst = OPCODE_AND;
5764 value = inverted;
5765 break;
5766
5767 case OPCODE_ADC: /* ADC <-> SBC */
5768 new_inst = OPCODE_SBC;
5769 value = inverted;
5770 break;
5771
5772 case OPCODE_SBC:
5773 new_inst = OPCODE_ADC;
5774 value = inverted;
5775 break;
5776
5777 /* We cannot do anything. */
5778 default:
5779 return FAIL;
5780 }
5781
5782 if (value == (unsigned) FAIL)
5783 return FAIL;
5784
5785 *instruction &= OPCODE_MASK;
5786 *instruction |= new_inst << DATA_OP_SHIFT;
5787 return value;
5788 }
5789
5790 static int
5791 data_op2 (char ** str)
5792 {
5793 int value;
5794 expressionS expr;
5795
5796 skip_whitespace (* str);
5797
5798 if (reg_required_here (str, 0) != FAIL)
5799 {
5800 if (skip_past_comma (str) == SUCCESS)
5801 /* Shift operation on register. */
5802 return decode_shift (str, NO_SHIFT_RESTRICT);
5803
5804 return SUCCESS;
5805 }
5806 else
5807 {
5808 /* Immediate expression. */
5809 if (is_immediate_prefix (**str))
5810 {
5811 (*str)++;
5812 inst.error = NULL;
5813
5814 if (my_get_expression (&inst.reloc.exp, str))
5815 return FAIL;
5816
5817 if (inst.reloc.exp.X_add_symbol)
5818 {
5819 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
5820 inst.reloc.pc_rel = 0;
5821 }
5822 else
5823 {
5824 if (skip_past_comma (str) == SUCCESS)
5825 {
5826 /* #x, y -- ie explicit rotation by Y. */
5827 if (my_get_expression (&expr, str))
5828 return FAIL;
5829
5830 if (expr.X_op != O_constant)
5831 {
5832 inst.error = _("constant expression expected");
5833 return FAIL;
5834 }
5835
5836 /* Rotate must be a multiple of 2. */
5837 if (((unsigned) expr.X_add_number) > 30
5838 || (expr.X_add_number & 1) != 0
5839 || ((unsigned) inst.reloc.exp.X_add_number) > 255)
5840 {
5841 inst.error = _("invalid constant");
5842 return FAIL;
5843 }
5844 inst.instruction |= INST_IMMEDIATE;
5845 inst.instruction |= inst.reloc.exp.X_add_number;
5846 inst.instruction |= expr.X_add_number << 7;
5847 return SUCCESS;
5848 }
5849
5850 /* Implicit rotation, select a suitable one. */
5851 value = validate_immediate (inst.reloc.exp.X_add_number);
5852
5853 if (value == FAIL)
5854 {
5855 /* Can't be done. Perhaps the code reads something like
5856 "add Rd, Rn, #-n", where "sub Rd, Rn, #n" would be OK. */
5857 if ((value = negate_data_op (&inst.instruction,
5858 inst.reloc.exp.X_add_number))
5859 == FAIL)
5860 {
5861 inst.error = _("invalid constant");
5862 return FAIL;
5863 }
5864 }
5865
5866 inst.instruction |= value;
5867 }
5868
5869 inst.instruction |= INST_IMMEDIATE;
5870 return SUCCESS;
5871 }
5872
5873 (*str)++;
5874 inst.error = _("register or shift expression expected");
5875 return FAIL;
5876 }
5877 }
5878
5879 static int
5880 fp_op2 (char ** str)
5881 {
5882 skip_whitespace (* str);
5883
5884 if (fp_reg_required_here (str, 0) != FAIL)
5885 return SUCCESS;
5886 else
5887 {
5888 /* Immediate expression. */
5889 if (*((*str)++) == '#')
5890 {
5891 int i;
5892
5893 inst.error = NULL;
5894
5895 skip_whitespace (* str);
5896
5897 /* First try and match exact strings, this is to guarantee
5898 that some formats will work even for cross assembly. */
5899
5900 for (i = 0; fp_const[i]; i++)
5901 {
5902 if (strncmp (*str, fp_const[i], strlen (fp_const[i])) == 0)
5903 {
5904 char *start = *str;
5905
5906 *str += strlen (fp_const[i]);
5907 if (is_end_of_line[(unsigned char) **str])
5908 {
5909 inst.instruction |= i + 8;
5910 return SUCCESS;
5911 }
5912 *str = start;
5913 }
5914 }
5915
5916 /* Just because we didn't get a match doesn't mean that the
5917 constant isn't valid, just that it is in a format that we
5918 don't automatically recognize. Try parsing it with
5919 the standard expression routines. */
5920 if ((i = my_get_float_expression (str)) >= 0)
5921 {
5922 inst.instruction |= i + 8;
5923 return SUCCESS;
5924 }
5925
5926 inst.error = _("invalid floating point immediate expression");
5927 return FAIL;
5928 }
5929 inst.error =
5930 _("floating point register or immediate expression expected");
5931 return FAIL;
5932 }
5933 }
5934
5935 static void
5936 do_arit (char * str)
5937 {
5938 skip_whitespace (str);
5939
5940 if (reg_required_here (&str, 12) == FAIL
5941 || skip_past_comma (&str) == FAIL
5942 || reg_required_here (&str, 16) == FAIL
5943 || skip_past_comma (&str) == FAIL
5944 || data_op2 (&str) == FAIL)
5945 {
5946 if (!inst.error)
5947 inst.error = BAD_ARGS;
5948 return;
5949 }
5950
5951 end_of_line (str);
5952 }
5953
5954 static void
5955 do_adr (char * str)
5956 {
5957 /* This is a pseudo-op of the form "adr rd, label" to be converted
5958 into a relative address of the form "add rd, pc, #label-.-8". */
5959 skip_whitespace (str);
5960
5961 if (reg_required_here (&str, 12) == FAIL
5962 || skip_past_comma (&str) == FAIL
5963 || my_get_expression (&inst.reloc.exp, &str))
5964 {
5965 if (!inst.error)
5966 inst.error = BAD_ARGS;
5967 return;
5968 }
5969
5970 /* Frag hacking will turn this into a sub instruction if the offset turns
5971 out to be negative. */
5972 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
5973 #ifndef TE_WINCE
5974 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust. */
5975 #endif
5976 inst.reloc.pc_rel = 1;
5977
5978 end_of_line (str);
5979 }
5980
5981 static void
5982 do_adrl (char * str)
5983 {
5984 /* This is a pseudo-op of the form "adrl rd, label" to be converted
5985 into a relative address of the form:
5986 add rd, pc, #low(label-.-8)"
5987 add rd, rd, #high(label-.-8)" */
5988
5989 skip_whitespace (str);
5990
5991 if (reg_required_here (&str, 12) == FAIL
5992 || skip_past_comma (&str) == FAIL
5993 || my_get_expression (&inst.reloc.exp, &str))
5994 {
5995 if (!inst.error)
5996 inst.error = BAD_ARGS;
5997
5998 return;
5999 }
6000
6001 end_of_line (str);
6002 /* Frag hacking will turn this into a sub instruction if the offset turns
6003 out to be negative. */
6004 inst.reloc.type = BFD_RELOC_ARM_ADRL_IMMEDIATE;
6005 #ifndef TE_WINCE
6006 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust */
6007 #endif
6008 inst.reloc.pc_rel = 1;
6009 inst.size = INSN_SIZE * 2;
6010 }
6011
6012 static void
6013 do_cmp (char * str)
6014 {
6015 skip_whitespace (str);
6016
6017 if (reg_required_here (&str, 16) == FAIL)
6018 {
6019 if (!inst.error)
6020 inst.error = BAD_ARGS;
6021 return;
6022 }
6023
6024 if (skip_past_comma (&str) == FAIL
6025 || data_op2 (&str) == FAIL)
6026 {
6027 if (!inst.error)
6028 inst.error = BAD_ARGS;
6029 return;
6030 }
6031
6032 end_of_line (str);
6033 }
6034
6035 static void
6036 do_mov (char * str)
6037 {
6038 skip_whitespace (str);
6039
6040 if (reg_required_here (&str, 12) == 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 }
6057
6058 static void
6059 do_ldst (char * str)
6060 {
6061 int pre_inc = 0;
6062 int conflict_reg;
6063 int value;
6064
6065 skip_whitespace (str);
6066
6067 if ((conflict_reg = reg_required_here (&str, 12)) == FAIL)
6068 {
6069 if (!inst.error)
6070 inst.error = BAD_ARGS;
6071 return;
6072 }
6073
6074 if (skip_past_comma (&str) == FAIL)
6075 {
6076 inst.error = _("address expected");
6077 return;
6078 }
6079
6080 if (*str == '[')
6081 {
6082 int reg;
6083
6084 str++;
6085
6086 skip_whitespace (str);
6087
6088 if ((reg = reg_required_here (&str, 16)) == FAIL)
6089 return;
6090
6091 /* Conflicts can occur on stores as well as loads. */
6092 conflict_reg = (conflict_reg == reg);
6093
6094 skip_whitespace (str);
6095
6096 if (*str == ']')
6097 {
6098 str ++;
6099
6100 if (skip_past_comma (&str) == SUCCESS)
6101 {
6102 /* [Rn],... (post inc) */
6103 if (ldst_extend (&str) == FAIL)
6104 return;
6105 if (conflict_reg)
6106 as_warn (_("%s register same as write-back base"),
6107 ((inst.instruction & LOAD_BIT)
6108 ? _("destination") : _("source")));
6109 }
6110 else
6111 {
6112 /* [Rn] */
6113 skip_whitespace (str);
6114
6115 if (*str == '!')
6116 {
6117 if (conflict_reg)
6118 as_warn (_("%s register same as write-back base"),
6119 ((inst.instruction & LOAD_BIT)
6120 ? _("destination") : _("source")));
6121 str++;
6122 inst.instruction |= WRITE_BACK;
6123 }
6124
6125 inst.instruction |= INDEX_UP;
6126 pre_inc = 1;
6127 }
6128 }
6129 else
6130 {
6131 /* [Rn,...] */
6132 if (skip_past_comma (&str) == FAIL)
6133 {
6134 inst.error = _("pre-indexed expression expected");
6135 return;
6136 }
6137
6138 pre_inc = 1;
6139 if (ldst_extend (&str) == FAIL)
6140 return;
6141
6142 skip_whitespace (str);
6143
6144 if (*str++ != ']')
6145 {
6146 inst.error = _("missing ]");
6147 return;
6148 }
6149
6150 skip_whitespace (str);
6151
6152 if (*str == '!')
6153 {
6154 if (conflict_reg)
6155 as_warn (_("%s register same as write-back base"),
6156 ((inst.instruction & LOAD_BIT)
6157 ? _("destination") : _("source")));
6158 str++;
6159 inst.instruction |= WRITE_BACK;
6160 }
6161 }
6162 }
6163 else if (*str == '=')
6164 {
6165 if ((inst.instruction & LOAD_BIT) == 0)
6166 {
6167 inst.error = _("invalid pseudo operation");
6168 return;
6169 }
6170
6171 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
6172 str++;
6173
6174 skip_whitespace (str);
6175
6176 if (my_get_expression (&inst.reloc.exp, &str))
6177 return;
6178
6179 if (inst.reloc.exp.X_op != O_constant
6180 && inst.reloc.exp.X_op != O_symbol)
6181 {
6182 inst.error = _("constant expression expected");
6183 return;
6184 }
6185
6186 if (inst.reloc.exp.X_op == O_constant)
6187 {
6188 value = validate_immediate (inst.reloc.exp.X_add_number);
6189
6190 if (value != FAIL)
6191 {
6192 /* This can be done with a mov instruction. */
6193 inst.instruction &= LITERAL_MASK;
6194 inst.instruction |= (INST_IMMEDIATE
6195 | (OPCODE_MOV << DATA_OP_SHIFT));
6196 inst.instruction |= value & 0xfff;
6197 end_of_line (str);
6198 return;
6199 }
6200
6201 value = validate_immediate (~inst.reloc.exp.X_add_number);
6202
6203 if (value != FAIL)
6204 {
6205 /* This can be done with a mvn instruction. */
6206 inst.instruction &= LITERAL_MASK;
6207 inst.instruction |= (INST_IMMEDIATE
6208 | (OPCODE_MVN << DATA_OP_SHIFT));
6209 inst.instruction |= value & 0xfff;
6210 end_of_line (str);
6211 return;
6212 }
6213 }
6214
6215 /* Insert into literal pool. */
6216 if (add_to_lit_pool () == FAIL)
6217 {
6218 if (!inst.error)
6219 inst.error = _("literal pool insertion failed");
6220 return;
6221 }
6222
6223 /* Change the instruction exp to point to the pool. */
6224 inst.reloc.type = BFD_RELOC_ARM_LITERAL;
6225 inst.reloc.pc_rel = 1;
6226 inst.instruction |= (REG_PC << 16);
6227 pre_inc = 1;
6228 }
6229 else
6230 {
6231 if (my_get_expression (&inst.reloc.exp, &str))
6232 return;
6233
6234 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
6235 #ifndef TE_WINCE
6236 /* PC rel adjust. */
6237 inst.reloc.exp.X_add_number -= 8;
6238 #endif
6239 inst.reloc.pc_rel = 1;
6240 inst.instruction |= (REG_PC << 16);
6241 pre_inc = 1;
6242 }
6243
6244 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
6245 end_of_line (str);
6246 }
6247
6248 static void
6249 do_ldstt (char * str)
6250 {
6251 int conflict_reg;
6252
6253 skip_whitespace (str);
6254
6255 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
6256 {
6257 if (!inst.error)
6258 inst.error = BAD_ARGS;
6259 return;
6260 }
6261
6262 if (skip_past_comma (& str) == FAIL)
6263 {
6264 inst.error = _("address expected");
6265 return;
6266 }
6267
6268 if (*str == '[')
6269 {
6270 int reg;
6271
6272 str++;
6273
6274 skip_whitespace (str);
6275
6276 if ((reg = reg_required_here (&str, 16)) == FAIL)
6277 return;
6278
6279 /* ldrt/strt always use post-indexed addressing, so if the base is
6280 the same as Rd, we warn. */
6281 if (conflict_reg == reg)
6282 as_warn (_("%s register same as write-back base"),
6283 ((inst.instruction & LOAD_BIT)
6284 ? _("destination") : _("source")));
6285
6286 skip_whitespace (str);
6287
6288 if (*str == ']')
6289 {
6290 str ++;
6291
6292 if (skip_past_comma (&str) == SUCCESS)
6293 {
6294 /* [Rn],... (post inc) */
6295 if (ldst_extend (&str) == FAIL)
6296 return;
6297 }
6298 else
6299 {
6300 /* [Rn] */
6301 skip_whitespace (str);
6302
6303 /* Skip a write-back '!'. */
6304 if (*str == '!')
6305 str++;
6306
6307 inst.instruction |= INDEX_UP;
6308 }
6309 }
6310 else
6311 {
6312 inst.error = _("post-indexed expression expected");
6313 return;
6314 }
6315 }
6316 else
6317 {
6318 inst.error = _("post-indexed expression expected");
6319 return;
6320 }
6321
6322 end_of_line (str);
6323 }
6324
6325 /* Halfword and signed-byte load/store operations. */
6326
6327 static void
6328 do_ldstv4 (char * str)
6329 {
6330 int pre_inc = 0;
6331 int conflict_reg;
6332 int value;
6333
6334 skip_whitespace (str);
6335
6336 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
6337 {
6338 if (!inst.error)
6339 inst.error = BAD_ARGS;
6340 return;
6341 }
6342
6343 if (skip_past_comma (& str) == FAIL)
6344 {
6345 inst.error = _("address expected");
6346 return;
6347 }
6348
6349 if (*str == '[')
6350 {
6351 int reg;
6352
6353 str++;
6354
6355 skip_whitespace (str);
6356
6357 if ((reg = reg_required_here (&str, 16)) == FAIL)
6358 return;
6359
6360 /* Conflicts can occur on stores as well as loads. */
6361 conflict_reg = (conflict_reg == reg);
6362
6363 skip_whitespace (str);
6364
6365 if (*str == ']')
6366 {
6367 str ++;
6368
6369 if (skip_past_comma (&str) == SUCCESS)
6370 {
6371 /* [Rn],... (post inc) */
6372 if (ldst_extend_v4 (&str) == FAIL)
6373 return;
6374 if (conflict_reg)
6375 as_warn (_("%s register same as write-back base"),
6376 ((inst.instruction & LOAD_BIT)
6377 ? _("destination") : _("source")));
6378 }
6379 else
6380 {
6381 /* [Rn] */
6382 inst.instruction |= HWOFFSET_IMM;
6383
6384 skip_whitespace (str);
6385
6386 if (*str == '!')
6387 {
6388 if (conflict_reg)
6389 as_warn (_("%s register same as write-back base"),
6390 ((inst.instruction & LOAD_BIT)
6391 ? _("destination") : _("source")));
6392 str++;
6393 inst.instruction |= WRITE_BACK;
6394 }
6395
6396 inst.instruction |= INDEX_UP;
6397 pre_inc = 1;
6398 }
6399 }
6400 else
6401 {
6402 /* [Rn,...] */
6403 if (skip_past_comma (&str) == FAIL)
6404 {
6405 inst.error = _("pre-indexed expression expected");
6406 return;
6407 }
6408
6409 pre_inc = 1;
6410 if (ldst_extend_v4 (&str) == FAIL)
6411 return;
6412
6413 skip_whitespace (str);
6414
6415 if (*str++ != ']')
6416 {
6417 inst.error = _("missing ]");
6418 return;
6419 }
6420
6421 skip_whitespace (str);
6422
6423 if (*str == '!')
6424 {
6425 if (conflict_reg)
6426 as_warn (_("%s register same as write-back base"),
6427 ((inst.instruction & LOAD_BIT)
6428 ? _("destination") : _("source")));
6429 str++;
6430 inst.instruction |= WRITE_BACK;
6431 }
6432 }
6433 }
6434 else if (*str == '=')
6435 {
6436 if ((inst.instruction & LOAD_BIT) == 0)
6437 {
6438 inst.error = _("invalid pseudo operation");
6439 return;
6440 }
6441
6442 /* XXX Does this work correctly for half-word/byte ops? */
6443 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
6444 str++;
6445
6446 skip_whitespace (str);
6447
6448 if (my_get_expression (&inst.reloc.exp, &str))
6449 return;
6450
6451 if (inst.reloc.exp.X_op != O_constant
6452 && inst.reloc.exp.X_op != O_symbol)
6453 {
6454 inst.error = _("constant expression expected");
6455 return;
6456 }
6457
6458 if (inst.reloc.exp.X_op == O_constant)
6459 {
6460 value = validate_immediate (inst.reloc.exp.X_add_number);
6461
6462 if (value != FAIL)
6463 {
6464 /* This can be done with a mov instruction. */
6465 inst.instruction &= LITERAL_MASK;
6466 inst.instruction |= INST_IMMEDIATE | (OPCODE_MOV << DATA_OP_SHIFT);
6467 inst.instruction |= value & 0xfff;
6468 end_of_line (str);
6469 return;
6470 }
6471
6472 value = validate_immediate (~ inst.reloc.exp.X_add_number);
6473
6474 if (value != FAIL)
6475 {
6476 /* This can be done with a mvn instruction. */
6477 inst.instruction &= LITERAL_MASK;
6478 inst.instruction |= INST_IMMEDIATE | (OPCODE_MVN << DATA_OP_SHIFT);
6479 inst.instruction |= value & 0xfff;
6480 end_of_line (str);
6481 return;
6482 }
6483 }
6484
6485 /* Insert into literal pool. */
6486 if (add_to_lit_pool () == FAIL)
6487 {
6488 if (!inst.error)
6489 inst.error = _("literal pool insertion failed");
6490 return;
6491 }
6492
6493 /* Change the instruction exp to point to the pool. */
6494 inst.instruction |= HWOFFSET_IMM;
6495 inst.reloc.type = BFD_RELOC_ARM_HWLITERAL;
6496 inst.reloc.pc_rel = 1;
6497 inst.instruction |= (REG_PC << 16);
6498 pre_inc = 1;
6499 }
6500 else
6501 {
6502 if (my_get_expression (&inst.reloc.exp, &str))
6503 return;
6504
6505 inst.instruction |= HWOFFSET_IMM;
6506 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
6507 #ifndef TE_WINCE
6508 /* PC rel adjust. */
6509 inst.reloc.exp.X_add_number -= 8;
6510 #endif
6511 inst.reloc.pc_rel = 1;
6512 inst.instruction |= (REG_PC << 16);
6513 pre_inc = 1;
6514 }
6515
6516 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
6517 end_of_line (str);
6518 }
6519
6520 static long
6521 reg_list (char ** strp)
6522 {
6523 char * str = * strp;
6524 long range = 0;
6525 int another_range;
6526
6527 /* We come back here if we get ranges concatenated by '+' or '|'. */
6528 do
6529 {
6530 another_range = 0;
6531
6532 if (*str == '{')
6533 {
6534 int in_range = 0;
6535 int cur_reg = -1;
6536
6537 str++;
6538 do
6539 {
6540 int reg;
6541
6542 skip_whitespace (str);
6543
6544 if ((reg = reg_required_here (& str, -1)) == FAIL)
6545 return FAIL;
6546
6547 if (in_range)
6548 {
6549 int i;
6550
6551 if (reg <= cur_reg)
6552 {
6553 inst.error = _("bad range in register list");
6554 return FAIL;
6555 }
6556
6557 for (i = cur_reg + 1; i < reg; i++)
6558 {
6559 if (range & (1 << i))
6560 as_tsktsk
6561 (_("Warning: duplicated register (r%d) in register list"),
6562 i);
6563 else
6564 range |= 1 << i;
6565 }
6566 in_range = 0;
6567 }
6568
6569 if (range & (1 << reg))
6570 as_tsktsk (_("Warning: duplicated register (r%d) in register list"),
6571 reg);
6572 else if (reg <= cur_reg)
6573 as_tsktsk (_("Warning: register range not in ascending order"));
6574
6575 range |= 1 << reg;
6576 cur_reg = reg;
6577 }
6578 while (skip_past_comma (&str) != FAIL
6579 || (in_range = 1, *str++ == '-'));
6580 str--;
6581 skip_whitespace (str);
6582
6583 if (*str++ != '}')
6584 {
6585 inst.error = _("missing `}'");
6586 return FAIL;
6587 }
6588 }
6589 else
6590 {
6591 expressionS expr;
6592
6593 if (my_get_expression (&expr, &str))
6594 return FAIL;
6595
6596 if (expr.X_op == O_constant)
6597 {
6598 if (expr.X_add_number
6599 != (expr.X_add_number & 0x0000ffff))
6600 {
6601 inst.error = _("invalid register mask");
6602 return FAIL;
6603 }
6604
6605 if ((range & expr.X_add_number) != 0)
6606 {
6607 int regno = range & expr.X_add_number;
6608
6609 regno &= -regno;
6610 regno = (1 << regno) - 1;
6611 as_tsktsk
6612 (_("Warning: duplicated register (r%d) in register list"),
6613 regno);
6614 }
6615
6616 range |= expr.X_add_number;
6617 }
6618 else
6619 {
6620 if (inst.reloc.type != 0)
6621 {
6622 inst.error = _("expression too complex");
6623 return FAIL;
6624 }
6625
6626 memcpy (&inst.reloc.exp, &expr, sizeof (expressionS));
6627 inst.reloc.type = BFD_RELOC_ARM_MULTI;
6628 inst.reloc.pc_rel = 0;
6629 }
6630 }
6631
6632 skip_whitespace (str);
6633
6634 if (*str == '|' || *str == '+')
6635 {
6636 str++;
6637 another_range = 1;
6638 }
6639 }
6640 while (another_range);
6641
6642 *strp = str;
6643 return range;
6644 }
6645
6646 static void
6647 do_ldmstm (char * str)
6648 {
6649 int base_reg;
6650 long range;
6651
6652 skip_whitespace (str);
6653
6654 if ((base_reg = reg_required_here (&str, 16)) == FAIL)
6655 return;
6656
6657 if (base_reg == REG_PC)
6658 {
6659 inst.error = _("r15 not allowed as base register");
6660 return;
6661 }
6662
6663 skip_whitespace (str);
6664
6665 if (*str == '!')
6666 {
6667 inst.instruction |= WRITE_BACK;
6668 str++;
6669 }
6670
6671 if (skip_past_comma (&str) == FAIL
6672 || (range = reg_list (&str)) == FAIL)
6673 {
6674 if (! inst.error)
6675 inst.error = BAD_ARGS;
6676 return;
6677 }
6678
6679 if (*str == '^')
6680 {
6681 str++;
6682 inst.instruction |= LDM_TYPE_2_OR_3;
6683 }
6684
6685 if (inst.instruction & WRITE_BACK)
6686 {
6687 /* Check for unpredictable uses of writeback. */
6688 if (inst.instruction & LOAD_BIT)
6689 {
6690 /* Not allowed in LDM type 2. */
6691 if ((inst.instruction & LDM_TYPE_2_OR_3)
6692 && ((range & (1 << REG_PC)) == 0))
6693 as_warn (_("writeback of base register is UNPREDICTABLE"));
6694 /* Only allowed if base reg not in list for other types. */
6695 else if (range & (1 << base_reg))
6696 as_warn (_("writeback of base register when in register list is UNPREDICTABLE"));
6697 }
6698 else /* STM. */
6699 {
6700 /* Not allowed for type 2. */
6701 if (inst.instruction & LDM_TYPE_2_OR_3)
6702 as_warn (_("writeback of base register is UNPREDICTABLE"));
6703 /* Only allowed if base reg not in list, or first in list. */
6704 else if ((range & (1 << base_reg))
6705 && (range & ((1 << base_reg) - 1)))
6706 as_warn (_("if writeback register is in list, it must be the lowest reg in the list"));
6707 }
6708 }
6709
6710 inst.instruction |= range;
6711 end_of_line (str);
6712 }
6713
6714 static void
6715 do_smi (char * str)
6716 {
6717 skip_whitespace (str);
6718
6719 /* Allow optional leading '#'. */
6720 if (is_immediate_prefix (*str))
6721 str++;
6722
6723 if (my_get_expression (& inst.reloc.exp, & str))
6724 return;
6725
6726 inst.reloc.type = BFD_RELOC_ARM_SMI;
6727 inst.reloc.pc_rel = 0;
6728 end_of_line (str);
6729 }
6730
6731 static void
6732 do_swi (char * str)
6733 {
6734 skip_whitespace (str);
6735
6736 /* Allow optional leading '#'. */
6737 if (is_immediate_prefix (*str))
6738 str++;
6739
6740 if (my_get_expression (& inst.reloc.exp, & str))
6741 return;
6742
6743 inst.reloc.type = BFD_RELOC_ARM_SWI;
6744 inst.reloc.pc_rel = 0;
6745 end_of_line (str);
6746 }
6747
6748 static void
6749 do_swap (char * str)
6750 {
6751 int reg;
6752
6753 skip_whitespace (str);
6754
6755 if ((reg = reg_required_here (&str, 12)) == FAIL)
6756 return;
6757
6758 if (reg == REG_PC)
6759 {
6760 inst.error = _("r15 not allowed in swap");
6761 return;
6762 }
6763
6764 if (skip_past_comma (&str) == FAIL
6765 || (reg = reg_required_here (&str, 0)) == FAIL)
6766 {
6767 if (!inst.error)
6768 inst.error = BAD_ARGS;
6769 return;
6770 }
6771
6772 if (reg == REG_PC)
6773 {
6774 inst.error = _("r15 not allowed in swap");
6775 return;
6776 }
6777
6778 if (skip_past_comma (&str) == FAIL
6779 || *str++ != '[')
6780 {
6781 inst.error = BAD_ARGS;
6782 return;
6783 }
6784
6785 skip_whitespace (str);
6786
6787 if ((reg = reg_required_here (&str, 16)) == FAIL)
6788 return;
6789
6790 if (reg == REG_PC)
6791 {
6792 inst.error = BAD_PC;
6793 return;
6794 }
6795
6796 skip_whitespace (str);
6797
6798 if (*str++ != ']')
6799 {
6800 inst.error = _("missing ]");
6801 return;
6802 }
6803
6804 end_of_line (str);
6805 }
6806
6807 static void
6808 do_branch (char * str)
6809 {
6810 if (my_get_expression (&inst.reloc.exp, &str))
6811 return;
6812
6813 #ifdef OBJ_ELF
6814 {
6815 char * save_in;
6816
6817 /* ScottB: February 5, 1998 - Check to see of PLT32 reloc
6818 required for the instruction. */
6819
6820 /* arm_parse_reloc () works on input_line_pointer.
6821 We actually want to parse the operands to the branch instruction
6822 passed in 'str'. Save the input pointer and restore it later. */
6823 save_in = input_line_pointer;
6824 input_line_pointer = str;
6825 if (inst.reloc.exp.X_op == O_symbol
6826 && *str == '('
6827 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
6828 {
6829 inst.reloc.type = BFD_RELOC_ARM_PLT32;
6830 inst.reloc.pc_rel = 0;
6831 /* Modify str to point to after parsed operands, otherwise
6832 end_of_line() will complain about the (PLT) left in str. */
6833 str = input_line_pointer;
6834 }
6835 else
6836 {
6837 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
6838 inst.reloc.pc_rel = 1;
6839 }
6840 input_line_pointer = save_in;
6841 }
6842 #else
6843 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
6844 inst.reloc.pc_rel = 1;
6845 #endif /* OBJ_ELF */
6846
6847 end_of_line (str);
6848 }
6849
6850 static void
6851 do_cdp (char * str)
6852 {
6853 /* Co-processor data operation.
6854 Format: CDP{cond} CP#,<expr>,CRd,CRn,CRm{,<expr>} */
6855 skip_whitespace (str);
6856
6857 if (co_proc_number (&str) == FAIL)
6858 {
6859 if (!inst.error)
6860 inst.error = BAD_ARGS;
6861 return;
6862 }
6863
6864 if (skip_past_comma (&str) == FAIL
6865 || cp_opc_expr (&str, 20,4) == FAIL)
6866 {
6867 if (!inst.error)
6868 inst.error = BAD_ARGS;
6869 return;
6870 }
6871
6872 if (skip_past_comma (&str) == FAIL
6873 || cp_reg_required_here (&str, 12) == FAIL)
6874 {
6875 if (!inst.error)
6876 inst.error = BAD_ARGS;
6877 return;
6878 }
6879
6880 if (skip_past_comma (&str) == FAIL
6881 || cp_reg_required_here (&str, 16) == FAIL)
6882 {
6883 if (!inst.error)
6884 inst.error = BAD_ARGS;
6885 return;
6886 }
6887
6888 if (skip_past_comma (&str) == FAIL
6889 || cp_reg_required_here (&str, 0) == FAIL)
6890 {
6891 if (!inst.error)
6892 inst.error = BAD_ARGS;
6893 return;
6894 }
6895
6896 if (skip_past_comma (&str) == SUCCESS)
6897 {
6898 if (cp_opc_expr (&str, 5, 3) == FAIL)
6899 {
6900 if (!inst.error)
6901 inst.error = BAD_ARGS;
6902 return;
6903 }
6904 }
6905
6906 end_of_line (str);
6907 }
6908
6909 static void
6910 do_lstc (char * str)
6911 {
6912 /* Co-processor register load/store.
6913 Format: <LDC|STC{cond}[L] CP#,CRd,<address> */
6914
6915 skip_whitespace (str);
6916
6917 if (co_proc_number (&str) == FAIL)
6918 {
6919 if (!inst.error)
6920 inst.error = BAD_ARGS;
6921 return;
6922 }
6923
6924 if (skip_past_comma (&str) == FAIL
6925 || cp_reg_required_here (&str, 12) == FAIL)
6926 {
6927 if (!inst.error)
6928 inst.error = BAD_ARGS;
6929 return;
6930 }
6931
6932 if (skip_past_comma (&str) == FAIL
6933 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
6934 {
6935 if (! inst.error)
6936 inst.error = BAD_ARGS;
6937 return;
6938 }
6939
6940 end_of_line (str);
6941 }
6942
6943 static void
6944 do_co_reg (char * str)
6945 {
6946 /* Co-processor register transfer.
6947 Format: <MCR|MRC>{cond} CP#,<expr1>,Rd,CRn,CRm{,<expr2>} */
6948
6949 skip_whitespace (str);
6950
6951 if (co_proc_number (&str) == FAIL)
6952 {
6953 if (!inst.error)
6954 inst.error = BAD_ARGS;
6955 return;
6956 }
6957
6958 if (skip_past_comma (&str) == FAIL
6959 || cp_opc_expr (&str, 21, 3) == FAIL)
6960 {
6961 if (!inst.error)
6962 inst.error = BAD_ARGS;
6963 return;
6964 }
6965
6966 if (skip_past_comma (&str) == FAIL
6967 || reg_required_here (&str, 12) == FAIL)
6968 {
6969 if (!inst.error)
6970 inst.error = BAD_ARGS;
6971 return;
6972 }
6973
6974 if (skip_past_comma (&str) == FAIL
6975 || cp_reg_required_here (&str, 16) == FAIL)
6976 {
6977 if (!inst.error)
6978 inst.error = BAD_ARGS;
6979 return;
6980 }
6981
6982 if (skip_past_comma (&str) == FAIL
6983 || cp_reg_required_here (&str, 0) == FAIL)
6984 {
6985 if (!inst.error)
6986 inst.error = BAD_ARGS;
6987 return;
6988 }
6989
6990 if (skip_past_comma (&str) == SUCCESS)
6991 {
6992 if (cp_opc_expr (&str, 5, 3) == FAIL)
6993 {
6994 if (!inst.error)
6995 inst.error = BAD_ARGS;
6996 return;
6997 }
6998 }
6999
7000 end_of_line (str);
7001 }
7002
7003 static void
7004 do_fpa_ctrl (char * str)
7005 {
7006 /* FP control registers.
7007 Format: <WFS|RFS|WFC|RFC>{cond} Rn */
7008
7009 skip_whitespace (str);
7010
7011 if (reg_required_here (&str, 12) == FAIL)
7012 {
7013 if (!inst.error)
7014 inst.error = BAD_ARGS;
7015 return;
7016 }
7017
7018 end_of_line (str);
7019 }
7020
7021 static void
7022 do_fpa_ldst (char * str)
7023 {
7024 skip_whitespace (str);
7025
7026 if (fp_reg_required_here (&str, 12) == FAIL)
7027 {
7028 if (!inst.error)
7029 inst.error = BAD_ARGS;
7030 return;
7031 }
7032
7033 if (skip_past_comma (&str) == FAIL
7034 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
7035 {
7036 if (!inst.error)
7037 inst.error = BAD_ARGS;
7038 return;
7039 }
7040
7041 end_of_line (str);
7042 }
7043
7044 static void
7045 do_fpa_ldmstm (char * str)
7046 {
7047 int num_regs;
7048
7049 skip_whitespace (str);
7050
7051 if (fp_reg_required_here (&str, 12) == FAIL)
7052 {
7053 if (! inst.error)
7054 inst.error = BAD_ARGS;
7055 return;
7056 }
7057
7058 /* Get Number of registers to transfer. */
7059 if (skip_past_comma (&str) == FAIL
7060 || my_get_expression (&inst.reloc.exp, &str))
7061 {
7062 if (! inst.error)
7063 inst.error = _("constant expression expected");
7064 return;
7065 }
7066
7067 if (inst.reloc.exp.X_op != O_constant)
7068 {
7069 inst.error = _("constant value required for number of registers");
7070 return;
7071 }
7072
7073 num_regs = inst.reloc.exp.X_add_number;
7074
7075 if (num_regs < 1 || num_regs > 4)
7076 {
7077 inst.error = _("number of registers must be in the range [1:4]");
7078 return;
7079 }
7080
7081 switch (num_regs)
7082 {
7083 case 1:
7084 inst.instruction |= CP_T_X;
7085 break;
7086 case 2:
7087 inst.instruction |= CP_T_Y;
7088 break;
7089 case 3:
7090 inst.instruction |= CP_T_Y | CP_T_X;
7091 break;
7092 case 4:
7093 break;
7094 default:
7095 abort ();
7096 }
7097
7098 if (inst.instruction & (CP_T_Pre | CP_T_UD)) /* ea/fd format. */
7099 {
7100 int reg;
7101 int write_back;
7102 int offset;
7103
7104 /* The instruction specified "ea" or "fd", so we can only accept
7105 [Rn]{!}. The instruction does not really support stacking or
7106 unstacking, so we have to emulate these by setting appropriate
7107 bits and offsets. */
7108 if (skip_past_comma (&str) == FAIL
7109 || *str != '[')
7110 {
7111 if (! inst.error)
7112 inst.error = BAD_ARGS;
7113 return;
7114 }
7115
7116 str++;
7117 skip_whitespace (str);
7118
7119 if ((reg = reg_required_here (&str, 16)) == FAIL)
7120 return;
7121
7122 skip_whitespace (str);
7123
7124 if (*str != ']')
7125 {
7126 inst.error = BAD_ARGS;
7127 return;
7128 }
7129
7130 str++;
7131 if (*str == '!')
7132 {
7133 write_back = 1;
7134 str++;
7135 if (reg == REG_PC)
7136 {
7137 inst.error =
7138 _("r15 not allowed as base register with write-back");
7139 return;
7140 }
7141 }
7142 else
7143 write_back = 0;
7144
7145 if (inst.instruction & CP_T_Pre)
7146 {
7147 /* Pre-decrement. */
7148 offset = 3 * num_regs;
7149 if (write_back)
7150 inst.instruction |= CP_T_WB;
7151 }
7152 else
7153 {
7154 /* Post-increment. */
7155 if (write_back)
7156 {
7157 inst.instruction |= CP_T_WB;
7158 offset = 3 * num_regs;
7159 }
7160 else
7161 {
7162 /* No write-back, so convert this into a standard pre-increment
7163 instruction -- aesthetically more pleasing. */
7164 inst.instruction |= CP_T_Pre | CP_T_UD;
7165 offset = 0;
7166 }
7167 }
7168
7169 inst.instruction |= offset;
7170 }
7171 else if (skip_past_comma (&str) == FAIL
7172 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
7173 {
7174 if (! inst.error)
7175 inst.error = BAD_ARGS;
7176 return;
7177 }
7178
7179 end_of_line (str);
7180 }
7181
7182 static void
7183 do_fpa_dyadic (char * str)
7184 {
7185 skip_whitespace (str);
7186
7187 if (fp_reg_required_here (&str, 12) == FAIL)
7188 {
7189 if (! inst.error)
7190 inst.error = BAD_ARGS;
7191 return;
7192 }
7193
7194 if (skip_past_comma (&str) == FAIL
7195 || fp_reg_required_here (&str, 16) == FAIL)
7196 {
7197 if (! inst.error)
7198 inst.error = BAD_ARGS;
7199 return;
7200 }
7201
7202 if (skip_past_comma (&str) == FAIL
7203 || fp_op2 (&str) == FAIL)
7204 {
7205 if (! inst.error)
7206 inst.error = BAD_ARGS;
7207 return;
7208 }
7209
7210 end_of_line (str);
7211 }
7212
7213 static void
7214 do_fpa_monadic (char * str)
7215 {
7216 skip_whitespace (str);
7217
7218 if (fp_reg_required_here (&str, 12) == FAIL)
7219 {
7220 if (! inst.error)
7221 inst.error = BAD_ARGS;
7222 return;
7223 }
7224
7225 if (skip_past_comma (&str) == FAIL
7226 || fp_op2 (&str) == FAIL)
7227 {
7228 if (! inst.error)
7229 inst.error = BAD_ARGS;
7230 return;
7231 }
7232
7233 end_of_line (str);
7234 }
7235
7236 static void
7237 do_fpa_cmp (char * str)
7238 {
7239 skip_whitespace (str);
7240
7241 if (fp_reg_required_here (&str, 16) == FAIL)
7242 {
7243 if (! inst.error)
7244 inst.error = BAD_ARGS;
7245 return;
7246 }
7247
7248 if (skip_past_comma (&str) == FAIL
7249 || fp_op2 (&str) == FAIL)
7250 {
7251 if (! inst.error)
7252 inst.error = BAD_ARGS;
7253 return;
7254 }
7255
7256 end_of_line (str);
7257 }
7258
7259 static void
7260 do_fpa_from_reg (char * str)
7261 {
7262 skip_whitespace (str);
7263
7264 if (fp_reg_required_here (&str, 16) == FAIL)
7265 {
7266 if (! inst.error)
7267 inst.error = BAD_ARGS;
7268 return;
7269 }
7270
7271 if (skip_past_comma (&str) == FAIL
7272 || reg_required_here (&str, 12) == FAIL)
7273 {
7274 if (! inst.error)
7275 inst.error = BAD_ARGS;
7276 return;
7277 }
7278
7279 end_of_line (str);
7280 }
7281
7282 static void
7283 do_fpa_to_reg (char * str)
7284 {
7285 skip_whitespace (str);
7286
7287 if (reg_required_here (&str, 12) == FAIL)
7288 return;
7289
7290 if (skip_past_comma (&str) == FAIL
7291 || fp_reg_required_here (&str, 0) == FAIL)
7292 {
7293 if (! inst.error)
7294 inst.error = BAD_ARGS;
7295 return;
7296 }
7297
7298 end_of_line (str);
7299 }
7300
7301 /* Encode a VFP SP register number. */
7302
7303 static void
7304 vfp_sp_encode_reg (int reg, enum vfp_sp_reg_pos pos)
7305 {
7306 switch (pos)
7307 {
7308 case VFP_REG_Sd:
7309 inst.instruction |= ((reg >> 1) << 12) | ((reg & 1) << 22);
7310 break;
7311
7312 case VFP_REG_Sn:
7313 inst.instruction |= ((reg >> 1) << 16) | ((reg & 1) << 7);
7314 break;
7315
7316 case VFP_REG_Sm:
7317 inst.instruction |= ((reg >> 1) << 0) | ((reg & 1) << 5);
7318 break;
7319
7320 default:
7321 abort ();
7322 }
7323 }
7324
7325 static int
7326 vfp_sp_reg_required_here (char ** str,
7327 enum vfp_sp_reg_pos pos)
7328 {
7329 int reg;
7330 char * start = *str;
7331
7332 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_SN].htab)) != FAIL)
7333 {
7334 vfp_sp_encode_reg (reg, pos);
7335 return reg;
7336 }
7337
7338 /* In the few cases where we might be able to accept something else
7339 this error can be overridden. */
7340 inst.error = _(all_reg_maps[REG_TYPE_SN].expected);
7341
7342 /* Restore the start point. */
7343 *str = start;
7344 return FAIL;
7345 }
7346
7347 static int
7348 vfp_dp_reg_required_here (char ** str,
7349 enum vfp_dp_reg_pos pos)
7350 {
7351 int reg;
7352 char * start = *str;
7353
7354 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_DN].htab)) != FAIL)
7355 {
7356 switch (pos)
7357 {
7358 case VFP_REG_Dd:
7359 inst.instruction |= reg << 12;
7360 break;
7361
7362 case VFP_REG_Dn:
7363 inst.instruction |= reg << 16;
7364 break;
7365
7366 case VFP_REG_Dm:
7367 inst.instruction |= reg << 0;
7368 break;
7369
7370 default:
7371 abort ();
7372 }
7373 return reg;
7374 }
7375
7376 /* In the few cases where we might be able to accept something else
7377 this error can be overridden. */
7378 inst.error = _(all_reg_maps[REG_TYPE_DN].expected);
7379
7380 /* Restore the start point. */
7381 *str = start;
7382 return FAIL;
7383 }
7384
7385 static void
7386 do_vfp_sp_monadic (char * str)
7387 {
7388 skip_whitespace (str);
7389
7390 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
7391 return;
7392
7393 if (skip_past_comma (&str) == FAIL
7394 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
7395 {
7396 if (! inst.error)
7397 inst.error = BAD_ARGS;
7398 return;
7399 }
7400
7401 end_of_line (str);
7402 }
7403
7404 static void
7405 do_vfp_dp_monadic (char * str)
7406 {
7407 skip_whitespace (str);
7408
7409 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
7410 return;
7411
7412 if (skip_past_comma (&str) == FAIL
7413 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
7414 {
7415 if (! inst.error)
7416 inst.error = BAD_ARGS;
7417 return;
7418 }
7419
7420 end_of_line (str);
7421 }
7422
7423 static void
7424 do_vfp_sp_dyadic (char * str)
7425 {
7426 skip_whitespace (str);
7427
7428 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
7429 return;
7430
7431 if (skip_past_comma (&str) == FAIL
7432 || vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL
7433 || skip_past_comma (&str) == FAIL
7434 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
7435 {
7436 if (! inst.error)
7437 inst.error = BAD_ARGS;
7438 return;
7439 }
7440
7441 end_of_line (str);
7442 }
7443
7444 static void
7445 do_vfp_dp_dyadic (char * str)
7446 {
7447 skip_whitespace (str);
7448
7449 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
7450 return;
7451
7452 if (skip_past_comma (&str) == FAIL
7453 || vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL
7454 || skip_past_comma (&str) == FAIL
7455 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
7456 {
7457 if (! inst.error)
7458 inst.error = BAD_ARGS;
7459 return;
7460 }
7461
7462 end_of_line (str);
7463 }
7464
7465 static void
7466 do_vfp_reg_from_sp (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 || vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL)
7475 {
7476 if (! inst.error)
7477 inst.error = BAD_ARGS;
7478 return;
7479 }
7480
7481 end_of_line (str);
7482 }
7483
7484 /* Parse a VFP register list. If the string is invalid return FAIL.
7485 Otherwise return the number of registers, and set PBASE to the first
7486 register. Double precision registers are matched if DP is nonzero. */
7487
7488 static int
7489 vfp_parse_reg_list (char **str, int *pbase, int dp)
7490 {
7491 int base_reg;
7492 int new_base;
7493 int regtype;
7494 int max_regs;
7495 int count = 0;
7496 int warned = 0;
7497 unsigned long mask = 0;
7498 int i;
7499
7500 if (**str != '{')
7501 return FAIL;
7502
7503 (*str)++;
7504 skip_whitespace (*str);
7505
7506 if (dp)
7507 {
7508 regtype = REG_TYPE_DN;
7509 max_regs = 16;
7510 }
7511 else
7512 {
7513 regtype = REG_TYPE_SN;
7514 max_regs = 32;
7515 }
7516
7517 base_reg = max_regs;
7518
7519 do
7520 {
7521 new_base = arm_reg_parse (str, all_reg_maps[regtype].htab);
7522 if (new_base == FAIL)
7523 {
7524 inst.error = _(all_reg_maps[regtype].expected);
7525 return FAIL;
7526 }
7527
7528 if (new_base < base_reg)
7529 base_reg = new_base;
7530
7531 if (mask & (1 << new_base))
7532 {
7533 inst.error = _("invalid register list");
7534 return FAIL;
7535 }
7536
7537 if ((mask >> new_base) != 0 && ! warned)
7538 {
7539 as_tsktsk (_("register list not in ascending order"));
7540 warned = 1;
7541 }
7542
7543 mask |= 1 << new_base;
7544 count++;
7545
7546 skip_whitespace (*str);
7547
7548 if (**str == '-') /* We have the start of a range expression */
7549 {
7550 int high_range;
7551
7552 (*str)++;
7553
7554 if ((high_range
7555 = arm_reg_parse (str, all_reg_maps[regtype].htab))
7556 == FAIL)
7557 {
7558 inst.error = _(all_reg_maps[regtype].expected);
7559 return FAIL;
7560 }
7561
7562 if (high_range <= new_base)
7563 {
7564 inst.error = _("register range not in ascending order");
7565 return FAIL;
7566 }
7567
7568 for (new_base++; new_base <= high_range; new_base++)
7569 {
7570 if (mask & (1 << new_base))
7571 {
7572 inst.error = _("invalid register list");
7573 return FAIL;
7574 }
7575
7576 mask |= 1 << new_base;
7577 count++;
7578 }
7579 }
7580 }
7581 while (skip_past_comma (str) != FAIL);
7582
7583 (*str)++;
7584
7585 /* Sanity check -- should have raised a parse error above. */
7586 if (count == 0 || count > max_regs)
7587 abort ();
7588
7589 *pbase = base_reg;
7590
7591 /* Final test -- the registers must be consecutive. */
7592 mask >>= base_reg;
7593 for (i = 0; i < count; i++)
7594 {
7595 if ((mask & (1u << i)) == 0)
7596 {
7597 inst.error = _("non-contiguous register range");
7598 return FAIL;
7599 }
7600 }
7601
7602 return count;
7603 }
7604
7605 static void
7606 do_vfp_reg2_from_sp2 (char * str)
7607 {
7608 int reg;
7609
7610 skip_whitespace (str);
7611
7612 if (reg_required_here (&str, 12) == FAIL
7613 || skip_past_comma (&str) == FAIL
7614 || reg_required_here (&str, 16) == FAIL
7615 || skip_past_comma (&str) == FAIL)
7616 {
7617 if (! inst.error)
7618 inst.error = BAD_ARGS;
7619 return;
7620 }
7621
7622 /* We require exactly two consecutive SP registers. */
7623 if (vfp_parse_reg_list (&str, &reg, 0) != 2)
7624 {
7625 if (! inst.error)
7626 inst.error = _("only two consecutive VFP SP registers allowed here");
7627 }
7628 vfp_sp_encode_reg (reg, VFP_REG_Sm);
7629
7630 end_of_line (str);
7631 }
7632
7633 static void
7634 do_vfp_sp_from_reg (char * str)
7635 {
7636 skip_whitespace (str);
7637
7638 if (vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL)
7639 return;
7640
7641 if (skip_past_comma (&str) == FAIL
7642 || reg_required_here (&str, 12) == FAIL)
7643 {
7644 if (! inst.error)
7645 inst.error = BAD_ARGS;
7646 return;
7647 }
7648
7649 end_of_line (str);
7650 }
7651
7652 static void
7653 do_vfp_sp2_from_reg2 (char * str)
7654 {
7655 int reg;
7656
7657 skip_whitespace (str);
7658
7659 /* We require exactly two consecutive SP registers. */
7660 if (vfp_parse_reg_list (&str, &reg, 0) != 2)
7661 {
7662 if (! inst.error)
7663 inst.error = _("only two consecutive VFP SP registers allowed here");
7664 }
7665 vfp_sp_encode_reg (reg, VFP_REG_Sm);
7666
7667 if (skip_past_comma (&str) == FAIL
7668 || reg_required_here (&str, 12) == FAIL
7669 || skip_past_comma (&str) == FAIL
7670 || reg_required_here (&str, 16) == FAIL)
7671 {
7672 if (! inst.error)
7673 inst.error = BAD_ARGS;
7674 return;
7675 }
7676
7677 end_of_line (str);
7678 }
7679
7680 static void
7681 do_vfp_reg_from_dp (char * str)
7682 {
7683 skip_whitespace (str);
7684
7685 if (reg_required_here (&str, 12) == FAIL)
7686 return;
7687
7688 if (skip_past_comma (&str) == FAIL
7689 || vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL)
7690 {
7691 if (! inst.error)
7692 inst.error = BAD_ARGS;
7693 return;
7694 }
7695
7696 end_of_line (str);
7697 }
7698
7699 static void
7700 do_vfp_reg2_from_dp (char * str)
7701 {
7702 skip_whitespace (str);
7703
7704 if (reg_required_here (&str, 12) == FAIL)
7705 return;
7706
7707 if (skip_past_comma (&str) == FAIL
7708 || reg_required_here (&str, 16) == FAIL
7709 || skip_past_comma (&str) == FAIL
7710 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
7711 {
7712 if (! inst.error)
7713 inst.error = BAD_ARGS;
7714 return;
7715 }
7716
7717 end_of_line (str);
7718 }
7719
7720 static void
7721 do_vfp_dp_from_reg (char * str)
7722 {
7723 skip_whitespace (str);
7724
7725 if (vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL)
7726 return;
7727
7728 if (skip_past_comma (&str) == FAIL
7729 || reg_required_here (&str, 12) == FAIL)
7730 {
7731 if (! inst.error)
7732 inst.error = BAD_ARGS;
7733 return;
7734 }
7735
7736 end_of_line (str);
7737 }
7738
7739 static void
7740 do_vfp_dp_from_reg2 (char * str)
7741 {
7742 skip_whitespace (str);
7743
7744 if (vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
7745 return;
7746
7747 if (skip_past_comma (&str) == FAIL
7748 || reg_required_here (&str, 12) == FAIL
7749 || skip_past_comma (&str) == FAIL
7750 || reg_required_here (&str, 16) == FAIL)
7751 {
7752 if (! inst.error)
7753 inst.error = BAD_ARGS;
7754 return;
7755 }
7756
7757 end_of_line (str);
7758 }
7759
7760 static const struct vfp_reg *
7761 vfp_psr_parse (char ** str)
7762 {
7763 char *start = *str;
7764 char c;
7765 char *p;
7766 const struct vfp_reg *vreg;
7767
7768 p = start;
7769
7770 /* Find the end of the current token. */
7771 do
7772 {
7773 c = *p++;
7774 }
7775 while (ISALPHA (c));
7776
7777 /* Mark it. */
7778 *--p = 0;
7779
7780 for (vreg = vfp_regs + 0;
7781 vreg < vfp_regs + sizeof (vfp_regs) / sizeof (struct vfp_reg);
7782 vreg++)
7783 {
7784 if (streq (start, vreg->name))
7785 {
7786 *p = c;
7787 *str = p;
7788 return vreg;
7789 }
7790 }
7791
7792 *p = c;
7793 return NULL;
7794 }
7795
7796 static int
7797 vfp_psr_required_here (char ** str)
7798 {
7799 char *start = *str;
7800 const struct vfp_reg *vreg;
7801
7802 vreg = vfp_psr_parse (str);
7803
7804 if (vreg)
7805 {
7806 inst.instruction |= vreg->regno;
7807 return SUCCESS;
7808 }
7809
7810 inst.error = _("VFP system register expected");
7811
7812 *str = start;
7813 return FAIL;
7814 }
7815
7816 static void
7817 do_vfp_reg_from_ctrl (char * str)
7818 {
7819 skip_whitespace (str);
7820
7821 if (reg_required_here (&str, 12) == FAIL)
7822 return;
7823
7824 if (skip_past_comma (&str) == FAIL
7825 || vfp_psr_required_here (&str) == FAIL)
7826 {
7827 if (! inst.error)
7828 inst.error = BAD_ARGS;
7829 return;
7830 }
7831
7832 end_of_line (str);
7833 }
7834
7835 static void
7836 do_vfp_ctrl_from_reg (char * str)
7837 {
7838 skip_whitespace (str);
7839
7840 if (vfp_psr_required_here (&str) == FAIL)
7841 return;
7842
7843 if (skip_past_comma (&str) == FAIL
7844 || reg_required_here (&str, 12) == FAIL)
7845 {
7846 if (! inst.error)
7847 inst.error = BAD_ARGS;
7848 return;
7849 }
7850
7851 end_of_line (str);
7852 }
7853
7854 static void
7855 do_vfp_sp_ldst (char * str)
7856 {
7857 skip_whitespace (str);
7858
7859 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
7860 {
7861 if (!inst.error)
7862 inst.error = BAD_ARGS;
7863 return;
7864 }
7865
7866 if (skip_past_comma (&str) == FAIL
7867 || cp_address_required_here (&str, CP_NO_WB) == FAIL)
7868 {
7869 if (!inst.error)
7870 inst.error = BAD_ARGS;
7871 return;
7872 }
7873
7874 end_of_line (str);
7875 }
7876
7877 static void
7878 do_vfp_dp_ldst (char * str)
7879 {
7880 skip_whitespace (str);
7881
7882 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
7883 {
7884 if (!inst.error)
7885 inst.error = BAD_ARGS;
7886 return;
7887 }
7888
7889 if (skip_past_comma (&str) == FAIL
7890 || cp_address_required_here (&str, CP_NO_WB) == FAIL)
7891 {
7892 if (!inst.error)
7893 inst.error = BAD_ARGS;
7894 return;
7895 }
7896
7897 end_of_line (str);
7898 }
7899
7900
7901 static void
7902 vfp_sp_ldstm (char * str, enum vfp_ldstm_type ldstm_type)
7903 {
7904 int count;
7905 int reg;
7906
7907 skip_whitespace (str);
7908
7909 if (reg_required_here (&str, 16) == FAIL)
7910 return;
7911
7912 skip_whitespace (str);
7913
7914 if (*str == '!')
7915 {
7916 inst.instruction |= WRITE_BACK;
7917 str++;
7918 }
7919 else if (ldstm_type != VFP_LDSTMIA)
7920 {
7921 inst.error = _("this addressing mode requires base-register writeback");
7922 return;
7923 }
7924
7925 if (skip_past_comma (&str) == FAIL
7926 || (count = vfp_parse_reg_list (&str, &reg, 0)) == FAIL)
7927 {
7928 if (!inst.error)
7929 inst.error = BAD_ARGS;
7930 return;
7931 }
7932 vfp_sp_encode_reg (reg, VFP_REG_Sd);
7933
7934 inst.instruction |= count;
7935 end_of_line (str);
7936 }
7937
7938 static void
7939 vfp_dp_ldstm (char * str, enum vfp_ldstm_type ldstm_type)
7940 {
7941 int count;
7942 int reg;
7943
7944 skip_whitespace (str);
7945
7946 if (reg_required_here (&str, 16) == FAIL)
7947 return;
7948
7949 skip_whitespace (str);
7950
7951 if (*str == '!')
7952 {
7953 inst.instruction |= WRITE_BACK;
7954 str++;
7955 }
7956 else if (ldstm_type != VFP_LDSTMIA && ldstm_type != VFP_LDSTMIAX)
7957 {
7958 inst.error = _("this addressing mode requires base-register writeback");
7959 return;
7960 }
7961
7962 if (skip_past_comma (&str) == FAIL
7963 || (count = vfp_parse_reg_list (&str, &reg, 1)) == FAIL)
7964 {
7965 if (!inst.error)
7966 inst.error = BAD_ARGS;
7967 return;
7968 }
7969
7970 count <<= 1;
7971 if (ldstm_type == VFP_LDSTMIAX || ldstm_type == VFP_LDSTMDBX)
7972 count += 1;
7973
7974 inst.instruction |= (reg << 12) | count;
7975 end_of_line (str);
7976 }
7977
7978 static void
7979 do_vfp_sp_ldstmia (char * str)
7980 {
7981 vfp_sp_ldstm (str, VFP_LDSTMIA);
7982 }
7983
7984 static void
7985 do_vfp_sp_ldstmdb (char * str)
7986 {
7987 vfp_sp_ldstm (str, VFP_LDSTMDB);
7988 }
7989
7990 static void
7991 do_vfp_dp_ldstmia (char * str)
7992 {
7993 vfp_dp_ldstm (str, VFP_LDSTMIA);
7994 }
7995
7996 static void
7997 do_vfp_dp_ldstmdb (char * str)
7998 {
7999 vfp_dp_ldstm (str, VFP_LDSTMDB);
8000 }
8001
8002 static void
8003 do_vfp_xp_ldstmia (char *str)
8004 {
8005 vfp_dp_ldstm (str, VFP_LDSTMIAX);
8006 }
8007
8008 static void
8009 do_vfp_xp_ldstmdb (char * str)
8010 {
8011 vfp_dp_ldstm (str, VFP_LDSTMDBX);
8012 }
8013
8014 static void
8015 do_vfp_sp_compare_z (char * str)
8016 {
8017 skip_whitespace (str);
8018
8019 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
8020 {
8021 if (!inst.error)
8022 inst.error = BAD_ARGS;
8023 return;
8024 }
8025
8026 end_of_line (str);
8027 }
8028
8029 static void
8030 do_vfp_dp_compare_z (char * str)
8031 {
8032 skip_whitespace (str);
8033
8034 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
8035 {
8036 if (!inst.error)
8037 inst.error = BAD_ARGS;
8038 return;
8039 }
8040
8041 end_of_line (str);
8042 }
8043
8044 static void
8045 do_vfp_dp_sp_cvt (char * str)
8046 {
8047 skip_whitespace (str);
8048
8049 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
8050 return;
8051
8052 if (skip_past_comma (&str) == FAIL
8053 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
8054 {
8055 if (! inst.error)
8056 inst.error = BAD_ARGS;
8057 return;
8058 }
8059
8060 end_of_line (str);
8061 }
8062
8063 static void
8064 do_vfp_sp_dp_cvt (char * str)
8065 {
8066 skip_whitespace (str);
8067
8068 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
8069 return;
8070
8071 if (skip_past_comma (&str) == FAIL
8072 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
8073 {
8074 if (! inst.error)
8075 inst.error = BAD_ARGS;
8076 return;
8077 }
8078
8079 end_of_line (str);
8080 }
8081
8082 /* Thumb specific routines. */
8083
8084 /* Parse an add or subtract instruction, SUBTRACT is non-zero if the opcode
8085 was SUB. */
8086
8087 static void
8088 thumb_add_sub (char * str, int subtract)
8089 {
8090 int Rd, Rs, Rn = FAIL;
8091
8092 skip_whitespace (str);
8093
8094 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
8095 || skip_past_comma (&str) == FAIL)
8096 {
8097 if (! inst.error)
8098 inst.error = BAD_ARGS;
8099 return;
8100 }
8101
8102 if (is_immediate_prefix (*str))
8103 {
8104 Rs = Rd;
8105 str++;
8106 if (my_get_expression (&inst.reloc.exp, &str))
8107 return;
8108 }
8109 else
8110 {
8111 if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
8112 return;
8113
8114 if (skip_past_comma (&str) == FAIL)
8115 {
8116 /* Two operand format, shuffle the registers
8117 and pretend there are 3. */
8118 Rn = Rs;
8119 Rs = Rd;
8120 }
8121 else if (is_immediate_prefix (*str))
8122 {
8123 str++;
8124 if (my_get_expression (&inst.reloc.exp, &str))
8125 return;
8126 }
8127 else if ((Rn = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
8128 return;
8129 }
8130
8131 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
8132 for the latter case, EXPR contains the immediate that was found. */
8133 if (Rn != FAIL)
8134 {
8135 /* All register format. */
8136 if (Rd > 7 || Rs > 7 || Rn > 7)
8137 {
8138 if (Rs != Rd)
8139 {
8140 inst.error = _("dest and source1 must be the same register");
8141 return;
8142 }
8143
8144 /* Can't do this for SUB. */
8145 if (subtract)
8146 {
8147 inst.error = _("subtract valid only on lo regs");
8148 return;
8149 }
8150
8151 inst.instruction = (T_OPCODE_ADD_HI
8152 | (Rd > 7 ? THUMB_H1 : 0)
8153 | (Rn > 7 ? THUMB_H2 : 0));
8154 inst.instruction |= (Rd & 7) | ((Rn & 7) << 3);
8155 }
8156 else
8157 {
8158 inst.instruction = subtract ? T_OPCODE_SUB_R3 : T_OPCODE_ADD_R3;
8159 inst.instruction |= Rd | (Rs << 3) | (Rn << 6);
8160 }
8161 }
8162 else
8163 {
8164 /* Immediate expression, now things start to get nasty. */
8165
8166 /* First deal with HI regs, only very restricted cases allowed:
8167 Adjusting SP, and using PC or SP to get an address. */
8168 if ((Rd > 7 && (Rd != REG_SP || Rs != REG_SP))
8169 || (Rs > 7 && Rs != REG_SP && Rs != REG_PC))
8170 {
8171 inst.error = _("invalid Hi register with immediate");
8172 return;
8173 }
8174
8175 if (inst.reloc.exp.X_op != O_constant)
8176 {
8177 /* Value isn't known yet, all we can do is store all the fragments
8178 we know about in the instruction and let the reloc hacking
8179 work it all out. */
8180 inst.instruction = (subtract ? 0x8000 : 0) | (Rd << 4) | Rs;
8181 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
8182 }
8183 else
8184 {
8185 int offset = inst.reloc.exp.X_add_number;
8186
8187 if (subtract)
8188 offset = - offset;
8189
8190 if (offset < 0)
8191 {
8192 offset = - offset;
8193 subtract = 1;
8194
8195 /* Quick check, in case offset is MIN_INT. */
8196 if (offset < 0)
8197 {
8198 inst.error = _("immediate value out of range");
8199 return;
8200 }
8201 }
8202 /* Note - you cannot convert a subtract of 0 into an
8203 add of 0 because the carry flag is set differently. */
8204 else if (offset > 0)
8205 subtract = 0;
8206
8207 if (Rd == REG_SP)
8208 {
8209 if (offset & ~0x1fc)
8210 {
8211 inst.error = _("invalid immediate value for stack adjust");
8212 return;
8213 }
8214 inst.instruction = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
8215 inst.instruction |= offset >> 2;
8216 }
8217 else if (Rs == REG_PC || Rs == REG_SP)
8218 {
8219 if (subtract
8220 || (offset & ~0x3fc))
8221 {
8222 inst.error = _("invalid immediate for address calculation");
8223 return;
8224 }
8225 inst.instruction = (Rs == REG_PC ? T_OPCODE_ADD_PC
8226 : T_OPCODE_ADD_SP);
8227 inst.instruction |= (Rd << 8) | (offset >> 2);
8228 }
8229 else if (Rs == Rd)
8230 {
8231 if (offset & ~0xff)
8232 {
8233 inst.error = _("immediate value out of range");
8234 return;
8235 }
8236 inst.instruction = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
8237 inst.instruction |= (Rd << 8) | offset;
8238 }
8239 else
8240 {
8241 if (offset & ~0x7)
8242 {
8243 inst.error = _("immediate value out of range");
8244 return;
8245 }
8246 inst.instruction = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
8247 inst.instruction |= Rd | (Rs << 3) | (offset << 6);
8248 }
8249 }
8250 }
8251
8252 end_of_line (str);
8253 }
8254
8255 static void
8256 thumb_shift (char * str, int shift)
8257 {
8258 int Rd, Rs, Rn = FAIL;
8259
8260 skip_whitespace (str);
8261
8262 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
8263 || skip_past_comma (&str) == FAIL)
8264 {
8265 if (! inst.error)
8266 inst.error = BAD_ARGS;
8267 return;
8268 }
8269
8270 if (is_immediate_prefix (*str))
8271 {
8272 /* Two operand immediate format, set Rs to Rd. */
8273 Rs = Rd;
8274 str ++;
8275 if (my_get_expression (&inst.reloc.exp, &str))
8276 return;
8277 }
8278 else
8279 {
8280 if ((Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
8281 return;
8282
8283 if (skip_past_comma (&str) == FAIL)
8284 {
8285 /* Two operand format, shuffle the registers
8286 and pretend there are 3. */
8287 Rn = Rs;
8288 Rs = Rd;
8289 }
8290 else if (is_immediate_prefix (*str))
8291 {
8292 str++;
8293 if (my_get_expression (&inst.reloc.exp, &str))
8294 return;
8295 }
8296 else if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
8297 return;
8298 }
8299
8300 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
8301 for the latter case, EXPR contains the immediate that was found. */
8302
8303 if (Rn != FAIL)
8304 {
8305 if (Rs != Rd)
8306 {
8307 inst.error = _("source1 and dest must be same register");
8308 return;
8309 }
8310
8311 switch (shift)
8312 {
8313 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_R; break;
8314 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_R; break;
8315 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_R; break;
8316 }
8317
8318 inst.instruction |= Rd | (Rn << 3);
8319 }
8320 else
8321 {
8322 switch (shift)
8323 {
8324 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_I; break;
8325 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_I; break;
8326 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_I; break;
8327 }
8328
8329 if (inst.reloc.exp.X_op != O_constant)
8330 {
8331 /* Value isn't known yet, create a dummy reloc and let reloc
8332 hacking fix it up. */
8333 inst.reloc.type = BFD_RELOC_ARM_THUMB_SHIFT;
8334 }
8335 else
8336 {
8337 unsigned shift_value = inst.reloc.exp.X_add_number;
8338
8339 if (shift_value > 32 || (shift_value == 32 && shift == THUMB_LSL))
8340 {
8341 inst.error = _("invalid immediate for shift");
8342 return;
8343 }
8344
8345 /* Shifts of zero are handled by converting to LSL. */
8346 if (shift_value == 0)
8347 inst.instruction = T_OPCODE_LSL_I;
8348
8349 /* Shifts of 32 are encoded as a shift of zero. */
8350 if (shift_value == 32)
8351 shift_value = 0;
8352
8353 inst.instruction |= shift_value << 6;
8354 }
8355
8356 inst.instruction |= Rd | (Rs << 3);
8357 }
8358
8359 end_of_line (str);
8360 }
8361
8362 static void
8363 thumb_load_store (char * str, int load_store, int size)
8364 {
8365 int Rd, Rb, Ro = FAIL;
8366
8367 skip_whitespace (str);
8368
8369 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
8370 || skip_past_comma (&str) == FAIL)
8371 {
8372 if (! inst.error)
8373 inst.error = BAD_ARGS;
8374 return;
8375 }
8376
8377 if (*str == '[')
8378 {
8379 str++;
8380 if ((Rb = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
8381 return;
8382
8383 if (skip_past_comma (&str) != FAIL)
8384 {
8385 if (is_immediate_prefix (*str))
8386 {
8387 str++;
8388 if (my_get_expression (&inst.reloc.exp, &str))
8389 return;
8390 }
8391 else if ((Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
8392 return;
8393 }
8394 else
8395 {
8396 inst.reloc.exp.X_op = O_constant;
8397 inst.reloc.exp.X_add_number = 0;
8398 }
8399
8400 if (*str != ']')
8401 {
8402 inst.error = _("expected ']'");
8403 return;
8404 }
8405 str++;
8406 }
8407 else if (*str == '=')
8408 {
8409 if (load_store != THUMB_LOAD)
8410 {
8411 inst.error = _("invalid pseudo operation");
8412 return;
8413 }
8414
8415 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
8416 str++;
8417
8418 skip_whitespace (str);
8419
8420 if (my_get_expression (& inst.reloc.exp, & str))
8421 return;
8422
8423 end_of_line (str);
8424
8425 if ( inst.reloc.exp.X_op != O_constant
8426 && inst.reloc.exp.X_op != O_symbol)
8427 {
8428 inst.error = "Constant expression expected";
8429 return;
8430 }
8431
8432 if (inst.reloc.exp.X_op == O_constant
8433 && ((inst.reloc.exp.X_add_number & ~0xFF) == 0))
8434 {
8435 /* This can be done with a mov instruction. */
8436
8437 inst.instruction = T_OPCODE_MOV_I8 | (Rd << 8);
8438 inst.instruction |= inst.reloc.exp.X_add_number;
8439 return;
8440 }
8441
8442 /* Insert into literal pool. */
8443 if (add_to_lit_pool () == FAIL)
8444 {
8445 if (!inst.error)
8446 inst.error = "literal pool insertion failed";
8447 return;
8448 }
8449
8450 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
8451 inst.reloc.pc_rel = 1;
8452 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
8453 /* Adjust ARM pipeline offset to Thumb. */
8454 inst.reloc.exp.X_add_number += 4;
8455
8456 return;
8457 }
8458 else
8459 {
8460 if (my_get_expression (&inst.reloc.exp, &str))
8461 return;
8462
8463 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
8464 inst.reloc.pc_rel = 1;
8465 inst.reloc.exp.X_add_number -= 4; /* Pipeline offset. */
8466 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
8467 end_of_line (str);
8468 return;
8469 }
8470
8471 if (Rb == REG_PC || Rb == REG_SP)
8472 {
8473 if (size != THUMB_WORD)
8474 {
8475 inst.error = _("byte or halfword not valid for base register");
8476 return;
8477 }
8478 else if (Rb == REG_PC && load_store != THUMB_LOAD)
8479 {
8480 inst.error = _("r15 based store not allowed");
8481 return;
8482 }
8483 else if (Ro != FAIL)
8484 {
8485 inst.error = _("invalid base register for register offset");
8486 return;
8487 }
8488
8489 if (Rb == REG_PC)
8490 inst.instruction = T_OPCODE_LDR_PC;
8491 else if (load_store == THUMB_LOAD)
8492 inst.instruction = T_OPCODE_LDR_SP;
8493 else
8494 inst.instruction = T_OPCODE_STR_SP;
8495
8496 inst.instruction |= Rd << 8;
8497 if (inst.reloc.exp.X_op == O_constant)
8498 {
8499 unsigned offset = inst.reloc.exp.X_add_number;
8500
8501 if (offset & ~0x3fc)
8502 {
8503 inst.error = _("invalid offset");
8504 return;
8505 }
8506
8507 inst.instruction |= offset >> 2;
8508 }
8509 else
8510 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
8511 }
8512 else if (Rb > 7)
8513 {
8514 inst.error = _("invalid base register in load/store");
8515 return;
8516 }
8517 else if (Ro == FAIL)
8518 {
8519 /* Immediate offset. */
8520 if (size == THUMB_WORD)
8521 inst.instruction = (load_store == THUMB_LOAD
8522 ? T_OPCODE_LDR_IW : T_OPCODE_STR_IW);
8523 else if (size == THUMB_HALFWORD)
8524 inst.instruction = (load_store == THUMB_LOAD
8525 ? T_OPCODE_LDR_IH : T_OPCODE_STR_IH);
8526 else
8527 inst.instruction = (load_store == THUMB_LOAD
8528 ? T_OPCODE_LDR_IB : T_OPCODE_STR_IB);
8529
8530 inst.instruction |= Rd | (Rb << 3);
8531
8532 if (inst.reloc.exp.X_op == O_constant)
8533 {
8534 unsigned offset = inst.reloc.exp.X_add_number;
8535
8536 if (offset & ~(0x1f << size))
8537 {
8538 inst.error = _("invalid offset");
8539 return;
8540 }
8541 inst.instruction |= (offset >> size) << 6;
8542 }
8543 else
8544 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
8545 }
8546 else
8547 {
8548 /* Register offset. */
8549 if (size == THUMB_WORD)
8550 inst.instruction = (load_store == THUMB_LOAD
8551 ? T_OPCODE_LDR_RW : T_OPCODE_STR_RW);
8552 else if (size == THUMB_HALFWORD)
8553 inst.instruction = (load_store == THUMB_LOAD
8554 ? T_OPCODE_LDR_RH : T_OPCODE_STR_RH);
8555 else
8556 inst.instruction = (load_store == THUMB_LOAD
8557 ? T_OPCODE_LDR_RB : T_OPCODE_STR_RB);
8558
8559 inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
8560 }
8561
8562 end_of_line (str);
8563 }
8564
8565 /* A register must be given at this point.
8566
8567 Shift is the place to put it in inst.instruction.
8568
8569 Restores input start point on err.
8570 Returns the reg#, or FAIL. */
8571
8572 static int
8573 mav_reg_required_here (char ** str, int shift, enum arm_reg_type regtype)
8574 {
8575 int reg;
8576 char *start = *str;
8577
8578 if ((reg = arm_reg_parse (str, all_reg_maps[regtype].htab)) != FAIL)
8579 {
8580 if (shift >= 0)
8581 inst.instruction |= reg << shift;
8582
8583 return reg;
8584 }
8585
8586 /* Restore the start point. */
8587 *str = start;
8588
8589 /* Try generic coprocessor name if applicable. */
8590 if (regtype == REG_TYPE_MVF ||
8591 regtype == REG_TYPE_MVD ||
8592 regtype == REG_TYPE_MVFX ||
8593 regtype == REG_TYPE_MVDX)
8594 {
8595 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_CN].htab)) != FAIL)
8596 {
8597 if (shift >= 0)
8598 inst.instruction |= reg << shift;
8599
8600 return reg;
8601 }
8602
8603 /* Restore the start point. */
8604 *str = start;
8605 }
8606
8607 /* In the few cases where we might be able to accept something else
8608 this error can be overridden. */
8609 inst.error = _(all_reg_maps[regtype].expected);
8610
8611 return FAIL;
8612 }
8613
8614 /* Cirrus Maverick Instructions. */
8615
8616 /* Isnsn like "foo X,Y". */
8617
8618 static void
8619 do_mav_binops (char * str,
8620 int mode,
8621 enum arm_reg_type reg0,
8622 enum arm_reg_type reg1)
8623 {
8624 int shift0, shift1;
8625
8626 shift0 = mode & 0xff;
8627 shift1 = (mode >> 8) & 0xff;
8628
8629 skip_whitespace (str);
8630
8631 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
8632 || skip_past_comma (&str) == FAIL
8633 || mav_reg_required_here (&str, shift1, reg1) == FAIL)
8634 {
8635 if (!inst.error)
8636 inst.error = BAD_ARGS;
8637 }
8638 else
8639 end_of_line (str);
8640 }
8641
8642 /* Isnsn like "foo X,Y,Z". */
8643
8644 static void
8645 do_mav_triple (char * str,
8646 int mode,
8647 enum arm_reg_type reg0,
8648 enum arm_reg_type reg1,
8649 enum arm_reg_type reg2)
8650 {
8651 int shift0, shift1, shift2;
8652
8653 shift0 = mode & 0xff;
8654 shift1 = (mode >> 8) & 0xff;
8655 shift2 = (mode >> 16) & 0xff;
8656
8657 skip_whitespace (str);
8658
8659 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
8660 || skip_past_comma (&str) == FAIL
8661 || mav_reg_required_here (&str, shift1, reg1) == FAIL
8662 || skip_past_comma (&str) == FAIL
8663 || mav_reg_required_here (&str, shift2, reg2) == FAIL)
8664 {
8665 if (!inst.error)
8666 inst.error = BAD_ARGS;
8667 }
8668 else
8669 end_of_line (str);
8670 }
8671
8672 /* Wrapper functions. */
8673
8674 static void
8675 do_mav_binops_1a (char * str)
8676 {
8677 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVF);
8678 }
8679
8680 static void
8681 do_mav_binops_1b (char * str)
8682 {
8683 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVD);
8684 }
8685
8686 static void
8687 do_mav_binops_1c (char * str)
8688 {
8689 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVDX);
8690 }
8691
8692 static void
8693 do_mav_binops_1d (char * str)
8694 {
8695 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVF);
8696 }
8697
8698 static void
8699 do_mav_binops_1e (char * str)
8700 {
8701 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVD);
8702 }
8703
8704 static void
8705 do_mav_binops_1f (char * str)
8706 {
8707 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVF);
8708 }
8709
8710 static void
8711 do_mav_binops_1g (char * str)
8712 {
8713 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVD);
8714 }
8715
8716 static void
8717 do_mav_binops_1h (char * str)
8718 {
8719 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVFX);
8720 }
8721
8722 static void
8723 do_mav_binops_1i (char * str)
8724 {
8725 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVFX);
8726 }
8727
8728 static void
8729 do_mav_binops_1j (char * str)
8730 {
8731 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVDX);
8732 }
8733
8734 static void
8735 do_mav_binops_1k (char * str)
8736 {
8737 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVDX);
8738 }
8739
8740 static void
8741 do_mav_binops_1l (char * str)
8742 {
8743 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVF);
8744 }
8745
8746 static void
8747 do_mav_binops_1m (char * str)
8748 {
8749 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVD);
8750 }
8751
8752 static void
8753 do_mav_binops_1n (char * str)
8754 {
8755 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVFX);
8756 }
8757
8758 static void
8759 do_mav_binops_1o (char * str)
8760 {
8761 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVDX, REG_TYPE_MVDX);
8762 }
8763
8764 static void
8765 do_mav_binops_2a (char * str)
8766 {
8767 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVF, REG_TYPE_RN);
8768 }
8769
8770 static void
8771 do_mav_binops_2b (char * str)
8772 {
8773 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVD, REG_TYPE_RN);
8774 }
8775
8776 static void
8777 do_mav_binops_2c (char * str)
8778 {
8779 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVDX, REG_TYPE_RN);
8780 }
8781
8782 static void
8783 do_mav_binops_3a (char * str)
8784 {
8785 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVAX, REG_TYPE_MVFX);
8786 }
8787
8788 static void
8789 do_mav_binops_3b (char * str)
8790 {
8791 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVFX, REG_TYPE_MVAX);
8792 }
8793
8794 static void
8795 do_mav_binops_3c (char * str)
8796 {
8797 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVAX, REG_TYPE_MVDX);
8798 }
8799
8800 static void
8801 do_mav_binops_3d (char * str)
8802 {
8803 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVDX, REG_TYPE_MVAX);
8804 }
8805
8806 static void
8807 do_mav_triple_4a (char * str)
8808 {
8809 do_mav_triple (str, MAV_MODE4, REG_TYPE_MVFX, REG_TYPE_MVFX, REG_TYPE_RN);
8810 }
8811
8812 static void
8813 do_mav_triple_4b (char * str)
8814 {
8815 do_mav_triple (str, MAV_MODE4, REG_TYPE_MVDX, REG_TYPE_MVDX, REG_TYPE_RN);
8816 }
8817
8818 static void
8819 do_mav_triple_5a (char * str)
8820 {
8821 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVF, REG_TYPE_MVF);
8822 }
8823
8824 static void
8825 do_mav_triple_5b (char * str)
8826 {
8827 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVD, REG_TYPE_MVD);
8828 }
8829
8830 static void
8831 do_mav_triple_5c (char * str)
8832 {
8833 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVFX, REG_TYPE_MVFX);
8834 }
8835
8836 static void
8837 do_mav_triple_5d (char * str)
8838 {
8839 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVDX, REG_TYPE_MVDX);
8840 }
8841
8842 static void
8843 do_mav_triple_5e (char * str)
8844 {
8845 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVF, REG_TYPE_MVF, REG_TYPE_MVF);
8846 }
8847
8848 static void
8849 do_mav_triple_5f (char * str)
8850 {
8851 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVD, REG_TYPE_MVD, REG_TYPE_MVD);
8852 }
8853
8854 static void
8855 do_mav_triple_5g (char * str)
8856 {
8857 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVFX, REG_TYPE_MVFX, REG_TYPE_MVFX);
8858 }
8859
8860 static void
8861 do_mav_triple_5h (char * str)
8862 {
8863 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVDX, REG_TYPE_MVDX, REG_TYPE_MVDX);
8864 }
8865
8866 /* Isnsn like "foo W,X,Y,Z".
8867 where W=MVAX[0:3] and X,Y,Z=MVFX[0:15]. */
8868
8869 static void
8870 do_mav_quad (char * str,
8871 int mode,
8872 enum arm_reg_type reg0,
8873 enum arm_reg_type reg1,
8874 enum arm_reg_type reg2,
8875 enum arm_reg_type reg3)
8876 {
8877 int shift0, shift1, shift2, shift3;
8878
8879 shift0= mode & 0xff;
8880 shift1 = (mode >> 8) & 0xff;
8881 shift2 = (mode >> 16) & 0xff;
8882 shift3 = (mode >> 24) & 0xff;
8883
8884 skip_whitespace (str);
8885
8886 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
8887 || skip_past_comma (&str) == FAIL
8888 || mav_reg_required_here (&str, shift1, reg1) == FAIL
8889 || skip_past_comma (&str) == FAIL
8890 || mav_reg_required_here (&str, shift2, reg2) == FAIL
8891 || skip_past_comma (&str) == FAIL
8892 || mav_reg_required_here (&str, shift3, reg3) == FAIL)
8893 {
8894 if (!inst.error)
8895 inst.error = BAD_ARGS;
8896 }
8897 else
8898 end_of_line (str);
8899 }
8900
8901 static void
8902 do_mav_quad_6a (char * str)
8903 {
8904 do_mav_quad (str, MAV_MODE6, REG_TYPE_MVAX, REG_TYPE_MVFX, REG_TYPE_MVFX,
8905 REG_TYPE_MVFX);
8906 }
8907
8908 static void
8909 do_mav_quad_6b (char * str)
8910 {
8911 do_mav_quad (str, MAV_MODE6, REG_TYPE_MVAX, REG_TYPE_MVAX, REG_TYPE_MVFX,
8912 REG_TYPE_MVFX);
8913 }
8914
8915 /* cfmvsc32<cond> DSPSC,MVDX[15:0]. */
8916 static void
8917 do_mav_dspsc_1 (char * str)
8918 {
8919 skip_whitespace (str);
8920
8921 /* cfmvsc32. */
8922 if (mav_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL
8923 || skip_past_comma (&str) == FAIL
8924 || mav_reg_required_here (&str, 12, REG_TYPE_MVDX) == FAIL)
8925 {
8926 if (!inst.error)
8927 inst.error = BAD_ARGS;
8928
8929 return;
8930 }
8931
8932 end_of_line (str);
8933 }
8934
8935 /* cfmv32sc<cond> MVDX[15:0],DSPSC. */
8936 static void
8937 do_mav_dspsc_2 (char * str)
8938 {
8939 skip_whitespace (str);
8940
8941 /* cfmv32sc. */
8942 if (mav_reg_required_here (&str, 12, REG_TYPE_MVDX) == FAIL
8943 || skip_past_comma (&str) == FAIL
8944 || mav_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL)
8945 {
8946 if (!inst.error)
8947 inst.error = BAD_ARGS;
8948
8949 return;
8950 }
8951
8952 end_of_line (str);
8953 }
8954
8955 /* Maverick shift immediate instructions.
8956 cfsh32<cond> MVFX[15:0],MVFX[15:0],Shift[6:0].
8957 cfsh64<cond> MVDX[15:0],MVDX[15:0],Shift[6:0]. */
8958
8959 static void
8960 do_mav_shift (char * str,
8961 enum arm_reg_type reg0,
8962 enum arm_reg_type reg1)
8963 {
8964 int error;
8965 int imm, neg = 0;
8966
8967 skip_whitespace (str);
8968
8969 error = 0;
8970
8971 if (mav_reg_required_here (&str, 12, reg0) == FAIL
8972 || skip_past_comma (&str) == FAIL
8973 || mav_reg_required_here (&str, 16, reg1) == FAIL
8974 || skip_past_comma (&str) == FAIL)
8975 {
8976 if (!inst.error)
8977 inst.error = BAD_ARGS;
8978 return;
8979 }
8980
8981 /* Calculate the immediate operand.
8982 The operand is a 7bit signed number. */
8983 skip_whitespace (str);
8984
8985 if (*str == '#')
8986 ++str;
8987
8988 if (!ISDIGIT (*str) && *str != '-')
8989 {
8990 inst.error = _("expecting immediate, 7bit operand");
8991 return;
8992 }
8993
8994 if (*str == '-')
8995 {
8996 neg = 1;
8997 ++str;
8998 }
8999
9000 for (imm = 0; *str && ISDIGIT (*str); ++str)
9001 imm = imm * 10 + *str - '0';
9002
9003 if (imm > 64)
9004 {
9005 inst.error = _("immediate out of range");
9006 return;
9007 }
9008
9009 /* Make negative imm's into 7bit signed numbers. */
9010 if (neg)
9011 {
9012 imm = -imm;
9013 imm &= 0x0000007f;
9014 }
9015
9016 /* Bits 0-3 of the insn should have bits 0-3 of the immediate.
9017 Bits 5-7 of the insn should have bits 4-6 of the immediate.
9018 Bit 4 should be 0. */
9019 imm = (imm & 0xf) | ((imm & 0x70) << 1);
9020
9021 inst.instruction |= imm;
9022 end_of_line (str);
9023 }
9024
9025 static void
9026 do_mav_shift_1 (char * str)
9027 {
9028 do_mav_shift (str, REG_TYPE_MVFX, REG_TYPE_MVFX);
9029 }
9030
9031 static void
9032 do_mav_shift_2 (char * str)
9033 {
9034 do_mav_shift (str, REG_TYPE_MVDX, REG_TYPE_MVDX);
9035 }
9036
9037 static int
9038 mav_parse_offset (char ** str, int * negative)
9039 {
9040 char * p = *str;
9041 int offset;
9042
9043 *negative = 0;
9044
9045 skip_whitespace (p);
9046
9047 if (*p == '#')
9048 ++p;
9049
9050 if (*p == '-')
9051 {
9052 *negative = 1;
9053 ++p;
9054 }
9055
9056 if (!ISDIGIT (*p))
9057 {
9058 inst.error = _("offset expected");
9059 return 0;
9060 }
9061
9062 for (offset = 0; *p && ISDIGIT (*p); ++p)
9063 offset = offset * 10 + *p - '0';
9064
9065 if (offset > 0x3fc)
9066 {
9067 inst.error = _("offset out of range");
9068 return 0;
9069 }
9070 if (offset & 0x3)
9071 {
9072 inst.error = _("offset not a multiple of 4");
9073 return 0;
9074 }
9075
9076 *str = p;
9077
9078 return *negative ? -offset : offset;
9079 }
9080
9081 /* Maverick load/store instructions.
9082 <insn><cond> CRd,[Rn,<offset>]{!}.
9083 <insn><cond> CRd,[Rn],<offset>. */
9084
9085 static void
9086 do_mav_ldst (char * str, enum arm_reg_type reg0)
9087 {
9088 int offset, negative;
9089
9090 skip_whitespace (str);
9091
9092 if (mav_reg_required_here (&str, 12, reg0) == FAIL
9093 || skip_past_comma (&str) == FAIL
9094 || *str++ != '['
9095 || reg_required_here (&str, 16) == FAIL)
9096 goto fail_ldst;
9097
9098 if (skip_past_comma (&str) == SUCCESS)
9099 {
9100 /* You are here: "<offset>]{!}". */
9101 inst.instruction |= PRE_INDEX;
9102
9103 offset = mav_parse_offset (&str, &negative);
9104
9105 if (inst.error)
9106 return;
9107
9108 if (*str++ != ']')
9109 {
9110 inst.error = _("missing ]");
9111 return;
9112 }
9113
9114 if (*str == '!')
9115 {
9116 inst.instruction |= WRITE_BACK;
9117 ++str;
9118 }
9119 }
9120 else
9121 {
9122 /* You are here: "], <offset>". */
9123 if (*str++ != ']')
9124 {
9125 inst.error = _("missing ]");
9126 return;
9127 }
9128
9129 if (skip_past_comma (&str) == FAIL
9130 || (offset = mav_parse_offset (&str, &negative), inst.error))
9131 goto fail_ldst;
9132
9133 inst.instruction |= CP_T_WB; /* Post indexed, set bit W. */
9134 }
9135
9136 if (negative)
9137 offset = -offset;
9138 else
9139 inst.instruction |= CP_T_UD; /* Positive, so set bit U. */
9140
9141 inst.instruction |= offset >> 2;
9142 end_of_line (str);
9143 return;
9144
9145 fail_ldst:
9146 if (!inst.error)
9147 inst.error = BAD_ARGS;
9148 }
9149
9150 static void
9151 do_mav_ldst_1 (char * str)
9152 {
9153 do_mav_ldst (str, REG_TYPE_MVF);
9154 }
9155
9156 static void
9157 do_mav_ldst_2 (char * str)
9158 {
9159 do_mav_ldst (str, REG_TYPE_MVD);
9160 }
9161
9162 static void
9163 do_mav_ldst_3 (char * str)
9164 {
9165 do_mav_ldst (str, REG_TYPE_MVFX);
9166 }
9167
9168 static void
9169 do_mav_ldst_4 (char * str)
9170 {
9171 do_mav_ldst (str, REG_TYPE_MVDX);
9172 }
9173
9174 static void
9175 do_t_nop (char * str)
9176 {
9177 /* Do nothing. */
9178 end_of_line (str);
9179 }
9180
9181 /* Handle the Format 4 instructions that do not have equivalents in other
9182 formats. That is, ADC, AND, EOR, SBC, ROR, TST, NEG, CMN, ORR, MUL,
9183 BIC and MVN. */
9184
9185 static void
9186 do_t_arit (char * str)
9187 {
9188 int Rd, Rs, Rn;
9189
9190 skip_whitespace (str);
9191
9192 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9193 || skip_past_comma (&str) == FAIL
9194 || (Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9195 {
9196 inst.error = BAD_ARGS;
9197 return;
9198 }
9199
9200 if (skip_past_comma (&str) != FAIL)
9201 {
9202 /* Three operand format not allowed for TST, CMN, NEG and MVN.
9203 (It isn't allowed for CMP either, but that isn't handled by this
9204 function.) */
9205 if (inst.instruction == T_OPCODE_TST
9206 || inst.instruction == T_OPCODE_CMN
9207 || inst.instruction == T_OPCODE_NEG
9208 || inst.instruction == T_OPCODE_MVN)
9209 {
9210 inst.error = BAD_ARGS;
9211 return;
9212 }
9213
9214 if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9215 return;
9216
9217 if (Rs != Rd)
9218 {
9219 inst.error = _("dest and source1 must be the same register");
9220 return;
9221 }
9222 Rs = Rn;
9223 }
9224
9225 if (inst.instruction == T_OPCODE_MUL
9226 && Rs == Rd)
9227 as_tsktsk (_("Rs and Rd must be different in MUL"));
9228
9229 inst.instruction |= Rd | (Rs << 3);
9230 end_of_line (str);
9231 }
9232
9233 static void
9234 do_t_add (char * str)
9235 {
9236 thumb_add_sub (str, 0);
9237 }
9238
9239 static void
9240 do_t_asr (char * str)
9241 {
9242 thumb_shift (str, THUMB_ASR);
9243 }
9244
9245 static void
9246 do_t_branch9 (char * str)
9247 {
9248 if (my_get_expression (&inst.reloc.exp, &str))
9249 return;
9250 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH9;
9251 inst.reloc.pc_rel = 1;
9252 end_of_line (str);
9253 }
9254
9255 static void
9256 do_t_branch12 (char * str)
9257 {
9258 if (my_get_expression (&inst.reloc.exp, &str))
9259 return;
9260 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH12;
9261 inst.reloc.pc_rel = 1;
9262 end_of_line (str);
9263 }
9264
9265 /* Find the real, Thumb encoded start of a Thumb function. */
9266
9267 static symbolS *
9268 find_real_start (symbolS * symbolP)
9269 {
9270 char * real_start;
9271 const char * name = S_GET_NAME (symbolP);
9272 symbolS * new_target;
9273
9274 /* This definition must agree with the one in gcc/config/arm/thumb.c. */
9275 #define STUB_NAME ".real_start_of"
9276
9277 if (name == NULL)
9278 abort ();
9279
9280 /* Names that start with '.' are local labels, not function entry points.
9281 The compiler may generate BL instructions to these labels because it
9282 needs to perform a branch to a far away location. */
9283 if (name[0] == '.')
9284 return symbolP;
9285
9286 real_start = malloc (strlen (name) + strlen (STUB_NAME) + 1);
9287 sprintf (real_start, "%s%s", STUB_NAME, name);
9288
9289 new_target = symbol_find (real_start);
9290
9291 if (new_target == NULL)
9292 {
9293 as_warn ("Failed to find real start of function: %s\n", name);
9294 new_target = symbolP;
9295 }
9296
9297 free (real_start);
9298
9299 return new_target;
9300 }
9301
9302 static void
9303 do_t_branch23 (char * str)
9304 {
9305 if (my_get_expression (& inst.reloc.exp, & str))
9306 return;
9307
9308 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH23;
9309 inst.reloc.pc_rel = 1;
9310 end_of_line (str);
9311
9312 /* If the destination of the branch is a defined symbol which does not have
9313 the THUMB_FUNC attribute, then we must be calling a function which has
9314 the (interfacearm) attribute. We look for the Thumb entry point to that
9315 function and change the branch to refer to that function instead. */
9316 if ( inst.reloc.exp.X_op == O_symbol
9317 && inst.reloc.exp.X_add_symbol != NULL
9318 && S_IS_DEFINED (inst.reloc.exp.X_add_symbol)
9319 && ! THUMB_IS_FUNC (inst.reloc.exp.X_add_symbol))
9320 inst.reloc.exp.X_add_symbol =
9321 find_real_start (inst.reloc.exp.X_add_symbol);
9322 }
9323
9324 static void
9325 do_t_bx (char * str)
9326 {
9327 int reg;
9328
9329 skip_whitespace (str);
9330
9331 if ((reg = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
9332 return;
9333
9334 /* This sets THUMB_H2 from the top bit of reg. */
9335 inst.instruction |= reg << 3;
9336
9337 /* ??? FIXME: Should add a hacky reloc here if reg is REG_PC. The reloc
9338 should cause the alignment to be checked once it is known. This is
9339 because BX PC only works if the instruction is word aligned. */
9340
9341 end_of_line (str);
9342 }
9343
9344 static void
9345 do_t_compare (char * str)
9346 {
9347 thumb_mov_compare (str, THUMB_COMPARE);
9348 }
9349
9350 static void
9351 do_t_ldmstm (char * str)
9352 {
9353 int Rb;
9354 long range;
9355
9356 skip_whitespace (str);
9357
9358 if ((Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9359 return;
9360
9361 if (*str != '!')
9362 as_warn (_("inserted missing '!': load/store multiple always writes back base register"));
9363 else
9364 str++;
9365
9366 if (skip_past_comma (&str) == FAIL
9367 || (range = reg_list (&str)) == FAIL)
9368 {
9369 if (! inst.error)
9370 inst.error = BAD_ARGS;
9371 return;
9372 }
9373
9374 if (inst.reloc.type != BFD_RELOC_UNUSED)
9375 {
9376 /* This really doesn't seem worth it. */
9377 inst.reloc.type = BFD_RELOC_UNUSED;
9378 inst.error = _("expression too complex");
9379 return;
9380 }
9381
9382 if (range & ~0xff)
9383 {
9384 inst.error = _("only lo-regs valid in load/store multiple");
9385 return;
9386 }
9387
9388 inst.instruction |= (Rb << 8) | range;
9389 end_of_line (str);
9390 }
9391
9392 static void
9393 do_t_ldr (char * str)
9394 {
9395 thumb_load_store (str, THUMB_LOAD, THUMB_WORD);
9396 }
9397
9398 static void
9399 do_t_ldrb (char * str)
9400 {
9401 thumb_load_store (str, THUMB_LOAD, THUMB_BYTE);
9402 }
9403
9404 static void
9405 do_t_ldrh (char * str)
9406 {
9407 thumb_load_store (str, THUMB_LOAD, THUMB_HALFWORD);
9408 }
9409
9410 static void
9411 do_t_lds (char * str)
9412 {
9413 int Rd, Rb, Ro;
9414
9415 skip_whitespace (str);
9416
9417 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9418 || skip_past_comma (&str) == FAIL
9419 || *str++ != '['
9420 || (Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9421 || skip_past_comma (&str) == FAIL
9422 || (Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9423 || *str++ != ']')
9424 {
9425 if (! inst.error)
9426 inst.error = _("syntax: ldrs[b] Rd, [Rb, Ro]");
9427 return;
9428 }
9429
9430 inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
9431 end_of_line (str);
9432 }
9433
9434 static void
9435 do_t_lsl (char * str)
9436 {
9437 thumb_shift (str, THUMB_LSL);
9438 }
9439
9440 static void
9441 do_t_lsr (char * str)
9442 {
9443 thumb_shift (str, THUMB_LSR);
9444 }
9445
9446 static void
9447 do_t_mov (char * str)
9448 {
9449 thumb_mov_compare (str, THUMB_MOVE);
9450 }
9451
9452 static void
9453 do_t_push_pop (char * str)
9454 {
9455 long range;
9456
9457 skip_whitespace (str);
9458
9459 if ((range = reg_list (&str)) == FAIL)
9460 {
9461 if (! inst.error)
9462 inst.error = BAD_ARGS;
9463 return;
9464 }
9465
9466 if (inst.reloc.type != BFD_RELOC_UNUSED)
9467 {
9468 /* This really doesn't seem worth it. */
9469 inst.reloc.type = BFD_RELOC_UNUSED;
9470 inst.error = _("expression too complex");
9471 return;
9472 }
9473
9474 if (range & ~0xff)
9475 {
9476 if ((inst.instruction == T_OPCODE_PUSH
9477 && (range & ~0xff) == 1 << REG_LR)
9478 || (inst.instruction == T_OPCODE_POP
9479 && (range & ~0xff) == 1 << REG_PC))
9480 {
9481 inst.instruction |= THUMB_PP_PC_LR;
9482 range &= 0xff;
9483 }
9484 else
9485 {
9486 inst.error = _("invalid register list to push/pop instruction");
9487 return;
9488 }
9489 }
9490
9491 inst.instruction |= range;
9492 end_of_line (str);
9493 }
9494
9495 static void
9496 do_t_str (char * str)
9497 {
9498 thumb_load_store (str, THUMB_STORE, THUMB_WORD);
9499 }
9500
9501 static void
9502 do_t_strb (char * str)
9503 {
9504 thumb_load_store (str, THUMB_STORE, THUMB_BYTE);
9505 }
9506
9507 static void
9508 do_t_strh (char * str)
9509 {
9510 thumb_load_store (str, THUMB_STORE, THUMB_HALFWORD);
9511 }
9512
9513 static void
9514 do_t_sub (char * str)
9515 {
9516 thumb_add_sub (str, 1);
9517 }
9518
9519 static void
9520 do_t_swi (char * str)
9521 {
9522 skip_whitespace (str);
9523
9524 if (my_get_expression (&inst.reloc.exp, &str))
9525 return;
9526
9527 inst.reloc.type = BFD_RELOC_ARM_SWI;
9528 end_of_line (str);
9529 }
9530
9531 static void
9532 do_t_adr (char * str)
9533 {
9534 int reg;
9535
9536 /* This is a pseudo-op of the form "adr rd, label" to be converted
9537 into a relative address of the form "add rd, pc, #label-.-4". */
9538 skip_whitespace (str);
9539
9540 /* Store Rd in temporary location inside instruction. */
9541 if ((reg = reg_required_here (&str, 4)) == FAIL
9542 || (reg > 7) /* For Thumb reg must be r0..r7. */
9543 || skip_past_comma (&str) == FAIL
9544 || my_get_expression (&inst.reloc.exp, &str))
9545 {
9546 if (!inst.error)
9547 inst.error = BAD_ARGS;
9548 return;
9549 }
9550
9551 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
9552 inst.reloc.exp.X_add_number -= 4; /* PC relative adjust. */
9553 inst.reloc.pc_rel = 1;
9554 inst.instruction |= REG_PC; /* Rd is already placed into the instruction. */
9555
9556 end_of_line (str);
9557 }
9558
9559 static void
9560 insert_reg (const struct reg_entry * r,
9561 struct hash_control * htab)
9562 {
9563 int len = strlen (r->name) + 2;
9564 char * buf = xmalloc (len);
9565 char * buf2 = xmalloc (len);
9566 int i = 0;
9567
9568 #ifdef REGISTER_PREFIX
9569 buf[i++] = REGISTER_PREFIX;
9570 #endif
9571
9572 strcpy (buf + i, r->name);
9573
9574 for (i = 0; buf[i]; i++)
9575 buf2[i] = TOUPPER (buf[i]);
9576
9577 buf2[i] = '\0';
9578
9579 hash_insert (htab, buf, (PTR) r);
9580 hash_insert (htab, buf2, (PTR) r);
9581 }
9582
9583 static void
9584 build_reg_hsh (struct reg_map * map)
9585 {
9586 const struct reg_entry *r;
9587
9588 if ((map->htab = hash_new ()) == NULL)
9589 as_fatal (_("virtual memory exhausted"));
9590
9591 for (r = map->names; r->name != NULL; r++)
9592 insert_reg (r, map->htab);
9593 }
9594
9595 static void
9596 insert_reg_alias (char * str,
9597 int regnum,
9598 struct hash_control *htab)
9599 {
9600 const char * error;
9601 struct reg_entry * new = xmalloc (sizeof (struct reg_entry));
9602 const char * name = xmalloc (strlen (str) + 1);
9603
9604 strcpy ((char *) name, str);
9605
9606 new->name = name;
9607 new->number = regnum;
9608 new->builtin = FALSE;
9609
9610 error = hash_insert (htab, name, (PTR) new);
9611 if (error)
9612 {
9613 as_bad (_("failed to create an alias for %s, reason: %s"),
9614 str, error);
9615 free ((char *) name);
9616 free (new);
9617 }
9618 }
9619
9620 /* Look for the .req directive. This is of the form:
9621
9622 new_register_name .req existing_register_name
9623
9624 If we find one, or if it looks sufficiently like one that we want to
9625 handle any error here, return non-zero. Otherwise return zero. */
9626
9627 static int
9628 create_register_alias (char * newname, char * p)
9629 {
9630 char * q;
9631 char c;
9632
9633 q = p;
9634 skip_whitespace (q);
9635
9636 c = *p;
9637 *p = '\0';
9638
9639 if (*q && !strncmp (q, ".req ", 5))
9640 {
9641 char *copy_of_str;
9642 char *r;
9643
9644 #ifndef IGNORE_OPCODE_CASE
9645 newname = original_case_string;
9646 #endif
9647 copy_of_str = newname;
9648
9649 q += 4;
9650 skip_whitespace (q);
9651
9652 for (r = q; *r != '\0'; r++)
9653 if (*r == ' ')
9654 break;
9655
9656 if (r != q)
9657 {
9658 enum arm_reg_type new_type, old_type;
9659 int old_regno;
9660 char d = *r;
9661
9662 *r = '\0';
9663 old_type = arm_reg_parse_any (q);
9664 *r = d;
9665
9666 new_type = arm_reg_parse_any (newname);
9667
9668 if (new_type == REG_TYPE_MAX)
9669 {
9670 if (old_type != REG_TYPE_MAX)
9671 {
9672 old_regno = arm_reg_parse (&q, all_reg_maps[old_type].htab);
9673 insert_reg_alias (newname, old_regno,
9674 all_reg_maps[old_type].htab);
9675 }
9676 else
9677 as_warn (_("register '%s' does not exist\n"), q);
9678 }
9679 else if (old_type == REG_TYPE_MAX)
9680 {
9681 as_warn (_("ignoring redefinition of register alias '%s' to non-existant register '%s'"),
9682 copy_of_str, q);
9683 }
9684 else
9685 {
9686 /* Do not warn about redefinitions to the same alias. */
9687 if (new_type != old_type
9688 || (arm_reg_parse (&q, all_reg_maps[old_type].htab)
9689 != arm_reg_parse (&q, all_reg_maps[new_type].htab)))
9690 as_warn (_("ignoring redefinition of register alias '%s'"),
9691 copy_of_str);
9692
9693 }
9694 }
9695 else
9696 as_warn (_("ignoring incomplete .req pseuso op"));
9697
9698 *p = c;
9699 return 1;
9700 }
9701
9702 *p = c;
9703 return 0;
9704 }
9705
9706 static void
9707 set_constant_flonums (void)
9708 {
9709 int i;
9710
9711 for (i = 0; i < NUM_FLOAT_VALS; i++)
9712 if (atof_ieee ((char *) fp_const[i], 'x', fp_values[i]) == NULL)
9713 abort ();
9714 }
9715
9716 \f
9717 static const struct asm_opcode insns[] =
9718 {
9719 /* Core ARM Instructions. */
9720 {"and", 0xe0000000, 3, ARM_EXT_V1, do_arit},
9721 {"ands", 0xe0100000, 3, ARM_EXT_V1, do_arit},
9722 {"eor", 0xe0200000, 3, ARM_EXT_V1, do_arit},
9723 {"eors", 0xe0300000, 3, ARM_EXT_V1, do_arit},
9724 {"sub", 0xe0400000, 3, ARM_EXT_V1, do_arit},
9725 {"subs", 0xe0500000, 3, ARM_EXT_V1, do_arit},
9726 {"rsb", 0xe0600000, 3, ARM_EXT_V1, do_arit},
9727 {"rsbs", 0xe0700000, 3, ARM_EXT_V1, do_arit},
9728 {"add", 0xe0800000, 3, ARM_EXT_V1, do_arit},
9729 {"adds", 0xe0900000, 3, ARM_EXT_V1, do_arit},
9730 {"adc", 0xe0a00000, 3, ARM_EXT_V1, do_arit},
9731 {"adcs", 0xe0b00000, 3, ARM_EXT_V1, do_arit},
9732 {"sbc", 0xe0c00000, 3, ARM_EXT_V1, do_arit},
9733 {"sbcs", 0xe0d00000, 3, ARM_EXT_V1, do_arit},
9734 {"rsc", 0xe0e00000, 3, ARM_EXT_V1, do_arit},
9735 {"rscs", 0xe0f00000, 3, ARM_EXT_V1, do_arit},
9736 {"orr", 0xe1800000, 3, ARM_EXT_V1, do_arit},
9737 {"orrs", 0xe1900000, 3, ARM_EXT_V1, do_arit},
9738 {"bic", 0xe1c00000, 3, ARM_EXT_V1, do_arit},
9739 {"bics", 0xe1d00000, 3, ARM_EXT_V1, do_arit},
9740
9741 {"tst", 0xe1100000, 3, ARM_EXT_V1, do_cmp},
9742 {"tsts", 0xe1100000, 3, ARM_EXT_V1, do_cmp},
9743 {"tstp", 0xe110f000, 3, ARM_EXT_V1, do_cmp},
9744 {"teq", 0xe1300000, 3, ARM_EXT_V1, do_cmp},
9745 {"teqs", 0xe1300000, 3, ARM_EXT_V1, do_cmp},
9746 {"teqp", 0xe130f000, 3, ARM_EXT_V1, do_cmp},
9747 {"cmp", 0xe1500000, 3, ARM_EXT_V1, do_cmp},
9748 {"cmps", 0xe1500000, 3, ARM_EXT_V1, do_cmp},
9749 {"cmpp", 0xe150f000, 3, ARM_EXT_V1, do_cmp},
9750 {"cmn", 0xe1700000, 3, ARM_EXT_V1, do_cmp},
9751 {"cmns", 0xe1700000, 3, ARM_EXT_V1, do_cmp},
9752 {"cmnp", 0xe170f000, 3, ARM_EXT_V1, do_cmp},
9753
9754 {"mov", 0xe1a00000, 3, ARM_EXT_V1, do_mov},
9755 {"movs", 0xe1b00000, 3, ARM_EXT_V1, do_mov},
9756 {"mvn", 0xe1e00000, 3, ARM_EXT_V1, do_mov},
9757 {"mvns", 0xe1f00000, 3, ARM_EXT_V1, do_mov},
9758
9759 {"ldr", 0xe4100000, 3, ARM_EXT_V1, do_ldst},
9760 {"ldrb", 0xe4500000, 3, ARM_EXT_V1, do_ldst},
9761 {"ldrt", 0xe4300000, 3, ARM_EXT_V1, do_ldstt},
9762 {"ldrbt", 0xe4700000, 3, ARM_EXT_V1, do_ldstt},
9763 {"str", 0xe4000000, 3, ARM_EXT_V1, do_ldst},
9764 {"strb", 0xe4400000, 3, ARM_EXT_V1, do_ldst},
9765 {"strt", 0xe4200000, 3, ARM_EXT_V1, do_ldstt},
9766 {"strbt", 0xe4600000, 3, ARM_EXT_V1, do_ldstt},
9767
9768 {"stmia", 0xe8800000, 3, ARM_EXT_V1, do_ldmstm},
9769 {"stmib", 0xe9800000, 3, ARM_EXT_V1, do_ldmstm},
9770 {"stmda", 0xe8000000, 3, ARM_EXT_V1, do_ldmstm},
9771 {"stmdb", 0xe9000000, 3, ARM_EXT_V1, do_ldmstm},
9772 {"stmfd", 0xe9000000, 3, ARM_EXT_V1, do_ldmstm},
9773 {"stmfa", 0xe9800000, 3, ARM_EXT_V1, do_ldmstm},
9774 {"stmea", 0xe8800000, 3, ARM_EXT_V1, do_ldmstm},
9775 {"stmed", 0xe8000000, 3, ARM_EXT_V1, do_ldmstm},
9776
9777 {"ldmia", 0xe8900000, 3, ARM_EXT_V1, do_ldmstm},
9778 {"ldmib", 0xe9900000, 3, ARM_EXT_V1, do_ldmstm},
9779 {"ldmda", 0xe8100000, 3, ARM_EXT_V1, do_ldmstm},
9780 {"ldmdb", 0xe9100000, 3, ARM_EXT_V1, do_ldmstm},
9781 {"ldmfd", 0xe8900000, 3, ARM_EXT_V1, do_ldmstm},
9782 {"ldmfa", 0xe8100000, 3, ARM_EXT_V1, do_ldmstm},
9783 {"ldmea", 0xe9100000, 3, ARM_EXT_V1, do_ldmstm},
9784 {"ldmed", 0xe9900000, 3, ARM_EXT_V1, do_ldmstm},
9785
9786 {"swi", 0xef000000, 3, ARM_EXT_V1, do_swi},
9787 #ifdef TE_WINCE
9788 /* XXX This is the wrong place to do this. Think multi-arch. */
9789 {"bl", 0xeb000000, 2, ARM_EXT_V1, do_branch},
9790 {"b", 0xea000000, 1, ARM_EXT_V1, do_branch},
9791 #else
9792 {"bl", 0xebfffffe, 2, ARM_EXT_V1, do_branch},
9793 {"b", 0xeafffffe, 1, ARM_EXT_V1, do_branch},
9794 #endif
9795
9796 /* Pseudo ops. */
9797 {"adr", 0xe28f0000, 3, ARM_EXT_V1, do_adr},
9798 {"adrl", 0xe28f0000, 3, ARM_EXT_V1, do_adrl},
9799 {"nop", 0xe1a00000, 3, ARM_EXT_V1, do_nop},
9800
9801 /* ARM 2 multiplies. */
9802 {"mul", 0xe0000090, 3, ARM_EXT_V2, do_mul},
9803 {"muls", 0xe0100090, 3, ARM_EXT_V2, do_mul},
9804 {"mla", 0xe0200090, 3, ARM_EXT_V2, do_mla},
9805 {"mlas", 0xe0300090, 3, ARM_EXT_V2, do_mla},
9806
9807 /* Generic coprocessor instructions. */
9808 {"cdp", 0xee000000, 3, ARM_EXT_V2, do_cdp},
9809 {"ldc", 0xec100000, 3, ARM_EXT_V2, do_lstc},
9810 {"ldcl", 0xec500000, 3, ARM_EXT_V2, do_lstc},
9811 {"stc", 0xec000000, 3, ARM_EXT_V2, do_lstc},
9812 {"stcl", 0xec400000, 3, ARM_EXT_V2, do_lstc},
9813 {"mcr", 0xee000010, 3, ARM_EXT_V2, do_co_reg},
9814 {"mrc", 0xee100010, 3, ARM_EXT_V2, do_co_reg},
9815
9816 /* ARM 3 - swp instructions. */
9817 {"swp", 0xe1000090, 3, ARM_EXT_V2S, do_swap},
9818 {"swpb", 0xe1400090, 3, ARM_EXT_V2S, do_swap},
9819
9820 /* ARM 6 Status register instructions. */
9821 {"mrs", 0xe10f0000, 3, ARM_EXT_V3, do_mrs},
9822 {"msr", 0xe120f000, 3, ARM_EXT_V3, do_msr},
9823 /* ScottB: our code uses 0xe128f000 for msr.
9824 NickC: but this is wrong because the bits 16 through 19 are
9825 handled by the PSR_xxx defines above. */
9826
9827 /* ARM 7M long multiplies. */
9828 {"smull", 0xe0c00090, 5, ARM_EXT_V3M, do_mull},
9829 {"smulls", 0xe0d00090, 5, ARM_EXT_V3M, do_mull},
9830 {"umull", 0xe0800090, 5, ARM_EXT_V3M, do_mull},
9831 {"umulls", 0xe0900090, 5, ARM_EXT_V3M, do_mull},
9832 {"smlal", 0xe0e00090, 5, ARM_EXT_V3M, do_mull},
9833 {"smlals", 0xe0f00090, 5, ARM_EXT_V3M, do_mull},
9834 {"umlal", 0xe0a00090, 5, ARM_EXT_V3M, do_mull},
9835 {"umlals", 0xe0b00090, 5, ARM_EXT_V3M, do_mull},
9836
9837 /* ARM Architecture 4. */
9838 {"ldrh", 0xe01000b0, 3, ARM_EXT_V4, do_ldstv4},
9839 {"ldrsh", 0xe01000f0, 3, ARM_EXT_V4, do_ldstv4},
9840 {"ldrsb", 0xe01000d0, 3, ARM_EXT_V4, do_ldstv4},
9841 {"strh", 0xe00000b0, 3, ARM_EXT_V4, do_ldstv4},
9842
9843 /* ARM Architecture 4T. */
9844 /* Note: bx (and blx) are required on V5, even if the processor does
9845 not support Thumb. */
9846 {"bx", 0xe12fff10, 2, ARM_EXT_V4T | ARM_EXT_V5, do_bx},
9847
9848 /* ARM Architecture 5T. */
9849 /* Note: blx has 2 variants, so the .value is set dynamically.
9850 Only one of the variants has conditional execution. */
9851 {"blx", 0xe0000000, 3, ARM_EXT_V5, do_blx},
9852 {"clz", 0xe16f0f10, 3, ARM_EXT_V5, do_clz},
9853 {"bkpt", 0xe1200070, 0, ARM_EXT_V5, do_bkpt},
9854 {"ldc2", 0xfc100000, 0, ARM_EXT_V5, do_lstc2},
9855 {"ldc2l", 0xfc500000, 0, ARM_EXT_V5, do_lstc2},
9856 {"stc2", 0xfc000000, 0, ARM_EXT_V5, do_lstc2},
9857 {"stc2l", 0xfc400000, 0, ARM_EXT_V5, do_lstc2},
9858 {"cdp2", 0xfe000000, 0, ARM_EXT_V5, do_cdp2},
9859 {"mcr2", 0xfe000010, 0, ARM_EXT_V5, do_co_reg2},
9860 {"mrc2", 0xfe100010, 0, ARM_EXT_V5, do_co_reg2},
9861
9862 /* ARM Architecture 5TExP. */
9863 {"smlabb", 0xe1000080, 6, ARM_EXT_V5ExP, do_smla},
9864 {"smlatb", 0xe10000a0, 6, ARM_EXT_V5ExP, do_smla},
9865 {"smlabt", 0xe10000c0, 6, ARM_EXT_V5ExP, do_smla},
9866 {"smlatt", 0xe10000e0, 6, ARM_EXT_V5ExP, do_smla},
9867
9868 {"smlawb", 0xe1200080, 6, ARM_EXT_V5ExP, do_smla},
9869 {"smlawt", 0xe12000c0, 6, ARM_EXT_V5ExP, do_smla},
9870
9871 {"smlalbb", 0xe1400080, 7, ARM_EXT_V5ExP, do_smlal},
9872 {"smlaltb", 0xe14000a0, 7, ARM_EXT_V5ExP, do_smlal},
9873 {"smlalbt", 0xe14000c0, 7, ARM_EXT_V5ExP, do_smlal},
9874 {"smlaltt", 0xe14000e0, 7, ARM_EXT_V5ExP, do_smlal},
9875
9876 {"smulbb", 0xe1600080, 6, ARM_EXT_V5ExP, do_smul},
9877 {"smultb", 0xe16000a0, 6, ARM_EXT_V5ExP, do_smul},
9878 {"smulbt", 0xe16000c0, 6, ARM_EXT_V5ExP, do_smul},
9879 {"smultt", 0xe16000e0, 6, ARM_EXT_V5ExP, do_smul},
9880
9881 {"smulwb", 0xe12000a0, 6, ARM_EXT_V5ExP, do_smul},
9882 {"smulwt", 0xe12000e0, 6, ARM_EXT_V5ExP, do_smul},
9883
9884 {"qadd", 0xe1000050, 4, ARM_EXT_V5ExP, do_qadd},
9885 {"qdadd", 0xe1400050, 5, ARM_EXT_V5ExP, do_qadd},
9886 {"qsub", 0xe1200050, 4, ARM_EXT_V5ExP, do_qadd},
9887 {"qdsub", 0xe1600050, 5, ARM_EXT_V5ExP, do_qadd},
9888
9889 /* ARM Architecture 5TE. */
9890 {"pld", 0xf450f000, 0, ARM_EXT_V5E, do_pld},
9891 {"ldrd", 0xe00000d0, 3, ARM_EXT_V5E, do_ldrd},
9892 {"strd", 0xe00000f0, 3, ARM_EXT_V5E, do_ldrd},
9893
9894 {"mcrr", 0xec400000, 4, ARM_EXT_V5E, do_co_reg2c},
9895 {"mrrc", 0xec500000, 4, ARM_EXT_V5E, do_co_reg2c},
9896
9897 /* ARM Architecture 5TEJ. */
9898 {"bxj", 0xe12fff20, 3, ARM_EXT_V5J, do_bxj},
9899
9900 /* ARM V6. */
9901 { "cps", 0xf1020000, 0, ARM_EXT_V6, do_cps},
9902 { "cpsie", 0xf1080000, 0, ARM_EXT_V6, do_cpsi},
9903 { "cpsid", 0xf10C0000, 0, ARM_EXT_V6, do_cpsi},
9904 { "ldrex", 0xe1900f9f, 5, ARM_EXT_V6, do_ldrex},
9905 { "mcrr2", 0xfc400000, 0, ARM_EXT_V6, do_co_reg2c},
9906 { "mrrc2", 0xfc500000, 0, ARM_EXT_V6, do_co_reg2c},
9907 { "pkhbt", 0xe6800010, 5, ARM_EXT_V6, do_pkhbt},
9908 { "pkhtb", 0xe6800050, 5, ARM_EXT_V6, do_pkhtb},
9909 { "qadd16", 0xe6200f10, 6, ARM_EXT_V6, do_qadd16},
9910 { "qadd8", 0xe6200f90, 5, ARM_EXT_V6, do_qadd16},
9911 { "qaddsubx", 0xe6200f30, 8, ARM_EXT_V6, do_qadd16},
9912 { "qsub16", 0xe6200f70, 6, ARM_EXT_V6, do_qadd16},
9913 { "qsub8", 0xe6200ff0, 5, ARM_EXT_V6, do_qadd16},
9914 { "qsubaddx", 0xe6200f50, 8, ARM_EXT_V6, do_qadd16},
9915 { "sadd16", 0xe6100f10, 6, ARM_EXT_V6, do_qadd16},
9916 { "sadd8", 0xe6100f90, 5, ARM_EXT_V6, do_qadd16},
9917 { "saddsubx", 0xe6100f30, 8, ARM_EXT_V6, do_qadd16},
9918 { "shadd16", 0xe6300f10, 7, ARM_EXT_V6, do_qadd16},
9919 { "shadd8", 0xe6300f90, 6, ARM_EXT_V6, do_qadd16},
9920 { "shaddsubx", 0xe6300f30, 9, ARM_EXT_V6, do_qadd16},
9921 { "shsub16", 0xe6300f70, 7, ARM_EXT_V6, do_qadd16},
9922 { "shsub8", 0xe6300ff0, 6, ARM_EXT_V6, do_qadd16},
9923 { "shsubaddx", 0xe6300f50, 9, ARM_EXT_V6, do_qadd16},
9924 { "ssub16", 0xe6100f70, 6, ARM_EXT_V6, do_qadd16},
9925 { "ssub8", 0xe6100ff0, 5, ARM_EXT_V6, do_qadd16},
9926 { "ssubaddx", 0xe6100f50, 8, ARM_EXT_V6, do_qadd16},
9927 { "uadd16", 0xe6500f10, 6, ARM_EXT_V6, do_qadd16},
9928 { "uadd8", 0xe6500f90, 5, ARM_EXT_V6, do_qadd16},
9929 { "uaddsubx", 0xe6500f30, 8, ARM_EXT_V6, do_qadd16},
9930 { "uhadd16", 0xe6700f10, 7, ARM_EXT_V6, do_qadd16},
9931 { "uhadd8", 0xe6700f90, 6, ARM_EXT_V6, do_qadd16},
9932 { "uhaddsubx", 0xe6700f30, 9, ARM_EXT_V6, do_qadd16},
9933 { "uhsub16", 0xe6700f70, 7, ARM_EXT_V6, do_qadd16},
9934 { "uhsub8", 0xe6700ff0, 6, ARM_EXT_V6, do_qadd16},
9935 { "uhsubaddx", 0xe6700f50, 9, ARM_EXT_V6, do_qadd16},
9936 { "uqadd16", 0xe6600f10, 7, ARM_EXT_V6, do_qadd16},
9937 { "uqadd8", 0xe6600f90, 6, ARM_EXT_V6, do_qadd16},
9938 { "uqaddsubx", 0xe6600f30, 9, ARM_EXT_V6, do_qadd16},
9939 { "uqsub16", 0xe6600f70, 7, ARM_EXT_V6, do_qadd16},
9940 { "uqsub8", 0xe6600ff0, 6, ARM_EXT_V6, do_qadd16},
9941 { "uqsubaddx", 0xe6600f50, 9, ARM_EXT_V6, do_qadd16},
9942 { "usub16", 0xe6500f70, 6, ARM_EXT_V6, do_qadd16},
9943 { "usub8", 0xe6500ff0, 5, ARM_EXT_V6, do_qadd16},
9944 { "usubaddx", 0xe6500f50, 8, ARM_EXT_V6, do_qadd16},
9945 { "rev", 0xe6bf0f30, 3, ARM_EXT_V6, do_rev},
9946 { "rev16", 0xe6bf0fb0, 5, ARM_EXT_V6, do_rev},
9947 { "revsh", 0xe6ff0fb0, 5, ARM_EXT_V6, do_rev},
9948 { "rfeia", 0xf8900a00, 0, ARM_EXT_V6, do_rfe},
9949 { "rfeib", 0xf9900a00, 0, ARM_EXT_V6, do_rfe},
9950 { "rfeda", 0xf8100a00, 0, ARM_EXT_V6, do_rfe},
9951 { "rfedb", 0xf9100a00, 0, ARM_EXT_V6, do_rfe},
9952 { "rfefd", 0xf8900a00, 0, ARM_EXT_V6, do_rfe},
9953 { "rfefa", 0xf9900a00, 0, ARM_EXT_V6, do_rfe},
9954 { "rfeea", 0xf8100a00, 0, ARM_EXT_V6, do_rfe},
9955 { "rfeed", 0xf9100a00, 0, ARM_EXT_V6, do_rfe},
9956 { "sxtah", 0xe6b00070, 5, ARM_EXT_V6, do_sxtah},
9957 { "sxtab16", 0xe6800070, 7, ARM_EXT_V6, do_sxtah},
9958 { "sxtab", 0xe6a00070, 5, ARM_EXT_V6, do_sxtah},
9959 { "sxth", 0xe6bf0070, 4, ARM_EXT_V6, do_sxth},
9960 { "sxtb16", 0xe68f0070, 6, ARM_EXT_V6, do_sxth},
9961 { "sxtb", 0xe6af0070, 4, ARM_EXT_V6, do_sxth},
9962 { "uxtah", 0xe6f00070, 5, ARM_EXT_V6, do_sxtah},
9963 { "uxtab16", 0xe6c00070, 7, ARM_EXT_V6, do_sxtah},
9964 { "uxtab", 0xe6e00070, 5, ARM_EXT_V6, do_sxtah},
9965 { "uxth", 0xe6ff0070, 4, ARM_EXT_V6, do_sxth},
9966 { "uxtb16", 0xe6cf0070, 6, ARM_EXT_V6, do_sxth},
9967 { "uxtb", 0xe6ef0070, 4, ARM_EXT_V6, do_sxth},
9968 { "sel", 0xe68000b0, 3, ARM_EXT_V6, do_qadd16},
9969 { "setend", 0xf1010000, 0, ARM_EXT_V6, do_setend},
9970 { "smlad", 0xe7000010, 5, ARM_EXT_V6, do_smlad},
9971 { "smladx", 0xe7000030, 6, ARM_EXT_V6, do_smlad},
9972 { "smlald", 0xe7400010, 6, ARM_EXT_V6, do_smlald},
9973 { "smlaldx", 0xe7400030, 7, ARM_EXT_V6, do_smlald},
9974 { "smlsd", 0xe7000050, 5, ARM_EXT_V6, do_smlad},
9975 { "smlsdx", 0xe7000070, 6, ARM_EXT_V6, do_smlad},
9976 { "smlsld", 0xe7400050, 6, ARM_EXT_V6, do_smlald},
9977 { "smlsldx", 0xe7400070, 7, ARM_EXT_V6, do_smlald},
9978 { "smmla", 0xe7500010, 5, ARM_EXT_V6, do_smlad},
9979 { "smmlar", 0xe7500030, 6, ARM_EXT_V6, do_smlad},
9980 { "smmls", 0xe75000d0, 5, ARM_EXT_V6, do_smlad},
9981 { "smmlsr", 0xe75000f0, 6, ARM_EXT_V6, do_smlad},
9982 { "smmul", 0xe750f010, 5, ARM_EXT_V6, do_smmul},
9983 { "smmulr", 0xe750f030, 6, ARM_EXT_V6, do_smmul},
9984 { "smuad", 0xe700f010, 5, ARM_EXT_V6, do_smmul},
9985 { "smuadx", 0xe700f030, 6, ARM_EXT_V6, do_smmul},
9986 { "smusd", 0xe700f050, 5, ARM_EXT_V6, do_smmul},
9987 { "smusdx", 0xe700f070, 6, ARM_EXT_V6, do_smmul},
9988 { "srsia", 0xf8cd0500, 0, ARM_EXT_V6, do_srs},
9989 { "srsib", 0xf9cd0500, 0, ARM_EXT_V6, do_srs},
9990 { "srsda", 0xf84d0500, 0, ARM_EXT_V6, do_srs},
9991 { "srsdb", 0xf94d0500, 0, ARM_EXT_V6, do_srs},
9992 { "ssat", 0xe6a00010, 4, ARM_EXT_V6, do_ssat},
9993 { "ssat16", 0xe6a00f30, 6, ARM_EXT_V6, do_ssat16},
9994 { "strex", 0xe1800f90, 5, ARM_EXT_V6, do_strex},
9995 { "umaal", 0xe0400090, 5, ARM_EXT_V6, do_umaal},
9996 { "usad8", 0xe780f010, 5, ARM_EXT_V6, do_smmul},
9997 { "usada8", 0xe7800010, 6, ARM_EXT_V6, do_smlad},
9998 { "usat", 0xe6e00010, 4, ARM_EXT_V6, do_usat},
9999 { "usat16", 0xe6e00f30, 6, ARM_EXT_V6, do_usat16},
10000
10001 /* ARM V6K. */
10002 { "clrex", 0xf57ff01f, 0, ARM_EXT_V6K, do_empty},
10003 { "ldrexb", 0xe1d00f9f, 6, ARM_EXT_V6K, do_ldrex},
10004 { "ldrexd", 0xe1b00f9f, 6, ARM_EXT_V6K, do_ldrex},
10005 { "ldrexh", 0xe1f00f9f, 6, ARM_EXT_V6K, do_ldrex},
10006 { "sev", 0xe320f004, 3, ARM_EXT_V6K, do_empty},
10007 { "strexb", 0xe1c00f90, 6, ARM_EXT_V6K, do_strex},
10008 { "strexd", 0xe1a00f90, 6, ARM_EXT_V6K, do_strex},
10009 { "strexh", 0xe1e00f90, 6, ARM_EXT_V6K, do_strex},
10010 { "wfe", 0xe320f002, 3, ARM_EXT_V6K, do_empty},
10011 { "wfi", 0xe320f003, 3, ARM_EXT_V6K, do_empty},
10012 { "yield", 0xe320f001, 5, ARM_EXT_V6K, do_empty},
10013
10014 /* ARM V6Z. */
10015 { "smi", 0xe1600070, 3, ARM_EXT_V6Z, do_smi},
10016
10017 /* Core FPA instruction set (V1). */
10018 {"wfs", 0xee200110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
10019 {"rfs", 0xee300110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
10020 {"wfc", 0xee400110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
10021 {"rfc", 0xee500110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
10022
10023 {"ldfs", 0xec100100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10024 {"ldfd", 0xec108100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10025 {"ldfe", 0xec500100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10026 {"ldfp", 0xec508100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10027
10028 {"stfs", 0xec000100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10029 {"stfd", 0xec008100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10030 {"stfe", 0xec400100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10031 {"stfp", 0xec408100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10032
10033 {"mvfs", 0xee008100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10034 {"mvfsp", 0xee008120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10035 {"mvfsm", 0xee008140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10036 {"mvfsz", 0xee008160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10037 {"mvfd", 0xee008180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10038 {"mvfdp", 0xee0081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10039 {"mvfdm", 0xee0081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10040 {"mvfdz", 0xee0081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10041 {"mvfe", 0xee088100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10042 {"mvfep", 0xee088120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10043 {"mvfem", 0xee088140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10044 {"mvfez", 0xee088160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10045
10046 {"mnfs", 0xee108100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10047 {"mnfsp", 0xee108120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10048 {"mnfsm", 0xee108140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10049 {"mnfsz", 0xee108160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10050 {"mnfd", 0xee108180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10051 {"mnfdp", 0xee1081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10052 {"mnfdm", 0xee1081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10053 {"mnfdz", 0xee1081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10054 {"mnfe", 0xee188100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10055 {"mnfep", 0xee188120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10056 {"mnfem", 0xee188140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10057 {"mnfez", 0xee188160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10058
10059 {"abss", 0xee208100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10060 {"abssp", 0xee208120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10061 {"abssm", 0xee208140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10062 {"abssz", 0xee208160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10063 {"absd", 0xee208180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10064 {"absdp", 0xee2081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10065 {"absdm", 0xee2081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10066 {"absdz", 0xee2081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10067 {"abse", 0xee288100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10068 {"absep", 0xee288120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10069 {"absem", 0xee288140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10070 {"absez", 0xee288160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10071
10072 {"rnds", 0xee308100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10073 {"rndsp", 0xee308120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10074 {"rndsm", 0xee308140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10075 {"rndsz", 0xee308160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10076 {"rndd", 0xee308180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10077 {"rnddp", 0xee3081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10078 {"rnddm", 0xee3081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10079 {"rnddz", 0xee3081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10080 {"rnde", 0xee388100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10081 {"rndep", 0xee388120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10082 {"rndem", 0xee388140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10083 {"rndez", 0xee388160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10084
10085 {"sqts", 0xee408100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10086 {"sqtsp", 0xee408120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10087 {"sqtsm", 0xee408140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10088 {"sqtsz", 0xee408160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10089 {"sqtd", 0xee408180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10090 {"sqtdp", 0xee4081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10091 {"sqtdm", 0xee4081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10092 {"sqtdz", 0xee4081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10093 {"sqte", 0xee488100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10094 {"sqtep", 0xee488120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10095 {"sqtem", 0xee488140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10096 {"sqtez", 0xee488160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10097
10098 {"logs", 0xee508100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10099 {"logsp", 0xee508120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10100 {"logsm", 0xee508140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10101 {"logsz", 0xee508160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10102 {"logd", 0xee508180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10103 {"logdp", 0xee5081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10104 {"logdm", 0xee5081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10105 {"logdz", 0xee5081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10106 {"loge", 0xee588100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10107 {"logep", 0xee588120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10108 {"logem", 0xee588140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10109 {"logez", 0xee588160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10110
10111 {"lgns", 0xee608100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10112 {"lgnsp", 0xee608120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10113 {"lgnsm", 0xee608140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10114 {"lgnsz", 0xee608160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10115 {"lgnd", 0xee608180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10116 {"lgndp", 0xee6081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10117 {"lgndm", 0xee6081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10118 {"lgndz", 0xee6081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10119 {"lgne", 0xee688100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10120 {"lgnep", 0xee688120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10121 {"lgnem", 0xee688140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10122 {"lgnez", 0xee688160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10123
10124 {"exps", 0xee708100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10125 {"expsp", 0xee708120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10126 {"expsm", 0xee708140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10127 {"expsz", 0xee708160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10128 {"expd", 0xee708180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10129 {"expdp", 0xee7081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10130 {"expdm", 0xee7081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10131 {"expdz", 0xee7081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10132 {"expe", 0xee788100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10133 {"expep", 0xee788120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10134 {"expem", 0xee788140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10135 {"expdz", 0xee788160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10136
10137 {"sins", 0xee808100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10138 {"sinsp", 0xee808120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10139 {"sinsm", 0xee808140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10140 {"sinsz", 0xee808160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10141 {"sind", 0xee808180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10142 {"sindp", 0xee8081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10143 {"sindm", 0xee8081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10144 {"sindz", 0xee8081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10145 {"sine", 0xee888100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10146 {"sinep", 0xee888120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10147 {"sinem", 0xee888140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10148 {"sinez", 0xee888160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10149
10150 {"coss", 0xee908100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10151 {"cossp", 0xee908120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10152 {"cossm", 0xee908140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10153 {"cossz", 0xee908160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10154 {"cosd", 0xee908180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10155 {"cosdp", 0xee9081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10156 {"cosdm", 0xee9081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10157 {"cosdz", 0xee9081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10158 {"cose", 0xee988100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10159 {"cosep", 0xee988120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10160 {"cosem", 0xee988140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10161 {"cosez", 0xee988160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10162
10163 {"tans", 0xeea08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10164 {"tansp", 0xeea08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10165 {"tansm", 0xeea08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10166 {"tansz", 0xeea08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10167 {"tand", 0xeea08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10168 {"tandp", 0xeea081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10169 {"tandm", 0xeea081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10170 {"tandz", 0xeea081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10171 {"tane", 0xeea88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10172 {"tanep", 0xeea88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10173 {"tanem", 0xeea88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10174 {"tanez", 0xeea88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10175
10176 {"asns", 0xeeb08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10177 {"asnsp", 0xeeb08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10178 {"asnsm", 0xeeb08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10179 {"asnsz", 0xeeb08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10180 {"asnd", 0xeeb08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10181 {"asndp", 0xeeb081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10182 {"asndm", 0xeeb081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10183 {"asndz", 0xeeb081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10184 {"asne", 0xeeb88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10185 {"asnep", 0xeeb88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10186 {"asnem", 0xeeb88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10187 {"asnez", 0xeeb88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10188
10189 {"acss", 0xeec08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10190 {"acssp", 0xeec08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10191 {"acssm", 0xeec08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10192 {"acssz", 0xeec08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10193 {"acsd", 0xeec08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10194 {"acsdp", 0xeec081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10195 {"acsdm", 0xeec081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10196 {"acsdz", 0xeec081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10197 {"acse", 0xeec88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10198 {"acsep", 0xeec88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10199 {"acsem", 0xeec88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10200 {"acsez", 0xeec88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10201
10202 {"atns", 0xeed08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10203 {"atnsp", 0xeed08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10204 {"atnsm", 0xeed08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10205 {"atnsz", 0xeed08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10206 {"atnd", 0xeed08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10207 {"atndp", 0xeed081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10208 {"atndm", 0xeed081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10209 {"atndz", 0xeed081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10210 {"atne", 0xeed88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10211 {"atnep", 0xeed88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10212 {"atnem", 0xeed88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10213 {"atnez", 0xeed88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10214
10215 {"urds", 0xeee08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10216 {"urdsp", 0xeee08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10217 {"urdsm", 0xeee08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10218 {"urdsz", 0xeee08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10219 {"urdd", 0xeee08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10220 {"urddp", 0xeee081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10221 {"urddm", 0xeee081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10222 {"urddz", 0xeee081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10223 {"urde", 0xeee88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10224 {"urdep", 0xeee88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10225 {"urdem", 0xeee88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10226 {"urdez", 0xeee88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10227
10228 {"nrms", 0xeef08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10229 {"nrmsp", 0xeef08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10230 {"nrmsm", 0xeef08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10231 {"nrmsz", 0xeef08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10232 {"nrmd", 0xeef08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10233 {"nrmdp", 0xeef081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10234 {"nrmdm", 0xeef081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10235 {"nrmdz", 0xeef081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10236 {"nrme", 0xeef88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10237 {"nrmep", 0xeef88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10238 {"nrmem", 0xeef88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10239 {"nrmez", 0xeef88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10240
10241 {"adfs", 0xee000100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10242 {"adfsp", 0xee000120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10243 {"adfsm", 0xee000140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10244 {"adfsz", 0xee000160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10245 {"adfd", 0xee000180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10246 {"adfdp", 0xee0001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10247 {"adfdm", 0xee0001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10248 {"adfdz", 0xee0001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10249 {"adfe", 0xee080100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10250 {"adfep", 0xee080120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10251 {"adfem", 0xee080140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10252 {"adfez", 0xee080160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10253
10254 {"sufs", 0xee200100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10255 {"sufsp", 0xee200120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10256 {"sufsm", 0xee200140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10257 {"sufsz", 0xee200160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10258 {"sufd", 0xee200180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10259 {"sufdp", 0xee2001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10260 {"sufdm", 0xee2001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10261 {"sufdz", 0xee2001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10262 {"sufe", 0xee280100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10263 {"sufep", 0xee280120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10264 {"sufem", 0xee280140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10265 {"sufez", 0xee280160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10266
10267 {"rsfs", 0xee300100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10268 {"rsfsp", 0xee300120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10269 {"rsfsm", 0xee300140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10270 {"rsfsz", 0xee300160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10271 {"rsfd", 0xee300180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10272 {"rsfdp", 0xee3001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10273 {"rsfdm", 0xee3001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10274 {"rsfdz", 0xee3001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10275 {"rsfe", 0xee380100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10276 {"rsfep", 0xee380120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10277 {"rsfem", 0xee380140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10278 {"rsfez", 0xee380160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10279
10280 {"mufs", 0xee100100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10281 {"mufsp", 0xee100120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10282 {"mufsm", 0xee100140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10283 {"mufsz", 0xee100160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10284 {"mufd", 0xee100180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10285 {"mufdp", 0xee1001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10286 {"mufdm", 0xee1001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10287 {"mufdz", 0xee1001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10288 {"mufe", 0xee180100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10289 {"mufep", 0xee180120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10290 {"mufem", 0xee180140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10291 {"mufez", 0xee180160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10292
10293 {"dvfs", 0xee400100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10294 {"dvfsp", 0xee400120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10295 {"dvfsm", 0xee400140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10296 {"dvfsz", 0xee400160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10297 {"dvfd", 0xee400180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10298 {"dvfdp", 0xee4001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10299 {"dvfdm", 0xee4001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10300 {"dvfdz", 0xee4001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10301 {"dvfe", 0xee480100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10302 {"dvfep", 0xee480120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10303 {"dvfem", 0xee480140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10304 {"dvfez", 0xee480160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10305
10306 {"rdfs", 0xee500100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10307 {"rdfsp", 0xee500120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10308 {"rdfsm", 0xee500140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10309 {"rdfsz", 0xee500160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10310 {"rdfd", 0xee500180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10311 {"rdfdp", 0xee5001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10312 {"rdfdm", 0xee5001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10313 {"rdfdz", 0xee5001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10314 {"rdfe", 0xee580100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10315 {"rdfep", 0xee580120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10316 {"rdfem", 0xee580140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10317 {"rdfez", 0xee580160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10318
10319 {"pows", 0xee600100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10320 {"powsp", 0xee600120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10321 {"powsm", 0xee600140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10322 {"powsz", 0xee600160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10323 {"powd", 0xee600180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10324 {"powdp", 0xee6001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10325 {"powdm", 0xee6001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10326 {"powdz", 0xee6001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10327 {"powe", 0xee680100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10328 {"powep", 0xee680120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10329 {"powem", 0xee680140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10330 {"powez", 0xee680160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10331
10332 {"rpws", 0xee700100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10333 {"rpwsp", 0xee700120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10334 {"rpwsm", 0xee700140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10335 {"rpwsz", 0xee700160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10336 {"rpwd", 0xee700180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10337 {"rpwdp", 0xee7001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10338 {"rpwdm", 0xee7001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10339 {"rpwdz", 0xee7001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10340 {"rpwe", 0xee780100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10341 {"rpwep", 0xee780120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10342 {"rpwem", 0xee780140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10343 {"rpwez", 0xee780160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10344
10345 {"rmfs", 0xee800100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10346 {"rmfsp", 0xee800120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10347 {"rmfsm", 0xee800140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10348 {"rmfsz", 0xee800160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10349 {"rmfd", 0xee800180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10350 {"rmfdp", 0xee8001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10351 {"rmfdm", 0xee8001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10352 {"rmfdz", 0xee8001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10353 {"rmfe", 0xee880100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10354 {"rmfep", 0xee880120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10355 {"rmfem", 0xee880140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10356 {"rmfez", 0xee880160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10357
10358 {"fmls", 0xee900100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10359 {"fmlsp", 0xee900120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10360 {"fmlsm", 0xee900140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10361 {"fmlsz", 0xee900160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10362 {"fmld", 0xee900180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10363 {"fmldp", 0xee9001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10364 {"fmldm", 0xee9001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10365 {"fmldz", 0xee9001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10366 {"fmle", 0xee980100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10367 {"fmlep", 0xee980120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10368 {"fmlem", 0xee980140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10369 {"fmlez", 0xee980160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10370
10371 {"fdvs", 0xeea00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10372 {"fdvsp", 0xeea00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10373 {"fdvsm", 0xeea00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10374 {"fdvsz", 0xeea00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10375 {"fdvd", 0xeea00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10376 {"fdvdp", 0xeea001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10377 {"fdvdm", 0xeea001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10378 {"fdvdz", 0xeea001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10379 {"fdve", 0xeea80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10380 {"fdvep", 0xeea80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10381 {"fdvem", 0xeea80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10382 {"fdvez", 0xeea80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10383
10384 {"frds", 0xeeb00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10385 {"frdsp", 0xeeb00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10386 {"frdsm", 0xeeb00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10387 {"frdsz", 0xeeb00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10388 {"frdd", 0xeeb00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10389 {"frddp", 0xeeb001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10390 {"frddm", 0xeeb001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10391 {"frddz", 0xeeb001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10392 {"frde", 0xeeb80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10393 {"frdep", 0xeeb80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10394 {"frdem", 0xeeb80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10395 {"frdez", 0xeeb80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10396
10397 {"pols", 0xeec00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10398 {"polsp", 0xeec00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10399 {"polsm", 0xeec00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10400 {"polsz", 0xeec00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10401 {"pold", 0xeec00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10402 {"poldp", 0xeec001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10403 {"poldm", 0xeec001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10404 {"poldz", 0xeec001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10405 {"pole", 0xeec80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10406 {"polep", 0xeec80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10407 {"polem", 0xeec80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10408 {"polez", 0xeec80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10409
10410 {"cmf", 0xee90f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
10411 {"cmfe", 0xeed0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
10412 {"cnf", 0xeeb0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
10413 {"cnfe", 0xeef0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
10414 /* The FPA10 data sheet suggests that the 'E' of cmfe/cnfe should
10415 not be an optional suffix, but part of the instruction. To be
10416 compatible, we accept either. */
10417 {"cmfe", 0xeed0f110, 4, FPU_FPA_EXT_V1, do_fpa_cmp},
10418 {"cnfe", 0xeef0f110, 4, FPU_FPA_EXT_V1, do_fpa_cmp},
10419
10420 {"flts", 0xee000110, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10421 {"fltsp", 0xee000130, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10422 {"fltsm", 0xee000150, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10423 {"fltsz", 0xee000170, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10424 {"fltd", 0xee000190, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10425 {"fltdp", 0xee0001b0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10426 {"fltdm", 0xee0001d0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10427 {"fltdz", 0xee0001f0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10428 {"flte", 0xee080110, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10429 {"fltep", 0xee080130, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10430 {"fltem", 0xee080150, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10431 {"fltez", 0xee080170, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10432
10433 /* The implementation of the FIX instruction is broken on some
10434 assemblers, in that it accepts a precision specifier as well as a
10435 rounding specifier, despite the fact that this is meaningless.
10436 To be more compatible, we accept it as well, though of course it
10437 does not set any bits. */
10438 {"fix", 0xee100110, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10439 {"fixp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10440 {"fixm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10441 {"fixz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10442 {"fixsp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10443 {"fixsm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10444 {"fixsz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10445 {"fixdp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10446 {"fixdm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10447 {"fixdz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10448 {"fixep", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10449 {"fixem", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10450 {"fixez", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10451
10452 /* Instructions that were new with the real FPA, call them V2. */
10453 {"lfm", 0xec100200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10454 {"lfmfd", 0xec900200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10455 {"lfmea", 0xed100200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10456 {"sfm", 0xec000200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10457 {"sfmfd", 0xed000200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10458 {"sfmea", 0xec800200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10459
10460 /* VFP V1xD (single precision). */
10461 /* Moves and type conversions. */
10462 {"fcpys", 0xeeb00a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10463 {"fmrs", 0xee100a10, 4, FPU_VFP_EXT_V1xD, do_vfp_reg_from_sp},
10464 {"fmsr", 0xee000a10, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_from_reg},
10465 {"fmstat", 0xeef1fa10, 6, FPU_VFP_EXT_V1xD, do_empty},
10466 {"fsitos", 0xeeb80ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10467 {"fuitos", 0xeeb80a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10468 {"ftosis", 0xeebd0a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10469 {"ftosizs", 0xeebd0ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10470 {"ftouis", 0xeebc0a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10471 {"ftouizs", 0xeebc0ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10472 {"fmrx", 0xeef00a10, 4, FPU_VFP_EXT_V1xD, do_vfp_reg_from_ctrl},
10473 {"fmxr", 0xeee00a10, 4, FPU_VFP_EXT_V1xD, do_vfp_ctrl_from_reg},
10474
10475 /* Memory operations. */
10476 {"flds", 0xed100a00, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_ldst},
10477 {"fsts", 0xed000a00, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_ldst},
10478 {"fldmias", 0xec900a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
10479 {"fldmfds", 0xec900a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
10480 {"fldmdbs", 0xed300a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
10481 {"fldmeas", 0xed300a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
10482 {"fldmiax", 0xec900b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
10483 {"fldmfdx", 0xec900b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
10484 {"fldmdbx", 0xed300b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
10485 {"fldmeax", 0xed300b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
10486 {"fstmias", 0xec800a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
10487 {"fstmeas", 0xec800a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
10488 {"fstmdbs", 0xed200a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
10489 {"fstmfds", 0xed200a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
10490 {"fstmiax", 0xec800b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
10491 {"fstmeax", 0xec800b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
10492 {"fstmdbx", 0xed200b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
10493 {"fstmfdx", 0xed200b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
10494
10495 /* Monadic operations. */
10496 {"fabss", 0xeeb00ac0, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10497 {"fnegs", 0xeeb10a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10498 {"fsqrts", 0xeeb10ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10499
10500 /* Dyadic operations. */
10501 {"fadds", 0xee300a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10502 {"fsubs", 0xee300a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10503 {"fmuls", 0xee200a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10504 {"fdivs", 0xee800a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10505 {"fmacs", 0xee000a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10506 {"fmscs", 0xee100a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10507 {"fnmuls", 0xee200a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10508 {"fnmacs", 0xee000a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10509 {"fnmscs", 0xee100a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10510
10511 /* Comparisons. */
10512 {"fcmps", 0xeeb40a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10513 {"fcmpzs", 0xeeb50a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_compare_z},
10514 {"fcmpes", 0xeeb40ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10515 {"fcmpezs", 0xeeb50ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_compare_z},
10516
10517 /* VFP V1 (Double precision). */
10518 /* Moves and type conversions. */
10519 {"fcpyd", 0xeeb00b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10520 {"fcvtds", 0xeeb70ac0, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
10521 {"fcvtsd", 0xeeb70bc0, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
10522 {"fmdhr", 0xee200b10, 5, FPU_VFP_EXT_V1, do_vfp_dp_from_reg},
10523 {"fmdlr", 0xee000b10, 5, FPU_VFP_EXT_V1, do_vfp_dp_from_reg},
10524 {"fmrdh", 0xee300b10, 5, FPU_VFP_EXT_V1, do_vfp_reg_from_dp},
10525 {"fmrdl", 0xee100b10, 5, FPU_VFP_EXT_V1, do_vfp_reg_from_dp},
10526 {"fsitod", 0xeeb80bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
10527 {"fuitod", 0xeeb80b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
10528 {"ftosid", 0xeebd0b40, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
10529 {"ftosizd", 0xeebd0bc0, 7, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
10530 {"ftouid", 0xeebc0b40, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
10531 {"ftouizd", 0xeebc0bc0, 7, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
10532
10533 /* Memory operations. */
10534 {"fldd", 0xed100b00, 4, FPU_VFP_EXT_V1, do_vfp_dp_ldst},
10535 {"fstd", 0xed000b00, 4, FPU_VFP_EXT_V1, do_vfp_dp_ldst},
10536 {"fldmiad", 0xec900b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
10537 {"fldmfdd", 0xec900b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
10538 {"fldmdbd", 0xed300b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
10539 {"fldmead", 0xed300b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
10540 {"fstmiad", 0xec800b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
10541 {"fstmead", 0xec800b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
10542 {"fstmdbd", 0xed200b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
10543 {"fstmfdd", 0xed200b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
10544
10545 /* Monadic operations. */
10546 {"fabsd", 0xeeb00bc0, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10547 {"fnegd", 0xeeb10b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10548 {"fsqrtd", 0xeeb10bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10549
10550 /* Dyadic operations. */
10551 {"faddd", 0xee300b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10552 {"fsubd", 0xee300b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10553 {"fmuld", 0xee200b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10554 {"fdivd", 0xee800b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10555 {"fmacd", 0xee000b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10556 {"fmscd", 0xee100b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10557 {"fnmuld", 0xee200b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10558 {"fnmacd", 0xee000b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10559 {"fnmscd", 0xee100b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10560
10561 /* Comparisons. */
10562 {"fcmpd", 0xeeb40b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10563 {"fcmpzd", 0xeeb50b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_compare_z},
10564 {"fcmped", 0xeeb40bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10565 {"fcmpezd", 0xeeb50bc0, 7, FPU_VFP_EXT_V1, do_vfp_dp_compare_z},
10566
10567 /* VFP V2. */
10568 {"fmsrr", 0xec400a10, 5, FPU_VFP_EXT_V2, do_vfp_sp2_from_reg2},
10569 {"fmrrs", 0xec500a10, 5, FPU_VFP_EXT_V2, do_vfp_reg2_from_sp2},
10570 {"fmdrr", 0xec400b10, 5, FPU_VFP_EXT_V2, do_vfp_dp_from_reg2},
10571 {"fmrrd", 0xec500b10, 5, FPU_VFP_EXT_V2, do_vfp_reg2_from_dp},
10572
10573 /* Intel XScale extensions to ARM V5 ISA. (All use CP0). */
10574 {"mia", 0xee200010, 3, ARM_CEXT_XSCALE, do_xsc_mia},
10575 {"miaph", 0xee280010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
10576 {"miabb", 0xee2c0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
10577 {"miabt", 0xee2d0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
10578 {"miatb", 0xee2e0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
10579 {"miatt", 0xee2f0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
10580 {"mar", 0xec400000, 3, ARM_CEXT_XSCALE, do_xsc_mar},
10581 {"mra", 0xec500000, 3, ARM_CEXT_XSCALE, do_xsc_mra},
10582
10583 /* Intel Wireless MMX technology instructions. */
10584 {"tandcb", 0xee130130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
10585 {"tandch", 0xee530130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
10586 {"tandcw", 0xee930130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
10587 {"tbcstb", 0xee400010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
10588 {"tbcsth", 0xee400050, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
10589 {"tbcstw", 0xee400090, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
10590 {"textrcb", 0xee130170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
10591 {"textrch", 0xee530170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
10592 {"textrcw", 0xee930170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
10593 {"textrmub", 0xee100070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10594 {"textrmuh", 0xee500070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10595 {"textrmuw", 0xee900070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10596 {"textrmsb", 0xee100078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10597 {"textrmsh", 0xee500078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10598 {"textrmsw", 0xee900078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10599 {"tinsrb", 0xee600010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
10600 {"tinsrh", 0xee600050, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
10601 {"tinsrw", 0xee600090, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
10602 {"tmcr", 0xee000110, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmcr},
10603 {"tmcrr", 0xec400000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_tmcrr},
10604 {"tmia", 0xee200010, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10605 {"tmiaph", 0xee280010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10606 {"tmiabb", 0xee2c0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10607 {"tmiabt", 0xee2d0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10608 {"tmiatb", 0xee2e0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10609 {"tmiatt", 0xee2f0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10610 {"tmovmskb", 0xee100030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
10611 {"tmovmskh", 0xee500030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
10612 {"tmovmskw", 0xee900030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
10613 {"tmrc", 0xee100110, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmrc},
10614 {"tmrrc", 0xec500000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_tmrrc},
10615 {"torcb", 0xee130150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
10616 {"torch", 0xee530150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
10617 {"torcw", 0xee930150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
10618 {"waccb", 0xee0001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10619 {"wacch", 0xee4001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10620 {"waccw", 0xee8001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10621 {"waddbss", 0xee300180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10622 {"waddb", 0xee000180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10623 {"waddbus", 0xee100180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10624 {"waddhss", 0xee700180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10625 {"waddh", 0xee400180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10626 {"waddhus", 0xee500180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10627 {"waddwss", 0xeeb00180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10628 {"waddw", 0xee800180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10629 {"waddwus", 0xee900180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10630 {"waligni", 0xee000020, 7, ARM_CEXT_IWMMXT, do_iwmmxt_waligni},
10631 {"walignr0", 0xee800020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10632 {"walignr1", 0xee900020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10633 {"walignr2", 0xeea00020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10634 {"walignr3", 0xeeb00020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10635 {"wand", 0xee200000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10636 {"wandn", 0xee300000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10637 {"wavg2b", 0xee800000, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10638 {"wavg2br", 0xee900000, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10639 {"wavg2h", 0xeec00000, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10640 {"wavg2hr", 0xeed00000, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10641 {"wcmpeqb", 0xee000060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10642 {"wcmpeqh", 0xee400060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10643 {"wcmpeqw", 0xee800060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10644 {"wcmpgtub", 0xee100060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10645 {"wcmpgtuh", 0xee500060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10646 {"wcmpgtuw", 0xee900060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10647 {"wcmpgtsb", 0xee300060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10648 {"wcmpgtsh", 0xee700060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10649 {"wcmpgtsw", 0xeeb00060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10650 {"wldrb", 0xec100000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
10651 {"wldrh", 0xec100100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
10652 {"wldrw", 0xec100200, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
10653 {"wldrd", 0xec100300, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
10654 {"wmacs", 0xee600100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10655 {"wmacsz", 0xee700100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10656 {"wmacu", 0xee400100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10657 {"wmacuz", 0xee500100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10658 {"wmadds", 0xeea00100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10659 {"wmaddu", 0xee800100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10660 {"wmaxsb", 0xee200160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10661 {"wmaxsh", 0xee600160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10662 {"wmaxsw", 0xeea00160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10663 {"wmaxub", 0xee000160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10664 {"wmaxuh", 0xee400160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10665 {"wmaxuw", 0xee800160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10666 {"wminsb", 0xee300160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10667 {"wminsh", 0xee700160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10668 {"wminsw", 0xeeb00160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10669 {"wminub", 0xee100160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10670 {"wminuh", 0xee500160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10671 {"wminuw", 0xee900160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10672 {"wmov", 0xee000000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wmov},
10673 {"wmulsm", 0xee300100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10674 {"wmulsl", 0xee200100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10675 {"wmulum", 0xee100100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10676 {"wmulul", 0xee000100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10677 {"wor", 0xee000000, 3, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10678 {"wpackhss", 0xee700080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10679 {"wpackhus", 0xee500080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10680 {"wpackwss", 0xeeb00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10681 {"wpackwus", 0xee900080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10682 {"wpackdss", 0xeef00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10683 {"wpackdus", 0xeed00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10684 {"wrorh", 0xee700040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10685 {"wrorhg", 0xee700148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
10686 {"wrorw", 0xeeb00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10687 {"wrorwg", 0xeeb00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
10688 {"wrord", 0xeef00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10689 {"wrordg", 0xeef00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
10690 {"wsadb", 0xee000120, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10691 {"wsadbz", 0xee100120, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10692 {"wsadh", 0xee400120, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10693 {"wsadhz", 0xee500120, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10694 {"wshufh", 0xee0001e0, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wshufh},
10695 {"wsllh", 0xee500040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10696 {"wsllhg", 0xee500148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
10697 {"wsllw", 0xee900040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10698 {"wsllwg", 0xee900148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
10699 {"wslld", 0xeed00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10700 {"wslldg", 0xeed00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
10701 {"wsrah", 0xee400040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10702 {"wsrahg", 0xee400148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
10703 {"wsraw", 0xee800040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10704 {"wsrawg", 0xee800148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
10705 {"wsrad", 0xeec00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10706 {"wsradg", 0xeec00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
10707 {"wsrlh", 0xee600040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10708 {"wsrlhg", 0xee600148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
10709 {"wsrlw", 0xeea00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10710 {"wsrlwg", 0xeea00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
10711 {"wsrld", 0xeee00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10712 {"wsrldg", 0xeee00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
10713 {"wstrb", 0xec000000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
10714 {"wstrh", 0xec000100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
10715 {"wstrw", 0xec000200, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
10716 {"wstrd", 0xec000300, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
10717 {"wsubbss", 0xee3001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10718 {"wsubb", 0xee0001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10719 {"wsubbus", 0xee1001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10720 {"wsubhss", 0xee7001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10721 {"wsubh", 0xee4001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10722 {"wsubhus", 0xee5001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10723 {"wsubwss", 0xeeb001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10724 {"wsubw", 0xee8001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10725 {"wsubwus", 0xee9001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10726 {"wunpckehub", 0xee0000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10727 {"wunpckehuh", 0xee4000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10728 {"wunpckehuw", 0xee8000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10729 {"wunpckehsb", 0xee2000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10730 {"wunpckehsh", 0xee6000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10731 {"wunpckehsw", 0xeea000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10732 {"wunpckihb", 0xee1000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10733 {"wunpckihh", 0xee5000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10734 {"wunpckihw", 0xee9000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10735 {"wunpckelub", 0xee0000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10736 {"wunpckeluh", 0xee4000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10737 {"wunpckeluw", 0xee8000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10738 {"wunpckelsb", 0xee2000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10739 {"wunpckelsh", 0xee6000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10740 {"wunpckelsw", 0xeea000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10741 {"wunpckilb", 0xee1000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10742 {"wunpckilh", 0xee5000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10743 {"wunpckilw", 0xee9000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10744 {"wxor", 0xee100000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10745 {"wzero", 0xee300000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wzero},
10746
10747 /* Cirrus Maverick instructions. */
10748 {"cfldrs", 0xec100400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_1},
10749 {"cfldrd", 0xec500400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_2},
10750 {"cfldr32", 0xec100500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_3},
10751 {"cfldr64", 0xec500500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_4},
10752 {"cfstrs", 0xec000400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_1},
10753 {"cfstrd", 0xec400400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_2},
10754 {"cfstr32", 0xec000500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_3},
10755 {"cfstr64", 0xec400500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_4},
10756 {"cfmvsr", 0xee000450, 6, ARM_CEXT_MAVERICK, do_mav_binops_2a},
10757 {"cfmvrs", 0xee100450, 6, ARM_CEXT_MAVERICK, do_mav_binops_1a},
10758 {"cfmvdlr", 0xee000410, 7, ARM_CEXT_MAVERICK, do_mav_binops_2b},
10759 {"cfmvrdl", 0xee100410, 7, ARM_CEXT_MAVERICK, do_mav_binops_1b},
10760 {"cfmvdhr", 0xee000430, 7, ARM_CEXT_MAVERICK, do_mav_binops_2b},
10761 {"cfmvrdh", 0xee100430, 7, ARM_CEXT_MAVERICK, do_mav_binops_1b},
10762 {"cfmv64lr", 0xee000510, 8, ARM_CEXT_MAVERICK, do_mav_binops_2c},
10763 {"cfmvr64l", 0xee100510, 8, ARM_CEXT_MAVERICK, do_mav_binops_1c},
10764 {"cfmv64hr", 0xee000530, 8, ARM_CEXT_MAVERICK, do_mav_binops_2c},
10765 {"cfmvr64h", 0xee100530, 8, ARM_CEXT_MAVERICK, do_mav_binops_1c},
10766 {"cfmval32", 0xee200440, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
10767 {"cfmv32al", 0xee100440, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
10768 {"cfmvam32", 0xee200460, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
10769 {"cfmv32am", 0xee100460, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
10770 {"cfmvah32", 0xee200480, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
10771 {"cfmv32ah", 0xee100480, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
10772 {"cfmva32", 0xee2004a0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3a},
10773 {"cfmv32a", 0xee1004a0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3b},
10774 {"cfmva64", 0xee2004c0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3c},
10775 {"cfmv64a", 0xee1004c0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3d},
10776 {"cfmvsc32", 0xee2004e0, 8, ARM_CEXT_MAVERICK, do_mav_dspsc_1},
10777 {"cfmv32sc", 0xee1004e0, 8, ARM_CEXT_MAVERICK, do_mav_dspsc_2},
10778 {"cfcpys", 0xee000400, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
10779 {"cfcpyd", 0xee000420, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
10780 {"cfcvtsd", 0xee000460, 7, ARM_CEXT_MAVERICK, do_mav_binops_1f},
10781 {"cfcvtds", 0xee000440, 7, ARM_CEXT_MAVERICK, do_mav_binops_1g},
10782 {"cfcvt32s", 0xee000480, 8, ARM_CEXT_MAVERICK, do_mav_binops_1h},
10783 {"cfcvt32d", 0xee0004a0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1i},
10784 {"cfcvt64s", 0xee0004c0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1j},
10785 {"cfcvt64d", 0xee0004e0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1k},
10786 {"cfcvts32", 0xee100580, 8, ARM_CEXT_MAVERICK, do_mav_binops_1l},
10787 {"cfcvtd32", 0xee1005a0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1m},
10788 {"cftruncs32", 0xee1005c0, 10, ARM_CEXT_MAVERICK, do_mav_binops_1l},
10789 {"cftruncd32", 0xee1005e0, 10, ARM_CEXT_MAVERICK, do_mav_binops_1m},
10790 {"cfrshl32", 0xee000550, 8, ARM_CEXT_MAVERICK, do_mav_triple_4a},
10791 {"cfrshl64", 0xee000570, 8, ARM_CEXT_MAVERICK, do_mav_triple_4b},
10792 {"cfsh32", 0xee000500, 6, ARM_CEXT_MAVERICK, do_mav_shift_1},
10793 {"cfsh64", 0xee200500, 6, ARM_CEXT_MAVERICK, do_mav_shift_2},
10794 {"cfcmps", 0xee100490, 6, ARM_CEXT_MAVERICK, do_mav_triple_5a},
10795 {"cfcmpd", 0xee1004b0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5b},
10796 {"cfcmp32", 0xee100590, 7, ARM_CEXT_MAVERICK, do_mav_triple_5c},
10797 {"cfcmp64", 0xee1005b0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5d},
10798 {"cfabss", 0xee300400, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
10799 {"cfabsd", 0xee300420, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
10800 {"cfnegs", 0xee300440, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
10801 {"cfnegd", 0xee300460, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
10802 {"cfadds", 0xee300480, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
10803 {"cfaddd", 0xee3004a0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
10804 {"cfsubs", 0xee3004c0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
10805 {"cfsubd", 0xee3004e0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
10806 {"cfmuls", 0xee100400, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
10807 {"cfmuld", 0xee100420, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
10808 {"cfabs32", 0xee300500, 7, ARM_CEXT_MAVERICK, do_mav_binops_1n},
10809 {"cfabs64", 0xee300520, 7, ARM_CEXT_MAVERICK, do_mav_binops_1o},
10810 {"cfneg32", 0xee300540, 7, ARM_CEXT_MAVERICK, do_mav_binops_1n},
10811 {"cfneg64", 0xee300560, 7, ARM_CEXT_MAVERICK, do_mav_binops_1o},
10812 {"cfadd32", 0xee300580, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
10813 {"cfadd64", 0xee3005a0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
10814 {"cfsub32", 0xee3005c0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
10815 {"cfsub64", 0xee3005e0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
10816 {"cfmul32", 0xee100500, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
10817 {"cfmul64", 0xee100520, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
10818 {"cfmac32", 0xee100540, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
10819 {"cfmsc32", 0xee100560, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
10820 {"cfmadd32", 0xee000600, 8, ARM_CEXT_MAVERICK, do_mav_quad_6a},
10821 {"cfmsub32", 0xee100600, 8, ARM_CEXT_MAVERICK, do_mav_quad_6a},
10822 {"cfmadda32", 0xee200600, 9, ARM_CEXT_MAVERICK, do_mav_quad_6b},
10823 {"cfmsuba32", 0xee300600, 9, ARM_CEXT_MAVERICK, do_mav_quad_6b},
10824 };
10825
10826 /* Iterate over the base tables to create the instruction patterns. */
10827
10828 static void
10829 build_arm_ops_hsh (void)
10830 {
10831 unsigned int i;
10832 unsigned int j;
10833 static struct obstack insn_obstack;
10834
10835 obstack_begin (&insn_obstack, 4000);
10836
10837 for (i = 0; i < sizeof (insns) / sizeof (struct asm_opcode); i++)
10838 {
10839 const struct asm_opcode *insn = insns + i;
10840
10841 if (insn->cond_offset != 0)
10842 {
10843 /* Insn supports conditional execution. Build the varaints
10844 and insert them in the hash table. */
10845 for (j = 0; j < sizeof (conds) / sizeof (struct asm_cond); j++)
10846 {
10847 unsigned len = strlen (insn->template);
10848 struct asm_opcode *new;
10849 char *template;
10850
10851 new = obstack_alloc (&insn_obstack, sizeof (struct asm_opcode));
10852 /* All condition codes are two characters. */
10853 template = obstack_alloc (&insn_obstack, len + 3);
10854
10855 strncpy (template, insn->template, insn->cond_offset);
10856 strcpy (template + insn->cond_offset, conds[j].template);
10857 if (len > insn->cond_offset)
10858 strcpy (template + insn->cond_offset + 2,
10859 insn->template + insn->cond_offset);
10860 new->template = template;
10861 new->cond_offset = 0;
10862 new->variant = insn->variant;
10863 new->parms = insn->parms;
10864 new->value = (insn->value & ~COND_MASK) | conds[j].value;
10865
10866 hash_insert (arm_ops_hsh, new->template, (PTR) new);
10867 }
10868 }
10869 /* Finally, insert the unconditional insn in the table directly;
10870 no need to build a copy. */
10871 hash_insert (arm_ops_hsh, insn->template, (PTR) insn);
10872 }
10873 }
10874
10875 \f
10876 static const struct thumb_opcode tinsns[] =
10877 {
10878 /* Thumb v1 (ARMv4T). */
10879 {"adc", 0x4140, 2, ARM_EXT_V4T, do_t_arit},
10880 {"add", 0x0000, 2, ARM_EXT_V4T, do_t_add},
10881 {"and", 0x4000, 2, ARM_EXT_V4T, do_t_arit},
10882 {"asr", 0x0000, 2, ARM_EXT_V4T, do_t_asr},
10883 {"b", T_OPCODE_BRANCH, 2, ARM_EXT_V4T, do_t_branch12},
10884 {"beq", 0xd0fe, 2, ARM_EXT_V4T, do_t_branch9},
10885 {"bne", 0xd1fe, 2, ARM_EXT_V4T, do_t_branch9},
10886 {"bcs", 0xd2fe, 2, ARM_EXT_V4T, do_t_branch9},
10887 {"bhs", 0xd2fe, 2, ARM_EXT_V4T, do_t_branch9},
10888 {"bcc", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
10889 {"bul", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
10890 {"blo", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
10891 {"bmi", 0xd4fe, 2, ARM_EXT_V4T, do_t_branch9},
10892 {"bpl", 0xd5fe, 2, ARM_EXT_V4T, do_t_branch9},
10893 {"bvs", 0xd6fe, 2, ARM_EXT_V4T, do_t_branch9},
10894 {"bvc", 0xd7fe, 2, ARM_EXT_V4T, do_t_branch9},
10895 {"bhi", 0xd8fe, 2, ARM_EXT_V4T, do_t_branch9},
10896 {"bls", 0xd9fe, 2, ARM_EXT_V4T, do_t_branch9},
10897 {"bge", 0xdafe, 2, ARM_EXT_V4T, do_t_branch9},
10898 {"blt", 0xdbfe, 2, ARM_EXT_V4T, do_t_branch9},
10899 {"bgt", 0xdcfe, 2, ARM_EXT_V4T, do_t_branch9},
10900 {"ble", 0xddfe, 2, ARM_EXT_V4T, do_t_branch9},
10901 {"bal", 0xdefe, 2, ARM_EXT_V4T, do_t_branch9},
10902 {"bic", 0x4380, 2, ARM_EXT_V4T, do_t_arit},
10903 {"bl", 0xf7fffffe, 4, ARM_EXT_V4T, do_t_branch23},
10904 {"bx", 0x4700, 2, ARM_EXT_V4T, do_t_bx},
10905 {"cmn", T_OPCODE_CMN, 2, ARM_EXT_V4T, do_t_arit},
10906 {"cmp", 0x0000, 2, ARM_EXT_V4T, do_t_compare},
10907 {"eor", 0x4040, 2, ARM_EXT_V4T, do_t_arit},
10908 {"ldmia", 0xc800, 2, ARM_EXT_V4T, do_t_ldmstm},
10909 {"ldr", 0x0000, 2, ARM_EXT_V4T, do_t_ldr},
10910 {"ldrb", 0x0000, 2, ARM_EXT_V4T, do_t_ldrb},
10911 {"ldrh", 0x0000, 2, ARM_EXT_V4T, do_t_ldrh},
10912 {"ldrsb", 0x5600, 2, ARM_EXT_V4T, do_t_lds},
10913 {"ldrsh", 0x5e00, 2, ARM_EXT_V4T, do_t_lds},
10914 {"ldsb", 0x5600, 2, ARM_EXT_V4T, do_t_lds},
10915 {"ldsh", 0x5e00, 2, ARM_EXT_V4T, do_t_lds},
10916 {"lsl", 0x0000, 2, ARM_EXT_V4T, do_t_lsl},
10917 {"lsr", 0x0000, 2, ARM_EXT_V4T, do_t_lsr},
10918 {"mov", 0x0000, 2, ARM_EXT_V4T, do_t_mov},
10919 {"mul", T_OPCODE_MUL, 2, ARM_EXT_V4T, do_t_arit},
10920 {"mvn", T_OPCODE_MVN, 2, ARM_EXT_V4T, do_t_arit},
10921 {"neg", T_OPCODE_NEG, 2, ARM_EXT_V4T, do_t_arit},
10922 {"orr", 0x4300, 2, ARM_EXT_V4T, do_t_arit},
10923 {"pop", 0xbc00, 2, ARM_EXT_V4T, do_t_push_pop},
10924 {"push", 0xb400, 2, ARM_EXT_V4T, do_t_push_pop},
10925 {"ror", 0x41c0, 2, ARM_EXT_V4T, do_t_arit},
10926 {"sbc", 0x4180, 2, ARM_EXT_V4T, do_t_arit},
10927 {"stmia", 0xc000, 2, ARM_EXT_V4T, do_t_ldmstm},
10928 {"str", 0x0000, 2, ARM_EXT_V4T, do_t_str},
10929 {"strb", 0x0000, 2, ARM_EXT_V4T, do_t_strb},
10930 {"strh", 0x0000, 2, ARM_EXT_V4T, do_t_strh},
10931 {"swi", 0xdf00, 2, ARM_EXT_V4T, do_t_swi},
10932 {"sub", 0x0000, 2, ARM_EXT_V4T, do_t_sub},
10933 {"tst", T_OPCODE_TST, 2, ARM_EXT_V4T, do_t_arit},
10934 /* Pseudo ops: */
10935 {"adr", 0x0000, 2, ARM_EXT_V4T, do_t_adr},
10936 {"nop", 0x46C0, 2, ARM_EXT_V4T, do_t_nop}, /* mov r8,r8 */
10937 /* Thumb v2 (ARMv5T). */
10938 {"blx", 0, 0, ARM_EXT_V5T, do_t_blx},
10939 {"bkpt", 0xbe00, 2, ARM_EXT_V5T, do_t_bkpt},
10940
10941 /* ARM V6. */
10942 {"cpsie", 0xb660, 2, ARM_EXT_V6, do_t_cps},
10943 {"cpsid", 0xb670, 2, ARM_EXT_V6, do_t_cps},
10944 {"cpy", 0x4600, 2, ARM_EXT_V6, do_t_cpy},
10945 {"rev", 0xba00, 2, ARM_EXT_V6, do_t_arit},
10946 {"rev16", 0xba40, 2, ARM_EXT_V6, do_t_arit},
10947 {"revsh", 0xbac0, 2, ARM_EXT_V6, do_t_arit},
10948 {"setend", 0xb650, 2, ARM_EXT_V6, do_t_setend},
10949 {"sxth", 0xb200, 2, ARM_EXT_V6, do_t_arit},
10950 {"sxtb", 0xb240, 2, ARM_EXT_V6, do_t_arit},
10951 {"uxth", 0xb280, 2, ARM_EXT_V6, do_t_arit},
10952 {"uxtb", 0xb2c0, 2, ARM_EXT_V6, do_t_arit},
10953 };
10954
10955 void
10956 md_begin (void)
10957 {
10958 unsigned mach;
10959 unsigned int i;
10960
10961 if ( (arm_ops_hsh = hash_new ()) == NULL
10962 || (arm_tops_hsh = hash_new ()) == NULL
10963 || (arm_cond_hsh = hash_new ()) == NULL
10964 || (arm_shift_hsh = hash_new ()) == NULL
10965 || (arm_psr_hsh = hash_new ()) == NULL)
10966 as_fatal (_("virtual memory exhausted"));
10967
10968 build_arm_ops_hsh ();
10969 for (i = 0; i < sizeof (tinsns) / sizeof (struct thumb_opcode); i++)
10970 hash_insert (arm_tops_hsh, tinsns[i].template, (PTR) (tinsns + i));
10971 for (i = 0; i < sizeof (conds) / sizeof (struct asm_cond); i++)
10972 hash_insert (arm_cond_hsh, conds[i].template, (PTR) (conds + i));
10973 for (i = 0; i < sizeof (shift_names) / sizeof (struct asm_shift_name); i++)
10974 hash_insert (arm_shift_hsh, shift_names[i].name, (PTR) (shift_names + i));
10975 for (i = 0; i < sizeof (psrs) / sizeof (struct asm_psr); i++)
10976 hash_insert (arm_psr_hsh, psrs[i].template, (PTR) (psrs + i));
10977
10978 for (i = (int) REG_TYPE_FIRST; i < (int) REG_TYPE_MAX; i++)
10979 build_reg_hsh (all_reg_maps + i);
10980
10981 set_constant_flonums ();
10982
10983 /* Set the cpu variant based on the command-line options. We prefer
10984 -mcpu= over -march= if both are set (as for GCC); and we prefer
10985 -mfpu= over any other way of setting the floating point unit.
10986 Use of legacy options with new options are faulted. */
10987 if (legacy_cpu != -1)
10988 {
10989 if (mcpu_cpu_opt != -1 || march_cpu_opt != -1)
10990 as_bad (_("use of old and new-style options to set CPU type"));
10991
10992 mcpu_cpu_opt = legacy_cpu;
10993 }
10994 else if (mcpu_cpu_opt == -1)
10995 mcpu_cpu_opt = march_cpu_opt;
10996
10997 if (legacy_fpu != -1)
10998 {
10999 if (mfpu_opt != -1)
11000 as_bad (_("use of old and new-style options to set FPU type"));
11001
11002 mfpu_opt = legacy_fpu;
11003 }
11004 else if (mfpu_opt == -1)
11005 {
11006 #if !(defined (TE_LINUX) || defined (TE_NetBSD) || defined (TE_VXWORKS))
11007 /* Some environments specify a default FPU. If they don't, infer it
11008 from the processor. */
11009 if (mcpu_fpu_opt != -1)
11010 mfpu_opt = mcpu_fpu_opt;
11011 else
11012 mfpu_opt = march_fpu_opt;
11013 #else
11014 mfpu_opt = FPU_DEFAULT;
11015 #endif
11016 }
11017
11018 if (mfpu_opt == -1)
11019 {
11020 if (mcpu_cpu_opt == -1)
11021 mfpu_opt = FPU_DEFAULT;
11022 else if (mcpu_cpu_opt & ARM_EXT_V5)
11023 mfpu_opt = FPU_ARCH_VFP_V2;
11024 else
11025 mfpu_opt = FPU_ARCH_FPA;
11026 }
11027
11028 if (mcpu_cpu_opt == -1)
11029 mcpu_cpu_opt = CPU_DEFAULT;
11030
11031 cpu_variant = mcpu_cpu_opt | mfpu_opt;
11032
11033 #if defined OBJ_COFF || defined OBJ_ELF
11034 {
11035 unsigned int flags = 0;
11036
11037 #if defined OBJ_ELF
11038 flags = meabi_flags;
11039
11040 switch (meabi_flags)
11041 {
11042 case EF_ARM_EABI_UNKNOWN:
11043 #endif
11044 /* Set the flags in the private structure. */
11045 if (uses_apcs_26) flags |= F_APCS26;
11046 if (support_interwork) flags |= F_INTERWORK;
11047 if (uses_apcs_float) flags |= F_APCS_FLOAT;
11048 if (pic_code) flags |= F_PIC;
11049 if ((cpu_variant & FPU_ANY) == FPU_NONE
11050 || (cpu_variant & FPU_ANY) == FPU_ARCH_VFP) /* VFP layout only. */
11051 flags |= F_SOFT_FLOAT;
11052
11053 switch (mfloat_abi_opt)
11054 {
11055 case ARM_FLOAT_ABI_SOFT:
11056 case ARM_FLOAT_ABI_SOFTFP:
11057 flags |= F_SOFT_FLOAT;
11058 break;
11059
11060 case ARM_FLOAT_ABI_HARD:
11061 if (flags & F_SOFT_FLOAT)
11062 as_bad (_("hard-float conflicts with specified fpu"));
11063 break;
11064 }
11065
11066 /* Using VFP conventions (even if soft-float). */
11067 if (cpu_variant & FPU_VFP_EXT_NONE)
11068 flags |= F_VFP_FLOAT;
11069
11070 #if defined OBJ_ELF
11071 if (cpu_variant & FPU_ARCH_MAVERICK)
11072 flags |= EF_ARM_MAVERICK_FLOAT;
11073 break;
11074
11075 case EF_ARM_EABI_VER4:
11076 /* No additional flags to set. */
11077 break;
11078
11079 default:
11080 abort ();
11081 }
11082 #endif
11083 bfd_set_private_flags (stdoutput, flags);
11084
11085 /* We have run out flags in the COFF header to encode the
11086 status of ATPCS support, so instead we create a dummy,
11087 empty, debug section called .arm.atpcs. */
11088 if (atpcs)
11089 {
11090 asection * sec;
11091
11092 sec = bfd_make_section (stdoutput, ".arm.atpcs");
11093
11094 if (sec != NULL)
11095 {
11096 bfd_set_section_flags
11097 (stdoutput, sec, SEC_READONLY | SEC_DEBUGGING /* | SEC_HAS_CONTENTS */);
11098 bfd_set_section_size (stdoutput, sec, 0);
11099 bfd_set_section_contents (stdoutput, sec, NULL, 0, 0);
11100 }
11101 }
11102 }
11103 #endif
11104
11105 /* Record the CPU type as well. */
11106 switch (cpu_variant & ARM_CPU_MASK)
11107 {
11108 case ARM_2:
11109 mach = bfd_mach_arm_2;
11110 break;
11111
11112 case ARM_3: /* Also ARM_250. */
11113 mach = bfd_mach_arm_2a;
11114 break;
11115
11116 case ARM_6: /* Also ARM_7. */
11117 mach = bfd_mach_arm_3;
11118 break;
11119
11120 default:
11121 mach = bfd_mach_arm_unknown;
11122 break;
11123 }
11124
11125 /* Catch special cases. */
11126 if (cpu_variant & ARM_CEXT_IWMMXT)
11127 mach = bfd_mach_arm_iWMMXt;
11128 else if (cpu_variant & ARM_CEXT_XSCALE)
11129 mach = bfd_mach_arm_XScale;
11130 else if (cpu_variant & ARM_CEXT_MAVERICK)
11131 mach = bfd_mach_arm_ep9312;
11132 else if (cpu_variant & ARM_EXT_V5E)
11133 mach = bfd_mach_arm_5TE;
11134 else if (cpu_variant & ARM_EXT_V5)
11135 {
11136 if (cpu_variant & ARM_EXT_V4T)
11137 mach = bfd_mach_arm_5T;
11138 else
11139 mach = bfd_mach_arm_5;
11140 }
11141 else if (cpu_variant & ARM_EXT_V4)
11142 {
11143 if (cpu_variant & ARM_EXT_V4T)
11144 mach = bfd_mach_arm_4T;
11145 else
11146 mach = bfd_mach_arm_4;
11147 }
11148 else if (cpu_variant & ARM_EXT_V3M)
11149 mach = bfd_mach_arm_3M;
11150
11151 bfd_set_arch_mach (stdoutput, TARGET_ARCH, mach);
11152 }
11153
11154 /* Turn an integer of n bytes (in val) into a stream of bytes appropriate
11155 for use in the a.out file, and stores them in the array pointed to by buf.
11156 This knows about the endian-ness of the target machine and does
11157 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
11158 2 (short) and 4 (long) Floating numbers are put out as a series of
11159 LITTLENUMS (shorts, here at least). */
11160
11161 void
11162 md_number_to_chars (char * buf, valueT val, int n)
11163 {
11164 if (target_big_endian)
11165 number_to_chars_bigendian (buf, val, n);
11166 else
11167 number_to_chars_littleendian (buf, val, n);
11168 }
11169
11170 static valueT
11171 md_chars_to_number (char * buf, int n)
11172 {
11173 valueT result = 0;
11174 unsigned char * where = (unsigned char *) buf;
11175
11176 if (target_big_endian)
11177 {
11178 while (n--)
11179 {
11180 result <<= 8;
11181 result |= (*where++ & 255);
11182 }
11183 }
11184 else
11185 {
11186 while (n--)
11187 {
11188 result <<= 8;
11189 result |= (where[n] & 255);
11190 }
11191 }
11192
11193 return result;
11194 }
11195
11196 /* Turn a string in input_line_pointer into a floating point constant
11197 of type TYPE, and store the appropriate bytes in *LITP. The number
11198 of LITTLENUMS emitted is stored in *SIZEP. An error message is
11199 returned, or NULL on OK.
11200
11201 Note that fp constants aren't represent in the normal way on the ARM.
11202 In big endian mode, things are as expected. However, in little endian
11203 mode fp constants are big-endian word-wise, and little-endian byte-wise
11204 within the words. For example, (double) 1.1 in big endian mode is
11205 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
11206 the byte sequence 99 99 f1 3f 9a 99 99 99.
11207
11208 ??? The format of 12 byte floats is uncertain according to gcc's arm.h. */
11209
11210 char *
11211 md_atof (int type, char * litP, int * sizeP)
11212 {
11213 int prec;
11214 LITTLENUM_TYPE words[MAX_LITTLENUMS];
11215 char *t;
11216 int i;
11217
11218 switch (type)
11219 {
11220 case 'f':
11221 case 'F':
11222 case 's':
11223 case 'S':
11224 prec = 2;
11225 break;
11226
11227 case 'd':
11228 case 'D':
11229 case 'r':
11230 case 'R':
11231 prec = 4;
11232 break;
11233
11234 case 'x':
11235 case 'X':
11236 prec = 6;
11237 break;
11238
11239 case 'p':
11240 case 'P':
11241 prec = 6;
11242 break;
11243
11244 default:
11245 *sizeP = 0;
11246 return _("bad call to MD_ATOF()");
11247 }
11248
11249 t = atof_ieee (input_line_pointer, type, words);
11250 if (t)
11251 input_line_pointer = t;
11252 *sizeP = prec * 2;
11253
11254 if (target_big_endian)
11255 {
11256 for (i = 0; i < prec; i++)
11257 {
11258 md_number_to_chars (litP, (valueT) words[i], 2);
11259 litP += 2;
11260 }
11261 }
11262 else
11263 {
11264 if (cpu_variant & FPU_ARCH_VFP)
11265 for (i = prec - 1; i >= 0; i--)
11266 {
11267 md_number_to_chars (litP, (valueT) words[i], 2);
11268 litP += 2;
11269 }
11270 else
11271 /* For a 4 byte float the order of elements in `words' is 1 0.
11272 For an 8 byte float the order is 1 0 3 2. */
11273 for (i = 0; i < prec; i += 2)
11274 {
11275 md_number_to_chars (litP, (valueT) words[i + 1], 2);
11276 md_number_to_chars (litP + 2, (valueT) words[i], 2);
11277 litP += 4;
11278 }
11279 }
11280
11281 return 0;
11282 }
11283
11284 /* The knowledge of the PC's pipeline offset is built into the insns
11285 themselves. */
11286
11287 long
11288 md_pcrel_from (fixS * fixP)
11289 {
11290 if (fixP->fx_addsy
11291 && S_GET_SEGMENT (fixP->fx_addsy) == undefined_section
11292 && fixP->fx_subsy == NULL)
11293 return 0;
11294
11295 if (fixP->fx_pcrel && (fixP->fx_r_type == BFD_RELOC_ARM_THUMB_ADD))
11296 {
11297 /* PC relative addressing on the Thumb is slightly odd
11298 as the bottom two bits of the PC are forced to zero
11299 for the calculation. */
11300 return (fixP->fx_where + fixP->fx_frag->fr_address) & ~3;
11301 }
11302
11303 #ifdef TE_WINCE
11304 /* The pattern was adjusted to accommodate CE's off-by-one fixups,
11305 so we un-adjust here to compensate for the accommodation. */
11306 return fixP->fx_where + fixP->fx_frag->fr_address + 8;
11307 #else
11308 return fixP->fx_where + fixP->fx_frag->fr_address;
11309 #endif
11310 }
11311
11312 /* Round up a section size to the appropriate boundary. */
11313
11314 valueT
11315 md_section_align (segT segment ATTRIBUTE_UNUSED,
11316 valueT size)
11317 {
11318 #ifdef OBJ_ELF
11319 return size;
11320 #else
11321 /* Round all sects to multiple of 4. */
11322 return (size + 3) & ~3;
11323 #endif
11324 }
11325
11326 /* Under ELF we need to default _GLOBAL_OFFSET_TABLE.
11327 Otherwise we have no need to default values of symbols. */
11328
11329 symbolS *
11330 md_undefined_symbol (char * name ATTRIBUTE_UNUSED)
11331 {
11332 #ifdef OBJ_ELF
11333 if (name[0] == '_' && name[1] == 'G'
11334 && streq (name, GLOBAL_OFFSET_TABLE_NAME))
11335 {
11336 if (!GOT_symbol)
11337 {
11338 if (symbol_find (name))
11339 as_bad ("GOT already in the symbol table");
11340
11341 GOT_symbol = symbol_new (name, undefined_section,
11342 (valueT) 0, & zero_address_frag);
11343 }
11344
11345 return GOT_symbol;
11346 }
11347 #endif
11348
11349 return 0;
11350 }
11351
11352 void
11353 md_apply_fix3 (fixS * fixP,
11354 valueT * valP,
11355 segT seg)
11356 {
11357 offsetT value = * valP;
11358 offsetT newval;
11359 unsigned int newimm;
11360 unsigned long temp;
11361 int sign;
11362 char * buf = fixP->fx_where + fixP->fx_frag->fr_literal;
11363 arm_fix_data * arm_data = (arm_fix_data *) fixP->tc_fix_data;
11364
11365 assert (fixP->fx_r_type <= BFD_RELOC_UNUSED);
11366
11367 /* Note whether this will delete the relocation. */
11368 if (fixP->fx_addsy == 0 && !fixP->fx_pcrel)
11369 fixP->fx_done = 1;
11370
11371 /* If this symbol is in a different section then we need to leave it for
11372 the linker to deal with. Unfortunately, md_pcrel_from can't tell,
11373 so we have to undo it's effects here. */
11374 if (fixP->fx_pcrel)
11375 {
11376 if (fixP->fx_addsy != NULL
11377 && S_IS_DEFINED (fixP->fx_addsy)
11378 && S_GET_SEGMENT (fixP->fx_addsy) != seg)
11379 value += md_pcrel_from (fixP);
11380 }
11381
11382 /* Remember value for emit_reloc. */
11383 fixP->fx_addnumber = value;
11384
11385 switch (fixP->fx_r_type)
11386 {
11387 case BFD_RELOC_NONE:
11388 /* This will need to go in the object file. */
11389 fixP->fx_done = 0;
11390 break;
11391
11392 case BFD_RELOC_ARM_IMMEDIATE:
11393 /* We claim that this fixup has been processed here,
11394 even if in fact we generate an error because we do
11395 not have a reloc for it, so tc_gen_reloc will reject it. */
11396 fixP->fx_done = 1;
11397
11398 if (fixP->fx_addsy
11399 && ! S_IS_DEFINED (fixP->fx_addsy))
11400 {
11401 as_bad_where (fixP->fx_file, fixP->fx_line,
11402 _("undefined symbol %s used as an immediate value"),
11403 S_GET_NAME (fixP->fx_addsy));
11404 break;
11405 }
11406
11407 newimm = validate_immediate (value);
11408 temp = md_chars_to_number (buf, INSN_SIZE);
11409
11410 /* If the instruction will fail, see if we can fix things up by
11411 changing the opcode. */
11412 if (newimm == (unsigned int) FAIL
11413 && (newimm = negate_data_op (&temp, value)) == (unsigned int) FAIL)
11414 {
11415 as_bad_where (fixP->fx_file, fixP->fx_line,
11416 _("invalid constant (%lx) after fixup"),
11417 (unsigned long) value);
11418 break;
11419 }
11420
11421 newimm |= (temp & 0xfffff000);
11422 md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
11423 break;
11424
11425 case BFD_RELOC_ARM_ADRL_IMMEDIATE:
11426 {
11427 unsigned int highpart = 0;
11428 unsigned int newinsn = 0xe1a00000; /* nop. */
11429
11430 newimm = validate_immediate (value);
11431 temp = md_chars_to_number (buf, INSN_SIZE);
11432
11433 /* If the instruction will fail, see if we can fix things up by
11434 changing the opcode. */
11435 if (newimm == (unsigned int) FAIL
11436 && (newimm = negate_data_op (& temp, value)) == (unsigned int) FAIL)
11437 {
11438 /* No ? OK - try using two ADD instructions to generate
11439 the value. */
11440 newimm = validate_immediate_twopart (value, & highpart);
11441
11442 /* Yes - then make sure that the second instruction is
11443 also an add. */
11444 if (newimm != (unsigned int) FAIL)
11445 newinsn = temp;
11446 /* Still No ? Try using a negated value. */
11447 else if ((newimm = validate_immediate_twopart (- value, & highpart)) != (unsigned int) FAIL)
11448 temp = newinsn = (temp & OPCODE_MASK) | OPCODE_SUB << DATA_OP_SHIFT;
11449 /* Otherwise - give up. */
11450 else
11451 {
11452 as_bad_where (fixP->fx_file, fixP->fx_line,
11453 _("unable to compute ADRL instructions for PC offset of 0x%lx"),
11454 (long) value);
11455 break;
11456 }
11457
11458 /* Replace the first operand in the 2nd instruction (which
11459 is the PC) with the destination register. We have
11460 already added in the PC in the first instruction and we
11461 do not want to do it again. */
11462 newinsn &= ~ 0xf0000;
11463 newinsn |= ((newinsn & 0x0f000) << 4);
11464 }
11465
11466 newimm |= (temp & 0xfffff000);
11467 md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
11468
11469 highpart |= (newinsn & 0xfffff000);
11470 md_number_to_chars (buf + INSN_SIZE, (valueT) highpart, INSN_SIZE);
11471 }
11472 break;
11473
11474 case BFD_RELOC_ARM_OFFSET_IMM:
11475 sign = value >= 0;
11476
11477 if (value < 0)
11478 value = - value;
11479
11480 if (validate_offset_imm (value, 0) == FAIL)
11481 {
11482 as_bad_where (fixP->fx_file, fixP->fx_line,
11483 _("bad immediate value for offset (%ld)"),
11484 (long) value);
11485 break;
11486 }
11487
11488 newval = md_chars_to_number (buf, INSN_SIZE);
11489 newval &= 0xff7ff000;
11490 newval |= value | (sign ? INDEX_UP : 0);
11491 md_number_to_chars (buf, newval, INSN_SIZE);
11492 break;
11493
11494 case BFD_RELOC_ARM_OFFSET_IMM8:
11495 case BFD_RELOC_ARM_HWLITERAL:
11496 sign = value >= 0;
11497
11498 if (value < 0)
11499 value = - value;
11500
11501 if (validate_offset_imm (value, 1) == FAIL)
11502 {
11503 if (fixP->fx_r_type == BFD_RELOC_ARM_HWLITERAL)
11504 as_bad_where (fixP->fx_file, fixP->fx_line,
11505 _("invalid literal constant: pool needs to be closer"));
11506 else
11507 as_bad (_("bad immediate value for half-word offset (%ld)"),
11508 (long) value);
11509 break;
11510 }
11511
11512 newval = md_chars_to_number (buf, INSN_SIZE);
11513 newval &= 0xff7ff0f0;
11514 newval |= ((value >> 4) << 8) | (value & 0xf) | (sign ? INDEX_UP : 0);
11515 md_number_to_chars (buf, newval, INSN_SIZE);
11516 break;
11517
11518 case BFD_RELOC_ARM_LITERAL:
11519 sign = value >= 0;
11520
11521 if (value < 0)
11522 value = - value;
11523
11524 if (validate_offset_imm (value, 0) == FAIL)
11525 {
11526 as_bad_where (fixP->fx_file, fixP->fx_line,
11527 _("invalid literal constant: pool needs to be closer"));
11528 break;
11529 }
11530
11531 newval = md_chars_to_number (buf, INSN_SIZE);
11532 newval &= 0xff7ff000;
11533 newval |= value | (sign ? INDEX_UP : 0);
11534 md_number_to_chars (buf, newval, INSN_SIZE);
11535 break;
11536
11537 case BFD_RELOC_ARM_SHIFT_IMM:
11538 newval = md_chars_to_number (buf, INSN_SIZE);
11539 if (((unsigned long) value) > 32
11540 || (value == 32
11541 && (((newval & 0x60) == 0) || (newval & 0x60) == 0x60)))
11542 {
11543 as_bad_where (fixP->fx_file, fixP->fx_line,
11544 _("shift expression is too large"));
11545 break;
11546 }
11547
11548 if (value == 0)
11549 /* Shifts of zero must be done as lsl. */
11550 newval &= ~0x60;
11551 else if (value == 32)
11552 value = 0;
11553 newval &= 0xfffff07f;
11554 newval |= (value & 0x1f) << 7;
11555 md_number_to_chars (buf, newval, INSN_SIZE);
11556 break;
11557
11558 case BFD_RELOC_ARM_SMI:
11559 if (((unsigned long) value) > 0xffff)
11560 as_bad_where (fixP->fx_file, fixP->fx_line,
11561 _("invalid smi expression"));
11562 newval = md_chars_to_number (buf, INSN_SIZE) & 0xfff000f0;
11563 newval |= (value & 0xf) | ((value & 0xfff0) << 4);
11564 md_number_to_chars (buf, newval, INSN_SIZE);
11565 break;
11566
11567 case BFD_RELOC_ARM_SWI:
11568 if (arm_data->thumb_mode)
11569 {
11570 if (((unsigned long) value) > 0xff)
11571 as_bad_where (fixP->fx_file, fixP->fx_line,
11572 _("invalid swi expression"));
11573 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xff00;
11574 newval |= value;
11575 md_number_to_chars (buf, newval, THUMB_SIZE);
11576 }
11577 else
11578 {
11579 if (((unsigned long) value) > 0x00ffffff)
11580 as_bad_where (fixP->fx_file, fixP->fx_line,
11581 _("invalid swi expression"));
11582 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff000000;
11583 newval |= value;
11584 md_number_to_chars (buf, newval, INSN_SIZE);
11585 }
11586 break;
11587
11588 case BFD_RELOC_ARM_MULTI:
11589 if (((unsigned long) value) > 0xffff)
11590 as_bad_where (fixP->fx_file, fixP->fx_line,
11591 _("invalid expression in load/store multiple"));
11592 newval = value | md_chars_to_number (buf, INSN_SIZE);
11593 md_number_to_chars (buf, newval, INSN_SIZE);
11594 break;
11595
11596 case BFD_RELOC_ARM_PCREL_BRANCH:
11597 newval = md_chars_to_number (buf, INSN_SIZE);
11598
11599 /* Sign-extend a 24-bit number. */
11600 #define SEXT24(x) ((((x) & 0xffffff) ^ (~ 0x7fffff)) + 0x800000)
11601
11602 #ifdef OBJ_ELF
11603 value = fixP->fx_offset;
11604 #endif
11605
11606 /* We are going to store value (shifted right by two) in the
11607 instruction, in a 24 bit, signed field. Thus we need to check
11608 that none of the top 8 bits of the shifted value (top 7 bits of
11609 the unshifted, unsigned value) are set, or that they are all set. */
11610 if ((value & ~ ((offsetT) 0x1ffffff)) != 0
11611 && ((value & ~ ((offsetT) 0x1ffffff)) != ~ ((offsetT) 0x1ffffff)))
11612 {
11613 #ifdef OBJ_ELF
11614 /* Normally we would be stuck at this point, since we cannot store
11615 the absolute address that is the destination of the branch in the
11616 24 bits of the branch instruction. If however, we happen to know
11617 that the destination of the branch is in the same section as the
11618 branch instruction itself, then we can compute the relocation for
11619 ourselves and not have to bother the linker with it.
11620
11621 FIXME: The test for OBJ_ELF is only here because I have not
11622 worked out how to do this for OBJ_COFF. */
11623 if (fixP->fx_addsy != NULL
11624 && S_IS_DEFINED (fixP->fx_addsy)
11625 && S_GET_SEGMENT (fixP->fx_addsy) == seg)
11626 {
11627 /* Get pc relative value to go into the branch. */
11628 value = * valP;
11629
11630 /* Permit a backward branch provided that enough bits
11631 are set. Allow a forwards branch, provided that
11632 enough bits are clear. */
11633 if ( (value & ~ ((offsetT) 0x1ffffff)) == ~ ((offsetT) 0x1ffffff)
11634 || (value & ~ ((offsetT) 0x1ffffff)) == 0)
11635 fixP->fx_done = 1;
11636 }
11637
11638 if (! fixP->fx_done)
11639 #endif
11640 as_bad_where (fixP->fx_file, fixP->fx_line,
11641 _("GAS can't handle same-section branch dest >= 0x04000000"));
11642 }
11643
11644 value >>= 2;
11645 value += SEXT24 (newval);
11646
11647 if ( (value & ~ ((offsetT) 0xffffff)) != 0
11648 && ((value & ~ ((offsetT) 0xffffff)) != ~ ((offsetT) 0xffffff)))
11649 as_bad_where (fixP->fx_file, fixP->fx_line,
11650 _("out of range branch"));
11651
11652 if (seg->use_rela_p && !fixP->fx_done)
11653 {
11654 /* Must unshift the value before storing it in the addend. */
11655 value <<= 2;
11656 #ifdef OBJ_ELF
11657 fixP->fx_offset = value;
11658 #endif
11659 fixP->fx_addnumber = value;
11660 newval = newval & 0xff000000;
11661 }
11662 else
11663 newval = (value & 0x00ffffff) | (newval & 0xff000000);
11664 md_number_to_chars (buf, newval, INSN_SIZE);
11665 break;
11666
11667 case BFD_RELOC_ARM_PCREL_BLX:
11668 {
11669 offsetT hbit;
11670 newval = md_chars_to_number (buf, INSN_SIZE);
11671
11672 #ifdef OBJ_ELF
11673 value = fixP->fx_offset;
11674 #endif
11675 hbit = (value >> 1) & 1;
11676 value = (value >> 2) & 0x00ffffff;
11677 value = (value + (newval & 0x00ffffff)) & 0x00ffffff;
11678
11679 if (seg->use_rela_p && !fixP->fx_done)
11680 {
11681 /* Must sign-extend and unshift the value before storing
11682 it in the addend. */
11683 value = SEXT24 (value);
11684 value = (value << 2) | hbit;
11685 #ifdef OBJ_ELF
11686 fixP->fx_offset = value;
11687 #endif
11688 fixP->fx_addnumber = value;
11689 newval = newval & 0xfe000000;
11690 }
11691 else
11692 newval = value | (newval & 0xfe000000) | (hbit << 24);
11693 md_number_to_chars (buf, newval, INSN_SIZE);
11694 }
11695 break;
11696
11697 case BFD_RELOC_THUMB_PCREL_BRANCH9: /* Conditional branch. */
11698 newval = md_chars_to_number (buf, THUMB_SIZE);
11699 {
11700 addressT diff = (newval & 0xff) << 1;
11701 if (diff & 0x100)
11702 diff |= ~0xff;
11703
11704 value += diff;
11705 if ((value & ~0xff) && ((value & ~0xff) != ~0xff))
11706 as_bad_where (fixP->fx_file, fixP->fx_line,
11707 _("branch out of range"));
11708 if (seg->use_rela_p && !fixP->fx_done)
11709 {
11710 #ifdef OBJ_ELF
11711 fixP->fx_offset = value;
11712 #endif
11713 fixP->fx_addnumber = value;
11714 newval = newval & 0xff00;
11715 }
11716 else
11717 newval = (newval & 0xff00) | ((value & 0x1ff) >> 1);
11718 }
11719 md_number_to_chars (buf, newval, THUMB_SIZE);
11720 break;
11721
11722 case BFD_RELOC_THUMB_PCREL_BRANCH12: /* Unconditional branch. */
11723 newval = md_chars_to_number (buf, THUMB_SIZE);
11724 {
11725 addressT diff = (newval & 0x7ff) << 1;
11726 if (diff & 0x800)
11727 diff |= ~0x7ff;
11728
11729 value += diff;
11730 if ((value & ~0x7ff) && ((value & ~0x7ff) != ~0x7ff))
11731 as_bad_where (fixP->fx_file, fixP->fx_line,
11732 _("branch out of range"));
11733 if (seg->use_rela_p && !fixP->fx_done)
11734 {
11735 #ifdef OBJ_ELF
11736 fixP->fx_offset = value;
11737 #endif
11738 fixP->fx_addnumber = value;
11739 newval = newval & 0xf800;
11740 }
11741 else
11742 newval = (newval & 0xf800) | ((value & 0xfff) >> 1);
11743 }
11744 md_number_to_chars (buf, newval, THUMB_SIZE);
11745 break;
11746
11747 case BFD_RELOC_THUMB_PCREL_BLX:
11748 case BFD_RELOC_THUMB_PCREL_BRANCH23:
11749 {
11750 offsetT newval2;
11751 addressT diff;
11752
11753 newval = md_chars_to_number (buf, THUMB_SIZE);
11754 newval2 = md_chars_to_number (buf + THUMB_SIZE, THUMB_SIZE);
11755 diff = ((newval & 0x7ff) << 12) | ((newval2 & 0x7ff) << 1);
11756 if (diff & 0x400000)
11757 diff |= ~0x3fffff;
11758 #ifdef OBJ_ELF
11759 value = fixP->fx_offset;
11760 #endif
11761 value += diff;
11762
11763 if ((value & ~0x3fffff) && ((value & ~0x3fffff) != ~0x3fffff))
11764 as_bad_where (fixP->fx_file, fixP->fx_line,
11765 _("branch with link out of range"));
11766
11767 if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX)
11768 /* For a BLX instruction, make sure that the relocation is rounded up
11769 to a word boundary. This follows the semantics of the instruction
11770 which specifies that bit 1 of the target address will come from bit
11771 1 of the base address. */
11772 value = (value + 1) & ~ 1;
11773
11774 if (seg->use_rela_p && !fixP->fx_done)
11775 {
11776 #ifdef OBJ_ELF
11777 fixP->fx_offset = value;
11778 #endif
11779 fixP->fx_addnumber = value;
11780 newval = newval & 0xf800;
11781 newval2 = newval2 & 0xf800;
11782 }
11783 else
11784 {
11785 newval = (newval & 0xf800) | ((value & 0x7fffff) >> 12);
11786 newval2 = (newval2 & 0xf800) | ((value & 0xfff) >> 1);
11787 }
11788 md_number_to_chars (buf, newval, THUMB_SIZE);
11789 md_number_to_chars (buf + THUMB_SIZE, newval2, THUMB_SIZE);
11790 }
11791 break;
11792
11793 case BFD_RELOC_8:
11794 if (seg->use_rela_p && !fixP->fx_done)
11795 break;
11796 if (fixP->fx_done || fixP->fx_pcrel)
11797 md_number_to_chars (buf, value, 1);
11798 #ifdef OBJ_ELF
11799 else
11800 {
11801 value = fixP->fx_offset;
11802 md_number_to_chars (buf, value, 1);
11803 }
11804 #endif
11805 break;
11806
11807 case BFD_RELOC_16:
11808 if (seg->use_rela_p && !fixP->fx_done)
11809 break;
11810 if (fixP->fx_done || fixP->fx_pcrel)
11811 md_number_to_chars (buf, value, 2);
11812 #ifdef OBJ_ELF
11813 else
11814 {
11815 value = fixP->fx_offset;
11816 md_number_to_chars (buf, value, 2);
11817 }
11818 #endif
11819 break;
11820
11821 #ifdef OBJ_ELF
11822 case BFD_RELOC_ARM_GOT32:
11823 case BFD_RELOC_ARM_GOTOFF:
11824 case BFD_RELOC_ARM_TARGET2:
11825 if (seg->use_rela_p && !fixP->fx_done)
11826 break;
11827 md_number_to_chars (buf, 0, 4);
11828 break;
11829 #endif
11830
11831 case BFD_RELOC_RVA:
11832 case BFD_RELOC_32:
11833 case BFD_RELOC_ARM_TARGET1:
11834 case BFD_RELOC_ARM_ROSEGREL32:
11835 case BFD_RELOC_ARM_SBREL32:
11836 case BFD_RELOC_32_PCREL:
11837 if (seg->use_rela_p && !fixP->fx_done)
11838 break;
11839 if (fixP->fx_done || fixP->fx_pcrel)
11840 md_number_to_chars (buf, value, 4);
11841 #ifdef OBJ_ELF
11842 else
11843 {
11844 value = fixP->fx_offset;
11845 md_number_to_chars (buf, value, 4);
11846 }
11847 #endif
11848 break;
11849
11850 #ifdef OBJ_ELF
11851 case BFD_RELOC_ARM_PREL31:
11852 if (fixP->fx_done || fixP->fx_pcrel)
11853 {
11854 newval = md_chars_to_number (buf, 4) & 0x80000000;
11855 if ((value ^ (value >> 1)) & 0x40000000)
11856 {
11857 as_bad_where (fixP->fx_file, fixP->fx_line,
11858 _("rel31 relocation overflow"));
11859 }
11860 newval |= value & 0x7fffffff;
11861 md_number_to_chars (buf, newval, 4);
11862 }
11863 break;
11864
11865 case BFD_RELOC_ARM_PLT32:
11866 /* It appears the instruction is fully prepared at this point. */
11867 break;
11868 #endif
11869
11870 case BFD_RELOC_ARM_CP_OFF_IMM:
11871 sign = value >= 0;
11872 if (value < -1023 || value > 1023 || (value & 3))
11873 as_bad_where (fixP->fx_file, fixP->fx_line,
11874 _("illegal value for co-processor offset"));
11875 if (value < 0)
11876 value = -value;
11877 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
11878 newval |= (value >> 2) | (sign ? INDEX_UP : 0);
11879 md_number_to_chars (buf, newval, INSN_SIZE);
11880 break;
11881
11882 case BFD_RELOC_ARM_CP_OFF_IMM_S2:
11883 sign = value >= 0;
11884 if (value < -255 || value > 255)
11885 as_bad_where (fixP->fx_file, fixP->fx_line,
11886 _("Illegal value for co-processor offset"));
11887 if (value < 0)
11888 value = -value;
11889 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
11890 newval |= value | (sign ? INDEX_UP : 0);
11891 md_number_to_chars (buf, newval , INSN_SIZE);
11892 break;
11893
11894 case BFD_RELOC_ARM_THUMB_OFFSET:
11895 newval = md_chars_to_number (buf, THUMB_SIZE);
11896 /* Exactly what ranges, and where the offset is inserted depends
11897 on the type of instruction, we can establish this from the
11898 top 4 bits. */
11899 switch (newval >> 12)
11900 {
11901 case 4: /* PC load. */
11902 /* Thumb PC loads are somewhat odd, bit 1 of the PC is
11903 forced to zero for these loads, so we will need to round
11904 up the offset if the instruction address is not word
11905 aligned (since the final address produced must be, and
11906 we can only describe word-aligned immediate offsets). */
11907
11908 if ((fixP->fx_frag->fr_address + fixP->fx_where + value) & 3)
11909 as_bad_where (fixP->fx_file, fixP->fx_line,
11910 _("invalid offset, target not word aligned (0x%08X)"),
11911 (unsigned int) (fixP->fx_frag->fr_address
11912 + fixP->fx_where + value));
11913
11914 if ((value + 2) & ~0x3fe)
11915 as_bad_where (fixP->fx_file, fixP->fx_line,
11916 _("invalid offset, value too big (0x%08lX)"),
11917 (long) value);
11918
11919 /* Round up, since pc will be rounded down. */
11920 newval |= (value + 2) >> 2;
11921 break;
11922
11923 case 9: /* SP load/store. */
11924 if (value & ~0x3fc)
11925 as_bad_where (fixP->fx_file, fixP->fx_line,
11926 _("invalid offset, value too big (0x%08lX)"),
11927 (long) value);
11928 newval |= value >> 2;
11929 break;
11930
11931 case 6: /* Word load/store. */
11932 if (value & ~0x7c)
11933 as_bad_where (fixP->fx_file, fixP->fx_line,
11934 _("invalid offset, value too big (0x%08lX)"),
11935 (long) value);
11936 newval |= value << 4; /* 6 - 2. */
11937 break;
11938
11939 case 7: /* Byte load/store. */
11940 if (value & ~0x1f)
11941 as_bad_where (fixP->fx_file, fixP->fx_line,
11942 _("invalid offset, value too big (0x%08lX)"),
11943 (long) value);
11944 newval |= value << 6;
11945 break;
11946
11947 case 8: /* Halfword load/store. */
11948 if (value & ~0x3e)
11949 as_bad_where (fixP->fx_file, fixP->fx_line,
11950 _("invalid offset, value too big (0x%08lX)"),
11951 (long) value);
11952 newval |= value << 5; /* 6 - 1. */
11953 break;
11954
11955 default:
11956 as_bad_where (fixP->fx_file, fixP->fx_line,
11957 "Unable to process relocation for thumb opcode: %lx",
11958 (unsigned long) newval);
11959 break;
11960 }
11961 md_number_to_chars (buf, newval, THUMB_SIZE);
11962 break;
11963
11964 case BFD_RELOC_ARM_THUMB_ADD:
11965 /* This is a complicated relocation, since we use it for all of
11966 the following immediate relocations:
11967
11968 3bit ADD/SUB
11969 8bit ADD/SUB
11970 9bit ADD/SUB SP word-aligned
11971 10bit ADD PC/SP word-aligned
11972
11973 The type of instruction being processed is encoded in the
11974 instruction field:
11975
11976 0x8000 SUB
11977 0x00F0 Rd
11978 0x000F Rs
11979 */
11980 newval = md_chars_to_number (buf, THUMB_SIZE);
11981 {
11982 int rd = (newval >> 4) & 0xf;
11983 int rs = newval & 0xf;
11984 int subtract = newval & 0x8000;
11985
11986 if (rd == REG_SP)
11987 {
11988 if (value & ~0x1fc)
11989 as_bad_where (fixP->fx_file, fixP->fx_line,
11990 _("invalid immediate for stack address calculation"));
11991 newval = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
11992 newval |= value >> 2;
11993 }
11994 else if (rs == REG_PC || rs == REG_SP)
11995 {
11996 if (subtract ||
11997 value & ~0x3fc)
11998 as_bad_where (fixP->fx_file, fixP->fx_line,
11999 _("invalid immediate for address calculation (value = 0x%08lX)"),
12000 (unsigned long) value);
12001 newval = (rs == REG_PC ? T_OPCODE_ADD_PC : T_OPCODE_ADD_SP);
12002 newval |= rd << 8;
12003 newval |= value >> 2;
12004 }
12005 else if (rs == rd)
12006 {
12007 if (value & ~0xff)
12008 as_bad_where (fixP->fx_file, fixP->fx_line,
12009 _("invalid 8bit immediate"));
12010 newval = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
12011 newval |= (rd << 8) | value;
12012 }
12013 else
12014 {
12015 if (value & ~0x7)
12016 as_bad_where (fixP->fx_file, fixP->fx_line,
12017 _("invalid 3bit immediate"));
12018 newval = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
12019 newval |= rd | (rs << 3) | (value << 6);
12020 }
12021 }
12022 md_number_to_chars (buf, newval, THUMB_SIZE);
12023 break;
12024
12025 case BFD_RELOC_ARM_THUMB_IMM:
12026 newval = md_chars_to_number (buf, THUMB_SIZE);
12027 switch (newval >> 11)
12028 {
12029 case 0x04: /* 8bit immediate MOV. */
12030 case 0x05: /* 8bit immediate CMP. */
12031 if (value < 0 || value > 255)
12032 as_bad_where (fixP->fx_file, fixP->fx_line,
12033 _("invalid immediate: %ld is too large"),
12034 (long) value);
12035 newval |= value;
12036 break;
12037
12038 default:
12039 abort ();
12040 }
12041 md_number_to_chars (buf, newval, THUMB_SIZE);
12042 break;
12043
12044 case BFD_RELOC_ARM_THUMB_SHIFT:
12045 /* 5bit shift value (0..31). */
12046 if (value < 0 || value > 31)
12047 as_bad_where (fixP->fx_file, fixP->fx_line,
12048 _("illegal Thumb shift value: %ld"), (long) value);
12049 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xf03f;
12050 newval |= value << 6;
12051 md_number_to_chars (buf, newval, THUMB_SIZE);
12052 break;
12053
12054 case BFD_RELOC_VTABLE_INHERIT:
12055 case BFD_RELOC_VTABLE_ENTRY:
12056 fixP->fx_done = 0;
12057 return;
12058
12059 case BFD_RELOC_UNUSED:
12060 default:
12061 as_bad_where (fixP->fx_file, fixP->fx_line,
12062 _("bad relocation fixup type (%d)"), fixP->fx_r_type);
12063 }
12064 }
12065
12066 /* Translate internal representation of relocation info to BFD target
12067 format. */
12068
12069 arelent *
12070 tc_gen_reloc (asection * section ATTRIBUTE_UNUSED,
12071 fixS * fixp)
12072 {
12073 arelent * reloc;
12074 bfd_reloc_code_real_type code;
12075
12076 reloc = xmalloc (sizeof (arelent));
12077
12078 reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
12079 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
12080 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
12081
12082 /* @@ Why fx_addnumber sometimes and fx_offset other times? */
12083 #ifndef OBJ_ELF
12084 if (fixp->fx_pcrel == 0)
12085 reloc->addend = fixp->fx_offset;
12086 else
12087 reloc->addend = fixp->fx_offset = reloc->address;
12088 #else /* OBJ_ELF */
12089 reloc->addend = fixp->fx_offset;
12090 #endif
12091
12092 switch (fixp->fx_r_type)
12093 {
12094 case BFD_RELOC_8:
12095 if (fixp->fx_pcrel)
12096 {
12097 code = BFD_RELOC_8_PCREL;
12098 break;
12099 }
12100
12101 case BFD_RELOC_16:
12102 if (fixp->fx_pcrel)
12103 {
12104 code = BFD_RELOC_16_PCREL;
12105 break;
12106 }
12107
12108 case BFD_RELOC_32:
12109 if (fixp->fx_pcrel)
12110 {
12111 code = BFD_RELOC_32_PCREL;
12112 break;
12113 }
12114
12115 case BFD_RELOC_NONE:
12116 case BFD_RELOC_ARM_PCREL_BRANCH:
12117 case BFD_RELOC_ARM_PCREL_BLX:
12118 case BFD_RELOC_RVA:
12119 case BFD_RELOC_THUMB_PCREL_BRANCH9:
12120 case BFD_RELOC_THUMB_PCREL_BRANCH12:
12121 case BFD_RELOC_THUMB_PCREL_BRANCH23:
12122 case BFD_RELOC_THUMB_PCREL_BLX:
12123 case BFD_RELOC_VTABLE_ENTRY:
12124 case BFD_RELOC_VTABLE_INHERIT:
12125 code = fixp->fx_r_type;
12126 break;
12127
12128 case BFD_RELOC_ARM_LITERAL:
12129 case BFD_RELOC_ARM_HWLITERAL:
12130 /* If this is called then the a literal has
12131 been referenced across a section boundary. */
12132 as_bad_where (fixp->fx_file, fixp->fx_line,
12133 _("literal referenced across section boundary"));
12134 return NULL;
12135
12136 #ifdef OBJ_ELF
12137 case BFD_RELOC_ARM_GOT32:
12138 case BFD_RELOC_ARM_GOTOFF:
12139 case BFD_RELOC_ARM_PLT32:
12140 case BFD_RELOC_ARM_TARGET1:
12141 case BFD_RELOC_ARM_ROSEGREL32:
12142 case BFD_RELOC_ARM_SBREL32:
12143 case BFD_RELOC_ARM_PREL31:
12144 case BFD_RELOC_ARM_TARGET2:
12145 code = fixp->fx_r_type;
12146 break;
12147 #endif
12148
12149 case BFD_RELOC_ARM_IMMEDIATE:
12150 as_bad_where (fixp->fx_file, fixp->fx_line,
12151 _("internal relocation (type: IMMEDIATE) not fixed up"));
12152 return NULL;
12153
12154 case BFD_RELOC_ARM_ADRL_IMMEDIATE:
12155 as_bad_where (fixp->fx_file, fixp->fx_line,
12156 _("ADRL used for a symbol not defined in the same file"));
12157 return NULL;
12158
12159 case BFD_RELOC_ARM_OFFSET_IMM:
12160 if (fixp->fx_addsy != NULL
12161 && !S_IS_DEFINED (fixp->fx_addsy)
12162 && S_IS_LOCAL (fixp->fx_addsy))
12163 {
12164 as_bad_where (fixp->fx_file, fixp->fx_line,
12165 _("undefined local label `%s'"),
12166 S_GET_NAME (fixp->fx_addsy));
12167 return NULL;
12168 }
12169
12170 as_bad_where (fixp->fx_file, fixp->fx_line,
12171 _("internal_relocation (type: OFFSET_IMM) not fixed up"));
12172 return NULL;
12173
12174 default:
12175 {
12176 char * type;
12177
12178 switch (fixp->fx_r_type)
12179 {
12180 case BFD_RELOC_NONE: type = "NONE"; break;
12181 case BFD_RELOC_ARM_OFFSET_IMM8: type = "OFFSET_IMM8"; break;
12182 case BFD_RELOC_ARM_SHIFT_IMM: type = "SHIFT_IMM"; break;
12183 case BFD_RELOC_ARM_SMI: type = "SMI"; break;
12184 case BFD_RELOC_ARM_SWI: type = "SWI"; break;
12185 case BFD_RELOC_ARM_MULTI: type = "MULTI"; break;
12186 case BFD_RELOC_ARM_CP_OFF_IMM: type = "CP_OFF_IMM"; break;
12187 case BFD_RELOC_ARM_THUMB_ADD: type = "THUMB_ADD"; break;
12188 case BFD_RELOC_ARM_THUMB_SHIFT: type = "THUMB_SHIFT"; break;
12189 case BFD_RELOC_ARM_THUMB_IMM: type = "THUMB_IMM"; break;
12190 case BFD_RELOC_ARM_THUMB_OFFSET: type = "THUMB_OFFSET"; break;
12191 default: type = _("<unknown>"); break;
12192 }
12193 as_bad_where (fixp->fx_file, fixp->fx_line,
12194 _("cannot represent %s relocation in this object file format"),
12195 type);
12196 return NULL;
12197 }
12198 }
12199
12200 #ifdef OBJ_ELF
12201 if ((code == BFD_RELOC_32_PCREL || code == BFD_RELOC_32)
12202 && GOT_symbol
12203 && fixp->fx_addsy == GOT_symbol)
12204 {
12205 code = BFD_RELOC_ARM_GOTPC;
12206 reloc->addend = fixp->fx_offset = reloc->address;
12207 }
12208 #endif
12209
12210 reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
12211
12212 if (reloc->howto == NULL)
12213 {
12214 as_bad_where (fixp->fx_file, fixp->fx_line,
12215 _("cannot represent %s relocation in this object file format"),
12216 bfd_get_reloc_code_name (code));
12217 return NULL;
12218 }
12219
12220 /* HACK: Since arm ELF uses Rel instead of Rela, encode the
12221 vtable entry to be used in the relocation's section offset. */
12222 if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
12223 reloc->address = fixp->fx_offset;
12224
12225 return reloc;
12226 }
12227
12228 int
12229 md_estimate_size_before_relax (fragS * fragP ATTRIBUTE_UNUSED,
12230 segT segtype ATTRIBUTE_UNUSED)
12231 {
12232 as_fatal (_("md_estimate_size_before_relax\n"));
12233 return 1;
12234 }
12235
12236 /* We need to be able to fix up arbitrary expressions in some statements.
12237 This is so that we can handle symbols that are an arbitrary distance from
12238 the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
12239 which returns part of an address in a form which will be valid for
12240 a data instruction. We do this by pushing the expression into a symbol
12241 in the expr_section, and creating a fix for that. */
12242
12243 static void
12244 fix_new_arm (fragS * frag,
12245 int where,
12246 short int size,
12247 expressionS * exp,
12248 int pc_rel,
12249 int reloc)
12250 {
12251 fixS * new_fix;
12252 arm_fix_data * arm_data;
12253
12254 switch (exp->X_op)
12255 {
12256 case O_constant:
12257 case O_symbol:
12258 case O_add:
12259 case O_subtract:
12260 new_fix = fix_new_exp (frag, where, size, exp, pc_rel, reloc);
12261 break;
12262
12263 default:
12264 new_fix = fix_new (frag, where, size, make_expr_symbol (exp), 0,
12265 pc_rel, reloc);
12266 break;
12267 }
12268
12269 /* Mark whether the fix is to a THUMB instruction, or an ARM
12270 instruction. */
12271 arm_data = obstack_alloc (& notes, sizeof (arm_fix_data));
12272 new_fix->tc_fix_data = (PTR) arm_data;
12273 arm_data->thumb_mode = thumb_mode;
12274 }
12275
12276 static void
12277 output_inst (const char * str)
12278 {
12279 char * to = NULL;
12280
12281 if (inst.error)
12282 {
12283 as_bad ("%s -- `%s'", inst.error, str);
12284 return;
12285 }
12286
12287 to = frag_more (inst.size);
12288
12289 if (thumb_mode && (inst.size > THUMB_SIZE))
12290 {
12291 assert (inst.size == (2 * THUMB_SIZE));
12292 md_number_to_chars (to, inst.instruction >> 16, THUMB_SIZE);
12293 md_number_to_chars (to + THUMB_SIZE, inst.instruction, THUMB_SIZE);
12294 }
12295 else if (inst.size > INSN_SIZE)
12296 {
12297 assert (inst.size == (2 * INSN_SIZE));
12298 md_number_to_chars (to, inst.instruction, INSN_SIZE);
12299 md_number_to_chars (to + INSN_SIZE, inst.instruction, INSN_SIZE);
12300 }
12301 else
12302 md_number_to_chars (to, inst.instruction, inst.size);
12303
12304 if (inst.reloc.type != BFD_RELOC_UNUSED)
12305 fix_new_arm (frag_now, to - frag_now->fr_literal,
12306 inst.size, & inst.reloc.exp, inst.reloc.pc_rel,
12307 inst.reloc.type);
12308
12309 #ifdef OBJ_ELF
12310 dwarf2_emit_insn (inst.size);
12311 #endif
12312 }
12313
12314 void
12315 md_assemble (char * str)
12316 {
12317 char c;
12318 char *p;
12319 char *start;
12320
12321 /* Align the previous label if needed. */
12322 if (last_label_seen != NULL)
12323 {
12324 symbol_set_frag (last_label_seen, frag_now);
12325 S_SET_VALUE (last_label_seen, (valueT) frag_now_fix ());
12326 S_SET_SEGMENT (last_label_seen, now_seg);
12327 }
12328
12329 memset (&inst, '\0', sizeof (inst));
12330 inst.reloc.type = BFD_RELOC_UNUSED;
12331
12332 skip_whitespace (str);
12333
12334 /* Scan up to the end of the op-code, which must end in white space or
12335 end of string. */
12336 for (start = p = str; *p != '\0'; p++)
12337 if (*p == ' ')
12338 break;
12339
12340 if (p == str)
12341 {
12342 as_bad (_("no operator -- statement `%s'\n"), str);
12343 return;
12344 }
12345
12346 if (thumb_mode)
12347 {
12348 const struct thumb_opcode * opcode;
12349
12350 c = *p;
12351 *p = '\0';
12352 opcode = (const struct thumb_opcode *) hash_find (arm_tops_hsh, str);
12353 *p = c;
12354
12355 if (opcode)
12356 {
12357 /* Check that this instruction is supported for this CPU. */
12358 if (thumb_mode == 1 && (opcode->variant & cpu_variant) == 0)
12359 {
12360 as_bad (_("selected processor does not support `%s'"), str);
12361 return;
12362 }
12363
12364 mapping_state (MAP_THUMB);
12365 inst.instruction = opcode->value;
12366 inst.size = opcode->size;
12367 opcode->parms (p);
12368 output_inst (str);
12369 return;
12370 }
12371 }
12372 else
12373 {
12374 const struct asm_opcode * opcode;
12375
12376 c = *p;
12377 *p = '\0';
12378 opcode = (const struct asm_opcode *) hash_find (arm_ops_hsh, str);
12379 *p = c;
12380
12381 if (opcode)
12382 {
12383 /* Check that this instruction is supported for this CPU. */
12384 if ((opcode->variant & cpu_variant) == 0)
12385 {
12386 as_bad (_("selected processor does not support `%s'"), str);
12387 return;
12388 }
12389
12390 mapping_state (MAP_ARM);
12391 inst.instruction = opcode->value;
12392 inst.size = INSN_SIZE;
12393 opcode->parms (p);
12394 output_inst (str);
12395 return;
12396 }
12397 }
12398
12399 /* It wasn't an instruction, but it might be a register alias of the form
12400 alias .req reg. */
12401 if (create_register_alias (str, p))
12402 return;
12403
12404 as_bad (_("bad instruction `%s'"), start);
12405 }
12406
12407 /* md_parse_option
12408 Invocation line includes a switch not recognized by the base assembler.
12409 See if it's a processor-specific option.
12410
12411 This routine is somewhat complicated by the need for backwards
12412 compatibility (since older releases of gcc can't be changed).
12413 The new options try to make the interface as compatible as
12414 possible with GCC.
12415
12416 New options (supported) are:
12417
12418 -mcpu=<cpu name> Assemble for selected processor
12419 -march=<architecture name> Assemble for selected architecture
12420 -mfpu=<fpu architecture> Assemble for selected FPU.
12421 -EB/-mbig-endian Big-endian
12422 -EL/-mlittle-endian Little-endian
12423 -k Generate PIC code
12424 -mthumb Start in Thumb mode
12425 -mthumb-interwork Code supports ARM/Thumb interworking
12426
12427 For now we will also provide support for:
12428
12429 -mapcs-32 32-bit Program counter
12430 -mapcs-26 26-bit Program counter
12431 -macps-float Floats passed in FP registers
12432 -mapcs-reentrant Reentrant code
12433 -matpcs
12434 (sometime these will probably be replaced with -mapcs=<list of options>
12435 and -matpcs=<list of options>)
12436
12437 The remaining options are only supported for back-wards compatibility.
12438 Cpu variants, the arm part is optional:
12439 -m[arm]1 Currently not supported.
12440 -m[arm]2, -m[arm]250 Arm 2 and Arm 250 processor
12441 -m[arm]3 Arm 3 processor
12442 -m[arm]6[xx], Arm 6 processors
12443 -m[arm]7[xx][t][[d]m] Arm 7 processors
12444 -m[arm]8[10] Arm 8 processors
12445 -m[arm]9[20][tdmi] Arm 9 processors
12446 -mstrongarm[110[0]] StrongARM processors
12447 -mxscale XScale processors
12448 -m[arm]v[2345[t[e]]] Arm architectures
12449 -mall All (except the ARM1)
12450 FP variants:
12451 -mfpa10, -mfpa11 FPA10 and 11 co-processor instructions
12452 -mfpe-old (No float load/store multiples)
12453 -mvfpxd VFP Single precision
12454 -mvfp All VFP
12455 -mno-fpu Disable all floating point instructions
12456
12457 The following CPU names are recognized:
12458 arm1, arm2, arm250, arm3, arm6, arm600, arm610, arm620,
12459 arm7, arm7m, arm7d, arm7dm, arm7di, arm7dmi, arm70, arm700,
12460 arm700i, arm710 arm710t, arm720, arm720t, arm740t, arm710c,
12461 arm7100, arm7500, arm7500fe, arm7tdmi, arm8, arm810, arm9,
12462 arm920, arm920t, arm940t, arm946, arm966, arm9tdmi, arm9e,
12463 arm10t arm10e, arm1020t, arm1020e, arm10200e,
12464 strongarm, strongarm110, strongarm1100, strongarm1110, xscale.
12465
12466 */
12467
12468 const char * md_shortopts = "m:k";
12469
12470 #ifdef ARM_BI_ENDIAN
12471 #define OPTION_EB (OPTION_MD_BASE + 0)
12472 #define OPTION_EL (OPTION_MD_BASE + 1)
12473 #else
12474 #if TARGET_BYTES_BIG_ENDIAN
12475 #define OPTION_EB (OPTION_MD_BASE + 0)
12476 #else
12477 #define OPTION_EL (OPTION_MD_BASE + 1)
12478 #endif
12479 #endif
12480
12481 struct option md_longopts[] =
12482 {
12483 #ifdef OPTION_EB
12484 {"EB", no_argument, NULL, OPTION_EB},
12485 #endif
12486 #ifdef OPTION_EL
12487 {"EL", no_argument, NULL, OPTION_EL},
12488 #endif
12489 {NULL, no_argument, NULL, 0}
12490 };
12491
12492 size_t md_longopts_size = sizeof (md_longopts);
12493
12494 struct arm_option_table
12495 {
12496 char *option; /* Option name to match. */
12497 char *help; /* Help information. */
12498 int *var; /* Variable to change. */
12499 int value; /* What to change it to. */
12500 char *deprecated; /* If non-null, print this message. */
12501 };
12502
12503 struct arm_option_table arm_opts[] =
12504 {
12505 {"k", N_("generate PIC code"), &pic_code, 1, NULL},
12506 {"mthumb", N_("assemble Thumb code"), &thumb_mode, 1, NULL},
12507 {"mthumb-interwork", N_("support ARM/Thumb interworking"),
12508 &support_interwork, 1, NULL},
12509 {"mapcs-32", N_("code uses 32-bit program counter"), &uses_apcs_26, 0, NULL},
12510 {"mapcs-26", N_("code uses 26-bit program counter"), &uses_apcs_26, 1, NULL},
12511 {"mapcs-float", N_("floating point args are in fp regs"), &uses_apcs_float,
12512 1, NULL},
12513 {"mapcs-reentrant", N_("re-entrant code"), &pic_code, 1, NULL},
12514 {"matpcs", N_("code is ATPCS conformant"), &atpcs, 1, NULL},
12515 {"mbig-endian", N_("assemble for big-endian"), &target_big_endian, 1, NULL},
12516 {"mlittle-endian", N_("assemble for little-endian"), &target_big_endian, 1,
12517 NULL},
12518
12519 /* These are recognized by the assembler, but have no affect on code. */
12520 {"mapcs-frame", N_("use frame pointer"), NULL, 0, NULL},
12521 {"mapcs-stack-check", N_("use stack size checking"), NULL, 0, NULL},
12522
12523 /* DON'T add any new processors to this list -- we want the whole list
12524 to go away... Add them to the processors table instead. */
12525 {"marm1", NULL, &legacy_cpu, ARM_ARCH_V1, N_("use -mcpu=arm1")},
12526 {"m1", NULL, &legacy_cpu, ARM_ARCH_V1, N_("use -mcpu=arm1")},
12527 {"marm2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -mcpu=arm2")},
12528 {"m2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -mcpu=arm2")},
12529 {"marm250", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm250")},
12530 {"m250", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm250")},
12531 {"marm3", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm3")},
12532 {"m3", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm3")},
12533 {"marm6", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm6")},
12534 {"m6", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm6")},
12535 {"marm600", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm600")},
12536 {"m600", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm600")},
12537 {"marm610", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm610")},
12538 {"m610", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm610")},
12539 {"marm620", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm620")},
12540 {"m620", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm620")},
12541 {"marm7", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7")},
12542 {"m7", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7")},
12543 {"marm70", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm70")},
12544 {"m70", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm70")},
12545 {"marm700", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700")},
12546 {"m700", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700")},
12547 {"marm700i", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700i")},
12548 {"m700i", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700i")},
12549 {"marm710", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710")},
12550 {"m710", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710")},
12551 {"marm710c", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710c")},
12552 {"m710c", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710c")},
12553 {"marm720", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm720")},
12554 {"m720", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm720")},
12555 {"marm7d", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7d")},
12556 {"m7d", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7d")},
12557 {"marm7di", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7di")},
12558 {"m7di", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7di")},
12559 {"marm7m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7m")},
12560 {"m7m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7m")},
12561 {"marm7dm", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dm")},
12562 {"m7dm", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dm")},
12563 {"marm7dmi", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dmi")},
12564 {"m7dmi", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dmi")},
12565 {"marm7100", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7100")},
12566 {"m7100", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7100")},
12567 {"marm7500", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500")},
12568 {"m7500", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500")},
12569 {"marm7500fe", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500fe")},
12570 {"m7500fe", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500fe")},
12571 {"marm7t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
12572 {"m7t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
12573 {"marm7tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
12574 {"m7tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
12575 {"marm710t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm710t")},
12576 {"m710t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm710t")},
12577 {"marm720t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm720t")},
12578 {"m720t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm720t")},
12579 {"marm740t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm740t")},
12580 {"m740t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm740t")},
12581 {"marm8", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm8")},
12582 {"m8", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm8")},
12583 {"marm810", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm810")},
12584 {"m810", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm810")},
12585 {"marm9", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9")},
12586 {"m9", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9")},
12587 {"marm9tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9tdmi")},
12588 {"m9tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9tdmi")},
12589 {"marm920", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm920")},
12590 {"m920", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm920")},
12591 {"marm940", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm940")},
12592 {"m940", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm940")},
12593 {"mstrongarm", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=strongarm")},
12594 {"mstrongarm110", NULL, &legacy_cpu, ARM_ARCH_V4,
12595 N_("use -mcpu=strongarm110")},
12596 {"mstrongarm1100", NULL, &legacy_cpu, ARM_ARCH_V4,
12597 N_("use -mcpu=strongarm1100")},
12598 {"mstrongarm1110", NULL, &legacy_cpu, ARM_ARCH_V4,
12599 N_("use -mcpu=strongarm1110")},
12600 {"mxscale", NULL, &legacy_cpu, ARM_ARCH_XSCALE, N_("use -mcpu=xscale")},
12601 {"miwmmxt", NULL, &legacy_cpu, ARM_ARCH_IWMMXT, N_("use -mcpu=iwmmxt")},
12602 {"mall", NULL, &legacy_cpu, ARM_ANY, N_("use -mcpu=all")},
12603
12604 /* Architecture variants -- don't add any more to this list either. */
12605 {"mv2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -march=armv2")},
12606 {"marmv2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -march=armv2")},
12607 {"mv2a", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -march=armv2a")},
12608 {"marmv2a", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -march=armv2a")},
12609 {"mv3", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -march=armv3")},
12610 {"marmv3", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -march=armv3")},
12611 {"mv3m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -march=armv3m")},
12612 {"marmv3m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -march=armv3m")},
12613 {"mv4", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -march=armv4")},
12614 {"marmv4", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -march=armv4")},
12615 {"mv4t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -march=armv4t")},
12616 {"marmv4t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -march=armv4t")},
12617 {"mv5", NULL, &legacy_cpu, ARM_ARCH_V5, N_("use -march=armv5")},
12618 {"marmv5", NULL, &legacy_cpu, ARM_ARCH_V5, N_("use -march=armv5")},
12619 {"mv5t", NULL, &legacy_cpu, ARM_ARCH_V5T, N_("use -march=armv5t")},
12620 {"marmv5t", NULL, &legacy_cpu, ARM_ARCH_V5T, N_("use -march=armv5t")},
12621 {"mv5e", NULL, &legacy_cpu, ARM_ARCH_V5TE, N_("use -march=armv5te")},
12622 {"marmv5e", NULL, &legacy_cpu, ARM_ARCH_V5TE, N_("use -march=armv5te")},
12623
12624 /* Floating point variants -- don't add any more to this list either. */
12625 {"mfpe-old", NULL, &legacy_fpu, FPU_ARCH_FPE, N_("use -mfpu=fpe")},
12626 {"mfpa10", NULL, &legacy_fpu, FPU_ARCH_FPA, N_("use -mfpu=fpa10")},
12627 {"mfpa11", NULL, &legacy_fpu, FPU_ARCH_FPA, N_("use -mfpu=fpa11")},
12628 {"mno-fpu", NULL, &legacy_fpu, 0,
12629 N_("use either -mfpu=softfpa or -mfpu=softvfp")},
12630
12631 {NULL, NULL, NULL, 0, NULL}
12632 };
12633
12634 struct arm_cpu_option_table
12635 {
12636 char *name;
12637 int value;
12638 /* For some CPUs we assume an FPU unless the user explicitly sets
12639 -mfpu=... */
12640 int default_fpu;
12641 };
12642
12643 /* This list should, at a minimum, contain all the cpu names
12644 recognized by GCC. */
12645 static struct arm_cpu_option_table arm_cpus[] =
12646 {
12647 {"all", ARM_ANY, FPU_ARCH_FPA},
12648 {"arm1", ARM_ARCH_V1, FPU_ARCH_FPA},
12649 {"arm2", ARM_ARCH_V2, FPU_ARCH_FPA},
12650 {"arm250", ARM_ARCH_V2S, FPU_ARCH_FPA},
12651 {"arm3", ARM_ARCH_V2S, FPU_ARCH_FPA},
12652 {"arm6", ARM_ARCH_V3, FPU_ARCH_FPA},
12653 {"arm60", ARM_ARCH_V3, FPU_ARCH_FPA},
12654 {"arm600", ARM_ARCH_V3, FPU_ARCH_FPA},
12655 {"arm610", ARM_ARCH_V3, FPU_ARCH_FPA},
12656 {"arm620", ARM_ARCH_V3, FPU_ARCH_FPA},
12657 {"arm7", ARM_ARCH_V3, FPU_ARCH_FPA},
12658 {"arm7m", ARM_ARCH_V3M, FPU_ARCH_FPA},
12659 {"arm7d", ARM_ARCH_V3, FPU_ARCH_FPA},
12660 {"arm7dm", ARM_ARCH_V3M, FPU_ARCH_FPA},
12661 {"arm7di", ARM_ARCH_V3, FPU_ARCH_FPA},
12662 {"arm7dmi", ARM_ARCH_V3M, FPU_ARCH_FPA},
12663 {"arm70", ARM_ARCH_V3, FPU_ARCH_FPA},
12664 {"arm700", ARM_ARCH_V3, FPU_ARCH_FPA},
12665 {"arm700i", ARM_ARCH_V3, FPU_ARCH_FPA},
12666 {"arm710", ARM_ARCH_V3, FPU_ARCH_FPA},
12667 {"arm710t", ARM_ARCH_V4T, FPU_ARCH_FPA},
12668 {"arm720", ARM_ARCH_V3, FPU_ARCH_FPA},
12669 {"arm720t", ARM_ARCH_V4T, FPU_ARCH_FPA},
12670 {"arm740t", ARM_ARCH_V4T, FPU_ARCH_FPA},
12671 {"arm710c", ARM_ARCH_V3, FPU_ARCH_FPA},
12672 {"arm7100", ARM_ARCH_V3, FPU_ARCH_FPA},
12673 {"arm7500", ARM_ARCH_V3, FPU_ARCH_FPA},
12674 {"arm7500fe", ARM_ARCH_V3, FPU_ARCH_FPA},
12675 {"arm7t", ARM_ARCH_V4T, FPU_ARCH_FPA},
12676 {"arm7tdmi", ARM_ARCH_V4T, FPU_ARCH_FPA},
12677 {"arm7tdmi-s", ARM_ARCH_V4T, FPU_ARCH_FPA},
12678 {"arm8", ARM_ARCH_V4, FPU_ARCH_FPA},
12679 {"arm810", ARM_ARCH_V4, FPU_ARCH_FPA},
12680 {"strongarm", ARM_ARCH_V4, FPU_ARCH_FPA},
12681 {"strongarm1", ARM_ARCH_V4, FPU_ARCH_FPA},
12682 {"strongarm110", ARM_ARCH_V4, FPU_ARCH_FPA},
12683 {"strongarm1100", ARM_ARCH_V4, FPU_ARCH_FPA},
12684 {"strongarm1110", ARM_ARCH_V4, FPU_ARCH_FPA},
12685 {"arm9", ARM_ARCH_V4T, FPU_ARCH_FPA},
12686 {"arm920", ARM_ARCH_V4T, FPU_ARCH_FPA},
12687 {"arm920t", ARM_ARCH_V4T, FPU_ARCH_FPA},
12688 {"arm922t", ARM_ARCH_V4T, FPU_ARCH_FPA},
12689 {"arm940t", ARM_ARCH_V4T, FPU_ARCH_FPA},
12690 {"arm9tdmi", ARM_ARCH_V4T, FPU_ARCH_FPA},
12691 /* For V5 or later processors we default to using VFP; but the user
12692 should really set the FPU type explicitly. */
12693 {"arm9e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
12694 {"arm9e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
12695 {"arm926ej", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
12696 {"arm926ejs", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
12697 {"arm926ej-s", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
12698 {"arm946e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
12699 {"arm946e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
12700 {"arm966e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
12701 {"arm966e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
12702 {"arm10t", ARM_ARCH_V5T, FPU_ARCH_VFP_V1},
12703 {"arm10e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
12704 {"arm1020", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
12705 {"arm1020t", ARM_ARCH_V5T, FPU_ARCH_VFP_V1},
12706 {"arm1020e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
12707 {"arm1026ejs", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
12708 {"arm1026ej-s", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
12709 {"arm1136js", ARM_ARCH_V6, FPU_NONE},
12710 {"arm1136j-s", ARM_ARCH_V6, FPU_NONE},
12711 {"arm1136jfs", ARM_ARCH_V6, FPU_ARCH_VFP_V2},
12712 {"arm1136jf-s", ARM_ARCH_V6, FPU_ARCH_VFP_V2},
12713 {"mpcore", ARM_ARCH_V6K, FPU_ARCH_VFP_V2},
12714 {"mpcorenovfp", ARM_ARCH_V6K, FPU_NONE},
12715 {"arm1176jz-s", ARM_ARCH_V6ZK, FPU_NONE},
12716 {"arm1176jzf-s", ARM_ARCH_V6ZK, FPU_ARCH_VFP_V2},
12717 /* ??? XSCALE is really an architecture. */
12718 {"xscale", ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2},
12719 /* ??? iwmmxt is not a processor. */
12720 {"iwmmxt", ARM_ARCH_IWMMXT, FPU_ARCH_VFP_V2},
12721 {"i80200", ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2},
12722 /* Maverick */
12723 {"ep9312", ARM_ARCH_V4T | ARM_CEXT_MAVERICK, FPU_ARCH_MAVERICK},
12724 {NULL, 0, 0}
12725 };
12726
12727 struct arm_arch_option_table
12728 {
12729 char *name;
12730 int value;
12731 int default_fpu;
12732 };
12733
12734 /* This list should, at a minimum, contain all the architecture names
12735 recognized by GCC. */
12736 static struct arm_arch_option_table arm_archs[] =
12737 {
12738 {"all", ARM_ANY, FPU_ARCH_FPA},
12739 {"armv1", ARM_ARCH_V1, FPU_ARCH_FPA},
12740 {"armv2", ARM_ARCH_V2, FPU_ARCH_FPA},
12741 {"armv2a", ARM_ARCH_V2S, FPU_ARCH_FPA},
12742 {"armv2s", ARM_ARCH_V2S, FPU_ARCH_FPA},
12743 {"armv3", ARM_ARCH_V3, FPU_ARCH_FPA},
12744 {"armv3m", ARM_ARCH_V3M, FPU_ARCH_FPA},
12745 {"armv4", ARM_ARCH_V4, FPU_ARCH_FPA},
12746 {"armv4xm", ARM_ARCH_V4xM, FPU_ARCH_FPA},
12747 {"armv4t", ARM_ARCH_V4T, FPU_ARCH_FPA},
12748 {"armv4txm", ARM_ARCH_V4TxM, FPU_ARCH_FPA},
12749 {"armv5", ARM_ARCH_V5, FPU_ARCH_VFP},
12750 {"armv5t", ARM_ARCH_V5T, FPU_ARCH_VFP},
12751 {"armv5txm", ARM_ARCH_V5TxM, FPU_ARCH_VFP},
12752 {"armv5te", ARM_ARCH_V5TE, FPU_ARCH_VFP},
12753 {"armv5texp", ARM_ARCH_V5TExP, FPU_ARCH_VFP},
12754 {"armv5tej", ARM_ARCH_V5TEJ, FPU_ARCH_VFP},
12755 {"armv6", ARM_ARCH_V6, FPU_ARCH_VFP},
12756 {"armv6j", ARM_ARCH_V6, FPU_ARCH_VFP},
12757 {"armv6k", ARM_ARCH_V6K, FPU_ARCH_VFP},
12758 {"armv6z", ARM_ARCH_V6Z, FPU_ARCH_VFP},
12759 {"armv6zk", ARM_ARCH_V6ZK, FPU_ARCH_VFP},
12760 {"xscale", ARM_ARCH_XSCALE, FPU_ARCH_VFP},
12761 {"iwmmxt", ARM_ARCH_IWMMXT, FPU_ARCH_VFP},
12762 {NULL, 0, 0}
12763 };
12764
12765 /* ISA extensions in the co-processor space. */
12766 struct arm_arch_extension_table
12767 {
12768 char *name;
12769 int value;
12770 };
12771
12772 static struct arm_arch_extension_table arm_extensions[] =
12773 {
12774 {"maverick", ARM_CEXT_MAVERICK},
12775 {"xscale", ARM_CEXT_XSCALE},
12776 {"iwmmxt", ARM_CEXT_IWMMXT},
12777 {NULL, 0}
12778 };
12779
12780 struct arm_fpu_option_table
12781 {
12782 char *name;
12783 int value;
12784 };
12785
12786 /* This list should, at a minimum, contain all the fpu names
12787 recognized by GCC. */
12788 static struct arm_fpu_option_table arm_fpus[] =
12789 {
12790 {"softfpa", FPU_NONE},
12791 {"fpe", FPU_ARCH_FPE},
12792 {"fpe2", FPU_ARCH_FPE},
12793 {"fpe3", FPU_ARCH_FPA}, /* Third release supports LFM/SFM. */
12794 {"fpa", FPU_ARCH_FPA},
12795 {"fpa10", FPU_ARCH_FPA},
12796 {"fpa11", FPU_ARCH_FPA},
12797 {"arm7500fe", FPU_ARCH_FPA},
12798 {"softvfp", FPU_ARCH_VFP},
12799 {"softvfp+vfp", FPU_ARCH_VFP_V2},
12800 {"vfp", FPU_ARCH_VFP_V2},
12801 {"vfp9", FPU_ARCH_VFP_V2},
12802 {"vfp10", FPU_ARCH_VFP_V2},
12803 {"vfp10-r0", FPU_ARCH_VFP_V1},
12804 {"vfpxd", FPU_ARCH_VFP_V1xD},
12805 {"arm1020t", FPU_ARCH_VFP_V1},
12806 {"arm1020e", FPU_ARCH_VFP_V2},
12807 {"arm1136jfs", FPU_ARCH_VFP_V2},
12808 {"arm1136jf-s", FPU_ARCH_VFP_V2},
12809 {"maverick", FPU_ARCH_MAVERICK},
12810 {NULL, 0}
12811 };
12812
12813 struct arm_float_abi_option_table
12814 {
12815 char *name;
12816 int value;
12817 };
12818
12819 static struct arm_float_abi_option_table arm_float_abis[] =
12820 {
12821 {"hard", ARM_FLOAT_ABI_HARD},
12822 {"softfp", ARM_FLOAT_ABI_SOFTFP},
12823 {"soft", ARM_FLOAT_ABI_SOFT},
12824 {NULL, 0}
12825 };
12826
12827 struct arm_eabi_option_table
12828 {
12829 char *name;
12830 unsigned int value;
12831 };
12832
12833 #ifdef OBJ_ELF
12834 /* We only know how to output GNU and ver 4 (AAELF) formats. */
12835 static struct arm_eabi_option_table arm_eabis[] =
12836 {
12837 {"gnu", EF_ARM_EABI_UNKNOWN},
12838 {"4", EF_ARM_EABI_VER4},
12839 {NULL, 0}
12840 };
12841 #endif
12842
12843 struct arm_long_option_table
12844 {
12845 char * option; /* Substring to match. */
12846 char * help; /* Help information. */
12847 int (* func) (char * subopt); /* Function to decode sub-option. */
12848 char * deprecated; /* If non-null, print this message. */
12849 };
12850
12851 static int
12852 arm_parse_extension (char * str, int * opt_p)
12853 {
12854 while (str != NULL && *str != 0)
12855 {
12856 struct arm_arch_extension_table * opt;
12857 char * ext;
12858 int optlen;
12859
12860 if (*str != '+')
12861 {
12862 as_bad (_("invalid architectural extension"));
12863 return 0;
12864 }
12865
12866 str++;
12867 ext = strchr (str, '+');
12868
12869 if (ext != NULL)
12870 optlen = ext - str;
12871 else
12872 optlen = strlen (str);
12873
12874 if (optlen == 0)
12875 {
12876 as_bad (_("missing architectural extension"));
12877 return 0;
12878 }
12879
12880 for (opt = arm_extensions; opt->name != NULL; opt++)
12881 if (strncmp (opt->name, str, optlen) == 0)
12882 {
12883 *opt_p |= opt->value;
12884 break;
12885 }
12886
12887 if (opt->name == NULL)
12888 {
12889 as_bad (_("unknown architectural extnsion `%s'"), str);
12890 return 0;
12891 }
12892
12893 str = ext;
12894 };
12895
12896 return 1;
12897 }
12898
12899 static int
12900 arm_parse_cpu (char * str)
12901 {
12902 struct arm_cpu_option_table * opt;
12903 char * ext = strchr (str, '+');
12904 int optlen;
12905
12906 if (ext != NULL)
12907 optlen = ext - str;
12908 else
12909 optlen = strlen (str);
12910
12911 if (optlen == 0)
12912 {
12913 as_bad (_("missing cpu name `%s'"), str);
12914 return 0;
12915 }
12916
12917 for (opt = arm_cpus; opt->name != NULL; opt++)
12918 if (strncmp (opt->name, str, optlen) == 0)
12919 {
12920 mcpu_cpu_opt = opt->value;
12921 mcpu_fpu_opt = opt->default_fpu;
12922
12923 if (ext != NULL)
12924 return arm_parse_extension (ext, &mcpu_cpu_opt);
12925
12926 return 1;
12927 }
12928
12929 as_bad (_("unknown cpu `%s'"), str);
12930 return 0;
12931 }
12932
12933 static int
12934 arm_parse_arch (char * str)
12935 {
12936 struct arm_arch_option_table *opt;
12937 char *ext = strchr (str, '+');
12938 int optlen;
12939
12940 if (ext != NULL)
12941 optlen = ext - str;
12942 else
12943 optlen = strlen (str);
12944
12945 if (optlen == 0)
12946 {
12947 as_bad (_("missing architecture name `%s'"), str);
12948 return 0;
12949 }
12950
12951
12952 for (opt = arm_archs; opt->name != NULL; opt++)
12953 if (streq (opt->name, str))
12954 {
12955 march_cpu_opt = opt->value;
12956 march_fpu_opt = opt->default_fpu;
12957
12958 if (ext != NULL)
12959 return arm_parse_extension (ext, &march_cpu_opt);
12960
12961 return 1;
12962 }
12963
12964 as_bad (_("unknown architecture `%s'\n"), str);
12965 return 0;
12966 }
12967
12968 static int
12969 arm_parse_fpu (char * str)
12970 {
12971 struct arm_fpu_option_table * opt;
12972
12973 for (opt = arm_fpus; opt->name != NULL; opt++)
12974 if (streq (opt->name, str))
12975 {
12976 mfpu_opt = opt->value;
12977 return 1;
12978 }
12979
12980 as_bad (_("unknown floating point format `%s'\n"), str);
12981 return 0;
12982 }
12983
12984 static int
12985 arm_parse_float_abi (char * str)
12986 {
12987 struct arm_float_abi_option_table * opt;
12988
12989 for (opt = arm_float_abis; opt->name != NULL; opt++)
12990 if (streq (opt->name, str))
12991 {
12992 mfloat_abi_opt = opt->value;
12993 return 1;
12994 }
12995
12996 as_bad (_("unknown floating point abi `%s'\n"), str);
12997 return 0;
12998 }
12999
13000 #ifdef OBJ_ELF
13001 static int
13002 arm_parse_eabi (char * str)
13003 {
13004 struct arm_eabi_option_table *opt;
13005
13006 for (opt = arm_eabis; opt->name != NULL; opt++)
13007 if (streq (opt->name, str))
13008 {
13009 meabi_flags = opt->value;
13010 return 1;
13011 }
13012 as_bad (_("unknown EABI `%s'\n"), str);
13013 return 0;
13014 }
13015 #endif
13016
13017 struct arm_long_option_table arm_long_opts[] =
13018 {
13019 {"mcpu=", N_("<cpu name>\t assemble for CPU <cpu name>"),
13020 arm_parse_cpu, NULL},
13021 {"march=", N_("<arch name>\t assemble for architecture <arch name>"),
13022 arm_parse_arch, NULL},
13023 {"mfpu=", N_("<fpu name>\t assemble for FPU architecture <fpu name>"),
13024 arm_parse_fpu, NULL},
13025 {"mfloat-abi=", N_("<abi>\t assemble for floating point ABI <abi>"),
13026 arm_parse_float_abi, NULL},
13027 #ifdef OBJ_ELF
13028 {"meabi=", N_("<ver>\t assemble for eabi version <ver>"),
13029 arm_parse_eabi, NULL},
13030 #endif
13031 {NULL, NULL, 0, NULL}
13032 };
13033
13034 int
13035 md_parse_option (int c, char * arg)
13036 {
13037 struct arm_option_table *opt;
13038 struct arm_long_option_table *lopt;
13039
13040 switch (c)
13041 {
13042 #ifdef OPTION_EB
13043 case OPTION_EB:
13044 target_big_endian = 1;
13045 break;
13046 #endif
13047
13048 #ifdef OPTION_EL
13049 case OPTION_EL:
13050 target_big_endian = 0;
13051 break;
13052 #endif
13053
13054 case 'a':
13055 /* Listing option. Just ignore these, we don't support additional
13056 ones. */
13057 return 0;
13058
13059 default:
13060 for (opt = arm_opts; opt->option != NULL; opt++)
13061 {
13062 if (c == opt->option[0]
13063 && ((arg == NULL && opt->option[1] == 0)
13064 || streq (arg, opt->option + 1)))
13065 {
13066 #if WARN_DEPRECATED
13067 /* If the option is deprecated, tell the user. */
13068 if (opt->deprecated != NULL)
13069 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c,
13070 arg ? arg : "", _(opt->deprecated));
13071 #endif
13072
13073 if (opt->var != NULL)
13074 *opt->var = opt->value;
13075
13076 return 1;
13077 }
13078 }
13079
13080 for (lopt = arm_long_opts; lopt->option != NULL; lopt++)
13081 {
13082 /* These options are expected to have an argument. */
13083 if (c == lopt->option[0]
13084 && arg != NULL
13085 && strncmp (arg, lopt->option + 1,
13086 strlen (lopt->option + 1)) == 0)
13087 {
13088 #if WARN_DEPRECATED
13089 /* If the option is deprecated, tell the user. */
13090 if (lopt->deprecated != NULL)
13091 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c, arg,
13092 _(lopt->deprecated));
13093 #endif
13094
13095 /* Call the sup-option parser. */
13096 return lopt->func (arg + strlen (lopt->option) - 1);
13097 }
13098 }
13099
13100 return 0;
13101 }
13102
13103 return 1;
13104 }
13105
13106 void
13107 md_show_usage (FILE * fp)
13108 {
13109 struct arm_option_table *opt;
13110 struct arm_long_option_table *lopt;
13111
13112 fprintf (fp, _(" ARM-specific assembler options:\n"));
13113
13114 for (opt = arm_opts; opt->option != NULL; opt++)
13115 if (opt->help != NULL)
13116 fprintf (fp, " -%-23s%s\n", opt->option, _(opt->help));
13117
13118 for (lopt = arm_long_opts; lopt->option != NULL; lopt++)
13119 if (lopt->help != NULL)
13120 fprintf (fp, " -%s%s\n", lopt->option, _(lopt->help));
13121
13122 #ifdef OPTION_EB
13123 fprintf (fp, _("\
13124 -EB assemble code for a big-endian cpu\n"));
13125 #endif
13126
13127 #ifdef OPTION_EL
13128 fprintf (fp, _("\
13129 -EL assemble code for a little-endian cpu\n"));
13130 #endif
13131 }
13132
13133 /* This fix_new is called by cons via TC_CONS_FIX_NEW. */
13134
13135 void
13136 cons_fix_new_arm (fragS * frag,
13137 int where,
13138 int size,
13139 expressionS * exp)
13140 {
13141 bfd_reloc_code_real_type type;
13142 int pcrel = 0;
13143
13144 /* Pick a reloc.
13145 FIXME: @@ Should look at CPU word size. */
13146 switch (size)
13147 {
13148 case 1:
13149 type = BFD_RELOC_8;
13150 break;
13151 case 2:
13152 type = BFD_RELOC_16;
13153 break;
13154 case 4:
13155 default:
13156 type = BFD_RELOC_32;
13157 break;
13158 case 8:
13159 type = BFD_RELOC_64;
13160 break;
13161 }
13162
13163 fix_new_exp (frag, where, (int) size, exp, pcrel, type);
13164 }
13165
13166 /* A good place to do this, although this was probably not intended
13167 for this kind of use. We need to dump the literal pool before
13168 references are made to a null symbol pointer. */
13169
13170 void
13171 arm_cleanup (void)
13172 {
13173 literal_pool * pool;
13174
13175 for (pool = list_of_pools; pool; pool = pool->next)
13176 {
13177 /* Put it at the end of the relevent section. */
13178 subseg_set (pool->section, pool->sub_section);
13179 #ifdef OBJ_ELF
13180 arm_elf_change_section ();
13181 #endif
13182 s_ltorg (0);
13183 }
13184 }
13185
13186 void
13187 arm_start_line_hook (void)
13188 {
13189 last_label_seen = NULL;
13190 }
13191
13192 void
13193 arm_frob_label (symbolS * sym)
13194 {
13195 last_label_seen = sym;
13196
13197 ARM_SET_THUMB (sym, thumb_mode);
13198
13199 #if defined OBJ_COFF || defined OBJ_ELF
13200 ARM_SET_INTERWORK (sym, support_interwork);
13201 #endif
13202
13203 /* Note - do not allow local symbols (.Lxxx) to be labeled
13204 as Thumb functions. This is because these labels, whilst
13205 they exist inside Thumb code, are not the entry points for
13206 possible ARM->Thumb calls. Also, these labels can be used
13207 as part of a computed goto or switch statement. eg gcc
13208 can generate code that looks like this:
13209
13210 ldr r2, [pc, .Laaa]
13211 lsl r3, r3, #2
13212 ldr r2, [r3, r2]
13213 mov pc, r2
13214
13215 .Lbbb: .word .Lxxx
13216 .Lccc: .word .Lyyy
13217 ..etc...
13218 .Laaa: .word Lbbb
13219
13220 The first instruction loads the address of the jump table.
13221 The second instruction converts a table index into a byte offset.
13222 The third instruction gets the jump address out of the table.
13223 The fourth instruction performs the jump.
13224
13225 If the address stored at .Laaa is that of a symbol which has the
13226 Thumb_Func bit set, then the linker will arrange for this address
13227 to have the bottom bit set, which in turn would mean that the
13228 address computation performed by the third instruction would end
13229 up with the bottom bit set. Since the ARM is capable of unaligned
13230 word loads, the instruction would then load the incorrect address
13231 out of the jump table, and chaos would ensue. */
13232 if (label_is_thumb_function_name
13233 && (S_GET_NAME (sym)[0] != '.' || S_GET_NAME (sym)[1] != 'L')
13234 && (bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
13235 {
13236 /* When the address of a Thumb function is taken the bottom
13237 bit of that address should be set. This will allow
13238 interworking between Arm and Thumb functions to work
13239 correctly. */
13240
13241 THUMB_SET_FUNC (sym, 1);
13242
13243 label_is_thumb_function_name = FALSE;
13244 }
13245 }
13246
13247 /* Adjust the symbol table. This marks Thumb symbols as distinct from
13248 ARM ones. */
13249
13250 void
13251 arm_adjust_symtab (void)
13252 {
13253 #ifdef OBJ_COFF
13254 symbolS * sym;
13255
13256 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
13257 {
13258 if (ARM_IS_THUMB (sym))
13259 {
13260 if (THUMB_IS_FUNC (sym))
13261 {
13262 /* Mark the symbol as a Thumb function. */
13263 if ( S_GET_STORAGE_CLASS (sym) == C_STAT
13264 || S_GET_STORAGE_CLASS (sym) == C_LABEL) /* This can happen! */
13265 S_SET_STORAGE_CLASS (sym, C_THUMBSTATFUNC);
13266
13267 else if (S_GET_STORAGE_CLASS (sym) == C_EXT)
13268 S_SET_STORAGE_CLASS (sym, C_THUMBEXTFUNC);
13269 else
13270 as_bad (_("%s: unexpected function type: %d"),
13271 S_GET_NAME (sym), S_GET_STORAGE_CLASS (sym));
13272 }
13273 else switch (S_GET_STORAGE_CLASS (sym))
13274 {
13275 case C_EXT:
13276 S_SET_STORAGE_CLASS (sym, C_THUMBEXT);
13277 break;
13278 case C_STAT:
13279 S_SET_STORAGE_CLASS (sym, C_THUMBSTAT);
13280 break;
13281 case C_LABEL:
13282 S_SET_STORAGE_CLASS (sym, C_THUMBLABEL);
13283 break;
13284 default:
13285 /* Do nothing. */
13286 break;
13287 }
13288 }
13289
13290 if (ARM_IS_INTERWORK (sym))
13291 coffsymbol (symbol_get_bfdsym (sym))->native->u.syment.n_flags = 0xFF;
13292 }
13293 #endif
13294 #ifdef OBJ_ELF
13295 symbolS * sym;
13296 char bind;
13297
13298 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
13299 {
13300 if (ARM_IS_THUMB (sym))
13301 {
13302 elf_symbol_type * elf_sym;
13303
13304 elf_sym = elf_symbol (symbol_get_bfdsym (sym));
13305 bind = ELF_ST_BIND (elf_sym);
13306
13307 /* If it's a .thumb_func, declare it as so,
13308 otherwise tag label as .code 16. */
13309 if (THUMB_IS_FUNC (sym))
13310 elf_sym->internal_elf_sym.st_info =
13311 ELF_ST_INFO (bind, STT_ARM_TFUNC);
13312 else
13313 elf_sym->internal_elf_sym.st_info =
13314 ELF_ST_INFO (bind, STT_ARM_16BIT);
13315 }
13316 }
13317 #endif
13318 }
13319
13320 int
13321 arm_data_in_code (void)
13322 {
13323 if (thumb_mode && ! strncmp (input_line_pointer + 1, "data:", 5))
13324 {
13325 *input_line_pointer = '/';
13326 input_line_pointer += 5;
13327 *input_line_pointer = 0;
13328 return 1;
13329 }
13330
13331 return 0;
13332 }
13333
13334 char *
13335 arm_canonicalize_symbol_name (char * name)
13336 {
13337 int len;
13338
13339 if (thumb_mode && (len = strlen (name)) > 5
13340 && streq (name + len - 5, "/data"))
13341 *(name + len - 5) = 0;
13342
13343 return name;
13344 }
13345
13346 #if defined OBJ_COFF || defined OBJ_ELF
13347 void
13348 arm_validate_fix (fixS * fixP)
13349 {
13350 /* If the destination of the branch is a defined symbol which does not have
13351 the THUMB_FUNC attribute, then we must be calling a function which has
13352 the (interfacearm) attribute. We look for the Thumb entry point to that
13353 function and change the branch to refer to that function instead. */
13354 if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23
13355 && fixP->fx_addsy != NULL
13356 && S_IS_DEFINED (fixP->fx_addsy)
13357 && ! THUMB_IS_FUNC (fixP->fx_addsy))
13358 {
13359 fixP->fx_addsy = find_real_start (fixP->fx_addsy);
13360 }
13361 }
13362 #endif
13363
13364 int
13365 arm_force_relocation (struct fix * fixp)
13366 {
13367 #if defined (OBJ_COFF) && defined (TE_PE)
13368 if (fixp->fx_r_type == BFD_RELOC_RVA)
13369 return 1;
13370 #endif
13371 #ifdef OBJ_ELF
13372 if (fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH
13373 || fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BLX
13374 || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX
13375 || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23)
13376 return 1;
13377 #endif
13378
13379 /* Resolve these relocations even if the symbol is extern or weak. */
13380 if (fixp->fx_r_type == BFD_RELOC_ARM_IMMEDIATE
13381 || fixp->fx_r_type == BFD_RELOC_ARM_OFFSET_IMM
13382 || fixp->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE)
13383 return 0;
13384
13385 return generic_force_reloc (fixp);
13386 }
13387
13388 #ifdef OBJ_COFF
13389 /* This is a little hack to help the gas/arm/adrl.s test. It prevents
13390 local labels from being added to the output symbol table when they
13391 are used with the ADRL pseudo op. The ADRL relocation should always
13392 be resolved before the binbary is emitted, so it is safe to say that
13393 it is adjustable. */
13394
13395 bfd_boolean
13396 arm_fix_adjustable (fixS * fixP)
13397 {
13398 if (fixP->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE)
13399 return 1;
13400 return 0;
13401 }
13402 #endif
13403
13404 #ifdef OBJ_ELF
13405 /* Relocations against Thumb function names must be left unadjusted,
13406 so that the linker can use this information to correctly set the
13407 bottom bit of their addresses. The MIPS version of this function
13408 also prevents relocations that are mips-16 specific, but I do not
13409 know why it does this.
13410
13411 FIXME:
13412 There is one other problem that ought to be addressed here, but
13413 which currently is not: Taking the address of a label (rather
13414 than a function) and then later jumping to that address. Such
13415 addresses also ought to have their bottom bit set (assuming that
13416 they reside in Thumb code), but at the moment they will not. */
13417
13418 bfd_boolean
13419 arm_fix_adjustable (fixS * fixP)
13420 {
13421 if (fixP->fx_addsy == NULL)
13422 return 1;
13423
13424 if (THUMB_IS_FUNC (fixP->fx_addsy)
13425 && fixP->fx_subsy == NULL)
13426 return 0;
13427
13428 /* We need the symbol name for the VTABLE entries. */
13429 if ( fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
13430 || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
13431 return 0;
13432
13433 /* Don't allow symbols to be discarded on GOT related relocs. */
13434 if (fixP->fx_r_type == BFD_RELOC_ARM_PLT32
13435 || fixP->fx_r_type == BFD_RELOC_ARM_GOT32
13436 || fixP->fx_r_type == BFD_RELOC_ARM_GOTOFF
13437 || fixP->fx_r_type == BFD_RELOC_ARM_TARGET2)
13438 return 0;
13439
13440 return 1;
13441 }
13442
13443 const char *
13444 elf32_arm_target_format (void)
13445 {
13446 #ifdef TE_SYMBIAN
13447 return (target_big_endian
13448 ? "elf32-bigarm-symbian"
13449 : "elf32-littlearm-symbian");
13450 #elif defined (TE_VXWORKS)
13451 return (target_big_endian
13452 ? "elf32-bigarm-vxworks"
13453 : "elf32-littlearm-vxworks");
13454 #else
13455 if (target_big_endian)
13456 return "elf32-bigarm";
13457 else
13458 return "elf32-littlearm";
13459 #endif
13460 }
13461
13462 void
13463 armelf_frob_symbol (symbolS * symp,
13464 int * puntp)
13465 {
13466 elf_frob_symbol (symp, puntp);
13467 }
13468
13469 static void
13470 s_arm_elf_cons (int nbytes)
13471 {
13472 expressionS exp;
13473
13474 #ifdef md_flush_pending_output
13475 md_flush_pending_output ();
13476 #endif
13477
13478 if (is_it_end_of_statement ())
13479 {
13480 demand_empty_rest_of_line ();
13481 return;
13482 }
13483
13484 #ifdef md_cons_align
13485 md_cons_align (nbytes);
13486 #endif
13487
13488 mapping_state (MAP_DATA);
13489 do
13490 {
13491 bfd_reloc_code_real_type reloc;
13492
13493 expression (& exp);
13494
13495 if (exp.X_op == O_symbol
13496 && * input_line_pointer == '('
13497 && (reloc = arm_parse_reloc ()) != BFD_RELOC_UNUSED)
13498 {
13499 reloc_howto_type *howto = bfd_reloc_type_lookup (stdoutput, reloc);
13500 int size = bfd_get_reloc_size (howto);
13501
13502 if (size > nbytes)
13503 as_bad ("%s relocations do not fit in %d bytes",
13504 howto->name, nbytes);
13505 else
13506 {
13507 char *p = frag_more ((int) nbytes);
13508 int offset = nbytes - size;
13509
13510 fix_new_exp (frag_now, p - frag_now->fr_literal + offset, size,
13511 &exp, 0, reloc);
13512 }
13513 }
13514 else
13515 emit_expr (&exp, (unsigned int) nbytes);
13516 }
13517 while (*input_line_pointer++ == ',');
13518
13519 /* Put terminator back into stream. */
13520 input_line_pointer --;
13521 demand_empty_rest_of_line ();
13522 }
13523
13524
13525 /* Parse a .rel31 directive. */
13526
13527 static void
13528 s_arm_rel31 (int ignored ATTRIBUTE_UNUSED)
13529 {
13530 expressionS exp;
13531 char *p;
13532 valueT highbit;
13533
13534 SKIP_WHITESPACE ();
13535
13536 highbit = 0;
13537 if (*input_line_pointer == '1')
13538 highbit = 0x80000000;
13539 else if (*input_line_pointer != '0')
13540 as_bad (_("expected 0 or 1"));
13541
13542 input_line_pointer++;
13543 SKIP_WHITESPACE ();
13544 if (*input_line_pointer != ',')
13545 as_bad (_("missing comma"));
13546 input_line_pointer++;
13547
13548 #ifdef md_flush_pending_output
13549 md_flush_pending_output ();
13550 #endif
13551
13552 #ifdef md_cons_align
13553 md_cons_align (4);
13554 #endif
13555
13556 mapping_state (MAP_DATA);
13557
13558 expression (&exp);
13559
13560 p = frag_more (4);
13561 md_number_to_chars (p, highbit, 4);
13562 fix_new_arm (frag_now, p - frag_now->fr_literal, 4, &exp, 1,
13563 BFD_RELOC_ARM_PREL31);
13564
13565 demand_empty_rest_of_line ();
13566 }
13567 \f
13568 /* Code to deal with unwinding tables. */
13569
13570 static void add_unwind_adjustsp (offsetT);
13571
13572 /* Switch to section NAME and create section if necessary. It's
13573 rather ugly that we have to manipulate input_line_pointer but I
13574 don't see any other way to accomplish the same thing without
13575 changing obj-elf.c (which may be the Right Thing, in the end).
13576 Copied from tc-ia64.c. */
13577
13578 static void
13579 set_section (char *name)
13580 {
13581 char *saved_input_line_pointer;
13582
13583 saved_input_line_pointer = input_line_pointer;
13584 input_line_pointer = name;
13585 obj_elf_section (0);
13586 input_line_pointer = saved_input_line_pointer;
13587 }
13588
13589 /* Cenerate and deferred unwind frame offset. */
13590
13591 static void
13592 flush_pending_unwind (void)
13593 {
13594 offsetT offset;
13595
13596 offset = unwind.pending_offset;
13597 unwind.pending_offset = 0;
13598 if (offset != 0)
13599 add_unwind_adjustsp (offset);
13600 }
13601
13602 /* Add an opcode to this list for this function. Two-byte opcodes should
13603 be passed as op[0] << 8 | op[1]. The list of opcodes is built in reverse
13604 order. */
13605
13606 static void
13607 add_unwind_opcode (valueT op, int length)
13608 {
13609 /* Add any deferred stack adjustment. */
13610 if (unwind.pending_offset)
13611 flush_pending_unwind ();
13612
13613 unwind.sp_restored = 0;
13614
13615 if (unwind.opcode_count + length > unwind.opcode_alloc)
13616 {
13617 unwind.opcode_alloc += ARM_OPCODE_CHUNK_SIZE;
13618 if (unwind.opcodes)
13619 unwind.opcodes = xrealloc (unwind.opcodes,
13620 unwind.opcode_alloc);
13621 else
13622 unwind.opcodes = xmalloc (unwind.opcode_alloc);
13623 }
13624 while (length > 0)
13625 {
13626 length--;
13627 unwind.opcodes[unwind.opcode_count] = op & 0xff;
13628 op >>= 8;
13629 unwind.opcode_count++;
13630 }
13631 }
13632
13633 /* Add unwind opcodes to adjust the stack pointer. */
13634
13635 static void
13636 add_unwind_adjustsp (offsetT offset)
13637 {
13638 valueT op;
13639
13640 if (offset > 0x200)
13641 {
13642 /* We need at most 5 bytes to hold a 32-bit value in a uleb128. */
13643 char bytes[5];
13644 int n;
13645 valueT o;
13646
13647 /* Long form: 0xb2, uleb128. */
13648 /* This might not fit in a word so add the individual bytes,
13649 remembering the list is built in reverse order. */
13650 o = (valueT) ((offset - 0x204) >> 2);
13651 if (o == 0)
13652 add_unwind_opcode (0, 1);
13653
13654 /* Calculate the uleb128 encoding of the offset. */
13655 n = 0;
13656 while (o)
13657 {
13658 bytes[n] = o & 0x7f;
13659 o >>= 7;
13660 if (o)
13661 bytes[n] |= 0x80;
13662 n++;
13663 }
13664 /* Add the insn. */
13665 for (; n; n--)
13666 add_unwind_opcode (bytes[n - 1], 1);
13667 add_unwind_opcode (0xb2, 1);
13668 }
13669 else if (offset > 0x100)
13670 {
13671 /* Two short opcodes. */
13672 add_unwind_opcode (0x3f, 1);
13673 op = (offset - 0x104) >> 2;
13674 add_unwind_opcode (op, 1);
13675 }
13676 else if (offset > 0)
13677 {
13678 /* Short opcode. */
13679 op = (offset - 4) >> 2;
13680 add_unwind_opcode (op, 1);
13681 }
13682 else if (offset < 0)
13683 {
13684 offset = -offset;
13685 while (offset > 0x100)
13686 {
13687 add_unwind_opcode (0x7f, 1);
13688 offset -= 0x100;
13689 }
13690 op = ((offset - 4) >> 2) | 0x40;
13691 add_unwind_opcode (op, 1);
13692 }
13693 }
13694
13695 /* Finish the list of unwind opcodes for this function. */
13696 static void
13697 finish_unwind_opcodes (void)
13698 {
13699 valueT op;
13700
13701 if (unwind.fp_used)
13702 {
13703 /* Adjust sp as neccessary. */
13704 unwind.pending_offset += unwind.fp_offset - unwind.frame_size;
13705 flush_pending_unwind ();
13706
13707 /* After restoring sp from the frame pointer. */
13708 op = 0x90 | unwind.fp_reg;
13709 add_unwind_opcode (op, 1);
13710 }
13711 else
13712 flush_pending_unwind ();
13713 }
13714
13715
13716 /* Start an exception table entry. If idx is nonzero this is an index table
13717 entry. */
13718
13719 static void
13720 start_unwind_section (const segT text_seg, int idx)
13721 {
13722 const char * text_name;
13723 const char * prefix;
13724 const char * prefix_once;
13725 size_t prefix_len;
13726 size_t text_len;
13727 char * sec_name;
13728 size_t sec_name_len;
13729
13730 if (idx)
13731 {
13732 prefix = ELF_STRING_ARM_unwind;
13733 prefix_once = ELF_STRING_ARM_unwind_once;
13734 }
13735 else
13736 {
13737 prefix = ELF_STRING_ARM_unwind_info;
13738 prefix_once = ELF_STRING_ARM_unwind_info_once;
13739 }
13740
13741 text_name = segment_name (text_seg);
13742 if (streq (text_name, ".text"))
13743 text_name = "";
13744
13745 if (strncmp (text_name, ".gnu.linkonce.t.",
13746 strlen (".gnu.linkonce.t.")) == 0)
13747 {
13748 prefix = prefix_once;
13749 text_name += strlen (".gnu.linkonce.t.");
13750 }
13751
13752 prefix_len = strlen (prefix);
13753 text_len = strlen (text_name);
13754 sec_name_len = prefix_len + text_len;
13755 sec_name = alloca (sec_name_len + 1);
13756 memcpy (sec_name, prefix, prefix_len);
13757 memcpy (sec_name + prefix_len, text_name, text_len);
13758 sec_name[prefix_len + text_len] = '\0';
13759
13760 /* Handle COMDAT group. */
13761 if (prefix != prefix_once && (text_seg->flags & SEC_LINK_ONCE) != 0)
13762 {
13763 char *section;
13764 size_t len, group_name_len;
13765 const char *group_name = elf_group_name (text_seg);
13766
13767 if (group_name == NULL)
13768 {
13769 as_bad ("Group section `%s' has no group signature",
13770 segment_name (text_seg));
13771 ignore_rest_of_line ();
13772 return;
13773 }
13774 /* We have to construct a fake section directive. */
13775 group_name_len = strlen (group_name);
13776 if (idx)
13777 prefix_len = 13;
13778 else
13779 prefix_len = 16;
13780
13781 len = (sec_name_len
13782 + prefix_len /* ,"aG",%sectiontype, */
13783 + group_name_len /* ,group_name */
13784 + 7); /* ,comdat */
13785
13786 section = alloca (len + 1);
13787 memcpy (section, sec_name, sec_name_len);
13788 if (idx)
13789 memcpy (section + sec_name_len, ",\"aG\",%exidx,", 13);
13790 else
13791 memcpy (section + sec_name_len, ",\"aG\",%progbits,", 16);
13792 memcpy (section + sec_name_len + prefix_len, group_name, group_name_len);
13793 memcpy (section + len - 7, ",comdat", 7);
13794 section [len] = '\0';
13795 set_section (section);
13796 }
13797 else
13798 {
13799 set_section (sec_name);
13800 bfd_set_section_flags (stdoutput, now_seg,
13801 SEC_LOAD | SEC_ALLOC | SEC_READONLY);
13802 }
13803
13804 /* Set the setion link for index tables. */
13805 if (idx)
13806 elf_linked_to_section (now_seg) = text_seg;
13807 }
13808
13809
13810 /* Start an unwind table entry. HAVE_DATA is nonzero if we have additional
13811 personality routine data. Returns zero, or the index table value for
13812 and inline entry. */
13813
13814 static valueT
13815 create_unwind_entry (int have_data)
13816 {
13817 int size;
13818 addressT where;
13819 unsigned char *ptr;
13820 /* The current word of data. */
13821 valueT data;
13822 /* The number of bytes left in this word. */
13823 int n;
13824
13825 finish_unwind_opcodes ();
13826
13827 /* Remember the current text section. */
13828 unwind.saved_seg = now_seg;
13829 unwind.saved_subseg = now_subseg;
13830
13831 start_unwind_section (now_seg, 0);
13832
13833 if (unwind.personality_routine == NULL)
13834 {
13835 if (unwind.personality_index == -2)
13836 {
13837 if (have_data)
13838 as_bad (_("handerdata in cantunwind frame"));
13839 return 1; /* EXIDX_CANTUNWIND. */
13840 }
13841
13842 /* Use a default personality routine if none is specified. */
13843 if (unwind.personality_index == -1)
13844 {
13845 if (unwind.opcode_count > 3)
13846 unwind.personality_index = 1;
13847 else
13848 unwind.personality_index = 0;
13849 }
13850
13851 /* Space for the personality routine entry. */
13852 if (unwind.personality_index == 0)
13853 {
13854 if (unwind.opcode_count > 3)
13855 as_bad (_("too many unwind opcodes for personality routine 0"));
13856
13857 if (!have_data)
13858 {
13859 /* All the data is inline in the index table. */
13860 data = 0x80;
13861 n = 3;
13862 while (unwind.opcode_count > 0)
13863 {
13864 unwind.opcode_count--;
13865 data = (data << 8) | unwind.opcodes[unwind.opcode_count];
13866 n--;
13867 }
13868
13869 /* Pad with "finish" opcodes. */
13870 while (n--)
13871 data = (data << 8) | 0xb0;
13872
13873 return data;
13874 }
13875 size = 0;
13876 }
13877 else
13878 /* We get two opcodes "free" in the first word. */
13879 size = unwind.opcode_count - 2;
13880 }
13881 else
13882 /* An extra byte is required for the opcode count. */
13883 size = unwind.opcode_count + 1;
13884
13885 size = (size + 3) >> 2;
13886 if (size > 0xff)
13887 as_bad (_("too many unwind opcodes"));
13888
13889 frag_align (2, 0, 0);
13890 record_alignment (now_seg, 2);
13891 unwind.table_entry = expr_build_dot ();
13892
13893 /* Allocate the table entry. */
13894 ptr = frag_more ((size << 2) + 4);
13895 where = frag_now_fix () - ((size << 2) + 4);
13896
13897 switch (unwind.personality_index)
13898 {
13899 case -1:
13900 /* ??? Should this be a PLT generating relocation? */
13901 /* Custom personality routine. */
13902 fix_new (frag_now, where, 4, unwind.personality_routine, 0, 1,
13903 BFD_RELOC_ARM_PREL31);
13904
13905 /* Indicate dependency to linker. */
13906 {
13907 char *name = "__aeabi_unwind_cpp_pr0";
13908 symbolS *pr = symbol_find_or_make (name);
13909 fix_new (frag_now, where, 4, pr, 0, 1, BFD_RELOC_NONE);
13910 }
13911
13912 where += 4;
13913 ptr += 4;
13914
13915 /* Set the first byte to the number of additional words. */
13916 data = size - 1;
13917 n = 3;
13918 break;
13919
13920 /* ABI defined personality routines. */
13921 case 0:
13922 /* Three opcodes bytes are packed into the first word. */
13923 data = 0x80;
13924 n = 3;
13925 goto emit_reloc;
13926
13927 case 1:
13928 case 2:
13929 /* The size and first two opcode bytes go in the first word. */
13930 data = ((0x80 + unwind.personality_index) << 8) | size;
13931 n = 2;
13932 goto emit_reloc;
13933
13934 emit_reloc:
13935 {
13936 /* Indicate dependency to linker. */
13937 char *name[] = { "__aeabi_unwind_cpp_pr0",
13938 "__aeabi_unwind_cpp_pr1",
13939 "__aeabi_unwind_cpp_pr2" };
13940 symbolS *pr = symbol_find_or_make (name[unwind.personality_index]);
13941 fix_new (frag_now, where, 4, pr, 0, 1, BFD_RELOC_NONE);
13942 }
13943 break;
13944
13945 default:
13946 /* Should never happen. */
13947 abort ();
13948 }
13949
13950 /* Pack the opcodes into words (MSB first), reversing the list at the same
13951 time. */
13952 while (unwind.opcode_count > 0)
13953 {
13954 if (n == 0)
13955 {
13956 md_number_to_chars (ptr, data, 4);
13957 ptr += 4;
13958 n = 4;
13959 data = 0;
13960 }
13961 unwind.opcode_count--;
13962 n--;
13963 data = (data << 8) | unwind.opcodes[unwind.opcode_count];
13964 }
13965
13966 /* Finish off the last word. */
13967 if (n < 4)
13968 {
13969 /* Pad with "finish" opcodes. */
13970 while (n--)
13971 data = (data << 8) | 0xb0;
13972
13973 md_number_to_chars (ptr, data, 4);
13974 }
13975
13976 if (!have_data)
13977 {
13978 /* Add an empty descriptor if there is no user-specified data. */
13979 ptr = frag_more (4);
13980 md_number_to_chars (ptr, 0, 4);
13981 }
13982
13983 return 0;
13984 }
13985
13986
13987 /* Parse an unwind_fnstart directive. Simply records the current location. */
13988
13989 static void
13990 s_arm_unwind_fnstart (int ignored ATTRIBUTE_UNUSED)
13991 {
13992 demand_empty_rest_of_line ();
13993 /* Mark the start of the function. */
13994 unwind.proc_start = expr_build_dot ();
13995
13996 /* Reset the rest of the unwind info. */
13997 unwind.opcode_count = 0;
13998 unwind.table_entry = NULL;
13999 unwind.personality_routine = NULL;
14000 unwind.personality_index = -1;
14001 unwind.frame_size = 0;
14002 unwind.fp_offset = 0;
14003 unwind.fp_reg = 13;
14004 unwind.fp_used = 0;
14005 unwind.sp_restored = 0;
14006 }
14007
14008
14009 /* Parse a handlerdata directive. Creates the exception handling table entry
14010 for the function. */
14011
14012 static void
14013 s_arm_unwind_handlerdata (int ignored ATTRIBUTE_UNUSED)
14014 {
14015 demand_empty_rest_of_line ();
14016 if (unwind.table_entry)
14017 as_bad (_("dupicate .handlerdata directive"));
14018
14019 create_unwind_entry (1);
14020 }
14021
14022 /* Parse an unwind_fnend directive. Generates the index table entry. */
14023
14024 static void
14025 s_arm_unwind_fnend (int ignored ATTRIBUTE_UNUSED)
14026 {
14027 long where;
14028 unsigned char *ptr;
14029 valueT val;
14030
14031 demand_empty_rest_of_line ();
14032
14033 /* Add eh table entry. */
14034 if (unwind.table_entry == NULL)
14035 val = create_unwind_entry (0);
14036 else
14037 val = 0;
14038
14039 /* Add index table entry. This is two words. */
14040 start_unwind_section (unwind.saved_seg, 1);
14041 frag_align (2, 0, 0);
14042 record_alignment (now_seg, 2);
14043
14044 ptr = frag_more (8);
14045 where = frag_now_fix () - 8;
14046
14047 /* Self relative offset of the function start. */
14048 fix_new (frag_now, where, 4, unwind.proc_start, 0, 1,
14049 BFD_RELOC_ARM_PREL31);
14050
14051 if (val)
14052 /* Inline exception table entry. */
14053 md_number_to_chars (ptr + 4, val, 4);
14054 else
14055 /* Self relative offset of the table entry. */
14056 fix_new (frag_now, where + 4, 4, unwind.table_entry, 0, 1,
14057 BFD_RELOC_ARM_PREL31);
14058
14059 /* Restore the original section. */
14060 subseg_set (unwind.saved_seg, unwind.saved_subseg);
14061 }
14062
14063
14064 /* Parse an unwind_cantunwind directive. */
14065
14066 static void
14067 s_arm_unwind_cantunwind (int ignored ATTRIBUTE_UNUSED)
14068 {
14069 demand_empty_rest_of_line ();
14070 if (unwind.personality_routine || unwind.personality_index != -1)
14071 as_bad (_("personality routine specified for cantunwind frame"));
14072
14073 unwind.personality_index = -2;
14074 }
14075
14076
14077 /* Parse a personalityindex directive. */
14078
14079 static void
14080 s_arm_unwind_personalityindex (int ignored ATTRIBUTE_UNUSED)
14081 {
14082 expressionS exp;
14083
14084 if (unwind.personality_routine || unwind.personality_index != -1)
14085 as_bad (_("duplicate .personalityindex directive"));
14086
14087 SKIP_WHITESPACE ();
14088
14089 expression (&exp);
14090
14091 if (exp.X_op != O_constant
14092 || exp.X_add_number < 0 || exp.X_add_number > 15)
14093 {
14094 as_bad (_("bad personality routine number"));
14095 ignore_rest_of_line ();
14096 return;
14097 }
14098
14099 unwind.personality_index = exp.X_add_number;
14100
14101 demand_empty_rest_of_line ();
14102 }
14103
14104
14105 /* Parse a personality directive. */
14106
14107 static void
14108 s_arm_unwind_personality (int ignored ATTRIBUTE_UNUSED)
14109 {
14110 char *name, *p, c;
14111
14112 if (unwind.personality_routine || unwind.personality_index != -1)
14113 as_bad (_("duplicate .personality directive"));
14114
14115 SKIP_WHITESPACE ();
14116 name = input_line_pointer;
14117 c = get_symbol_end ();
14118 p = input_line_pointer;
14119 unwind.personality_routine = symbol_find_or_make (name);
14120 *p = c;
14121 SKIP_WHITESPACE ();
14122 demand_empty_rest_of_line ();
14123 }
14124
14125
14126 /* Parse a directive saving core registers. */
14127
14128 static void
14129 s_arm_unwind_save_core (void)
14130 {
14131 valueT op;
14132 long range;
14133 int n;
14134
14135 SKIP_WHITESPACE ();
14136 range = reg_list (&input_line_pointer);
14137 if (range == FAIL)
14138 {
14139 as_bad (_("expected register list"));
14140 ignore_rest_of_line ();
14141 return;
14142 }
14143
14144 demand_empty_rest_of_line ();
14145
14146 /* Turn .unwind_movsp ip followed by .unwind_save {..., ip, ...}
14147 into .unwind_save {..., sp...}. We aren't bothered about the value of
14148 ip because it is clobbered by calls. */
14149 if (unwind.sp_restored && unwind.fp_reg == 12
14150 && (range & 0x3000) == 0x1000)
14151 {
14152 unwind.opcode_count--;
14153 unwind.sp_restored = 0;
14154 range = (range | 0x2000) & ~0x1000;
14155 unwind.pending_offset = 0;
14156 }
14157
14158 /* See if we can use the short opcodes. These pop a block of upto 8
14159 registers starting with r4, plus maybe r14. */
14160 for (n = 0; n < 8; n++)
14161 {
14162 /* Break at the first non-saved register. */
14163 if ((range & (1 << (n + 4))) == 0)
14164 break;
14165 }
14166 /* See if there are any other bits set. */
14167 if (n == 0 || (range & (0xfff0 << n) & 0xbff0) != 0)
14168 {
14169 /* Use the long form. */
14170 op = 0x8000 | ((range >> 4) & 0xfff);
14171 add_unwind_opcode (op, 2);
14172 }
14173 else
14174 {
14175 /* Use the short form. */
14176 if (range & 0x4000)
14177 op = 0xa8; /* Pop r14. */
14178 else
14179 op = 0xa0; /* Do not pop r14. */
14180 op |= (n - 1);
14181 add_unwind_opcode (op, 1);
14182 }
14183
14184 /* Pop r0-r3. */
14185 if (range & 0xf)
14186 {
14187 op = 0xb100 | (range & 0xf);
14188 add_unwind_opcode (op, 2);
14189 }
14190
14191 /* Record the number of bytes pushed. */
14192 for (n = 0; n < 16; n++)
14193 {
14194 if (range & (1 << n))
14195 unwind.frame_size += 4;
14196 }
14197 }
14198
14199
14200 /* Parse a directive saving FPA registers. */
14201
14202 static void
14203 s_arm_unwind_save_fpa (int reg)
14204 {
14205 expressionS exp;
14206 int num_regs;
14207 valueT op;
14208
14209 /* Get Number of registers to transfer. */
14210 if (skip_past_comma (&input_line_pointer) != FAIL)
14211 expression (&exp);
14212 else
14213 exp.X_op = O_illegal;
14214
14215 if (exp.X_op != O_constant)
14216 {
14217 as_bad (_("expected , <constant>"));
14218 ignore_rest_of_line ();
14219 return;
14220 }
14221
14222 num_regs = exp.X_add_number;
14223
14224 if (num_regs < 1 || num_regs > 4)
14225 {
14226 as_bad (_("number of registers must be in the range [1:4]"));
14227 ignore_rest_of_line ();
14228 return;
14229 }
14230
14231 demand_empty_rest_of_line ();
14232
14233 if (reg == 4)
14234 {
14235 /* Short form. */
14236 op = 0xb4 | (num_regs - 1);
14237 add_unwind_opcode (op, 1);
14238 }
14239 else
14240 {
14241 /* Long form. */
14242 op = 0xc800 | (reg << 4) | (num_regs - 1);
14243 add_unwind_opcode (op, 2);
14244 }
14245 unwind.frame_size += num_regs * 12;
14246 }
14247
14248
14249 /* Parse a directive saving VFP registers. */
14250
14251 static void
14252 s_arm_unwind_save_vfp (void)
14253 {
14254 int count;
14255 int reg;
14256 valueT op;
14257
14258 count = vfp_parse_reg_list (&input_line_pointer, &reg, 1);
14259 if (count == FAIL)
14260 {
14261 as_bad (_("expected register list"));
14262 ignore_rest_of_line ();
14263 return;
14264 }
14265
14266 demand_empty_rest_of_line ();
14267
14268 if (reg == 8)
14269 {
14270 /* Short form. */
14271 op = 0xb8 | (count - 1);
14272 add_unwind_opcode (op, 1);
14273 }
14274 else
14275 {
14276 /* Long form. */
14277 op = 0xb300 | (reg << 4) | (count - 1);
14278 add_unwind_opcode (op, 2);
14279 }
14280 unwind.frame_size += count * 8 + 4;
14281 }
14282
14283
14284 /* Parse a directive saving iWMMXt registers. */
14285
14286 static void
14287 s_arm_unwind_save_wmmx (void)
14288 {
14289 int reg;
14290 int hi_reg;
14291 int i;
14292 unsigned wcg_mask;
14293 unsigned wr_mask;
14294 valueT op;
14295
14296 if (*input_line_pointer == '{')
14297 input_line_pointer++;
14298
14299 wcg_mask = 0;
14300 wr_mask = 0;
14301 do
14302 {
14303 reg = arm_reg_parse (&input_line_pointer,
14304 all_reg_maps[REG_TYPE_IWMMXT].htab);
14305
14306 if (wr_register (reg))
14307 {
14308 i = reg & ~WR_PREFIX;
14309 if (wr_mask >> i)
14310 as_tsktsk (_("register list not in ascending order"));
14311 wr_mask |= 1 << i;
14312 }
14313 else if (wcg_register (reg))
14314 {
14315 i = (reg & ~WC_PREFIX) - 8;
14316 if (wcg_mask >> i)
14317 as_tsktsk (_("register list not in ascending order"));
14318 wcg_mask |= 1 << i;
14319 }
14320 else
14321 {
14322 as_bad (_("expected wr or wcgr"));
14323 goto error;
14324 }
14325
14326 SKIP_WHITESPACE ();
14327 if (*input_line_pointer == '-')
14328 {
14329 hi_reg = arm_reg_parse (&input_line_pointer,
14330 all_reg_maps[REG_TYPE_IWMMXT].htab);
14331 if (wr_register (reg) && wr_register (hi_reg))
14332 {
14333 for (; reg < hi_reg; reg++)
14334 wr_mask |= 1 << (reg & ~WR_PREFIX);
14335 }
14336 else if (wcg_register (reg) && wcg_register (hi_reg))
14337 {
14338 for (; reg < hi_reg; reg++)
14339 wcg_mask |= 1 << ((reg & ~WC_PREFIX) - 8);
14340 }
14341 else
14342 {
14343 as_bad (_("bad register range"));
14344 goto error;
14345 }
14346 }
14347 }
14348 while (skip_past_comma (&input_line_pointer) != FAIL);
14349
14350 SKIP_WHITESPACE ();
14351 if (*input_line_pointer == '}')
14352 input_line_pointer++;
14353
14354 demand_empty_rest_of_line ();
14355
14356 if (wr_mask && wcg_mask)
14357 {
14358 as_bad (_("inconsistent register types"));
14359 goto error;
14360 }
14361
14362 /* Generate any deferred opcodes becuuse we're going to be looking at
14363 the list. */
14364 flush_pending_unwind ();
14365
14366 if (wcg_mask)
14367 {
14368 for (i = 0; i < 16; i++)
14369 {
14370 if (wcg_mask & (1 << i))
14371 unwind.frame_size += 4;
14372 }
14373 op = 0xc700 | wcg_mask;
14374 add_unwind_opcode (op, 2);
14375 }
14376 else
14377 {
14378 for (i = 0; i < 16; i++)
14379 {
14380 if (wr_mask & (1 << i))
14381 unwind.frame_size += 8;
14382 }
14383 /* Attempt to combine with a previous opcode. We do this because gcc
14384 likes to output separate unwind directives for a single block of
14385 registers. */
14386 if (unwind.opcode_count > 0)
14387 {
14388 i = unwind.opcodes[unwind.opcode_count - 1];
14389 if ((i & 0xf8) == 0xc0)
14390 {
14391 i &= 7;
14392 /* Only merge if the blocks are contiguous. */
14393 if (i < 6)
14394 {
14395 if ((wr_mask & 0xfe00) == (1 << 9))
14396 {
14397 wr_mask |= ((1 << (i + 11)) - 1) & 0xfc00;
14398 unwind.opcode_count--;
14399 }
14400 }
14401 else if (i == 6 && unwind.opcode_count >= 2)
14402 {
14403 i = unwind.opcodes[unwind.opcode_count - 2];
14404 reg = i >> 4;
14405 i &= 0xf;
14406
14407 op = 0xffff << (reg - 1);
14408 if (reg > 0
14409 || ((wr_mask & op) == (1u << (reg - 1))))
14410 {
14411 op = (1 << (reg + i + 1)) - 1;
14412 op &= ~((1 << reg) - 1);
14413 wr_mask |= op;
14414 unwind.opcode_count -= 2;
14415 }
14416 }
14417 }
14418 }
14419
14420 hi_reg = 15;
14421 /* We want to generate opcodes in the order the registers have been
14422 saved, ie. descending order. */
14423 for (reg = 15; reg >= -1; reg--)
14424 {
14425 /* Save registers in blocks. */
14426 if (reg < 0
14427 || !(wr_mask & (1 << reg)))
14428 {
14429 /* We found an unsaved reg. Generate opcodes to save the
14430 preceeding block. */
14431 if (reg != hi_reg)
14432 {
14433 if (reg == 9)
14434 {
14435 /* Short form. */
14436 op = 0xc0 | (hi_reg - 10);
14437 add_unwind_opcode (op, 1);
14438 }
14439 else
14440 {
14441 /* Long form. */
14442 op = 0xc600 | ((reg + 1) << 4) | ((hi_reg - reg) - 1);
14443 add_unwind_opcode (op, 2);
14444 }
14445 }
14446 hi_reg = reg - 1;
14447 }
14448 }
14449 }
14450 return;
14451 error:
14452 ignore_rest_of_line ();
14453 }
14454
14455
14456 /* Parse an unwind_save directive. */
14457
14458 static void
14459 s_arm_unwind_save (int ignored ATTRIBUTE_UNUSED)
14460 {
14461 char *saved_ptr;
14462 int reg;
14463
14464 /* Figure out what sort of save we have. */
14465 SKIP_WHITESPACE ();
14466 saved_ptr = input_line_pointer;
14467
14468 reg = arm_reg_parse (&input_line_pointer, all_reg_maps[REG_TYPE_FN].htab);
14469 if (reg != FAIL)
14470 {
14471 s_arm_unwind_save_fpa (reg);
14472 return;
14473 }
14474
14475 if (*input_line_pointer == '{')
14476 input_line_pointer++;
14477
14478 SKIP_WHITESPACE ();
14479
14480 reg = arm_reg_parse (&input_line_pointer, all_reg_maps[REG_TYPE_RN].htab);
14481 if (reg != FAIL)
14482 {
14483 input_line_pointer = saved_ptr;
14484 s_arm_unwind_save_core ();
14485 return;
14486 }
14487
14488 reg = arm_reg_parse (&input_line_pointer, all_reg_maps[REG_TYPE_DN].htab);
14489 if (reg != FAIL)
14490 {
14491 input_line_pointer = saved_ptr;
14492 s_arm_unwind_save_vfp ();
14493 return;
14494 }
14495
14496 reg = arm_reg_parse (&input_line_pointer,
14497 all_reg_maps[REG_TYPE_IWMMXT].htab);
14498 if (reg != FAIL)
14499 {
14500 input_line_pointer = saved_ptr;
14501 s_arm_unwind_save_wmmx ();
14502 return;
14503 }
14504
14505 /* TODO: Maverick registers. */
14506 as_bad (_("unrecognised register"));
14507 }
14508
14509
14510 /* Parse an unwind_movsp directive. */
14511
14512 static void
14513 s_arm_unwind_movsp (int ignored ATTRIBUTE_UNUSED)
14514 {
14515 int reg;
14516 valueT op;
14517
14518 SKIP_WHITESPACE ();
14519 reg = reg_required_here (&input_line_pointer, -1);
14520 if (reg == FAIL)
14521 {
14522 as_bad (_("ARM register expected"));
14523 ignore_rest_of_line ();
14524 return;
14525 }
14526
14527 if (reg == 13 || reg == 15)
14528 {
14529 as_bad (_("r%d not permitted in .unwind_movsp directive"), reg);
14530 ignore_rest_of_line ();
14531 return;
14532 }
14533
14534 if (unwind.fp_reg != 13)
14535 as_bad (_("unexpected .unwind_movsp directive"));
14536
14537 /* Generate opcode to restore the value. */
14538 op = 0x90 | reg;
14539 add_unwind_opcode (op, 1);
14540
14541 /* Record the information for later. */
14542 unwind.fp_reg = reg;
14543 unwind.fp_offset = unwind.frame_size;
14544 unwind.sp_restored = 1;
14545 demand_empty_rest_of_line ();
14546 }
14547
14548
14549 /* Parse #<number>. */
14550
14551 static int
14552 require_hashconst (int * val)
14553 {
14554 expressionS exp;
14555
14556 SKIP_WHITESPACE ();
14557 if (*input_line_pointer == '#')
14558 {
14559 input_line_pointer++;
14560 expression (&exp);
14561 }
14562 else
14563 exp.X_op = O_illegal;
14564
14565 if (exp.X_op != O_constant)
14566 {
14567 as_bad (_("expected #constant"));
14568 ignore_rest_of_line ();
14569 return FAIL;
14570 }
14571 *val = exp.X_add_number;
14572 return SUCCESS;
14573 }
14574
14575 /* Parse an unwind_pad directive. */
14576
14577 static void
14578 s_arm_unwind_pad (int ignored ATTRIBUTE_UNUSED)
14579 {
14580 int offset;
14581
14582 if (require_hashconst (&offset) == FAIL)
14583 return;
14584
14585 if (offset & 3)
14586 {
14587 as_bad (_("stack increment must be multiple of 4"));
14588 ignore_rest_of_line ();
14589 return;
14590 }
14591
14592 /* Don't generate any opcodes, just record the details for later. */
14593 unwind.frame_size += offset;
14594 unwind.pending_offset += offset;
14595
14596 demand_empty_rest_of_line ();
14597 }
14598
14599 /* Parse an unwind_setfp directive. */
14600
14601 static void
14602 s_arm_unwind_setfp (int ignored ATTRIBUTE_UNUSED)
14603 {
14604 int sp_reg;
14605 int fp_reg;
14606 int offset;
14607
14608 fp_reg = reg_required_here (&input_line_pointer, -1);
14609 if (skip_past_comma (&input_line_pointer) == FAIL)
14610 sp_reg = FAIL;
14611 else
14612 sp_reg = reg_required_here (&input_line_pointer, -1);
14613
14614 if (fp_reg == FAIL || sp_reg == FAIL)
14615 {
14616 as_bad (_("expected <reg>, <reg>"));
14617 ignore_rest_of_line ();
14618 return;
14619 }
14620
14621 /* Optonal constant. */
14622 if (skip_past_comma (&input_line_pointer) != FAIL)
14623 {
14624 if (require_hashconst (&offset) == FAIL)
14625 return;
14626 }
14627 else
14628 offset = 0;
14629
14630 demand_empty_rest_of_line ();
14631
14632 if (sp_reg != 13 && sp_reg != unwind.fp_reg)
14633 {
14634 as_bad (_("register must be either sp or set by a previous"
14635 "unwind_movsp directive"));
14636 return;
14637 }
14638
14639 /* Don't generate any opcodes, just record the information for later. */
14640 unwind.fp_reg = fp_reg;
14641 unwind.fp_used = 1;
14642 if (sp_reg == 13)
14643 unwind.fp_offset = unwind.frame_size - offset;
14644 else
14645 unwind.fp_offset -= offset;
14646 }
14647
14648 /* Parse an unwind_raw directive. */
14649
14650 static void
14651 s_arm_unwind_raw (int ignored ATTRIBUTE_UNUSED)
14652 {
14653 expressionS exp;
14654 /* This is an arbitary limit. */
14655 unsigned char op[16];
14656 int count;
14657
14658 SKIP_WHITESPACE ();
14659 expression (&exp);
14660 if (exp.X_op == O_constant
14661 && skip_past_comma (&input_line_pointer) != FAIL)
14662 {
14663 unwind.frame_size += exp.X_add_number;
14664 expression (&exp);
14665 }
14666 else
14667 exp.X_op = O_illegal;
14668
14669 if (exp.X_op != O_constant)
14670 {
14671 as_bad (_("expected <offset>, <opcode>"));
14672 ignore_rest_of_line ();
14673 return;
14674 }
14675
14676 count = 0;
14677
14678 /* Parse the opcode. */
14679 for (;;)
14680 {
14681 if (count >= 16)
14682 {
14683 as_bad (_("unwind opcode too long"));
14684 ignore_rest_of_line ();
14685 }
14686 if (exp.X_op != O_constant || exp.X_add_number & ~0xff)
14687 {
14688 as_bad (_("invalid unwind opcode"));
14689 ignore_rest_of_line ();
14690 return;
14691 }
14692 op[count++] = exp.X_add_number;
14693
14694 /* Parse the next byte. */
14695 if (skip_past_comma (&input_line_pointer) == FAIL)
14696 break;
14697
14698 expression (&exp);
14699 }
14700
14701 /* Add the opcode bytes in reverse order. */
14702 while (count--)
14703 add_unwind_opcode (op[count], 1);
14704
14705 demand_empty_rest_of_line ();
14706 }
14707
14708 #endif /* OBJ_ELF */
14709
14710 /* This is called from HANDLE_ALIGN in write.c. Fill in the contents
14711 of an rs_align_code fragment. */
14712
14713 void
14714 arm_handle_align (fragS * fragP)
14715 {
14716 static char const arm_noop[4] = { 0x00, 0x00, 0xa0, 0xe1 };
14717 static char const thumb_noop[2] = { 0xc0, 0x46 };
14718 static char const arm_bigend_noop[4] = { 0xe1, 0xa0, 0x00, 0x00 };
14719 static char const thumb_bigend_noop[2] = { 0x46, 0xc0 };
14720
14721 int bytes, fix, noop_size;
14722 char * p;
14723 const char * noop;
14724
14725 if (fragP->fr_type != rs_align_code)
14726 return;
14727
14728 bytes = fragP->fr_next->fr_address - fragP->fr_address - fragP->fr_fix;
14729 p = fragP->fr_literal + fragP->fr_fix;
14730 fix = 0;
14731
14732 if (bytes > MAX_MEM_FOR_RS_ALIGN_CODE)
14733 bytes &= MAX_MEM_FOR_RS_ALIGN_CODE;
14734
14735 if (fragP->tc_frag_data)
14736 {
14737 if (target_big_endian)
14738 noop = thumb_bigend_noop;
14739 else
14740 noop = thumb_noop;
14741 noop_size = sizeof (thumb_noop);
14742 }
14743 else
14744 {
14745 if (target_big_endian)
14746 noop = arm_bigend_noop;
14747 else
14748 noop = arm_noop;
14749 noop_size = sizeof (arm_noop);
14750 }
14751
14752 if (bytes & (noop_size - 1))
14753 {
14754 fix = bytes & (noop_size - 1);
14755 memset (p, 0, fix);
14756 p += fix;
14757 bytes -= fix;
14758 }
14759
14760 while (bytes >= noop_size)
14761 {
14762 memcpy (p, noop, noop_size);
14763 p += noop_size;
14764 bytes -= noop_size;
14765 fix += noop_size;
14766 }
14767
14768 fragP->fr_fix += fix;
14769 fragP->fr_var = noop_size;
14770 }
14771
14772 /* Called from md_do_align. Used to create an alignment
14773 frag in a code section. */
14774
14775 void
14776 arm_frag_align_code (int n, int max)
14777 {
14778 char * p;
14779
14780 /* We assume that there will never be a requirement
14781 to support alignments greater than 32 bytes. */
14782 if (max > MAX_MEM_FOR_RS_ALIGN_CODE)
14783 as_fatal (_("alignments greater than 32 bytes not supported in .text sections."));
14784
14785 p = frag_var (rs_align_code,
14786 MAX_MEM_FOR_RS_ALIGN_CODE,
14787 1,
14788 (relax_substateT) max,
14789 (symbolS *) NULL,
14790 (offsetT) n,
14791 (char *) NULL);
14792 *p = 0;
14793 }
14794
14795 /* Perform target specific initialisation of a frag. */
14796
14797 void
14798 arm_init_frag (fragS * fragP)
14799 {
14800 /* Record whether this frag is in an ARM or a THUMB area. */
14801 fragP->tc_frag_data = thumb_mode;
14802 }
14803
14804 #ifdef OBJ_ELF
14805
14806 /* Convert REGNAME to a DWARF-2 register number. */
14807
14808 int
14809 tc_arm_regname_to_dw2regnum (const char *regname)
14810 {
14811 unsigned int i;
14812
14813 for (i = 0; rn_table[i].name; i++)
14814 if (streq (regname, rn_table[i].name))
14815 return rn_table[i].number;
14816
14817 return -1;
14818 }
14819
14820 /* Initialize the DWARF-2 unwind information for this procedure. */
14821
14822 void
14823 tc_arm_frame_initial_instructions (void)
14824 {
14825 cfi_add_CFA_def_cfa (REG_SP, 0);
14826 }
14827 #endif
14828
14829 /* This table describes all the machine specific pseudo-ops the assembler
14830 has to support. The fields are:
14831 pseudo-op name without dot
14832 function to call to execute this pseudo-op
14833 Integer arg to pass to the function. */
14834
14835 const pseudo_typeS md_pseudo_table[] =
14836 {
14837 /* Never called because '.req' does not start a line. */
14838 { "req", s_req, 0 },
14839 { "unreq", s_unreq, 0 },
14840 { "bss", s_bss, 0 },
14841 { "align", s_align, 0 },
14842 { "arm", s_arm, 0 },
14843 { "thumb", s_thumb, 0 },
14844 { "code", s_code, 0 },
14845 { "force_thumb", s_force_thumb, 0 },
14846 { "thumb_func", s_thumb_func, 0 },
14847 { "thumb_set", s_thumb_set, 0 },
14848 { "even", s_even, 0 },
14849 { "ltorg", s_ltorg, 0 },
14850 { "pool", s_ltorg, 0 },
14851 #ifdef OBJ_ELF
14852 { "word", s_arm_elf_cons, 4 },
14853 { "long", s_arm_elf_cons, 4 },
14854 { "rel31", s_arm_rel31, 0 },
14855 { "fnstart", s_arm_unwind_fnstart, 0 },
14856 { "fnend", s_arm_unwind_fnend, 0 },
14857 { "cantunwind", s_arm_unwind_cantunwind, 0 },
14858 { "personality", s_arm_unwind_personality, 0 },
14859 { "personalityindex", s_arm_unwind_personalityindex, 0 },
14860 { "handlerdata", s_arm_unwind_handlerdata, 0 },
14861 { "save", s_arm_unwind_save, 0 },
14862 { "movsp", s_arm_unwind_movsp, 0 },
14863 { "pad", s_arm_unwind_pad, 0 },
14864 { "setfp", s_arm_unwind_setfp, 0 },
14865 { "unwind_raw", s_arm_unwind_raw, 0 },
14866 #else
14867 { "word", cons, 4},
14868 #endif
14869 { "extend", float_cons, 'x' },
14870 { "ldouble", float_cons, 'x' },
14871 { "packed", float_cons, 'p' },
14872 { 0, 0, 0 }
14873 };