3ab5aa1524a411f851828b919cea0da5870f6b3b
[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 /* ARM V6K. */
10955 {"sev", 0xbf40, 2, ARM_EXT_V6K, do_empty},
10956 {"wfe", 0xbf20, 2, ARM_EXT_V6K, do_empty},
10957 {"wfi", 0xbf30, 2, ARM_EXT_V6K, do_empty},
10958 {"yield", 0xbf10, 2, ARM_EXT_V6K, do_empty},
10959 };
10960
10961 void
10962 md_begin (void)
10963 {
10964 unsigned mach;
10965 unsigned int i;
10966
10967 if ( (arm_ops_hsh = hash_new ()) == NULL
10968 || (arm_tops_hsh = hash_new ()) == NULL
10969 || (arm_cond_hsh = hash_new ()) == NULL
10970 || (arm_shift_hsh = hash_new ()) == NULL
10971 || (arm_psr_hsh = hash_new ()) == NULL)
10972 as_fatal (_("virtual memory exhausted"));
10973
10974 build_arm_ops_hsh ();
10975 for (i = 0; i < sizeof (tinsns) / sizeof (struct thumb_opcode); i++)
10976 hash_insert (arm_tops_hsh, tinsns[i].template, (PTR) (tinsns + i));
10977 for (i = 0; i < sizeof (conds) / sizeof (struct asm_cond); i++)
10978 hash_insert (arm_cond_hsh, conds[i].template, (PTR) (conds + i));
10979 for (i = 0; i < sizeof (shift_names) / sizeof (struct asm_shift_name); i++)
10980 hash_insert (arm_shift_hsh, shift_names[i].name, (PTR) (shift_names + i));
10981 for (i = 0; i < sizeof (psrs) / sizeof (struct asm_psr); i++)
10982 hash_insert (arm_psr_hsh, psrs[i].template, (PTR) (psrs + i));
10983
10984 for (i = (int) REG_TYPE_FIRST; i < (int) REG_TYPE_MAX; i++)
10985 build_reg_hsh (all_reg_maps + i);
10986
10987 set_constant_flonums ();
10988
10989 /* Set the cpu variant based on the command-line options. We prefer
10990 -mcpu= over -march= if both are set (as for GCC); and we prefer
10991 -mfpu= over any other way of setting the floating point unit.
10992 Use of legacy options with new options are faulted. */
10993 if (legacy_cpu != -1)
10994 {
10995 if (mcpu_cpu_opt != -1 || march_cpu_opt != -1)
10996 as_bad (_("use of old and new-style options to set CPU type"));
10997
10998 mcpu_cpu_opt = legacy_cpu;
10999 }
11000 else if (mcpu_cpu_opt == -1)
11001 mcpu_cpu_opt = march_cpu_opt;
11002
11003 if (legacy_fpu != -1)
11004 {
11005 if (mfpu_opt != -1)
11006 as_bad (_("use of old and new-style options to set FPU type"));
11007
11008 mfpu_opt = legacy_fpu;
11009 }
11010 else if (mfpu_opt == -1)
11011 {
11012 #if !(defined (TE_LINUX) || defined (TE_NetBSD) || defined (TE_VXWORKS))
11013 /* Some environments specify a default FPU. If they don't, infer it
11014 from the processor. */
11015 if (mcpu_fpu_opt != -1)
11016 mfpu_opt = mcpu_fpu_opt;
11017 else
11018 mfpu_opt = march_fpu_opt;
11019 #else
11020 mfpu_opt = FPU_DEFAULT;
11021 #endif
11022 }
11023
11024 if (mfpu_opt == -1)
11025 {
11026 if (mcpu_cpu_opt == -1)
11027 mfpu_opt = FPU_DEFAULT;
11028 else if (mcpu_cpu_opt & ARM_EXT_V5)
11029 mfpu_opt = FPU_ARCH_VFP_V2;
11030 else
11031 mfpu_opt = FPU_ARCH_FPA;
11032 }
11033
11034 if (mcpu_cpu_opt == -1)
11035 mcpu_cpu_opt = CPU_DEFAULT;
11036
11037 cpu_variant = mcpu_cpu_opt | mfpu_opt;
11038
11039 #if defined OBJ_COFF || defined OBJ_ELF
11040 {
11041 unsigned int flags = 0;
11042
11043 #if defined OBJ_ELF
11044 flags = meabi_flags;
11045
11046 switch (meabi_flags)
11047 {
11048 case EF_ARM_EABI_UNKNOWN:
11049 #endif
11050 /* Set the flags in the private structure. */
11051 if (uses_apcs_26) flags |= F_APCS26;
11052 if (support_interwork) flags |= F_INTERWORK;
11053 if (uses_apcs_float) flags |= F_APCS_FLOAT;
11054 if (pic_code) flags |= F_PIC;
11055 if ((cpu_variant & FPU_ANY) == FPU_NONE
11056 || (cpu_variant & FPU_ANY) == FPU_ARCH_VFP) /* VFP layout only. */
11057 flags |= F_SOFT_FLOAT;
11058
11059 switch (mfloat_abi_opt)
11060 {
11061 case ARM_FLOAT_ABI_SOFT:
11062 case ARM_FLOAT_ABI_SOFTFP:
11063 flags |= F_SOFT_FLOAT;
11064 break;
11065
11066 case ARM_FLOAT_ABI_HARD:
11067 if (flags & F_SOFT_FLOAT)
11068 as_bad (_("hard-float conflicts with specified fpu"));
11069 break;
11070 }
11071
11072 /* Using VFP conventions (even if soft-float). */
11073 if (cpu_variant & FPU_VFP_EXT_NONE)
11074 flags |= F_VFP_FLOAT;
11075
11076 #if defined OBJ_ELF
11077 if (cpu_variant & FPU_ARCH_MAVERICK)
11078 flags |= EF_ARM_MAVERICK_FLOAT;
11079 break;
11080
11081 case EF_ARM_EABI_VER4:
11082 /* No additional flags to set. */
11083 break;
11084
11085 default:
11086 abort ();
11087 }
11088 #endif
11089 bfd_set_private_flags (stdoutput, flags);
11090
11091 /* We have run out flags in the COFF header to encode the
11092 status of ATPCS support, so instead we create a dummy,
11093 empty, debug section called .arm.atpcs. */
11094 if (atpcs)
11095 {
11096 asection * sec;
11097
11098 sec = bfd_make_section (stdoutput, ".arm.atpcs");
11099
11100 if (sec != NULL)
11101 {
11102 bfd_set_section_flags
11103 (stdoutput, sec, SEC_READONLY | SEC_DEBUGGING /* | SEC_HAS_CONTENTS */);
11104 bfd_set_section_size (stdoutput, sec, 0);
11105 bfd_set_section_contents (stdoutput, sec, NULL, 0, 0);
11106 }
11107 }
11108 }
11109 #endif
11110
11111 /* Record the CPU type as well. */
11112 switch (cpu_variant & ARM_CPU_MASK)
11113 {
11114 case ARM_2:
11115 mach = bfd_mach_arm_2;
11116 break;
11117
11118 case ARM_3: /* Also ARM_250. */
11119 mach = bfd_mach_arm_2a;
11120 break;
11121
11122 case ARM_6: /* Also ARM_7. */
11123 mach = bfd_mach_arm_3;
11124 break;
11125
11126 default:
11127 mach = bfd_mach_arm_unknown;
11128 break;
11129 }
11130
11131 /* Catch special cases. */
11132 if (cpu_variant & ARM_CEXT_IWMMXT)
11133 mach = bfd_mach_arm_iWMMXt;
11134 else if (cpu_variant & ARM_CEXT_XSCALE)
11135 mach = bfd_mach_arm_XScale;
11136 else if (cpu_variant & ARM_CEXT_MAVERICK)
11137 mach = bfd_mach_arm_ep9312;
11138 else if (cpu_variant & ARM_EXT_V5E)
11139 mach = bfd_mach_arm_5TE;
11140 else if (cpu_variant & ARM_EXT_V5)
11141 {
11142 if (cpu_variant & ARM_EXT_V4T)
11143 mach = bfd_mach_arm_5T;
11144 else
11145 mach = bfd_mach_arm_5;
11146 }
11147 else if (cpu_variant & ARM_EXT_V4)
11148 {
11149 if (cpu_variant & ARM_EXT_V4T)
11150 mach = bfd_mach_arm_4T;
11151 else
11152 mach = bfd_mach_arm_4;
11153 }
11154 else if (cpu_variant & ARM_EXT_V3M)
11155 mach = bfd_mach_arm_3M;
11156
11157 bfd_set_arch_mach (stdoutput, TARGET_ARCH, mach);
11158 }
11159
11160 /* Turn an integer of n bytes (in val) into a stream of bytes appropriate
11161 for use in the a.out file, and stores them in the array pointed to by buf.
11162 This knows about the endian-ness of the target machine and does
11163 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
11164 2 (short) and 4 (long) Floating numbers are put out as a series of
11165 LITTLENUMS (shorts, here at least). */
11166
11167 void
11168 md_number_to_chars (char * buf, valueT val, int n)
11169 {
11170 if (target_big_endian)
11171 number_to_chars_bigendian (buf, val, n);
11172 else
11173 number_to_chars_littleendian (buf, val, n);
11174 }
11175
11176 static valueT
11177 md_chars_to_number (char * buf, int n)
11178 {
11179 valueT result = 0;
11180 unsigned char * where = (unsigned char *) buf;
11181
11182 if (target_big_endian)
11183 {
11184 while (n--)
11185 {
11186 result <<= 8;
11187 result |= (*where++ & 255);
11188 }
11189 }
11190 else
11191 {
11192 while (n--)
11193 {
11194 result <<= 8;
11195 result |= (where[n] & 255);
11196 }
11197 }
11198
11199 return result;
11200 }
11201
11202 /* Turn a string in input_line_pointer into a floating point constant
11203 of type TYPE, and store the appropriate bytes in *LITP. The number
11204 of LITTLENUMS emitted is stored in *SIZEP. An error message is
11205 returned, or NULL on OK.
11206
11207 Note that fp constants aren't represent in the normal way on the ARM.
11208 In big endian mode, things are as expected. However, in little endian
11209 mode fp constants are big-endian word-wise, and little-endian byte-wise
11210 within the words. For example, (double) 1.1 in big endian mode is
11211 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
11212 the byte sequence 99 99 f1 3f 9a 99 99 99.
11213
11214 ??? The format of 12 byte floats is uncertain according to gcc's arm.h. */
11215
11216 char *
11217 md_atof (int type, char * litP, int * sizeP)
11218 {
11219 int prec;
11220 LITTLENUM_TYPE words[MAX_LITTLENUMS];
11221 char *t;
11222 int i;
11223
11224 switch (type)
11225 {
11226 case 'f':
11227 case 'F':
11228 case 's':
11229 case 'S':
11230 prec = 2;
11231 break;
11232
11233 case 'd':
11234 case 'D':
11235 case 'r':
11236 case 'R':
11237 prec = 4;
11238 break;
11239
11240 case 'x':
11241 case 'X':
11242 prec = 6;
11243 break;
11244
11245 case 'p':
11246 case 'P':
11247 prec = 6;
11248 break;
11249
11250 default:
11251 *sizeP = 0;
11252 return _("bad call to MD_ATOF()");
11253 }
11254
11255 t = atof_ieee (input_line_pointer, type, words);
11256 if (t)
11257 input_line_pointer = t;
11258 *sizeP = prec * 2;
11259
11260 if (target_big_endian)
11261 {
11262 for (i = 0; i < prec; i++)
11263 {
11264 md_number_to_chars (litP, (valueT) words[i], 2);
11265 litP += 2;
11266 }
11267 }
11268 else
11269 {
11270 if (cpu_variant & FPU_ARCH_VFP)
11271 for (i = prec - 1; i >= 0; i--)
11272 {
11273 md_number_to_chars (litP, (valueT) words[i], 2);
11274 litP += 2;
11275 }
11276 else
11277 /* For a 4 byte float the order of elements in `words' is 1 0.
11278 For an 8 byte float the order is 1 0 3 2. */
11279 for (i = 0; i < prec; i += 2)
11280 {
11281 md_number_to_chars (litP, (valueT) words[i + 1], 2);
11282 md_number_to_chars (litP + 2, (valueT) words[i], 2);
11283 litP += 4;
11284 }
11285 }
11286
11287 return 0;
11288 }
11289
11290 /* The knowledge of the PC's pipeline offset is built into the insns
11291 themselves. */
11292
11293 long
11294 md_pcrel_from (fixS * fixP)
11295 {
11296 if (fixP->fx_addsy
11297 && S_GET_SEGMENT (fixP->fx_addsy) == undefined_section
11298 && fixP->fx_subsy == NULL)
11299 return 0;
11300
11301 if (fixP->fx_pcrel && (fixP->fx_r_type == BFD_RELOC_ARM_THUMB_ADD))
11302 {
11303 /* PC relative addressing on the Thumb is slightly odd
11304 as the bottom two bits of the PC are forced to zero
11305 for the calculation. */
11306 return (fixP->fx_where + fixP->fx_frag->fr_address) & ~3;
11307 }
11308
11309 #ifdef TE_WINCE
11310 /* The pattern was adjusted to accommodate CE's off-by-one fixups,
11311 so we un-adjust here to compensate for the accommodation. */
11312 return fixP->fx_where + fixP->fx_frag->fr_address + 8;
11313 #else
11314 return fixP->fx_where + fixP->fx_frag->fr_address;
11315 #endif
11316 }
11317
11318 /* Round up a section size to the appropriate boundary. */
11319
11320 valueT
11321 md_section_align (segT segment ATTRIBUTE_UNUSED,
11322 valueT size)
11323 {
11324 #ifdef OBJ_ELF
11325 return size;
11326 #else
11327 /* Round all sects to multiple of 4. */
11328 return (size + 3) & ~3;
11329 #endif
11330 }
11331
11332 /* Under ELF we need to default _GLOBAL_OFFSET_TABLE.
11333 Otherwise we have no need to default values of symbols. */
11334
11335 symbolS *
11336 md_undefined_symbol (char * name ATTRIBUTE_UNUSED)
11337 {
11338 #ifdef OBJ_ELF
11339 if (name[0] == '_' && name[1] == 'G'
11340 && streq (name, GLOBAL_OFFSET_TABLE_NAME))
11341 {
11342 if (!GOT_symbol)
11343 {
11344 if (symbol_find (name))
11345 as_bad ("GOT already in the symbol table");
11346
11347 GOT_symbol = symbol_new (name, undefined_section,
11348 (valueT) 0, & zero_address_frag);
11349 }
11350
11351 return GOT_symbol;
11352 }
11353 #endif
11354
11355 return 0;
11356 }
11357
11358 void
11359 md_apply_fix3 (fixS * fixP,
11360 valueT * valP,
11361 segT seg)
11362 {
11363 offsetT value = * valP;
11364 offsetT newval;
11365 unsigned int newimm;
11366 unsigned long temp;
11367 int sign;
11368 char * buf = fixP->fx_where + fixP->fx_frag->fr_literal;
11369 arm_fix_data * arm_data = (arm_fix_data *) fixP->tc_fix_data;
11370
11371 assert (fixP->fx_r_type <= BFD_RELOC_UNUSED);
11372
11373 /* Note whether this will delete the relocation. */
11374 if (fixP->fx_addsy == 0 && !fixP->fx_pcrel)
11375 fixP->fx_done = 1;
11376
11377 /* If this symbol is in a different section then we need to leave it for
11378 the linker to deal with. Unfortunately, md_pcrel_from can't tell,
11379 so we have to undo it's effects here. */
11380 if (fixP->fx_pcrel)
11381 {
11382 if (fixP->fx_addsy != NULL
11383 && S_IS_DEFINED (fixP->fx_addsy)
11384 && S_GET_SEGMENT (fixP->fx_addsy) != seg)
11385 value += md_pcrel_from (fixP);
11386 }
11387
11388 /* Remember value for emit_reloc. */
11389 fixP->fx_addnumber = value;
11390
11391 switch (fixP->fx_r_type)
11392 {
11393 case BFD_RELOC_NONE:
11394 /* This will need to go in the object file. */
11395 fixP->fx_done = 0;
11396 break;
11397
11398 case BFD_RELOC_ARM_IMMEDIATE:
11399 /* We claim that this fixup has been processed here,
11400 even if in fact we generate an error because we do
11401 not have a reloc for it, so tc_gen_reloc will reject it. */
11402 fixP->fx_done = 1;
11403
11404 if (fixP->fx_addsy
11405 && ! S_IS_DEFINED (fixP->fx_addsy))
11406 {
11407 as_bad_where (fixP->fx_file, fixP->fx_line,
11408 _("undefined symbol %s used as an immediate value"),
11409 S_GET_NAME (fixP->fx_addsy));
11410 break;
11411 }
11412
11413 newimm = validate_immediate (value);
11414 temp = md_chars_to_number (buf, INSN_SIZE);
11415
11416 /* If the instruction will fail, see if we can fix things up by
11417 changing the opcode. */
11418 if (newimm == (unsigned int) FAIL
11419 && (newimm = negate_data_op (&temp, value)) == (unsigned int) FAIL)
11420 {
11421 as_bad_where (fixP->fx_file, fixP->fx_line,
11422 _("invalid constant (%lx) after fixup"),
11423 (unsigned long) value);
11424 break;
11425 }
11426
11427 newimm |= (temp & 0xfffff000);
11428 md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
11429 break;
11430
11431 case BFD_RELOC_ARM_ADRL_IMMEDIATE:
11432 {
11433 unsigned int highpart = 0;
11434 unsigned int newinsn = 0xe1a00000; /* nop. */
11435
11436 newimm = validate_immediate (value);
11437 temp = md_chars_to_number (buf, INSN_SIZE);
11438
11439 /* If the instruction will fail, see if we can fix things up by
11440 changing the opcode. */
11441 if (newimm == (unsigned int) FAIL
11442 && (newimm = negate_data_op (& temp, value)) == (unsigned int) FAIL)
11443 {
11444 /* No ? OK - try using two ADD instructions to generate
11445 the value. */
11446 newimm = validate_immediate_twopart (value, & highpart);
11447
11448 /* Yes - then make sure that the second instruction is
11449 also an add. */
11450 if (newimm != (unsigned int) FAIL)
11451 newinsn = temp;
11452 /* Still No ? Try using a negated value. */
11453 else if ((newimm = validate_immediate_twopart (- value, & highpart)) != (unsigned int) FAIL)
11454 temp = newinsn = (temp & OPCODE_MASK) | OPCODE_SUB << DATA_OP_SHIFT;
11455 /* Otherwise - give up. */
11456 else
11457 {
11458 as_bad_where (fixP->fx_file, fixP->fx_line,
11459 _("unable to compute ADRL instructions for PC offset of 0x%lx"),
11460 (long) value);
11461 break;
11462 }
11463
11464 /* Replace the first operand in the 2nd instruction (which
11465 is the PC) with the destination register. We have
11466 already added in the PC in the first instruction and we
11467 do not want to do it again. */
11468 newinsn &= ~ 0xf0000;
11469 newinsn |= ((newinsn & 0x0f000) << 4);
11470 }
11471
11472 newimm |= (temp & 0xfffff000);
11473 md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
11474
11475 highpart |= (newinsn & 0xfffff000);
11476 md_number_to_chars (buf + INSN_SIZE, (valueT) highpart, INSN_SIZE);
11477 }
11478 break;
11479
11480 case BFD_RELOC_ARM_OFFSET_IMM:
11481 sign = value >= 0;
11482
11483 if (value < 0)
11484 value = - value;
11485
11486 if (validate_offset_imm (value, 0) == FAIL)
11487 {
11488 as_bad_where (fixP->fx_file, fixP->fx_line,
11489 _("bad immediate value for offset (%ld)"),
11490 (long) value);
11491 break;
11492 }
11493
11494 newval = md_chars_to_number (buf, INSN_SIZE);
11495 newval &= 0xff7ff000;
11496 newval |= value | (sign ? INDEX_UP : 0);
11497 md_number_to_chars (buf, newval, INSN_SIZE);
11498 break;
11499
11500 case BFD_RELOC_ARM_OFFSET_IMM8:
11501 case BFD_RELOC_ARM_HWLITERAL:
11502 sign = value >= 0;
11503
11504 if (value < 0)
11505 value = - value;
11506
11507 if (validate_offset_imm (value, 1) == FAIL)
11508 {
11509 if (fixP->fx_r_type == BFD_RELOC_ARM_HWLITERAL)
11510 as_bad_where (fixP->fx_file, fixP->fx_line,
11511 _("invalid literal constant: pool needs to be closer"));
11512 else
11513 as_bad (_("bad immediate value for half-word offset (%ld)"),
11514 (long) value);
11515 break;
11516 }
11517
11518 newval = md_chars_to_number (buf, INSN_SIZE);
11519 newval &= 0xff7ff0f0;
11520 newval |= ((value >> 4) << 8) | (value & 0xf) | (sign ? INDEX_UP : 0);
11521 md_number_to_chars (buf, newval, INSN_SIZE);
11522 break;
11523
11524 case BFD_RELOC_ARM_LITERAL:
11525 sign = value >= 0;
11526
11527 if (value < 0)
11528 value = - value;
11529
11530 if (validate_offset_imm (value, 0) == FAIL)
11531 {
11532 as_bad_where (fixP->fx_file, fixP->fx_line,
11533 _("invalid literal constant: pool needs to be closer"));
11534 break;
11535 }
11536
11537 newval = md_chars_to_number (buf, INSN_SIZE);
11538 newval &= 0xff7ff000;
11539 newval |= value | (sign ? INDEX_UP : 0);
11540 md_number_to_chars (buf, newval, INSN_SIZE);
11541 break;
11542
11543 case BFD_RELOC_ARM_SHIFT_IMM:
11544 newval = md_chars_to_number (buf, INSN_SIZE);
11545 if (((unsigned long) value) > 32
11546 || (value == 32
11547 && (((newval & 0x60) == 0) || (newval & 0x60) == 0x60)))
11548 {
11549 as_bad_where (fixP->fx_file, fixP->fx_line,
11550 _("shift expression is too large"));
11551 break;
11552 }
11553
11554 if (value == 0)
11555 /* Shifts of zero must be done as lsl. */
11556 newval &= ~0x60;
11557 else if (value == 32)
11558 value = 0;
11559 newval &= 0xfffff07f;
11560 newval |= (value & 0x1f) << 7;
11561 md_number_to_chars (buf, newval, INSN_SIZE);
11562 break;
11563
11564 case BFD_RELOC_ARM_SMI:
11565 if (((unsigned long) value) > 0xffff)
11566 as_bad_where (fixP->fx_file, fixP->fx_line,
11567 _("invalid smi expression"));
11568 newval = md_chars_to_number (buf, INSN_SIZE) & 0xfff000f0;
11569 newval |= (value & 0xf) | ((value & 0xfff0) << 4);
11570 md_number_to_chars (buf, newval, INSN_SIZE);
11571 break;
11572
11573 case BFD_RELOC_ARM_SWI:
11574 if (arm_data->thumb_mode)
11575 {
11576 if (((unsigned long) value) > 0xff)
11577 as_bad_where (fixP->fx_file, fixP->fx_line,
11578 _("invalid swi expression"));
11579 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xff00;
11580 newval |= value;
11581 md_number_to_chars (buf, newval, THUMB_SIZE);
11582 }
11583 else
11584 {
11585 if (((unsigned long) value) > 0x00ffffff)
11586 as_bad_where (fixP->fx_file, fixP->fx_line,
11587 _("invalid swi expression"));
11588 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff000000;
11589 newval |= value;
11590 md_number_to_chars (buf, newval, INSN_SIZE);
11591 }
11592 break;
11593
11594 case BFD_RELOC_ARM_MULTI:
11595 if (((unsigned long) value) > 0xffff)
11596 as_bad_where (fixP->fx_file, fixP->fx_line,
11597 _("invalid expression in load/store multiple"));
11598 newval = value | md_chars_to_number (buf, INSN_SIZE);
11599 md_number_to_chars (buf, newval, INSN_SIZE);
11600 break;
11601
11602 case BFD_RELOC_ARM_PCREL_BRANCH:
11603 newval = md_chars_to_number (buf, INSN_SIZE);
11604
11605 /* Sign-extend a 24-bit number. */
11606 #define SEXT24(x) ((((x) & 0xffffff) ^ (~ 0x7fffff)) + 0x800000)
11607
11608 #ifdef OBJ_ELF
11609 value = fixP->fx_offset;
11610 #endif
11611
11612 /* We are going to store value (shifted right by two) in the
11613 instruction, in a 24 bit, signed field. Thus we need to check
11614 that none of the top 8 bits of the shifted value (top 7 bits of
11615 the unshifted, unsigned value) are set, or that they are all set. */
11616 if ((value & ~ ((offsetT) 0x1ffffff)) != 0
11617 && ((value & ~ ((offsetT) 0x1ffffff)) != ~ ((offsetT) 0x1ffffff)))
11618 {
11619 #ifdef OBJ_ELF
11620 /* Normally we would be stuck at this point, since we cannot store
11621 the absolute address that is the destination of the branch in the
11622 24 bits of the branch instruction. If however, we happen to know
11623 that the destination of the branch is in the same section as the
11624 branch instruction itself, then we can compute the relocation for
11625 ourselves and not have to bother the linker with it.
11626
11627 FIXME: The test for OBJ_ELF is only here because I have not
11628 worked out how to do this for OBJ_COFF. */
11629 if (fixP->fx_addsy != NULL
11630 && S_IS_DEFINED (fixP->fx_addsy)
11631 && S_GET_SEGMENT (fixP->fx_addsy) == seg)
11632 {
11633 /* Get pc relative value to go into the branch. */
11634 value = * valP;
11635
11636 /* Permit a backward branch provided that enough bits
11637 are set. Allow a forwards branch, provided that
11638 enough bits are clear. */
11639 if ( (value & ~ ((offsetT) 0x1ffffff)) == ~ ((offsetT) 0x1ffffff)
11640 || (value & ~ ((offsetT) 0x1ffffff)) == 0)
11641 fixP->fx_done = 1;
11642 }
11643
11644 if (! fixP->fx_done)
11645 #endif
11646 as_bad_where (fixP->fx_file, fixP->fx_line,
11647 _("GAS can't handle same-section branch dest >= 0x04000000"));
11648 }
11649
11650 value >>= 2;
11651 value += SEXT24 (newval);
11652
11653 if ( (value & ~ ((offsetT) 0xffffff)) != 0
11654 && ((value & ~ ((offsetT) 0xffffff)) != ~ ((offsetT) 0xffffff)))
11655 as_bad_where (fixP->fx_file, fixP->fx_line,
11656 _("out of range branch"));
11657
11658 if (seg->use_rela_p && !fixP->fx_done)
11659 {
11660 /* Must unshift the value before storing it in the addend. */
11661 value <<= 2;
11662 #ifdef OBJ_ELF
11663 fixP->fx_offset = value;
11664 #endif
11665 fixP->fx_addnumber = value;
11666 newval = newval & 0xff000000;
11667 }
11668 else
11669 newval = (value & 0x00ffffff) | (newval & 0xff000000);
11670 md_number_to_chars (buf, newval, INSN_SIZE);
11671 break;
11672
11673 case BFD_RELOC_ARM_PCREL_BLX:
11674 {
11675 offsetT hbit;
11676 newval = md_chars_to_number (buf, INSN_SIZE);
11677
11678 #ifdef OBJ_ELF
11679 value = fixP->fx_offset;
11680 #endif
11681 hbit = (value >> 1) & 1;
11682 value = (value >> 2) & 0x00ffffff;
11683 value = (value + (newval & 0x00ffffff)) & 0x00ffffff;
11684
11685 if (seg->use_rela_p && !fixP->fx_done)
11686 {
11687 /* Must sign-extend and unshift the value before storing
11688 it in the addend. */
11689 value = SEXT24 (value);
11690 value = (value << 2) | hbit;
11691 #ifdef OBJ_ELF
11692 fixP->fx_offset = value;
11693 #endif
11694 fixP->fx_addnumber = value;
11695 newval = newval & 0xfe000000;
11696 }
11697 else
11698 newval = value | (newval & 0xfe000000) | (hbit << 24);
11699 md_number_to_chars (buf, newval, INSN_SIZE);
11700 }
11701 break;
11702
11703 case BFD_RELOC_THUMB_PCREL_BRANCH9: /* Conditional branch. */
11704 newval = md_chars_to_number (buf, THUMB_SIZE);
11705 {
11706 addressT diff = (newval & 0xff) << 1;
11707 if (diff & 0x100)
11708 diff |= ~0xff;
11709
11710 value += diff;
11711 if ((value & ~0xff) && ((value & ~0xff) != ~0xff))
11712 as_bad_where (fixP->fx_file, fixP->fx_line,
11713 _("branch out of range"));
11714 if (seg->use_rela_p && !fixP->fx_done)
11715 {
11716 #ifdef OBJ_ELF
11717 fixP->fx_offset = value;
11718 #endif
11719 fixP->fx_addnumber = value;
11720 newval = newval & 0xff00;
11721 }
11722 else
11723 newval = (newval & 0xff00) | ((value & 0x1ff) >> 1);
11724 }
11725 md_number_to_chars (buf, newval, THUMB_SIZE);
11726 break;
11727
11728 case BFD_RELOC_THUMB_PCREL_BRANCH12: /* Unconditional branch. */
11729 newval = md_chars_to_number (buf, THUMB_SIZE);
11730 {
11731 addressT diff = (newval & 0x7ff) << 1;
11732 if (diff & 0x800)
11733 diff |= ~0x7ff;
11734
11735 value += diff;
11736 if ((value & ~0x7ff) && ((value & ~0x7ff) != ~0x7ff))
11737 as_bad_where (fixP->fx_file, fixP->fx_line,
11738 _("branch out of range"));
11739 if (seg->use_rela_p && !fixP->fx_done)
11740 {
11741 #ifdef OBJ_ELF
11742 fixP->fx_offset = value;
11743 #endif
11744 fixP->fx_addnumber = value;
11745 newval = newval & 0xf800;
11746 }
11747 else
11748 newval = (newval & 0xf800) | ((value & 0xfff) >> 1);
11749 }
11750 md_number_to_chars (buf, newval, THUMB_SIZE);
11751 break;
11752
11753 case BFD_RELOC_THUMB_PCREL_BLX:
11754 case BFD_RELOC_THUMB_PCREL_BRANCH23:
11755 {
11756 offsetT newval2;
11757 addressT diff;
11758
11759 newval = md_chars_to_number (buf, THUMB_SIZE);
11760 newval2 = md_chars_to_number (buf + THUMB_SIZE, THUMB_SIZE);
11761 diff = ((newval & 0x7ff) << 12) | ((newval2 & 0x7ff) << 1);
11762 if (diff & 0x400000)
11763 diff |= ~0x3fffff;
11764 #ifdef OBJ_ELF
11765 value = fixP->fx_offset;
11766 #endif
11767 value += diff;
11768
11769 if ((value & ~0x3fffff) && ((value & ~0x3fffff) != ~0x3fffff))
11770 as_bad_where (fixP->fx_file, fixP->fx_line,
11771 _("branch with link out of range"));
11772
11773 if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX)
11774 /* For a BLX instruction, make sure that the relocation is rounded up
11775 to a word boundary. This follows the semantics of the instruction
11776 which specifies that bit 1 of the target address will come from bit
11777 1 of the base address. */
11778 value = (value + 1) & ~ 1;
11779
11780 if (seg->use_rela_p && !fixP->fx_done)
11781 {
11782 #ifdef OBJ_ELF
11783 fixP->fx_offset = value;
11784 #endif
11785 fixP->fx_addnumber = value;
11786 newval = newval & 0xf800;
11787 newval2 = newval2 & 0xf800;
11788 }
11789 else
11790 {
11791 newval = (newval & 0xf800) | ((value & 0x7fffff) >> 12);
11792 newval2 = (newval2 & 0xf800) | ((value & 0xfff) >> 1);
11793 }
11794 md_number_to_chars (buf, newval, THUMB_SIZE);
11795 md_number_to_chars (buf + THUMB_SIZE, newval2, THUMB_SIZE);
11796 }
11797 break;
11798
11799 case BFD_RELOC_8:
11800 if (seg->use_rela_p && !fixP->fx_done)
11801 break;
11802 if (fixP->fx_done || fixP->fx_pcrel)
11803 md_number_to_chars (buf, value, 1);
11804 #ifdef OBJ_ELF
11805 else
11806 {
11807 value = fixP->fx_offset;
11808 md_number_to_chars (buf, value, 1);
11809 }
11810 #endif
11811 break;
11812
11813 case BFD_RELOC_16:
11814 if (seg->use_rela_p && !fixP->fx_done)
11815 break;
11816 if (fixP->fx_done || fixP->fx_pcrel)
11817 md_number_to_chars (buf, value, 2);
11818 #ifdef OBJ_ELF
11819 else
11820 {
11821 value = fixP->fx_offset;
11822 md_number_to_chars (buf, value, 2);
11823 }
11824 #endif
11825 break;
11826
11827 #ifdef OBJ_ELF
11828 case BFD_RELOC_ARM_GOT32:
11829 case BFD_RELOC_ARM_GOTOFF:
11830 case BFD_RELOC_ARM_TARGET2:
11831 if (seg->use_rela_p && !fixP->fx_done)
11832 break;
11833 md_number_to_chars (buf, 0, 4);
11834 break;
11835 #endif
11836
11837 case BFD_RELOC_RVA:
11838 case BFD_RELOC_32:
11839 case BFD_RELOC_ARM_TARGET1:
11840 case BFD_RELOC_ARM_ROSEGREL32:
11841 case BFD_RELOC_ARM_SBREL32:
11842 case BFD_RELOC_32_PCREL:
11843 if (seg->use_rela_p && !fixP->fx_done)
11844 break;
11845 if (fixP->fx_done || fixP->fx_pcrel)
11846 md_number_to_chars (buf, value, 4);
11847 #ifdef OBJ_ELF
11848 else
11849 {
11850 value = fixP->fx_offset;
11851 md_number_to_chars (buf, value, 4);
11852 }
11853 #endif
11854 break;
11855
11856 #ifdef OBJ_ELF
11857 case BFD_RELOC_ARM_PREL31:
11858 if (fixP->fx_done || fixP->fx_pcrel)
11859 {
11860 newval = md_chars_to_number (buf, 4) & 0x80000000;
11861 if ((value ^ (value >> 1)) & 0x40000000)
11862 {
11863 as_bad_where (fixP->fx_file, fixP->fx_line,
11864 _("rel31 relocation overflow"));
11865 }
11866 newval |= value & 0x7fffffff;
11867 md_number_to_chars (buf, newval, 4);
11868 }
11869 break;
11870
11871 case BFD_RELOC_ARM_PLT32:
11872 /* It appears the instruction is fully prepared at this point. */
11873 break;
11874 #endif
11875
11876 case BFD_RELOC_ARM_CP_OFF_IMM:
11877 sign = value >= 0;
11878 if (value < -1023 || value > 1023 || (value & 3))
11879 as_bad_where (fixP->fx_file, fixP->fx_line,
11880 _("illegal value for co-processor offset"));
11881 if (value < 0)
11882 value = -value;
11883 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
11884 newval |= (value >> 2) | (sign ? INDEX_UP : 0);
11885 md_number_to_chars (buf, newval, INSN_SIZE);
11886 break;
11887
11888 case BFD_RELOC_ARM_CP_OFF_IMM_S2:
11889 sign = value >= 0;
11890 if (value < -255 || value > 255)
11891 as_bad_where (fixP->fx_file, fixP->fx_line,
11892 _("Illegal value for co-processor offset"));
11893 if (value < 0)
11894 value = -value;
11895 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
11896 newval |= value | (sign ? INDEX_UP : 0);
11897 md_number_to_chars (buf, newval , INSN_SIZE);
11898 break;
11899
11900 case BFD_RELOC_ARM_THUMB_OFFSET:
11901 newval = md_chars_to_number (buf, THUMB_SIZE);
11902 /* Exactly what ranges, and where the offset is inserted depends
11903 on the type of instruction, we can establish this from the
11904 top 4 bits. */
11905 switch (newval >> 12)
11906 {
11907 case 4: /* PC load. */
11908 /* Thumb PC loads are somewhat odd, bit 1 of the PC is
11909 forced to zero for these loads, so we will need to round
11910 up the offset if the instruction address is not word
11911 aligned (since the final address produced must be, and
11912 we can only describe word-aligned immediate offsets). */
11913
11914 if ((fixP->fx_frag->fr_address + fixP->fx_where + value) & 3)
11915 as_bad_where (fixP->fx_file, fixP->fx_line,
11916 _("invalid offset, target not word aligned (0x%08X)"),
11917 (unsigned int) (fixP->fx_frag->fr_address
11918 + fixP->fx_where + value));
11919
11920 if ((value + 2) & ~0x3fe)
11921 as_bad_where (fixP->fx_file, fixP->fx_line,
11922 _("invalid offset, value too big (0x%08lX)"),
11923 (long) value);
11924
11925 /* Round up, since pc will be rounded down. */
11926 newval |= (value + 2) >> 2;
11927 break;
11928
11929 case 9: /* SP load/store. */
11930 if (value & ~0x3fc)
11931 as_bad_where (fixP->fx_file, fixP->fx_line,
11932 _("invalid offset, value too big (0x%08lX)"),
11933 (long) value);
11934 newval |= value >> 2;
11935 break;
11936
11937 case 6: /* Word load/store. */
11938 if (value & ~0x7c)
11939 as_bad_where (fixP->fx_file, fixP->fx_line,
11940 _("invalid offset, value too big (0x%08lX)"),
11941 (long) value);
11942 newval |= value << 4; /* 6 - 2. */
11943 break;
11944
11945 case 7: /* Byte load/store. */
11946 if (value & ~0x1f)
11947 as_bad_where (fixP->fx_file, fixP->fx_line,
11948 _("invalid offset, value too big (0x%08lX)"),
11949 (long) value);
11950 newval |= value << 6;
11951 break;
11952
11953 case 8: /* Halfword load/store. */
11954 if (value & ~0x3e)
11955 as_bad_where (fixP->fx_file, fixP->fx_line,
11956 _("invalid offset, value too big (0x%08lX)"),
11957 (long) value);
11958 newval |= value << 5; /* 6 - 1. */
11959 break;
11960
11961 default:
11962 as_bad_where (fixP->fx_file, fixP->fx_line,
11963 "Unable to process relocation for thumb opcode: %lx",
11964 (unsigned long) newval);
11965 break;
11966 }
11967 md_number_to_chars (buf, newval, THUMB_SIZE);
11968 break;
11969
11970 case BFD_RELOC_ARM_THUMB_ADD:
11971 /* This is a complicated relocation, since we use it for all of
11972 the following immediate relocations:
11973
11974 3bit ADD/SUB
11975 8bit ADD/SUB
11976 9bit ADD/SUB SP word-aligned
11977 10bit ADD PC/SP word-aligned
11978
11979 The type of instruction being processed is encoded in the
11980 instruction field:
11981
11982 0x8000 SUB
11983 0x00F0 Rd
11984 0x000F Rs
11985 */
11986 newval = md_chars_to_number (buf, THUMB_SIZE);
11987 {
11988 int rd = (newval >> 4) & 0xf;
11989 int rs = newval & 0xf;
11990 int subtract = newval & 0x8000;
11991
11992 if (rd == REG_SP)
11993 {
11994 if (value & ~0x1fc)
11995 as_bad_where (fixP->fx_file, fixP->fx_line,
11996 _("invalid immediate for stack address calculation"));
11997 newval = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
11998 newval |= value >> 2;
11999 }
12000 else if (rs == REG_PC || rs == REG_SP)
12001 {
12002 if (subtract ||
12003 value & ~0x3fc)
12004 as_bad_where (fixP->fx_file, fixP->fx_line,
12005 _("invalid immediate for address calculation (value = 0x%08lX)"),
12006 (unsigned long) value);
12007 newval = (rs == REG_PC ? T_OPCODE_ADD_PC : T_OPCODE_ADD_SP);
12008 newval |= rd << 8;
12009 newval |= value >> 2;
12010 }
12011 else if (rs == rd)
12012 {
12013 if (value & ~0xff)
12014 as_bad_where (fixP->fx_file, fixP->fx_line,
12015 _("invalid 8bit immediate"));
12016 newval = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
12017 newval |= (rd << 8) | value;
12018 }
12019 else
12020 {
12021 if (value & ~0x7)
12022 as_bad_where (fixP->fx_file, fixP->fx_line,
12023 _("invalid 3bit immediate"));
12024 newval = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
12025 newval |= rd | (rs << 3) | (value << 6);
12026 }
12027 }
12028 md_number_to_chars (buf, newval, THUMB_SIZE);
12029 break;
12030
12031 case BFD_RELOC_ARM_THUMB_IMM:
12032 newval = md_chars_to_number (buf, THUMB_SIZE);
12033 switch (newval >> 11)
12034 {
12035 case 0x04: /* 8bit immediate MOV. */
12036 case 0x05: /* 8bit immediate CMP. */
12037 if (value < 0 || value > 255)
12038 as_bad_where (fixP->fx_file, fixP->fx_line,
12039 _("invalid immediate: %ld is too large"),
12040 (long) value);
12041 newval |= value;
12042 break;
12043
12044 default:
12045 abort ();
12046 }
12047 md_number_to_chars (buf, newval, THUMB_SIZE);
12048 break;
12049
12050 case BFD_RELOC_ARM_THUMB_SHIFT:
12051 /* 5bit shift value (0..31). */
12052 if (value < 0 || value > 31)
12053 as_bad_where (fixP->fx_file, fixP->fx_line,
12054 _("illegal Thumb shift value: %ld"), (long) value);
12055 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xf03f;
12056 newval |= value << 6;
12057 md_number_to_chars (buf, newval, THUMB_SIZE);
12058 break;
12059
12060 case BFD_RELOC_VTABLE_INHERIT:
12061 case BFD_RELOC_VTABLE_ENTRY:
12062 fixP->fx_done = 0;
12063 return;
12064
12065 case BFD_RELOC_UNUSED:
12066 default:
12067 as_bad_where (fixP->fx_file, fixP->fx_line,
12068 _("bad relocation fixup type (%d)"), fixP->fx_r_type);
12069 }
12070 }
12071
12072 /* Translate internal representation of relocation info to BFD target
12073 format. */
12074
12075 arelent *
12076 tc_gen_reloc (asection * section ATTRIBUTE_UNUSED,
12077 fixS * fixp)
12078 {
12079 arelent * reloc;
12080 bfd_reloc_code_real_type code;
12081
12082 reloc = xmalloc (sizeof (arelent));
12083
12084 reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
12085 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
12086 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
12087
12088 /* @@ Why fx_addnumber sometimes and fx_offset other times? */
12089 #ifndef OBJ_ELF
12090 if (fixp->fx_pcrel == 0)
12091 reloc->addend = fixp->fx_offset;
12092 else
12093 reloc->addend = fixp->fx_offset = reloc->address;
12094 #else /* OBJ_ELF */
12095 reloc->addend = fixp->fx_offset;
12096 #endif
12097
12098 switch (fixp->fx_r_type)
12099 {
12100 case BFD_RELOC_8:
12101 if (fixp->fx_pcrel)
12102 {
12103 code = BFD_RELOC_8_PCREL;
12104 break;
12105 }
12106
12107 case BFD_RELOC_16:
12108 if (fixp->fx_pcrel)
12109 {
12110 code = BFD_RELOC_16_PCREL;
12111 break;
12112 }
12113
12114 case BFD_RELOC_32:
12115 if (fixp->fx_pcrel)
12116 {
12117 code = BFD_RELOC_32_PCREL;
12118 break;
12119 }
12120
12121 case BFD_RELOC_NONE:
12122 case BFD_RELOC_ARM_PCREL_BRANCH:
12123 case BFD_RELOC_ARM_PCREL_BLX:
12124 case BFD_RELOC_RVA:
12125 case BFD_RELOC_THUMB_PCREL_BRANCH9:
12126 case BFD_RELOC_THUMB_PCREL_BRANCH12:
12127 case BFD_RELOC_THUMB_PCREL_BRANCH23:
12128 case BFD_RELOC_THUMB_PCREL_BLX:
12129 case BFD_RELOC_VTABLE_ENTRY:
12130 case BFD_RELOC_VTABLE_INHERIT:
12131 code = fixp->fx_r_type;
12132 break;
12133
12134 case BFD_RELOC_ARM_LITERAL:
12135 case BFD_RELOC_ARM_HWLITERAL:
12136 /* If this is called then the a literal has
12137 been referenced across a section boundary. */
12138 as_bad_where (fixp->fx_file, fixp->fx_line,
12139 _("literal referenced across section boundary"));
12140 return NULL;
12141
12142 #ifdef OBJ_ELF
12143 case BFD_RELOC_ARM_GOT32:
12144 case BFD_RELOC_ARM_GOTOFF:
12145 case BFD_RELOC_ARM_PLT32:
12146 case BFD_RELOC_ARM_TARGET1:
12147 case BFD_RELOC_ARM_ROSEGREL32:
12148 case BFD_RELOC_ARM_SBREL32:
12149 case BFD_RELOC_ARM_PREL31:
12150 case BFD_RELOC_ARM_TARGET2:
12151 code = fixp->fx_r_type;
12152 break;
12153 #endif
12154
12155 case BFD_RELOC_ARM_IMMEDIATE:
12156 as_bad_where (fixp->fx_file, fixp->fx_line,
12157 _("internal relocation (type: IMMEDIATE) not fixed up"));
12158 return NULL;
12159
12160 case BFD_RELOC_ARM_ADRL_IMMEDIATE:
12161 as_bad_where (fixp->fx_file, fixp->fx_line,
12162 _("ADRL used for a symbol not defined in the same file"));
12163 return NULL;
12164
12165 case BFD_RELOC_ARM_OFFSET_IMM:
12166 if (fixp->fx_addsy != NULL
12167 && !S_IS_DEFINED (fixp->fx_addsy)
12168 && S_IS_LOCAL (fixp->fx_addsy))
12169 {
12170 as_bad_where (fixp->fx_file, fixp->fx_line,
12171 _("undefined local label `%s'"),
12172 S_GET_NAME (fixp->fx_addsy));
12173 return NULL;
12174 }
12175
12176 as_bad_where (fixp->fx_file, fixp->fx_line,
12177 _("internal_relocation (type: OFFSET_IMM) not fixed up"));
12178 return NULL;
12179
12180 default:
12181 {
12182 char * type;
12183
12184 switch (fixp->fx_r_type)
12185 {
12186 case BFD_RELOC_NONE: type = "NONE"; break;
12187 case BFD_RELOC_ARM_OFFSET_IMM8: type = "OFFSET_IMM8"; break;
12188 case BFD_RELOC_ARM_SHIFT_IMM: type = "SHIFT_IMM"; break;
12189 case BFD_RELOC_ARM_SMI: type = "SMI"; break;
12190 case BFD_RELOC_ARM_SWI: type = "SWI"; break;
12191 case BFD_RELOC_ARM_MULTI: type = "MULTI"; break;
12192 case BFD_RELOC_ARM_CP_OFF_IMM: type = "CP_OFF_IMM"; break;
12193 case BFD_RELOC_ARM_THUMB_ADD: type = "THUMB_ADD"; break;
12194 case BFD_RELOC_ARM_THUMB_SHIFT: type = "THUMB_SHIFT"; break;
12195 case BFD_RELOC_ARM_THUMB_IMM: type = "THUMB_IMM"; break;
12196 case BFD_RELOC_ARM_THUMB_OFFSET: type = "THUMB_OFFSET"; break;
12197 default: type = _("<unknown>"); break;
12198 }
12199 as_bad_where (fixp->fx_file, fixp->fx_line,
12200 _("cannot represent %s relocation in this object file format"),
12201 type);
12202 return NULL;
12203 }
12204 }
12205
12206 #ifdef OBJ_ELF
12207 if ((code == BFD_RELOC_32_PCREL || code == BFD_RELOC_32)
12208 && GOT_symbol
12209 && fixp->fx_addsy == GOT_symbol)
12210 {
12211 code = BFD_RELOC_ARM_GOTPC;
12212 reloc->addend = fixp->fx_offset = reloc->address;
12213 }
12214 #endif
12215
12216 reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
12217
12218 if (reloc->howto == NULL)
12219 {
12220 as_bad_where (fixp->fx_file, fixp->fx_line,
12221 _("cannot represent %s relocation in this object file format"),
12222 bfd_get_reloc_code_name (code));
12223 return NULL;
12224 }
12225
12226 /* HACK: Since arm ELF uses Rel instead of Rela, encode the
12227 vtable entry to be used in the relocation's section offset. */
12228 if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
12229 reloc->address = fixp->fx_offset;
12230
12231 return reloc;
12232 }
12233
12234 int
12235 md_estimate_size_before_relax (fragS * fragP ATTRIBUTE_UNUSED,
12236 segT segtype ATTRIBUTE_UNUSED)
12237 {
12238 as_fatal (_("md_estimate_size_before_relax\n"));
12239 return 1;
12240 }
12241
12242 /* We need to be able to fix up arbitrary expressions in some statements.
12243 This is so that we can handle symbols that are an arbitrary distance from
12244 the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
12245 which returns part of an address in a form which will be valid for
12246 a data instruction. We do this by pushing the expression into a symbol
12247 in the expr_section, and creating a fix for that. */
12248
12249 static void
12250 fix_new_arm (fragS * frag,
12251 int where,
12252 short int size,
12253 expressionS * exp,
12254 int pc_rel,
12255 int reloc)
12256 {
12257 fixS * new_fix;
12258 arm_fix_data * arm_data;
12259
12260 switch (exp->X_op)
12261 {
12262 case O_constant:
12263 case O_symbol:
12264 case O_add:
12265 case O_subtract:
12266 new_fix = fix_new_exp (frag, where, size, exp, pc_rel, reloc);
12267 break;
12268
12269 default:
12270 new_fix = fix_new (frag, where, size, make_expr_symbol (exp), 0,
12271 pc_rel, reloc);
12272 break;
12273 }
12274
12275 /* Mark whether the fix is to a THUMB instruction, or an ARM
12276 instruction. */
12277 arm_data = obstack_alloc (& notes, sizeof (arm_fix_data));
12278 new_fix->tc_fix_data = (PTR) arm_data;
12279 arm_data->thumb_mode = thumb_mode;
12280 }
12281
12282 static void
12283 output_inst (const char * str)
12284 {
12285 char * to = NULL;
12286
12287 if (inst.error)
12288 {
12289 as_bad ("%s -- `%s'", inst.error, str);
12290 return;
12291 }
12292
12293 to = frag_more (inst.size);
12294
12295 if (thumb_mode && (inst.size > THUMB_SIZE))
12296 {
12297 assert (inst.size == (2 * THUMB_SIZE));
12298 md_number_to_chars (to, inst.instruction >> 16, THUMB_SIZE);
12299 md_number_to_chars (to + THUMB_SIZE, inst.instruction, THUMB_SIZE);
12300 }
12301 else if (inst.size > INSN_SIZE)
12302 {
12303 assert (inst.size == (2 * INSN_SIZE));
12304 md_number_to_chars (to, inst.instruction, INSN_SIZE);
12305 md_number_to_chars (to + INSN_SIZE, inst.instruction, INSN_SIZE);
12306 }
12307 else
12308 md_number_to_chars (to, inst.instruction, inst.size);
12309
12310 if (inst.reloc.type != BFD_RELOC_UNUSED)
12311 fix_new_arm (frag_now, to - frag_now->fr_literal,
12312 inst.size, & inst.reloc.exp, inst.reloc.pc_rel,
12313 inst.reloc.type);
12314
12315 #ifdef OBJ_ELF
12316 dwarf2_emit_insn (inst.size);
12317 #endif
12318 }
12319
12320 void
12321 md_assemble (char * str)
12322 {
12323 char c;
12324 char *p;
12325 char *start;
12326
12327 /* Align the previous label if needed. */
12328 if (last_label_seen != NULL)
12329 {
12330 symbol_set_frag (last_label_seen, frag_now);
12331 S_SET_VALUE (last_label_seen, (valueT) frag_now_fix ());
12332 S_SET_SEGMENT (last_label_seen, now_seg);
12333 }
12334
12335 memset (&inst, '\0', sizeof (inst));
12336 inst.reloc.type = BFD_RELOC_UNUSED;
12337
12338 skip_whitespace (str);
12339
12340 /* Scan up to the end of the op-code, which must end in white space or
12341 end of string. */
12342 for (start = p = str; *p != '\0'; p++)
12343 if (*p == ' ')
12344 break;
12345
12346 if (p == str)
12347 {
12348 as_bad (_("no operator -- statement `%s'\n"), str);
12349 return;
12350 }
12351
12352 if (thumb_mode)
12353 {
12354 const struct thumb_opcode * opcode;
12355
12356 c = *p;
12357 *p = '\0';
12358 opcode = (const struct thumb_opcode *) hash_find (arm_tops_hsh, str);
12359 *p = c;
12360
12361 if (opcode)
12362 {
12363 /* Check that this instruction is supported for this CPU. */
12364 if (thumb_mode == 1 && (opcode->variant & cpu_variant) == 0)
12365 {
12366 as_bad (_("selected processor does not support `%s'"), str);
12367 return;
12368 }
12369
12370 mapping_state (MAP_THUMB);
12371 inst.instruction = opcode->value;
12372 inst.size = opcode->size;
12373 opcode->parms (p);
12374 output_inst (str);
12375 return;
12376 }
12377 }
12378 else
12379 {
12380 const struct asm_opcode * opcode;
12381
12382 c = *p;
12383 *p = '\0';
12384 opcode = (const struct asm_opcode *) hash_find (arm_ops_hsh, str);
12385 *p = c;
12386
12387 if (opcode)
12388 {
12389 /* Check that this instruction is supported for this CPU. */
12390 if ((opcode->variant & cpu_variant) == 0)
12391 {
12392 as_bad (_("selected processor does not support `%s'"), str);
12393 return;
12394 }
12395
12396 mapping_state (MAP_ARM);
12397 inst.instruction = opcode->value;
12398 inst.size = INSN_SIZE;
12399 opcode->parms (p);
12400 output_inst (str);
12401 return;
12402 }
12403 }
12404
12405 /* It wasn't an instruction, but it might be a register alias of the form
12406 alias .req reg. */
12407 if (create_register_alias (str, p))
12408 return;
12409
12410 as_bad (_("bad instruction `%s'"), start);
12411 }
12412
12413 /* md_parse_option
12414 Invocation line includes a switch not recognized by the base assembler.
12415 See if it's a processor-specific option.
12416
12417 This routine is somewhat complicated by the need for backwards
12418 compatibility (since older releases of gcc can't be changed).
12419 The new options try to make the interface as compatible as
12420 possible with GCC.
12421
12422 New options (supported) are:
12423
12424 -mcpu=<cpu name> Assemble for selected processor
12425 -march=<architecture name> Assemble for selected architecture
12426 -mfpu=<fpu architecture> Assemble for selected FPU.
12427 -EB/-mbig-endian Big-endian
12428 -EL/-mlittle-endian Little-endian
12429 -k Generate PIC code
12430 -mthumb Start in Thumb mode
12431 -mthumb-interwork Code supports ARM/Thumb interworking
12432
12433 For now we will also provide support for:
12434
12435 -mapcs-32 32-bit Program counter
12436 -mapcs-26 26-bit Program counter
12437 -macps-float Floats passed in FP registers
12438 -mapcs-reentrant Reentrant code
12439 -matpcs
12440 (sometime these will probably be replaced with -mapcs=<list of options>
12441 and -matpcs=<list of options>)
12442
12443 The remaining options are only supported for back-wards compatibility.
12444 Cpu variants, the arm part is optional:
12445 -m[arm]1 Currently not supported.
12446 -m[arm]2, -m[arm]250 Arm 2 and Arm 250 processor
12447 -m[arm]3 Arm 3 processor
12448 -m[arm]6[xx], Arm 6 processors
12449 -m[arm]7[xx][t][[d]m] Arm 7 processors
12450 -m[arm]8[10] Arm 8 processors
12451 -m[arm]9[20][tdmi] Arm 9 processors
12452 -mstrongarm[110[0]] StrongARM processors
12453 -mxscale XScale processors
12454 -m[arm]v[2345[t[e]]] Arm architectures
12455 -mall All (except the ARM1)
12456 FP variants:
12457 -mfpa10, -mfpa11 FPA10 and 11 co-processor instructions
12458 -mfpe-old (No float load/store multiples)
12459 -mvfpxd VFP Single precision
12460 -mvfp All VFP
12461 -mno-fpu Disable all floating point instructions
12462
12463 The following CPU names are recognized:
12464 arm1, arm2, arm250, arm3, arm6, arm600, arm610, arm620,
12465 arm7, arm7m, arm7d, arm7dm, arm7di, arm7dmi, arm70, arm700,
12466 arm700i, arm710 arm710t, arm720, arm720t, arm740t, arm710c,
12467 arm7100, arm7500, arm7500fe, arm7tdmi, arm8, arm810, arm9,
12468 arm920, arm920t, arm940t, arm946, arm966, arm9tdmi, arm9e,
12469 arm10t arm10e, arm1020t, arm1020e, arm10200e,
12470 strongarm, strongarm110, strongarm1100, strongarm1110, xscale.
12471
12472 */
12473
12474 const char * md_shortopts = "m:k";
12475
12476 #ifdef ARM_BI_ENDIAN
12477 #define OPTION_EB (OPTION_MD_BASE + 0)
12478 #define OPTION_EL (OPTION_MD_BASE + 1)
12479 #else
12480 #if TARGET_BYTES_BIG_ENDIAN
12481 #define OPTION_EB (OPTION_MD_BASE + 0)
12482 #else
12483 #define OPTION_EL (OPTION_MD_BASE + 1)
12484 #endif
12485 #endif
12486
12487 struct option md_longopts[] =
12488 {
12489 #ifdef OPTION_EB
12490 {"EB", no_argument, NULL, OPTION_EB},
12491 #endif
12492 #ifdef OPTION_EL
12493 {"EL", no_argument, NULL, OPTION_EL},
12494 #endif
12495 {NULL, no_argument, NULL, 0}
12496 };
12497
12498 size_t md_longopts_size = sizeof (md_longopts);
12499
12500 struct arm_option_table
12501 {
12502 char *option; /* Option name to match. */
12503 char *help; /* Help information. */
12504 int *var; /* Variable to change. */
12505 int value; /* What to change it to. */
12506 char *deprecated; /* If non-null, print this message. */
12507 };
12508
12509 struct arm_option_table arm_opts[] =
12510 {
12511 {"k", N_("generate PIC code"), &pic_code, 1, NULL},
12512 {"mthumb", N_("assemble Thumb code"), &thumb_mode, 1, NULL},
12513 {"mthumb-interwork", N_("support ARM/Thumb interworking"),
12514 &support_interwork, 1, NULL},
12515 {"mapcs-32", N_("code uses 32-bit program counter"), &uses_apcs_26, 0, NULL},
12516 {"mapcs-26", N_("code uses 26-bit program counter"), &uses_apcs_26, 1, NULL},
12517 {"mapcs-float", N_("floating point args are in fp regs"), &uses_apcs_float,
12518 1, NULL},
12519 {"mapcs-reentrant", N_("re-entrant code"), &pic_code, 1, NULL},
12520 {"matpcs", N_("code is ATPCS conformant"), &atpcs, 1, NULL},
12521 {"mbig-endian", N_("assemble for big-endian"), &target_big_endian, 1, NULL},
12522 {"mlittle-endian", N_("assemble for little-endian"), &target_big_endian, 1,
12523 NULL},
12524
12525 /* These are recognized by the assembler, but have no affect on code. */
12526 {"mapcs-frame", N_("use frame pointer"), NULL, 0, NULL},
12527 {"mapcs-stack-check", N_("use stack size checking"), NULL, 0, NULL},
12528
12529 /* DON'T add any new processors to this list -- we want the whole list
12530 to go away... Add them to the processors table instead. */
12531 {"marm1", NULL, &legacy_cpu, ARM_ARCH_V1, N_("use -mcpu=arm1")},
12532 {"m1", NULL, &legacy_cpu, ARM_ARCH_V1, N_("use -mcpu=arm1")},
12533 {"marm2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -mcpu=arm2")},
12534 {"m2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -mcpu=arm2")},
12535 {"marm250", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm250")},
12536 {"m250", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm250")},
12537 {"marm3", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm3")},
12538 {"m3", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm3")},
12539 {"marm6", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm6")},
12540 {"m6", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm6")},
12541 {"marm600", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm600")},
12542 {"m600", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm600")},
12543 {"marm610", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm610")},
12544 {"m610", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm610")},
12545 {"marm620", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm620")},
12546 {"m620", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm620")},
12547 {"marm7", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7")},
12548 {"m7", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7")},
12549 {"marm70", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm70")},
12550 {"m70", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm70")},
12551 {"marm700", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700")},
12552 {"m700", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700")},
12553 {"marm700i", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700i")},
12554 {"m700i", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700i")},
12555 {"marm710", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710")},
12556 {"m710", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710")},
12557 {"marm710c", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710c")},
12558 {"m710c", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710c")},
12559 {"marm720", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm720")},
12560 {"m720", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm720")},
12561 {"marm7d", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7d")},
12562 {"m7d", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7d")},
12563 {"marm7di", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7di")},
12564 {"m7di", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7di")},
12565 {"marm7m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7m")},
12566 {"m7m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7m")},
12567 {"marm7dm", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dm")},
12568 {"m7dm", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dm")},
12569 {"marm7dmi", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dmi")},
12570 {"m7dmi", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dmi")},
12571 {"marm7100", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7100")},
12572 {"m7100", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7100")},
12573 {"marm7500", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500")},
12574 {"m7500", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500")},
12575 {"marm7500fe", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500fe")},
12576 {"m7500fe", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500fe")},
12577 {"marm7t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
12578 {"m7t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
12579 {"marm7tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
12580 {"m7tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
12581 {"marm710t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm710t")},
12582 {"m710t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm710t")},
12583 {"marm720t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm720t")},
12584 {"m720t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm720t")},
12585 {"marm740t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm740t")},
12586 {"m740t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm740t")},
12587 {"marm8", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm8")},
12588 {"m8", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm8")},
12589 {"marm810", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm810")},
12590 {"m810", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm810")},
12591 {"marm9", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9")},
12592 {"m9", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9")},
12593 {"marm9tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9tdmi")},
12594 {"m9tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9tdmi")},
12595 {"marm920", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm920")},
12596 {"m920", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm920")},
12597 {"marm940", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm940")},
12598 {"m940", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm940")},
12599 {"mstrongarm", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=strongarm")},
12600 {"mstrongarm110", NULL, &legacy_cpu, ARM_ARCH_V4,
12601 N_("use -mcpu=strongarm110")},
12602 {"mstrongarm1100", NULL, &legacy_cpu, ARM_ARCH_V4,
12603 N_("use -mcpu=strongarm1100")},
12604 {"mstrongarm1110", NULL, &legacy_cpu, ARM_ARCH_V4,
12605 N_("use -mcpu=strongarm1110")},
12606 {"mxscale", NULL, &legacy_cpu, ARM_ARCH_XSCALE, N_("use -mcpu=xscale")},
12607 {"miwmmxt", NULL, &legacy_cpu, ARM_ARCH_IWMMXT, N_("use -mcpu=iwmmxt")},
12608 {"mall", NULL, &legacy_cpu, ARM_ANY, N_("use -mcpu=all")},
12609
12610 /* Architecture variants -- don't add any more to this list either. */
12611 {"mv2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -march=armv2")},
12612 {"marmv2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -march=armv2")},
12613 {"mv2a", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -march=armv2a")},
12614 {"marmv2a", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -march=armv2a")},
12615 {"mv3", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -march=armv3")},
12616 {"marmv3", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -march=armv3")},
12617 {"mv3m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -march=armv3m")},
12618 {"marmv3m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -march=armv3m")},
12619 {"mv4", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -march=armv4")},
12620 {"marmv4", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -march=armv4")},
12621 {"mv4t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -march=armv4t")},
12622 {"marmv4t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -march=armv4t")},
12623 {"mv5", NULL, &legacy_cpu, ARM_ARCH_V5, N_("use -march=armv5")},
12624 {"marmv5", NULL, &legacy_cpu, ARM_ARCH_V5, N_("use -march=armv5")},
12625 {"mv5t", NULL, &legacy_cpu, ARM_ARCH_V5T, N_("use -march=armv5t")},
12626 {"marmv5t", NULL, &legacy_cpu, ARM_ARCH_V5T, N_("use -march=armv5t")},
12627 {"mv5e", NULL, &legacy_cpu, ARM_ARCH_V5TE, N_("use -march=armv5te")},
12628 {"marmv5e", NULL, &legacy_cpu, ARM_ARCH_V5TE, N_("use -march=armv5te")},
12629
12630 /* Floating point variants -- don't add any more to this list either. */
12631 {"mfpe-old", NULL, &legacy_fpu, FPU_ARCH_FPE, N_("use -mfpu=fpe")},
12632 {"mfpa10", NULL, &legacy_fpu, FPU_ARCH_FPA, N_("use -mfpu=fpa10")},
12633 {"mfpa11", NULL, &legacy_fpu, FPU_ARCH_FPA, N_("use -mfpu=fpa11")},
12634 {"mno-fpu", NULL, &legacy_fpu, 0,
12635 N_("use either -mfpu=softfpa or -mfpu=softvfp")},
12636
12637 {NULL, NULL, NULL, 0, NULL}
12638 };
12639
12640 struct arm_cpu_option_table
12641 {
12642 char *name;
12643 int value;
12644 /* For some CPUs we assume an FPU unless the user explicitly sets
12645 -mfpu=... */
12646 int default_fpu;
12647 };
12648
12649 /* This list should, at a minimum, contain all the cpu names
12650 recognized by GCC. */
12651 static struct arm_cpu_option_table arm_cpus[] =
12652 {
12653 {"all", ARM_ANY, FPU_ARCH_FPA},
12654 {"arm1", ARM_ARCH_V1, FPU_ARCH_FPA},
12655 {"arm2", ARM_ARCH_V2, FPU_ARCH_FPA},
12656 {"arm250", ARM_ARCH_V2S, FPU_ARCH_FPA},
12657 {"arm3", ARM_ARCH_V2S, FPU_ARCH_FPA},
12658 {"arm6", ARM_ARCH_V3, FPU_ARCH_FPA},
12659 {"arm60", ARM_ARCH_V3, FPU_ARCH_FPA},
12660 {"arm600", ARM_ARCH_V3, FPU_ARCH_FPA},
12661 {"arm610", ARM_ARCH_V3, FPU_ARCH_FPA},
12662 {"arm620", ARM_ARCH_V3, FPU_ARCH_FPA},
12663 {"arm7", ARM_ARCH_V3, FPU_ARCH_FPA},
12664 {"arm7m", ARM_ARCH_V3M, FPU_ARCH_FPA},
12665 {"arm7d", ARM_ARCH_V3, FPU_ARCH_FPA},
12666 {"arm7dm", ARM_ARCH_V3M, FPU_ARCH_FPA},
12667 {"arm7di", ARM_ARCH_V3, FPU_ARCH_FPA},
12668 {"arm7dmi", ARM_ARCH_V3M, FPU_ARCH_FPA},
12669 {"arm70", ARM_ARCH_V3, FPU_ARCH_FPA},
12670 {"arm700", ARM_ARCH_V3, FPU_ARCH_FPA},
12671 {"arm700i", ARM_ARCH_V3, FPU_ARCH_FPA},
12672 {"arm710", ARM_ARCH_V3, FPU_ARCH_FPA},
12673 {"arm710t", ARM_ARCH_V4T, FPU_ARCH_FPA},
12674 {"arm720", ARM_ARCH_V3, FPU_ARCH_FPA},
12675 {"arm720t", ARM_ARCH_V4T, FPU_ARCH_FPA},
12676 {"arm740t", ARM_ARCH_V4T, FPU_ARCH_FPA},
12677 {"arm710c", ARM_ARCH_V3, FPU_ARCH_FPA},
12678 {"arm7100", ARM_ARCH_V3, FPU_ARCH_FPA},
12679 {"arm7500", ARM_ARCH_V3, FPU_ARCH_FPA},
12680 {"arm7500fe", ARM_ARCH_V3, FPU_ARCH_FPA},
12681 {"arm7t", ARM_ARCH_V4T, FPU_ARCH_FPA},
12682 {"arm7tdmi", ARM_ARCH_V4T, FPU_ARCH_FPA},
12683 {"arm7tdmi-s", ARM_ARCH_V4T, FPU_ARCH_FPA},
12684 {"arm8", ARM_ARCH_V4, FPU_ARCH_FPA},
12685 {"arm810", ARM_ARCH_V4, FPU_ARCH_FPA},
12686 {"strongarm", ARM_ARCH_V4, FPU_ARCH_FPA},
12687 {"strongarm1", ARM_ARCH_V4, FPU_ARCH_FPA},
12688 {"strongarm110", ARM_ARCH_V4, FPU_ARCH_FPA},
12689 {"strongarm1100", ARM_ARCH_V4, FPU_ARCH_FPA},
12690 {"strongarm1110", ARM_ARCH_V4, FPU_ARCH_FPA},
12691 {"arm9", ARM_ARCH_V4T, FPU_ARCH_FPA},
12692 {"arm920", ARM_ARCH_V4T, FPU_ARCH_FPA},
12693 {"arm920t", ARM_ARCH_V4T, FPU_ARCH_FPA},
12694 {"arm922t", ARM_ARCH_V4T, FPU_ARCH_FPA},
12695 {"arm940t", ARM_ARCH_V4T, FPU_ARCH_FPA},
12696 {"arm9tdmi", ARM_ARCH_V4T, FPU_ARCH_FPA},
12697 /* For V5 or later processors we default to using VFP; but the user
12698 should really set the FPU type explicitly. */
12699 {"arm9e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
12700 {"arm9e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
12701 {"arm926ej", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
12702 {"arm926ejs", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
12703 {"arm926ej-s", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
12704 {"arm946e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
12705 {"arm946e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
12706 {"arm966e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
12707 {"arm966e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
12708 {"arm10t", ARM_ARCH_V5T, FPU_ARCH_VFP_V1},
12709 {"arm10e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
12710 {"arm1020", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
12711 {"arm1020t", ARM_ARCH_V5T, FPU_ARCH_VFP_V1},
12712 {"arm1020e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
12713 {"arm1026ejs", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
12714 {"arm1026ej-s", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
12715 {"arm1136js", ARM_ARCH_V6, FPU_NONE},
12716 {"arm1136j-s", ARM_ARCH_V6, FPU_NONE},
12717 {"arm1136jfs", ARM_ARCH_V6, FPU_ARCH_VFP_V2},
12718 {"arm1136jf-s", ARM_ARCH_V6, FPU_ARCH_VFP_V2},
12719 {"mpcore", ARM_ARCH_V6K, FPU_ARCH_VFP_V2},
12720 {"mpcorenovfp", ARM_ARCH_V6K, FPU_NONE},
12721 {"arm1176jz-s", ARM_ARCH_V6ZK, FPU_NONE},
12722 {"arm1176jzf-s", ARM_ARCH_V6ZK, FPU_ARCH_VFP_V2},
12723 /* ??? XSCALE is really an architecture. */
12724 {"xscale", ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2},
12725 /* ??? iwmmxt is not a processor. */
12726 {"iwmmxt", ARM_ARCH_IWMMXT, FPU_ARCH_VFP_V2},
12727 {"i80200", ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2},
12728 /* Maverick */
12729 {"ep9312", ARM_ARCH_V4T | ARM_CEXT_MAVERICK, FPU_ARCH_MAVERICK},
12730 {NULL, 0, 0}
12731 };
12732
12733 struct arm_arch_option_table
12734 {
12735 char *name;
12736 int value;
12737 int default_fpu;
12738 };
12739
12740 /* This list should, at a minimum, contain all the architecture names
12741 recognized by GCC. */
12742 static struct arm_arch_option_table arm_archs[] =
12743 {
12744 {"all", ARM_ANY, FPU_ARCH_FPA},
12745 {"armv1", ARM_ARCH_V1, FPU_ARCH_FPA},
12746 {"armv2", ARM_ARCH_V2, FPU_ARCH_FPA},
12747 {"armv2a", ARM_ARCH_V2S, FPU_ARCH_FPA},
12748 {"armv2s", ARM_ARCH_V2S, FPU_ARCH_FPA},
12749 {"armv3", ARM_ARCH_V3, FPU_ARCH_FPA},
12750 {"armv3m", ARM_ARCH_V3M, FPU_ARCH_FPA},
12751 {"armv4", ARM_ARCH_V4, FPU_ARCH_FPA},
12752 {"armv4xm", ARM_ARCH_V4xM, FPU_ARCH_FPA},
12753 {"armv4t", ARM_ARCH_V4T, FPU_ARCH_FPA},
12754 {"armv4txm", ARM_ARCH_V4TxM, FPU_ARCH_FPA},
12755 {"armv5", ARM_ARCH_V5, FPU_ARCH_VFP},
12756 {"armv5t", ARM_ARCH_V5T, FPU_ARCH_VFP},
12757 {"armv5txm", ARM_ARCH_V5TxM, FPU_ARCH_VFP},
12758 {"armv5te", ARM_ARCH_V5TE, FPU_ARCH_VFP},
12759 {"armv5texp", ARM_ARCH_V5TExP, FPU_ARCH_VFP},
12760 {"armv5tej", ARM_ARCH_V5TEJ, FPU_ARCH_VFP},
12761 {"armv6", ARM_ARCH_V6, FPU_ARCH_VFP},
12762 {"armv6j", ARM_ARCH_V6, FPU_ARCH_VFP},
12763 {"armv6k", ARM_ARCH_V6K, FPU_ARCH_VFP},
12764 {"armv6z", ARM_ARCH_V6Z, FPU_ARCH_VFP},
12765 {"armv6zk", ARM_ARCH_V6ZK, FPU_ARCH_VFP},
12766 {"xscale", ARM_ARCH_XSCALE, FPU_ARCH_VFP},
12767 {"iwmmxt", ARM_ARCH_IWMMXT, FPU_ARCH_VFP},
12768 {NULL, 0, 0}
12769 };
12770
12771 /* ISA extensions in the co-processor space. */
12772 struct arm_arch_extension_table
12773 {
12774 char *name;
12775 int value;
12776 };
12777
12778 static struct arm_arch_extension_table arm_extensions[] =
12779 {
12780 {"maverick", ARM_CEXT_MAVERICK},
12781 {"xscale", ARM_CEXT_XSCALE},
12782 {"iwmmxt", ARM_CEXT_IWMMXT},
12783 {NULL, 0}
12784 };
12785
12786 struct arm_fpu_option_table
12787 {
12788 char *name;
12789 int value;
12790 };
12791
12792 /* This list should, at a minimum, contain all the fpu names
12793 recognized by GCC. */
12794 static struct arm_fpu_option_table arm_fpus[] =
12795 {
12796 {"softfpa", FPU_NONE},
12797 {"fpe", FPU_ARCH_FPE},
12798 {"fpe2", FPU_ARCH_FPE},
12799 {"fpe3", FPU_ARCH_FPA}, /* Third release supports LFM/SFM. */
12800 {"fpa", FPU_ARCH_FPA},
12801 {"fpa10", FPU_ARCH_FPA},
12802 {"fpa11", FPU_ARCH_FPA},
12803 {"arm7500fe", FPU_ARCH_FPA},
12804 {"softvfp", FPU_ARCH_VFP},
12805 {"softvfp+vfp", FPU_ARCH_VFP_V2},
12806 {"vfp", FPU_ARCH_VFP_V2},
12807 {"vfp9", FPU_ARCH_VFP_V2},
12808 {"vfp10", FPU_ARCH_VFP_V2},
12809 {"vfp10-r0", FPU_ARCH_VFP_V1},
12810 {"vfpxd", FPU_ARCH_VFP_V1xD},
12811 {"arm1020t", FPU_ARCH_VFP_V1},
12812 {"arm1020e", FPU_ARCH_VFP_V2},
12813 {"arm1136jfs", FPU_ARCH_VFP_V2},
12814 {"arm1136jf-s", FPU_ARCH_VFP_V2},
12815 {"maverick", FPU_ARCH_MAVERICK},
12816 {NULL, 0}
12817 };
12818
12819 struct arm_float_abi_option_table
12820 {
12821 char *name;
12822 int value;
12823 };
12824
12825 static struct arm_float_abi_option_table arm_float_abis[] =
12826 {
12827 {"hard", ARM_FLOAT_ABI_HARD},
12828 {"softfp", ARM_FLOAT_ABI_SOFTFP},
12829 {"soft", ARM_FLOAT_ABI_SOFT},
12830 {NULL, 0}
12831 };
12832
12833 struct arm_eabi_option_table
12834 {
12835 char *name;
12836 unsigned int value;
12837 };
12838
12839 #ifdef OBJ_ELF
12840 /* We only know how to output GNU and ver 4 (AAELF) formats. */
12841 static struct arm_eabi_option_table arm_eabis[] =
12842 {
12843 {"gnu", EF_ARM_EABI_UNKNOWN},
12844 {"4", EF_ARM_EABI_VER4},
12845 {NULL, 0}
12846 };
12847 #endif
12848
12849 struct arm_long_option_table
12850 {
12851 char * option; /* Substring to match. */
12852 char * help; /* Help information. */
12853 int (* func) (char * subopt); /* Function to decode sub-option. */
12854 char * deprecated; /* If non-null, print this message. */
12855 };
12856
12857 static int
12858 arm_parse_extension (char * str, int * opt_p)
12859 {
12860 while (str != NULL && *str != 0)
12861 {
12862 struct arm_arch_extension_table * opt;
12863 char * ext;
12864 int optlen;
12865
12866 if (*str != '+')
12867 {
12868 as_bad (_("invalid architectural extension"));
12869 return 0;
12870 }
12871
12872 str++;
12873 ext = strchr (str, '+');
12874
12875 if (ext != NULL)
12876 optlen = ext - str;
12877 else
12878 optlen = strlen (str);
12879
12880 if (optlen == 0)
12881 {
12882 as_bad (_("missing architectural extension"));
12883 return 0;
12884 }
12885
12886 for (opt = arm_extensions; opt->name != NULL; opt++)
12887 if (strncmp (opt->name, str, optlen) == 0)
12888 {
12889 *opt_p |= opt->value;
12890 break;
12891 }
12892
12893 if (opt->name == NULL)
12894 {
12895 as_bad (_("unknown architectural extnsion `%s'"), str);
12896 return 0;
12897 }
12898
12899 str = ext;
12900 };
12901
12902 return 1;
12903 }
12904
12905 static int
12906 arm_parse_cpu (char * str)
12907 {
12908 struct arm_cpu_option_table * opt;
12909 char * ext = strchr (str, '+');
12910 int optlen;
12911
12912 if (ext != NULL)
12913 optlen = ext - str;
12914 else
12915 optlen = strlen (str);
12916
12917 if (optlen == 0)
12918 {
12919 as_bad (_("missing cpu name `%s'"), str);
12920 return 0;
12921 }
12922
12923 for (opt = arm_cpus; opt->name != NULL; opt++)
12924 if (strncmp (opt->name, str, optlen) == 0)
12925 {
12926 mcpu_cpu_opt = opt->value;
12927 mcpu_fpu_opt = opt->default_fpu;
12928
12929 if (ext != NULL)
12930 return arm_parse_extension (ext, &mcpu_cpu_opt);
12931
12932 return 1;
12933 }
12934
12935 as_bad (_("unknown cpu `%s'"), str);
12936 return 0;
12937 }
12938
12939 static int
12940 arm_parse_arch (char * str)
12941 {
12942 struct arm_arch_option_table *opt;
12943 char *ext = strchr (str, '+');
12944 int optlen;
12945
12946 if (ext != NULL)
12947 optlen = ext - str;
12948 else
12949 optlen = strlen (str);
12950
12951 if (optlen == 0)
12952 {
12953 as_bad (_("missing architecture name `%s'"), str);
12954 return 0;
12955 }
12956
12957
12958 for (opt = arm_archs; opt->name != NULL; opt++)
12959 if (streq (opt->name, str))
12960 {
12961 march_cpu_opt = opt->value;
12962 march_fpu_opt = opt->default_fpu;
12963
12964 if (ext != NULL)
12965 return arm_parse_extension (ext, &march_cpu_opt);
12966
12967 return 1;
12968 }
12969
12970 as_bad (_("unknown architecture `%s'\n"), str);
12971 return 0;
12972 }
12973
12974 static int
12975 arm_parse_fpu (char * str)
12976 {
12977 struct arm_fpu_option_table * opt;
12978
12979 for (opt = arm_fpus; opt->name != NULL; opt++)
12980 if (streq (opt->name, str))
12981 {
12982 mfpu_opt = opt->value;
12983 return 1;
12984 }
12985
12986 as_bad (_("unknown floating point format `%s'\n"), str);
12987 return 0;
12988 }
12989
12990 static int
12991 arm_parse_float_abi (char * str)
12992 {
12993 struct arm_float_abi_option_table * opt;
12994
12995 for (opt = arm_float_abis; opt->name != NULL; opt++)
12996 if (streq (opt->name, str))
12997 {
12998 mfloat_abi_opt = opt->value;
12999 return 1;
13000 }
13001
13002 as_bad (_("unknown floating point abi `%s'\n"), str);
13003 return 0;
13004 }
13005
13006 #ifdef OBJ_ELF
13007 static int
13008 arm_parse_eabi (char * str)
13009 {
13010 struct arm_eabi_option_table *opt;
13011
13012 for (opt = arm_eabis; opt->name != NULL; opt++)
13013 if (streq (opt->name, str))
13014 {
13015 meabi_flags = opt->value;
13016 return 1;
13017 }
13018 as_bad (_("unknown EABI `%s'\n"), str);
13019 return 0;
13020 }
13021 #endif
13022
13023 struct arm_long_option_table arm_long_opts[] =
13024 {
13025 {"mcpu=", N_("<cpu name>\t assemble for CPU <cpu name>"),
13026 arm_parse_cpu, NULL},
13027 {"march=", N_("<arch name>\t assemble for architecture <arch name>"),
13028 arm_parse_arch, NULL},
13029 {"mfpu=", N_("<fpu name>\t assemble for FPU architecture <fpu name>"),
13030 arm_parse_fpu, NULL},
13031 {"mfloat-abi=", N_("<abi>\t assemble for floating point ABI <abi>"),
13032 arm_parse_float_abi, NULL},
13033 #ifdef OBJ_ELF
13034 {"meabi=", N_("<ver>\t assemble for eabi version <ver>"),
13035 arm_parse_eabi, NULL},
13036 #endif
13037 {NULL, NULL, 0, NULL}
13038 };
13039
13040 int
13041 md_parse_option (int c, char * arg)
13042 {
13043 struct arm_option_table *opt;
13044 struct arm_long_option_table *lopt;
13045
13046 switch (c)
13047 {
13048 #ifdef OPTION_EB
13049 case OPTION_EB:
13050 target_big_endian = 1;
13051 break;
13052 #endif
13053
13054 #ifdef OPTION_EL
13055 case OPTION_EL:
13056 target_big_endian = 0;
13057 break;
13058 #endif
13059
13060 case 'a':
13061 /* Listing option. Just ignore these, we don't support additional
13062 ones. */
13063 return 0;
13064
13065 default:
13066 for (opt = arm_opts; opt->option != NULL; opt++)
13067 {
13068 if (c == opt->option[0]
13069 && ((arg == NULL && opt->option[1] == 0)
13070 || streq (arg, opt->option + 1)))
13071 {
13072 #if WARN_DEPRECATED
13073 /* If the option is deprecated, tell the user. */
13074 if (opt->deprecated != NULL)
13075 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c,
13076 arg ? arg : "", _(opt->deprecated));
13077 #endif
13078
13079 if (opt->var != NULL)
13080 *opt->var = opt->value;
13081
13082 return 1;
13083 }
13084 }
13085
13086 for (lopt = arm_long_opts; lopt->option != NULL; lopt++)
13087 {
13088 /* These options are expected to have an argument. */
13089 if (c == lopt->option[0]
13090 && arg != NULL
13091 && strncmp (arg, lopt->option + 1,
13092 strlen (lopt->option + 1)) == 0)
13093 {
13094 #if WARN_DEPRECATED
13095 /* If the option is deprecated, tell the user. */
13096 if (lopt->deprecated != NULL)
13097 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c, arg,
13098 _(lopt->deprecated));
13099 #endif
13100
13101 /* Call the sup-option parser. */
13102 return lopt->func (arg + strlen (lopt->option) - 1);
13103 }
13104 }
13105
13106 return 0;
13107 }
13108
13109 return 1;
13110 }
13111
13112 void
13113 md_show_usage (FILE * fp)
13114 {
13115 struct arm_option_table *opt;
13116 struct arm_long_option_table *lopt;
13117
13118 fprintf (fp, _(" ARM-specific assembler options:\n"));
13119
13120 for (opt = arm_opts; opt->option != NULL; opt++)
13121 if (opt->help != NULL)
13122 fprintf (fp, " -%-23s%s\n", opt->option, _(opt->help));
13123
13124 for (lopt = arm_long_opts; lopt->option != NULL; lopt++)
13125 if (lopt->help != NULL)
13126 fprintf (fp, " -%s%s\n", lopt->option, _(lopt->help));
13127
13128 #ifdef OPTION_EB
13129 fprintf (fp, _("\
13130 -EB assemble code for a big-endian cpu\n"));
13131 #endif
13132
13133 #ifdef OPTION_EL
13134 fprintf (fp, _("\
13135 -EL assemble code for a little-endian cpu\n"));
13136 #endif
13137 }
13138
13139 /* This fix_new is called by cons via TC_CONS_FIX_NEW. */
13140
13141 void
13142 cons_fix_new_arm (fragS * frag,
13143 int where,
13144 int size,
13145 expressionS * exp)
13146 {
13147 bfd_reloc_code_real_type type;
13148 int pcrel = 0;
13149
13150 /* Pick a reloc.
13151 FIXME: @@ Should look at CPU word size. */
13152 switch (size)
13153 {
13154 case 1:
13155 type = BFD_RELOC_8;
13156 break;
13157 case 2:
13158 type = BFD_RELOC_16;
13159 break;
13160 case 4:
13161 default:
13162 type = BFD_RELOC_32;
13163 break;
13164 case 8:
13165 type = BFD_RELOC_64;
13166 break;
13167 }
13168
13169 fix_new_exp (frag, where, (int) size, exp, pcrel, type);
13170 }
13171
13172 /* A good place to do this, although this was probably not intended
13173 for this kind of use. We need to dump the literal pool before
13174 references are made to a null symbol pointer. */
13175
13176 void
13177 arm_cleanup (void)
13178 {
13179 literal_pool * pool;
13180
13181 for (pool = list_of_pools; pool; pool = pool->next)
13182 {
13183 /* Put it at the end of the relevent section. */
13184 subseg_set (pool->section, pool->sub_section);
13185 #ifdef OBJ_ELF
13186 arm_elf_change_section ();
13187 #endif
13188 s_ltorg (0);
13189 }
13190 }
13191
13192 void
13193 arm_start_line_hook (void)
13194 {
13195 last_label_seen = NULL;
13196 }
13197
13198 void
13199 arm_frob_label (symbolS * sym)
13200 {
13201 last_label_seen = sym;
13202
13203 ARM_SET_THUMB (sym, thumb_mode);
13204
13205 #if defined OBJ_COFF || defined OBJ_ELF
13206 ARM_SET_INTERWORK (sym, support_interwork);
13207 #endif
13208
13209 /* Note - do not allow local symbols (.Lxxx) to be labeled
13210 as Thumb functions. This is because these labels, whilst
13211 they exist inside Thumb code, are not the entry points for
13212 possible ARM->Thumb calls. Also, these labels can be used
13213 as part of a computed goto or switch statement. eg gcc
13214 can generate code that looks like this:
13215
13216 ldr r2, [pc, .Laaa]
13217 lsl r3, r3, #2
13218 ldr r2, [r3, r2]
13219 mov pc, r2
13220
13221 .Lbbb: .word .Lxxx
13222 .Lccc: .word .Lyyy
13223 ..etc...
13224 .Laaa: .word Lbbb
13225
13226 The first instruction loads the address of the jump table.
13227 The second instruction converts a table index into a byte offset.
13228 The third instruction gets the jump address out of the table.
13229 The fourth instruction performs the jump.
13230
13231 If the address stored at .Laaa is that of a symbol which has the
13232 Thumb_Func bit set, then the linker will arrange for this address
13233 to have the bottom bit set, which in turn would mean that the
13234 address computation performed by the third instruction would end
13235 up with the bottom bit set. Since the ARM is capable of unaligned
13236 word loads, the instruction would then load the incorrect address
13237 out of the jump table, and chaos would ensue. */
13238 if (label_is_thumb_function_name
13239 && (S_GET_NAME (sym)[0] != '.' || S_GET_NAME (sym)[1] != 'L')
13240 && (bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
13241 {
13242 /* When the address of a Thumb function is taken the bottom
13243 bit of that address should be set. This will allow
13244 interworking between Arm and Thumb functions to work
13245 correctly. */
13246
13247 THUMB_SET_FUNC (sym, 1);
13248
13249 label_is_thumb_function_name = FALSE;
13250 }
13251 }
13252
13253 /* Adjust the symbol table. This marks Thumb symbols as distinct from
13254 ARM ones. */
13255
13256 void
13257 arm_adjust_symtab (void)
13258 {
13259 #ifdef OBJ_COFF
13260 symbolS * sym;
13261
13262 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
13263 {
13264 if (ARM_IS_THUMB (sym))
13265 {
13266 if (THUMB_IS_FUNC (sym))
13267 {
13268 /* Mark the symbol as a Thumb function. */
13269 if ( S_GET_STORAGE_CLASS (sym) == C_STAT
13270 || S_GET_STORAGE_CLASS (sym) == C_LABEL) /* This can happen! */
13271 S_SET_STORAGE_CLASS (sym, C_THUMBSTATFUNC);
13272
13273 else if (S_GET_STORAGE_CLASS (sym) == C_EXT)
13274 S_SET_STORAGE_CLASS (sym, C_THUMBEXTFUNC);
13275 else
13276 as_bad (_("%s: unexpected function type: %d"),
13277 S_GET_NAME (sym), S_GET_STORAGE_CLASS (sym));
13278 }
13279 else switch (S_GET_STORAGE_CLASS (sym))
13280 {
13281 case C_EXT:
13282 S_SET_STORAGE_CLASS (sym, C_THUMBEXT);
13283 break;
13284 case C_STAT:
13285 S_SET_STORAGE_CLASS (sym, C_THUMBSTAT);
13286 break;
13287 case C_LABEL:
13288 S_SET_STORAGE_CLASS (sym, C_THUMBLABEL);
13289 break;
13290 default:
13291 /* Do nothing. */
13292 break;
13293 }
13294 }
13295
13296 if (ARM_IS_INTERWORK (sym))
13297 coffsymbol (symbol_get_bfdsym (sym))->native->u.syment.n_flags = 0xFF;
13298 }
13299 #endif
13300 #ifdef OBJ_ELF
13301 symbolS * sym;
13302 char bind;
13303
13304 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
13305 {
13306 if (ARM_IS_THUMB (sym))
13307 {
13308 elf_symbol_type * elf_sym;
13309
13310 elf_sym = elf_symbol (symbol_get_bfdsym (sym));
13311 bind = ELF_ST_BIND (elf_sym);
13312
13313 /* If it's a .thumb_func, declare it as so,
13314 otherwise tag label as .code 16. */
13315 if (THUMB_IS_FUNC (sym))
13316 elf_sym->internal_elf_sym.st_info =
13317 ELF_ST_INFO (bind, STT_ARM_TFUNC);
13318 else
13319 elf_sym->internal_elf_sym.st_info =
13320 ELF_ST_INFO (bind, STT_ARM_16BIT);
13321 }
13322 }
13323 #endif
13324 }
13325
13326 int
13327 arm_data_in_code (void)
13328 {
13329 if (thumb_mode && ! strncmp (input_line_pointer + 1, "data:", 5))
13330 {
13331 *input_line_pointer = '/';
13332 input_line_pointer += 5;
13333 *input_line_pointer = 0;
13334 return 1;
13335 }
13336
13337 return 0;
13338 }
13339
13340 char *
13341 arm_canonicalize_symbol_name (char * name)
13342 {
13343 int len;
13344
13345 if (thumb_mode && (len = strlen (name)) > 5
13346 && streq (name + len - 5, "/data"))
13347 *(name + len - 5) = 0;
13348
13349 return name;
13350 }
13351
13352 #if defined OBJ_COFF || defined OBJ_ELF
13353 void
13354 arm_validate_fix (fixS * fixP)
13355 {
13356 /* If the destination of the branch is a defined symbol which does not have
13357 the THUMB_FUNC attribute, then we must be calling a function which has
13358 the (interfacearm) attribute. We look for the Thumb entry point to that
13359 function and change the branch to refer to that function instead. */
13360 if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23
13361 && fixP->fx_addsy != NULL
13362 && S_IS_DEFINED (fixP->fx_addsy)
13363 && ! THUMB_IS_FUNC (fixP->fx_addsy))
13364 {
13365 fixP->fx_addsy = find_real_start (fixP->fx_addsy);
13366 }
13367 }
13368 #endif
13369
13370 int
13371 arm_force_relocation (struct fix * fixp)
13372 {
13373 #if defined (OBJ_COFF) && defined (TE_PE)
13374 if (fixp->fx_r_type == BFD_RELOC_RVA)
13375 return 1;
13376 #endif
13377 #ifdef OBJ_ELF
13378 if (fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH
13379 || fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BLX
13380 || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX
13381 || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23)
13382 return 1;
13383 #endif
13384
13385 /* Resolve these relocations even if the symbol is extern or weak. */
13386 if (fixp->fx_r_type == BFD_RELOC_ARM_IMMEDIATE
13387 || fixp->fx_r_type == BFD_RELOC_ARM_OFFSET_IMM
13388 || fixp->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE)
13389 return 0;
13390
13391 return generic_force_reloc (fixp);
13392 }
13393
13394 #ifdef OBJ_COFF
13395 /* This is a little hack to help the gas/arm/adrl.s test. It prevents
13396 local labels from being added to the output symbol table when they
13397 are used with the ADRL pseudo op. The ADRL relocation should always
13398 be resolved before the binbary is emitted, so it is safe to say that
13399 it is adjustable. */
13400
13401 bfd_boolean
13402 arm_fix_adjustable (fixS * fixP)
13403 {
13404 if (fixP->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE)
13405 return 1;
13406 return 0;
13407 }
13408 #endif
13409
13410 #ifdef OBJ_ELF
13411 /* Relocations against Thumb function names must be left unadjusted,
13412 so that the linker can use this information to correctly set the
13413 bottom bit of their addresses. The MIPS version of this function
13414 also prevents relocations that are mips-16 specific, but I do not
13415 know why it does this.
13416
13417 FIXME:
13418 There is one other problem that ought to be addressed here, but
13419 which currently is not: Taking the address of a label (rather
13420 than a function) and then later jumping to that address. Such
13421 addresses also ought to have their bottom bit set (assuming that
13422 they reside in Thumb code), but at the moment they will not. */
13423
13424 bfd_boolean
13425 arm_fix_adjustable (fixS * fixP)
13426 {
13427 if (fixP->fx_addsy == NULL)
13428 return 1;
13429
13430 if (THUMB_IS_FUNC (fixP->fx_addsy)
13431 && fixP->fx_subsy == NULL)
13432 return 0;
13433
13434 /* We need the symbol name for the VTABLE entries. */
13435 if ( fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
13436 || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
13437 return 0;
13438
13439 /* Don't allow symbols to be discarded on GOT related relocs. */
13440 if (fixP->fx_r_type == BFD_RELOC_ARM_PLT32
13441 || fixP->fx_r_type == BFD_RELOC_ARM_GOT32
13442 || fixP->fx_r_type == BFD_RELOC_ARM_GOTOFF
13443 || fixP->fx_r_type == BFD_RELOC_ARM_TARGET2)
13444 return 0;
13445
13446 return 1;
13447 }
13448
13449 const char *
13450 elf32_arm_target_format (void)
13451 {
13452 #ifdef TE_SYMBIAN
13453 return (target_big_endian
13454 ? "elf32-bigarm-symbian"
13455 : "elf32-littlearm-symbian");
13456 #elif defined (TE_VXWORKS)
13457 return (target_big_endian
13458 ? "elf32-bigarm-vxworks"
13459 : "elf32-littlearm-vxworks");
13460 #else
13461 if (target_big_endian)
13462 return "elf32-bigarm";
13463 else
13464 return "elf32-littlearm";
13465 #endif
13466 }
13467
13468 void
13469 armelf_frob_symbol (symbolS * symp,
13470 int * puntp)
13471 {
13472 elf_frob_symbol (symp, puntp);
13473 }
13474
13475 static void
13476 s_arm_elf_cons (int nbytes)
13477 {
13478 expressionS exp;
13479
13480 #ifdef md_flush_pending_output
13481 md_flush_pending_output ();
13482 #endif
13483
13484 if (is_it_end_of_statement ())
13485 {
13486 demand_empty_rest_of_line ();
13487 return;
13488 }
13489
13490 #ifdef md_cons_align
13491 md_cons_align (nbytes);
13492 #endif
13493
13494 mapping_state (MAP_DATA);
13495 do
13496 {
13497 bfd_reloc_code_real_type reloc;
13498
13499 expression (& exp);
13500
13501 if (exp.X_op == O_symbol
13502 && * input_line_pointer == '('
13503 && (reloc = arm_parse_reloc ()) != BFD_RELOC_UNUSED)
13504 {
13505 reloc_howto_type *howto = bfd_reloc_type_lookup (stdoutput, reloc);
13506 int size = bfd_get_reloc_size (howto);
13507
13508 if (size > nbytes)
13509 as_bad ("%s relocations do not fit in %d bytes",
13510 howto->name, nbytes);
13511 else
13512 {
13513 char *p = frag_more ((int) nbytes);
13514 int offset = nbytes - size;
13515
13516 fix_new_exp (frag_now, p - frag_now->fr_literal + offset, size,
13517 &exp, 0, reloc);
13518 }
13519 }
13520 else
13521 emit_expr (&exp, (unsigned int) nbytes);
13522 }
13523 while (*input_line_pointer++ == ',');
13524
13525 /* Put terminator back into stream. */
13526 input_line_pointer --;
13527 demand_empty_rest_of_line ();
13528 }
13529
13530
13531 /* Parse a .rel31 directive. */
13532
13533 static void
13534 s_arm_rel31 (int ignored ATTRIBUTE_UNUSED)
13535 {
13536 expressionS exp;
13537 char *p;
13538 valueT highbit;
13539
13540 SKIP_WHITESPACE ();
13541
13542 highbit = 0;
13543 if (*input_line_pointer == '1')
13544 highbit = 0x80000000;
13545 else if (*input_line_pointer != '0')
13546 as_bad (_("expected 0 or 1"));
13547
13548 input_line_pointer++;
13549 SKIP_WHITESPACE ();
13550 if (*input_line_pointer != ',')
13551 as_bad (_("missing comma"));
13552 input_line_pointer++;
13553
13554 #ifdef md_flush_pending_output
13555 md_flush_pending_output ();
13556 #endif
13557
13558 #ifdef md_cons_align
13559 md_cons_align (4);
13560 #endif
13561
13562 mapping_state (MAP_DATA);
13563
13564 expression (&exp);
13565
13566 p = frag_more (4);
13567 md_number_to_chars (p, highbit, 4);
13568 fix_new_arm (frag_now, p - frag_now->fr_literal, 4, &exp, 1,
13569 BFD_RELOC_ARM_PREL31);
13570
13571 demand_empty_rest_of_line ();
13572 }
13573 \f
13574 /* Code to deal with unwinding tables. */
13575
13576 static void add_unwind_adjustsp (offsetT);
13577
13578 /* Switch to section NAME and create section if necessary. It's
13579 rather ugly that we have to manipulate input_line_pointer but I
13580 don't see any other way to accomplish the same thing without
13581 changing obj-elf.c (which may be the Right Thing, in the end).
13582 Copied from tc-ia64.c. */
13583
13584 static void
13585 set_section (char *name)
13586 {
13587 char *saved_input_line_pointer;
13588
13589 saved_input_line_pointer = input_line_pointer;
13590 input_line_pointer = name;
13591 obj_elf_section (0);
13592 input_line_pointer = saved_input_line_pointer;
13593 }
13594
13595 /* Cenerate and deferred unwind frame offset. */
13596
13597 static void
13598 flush_pending_unwind (void)
13599 {
13600 offsetT offset;
13601
13602 offset = unwind.pending_offset;
13603 unwind.pending_offset = 0;
13604 if (offset != 0)
13605 add_unwind_adjustsp (offset);
13606 }
13607
13608 /* Add an opcode to this list for this function. Two-byte opcodes should
13609 be passed as op[0] << 8 | op[1]. The list of opcodes is built in reverse
13610 order. */
13611
13612 static void
13613 add_unwind_opcode (valueT op, int length)
13614 {
13615 /* Add any deferred stack adjustment. */
13616 if (unwind.pending_offset)
13617 flush_pending_unwind ();
13618
13619 unwind.sp_restored = 0;
13620
13621 if (unwind.opcode_count + length > unwind.opcode_alloc)
13622 {
13623 unwind.opcode_alloc += ARM_OPCODE_CHUNK_SIZE;
13624 if (unwind.opcodes)
13625 unwind.opcodes = xrealloc (unwind.opcodes,
13626 unwind.opcode_alloc);
13627 else
13628 unwind.opcodes = xmalloc (unwind.opcode_alloc);
13629 }
13630 while (length > 0)
13631 {
13632 length--;
13633 unwind.opcodes[unwind.opcode_count] = op & 0xff;
13634 op >>= 8;
13635 unwind.opcode_count++;
13636 }
13637 }
13638
13639 /* Add unwind opcodes to adjust the stack pointer. */
13640
13641 static void
13642 add_unwind_adjustsp (offsetT offset)
13643 {
13644 valueT op;
13645
13646 if (offset > 0x200)
13647 {
13648 /* We need at most 5 bytes to hold a 32-bit value in a uleb128. */
13649 char bytes[5];
13650 int n;
13651 valueT o;
13652
13653 /* Long form: 0xb2, uleb128. */
13654 /* This might not fit in a word so add the individual bytes,
13655 remembering the list is built in reverse order. */
13656 o = (valueT) ((offset - 0x204) >> 2);
13657 if (o == 0)
13658 add_unwind_opcode (0, 1);
13659
13660 /* Calculate the uleb128 encoding of the offset. */
13661 n = 0;
13662 while (o)
13663 {
13664 bytes[n] = o & 0x7f;
13665 o >>= 7;
13666 if (o)
13667 bytes[n] |= 0x80;
13668 n++;
13669 }
13670 /* Add the insn. */
13671 for (; n; n--)
13672 add_unwind_opcode (bytes[n - 1], 1);
13673 add_unwind_opcode (0xb2, 1);
13674 }
13675 else if (offset > 0x100)
13676 {
13677 /* Two short opcodes. */
13678 add_unwind_opcode (0x3f, 1);
13679 op = (offset - 0x104) >> 2;
13680 add_unwind_opcode (op, 1);
13681 }
13682 else if (offset > 0)
13683 {
13684 /* Short opcode. */
13685 op = (offset - 4) >> 2;
13686 add_unwind_opcode (op, 1);
13687 }
13688 else if (offset < 0)
13689 {
13690 offset = -offset;
13691 while (offset > 0x100)
13692 {
13693 add_unwind_opcode (0x7f, 1);
13694 offset -= 0x100;
13695 }
13696 op = ((offset - 4) >> 2) | 0x40;
13697 add_unwind_opcode (op, 1);
13698 }
13699 }
13700
13701 /* Finish the list of unwind opcodes for this function. */
13702 static void
13703 finish_unwind_opcodes (void)
13704 {
13705 valueT op;
13706
13707 if (unwind.fp_used)
13708 {
13709 /* Adjust sp as neccessary. */
13710 unwind.pending_offset += unwind.fp_offset - unwind.frame_size;
13711 flush_pending_unwind ();
13712
13713 /* After restoring sp from the frame pointer. */
13714 op = 0x90 | unwind.fp_reg;
13715 add_unwind_opcode (op, 1);
13716 }
13717 else
13718 flush_pending_unwind ();
13719 }
13720
13721
13722 /* Start an exception table entry. If idx is nonzero this is an index table
13723 entry. */
13724
13725 static void
13726 start_unwind_section (const segT text_seg, int idx)
13727 {
13728 const char * text_name;
13729 const char * prefix;
13730 const char * prefix_once;
13731 size_t prefix_len;
13732 size_t text_len;
13733 char * sec_name;
13734 size_t sec_name_len;
13735
13736 if (idx)
13737 {
13738 prefix = ELF_STRING_ARM_unwind;
13739 prefix_once = ELF_STRING_ARM_unwind_once;
13740 }
13741 else
13742 {
13743 prefix = ELF_STRING_ARM_unwind_info;
13744 prefix_once = ELF_STRING_ARM_unwind_info_once;
13745 }
13746
13747 text_name = segment_name (text_seg);
13748 if (streq (text_name, ".text"))
13749 text_name = "";
13750
13751 if (strncmp (text_name, ".gnu.linkonce.t.",
13752 strlen (".gnu.linkonce.t.")) == 0)
13753 {
13754 prefix = prefix_once;
13755 text_name += strlen (".gnu.linkonce.t.");
13756 }
13757
13758 prefix_len = strlen (prefix);
13759 text_len = strlen (text_name);
13760 sec_name_len = prefix_len + text_len;
13761 sec_name = alloca (sec_name_len + 1);
13762 memcpy (sec_name, prefix, prefix_len);
13763 memcpy (sec_name + prefix_len, text_name, text_len);
13764 sec_name[prefix_len + text_len] = '\0';
13765
13766 /* Handle COMDAT group. */
13767 if (prefix != prefix_once && (text_seg->flags & SEC_LINK_ONCE) != 0)
13768 {
13769 char *section;
13770 size_t len, group_name_len;
13771 const char *group_name = elf_group_name (text_seg);
13772
13773 if (group_name == NULL)
13774 {
13775 as_bad ("Group section `%s' has no group signature",
13776 segment_name (text_seg));
13777 ignore_rest_of_line ();
13778 return;
13779 }
13780 /* We have to construct a fake section directive. */
13781 group_name_len = strlen (group_name);
13782 if (idx)
13783 prefix_len = 13;
13784 else
13785 prefix_len = 16;
13786
13787 len = (sec_name_len
13788 + prefix_len /* ,"aG",%sectiontype, */
13789 + group_name_len /* ,group_name */
13790 + 7); /* ,comdat */
13791
13792 section = alloca (len + 1);
13793 memcpy (section, sec_name, sec_name_len);
13794 if (idx)
13795 memcpy (section + sec_name_len, ",\"aG\",%exidx,", 13);
13796 else
13797 memcpy (section + sec_name_len, ",\"aG\",%progbits,", 16);
13798 memcpy (section + sec_name_len + prefix_len, group_name, group_name_len);
13799 memcpy (section + len - 7, ",comdat", 7);
13800 section [len] = '\0';
13801 set_section (section);
13802 }
13803 else
13804 {
13805 set_section (sec_name);
13806 bfd_set_section_flags (stdoutput, now_seg,
13807 SEC_LOAD | SEC_ALLOC | SEC_READONLY);
13808 }
13809
13810 /* Set the setion link for index tables. */
13811 if (idx)
13812 elf_linked_to_section (now_seg) = text_seg;
13813 }
13814
13815
13816 /* Start an unwind table entry. HAVE_DATA is nonzero if we have additional
13817 personality routine data. Returns zero, or the index table value for
13818 and inline entry. */
13819
13820 static valueT
13821 create_unwind_entry (int have_data)
13822 {
13823 int size;
13824 addressT where;
13825 char *ptr;
13826 /* The current word of data. */
13827 valueT data;
13828 /* The number of bytes left in this word. */
13829 int n;
13830
13831 finish_unwind_opcodes ();
13832
13833 /* Remember the current text section. */
13834 unwind.saved_seg = now_seg;
13835 unwind.saved_subseg = now_subseg;
13836
13837 start_unwind_section (now_seg, 0);
13838
13839 if (unwind.personality_routine == NULL)
13840 {
13841 if (unwind.personality_index == -2)
13842 {
13843 if (have_data)
13844 as_bad (_("handerdata in cantunwind frame"));
13845 return 1; /* EXIDX_CANTUNWIND. */
13846 }
13847
13848 /* Use a default personality routine if none is specified. */
13849 if (unwind.personality_index == -1)
13850 {
13851 if (unwind.opcode_count > 3)
13852 unwind.personality_index = 1;
13853 else
13854 unwind.personality_index = 0;
13855 }
13856
13857 /* Space for the personality routine entry. */
13858 if (unwind.personality_index == 0)
13859 {
13860 if (unwind.opcode_count > 3)
13861 as_bad (_("too many unwind opcodes for personality routine 0"));
13862
13863 if (!have_data)
13864 {
13865 /* All the data is inline in the index table. */
13866 data = 0x80;
13867 n = 3;
13868 while (unwind.opcode_count > 0)
13869 {
13870 unwind.opcode_count--;
13871 data = (data << 8) | unwind.opcodes[unwind.opcode_count];
13872 n--;
13873 }
13874
13875 /* Pad with "finish" opcodes. */
13876 while (n--)
13877 data = (data << 8) | 0xb0;
13878
13879 return data;
13880 }
13881 size = 0;
13882 }
13883 else
13884 /* We get two opcodes "free" in the first word. */
13885 size = unwind.opcode_count - 2;
13886 }
13887 else
13888 /* An extra byte is required for the opcode count. */
13889 size = unwind.opcode_count + 1;
13890
13891 size = (size + 3) >> 2;
13892 if (size > 0xff)
13893 as_bad (_("too many unwind opcodes"));
13894
13895 frag_align (2, 0, 0);
13896 record_alignment (now_seg, 2);
13897 unwind.table_entry = expr_build_dot ();
13898
13899 /* Allocate the table entry. */
13900 ptr = frag_more ((size << 2) + 4);
13901 where = frag_now_fix () - ((size << 2) + 4);
13902
13903 switch (unwind.personality_index)
13904 {
13905 case -1:
13906 /* ??? Should this be a PLT generating relocation? */
13907 /* Custom personality routine. */
13908 fix_new (frag_now, where, 4, unwind.personality_routine, 0, 1,
13909 BFD_RELOC_ARM_PREL31);
13910
13911 /* Indicate dependency to linker. */
13912 {
13913 char *name = "__aeabi_unwind_cpp_pr0";
13914 symbolS *pr = symbol_find_or_make (name);
13915 fix_new (frag_now, where, 4, pr, 0, 1, BFD_RELOC_NONE);
13916 }
13917
13918 where += 4;
13919 ptr += 4;
13920
13921 /* Set the first byte to the number of additional words. */
13922 data = size - 1;
13923 n = 3;
13924 break;
13925
13926 /* ABI defined personality routines. */
13927 case 0:
13928 /* Three opcodes bytes are packed into the first word. */
13929 data = 0x80;
13930 n = 3;
13931 goto emit_reloc;
13932
13933 case 1:
13934 case 2:
13935 /* The size and first two opcode bytes go in the first word. */
13936 data = ((0x80 + unwind.personality_index) << 8) | size;
13937 n = 2;
13938 goto emit_reloc;
13939
13940 emit_reloc:
13941 {
13942 /* Indicate dependency to linker. */
13943 char *name[] = { "__aeabi_unwind_cpp_pr0",
13944 "__aeabi_unwind_cpp_pr1",
13945 "__aeabi_unwind_cpp_pr2" };
13946 symbolS *pr = symbol_find_or_make (name[unwind.personality_index]);
13947 fix_new (frag_now, where, 4, pr, 0, 1, BFD_RELOC_NONE);
13948 }
13949 break;
13950
13951 default:
13952 /* Should never happen. */
13953 abort ();
13954 }
13955
13956 /* Pack the opcodes into words (MSB first), reversing the list at the same
13957 time. */
13958 while (unwind.opcode_count > 0)
13959 {
13960 if (n == 0)
13961 {
13962 md_number_to_chars (ptr, data, 4);
13963 ptr += 4;
13964 n = 4;
13965 data = 0;
13966 }
13967 unwind.opcode_count--;
13968 n--;
13969 data = (data << 8) | unwind.opcodes[unwind.opcode_count];
13970 }
13971
13972 /* Finish off the last word. */
13973 if (n < 4)
13974 {
13975 /* Pad with "finish" opcodes. */
13976 while (n--)
13977 data = (data << 8) | 0xb0;
13978
13979 md_number_to_chars (ptr, data, 4);
13980 }
13981
13982 if (!have_data)
13983 {
13984 /* Add an empty descriptor if there is no user-specified data. */
13985 ptr = frag_more (4);
13986 md_number_to_chars (ptr, 0, 4);
13987 }
13988
13989 return 0;
13990 }
13991
13992
13993 /* Parse an unwind_fnstart directive. Simply records the current location. */
13994
13995 static void
13996 s_arm_unwind_fnstart (int ignored ATTRIBUTE_UNUSED)
13997 {
13998 demand_empty_rest_of_line ();
13999 /* Mark the start of the function. */
14000 unwind.proc_start = expr_build_dot ();
14001
14002 /* Reset the rest of the unwind info. */
14003 unwind.opcode_count = 0;
14004 unwind.table_entry = NULL;
14005 unwind.personality_routine = NULL;
14006 unwind.personality_index = -1;
14007 unwind.frame_size = 0;
14008 unwind.fp_offset = 0;
14009 unwind.fp_reg = 13;
14010 unwind.fp_used = 0;
14011 unwind.sp_restored = 0;
14012 }
14013
14014
14015 /* Parse a handlerdata directive. Creates the exception handling table entry
14016 for the function. */
14017
14018 static void
14019 s_arm_unwind_handlerdata (int ignored ATTRIBUTE_UNUSED)
14020 {
14021 demand_empty_rest_of_line ();
14022 if (unwind.table_entry)
14023 as_bad (_("dupicate .handlerdata directive"));
14024
14025 create_unwind_entry (1);
14026 }
14027
14028 /* Parse an unwind_fnend directive. Generates the index table entry. */
14029
14030 static void
14031 s_arm_unwind_fnend (int ignored ATTRIBUTE_UNUSED)
14032 {
14033 long where;
14034 char *ptr;
14035 valueT val;
14036
14037 demand_empty_rest_of_line ();
14038
14039 /* Add eh table entry. */
14040 if (unwind.table_entry == NULL)
14041 val = create_unwind_entry (0);
14042 else
14043 val = 0;
14044
14045 /* Add index table entry. This is two words. */
14046 start_unwind_section (unwind.saved_seg, 1);
14047 frag_align (2, 0, 0);
14048 record_alignment (now_seg, 2);
14049
14050 ptr = frag_more (8);
14051 where = frag_now_fix () - 8;
14052
14053 /* Self relative offset of the function start. */
14054 fix_new (frag_now, where, 4, unwind.proc_start, 0, 1,
14055 BFD_RELOC_ARM_PREL31);
14056
14057 if (val)
14058 /* Inline exception table entry. */
14059 md_number_to_chars (ptr + 4, val, 4);
14060 else
14061 /* Self relative offset of the table entry. */
14062 fix_new (frag_now, where + 4, 4, unwind.table_entry, 0, 1,
14063 BFD_RELOC_ARM_PREL31);
14064
14065 /* Restore the original section. */
14066 subseg_set (unwind.saved_seg, unwind.saved_subseg);
14067 }
14068
14069
14070 /* Parse an unwind_cantunwind directive. */
14071
14072 static void
14073 s_arm_unwind_cantunwind (int ignored ATTRIBUTE_UNUSED)
14074 {
14075 demand_empty_rest_of_line ();
14076 if (unwind.personality_routine || unwind.personality_index != -1)
14077 as_bad (_("personality routine specified for cantunwind frame"));
14078
14079 unwind.personality_index = -2;
14080 }
14081
14082
14083 /* Parse a personalityindex directive. */
14084
14085 static void
14086 s_arm_unwind_personalityindex (int ignored ATTRIBUTE_UNUSED)
14087 {
14088 expressionS exp;
14089
14090 if (unwind.personality_routine || unwind.personality_index != -1)
14091 as_bad (_("duplicate .personalityindex directive"));
14092
14093 SKIP_WHITESPACE ();
14094
14095 expression (&exp);
14096
14097 if (exp.X_op != O_constant
14098 || exp.X_add_number < 0 || exp.X_add_number > 15)
14099 {
14100 as_bad (_("bad personality routine number"));
14101 ignore_rest_of_line ();
14102 return;
14103 }
14104
14105 unwind.personality_index = exp.X_add_number;
14106
14107 demand_empty_rest_of_line ();
14108 }
14109
14110
14111 /* Parse a personality directive. */
14112
14113 static void
14114 s_arm_unwind_personality (int ignored ATTRIBUTE_UNUSED)
14115 {
14116 char *name, *p, c;
14117
14118 if (unwind.personality_routine || unwind.personality_index != -1)
14119 as_bad (_("duplicate .personality directive"));
14120
14121 SKIP_WHITESPACE ();
14122 name = input_line_pointer;
14123 c = get_symbol_end ();
14124 p = input_line_pointer;
14125 unwind.personality_routine = symbol_find_or_make (name);
14126 *p = c;
14127 SKIP_WHITESPACE ();
14128 demand_empty_rest_of_line ();
14129 }
14130
14131
14132 /* Parse a directive saving core registers. */
14133
14134 static void
14135 s_arm_unwind_save_core (void)
14136 {
14137 valueT op;
14138 long range;
14139 int n;
14140
14141 SKIP_WHITESPACE ();
14142 range = reg_list (&input_line_pointer);
14143 if (range == FAIL)
14144 {
14145 as_bad (_("expected register list"));
14146 ignore_rest_of_line ();
14147 return;
14148 }
14149
14150 demand_empty_rest_of_line ();
14151
14152 /* Turn .unwind_movsp ip followed by .unwind_save {..., ip, ...}
14153 into .unwind_save {..., sp...}. We aren't bothered about the value of
14154 ip because it is clobbered by calls. */
14155 if (unwind.sp_restored && unwind.fp_reg == 12
14156 && (range & 0x3000) == 0x1000)
14157 {
14158 unwind.opcode_count--;
14159 unwind.sp_restored = 0;
14160 range = (range | 0x2000) & ~0x1000;
14161 unwind.pending_offset = 0;
14162 }
14163
14164 /* See if we can use the short opcodes. These pop a block of upto 8
14165 registers starting with r4, plus maybe r14. */
14166 for (n = 0; n < 8; n++)
14167 {
14168 /* Break at the first non-saved register. */
14169 if ((range & (1 << (n + 4))) == 0)
14170 break;
14171 }
14172 /* See if there are any other bits set. */
14173 if (n == 0 || (range & (0xfff0 << n) & 0xbff0) != 0)
14174 {
14175 /* Use the long form. */
14176 op = 0x8000 | ((range >> 4) & 0xfff);
14177 add_unwind_opcode (op, 2);
14178 }
14179 else
14180 {
14181 /* Use the short form. */
14182 if (range & 0x4000)
14183 op = 0xa8; /* Pop r14. */
14184 else
14185 op = 0xa0; /* Do not pop r14. */
14186 op |= (n - 1);
14187 add_unwind_opcode (op, 1);
14188 }
14189
14190 /* Pop r0-r3. */
14191 if (range & 0xf)
14192 {
14193 op = 0xb100 | (range & 0xf);
14194 add_unwind_opcode (op, 2);
14195 }
14196
14197 /* Record the number of bytes pushed. */
14198 for (n = 0; n < 16; n++)
14199 {
14200 if (range & (1 << n))
14201 unwind.frame_size += 4;
14202 }
14203 }
14204
14205
14206 /* Parse a directive saving FPA registers. */
14207
14208 static void
14209 s_arm_unwind_save_fpa (int reg)
14210 {
14211 expressionS exp;
14212 int num_regs;
14213 valueT op;
14214
14215 /* Get Number of registers to transfer. */
14216 if (skip_past_comma (&input_line_pointer) != FAIL)
14217 expression (&exp);
14218 else
14219 exp.X_op = O_illegal;
14220
14221 if (exp.X_op != O_constant)
14222 {
14223 as_bad (_("expected , <constant>"));
14224 ignore_rest_of_line ();
14225 return;
14226 }
14227
14228 num_regs = exp.X_add_number;
14229
14230 if (num_regs < 1 || num_regs > 4)
14231 {
14232 as_bad (_("number of registers must be in the range [1:4]"));
14233 ignore_rest_of_line ();
14234 return;
14235 }
14236
14237 demand_empty_rest_of_line ();
14238
14239 if (reg == 4)
14240 {
14241 /* Short form. */
14242 op = 0xb4 | (num_regs - 1);
14243 add_unwind_opcode (op, 1);
14244 }
14245 else
14246 {
14247 /* Long form. */
14248 op = 0xc800 | (reg << 4) | (num_regs - 1);
14249 add_unwind_opcode (op, 2);
14250 }
14251 unwind.frame_size += num_regs * 12;
14252 }
14253
14254
14255 /* Parse a directive saving VFP registers. */
14256
14257 static void
14258 s_arm_unwind_save_vfp (void)
14259 {
14260 int count;
14261 int reg;
14262 valueT op;
14263
14264 count = vfp_parse_reg_list (&input_line_pointer, &reg, 1);
14265 if (count == FAIL)
14266 {
14267 as_bad (_("expected register list"));
14268 ignore_rest_of_line ();
14269 return;
14270 }
14271
14272 demand_empty_rest_of_line ();
14273
14274 if (reg == 8)
14275 {
14276 /* Short form. */
14277 op = 0xb8 | (count - 1);
14278 add_unwind_opcode (op, 1);
14279 }
14280 else
14281 {
14282 /* Long form. */
14283 op = 0xb300 | (reg << 4) | (count - 1);
14284 add_unwind_opcode (op, 2);
14285 }
14286 unwind.frame_size += count * 8 + 4;
14287 }
14288
14289
14290 /* Parse a directive saving iWMMXt registers. */
14291
14292 static void
14293 s_arm_unwind_save_wmmx (void)
14294 {
14295 int reg;
14296 int hi_reg;
14297 int i;
14298 unsigned wcg_mask;
14299 unsigned wr_mask;
14300 valueT op;
14301
14302 if (*input_line_pointer == '{')
14303 input_line_pointer++;
14304
14305 wcg_mask = 0;
14306 wr_mask = 0;
14307 do
14308 {
14309 reg = arm_reg_parse (&input_line_pointer,
14310 all_reg_maps[REG_TYPE_IWMMXT].htab);
14311
14312 if (wr_register (reg))
14313 {
14314 i = reg & ~WR_PREFIX;
14315 if (wr_mask >> i)
14316 as_tsktsk (_("register list not in ascending order"));
14317 wr_mask |= 1 << i;
14318 }
14319 else if (wcg_register (reg))
14320 {
14321 i = (reg & ~WC_PREFIX) - 8;
14322 if (wcg_mask >> i)
14323 as_tsktsk (_("register list not in ascending order"));
14324 wcg_mask |= 1 << i;
14325 }
14326 else
14327 {
14328 as_bad (_("expected wr or wcgr"));
14329 goto error;
14330 }
14331
14332 SKIP_WHITESPACE ();
14333 if (*input_line_pointer == '-')
14334 {
14335 hi_reg = arm_reg_parse (&input_line_pointer,
14336 all_reg_maps[REG_TYPE_IWMMXT].htab);
14337 if (wr_register (reg) && wr_register (hi_reg))
14338 {
14339 for (; reg < hi_reg; reg++)
14340 wr_mask |= 1 << (reg & ~WR_PREFIX);
14341 }
14342 else if (wcg_register (reg) && wcg_register (hi_reg))
14343 {
14344 for (; reg < hi_reg; reg++)
14345 wcg_mask |= 1 << ((reg & ~WC_PREFIX) - 8);
14346 }
14347 else
14348 {
14349 as_bad (_("bad register range"));
14350 goto error;
14351 }
14352 }
14353 }
14354 while (skip_past_comma (&input_line_pointer) != FAIL);
14355
14356 SKIP_WHITESPACE ();
14357 if (*input_line_pointer == '}')
14358 input_line_pointer++;
14359
14360 demand_empty_rest_of_line ();
14361
14362 if (wr_mask && wcg_mask)
14363 {
14364 as_bad (_("inconsistent register types"));
14365 goto error;
14366 }
14367
14368 /* Generate any deferred opcodes becuuse we're going to be looking at
14369 the list. */
14370 flush_pending_unwind ();
14371
14372 if (wcg_mask)
14373 {
14374 for (i = 0; i < 16; i++)
14375 {
14376 if (wcg_mask & (1 << i))
14377 unwind.frame_size += 4;
14378 }
14379 op = 0xc700 | wcg_mask;
14380 add_unwind_opcode (op, 2);
14381 }
14382 else
14383 {
14384 for (i = 0; i < 16; i++)
14385 {
14386 if (wr_mask & (1 << i))
14387 unwind.frame_size += 8;
14388 }
14389 /* Attempt to combine with a previous opcode. We do this because gcc
14390 likes to output separate unwind directives for a single block of
14391 registers. */
14392 if (unwind.opcode_count > 0)
14393 {
14394 i = unwind.opcodes[unwind.opcode_count - 1];
14395 if ((i & 0xf8) == 0xc0)
14396 {
14397 i &= 7;
14398 /* Only merge if the blocks are contiguous. */
14399 if (i < 6)
14400 {
14401 if ((wr_mask & 0xfe00) == (1 << 9))
14402 {
14403 wr_mask |= ((1 << (i + 11)) - 1) & 0xfc00;
14404 unwind.opcode_count--;
14405 }
14406 }
14407 else if (i == 6 && unwind.opcode_count >= 2)
14408 {
14409 i = unwind.opcodes[unwind.opcode_count - 2];
14410 reg = i >> 4;
14411 i &= 0xf;
14412
14413 op = 0xffff << (reg - 1);
14414 if (reg > 0
14415 || ((wr_mask & op) == (1u << (reg - 1))))
14416 {
14417 op = (1 << (reg + i + 1)) - 1;
14418 op &= ~((1 << reg) - 1);
14419 wr_mask |= op;
14420 unwind.opcode_count -= 2;
14421 }
14422 }
14423 }
14424 }
14425
14426 hi_reg = 15;
14427 /* We want to generate opcodes in the order the registers have been
14428 saved, ie. descending order. */
14429 for (reg = 15; reg >= -1; reg--)
14430 {
14431 /* Save registers in blocks. */
14432 if (reg < 0
14433 || !(wr_mask & (1 << reg)))
14434 {
14435 /* We found an unsaved reg. Generate opcodes to save the
14436 preceeding block. */
14437 if (reg != hi_reg)
14438 {
14439 if (reg == 9)
14440 {
14441 /* Short form. */
14442 op = 0xc0 | (hi_reg - 10);
14443 add_unwind_opcode (op, 1);
14444 }
14445 else
14446 {
14447 /* Long form. */
14448 op = 0xc600 | ((reg + 1) << 4) | ((hi_reg - reg) - 1);
14449 add_unwind_opcode (op, 2);
14450 }
14451 }
14452 hi_reg = reg - 1;
14453 }
14454 }
14455 }
14456 return;
14457 error:
14458 ignore_rest_of_line ();
14459 }
14460
14461
14462 /* Parse an unwind_save directive. */
14463
14464 static void
14465 s_arm_unwind_save (int ignored ATTRIBUTE_UNUSED)
14466 {
14467 char *saved_ptr;
14468 int reg;
14469
14470 /* Figure out what sort of save we have. */
14471 SKIP_WHITESPACE ();
14472 saved_ptr = input_line_pointer;
14473
14474 reg = arm_reg_parse (&input_line_pointer, all_reg_maps[REG_TYPE_FN].htab);
14475 if (reg != FAIL)
14476 {
14477 s_arm_unwind_save_fpa (reg);
14478 return;
14479 }
14480
14481 if (*input_line_pointer == '{')
14482 input_line_pointer++;
14483
14484 SKIP_WHITESPACE ();
14485
14486 reg = arm_reg_parse (&input_line_pointer, all_reg_maps[REG_TYPE_RN].htab);
14487 if (reg != FAIL)
14488 {
14489 input_line_pointer = saved_ptr;
14490 s_arm_unwind_save_core ();
14491 return;
14492 }
14493
14494 reg = arm_reg_parse (&input_line_pointer, all_reg_maps[REG_TYPE_DN].htab);
14495 if (reg != FAIL)
14496 {
14497 input_line_pointer = saved_ptr;
14498 s_arm_unwind_save_vfp ();
14499 return;
14500 }
14501
14502 reg = arm_reg_parse (&input_line_pointer,
14503 all_reg_maps[REG_TYPE_IWMMXT].htab);
14504 if (reg != FAIL)
14505 {
14506 input_line_pointer = saved_ptr;
14507 s_arm_unwind_save_wmmx ();
14508 return;
14509 }
14510
14511 /* TODO: Maverick registers. */
14512 as_bad (_("unrecognised register"));
14513 }
14514
14515
14516 /* Parse an unwind_movsp directive. */
14517
14518 static void
14519 s_arm_unwind_movsp (int ignored ATTRIBUTE_UNUSED)
14520 {
14521 int reg;
14522 valueT op;
14523
14524 SKIP_WHITESPACE ();
14525 reg = reg_required_here (&input_line_pointer, -1);
14526 if (reg == FAIL)
14527 {
14528 as_bad (_("ARM register expected"));
14529 ignore_rest_of_line ();
14530 return;
14531 }
14532
14533 if (reg == 13 || reg == 15)
14534 {
14535 as_bad (_("r%d not permitted in .unwind_movsp directive"), reg);
14536 ignore_rest_of_line ();
14537 return;
14538 }
14539
14540 if (unwind.fp_reg != 13)
14541 as_bad (_("unexpected .unwind_movsp directive"));
14542
14543 /* Generate opcode to restore the value. */
14544 op = 0x90 | reg;
14545 add_unwind_opcode (op, 1);
14546
14547 /* Record the information for later. */
14548 unwind.fp_reg = reg;
14549 unwind.fp_offset = unwind.frame_size;
14550 unwind.sp_restored = 1;
14551 demand_empty_rest_of_line ();
14552 }
14553
14554
14555 /* Parse #<number>. */
14556
14557 static int
14558 require_hashconst (int * val)
14559 {
14560 expressionS exp;
14561
14562 SKIP_WHITESPACE ();
14563 if (*input_line_pointer == '#')
14564 {
14565 input_line_pointer++;
14566 expression (&exp);
14567 }
14568 else
14569 exp.X_op = O_illegal;
14570
14571 if (exp.X_op != O_constant)
14572 {
14573 as_bad (_("expected #constant"));
14574 ignore_rest_of_line ();
14575 return FAIL;
14576 }
14577 *val = exp.X_add_number;
14578 return SUCCESS;
14579 }
14580
14581 /* Parse an unwind_pad directive. */
14582
14583 static void
14584 s_arm_unwind_pad (int ignored ATTRIBUTE_UNUSED)
14585 {
14586 int offset;
14587
14588 if (require_hashconst (&offset) == FAIL)
14589 return;
14590
14591 if (offset & 3)
14592 {
14593 as_bad (_("stack increment must be multiple of 4"));
14594 ignore_rest_of_line ();
14595 return;
14596 }
14597
14598 /* Don't generate any opcodes, just record the details for later. */
14599 unwind.frame_size += offset;
14600 unwind.pending_offset += offset;
14601
14602 demand_empty_rest_of_line ();
14603 }
14604
14605 /* Parse an unwind_setfp directive. */
14606
14607 static void
14608 s_arm_unwind_setfp (int ignored ATTRIBUTE_UNUSED)
14609 {
14610 int sp_reg;
14611 int fp_reg;
14612 int offset;
14613
14614 fp_reg = reg_required_here (&input_line_pointer, -1);
14615 if (skip_past_comma (&input_line_pointer) == FAIL)
14616 sp_reg = FAIL;
14617 else
14618 sp_reg = reg_required_here (&input_line_pointer, -1);
14619
14620 if (fp_reg == FAIL || sp_reg == FAIL)
14621 {
14622 as_bad (_("expected <reg>, <reg>"));
14623 ignore_rest_of_line ();
14624 return;
14625 }
14626
14627 /* Optonal constant. */
14628 if (skip_past_comma (&input_line_pointer) != FAIL)
14629 {
14630 if (require_hashconst (&offset) == FAIL)
14631 return;
14632 }
14633 else
14634 offset = 0;
14635
14636 demand_empty_rest_of_line ();
14637
14638 if (sp_reg != 13 && sp_reg != unwind.fp_reg)
14639 {
14640 as_bad (_("register must be either sp or set by a previous"
14641 "unwind_movsp directive"));
14642 return;
14643 }
14644
14645 /* Don't generate any opcodes, just record the information for later. */
14646 unwind.fp_reg = fp_reg;
14647 unwind.fp_used = 1;
14648 if (sp_reg == 13)
14649 unwind.fp_offset = unwind.frame_size - offset;
14650 else
14651 unwind.fp_offset -= offset;
14652 }
14653
14654 /* Parse an unwind_raw directive. */
14655
14656 static void
14657 s_arm_unwind_raw (int ignored ATTRIBUTE_UNUSED)
14658 {
14659 expressionS exp;
14660 /* This is an arbitary limit. */
14661 unsigned char op[16];
14662 int count;
14663
14664 SKIP_WHITESPACE ();
14665 expression (&exp);
14666 if (exp.X_op == O_constant
14667 && skip_past_comma (&input_line_pointer) != FAIL)
14668 {
14669 unwind.frame_size += exp.X_add_number;
14670 expression (&exp);
14671 }
14672 else
14673 exp.X_op = O_illegal;
14674
14675 if (exp.X_op != O_constant)
14676 {
14677 as_bad (_("expected <offset>, <opcode>"));
14678 ignore_rest_of_line ();
14679 return;
14680 }
14681
14682 count = 0;
14683
14684 /* Parse the opcode. */
14685 for (;;)
14686 {
14687 if (count >= 16)
14688 {
14689 as_bad (_("unwind opcode too long"));
14690 ignore_rest_of_line ();
14691 }
14692 if (exp.X_op != O_constant || exp.X_add_number & ~0xff)
14693 {
14694 as_bad (_("invalid unwind opcode"));
14695 ignore_rest_of_line ();
14696 return;
14697 }
14698 op[count++] = exp.X_add_number;
14699
14700 /* Parse the next byte. */
14701 if (skip_past_comma (&input_line_pointer) == FAIL)
14702 break;
14703
14704 expression (&exp);
14705 }
14706
14707 /* Add the opcode bytes in reverse order. */
14708 while (count--)
14709 add_unwind_opcode (op[count], 1);
14710
14711 demand_empty_rest_of_line ();
14712 }
14713
14714 #endif /* OBJ_ELF */
14715
14716 /* This is called from HANDLE_ALIGN in write.c. Fill in the contents
14717 of an rs_align_code fragment. */
14718
14719 void
14720 arm_handle_align (fragS * fragP)
14721 {
14722 static char const arm_noop[4] = { 0x00, 0x00, 0xa0, 0xe1 };
14723 static char const thumb_noop[2] = { 0xc0, 0x46 };
14724 static char const arm_bigend_noop[4] = { 0xe1, 0xa0, 0x00, 0x00 };
14725 static char const thumb_bigend_noop[2] = { 0x46, 0xc0 };
14726
14727 int bytes, fix, noop_size;
14728 char * p;
14729 const char * noop;
14730
14731 if (fragP->fr_type != rs_align_code)
14732 return;
14733
14734 bytes = fragP->fr_next->fr_address - fragP->fr_address - fragP->fr_fix;
14735 p = fragP->fr_literal + fragP->fr_fix;
14736 fix = 0;
14737
14738 if (bytes > MAX_MEM_FOR_RS_ALIGN_CODE)
14739 bytes &= MAX_MEM_FOR_RS_ALIGN_CODE;
14740
14741 if (fragP->tc_frag_data)
14742 {
14743 if (target_big_endian)
14744 noop = thumb_bigend_noop;
14745 else
14746 noop = thumb_noop;
14747 noop_size = sizeof (thumb_noop);
14748 }
14749 else
14750 {
14751 if (target_big_endian)
14752 noop = arm_bigend_noop;
14753 else
14754 noop = arm_noop;
14755 noop_size = sizeof (arm_noop);
14756 }
14757
14758 if (bytes & (noop_size - 1))
14759 {
14760 fix = bytes & (noop_size - 1);
14761 memset (p, 0, fix);
14762 p += fix;
14763 bytes -= fix;
14764 }
14765
14766 while (bytes >= noop_size)
14767 {
14768 memcpy (p, noop, noop_size);
14769 p += noop_size;
14770 bytes -= noop_size;
14771 fix += noop_size;
14772 }
14773
14774 fragP->fr_fix += fix;
14775 fragP->fr_var = noop_size;
14776 }
14777
14778 /* Called from md_do_align. Used to create an alignment
14779 frag in a code section. */
14780
14781 void
14782 arm_frag_align_code (int n, int max)
14783 {
14784 char * p;
14785
14786 /* We assume that there will never be a requirement
14787 to support alignments greater than 32 bytes. */
14788 if (max > MAX_MEM_FOR_RS_ALIGN_CODE)
14789 as_fatal (_("alignments greater than 32 bytes not supported in .text sections."));
14790
14791 p = frag_var (rs_align_code,
14792 MAX_MEM_FOR_RS_ALIGN_CODE,
14793 1,
14794 (relax_substateT) max,
14795 (symbolS *) NULL,
14796 (offsetT) n,
14797 (char *) NULL);
14798 *p = 0;
14799 }
14800
14801 /* Perform target specific initialisation of a frag. */
14802
14803 void
14804 arm_init_frag (fragS * fragP)
14805 {
14806 /* Record whether this frag is in an ARM or a THUMB area. */
14807 fragP->tc_frag_data = thumb_mode;
14808 }
14809
14810 #ifdef OBJ_ELF
14811
14812 /* Convert REGNAME to a DWARF-2 register number. */
14813
14814 int
14815 tc_arm_regname_to_dw2regnum (const char *regname)
14816 {
14817 unsigned int i;
14818
14819 for (i = 0; rn_table[i].name; i++)
14820 if (streq (regname, rn_table[i].name))
14821 return rn_table[i].number;
14822
14823 return -1;
14824 }
14825
14826 /* Initialize the DWARF-2 unwind information for this procedure. */
14827
14828 void
14829 tc_arm_frame_initial_instructions (void)
14830 {
14831 cfi_add_CFA_def_cfa (REG_SP, 0);
14832 }
14833 #endif
14834
14835 /* This table describes all the machine specific pseudo-ops the assembler
14836 has to support. The fields are:
14837 pseudo-op name without dot
14838 function to call to execute this pseudo-op
14839 Integer arg to pass to the function. */
14840
14841 const pseudo_typeS md_pseudo_table[] =
14842 {
14843 /* Never called because '.req' does not start a line. */
14844 { "req", s_req, 0 },
14845 { "unreq", s_unreq, 0 },
14846 { "bss", s_bss, 0 },
14847 { "align", s_align, 0 },
14848 { "arm", s_arm, 0 },
14849 { "thumb", s_thumb, 0 },
14850 { "code", s_code, 0 },
14851 { "force_thumb", s_force_thumb, 0 },
14852 { "thumb_func", s_thumb_func, 0 },
14853 { "thumb_set", s_thumb_set, 0 },
14854 { "even", s_even, 0 },
14855 { "ltorg", s_ltorg, 0 },
14856 { "pool", s_ltorg, 0 },
14857 #ifdef OBJ_ELF
14858 { "word", s_arm_elf_cons, 4 },
14859 { "long", s_arm_elf_cons, 4 },
14860 { "rel31", s_arm_rel31, 0 },
14861 { "fnstart", s_arm_unwind_fnstart, 0 },
14862 { "fnend", s_arm_unwind_fnend, 0 },
14863 { "cantunwind", s_arm_unwind_cantunwind, 0 },
14864 { "personality", s_arm_unwind_personality, 0 },
14865 { "personalityindex", s_arm_unwind_personalityindex, 0 },
14866 { "handlerdata", s_arm_unwind_handlerdata, 0 },
14867 { "save", s_arm_unwind_save, 0 },
14868 { "movsp", s_arm_unwind_movsp, 0 },
14869 { "pad", s_arm_unwind_pad, 0 },
14870 { "setfp", s_arm_unwind_setfp, 0 },
14871 { "unwind_raw", s_arm_unwind_raw, 0 },
14872 #else
14873 { "word", cons, 4},
14874 #endif
14875 { "extend", float_cons, 'x' },
14876 { "ldouble", float_cons, 'x' },
14877 { "packed", float_cons, 'p' },
14878 { 0, 0, 0 }
14879 };