* config/tc-arm.c (do_mla): Rename to do_mlas, take second
[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_mlas (char * str, bfd_boolean is_mls)
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 /* This restriction does not apply to mls (nor to mla in v6, but
2850 that's hard to detect at present). */
2851 if (rm == rd && !is_mls)
2852 as_tsktsk (_("rd and rm should be different in mla"));
2853
2854 if (skip_past_comma (&str) == FAIL
2855 || (rd = reg_required_here (&str, 8)) == FAIL
2856 || skip_past_comma (&str) == FAIL
2857 || (rm = reg_required_here (&str, 12)) == FAIL)
2858 {
2859 inst.error = BAD_ARGS;
2860 return;
2861 }
2862
2863 if (rd == REG_PC || rm == REG_PC)
2864 {
2865 inst.error = BAD_PC;
2866 return;
2867 }
2868
2869 end_of_line (str);
2870 }
2871
2872 static void
2873 do_mla (char *str)
2874 {
2875 do_mlas (str, FALSE);
2876 }
2877
2878 static void
2879 do_mls (char *str)
2880 {
2881 do_mlas (str, TRUE);
2882 }
2883
2884 /* Expects *str -> the characters "acc0", possibly with leading blanks.
2885 Advances *str to the next non-alphanumeric.
2886 Returns 0, or else FAIL (in which case sets inst.error).
2887
2888 (In a future XScale, there may be accumulators other than zero.
2889 At that time this routine and its callers can be upgraded to suit.) */
2890
2891 static int
2892 accum0_required_here (char ** str)
2893 {
2894 static char buff [128]; /* Note the address is taken. Hence, static. */
2895 char * p = * str;
2896 char c;
2897 int result = 0; /* The accum number. */
2898
2899 skip_whitespace (p);
2900
2901 *str = p; /* Advance caller's string pointer too. */
2902 c = *p++;
2903 while (ISALNUM (c))
2904 c = *p++;
2905
2906 *--p = 0; /* Aap nul into input buffer at non-alnum. */
2907
2908 if (! ( streq (*str, "acc0") || streq (*str, "ACC0")))
2909 {
2910 sprintf (buff, _("acc0 expected, not '%.100s'"), *str);
2911 inst.error = buff;
2912 result = FAIL;
2913 }
2914
2915 *p = c; /* Unzap. */
2916 *str = p; /* Caller's string pointer to after match. */
2917 return result;
2918 }
2919
2920 static int
2921 ldst_extend_v4 (char ** str)
2922 {
2923 int add = INDEX_UP;
2924
2925 switch (**str)
2926 {
2927 case '#':
2928 case '$':
2929 (*str)++;
2930 if (my_get_expression (& inst.reloc.exp, str))
2931 return FAIL;
2932
2933 if (inst.reloc.exp.X_op == O_constant)
2934 {
2935 int value = inst.reloc.exp.X_add_number;
2936
2937 if (value < -255 || value > 255)
2938 {
2939 inst.error = _("address offset too large");
2940 return FAIL;
2941 }
2942
2943 if (value < 0)
2944 {
2945 value = -value;
2946 add = 0;
2947 }
2948
2949 /* Halfword and signextension instructions have the
2950 immediate value split across bits 11..8 and bits 3..0. */
2951 inst.instruction |= (add | HWOFFSET_IMM
2952 | ((value >> 4) << 8) | (value & 0xF));
2953 }
2954 else
2955 {
2956 inst.instruction |= HWOFFSET_IMM;
2957 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
2958 inst.reloc.pc_rel = 0;
2959 }
2960 return SUCCESS;
2961
2962 case '-':
2963 add = 0;
2964 /* Fall through. */
2965
2966 case '+':
2967 (*str)++;
2968 /* Fall through. */
2969
2970 default:
2971 if (reg_required_here (str, 0) == FAIL)
2972 return FAIL;
2973
2974 inst.instruction |= add;
2975 return SUCCESS;
2976 }
2977 }
2978
2979 /* Expects **str -> after a comma. May be leading blanks.
2980 Advances *str, recognizing a load mode, and setting inst.instruction.
2981 Returns rn, or else FAIL (in which case may set inst.error
2982 and not advance str)
2983
2984 Note: doesn't know Rd, so no err checks that require such knowledge. */
2985
2986 static int
2987 ld_mode_required_here (char ** string)
2988 {
2989 char * str = * string;
2990 int rn;
2991 int pre_inc = 0;
2992
2993 skip_whitespace (str);
2994
2995 if (* str == '[')
2996 {
2997 str++;
2998
2999 skip_whitespace (str);
3000
3001 if ((rn = reg_required_here (& str, 16)) == FAIL)
3002 return FAIL;
3003
3004 skip_whitespace (str);
3005
3006 if (* str == ']')
3007 {
3008 str ++;
3009
3010 if (skip_past_comma (& str) == SUCCESS)
3011 {
3012 /* [Rn],... (post inc) */
3013 if (ldst_extend_v4 (&str) == FAIL)
3014 return FAIL;
3015 }
3016 else /* [Rn] */
3017 {
3018 skip_whitespace (str);
3019
3020 if (* str == '!')
3021 {
3022 str ++;
3023 inst.instruction |= WRITE_BACK;
3024 }
3025
3026 inst.instruction |= INDEX_UP | HWOFFSET_IMM;
3027 pre_inc = 1;
3028 }
3029 }
3030 else /* [Rn,...] */
3031 {
3032 if (skip_past_comma (& str) == FAIL)
3033 {
3034 inst.error = _("pre-indexed expression expected");
3035 return FAIL;
3036 }
3037
3038 pre_inc = 1;
3039
3040 if (ldst_extend_v4 (&str) == FAIL)
3041 return FAIL;
3042
3043 skip_whitespace (str);
3044
3045 if (* str ++ != ']')
3046 {
3047 inst.error = _("missing ]");
3048 return FAIL;
3049 }
3050
3051 skip_whitespace (str);
3052
3053 if (* str == '!')
3054 {
3055 str ++;
3056 inst.instruction |= WRITE_BACK;
3057 }
3058 }
3059 }
3060 else if (* str == '=') /* ldr's "r,=label" syntax */
3061 /* We should never reach here, because <text> = <expression> is
3062 caught gas/read.c read_a_source_file() as a .set operation. */
3063 return FAIL;
3064 else /* PC +- 8 bit immediate offset. */
3065 {
3066 if (my_get_expression (& inst.reloc.exp, & str))
3067 return FAIL;
3068
3069 inst.instruction |= HWOFFSET_IMM; /* The I bit. */
3070 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
3071 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
3072 inst.reloc.pc_rel = 1;
3073 inst.instruction |= (REG_PC << 16);
3074
3075 rn = REG_PC;
3076 pre_inc = 1;
3077 }
3078
3079 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
3080 * string = str;
3081
3082 return rn;
3083 }
3084
3085 /* ARM V5E (El Segundo) signed-multiply-accumulate (argument parse)
3086 SMLAxy{cond} Rd,Rm,Rs,Rn
3087 SMLAWy{cond} Rd,Rm,Rs,Rn
3088 Error if any register is R15. */
3089
3090 static void
3091 do_smla (char * str)
3092 {
3093 int rd, rm, rs, rn;
3094
3095 skip_whitespace (str);
3096
3097 if ((rd = reg_required_here (& str, 16)) == FAIL
3098 || skip_past_comma (& str) == FAIL
3099 || (rm = reg_required_here (& str, 0)) == FAIL
3100 || skip_past_comma (& str) == FAIL
3101 || (rs = reg_required_here (& str, 8)) == FAIL
3102 || skip_past_comma (& str) == FAIL
3103 || (rn = reg_required_here (& str, 12)) == FAIL)
3104 inst.error = BAD_ARGS;
3105
3106 else if (rd == REG_PC || rm == REG_PC || rs == REG_PC || rn == REG_PC)
3107 inst.error = BAD_PC;
3108
3109 else
3110 end_of_line (str);
3111 }
3112
3113 /* ARM V5E (El Segundo) signed-multiply-accumulate-long (argument parse)
3114 SMLALxy{cond} Rdlo,Rdhi,Rm,Rs
3115 Error if any register is R15.
3116 Warning if Rdlo == Rdhi. */
3117
3118 static void
3119 do_smlal (char * str)
3120 {
3121 int rdlo, rdhi, rm, rs;
3122
3123 skip_whitespace (str);
3124
3125 if ((rdlo = reg_required_here (& str, 12)) == FAIL
3126 || skip_past_comma (& str) == FAIL
3127 || (rdhi = reg_required_here (& str, 16)) == FAIL
3128 || skip_past_comma (& str) == FAIL
3129 || (rm = reg_required_here (& str, 0)) == FAIL
3130 || skip_past_comma (& str) == FAIL
3131 || (rs = reg_required_here (& str, 8)) == FAIL)
3132 {
3133 inst.error = BAD_ARGS;
3134 return;
3135 }
3136
3137 if (rdlo == REG_PC || rdhi == REG_PC || rm == REG_PC || rs == REG_PC)
3138 {
3139 inst.error = BAD_PC;
3140 return;
3141 }
3142
3143 if (rdlo == rdhi)
3144 as_tsktsk (_("rdhi and rdlo must be different"));
3145
3146 end_of_line (str);
3147 }
3148
3149 /* ARM V5E (El Segundo) signed-multiply (argument parse)
3150 SMULxy{cond} Rd,Rm,Rs
3151 Error if any register is R15. */
3152
3153 static void
3154 do_smul (char * str)
3155 {
3156 int rd, rm, rs;
3157
3158 skip_whitespace (str);
3159
3160 if ((rd = reg_required_here (& str, 16)) == FAIL
3161 || skip_past_comma (& str) == FAIL
3162 || (rm = reg_required_here (& str, 0)) == FAIL
3163 || skip_past_comma (& str) == FAIL
3164 || (rs = reg_required_here (& str, 8)) == FAIL)
3165 inst.error = BAD_ARGS;
3166
3167 else if (rd == REG_PC || rm == REG_PC || rs == REG_PC)
3168 inst.error = BAD_PC;
3169
3170 else
3171 end_of_line (str);
3172 }
3173
3174 /* ARM V5E (El Segundo) saturating-add/subtract (argument parse)
3175 Q[D]{ADD,SUB}{cond} Rd,Rm,Rn
3176 Error if any register is R15. */
3177
3178 static void
3179 do_qadd (char * str)
3180 {
3181 int rd, rm, rn;
3182
3183 skip_whitespace (str);
3184
3185 if ((rd = reg_required_here (& str, 12)) == FAIL
3186 || skip_past_comma (& str) == FAIL
3187 || (rm = reg_required_here (& str, 0)) == FAIL
3188 || skip_past_comma (& str) == FAIL
3189 || (rn = reg_required_here (& str, 16)) == FAIL)
3190 inst.error = BAD_ARGS;
3191
3192 else if (rd == REG_PC || rm == REG_PC || rn == REG_PC)
3193 inst.error = BAD_PC;
3194
3195 else
3196 end_of_line (str);
3197 }
3198
3199 /* ARM V5E (el Segundo)
3200 MCRRcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
3201 MRRCcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
3202
3203 These are equivalent to the XScale instructions MAR and MRA,
3204 respectively, when coproc == 0, opcode == 0, and CRm == 0.
3205
3206 Result unpredicatable if Rd or Rn is R15. */
3207
3208 static void
3209 do_co_reg2c (char * str)
3210 {
3211 int rd, rn;
3212
3213 skip_whitespace (str);
3214
3215 if (co_proc_number (& str) == FAIL)
3216 {
3217 if (!inst.error)
3218 inst.error = BAD_ARGS;
3219 return;
3220 }
3221
3222 if (skip_past_comma (& str) == FAIL
3223 || cp_opc_expr (& str, 4, 4) == FAIL)
3224 {
3225 if (!inst.error)
3226 inst.error = BAD_ARGS;
3227 return;
3228 }
3229
3230 if (skip_past_comma (& str) == FAIL
3231 || (rd = reg_required_here (& str, 12)) == FAIL)
3232 {
3233 if (!inst.error)
3234 inst.error = BAD_ARGS;
3235 return;
3236 }
3237
3238 if (skip_past_comma (& str) == FAIL
3239 || (rn = reg_required_here (& str, 16)) == FAIL)
3240 {
3241 if (!inst.error)
3242 inst.error = BAD_ARGS;
3243 return;
3244 }
3245
3246 /* Unpredictable result if rd or rn is R15. */
3247 if (rd == REG_PC || rn == REG_PC)
3248 as_tsktsk
3249 (_("Warning: instruction unpredictable when using r15"));
3250
3251 if (skip_past_comma (& str) == FAIL
3252 || cp_reg_required_here (& str, 0) == FAIL)
3253 {
3254 if (!inst.error)
3255 inst.error = BAD_ARGS;
3256 return;
3257 }
3258
3259 end_of_line (str);
3260 }
3261
3262 /* ARM V5 count-leading-zeroes instruction (argument parse)
3263 CLZ{<cond>} <Rd>, <Rm>
3264 Condition defaults to COND_ALWAYS.
3265 Error if Rd or Rm are R15. */
3266
3267 static void
3268 do_clz (char * str)
3269 {
3270 int rd, rm;
3271
3272 skip_whitespace (str);
3273
3274 if (((rd = reg_required_here (& str, 12)) == FAIL)
3275 || (skip_past_comma (& str) == FAIL)
3276 || ((rm = reg_required_here (& str, 0)) == FAIL))
3277 inst.error = BAD_ARGS;
3278
3279 else if (rd == REG_PC || rm == REG_PC )
3280 inst.error = BAD_PC;
3281
3282 else
3283 end_of_line (str);
3284 }
3285
3286 /* ARM V5 (argument parse)
3287 LDC2{L} <coproc>, <CRd>, <addressing mode>
3288 STC2{L} <coproc>, <CRd>, <addressing mode>
3289 Instruction is not conditional, and has 0xf in the condition field.
3290 Otherwise, it's the same as LDC/STC. */
3291
3292 static void
3293 do_lstc2 (char * str)
3294 {
3295 skip_whitespace (str);
3296
3297 if (co_proc_number (& str) == FAIL)
3298 {
3299 if (!inst.error)
3300 inst.error = BAD_ARGS;
3301 }
3302 else if (skip_past_comma (& str) == FAIL
3303 || cp_reg_required_here (& str, 12) == FAIL)
3304 {
3305 if (!inst.error)
3306 inst.error = BAD_ARGS;
3307 }
3308 else if (skip_past_comma (& str) == FAIL
3309 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
3310 {
3311 if (! inst.error)
3312 inst.error = BAD_ARGS;
3313 }
3314 else
3315 end_of_line (str);
3316 }
3317
3318 /* ARM V5 (argument parse)
3319 CDP2 <coproc>, <opcode_1>, <CRd>, <CRn>, <CRm>, <opcode_2>
3320 Instruction is not conditional, and has 0xf in the condition field.
3321 Otherwise, it's the same as CDP. */
3322
3323 static void
3324 do_cdp2 (char * str)
3325 {
3326 skip_whitespace (str);
3327
3328 if (co_proc_number (& str) == FAIL)
3329 {
3330 if (!inst.error)
3331 inst.error = BAD_ARGS;
3332 return;
3333 }
3334
3335 if (skip_past_comma (& str) == FAIL
3336 || cp_opc_expr (& str, 20,4) == FAIL)
3337 {
3338 if (!inst.error)
3339 inst.error = BAD_ARGS;
3340 return;
3341 }
3342
3343 if (skip_past_comma (& str) == FAIL
3344 || cp_reg_required_here (& str, 12) == FAIL)
3345 {
3346 if (!inst.error)
3347 inst.error = BAD_ARGS;
3348 return;
3349 }
3350
3351 if (skip_past_comma (& str) == FAIL
3352 || cp_reg_required_here (& str, 16) == FAIL)
3353 {
3354 if (!inst.error)
3355 inst.error = BAD_ARGS;
3356 return;
3357 }
3358
3359 if (skip_past_comma (& str) == FAIL
3360 || cp_reg_required_here (& str, 0) == FAIL)
3361 {
3362 if (!inst.error)
3363 inst.error = BAD_ARGS;
3364 return;
3365 }
3366
3367 if (skip_past_comma (& str) == SUCCESS)
3368 {
3369 if (cp_opc_expr (& str, 5, 3) == FAIL)
3370 {
3371 if (!inst.error)
3372 inst.error = BAD_ARGS;
3373 return;
3374 }
3375 }
3376
3377 end_of_line (str);
3378 }
3379
3380 /* ARM V5 (argument parse)
3381 MCR2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
3382 MRC2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
3383 Instruction is not conditional, and has 0xf in the condition field.
3384 Otherwise, it's the same as MCR/MRC. */
3385
3386 static void
3387 do_co_reg2 (char * str)
3388 {
3389 skip_whitespace (str);
3390
3391 if (co_proc_number (& str) == FAIL)
3392 {
3393 if (!inst.error)
3394 inst.error = BAD_ARGS;
3395 return;
3396 }
3397
3398 if (skip_past_comma (& str) == FAIL
3399 || cp_opc_expr (& str, 21, 3) == FAIL)
3400 {
3401 if (!inst.error)
3402 inst.error = BAD_ARGS;
3403 return;
3404 }
3405
3406 if (skip_past_comma (& str) == FAIL
3407 || reg_required_here (& str, 12) == FAIL)
3408 {
3409 if (!inst.error)
3410 inst.error = BAD_ARGS;
3411 return;
3412 }
3413
3414 if (skip_past_comma (& str) == FAIL
3415 || cp_reg_required_here (& str, 16) == FAIL)
3416 {
3417 if (!inst.error)
3418 inst.error = BAD_ARGS;
3419 return;
3420 }
3421
3422 if (skip_past_comma (& str) == FAIL
3423 || cp_reg_required_here (& str, 0) == FAIL)
3424 {
3425 if (!inst.error)
3426 inst.error = BAD_ARGS;
3427 return;
3428 }
3429
3430 if (skip_past_comma (& str) == SUCCESS)
3431 {
3432 if (cp_opc_expr (& str, 5, 3) == FAIL)
3433 {
3434 if (!inst.error)
3435 inst.error = BAD_ARGS;
3436 return;
3437 }
3438 }
3439
3440 end_of_line (str);
3441 }
3442
3443 static void
3444 do_bx (char * str)
3445 {
3446 int reg;
3447
3448 skip_whitespace (str);
3449
3450 if ((reg = reg_required_here (&str, 0)) == FAIL)
3451 {
3452 inst.error = BAD_ARGS;
3453 return;
3454 }
3455
3456 /* Note - it is not illegal to do a "bx pc". Useless, but not illegal. */
3457 if (reg == REG_PC)
3458 as_tsktsk (_("use of r15 in bx in ARM mode is not really useful"));
3459
3460 end_of_line (str);
3461 }
3462
3463 /* ARM v5TEJ. Jump to Jazelle code. */
3464
3465 static void
3466 do_bxj (char * str)
3467 {
3468 int reg;
3469
3470 skip_whitespace (str);
3471
3472 if ((reg = reg_required_here (&str, 0)) == FAIL)
3473 {
3474 inst.error = BAD_ARGS;
3475 return;
3476 }
3477
3478 /* Note - it is not illegal to do a "bxj pc". Useless, but not illegal. */
3479 if (reg == REG_PC)
3480 as_tsktsk (_("use of r15 in bxj is not really useful"));
3481
3482 end_of_line (str);
3483 }
3484
3485 /* ARM V6 umaal (argument parse). */
3486
3487 static void
3488 do_umaal (char * str)
3489 {
3490 int rdlo, rdhi, rm, rs;
3491
3492 skip_whitespace (str);
3493 if ((rdlo = reg_required_here (& str, 12)) == FAIL
3494 || skip_past_comma (& str) == FAIL
3495 || (rdhi = reg_required_here (& str, 16)) == FAIL
3496 || skip_past_comma (& str) == FAIL
3497 || (rm = reg_required_here (& str, 0)) == FAIL
3498 || skip_past_comma (& str) == FAIL
3499 || (rs = reg_required_here (& str, 8)) == FAIL)
3500 {
3501 inst.error = BAD_ARGS;
3502 return;
3503 }
3504
3505 if (rdlo == REG_PC || rdhi == REG_PC || rm == REG_PC || rs == REG_PC)
3506 {
3507 inst.error = BAD_PC;
3508 return;
3509 }
3510
3511 end_of_line (str);
3512 }
3513
3514 /* ARM V6 strex (argument parse). */
3515
3516 static void
3517 do_strex (char * str)
3518 {
3519 int rd, rm, rn;
3520
3521 /* Parse Rd, Rm,. */
3522 skip_whitespace (str);
3523 if ((rd = reg_required_here (& str, 12)) == FAIL
3524 || skip_past_comma (& str) == FAIL
3525 || (rm = reg_required_here (& str, 0)) == FAIL
3526 || skip_past_comma (& str) == FAIL)
3527 {
3528 inst.error = BAD_ARGS;
3529 return;
3530 }
3531 if (rd == REG_PC || rm == REG_PC)
3532 {
3533 inst.error = BAD_PC;
3534 return;
3535 }
3536 if (rd == rm)
3537 {
3538 inst.error = _("Rd equal to Rm or Rn yields unpredictable results");
3539 return;
3540 }
3541
3542 /* Skip past '['. */
3543 if ((strlen (str) >= 1)
3544 && strncmp (str, "[", 1) == 0)
3545 str += 1;
3546
3547 skip_whitespace (str);
3548
3549 /* Parse Rn. */
3550 if ((rn = reg_required_here (& str, 16)) == FAIL)
3551 {
3552 inst.error = BAD_ARGS;
3553 return;
3554 }
3555 else if (rn == REG_PC)
3556 {
3557 inst.error = BAD_PC;
3558 return;
3559 }
3560 if (rd == rn)
3561 {
3562 inst.error = _("Rd equal to Rm or Rn yields unpredictable results");
3563 return;
3564 }
3565 skip_whitespace (str);
3566
3567 /* Skip past ']'. */
3568 if ((strlen (str) >= 1)
3569 && strncmp (str, "]", 1) == 0)
3570 str += 1;
3571
3572 end_of_line (str);
3573 }
3574
3575 /* KIND indicates what kind of shifts are accepted. */
3576
3577 static int
3578 decode_shift (char ** str, int kind)
3579 {
3580 const struct asm_shift_name * shift;
3581 char * p;
3582 char c;
3583
3584 skip_whitespace (* str);
3585
3586 for (p = * str; ISALPHA (* p); p ++)
3587 ;
3588
3589 if (p == * str)
3590 {
3591 inst.error = _("shift expression expected");
3592 return FAIL;
3593 }
3594
3595 c = * p;
3596 * p = '\0';
3597 shift = (const struct asm_shift_name *) hash_find (arm_shift_hsh, * str);
3598 * p = c;
3599
3600 if (shift == NULL)
3601 {
3602 inst.error = _("shift expression expected");
3603 return FAIL;
3604 }
3605
3606 assert (shift->properties->index == shift_properties[shift->properties->index].index);
3607
3608 if (kind == SHIFT_LSL_OR_ASR_IMMEDIATE
3609 && shift->properties->index != SHIFT_LSL
3610 && shift->properties->index != SHIFT_ASR)
3611 {
3612 inst.error = _("'LSL' or 'ASR' required");
3613 return FAIL;
3614 }
3615 else if (kind == SHIFT_LSL_IMMEDIATE
3616 && shift->properties->index != SHIFT_LSL)
3617 {
3618 inst.error = _("'LSL' required");
3619 return FAIL;
3620 }
3621 else if (kind == SHIFT_ASR_IMMEDIATE
3622 && shift->properties->index != SHIFT_ASR)
3623 {
3624 inst.error = _("'ASR' required");
3625 return FAIL;
3626 }
3627
3628 if (shift->properties->index == SHIFT_RRX)
3629 {
3630 * str = p;
3631 inst.instruction |= shift->properties->bit_field;
3632 return SUCCESS;
3633 }
3634
3635 skip_whitespace (p);
3636
3637 if (kind == NO_SHIFT_RESTRICT && reg_required_here (& p, 8) != FAIL)
3638 {
3639 inst.instruction |= shift->properties->bit_field | SHIFT_BY_REG;
3640 * str = p;
3641 return SUCCESS;
3642 }
3643 else if (! is_immediate_prefix (* p))
3644 {
3645 inst.error = (NO_SHIFT_RESTRICT
3646 ? _("shift requires register or #expression")
3647 : _("shift requires #expression"));
3648 * str = p;
3649 return FAIL;
3650 }
3651
3652 inst.error = NULL;
3653 p ++;
3654
3655 if (my_get_expression (& inst.reloc.exp, & p))
3656 return FAIL;
3657
3658 /* Validate some simple #expressions. */
3659 if (inst.reloc.exp.X_op == O_constant)
3660 {
3661 unsigned num = inst.reloc.exp.X_add_number;
3662
3663 /* Reject operations greater than 32. */
3664 if (num > 32
3665 /* Reject a shift of 0 unless the mode allows it. */
3666 || (num == 0 && shift->properties->allows_0 == 0)
3667 /* Reject a shift of 32 unless the mode allows it. */
3668 || (num == 32 && shift->properties->allows_32 == 0)
3669 )
3670 {
3671 /* As a special case we allow a shift of zero for
3672 modes that do not support it to be recoded as an
3673 logical shift left of zero (ie nothing). We warn
3674 about this though. */
3675 if (num == 0)
3676 {
3677 as_warn (_("shift of 0 ignored."));
3678 shift = & shift_names[0];
3679 assert (shift->properties->index == SHIFT_LSL);
3680 }
3681 else
3682 {
3683 inst.error = _("invalid immediate shift");
3684 return FAIL;
3685 }
3686 }
3687
3688 /* Shifts of 32 are encoded as 0, for those shifts that
3689 support it. */
3690 if (num == 32)
3691 num = 0;
3692
3693 inst.instruction |= (num << 7) | shift->properties->bit_field;
3694 }
3695 else
3696 {
3697 inst.reloc.type = BFD_RELOC_ARM_SHIFT_IMM;
3698 inst.reloc.pc_rel = 0;
3699 inst.instruction |= shift->properties->bit_field;
3700 }
3701
3702 * str = p;
3703 return SUCCESS;
3704 }
3705
3706 static void
3707 do_sat (char ** str, int bias)
3708 {
3709 int rd, rm;
3710 expressionS expr;
3711
3712 skip_whitespace (*str);
3713
3714 /* Parse <Rd>, field. */
3715 if ((rd = reg_required_here (str, 12)) == FAIL
3716 || skip_past_comma (str) == FAIL)
3717 {
3718 inst.error = BAD_ARGS;
3719 return;
3720 }
3721 if (rd == REG_PC)
3722 {
3723 inst.error = BAD_PC;
3724 return;
3725 }
3726
3727 /* Parse #<immed>, field. */
3728 if (is_immediate_prefix (**str))
3729 (*str)++;
3730 else
3731 {
3732 inst.error = _("immediate expression expected");
3733 return;
3734 }
3735 if (my_get_expression (&expr, str))
3736 {
3737 inst.error = _("bad expression");
3738 return;
3739 }
3740 if (expr.X_op != O_constant)
3741 {
3742 inst.error = _("constant expression expected");
3743 return;
3744 }
3745 if (expr.X_add_number + bias < 0
3746 || expr.X_add_number + bias > 31)
3747 {
3748 inst.error = _("immediate value out of range");
3749 return;
3750 }
3751 inst.instruction |= (expr.X_add_number + bias) << 16;
3752 if (skip_past_comma (str) == FAIL)
3753 {
3754 inst.error = BAD_ARGS;
3755 return;
3756 }
3757
3758 /* Parse <Rm> field. */
3759 if ((rm = reg_required_here (str, 0)) == FAIL)
3760 {
3761 inst.error = BAD_ARGS;
3762 return;
3763 }
3764 if (rm == REG_PC)
3765 {
3766 inst.error = BAD_PC;
3767 return;
3768 }
3769
3770 if (skip_past_comma (str) == SUCCESS)
3771 decode_shift (str, SHIFT_LSL_OR_ASR_IMMEDIATE);
3772 }
3773
3774 /* ARM V6 ssat (argument parse). */
3775
3776 static void
3777 do_ssat (char * str)
3778 {
3779 do_sat (&str, /*bias=*/-1);
3780 end_of_line (str);
3781 }
3782
3783 /* ARM V6 usat (argument parse). */
3784
3785 static void
3786 do_usat (char * str)
3787 {
3788 do_sat (&str, /*bias=*/0);
3789 end_of_line (str);
3790 }
3791
3792 static void
3793 do_sat16 (char ** str, int bias)
3794 {
3795 int rd, rm;
3796 expressionS expr;
3797
3798 skip_whitespace (*str);
3799
3800 /* Parse the <Rd> field. */
3801 if ((rd = reg_required_here (str, 12)) == FAIL
3802 || skip_past_comma (str) == FAIL)
3803 {
3804 inst.error = BAD_ARGS;
3805 return;
3806 }
3807 if (rd == REG_PC)
3808 {
3809 inst.error = BAD_PC;
3810 return;
3811 }
3812
3813 /* Parse #<immed>, field. */
3814 if (is_immediate_prefix (**str))
3815 (*str)++;
3816 else
3817 {
3818 inst.error = _("immediate expression expected");
3819 return;
3820 }
3821 if (my_get_expression (&expr, str))
3822 {
3823 inst.error = _("bad expression");
3824 return;
3825 }
3826 if (expr.X_op != O_constant)
3827 {
3828 inst.error = _("constant expression expected");
3829 return;
3830 }
3831 if (expr.X_add_number + bias < 0
3832 || expr.X_add_number + bias > 15)
3833 {
3834 inst.error = _("immediate value out of range");
3835 return;
3836 }
3837 inst.instruction |= (expr.X_add_number + bias) << 16;
3838 if (skip_past_comma (str) == FAIL)
3839 {
3840 inst.error = BAD_ARGS;
3841 return;
3842 }
3843
3844 /* Parse <Rm> field. */
3845 if ((rm = reg_required_here (str, 0)) == FAIL)
3846 {
3847 inst.error = BAD_ARGS;
3848 return;
3849 }
3850 if (rm == REG_PC)
3851 {
3852 inst.error = BAD_PC;
3853 return;
3854 }
3855 }
3856
3857 /* ARM V6 ssat16 (argument parse). */
3858
3859 static void
3860 do_ssat16 (char * str)
3861 {
3862 do_sat16 (&str, /*bias=*/-1);
3863 end_of_line (str);
3864 }
3865
3866 static void
3867 do_usat16 (char * str)
3868 {
3869 do_sat16 (&str, /*bias=*/0);
3870 end_of_line (str);
3871 }
3872
3873 static void
3874 do_cps_mode (char ** str)
3875 {
3876 expressionS expr;
3877
3878 skip_whitespace (*str);
3879
3880 if (! is_immediate_prefix (**str))
3881 {
3882 inst.error = _("immediate expression expected");
3883 return;
3884 }
3885
3886 (*str)++; /* Strip off the immediate signifier. */
3887 if (my_get_expression (&expr, str))
3888 {
3889 inst.error = _("bad expression");
3890 return;
3891 }
3892
3893 if (expr.X_op != O_constant)
3894 {
3895 inst.error = _("constant expression expected");
3896 return;
3897 }
3898
3899 /* The mode is a 5 bit field. Valid values are 0-31. */
3900 if (((unsigned) expr.X_add_number) > 31
3901 || (inst.reloc.exp.X_add_number) < 0)
3902 {
3903 inst.error = _("invalid constant");
3904 return;
3905 }
3906
3907 inst.instruction |= expr.X_add_number;
3908 }
3909
3910 /* ARM V6 srs (argument parse). */
3911
3912 static void
3913 do_srs (char * str)
3914 {
3915 char *exclam;
3916 skip_whitespace (str);
3917 exclam = strchr (str, '!');
3918 if (exclam)
3919 *exclam = '\0';
3920 do_cps_mode (&str);
3921 if (exclam)
3922 *exclam = '!';
3923 if (*str == '!')
3924 {
3925 inst.instruction |= WRITE_BACK;
3926 str++;
3927 }
3928 end_of_line (str);
3929 }
3930
3931 /* ARM V6 SMMUL (argument parse). */
3932
3933 static void
3934 do_smmul (char * str)
3935 {
3936 int rd, rm, rs;
3937
3938 skip_whitespace (str);
3939 if ((rd = reg_required_here (&str, 16)) == FAIL
3940 || skip_past_comma (&str) == FAIL
3941 || (rm = reg_required_here (&str, 0)) == FAIL
3942 || skip_past_comma (&str) == FAIL
3943 || (rs = reg_required_here (&str, 8)) == FAIL)
3944 {
3945 inst.error = BAD_ARGS;
3946 return;
3947 }
3948
3949 if ( rd == REG_PC
3950 || rm == REG_PC
3951 || rs == REG_PC)
3952 {
3953 inst.error = BAD_PC;
3954 return;
3955 }
3956
3957 end_of_line (str);
3958 }
3959
3960 /* ARM V6 SMLALD (argument parse). */
3961
3962 static void
3963 do_smlald (char * str)
3964 {
3965 int rdlo, rdhi, rm, rs;
3966
3967 skip_whitespace (str);
3968 if ((rdlo = reg_required_here (&str, 12)) == FAIL
3969 || skip_past_comma (&str) == FAIL
3970 || (rdhi = reg_required_here (&str, 16)) == FAIL
3971 || skip_past_comma (&str) == FAIL
3972 || (rm = reg_required_here (&str, 0)) == FAIL
3973 || skip_past_comma (&str) == FAIL
3974 || (rs = reg_required_here (&str, 8)) == FAIL)
3975 {
3976 inst.error = BAD_ARGS;
3977 return;
3978 }
3979
3980 if ( rdlo == REG_PC
3981 || rdhi == REG_PC
3982 || rm == REG_PC
3983 || rs == REG_PC)
3984 {
3985 inst.error = BAD_PC;
3986 return;
3987 }
3988
3989 end_of_line (str);
3990 }
3991
3992 /* ARM V6 SMLAD (argument parse). Signed multiply accumulate dual.
3993 smlad{x}{<cond>} Rd, Rm, Rs, Rn */
3994
3995 static void
3996 do_smlad (char * str)
3997 {
3998 int rd, rm, rs, rn;
3999
4000 skip_whitespace (str);
4001 if ((rd = reg_required_here (&str, 16)) == FAIL
4002 || skip_past_comma (&str) == FAIL
4003 || (rm = reg_required_here (&str, 0)) == FAIL
4004 || skip_past_comma (&str) == FAIL
4005 || (rs = reg_required_here (&str, 8)) == FAIL
4006 || skip_past_comma (&str) == FAIL
4007 || (rn = reg_required_here (&str, 12)) == FAIL)
4008 {
4009 inst.error = BAD_ARGS;
4010 return;
4011 }
4012
4013 if ( rd == REG_PC
4014 || rn == REG_PC
4015 || rs == REG_PC
4016 || rm == REG_PC)
4017 {
4018 inst.error = BAD_PC;
4019 return;
4020 }
4021
4022 end_of_line (str);
4023 }
4024
4025 /* Returns true if the endian-specifier indicates big-endianness. */
4026
4027 static int
4028 do_endian_specifier (char * str)
4029 {
4030 int big_endian = 0;
4031
4032 skip_whitespace (str);
4033 if (strlen (str) < 2)
4034 inst.error = _("missing endian specifier");
4035 else if (strncasecmp (str, "BE", 2) == 0)
4036 {
4037 str += 2;
4038 big_endian = 1;
4039 }
4040 else if (strncasecmp (str, "LE", 2) == 0)
4041 str += 2;
4042 else
4043 inst.error = _("valid endian specifiers are be or le");
4044
4045 end_of_line (str);
4046
4047 return big_endian;
4048 }
4049
4050 /* ARM V6 SETEND (argument parse). Sets the E bit in the CPSR while
4051 preserving the other bits.
4052
4053 setend <endian_specifier>, where <endian_specifier> is either
4054 BE or LE. */
4055
4056 static void
4057 do_setend (char * str)
4058 {
4059 if (do_endian_specifier (str))
4060 inst.instruction |= 0x200;
4061 }
4062
4063 /* ARM V6 SXTH.
4064
4065 SXTH {<cond>} <Rd>, <Rm>{, <rotation>}
4066 Condition defaults to COND_ALWAYS.
4067 Error if any register uses R15. */
4068
4069 static void
4070 do_sxth (char * str)
4071 {
4072 int rd, rm;
4073 expressionS expr;
4074 int rotation_clear_mask = 0xfffff3ff;
4075 int rotation_eight_mask = 0x00000400;
4076 int rotation_sixteen_mask = 0x00000800;
4077 int rotation_twenty_four_mask = 0x00000c00;
4078
4079 skip_whitespace (str);
4080 if ((rd = reg_required_here (&str, 12)) == FAIL
4081 || skip_past_comma (&str) == FAIL
4082 || (rm = reg_required_here (&str, 0)) == FAIL)
4083 {
4084 inst.error = BAD_ARGS;
4085 return;
4086 }
4087
4088 else if (rd == REG_PC || rm == REG_PC)
4089 {
4090 inst.error = BAD_PC;
4091 return;
4092 }
4093
4094 /* Zero out the rotation field. */
4095 inst.instruction &= rotation_clear_mask;
4096
4097 /* Check for lack of optional rotation field. */
4098 if (skip_past_comma (&str) == FAIL)
4099 {
4100 end_of_line (str);
4101 return;
4102 }
4103
4104 /* Move past 'ROR'. */
4105 skip_whitespace (str);
4106 if (strncasecmp (str, "ROR", 3) == 0)
4107 str += 3;
4108 else
4109 {
4110 inst.error = _("missing rotation field after comma");
4111 return;
4112 }
4113
4114 /* Get the immediate constant. */
4115 skip_whitespace (str);
4116 if (is_immediate_prefix (* str))
4117 str++;
4118 else
4119 {
4120 inst.error = _("immediate expression expected");
4121 return;
4122 }
4123
4124 if (my_get_expression (&expr, &str))
4125 {
4126 inst.error = _("bad expression");
4127 return;
4128 }
4129
4130 if (expr.X_op != O_constant)
4131 {
4132 inst.error = _("constant expression expected");
4133 return;
4134 }
4135
4136 switch (expr.X_add_number)
4137 {
4138 case 0:
4139 /* Rotation field has already been zeroed. */
4140 break;
4141 case 8:
4142 inst.instruction |= rotation_eight_mask;
4143 break;
4144
4145 case 16:
4146 inst.instruction |= rotation_sixteen_mask;
4147 break;
4148
4149 case 24:
4150 inst.instruction |= rotation_twenty_four_mask;
4151 break;
4152
4153 default:
4154 inst.error = _("rotation can be 8, 16, 24 or 0 when field is ommited");
4155 break;
4156 }
4157
4158 end_of_line (str);
4159 }
4160
4161 /* ARM V6 SXTAH extracts a 16-bit value from a register, sign
4162 extends it to 32-bits, and adds the result to a value in another
4163 register. You can specify a rotation by 0, 8, 16, or 24 bits
4164 before extracting the 16-bit value.
4165 SXTAH{<cond>} <Rd>, <Rn>, <Rm>{, <rotation>}
4166 Condition defaults to COND_ALWAYS.
4167 Error if any register uses R15. */
4168
4169 static void
4170 do_sxtah (char * str)
4171 {
4172 int rd, rn, rm;
4173 expressionS expr;
4174 int rotation_clear_mask = 0xfffff3ff;
4175 int rotation_eight_mask = 0x00000400;
4176 int rotation_sixteen_mask = 0x00000800;
4177 int rotation_twenty_four_mask = 0x00000c00;
4178
4179 skip_whitespace (str);
4180 if ((rd = reg_required_here (&str, 12)) == FAIL
4181 || skip_past_comma (&str) == FAIL
4182 || (rn = reg_required_here (&str, 16)) == FAIL
4183 || skip_past_comma (&str) == FAIL
4184 || (rm = reg_required_here (&str, 0)) == FAIL)
4185 {
4186 inst.error = BAD_ARGS;
4187 return;
4188 }
4189
4190 else if (rd == REG_PC || rn == REG_PC || rm == REG_PC)
4191 {
4192 inst.error = BAD_PC;
4193 return;
4194 }
4195
4196 /* Zero out the rotation field. */
4197 inst.instruction &= rotation_clear_mask;
4198
4199 /* Check for lack of optional rotation field. */
4200 if (skip_past_comma (&str) == FAIL)
4201 {
4202 end_of_line (str);
4203 return;
4204 }
4205
4206 /* Move past 'ROR'. */
4207 skip_whitespace (str);
4208 if (strncasecmp (str, "ROR", 3) == 0)
4209 str += 3;
4210 else
4211 {
4212 inst.error = _("missing rotation field after comma");
4213 return;
4214 }
4215
4216 /* Get the immediate constant. */
4217 skip_whitespace (str);
4218 if (is_immediate_prefix (* str))
4219 str++;
4220 else
4221 {
4222 inst.error = _("immediate expression expected");
4223 return;
4224 }
4225
4226 if (my_get_expression (&expr, &str))
4227 {
4228 inst.error = _("bad expression");
4229 return;
4230 }
4231
4232 if (expr.X_op != O_constant)
4233 {
4234 inst.error = _("constant expression expected");
4235 return;
4236 }
4237
4238 switch (expr.X_add_number)
4239 {
4240 case 0:
4241 /* Rotation field has already been zeroed. */
4242 break;
4243
4244 case 8:
4245 inst.instruction |= rotation_eight_mask;
4246 break;
4247
4248 case 16:
4249 inst.instruction |= rotation_sixteen_mask;
4250 break;
4251
4252 case 24:
4253 inst.instruction |= rotation_twenty_four_mask;
4254 break;
4255
4256 default:
4257 inst.error = _("rotation can be 8, 16, 24 or 0 when field is ommited");
4258 break;
4259 }
4260
4261 end_of_line (str);
4262 }
4263
4264
4265 /* ARM V6 RFE (Return from Exception) loads the PC and CPSR from the
4266 word at the specified address and the following word
4267 respectively.
4268 Unconditionally executed.
4269 Error if Rn is R15. */
4270
4271 static void
4272 do_rfe (char * str)
4273 {
4274 int rn;
4275
4276 skip_whitespace (str);
4277
4278 if ((rn = reg_required_here (&str, 16)) == FAIL)
4279 return;
4280
4281 if (rn == REG_PC)
4282 {
4283 inst.error = BAD_PC;
4284 return;
4285 }
4286
4287 skip_whitespace (str);
4288
4289 if (*str == '!')
4290 {
4291 inst.instruction |= WRITE_BACK;
4292 str++;
4293 }
4294 end_of_line (str);
4295 }
4296
4297 /* ARM V6 REV (Byte Reverse Word) reverses the byte order in a 32-bit
4298 register (argument parse).
4299 REV{<cond>} Rd, Rm.
4300 Condition defaults to COND_ALWAYS.
4301 Error if Rd or Rm are R15. */
4302
4303 static void
4304 do_rev (char * str)
4305 {
4306 int rd, rm;
4307
4308 skip_whitespace (str);
4309
4310 if ((rd = reg_required_here (&str, 12)) == FAIL
4311 || skip_past_comma (&str) == FAIL
4312 || (rm = reg_required_here (&str, 0)) == FAIL)
4313 inst.error = BAD_ARGS;
4314
4315 else if (rd == REG_PC || rm == REG_PC)
4316 inst.error = BAD_PC;
4317
4318 else
4319 end_of_line (str);
4320 }
4321
4322 /* ARM V6 Perform Two Sixteen Bit Integer Additions. (argument parse).
4323 QADD16{<cond>} <Rd>, <Rn>, <Rm>
4324 Condition defaults to COND_ALWAYS.
4325 Error if Rd, Rn or Rm are R15. */
4326
4327 static void
4328 do_qadd16 (char * str)
4329 {
4330 int rd, rm, rn;
4331
4332 skip_whitespace (str);
4333
4334 if ((rd = reg_required_here (&str, 12)) == FAIL
4335 || skip_past_comma (&str) == FAIL
4336 || (rn = reg_required_here (&str, 16)) == FAIL
4337 || skip_past_comma (&str) == FAIL
4338 || (rm = reg_required_here (&str, 0)) == FAIL)
4339 inst.error = BAD_ARGS;
4340
4341 else if (rd == REG_PC || rm == REG_PC || rn == REG_PC)
4342 inst.error = BAD_PC;
4343
4344 else
4345 end_of_line (str);
4346 }
4347
4348 static void
4349 do_pkh_core (char * str, int shift)
4350 {
4351 int rd, rn, rm;
4352
4353 skip_whitespace (str);
4354 if (((rd = reg_required_here (&str, 12)) == FAIL)
4355 || (skip_past_comma (&str) == FAIL)
4356 || ((rn = reg_required_here (&str, 16)) == FAIL)
4357 || (skip_past_comma (&str) == FAIL)
4358 || ((rm = reg_required_here (&str, 0)) == FAIL))
4359 {
4360 inst.error = BAD_ARGS;
4361 return;
4362 }
4363
4364 else if (rd == REG_PC || rn == REG_PC || rm == REG_PC)
4365 {
4366 inst.error = BAD_PC;
4367 return;
4368 }
4369
4370 /* Check for optional shift immediate constant. */
4371 if (skip_past_comma (&str) == FAIL)
4372 {
4373 if (shift == SHIFT_ASR_IMMEDIATE)
4374 {
4375 /* If the shift specifier is ommited, turn the instruction
4376 into pkhbt rd, rm, rn. First, switch the instruction
4377 code, and clear the rn and rm fields. */
4378 inst.instruction &= 0xfff0f010;
4379 /* Now, re-encode the registers. */
4380 inst.instruction |= (rm << 16) | rn;
4381 }
4382 return;
4383 }
4384
4385 decode_shift (&str, shift);
4386 }
4387
4388 /* ARM V6 Pack Halfword Bottom Top instruction (argument parse).
4389 PKHBT {<cond>} <Rd>, <Rn>, <Rm> {, LSL #<shift_imm>}
4390 Condition defaults to COND_ALWAYS.
4391 Error if Rd, Rn or Rm are R15. */
4392
4393 static void
4394 do_pkhbt (char * str)
4395 {
4396 do_pkh_core (str, SHIFT_LSL_IMMEDIATE);
4397 }
4398
4399 /* ARM V6 PKHTB (Argument Parse). */
4400
4401 static void
4402 do_pkhtb (char * str)
4403 {
4404 do_pkh_core (str, SHIFT_ASR_IMMEDIATE);
4405 }
4406
4407 /* ARM V6 Load Register Exclusive instruction (argument parse).
4408 LDREX{,B,D,H}{<cond>} <Rd, [<Rn>]
4409 Condition defaults to COND_ALWAYS.
4410 Error if Rd or Rn are R15.
4411 See ARMARMv6 A4.1.27: LDREX. */
4412
4413 static void
4414 do_ldrex (char * str)
4415 {
4416 int rd, rn;
4417
4418 skip_whitespace (str);
4419
4420 /* Parse Rd. */
4421 if (((rd = reg_required_here (&str, 12)) == FAIL)
4422 || (skip_past_comma (&str) == FAIL))
4423 {
4424 inst.error = BAD_ARGS;
4425 return;
4426 }
4427 else if (rd == REG_PC)
4428 {
4429 inst.error = BAD_PC;
4430 return;
4431 }
4432 skip_whitespace (str);
4433
4434 /* Skip past '['. */
4435 if ((strlen (str) >= 1)
4436 &&strncmp (str, "[", 1) == 0)
4437 str += 1;
4438 skip_whitespace (str);
4439
4440 /* Parse Rn. */
4441 if ((rn = reg_required_here (&str, 16)) == FAIL)
4442 {
4443 inst.error = BAD_ARGS;
4444 return;
4445 }
4446 else if (rn == REG_PC)
4447 {
4448 inst.error = BAD_PC;
4449 return;
4450 }
4451 skip_whitespace (str);
4452
4453 /* Skip past ']'. */
4454 if ((strlen (str) >= 1)
4455 && strncmp (str, "]", 1) == 0)
4456 str += 1;
4457
4458 end_of_line (str);
4459 }
4460
4461 /* ARM V6 change processor state instruction (argument parse)
4462 CPS, CPSIE, CSPID . */
4463
4464 static void
4465 do_cps (char * str)
4466 {
4467 do_cps_mode (&str);
4468 end_of_line (str);
4469 }
4470
4471 static void
4472 do_cps_flags (char ** str, int thumb_p)
4473 {
4474 struct cps_flag
4475 {
4476 char character;
4477 unsigned long arm_value;
4478 unsigned long thumb_value;
4479 };
4480 static struct cps_flag flag_table[] =
4481 {
4482 {'a', 0x100, 0x4 },
4483 {'i', 0x080, 0x2 },
4484 {'f', 0x040, 0x1 }
4485 };
4486
4487 int saw_a_flag = 0;
4488
4489 skip_whitespace (*str);
4490
4491 /* Get the a, f and i flags. */
4492 while (**str && **str != ',')
4493 {
4494 struct cps_flag *p;
4495 struct cps_flag *q = flag_table + sizeof (flag_table)/sizeof (*p);
4496
4497 for (p = flag_table; p < q; ++p)
4498 if (strncasecmp (*str, &p->character, 1) == 0)
4499 {
4500 inst.instruction |= (thumb_p ? p->thumb_value : p->arm_value);
4501 saw_a_flag = 1;
4502 break;
4503 }
4504 if (p == q)
4505 {
4506 inst.error = _("unrecognized flag");
4507 return;
4508 }
4509 (*str)++;
4510 }
4511
4512 if (!saw_a_flag)
4513 inst.error = _("no 'a', 'i', or 'f' flags for 'cps'");
4514 }
4515
4516 static void
4517 do_cpsi (char * str)
4518 {
4519 do_cps_flags (&str, /*thumb_p=*/0);
4520
4521 if (skip_past_comma (&str) == SUCCESS)
4522 {
4523 skip_whitespace (str);
4524 do_cps_mode (&str);
4525 }
4526 end_of_line (str);
4527 }
4528
4529 /* ARM V6T2 bitfield manipulation instructions. */
4530
4531 static int
4532 five_bit_unsigned_immediate (char **str)
4533 {
4534 expressionS expr;
4535
4536 skip_whitespace (*str);
4537 if (!is_immediate_prefix (**str))
4538 {
4539 inst.error = _("immediate expression expected");
4540 return -1;
4541 }
4542 (*str)++;
4543 if (my_get_expression (&expr, str))
4544 {
4545 inst.error = _("bad expression");
4546 return -1;
4547 }
4548 if (expr.X_op != O_constant)
4549 {
4550 inst.error = _("constant expression expected");
4551 return -1;
4552 }
4553 if (expr.X_add_number < 0 || expr.X_add_number > 32)
4554 {
4555 inst.error = _("immediate value out of range");
4556 return -1;
4557 }
4558
4559 return expr.X_add_number;
4560 }
4561
4562 static void
4563 bfci_lsb_and_width (char *str)
4564 {
4565 int lsb, width;
4566
4567 if ((lsb = five_bit_unsigned_immediate (&str)) == -1)
4568 return;
4569
4570 if (skip_past_comma (&str) == FAIL)
4571 {
4572 inst.error = BAD_ARGS;
4573 return;
4574 }
4575 if ((width = five_bit_unsigned_immediate (&str)) == -1)
4576 return;
4577
4578 end_of_line (str);
4579
4580 if (width == 0 || lsb == 32)
4581 {
4582 inst.error = _("immediate value out of range");
4583 return;
4584 }
4585 else if (width + lsb > 32)
4586 {
4587 inst.error = _("bit-field extends past end of register");
4588 return;
4589 }
4590
4591 /* Convert to LSB/MSB and write to register. */
4592 inst.instruction |= lsb << 7;
4593 inst.instruction |= (width + lsb - 1) << 16;
4594 }
4595
4596 static void
4597 do_bfc (char *str)
4598 {
4599 int rd;
4600
4601 /* Rd. */
4602 skip_whitespace (str);
4603 if (((rd = reg_required_here (&str, 12)) == FAIL)
4604 || (skip_past_comma (&str) == FAIL))
4605 {
4606 inst.error = BAD_ARGS;
4607 return;
4608 }
4609 else if (rd == REG_PC)
4610 {
4611 inst.error = BAD_PC;
4612 return;
4613 }
4614
4615 bfci_lsb_and_width (str);
4616 }
4617
4618 static void
4619 do_bfi (char *str)
4620 {
4621 int rd, rm;
4622
4623 /* Rd. */
4624 skip_whitespace (str);
4625 if (((rd = reg_required_here (&str, 12)) == FAIL)
4626 || (skip_past_comma (&str) == FAIL))
4627 {
4628 inst.error = BAD_ARGS;
4629 return;
4630 }
4631 else if (rd == REG_PC)
4632 {
4633 inst.error = BAD_PC;
4634 return;
4635 }
4636
4637 /* Rm. Accept #0 in this position as an alternative syntax for bfc. */
4638 skip_whitespace (str);
4639 if (is_immediate_prefix (*str))
4640 {
4641 expressionS expr;
4642 str++;
4643 if (my_get_expression (&expr, &str))
4644 {
4645 inst.error = _("bad expression");
4646 return;
4647 }
4648 if (expr.X_op != O_constant)
4649 {
4650 inst.error = _("constant expression expected");
4651 return;
4652 }
4653 if (expr.X_add_number != 0)
4654 {
4655 inst.error = _("immediate value out of range");
4656 return;
4657 }
4658 inst.instruction |= 0x0000000f; /* Rm = PC -> bfc, not bfi. */
4659 }
4660 else
4661 {
4662 if ((rm = reg_required_here (&str, 0)) == FAIL)
4663 {
4664 inst.error = BAD_ARGS;
4665 return;
4666 }
4667 else if (rm == REG_PC)
4668 {
4669 inst.error = BAD_PC;
4670 return;
4671 }
4672 }
4673 if (skip_past_comma (&str) == FAIL)
4674 {
4675 inst.error = BAD_ARGS;
4676 return;
4677 }
4678
4679 bfci_lsb_and_width (str);
4680 }
4681
4682 static void
4683 do_bfx (char *str)
4684 {
4685 int lsb, width;
4686
4687 /* Rd. */
4688 skip_whitespace (str);
4689 if (reg_required_here (&str, 12) == FAIL
4690 || skip_past_comma (&str) == FAIL)
4691 {
4692 inst.error = BAD_ARGS;
4693 return;
4694 }
4695
4696 /* Rm. */
4697 skip_whitespace (str);
4698 if (reg_required_here (&str, 0) == FAIL
4699 || skip_past_comma (&str) == FAIL)
4700 {
4701 inst.error = BAD_ARGS;
4702 return;
4703 }
4704
4705 if ((lsb = five_bit_unsigned_immediate (&str)) == -1)
4706 return;
4707
4708 if (skip_past_comma (&str) == FAIL)
4709 {
4710 inst.error = BAD_ARGS;
4711 return;
4712 }
4713 if ((width = five_bit_unsigned_immediate (&str)) == -1)
4714 return;
4715
4716 end_of_line (str);
4717
4718 if (width == 0 || lsb == 32)
4719 {
4720 inst.error = _("immediate value out of range");
4721 return;
4722 }
4723 else if (width + lsb > 32)
4724 {
4725 inst.error = _("bit-field extends past end of register");
4726 return;
4727 }
4728
4729 inst.instruction |= lsb << 7;
4730 inst.instruction |= (width - 1) << 16;
4731 }
4732
4733 static void
4734 do_rbit (char *str)
4735 {
4736 /* Rd. */
4737 skip_whitespace (str);
4738 if (reg_required_here (&str, 12) == FAIL
4739 || skip_past_comma (&str) == FAIL)
4740 {
4741 inst.error = BAD_ARGS;
4742 return;
4743 }
4744
4745 /* Rm. */
4746 skip_whitespace (str);
4747 if (reg_required_here (&str, 0) == FAIL)
4748 {
4749 inst.error = BAD_ARGS;
4750 return;
4751 }
4752
4753 end_of_line (str);
4754 }
4755
4756 /* ARM V6T2 16-bit immediate register load: MOV[WT]{cond} Rd, #<imm16>. */
4757 static void
4758 do_mov16 (char *str)
4759 {
4760 int rd;
4761 expressionS expr;
4762
4763 /* Rd. */
4764 skip_whitespace (str);
4765 if (((rd = reg_required_here (&str, 12)) == FAIL)
4766 || (skip_past_comma (&str) == FAIL))
4767 {
4768 inst.error = BAD_ARGS;
4769 return;
4770 }
4771 else if (rd == REG_PC)
4772 {
4773 inst.error = BAD_PC;
4774 return;
4775 }
4776
4777 /* Imm16. */
4778 skip_whitespace (str);
4779 if (!is_immediate_prefix (*str))
4780 {
4781 inst.error = _("immediate expression expected");
4782 return;
4783 }
4784 str++;
4785 if (my_get_expression (&expr, &str))
4786 {
4787 inst.error = _("bad expression");
4788 return;
4789 }
4790 if (expr.X_op != O_constant)
4791 {
4792 inst.error = _("constant expression expected");
4793 return;
4794 }
4795 if (expr.X_add_number < 0 || expr.X_add_number > 65535)
4796 {
4797 inst.error = _("immediate value out of range");
4798 return;
4799 }
4800
4801 end_of_line (str);
4802
4803 /* The value is in two pieces: 0:11, 16:19. */
4804 inst.instruction |= (expr.X_add_number & 0x00000fff);
4805 inst.instruction |= (expr.X_add_number & 0x0000f000) << 4;
4806 }
4807
4808
4809 /* THUMB V5 breakpoint instruction (argument parse)
4810 BKPT <immed_8>. */
4811
4812 static void
4813 do_t_bkpt (char * str)
4814 {
4815 expressionS expr;
4816 unsigned long number;
4817
4818 skip_whitespace (str);
4819
4820 /* Allow optional leading '#'. */
4821 if (is_immediate_prefix (*str))
4822 str ++;
4823
4824 memset (& expr, '\0', sizeof (expr));
4825 if (my_get_expression (& expr, & str)
4826 || (expr.X_op != O_constant
4827 /* As a convenience we allow 'bkpt' without an operand. */
4828 && expr.X_op != O_absent))
4829 {
4830 inst.error = _("bad expression");
4831 return;
4832 }
4833
4834 number = expr.X_add_number;
4835
4836 /* Check it fits an 8 bit unsigned. */
4837 if (number != (number & 0xff))
4838 {
4839 inst.error = _("immediate value out of range");
4840 return;
4841 }
4842
4843 inst.instruction |= number;
4844
4845 end_of_line (str);
4846 }
4847
4848 #ifdef OBJ_ELF
4849 static bfd_reloc_code_real_type
4850 arm_parse_reloc (void)
4851 {
4852 char id [16];
4853 char * ip;
4854 unsigned int i;
4855 static struct
4856 {
4857 char * str;
4858 int len;
4859 bfd_reloc_code_real_type reloc;
4860 }
4861 reloc_map[] =
4862 {
4863 #define MAP(str,reloc) { str, sizeof (str) - 1, reloc }
4864 MAP ("(got)", BFD_RELOC_ARM_GOT32),
4865 MAP ("(gotoff)", BFD_RELOC_ARM_GOTOFF),
4866 /* ScottB: Jan 30, 1998 - Added support for parsing "var(PLT)"
4867 branch instructions generated by GCC for PLT relocs. */
4868 MAP ("(plt)", BFD_RELOC_ARM_PLT32),
4869 MAP ("(target1)", BFD_RELOC_ARM_TARGET1),
4870 MAP ("(sbrel)", BFD_RELOC_ARM_SBREL32),
4871 MAP ("(target2)", BFD_RELOC_ARM_TARGET2),
4872 { NULL, 0, BFD_RELOC_UNUSED }
4873 #undef MAP
4874 };
4875
4876 for (i = 0, ip = input_line_pointer;
4877 i < sizeof (id) && (ISALNUM (*ip) || ISPUNCT (*ip));
4878 i++, ip++)
4879 id[i] = TOLOWER (*ip);
4880
4881 for (i = 0; reloc_map[i].str; i++)
4882 if (strncmp (id, reloc_map[i].str, reloc_map[i].len) == 0)
4883 break;
4884
4885 input_line_pointer += reloc_map[i].len;
4886
4887 return reloc_map[i].reloc;
4888 }
4889 #endif
4890
4891 /* ARM V5 branch-link-exchange (argument parse) for BLX(1) only.
4892 Expects inst.instruction is set for BLX(1).
4893 Note: this is cloned from do_branch, and the reloc changed to be a
4894 new one that can cope with setting one extra bit (the H bit). */
4895
4896 static void
4897 do_branch25 (char * str)
4898 {
4899 if (my_get_expression (& inst.reloc.exp, & str))
4900 return;
4901
4902 #ifdef OBJ_ELF
4903 {
4904 char * save_in;
4905
4906 /* ScottB: February 5, 1998 */
4907 /* Check to see of PLT32 reloc required for the instruction. */
4908
4909 /* arm_parse_reloc() works on input_line_pointer.
4910 We actually want to parse the operands to the branch instruction
4911 passed in 'str'. Save the input pointer and restore it later. */
4912 save_in = input_line_pointer;
4913 input_line_pointer = str;
4914
4915 if (inst.reloc.exp.X_op == O_symbol
4916 && *str == '('
4917 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
4918 {
4919 inst.reloc.type = BFD_RELOC_ARM_PLT32;
4920 inst.reloc.pc_rel = 0;
4921 /* Modify str to point to after parsed operands, otherwise
4922 end_of_line() will complain about the (PLT) left in str. */
4923 str = input_line_pointer;
4924 }
4925 else
4926 {
4927 inst.reloc.type = BFD_RELOC_ARM_PCREL_BLX;
4928 inst.reloc.pc_rel = 1;
4929 }
4930
4931 input_line_pointer = save_in;
4932 }
4933 #else
4934 inst.reloc.type = BFD_RELOC_ARM_PCREL_BLX;
4935 inst.reloc.pc_rel = 1;
4936 #endif /* OBJ_ELF */
4937
4938 end_of_line (str);
4939 }
4940
4941 /* ARM V5 branch-link-exchange instruction (argument parse)
4942 BLX <target_addr> ie BLX(1)
4943 BLX{<condition>} <Rm> ie BLX(2)
4944 Unfortunately, there are two different opcodes for this mnemonic.
4945 So, the insns[].value is not used, and the code here zaps values
4946 into inst.instruction.
4947 Also, the <target_addr> can be 25 bits, hence has its own reloc. */
4948
4949 static void
4950 do_blx (char * str)
4951 {
4952 char * mystr = str;
4953 int rm;
4954
4955 skip_whitespace (mystr);
4956 rm = reg_required_here (& mystr, 0);
4957
4958 /* The above may set inst.error. Ignore his opinion. */
4959 inst.error = 0;
4960
4961 if (rm != FAIL)
4962 {
4963 /* Arg is a register.
4964 Use the condition code our caller put in inst.instruction.
4965 Pass ourselves off as a BX with a funny opcode. */
4966 inst.instruction |= 0x012fff30;
4967 do_bx (str);
4968 }
4969 else
4970 {
4971 /* This must be is BLX <target address>, no condition allowed. */
4972 if (inst.instruction != COND_ALWAYS)
4973 {
4974 inst.error = BAD_COND;
4975 return;
4976 }
4977
4978 inst.instruction = 0xfafffffe;
4979
4980 /* Process like a B/BL, but with a different reloc.
4981 Note that B/BL expecte fffffe, not 0, offset in the opcode table. */
4982 do_branch25 (str);
4983 }
4984 }
4985
4986 /* ARM V5 Thumb BLX (argument parse)
4987 BLX <target_addr> which is BLX(1)
4988 BLX <Rm> which is BLX(2)
4989 Unfortunately, there are two different opcodes for this mnemonic.
4990 So, the tinsns[].value is not used, and the code here zaps values
4991 into inst.instruction. */
4992
4993 static void
4994 do_t_blx (char * str)
4995 {
4996 char * mystr = str;
4997 int rm;
4998
4999 skip_whitespace (mystr);
5000 inst.instruction = 0x4780;
5001
5002 /* Note that this call is to the ARM register recognizer. BLX(2)
5003 uses the ARM register space, not the Thumb one, so a call to
5004 thumb_reg() would be wrong. */
5005 rm = reg_required_here (& mystr, 3);
5006 inst.error = 0;
5007
5008 if (rm != FAIL)
5009 {
5010 /* It's BLX(2). The .instruction was zapped with rm & is final. */
5011 inst.size = 2;
5012 }
5013 else
5014 {
5015 /* No ARM register. This must be BLX(1). Change the .instruction. */
5016 inst.instruction = 0xf7ffeffe;
5017 inst.size = 4;
5018
5019 if (my_get_expression (& inst.reloc.exp, & mystr))
5020 return;
5021
5022 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BLX;
5023 inst.reloc.pc_rel = 1;
5024 }
5025
5026 end_of_line (mystr);
5027 }
5028
5029 /* ARM V5 breakpoint instruction (argument parse)
5030 BKPT <16 bit unsigned immediate>
5031 Instruction is not conditional.
5032 The bit pattern given in insns[] has the COND_ALWAYS condition,
5033 and it is an error if the caller tried to override that. */
5034
5035 static void
5036 do_bkpt (char * str)
5037 {
5038 expressionS expr;
5039 unsigned long number;
5040
5041 skip_whitespace (str);
5042
5043 /* Allow optional leading '#'. */
5044 if (is_immediate_prefix (* str))
5045 str++;
5046
5047 memset (& expr, '\0', sizeof (expr));
5048
5049 if (my_get_expression (& expr, & str)
5050 || (expr.X_op != O_constant
5051 /* As a convenience we allow 'bkpt' without an operand. */
5052 && expr.X_op != O_absent))
5053 {
5054 inst.error = _("bad expression");
5055 return;
5056 }
5057
5058 number = expr.X_add_number;
5059
5060 /* Check it fits a 16 bit unsigned. */
5061 if (number != (number & 0xffff))
5062 {
5063 inst.error = _("immediate value out of range");
5064 return;
5065 }
5066
5067 /* Top 12 of 16 bits to bits 19:8. */
5068 inst.instruction |= (number & 0xfff0) << 4;
5069
5070 /* Bottom 4 of 16 bits to bits 3:0. */
5071 inst.instruction |= number & 0xf;
5072
5073 end_of_line (str);
5074 }
5075
5076 /* THUMB CPS instruction (argument parse). */
5077
5078 static void
5079 do_t_cps (char * str)
5080 {
5081 do_cps_flags (&str, /*thumb_p=*/1);
5082 end_of_line (str);
5083 }
5084
5085 /* Parse and validate that a register is of the right form, this saves
5086 repeated checking of this information in many similar cases.
5087 Unlike the 32-bit case we do not insert the register into the opcode
5088 here, since the position is often unknown until the full instruction
5089 has been parsed. */
5090
5091 static int
5092 thumb_reg (char ** strp, int hi_lo)
5093 {
5094 int reg;
5095
5096 if ((reg = reg_required_here (strp, -1)) == FAIL)
5097 return FAIL;
5098
5099 switch (hi_lo)
5100 {
5101 case THUMB_REG_LO:
5102 if (reg > 7)
5103 {
5104 inst.error = _("lo register required");
5105 return FAIL;
5106 }
5107 break;
5108
5109 case THUMB_REG_HI:
5110 if (reg < 8)
5111 {
5112 inst.error = _("hi register required");
5113 return FAIL;
5114 }
5115 break;
5116
5117 default:
5118 break;
5119 }
5120
5121 return reg;
5122 }
5123
5124 static void
5125 thumb_mov_compare (char * str, int move)
5126 {
5127 int Rd, Rs = FAIL;
5128
5129 skip_whitespace (str);
5130
5131 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
5132 || skip_past_comma (&str) == FAIL)
5133 {
5134 if (! inst.error)
5135 inst.error = BAD_ARGS;
5136 return;
5137 }
5138
5139 if (move != THUMB_CPY && is_immediate_prefix (*str))
5140 {
5141 str++;
5142 if (my_get_expression (&inst.reloc.exp, &str))
5143 return;
5144 }
5145 else if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
5146 return;
5147
5148 if (Rs != FAIL)
5149 {
5150 if (move != THUMB_CPY && Rs < 8 && Rd < 8)
5151 {
5152 if (move == THUMB_MOVE)
5153 /* A move of two lowregs is encoded as ADD Rd, Rs, #0
5154 since a MOV instruction produces unpredictable results. */
5155 inst.instruction = T_OPCODE_ADD_I3;
5156 else
5157 inst.instruction = T_OPCODE_CMP_LR;
5158 inst.instruction |= Rd | (Rs << 3);
5159 }
5160 else
5161 {
5162 if (move == THUMB_MOVE)
5163 inst.instruction = T_OPCODE_MOV_HR;
5164 else if (move != THUMB_CPY)
5165 inst.instruction = T_OPCODE_CMP_HR;
5166
5167 if (Rd > 7)
5168 inst.instruction |= THUMB_H1;
5169
5170 if (Rs > 7)
5171 inst.instruction |= THUMB_H2;
5172
5173 inst.instruction |= (Rd & 7) | ((Rs & 7) << 3);
5174 }
5175 }
5176 else
5177 {
5178 if (Rd > 7)
5179 {
5180 inst.error = _("only lo regs allowed with immediate");
5181 return;
5182 }
5183
5184 if (move == THUMB_MOVE)
5185 inst.instruction = T_OPCODE_MOV_I8;
5186 else
5187 inst.instruction = T_OPCODE_CMP_I8;
5188
5189 inst.instruction |= Rd << 8;
5190
5191 if (inst.reloc.exp.X_op != O_constant)
5192 inst.reloc.type = BFD_RELOC_ARM_THUMB_IMM;
5193 else
5194 {
5195 unsigned value = inst.reloc.exp.X_add_number;
5196
5197 if (value > 255)
5198 {
5199 inst.error = _("invalid immediate");
5200 return;
5201 }
5202
5203 inst.instruction |= value;
5204 }
5205 }
5206
5207 end_of_line (str);
5208 }
5209
5210 /* THUMB CPY instruction (argument parse). */
5211
5212 static void
5213 do_t_cpy (char * str)
5214 {
5215 thumb_mov_compare (str, THUMB_CPY);
5216 }
5217
5218 /* THUMB SETEND instruction (argument parse). */
5219
5220 static void
5221 do_t_setend (char * str)
5222 {
5223 if (do_endian_specifier (str))
5224 inst.instruction |= 0x8;
5225 }
5226
5227 /* Parse INSN_TYPE insn STR having a possible IMMEDIATE_SIZE immediate. */
5228
5229 static unsigned long
5230 check_iwmmxt_insn (char * str,
5231 enum iwmmxt_insn_type insn_type,
5232 int immediate_size)
5233 {
5234 int reg = 0;
5235 const char * inst_error;
5236 expressionS expr;
5237 unsigned long number;
5238
5239 inst_error = inst.error;
5240 if (!inst.error)
5241 inst.error = BAD_ARGS;
5242 skip_whitespace (str);
5243
5244 switch (insn_type)
5245 {
5246 case check_rd:
5247 if ((reg = reg_required_here (&str, 12)) == FAIL)
5248 return FAIL;
5249 break;
5250
5251 case check_wr:
5252 if ((wreg_required_here (&str, 0, IWMMXT_REG_WR)) == FAIL)
5253 return FAIL;
5254 break;
5255
5256 case check_wrwr:
5257 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
5258 || skip_past_comma (&str) == FAIL
5259 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL))
5260 return FAIL;
5261 break;
5262
5263 case check_wrwrwr:
5264 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
5265 || skip_past_comma (&str) == FAIL
5266 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5267 || skip_past_comma (&str) == FAIL
5268 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL))
5269 return FAIL;
5270 break;
5271
5272 case check_wrwrwcg:
5273 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
5274 || skip_past_comma (&str) == FAIL
5275 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5276 || skip_past_comma (&str) == FAIL
5277 || wreg_required_here (&str, 0, IWMMXT_REG_WCG) == FAIL))
5278 return FAIL;
5279 break;
5280
5281 case check_tbcst:
5282 if ((wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5283 || skip_past_comma (&str) == FAIL
5284 || reg_required_here (&str, 12) == FAIL))
5285 return FAIL;
5286 break;
5287
5288 case check_tmovmsk:
5289 if ((reg_required_here (&str, 12) == FAIL
5290 || skip_past_comma (&str) == FAIL
5291 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL))
5292 return FAIL;
5293 break;
5294
5295 case check_tmia:
5296 if ((wreg_required_here (&str, 5, IWMMXT_REG_WR) == FAIL
5297 || skip_past_comma (&str) == FAIL
5298 || reg_required_here (&str, 0) == FAIL
5299 || skip_past_comma (&str) == FAIL
5300 || reg_required_here (&str, 12) == FAIL))
5301 return FAIL;
5302 break;
5303
5304 case check_tmcrr:
5305 if ((wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL
5306 || skip_past_comma (&str) == FAIL
5307 || reg_required_here (&str, 12) == FAIL
5308 || skip_past_comma (&str) == FAIL
5309 || reg_required_here (&str, 16) == FAIL))
5310 return FAIL;
5311 break;
5312
5313 case check_tmrrc:
5314 if ((reg_required_here (&str, 12) == FAIL
5315 || skip_past_comma (&str) == FAIL
5316 || reg_required_here (&str, 16) == FAIL
5317 || skip_past_comma (&str) == FAIL
5318 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL))
5319 return FAIL;
5320 break;
5321
5322 case check_tmcr:
5323 if ((wreg_required_here (&str, 16, IWMMXT_REG_WC) == FAIL
5324 || skip_past_comma (&str) == FAIL
5325 || reg_required_here (&str, 12) == FAIL))
5326 return FAIL;
5327 break;
5328
5329 case check_tmrc:
5330 if ((reg_required_here (&str, 12) == FAIL
5331 || skip_past_comma (&str) == FAIL
5332 || wreg_required_here (&str, 16, IWMMXT_REG_WC) == FAIL))
5333 return FAIL;
5334 break;
5335
5336 case check_tinsr:
5337 if ((wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5338 || skip_past_comma (&str) == FAIL
5339 || reg_required_here (&str, 12) == FAIL
5340 || skip_past_comma (&str) == FAIL))
5341 return FAIL;
5342 break;
5343
5344 case check_textrc:
5345 if ((reg_required_here (&str, 12) == FAIL
5346 || skip_past_comma (&str) == FAIL))
5347 return FAIL;
5348 break;
5349
5350 case check_waligni:
5351 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
5352 || skip_past_comma (&str) == FAIL
5353 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5354 || skip_past_comma (&str) == FAIL
5355 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL
5356 || skip_past_comma (&str) == FAIL))
5357 return FAIL;
5358 break;
5359
5360 case check_textrm:
5361 if ((reg_required_here (&str, 12) == FAIL
5362 || skip_past_comma (&str) == FAIL
5363 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5364 || skip_past_comma (&str) == FAIL))
5365 return FAIL;
5366 break;
5367
5368 case check_wshufh:
5369 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
5370 || skip_past_comma (&str) == FAIL
5371 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5372 || skip_past_comma (&str) == FAIL))
5373 return FAIL;
5374 break;
5375 }
5376
5377 if (immediate_size == 0)
5378 {
5379 end_of_line (str);
5380 inst.error = inst_error;
5381 return reg;
5382 }
5383 else
5384 {
5385 skip_whitespace (str);
5386
5387 /* Allow optional leading '#'. */
5388 if (is_immediate_prefix (* str))
5389 str++;
5390
5391 memset (& expr, '\0', sizeof (expr));
5392
5393 if (my_get_expression (& expr, & str) || (expr.X_op != O_constant))
5394 {
5395 inst.error = _("bad or missing expression");
5396 return FAIL;
5397 }
5398
5399 number = expr.X_add_number;
5400
5401 if (number != (number & immediate_size))
5402 {
5403 inst.error = _("immediate value out of range");
5404 return FAIL;
5405 }
5406 end_of_line (str);
5407 inst.error = inst_error;
5408 return number;
5409 }
5410 }
5411
5412 static void
5413 do_iwmmxt_byte_addr (char * str)
5414 {
5415 int op = (inst.instruction & 0x300) >> 8;
5416 int reg;
5417
5418 inst.instruction &= ~0x300;
5419 inst.instruction |= (op & 1) << 22 | (op & 2) << 7;
5420
5421 skip_whitespace (str);
5422
5423 if ((reg = wreg_required_here (&str, 12, IWMMXT_REG_WR_OR_WC)) == FAIL
5424 || skip_past_comma (& str) == FAIL
5425 || cp_byte_address_required_here (&str) == FAIL)
5426 {
5427 if (! inst.error)
5428 inst.error = BAD_ARGS;
5429 }
5430 else
5431 end_of_line (str);
5432
5433 if (wc_register (reg))
5434 {
5435 as_bad (_("non-word size not supported with control register"));
5436 inst.instruction |= 0xf0000100;
5437 inst.instruction &= ~0x00400000;
5438 }
5439 }
5440
5441 static void
5442 do_iwmmxt_tandc (char * str)
5443 {
5444 int reg;
5445
5446 reg = check_iwmmxt_insn (str, check_rd, 0);
5447
5448 if (reg != REG_PC && !inst.error)
5449 inst.error = _("only r15 allowed here");
5450 }
5451
5452 static void
5453 do_iwmmxt_tbcst (char * str)
5454 {
5455 check_iwmmxt_insn (str, check_tbcst, 0);
5456 }
5457
5458 static void
5459 do_iwmmxt_textrc (char * str)
5460 {
5461 unsigned long number;
5462
5463 if ((number = check_iwmmxt_insn (str, check_textrc, 7)) == (unsigned long) FAIL)
5464 return;
5465
5466 inst.instruction |= number & 0x7;
5467 }
5468
5469 static void
5470 do_iwmmxt_textrm (char * str)
5471 {
5472 unsigned long number;
5473
5474 if ((number = check_iwmmxt_insn (str, check_textrm, 7)) == (unsigned long) FAIL)
5475 return;
5476
5477 inst.instruction |= number & 0x7;
5478 }
5479
5480 static void
5481 do_iwmmxt_tinsr (char * str)
5482 {
5483 unsigned long number;
5484
5485 if ((number = check_iwmmxt_insn (str, check_tinsr, 7)) == (unsigned long) FAIL)
5486 return;
5487
5488 inst.instruction |= number & 0x7;
5489 }
5490
5491 static void
5492 do_iwmmxt_tmcr (char * str)
5493 {
5494 check_iwmmxt_insn (str, check_tmcr, 0);
5495 }
5496
5497 static void
5498 do_iwmmxt_tmcrr (char * str)
5499 {
5500 check_iwmmxt_insn (str, check_tmcrr, 0);
5501 }
5502
5503 static void
5504 do_iwmmxt_tmia (char * str)
5505 {
5506 check_iwmmxt_insn (str, check_tmia, 0);
5507 }
5508
5509 static void
5510 do_iwmmxt_tmovmsk (char * str)
5511 {
5512 check_iwmmxt_insn (str, check_tmovmsk, 0);
5513 }
5514
5515 static void
5516 do_iwmmxt_tmrc (char * str)
5517 {
5518 check_iwmmxt_insn (str, check_tmrc, 0);
5519 }
5520
5521 static void
5522 do_iwmmxt_tmrrc (char * str)
5523 {
5524 check_iwmmxt_insn (str, check_tmrrc, 0);
5525 }
5526
5527 static void
5528 do_iwmmxt_torc (char * str)
5529 {
5530 check_iwmmxt_insn (str, check_rd, 0);
5531 }
5532
5533 static void
5534 do_iwmmxt_waligni (char * str)
5535 {
5536 unsigned long number;
5537
5538 if ((number = check_iwmmxt_insn (str, check_waligni, 7)) == (unsigned long) FAIL)
5539 return;
5540
5541 inst.instruction |= ((number & 0x7) << 20);
5542 }
5543
5544 static void
5545 do_iwmmxt_wmov (char * str)
5546 {
5547 if (check_iwmmxt_insn (str, check_wrwr, 0) == (unsigned long) FAIL)
5548 return;
5549
5550 inst.instruction |= ((inst.instruction >> 16) & 0xf);
5551 }
5552
5553 static void
5554 do_iwmmxt_word_addr (char * str)
5555 {
5556 int op = (inst.instruction & 0x300) >> 8;
5557 int reg;
5558
5559 inst.instruction &= ~0x300;
5560 inst.instruction |= (op & 1) << 22 | (op & 2) << 7;
5561
5562 skip_whitespace (str);
5563
5564 if ((reg = wreg_required_here (&str, 12, IWMMXT_REG_WR_OR_WC)) == FAIL
5565 || skip_past_comma (& str) == FAIL
5566 || cp_address_required_here (& str, CP_WB_OK) == FAIL)
5567 {
5568 if (! inst.error)
5569 inst.error = BAD_ARGS;
5570 }
5571 else
5572 end_of_line (str);
5573
5574 if (wc_register (reg))
5575 {
5576 if ((inst.instruction & COND_MASK) != COND_ALWAYS)
5577 as_bad (_("conditional execution not supported with control register"));
5578 if (op != 2)
5579 as_bad (_("non-word size not supported with control register"));
5580 inst.instruction |= 0xf0000100;
5581 inst.instruction &= ~0x00400000;
5582 }
5583 }
5584
5585 static void
5586 do_iwmmxt_wrwr (char * str)
5587 {
5588 check_iwmmxt_insn (str, check_wrwr, 0);
5589 }
5590
5591 static void
5592 do_iwmmxt_wrwrwcg (char * str)
5593 {
5594 check_iwmmxt_insn (str, check_wrwrwcg, 0);
5595 }
5596
5597 static void
5598 do_iwmmxt_wrwrwr (char * str)
5599 {
5600 check_iwmmxt_insn (str, check_wrwrwr, 0);
5601 }
5602
5603 static void
5604 do_iwmmxt_wshufh (char * str)
5605 {
5606 unsigned long number;
5607
5608 if ((number = check_iwmmxt_insn (str, check_wshufh, 0xff)) == (unsigned long) FAIL)
5609 return;
5610
5611 inst.instruction |= ((number & 0xf0) << 16) | (number & 0xf);
5612 }
5613
5614 static void
5615 do_iwmmxt_wzero (char * str)
5616 {
5617 if (check_iwmmxt_insn (str, check_wr, 0) == (unsigned long) FAIL)
5618 return;
5619
5620 inst.instruction |= ((inst.instruction & 0xf) << 12) | ((inst.instruction & 0xf) << 16);
5621 }
5622
5623 /* Xscale multiply-accumulate (argument parse)
5624 MIAcc acc0,Rm,Rs
5625 MIAPHcc acc0,Rm,Rs
5626 MIAxycc acc0,Rm,Rs. */
5627
5628 static void
5629 do_xsc_mia (char * str)
5630 {
5631 int rs;
5632 int rm;
5633
5634 if (accum0_required_here (& str) == FAIL)
5635 inst.error = ERR_NO_ACCUM;
5636
5637 else if (skip_past_comma (& str) == FAIL
5638 || (rm = reg_required_here (& str, 0)) == FAIL)
5639 inst.error = BAD_ARGS;
5640
5641 else if (skip_past_comma (& str) == FAIL
5642 || (rs = reg_required_here (& str, 12)) == FAIL)
5643 inst.error = BAD_ARGS;
5644
5645 /* inst.instruction has now been zapped with both rm and rs. */
5646 else if (rm == REG_PC || rs == REG_PC)
5647 inst.error = BAD_PC; /* Undefined result if rm or rs is R15. */
5648
5649 else
5650 end_of_line (str);
5651 }
5652
5653 /* Xscale move-accumulator-register (argument parse)
5654
5655 MARcc acc0,RdLo,RdHi. */
5656
5657 static void
5658 do_xsc_mar (char * str)
5659 {
5660 int rdlo, rdhi;
5661
5662 if (accum0_required_here (& str) == FAIL)
5663 inst.error = ERR_NO_ACCUM;
5664
5665 else if (skip_past_comma (& str) == FAIL
5666 || (rdlo = reg_required_here (& str, 12)) == FAIL)
5667 inst.error = BAD_ARGS;
5668
5669 else if (skip_past_comma (& str) == FAIL
5670 || (rdhi = reg_required_here (& str, 16)) == FAIL)
5671 inst.error = BAD_ARGS;
5672
5673 /* inst.instruction has now been zapped with both rdlo and rdhi. */
5674 else if (rdlo == REG_PC || rdhi == REG_PC)
5675 inst.error = BAD_PC; /* Undefined result if rdlo or rdhi is R15. */
5676
5677 else
5678 end_of_line (str);
5679 }
5680
5681 /* Xscale move-register-accumulator (argument parse)
5682
5683 MRAcc RdLo,RdHi,acc0. */
5684
5685 static void
5686 do_xsc_mra (char * str)
5687 {
5688 int rdlo;
5689 int rdhi;
5690
5691 skip_whitespace (str);
5692
5693 if ((rdlo = reg_required_here (& str, 12)) == FAIL)
5694 inst.error = BAD_ARGS;
5695
5696 else if (skip_past_comma (& str) == FAIL
5697 || (rdhi = reg_required_here (& str, 16)) == FAIL)
5698 inst.error = BAD_ARGS;
5699
5700 else if (skip_past_comma (& str) == FAIL
5701 || accum0_required_here (& str) == FAIL)
5702 inst.error = ERR_NO_ACCUM;
5703
5704 /* inst.instruction has now been zapped with both rdlo and rdhi. */
5705 else if (rdlo == rdhi)
5706 inst.error = BAD_ARGS; /* Undefined result if 2 writes to same reg. */
5707
5708 else if (rdlo == REG_PC || rdhi == REG_PC)
5709 inst.error = BAD_PC; /* Undefined result if rdlo or rdhi is R15. */
5710 else
5711 end_of_line (str);
5712 }
5713
5714 static int
5715 ldst_extend (char ** str)
5716 {
5717 int add = INDEX_UP;
5718
5719 switch (**str)
5720 {
5721 case '#':
5722 case '$':
5723 (*str)++;
5724 if (my_get_expression (& inst.reloc.exp, str))
5725 return FAIL;
5726
5727 if (inst.reloc.exp.X_op == O_constant)
5728 {
5729 int value = inst.reloc.exp.X_add_number;
5730
5731 if (value < -4095 || value > 4095)
5732 {
5733 inst.error = _("address offset too large");
5734 return FAIL;
5735 }
5736
5737 if (value < 0)
5738 {
5739 value = -value;
5740 add = 0;
5741 }
5742
5743 inst.instruction |= add | value;
5744 }
5745 else
5746 {
5747 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
5748 inst.reloc.pc_rel = 0;
5749 }
5750 return SUCCESS;
5751
5752 case '-':
5753 add = 0;
5754 /* Fall through. */
5755
5756 case '+':
5757 (*str)++;
5758 /* Fall through. */
5759
5760 default:
5761 if (reg_required_here (str, 0) == FAIL)
5762 return FAIL;
5763
5764 inst.instruction |= add | OFFSET_REG;
5765 if (skip_past_comma (str) == SUCCESS)
5766 return decode_shift (str, SHIFT_IMMEDIATE);
5767
5768 return SUCCESS;
5769 }
5770 }
5771
5772 /* ARMv5TE: Preload-Cache
5773
5774 PLD <addr_mode>
5775
5776 Syntactically, like LDR with B=1, W=0, L=1. */
5777
5778 static void
5779 do_pld (char * str)
5780 {
5781 int rd;
5782
5783 skip_whitespace (str);
5784
5785 if (* str != '[')
5786 {
5787 inst.error = _("'[' expected after PLD mnemonic");
5788 return;
5789 }
5790
5791 ++str;
5792 skip_whitespace (str);
5793
5794 if ((rd = reg_required_here (& str, 16)) == FAIL)
5795 return;
5796
5797 skip_whitespace (str);
5798
5799 if (*str == ']')
5800 {
5801 /* [Rn], ... ? */
5802 ++str;
5803 skip_whitespace (str);
5804
5805 /* Post-indexed addressing is not allowed with PLD. */
5806 if (skip_past_comma (&str) == SUCCESS)
5807 {
5808 inst.error
5809 = _("post-indexed expression used in preload instruction");
5810 return;
5811 }
5812 else if (*str == '!') /* [Rn]! */
5813 {
5814 inst.error = _("writeback used in preload instruction");
5815 ++str;
5816 }
5817 else /* [Rn] */
5818 inst.instruction |= INDEX_UP | PRE_INDEX;
5819 }
5820 else /* [Rn, ...] */
5821 {
5822 if (skip_past_comma (& str) == FAIL)
5823 {
5824 inst.error = _("pre-indexed expression expected");
5825 return;
5826 }
5827
5828 if (ldst_extend (&str) == FAIL)
5829 return;
5830
5831 skip_whitespace (str);
5832
5833 if (* str != ']')
5834 {
5835 inst.error = _("missing ]");
5836 return;
5837 }
5838
5839 ++ str;
5840 skip_whitespace (str);
5841
5842 if (* str == '!') /* [Rn]! */
5843 {
5844 inst.error = _("writeback used in preload instruction");
5845 ++ str;
5846 }
5847
5848 inst.instruction |= PRE_INDEX;
5849 }
5850
5851 end_of_line (str);
5852 }
5853
5854 /* ARMv5TE load-consecutive (argument parse)
5855 Mode is like LDRH.
5856
5857 LDRccD R, mode
5858 STRccD R, mode. */
5859
5860 static void
5861 do_ldrd (char * str)
5862 {
5863 int rd;
5864 int rn;
5865
5866 skip_whitespace (str);
5867
5868 if ((rd = reg_required_here (& str, 12)) == FAIL)
5869 {
5870 inst.error = BAD_ARGS;
5871 return;
5872 }
5873
5874 if (skip_past_comma (& str) == FAIL
5875 || (rn = ld_mode_required_here (& str)) == FAIL)
5876 {
5877 if (!inst.error)
5878 inst.error = BAD_ARGS;
5879 return;
5880 }
5881
5882 /* inst.instruction has now been zapped with Rd and the addressing mode. */
5883 if (rd & 1) /* Unpredictable result if Rd is odd. */
5884 {
5885 inst.error = _("destination register must be even");
5886 return;
5887 }
5888
5889 if (rd == REG_LR)
5890 {
5891 inst.error = _("r14 not allowed here");
5892 return;
5893 }
5894
5895 if (((rd == rn) || (rd + 1 == rn))
5896 && ((inst.instruction & WRITE_BACK)
5897 || (!(inst.instruction & PRE_INDEX))))
5898 as_warn (_("pre/post-indexing used when modified address register is destination"));
5899
5900 /* For an index-register load, the index register must not overlap the
5901 destination (even if not write-back). */
5902 if ((inst.instruction & V4_STR_BIT) == 0
5903 && (inst.instruction & HWOFFSET_IMM) == 0)
5904 {
5905 int rm = inst.instruction & 0x0000000f;
5906
5907 if (rm == rd || (rm == rd + 1))
5908 as_warn (_("ldrd destination registers must not overlap index register"));
5909 }
5910
5911 end_of_line (str);
5912 }
5913
5914 /* Returns the index into fp_values of a floating point number,
5915 or -1 if not in the table. */
5916
5917 static int
5918 my_get_float_expression (char ** str)
5919 {
5920 LITTLENUM_TYPE words[MAX_LITTLENUMS];
5921 char * save_in;
5922 expressionS exp;
5923 int i;
5924 int j;
5925
5926 memset (words, 0, MAX_LITTLENUMS * sizeof (LITTLENUM_TYPE));
5927
5928 /* Look for a raw floating point number. */
5929 if ((save_in = atof_ieee (*str, 'x', words)) != NULL
5930 && is_end_of_line[(unsigned char) *save_in])
5931 {
5932 for (i = 0; i < NUM_FLOAT_VALS; i++)
5933 {
5934 for (j = 0; j < MAX_LITTLENUMS; j++)
5935 {
5936 if (words[j] != fp_values[i][j])
5937 break;
5938 }
5939
5940 if (j == MAX_LITTLENUMS)
5941 {
5942 *str = save_in;
5943 return i;
5944 }
5945 }
5946 }
5947
5948 /* Try and parse a more complex expression, this will probably fail
5949 unless the code uses a floating point prefix (eg "0f"). */
5950 save_in = input_line_pointer;
5951 input_line_pointer = *str;
5952 if (expression (&exp) == absolute_section
5953 && exp.X_op == O_big
5954 && exp.X_add_number < 0)
5955 {
5956 /* FIXME: 5 = X_PRECISION, should be #define'd where we can use it.
5957 Ditto for 15. */
5958 if (gen_to_words (words, 5, (long) 15) == 0)
5959 {
5960 for (i = 0; i < NUM_FLOAT_VALS; i++)
5961 {
5962 for (j = 0; j < MAX_LITTLENUMS; j++)
5963 {
5964 if (words[j] != fp_values[i][j])
5965 break;
5966 }
5967
5968 if (j == MAX_LITTLENUMS)
5969 {
5970 *str = input_line_pointer;
5971 input_line_pointer = save_in;
5972 return i;
5973 }
5974 }
5975 }
5976 }
5977
5978 *str = input_line_pointer;
5979 input_line_pointer = save_in;
5980 return -1;
5981 }
5982
5983 /* We handle all bad expressions here, so that we can report the faulty
5984 instruction in the error message. */
5985 void
5986 md_operand (expressionS * expr)
5987 {
5988 if (in_my_get_expression)
5989 {
5990 expr->X_op = O_illegal;
5991 if (inst.error == NULL)
5992 inst.error = _("bad expression");
5993 }
5994 }
5995
5996 /* Do those data_ops which can take a negative immediate constant
5997 by altering the instruction. A bit of a hack really.
5998 MOV <-> MVN
5999 AND <-> BIC
6000 ADC <-> SBC
6001 by inverting the second operand, and
6002 ADD <-> SUB
6003 CMP <-> CMN
6004 by negating the second operand. */
6005
6006 static int
6007 negate_data_op (unsigned long * instruction,
6008 unsigned long value)
6009 {
6010 int op, new_inst;
6011 unsigned long negated, inverted;
6012
6013 negated = validate_immediate (-value);
6014 inverted = validate_immediate (~value);
6015
6016 op = (*instruction >> DATA_OP_SHIFT) & 0xf;
6017 switch (op)
6018 {
6019 /* First negates. */
6020 case OPCODE_SUB: /* ADD <-> SUB */
6021 new_inst = OPCODE_ADD;
6022 value = negated;
6023 break;
6024
6025 case OPCODE_ADD:
6026 new_inst = OPCODE_SUB;
6027 value = negated;
6028 break;
6029
6030 case OPCODE_CMP: /* CMP <-> CMN */
6031 new_inst = OPCODE_CMN;
6032 value = negated;
6033 break;
6034
6035 case OPCODE_CMN:
6036 new_inst = OPCODE_CMP;
6037 value = negated;
6038 break;
6039
6040 /* Now Inverted ops. */
6041 case OPCODE_MOV: /* MOV <-> MVN */
6042 new_inst = OPCODE_MVN;
6043 value = inverted;
6044 break;
6045
6046 case OPCODE_MVN:
6047 new_inst = OPCODE_MOV;
6048 value = inverted;
6049 break;
6050
6051 case OPCODE_AND: /* AND <-> BIC */
6052 new_inst = OPCODE_BIC;
6053 value = inverted;
6054 break;
6055
6056 case OPCODE_BIC:
6057 new_inst = OPCODE_AND;
6058 value = inverted;
6059 break;
6060
6061 case OPCODE_ADC: /* ADC <-> SBC */
6062 new_inst = OPCODE_SBC;
6063 value = inverted;
6064 break;
6065
6066 case OPCODE_SBC:
6067 new_inst = OPCODE_ADC;
6068 value = inverted;
6069 break;
6070
6071 /* We cannot do anything. */
6072 default:
6073 return FAIL;
6074 }
6075
6076 if (value == (unsigned) FAIL)
6077 return FAIL;
6078
6079 *instruction &= OPCODE_MASK;
6080 *instruction |= new_inst << DATA_OP_SHIFT;
6081 return value;
6082 }
6083
6084 static int
6085 data_op2 (char ** str)
6086 {
6087 int value;
6088 expressionS expr;
6089
6090 skip_whitespace (* str);
6091
6092 if (reg_required_here (str, 0) != FAIL)
6093 {
6094 if (skip_past_comma (str) == SUCCESS)
6095 /* Shift operation on register. */
6096 return decode_shift (str, NO_SHIFT_RESTRICT);
6097
6098 return SUCCESS;
6099 }
6100 else
6101 {
6102 /* Immediate expression. */
6103 if (is_immediate_prefix (**str))
6104 {
6105 (*str)++;
6106 inst.error = NULL;
6107
6108 if (my_get_expression (&inst.reloc.exp, str))
6109 return FAIL;
6110
6111 if (inst.reloc.exp.X_add_symbol)
6112 {
6113 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
6114 inst.reloc.pc_rel = 0;
6115 }
6116 else
6117 {
6118 if (skip_past_comma (str) == SUCCESS)
6119 {
6120 /* #x, y -- ie explicit rotation by Y. */
6121 if (my_get_expression (&expr, str))
6122 return FAIL;
6123
6124 if (expr.X_op != O_constant)
6125 {
6126 inst.error = _("constant expression expected");
6127 return FAIL;
6128 }
6129
6130 /* Rotate must be a multiple of 2. */
6131 if (((unsigned) expr.X_add_number) > 30
6132 || (expr.X_add_number & 1) != 0
6133 || ((unsigned) inst.reloc.exp.X_add_number) > 255)
6134 {
6135 inst.error = _("invalid constant");
6136 return FAIL;
6137 }
6138 inst.instruction |= INST_IMMEDIATE;
6139 inst.instruction |= inst.reloc.exp.X_add_number;
6140 inst.instruction |= expr.X_add_number << 7;
6141 return SUCCESS;
6142 }
6143
6144 /* Implicit rotation, select a suitable one. */
6145 value = validate_immediate (inst.reloc.exp.X_add_number);
6146
6147 if (value == FAIL)
6148 {
6149 /* Can't be done. Perhaps the code reads something like
6150 "add Rd, Rn, #-n", where "sub Rd, Rn, #n" would be OK. */
6151 if ((value = negate_data_op (&inst.instruction,
6152 inst.reloc.exp.X_add_number))
6153 == FAIL)
6154 {
6155 inst.error = _("invalid constant");
6156 return FAIL;
6157 }
6158 }
6159
6160 inst.instruction |= value;
6161 }
6162
6163 inst.instruction |= INST_IMMEDIATE;
6164 return SUCCESS;
6165 }
6166
6167 (*str)++;
6168 inst.error = _("register or shift expression expected");
6169 return FAIL;
6170 }
6171 }
6172
6173 static int
6174 fp_op2 (char ** str)
6175 {
6176 skip_whitespace (* str);
6177
6178 if (fp_reg_required_here (str, 0) != FAIL)
6179 return SUCCESS;
6180 else
6181 {
6182 /* Immediate expression. */
6183 if (*((*str)++) == '#')
6184 {
6185 int i;
6186
6187 inst.error = NULL;
6188
6189 skip_whitespace (* str);
6190
6191 /* First try and match exact strings, this is to guarantee
6192 that some formats will work even for cross assembly. */
6193
6194 for (i = 0; fp_const[i]; i++)
6195 {
6196 if (strncmp (*str, fp_const[i], strlen (fp_const[i])) == 0)
6197 {
6198 char *start = *str;
6199
6200 *str += strlen (fp_const[i]);
6201 if (is_end_of_line[(unsigned char) **str])
6202 {
6203 inst.instruction |= i + 8;
6204 return SUCCESS;
6205 }
6206 *str = start;
6207 }
6208 }
6209
6210 /* Just because we didn't get a match doesn't mean that the
6211 constant isn't valid, just that it is in a format that we
6212 don't automatically recognize. Try parsing it with
6213 the standard expression routines. */
6214 if ((i = my_get_float_expression (str)) >= 0)
6215 {
6216 inst.instruction |= i + 8;
6217 return SUCCESS;
6218 }
6219
6220 inst.error = _("invalid floating point immediate expression");
6221 return FAIL;
6222 }
6223 inst.error =
6224 _("floating point register or immediate expression expected");
6225 return FAIL;
6226 }
6227 }
6228
6229 static void
6230 do_arit (char * str)
6231 {
6232 skip_whitespace (str);
6233
6234 if (reg_required_here (&str, 12) == FAIL
6235 || skip_past_comma (&str) == FAIL
6236 || reg_required_here (&str, 16) == FAIL
6237 || skip_past_comma (&str) == FAIL
6238 || data_op2 (&str) == FAIL)
6239 {
6240 if (!inst.error)
6241 inst.error = BAD_ARGS;
6242 return;
6243 }
6244
6245 end_of_line (str);
6246 }
6247
6248 static void
6249 do_adr (char * str)
6250 {
6251 /* This is a pseudo-op of the form "adr rd, label" to be converted
6252 into a relative address of the form "add rd, pc, #label-.-8". */
6253 skip_whitespace (str);
6254
6255 if (reg_required_here (&str, 12) == FAIL
6256 || skip_past_comma (&str) == FAIL
6257 || my_get_expression (&inst.reloc.exp, &str))
6258 {
6259 if (!inst.error)
6260 inst.error = BAD_ARGS;
6261 return;
6262 }
6263
6264 /* Frag hacking will turn this into a sub instruction if the offset turns
6265 out to be negative. */
6266 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
6267 #ifndef TE_WINCE
6268 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust. */
6269 #endif
6270 inst.reloc.pc_rel = 1;
6271
6272 end_of_line (str);
6273 }
6274
6275 static void
6276 do_adrl (char * str)
6277 {
6278 /* This is a pseudo-op of the form "adrl rd, label" to be converted
6279 into a relative address of the form:
6280 add rd, pc, #low(label-.-8)"
6281 add rd, rd, #high(label-.-8)" */
6282
6283 skip_whitespace (str);
6284
6285 if (reg_required_here (&str, 12) == FAIL
6286 || skip_past_comma (&str) == FAIL
6287 || my_get_expression (&inst.reloc.exp, &str))
6288 {
6289 if (!inst.error)
6290 inst.error = BAD_ARGS;
6291
6292 return;
6293 }
6294
6295 end_of_line (str);
6296 /* Frag hacking will turn this into a sub instruction if the offset turns
6297 out to be negative. */
6298 inst.reloc.type = BFD_RELOC_ARM_ADRL_IMMEDIATE;
6299 #ifndef TE_WINCE
6300 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust */
6301 #endif
6302 inst.reloc.pc_rel = 1;
6303 inst.size = INSN_SIZE * 2;
6304 }
6305
6306 static void
6307 do_cmp (char * str)
6308 {
6309 skip_whitespace (str);
6310
6311 if (reg_required_here (&str, 16) == FAIL)
6312 {
6313 if (!inst.error)
6314 inst.error = BAD_ARGS;
6315 return;
6316 }
6317
6318 if (skip_past_comma (&str) == FAIL
6319 || data_op2 (&str) == FAIL)
6320 {
6321 if (!inst.error)
6322 inst.error = BAD_ARGS;
6323 return;
6324 }
6325
6326 end_of_line (str);
6327 }
6328
6329 static void
6330 do_mov (char * str)
6331 {
6332 skip_whitespace (str);
6333
6334 if (reg_required_here (&str, 12) == FAIL)
6335 {
6336 if (!inst.error)
6337 inst.error = BAD_ARGS;
6338 return;
6339 }
6340
6341 if (skip_past_comma (&str) == FAIL
6342 || data_op2 (&str) == FAIL)
6343 {
6344 if (!inst.error)
6345 inst.error = BAD_ARGS;
6346 return;
6347 }
6348
6349 end_of_line (str);
6350 }
6351
6352 static void
6353 do_ldst (char * str)
6354 {
6355 int pre_inc = 0;
6356 int conflict_reg;
6357 int value;
6358
6359 skip_whitespace (str);
6360
6361 if ((conflict_reg = reg_required_here (&str, 12)) == FAIL)
6362 {
6363 if (!inst.error)
6364 inst.error = BAD_ARGS;
6365 return;
6366 }
6367
6368 if (skip_past_comma (&str) == FAIL)
6369 {
6370 inst.error = _("address expected");
6371 return;
6372 }
6373
6374 if (*str == '[')
6375 {
6376 int reg;
6377
6378 str++;
6379
6380 skip_whitespace (str);
6381
6382 if ((reg = reg_required_here (&str, 16)) == FAIL)
6383 return;
6384
6385 /* Conflicts can occur on stores as well as loads. */
6386 conflict_reg = (conflict_reg == reg);
6387
6388 skip_whitespace (str);
6389
6390 if (*str == ']')
6391 {
6392 str ++;
6393
6394 if (skip_past_comma (&str) == SUCCESS)
6395 {
6396 /* [Rn],... (post inc) */
6397 if (ldst_extend (&str) == FAIL)
6398 return;
6399 if (conflict_reg)
6400 as_warn (_("%s register same as write-back base"),
6401 ((inst.instruction & LOAD_BIT)
6402 ? _("destination") : _("source")));
6403 }
6404 else
6405 {
6406 /* [Rn] */
6407 skip_whitespace (str);
6408
6409 if (*str == '!')
6410 {
6411 if (conflict_reg)
6412 as_warn (_("%s register same as write-back base"),
6413 ((inst.instruction & LOAD_BIT)
6414 ? _("destination") : _("source")));
6415 str++;
6416 inst.instruction |= WRITE_BACK;
6417 }
6418
6419 inst.instruction |= INDEX_UP;
6420 pre_inc = 1;
6421 }
6422 }
6423 else
6424 {
6425 /* [Rn,...] */
6426 if (skip_past_comma (&str) == FAIL)
6427 {
6428 inst.error = _("pre-indexed expression expected");
6429 return;
6430 }
6431
6432 pre_inc = 1;
6433 if (ldst_extend (&str) == FAIL)
6434 return;
6435
6436 skip_whitespace (str);
6437
6438 if (*str++ != ']')
6439 {
6440 inst.error = _("missing ]");
6441 return;
6442 }
6443
6444 skip_whitespace (str);
6445
6446 if (*str == '!')
6447 {
6448 if (conflict_reg)
6449 as_warn (_("%s register same as write-back base"),
6450 ((inst.instruction & LOAD_BIT)
6451 ? _("destination") : _("source")));
6452 str++;
6453 inst.instruction |= WRITE_BACK;
6454 }
6455 }
6456 }
6457 else if (*str == '=')
6458 {
6459 if ((inst.instruction & LOAD_BIT) == 0)
6460 {
6461 inst.error = _("invalid pseudo operation");
6462 return;
6463 }
6464
6465 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
6466 str++;
6467
6468 skip_whitespace (str);
6469
6470 if (my_get_expression (&inst.reloc.exp, &str))
6471 return;
6472
6473 if (inst.reloc.exp.X_op != O_constant
6474 && inst.reloc.exp.X_op != O_symbol)
6475 {
6476 inst.error = _("constant expression expected");
6477 return;
6478 }
6479
6480 if (inst.reloc.exp.X_op == O_constant)
6481 {
6482 value = validate_immediate (inst.reloc.exp.X_add_number);
6483
6484 if (value != FAIL)
6485 {
6486 /* This can be done with a mov instruction. */
6487 inst.instruction &= LITERAL_MASK;
6488 inst.instruction |= (INST_IMMEDIATE
6489 | (OPCODE_MOV << DATA_OP_SHIFT));
6490 inst.instruction |= value & 0xfff;
6491 end_of_line (str);
6492 return;
6493 }
6494
6495 value = validate_immediate (~inst.reloc.exp.X_add_number);
6496
6497 if (value != FAIL)
6498 {
6499 /* This can be done with a mvn instruction. */
6500 inst.instruction &= LITERAL_MASK;
6501 inst.instruction |= (INST_IMMEDIATE
6502 | (OPCODE_MVN << DATA_OP_SHIFT));
6503 inst.instruction |= value & 0xfff;
6504 end_of_line (str);
6505 return;
6506 }
6507 }
6508
6509 /* Insert into literal pool. */
6510 if (add_to_lit_pool () == FAIL)
6511 {
6512 if (!inst.error)
6513 inst.error = _("literal pool insertion failed");
6514 return;
6515 }
6516
6517 /* Change the instruction exp to point to the pool. */
6518 inst.reloc.type = BFD_RELOC_ARM_LITERAL;
6519 inst.reloc.pc_rel = 1;
6520 inst.instruction |= (REG_PC << 16);
6521 pre_inc = 1;
6522 }
6523 else
6524 {
6525 if (my_get_expression (&inst.reloc.exp, &str))
6526 return;
6527
6528 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
6529 #ifndef TE_WINCE
6530 /* PC rel adjust. */
6531 inst.reloc.exp.X_add_number -= 8;
6532 #endif
6533 inst.reloc.pc_rel = 1;
6534 inst.instruction |= (REG_PC << 16);
6535 pre_inc = 1;
6536 }
6537
6538 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
6539 end_of_line (str);
6540 }
6541
6542 static void
6543 do_ldstt (char * str)
6544 {
6545 int conflict_reg;
6546
6547 skip_whitespace (str);
6548
6549 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
6550 {
6551 if (!inst.error)
6552 inst.error = BAD_ARGS;
6553 return;
6554 }
6555
6556 if (skip_past_comma (& str) == FAIL)
6557 {
6558 inst.error = _("address expected");
6559 return;
6560 }
6561
6562 if (*str == '[')
6563 {
6564 int reg;
6565
6566 str++;
6567
6568 skip_whitespace (str);
6569
6570 if ((reg = reg_required_here (&str, 16)) == FAIL)
6571 return;
6572
6573 /* ldrt/strt always use post-indexed addressing, so if the base is
6574 the same as Rd, we warn. */
6575 if (conflict_reg == reg)
6576 as_warn (_("%s register same as write-back base"),
6577 ((inst.instruction & LOAD_BIT)
6578 ? _("destination") : _("source")));
6579
6580 skip_whitespace (str);
6581
6582 if (*str == ']')
6583 {
6584 str ++;
6585
6586 if (skip_past_comma (&str) == SUCCESS)
6587 {
6588 /* [Rn],... (post inc) */
6589 if (ldst_extend (&str) == FAIL)
6590 return;
6591 }
6592 else
6593 {
6594 /* [Rn] */
6595 skip_whitespace (str);
6596
6597 /* Skip a write-back '!'. */
6598 if (*str == '!')
6599 str++;
6600
6601 inst.instruction |= INDEX_UP;
6602 }
6603 }
6604 else
6605 {
6606 inst.error = _("post-indexed expression expected");
6607 return;
6608 }
6609 }
6610 else
6611 {
6612 inst.error = _("post-indexed expression expected");
6613 return;
6614 }
6615
6616 end_of_line (str);
6617 }
6618
6619 /* Halfword and signed-byte load/store operations. */
6620
6621 static void
6622 do_ldstv4 (char * str)
6623 {
6624 int pre_inc = 0;
6625 int conflict_reg;
6626 int value;
6627
6628 skip_whitespace (str);
6629
6630 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
6631 {
6632 if (!inst.error)
6633 inst.error = BAD_ARGS;
6634 return;
6635 }
6636
6637 if (skip_past_comma (& str) == FAIL)
6638 {
6639 inst.error = _("address expected");
6640 return;
6641 }
6642
6643 if (*str == '[')
6644 {
6645 int reg;
6646
6647 str++;
6648
6649 skip_whitespace (str);
6650
6651 if ((reg = reg_required_here (&str, 16)) == FAIL)
6652 return;
6653
6654 /* Conflicts can occur on stores as well as loads. */
6655 conflict_reg = (conflict_reg == reg);
6656
6657 skip_whitespace (str);
6658
6659 if (*str == ']')
6660 {
6661 str ++;
6662
6663 if (skip_past_comma (&str) == SUCCESS)
6664 {
6665 /* [Rn],... (post inc) */
6666 if (ldst_extend_v4 (&str) == FAIL)
6667 return;
6668 if (conflict_reg)
6669 as_warn (_("%s register same as write-back base"),
6670 ((inst.instruction & LOAD_BIT)
6671 ? _("destination") : _("source")));
6672 }
6673 else
6674 {
6675 /* [Rn] */
6676 inst.instruction |= HWOFFSET_IMM;
6677
6678 skip_whitespace (str);
6679
6680 if (*str == '!')
6681 {
6682 if (conflict_reg)
6683 as_warn (_("%s register same as write-back base"),
6684 ((inst.instruction & LOAD_BIT)
6685 ? _("destination") : _("source")));
6686 str++;
6687 inst.instruction |= WRITE_BACK;
6688 }
6689
6690 inst.instruction |= INDEX_UP;
6691 pre_inc = 1;
6692 }
6693 }
6694 else
6695 {
6696 /* [Rn,...] */
6697 if (skip_past_comma (&str) == FAIL)
6698 {
6699 inst.error = _("pre-indexed expression expected");
6700 return;
6701 }
6702
6703 pre_inc = 1;
6704 if (ldst_extend_v4 (&str) == FAIL)
6705 return;
6706
6707 skip_whitespace (str);
6708
6709 if (*str++ != ']')
6710 {
6711 inst.error = _("missing ]");
6712 return;
6713 }
6714
6715 skip_whitespace (str);
6716
6717 if (*str == '!')
6718 {
6719 if (conflict_reg)
6720 as_warn (_("%s register same as write-back base"),
6721 ((inst.instruction & LOAD_BIT)
6722 ? _("destination") : _("source")));
6723 str++;
6724 inst.instruction |= WRITE_BACK;
6725 }
6726 }
6727 }
6728 else if (*str == '=')
6729 {
6730 if ((inst.instruction & LOAD_BIT) == 0)
6731 {
6732 inst.error = _("invalid pseudo operation");
6733 return;
6734 }
6735
6736 /* XXX Does this work correctly for half-word/byte ops? */
6737 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
6738 str++;
6739
6740 skip_whitespace (str);
6741
6742 if (my_get_expression (&inst.reloc.exp, &str))
6743 return;
6744
6745 if (inst.reloc.exp.X_op != O_constant
6746 && inst.reloc.exp.X_op != O_symbol)
6747 {
6748 inst.error = _("constant expression expected");
6749 return;
6750 }
6751
6752 if (inst.reloc.exp.X_op == O_constant)
6753 {
6754 value = validate_immediate (inst.reloc.exp.X_add_number);
6755
6756 if (value != FAIL)
6757 {
6758 /* This can be done with a mov instruction. */
6759 inst.instruction &= LITERAL_MASK;
6760 inst.instruction |= INST_IMMEDIATE | (OPCODE_MOV << DATA_OP_SHIFT);
6761 inst.instruction |= value & 0xfff;
6762 end_of_line (str);
6763 return;
6764 }
6765
6766 value = validate_immediate (~ inst.reloc.exp.X_add_number);
6767
6768 if (value != FAIL)
6769 {
6770 /* This can be done with a mvn instruction. */
6771 inst.instruction &= LITERAL_MASK;
6772 inst.instruction |= INST_IMMEDIATE | (OPCODE_MVN << DATA_OP_SHIFT);
6773 inst.instruction |= value & 0xfff;
6774 end_of_line (str);
6775 return;
6776 }
6777 }
6778
6779 /* Insert into literal pool. */
6780 if (add_to_lit_pool () == FAIL)
6781 {
6782 if (!inst.error)
6783 inst.error = _("literal pool insertion failed");
6784 return;
6785 }
6786
6787 /* Change the instruction exp to point to the pool. */
6788 inst.instruction |= HWOFFSET_IMM;
6789 inst.reloc.type = BFD_RELOC_ARM_HWLITERAL;
6790 inst.reloc.pc_rel = 1;
6791 inst.instruction |= (REG_PC << 16);
6792 pre_inc = 1;
6793 }
6794 else
6795 {
6796 if (my_get_expression (&inst.reloc.exp, &str))
6797 return;
6798
6799 inst.instruction |= HWOFFSET_IMM;
6800 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
6801 #ifndef TE_WINCE
6802 /* PC rel adjust. */
6803 inst.reloc.exp.X_add_number -= 8;
6804 #endif
6805 inst.reloc.pc_rel = 1;
6806 inst.instruction |= (REG_PC << 16);
6807 pre_inc = 1;
6808 }
6809
6810 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
6811 end_of_line (str);
6812 }
6813
6814 static void
6815 do_ldsttv4 (char * str)
6816 {
6817 int conflict_reg;
6818
6819 skip_whitespace (str);
6820
6821 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
6822 {
6823 if (!inst.error)
6824 inst.error = BAD_ARGS;
6825 return;
6826 }
6827
6828 if (skip_past_comma (& str) == FAIL)
6829 {
6830 inst.error = _("address expected");
6831 return;
6832 }
6833
6834 if (*str == '[')
6835 {
6836 int reg;
6837
6838 str++;
6839
6840 skip_whitespace (str);
6841
6842 if ((reg = reg_required_here (&str, 16)) == FAIL)
6843 return;
6844
6845 /* ldrt/strt always use post-indexed addressing, so if the base is
6846 the same as Rd, we warn. */
6847 if (conflict_reg == reg)
6848 as_warn (_("%s register same as write-back base"),
6849 ((inst.instruction & LOAD_BIT)
6850 ? _("destination") : _("source")));
6851
6852 skip_whitespace (str);
6853
6854 if (*str == ']')
6855 {
6856 str ++;
6857
6858 if (skip_past_comma (&str) == SUCCESS)
6859 {
6860 /* [Rn],... (post inc) */
6861 if (ldst_extend_v4 (&str) == FAIL)
6862 return;
6863 }
6864 else
6865 {
6866 /* [Rn] */
6867 skip_whitespace (str);
6868
6869 /* Skip a write-back '!'. */
6870 if (*str == '!')
6871 str++;
6872
6873 inst.instruction |= (INDEX_UP|HWOFFSET_IMM);
6874 }
6875 }
6876 else
6877 {
6878 inst.error = _("post-indexed expression expected");
6879 return;
6880 }
6881 }
6882 else
6883 {
6884 inst.error = _("post-indexed expression expected");
6885 return;
6886 }
6887
6888 end_of_line (str);
6889 }
6890
6891
6892 static long
6893 reg_list (char ** strp)
6894 {
6895 char * str = * strp;
6896 long range = 0;
6897 int another_range;
6898
6899 /* We come back here if we get ranges concatenated by '+' or '|'. */
6900 do
6901 {
6902 another_range = 0;
6903
6904 if (*str == '{')
6905 {
6906 int in_range = 0;
6907 int cur_reg = -1;
6908
6909 str++;
6910 do
6911 {
6912 int reg;
6913
6914 skip_whitespace (str);
6915
6916 if ((reg = reg_required_here (& str, -1)) == FAIL)
6917 return FAIL;
6918
6919 if (in_range)
6920 {
6921 int i;
6922
6923 if (reg <= cur_reg)
6924 {
6925 inst.error = _("bad range in register list");
6926 return FAIL;
6927 }
6928
6929 for (i = cur_reg + 1; i < reg; i++)
6930 {
6931 if (range & (1 << i))
6932 as_tsktsk
6933 (_("Warning: duplicated register (r%d) in register list"),
6934 i);
6935 else
6936 range |= 1 << i;
6937 }
6938 in_range = 0;
6939 }
6940
6941 if (range & (1 << reg))
6942 as_tsktsk (_("Warning: duplicated register (r%d) in register list"),
6943 reg);
6944 else if (reg <= cur_reg)
6945 as_tsktsk (_("Warning: register range not in ascending order"));
6946
6947 range |= 1 << reg;
6948 cur_reg = reg;
6949 }
6950 while (skip_past_comma (&str) != FAIL
6951 || (in_range = 1, *str++ == '-'));
6952 str--;
6953 skip_whitespace (str);
6954
6955 if (*str++ != '}')
6956 {
6957 inst.error = _("missing `}'");
6958 return FAIL;
6959 }
6960 }
6961 else
6962 {
6963 expressionS expr;
6964
6965 if (my_get_expression (&expr, &str))
6966 return FAIL;
6967
6968 if (expr.X_op == O_constant)
6969 {
6970 if (expr.X_add_number
6971 != (expr.X_add_number & 0x0000ffff))
6972 {
6973 inst.error = _("invalid register mask");
6974 return FAIL;
6975 }
6976
6977 if ((range & expr.X_add_number) != 0)
6978 {
6979 int regno = range & expr.X_add_number;
6980
6981 regno &= -regno;
6982 regno = (1 << regno) - 1;
6983 as_tsktsk
6984 (_("Warning: duplicated register (r%d) in register list"),
6985 regno);
6986 }
6987
6988 range |= expr.X_add_number;
6989 }
6990 else
6991 {
6992 if (inst.reloc.type != 0)
6993 {
6994 inst.error = _("expression too complex");
6995 return FAIL;
6996 }
6997
6998 memcpy (&inst.reloc.exp, &expr, sizeof (expressionS));
6999 inst.reloc.type = BFD_RELOC_ARM_MULTI;
7000 inst.reloc.pc_rel = 0;
7001 }
7002 }
7003
7004 skip_whitespace (str);
7005
7006 if (*str == '|' || *str == '+')
7007 {
7008 str++;
7009 another_range = 1;
7010 }
7011 }
7012 while (another_range);
7013
7014 *strp = str;
7015 return range;
7016 }
7017
7018 static void
7019 do_ldmstm (char * str)
7020 {
7021 int base_reg;
7022 long range;
7023
7024 skip_whitespace (str);
7025
7026 if ((base_reg = reg_required_here (&str, 16)) == FAIL)
7027 return;
7028
7029 if (base_reg == REG_PC)
7030 {
7031 inst.error = _("r15 not allowed as base register");
7032 return;
7033 }
7034
7035 skip_whitespace (str);
7036
7037 if (*str == '!')
7038 {
7039 inst.instruction |= WRITE_BACK;
7040 str++;
7041 }
7042
7043 if (skip_past_comma (&str) == FAIL
7044 || (range = reg_list (&str)) == FAIL)
7045 {
7046 if (! inst.error)
7047 inst.error = BAD_ARGS;
7048 return;
7049 }
7050
7051 if (*str == '^')
7052 {
7053 str++;
7054 inst.instruction |= LDM_TYPE_2_OR_3;
7055 }
7056
7057 if (inst.instruction & WRITE_BACK)
7058 {
7059 /* Check for unpredictable uses of writeback. */
7060 if (inst.instruction & LOAD_BIT)
7061 {
7062 /* Not allowed in LDM type 2. */
7063 if ((inst.instruction & LDM_TYPE_2_OR_3)
7064 && ((range & (1 << REG_PC)) == 0))
7065 as_warn (_("writeback of base register is UNPREDICTABLE"));
7066 /* Only allowed if base reg not in list for other types. */
7067 else if (range & (1 << base_reg))
7068 as_warn (_("writeback of base register when in register list is UNPREDICTABLE"));
7069 }
7070 else /* STM. */
7071 {
7072 /* Not allowed for type 2. */
7073 if (inst.instruction & LDM_TYPE_2_OR_3)
7074 as_warn (_("writeback of base register is UNPREDICTABLE"));
7075 /* Only allowed if base reg not in list, or first in list. */
7076 else if ((range & (1 << base_reg))
7077 && (range & ((1 << base_reg) - 1)))
7078 as_warn (_("if writeback register is in list, it must be the lowest reg in the list"));
7079 }
7080 }
7081
7082 inst.instruction |= range;
7083 end_of_line (str);
7084 }
7085
7086 static void
7087 do_smi (char * str)
7088 {
7089 skip_whitespace (str);
7090
7091 /* Allow optional leading '#'. */
7092 if (is_immediate_prefix (*str))
7093 str++;
7094
7095 if (my_get_expression (& inst.reloc.exp, & str))
7096 return;
7097
7098 inst.reloc.type = BFD_RELOC_ARM_SMI;
7099 inst.reloc.pc_rel = 0;
7100 end_of_line (str);
7101 }
7102
7103 static void
7104 do_swi (char * str)
7105 {
7106 skip_whitespace (str);
7107
7108 /* Allow optional leading '#'. */
7109 if (is_immediate_prefix (*str))
7110 str++;
7111
7112 if (my_get_expression (& inst.reloc.exp, & str))
7113 return;
7114
7115 inst.reloc.type = BFD_RELOC_ARM_SWI;
7116 inst.reloc.pc_rel = 0;
7117 end_of_line (str);
7118 }
7119
7120 static void
7121 do_swap (char * str)
7122 {
7123 int reg;
7124
7125 skip_whitespace (str);
7126
7127 if ((reg = reg_required_here (&str, 12)) == FAIL)
7128 return;
7129
7130 if (reg == REG_PC)
7131 {
7132 inst.error = _("r15 not allowed in swap");
7133 return;
7134 }
7135
7136 if (skip_past_comma (&str) == FAIL
7137 || (reg = reg_required_here (&str, 0)) == FAIL)
7138 {
7139 if (!inst.error)
7140 inst.error = BAD_ARGS;
7141 return;
7142 }
7143
7144 if (reg == REG_PC)
7145 {
7146 inst.error = _("r15 not allowed in swap");
7147 return;
7148 }
7149
7150 if (skip_past_comma (&str) == FAIL
7151 || *str++ != '[')
7152 {
7153 inst.error = BAD_ARGS;
7154 return;
7155 }
7156
7157 skip_whitespace (str);
7158
7159 if ((reg = reg_required_here (&str, 16)) == FAIL)
7160 return;
7161
7162 if (reg == REG_PC)
7163 {
7164 inst.error = BAD_PC;
7165 return;
7166 }
7167
7168 skip_whitespace (str);
7169
7170 if (*str++ != ']')
7171 {
7172 inst.error = _("missing ]");
7173 return;
7174 }
7175
7176 end_of_line (str);
7177 }
7178
7179 static void
7180 do_branch (char * str)
7181 {
7182 if (my_get_expression (&inst.reloc.exp, &str))
7183 return;
7184
7185 #ifdef OBJ_ELF
7186 {
7187 char * save_in;
7188
7189 /* ScottB: February 5, 1998 - Check to see of PLT32 reloc
7190 required for the instruction. */
7191
7192 /* arm_parse_reloc () works on input_line_pointer.
7193 We actually want to parse the operands to the branch instruction
7194 passed in 'str'. Save the input pointer and restore it later. */
7195 save_in = input_line_pointer;
7196 input_line_pointer = str;
7197 if (inst.reloc.exp.X_op == O_symbol
7198 && *str == '('
7199 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
7200 {
7201 inst.reloc.type = BFD_RELOC_ARM_PLT32;
7202 inst.reloc.pc_rel = 0;
7203 /* Modify str to point to after parsed operands, otherwise
7204 end_of_line() will complain about the (PLT) left in str. */
7205 str = input_line_pointer;
7206 }
7207 else
7208 {
7209 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
7210 inst.reloc.pc_rel = 1;
7211 }
7212 input_line_pointer = save_in;
7213 }
7214 #else
7215 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
7216 inst.reloc.pc_rel = 1;
7217 #endif /* OBJ_ELF */
7218
7219 end_of_line (str);
7220 }
7221
7222 static void
7223 do_cdp (char * str)
7224 {
7225 /* Co-processor data operation.
7226 Format: CDP{cond} CP#,<expr>,CRd,CRn,CRm{,<expr>} */
7227 skip_whitespace (str);
7228
7229 if (co_proc_number (&str) == FAIL)
7230 {
7231 if (!inst.error)
7232 inst.error = BAD_ARGS;
7233 return;
7234 }
7235
7236 if (skip_past_comma (&str) == FAIL
7237 || cp_opc_expr (&str, 20,4) == FAIL)
7238 {
7239 if (!inst.error)
7240 inst.error = BAD_ARGS;
7241 return;
7242 }
7243
7244 if (skip_past_comma (&str) == FAIL
7245 || cp_reg_required_here (&str, 12) == FAIL)
7246 {
7247 if (!inst.error)
7248 inst.error = BAD_ARGS;
7249 return;
7250 }
7251
7252 if (skip_past_comma (&str) == FAIL
7253 || cp_reg_required_here (&str, 16) == FAIL)
7254 {
7255 if (!inst.error)
7256 inst.error = BAD_ARGS;
7257 return;
7258 }
7259
7260 if (skip_past_comma (&str) == FAIL
7261 || cp_reg_required_here (&str, 0) == FAIL)
7262 {
7263 if (!inst.error)
7264 inst.error = BAD_ARGS;
7265 return;
7266 }
7267
7268 if (skip_past_comma (&str) == SUCCESS)
7269 {
7270 if (cp_opc_expr (&str, 5, 3) == FAIL)
7271 {
7272 if (!inst.error)
7273 inst.error = BAD_ARGS;
7274 return;
7275 }
7276 }
7277
7278 end_of_line (str);
7279 }
7280
7281 static void
7282 do_lstc (char * str)
7283 {
7284 /* Co-processor register load/store.
7285 Format: <LDC|STC{cond}[L] CP#,CRd,<address> */
7286
7287 skip_whitespace (str);
7288
7289 if (co_proc_number (&str) == FAIL)
7290 {
7291 if (!inst.error)
7292 inst.error = BAD_ARGS;
7293 return;
7294 }
7295
7296 if (skip_past_comma (&str) == FAIL
7297 || cp_reg_required_here (&str, 12) == FAIL)
7298 {
7299 if (!inst.error)
7300 inst.error = BAD_ARGS;
7301 return;
7302 }
7303
7304 if (skip_past_comma (&str) == FAIL
7305 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
7306 {
7307 if (! inst.error)
7308 inst.error = BAD_ARGS;
7309 return;
7310 }
7311
7312 end_of_line (str);
7313 }
7314
7315 static void
7316 do_co_reg (char * str)
7317 {
7318 /* Co-processor register transfer.
7319 Format: <MCR|MRC>{cond} CP#,<expr1>,Rd,CRn,CRm{,<expr2>} */
7320
7321 skip_whitespace (str);
7322
7323 if (co_proc_number (&str) == FAIL)
7324 {
7325 if (!inst.error)
7326 inst.error = BAD_ARGS;
7327 return;
7328 }
7329
7330 if (skip_past_comma (&str) == FAIL
7331 || cp_opc_expr (&str, 21, 3) == FAIL)
7332 {
7333 if (!inst.error)
7334 inst.error = BAD_ARGS;
7335 return;
7336 }
7337
7338 if (skip_past_comma (&str) == FAIL
7339 || reg_required_here (&str, 12) == FAIL)
7340 {
7341 if (!inst.error)
7342 inst.error = BAD_ARGS;
7343 return;
7344 }
7345
7346 if (skip_past_comma (&str) == FAIL
7347 || cp_reg_required_here (&str, 16) == FAIL)
7348 {
7349 if (!inst.error)
7350 inst.error = BAD_ARGS;
7351 return;
7352 }
7353
7354 if (skip_past_comma (&str) == FAIL
7355 || cp_reg_required_here (&str, 0) == FAIL)
7356 {
7357 if (!inst.error)
7358 inst.error = BAD_ARGS;
7359 return;
7360 }
7361
7362 if (skip_past_comma (&str) == SUCCESS)
7363 {
7364 if (cp_opc_expr (&str, 5, 3) == FAIL)
7365 {
7366 if (!inst.error)
7367 inst.error = BAD_ARGS;
7368 return;
7369 }
7370 }
7371
7372 end_of_line (str);
7373 }
7374
7375 static void
7376 do_fpa_ctrl (char * str)
7377 {
7378 /* FP control registers.
7379 Format: <WFS|RFS|WFC|RFC>{cond} Rn */
7380
7381 skip_whitespace (str);
7382
7383 if (reg_required_here (&str, 12) == FAIL)
7384 {
7385 if (!inst.error)
7386 inst.error = BAD_ARGS;
7387 return;
7388 }
7389
7390 end_of_line (str);
7391 }
7392
7393 static void
7394 do_fpa_ldst (char * str)
7395 {
7396 skip_whitespace (str);
7397
7398 if (fp_reg_required_here (&str, 12) == FAIL)
7399 {
7400 if (!inst.error)
7401 inst.error = BAD_ARGS;
7402 return;
7403 }
7404
7405 if (skip_past_comma (&str) == FAIL
7406 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
7407 {
7408 if (!inst.error)
7409 inst.error = BAD_ARGS;
7410 return;
7411 }
7412
7413 end_of_line (str);
7414 }
7415
7416 static void
7417 do_fpa_ldmstm (char * str)
7418 {
7419 int num_regs;
7420
7421 skip_whitespace (str);
7422
7423 if (fp_reg_required_here (&str, 12) == FAIL)
7424 {
7425 if (! inst.error)
7426 inst.error = BAD_ARGS;
7427 return;
7428 }
7429
7430 /* Get Number of registers to transfer. */
7431 if (skip_past_comma (&str) == FAIL
7432 || my_get_expression (&inst.reloc.exp, &str))
7433 {
7434 if (! inst.error)
7435 inst.error = _("constant expression expected");
7436 return;
7437 }
7438
7439 if (inst.reloc.exp.X_op != O_constant)
7440 {
7441 inst.error = _("constant value required for number of registers");
7442 return;
7443 }
7444
7445 num_regs = inst.reloc.exp.X_add_number;
7446
7447 if (num_regs < 1 || num_regs > 4)
7448 {
7449 inst.error = _("number of registers must be in the range [1:4]");
7450 return;
7451 }
7452
7453 switch (num_regs)
7454 {
7455 case 1:
7456 inst.instruction |= CP_T_X;
7457 break;
7458 case 2:
7459 inst.instruction |= CP_T_Y;
7460 break;
7461 case 3:
7462 inst.instruction |= CP_T_Y | CP_T_X;
7463 break;
7464 case 4:
7465 break;
7466 default:
7467 abort ();
7468 }
7469
7470 if (inst.instruction & (CP_T_Pre | CP_T_UD)) /* ea/fd format. */
7471 {
7472 int reg;
7473 int write_back;
7474 int offset;
7475
7476 /* The instruction specified "ea" or "fd", so we can only accept
7477 [Rn]{!}. The instruction does not really support stacking or
7478 unstacking, so we have to emulate these by setting appropriate
7479 bits and offsets. */
7480 if (skip_past_comma (&str) == FAIL
7481 || *str != '[')
7482 {
7483 if (! inst.error)
7484 inst.error = BAD_ARGS;
7485 return;
7486 }
7487
7488 str++;
7489 skip_whitespace (str);
7490
7491 if ((reg = reg_required_here (&str, 16)) == FAIL)
7492 return;
7493
7494 skip_whitespace (str);
7495
7496 if (*str != ']')
7497 {
7498 inst.error = BAD_ARGS;
7499 return;
7500 }
7501
7502 str++;
7503 if (*str == '!')
7504 {
7505 write_back = 1;
7506 str++;
7507 if (reg == REG_PC)
7508 {
7509 inst.error =
7510 _("r15 not allowed as base register with write-back");
7511 return;
7512 }
7513 }
7514 else
7515 write_back = 0;
7516
7517 if (inst.instruction & CP_T_Pre)
7518 {
7519 /* Pre-decrement. */
7520 offset = 3 * num_regs;
7521 if (write_back)
7522 inst.instruction |= CP_T_WB;
7523 }
7524 else
7525 {
7526 /* Post-increment. */
7527 if (write_back)
7528 {
7529 inst.instruction |= CP_T_WB;
7530 offset = 3 * num_regs;
7531 }
7532 else
7533 {
7534 /* No write-back, so convert this into a standard pre-increment
7535 instruction -- aesthetically more pleasing. */
7536 inst.instruction |= CP_T_Pre | CP_T_UD;
7537 offset = 0;
7538 }
7539 }
7540
7541 inst.instruction |= offset;
7542 }
7543 else if (skip_past_comma (&str) == FAIL
7544 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
7545 {
7546 if (! inst.error)
7547 inst.error = BAD_ARGS;
7548 return;
7549 }
7550
7551 end_of_line (str);
7552 }
7553
7554 static void
7555 do_fpa_dyadic (char * str)
7556 {
7557 skip_whitespace (str);
7558
7559 if (fp_reg_required_here (&str, 12) == FAIL)
7560 {
7561 if (! inst.error)
7562 inst.error = BAD_ARGS;
7563 return;
7564 }
7565
7566 if (skip_past_comma (&str) == FAIL
7567 || fp_reg_required_here (&str, 16) == FAIL)
7568 {
7569 if (! inst.error)
7570 inst.error = BAD_ARGS;
7571 return;
7572 }
7573
7574 if (skip_past_comma (&str) == FAIL
7575 || fp_op2 (&str) == FAIL)
7576 {
7577 if (! inst.error)
7578 inst.error = BAD_ARGS;
7579 return;
7580 }
7581
7582 end_of_line (str);
7583 }
7584
7585 static void
7586 do_fpa_monadic (char * str)
7587 {
7588 skip_whitespace (str);
7589
7590 if (fp_reg_required_here (&str, 12) == FAIL)
7591 {
7592 if (! inst.error)
7593 inst.error = BAD_ARGS;
7594 return;
7595 }
7596
7597 if (skip_past_comma (&str) == FAIL
7598 || fp_op2 (&str) == FAIL)
7599 {
7600 if (! inst.error)
7601 inst.error = BAD_ARGS;
7602 return;
7603 }
7604
7605 end_of_line (str);
7606 }
7607
7608 static void
7609 do_fpa_cmp (char * str)
7610 {
7611 skip_whitespace (str);
7612
7613 if (fp_reg_required_here (&str, 16) == FAIL)
7614 {
7615 if (! inst.error)
7616 inst.error = BAD_ARGS;
7617 return;
7618 }
7619
7620 if (skip_past_comma (&str) == FAIL
7621 || fp_op2 (&str) == FAIL)
7622 {
7623 if (! inst.error)
7624 inst.error = BAD_ARGS;
7625 return;
7626 }
7627
7628 end_of_line (str);
7629 }
7630
7631 static void
7632 do_fpa_from_reg (char * str)
7633 {
7634 skip_whitespace (str);
7635
7636 if (fp_reg_required_here (&str, 16) == FAIL)
7637 {
7638 if (! inst.error)
7639 inst.error = BAD_ARGS;
7640 return;
7641 }
7642
7643 if (skip_past_comma (&str) == FAIL
7644 || reg_required_here (&str, 12) == FAIL)
7645 {
7646 if (! inst.error)
7647 inst.error = BAD_ARGS;
7648 return;
7649 }
7650
7651 end_of_line (str);
7652 }
7653
7654 static void
7655 do_fpa_to_reg (char * str)
7656 {
7657 skip_whitespace (str);
7658
7659 if (reg_required_here (&str, 12) == FAIL)
7660 return;
7661
7662 if (skip_past_comma (&str) == FAIL
7663 || fp_reg_required_here (&str, 0) == FAIL)
7664 {
7665 if (! inst.error)
7666 inst.error = BAD_ARGS;
7667 return;
7668 }
7669
7670 end_of_line (str);
7671 }
7672
7673 /* Encode a VFP SP register number. */
7674
7675 static void
7676 vfp_sp_encode_reg (int reg, enum vfp_sp_reg_pos pos)
7677 {
7678 switch (pos)
7679 {
7680 case VFP_REG_Sd:
7681 inst.instruction |= ((reg >> 1) << 12) | ((reg & 1) << 22);
7682 break;
7683
7684 case VFP_REG_Sn:
7685 inst.instruction |= ((reg >> 1) << 16) | ((reg & 1) << 7);
7686 break;
7687
7688 case VFP_REG_Sm:
7689 inst.instruction |= ((reg >> 1) << 0) | ((reg & 1) << 5);
7690 break;
7691
7692 default:
7693 abort ();
7694 }
7695 }
7696
7697 static int
7698 vfp_sp_reg_required_here (char ** str,
7699 enum vfp_sp_reg_pos pos)
7700 {
7701 int reg;
7702 char * start = *str;
7703
7704 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_SN].htab)) != FAIL)
7705 {
7706 vfp_sp_encode_reg (reg, pos);
7707 return reg;
7708 }
7709
7710 /* In the few cases where we might be able to accept something else
7711 this error can be overridden. */
7712 inst.error = _(all_reg_maps[REG_TYPE_SN].expected);
7713
7714 /* Restore the start point. */
7715 *str = start;
7716 return FAIL;
7717 }
7718
7719 static int
7720 vfp_dp_reg_required_here (char ** str,
7721 enum vfp_dp_reg_pos pos)
7722 {
7723 int reg;
7724 char * start = *str;
7725
7726 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_DN].htab)) != FAIL)
7727 {
7728 switch (pos)
7729 {
7730 case VFP_REG_Dd:
7731 inst.instruction |= reg << 12;
7732 break;
7733
7734 case VFP_REG_Dn:
7735 inst.instruction |= reg << 16;
7736 break;
7737
7738 case VFP_REG_Dm:
7739 inst.instruction |= reg << 0;
7740 break;
7741
7742 default:
7743 abort ();
7744 }
7745 return reg;
7746 }
7747
7748 /* In the few cases where we might be able to accept something else
7749 this error can be overridden. */
7750 inst.error = _(all_reg_maps[REG_TYPE_DN].expected);
7751
7752 /* Restore the start point. */
7753 *str = start;
7754 return FAIL;
7755 }
7756
7757 static void
7758 do_vfp_sp_monadic (char * str)
7759 {
7760 skip_whitespace (str);
7761
7762 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
7763 return;
7764
7765 if (skip_past_comma (&str) == FAIL
7766 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
7767 {
7768 if (! inst.error)
7769 inst.error = BAD_ARGS;
7770 return;
7771 }
7772
7773 end_of_line (str);
7774 }
7775
7776 static void
7777 do_vfp_dp_monadic (char * str)
7778 {
7779 skip_whitespace (str);
7780
7781 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
7782 return;
7783
7784 if (skip_past_comma (&str) == FAIL
7785 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
7786 {
7787 if (! inst.error)
7788 inst.error = BAD_ARGS;
7789 return;
7790 }
7791
7792 end_of_line (str);
7793 }
7794
7795 static void
7796 do_vfp_sp_dyadic (char * str)
7797 {
7798 skip_whitespace (str);
7799
7800 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
7801 return;
7802
7803 if (skip_past_comma (&str) == FAIL
7804 || vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL
7805 || skip_past_comma (&str) == FAIL
7806 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
7807 {
7808 if (! inst.error)
7809 inst.error = BAD_ARGS;
7810 return;
7811 }
7812
7813 end_of_line (str);
7814 }
7815
7816 static void
7817 do_vfp_dp_dyadic (char * str)
7818 {
7819 skip_whitespace (str);
7820
7821 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
7822 return;
7823
7824 if (skip_past_comma (&str) == FAIL
7825 || vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL
7826 || skip_past_comma (&str) == FAIL
7827 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
7828 {
7829 if (! inst.error)
7830 inst.error = BAD_ARGS;
7831 return;
7832 }
7833
7834 end_of_line (str);
7835 }
7836
7837 static void
7838 do_vfp_reg_from_sp (char * str)
7839 {
7840 skip_whitespace (str);
7841
7842 if (reg_required_here (&str, 12) == FAIL)
7843 return;
7844
7845 if (skip_past_comma (&str) == FAIL
7846 || vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL)
7847 {
7848 if (! inst.error)
7849 inst.error = BAD_ARGS;
7850 return;
7851 }
7852
7853 end_of_line (str);
7854 }
7855
7856 /* Parse a VFP register list. If the string is invalid return FAIL.
7857 Otherwise return the number of registers, and set PBASE to the first
7858 register. Double precision registers are matched if DP is nonzero. */
7859
7860 static int
7861 vfp_parse_reg_list (char **str, int *pbase, int dp)
7862 {
7863 int base_reg;
7864 int new_base;
7865 int regtype;
7866 int max_regs;
7867 int count = 0;
7868 int warned = 0;
7869 unsigned long mask = 0;
7870 int i;
7871
7872 if (**str != '{')
7873 return FAIL;
7874
7875 (*str)++;
7876 skip_whitespace (*str);
7877
7878 if (dp)
7879 {
7880 regtype = REG_TYPE_DN;
7881 max_regs = 16;
7882 }
7883 else
7884 {
7885 regtype = REG_TYPE_SN;
7886 max_regs = 32;
7887 }
7888
7889 base_reg = max_regs;
7890
7891 do
7892 {
7893 new_base = arm_reg_parse (str, all_reg_maps[regtype].htab);
7894 if (new_base == FAIL)
7895 {
7896 inst.error = _(all_reg_maps[regtype].expected);
7897 return FAIL;
7898 }
7899
7900 if (new_base < base_reg)
7901 base_reg = new_base;
7902
7903 if (mask & (1 << new_base))
7904 {
7905 inst.error = _("invalid register list");
7906 return FAIL;
7907 }
7908
7909 if ((mask >> new_base) != 0 && ! warned)
7910 {
7911 as_tsktsk (_("register list not in ascending order"));
7912 warned = 1;
7913 }
7914
7915 mask |= 1 << new_base;
7916 count++;
7917
7918 skip_whitespace (*str);
7919
7920 if (**str == '-') /* We have the start of a range expression */
7921 {
7922 int high_range;
7923
7924 (*str)++;
7925
7926 if ((high_range
7927 = arm_reg_parse (str, all_reg_maps[regtype].htab))
7928 == FAIL)
7929 {
7930 inst.error = _(all_reg_maps[regtype].expected);
7931 return FAIL;
7932 }
7933
7934 if (high_range <= new_base)
7935 {
7936 inst.error = _("register range not in ascending order");
7937 return FAIL;
7938 }
7939
7940 for (new_base++; new_base <= high_range; new_base++)
7941 {
7942 if (mask & (1 << new_base))
7943 {
7944 inst.error = _("invalid register list");
7945 return FAIL;
7946 }
7947
7948 mask |= 1 << new_base;
7949 count++;
7950 }
7951 }
7952 }
7953 while (skip_past_comma (str) != FAIL);
7954
7955 (*str)++;
7956
7957 /* Sanity check -- should have raised a parse error above. */
7958 if (count == 0 || count > max_regs)
7959 abort ();
7960
7961 *pbase = base_reg;
7962
7963 /* Final test -- the registers must be consecutive. */
7964 mask >>= base_reg;
7965 for (i = 0; i < count; i++)
7966 {
7967 if ((mask & (1u << i)) == 0)
7968 {
7969 inst.error = _("non-contiguous register range");
7970 return FAIL;
7971 }
7972 }
7973
7974 return count;
7975 }
7976
7977 static void
7978 do_vfp_reg2_from_sp2 (char * str)
7979 {
7980 int reg;
7981
7982 skip_whitespace (str);
7983
7984 if (reg_required_here (&str, 12) == FAIL
7985 || skip_past_comma (&str) == FAIL
7986 || reg_required_here (&str, 16) == FAIL
7987 || skip_past_comma (&str) == FAIL)
7988 {
7989 if (! inst.error)
7990 inst.error = BAD_ARGS;
7991 return;
7992 }
7993
7994 /* We require exactly two consecutive SP registers. */
7995 if (vfp_parse_reg_list (&str, &reg, 0) != 2)
7996 {
7997 if (! inst.error)
7998 inst.error = _("only two consecutive VFP SP registers allowed here");
7999 }
8000 vfp_sp_encode_reg (reg, VFP_REG_Sm);
8001
8002 end_of_line (str);
8003 }
8004
8005 static void
8006 do_vfp_sp_from_reg (char * str)
8007 {
8008 skip_whitespace (str);
8009
8010 if (vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL)
8011 return;
8012
8013 if (skip_past_comma (&str) == FAIL
8014 || reg_required_here (&str, 12) == FAIL)
8015 {
8016 if (! inst.error)
8017 inst.error = BAD_ARGS;
8018 return;
8019 }
8020
8021 end_of_line (str);
8022 }
8023
8024 static void
8025 do_vfp_sp2_from_reg2 (char * str)
8026 {
8027 int reg;
8028
8029 skip_whitespace (str);
8030
8031 /* We require exactly two consecutive SP registers. */
8032 if (vfp_parse_reg_list (&str, &reg, 0) != 2)
8033 {
8034 if (! inst.error)
8035 inst.error = _("only two consecutive VFP SP registers allowed here");
8036 }
8037 vfp_sp_encode_reg (reg, VFP_REG_Sm);
8038
8039 if (skip_past_comma (&str) == FAIL
8040 || reg_required_here (&str, 12) == FAIL
8041 || skip_past_comma (&str) == FAIL
8042 || reg_required_here (&str, 16) == FAIL)
8043 {
8044 if (! inst.error)
8045 inst.error = BAD_ARGS;
8046 return;
8047 }
8048
8049 end_of_line (str);
8050 }
8051
8052 static void
8053 do_vfp_reg_from_dp (char * str)
8054 {
8055 skip_whitespace (str);
8056
8057 if (reg_required_here (&str, 12) == FAIL)
8058 return;
8059
8060 if (skip_past_comma (&str) == FAIL
8061 || vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL)
8062 {
8063 if (! inst.error)
8064 inst.error = BAD_ARGS;
8065 return;
8066 }
8067
8068 end_of_line (str);
8069 }
8070
8071 static void
8072 do_vfp_reg2_from_dp (char * str)
8073 {
8074 skip_whitespace (str);
8075
8076 if (reg_required_here (&str, 12) == FAIL)
8077 return;
8078
8079 if (skip_past_comma (&str) == FAIL
8080 || reg_required_here (&str, 16) == FAIL
8081 || skip_past_comma (&str) == FAIL
8082 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
8083 {
8084 if (! inst.error)
8085 inst.error = BAD_ARGS;
8086 return;
8087 }
8088
8089 end_of_line (str);
8090 }
8091
8092 static void
8093 do_vfp_dp_from_reg (char * str)
8094 {
8095 skip_whitespace (str);
8096
8097 if (vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL)
8098 return;
8099
8100 if (skip_past_comma (&str) == FAIL
8101 || reg_required_here (&str, 12) == FAIL)
8102 {
8103 if (! inst.error)
8104 inst.error = BAD_ARGS;
8105 return;
8106 }
8107
8108 end_of_line (str);
8109 }
8110
8111 static void
8112 do_vfp_dp_from_reg2 (char * str)
8113 {
8114 skip_whitespace (str);
8115
8116 if (vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
8117 return;
8118
8119 if (skip_past_comma (&str) == FAIL
8120 || reg_required_here (&str, 12) == FAIL
8121 || skip_past_comma (&str) == FAIL
8122 || reg_required_here (&str, 16) == FAIL)
8123 {
8124 if (! inst.error)
8125 inst.error = BAD_ARGS;
8126 return;
8127 }
8128
8129 end_of_line (str);
8130 }
8131
8132 static const struct vfp_reg *
8133 vfp_psr_parse (char ** str)
8134 {
8135 char *start = *str;
8136 char c;
8137 char *p;
8138 const struct vfp_reg *vreg;
8139
8140 p = start;
8141
8142 /* Find the end of the current token. */
8143 do
8144 {
8145 c = *p++;
8146 }
8147 while (ISALPHA (c));
8148
8149 /* Mark it. */
8150 *--p = 0;
8151
8152 for (vreg = vfp_regs + 0;
8153 vreg < vfp_regs + sizeof (vfp_regs) / sizeof (struct vfp_reg);
8154 vreg++)
8155 {
8156 if (streq (start, vreg->name))
8157 {
8158 *p = c;
8159 *str = p;
8160 return vreg;
8161 }
8162 }
8163
8164 *p = c;
8165 return NULL;
8166 }
8167
8168 static int
8169 vfp_psr_required_here (char ** str)
8170 {
8171 char *start = *str;
8172 const struct vfp_reg *vreg;
8173
8174 vreg = vfp_psr_parse (str);
8175
8176 if (vreg)
8177 {
8178 inst.instruction |= vreg->regno;
8179 return SUCCESS;
8180 }
8181
8182 inst.error = _("VFP system register expected");
8183
8184 *str = start;
8185 return FAIL;
8186 }
8187
8188 static void
8189 do_vfp_reg_from_ctrl (char * str)
8190 {
8191 skip_whitespace (str);
8192
8193 if (reg_required_here (&str, 12) == FAIL)
8194 return;
8195
8196 if (skip_past_comma (&str) == FAIL
8197 || vfp_psr_required_here (&str) == FAIL)
8198 {
8199 if (! inst.error)
8200 inst.error = BAD_ARGS;
8201 return;
8202 }
8203
8204 end_of_line (str);
8205 }
8206
8207 static void
8208 do_vfp_ctrl_from_reg (char * str)
8209 {
8210 skip_whitespace (str);
8211
8212 if (vfp_psr_required_here (&str) == FAIL)
8213 return;
8214
8215 if (skip_past_comma (&str) == FAIL
8216 || reg_required_here (&str, 12) == FAIL)
8217 {
8218 if (! inst.error)
8219 inst.error = BAD_ARGS;
8220 return;
8221 }
8222
8223 end_of_line (str);
8224 }
8225
8226 static void
8227 do_vfp_sp_ldst (char * str)
8228 {
8229 skip_whitespace (str);
8230
8231 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
8232 {
8233 if (!inst.error)
8234 inst.error = BAD_ARGS;
8235 return;
8236 }
8237
8238 if (skip_past_comma (&str) == FAIL
8239 || cp_address_required_here (&str, CP_NO_WB) == FAIL)
8240 {
8241 if (!inst.error)
8242 inst.error = BAD_ARGS;
8243 return;
8244 }
8245
8246 end_of_line (str);
8247 }
8248
8249 static void
8250 do_vfp_dp_ldst (char * str)
8251 {
8252 skip_whitespace (str);
8253
8254 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
8255 {
8256 if (!inst.error)
8257 inst.error = BAD_ARGS;
8258 return;
8259 }
8260
8261 if (skip_past_comma (&str) == FAIL
8262 || cp_address_required_here (&str, CP_NO_WB) == FAIL)
8263 {
8264 if (!inst.error)
8265 inst.error = BAD_ARGS;
8266 return;
8267 }
8268
8269 end_of_line (str);
8270 }
8271
8272
8273 static void
8274 vfp_sp_ldstm (char * str, enum vfp_ldstm_type ldstm_type)
8275 {
8276 int count;
8277 int reg;
8278
8279 skip_whitespace (str);
8280
8281 if (reg_required_here (&str, 16) == FAIL)
8282 return;
8283
8284 skip_whitespace (str);
8285
8286 if (*str == '!')
8287 {
8288 inst.instruction |= WRITE_BACK;
8289 str++;
8290 }
8291 else if (ldstm_type != VFP_LDSTMIA)
8292 {
8293 inst.error = _("this addressing mode requires base-register writeback");
8294 return;
8295 }
8296
8297 if (skip_past_comma (&str) == FAIL
8298 || (count = vfp_parse_reg_list (&str, &reg, 0)) == FAIL)
8299 {
8300 if (!inst.error)
8301 inst.error = BAD_ARGS;
8302 return;
8303 }
8304 vfp_sp_encode_reg (reg, VFP_REG_Sd);
8305
8306 inst.instruction |= count;
8307 end_of_line (str);
8308 }
8309
8310 static void
8311 vfp_dp_ldstm (char * str, enum vfp_ldstm_type ldstm_type)
8312 {
8313 int count;
8314 int reg;
8315
8316 skip_whitespace (str);
8317
8318 if (reg_required_here (&str, 16) == FAIL)
8319 return;
8320
8321 skip_whitespace (str);
8322
8323 if (*str == '!')
8324 {
8325 inst.instruction |= WRITE_BACK;
8326 str++;
8327 }
8328 else if (ldstm_type != VFP_LDSTMIA && ldstm_type != VFP_LDSTMIAX)
8329 {
8330 inst.error = _("this addressing mode requires base-register writeback");
8331 return;
8332 }
8333
8334 if (skip_past_comma (&str) == FAIL
8335 || (count = vfp_parse_reg_list (&str, &reg, 1)) == FAIL)
8336 {
8337 if (!inst.error)
8338 inst.error = BAD_ARGS;
8339 return;
8340 }
8341
8342 count <<= 1;
8343 if (ldstm_type == VFP_LDSTMIAX || ldstm_type == VFP_LDSTMDBX)
8344 count += 1;
8345
8346 inst.instruction |= (reg << 12) | count;
8347 end_of_line (str);
8348 }
8349
8350 static void
8351 do_vfp_sp_ldstmia (char * str)
8352 {
8353 vfp_sp_ldstm (str, VFP_LDSTMIA);
8354 }
8355
8356 static void
8357 do_vfp_sp_ldstmdb (char * str)
8358 {
8359 vfp_sp_ldstm (str, VFP_LDSTMDB);
8360 }
8361
8362 static void
8363 do_vfp_dp_ldstmia (char * str)
8364 {
8365 vfp_dp_ldstm (str, VFP_LDSTMIA);
8366 }
8367
8368 static void
8369 do_vfp_dp_ldstmdb (char * str)
8370 {
8371 vfp_dp_ldstm (str, VFP_LDSTMDB);
8372 }
8373
8374 static void
8375 do_vfp_xp_ldstmia (char *str)
8376 {
8377 vfp_dp_ldstm (str, VFP_LDSTMIAX);
8378 }
8379
8380 static void
8381 do_vfp_xp_ldstmdb (char * str)
8382 {
8383 vfp_dp_ldstm (str, VFP_LDSTMDBX);
8384 }
8385
8386 static void
8387 do_vfp_sp_compare_z (char * str)
8388 {
8389 skip_whitespace (str);
8390
8391 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
8392 {
8393 if (!inst.error)
8394 inst.error = BAD_ARGS;
8395 return;
8396 }
8397
8398 end_of_line (str);
8399 }
8400
8401 static void
8402 do_vfp_dp_compare_z (char * str)
8403 {
8404 skip_whitespace (str);
8405
8406 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
8407 {
8408 if (!inst.error)
8409 inst.error = BAD_ARGS;
8410 return;
8411 }
8412
8413 end_of_line (str);
8414 }
8415
8416 static void
8417 do_vfp_dp_sp_cvt (char * str)
8418 {
8419 skip_whitespace (str);
8420
8421 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
8422 return;
8423
8424 if (skip_past_comma (&str) == FAIL
8425 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
8426 {
8427 if (! inst.error)
8428 inst.error = BAD_ARGS;
8429 return;
8430 }
8431
8432 end_of_line (str);
8433 }
8434
8435 static void
8436 do_vfp_sp_dp_cvt (char * str)
8437 {
8438 skip_whitespace (str);
8439
8440 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
8441 return;
8442
8443 if (skip_past_comma (&str) == FAIL
8444 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
8445 {
8446 if (! inst.error)
8447 inst.error = BAD_ARGS;
8448 return;
8449 }
8450
8451 end_of_line (str);
8452 }
8453
8454 /* Thumb specific routines. */
8455
8456 /* Parse an add or subtract instruction, SUBTRACT is non-zero if the opcode
8457 was SUB. */
8458
8459 static void
8460 thumb_add_sub (char * str, int subtract)
8461 {
8462 int Rd, Rs, Rn = FAIL;
8463
8464 skip_whitespace (str);
8465
8466 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
8467 || skip_past_comma (&str) == FAIL)
8468 {
8469 if (! inst.error)
8470 inst.error = BAD_ARGS;
8471 return;
8472 }
8473
8474 if (is_immediate_prefix (*str))
8475 {
8476 Rs = Rd;
8477 str++;
8478 if (my_get_expression (&inst.reloc.exp, &str))
8479 return;
8480 }
8481 else
8482 {
8483 if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
8484 return;
8485
8486 if (skip_past_comma (&str) == FAIL)
8487 {
8488 /* Two operand format, shuffle the registers
8489 and pretend there are 3. */
8490 Rn = Rs;
8491 Rs = Rd;
8492 }
8493 else if (is_immediate_prefix (*str))
8494 {
8495 str++;
8496 if (my_get_expression (&inst.reloc.exp, &str))
8497 return;
8498 }
8499 else if ((Rn = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
8500 return;
8501 }
8502
8503 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
8504 for the latter case, EXPR contains the immediate that was found. */
8505 if (Rn != FAIL)
8506 {
8507 /* All register format. */
8508 if (Rd > 7 || Rs > 7 || Rn > 7)
8509 {
8510 if (Rs != Rd)
8511 {
8512 inst.error = _("dest and source1 must be the same register");
8513 return;
8514 }
8515
8516 /* Can't do this for SUB. */
8517 if (subtract)
8518 {
8519 inst.error = _("subtract valid only on lo regs");
8520 return;
8521 }
8522
8523 inst.instruction = (T_OPCODE_ADD_HI
8524 | (Rd > 7 ? THUMB_H1 : 0)
8525 | (Rn > 7 ? THUMB_H2 : 0));
8526 inst.instruction |= (Rd & 7) | ((Rn & 7) << 3);
8527 }
8528 else
8529 {
8530 inst.instruction = subtract ? T_OPCODE_SUB_R3 : T_OPCODE_ADD_R3;
8531 inst.instruction |= Rd | (Rs << 3) | (Rn << 6);
8532 }
8533 }
8534 else
8535 {
8536 /* Immediate expression, now things start to get nasty. */
8537
8538 /* First deal with HI regs, only very restricted cases allowed:
8539 Adjusting SP, and using PC or SP to get an address. */
8540 if ((Rd > 7 && (Rd != REG_SP || Rs != REG_SP))
8541 || (Rs > 7 && Rs != REG_SP && Rs != REG_PC))
8542 {
8543 inst.error = _("invalid Hi register with immediate");
8544 return;
8545 }
8546
8547 if (inst.reloc.exp.X_op != O_constant)
8548 {
8549 /* Value isn't known yet, all we can do is store all the fragments
8550 we know about in the instruction and let the reloc hacking
8551 work it all out. */
8552 inst.instruction = (subtract ? 0x8000 : 0) | (Rd << 4) | Rs;
8553 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
8554 }
8555 else
8556 {
8557 int offset = inst.reloc.exp.X_add_number;
8558
8559 if (subtract)
8560 offset = - offset;
8561
8562 if (offset < 0)
8563 {
8564 offset = - offset;
8565 subtract = 1;
8566
8567 /* Quick check, in case offset is MIN_INT. */
8568 if (offset < 0)
8569 {
8570 inst.error = _("immediate value out of range");
8571 return;
8572 }
8573 }
8574 /* Note - you cannot convert a subtract of 0 into an
8575 add of 0 because the carry flag is set differently. */
8576 else if (offset > 0)
8577 subtract = 0;
8578
8579 if (Rd == REG_SP)
8580 {
8581 if (offset & ~0x1fc)
8582 {
8583 inst.error = _("invalid immediate value for stack adjust");
8584 return;
8585 }
8586 inst.instruction = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
8587 inst.instruction |= offset >> 2;
8588 }
8589 else if (Rs == REG_PC || Rs == REG_SP)
8590 {
8591 if (subtract
8592 || (offset & ~0x3fc))
8593 {
8594 inst.error = _("invalid immediate for address calculation");
8595 return;
8596 }
8597 inst.instruction = (Rs == REG_PC ? T_OPCODE_ADD_PC
8598 : T_OPCODE_ADD_SP);
8599 inst.instruction |= (Rd << 8) | (offset >> 2);
8600 }
8601 else if (Rs == Rd)
8602 {
8603 if (offset & ~0xff)
8604 {
8605 inst.error = _("immediate value out of range");
8606 return;
8607 }
8608 inst.instruction = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
8609 inst.instruction |= (Rd << 8) | offset;
8610 }
8611 else
8612 {
8613 if (offset & ~0x7)
8614 {
8615 inst.error = _("immediate value out of range");
8616 return;
8617 }
8618 inst.instruction = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
8619 inst.instruction |= Rd | (Rs << 3) | (offset << 6);
8620 }
8621 }
8622 }
8623
8624 end_of_line (str);
8625 }
8626
8627 static void
8628 thumb_shift (char * str, int shift)
8629 {
8630 int Rd, Rs, Rn = FAIL;
8631
8632 skip_whitespace (str);
8633
8634 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
8635 || skip_past_comma (&str) == FAIL)
8636 {
8637 if (! inst.error)
8638 inst.error = BAD_ARGS;
8639 return;
8640 }
8641
8642 if (is_immediate_prefix (*str))
8643 {
8644 /* Two operand immediate format, set Rs to Rd. */
8645 Rs = Rd;
8646 str ++;
8647 if (my_get_expression (&inst.reloc.exp, &str))
8648 return;
8649 }
8650 else
8651 {
8652 if ((Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
8653 return;
8654
8655 if (skip_past_comma (&str) == FAIL)
8656 {
8657 /* Two operand format, shuffle the registers
8658 and pretend there are 3. */
8659 Rn = Rs;
8660 Rs = Rd;
8661 }
8662 else if (is_immediate_prefix (*str))
8663 {
8664 str++;
8665 if (my_get_expression (&inst.reloc.exp, &str))
8666 return;
8667 }
8668 else if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
8669 return;
8670 }
8671
8672 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
8673 for the latter case, EXPR contains the immediate that was found. */
8674
8675 if (Rn != FAIL)
8676 {
8677 if (Rs != Rd)
8678 {
8679 inst.error = _("source1 and dest must be same register");
8680 return;
8681 }
8682
8683 switch (shift)
8684 {
8685 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_R; break;
8686 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_R; break;
8687 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_R; break;
8688 }
8689
8690 inst.instruction |= Rd | (Rn << 3);
8691 }
8692 else
8693 {
8694 switch (shift)
8695 {
8696 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_I; break;
8697 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_I; break;
8698 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_I; break;
8699 }
8700
8701 if (inst.reloc.exp.X_op != O_constant)
8702 {
8703 /* Value isn't known yet, create a dummy reloc and let reloc
8704 hacking fix it up. */
8705 inst.reloc.type = BFD_RELOC_ARM_THUMB_SHIFT;
8706 }
8707 else
8708 {
8709 unsigned shift_value = inst.reloc.exp.X_add_number;
8710
8711 if (shift_value > 32 || (shift_value == 32 && shift == THUMB_LSL))
8712 {
8713 inst.error = _("invalid immediate for shift");
8714 return;
8715 }
8716
8717 /* Shifts of zero are handled by converting to LSL. */
8718 if (shift_value == 0)
8719 inst.instruction = T_OPCODE_LSL_I;
8720
8721 /* Shifts of 32 are encoded as a shift of zero. */
8722 if (shift_value == 32)
8723 shift_value = 0;
8724
8725 inst.instruction |= shift_value << 6;
8726 }
8727
8728 inst.instruction |= Rd | (Rs << 3);
8729 }
8730
8731 end_of_line (str);
8732 }
8733
8734 static void
8735 thumb_load_store (char * str, int load_store, int size)
8736 {
8737 int Rd, Rb, Ro = FAIL;
8738
8739 skip_whitespace (str);
8740
8741 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
8742 || skip_past_comma (&str) == FAIL)
8743 {
8744 if (! inst.error)
8745 inst.error = BAD_ARGS;
8746 return;
8747 }
8748
8749 if (*str == '[')
8750 {
8751 str++;
8752 if ((Rb = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
8753 return;
8754
8755 if (skip_past_comma (&str) != FAIL)
8756 {
8757 if (is_immediate_prefix (*str))
8758 {
8759 str++;
8760 if (my_get_expression (&inst.reloc.exp, &str))
8761 return;
8762 }
8763 else if ((Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
8764 return;
8765 }
8766 else
8767 {
8768 inst.reloc.exp.X_op = O_constant;
8769 inst.reloc.exp.X_add_number = 0;
8770 }
8771
8772 if (*str != ']')
8773 {
8774 inst.error = _("expected ']'");
8775 return;
8776 }
8777 str++;
8778 }
8779 else if (*str == '=')
8780 {
8781 if (load_store != THUMB_LOAD)
8782 {
8783 inst.error = _("invalid pseudo operation");
8784 return;
8785 }
8786
8787 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
8788 str++;
8789
8790 skip_whitespace (str);
8791
8792 if (my_get_expression (& inst.reloc.exp, & str))
8793 return;
8794
8795 end_of_line (str);
8796
8797 if ( inst.reloc.exp.X_op != O_constant
8798 && inst.reloc.exp.X_op != O_symbol)
8799 {
8800 inst.error = "Constant expression expected";
8801 return;
8802 }
8803
8804 if (inst.reloc.exp.X_op == O_constant
8805 && ((inst.reloc.exp.X_add_number & ~0xFF) == 0))
8806 {
8807 /* This can be done with a mov instruction. */
8808
8809 inst.instruction = T_OPCODE_MOV_I8 | (Rd << 8);
8810 inst.instruction |= inst.reloc.exp.X_add_number;
8811 return;
8812 }
8813
8814 /* Insert into literal pool. */
8815 if (add_to_lit_pool () == FAIL)
8816 {
8817 if (!inst.error)
8818 inst.error = "literal pool insertion failed";
8819 return;
8820 }
8821
8822 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
8823 inst.reloc.pc_rel = 1;
8824 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
8825 /* Adjust ARM pipeline offset to Thumb. */
8826 inst.reloc.exp.X_add_number += 4;
8827
8828 return;
8829 }
8830 else
8831 {
8832 if (my_get_expression (&inst.reloc.exp, &str))
8833 return;
8834
8835 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
8836 inst.reloc.pc_rel = 1;
8837 inst.reloc.exp.X_add_number -= 4; /* Pipeline offset. */
8838 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
8839 end_of_line (str);
8840 return;
8841 }
8842
8843 if (Rb == REG_PC || Rb == REG_SP)
8844 {
8845 if (size != THUMB_WORD)
8846 {
8847 inst.error = _("byte or halfword not valid for base register");
8848 return;
8849 }
8850 else if (Rb == REG_PC && load_store != THUMB_LOAD)
8851 {
8852 inst.error = _("r15 based store not allowed");
8853 return;
8854 }
8855 else if (Ro != FAIL)
8856 {
8857 inst.error = _("invalid base register for register offset");
8858 return;
8859 }
8860
8861 if (Rb == REG_PC)
8862 inst.instruction = T_OPCODE_LDR_PC;
8863 else if (load_store == THUMB_LOAD)
8864 inst.instruction = T_OPCODE_LDR_SP;
8865 else
8866 inst.instruction = T_OPCODE_STR_SP;
8867
8868 inst.instruction |= Rd << 8;
8869 if (inst.reloc.exp.X_op == O_constant)
8870 {
8871 unsigned offset = inst.reloc.exp.X_add_number;
8872
8873 if (offset & ~0x3fc)
8874 {
8875 inst.error = _("invalid offset");
8876 return;
8877 }
8878
8879 inst.instruction |= offset >> 2;
8880 }
8881 else
8882 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
8883 }
8884 else if (Rb > 7)
8885 {
8886 inst.error = _("invalid base register in load/store");
8887 return;
8888 }
8889 else if (Ro == FAIL)
8890 {
8891 /* Immediate offset. */
8892 if (size == THUMB_WORD)
8893 inst.instruction = (load_store == THUMB_LOAD
8894 ? T_OPCODE_LDR_IW : T_OPCODE_STR_IW);
8895 else if (size == THUMB_HALFWORD)
8896 inst.instruction = (load_store == THUMB_LOAD
8897 ? T_OPCODE_LDR_IH : T_OPCODE_STR_IH);
8898 else
8899 inst.instruction = (load_store == THUMB_LOAD
8900 ? T_OPCODE_LDR_IB : T_OPCODE_STR_IB);
8901
8902 inst.instruction |= Rd | (Rb << 3);
8903
8904 if (inst.reloc.exp.X_op == O_constant)
8905 {
8906 unsigned offset = inst.reloc.exp.X_add_number;
8907
8908 if (offset & ~(0x1f << size))
8909 {
8910 inst.error = _("invalid offset");
8911 return;
8912 }
8913 inst.instruction |= (offset >> size) << 6;
8914 }
8915 else
8916 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
8917 }
8918 else
8919 {
8920 /* Register offset. */
8921 if (size == THUMB_WORD)
8922 inst.instruction = (load_store == THUMB_LOAD
8923 ? T_OPCODE_LDR_RW : T_OPCODE_STR_RW);
8924 else if (size == THUMB_HALFWORD)
8925 inst.instruction = (load_store == THUMB_LOAD
8926 ? T_OPCODE_LDR_RH : T_OPCODE_STR_RH);
8927 else
8928 inst.instruction = (load_store == THUMB_LOAD
8929 ? T_OPCODE_LDR_RB : T_OPCODE_STR_RB);
8930
8931 inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
8932 }
8933
8934 end_of_line (str);
8935 }
8936
8937 /* A register must be given at this point.
8938
8939 Shift is the place to put it in inst.instruction.
8940
8941 Restores input start point on err.
8942 Returns the reg#, or FAIL. */
8943
8944 static int
8945 mav_reg_required_here (char ** str, int shift, enum arm_reg_type regtype)
8946 {
8947 int reg;
8948 char *start = *str;
8949
8950 if ((reg = arm_reg_parse (str, all_reg_maps[regtype].htab)) != FAIL)
8951 {
8952 if (shift >= 0)
8953 inst.instruction |= reg << shift;
8954
8955 return reg;
8956 }
8957
8958 /* Restore the start point. */
8959 *str = start;
8960
8961 /* Try generic coprocessor name if applicable. */
8962 if (regtype == REG_TYPE_MVF ||
8963 regtype == REG_TYPE_MVD ||
8964 regtype == REG_TYPE_MVFX ||
8965 regtype == REG_TYPE_MVDX)
8966 {
8967 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_CN].htab)) != FAIL)
8968 {
8969 if (shift >= 0)
8970 inst.instruction |= reg << shift;
8971
8972 return reg;
8973 }
8974
8975 /* Restore the start point. */
8976 *str = start;
8977 }
8978
8979 /* In the few cases where we might be able to accept something else
8980 this error can be overridden. */
8981 inst.error = _(all_reg_maps[regtype].expected);
8982
8983 return FAIL;
8984 }
8985
8986 /* Cirrus Maverick Instructions. */
8987
8988 /* Isnsn like "foo X,Y". */
8989
8990 static void
8991 do_mav_binops (char * str,
8992 int mode,
8993 enum arm_reg_type reg0,
8994 enum arm_reg_type reg1)
8995 {
8996 int shift0, shift1;
8997
8998 shift0 = mode & 0xff;
8999 shift1 = (mode >> 8) & 0xff;
9000
9001 skip_whitespace (str);
9002
9003 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
9004 || skip_past_comma (&str) == FAIL
9005 || mav_reg_required_here (&str, shift1, reg1) == FAIL)
9006 {
9007 if (!inst.error)
9008 inst.error = BAD_ARGS;
9009 }
9010 else
9011 end_of_line (str);
9012 }
9013
9014 /* Isnsn like "foo X,Y,Z". */
9015
9016 static void
9017 do_mav_triple (char * str,
9018 int mode,
9019 enum arm_reg_type reg0,
9020 enum arm_reg_type reg1,
9021 enum arm_reg_type reg2)
9022 {
9023 int shift0, shift1, shift2;
9024
9025 shift0 = mode & 0xff;
9026 shift1 = (mode >> 8) & 0xff;
9027 shift2 = (mode >> 16) & 0xff;
9028
9029 skip_whitespace (str);
9030
9031 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
9032 || skip_past_comma (&str) == FAIL
9033 || mav_reg_required_here (&str, shift1, reg1) == FAIL
9034 || skip_past_comma (&str) == FAIL
9035 || mav_reg_required_here (&str, shift2, reg2) == FAIL)
9036 {
9037 if (!inst.error)
9038 inst.error = BAD_ARGS;
9039 }
9040 else
9041 end_of_line (str);
9042 }
9043
9044 /* Wrapper functions. */
9045
9046 static void
9047 do_mav_binops_1a (char * str)
9048 {
9049 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVF);
9050 }
9051
9052 static void
9053 do_mav_binops_1b (char * str)
9054 {
9055 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVD);
9056 }
9057
9058 static void
9059 do_mav_binops_1c (char * str)
9060 {
9061 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVDX);
9062 }
9063
9064 static void
9065 do_mav_binops_1d (char * str)
9066 {
9067 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVF);
9068 }
9069
9070 static void
9071 do_mav_binops_1e (char * str)
9072 {
9073 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVD);
9074 }
9075
9076 static void
9077 do_mav_binops_1f (char * str)
9078 {
9079 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVF);
9080 }
9081
9082 static void
9083 do_mav_binops_1g (char * str)
9084 {
9085 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVD);
9086 }
9087
9088 static void
9089 do_mav_binops_1h (char * str)
9090 {
9091 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVFX);
9092 }
9093
9094 static void
9095 do_mav_binops_1i (char * str)
9096 {
9097 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVFX);
9098 }
9099
9100 static void
9101 do_mav_binops_1j (char * str)
9102 {
9103 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVDX);
9104 }
9105
9106 static void
9107 do_mav_binops_1k (char * str)
9108 {
9109 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVDX);
9110 }
9111
9112 static void
9113 do_mav_binops_1l (char * str)
9114 {
9115 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVF);
9116 }
9117
9118 static void
9119 do_mav_binops_1m (char * str)
9120 {
9121 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVD);
9122 }
9123
9124 static void
9125 do_mav_binops_1n (char * str)
9126 {
9127 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVFX);
9128 }
9129
9130 static void
9131 do_mav_binops_1o (char * str)
9132 {
9133 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVDX, REG_TYPE_MVDX);
9134 }
9135
9136 static void
9137 do_mav_binops_2a (char * str)
9138 {
9139 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVF, REG_TYPE_RN);
9140 }
9141
9142 static void
9143 do_mav_binops_2b (char * str)
9144 {
9145 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVD, REG_TYPE_RN);
9146 }
9147
9148 static void
9149 do_mav_binops_2c (char * str)
9150 {
9151 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVDX, REG_TYPE_RN);
9152 }
9153
9154 static void
9155 do_mav_binops_3a (char * str)
9156 {
9157 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVAX, REG_TYPE_MVFX);
9158 }
9159
9160 static void
9161 do_mav_binops_3b (char * str)
9162 {
9163 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVFX, REG_TYPE_MVAX);
9164 }
9165
9166 static void
9167 do_mav_binops_3c (char * str)
9168 {
9169 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVAX, REG_TYPE_MVDX);
9170 }
9171
9172 static void
9173 do_mav_binops_3d (char * str)
9174 {
9175 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVDX, REG_TYPE_MVAX);
9176 }
9177
9178 static void
9179 do_mav_triple_4a (char * str)
9180 {
9181 do_mav_triple (str, MAV_MODE4, REG_TYPE_MVFX, REG_TYPE_MVFX, REG_TYPE_RN);
9182 }
9183
9184 static void
9185 do_mav_triple_4b (char * str)
9186 {
9187 do_mav_triple (str, MAV_MODE4, REG_TYPE_MVDX, REG_TYPE_MVDX, REG_TYPE_RN);
9188 }
9189
9190 static void
9191 do_mav_triple_5a (char * str)
9192 {
9193 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVF, REG_TYPE_MVF);
9194 }
9195
9196 static void
9197 do_mav_triple_5b (char * str)
9198 {
9199 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVD, REG_TYPE_MVD);
9200 }
9201
9202 static void
9203 do_mav_triple_5c (char * str)
9204 {
9205 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVFX, REG_TYPE_MVFX);
9206 }
9207
9208 static void
9209 do_mav_triple_5d (char * str)
9210 {
9211 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVDX, REG_TYPE_MVDX);
9212 }
9213
9214 static void
9215 do_mav_triple_5e (char * str)
9216 {
9217 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVF, REG_TYPE_MVF, REG_TYPE_MVF);
9218 }
9219
9220 static void
9221 do_mav_triple_5f (char * str)
9222 {
9223 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVD, REG_TYPE_MVD, REG_TYPE_MVD);
9224 }
9225
9226 static void
9227 do_mav_triple_5g (char * str)
9228 {
9229 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVFX, REG_TYPE_MVFX, REG_TYPE_MVFX);
9230 }
9231
9232 static void
9233 do_mav_triple_5h (char * str)
9234 {
9235 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVDX, REG_TYPE_MVDX, REG_TYPE_MVDX);
9236 }
9237
9238 /* Isnsn like "foo W,X,Y,Z".
9239 where W=MVAX[0:3] and X,Y,Z=MVFX[0:15]. */
9240
9241 static void
9242 do_mav_quad (char * str,
9243 int mode,
9244 enum arm_reg_type reg0,
9245 enum arm_reg_type reg1,
9246 enum arm_reg_type reg2,
9247 enum arm_reg_type reg3)
9248 {
9249 int shift0, shift1, shift2, shift3;
9250
9251 shift0= mode & 0xff;
9252 shift1 = (mode >> 8) & 0xff;
9253 shift2 = (mode >> 16) & 0xff;
9254 shift3 = (mode >> 24) & 0xff;
9255
9256 skip_whitespace (str);
9257
9258 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
9259 || skip_past_comma (&str) == FAIL
9260 || mav_reg_required_here (&str, shift1, reg1) == FAIL
9261 || skip_past_comma (&str) == FAIL
9262 || mav_reg_required_here (&str, shift2, reg2) == FAIL
9263 || skip_past_comma (&str) == FAIL
9264 || mav_reg_required_here (&str, shift3, reg3) == FAIL)
9265 {
9266 if (!inst.error)
9267 inst.error = BAD_ARGS;
9268 }
9269 else
9270 end_of_line (str);
9271 }
9272
9273 static void
9274 do_mav_quad_6a (char * str)
9275 {
9276 do_mav_quad (str, MAV_MODE6, REG_TYPE_MVAX, REG_TYPE_MVFX, REG_TYPE_MVFX,
9277 REG_TYPE_MVFX);
9278 }
9279
9280 static void
9281 do_mav_quad_6b (char * str)
9282 {
9283 do_mav_quad (str, MAV_MODE6, REG_TYPE_MVAX, REG_TYPE_MVAX, REG_TYPE_MVFX,
9284 REG_TYPE_MVFX);
9285 }
9286
9287 /* cfmvsc32<cond> DSPSC,MVDX[15:0]. */
9288 static void
9289 do_mav_dspsc_1 (char * str)
9290 {
9291 skip_whitespace (str);
9292
9293 /* cfmvsc32. */
9294 if (mav_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL
9295 || skip_past_comma (&str) == FAIL
9296 || mav_reg_required_here (&str, 12, REG_TYPE_MVDX) == FAIL)
9297 {
9298 if (!inst.error)
9299 inst.error = BAD_ARGS;
9300
9301 return;
9302 }
9303
9304 end_of_line (str);
9305 }
9306
9307 /* cfmv32sc<cond> MVDX[15:0],DSPSC. */
9308 static void
9309 do_mav_dspsc_2 (char * str)
9310 {
9311 skip_whitespace (str);
9312
9313 /* cfmv32sc. */
9314 if (mav_reg_required_here (&str, 12, REG_TYPE_MVDX) == FAIL
9315 || skip_past_comma (&str) == FAIL
9316 || mav_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL)
9317 {
9318 if (!inst.error)
9319 inst.error = BAD_ARGS;
9320
9321 return;
9322 }
9323
9324 end_of_line (str);
9325 }
9326
9327 /* Maverick shift immediate instructions.
9328 cfsh32<cond> MVFX[15:0],MVFX[15:0],Shift[6:0].
9329 cfsh64<cond> MVDX[15:0],MVDX[15:0],Shift[6:0]. */
9330
9331 static void
9332 do_mav_shift (char * str,
9333 enum arm_reg_type reg0,
9334 enum arm_reg_type reg1)
9335 {
9336 int error;
9337 int imm, neg = 0;
9338
9339 skip_whitespace (str);
9340
9341 error = 0;
9342
9343 if (mav_reg_required_here (&str, 12, reg0) == FAIL
9344 || skip_past_comma (&str) == FAIL
9345 || mav_reg_required_here (&str, 16, reg1) == FAIL
9346 || skip_past_comma (&str) == FAIL)
9347 {
9348 if (!inst.error)
9349 inst.error = BAD_ARGS;
9350 return;
9351 }
9352
9353 /* Calculate the immediate operand.
9354 The operand is a 7bit signed number. */
9355 skip_whitespace (str);
9356
9357 if (*str == '#')
9358 ++str;
9359
9360 if (!ISDIGIT (*str) && *str != '-')
9361 {
9362 inst.error = _("expecting immediate, 7bit operand");
9363 return;
9364 }
9365
9366 if (*str == '-')
9367 {
9368 neg = 1;
9369 ++str;
9370 }
9371
9372 for (imm = 0; *str && ISDIGIT (*str); ++str)
9373 imm = imm * 10 + *str - '0';
9374
9375 if (imm > 64)
9376 {
9377 inst.error = _("immediate out of range");
9378 return;
9379 }
9380
9381 /* Make negative imm's into 7bit signed numbers. */
9382 if (neg)
9383 {
9384 imm = -imm;
9385 imm &= 0x0000007f;
9386 }
9387
9388 /* Bits 0-3 of the insn should have bits 0-3 of the immediate.
9389 Bits 5-7 of the insn should have bits 4-6 of the immediate.
9390 Bit 4 should be 0. */
9391 imm = (imm & 0xf) | ((imm & 0x70) << 1);
9392
9393 inst.instruction |= imm;
9394 end_of_line (str);
9395 }
9396
9397 static void
9398 do_mav_shift_1 (char * str)
9399 {
9400 do_mav_shift (str, REG_TYPE_MVFX, REG_TYPE_MVFX);
9401 }
9402
9403 static void
9404 do_mav_shift_2 (char * str)
9405 {
9406 do_mav_shift (str, REG_TYPE_MVDX, REG_TYPE_MVDX);
9407 }
9408
9409 static int
9410 mav_parse_offset (char ** str, int * negative)
9411 {
9412 char * p = *str;
9413 int offset;
9414
9415 *negative = 0;
9416
9417 skip_whitespace (p);
9418
9419 if (*p == '#')
9420 ++p;
9421
9422 if (*p == '-')
9423 {
9424 *negative = 1;
9425 ++p;
9426 }
9427
9428 if (!ISDIGIT (*p))
9429 {
9430 inst.error = _("offset expected");
9431 return 0;
9432 }
9433
9434 for (offset = 0; *p && ISDIGIT (*p); ++p)
9435 offset = offset * 10 + *p - '0';
9436
9437 if (offset > 0x3fc)
9438 {
9439 inst.error = _("offset out of range");
9440 return 0;
9441 }
9442 if (offset & 0x3)
9443 {
9444 inst.error = _("offset not a multiple of 4");
9445 return 0;
9446 }
9447
9448 *str = p;
9449
9450 return *negative ? -offset : offset;
9451 }
9452
9453 /* Maverick load/store instructions.
9454 <insn><cond> CRd,[Rn,<offset>]{!}.
9455 <insn><cond> CRd,[Rn],<offset>. */
9456
9457 static void
9458 do_mav_ldst (char * str, enum arm_reg_type reg0)
9459 {
9460 int offset, negative;
9461
9462 skip_whitespace (str);
9463
9464 if (mav_reg_required_here (&str, 12, reg0) == FAIL
9465 || skip_past_comma (&str) == FAIL
9466 || *str++ != '['
9467 || reg_required_here (&str, 16) == FAIL)
9468 goto fail_ldst;
9469
9470 if (skip_past_comma (&str) == SUCCESS)
9471 {
9472 /* You are here: "<offset>]{!}". */
9473 inst.instruction |= PRE_INDEX;
9474
9475 offset = mav_parse_offset (&str, &negative);
9476
9477 if (inst.error)
9478 return;
9479
9480 if (*str++ != ']')
9481 {
9482 inst.error = _("missing ]");
9483 return;
9484 }
9485
9486 if (*str == '!')
9487 {
9488 inst.instruction |= WRITE_BACK;
9489 ++str;
9490 }
9491 }
9492 else
9493 {
9494 /* You are here: "], <offset>". */
9495 if (*str++ != ']')
9496 {
9497 inst.error = _("missing ]");
9498 return;
9499 }
9500
9501 if (skip_past_comma (&str) == FAIL
9502 || (offset = mav_parse_offset (&str, &negative), inst.error))
9503 goto fail_ldst;
9504
9505 inst.instruction |= CP_T_WB; /* Post indexed, set bit W. */
9506 }
9507
9508 if (negative)
9509 offset = -offset;
9510 else
9511 inst.instruction |= CP_T_UD; /* Positive, so set bit U. */
9512
9513 inst.instruction |= offset >> 2;
9514 end_of_line (str);
9515 return;
9516
9517 fail_ldst:
9518 if (!inst.error)
9519 inst.error = BAD_ARGS;
9520 }
9521
9522 static void
9523 do_mav_ldst_1 (char * str)
9524 {
9525 do_mav_ldst (str, REG_TYPE_MVF);
9526 }
9527
9528 static void
9529 do_mav_ldst_2 (char * str)
9530 {
9531 do_mav_ldst (str, REG_TYPE_MVD);
9532 }
9533
9534 static void
9535 do_mav_ldst_3 (char * str)
9536 {
9537 do_mav_ldst (str, REG_TYPE_MVFX);
9538 }
9539
9540 static void
9541 do_mav_ldst_4 (char * str)
9542 {
9543 do_mav_ldst (str, REG_TYPE_MVDX);
9544 }
9545
9546 static void
9547 do_t_nop (char * str)
9548 {
9549 /* Do nothing. */
9550 end_of_line (str);
9551 }
9552
9553 /* Handle the Format 4 instructions that do not have equivalents in other
9554 formats. That is, ADC, AND, EOR, SBC, ROR, TST, NEG, CMN, ORR, MUL,
9555 BIC and MVN. */
9556
9557 static void
9558 do_t_arit (char * str)
9559 {
9560 int Rd, Rs, Rn;
9561
9562 skip_whitespace (str);
9563
9564 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9565 || skip_past_comma (&str) == FAIL
9566 || (Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9567 {
9568 inst.error = BAD_ARGS;
9569 return;
9570 }
9571
9572 if (skip_past_comma (&str) != FAIL)
9573 {
9574 /* Three operand format not allowed for TST, CMN, NEG and MVN.
9575 (It isn't allowed for CMP either, but that isn't handled by this
9576 function.) */
9577 if (inst.instruction == T_OPCODE_TST
9578 || inst.instruction == T_OPCODE_CMN
9579 || inst.instruction == T_OPCODE_NEG
9580 || inst.instruction == T_OPCODE_MVN)
9581 {
9582 inst.error = BAD_ARGS;
9583 return;
9584 }
9585
9586 if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9587 return;
9588
9589 if (Rs != Rd)
9590 {
9591 inst.error = _("dest and source1 must be the same register");
9592 return;
9593 }
9594 Rs = Rn;
9595 }
9596
9597 if (inst.instruction == T_OPCODE_MUL
9598 && Rs == Rd)
9599 as_tsktsk (_("Rs and Rd must be different in MUL"));
9600
9601 inst.instruction |= Rd | (Rs << 3);
9602 end_of_line (str);
9603 }
9604
9605 static void
9606 do_t_add (char * str)
9607 {
9608 thumb_add_sub (str, 0);
9609 }
9610
9611 static void
9612 do_t_asr (char * str)
9613 {
9614 thumb_shift (str, THUMB_ASR);
9615 }
9616
9617 static void
9618 do_t_branch9 (char * str)
9619 {
9620 if (my_get_expression (&inst.reloc.exp, &str))
9621 return;
9622 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH9;
9623 inst.reloc.pc_rel = 1;
9624 end_of_line (str);
9625 }
9626
9627 static void
9628 do_t_branch12 (char * str)
9629 {
9630 if (my_get_expression (&inst.reloc.exp, &str))
9631 return;
9632 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH12;
9633 inst.reloc.pc_rel = 1;
9634 end_of_line (str);
9635 }
9636
9637 /* Find the real, Thumb encoded start of a Thumb function. */
9638
9639 static symbolS *
9640 find_real_start (symbolS * symbolP)
9641 {
9642 char * real_start;
9643 const char * name = S_GET_NAME (symbolP);
9644 symbolS * new_target;
9645
9646 /* This definition must agree with the one in gcc/config/arm/thumb.c. */
9647 #define STUB_NAME ".real_start_of"
9648
9649 if (name == NULL)
9650 abort ();
9651
9652 /* Names that start with '.' are local labels, not function entry points.
9653 The compiler may generate BL instructions to these labels because it
9654 needs to perform a branch to a far away location. */
9655 if (name[0] == '.')
9656 return symbolP;
9657
9658 real_start = malloc (strlen (name) + strlen (STUB_NAME) + 1);
9659 sprintf (real_start, "%s%s", STUB_NAME, name);
9660
9661 new_target = symbol_find (real_start);
9662
9663 if (new_target == NULL)
9664 {
9665 as_warn ("Failed to find real start of function: %s\n", name);
9666 new_target = symbolP;
9667 }
9668
9669 free (real_start);
9670
9671 return new_target;
9672 }
9673
9674 static void
9675 do_t_branch23 (char * str)
9676 {
9677 if (my_get_expression (& inst.reloc.exp, & str))
9678 return;
9679
9680 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH23;
9681 inst.reloc.pc_rel = 1;
9682 end_of_line (str);
9683
9684 /* If the destination of the branch is a defined symbol which does not have
9685 the THUMB_FUNC attribute, then we must be calling a function which has
9686 the (interfacearm) attribute. We look for the Thumb entry point to that
9687 function and change the branch to refer to that function instead. */
9688 if ( inst.reloc.exp.X_op == O_symbol
9689 && inst.reloc.exp.X_add_symbol != NULL
9690 && S_IS_DEFINED (inst.reloc.exp.X_add_symbol)
9691 && ! THUMB_IS_FUNC (inst.reloc.exp.X_add_symbol))
9692 inst.reloc.exp.X_add_symbol =
9693 find_real_start (inst.reloc.exp.X_add_symbol);
9694 }
9695
9696 static void
9697 do_t_bx (char * str)
9698 {
9699 int reg;
9700
9701 skip_whitespace (str);
9702
9703 if ((reg = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
9704 return;
9705
9706 /* This sets THUMB_H2 from the top bit of reg. */
9707 inst.instruction |= reg << 3;
9708
9709 /* ??? FIXME: Should add a hacky reloc here if reg is REG_PC. The reloc
9710 should cause the alignment to be checked once it is known. This is
9711 because BX PC only works if the instruction is word aligned. */
9712
9713 end_of_line (str);
9714 }
9715
9716 static void
9717 do_t_compare (char * str)
9718 {
9719 thumb_mov_compare (str, THUMB_COMPARE);
9720 }
9721
9722 static void
9723 do_t_ldmstm (char * str)
9724 {
9725 int Rb;
9726 long range;
9727
9728 skip_whitespace (str);
9729
9730 if ((Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9731 return;
9732
9733 if (*str != '!')
9734 as_warn (_("inserted missing '!': load/store multiple always writes back base register"));
9735 else
9736 str++;
9737
9738 if (skip_past_comma (&str) == FAIL
9739 || (range = reg_list (&str)) == FAIL)
9740 {
9741 if (! inst.error)
9742 inst.error = BAD_ARGS;
9743 return;
9744 }
9745
9746 if (inst.reloc.type != BFD_RELOC_UNUSED)
9747 {
9748 /* This really doesn't seem worth it. */
9749 inst.reloc.type = BFD_RELOC_UNUSED;
9750 inst.error = _("expression too complex");
9751 return;
9752 }
9753
9754 if (range & ~0xff)
9755 {
9756 inst.error = _("only lo-regs valid in load/store multiple");
9757 return;
9758 }
9759
9760 inst.instruction |= (Rb << 8) | range;
9761 end_of_line (str);
9762 }
9763
9764 static void
9765 do_t_ldr (char * str)
9766 {
9767 thumb_load_store (str, THUMB_LOAD, THUMB_WORD);
9768 }
9769
9770 static void
9771 do_t_ldrb (char * str)
9772 {
9773 thumb_load_store (str, THUMB_LOAD, THUMB_BYTE);
9774 }
9775
9776 static void
9777 do_t_ldrh (char * str)
9778 {
9779 thumb_load_store (str, THUMB_LOAD, THUMB_HALFWORD);
9780 }
9781
9782 static void
9783 do_t_lds (char * str)
9784 {
9785 int Rd, Rb, Ro;
9786
9787 skip_whitespace (str);
9788
9789 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9790 || skip_past_comma (&str) == FAIL
9791 || *str++ != '['
9792 || (Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9793 || skip_past_comma (&str) == FAIL
9794 || (Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9795 || *str++ != ']')
9796 {
9797 if (! inst.error)
9798 inst.error = _("syntax: ldrs[b] Rd, [Rb, Ro]");
9799 return;
9800 }
9801
9802 inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
9803 end_of_line (str);
9804 }
9805
9806 static void
9807 do_t_lsl (char * str)
9808 {
9809 thumb_shift (str, THUMB_LSL);
9810 }
9811
9812 static void
9813 do_t_lsr (char * str)
9814 {
9815 thumb_shift (str, THUMB_LSR);
9816 }
9817
9818 static void
9819 do_t_mov (char * str)
9820 {
9821 thumb_mov_compare (str, THUMB_MOVE);
9822 }
9823
9824 static void
9825 do_t_push_pop (char * str)
9826 {
9827 long range;
9828
9829 skip_whitespace (str);
9830
9831 if ((range = reg_list (&str)) == FAIL)
9832 {
9833 if (! inst.error)
9834 inst.error = BAD_ARGS;
9835 return;
9836 }
9837
9838 if (inst.reloc.type != BFD_RELOC_UNUSED)
9839 {
9840 /* This really doesn't seem worth it. */
9841 inst.reloc.type = BFD_RELOC_UNUSED;
9842 inst.error = _("expression too complex");
9843 return;
9844 }
9845
9846 if (range & ~0xff)
9847 {
9848 if ((inst.instruction == T_OPCODE_PUSH
9849 && (range & ~0xff) == 1 << REG_LR)
9850 || (inst.instruction == T_OPCODE_POP
9851 && (range & ~0xff) == 1 << REG_PC))
9852 {
9853 inst.instruction |= THUMB_PP_PC_LR;
9854 range &= 0xff;
9855 }
9856 else
9857 {
9858 inst.error = _("invalid register list to push/pop instruction");
9859 return;
9860 }
9861 }
9862
9863 inst.instruction |= range;
9864 end_of_line (str);
9865 }
9866
9867 static void
9868 do_t_str (char * str)
9869 {
9870 thumb_load_store (str, THUMB_STORE, THUMB_WORD);
9871 }
9872
9873 static void
9874 do_t_strb (char * str)
9875 {
9876 thumb_load_store (str, THUMB_STORE, THUMB_BYTE);
9877 }
9878
9879 static void
9880 do_t_strh (char * str)
9881 {
9882 thumb_load_store (str, THUMB_STORE, THUMB_HALFWORD);
9883 }
9884
9885 static void
9886 do_t_sub (char * str)
9887 {
9888 thumb_add_sub (str, 1);
9889 }
9890
9891 static void
9892 do_t_swi (char * str)
9893 {
9894 skip_whitespace (str);
9895
9896 if (my_get_expression (&inst.reloc.exp, &str))
9897 return;
9898
9899 inst.reloc.type = BFD_RELOC_ARM_SWI;
9900 end_of_line (str);
9901 }
9902
9903 static void
9904 do_t_adr (char * str)
9905 {
9906 int reg;
9907
9908 /* This is a pseudo-op of the form "adr rd, label" to be converted
9909 into a relative address of the form "add rd, pc, #label-.-4". */
9910 skip_whitespace (str);
9911
9912 /* Store Rd in temporary location inside instruction. */
9913 if ((reg = reg_required_here (&str, 4)) == FAIL
9914 || (reg > 7) /* For Thumb reg must be r0..r7. */
9915 || skip_past_comma (&str) == FAIL
9916 || my_get_expression (&inst.reloc.exp, &str))
9917 {
9918 if (!inst.error)
9919 inst.error = BAD_ARGS;
9920 return;
9921 }
9922
9923 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
9924 inst.reloc.exp.X_add_number -= 4; /* PC relative adjust. */
9925 inst.reloc.pc_rel = 1;
9926 inst.instruction |= REG_PC; /* Rd is already placed into the instruction. */
9927
9928 end_of_line (str);
9929 }
9930
9931 static void
9932 insert_reg (const struct reg_entry * r,
9933 struct hash_control * htab)
9934 {
9935 int len = strlen (r->name) + 2;
9936 char * buf = xmalloc (len);
9937 char * buf2 = xmalloc (len);
9938 int i = 0;
9939
9940 #ifdef REGISTER_PREFIX
9941 buf[i++] = REGISTER_PREFIX;
9942 #endif
9943
9944 strcpy (buf + i, r->name);
9945
9946 for (i = 0; buf[i]; i++)
9947 buf2[i] = TOUPPER (buf[i]);
9948
9949 buf2[i] = '\0';
9950
9951 hash_insert (htab, buf, (PTR) r);
9952 hash_insert (htab, buf2, (PTR) r);
9953 }
9954
9955 static void
9956 build_reg_hsh (struct reg_map * map)
9957 {
9958 const struct reg_entry *r;
9959
9960 if ((map->htab = hash_new ()) == NULL)
9961 as_fatal (_("virtual memory exhausted"));
9962
9963 for (r = map->names; r->name != NULL; r++)
9964 insert_reg (r, map->htab);
9965 }
9966
9967 static void
9968 insert_reg_alias (char * str,
9969 int regnum,
9970 struct hash_control *htab)
9971 {
9972 const char * error;
9973 struct reg_entry * new = xmalloc (sizeof (struct reg_entry));
9974 const char * name = xmalloc (strlen (str) + 1);
9975
9976 strcpy ((char *) name, str);
9977
9978 new->name = name;
9979 new->number = regnum;
9980 new->builtin = FALSE;
9981
9982 error = hash_insert (htab, name, (PTR) new);
9983 if (error)
9984 {
9985 as_bad (_("failed to create an alias for %s, reason: %s"),
9986 str, error);
9987 free ((char *) name);
9988 free (new);
9989 }
9990 }
9991
9992 /* Look for the .req directive. This is of the form:
9993
9994 new_register_name .req existing_register_name
9995
9996 If we find one, or if it looks sufficiently like one that we want to
9997 handle any error here, return non-zero. Otherwise return zero. */
9998
9999 static int
10000 create_register_alias (char * newname, char * p)
10001 {
10002 char * q;
10003 char c;
10004
10005 q = p;
10006 skip_whitespace (q);
10007
10008 c = *p;
10009 *p = '\0';
10010
10011 if (*q && !strncmp (q, ".req ", 5))
10012 {
10013 char *copy_of_str;
10014 char *r;
10015
10016 #ifndef IGNORE_OPCODE_CASE
10017 newname = original_case_string;
10018 #endif
10019 copy_of_str = newname;
10020
10021 q += 4;
10022 skip_whitespace (q);
10023
10024 for (r = q; *r != '\0'; r++)
10025 if (*r == ' ')
10026 break;
10027
10028 if (r != q)
10029 {
10030 enum arm_reg_type new_type, old_type;
10031 int old_regno;
10032 char d = *r;
10033
10034 *r = '\0';
10035 old_type = arm_reg_parse_any (q);
10036 *r = d;
10037
10038 new_type = arm_reg_parse_any (newname);
10039
10040 if (new_type == REG_TYPE_MAX)
10041 {
10042 if (old_type != REG_TYPE_MAX)
10043 {
10044 old_regno = arm_reg_parse (&q, all_reg_maps[old_type].htab);
10045 insert_reg_alias (newname, old_regno,
10046 all_reg_maps[old_type].htab);
10047 }
10048 else
10049 as_warn (_("register '%s' does not exist\n"), q);
10050 }
10051 else if (old_type == REG_TYPE_MAX)
10052 {
10053 as_warn (_("ignoring redefinition of register alias '%s' to non-existant register '%s'"),
10054 copy_of_str, q);
10055 }
10056 else
10057 {
10058 /* Do not warn about redefinitions to the same alias. */
10059 if (new_type != old_type
10060 || (arm_reg_parse (&q, all_reg_maps[old_type].htab)
10061 != arm_reg_parse (&q, all_reg_maps[new_type].htab)))
10062 as_warn (_("ignoring redefinition of register alias '%s'"),
10063 copy_of_str);
10064
10065 }
10066 }
10067 else
10068 as_warn (_("ignoring incomplete .req pseuso op"));
10069
10070 *p = c;
10071 return 1;
10072 }
10073
10074 *p = c;
10075 return 0;
10076 }
10077
10078 static void
10079 set_constant_flonums (void)
10080 {
10081 int i;
10082
10083 for (i = 0; i < NUM_FLOAT_VALS; i++)
10084 if (atof_ieee ((char *) fp_const[i], 'x', fp_values[i]) == NULL)
10085 abort ();
10086 }
10087
10088 \f
10089 static const struct asm_opcode insns[] =
10090 {
10091 /* Core ARM Instructions. */
10092 {"and", 0xe0000000, 3, ARM_EXT_V1, do_arit},
10093 {"ands", 0xe0100000, 3, ARM_EXT_V1, do_arit},
10094 {"eor", 0xe0200000, 3, ARM_EXT_V1, do_arit},
10095 {"eors", 0xe0300000, 3, ARM_EXT_V1, do_arit},
10096 {"sub", 0xe0400000, 3, ARM_EXT_V1, do_arit},
10097 {"subs", 0xe0500000, 3, ARM_EXT_V1, do_arit},
10098 {"rsb", 0xe0600000, 3, ARM_EXT_V1, do_arit},
10099 {"rsbs", 0xe0700000, 3, ARM_EXT_V1, do_arit},
10100 {"add", 0xe0800000, 3, ARM_EXT_V1, do_arit},
10101 {"adds", 0xe0900000, 3, ARM_EXT_V1, do_arit},
10102 {"adc", 0xe0a00000, 3, ARM_EXT_V1, do_arit},
10103 {"adcs", 0xe0b00000, 3, ARM_EXT_V1, do_arit},
10104 {"sbc", 0xe0c00000, 3, ARM_EXT_V1, do_arit},
10105 {"sbcs", 0xe0d00000, 3, ARM_EXT_V1, do_arit},
10106 {"rsc", 0xe0e00000, 3, ARM_EXT_V1, do_arit},
10107 {"rscs", 0xe0f00000, 3, ARM_EXT_V1, do_arit},
10108 {"orr", 0xe1800000, 3, ARM_EXT_V1, do_arit},
10109 {"orrs", 0xe1900000, 3, ARM_EXT_V1, do_arit},
10110 {"bic", 0xe1c00000, 3, ARM_EXT_V1, do_arit},
10111 {"bics", 0xe1d00000, 3, ARM_EXT_V1, do_arit},
10112
10113 {"tst", 0xe1100000, 3, ARM_EXT_V1, do_cmp},
10114 {"tsts", 0xe1100000, 3, ARM_EXT_V1, do_cmp},
10115 {"tstp", 0xe110f000, 3, ARM_EXT_V1, do_cmp},
10116 {"teq", 0xe1300000, 3, ARM_EXT_V1, do_cmp},
10117 {"teqs", 0xe1300000, 3, ARM_EXT_V1, do_cmp},
10118 {"teqp", 0xe130f000, 3, ARM_EXT_V1, do_cmp},
10119 {"cmp", 0xe1500000, 3, ARM_EXT_V1, do_cmp},
10120 {"cmps", 0xe1500000, 3, ARM_EXT_V1, do_cmp},
10121 {"cmpp", 0xe150f000, 3, ARM_EXT_V1, do_cmp},
10122 {"cmn", 0xe1700000, 3, ARM_EXT_V1, do_cmp},
10123 {"cmns", 0xe1700000, 3, ARM_EXT_V1, do_cmp},
10124 {"cmnp", 0xe170f000, 3, ARM_EXT_V1, do_cmp},
10125
10126 {"mov", 0xe1a00000, 3, ARM_EXT_V1, do_mov},
10127 {"movs", 0xe1b00000, 3, ARM_EXT_V1, do_mov},
10128 {"mvn", 0xe1e00000, 3, ARM_EXT_V1, do_mov},
10129 {"mvns", 0xe1f00000, 3, ARM_EXT_V1, do_mov},
10130
10131 {"ldr", 0xe4100000, 3, ARM_EXT_V1, do_ldst},
10132 {"ldrb", 0xe4500000, 3, ARM_EXT_V1, do_ldst},
10133 {"ldrt", 0xe4300000, 3, ARM_EXT_V1, do_ldstt},
10134 {"ldrbt", 0xe4700000, 3, ARM_EXT_V1, do_ldstt},
10135 {"str", 0xe4000000, 3, ARM_EXT_V1, do_ldst},
10136 {"strb", 0xe4400000, 3, ARM_EXT_V1, do_ldst},
10137 {"strt", 0xe4200000, 3, ARM_EXT_V1, do_ldstt},
10138 {"strbt", 0xe4600000, 3, ARM_EXT_V1, do_ldstt},
10139
10140 {"stmia", 0xe8800000, 3, ARM_EXT_V1, do_ldmstm},
10141 {"stmib", 0xe9800000, 3, ARM_EXT_V1, do_ldmstm},
10142 {"stmda", 0xe8000000, 3, ARM_EXT_V1, do_ldmstm},
10143 {"stmdb", 0xe9000000, 3, ARM_EXT_V1, do_ldmstm},
10144 {"stmfd", 0xe9000000, 3, ARM_EXT_V1, do_ldmstm},
10145 {"stmfa", 0xe9800000, 3, ARM_EXT_V1, do_ldmstm},
10146 {"stmea", 0xe8800000, 3, ARM_EXT_V1, do_ldmstm},
10147 {"stmed", 0xe8000000, 3, ARM_EXT_V1, do_ldmstm},
10148
10149 {"ldmia", 0xe8900000, 3, ARM_EXT_V1, do_ldmstm},
10150 {"ldmib", 0xe9900000, 3, ARM_EXT_V1, do_ldmstm},
10151 {"ldmda", 0xe8100000, 3, ARM_EXT_V1, do_ldmstm},
10152 {"ldmdb", 0xe9100000, 3, ARM_EXT_V1, do_ldmstm},
10153 {"ldmfd", 0xe8900000, 3, ARM_EXT_V1, do_ldmstm},
10154 {"ldmfa", 0xe8100000, 3, ARM_EXT_V1, do_ldmstm},
10155 {"ldmea", 0xe9100000, 3, ARM_EXT_V1, do_ldmstm},
10156 {"ldmed", 0xe9900000, 3, ARM_EXT_V1, do_ldmstm},
10157
10158 {"swi", 0xef000000, 3, ARM_EXT_V1, do_swi},
10159 #ifdef TE_WINCE
10160 /* XXX This is the wrong place to do this. Think multi-arch. */
10161 {"bl", 0xeb000000, 2, ARM_EXT_V1, do_branch},
10162 {"b", 0xea000000, 1, ARM_EXT_V1, do_branch},
10163 #else
10164 {"bl", 0xebfffffe, 2, ARM_EXT_V1, do_branch},
10165 {"b", 0xeafffffe, 1, ARM_EXT_V1, do_branch},
10166 #endif
10167
10168 /* Pseudo ops. */
10169 {"adr", 0xe28f0000, 3, ARM_EXT_V1, do_adr},
10170 {"adrl", 0xe28f0000, 3, ARM_EXT_V1, do_adrl},
10171 {"nop", 0xe1a00000, 3, ARM_EXT_V1, do_nop},
10172
10173 /* ARM 2 multiplies. */
10174 {"mul", 0xe0000090, 3, ARM_EXT_V2, do_mul},
10175 {"muls", 0xe0100090, 3, ARM_EXT_V2, do_mul},
10176 {"mla", 0xe0200090, 3, ARM_EXT_V2, do_mla},
10177 {"mlas", 0xe0300090, 3, ARM_EXT_V2, do_mla},
10178
10179 /* Generic coprocessor instructions. */
10180 {"cdp", 0xee000000, 3, ARM_EXT_V2, do_cdp},
10181 {"ldc", 0xec100000, 3, ARM_EXT_V2, do_lstc},
10182 {"ldcl", 0xec500000, 3, ARM_EXT_V2, do_lstc},
10183 {"stc", 0xec000000, 3, ARM_EXT_V2, do_lstc},
10184 {"stcl", 0xec400000, 3, ARM_EXT_V2, do_lstc},
10185 {"mcr", 0xee000010, 3, ARM_EXT_V2, do_co_reg},
10186 {"mrc", 0xee100010, 3, ARM_EXT_V2, do_co_reg},
10187
10188 /* ARM 3 - swp instructions. */
10189 {"swp", 0xe1000090, 3, ARM_EXT_V2S, do_swap},
10190 {"swpb", 0xe1400090, 3, ARM_EXT_V2S, do_swap},
10191
10192 /* ARM 6 Status register instructions. */
10193 {"mrs", 0xe10f0000, 3, ARM_EXT_V3, do_mrs},
10194 {"msr", 0xe120f000, 3, ARM_EXT_V3, do_msr},
10195 /* ScottB: our code uses 0xe128f000 for msr.
10196 NickC: but this is wrong because the bits 16 through 19 are
10197 handled by the PSR_xxx defines above. */
10198
10199 /* ARM 7M long multiplies. */
10200 {"smull", 0xe0c00090, 5, ARM_EXT_V3M, do_mull},
10201 {"smulls", 0xe0d00090, 5, ARM_EXT_V3M, do_mull},
10202 {"umull", 0xe0800090, 5, ARM_EXT_V3M, do_mull},
10203 {"umulls", 0xe0900090, 5, ARM_EXT_V3M, do_mull},
10204 {"smlal", 0xe0e00090, 5, ARM_EXT_V3M, do_mull},
10205 {"smlals", 0xe0f00090, 5, ARM_EXT_V3M, do_mull},
10206 {"umlal", 0xe0a00090, 5, ARM_EXT_V3M, do_mull},
10207 {"umlals", 0xe0b00090, 5, ARM_EXT_V3M, do_mull},
10208
10209 /* ARM Architecture 4. */
10210 {"ldrh", 0xe01000b0, 3, ARM_EXT_V4, do_ldstv4},
10211 {"ldrsh", 0xe01000f0, 3, ARM_EXT_V4, do_ldstv4},
10212 {"ldrsb", 0xe01000d0, 3, ARM_EXT_V4, do_ldstv4},
10213 {"strh", 0xe00000b0, 3, ARM_EXT_V4, do_ldstv4},
10214
10215 /* ARM Architecture 4T. */
10216 /* Note: bx (and blx) are required on V5, even if the processor does
10217 not support Thumb. */
10218 {"bx", 0xe12fff10, 2, ARM_EXT_V4T | ARM_EXT_V5, do_bx},
10219
10220 /* ARM Architecture 5T. */
10221 /* Note: blx has 2 variants, so the .value is set dynamically.
10222 Only one of the variants has conditional execution. */
10223 {"blx", 0xe0000000, 3, ARM_EXT_V5, do_blx},
10224 {"clz", 0xe16f0f10, 3, ARM_EXT_V5, do_clz},
10225 {"bkpt", 0xe1200070, 0, ARM_EXT_V5, do_bkpt},
10226 {"ldc2", 0xfc100000, 0, ARM_EXT_V5, do_lstc2},
10227 {"ldc2l", 0xfc500000, 0, ARM_EXT_V5, do_lstc2},
10228 {"stc2", 0xfc000000, 0, ARM_EXT_V5, do_lstc2},
10229 {"stc2l", 0xfc400000, 0, ARM_EXT_V5, do_lstc2},
10230 {"cdp2", 0xfe000000, 0, ARM_EXT_V5, do_cdp2},
10231 {"mcr2", 0xfe000010, 0, ARM_EXT_V5, do_co_reg2},
10232 {"mrc2", 0xfe100010, 0, ARM_EXT_V5, do_co_reg2},
10233
10234 /* ARM Architecture 5TExP. */
10235 {"smlabb", 0xe1000080, 6, ARM_EXT_V5ExP, do_smla},
10236 {"smlatb", 0xe10000a0, 6, ARM_EXT_V5ExP, do_smla},
10237 {"smlabt", 0xe10000c0, 6, ARM_EXT_V5ExP, do_smla},
10238 {"smlatt", 0xe10000e0, 6, ARM_EXT_V5ExP, do_smla},
10239
10240 {"smlawb", 0xe1200080, 6, ARM_EXT_V5ExP, do_smla},
10241 {"smlawt", 0xe12000c0, 6, ARM_EXT_V5ExP, do_smla},
10242
10243 {"smlalbb", 0xe1400080, 7, ARM_EXT_V5ExP, do_smlal},
10244 {"smlaltb", 0xe14000a0, 7, ARM_EXT_V5ExP, do_smlal},
10245 {"smlalbt", 0xe14000c0, 7, ARM_EXT_V5ExP, do_smlal},
10246 {"smlaltt", 0xe14000e0, 7, ARM_EXT_V5ExP, do_smlal},
10247
10248 {"smulbb", 0xe1600080, 6, ARM_EXT_V5ExP, do_smul},
10249 {"smultb", 0xe16000a0, 6, ARM_EXT_V5ExP, do_smul},
10250 {"smulbt", 0xe16000c0, 6, ARM_EXT_V5ExP, do_smul},
10251 {"smultt", 0xe16000e0, 6, ARM_EXT_V5ExP, do_smul},
10252
10253 {"smulwb", 0xe12000a0, 6, ARM_EXT_V5ExP, do_smul},
10254 {"smulwt", 0xe12000e0, 6, ARM_EXT_V5ExP, do_smul},
10255
10256 {"qadd", 0xe1000050, 4, ARM_EXT_V5ExP, do_qadd},
10257 {"qdadd", 0xe1400050, 5, ARM_EXT_V5ExP, do_qadd},
10258 {"qsub", 0xe1200050, 4, ARM_EXT_V5ExP, do_qadd},
10259 {"qdsub", 0xe1600050, 5, ARM_EXT_V5ExP, do_qadd},
10260
10261 /* ARM Architecture 5TE. */
10262 {"pld", 0xf450f000, 0, ARM_EXT_V5E, do_pld},
10263 {"ldrd", 0xe00000d0, 3, ARM_EXT_V5E, do_ldrd},
10264 {"strd", 0xe00000f0, 3, ARM_EXT_V5E, do_ldrd},
10265
10266 {"mcrr", 0xec400000, 4, ARM_EXT_V5E, do_co_reg2c},
10267 {"mrrc", 0xec500000, 4, ARM_EXT_V5E, do_co_reg2c},
10268
10269 /* ARM Architecture 5TEJ. */
10270 {"bxj", 0xe12fff20, 3, ARM_EXT_V5J, do_bxj},
10271
10272 /* ARM V6. */
10273 { "cps", 0xf1020000, 0, ARM_EXT_V6, do_cps},
10274 { "cpsie", 0xf1080000, 0, ARM_EXT_V6, do_cpsi},
10275 { "cpsid", 0xf10C0000, 0, ARM_EXT_V6, do_cpsi},
10276 { "ldrex", 0xe1900f9f, 5, ARM_EXT_V6, do_ldrex},
10277 { "mcrr2", 0xfc400000, 0, ARM_EXT_V6, do_co_reg2c},
10278 { "mrrc2", 0xfc500000, 0, ARM_EXT_V6, do_co_reg2c},
10279 { "pkhbt", 0xe6800010, 5, ARM_EXT_V6, do_pkhbt},
10280 { "pkhtb", 0xe6800050, 5, ARM_EXT_V6, do_pkhtb},
10281 { "qadd16", 0xe6200f10, 6, ARM_EXT_V6, do_qadd16},
10282 { "qadd8", 0xe6200f90, 5, ARM_EXT_V6, do_qadd16},
10283 { "qaddsubx", 0xe6200f30, 8, ARM_EXT_V6, do_qadd16},
10284 { "qsub16", 0xe6200f70, 6, ARM_EXT_V6, do_qadd16},
10285 { "qsub8", 0xe6200ff0, 5, ARM_EXT_V6, do_qadd16},
10286 { "qsubaddx", 0xe6200f50, 8, ARM_EXT_V6, do_qadd16},
10287 { "sadd16", 0xe6100f10, 6, ARM_EXT_V6, do_qadd16},
10288 { "sadd8", 0xe6100f90, 5, ARM_EXT_V6, do_qadd16},
10289 { "saddsubx", 0xe6100f30, 8, ARM_EXT_V6, do_qadd16},
10290 { "shadd16", 0xe6300f10, 7, ARM_EXT_V6, do_qadd16},
10291 { "shadd8", 0xe6300f90, 6, ARM_EXT_V6, do_qadd16},
10292 { "shaddsubx", 0xe6300f30, 9, ARM_EXT_V6, do_qadd16},
10293 { "shsub16", 0xe6300f70, 7, ARM_EXT_V6, do_qadd16},
10294 { "shsub8", 0xe6300ff0, 6, ARM_EXT_V6, do_qadd16},
10295 { "shsubaddx", 0xe6300f50, 9, ARM_EXT_V6, do_qadd16},
10296 { "ssub16", 0xe6100f70, 6, ARM_EXT_V6, do_qadd16},
10297 { "ssub8", 0xe6100ff0, 5, ARM_EXT_V6, do_qadd16},
10298 { "ssubaddx", 0xe6100f50, 8, ARM_EXT_V6, do_qadd16},
10299 { "uadd16", 0xe6500f10, 6, ARM_EXT_V6, do_qadd16},
10300 { "uadd8", 0xe6500f90, 5, ARM_EXT_V6, do_qadd16},
10301 { "uaddsubx", 0xe6500f30, 8, ARM_EXT_V6, do_qadd16},
10302 { "uhadd16", 0xe6700f10, 7, ARM_EXT_V6, do_qadd16},
10303 { "uhadd8", 0xe6700f90, 6, ARM_EXT_V6, do_qadd16},
10304 { "uhaddsubx", 0xe6700f30, 9, ARM_EXT_V6, do_qadd16},
10305 { "uhsub16", 0xe6700f70, 7, ARM_EXT_V6, do_qadd16},
10306 { "uhsub8", 0xe6700ff0, 6, ARM_EXT_V6, do_qadd16},
10307 { "uhsubaddx", 0xe6700f50, 9, ARM_EXT_V6, do_qadd16},
10308 { "uqadd16", 0xe6600f10, 7, ARM_EXT_V6, do_qadd16},
10309 { "uqadd8", 0xe6600f90, 6, ARM_EXT_V6, do_qadd16},
10310 { "uqaddsubx", 0xe6600f30, 9, ARM_EXT_V6, do_qadd16},
10311 { "uqsub16", 0xe6600f70, 7, ARM_EXT_V6, do_qadd16},
10312 { "uqsub8", 0xe6600ff0, 6, ARM_EXT_V6, do_qadd16},
10313 { "uqsubaddx", 0xe6600f50, 9, ARM_EXT_V6, do_qadd16},
10314 { "usub16", 0xe6500f70, 6, ARM_EXT_V6, do_qadd16},
10315 { "usub8", 0xe6500ff0, 5, ARM_EXT_V6, do_qadd16},
10316 { "usubaddx", 0xe6500f50, 8, ARM_EXT_V6, do_qadd16},
10317 { "rev", 0xe6bf0f30, 3, ARM_EXT_V6, do_rev},
10318 { "rev16", 0xe6bf0fb0, 5, ARM_EXT_V6, do_rev},
10319 { "revsh", 0xe6ff0fb0, 5, ARM_EXT_V6, do_rev},
10320 { "rfeia", 0xf8900a00, 0, ARM_EXT_V6, do_rfe},
10321 { "rfeib", 0xf9900a00, 0, ARM_EXT_V6, do_rfe},
10322 { "rfeda", 0xf8100a00, 0, ARM_EXT_V6, do_rfe},
10323 { "rfedb", 0xf9100a00, 0, ARM_EXT_V6, do_rfe},
10324 { "rfefd", 0xf8900a00, 0, ARM_EXT_V6, do_rfe},
10325 { "rfefa", 0xf9900a00, 0, ARM_EXT_V6, do_rfe},
10326 { "rfeea", 0xf8100a00, 0, ARM_EXT_V6, do_rfe},
10327 { "rfeed", 0xf9100a00, 0, ARM_EXT_V6, do_rfe},
10328 { "sxtah", 0xe6b00070, 5, ARM_EXT_V6, do_sxtah},
10329 { "sxtab16", 0xe6800070, 7, ARM_EXT_V6, do_sxtah},
10330 { "sxtab", 0xe6a00070, 5, ARM_EXT_V6, do_sxtah},
10331 { "sxth", 0xe6bf0070, 4, ARM_EXT_V6, do_sxth},
10332 { "sxtb16", 0xe68f0070, 6, ARM_EXT_V6, do_sxth},
10333 { "sxtb", 0xe6af0070, 4, ARM_EXT_V6, do_sxth},
10334 { "uxtah", 0xe6f00070, 5, ARM_EXT_V6, do_sxtah},
10335 { "uxtab16", 0xe6c00070, 7, ARM_EXT_V6, do_sxtah},
10336 { "uxtab", 0xe6e00070, 5, ARM_EXT_V6, do_sxtah},
10337 { "uxth", 0xe6ff0070, 4, ARM_EXT_V6, do_sxth},
10338 { "uxtb16", 0xe6cf0070, 6, ARM_EXT_V6, do_sxth},
10339 { "uxtb", 0xe6ef0070, 4, ARM_EXT_V6, do_sxth},
10340 { "sel", 0xe68000b0, 3, ARM_EXT_V6, do_qadd16},
10341 { "setend", 0xf1010000, 0, ARM_EXT_V6, do_setend},
10342 { "smlad", 0xe7000010, 5, ARM_EXT_V6, do_smlad},
10343 { "smladx", 0xe7000030, 6, ARM_EXT_V6, do_smlad},
10344 { "smlald", 0xe7400010, 6, ARM_EXT_V6, do_smlald},
10345 { "smlaldx", 0xe7400030, 7, ARM_EXT_V6, do_smlald},
10346 { "smlsd", 0xe7000050, 5, ARM_EXT_V6, do_smlad},
10347 { "smlsdx", 0xe7000070, 6, ARM_EXT_V6, do_smlad},
10348 { "smlsld", 0xe7400050, 6, ARM_EXT_V6, do_smlald},
10349 { "smlsldx", 0xe7400070, 7, ARM_EXT_V6, do_smlald},
10350 { "smmla", 0xe7500010, 5, ARM_EXT_V6, do_smlad},
10351 { "smmlar", 0xe7500030, 6, ARM_EXT_V6, do_smlad},
10352 { "smmls", 0xe75000d0, 5, ARM_EXT_V6, do_smlad},
10353 { "smmlsr", 0xe75000f0, 6, ARM_EXT_V6, do_smlad},
10354 { "smmul", 0xe750f010, 5, ARM_EXT_V6, do_smmul},
10355 { "smmulr", 0xe750f030, 6, ARM_EXT_V6, do_smmul},
10356 { "smuad", 0xe700f010, 5, ARM_EXT_V6, do_smmul},
10357 { "smuadx", 0xe700f030, 6, ARM_EXT_V6, do_smmul},
10358 { "smusd", 0xe700f050, 5, ARM_EXT_V6, do_smmul},
10359 { "smusdx", 0xe700f070, 6, ARM_EXT_V6, do_smmul},
10360 { "srsia", 0xf8cd0500, 0, ARM_EXT_V6, do_srs},
10361 { "srsib", 0xf9cd0500, 0, ARM_EXT_V6, do_srs},
10362 { "srsda", 0xf84d0500, 0, ARM_EXT_V6, do_srs},
10363 { "srsdb", 0xf94d0500, 0, ARM_EXT_V6, do_srs},
10364 { "ssat", 0xe6a00010, 4, ARM_EXT_V6, do_ssat},
10365 { "ssat16", 0xe6a00f30, 6, ARM_EXT_V6, do_ssat16},
10366 { "strex", 0xe1800f90, 5, ARM_EXT_V6, do_strex},
10367 { "umaal", 0xe0400090, 5, ARM_EXT_V6, do_umaal},
10368 { "usad8", 0xe780f010, 5, ARM_EXT_V6, do_smmul},
10369 { "usada8", 0xe7800010, 6, ARM_EXT_V6, do_smlad},
10370 { "usat", 0xe6e00010, 4, ARM_EXT_V6, do_usat},
10371 { "usat16", 0xe6e00f30, 6, ARM_EXT_V6, do_usat16},
10372
10373 /* ARM V6K. */
10374 { "clrex", 0xf57ff01f, 0, ARM_EXT_V6K, do_empty},
10375 { "ldrexb", 0xe1d00f9f, 6, ARM_EXT_V6K, do_ldrex},
10376 { "ldrexd", 0xe1b00f9f, 6, ARM_EXT_V6K, do_ldrex},
10377 { "ldrexh", 0xe1f00f9f, 6, ARM_EXT_V6K, do_ldrex},
10378 { "sev", 0xe320f004, 3, ARM_EXT_V6K, do_empty},
10379 { "strexb", 0xe1c00f90, 6, ARM_EXT_V6K, do_strex},
10380 { "strexd", 0xe1a00f90, 6, ARM_EXT_V6K, do_strex},
10381 { "strexh", 0xe1e00f90, 6, ARM_EXT_V6K, do_strex},
10382 { "wfe", 0xe320f002, 3, ARM_EXT_V6K, do_empty},
10383 { "wfi", 0xe320f003, 3, ARM_EXT_V6K, do_empty},
10384 { "yield", 0xe320f001, 5, ARM_EXT_V6K, do_empty},
10385
10386 /* ARM V6Z. */
10387 { "smi", 0xe1600070, 3, ARM_EXT_V6Z, do_smi},
10388
10389 /* ARM V6T2. */
10390 { "bfc", 0xe7c0001f, 3, ARM_EXT_V6T2, do_bfc},
10391 { "bfi", 0xe7c00010, 3, ARM_EXT_V6T2, do_bfi},
10392 { "mls", 0xe0600090, 3, ARM_EXT_V6T2, do_mls},
10393 { "movw", 0xe3000000, 4, ARM_EXT_V6T2, do_mov16},
10394 { "movt", 0xe3400000, 4, ARM_EXT_V6T2, do_mov16},
10395 { "rbit", 0xe3ff0f30, 4, ARM_EXT_V6T2, do_rbit},
10396 { "sbfx", 0xe7a00050, 4, ARM_EXT_V6T2, do_bfx},
10397 { "ubfx", 0xe7e00050, 4, ARM_EXT_V6T2, do_bfx},
10398
10399 { "ldrht", 0xe03000b0, 3, ARM_EXT_V6T2, do_ldsttv4},
10400 { "ldrsht", 0xe03000f0, 3, ARM_EXT_V6T2, do_ldsttv4},
10401 { "ldrsbt", 0xe03000d0, 3, ARM_EXT_V6T2, do_ldsttv4},
10402 { "strht", 0xe02000b0, 3, ARM_EXT_V6T2, do_ldsttv4},
10403
10404 /* Core FPA instruction set (V1). */
10405 {"wfs", 0xee200110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
10406 {"rfs", 0xee300110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
10407 {"wfc", 0xee400110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
10408 {"rfc", 0xee500110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
10409
10410 {"ldfs", 0xec100100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10411 {"ldfd", 0xec108100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10412 {"ldfe", 0xec500100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10413 {"ldfp", 0xec508100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10414
10415 {"stfs", 0xec000100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10416 {"stfd", 0xec008100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10417 {"stfe", 0xec400100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10418 {"stfp", 0xec408100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10419
10420 {"mvfs", 0xee008100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10421 {"mvfsp", 0xee008120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10422 {"mvfsm", 0xee008140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10423 {"mvfsz", 0xee008160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10424 {"mvfd", 0xee008180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10425 {"mvfdp", 0xee0081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10426 {"mvfdm", 0xee0081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10427 {"mvfdz", 0xee0081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10428 {"mvfe", 0xee088100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10429 {"mvfep", 0xee088120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10430 {"mvfem", 0xee088140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10431 {"mvfez", 0xee088160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10432
10433 {"mnfs", 0xee108100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10434 {"mnfsp", 0xee108120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10435 {"mnfsm", 0xee108140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10436 {"mnfsz", 0xee108160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10437 {"mnfd", 0xee108180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10438 {"mnfdp", 0xee1081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10439 {"mnfdm", 0xee1081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10440 {"mnfdz", 0xee1081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10441 {"mnfe", 0xee188100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10442 {"mnfep", 0xee188120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10443 {"mnfem", 0xee188140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10444 {"mnfez", 0xee188160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10445
10446 {"abss", 0xee208100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10447 {"abssp", 0xee208120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10448 {"abssm", 0xee208140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10449 {"abssz", 0xee208160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10450 {"absd", 0xee208180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10451 {"absdp", 0xee2081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10452 {"absdm", 0xee2081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10453 {"absdz", 0xee2081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10454 {"abse", 0xee288100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10455 {"absep", 0xee288120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10456 {"absem", 0xee288140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10457 {"absez", 0xee288160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10458
10459 {"rnds", 0xee308100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10460 {"rndsp", 0xee308120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10461 {"rndsm", 0xee308140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10462 {"rndsz", 0xee308160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10463 {"rndd", 0xee308180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10464 {"rnddp", 0xee3081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10465 {"rnddm", 0xee3081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10466 {"rnddz", 0xee3081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10467 {"rnde", 0xee388100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10468 {"rndep", 0xee388120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10469 {"rndem", 0xee388140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10470 {"rndez", 0xee388160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10471
10472 {"sqts", 0xee408100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10473 {"sqtsp", 0xee408120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10474 {"sqtsm", 0xee408140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10475 {"sqtsz", 0xee408160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10476 {"sqtd", 0xee408180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10477 {"sqtdp", 0xee4081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10478 {"sqtdm", 0xee4081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10479 {"sqtdz", 0xee4081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10480 {"sqte", 0xee488100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10481 {"sqtep", 0xee488120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10482 {"sqtem", 0xee488140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10483 {"sqtez", 0xee488160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10484
10485 {"logs", 0xee508100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10486 {"logsp", 0xee508120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10487 {"logsm", 0xee508140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10488 {"logsz", 0xee508160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10489 {"logd", 0xee508180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10490 {"logdp", 0xee5081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10491 {"logdm", 0xee5081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10492 {"logdz", 0xee5081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10493 {"loge", 0xee588100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10494 {"logep", 0xee588120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10495 {"logem", 0xee588140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10496 {"logez", 0xee588160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10497
10498 {"lgns", 0xee608100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10499 {"lgnsp", 0xee608120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10500 {"lgnsm", 0xee608140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10501 {"lgnsz", 0xee608160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10502 {"lgnd", 0xee608180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10503 {"lgndp", 0xee6081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10504 {"lgndm", 0xee6081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10505 {"lgndz", 0xee6081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10506 {"lgne", 0xee688100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10507 {"lgnep", 0xee688120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10508 {"lgnem", 0xee688140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10509 {"lgnez", 0xee688160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10510
10511 {"exps", 0xee708100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10512 {"expsp", 0xee708120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10513 {"expsm", 0xee708140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10514 {"expsz", 0xee708160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10515 {"expd", 0xee708180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10516 {"expdp", 0xee7081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10517 {"expdm", 0xee7081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10518 {"expdz", 0xee7081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10519 {"expe", 0xee788100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10520 {"expep", 0xee788120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10521 {"expem", 0xee788140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10522 {"expdz", 0xee788160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10523
10524 {"sins", 0xee808100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10525 {"sinsp", 0xee808120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10526 {"sinsm", 0xee808140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10527 {"sinsz", 0xee808160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10528 {"sind", 0xee808180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10529 {"sindp", 0xee8081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10530 {"sindm", 0xee8081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10531 {"sindz", 0xee8081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10532 {"sine", 0xee888100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10533 {"sinep", 0xee888120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10534 {"sinem", 0xee888140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10535 {"sinez", 0xee888160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10536
10537 {"coss", 0xee908100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10538 {"cossp", 0xee908120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10539 {"cossm", 0xee908140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10540 {"cossz", 0xee908160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10541 {"cosd", 0xee908180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10542 {"cosdp", 0xee9081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10543 {"cosdm", 0xee9081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10544 {"cosdz", 0xee9081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10545 {"cose", 0xee988100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10546 {"cosep", 0xee988120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10547 {"cosem", 0xee988140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10548 {"cosez", 0xee988160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10549
10550 {"tans", 0xeea08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10551 {"tansp", 0xeea08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10552 {"tansm", 0xeea08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10553 {"tansz", 0xeea08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10554 {"tand", 0xeea08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10555 {"tandp", 0xeea081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10556 {"tandm", 0xeea081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10557 {"tandz", 0xeea081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10558 {"tane", 0xeea88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10559 {"tanep", 0xeea88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10560 {"tanem", 0xeea88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10561 {"tanez", 0xeea88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10562
10563 {"asns", 0xeeb08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10564 {"asnsp", 0xeeb08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10565 {"asnsm", 0xeeb08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10566 {"asnsz", 0xeeb08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10567 {"asnd", 0xeeb08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10568 {"asndp", 0xeeb081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10569 {"asndm", 0xeeb081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10570 {"asndz", 0xeeb081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10571 {"asne", 0xeeb88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10572 {"asnep", 0xeeb88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10573 {"asnem", 0xeeb88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10574 {"asnez", 0xeeb88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10575
10576 {"acss", 0xeec08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10577 {"acssp", 0xeec08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10578 {"acssm", 0xeec08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10579 {"acssz", 0xeec08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10580 {"acsd", 0xeec08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10581 {"acsdp", 0xeec081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10582 {"acsdm", 0xeec081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10583 {"acsdz", 0xeec081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10584 {"acse", 0xeec88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10585 {"acsep", 0xeec88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10586 {"acsem", 0xeec88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10587 {"acsez", 0xeec88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10588
10589 {"atns", 0xeed08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10590 {"atnsp", 0xeed08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10591 {"atnsm", 0xeed08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10592 {"atnsz", 0xeed08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10593 {"atnd", 0xeed08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10594 {"atndp", 0xeed081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10595 {"atndm", 0xeed081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10596 {"atndz", 0xeed081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10597 {"atne", 0xeed88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10598 {"atnep", 0xeed88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10599 {"atnem", 0xeed88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10600 {"atnez", 0xeed88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10601
10602 {"urds", 0xeee08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10603 {"urdsp", 0xeee08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10604 {"urdsm", 0xeee08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10605 {"urdsz", 0xeee08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10606 {"urdd", 0xeee08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10607 {"urddp", 0xeee081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10608 {"urddm", 0xeee081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10609 {"urddz", 0xeee081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10610 {"urde", 0xeee88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10611 {"urdep", 0xeee88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10612 {"urdem", 0xeee88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10613 {"urdez", 0xeee88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10614
10615 {"nrms", 0xeef08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10616 {"nrmsp", 0xeef08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10617 {"nrmsm", 0xeef08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10618 {"nrmsz", 0xeef08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10619 {"nrmd", 0xeef08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10620 {"nrmdp", 0xeef081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10621 {"nrmdm", 0xeef081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10622 {"nrmdz", 0xeef081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10623 {"nrme", 0xeef88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10624 {"nrmep", 0xeef88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10625 {"nrmem", 0xeef88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10626 {"nrmez", 0xeef88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10627
10628 {"adfs", 0xee000100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10629 {"adfsp", 0xee000120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10630 {"adfsm", 0xee000140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10631 {"adfsz", 0xee000160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10632 {"adfd", 0xee000180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10633 {"adfdp", 0xee0001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10634 {"adfdm", 0xee0001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10635 {"adfdz", 0xee0001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10636 {"adfe", 0xee080100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10637 {"adfep", 0xee080120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10638 {"adfem", 0xee080140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10639 {"adfez", 0xee080160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10640
10641 {"sufs", 0xee200100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10642 {"sufsp", 0xee200120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10643 {"sufsm", 0xee200140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10644 {"sufsz", 0xee200160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10645 {"sufd", 0xee200180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10646 {"sufdp", 0xee2001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10647 {"sufdm", 0xee2001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10648 {"sufdz", 0xee2001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10649 {"sufe", 0xee280100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10650 {"sufep", 0xee280120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10651 {"sufem", 0xee280140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10652 {"sufez", 0xee280160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10653
10654 {"rsfs", 0xee300100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10655 {"rsfsp", 0xee300120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10656 {"rsfsm", 0xee300140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10657 {"rsfsz", 0xee300160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10658 {"rsfd", 0xee300180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10659 {"rsfdp", 0xee3001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10660 {"rsfdm", 0xee3001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10661 {"rsfdz", 0xee3001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10662 {"rsfe", 0xee380100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10663 {"rsfep", 0xee380120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10664 {"rsfem", 0xee380140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10665 {"rsfez", 0xee380160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10666
10667 {"mufs", 0xee100100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10668 {"mufsp", 0xee100120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10669 {"mufsm", 0xee100140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10670 {"mufsz", 0xee100160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10671 {"mufd", 0xee100180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10672 {"mufdp", 0xee1001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10673 {"mufdm", 0xee1001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10674 {"mufdz", 0xee1001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10675 {"mufe", 0xee180100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10676 {"mufep", 0xee180120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10677 {"mufem", 0xee180140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10678 {"mufez", 0xee180160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10679
10680 {"dvfs", 0xee400100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10681 {"dvfsp", 0xee400120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10682 {"dvfsm", 0xee400140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10683 {"dvfsz", 0xee400160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10684 {"dvfd", 0xee400180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10685 {"dvfdp", 0xee4001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10686 {"dvfdm", 0xee4001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10687 {"dvfdz", 0xee4001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10688 {"dvfe", 0xee480100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10689 {"dvfep", 0xee480120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10690 {"dvfem", 0xee480140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10691 {"dvfez", 0xee480160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10692
10693 {"rdfs", 0xee500100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10694 {"rdfsp", 0xee500120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10695 {"rdfsm", 0xee500140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10696 {"rdfsz", 0xee500160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10697 {"rdfd", 0xee500180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10698 {"rdfdp", 0xee5001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10699 {"rdfdm", 0xee5001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10700 {"rdfdz", 0xee5001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10701 {"rdfe", 0xee580100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10702 {"rdfep", 0xee580120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10703 {"rdfem", 0xee580140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10704 {"rdfez", 0xee580160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10705
10706 {"pows", 0xee600100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10707 {"powsp", 0xee600120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10708 {"powsm", 0xee600140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10709 {"powsz", 0xee600160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10710 {"powd", 0xee600180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10711 {"powdp", 0xee6001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10712 {"powdm", 0xee6001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10713 {"powdz", 0xee6001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10714 {"powe", 0xee680100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10715 {"powep", 0xee680120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10716 {"powem", 0xee680140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10717 {"powez", 0xee680160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10718
10719 {"rpws", 0xee700100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10720 {"rpwsp", 0xee700120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10721 {"rpwsm", 0xee700140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10722 {"rpwsz", 0xee700160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10723 {"rpwd", 0xee700180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10724 {"rpwdp", 0xee7001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10725 {"rpwdm", 0xee7001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10726 {"rpwdz", 0xee7001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10727 {"rpwe", 0xee780100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10728 {"rpwep", 0xee780120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10729 {"rpwem", 0xee780140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10730 {"rpwez", 0xee780160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10731
10732 {"rmfs", 0xee800100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10733 {"rmfsp", 0xee800120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10734 {"rmfsm", 0xee800140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10735 {"rmfsz", 0xee800160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10736 {"rmfd", 0xee800180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10737 {"rmfdp", 0xee8001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10738 {"rmfdm", 0xee8001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10739 {"rmfdz", 0xee8001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10740 {"rmfe", 0xee880100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10741 {"rmfep", 0xee880120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10742 {"rmfem", 0xee880140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10743 {"rmfez", 0xee880160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10744
10745 {"fmls", 0xee900100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10746 {"fmlsp", 0xee900120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10747 {"fmlsm", 0xee900140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10748 {"fmlsz", 0xee900160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10749 {"fmld", 0xee900180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10750 {"fmldp", 0xee9001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10751 {"fmldm", 0xee9001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10752 {"fmldz", 0xee9001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10753 {"fmle", 0xee980100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10754 {"fmlep", 0xee980120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10755 {"fmlem", 0xee980140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10756 {"fmlez", 0xee980160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10757
10758 {"fdvs", 0xeea00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10759 {"fdvsp", 0xeea00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10760 {"fdvsm", 0xeea00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10761 {"fdvsz", 0xeea00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10762 {"fdvd", 0xeea00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10763 {"fdvdp", 0xeea001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10764 {"fdvdm", 0xeea001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10765 {"fdvdz", 0xeea001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10766 {"fdve", 0xeea80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10767 {"fdvep", 0xeea80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10768 {"fdvem", 0xeea80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10769 {"fdvez", 0xeea80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10770
10771 {"frds", 0xeeb00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10772 {"frdsp", 0xeeb00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10773 {"frdsm", 0xeeb00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10774 {"frdsz", 0xeeb00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10775 {"frdd", 0xeeb00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10776 {"frddp", 0xeeb001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10777 {"frddm", 0xeeb001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10778 {"frddz", 0xeeb001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10779 {"frde", 0xeeb80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10780 {"frdep", 0xeeb80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10781 {"frdem", 0xeeb80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10782 {"frdez", 0xeeb80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10783
10784 {"pols", 0xeec00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10785 {"polsp", 0xeec00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10786 {"polsm", 0xeec00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10787 {"polsz", 0xeec00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10788 {"pold", 0xeec00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10789 {"poldp", 0xeec001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10790 {"poldm", 0xeec001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10791 {"poldz", 0xeec001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10792 {"pole", 0xeec80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10793 {"polep", 0xeec80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10794 {"polem", 0xeec80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10795 {"polez", 0xeec80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10796
10797 {"cmf", 0xee90f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
10798 {"cmfe", 0xeed0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
10799 {"cnf", 0xeeb0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
10800 {"cnfe", 0xeef0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
10801 /* The FPA10 data sheet suggests that the 'E' of cmfe/cnfe should
10802 not be an optional suffix, but part of the instruction. To be
10803 compatible, we accept either. */
10804 {"cmfe", 0xeed0f110, 4, FPU_FPA_EXT_V1, do_fpa_cmp},
10805 {"cnfe", 0xeef0f110, 4, FPU_FPA_EXT_V1, do_fpa_cmp},
10806
10807 {"flts", 0xee000110, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10808 {"fltsp", 0xee000130, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10809 {"fltsm", 0xee000150, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10810 {"fltsz", 0xee000170, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10811 {"fltd", 0xee000190, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10812 {"fltdp", 0xee0001b0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10813 {"fltdm", 0xee0001d0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10814 {"fltdz", 0xee0001f0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10815 {"flte", 0xee080110, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10816 {"fltep", 0xee080130, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10817 {"fltem", 0xee080150, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10818 {"fltez", 0xee080170, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10819
10820 /* The implementation of the FIX instruction is broken on some
10821 assemblers, in that it accepts a precision specifier as well as a
10822 rounding specifier, despite the fact that this is meaningless.
10823 To be more compatible, we accept it as well, though of course it
10824 does not set any bits. */
10825 {"fix", 0xee100110, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10826 {"fixp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10827 {"fixm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10828 {"fixz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10829 {"fixsp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10830 {"fixsm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10831 {"fixsz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10832 {"fixdp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10833 {"fixdm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10834 {"fixdz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10835 {"fixep", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10836 {"fixem", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10837 {"fixez", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10838
10839 /* Instructions that were new with the real FPA, call them V2. */
10840 {"lfm", 0xec100200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10841 {"lfmfd", 0xec900200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10842 {"lfmea", 0xed100200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10843 {"sfm", 0xec000200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10844 {"sfmfd", 0xed000200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10845 {"sfmea", 0xec800200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10846
10847 /* VFP V1xD (single precision). */
10848 /* Moves and type conversions. */
10849 {"fcpys", 0xeeb00a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10850 {"fmrs", 0xee100a10, 4, FPU_VFP_EXT_V1xD, do_vfp_reg_from_sp},
10851 {"fmsr", 0xee000a10, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_from_reg},
10852 {"fmstat", 0xeef1fa10, 6, FPU_VFP_EXT_V1xD, do_empty},
10853 {"fsitos", 0xeeb80ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10854 {"fuitos", 0xeeb80a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10855 {"ftosis", 0xeebd0a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10856 {"ftosizs", 0xeebd0ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10857 {"ftouis", 0xeebc0a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10858 {"ftouizs", 0xeebc0ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10859 {"fmrx", 0xeef00a10, 4, FPU_VFP_EXT_V1xD, do_vfp_reg_from_ctrl},
10860 {"fmxr", 0xeee00a10, 4, FPU_VFP_EXT_V1xD, do_vfp_ctrl_from_reg},
10861
10862 /* Memory operations. */
10863 {"flds", 0xed100a00, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_ldst},
10864 {"fsts", 0xed000a00, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_ldst},
10865 {"fldmias", 0xec900a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
10866 {"fldmfds", 0xec900a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
10867 {"fldmdbs", 0xed300a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
10868 {"fldmeas", 0xed300a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
10869 {"fldmiax", 0xec900b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
10870 {"fldmfdx", 0xec900b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
10871 {"fldmdbx", 0xed300b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
10872 {"fldmeax", 0xed300b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
10873 {"fstmias", 0xec800a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
10874 {"fstmeas", 0xec800a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
10875 {"fstmdbs", 0xed200a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
10876 {"fstmfds", 0xed200a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
10877 {"fstmiax", 0xec800b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
10878 {"fstmeax", 0xec800b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
10879 {"fstmdbx", 0xed200b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
10880 {"fstmfdx", 0xed200b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
10881
10882 /* Monadic operations. */
10883 {"fabss", 0xeeb00ac0, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10884 {"fnegs", 0xeeb10a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10885 {"fsqrts", 0xeeb10ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10886
10887 /* Dyadic operations. */
10888 {"fadds", 0xee300a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10889 {"fsubs", 0xee300a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10890 {"fmuls", 0xee200a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10891 {"fdivs", 0xee800a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10892 {"fmacs", 0xee000a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10893 {"fmscs", 0xee100a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10894 {"fnmuls", 0xee200a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10895 {"fnmacs", 0xee000a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10896 {"fnmscs", 0xee100a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10897
10898 /* Comparisons. */
10899 {"fcmps", 0xeeb40a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10900 {"fcmpzs", 0xeeb50a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_compare_z},
10901 {"fcmpes", 0xeeb40ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10902 {"fcmpezs", 0xeeb50ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_compare_z},
10903
10904 /* VFP V1 (Double precision). */
10905 /* Moves and type conversions. */
10906 {"fcpyd", 0xeeb00b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10907 {"fcvtds", 0xeeb70ac0, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
10908 {"fcvtsd", 0xeeb70bc0, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
10909 {"fmdhr", 0xee200b10, 5, FPU_VFP_EXT_V1, do_vfp_dp_from_reg},
10910 {"fmdlr", 0xee000b10, 5, FPU_VFP_EXT_V1, do_vfp_dp_from_reg},
10911 {"fmrdh", 0xee300b10, 5, FPU_VFP_EXT_V1, do_vfp_reg_from_dp},
10912 {"fmrdl", 0xee100b10, 5, FPU_VFP_EXT_V1, do_vfp_reg_from_dp},
10913 {"fsitod", 0xeeb80bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
10914 {"fuitod", 0xeeb80b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
10915 {"ftosid", 0xeebd0b40, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
10916 {"ftosizd", 0xeebd0bc0, 7, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
10917 {"ftouid", 0xeebc0b40, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
10918 {"ftouizd", 0xeebc0bc0, 7, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
10919
10920 /* Memory operations. */
10921 {"fldd", 0xed100b00, 4, FPU_VFP_EXT_V1, do_vfp_dp_ldst},
10922 {"fstd", 0xed000b00, 4, FPU_VFP_EXT_V1, do_vfp_dp_ldst},
10923 {"fldmiad", 0xec900b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
10924 {"fldmfdd", 0xec900b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
10925 {"fldmdbd", 0xed300b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
10926 {"fldmead", 0xed300b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
10927 {"fstmiad", 0xec800b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
10928 {"fstmead", 0xec800b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
10929 {"fstmdbd", 0xed200b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
10930 {"fstmfdd", 0xed200b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
10931
10932 /* Monadic operations. */
10933 {"fabsd", 0xeeb00bc0, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10934 {"fnegd", 0xeeb10b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10935 {"fsqrtd", 0xeeb10bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10936
10937 /* Dyadic operations. */
10938 {"faddd", 0xee300b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10939 {"fsubd", 0xee300b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10940 {"fmuld", 0xee200b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10941 {"fdivd", 0xee800b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10942 {"fmacd", 0xee000b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10943 {"fmscd", 0xee100b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10944 {"fnmuld", 0xee200b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10945 {"fnmacd", 0xee000b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10946 {"fnmscd", 0xee100b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10947
10948 /* Comparisons. */
10949 {"fcmpd", 0xeeb40b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10950 {"fcmpzd", 0xeeb50b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_compare_z},
10951 {"fcmped", 0xeeb40bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10952 {"fcmpezd", 0xeeb50bc0, 7, FPU_VFP_EXT_V1, do_vfp_dp_compare_z},
10953
10954 /* VFP V2. */
10955 {"fmsrr", 0xec400a10, 5, FPU_VFP_EXT_V2, do_vfp_sp2_from_reg2},
10956 {"fmrrs", 0xec500a10, 5, FPU_VFP_EXT_V2, do_vfp_reg2_from_sp2},
10957 {"fmdrr", 0xec400b10, 5, FPU_VFP_EXT_V2, do_vfp_dp_from_reg2},
10958 {"fmrrd", 0xec500b10, 5, FPU_VFP_EXT_V2, do_vfp_reg2_from_dp},
10959
10960 /* Intel XScale extensions to ARM V5 ISA. (All use CP0). */
10961 {"mia", 0xee200010, 3, ARM_CEXT_XSCALE, do_xsc_mia},
10962 {"miaph", 0xee280010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
10963 {"miabb", 0xee2c0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
10964 {"miabt", 0xee2d0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
10965 {"miatb", 0xee2e0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
10966 {"miatt", 0xee2f0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
10967 {"mar", 0xec400000, 3, ARM_CEXT_XSCALE, do_xsc_mar},
10968 {"mra", 0xec500000, 3, ARM_CEXT_XSCALE, do_xsc_mra},
10969
10970 /* Intel Wireless MMX technology instructions. */
10971 {"tandcb", 0xee130130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
10972 {"tandch", 0xee530130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
10973 {"tandcw", 0xee930130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
10974 {"tbcstb", 0xee400010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
10975 {"tbcsth", 0xee400050, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
10976 {"tbcstw", 0xee400090, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
10977 {"textrcb", 0xee130170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
10978 {"textrch", 0xee530170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
10979 {"textrcw", 0xee930170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
10980 {"textrmub", 0xee100070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10981 {"textrmuh", 0xee500070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10982 {"textrmuw", 0xee900070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10983 {"textrmsb", 0xee100078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10984 {"textrmsh", 0xee500078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10985 {"textrmsw", 0xee900078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10986 {"tinsrb", 0xee600010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
10987 {"tinsrh", 0xee600050, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
10988 {"tinsrw", 0xee600090, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
10989 {"tmcr", 0xee000110, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmcr},
10990 {"tmcrr", 0xec400000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_tmcrr},
10991 {"tmia", 0xee200010, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10992 {"tmiaph", 0xee280010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10993 {"tmiabb", 0xee2c0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10994 {"tmiabt", 0xee2d0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10995 {"tmiatb", 0xee2e0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10996 {"tmiatt", 0xee2f0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10997 {"tmovmskb", 0xee100030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
10998 {"tmovmskh", 0xee500030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
10999 {"tmovmskw", 0xee900030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
11000 {"tmrc", 0xee100110, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmrc},
11001 {"tmrrc", 0xec500000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_tmrrc},
11002 {"torcb", 0xee130150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
11003 {"torch", 0xee530150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
11004 {"torcw", 0xee930150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
11005 {"waccb", 0xee0001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11006 {"wacch", 0xee4001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11007 {"waccw", 0xee8001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11008 {"waddbss", 0xee300180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11009 {"waddb", 0xee000180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11010 {"waddbus", 0xee100180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11011 {"waddhss", 0xee700180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11012 {"waddh", 0xee400180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11013 {"waddhus", 0xee500180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11014 {"waddwss", 0xeeb00180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11015 {"waddw", 0xee800180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11016 {"waddwus", 0xee900180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11017 {"waligni", 0xee000020, 7, ARM_CEXT_IWMMXT, do_iwmmxt_waligni},
11018 {"walignr0", 0xee800020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11019 {"walignr1", 0xee900020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11020 {"walignr2", 0xeea00020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11021 {"walignr3", 0xeeb00020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11022 {"wand", 0xee200000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11023 {"wandn", 0xee300000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11024 {"wavg2b", 0xee800000, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11025 {"wavg2br", 0xee900000, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11026 {"wavg2h", 0xeec00000, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11027 {"wavg2hr", 0xeed00000, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11028 {"wcmpeqb", 0xee000060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11029 {"wcmpeqh", 0xee400060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11030 {"wcmpeqw", 0xee800060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11031 {"wcmpgtub", 0xee100060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11032 {"wcmpgtuh", 0xee500060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11033 {"wcmpgtuw", 0xee900060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11034 {"wcmpgtsb", 0xee300060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11035 {"wcmpgtsh", 0xee700060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11036 {"wcmpgtsw", 0xeeb00060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11037 {"wldrb", 0xec100000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
11038 {"wldrh", 0xec100100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
11039 {"wldrw", 0xec100200, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
11040 {"wldrd", 0xec100300, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
11041 {"wmacs", 0xee600100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11042 {"wmacsz", 0xee700100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11043 {"wmacu", 0xee400100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11044 {"wmacuz", 0xee500100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11045 {"wmadds", 0xeea00100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11046 {"wmaddu", 0xee800100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11047 {"wmaxsb", 0xee200160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11048 {"wmaxsh", 0xee600160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11049 {"wmaxsw", 0xeea00160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11050 {"wmaxub", 0xee000160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11051 {"wmaxuh", 0xee400160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11052 {"wmaxuw", 0xee800160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11053 {"wminsb", 0xee300160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11054 {"wminsh", 0xee700160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11055 {"wminsw", 0xeeb00160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11056 {"wminub", 0xee100160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11057 {"wminuh", 0xee500160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11058 {"wminuw", 0xee900160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11059 {"wmov", 0xee000000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wmov},
11060 {"wmulsm", 0xee300100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11061 {"wmulsl", 0xee200100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11062 {"wmulum", 0xee100100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11063 {"wmulul", 0xee000100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11064 {"wor", 0xee000000, 3, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11065 {"wpackhss", 0xee700080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11066 {"wpackhus", 0xee500080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11067 {"wpackwss", 0xeeb00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11068 {"wpackwus", 0xee900080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11069 {"wpackdss", 0xeef00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11070 {"wpackdus", 0xeed00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11071 {"wrorh", 0xee700040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11072 {"wrorhg", 0xee700148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11073 {"wrorw", 0xeeb00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11074 {"wrorwg", 0xeeb00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11075 {"wrord", 0xeef00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11076 {"wrordg", 0xeef00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11077 {"wsadb", 0xee000120, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11078 {"wsadbz", 0xee100120, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11079 {"wsadh", 0xee400120, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11080 {"wsadhz", 0xee500120, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11081 {"wshufh", 0xee0001e0, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wshufh},
11082 {"wsllh", 0xee500040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11083 {"wsllhg", 0xee500148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11084 {"wsllw", 0xee900040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11085 {"wsllwg", 0xee900148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11086 {"wslld", 0xeed00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11087 {"wslldg", 0xeed00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11088 {"wsrah", 0xee400040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11089 {"wsrahg", 0xee400148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11090 {"wsraw", 0xee800040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11091 {"wsrawg", 0xee800148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11092 {"wsrad", 0xeec00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11093 {"wsradg", 0xeec00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11094 {"wsrlh", 0xee600040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11095 {"wsrlhg", 0xee600148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11096 {"wsrlw", 0xeea00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11097 {"wsrlwg", 0xeea00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11098 {"wsrld", 0xeee00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11099 {"wsrldg", 0xeee00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11100 {"wstrb", 0xec000000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
11101 {"wstrh", 0xec000100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
11102 {"wstrw", 0xec000200, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
11103 {"wstrd", 0xec000300, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
11104 {"wsubbss", 0xee3001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11105 {"wsubb", 0xee0001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11106 {"wsubbus", 0xee1001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11107 {"wsubhss", 0xee7001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11108 {"wsubh", 0xee4001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11109 {"wsubhus", 0xee5001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11110 {"wsubwss", 0xeeb001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11111 {"wsubw", 0xee8001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11112 {"wsubwus", 0xee9001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11113 {"wunpckehub", 0xee0000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11114 {"wunpckehuh", 0xee4000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11115 {"wunpckehuw", 0xee8000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11116 {"wunpckehsb", 0xee2000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11117 {"wunpckehsh", 0xee6000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11118 {"wunpckehsw", 0xeea000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11119 {"wunpckihb", 0xee1000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11120 {"wunpckihh", 0xee5000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11121 {"wunpckihw", 0xee9000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11122 {"wunpckelub", 0xee0000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11123 {"wunpckeluh", 0xee4000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11124 {"wunpckeluw", 0xee8000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11125 {"wunpckelsb", 0xee2000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11126 {"wunpckelsh", 0xee6000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11127 {"wunpckelsw", 0xeea000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11128 {"wunpckilb", 0xee1000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11129 {"wunpckilh", 0xee5000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11130 {"wunpckilw", 0xee9000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11131 {"wxor", 0xee100000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11132 {"wzero", 0xee300000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wzero},
11133
11134 /* Cirrus Maverick instructions. */
11135 {"cfldrs", 0xec100400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_1},
11136 {"cfldrd", 0xec500400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_2},
11137 {"cfldr32", 0xec100500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_3},
11138 {"cfldr64", 0xec500500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_4},
11139 {"cfstrs", 0xec000400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_1},
11140 {"cfstrd", 0xec400400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_2},
11141 {"cfstr32", 0xec000500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_3},
11142 {"cfstr64", 0xec400500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_4},
11143 {"cfmvsr", 0xee000450, 6, ARM_CEXT_MAVERICK, do_mav_binops_2a},
11144 {"cfmvrs", 0xee100450, 6, ARM_CEXT_MAVERICK, do_mav_binops_1a},
11145 {"cfmvdlr", 0xee000410, 7, ARM_CEXT_MAVERICK, do_mav_binops_2b},
11146 {"cfmvrdl", 0xee100410, 7, ARM_CEXT_MAVERICK, do_mav_binops_1b},
11147 {"cfmvdhr", 0xee000430, 7, ARM_CEXT_MAVERICK, do_mav_binops_2b},
11148 {"cfmvrdh", 0xee100430, 7, ARM_CEXT_MAVERICK, do_mav_binops_1b},
11149 {"cfmv64lr", 0xee000510, 8, ARM_CEXT_MAVERICK, do_mav_binops_2c},
11150 {"cfmvr64l", 0xee100510, 8, ARM_CEXT_MAVERICK, do_mav_binops_1c},
11151 {"cfmv64hr", 0xee000530, 8, ARM_CEXT_MAVERICK, do_mav_binops_2c},
11152 {"cfmvr64h", 0xee100530, 8, ARM_CEXT_MAVERICK, do_mav_binops_1c},
11153 {"cfmval32", 0xee200440, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
11154 {"cfmv32al", 0xee100440, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
11155 {"cfmvam32", 0xee200460, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
11156 {"cfmv32am", 0xee100460, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
11157 {"cfmvah32", 0xee200480, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
11158 {"cfmv32ah", 0xee100480, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
11159 {"cfmva32", 0xee2004a0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3a},
11160 {"cfmv32a", 0xee1004a0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3b},
11161 {"cfmva64", 0xee2004c0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3c},
11162 {"cfmv64a", 0xee1004c0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3d},
11163 {"cfmvsc32", 0xee2004e0, 8, ARM_CEXT_MAVERICK, do_mav_dspsc_1},
11164 {"cfmv32sc", 0xee1004e0, 8, ARM_CEXT_MAVERICK, do_mav_dspsc_2},
11165 {"cfcpys", 0xee000400, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
11166 {"cfcpyd", 0xee000420, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
11167 {"cfcvtsd", 0xee000460, 7, ARM_CEXT_MAVERICK, do_mav_binops_1f},
11168 {"cfcvtds", 0xee000440, 7, ARM_CEXT_MAVERICK, do_mav_binops_1g},
11169 {"cfcvt32s", 0xee000480, 8, ARM_CEXT_MAVERICK, do_mav_binops_1h},
11170 {"cfcvt32d", 0xee0004a0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1i},
11171 {"cfcvt64s", 0xee0004c0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1j},
11172 {"cfcvt64d", 0xee0004e0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1k},
11173 {"cfcvts32", 0xee100580, 8, ARM_CEXT_MAVERICK, do_mav_binops_1l},
11174 {"cfcvtd32", 0xee1005a0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1m},
11175 {"cftruncs32", 0xee1005c0, 10, ARM_CEXT_MAVERICK, do_mav_binops_1l},
11176 {"cftruncd32", 0xee1005e0, 10, ARM_CEXT_MAVERICK, do_mav_binops_1m},
11177 {"cfrshl32", 0xee000550, 8, ARM_CEXT_MAVERICK, do_mav_triple_4a},
11178 {"cfrshl64", 0xee000570, 8, ARM_CEXT_MAVERICK, do_mav_triple_4b},
11179 {"cfsh32", 0xee000500, 6, ARM_CEXT_MAVERICK, do_mav_shift_1},
11180 {"cfsh64", 0xee200500, 6, ARM_CEXT_MAVERICK, do_mav_shift_2},
11181 {"cfcmps", 0xee100490, 6, ARM_CEXT_MAVERICK, do_mav_triple_5a},
11182 {"cfcmpd", 0xee1004b0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5b},
11183 {"cfcmp32", 0xee100590, 7, ARM_CEXT_MAVERICK, do_mav_triple_5c},
11184 {"cfcmp64", 0xee1005b0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5d},
11185 {"cfabss", 0xee300400, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
11186 {"cfabsd", 0xee300420, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
11187 {"cfnegs", 0xee300440, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
11188 {"cfnegd", 0xee300460, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
11189 {"cfadds", 0xee300480, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
11190 {"cfaddd", 0xee3004a0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
11191 {"cfsubs", 0xee3004c0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
11192 {"cfsubd", 0xee3004e0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
11193 {"cfmuls", 0xee100400, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
11194 {"cfmuld", 0xee100420, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
11195 {"cfabs32", 0xee300500, 7, ARM_CEXT_MAVERICK, do_mav_binops_1n},
11196 {"cfabs64", 0xee300520, 7, ARM_CEXT_MAVERICK, do_mav_binops_1o},
11197 {"cfneg32", 0xee300540, 7, ARM_CEXT_MAVERICK, do_mav_binops_1n},
11198 {"cfneg64", 0xee300560, 7, ARM_CEXT_MAVERICK, do_mav_binops_1o},
11199 {"cfadd32", 0xee300580, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
11200 {"cfadd64", 0xee3005a0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
11201 {"cfsub32", 0xee3005c0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
11202 {"cfsub64", 0xee3005e0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
11203 {"cfmul32", 0xee100500, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
11204 {"cfmul64", 0xee100520, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
11205 {"cfmac32", 0xee100540, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
11206 {"cfmsc32", 0xee100560, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
11207 {"cfmadd32", 0xee000600, 8, ARM_CEXT_MAVERICK, do_mav_quad_6a},
11208 {"cfmsub32", 0xee100600, 8, ARM_CEXT_MAVERICK, do_mav_quad_6a},
11209 {"cfmadda32", 0xee200600, 9, ARM_CEXT_MAVERICK, do_mav_quad_6b},
11210 {"cfmsuba32", 0xee300600, 9, ARM_CEXT_MAVERICK, do_mav_quad_6b},
11211 };
11212
11213 /* Iterate over the base tables to create the instruction patterns. */
11214
11215 static void
11216 build_arm_ops_hsh (void)
11217 {
11218 unsigned int i;
11219 unsigned int j;
11220 static struct obstack insn_obstack;
11221
11222 obstack_begin (&insn_obstack, 4000);
11223
11224 for (i = 0; i < sizeof (insns) / sizeof (struct asm_opcode); i++)
11225 {
11226 const struct asm_opcode *insn = insns + i;
11227
11228 if (insn->cond_offset != 0)
11229 {
11230 /* Insn supports conditional execution. Build the varaints
11231 and insert them in the hash table. */
11232 for (j = 0; j < sizeof (conds) / sizeof (struct asm_cond); j++)
11233 {
11234 unsigned len = strlen (insn->template);
11235 struct asm_opcode *new;
11236 char *template;
11237
11238 new = obstack_alloc (&insn_obstack, sizeof (struct asm_opcode));
11239 /* All condition codes are two characters. */
11240 template = obstack_alloc (&insn_obstack, len + 3);
11241
11242 strncpy (template, insn->template, insn->cond_offset);
11243 strcpy (template + insn->cond_offset, conds[j].template);
11244 if (len > insn->cond_offset)
11245 strcpy (template + insn->cond_offset + 2,
11246 insn->template + insn->cond_offset);
11247 new->template = template;
11248 new->cond_offset = 0;
11249 new->variant = insn->variant;
11250 new->parms = insn->parms;
11251 new->value = (insn->value & ~COND_MASK) | conds[j].value;
11252
11253 hash_insert (arm_ops_hsh, new->template, (PTR) new);
11254 }
11255 }
11256 /* Finally, insert the unconditional insn in the table directly;
11257 no need to build a copy. */
11258 hash_insert (arm_ops_hsh, insn->template, (PTR) insn);
11259 }
11260 }
11261
11262 \f
11263 static const struct thumb_opcode tinsns[] =
11264 {
11265 /* Thumb v1 (ARMv4T). */
11266 {"adc", 0x4140, 2, ARM_EXT_V4T, do_t_arit},
11267 {"add", 0x0000, 2, ARM_EXT_V4T, do_t_add},
11268 {"and", 0x4000, 2, ARM_EXT_V4T, do_t_arit},
11269 {"asr", 0x0000, 2, ARM_EXT_V4T, do_t_asr},
11270 {"b", T_OPCODE_BRANCH, 2, ARM_EXT_V4T, do_t_branch12},
11271 {"beq", 0xd0fe, 2, ARM_EXT_V4T, do_t_branch9},
11272 {"bne", 0xd1fe, 2, ARM_EXT_V4T, do_t_branch9},
11273 {"bcs", 0xd2fe, 2, ARM_EXT_V4T, do_t_branch9},
11274 {"bhs", 0xd2fe, 2, ARM_EXT_V4T, do_t_branch9},
11275 {"bcc", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
11276 {"bul", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
11277 {"blo", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
11278 {"bmi", 0xd4fe, 2, ARM_EXT_V4T, do_t_branch9},
11279 {"bpl", 0xd5fe, 2, ARM_EXT_V4T, do_t_branch9},
11280 {"bvs", 0xd6fe, 2, ARM_EXT_V4T, do_t_branch9},
11281 {"bvc", 0xd7fe, 2, ARM_EXT_V4T, do_t_branch9},
11282 {"bhi", 0xd8fe, 2, ARM_EXT_V4T, do_t_branch9},
11283 {"bls", 0xd9fe, 2, ARM_EXT_V4T, do_t_branch9},
11284 {"bge", 0xdafe, 2, ARM_EXT_V4T, do_t_branch9},
11285 {"blt", 0xdbfe, 2, ARM_EXT_V4T, do_t_branch9},
11286 {"bgt", 0xdcfe, 2, ARM_EXT_V4T, do_t_branch9},
11287 {"ble", 0xddfe, 2, ARM_EXT_V4T, do_t_branch9},
11288 {"bal", 0xdefe, 2, ARM_EXT_V4T, do_t_branch9},
11289 {"bic", 0x4380, 2, ARM_EXT_V4T, do_t_arit},
11290 {"bl", 0xf7fffffe, 4, ARM_EXT_V4T, do_t_branch23},
11291 {"bx", 0x4700, 2, ARM_EXT_V4T, do_t_bx},
11292 {"cmn", T_OPCODE_CMN, 2, ARM_EXT_V4T, do_t_arit},
11293 {"cmp", 0x0000, 2, ARM_EXT_V4T, do_t_compare},
11294 {"eor", 0x4040, 2, ARM_EXT_V4T, do_t_arit},
11295 {"ldmia", 0xc800, 2, ARM_EXT_V4T, do_t_ldmstm},
11296 {"ldr", 0x0000, 2, ARM_EXT_V4T, do_t_ldr},
11297 {"ldrb", 0x0000, 2, ARM_EXT_V4T, do_t_ldrb},
11298 {"ldrh", 0x0000, 2, ARM_EXT_V4T, do_t_ldrh},
11299 {"ldrsb", 0x5600, 2, ARM_EXT_V4T, do_t_lds},
11300 {"ldrsh", 0x5e00, 2, ARM_EXT_V4T, do_t_lds},
11301 {"ldsb", 0x5600, 2, ARM_EXT_V4T, do_t_lds},
11302 {"ldsh", 0x5e00, 2, ARM_EXT_V4T, do_t_lds},
11303 {"lsl", 0x0000, 2, ARM_EXT_V4T, do_t_lsl},
11304 {"lsr", 0x0000, 2, ARM_EXT_V4T, do_t_lsr},
11305 {"mov", 0x0000, 2, ARM_EXT_V4T, do_t_mov},
11306 {"mul", T_OPCODE_MUL, 2, ARM_EXT_V4T, do_t_arit},
11307 {"mvn", T_OPCODE_MVN, 2, ARM_EXT_V4T, do_t_arit},
11308 {"neg", T_OPCODE_NEG, 2, ARM_EXT_V4T, do_t_arit},
11309 {"orr", 0x4300, 2, ARM_EXT_V4T, do_t_arit},
11310 {"pop", 0xbc00, 2, ARM_EXT_V4T, do_t_push_pop},
11311 {"push", 0xb400, 2, ARM_EXT_V4T, do_t_push_pop},
11312 {"ror", 0x41c0, 2, ARM_EXT_V4T, do_t_arit},
11313 {"sbc", 0x4180, 2, ARM_EXT_V4T, do_t_arit},
11314 {"stmia", 0xc000, 2, ARM_EXT_V4T, do_t_ldmstm},
11315 {"str", 0x0000, 2, ARM_EXT_V4T, do_t_str},
11316 {"strb", 0x0000, 2, ARM_EXT_V4T, do_t_strb},
11317 {"strh", 0x0000, 2, ARM_EXT_V4T, do_t_strh},
11318 {"swi", 0xdf00, 2, ARM_EXT_V4T, do_t_swi},
11319 {"sub", 0x0000, 2, ARM_EXT_V4T, do_t_sub},
11320 {"tst", T_OPCODE_TST, 2, ARM_EXT_V4T, do_t_arit},
11321 /* Pseudo ops: */
11322 {"adr", 0x0000, 2, ARM_EXT_V4T, do_t_adr},
11323 {"nop", 0x46C0, 2, ARM_EXT_V4T, do_t_nop}, /* mov r8,r8 */
11324 /* Thumb v2 (ARMv5T). */
11325 {"blx", 0, 0, ARM_EXT_V5T, do_t_blx},
11326 {"bkpt", 0xbe00, 2, ARM_EXT_V5T, do_t_bkpt},
11327
11328 /* ARM V6. */
11329 {"cpsie", 0xb660, 2, ARM_EXT_V6, do_t_cps},
11330 {"cpsid", 0xb670, 2, ARM_EXT_V6, do_t_cps},
11331 {"cpy", 0x4600, 2, ARM_EXT_V6, do_t_cpy},
11332 {"rev", 0xba00, 2, ARM_EXT_V6, do_t_arit},
11333 {"rev16", 0xba40, 2, ARM_EXT_V6, do_t_arit},
11334 {"revsh", 0xbac0, 2, ARM_EXT_V6, do_t_arit},
11335 {"setend", 0xb650, 2, ARM_EXT_V6, do_t_setend},
11336 {"sxth", 0xb200, 2, ARM_EXT_V6, do_t_arit},
11337 {"sxtb", 0xb240, 2, ARM_EXT_V6, do_t_arit},
11338 {"uxth", 0xb280, 2, ARM_EXT_V6, do_t_arit},
11339 {"uxtb", 0xb2c0, 2, ARM_EXT_V6, do_t_arit},
11340
11341 /* ARM V6K. */
11342 {"sev", 0xbf40, 2, ARM_EXT_V6K, do_empty},
11343 {"wfe", 0xbf20, 2, ARM_EXT_V6K, do_empty},
11344 {"wfi", 0xbf30, 2, ARM_EXT_V6K, do_empty},
11345 {"yield", 0xbf10, 2, ARM_EXT_V6K, do_empty},
11346 };
11347
11348 void
11349 md_begin (void)
11350 {
11351 unsigned mach;
11352 unsigned int i;
11353
11354 if ( (arm_ops_hsh = hash_new ()) == NULL
11355 || (arm_tops_hsh = hash_new ()) == NULL
11356 || (arm_cond_hsh = hash_new ()) == NULL
11357 || (arm_shift_hsh = hash_new ()) == NULL
11358 || (arm_psr_hsh = hash_new ()) == NULL)
11359 as_fatal (_("virtual memory exhausted"));
11360
11361 build_arm_ops_hsh ();
11362 for (i = 0; i < sizeof (tinsns) / sizeof (struct thumb_opcode); i++)
11363 hash_insert (arm_tops_hsh, tinsns[i].template, (PTR) (tinsns + i));
11364 for (i = 0; i < sizeof (conds) / sizeof (struct asm_cond); i++)
11365 hash_insert (arm_cond_hsh, conds[i].template, (PTR) (conds + i));
11366 for (i = 0; i < sizeof (shift_names) / sizeof (struct asm_shift_name); i++)
11367 hash_insert (arm_shift_hsh, shift_names[i].name, (PTR) (shift_names + i));
11368 for (i = 0; i < sizeof (psrs) / sizeof (struct asm_psr); i++)
11369 hash_insert (arm_psr_hsh, psrs[i].template, (PTR) (psrs + i));
11370
11371 for (i = (int) REG_TYPE_FIRST; i < (int) REG_TYPE_MAX; i++)
11372 build_reg_hsh (all_reg_maps + i);
11373
11374 set_constant_flonums ();
11375
11376 /* Set the cpu variant based on the command-line options. We prefer
11377 -mcpu= over -march= if both are set (as for GCC); and we prefer
11378 -mfpu= over any other way of setting the floating point unit.
11379 Use of legacy options with new options are faulted. */
11380 if (legacy_cpu != -1)
11381 {
11382 if (mcpu_cpu_opt != -1 || march_cpu_opt != -1)
11383 as_bad (_("use of old and new-style options to set CPU type"));
11384
11385 mcpu_cpu_opt = legacy_cpu;
11386 }
11387 else if (mcpu_cpu_opt == -1)
11388 mcpu_cpu_opt = march_cpu_opt;
11389
11390 if (legacy_fpu != -1)
11391 {
11392 if (mfpu_opt != -1)
11393 as_bad (_("use of old and new-style options to set FPU type"));
11394
11395 mfpu_opt = legacy_fpu;
11396 }
11397 else if (mfpu_opt == -1)
11398 {
11399 #if !(defined (TE_LINUX) || defined (TE_NetBSD) || defined (TE_VXWORKS))
11400 /* Some environments specify a default FPU. If they don't, infer it
11401 from the processor. */
11402 if (mcpu_fpu_opt != -1)
11403 mfpu_opt = mcpu_fpu_opt;
11404 else
11405 mfpu_opt = march_fpu_opt;
11406 #else
11407 mfpu_opt = FPU_DEFAULT;
11408 #endif
11409 }
11410
11411 if (mfpu_opt == -1)
11412 {
11413 if (mcpu_cpu_opt == -1)
11414 mfpu_opt = FPU_DEFAULT;
11415 else if (mcpu_cpu_opt & ARM_EXT_V5)
11416 mfpu_opt = FPU_ARCH_VFP_V2;
11417 else
11418 mfpu_opt = FPU_ARCH_FPA;
11419 }
11420
11421 if (mcpu_cpu_opt == -1)
11422 mcpu_cpu_opt = CPU_DEFAULT;
11423
11424 cpu_variant = mcpu_cpu_opt | mfpu_opt;
11425
11426 #if defined OBJ_COFF || defined OBJ_ELF
11427 {
11428 unsigned int flags = 0;
11429
11430 #if defined OBJ_ELF
11431 flags = meabi_flags;
11432
11433 switch (meabi_flags)
11434 {
11435 case EF_ARM_EABI_UNKNOWN:
11436 #endif
11437 /* Set the flags in the private structure. */
11438 if (uses_apcs_26) flags |= F_APCS26;
11439 if (support_interwork) flags |= F_INTERWORK;
11440 if (uses_apcs_float) flags |= F_APCS_FLOAT;
11441 if (pic_code) flags |= F_PIC;
11442 if ((cpu_variant & FPU_ANY) == FPU_NONE
11443 || (cpu_variant & FPU_ANY) == FPU_ARCH_VFP) /* VFP layout only. */
11444 flags |= F_SOFT_FLOAT;
11445
11446 switch (mfloat_abi_opt)
11447 {
11448 case ARM_FLOAT_ABI_SOFT:
11449 case ARM_FLOAT_ABI_SOFTFP:
11450 flags |= F_SOFT_FLOAT;
11451 break;
11452
11453 case ARM_FLOAT_ABI_HARD:
11454 if (flags & F_SOFT_FLOAT)
11455 as_bad (_("hard-float conflicts with specified fpu"));
11456 break;
11457 }
11458
11459 /* Using VFP conventions (even if soft-float). */
11460 if (cpu_variant & FPU_VFP_EXT_NONE)
11461 flags |= F_VFP_FLOAT;
11462
11463 #if defined OBJ_ELF
11464 if (cpu_variant & FPU_ARCH_MAVERICK)
11465 flags |= EF_ARM_MAVERICK_FLOAT;
11466 break;
11467
11468 case EF_ARM_EABI_VER4:
11469 /* No additional flags to set. */
11470 break;
11471
11472 default:
11473 abort ();
11474 }
11475 #endif
11476 bfd_set_private_flags (stdoutput, flags);
11477
11478 /* We have run out flags in the COFF header to encode the
11479 status of ATPCS support, so instead we create a dummy,
11480 empty, debug section called .arm.atpcs. */
11481 if (atpcs)
11482 {
11483 asection * sec;
11484
11485 sec = bfd_make_section (stdoutput, ".arm.atpcs");
11486
11487 if (sec != NULL)
11488 {
11489 bfd_set_section_flags
11490 (stdoutput, sec, SEC_READONLY | SEC_DEBUGGING /* | SEC_HAS_CONTENTS */);
11491 bfd_set_section_size (stdoutput, sec, 0);
11492 bfd_set_section_contents (stdoutput, sec, NULL, 0, 0);
11493 }
11494 }
11495 }
11496 #endif
11497
11498 /* Record the CPU type as well. */
11499 switch (cpu_variant & ARM_CPU_MASK)
11500 {
11501 case ARM_2:
11502 mach = bfd_mach_arm_2;
11503 break;
11504
11505 case ARM_3: /* Also ARM_250. */
11506 mach = bfd_mach_arm_2a;
11507 break;
11508
11509 case ARM_6: /* Also ARM_7. */
11510 mach = bfd_mach_arm_3;
11511 break;
11512
11513 default:
11514 mach = bfd_mach_arm_unknown;
11515 break;
11516 }
11517
11518 /* Catch special cases. */
11519 if (cpu_variant & ARM_CEXT_IWMMXT)
11520 mach = bfd_mach_arm_iWMMXt;
11521 else if (cpu_variant & ARM_CEXT_XSCALE)
11522 mach = bfd_mach_arm_XScale;
11523 else if (cpu_variant & ARM_CEXT_MAVERICK)
11524 mach = bfd_mach_arm_ep9312;
11525 else if (cpu_variant & ARM_EXT_V5E)
11526 mach = bfd_mach_arm_5TE;
11527 else if (cpu_variant & ARM_EXT_V5)
11528 {
11529 if (cpu_variant & ARM_EXT_V4T)
11530 mach = bfd_mach_arm_5T;
11531 else
11532 mach = bfd_mach_arm_5;
11533 }
11534 else if (cpu_variant & ARM_EXT_V4)
11535 {
11536 if (cpu_variant & ARM_EXT_V4T)
11537 mach = bfd_mach_arm_4T;
11538 else
11539 mach = bfd_mach_arm_4;
11540 }
11541 else if (cpu_variant & ARM_EXT_V3M)
11542 mach = bfd_mach_arm_3M;
11543
11544 bfd_set_arch_mach (stdoutput, TARGET_ARCH, mach);
11545 }
11546
11547 /* Turn an integer of n bytes (in val) into a stream of bytes appropriate
11548 for use in the a.out file, and stores them in the array pointed to by buf.
11549 This knows about the endian-ness of the target machine and does
11550 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
11551 2 (short) and 4 (long) Floating numbers are put out as a series of
11552 LITTLENUMS (shorts, here at least). */
11553
11554 void
11555 md_number_to_chars (char * buf, valueT val, int n)
11556 {
11557 if (target_big_endian)
11558 number_to_chars_bigendian (buf, val, n);
11559 else
11560 number_to_chars_littleendian (buf, val, n);
11561 }
11562
11563 static valueT
11564 md_chars_to_number (char * buf, int n)
11565 {
11566 valueT result = 0;
11567 unsigned char * where = (unsigned char *) buf;
11568
11569 if (target_big_endian)
11570 {
11571 while (n--)
11572 {
11573 result <<= 8;
11574 result |= (*where++ & 255);
11575 }
11576 }
11577 else
11578 {
11579 while (n--)
11580 {
11581 result <<= 8;
11582 result |= (where[n] & 255);
11583 }
11584 }
11585
11586 return result;
11587 }
11588
11589 /* Turn a string in input_line_pointer into a floating point constant
11590 of type TYPE, and store the appropriate bytes in *LITP. The number
11591 of LITTLENUMS emitted is stored in *SIZEP. An error message is
11592 returned, or NULL on OK.
11593
11594 Note that fp constants aren't represent in the normal way on the ARM.
11595 In big endian mode, things are as expected. However, in little endian
11596 mode fp constants are big-endian word-wise, and little-endian byte-wise
11597 within the words. For example, (double) 1.1 in big endian mode is
11598 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
11599 the byte sequence 99 99 f1 3f 9a 99 99 99.
11600
11601 ??? The format of 12 byte floats is uncertain according to gcc's arm.h. */
11602
11603 char *
11604 md_atof (int type, char * litP, int * sizeP)
11605 {
11606 int prec;
11607 LITTLENUM_TYPE words[MAX_LITTLENUMS];
11608 char *t;
11609 int i;
11610
11611 switch (type)
11612 {
11613 case 'f':
11614 case 'F':
11615 case 's':
11616 case 'S':
11617 prec = 2;
11618 break;
11619
11620 case 'd':
11621 case 'D':
11622 case 'r':
11623 case 'R':
11624 prec = 4;
11625 break;
11626
11627 case 'x':
11628 case 'X':
11629 prec = 6;
11630 break;
11631
11632 case 'p':
11633 case 'P':
11634 prec = 6;
11635 break;
11636
11637 default:
11638 *sizeP = 0;
11639 return _("bad call to MD_ATOF()");
11640 }
11641
11642 t = atof_ieee (input_line_pointer, type, words);
11643 if (t)
11644 input_line_pointer = t;
11645 *sizeP = prec * 2;
11646
11647 if (target_big_endian)
11648 {
11649 for (i = 0; i < prec; i++)
11650 {
11651 md_number_to_chars (litP, (valueT) words[i], 2);
11652 litP += 2;
11653 }
11654 }
11655 else
11656 {
11657 if (cpu_variant & FPU_ARCH_VFP)
11658 for (i = prec - 1; i >= 0; i--)
11659 {
11660 md_number_to_chars (litP, (valueT) words[i], 2);
11661 litP += 2;
11662 }
11663 else
11664 /* For a 4 byte float the order of elements in `words' is 1 0.
11665 For an 8 byte float the order is 1 0 3 2. */
11666 for (i = 0; i < prec; i += 2)
11667 {
11668 md_number_to_chars (litP, (valueT) words[i + 1], 2);
11669 md_number_to_chars (litP + 2, (valueT) words[i], 2);
11670 litP += 4;
11671 }
11672 }
11673
11674 return 0;
11675 }
11676
11677 /* The knowledge of the PC's pipeline offset is built into the insns
11678 themselves. */
11679
11680 long
11681 md_pcrel_from (fixS * fixP)
11682 {
11683 if (fixP->fx_addsy
11684 && S_GET_SEGMENT (fixP->fx_addsy) == undefined_section
11685 && fixP->fx_subsy == NULL)
11686 return 0;
11687
11688 if (fixP->fx_pcrel && (fixP->fx_r_type == BFD_RELOC_ARM_THUMB_ADD))
11689 {
11690 /* PC relative addressing on the Thumb is slightly odd
11691 as the bottom two bits of the PC are forced to zero
11692 for the calculation. */
11693 return (fixP->fx_where + fixP->fx_frag->fr_address) & ~3;
11694 }
11695
11696 #ifdef TE_WINCE
11697 /* The pattern was adjusted to accommodate CE's off-by-one fixups,
11698 so we un-adjust here to compensate for the accommodation. */
11699 return fixP->fx_where + fixP->fx_frag->fr_address + 8;
11700 #else
11701 return fixP->fx_where + fixP->fx_frag->fr_address;
11702 #endif
11703 }
11704
11705 /* Round up a section size to the appropriate boundary. */
11706
11707 valueT
11708 md_section_align (segT segment ATTRIBUTE_UNUSED,
11709 valueT size)
11710 {
11711 #ifdef OBJ_ELF
11712 return size;
11713 #else
11714 /* Round all sects to multiple of 4. */
11715 return (size + 3) & ~3;
11716 #endif
11717 }
11718
11719 /* Under ELF we need to default _GLOBAL_OFFSET_TABLE.
11720 Otherwise we have no need to default values of symbols. */
11721
11722 symbolS *
11723 md_undefined_symbol (char * name ATTRIBUTE_UNUSED)
11724 {
11725 #ifdef OBJ_ELF
11726 if (name[0] == '_' && name[1] == 'G'
11727 && streq (name, GLOBAL_OFFSET_TABLE_NAME))
11728 {
11729 if (!GOT_symbol)
11730 {
11731 if (symbol_find (name))
11732 as_bad ("GOT already in the symbol table");
11733
11734 GOT_symbol = symbol_new (name, undefined_section,
11735 (valueT) 0, & zero_address_frag);
11736 }
11737
11738 return GOT_symbol;
11739 }
11740 #endif
11741
11742 return 0;
11743 }
11744
11745 void
11746 md_apply_fix3 (fixS * fixP,
11747 valueT * valP,
11748 segT seg)
11749 {
11750 offsetT value = * valP;
11751 offsetT newval;
11752 unsigned int newimm;
11753 unsigned long temp;
11754 int sign;
11755 char * buf = fixP->fx_where + fixP->fx_frag->fr_literal;
11756 arm_fix_data * arm_data = (arm_fix_data *) fixP->tc_fix_data;
11757
11758 assert (fixP->fx_r_type <= BFD_RELOC_UNUSED);
11759
11760 /* Note whether this will delete the relocation. */
11761 if (fixP->fx_addsy == 0 && !fixP->fx_pcrel)
11762 fixP->fx_done = 1;
11763
11764 /* If this symbol is in a different section then we need to leave it for
11765 the linker to deal with. Unfortunately, md_pcrel_from can't tell,
11766 so we have to undo it's effects here. */
11767 if (fixP->fx_pcrel)
11768 {
11769 if (fixP->fx_addsy != NULL
11770 && S_IS_DEFINED (fixP->fx_addsy)
11771 && S_GET_SEGMENT (fixP->fx_addsy) != seg)
11772 value += md_pcrel_from (fixP);
11773 }
11774
11775 /* Remember value for emit_reloc. */
11776 fixP->fx_addnumber = value;
11777
11778 switch (fixP->fx_r_type)
11779 {
11780 case BFD_RELOC_NONE:
11781 /* This will need to go in the object file. */
11782 fixP->fx_done = 0;
11783 break;
11784
11785 case BFD_RELOC_ARM_IMMEDIATE:
11786 /* We claim that this fixup has been processed here,
11787 even if in fact we generate an error because we do
11788 not have a reloc for it, so tc_gen_reloc will reject it. */
11789 fixP->fx_done = 1;
11790
11791 if (fixP->fx_addsy
11792 && ! S_IS_DEFINED (fixP->fx_addsy))
11793 {
11794 as_bad_where (fixP->fx_file, fixP->fx_line,
11795 _("undefined symbol %s used as an immediate value"),
11796 S_GET_NAME (fixP->fx_addsy));
11797 break;
11798 }
11799
11800 newimm = validate_immediate (value);
11801 temp = md_chars_to_number (buf, INSN_SIZE);
11802
11803 /* If the instruction will fail, see if we can fix things up by
11804 changing the opcode. */
11805 if (newimm == (unsigned int) FAIL
11806 && (newimm = negate_data_op (&temp, value)) == (unsigned int) FAIL)
11807 {
11808 as_bad_where (fixP->fx_file, fixP->fx_line,
11809 _("invalid constant (%lx) after fixup"),
11810 (unsigned long) value);
11811 break;
11812 }
11813
11814 newimm |= (temp & 0xfffff000);
11815 md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
11816 break;
11817
11818 case BFD_RELOC_ARM_ADRL_IMMEDIATE:
11819 {
11820 unsigned int highpart = 0;
11821 unsigned int newinsn = 0xe1a00000; /* nop. */
11822
11823 newimm = validate_immediate (value);
11824 temp = md_chars_to_number (buf, INSN_SIZE);
11825
11826 /* If the instruction will fail, see if we can fix things up by
11827 changing the opcode. */
11828 if (newimm == (unsigned int) FAIL
11829 && (newimm = negate_data_op (& temp, value)) == (unsigned int) FAIL)
11830 {
11831 /* No ? OK - try using two ADD instructions to generate
11832 the value. */
11833 newimm = validate_immediate_twopart (value, & highpart);
11834
11835 /* Yes - then make sure that the second instruction is
11836 also an add. */
11837 if (newimm != (unsigned int) FAIL)
11838 newinsn = temp;
11839 /* Still No ? Try using a negated value. */
11840 else if ((newimm = validate_immediate_twopart (- value, & highpart)) != (unsigned int) FAIL)
11841 temp = newinsn = (temp & OPCODE_MASK) | OPCODE_SUB << DATA_OP_SHIFT;
11842 /* Otherwise - give up. */
11843 else
11844 {
11845 as_bad_where (fixP->fx_file, fixP->fx_line,
11846 _("unable to compute ADRL instructions for PC offset of 0x%lx"),
11847 (long) value);
11848 break;
11849 }
11850
11851 /* Replace the first operand in the 2nd instruction (which
11852 is the PC) with the destination register. We have
11853 already added in the PC in the first instruction and we
11854 do not want to do it again. */
11855 newinsn &= ~ 0xf0000;
11856 newinsn |= ((newinsn & 0x0f000) << 4);
11857 }
11858
11859 newimm |= (temp & 0xfffff000);
11860 md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
11861
11862 highpart |= (newinsn & 0xfffff000);
11863 md_number_to_chars (buf + INSN_SIZE, (valueT) highpart, INSN_SIZE);
11864 }
11865 break;
11866
11867 case BFD_RELOC_ARM_OFFSET_IMM:
11868 sign = value >= 0;
11869
11870 if (value < 0)
11871 value = - value;
11872
11873 if (validate_offset_imm (value, 0) == FAIL)
11874 {
11875 as_bad_where (fixP->fx_file, fixP->fx_line,
11876 _("bad immediate value for offset (%ld)"),
11877 (long) value);
11878 break;
11879 }
11880
11881 newval = md_chars_to_number (buf, INSN_SIZE);
11882 newval &= 0xff7ff000;
11883 newval |= value | (sign ? INDEX_UP : 0);
11884 md_number_to_chars (buf, newval, INSN_SIZE);
11885 break;
11886
11887 case BFD_RELOC_ARM_OFFSET_IMM8:
11888 case BFD_RELOC_ARM_HWLITERAL:
11889 sign = value >= 0;
11890
11891 if (value < 0)
11892 value = - value;
11893
11894 if (validate_offset_imm (value, 1) == FAIL)
11895 {
11896 if (fixP->fx_r_type == BFD_RELOC_ARM_HWLITERAL)
11897 as_bad_where (fixP->fx_file, fixP->fx_line,
11898 _("invalid literal constant: pool needs to be closer"));
11899 else
11900 as_bad (_("bad immediate value for half-word offset (%ld)"),
11901 (long) value);
11902 break;
11903 }
11904
11905 newval = md_chars_to_number (buf, INSN_SIZE);
11906 newval &= 0xff7ff0f0;
11907 newval |= ((value >> 4) << 8) | (value & 0xf) | (sign ? INDEX_UP : 0);
11908 md_number_to_chars (buf, newval, INSN_SIZE);
11909 break;
11910
11911 case BFD_RELOC_ARM_LITERAL:
11912 sign = value >= 0;
11913
11914 if (value < 0)
11915 value = - value;
11916
11917 if (validate_offset_imm (value, 0) == FAIL)
11918 {
11919 as_bad_where (fixP->fx_file, fixP->fx_line,
11920 _("invalid literal constant: pool needs to be closer"));
11921 break;
11922 }
11923
11924 newval = md_chars_to_number (buf, INSN_SIZE);
11925 newval &= 0xff7ff000;
11926 newval |= value | (sign ? INDEX_UP : 0);
11927 md_number_to_chars (buf, newval, INSN_SIZE);
11928 break;
11929
11930 case BFD_RELOC_ARM_SHIFT_IMM:
11931 newval = md_chars_to_number (buf, INSN_SIZE);
11932 if (((unsigned long) value) > 32
11933 || (value == 32
11934 && (((newval & 0x60) == 0) || (newval & 0x60) == 0x60)))
11935 {
11936 as_bad_where (fixP->fx_file, fixP->fx_line,
11937 _("shift expression is too large"));
11938 break;
11939 }
11940
11941 if (value == 0)
11942 /* Shifts of zero must be done as lsl. */
11943 newval &= ~0x60;
11944 else if (value == 32)
11945 value = 0;
11946 newval &= 0xfffff07f;
11947 newval |= (value & 0x1f) << 7;
11948 md_number_to_chars (buf, newval, INSN_SIZE);
11949 break;
11950
11951 case BFD_RELOC_ARM_SMI:
11952 if (((unsigned long) value) > 0xffff)
11953 as_bad_where (fixP->fx_file, fixP->fx_line,
11954 _("invalid smi expression"));
11955 newval = md_chars_to_number (buf, INSN_SIZE) & 0xfff000f0;
11956 newval |= (value & 0xf) | ((value & 0xfff0) << 4);
11957 md_number_to_chars (buf, newval, INSN_SIZE);
11958 break;
11959
11960 case BFD_RELOC_ARM_SWI:
11961 if (arm_data->thumb_mode)
11962 {
11963 if (((unsigned long) value) > 0xff)
11964 as_bad_where (fixP->fx_file, fixP->fx_line,
11965 _("invalid swi expression"));
11966 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xff00;
11967 newval |= value;
11968 md_number_to_chars (buf, newval, THUMB_SIZE);
11969 }
11970 else
11971 {
11972 if (((unsigned long) value) > 0x00ffffff)
11973 as_bad_where (fixP->fx_file, fixP->fx_line,
11974 _("invalid swi expression"));
11975 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff000000;
11976 newval |= value;
11977 md_number_to_chars (buf, newval, INSN_SIZE);
11978 }
11979 break;
11980
11981 case BFD_RELOC_ARM_MULTI:
11982 if (((unsigned long) value) > 0xffff)
11983 as_bad_where (fixP->fx_file, fixP->fx_line,
11984 _("invalid expression in load/store multiple"));
11985 newval = value | md_chars_to_number (buf, INSN_SIZE);
11986 md_number_to_chars (buf, newval, INSN_SIZE);
11987 break;
11988
11989 case BFD_RELOC_ARM_PCREL_BRANCH:
11990 newval = md_chars_to_number (buf, INSN_SIZE);
11991
11992 /* Sign-extend a 24-bit number. */
11993 #define SEXT24(x) ((((x) & 0xffffff) ^ (~ 0x7fffff)) + 0x800000)
11994
11995 #ifdef OBJ_ELF
11996 value = fixP->fx_offset;
11997 #endif
11998
11999 /* We are going to store value (shifted right by two) in the
12000 instruction, in a 24 bit, signed field. Thus we need to check
12001 that none of the top 8 bits of the shifted value (top 7 bits of
12002 the unshifted, unsigned value) are set, or that they are all set. */
12003 if ((value & ~ ((offsetT) 0x1ffffff)) != 0
12004 && ((value & ~ ((offsetT) 0x1ffffff)) != ~ ((offsetT) 0x1ffffff)))
12005 {
12006 #ifdef OBJ_ELF
12007 /* Normally we would be stuck at this point, since we cannot store
12008 the absolute address that is the destination of the branch in the
12009 24 bits of the branch instruction. If however, we happen to know
12010 that the destination of the branch is in the same section as the
12011 branch instruction itself, then we can compute the relocation for
12012 ourselves and not have to bother the linker with it.
12013
12014 FIXME: The test for OBJ_ELF is only here because I have not
12015 worked out how to do this for OBJ_COFF. */
12016 if (fixP->fx_addsy != NULL
12017 && S_IS_DEFINED (fixP->fx_addsy)
12018 && S_GET_SEGMENT (fixP->fx_addsy) == seg)
12019 {
12020 /* Get pc relative value to go into the branch. */
12021 value = * valP;
12022
12023 /* Permit a backward branch provided that enough bits
12024 are set. Allow a forwards branch, provided that
12025 enough bits are clear. */
12026 if ( (value & ~ ((offsetT) 0x1ffffff)) == ~ ((offsetT) 0x1ffffff)
12027 || (value & ~ ((offsetT) 0x1ffffff)) == 0)
12028 fixP->fx_done = 1;
12029 }
12030
12031 if (! fixP->fx_done)
12032 #endif
12033 as_bad_where (fixP->fx_file, fixP->fx_line,
12034 _("GAS can't handle same-section branch dest >= 0x04000000"));
12035 }
12036
12037 value >>= 2;
12038 value += SEXT24 (newval);
12039
12040 if ( (value & ~ ((offsetT) 0xffffff)) != 0
12041 && ((value & ~ ((offsetT) 0xffffff)) != ~ ((offsetT) 0xffffff)))
12042 as_bad_where (fixP->fx_file, fixP->fx_line,
12043 _("out of range branch"));
12044
12045 if (seg->use_rela_p && !fixP->fx_done)
12046 {
12047 /* Must unshift the value before storing it in the addend. */
12048 value <<= 2;
12049 #ifdef OBJ_ELF
12050 fixP->fx_offset = value;
12051 #endif
12052 fixP->fx_addnumber = value;
12053 newval = newval & 0xff000000;
12054 }
12055 else
12056 newval = (value & 0x00ffffff) | (newval & 0xff000000);
12057 md_number_to_chars (buf, newval, INSN_SIZE);
12058 break;
12059
12060 case BFD_RELOC_ARM_PCREL_BLX:
12061 {
12062 offsetT hbit;
12063 newval = md_chars_to_number (buf, INSN_SIZE);
12064
12065 #ifdef OBJ_ELF
12066 value = fixP->fx_offset;
12067 #endif
12068 hbit = (value >> 1) & 1;
12069 value = (value >> 2) & 0x00ffffff;
12070 value = (value + (newval & 0x00ffffff)) & 0x00ffffff;
12071
12072 if (seg->use_rela_p && !fixP->fx_done)
12073 {
12074 /* Must sign-extend and unshift the value before storing
12075 it in the addend. */
12076 value = SEXT24 (value);
12077 value = (value << 2) | hbit;
12078 #ifdef OBJ_ELF
12079 fixP->fx_offset = value;
12080 #endif
12081 fixP->fx_addnumber = value;
12082 newval = newval & 0xfe000000;
12083 }
12084 else
12085 newval = value | (newval & 0xfe000000) | (hbit << 24);
12086 md_number_to_chars (buf, newval, INSN_SIZE);
12087 }
12088 break;
12089
12090 case BFD_RELOC_THUMB_PCREL_BRANCH9: /* Conditional branch. */
12091 newval = md_chars_to_number (buf, THUMB_SIZE);
12092 {
12093 addressT diff = (newval & 0xff) << 1;
12094 if (diff & 0x100)
12095 diff |= ~0xff;
12096
12097 value += diff;
12098 if ((value & ~0xff) && ((value & ~0xff) != ~0xff))
12099 as_bad_where (fixP->fx_file, fixP->fx_line,
12100 _("branch out of range"));
12101 if (seg->use_rela_p && !fixP->fx_done)
12102 {
12103 #ifdef OBJ_ELF
12104 fixP->fx_offset = value;
12105 #endif
12106 fixP->fx_addnumber = value;
12107 newval = newval & 0xff00;
12108 }
12109 else
12110 newval = (newval & 0xff00) | ((value & 0x1ff) >> 1);
12111 }
12112 md_number_to_chars (buf, newval, THUMB_SIZE);
12113 break;
12114
12115 case BFD_RELOC_THUMB_PCREL_BRANCH12: /* Unconditional branch. */
12116 newval = md_chars_to_number (buf, THUMB_SIZE);
12117 {
12118 addressT diff = (newval & 0x7ff) << 1;
12119 if (diff & 0x800)
12120 diff |= ~0x7ff;
12121
12122 value += diff;
12123 if ((value & ~0x7ff) && ((value & ~0x7ff) != ~0x7ff))
12124 as_bad_where (fixP->fx_file, fixP->fx_line,
12125 _("branch out of range"));
12126 if (seg->use_rela_p && !fixP->fx_done)
12127 {
12128 #ifdef OBJ_ELF
12129 fixP->fx_offset = value;
12130 #endif
12131 fixP->fx_addnumber = value;
12132 newval = newval & 0xf800;
12133 }
12134 else
12135 newval = (newval & 0xf800) | ((value & 0xfff) >> 1);
12136 }
12137 md_number_to_chars (buf, newval, THUMB_SIZE);
12138 break;
12139
12140 case BFD_RELOC_THUMB_PCREL_BLX:
12141 case BFD_RELOC_THUMB_PCREL_BRANCH23:
12142 {
12143 offsetT newval2;
12144 addressT diff;
12145
12146 newval = md_chars_to_number (buf, THUMB_SIZE);
12147 newval2 = md_chars_to_number (buf + THUMB_SIZE, THUMB_SIZE);
12148 diff = ((newval & 0x7ff) << 12) | ((newval2 & 0x7ff) << 1);
12149 if (diff & 0x400000)
12150 diff |= ~0x3fffff;
12151 #ifdef OBJ_ELF
12152 value = fixP->fx_offset;
12153 #endif
12154 value += diff;
12155
12156 if ((value & ~0x3fffff) && ((value & ~0x3fffff) != ~0x3fffff))
12157 as_bad_where (fixP->fx_file, fixP->fx_line,
12158 _("branch with link out of range"));
12159
12160 if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX)
12161 /* For a BLX instruction, make sure that the relocation is rounded up
12162 to a word boundary. This follows the semantics of the instruction
12163 which specifies that bit 1 of the target address will come from bit
12164 1 of the base address. */
12165 value = (value + 1) & ~ 1;
12166
12167 if (seg->use_rela_p && !fixP->fx_done)
12168 {
12169 #ifdef OBJ_ELF
12170 fixP->fx_offset = value;
12171 #endif
12172 fixP->fx_addnumber = value;
12173 newval = newval & 0xf800;
12174 newval2 = newval2 & 0xf800;
12175 }
12176 else
12177 {
12178 newval = (newval & 0xf800) | ((value & 0x7fffff) >> 12);
12179 newval2 = (newval2 & 0xf800) | ((value & 0xfff) >> 1);
12180 }
12181 md_number_to_chars (buf, newval, THUMB_SIZE);
12182 md_number_to_chars (buf + THUMB_SIZE, newval2, THUMB_SIZE);
12183 }
12184 break;
12185
12186 case BFD_RELOC_8:
12187 if (seg->use_rela_p && !fixP->fx_done)
12188 break;
12189 if (fixP->fx_done || fixP->fx_pcrel)
12190 md_number_to_chars (buf, value, 1);
12191 #ifdef OBJ_ELF
12192 else
12193 {
12194 value = fixP->fx_offset;
12195 md_number_to_chars (buf, value, 1);
12196 }
12197 #endif
12198 break;
12199
12200 case BFD_RELOC_16:
12201 if (seg->use_rela_p && !fixP->fx_done)
12202 break;
12203 if (fixP->fx_done || fixP->fx_pcrel)
12204 md_number_to_chars (buf, value, 2);
12205 #ifdef OBJ_ELF
12206 else
12207 {
12208 value = fixP->fx_offset;
12209 md_number_to_chars (buf, value, 2);
12210 }
12211 #endif
12212 break;
12213
12214 #ifdef OBJ_ELF
12215 case BFD_RELOC_ARM_GOT32:
12216 case BFD_RELOC_ARM_GOTOFF:
12217 case BFD_RELOC_ARM_TARGET2:
12218 if (seg->use_rela_p && !fixP->fx_done)
12219 break;
12220 md_number_to_chars (buf, 0, 4);
12221 break;
12222 #endif
12223
12224 case BFD_RELOC_RVA:
12225 case BFD_RELOC_32:
12226 case BFD_RELOC_ARM_TARGET1:
12227 case BFD_RELOC_ARM_ROSEGREL32:
12228 case BFD_RELOC_ARM_SBREL32:
12229 case BFD_RELOC_32_PCREL:
12230 if (seg->use_rela_p && !fixP->fx_done)
12231 break;
12232 if (fixP->fx_done || fixP->fx_pcrel)
12233 md_number_to_chars (buf, value, 4);
12234 #ifdef OBJ_ELF
12235 else
12236 {
12237 value = fixP->fx_offset;
12238 md_number_to_chars (buf, value, 4);
12239 }
12240 #endif
12241 break;
12242
12243 #ifdef OBJ_ELF
12244 case BFD_RELOC_ARM_PREL31:
12245 if (fixP->fx_done || fixP->fx_pcrel)
12246 {
12247 newval = md_chars_to_number (buf, 4) & 0x80000000;
12248 if ((value ^ (value >> 1)) & 0x40000000)
12249 {
12250 as_bad_where (fixP->fx_file, fixP->fx_line,
12251 _("rel31 relocation overflow"));
12252 }
12253 newval |= value & 0x7fffffff;
12254 md_number_to_chars (buf, newval, 4);
12255 }
12256 break;
12257
12258 case BFD_RELOC_ARM_PLT32:
12259 /* It appears the instruction is fully prepared at this point. */
12260 break;
12261 #endif
12262
12263 case BFD_RELOC_ARM_CP_OFF_IMM:
12264 sign = value >= 0;
12265 if (value < -1023 || value > 1023 || (value & 3))
12266 as_bad_where (fixP->fx_file, fixP->fx_line,
12267 _("illegal value for co-processor offset"));
12268 if (value < 0)
12269 value = -value;
12270 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
12271 newval |= (value >> 2) | (sign ? INDEX_UP : 0);
12272 md_number_to_chars (buf, newval, INSN_SIZE);
12273 break;
12274
12275 case BFD_RELOC_ARM_CP_OFF_IMM_S2:
12276 sign = value >= 0;
12277 if (value < -255 || value > 255)
12278 as_bad_where (fixP->fx_file, fixP->fx_line,
12279 _("Illegal value for co-processor offset"));
12280 if (value < 0)
12281 value = -value;
12282 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
12283 newval |= value | (sign ? INDEX_UP : 0);
12284 md_number_to_chars (buf, newval , INSN_SIZE);
12285 break;
12286
12287 case BFD_RELOC_ARM_THUMB_OFFSET:
12288 newval = md_chars_to_number (buf, THUMB_SIZE);
12289 /* Exactly what ranges, and where the offset is inserted depends
12290 on the type of instruction, we can establish this from the
12291 top 4 bits. */
12292 switch (newval >> 12)
12293 {
12294 case 4: /* PC load. */
12295 /* Thumb PC loads are somewhat odd, bit 1 of the PC is
12296 forced to zero for these loads, so we will need to round
12297 up the offset if the instruction address is not word
12298 aligned (since the final address produced must be, and
12299 we can only describe word-aligned immediate offsets). */
12300
12301 if ((fixP->fx_frag->fr_address + fixP->fx_where + value) & 3)
12302 as_bad_where (fixP->fx_file, fixP->fx_line,
12303 _("invalid offset, target not word aligned (0x%08X)"),
12304 (unsigned int) (fixP->fx_frag->fr_address
12305 + fixP->fx_where + value));
12306
12307 if ((value + 2) & ~0x3fe)
12308 as_bad_where (fixP->fx_file, fixP->fx_line,
12309 _("invalid offset, value too big (0x%08lX)"),
12310 (long) value);
12311
12312 /* Round up, since pc will be rounded down. */
12313 newval |= (value + 2) >> 2;
12314 break;
12315
12316 case 9: /* SP load/store. */
12317 if (value & ~0x3fc)
12318 as_bad_where (fixP->fx_file, fixP->fx_line,
12319 _("invalid offset, value too big (0x%08lX)"),
12320 (long) value);
12321 newval |= value >> 2;
12322 break;
12323
12324 case 6: /* Word load/store. */
12325 if (value & ~0x7c)
12326 as_bad_where (fixP->fx_file, fixP->fx_line,
12327 _("invalid offset, value too big (0x%08lX)"),
12328 (long) value);
12329 newval |= value << 4; /* 6 - 2. */
12330 break;
12331
12332 case 7: /* Byte load/store. */
12333 if (value & ~0x1f)
12334 as_bad_where (fixP->fx_file, fixP->fx_line,
12335 _("invalid offset, value too big (0x%08lX)"),
12336 (long) value);
12337 newval |= value << 6;
12338 break;
12339
12340 case 8: /* Halfword load/store. */
12341 if (value & ~0x3e)
12342 as_bad_where (fixP->fx_file, fixP->fx_line,
12343 _("invalid offset, value too big (0x%08lX)"),
12344 (long) value);
12345 newval |= value << 5; /* 6 - 1. */
12346 break;
12347
12348 default:
12349 as_bad_where (fixP->fx_file, fixP->fx_line,
12350 "Unable to process relocation for thumb opcode: %lx",
12351 (unsigned long) newval);
12352 break;
12353 }
12354 md_number_to_chars (buf, newval, THUMB_SIZE);
12355 break;
12356
12357 case BFD_RELOC_ARM_THUMB_ADD:
12358 /* This is a complicated relocation, since we use it for all of
12359 the following immediate relocations:
12360
12361 3bit ADD/SUB
12362 8bit ADD/SUB
12363 9bit ADD/SUB SP word-aligned
12364 10bit ADD PC/SP word-aligned
12365
12366 The type of instruction being processed is encoded in the
12367 instruction field:
12368
12369 0x8000 SUB
12370 0x00F0 Rd
12371 0x000F Rs
12372 */
12373 newval = md_chars_to_number (buf, THUMB_SIZE);
12374 {
12375 int rd = (newval >> 4) & 0xf;
12376 int rs = newval & 0xf;
12377 int subtract = newval & 0x8000;
12378
12379 if (rd == REG_SP)
12380 {
12381 if (value & ~0x1fc)
12382 as_bad_where (fixP->fx_file, fixP->fx_line,
12383 _("invalid immediate for stack address calculation"));
12384 newval = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
12385 newval |= value >> 2;
12386 }
12387 else if (rs == REG_PC || rs == REG_SP)
12388 {
12389 if (subtract ||
12390 value & ~0x3fc)
12391 as_bad_where (fixP->fx_file, fixP->fx_line,
12392 _("invalid immediate for address calculation (value = 0x%08lX)"),
12393 (unsigned long) value);
12394 newval = (rs == REG_PC ? T_OPCODE_ADD_PC : T_OPCODE_ADD_SP);
12395 newval |= rd << 8;
12396 newval |= value >> 2;
12397 }
12398 else if (rs == rd)
12399 {
12400 if (value & ~0xff)
12401 as_bad_where (fixP->fx_file, fixP->fx_line,
12402 _("invalid 8bit immediate"));
12403 newval = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
12404 newval |= (rd << 8) | value;
12405 }
12406 else
12407 {
12408 if (value & ~0x7)
12409 as_bad_where (fixP->fx_file, fixP->fx_line,
12410 _("invalid 3bit immediate"));
12411 newval = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
12412 newval |= rd | (rs << 3) | (value << 6);
12413 }
12414 }
12415 md_number_to_chars (buf, newval, THUMB_SIZE);
12416 break;
12417
12418 case BFD_RELOC_ARM_THUMB_IMM:
12419 newval = md_chars_to_number (buf, THUMB_SIZE);
12420 switch (newval >> 11)
12421 {
12422 case 0x04: /* 8bit immediate MOV. */
12423 case 0x05: /* 8bit immediate CMP. */
12424 if (value < 0 || value > 255)
12425 as_bad_where (fixP->fx_file, fixP->fx_line,
12426 _("invalid immediate: %ld is too large"),
12427 (long) value);
12428 newval |= value;
12429 break;
12430
12431 default:
12432 abort ();
12433 }
12434 md_number_to_chars (buf, newval, THUMB_SIZE);
12435 break;
12436
12437 case BFD_RELOC_ARM_THUMB_SHIFT:
12438 /* 5bit shift value (0..31). */
12439 if (value < 0 || value > 31)
12440 as_bad_where (fixP->fx_file, fixP->fx_line,
12441 _("illegal Thumb shift value: %ld"), (long) value);
12442 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xf03f;
12443 newval |= value << 6;
12444 md_number_to_chars (buf, newval, THUMB_SIZE);
12445 break;
12446
12447 case BFD_RELOC_VTABLE_INHERIT:
12448 case BFD_RELOC_VTABLE_ENTRY:
12449 fixP->fx_done = 0;
12450 return;
12451
12452 case BFD_RELOC_UNUSED:
12453 default:
12454 as_bad_where (fixP->fx_file, fixP->fx_line,
12455 _("bad relocation fixup type (%d)"), fixP->fx_r_type);
12456 }
12457 }
12458
12459 /* Translate internal representation of relocation info to BFD target
12460 format. */
12461
12462 arelent *
12463 tc_gen_reloc (asection * section ATTRIBUTE_UNUSED,
12464 fixS * fixp)
12465 {
12466 arelent * reloc;
12467 bfd_reloc_code_real_type code;
12468
12469 reloc = xmalloc (sizeof (arelent));
12470
12471 reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
12472 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
12473 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
12474
12475 /* @@ Why fx_addnumber sometimes and fx_offset other times? */
12476 #ifndef OBJ_ELF
12477 if (fixp->fx_pcrel == 0)
12478 reloc->addend = fixp->fx_offset;
12479 else
12480 reloc->addend = fixp->fx_offset = reloc->address;
12481 #else /* OBJ_ELF */
12482 reloc->addend = fixp->fx_offset;
12483 #endif
12484
12485 switch (fixp->fx_r_type)
12486 {
12487 case BFD_RELOC_8:
12488 if (fixp->fx_pcrel)
12489 {
12490 code = BFD_RELOC_8_PCREL;
12491 break;
12492 }
12493
12494 case BFD_RELOC_16:
12495 if (fixp->fx_pcrel)
12496 {
12497 code = BFD_RELOC_16_PCREL;
12498 break;
12499 }
12500
12501 case BFD_RELOC_32:
12502 if (fixp->fx_pcrel)
12503 {
12504 code = BFD_RELOC_32_PCREL;
12505 break;
12506 }
12507
12508 case BFD_RELOC_NONE:
12509 case BFD_RELOC_ARM_PCREL_BRANCH:
12510 case BFD_RELOC_ARM_PCREL_BLX:
12511 case BFD_RELOC_RVA:
12512 case BFD_RELOC_THUMB_PCREL_BRANCH9:
12513 case BFD_RELOC_THUMB_PCREL_BRANCH12:
12514 case BFD_RELOC_THUMB_PCREL_BRANCH23:
12515 case BFD_RELOC_THUMB_PCREL_BLX:
12516 case BFD_RELOC_VTABLE_ENTRY:
12517 case BFD_RELOC_VTABLE_INHERIT:
12518 code = fixp->fx_r_type;
12519 break;
12520
12521 case BFD_RELOC_ARM_LITERAL:
12522 case BFD_RELOC_ARM_HWLITERAL:
12523 /* If this is called then the a literal has
12524 been referenced across a section boundary. */
12525 as_bad_where (fixp->fx_file, fixp->fx_line,
12526 _("literal referenced across section boundary"));
12527 return NULL;
12528
12529 #ifdef OBJ_ELF
12530 case BFD_RELOC_ARM_GOT32:
12531 case BFD_RELOC_ARM_GOTOFF:
12532 case BFD_RELOC_ARM_PLT32:
12533 case BFD_RELOC_ARM_TARGET1:
12534 case BFD_RELOC_ARM_ROSEGREL32:
12535 case BFD_RELOC_ARM_SBREL32:
12536 case BFD_RELOC_ARM_PREL31:
12537 case BFD_RELOC_ARM_TARGET2:
12538 code = fixp->fx_r_type;
12539 break;
12540 #endif
12541
12542 case BFD_RELOC_ARM_IMMEDIATE:
12543 as_bad_where (fixp->fx_file, fixp->fx_line,
12544 _("internal relocation (type: IMMEDIATE) not fixed up"));
12545 return NULL;
12546
12547 case BFD_RELOC_ARM_ADRL_IMMEDIATE:
12548 as_bad_where (fixp->fx_file, fixp->fx_line,
12549 _("ADRL used for a symbol not defined in the same file"));
12550 return NULL;
12551
12552 case BFD_RELOC_ARM_OFFSET_IMM:
12553 if (fixp->fx_addsy != NULL
12554 && !S_IS_DEFINED (fixp->fx_addsy)
12555 && S_IS_LOCAL (fixp->fx_addsy))
12556 {
12557 as_bad_where (fixp->fx_file, fixp->fx_line,
12558 _("undefined local label `%s'"),
12559 S_GET_NAME (fixp->fx_addsy));
12560 return NULL;
12561 }
12562
12563 as_bad_where (fixp->fx_file, fixp->fx_line,
12564 _("internal_relocation (type: OFFSET_IMM) not fixed up"));
12565 return NULL;
12566
12567 default:
12568 {
12569 char * type;
12570
12571 switch (fixp->fx_r_type)
12572 {
12573 case BFD_RELOC_NONE: type = "NONE"; break;
12574 case BFD_RELOC_ARM_OFFSET_IMM8: type = "OFFSET_IMM8"; break;
12575 case BFD_RELOC_ARM_SHIFT_IMM: type = "SHIFT_IMM"; break;
12576 case BFD_RELOC_ARM_SMI: type = "SMI"; break;
12577 case BFD_RELOC_ARM_SWI: type = "SWI"; break;
12578 case BFD_RELOC_ARM_MULTI: type = "MULTI"; break;
12579 case BFD_RELOC_ARM_CP_OFF_IMM: type = "CP_OFF_IMM"; break;
12580 case BFD_RELOC_ARM_THUMB_ADD: type = "THUMB_ADD"; break;
12581 case BFD_RELOC_ARM_THUMB_SHIFT: type = "THUMB_SHIFT"; break;
12582 case BFD_RELOC_ARM_THUMB_IMM: type = "THUMB_IMM"; break;
12583 case BFD_RELOC_ARM_THUMB_OFFSET: type = "THUMB_OFFSET"; break;
12584 default: type = _("<unknown>"); break;
12585 }
12586 as_bad_where (fixp->fx_file, fixp->fx_line,
12587 _("cannot represent %s relocation in this object file format"),
12588 type);
12589 return NULL;
12590 }
12591 }
12592
12593 #ifdef OBJ_ELF
12594 if ((code == BFD_RELOC_32_PCREL || code == BFD_RELOC_32)
12595 && GOT_symbol
12596 && fixp->fx_addsy == GOT_symbol)
12597 {
12598 code = BFD_RELOC_ARM_GOTPC;
12599 reloc->addend = fixp->fx_offset = reloc->address;
12600 }
12601 #endif
12602
12603 reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
12604
12605 if (reloc->howto == NULL)
12606 {
12607 as_bad_where (fixp->fx_file, fixp->fx_line,
12608 _("cannot represent %s relocation in this object file format"),
12609 bfd_get_reloc_code_name (code));
12610 return NULL;
12611 }
12612
12613 /* HACK: Since arm ELF uses Rel instead of Rela, encode the
12614 vtable entry to be used in the relocation's section offset. */
12615 if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
12616 reloc->address = fixp->fx_offset;
12617
12618 return reloc;
12619 }
12620
12621 int
12622 md_estimate_size_before_relax (fragS * fragP ATTRIBUTE_UNUSED,
12623 segT segtype ATTRIBUTE_UNUSED)
12624 {
12625 as_fatal (_("md_estimate_size_before_relax\n"));
12626 return 1;
12627 }
12628
12629 /* We need to be able to fix up arbitrary expressions in some statements.
12630 This is so that we can handle symbols that are an arbitrary distance from
12631 the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
12632 which returns part of an address in a form which will be valid for
12633 a data instruction. We do this by pushing the expression into a symbol
12634 in the expr_section, and creating a fix for that. */
12635
12636 static void
12637 fix_new_arm (fragS * frag,
12638 int where,
12639 short int size,
12640 expressionS * exp,
12641 int pc_rel,
12642 int reloc)
12643 {
12644 fixS * new_fix;
12645 arm_fix_data * arm_data;
12646
12647 switch (exp->X_op)
12648 {
12649 case O_constant:
12650 case O_symbol:
12651 case O_add:
12652 case O_subtract:
12653 new_fix = fix_new_exp (frag, where, size, exp, pc_rel, reloc);
12654 break;
12655
12656 default:
12657 new_fix = fix_new (frag, where, size, make_expr_symbol (exp), 0,
12658 pc_rel, reloc);
12659 break;
12660 }
12661
12662 /* Mark whether the fix is to a THUMB instruction, or an ARM
12663 instruction. */
12664 arm_data = obstack_alloc (& notes, sizeof (arm_fix_data));
12665 new_fix->tc_fix_data = (PTR) arm_data;
12666 arm_data->thumb_mode = thumb_mode;
12667 }
12668
12669 static void
12670 output_inst (const char * str)
12671 {
12672 char * to = NULL;
12673
12674 if (inst.error)
12675 {
12676 as_bad ("%s -- `%s'", inst.error, str);
12677 return;
12678 }
12679
12680 to = frag_more (inst.size);
12681
12682 if (thumb_mode && (inst.size > THUMB_SIZE))
12683 {
12684 assert (inst.size == (2 * THUMB_SIZE));
12685 md_number_to_chars (to, inst.instruction >> 16, THUMB_SIZE);
12686 md_number_to_chars (to + THUMB_SIZE, inst.instruction, THUMB_SIZE);
12687 }
12688 else if (inst.size > INSN_SIZE)
12689 {
12690 assert (inst.size == (2 * INSN_SIZE));
12691 md_number_to_chars (to, inst.instruction, INSN_SIZE);
12692 md_number_to_chars (to + INSN_SIZE, inst.instruction, INSN_SIZE);
12693 }
12694 else
12695 md_number_to_chars (to, inst.instruction, inst.size);
12696
12697 if (inst.reloc.type != BFD_RELOC_UNUSED)
12698 fix_new_arm (frag_now, to - frag_now->fr_literal,
12699 inst.size, & inst.reloc.exp, inst.reloc.pc_rel,
12700 inst.reloc.type);
12701
12702 #ifdef OBJ_ELF
12703 dwarf2_emit_insn (inst.size);
12704 #endif
12705 }
12706
12707 void
12708 md_assemble (char * str)
12709 {
12710 char c;
12711 char *p;
12712 char *start;
12713
12714 /* Align the previous label if needed. */
12715 if (last_label_seen != NULL)
12716 {
12717 symbol_set_frag (last_label_seen, frag_now);
12718 S_SET_VALUE (last_label_seen, (valueT) frag_now_fix ());
12719 S_SET_SEGMENT (last_label_seen, now_seg);
12720 }
12721
12722 memset (&inst, '\0', sizeof (inst));
12723 inst.reloc.type = BFD_RELOC_UNUSED;
12724
12725 skip_whitespace (str);
12726
12727 /* Scan up to the end of the op-code, which must end in white space or
12728 end of string. */
12729 for (start = p = str; *p != '\0'; p++)
12730 if (*p == ' ')
12731 break;
12732
12733 if (p == str)
12734 {
12735 as_bad (_("no operator -- statement `%s'\n"), str);
12736 return;
12737 }
12738
12739 if (thumb_mode)
12740 {
12741 const struct thumb_opcode * opcode;
12742
12743 c = *p;
12744 *p = '\0';
12745 opcode = (const struct thumb_opcode *) hash_find (arm_tops_hsh, str);
12746 *p = c;
12747
12748 if (opcode)
12749 {
12750 /* Check that this instruction is supported for this CPU. */
12751 if (thumb_mode == 1 && (opcode->variant & cpu_variant) == 0)
12752 {
12753 as_bad (_("selected processor does not support `%s'"), str);
12754 return;
12755 }
12756
12757 mapping_state (MAP_THUMB);
12758 inst.instruction = opcode->value;
12759 inst.size = opcode->size;
12760 opcode->parms (p);
12761 output_inst (str);
12762 return;
12763 }
12764 }
12765 else
12766 {
12767 const struct asm_opcode * opcode;
12768
12769 c = *p;
12770 *p = '\0';
12771 opcode = (const struct asm_opcode *) hash_find (arm_ops_hsh, str);
12772 *p = c;
12773
12774 if (opcode)
12775 {
12776 /* Check that this instruction is supported for this CPU. */
12777 if ((opcode->variant & cpu_variant) == 0)
12778 {
12779 as_bad (_("selected processor does not support `%s'"), str);
12780 return;
12781 }
12782
12783 mapping_state (MAP_ARM);
12784 inst.instruction = opcode->value;
12785 inst.size = INSN_SIZE;
12786 opcode->parms (p);
12787 output_inst (str);
12788 return;
12789 }
12790 }
12791
12792 /* It wasn't an instruction, but it might be a register alias of the form
12793 alias .req reg. */
12794 if (create_register_alias (str, p))
12795 return;
12796
12797 as_bad (_("bad instruction `%s'"), start);
12798 }
12799
12800 /* md_parse_option
12801 Invocation line includes a switch not recognized by the base assembler.
12802 See if it's a processor-specific option.
12803
12804 This routine is somewhat complicated by the need for backwards
12805 compatibility (since older releases of gcc can't be changed).
12806 The new options try to make the interface as compatible as
12807 possible with GCC.
12808
12809 New options (supported) are:
12810
12811 -mcpu=<cpu name> Assemble for selected processor
12812 -march=<architecture name> Assemble for selected architecture
12813 -mfpu=<fpu architecture> Assemble for selected FPU.
12814 -EB/-mbig-endian Big-endian
12815 -EL/-mlittle-endian Little-endian
12816 -k Generate PIC code
12817 -mthumb Start in Thumb mode
12818 -mthumb-interwork Code supports ARM/Thumb interworking
12819
12820 For now we will also provide support for:
12821
12822 -mapcs-32 32-bit Program counter
12823 -mapcs-26 26-bit Program counter
12824 -macps-float Floats passed in FP registers
12825 -mapcs-reentrant Reentrant code
12826 -matpcs
12827 (sometime these will probably be replaced with -mapcs=<list of options>
12828 and -matpcs=<list of options>)
12829
12830 The remaining options are only supported for back-wards compatibility.
12831 Cpu variants, the arm part is optional:
12832 -m[arm]1 Currently not supported.
12833 -m[arm]2, -m[arm]250 Arm 2 and Arm 250 processor
12834 -m[arm]3 Arm 3 processor
12835 -m[arm]6[xx], Arm 6 processors
12836 -m[arm]7[xx][t][[d]m] Arm 7 processors
12837 -m[arm]8[10] Arm 8 processors
12838 -m[arm]9[20][tdmi] Arm 9 processors
12839 -mstrongarm[110[0]] StrongARM processors
12840 -mxscale XScale processors
12841 -m[arm]v[2345[t[e]]] Arm architectures
12842 -mall All (except the ARM1)
12843 FP variants:
12844 -mfpa10, -mfpa11 FPA10 and 11 co-processor instructions
12845 -mfpe-old (No float load/store multiples)
12846 -mvfpxd VFP Single precision
12847 -mvfp All VFP
12848 -mno-fpu Disable all floating point instructions
12849
12850 The following CPU names are recognized:
12851 arm1, arm2, arm250, arm3, arm6, arm600, arm610, arm620,
12852 arm7, arm7m, arm7d, arm7dm, arm7di, arm7dmi, arm70, arm700,
12853 arm700i, arm710 arm710t, arm720, arm720t, arm740t, arm710c,
12854 arm7100, arm7500, arm7500fe, arm7tdmi, arm8, arm810, arm9,
12855 arm920, arm920t, arm940t, arm946, arm966, arm9tdmi, arm9e,
12856 arm10t arm10e, arm1020t, arm1020e, arm10200e,
12857 strongarm, strongarm110, strongarm1100, strongarm1110, xscale.
12858
12859 */
12860
12861 const char * md_shortopts = "m:k";
12862
12863 #ifdef ARM_BI_ENDIAN
12864 #define OPTION_EB (OPTION_MD_BASE + 0)
12865 #define OPTION_EL (OPTION_MD_BASE + 1)
12866 #else
12867 #if TARGET_BYTES_BIG_ENDIAN
12868 #define OPTION_EB (OPTION_MD_BASE + 0)
12869 #else
12870 #define OPTION_EL (OPTION_MD_BASE + 1)
12871 #endif
12872 #endif
12873
12874 struct option md_longopts[] =
12875 {
12876 #ifdef OPTION_EB
12877 {"EB", no_argument, NULL, OPTION_EB},
12878 #endif
12879 #ifdef OPTION_EL
12880 {"EL", no_argument, NULL, OPTION_EL},
12881 #endif
12882 {NULL, no_argument, NULL, 0}
12883 };
12884
12885 size_t md_longopts_size = sizeof (md_longopts);
12886
12887 struct arm_option_table
12888 {
12889 char *option; /* Option name to match. */
12890 char *help; /* Help information. */
12891 int *var; /* Variable to change. */
12892 int value; /* What to change it to. */
12893 char *deprecated; /* If non-null, print this message. */
12894 };
12895
12896 struct arm_option_table arm_opts[] =
12897 {
12898 {"k", N_("generate PIC code"), &pic_code, 1, NULL},
12899 {"mthumb", N_("assemble Thumb code"), &thumb_mode, 1, NULL},
12900 {"mthumb-interwork", N_("support ARM/Thumb interworking"),
12901 &support_interwork, 1, NULL},
12902 {"mapcs-32", N_("code uses 32-bit program counter"), &uses_apcs_26, 0, NULL},
12903 {"mapcs-26", N_("code uses 26-bit program counter"), &uses_apcs_26, 1, NULL},
12904 {"mapcs-float", N_("floating point args are in fp regs"), &uses_apcs_float,
12905 1, NULL},
12906 {"mapcs-reentrant", N_("re-entrant code"), &pic_code, 1, NULL},
12907 {"matpcs", N_("code is ATPCS conformant"), &atpcs, 1, NULL},
12908 {"mbig-endian", N_("assemble for big-endian"), &target_big_endian, 1, NULL},
12909 {"mlittle-endian", N_("assemble for little-endian"), &target_big_endian, 1,
12910 NULL},
12911
12912 /* These are recognized by the assembler, but have no affect on code. */
12913 {"mapcs-frame", N_("use frame pointer"), NULL, 0, NULL},
12914 {"mapcs-stack-check", N_("use stack size checking"), NULL, 0, NULL},
12915
12916 /* DON'T add any new processors to this list -- we want the whole list
12917 to go away... Add them to the processors table instead. */
12918 {"marm1", NULL, &legacy_cpu, ARM_ARCH_V1, N_("use -mcpu=arm1")},
12919 {"m1", NULL, &legacy_cpu, ARM_ARCH_V1, N_("use -mcpu=arm1")},
12920 {"marm2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -mcpu=arm2")},
12921 {"m2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -mcpu=arm2")},
12922 {"marm250", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm250")},
12923 {"m250", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm250")},
12924 {"marm3", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm3")},
12925 {"m3", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm3")},
12926 {"marm6", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm6")},
12927 {"m6", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm6")},
12928 {"marm600", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm600")},
12929 {"m600", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm600")},
12930 {"marm610", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm610")},
12931 {"m610", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm610")},
12932 {"marm620", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm620")},
12933 {"m620", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm620")},
12934 {"marm7", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7")},
12935 {"m7", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7")},
12936 {"marm70", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm70")},
12937 {"m70", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm70")},
12938 {"marm700", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700")},
12939 {"m700", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700")},
12940 {"marm700i", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700i")},
12941 {"m700i", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700i")},
12942 {"marm710", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710")},
12943 {"m710", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710")},
12944 {"marm710c", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710c")},
12945 {"m710c", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710c")},
12946 {"marm720", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm720")},
12947 {"m720", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm720")},
12948 {"marm7d", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7d")},
12949 {"m7d", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7d")},
12950 {"marm7di", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7di")},
12951 {"m7di", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7di")},
12952 {"marm7m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7m")},
12953 {"m7m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7m")},
12954 {"marm7dm", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dm")},
12955 {"m7dm", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dm")},
12956 {"marm7dmi", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dmi")},
12957 {"m7dmi", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dmi")},
12958 {"marm7100", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7100")},
12959 {"m7100", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7100")},
12960 {"marm7500", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500")},
12961 {"m7500", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500")},
12962 {"marm7500fe", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500fe")},
12963 {"m7500fe", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500fe")},
12964 {"marm7t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
12965 {"m7t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
12966 {"marm7tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
12967 {"m7tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
12968 {"marm710t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm710t")},
12969 {"m710t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm710t")},
12970 {"marm720t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm720t")},
12971 {"m720t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm720t")},
12972 {"marm740t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm740t")},
12973 {"m740t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm740t")},
12974 {"marm8", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm8")},
12975 {"m8", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm8")},
12976 {"marm810", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm810")},
12977 {"m810", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm810")},
12978 {"marm9", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9")},
12979 {"m9", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9")},
12980 {"marm9tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9tdmi")},
12981 {"m9tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9tdmi")},
12982 {"marm920", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm920")},
12983 {"m920", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm920")},
12984 {"marm940", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm940")},
12985 {"m940", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm940")},
12986 {"mstrongarm", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=strongarm")},
12987 {"mstrongarm110", NULL, &legacy_cpu, ARM_ARCH_V4,
12988 N_("use -mcpu=strongarm110")},
12989 {"mstrongarm1100", NULL, &legacy_cpu, ARM_ARCH_V4,
12990 N_("use -mcpu=strongarm1100")},
12991 {"mstrongarm1110", NULL, &legacy_cpu, ARM_ARCH_V4,
12992 N_("use -mcpu=strongarm1110")},
12993 {"mxscale", NULL, &legacy_cpu, ARM_ARCH_XSCALE, N_("use -mcpu=xscale")},
12994 {"miwmmxt", NULL, &legacy_cpu, ARM_ARCH_IWMMXT, N_("use -mcpu=iwmmxt")},
12995 {"mall", NULL, &legacy_cpu, ARM_ANY, N_("use -mcpu=all")},
12996
12997 /* Architecture variants -- don't add any more to this list either. */
12998 {"mv2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -march=armv2")},
12999 {"marmv2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -march=armv2")},
13000 {"mv2a", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -march=armv2a")},
13001 {"marmv2a", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -march=armv2a")},
13002 {"mv3", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -march=armv3")},
13003 {"marmv3", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -march=armv3")},
13004 {"mv3m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -march=armv3m")},
13005 {"marmv3m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -march=armv3m")},
13006 {"mv4", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -march=armv4")},
13007 {"marmv4", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -march=armv4")},
13008 {"mv4t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -march=armv4t")},
13009 {"marmv4t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -march=armv4t")},
13010 {"mv5", NULL, &legacy_cpu, ARM_ARCH_V5, N_("use -march=armv5")},
13011 {"marmv5", NULL, &legacy_cpu, ARM_ARCH_V5, N_("use -march=armv5")},
13012 {"mv5t", NULL, &legacy_cpu, ARM_ARCH_V5T, N_("use -march=armv5t")},
13013 {"marmv5t", NULL, &legacy_cpu, ARM_ARCH_V5T, N_("use -march=armv5t")},
13014 {"mv5e", NULL, &legacy_cpu, ARM_ARCH_V5TE, N_("use -march=armv5te")},
13015 {"marmv5e", NULL, &legacy_cpu, ARM_ARCH_V5TE, N_("use -march=armv5te")},
13016
13017 /* Floating point variants -- don't add any more to this list either. */
13018 {"mfpe-old", NULL, &legacy_fpu, FPU_ARCH_FPE, N_("use -mfpu=fpe")},
13019 {"mfpa10", NULL, &legacy_fpu, FPU_ARCH_FPA, N_("use -mfpu=fpa10")},
13020 {"mfpa11", NULL, &legacy_fpu, FPU_ARCH_FPA, N_("use -mfpu=fpa11")},
13021 {"mno-fpu", NULL, &legacy_fpu, 0,
13022 N_("use either -mfpu=softfpa or -mfpu=softvfp")},
13023
13024 {NULL, NULL, NULL, 0, NULL}
13025 };
13026
13027 struct arm_cpu_option_table
13028 {
13029 char *name;
13030 int value;
13031 /* For some CPUs we assume an FPU unless the user explicitly sets
13032 -mfpu=... */
13033 int default_fpu;
13034 };
13035
13036 /* This list should, at a minimum, contain all the cpu names
13037 recognized by GCC. */
13038 static struct arm_cpu_option_table arm_cpus[] =
13039 {
13040 {"all", ARM_ANY, FPU_ARCH_FPA},
13041 {"arm1", ARM_ARCH_V1, FPU_ARCH_FPA},
13042 {"arm2", ARM_ARCH_V2, FPU_ARCH_FPA},
13043 {"arm250", ARM_ARCH_V2S, FPU_ARCH_FPA},
13044 {"arm3", ARM_ARCH_V2S, FPU_ARCH_FPA},
13045 {"arm6", ARM_ARCH_V3, FPU_ARCH_FPA},
13046 {"arm60", ARM_ARCH_V3, FPU_ARCH_FPA},
13047 {"arm600", ARM_ARCH_V3, FPU_ARCH_FPA},
13048 {"arm610", ARM_ARCH_V3, FPU_ARCH_FPA},
13049 {"arm620", ARM_ARCH_V3, FPU_ARCH_FPA},
13050 {"arm7", ARM_ARCH_V3, FPU_ARCH_FPA},
13051 {"arm7m", ARM_ARCH_V3M, FPU_ARCH_FPA},
13052 {"arm7d", ARM_ARCH_V3, FPU_ARCH_FPA},
13053 {"arm7dm", ARM_ARCH_V3M, FPU_ARCH_FPA},
13054 {"arm7di", ARM_ARCH_V3, FPU_ARCH_FPA},
13055 {"arm7dmi", ARM_ARCH_V3M, FPU_ARCH_FPA},
13056 {"arm70", ARM_ARCH_V3, FPU_ARCH_FPA},
13057 {"arm700", ARM_ARCH_V3, FPU_ARCH_FPA},
13058 {"arm700i", ARM_ARCH_V3, FPU_ARCH_FPA},
13059 {"arm710", ARM_ARCH_V3, FPU_ARCH_FPA},
13060 {"arm710t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13061 {"arm720", ARM_ARCH_V3, FPU_ARCH_FPA},
13062 {"arm720t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13063 {"arm740t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13064 {"arm710c", ARM_ARCH_V3, FPU_ARCH_FPA},
13065 {"arm7100", ARM_ARCH_V3, FPU_ARCH_FPA},
13066 {"arm7500", ARM_ARCH_V3, FPU_ARCH_FPA},
13067 {"arm7500fe", ARM_ARCH_V3, FPU_ARCH_FPA},
13068 {"arm7t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13069 {"arm7tdmi", ARM_ARCH_V4T, FPU_ARCH_FPA},
13070 {"arm7tdmi-s", ARM_ARCH_V4T, FPU_ARCH_FPA},
13071 {"arm8", ARM_ARCH_V4, FPU_ARCH_FPA},
13072 {"arm810", ARM_ARCH_V4, FPU_ARCH_FPA},
13073 {"strongarm", ARM_ARCH_V4, FPU_ARCH_FPA},
13074 {"strongarm1", ARM_ARCH_V4, FPU_ARCH_FPA},
13075 {"strongarm110", ARM_ARCH_V4, FPU_ARCH_FPA},
13076 {"strongarm1100", ARM_ARCH_V4, FPU_ARCH_FPA},
13077 {"strongarm1110", ARM_ARCH_V4, FPU_ARCH_FPA},
13078 {"arm9", ARM_ARCH_V4T, FPU_ARCH_FPA},
13079 {"arm920", ARM_ARCH_V4T, FPU_ARCH_FPA},
13080 {"arm920t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13081 {"arm922t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13082 {"arm940t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13083 {"arm9tdmi", ARM_ARCH_V4T, FPU_ARCH_FPA},
13084 /* For V5 or later processors we default to using VFP; but the user
13085 should really set the FPU type explicitly. */
13086 {"arm9e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
13087 {"arm9e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13088 {"arm926ej", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
13089 {"arm926ejs", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
13090 {"arm926ej-s", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
13091 {"arm946e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
13092 {"arm946e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13093 {"arm966e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
13094 {"arm966e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13095 {"arm10t", ARM_ARCH_V5T, FPU_ARCH_VFP_V1},
13096 {"arm10e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13097 {"arm1020", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13098 {"arm1020t", ARM_ARCH_V5T, FPU_ARCH_VFP_V1},
13099 {"arm1020e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13100 {"arm1026ejs", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
13101 {"arm1026ej-s", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
13102 {"arm1136js", ARM_ARCH_V6, FPU_NONE},
13103 {"arm1136j-s", ARM_ARCH_V6, FPU_NONE},
13104 {"arm1136jfs", ARM_ARCH_V6, FPU_ARCH_VFP_V2},
13105 {"arm1136jf-s", ARM_ARCH_V6, FPU_ARCH_VFP_V2},
13106 {"mpcore", ARM_ARCH_V6K, FPU_ARCH_VFP_V2},
13107 {"mpcorenovfp", ARM_ARCH_V6K, FPU_NONE},
13108 {"arm1176jz-s", ARM_ARCH_V6ZK, FPU_NONE},
13109 {"arm1176jzf-s", ARM_ARCH_V6ZK, FPU_ARCH_VFP_V2},
13110 /* ??? XSCALE is really an architecture. */
13111 {"xscale", ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2},
13112 /* ??? iwmmxt is not a processor. */
13113 {"iwmmxt", ARM_ARCH_IWMMXT, FPU_ARCH_VFP_V2},
13114 {"i80200", ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2},
13115 /* Maverick */
13116 {"ep9312", ARM_ARCH_V4T | ARM_CEXT_MAVERICK, FPU_ARCH_MAVERICK},
13117 {NULL, 0, 0}
13118 };
13119
13120 struct arm_arch_option_table
13121 {
13122 char *name;
13123 int value;
13124 int default_fpu;
13125 };
13126
13127 /* This list should, at a minimum, contain all the architecture names
13128 recognized by GCC. */
13129 static struct arm_arch_option_table arm_archs[] =
13130 {
13131 {"all", ARM_ANY, FPU_ARCH_FPA},
13132 {"armv1", ARM_ARCH_V1, FPU_ARCH_FPA},
13133 {"armv2", ARM_ARCH_V2, FPU_ARCH_FPA},
13134 {"armv2a", ARM_ARCH_V2S, FPU_ARCH_FPA},
13135 {"armv2s", ARM_ARCH_V2S, FPU_ARCH_FPA},
13136 {"armv3", ARM_ARCH_V3, FPU_ARCH_FPA},
13137 {"armv3m", ARM_ARCH_V3M, FPU_ARCH_FPA},
13138 {"armv4", ARM_ARCH_V4, FPU_ARCH_FPA},
13139 {"armv4xm", ARM_ARCH_V4xM, FPU_ARCH_FPA},
13140 {"armv4t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13141 {"armv4txm", ARM_ARCH_V4TxM, FPU_ARCH_FPA},
13142 {"armv5", ARM_ARCH_V5, FPU_ARCH_VFP},
13143 {"armv5t", ARM_ARCH_V5T, FPU_ARCH_VFP},
13144 {"armv5txm", ARM_ARCH_V5TxM, FPU_ARCH_VFP},
13145 {"armv5te", ARM_ARCH_V5TE, FPU_ARCH_VFP},
13146 {"armv5texp", ARM_ARCH_V5TExP, FPU_ARCH_VFP},
13147 {"armv5tej", ARM_ARCH_V5TEJ, FPU_ARCH_VFP},
13148 {"armv6", ARM_ARCH_V6, FPU_ARCH_VFP},
13149 {"armv6j", ARM_ARCH_V6, FPU_ARCH_VFP},
13150 {"armv6k", ARM_ARCH_V6K, FPU_ARCH_VFP},
13151 {"armv6z", ARM_ARCH_V6Z, FPU_ARCH_VFP},
13152 {"armv6zk", ARM_ARCH_V6ZK, FPU_ARCH_VFP},
13153 {"armv6t2", ARM_ARCH_V6T2, FPU_ARCH_VFP},
13154 {"armv6kt2", ARM_ARCH_V6KT2, FPU_ARCH_VFP},
13155 {"armv6zt2", ARM_ARCH_V6ZT2, FPU_ARCH_VFP},
13156 {"armv6zkt2", ARM_ARCH_V6ZKT2, FPU_ARCH_VFP},
13157 {"xscale", ARM_ARCH_XSCALE, FPU_ARCH_VFP},
13158 {"iwmmxt", ARM_ARCH_IWMMXT, FPU_ARCH_VFP},
13159 {NULL, 0, 0}
13160 };
13161
13162 /* ISA extensions in the co-processor space. */
13163 struct arm_arch_extension_table
13164 {
13165 char *name;
13166 int value;
13167 };
13168
13169 static struct arm_arch_extension_table arm_extensions[] =
13170 {
13171 {"maverick", ARM_CEXT_MAVERICK},
13172 {"xscale", ARM_CEXT_XSCALE},
13173 {"iwmmxt", ARM_CEXT_IWMMXT},
13174 {NULL, 0}
13175 };
13176
13177 struct arm_fpu_option_table
13178 {
13179 char *name;
13180 int value;
13181 };
13182
13183 /* This list should, at a minimum, contain all the fpu names
13184 recognized by GCC. */
13185 static struct arm_fpu_option_table arm_fpus[] =
13186 {
13187 {"softfpa", FPU_NONE},
13188 {"fpe", FPU_ARCH_FPE},
13189 {"fpe2", FPU_ARCH_FPE},
13190 {"fpe3", FPU_ARCH_FPA}, /* Third release supports LFM/SFM. */
13191 {"fpa", FPU_ARCH_FPA},
13192 {"fpa10", FPU_ARCH_FPA},
13193 {"fpa11", FPU_ARCH_FPA},
13194 {"arm7500fe", FPU_ARCH_FPA},
13195 {"softvfp", FPU_ARCH_VFP},
13196 {"softvfp+vfp", FPU_ARCH_VFP_V2},
13197 {"vfp", FPU_ARCH_VFP_V2},
13198 {"vfp9", FPU_ARCH_VFP_V2},
13199 {"vfp10", FPU_ARCH_VFP_V2},
13200 {"vfp10-r0", FPU_ARCH_VFP_V1},
13201 {"vfpxd", FPU_ARCH_VFP_V1xD},
13202 {"arm1020t", FPU_ARCH_VFP_V1},
13203 {"arm1020e", FPU_ARCH_VFP_V2},
13204 {"arm1136jfs", FPU_ARCH_VFP_V2},
13205 {"arm1136jf-s", FPU_ARCH_VFP_V2},
13206 {"maverick", FPU_ARCH_MAVERICK},
13207 {NULL, 0}
13208 };
13209
13210 struct arm_float_abi_option_table
13211 {
13212 char *name;
13213 int value;
13214 };
13215
13216 static struct arm_float_abi_option_table arm_float_abis[] =
13217 {
13218 {"hard", ARM_FLOAT_ABI_HARD},
13219 {"softfp", ARM_FLOAT_ABI_SOFTFP},
13220 {"soft", ARM_FLOAT_ABI_SOFT},
13221 {NULL, 0}
13222 };
13223
13224 struct arm_eabi_option_table
13225 {
13226 char *name;
13227 unsigned int value;
13228 };
13229
13230 #ifdef OBJ_ELF
13231 /* We only know how to output GNU and ver 4 (AAELF) formats. */
13232 static struct arm_eabi_option_table arm_eabis[] =
13233 {
13234 {"gnu", EF_ARM_EABI_UNKNOWN},
13235 {"4", EF_ARM_EABI_VER4},
13236 {NULL, 0}
13237 };
13238 #endif
13239
13240 struct arm_long_option_table
13241 {
13242 char * option; /* Substring to match. */
13243 char * help; /* Help information. */
13244 int (* func) (char * subopt); /* Function to decode sub-option. */
13245 char * deprecated; /* If non-null, print this message. */
13246 };
13247
13248 static int
13249 arm_parse_extension (char * str, int * opt_p)
13250 {
13251 while (str != NULL && *str != 0)
13252 {
13253 struct arm_arch_extension_table * opt;
13254 char * ext;
13255 int optlen;
13256
13257 if (*str != '+')
13258 {
13259 as_bad (_("invalid architectural extension"));
13260 return 0;
13261 }
13262
13263 str++;
13264 ext = strchr (str, '+');
13265
13266 if (ext != NULL)
13267 optlen = ext - str;
13268 else
13269 optlen = strlen (str);
13270
13271 if (optlen == 0)
13272 {
13273 as_bad (_("missing architectural extension"));
13274 return 0;
13275 }
13276
13277 for (opt = arm_extensions; opt->name != NULL; opt++)
13278 if (strncmp (opt->name, str, optlen) == 0)
13279 {
13280 *opt_p |= opt->value;
13281 break;
13282 }
13283
13284 if (opt->name == NULL)
13285 {
13286 as_bad (_("unknown architectural extnsion `%s'"), str);
13287 return 0;
13288 }
13289
13290 str = ext;
13291 };
13292
13293 return 1;
13294 }
13295
13296 static int
13297 arm_parse_cpu (char * str)
13298 {
13299 struct arm_cpu_option_table * opt;
13300 char * ext = strchr (str, '+');
13301 int optlen;
13302
13303 if (ext != NULL)
13304 optlen = ext - str;
13305 else
13306 optlen = strlen (str);
13307
13308 if (optlen == 0)
13309 {
13310 as_bad (_("missing cpu name `%s'"), str);
13311 return 0;
13312 }
13313
13314 for (opt = arm_cpus; opt->name != NULL; opt++)
13315 if (strncmp (opt->name, str, optlen) == 0)
13316 {
13317 mcpu_cpu_opt = opt->value;
13318 mcpu_fpu_opt = opt->default_fpu;
13319
13320 if (ext != NULL)
13321 return arm_parse_extension (ext, &mcpu_cpu_opt);
13322
13323 return 1;
13324 }
13325
13326 as_bad (_("unknown cpu `%s'"), str);
13327 return 0;
13328 }
13329
13330 static int
13331 arm_parse_arch (char * str)
13332 {
13333 struct arm_arch_option_table *opt;
13334 char *ext = strchr (str, '+');
13335 int optlen;
13336
13337 if (ext != NULL)
13338 optlen = ext - str;
13339 else
13340 optlen = strlen (str);
13341
13342 if (optlen == 0)
13343 {
13344 as_bad (_("missing architecture name `%s'"), str);
13345 return 0;
13346 }
13347
13348
13349 for (opt = arm_archs; opt->name != NULL; opt++)
13350 if (streq (opt->name, str))
13351 {
13352 march_cpu_opt = opt->value;
13353 march_fpu_opt = opt->default_fpu;
13354
13355 if (ext != NULL)
13356 return arm_parse_extension (ext, &march_cpu_opt);
13357
13358 return 1;
13359 }
13360
13361 as_bad (_("unknown architecture `%s'\n"), str);
13362 return 0;
13363 }
13364
13365 static int
13366 arm_parse_fpu (char * str)
13367 {
13368 struct arm_fpu_option_table * opt;
13369
13370 for (opt = arm_fpus; opt->name != NULL; opt++)
13371 if (streq (opt->name, str))
13372 {
13373 mfpu_opt = opt->value;
13374 return 1;
13375 }
13376
13377 as_bad (_("unknown floating point format `%s'\n"), str);
13378 return 0;
13379 }
13380
13381 static int
13382 arm_parse_float_abi (char * str)
13383 {
13384 struct arm_float_abi_option_table * opt;
13385
13386 for (opt = arm_float_abis; opt->name != NULL; opt++)
13387 if (streq (opt->name, str))
13388 {
13389 mfloat_abi_opt = opt->value;
13390 return 1;
13391 }
13392
13393 as_bad (_("unknown floating point abi `%s'\n"), str);
13394 return 0;
13395 }
13396
13397 #ifdef OBJ_ELF
13398 static int
13399 arm_parse_eabi (char * str)
13400 {
13401 struct arm_eabi_option_table *opt;
13402
13403 for (opt = arm_eabis; opt->name != NULL; opt++)
13404 if (streq (opt->name, str))
13405 {
13406 meabi_flags = opt->value;
13407 return 1;
13408 }
13409 as_bad (_("unknown EABI `%s'\n"), str);
13410 return 0;
13411 }
13412 #endif
13413
13414 struct arm_long_option_table arm_long_opts[] =
13415 {
13416 {"mcpu=", N_("<cpu name>\t assemble for CPU <cpu name>"),
13417 arm_parse_cpu, NULL},
13418 {"march=", N_("<arch name>\t assemble for architecture <arch name>"),
13419 arm_parse_arch, NULL},
13420 {"mfpu=", N_("<fpu name>\t assemble for FPU architecture <fpu name>"),
13421 arm_parse_fpu, NULL},
13422 {"mfloat-abi=", N_("<abi>\t assemble for floating point ABI <abi>"),
13423 arm_parse_float_abi, NULL},
13424 #ifdef OBJ_ELF
13425 {"meabi=", N_("<ver>\t assemble for eabi version <ver>"),
13426 arm_parse_eabi, NULL},
13427 #endif
13428 {NULL, NULL, 0, NULL}
13429 };
13430
13431 int
13432 md_parse_option (int c, char * arg)
13433 {
13434 struct arm_option_table *opt;
13435 struct arm_long_option_table *lopt;
13436
13437 switch (c)
13438 {
13439 #ifdef OPTION_EB
13440 case OPTION_EB:
13441 target_big_endian = 1;
13442 break;
13443 #endif
13444
13445 #ifdef OPTION_EL
13446 case OPTION_EL:
13447 target_big_endian = 0;
13448 break;
13449 #endif
13450
13451 case 'a':
13452 /* Listing option. Just ignore these, we don't support additional
13453 ones. */
13454 return 0;
13455
13456 default:
13457 for (opt = arm_opts; opt->option != NULL; opt++)
13458 {
13459 if (c == opt->option[0]
13460 && ((arg == NULL && opt->option[1] == 0)
13461 || streq (arg, opt->option + 1)))
13462 {
13463 #if WARN_DEPRECATED
13464 /* If the option is deprecated, tell the user. */
13465 if (opt->deprecated != NULL)
13466 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c,
13467 arg ? arg : "", _(opt->deprecated));
13468 #endif
13469
13470 if (opt->var != NULL)
13471 *opt->var = opt->value;
13472
13473 return 1;
13474 }
13475 }
13476
13477 for (lopt = arm_long_opts; lopt->option != NULL; lopt++)
13478 {
13479 /* These options are expected to have an argument. */
13480 if (c == lopt->option[0]
13481 && arg != NULL
13482 && strncmp (arg, lopt->option + 1,
13483 strlen (lopt->option + 1)) == 0)
13484 {
13485 #if WARN_DEPRECATED
13486 /* If the option is deprecated, tell the user. */
13487 if (lopt->deprecated != NULL)
13488 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c, arg,
13489 _(lopt->deprecated));
13490 #endif
13491
13492 /* Call the sup-option parser. */
13493 return lopt->func (arg + strlen (lopt->option) - 1);
13494 }
13495 }
13496
13497 return 0;
13498 }
13499
13500 return 1;
13501 }
13502
13503 void
13504 md_show_usage (FILE * fp)
13505 {
13506 struct arm_option_table *opt;
13507 struct arm_long_option_table *lopt;
13508
13509 fprintf (fp, _(" ARM-specific assembler options:\n"));
13510
13511 for (opt = arm_opts; opt->option != NULL; opt++)
13512 if (opt->help != NULL)
13513 fprintf (fp, " -%-23s%s\n", opt->option, _(opt->help));
13514
13515 for (lopt = arm_long_opts; lopt->option != NULL; lopt++)
13516 if (lopt->help != NULL)
13517 fprintf (fp, " -%s%s\n", lopt->option, _(lopt->help));
13518
13519 #ifdef OPTION_EB
13520 fprintf (fp, _("\
13521 -EB assemble code for a big-endian cpu\n"));
13522 #endif
13523
13524 #ifdef OPTION_EL
13525 fprintf (fp, _("\
13526 -EL assemble code for a little-endian cpu\n"));
13527 #endif
13528 }
13529
13530 /* This fix_new is called by cons via TC_CONS_FIX_NEW. */
13531
13532 void
13533 cons_fix_new_arm (fragS * frag,
13534 int where,
13535 int size,
13536 expressionS * exp)
13537 {
13538 bfd_reloc_code_real_type type;
13539 int pcrel = 0;
13540
13541 /* Pick a reloc.
13542 FIXME: @@ Should look at CPU word size. */
13543 switch (size)
13544 {
13545 case 1:
13546 type = BFD_RELOC_8;
13547 break;
13548 case 2:
13549 type = BFD_RELOC_16;
13550 break;
13551 case 4:
13552 default:
13553 type = BFD_RELOC_32;
13554 break;
13555 case 8:
13556 type = BFD_RELOC_64;
13557 break;
13558 }
13559
13560 fix_new_exp (frag, where, (int) size, exp, pcrel, type);
13561 }
13562
13563 /* A good place to do this, although this was probably not intended
13564 for this kind of use. We need to dump the literal pool before
13565 references are made to a null symbol pointer. */
13566
13567 void
13568 arm_cleanup (void)
13569 {
13570 literal_pool * pool;
13571
13572 for (pool = list_of_pools; pool; pool = pool->next)
13573 {
13574 /* Put it at the end of the relevent section. */
13575 subseg_set (pool->section, pool->sub_section);
13576 #ifdef OBJ_ELF
13577 arm_elf_change_section ();
13578 #endif
13579 s_ltorg (0);
13580 }
13581 }
13582
13583 void
13584 arm_start_line_hook (void)
13585 {
13586 last_label_seen = NULL;
13587 }
13588
13589 void
13590 arm_frob_label (symbolS * sym)
13591 {
13592 last_label_seen = sym;
13593
13594 ARM_SET_THUMB (sym, thumb_mode);
13595
13596 #if defined OBJ_COFF || defined OBJ_ELF
13597 ARM_SET_INTERWORK (sym, support_interwork);
13598 #endif
13599
13600 /* Note - do not allow local symbols (.Lxxx) to be labeled
13601 as Thumb functions. This is because these labels, whilst
13602 they exist inside Thumb code, are not the entry points for
13603 possible ARM->Thumb calls. Also, these labels can be used
13604 as part of a computed goto or switch statement. eg gcc
13605 can generate code that looks like this:
13606
13607 ldr r2, [pc, .Laaa]
13608 lsl r3, r3, #2
13609 ldr r2, [r3, r2]
13610 mov pc, r2
13611
13612 .Lbbb: .word .Lxxx
13613 .Lccc: .word .Lyyy
13614 ..etc...
13615 .Laaa: .word Lbbb
13616
13617 The first instruction loads the address of the jump table.
13618 The second instruction converts a table index into a byte offset.
13619 The third instruction gets the jump address out of the table.
13620 The fourth instruction performs the jump.
13621
13622 If the address stored at .Laaa is that of a symbol which has the
13623 Thumb_Func bit set, then the linker will arrange for this address
13624 to have the bottom bit set, which in turn would mean that the
13625 address computation performed by the third instruction would end
13626 up with the bottom bit set. Since the ARM is capable of unaligned
13627 word loads, the instruction would then load the incorrect address
13628 out of the jump table, and chaos would ensue. */
13629 if (label_is_thumb_function_name
13630 && (S_GET_NAME (sym)[0] != '.' || S_GET_NAME (sym)[1] != 'L')
13631 && (bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
13632 {
13633 /* When the address of a Thumb function is taken the bottom
13634 bit of that address should be set. This will allow
13635 interworking between Arm and Thumb functions to work
13636 correctly. */
13637
13638 THUMB_SET_FUNC (sym, 1);
13639
13640 label_is_thumb_function_name = FALSE;
13641 }
13642 }
13643
13644 /* Adjust the symbol table. This marks Thumb symbols as distinct from
13645 ARM ones. */
13646
13647 void
13648 arm_adjust_symtab (void)
13649 {
13650 #ifdef OBJ_COFF
13651 symbolS * sym;
13652
13653 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
13654 {
13655 if (ARM_IS_THUMB (sym))
13656 {
13657 if (THUMB_IS_FUNC (sym))
13658 {
13659 /* Mark the symbol as a Thumb function. */
13660 if ( S_GET_STORAGE_CLASS (sym) == C_STAT
13661 || S_GET_STORAGE_CLASS (sym) == C_LABEL) /* This can happen! */
13662 S_SET_STORAGE_CLASS (sym, C_THUMBSTATFUNC);
13663
13664 else if (S_GET_STORAGE_CLASS (sym) == C_EXT)
13665 S_SET_STORAGE_CLASS (sym, C_THUMBEXTFUNC);
13666 else
13667 as_bad (_("%s: unexpected function type: %d"),
13668 S_GET_NAME (sym), S_GET_STORAGE_CLASS (sym));
13669 }
13670 else switch (S_GET_STORAGE_CLASS (sym))
13671 {
13672 case C_EXT:
13673 S_SET_STORAGE_CLASS (sym, C_THUMBEXT);
13674 break;
13675 case C_STAT:
13676 S_SET_STORAGE_CLASS (sym, C_THUMBSTAT);
13677 break;
13678 case C_LABEL:
13679 S_SET_STORAGE_CLASS (sym, C_THUMBLABEL);
13680 break;
13681 default:
13682 /* Do nothing. */
13683 break;
13684 }
13685 }
13686
13687 if (ARM_IS_INTERWORK (sym))
13688 coffsymbol (symbol_get_bfdsym (sym))->native->u.syment.n_flags = 0xFF;
13689 }
13690 #endif
13691 #ifdef OBJ_ELF
13692 symbolS * sym;
13693 char bind;
13694
13695 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
13696 {
13697 if (ARM_IS_THUMB (sym))
13698 {
13699 elf_symbol_type * elf_sym;
13700
13701 elf_sym = elf_symbol (symbol_get_bfdsym (sym));
13702 bind = ELF_ST_BIND (elf_sym);
13703
13704 /* If it's a .thumb_func, declare it as so,
13705 otherwise tag label as .code 16. */
13706 if (THUMB_IS_FUNC (sym))
13707 elf_sym->internal_elf_sym.st_info =
13708 ELF_ST_INFO (bind, STT_ARM_TFUNC);
13709 else
13710 elf_sym->internal_elf_sym.st_info =
13711 ELF_ST_INFO (bind, STT_ARM_16BIT);
13712 }
13713 }
13714 #endif
13715 }
13716
13717 int
13718 arm_data_in_code (void)
13719 {
13720 if (thumb_mode && ! strncmp (input_line_pointer + 1, "data:", 5))
13721 {
13722 *input_line_pointer = '/';
13723 input_line_pointer += 5;
13724 *input_line_pointer = 0;
13725 return 1;
13726 }
13727
13728 return 0;
13729 }
13730
13731 char *
13732 arm_canonicalize_symbol_name (char * name)
13733 {
13734 int len;
13735
13736 if (thumb_mode && (len = strlen (name)) > 5
13737 && streq (name + len - 5, "/data"))
13738 *(name + len - 5) = 0;
13739
13740 return name;
13741 }
13742
13743 #if defined OBJ_COFF || defined OBJ_ELF
13744 void
13745 arm_validate_fix (fixS * fixP)
13746 {
13747 /* If the destination of the branch is a defined symbol which does not have
13748 the THUMB_FUNC attribute, then we must be calling a function which has
13749 the (interfacearm) attribute. We look for the Thumb entry point to that
13750 function and change the branch to refer to that function instead. */
13751 if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23
13752 && fixP->fx_addsy != NULL
13753 && S_IS_DEFINED (fixP->fx_addsy)
13754 && ! THUMB_IS_FUNC (fixP->fx_addsy))
13755 {
13756 fixP->fx_addsy = find_real_start (fixP->fx_addsy);
13757 }
13758 }
13759 #endif
13760
13761 int
13762 arm_force_relocation (struct fix * fixp)
13763 {
13764 #if defined (OBJ_COFF) && defined (TE_PE)
13765 if (fixp->fx_r_type == BFD_RELOC_RVA)
13766 return 1;
13767 #endif
13768 #ifdef OBJ_ELF
13769 if (fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH
13770 || fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BLX
13771 || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX
13772 || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23)
13773 return 1;
13774 #endif
13775
13776 /* Resolve these relocations even if the symbol is extern or weak. */
13777 if (fixp->fx_r_type == BFD_RELOC_ARM_IMMEDIATE
13778 || fixp->fx_r_type == BFD_RELOC_ARM_OFFSET_IMM
13779 || fixp->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE)
13780 return 0;
13781
13782 return generic_force_reloc (fixp);
13783 }
13784
13785 #ifdef OBJ_COFF
13786 /* This is a little hack to help the gas/arm/adrl.s test. It prevents
13787 local labels from being added to the output symbol table when they
13788 are used with the ADRL pseudo op. The ADRL relocation should always
13789 be resolved before the binbary is emitted, so it is safe to say that
13790 it is adjustable. */
13791
13792 bfd_boolean
13793 arm_fix_adjustable (fixS * fixP)
13794 {
13795 if (fixP->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE)
13796 return 1;
13797 return 0;
13798 }
13799 #endif
13800
13801 #ifdef OBJ_ELF
13802 /* Relocations against Thumb function names must be left unadjusted,
13803 so that the linker can use this information to correctly set the
13804 bottom bit of their addresses. The MIPS version of this function
13805 also prevents relocations that are mips-16 specific, but I do not
13806 know why it does this.
13807
13808 FIXME:
13809 There is one other problem that ought to be addressed here, but
13810 which currently is not: Taking the address of a label (rather
13811 than a function) and then later jumping to that address. Such
13812 addresses also ought to have their bottom bit set (assuming that
13813 they reside in Thumb code), but at the moment they will not. */
13814
13815 bfd_boolean
13816 arm_fix_adjustable (fixS * fixP)
13817 {
13818 if (fixP->fx_addsy == NULL)
13819 return 1;
13820
13821 if (THUMB_IS_FUNC (fixP->fx_addsy)
13822 && fixP->fx_subsy == NULL)
13823 return 0;
13824
13825 /* We need the symbol name for the VTABLE entries. */
13826 if ( fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
13827 || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
13828 return 0;
13829
13830 /* Don't allow symbols to be discarded on GOT related relocs. */
13831 if (fixP->fx_r_type == BFD_RELOC_ARM_PLT32
13832 || fixP->fx_r_type == BFD_RELOC_ARM_GOT32
13833 || fixP->fx_r_type == BFD_RELOC_ARM_GOTOFF
13834 || fixP->fx_r_type == BFD_RELOC_ARM_TARGET2)
13835 return 0;
13836
13837 return 1;
13838 }
13839
13840 const char *
13841 elf32_arm_target_format (void)
13842 {
13843 #ifdef TE_SYMBIAN
13844 return (target_big_endian
13845 ? "elf32-bigarm-symbian"
13846 : "elf32-littlearm-symbian");
13847 #elif defined (TE_VXWORKS)
13848 return (target_big_endian
13849 ? "elf32-bigarm-vxworks"
13850 : "elf32-littlearm-vxworks");
13851 #else
13852 if (target_big_endian)
13853 return "elf32-bigarm";
13854 else
13855 return "elf32-littlearm";
13856 #endif
13857 }
13858
13859 void
13860 armelf_frob_symbol (symbolS * symp,
13861 int * puntp)
13862 {
13863 elf_frob_symbol (symp, puntp);
13864 }
13865
13866 static void
13867 s_arm_elf_cons (int nbytes)
13868 {
13869 expressionS exp;
13870
13871 #ifdef md_flush_pending_output
13872 md_flush_pending_output ();
13873 #endif
13874
13875 if (is_it_end_of_statement ())
13876 {
13877 demand_empty_rest_of_line ();
13878 return;
13879 }
13880
13881 #ifdef md_cons_align
13882 md_cons_align (nbytes);
13883 #endif
13884
13885 mapping_state (MAP_DATA);
13886 do
13887 {
13888 bfd_reloc_code_real_type reloc;
13889
13890 expression (& exp);
13891
13892 if (exp.X_op == O_symbol
13893 && * input_line_pointer == '('
13894 && (reloc = arm_parse_reloc ()) != BFD_RELOC_UNUSED)
13895 {
13896 reloc_howto_type *howto = bfd_reloc_type_lookup (stdoutput, reloc);
13897 int size = bfd_get_reloc_size (howto);
13898
13899 if (size > nbytes)
13900 as_bad ("%s relocations do not fit in %d bytes",
13901 howto->name, nbytes);
13902 else
13903 {
13904 char *p = frag_more ((int) nbytes);
13905 int offset = nbytes - size;
13906
13907 fix_new_exp (frag_now, p - frag_now->fr_literal + offset, size,
13908 &exp, 0, reloc);
13909 }
13910 }
13911 else
13912 emit_expr (&exp, (unsigned int) nbytes);
13913 }
13914 while (*input_line_pointer++ == ',');
13915
13916 /* Put terminator back into stream. */
13917 input_line_pointer --;
13918 demand_empty_rest_of_line ();
13919 }
13920
13921
13922 /* Parse a .rel31 directive. */
13923
13924 static void
13925 s_arm_rel31 (int ignored ATTRIBUTE_UNUSED)
13926 {
13927 expressionS exp;
13928 char *p;
13929 valueT highbit;
13930
13931 SKIP_WHITESPACE ();
13932
13933 highbit = 0;
13934 if (*input_line_pointer == '1')
13935 highbit = 0x80000000;
13936 else if (*input_line_pointer != '0')
13937 as_bad (_("expected 0 or 1"));
13938
13939 input_line_pointer++;
13940 SKIP_WHITESPACE ();
13941 if (*input_line_pointer != ',')
13942 as_bad (_("missing comma"));
13943 input_line_pointer++;
13944
13945 #ifdef md_flush_pending_output
13946 md_flush_pending_output ();
13947 #endif
13948
13949 #ifdef md_cons_align
13950 md_cons_align (4);
13951 #endif
13952
13953 mapping_state (MAP_DATA);
13954
13955 expression (&exp);
13956
13957 p = frag_more (4);
13958 md_number_to_chars (p, highbit, 4);
13959 fix_new_arm (frag_now, p - frag_now->fr_literal, 4, &exp, 1,
13960 BFD_RELOC_ARM_PREL31);
13961
13962 demand_empty_rest_of_line ();
13963 }
13964 \f
13965 /* Code to deal with unwinding tables. */
13966
13967 static void add_unwind_adjustsp (offsetT);
13968
13969 /* Switch to section NAME and create section if necessary. It's
13970 rather ugly that we have to manipulate input_line_pointer but I
13971 don't see any other way to accomplish the same thing without
13972 changing obj-elf.c (which may be the Right Thing, in the end).
13973 Copied from tc-ia64.c. */
13974
13975 static void
13976 set_section (char *name)
13977 {
13978 char *saved_input_line_pointer;
13979
13980 saved_input_line_pointer = input_line_pointer;
13981 input_line_pointer = name;
13982 obj_elf_section (0);
13983 input_line_pointer = saved_input_line_pointer;
13984 }
13985
13986 /* Cenerate and deferred unwind frame offset. */
13987
13988 static void
13989 flush_pending_unwind (void)
13990 {
13991 offsetT offset;
13992
13993 offset = unwind.pending_offset;
13994 unwind.pending_offset = 0;
13995 if (offset != 0)
13996 add_unwind_adjustsp (offset);
13997 }
13998
13999 /* Add an opcode to this list for this function. Two-byte opcodes should
14000 be passed as op[0] << 8 | op[1]. The list of opcodes is built in reverse
14001 order. */
14002
14003 static void
14004 add_unwind_opcode (valueT op, int length)
14005 {
14006 /* Add any deferred stack adjustment. */
14007 if (unwind.pending_offset)
14008 flush_pending_unwind ();
14009
14010 unwind.sp_restored = 0;
14011
14012 if (unwind.opcode_count + length > unwind.opcode_alloc)
14013 {
14014 unwind.opcode_alloc += ARM_OPCODE_CHUNK_SIZE;
14015 if (unwind.opcodes)
14016 unwind.opcodes = xrealloc (unwind.opcodes,
14017 unwind.opcode_alloc);
14018 else
14019 unwind.opcodes = xmalloc (unwind.opcode_alloc);
14020 }
14021 while (length > 0)
14022 {
14023 length--;
14024 unwind.opcodes[unwind.opcode_count] = op & 0xff;
14025 op >>= 8;
14026 unwind.opcode_count++;
14027 }
14028 }
14029
14030 /* Add unwind opcodes to adjust the stack pointer. */
14031
14032 static void
14033 add_unwind_adjustsp (offsetT offset)
14034 {
14035 valueT op;
14036
14037 if (offset > 0x200)
14038 {
14039 /* We need at most 5 bytes to hold a 32-bit value in a uleb128. */
14040 char bytes[5];
14041 int n;
14042 valueT o;
14043
14044 /* Long form: 0xb2, uleb128. */
14045 /* This might not fit in a word so add the individual bytes,
14046 remembering the list is built in reverse order. */
14047 o = (valueT) ((offset - 0x204) >> 2);
14048 if (o == 0)
14049 add_unwind_opcode (0, 1);
14050
14051 /* Calculate the uleb128 encoding of the offset. */
14052 n = 0;
14053 while (o)
14054 {
14055 bytes[n] = o & 0x7f;
14056 o >>= 7;
14057 if (o)
14058 bytes[n] |= 0x80;
14059 n++;
14060 }
14061 /* Add the insn. */
14062 for (; n; n--)
14063 add_unwind_opcode (bytes[n - 1], 1);
14064 add_unwind_opcode (0xb2, 1);
14065 }
14066 else if (offset > 0x100)
14067 {
14068 /* Two short opcodes. */
14069 add_unwind_opcode (0x3f, 1);
14070 op = (offset - 0x104) >> 2;
14071 add_unwind_opcode (op, 1);
14072 }
14073 else if (offset > 0)
14074 {
14075 /* Short opcode. */
14076 op = (offset - 4) >> 2;
14077 add_unwind_opcode (op, 1);
14078 }
14079 else if (offset < 0)
14080 {
14081 offset = -offset;
14082 while (offset > 0x100)
14083 {
14084 add_unwind_opcode (0x7f, 1);
14085 offset -= 0x100;
14086 }
14087 op = ((offset - 4) >> 2) | 0x40;
14088 add_unwind_opcode (op, 1);
14089 }
14090 }
14091
14092 /* Finish the list of unwind opcodes for this function. */
14093 static void
14094 finish_unwind_opcodes (void)
14095 {
14096 valueT op;
14097
14098 if (unwind.fp_used)
14099 {
14100 /* Adjust sp as neccessary. */
14101 unwind.pending_offset += unwind.fp_offset - unwind.frame_size;
14102 flush_pending_unwind ();
14103
14104 /* After restoring sp from the frame pointer. */
14105 op = 0x90 | unwind.fp_reg;
14106 add_unwind_opcode (op, 1);
14107 }
14108 else
14109 flush_pending_unwind ();
14110 }
14111
14112
14113 /* Start an exception table entry. If idx is nonzero this is an index table
14114 entry. */
14115
14116 static void
14117 start_unwind_section (const segT text_seg, int idx)
14118 {
14119 const char * text_name;
14120 const char * prefix;
14121 const char * prefix_once;
14122 size_t prefix_len;
14123 size_t text_len;
14124 char * sec_name;
14125 size_t sec_name_len;
14126
14127 if (idx)
14128 {
14129 prefix = ELF_STRING_ARM_unwind;
14130 prefix_once = ELF_STRING_ARM_unwind_once;
14131 }
14132 else
14133 {
14134 prefix = ELF_STRING_ARM_unwind_info;
14135 prefix_once = ELF_STRING_ARM_unwind_info_once;
14136 }
14137
14138 text_name = segment_name (text_seg);
14139 if (streq (text_name, ".text"))
14140 text_name = "";
14141
14142 if (strncmp (text_name, ".gnu.linkonce.t.",
14143 strlen (".gnu.linkonce.t.")) == 0)
14144 {
14145 prefix = prefix_once;
14146 text_name += strlen (".gnu.linkonce.t.");
14147 }
14148
14149 prefix_len = strlen (prefix);
14150 text_len = strlen (text_name);
14151 sec_name_len = prefix_len + text_len;
14152 sec_name = alloca (sec_name_len + 1);
14153 memcpy (sec_name, prefix, prefix_len);
14154 memcpy (sec_name + prefix_len, text_name, text_len);
14155 sec_name[prefix_len + text_len] = '\0';
14156
14157 /* Handle COMDAT group. */
14158 if (prefix != prefix_once && (text_seg->flags & SEC_LINK_ONCE) != 0)
14159 {
14160 char *section;
14161 size_t len, group_name_len;
14162 const char *group_name = elf_group_name (text_seg);
14163
14164 if (group_name == NULL)
14165 {
14166 as_bad ("Group section `%s' has no group signature",
14167 segment_name (text_seg));
14168 ignore_rest_of_line ();
14169 return;
14170 }
14171 /* We have to construct a fake section directive. */
14172 group_name_len = strlen (group_name);
14173 if (idx)
14174 prefix_len = 13;
14175 else
14176 prefix_len = 16;
14177
14178 len = (sec_name_len
14179 + prefix_len /* ,"aG",%sectiontype, */
14180 + group_name_len /* ,group_name */
14181 + 7); /* ,comdat */
14182
14183 section = alloca (len + 1);
14184 memcpy (section, sec_name, sec_name_len);
14185 if (idx)
14186 memcpy (section + sec_name_len, ",\"aG\",%exidx,", 13);
14187 else
14188 memcpy (section + sec_name_len, ",\"aG\",%progbits,", 16);
14189 memcpy (section + sec_name_len + prefix_len, group_name, group_name_len);
14190 memcpy (section + len - 7, ",comdat", 7);
14191 section [len] = '\0';
14192 set_section (section);
14193 }
14194 else
14195 {
14196 set_section (sec_name);
14197 bfd_set_section_flags (stdoutput, now_seg,
14198 SEC_LOAD | SEC_ALLOC | SEC_READONLY);
14199 }
14200
14201 /* Set the setion link for index tables. */
14202 if (idx)
14203 elf_linked_to_section (now_seg) = text_seg;
14204 }
14205
14206
14207 /* Start an unwind table entry. HAVE_DATA is nonzero if we have additional
14208 personality routine data. Returns zero, or the index table value for
14209 and inline entry. */
14210
14211 static valueT
14212 create_unwind_entry (int have_data)
14213 {
14214 int size;
14215 addressT where;
14216 char *ptr;
14217 /* The current word of data. */
14218 valueT data;
14219 /* The number of bytes left in this word. */
14220 int n;
14221
14222 finish_unwind_opcodes ();
14223
14224 /* Remember the current text section. */
14225 unwind.saved_seg = now_seg;
14226 unwind.saved_subseg = now_subseg;
14227
14228 start_unwind_section (now_seg, 0);
14229
14230 if (unwind.personality_routine == NULL)
14231 {
14232 if (unwind.personality_index == -2)
14233 {
14234 if (have_data)
14235 as_bad (_("handerdata in cantunwind frame"));
14236 return 1; /* EXIDX_CANTUNWIND. */
14237 }
14238
14239 /* Use a default personality routine if none is specified. */
14240 if (unwind.personality_index == -1)
14241 {
14242 if (unwind.opcode_count > 3)
14243 unwind.personality_index = 1;
14244 else
14245 unwind.personality_index = 0;
14246 }
14247
14248 /* Space for the personality routine entry. */
14249 if (unwind.personality_index == 0)
14250 {
14251 if (unwind.opcode_count > 3)
14252 as_bad (_("too many unwind opcodes for personality routine 0"));
14253
14254 if (!have_data)
14255 {
14256 /* All the data is inline in the index table. */
14257 data = 0x80;
14258 n = 3;
14259 while (unwind.opcode_count > 0)
14260 {
14261 unwind.opcode_count--;
14262 data = (data << 8) | unwind.opcodes[unwind.opcode_count];
14263 n--;
14264 }
14265
14266 /* Pad with "finish" opcodes. */
14267 while (n--)
14268 data = (data << 8) | 0xb0;
14269
14270 return data;
14271 }
14272 size = 0;
14273 }
14274 else
14275 /* We get two opcodes "free" in the first word. */
14276 size = unwind.opcode_count - 2;
14277 }
14278 else
14279 /* An extra byte is required for the opcode count. */
14280 size = unwind.opcode_count + 1;
14281
14282 size = (size + 3) >> 2;
14283 if (size > 0xff)
14284 as_bad (_("too many unwind opcodes"));
14285
14286 frag_align (2, 0, 0);
14287 record_alignment (now_seg, 2);
14288 unwind.table_entry = expr_build_dot ();
14289
14290 /* Allocate the table entry. */
14291 ptr = frag_more ((size << 2) + 4);
14292 where = frag_now_fix () - ((size << 2) + 4);
14293
14294 switch (unwind.personality_index)
14295 {
14296 case -1:
14297 /* ??? Should this be a PLT generating relocation? */
14298 /* Custom personality routine. */
14299 fix_new (frag_now, where, 4, unwind.personality_routine, 0, 1,
14300 BFD_RELOC_ARM_PREL31);
14301
14302 /* Indicate dependency to linker. */
14303 {
14304 char *name = "__aeabi_unwind_cpp_pr0";
14305 symbolS *pr = symbol_find_or_make (name);
14306 fix_new (frag_now, where, 4, pr, 0, 1, BFD_RELOC_NONE);
14307 }
14308
14309 where += 4;
14310 ptr += 4;
14311
14312 /* Set the first byte to the number of additional words. */
14313 data = size - 1;
14314 n = 3;
14315 break;
14316
14317 /* ABI defined personality routines. */
14318 case 0:
14319 /* Three opcodes bytes are packed into the first word. */
14320 data = 0x80;
14321 n = 3;
14322 goto emit_reloc;
14323
14324 case 1:
14325 case 2:
14326 /* The size and first two opcode bytes go in the first word. */
14327 data = ((0x80 + unwind.personality_index) << 8) | size;
14328 n = 2;
14329 goto emit_reloc;
14330
14331 emit_reloc:
14332 {
14333 /* Indicate dependency to linker. */
14334 char *name[] = { "__aeabi_unwind_cpp_pr0",
14335 "__aeabi_unwind_cpp_pr1",
14336 "__aeabi_unwind_cpp_pr2" };
14337 symbolS *pr = symbol_find_or_make (name[unwind.personality_index]);
14338 fix_new (frag_now, where, 4, pr, 0, 1, BFD_RELOC_NONE);
14339 }
14340 break;
14341
14342 default:
14343 /* Should never happen. */
14344 abort ();
14345 }
14346
14347 /* Pack the opcodes into words (MSB first), reversing the list at the same
14348 time. */
14349 while (unwind.opcode_count > 0)
14350 {
14351 if (n == 0)
14352 {
14353 md_number_to_chars (ptr, data, 4);
14354 ptr += 4;
14355 n = 4;
14356 data = 0;
14357 }
14358 unwind.opcode_count--;
14359 n--;
14360 data = (data << 8) | unwind.opcodes[unwind.opcode_count];
14361 }
14362
14363 /* Finish off the last word. */
14364 if (n < 4)
14365 {
14366 /* Pad with "finish" opcodes. */
14367 while (n--)
14368 data = (data << 8) | 0xb0;
14369
14370 md_number_to_chars (ptr, data, 4);
14371 }
14372
14373 if (!have_data)
14374 {
14375 /* Add an empty descriptor if there is no user-specified data. */
14376 ptr = frag_more (4);
14377 md_number_to_chars (ptr, 0, 4);
14378 }
14379
14380 return 0;
14381 }
14382
14383
14384 /* Parse an unwind_fnstart directive. Simply records the current location. */
14385
14386 static void
14387 s_arm_unwind_fnstart (int ignored ATTRIBUTE_UNUSED)
14388 {
14389 demand_empty_rest_of_line ();
14390 /* Mark the start of the function. */
14391 unwind.proc_start = expr_build_dot ();
14392
14393 /* Reset the rest of the unwind info. */
14394 unwind.opcode_count = 0;
14395 unwind.table_entry = NULL;
14396 unwind.personality_routine = NULL;
14397 unwind.personality_index = -1;
14398 unwind.frame_size = 0;
14399 unwind.fp_offset = 0;
14400 unwind.fp_reg = 13;
14401 unwind.fp_used = 0;
14402 unwind.sp_restored = 0;
14403 }
14404
14405
14406 /* Parse a handlerdata directive. Creates the exception handling table entry
14407 for the function. */
14408
14409 static void
14410 s_arm_unwind_handlerdata (int ignored ATTRIBUTE_UNUSED)
14411 {
14412 demand_empty_rest_of_line ();
14413 if (unwind.table_entry)
14414 as_bad (_("dupicate .handlerdata directive"));
14415
14416 create_unwind_entry (1);
14417 }
14418
14419 /* Parse an unwind_fnend directive. Generates the index table entry. */
14420
14421 static void
14422 s_arm_unwind_fnend (int ignored ATTRIBUTE_UNUSED)
14423 {
14424 long where;
14425 char *ptr;
14426 valueT val;
14427
14428 demand_empty_rest_of_line ();
14429
14430 /* Add eh table entry. */
14431 if (unwind.table_entry == NULL)
14432 val = create_unwind_entry (0);
14433 else
14434 val = 0;
14435
14436 /* Add index table entry. This is two words. */
14437 start_unwind_section (unwind.saved_seg, 1);
14438 frag_align (2, 0, 0);
14439 record_alignment (now_seg, 2);
14440
14441 ptr = frag_more (8);
14442 where = frag_now_fix () - 8;
14443
14444 /* Self relative offset of the function start. */
14445 fix_new (frag_now, where, 4, unwind.proc_start, 0, 1,
14446 BFD_RELOC_ARM_PREL31);
14447
14448 if (val)
14449 /* Inline exception table entry. */
14450 md_number_to_chars (ptr + 4, val, 4);
14451 else
14452 /* Self relative offset of the table entry. */
14453 fix_new (frag_now, where + 4, 4, unwind.table_entry, 0, 1,
14454 BFD_RELOC_ARM_PREL31);
14455
14456 /* Restore the original section. */
14457 subseg_set (unwind.saved_seg, unwind.saved_subseg);
14458 }
14459
14460
14461 /* Parse an unwind_cantunwind directive. */
14462
14463 static void
14464 s_arm_unwind_cantunwind (int ignored ATTRIBUTE_UNUSED)
14465 {
14466 demand_empty_rest_of_line ();
14467 if (unwind.personality_routine || unwind.personality_index != -1)
14468 as_bad (_("personality routine specified for cantunwind frame"));
14469
14470 unwind.personality_index = -2;
14471 }
14472
14473
14474 /* Parse a personalityindex directive. */
14475
14476 static void
14477 s_arm_unwind_personalityindex (int ignored ATTRIBUTE_UNUSED)
14478 {
14479 expressionS exp;
14480
14481 if (unwind.personality_routine || unwind.personality_index != -1)
14482 as_bad (_("duplicate .personalityindex directive"));
14483
14484 SKIP_WHITESPACE ();
14485
14486 expression (&exp);
14487
14488 if (exp.X_op != O_constant
14489 || exp.X_add_number < 0 || exp.X_add_number > 15)
14490 {
14491 as_bad (_("bad personality routine number"));
14492 ignore_rest_of_line ();
14493 return;
14494 }
14495
14496 unwind.personality_index = exp.X_add_number;
14497
14498 demand_empty_rest_of_line ();
14499 }
14500
14501
14502 /* Parse a personality directive. */
14503
14504 static void
14505 s_arm_unwind_personality (int ignored ATTRIBUTE_UNUSED)
14506 {
14507 char *name, *p, c;
14508
14509 if (unwind.personality_routine || unwind.personality_index != -1)
14510 as_bad (_("duplicate .personality directive"));
14511
14512 SKIP_WHITESPACE ();
14513 name = input_line_pointer;
14514 c = get_symbol_end ();
14515 p = input_line_pointer;
14516 unwind.personality_routine = symbol_find_or_make (name);
14517 *p = c;
14518 SKIP_WHITESPACE ();
14519 demand_empty_rest_of_line ();
14520 }
14521
14522
14523 /* Parse a directive saving core registers. */
14524
14525 static void
14526 s_arm_unwind_save_core (void)
14527 {
14528 valueT op;
14529 long range;
14530 int n;
14531
14532 SKIP_WHITESPACE ();
14533 range = reg_list (&input_line_pointer);
14534 if (range == FAIL)
14535 {
14536 as_bad (_("expected register list"));
14537 ignore_rest_of_line ();
14538 return;
14539 }
14540
14541 demand_empty_rest_of_line ();
14542
14543 /* Turn .unwind_movsp ip followed by .unwind_save {..., ip, ...}
14544 into .unwind_save {..., sp...}. We aren't bothered about the value of
14545 ip because it is clobbered by calls. */
14546 if (unwind.sp_restored && unwind.fp_reg == 12
14547 && (range & 0x3000) == 0x1000)
14548 {
14549 unwind.opcode_count--;
14550 unwind.sp_restored = 0;
14551 range = (range | 0x2000) & ~0x1000;
14552 unwind.pending_offset = 0;
14553 }
14554
14555 /* See if we can use the short opcodes. These pop a block of upto 8
14556 registers starting with r4, plus maybe r14. */
14557 for (n = 0; n < 8; n++)
14558 {
14559 /* Break at the first non-saved register. */
14560 if ((range & (1 << (n + 4))) == 0)
14561 break;
14562 }
14563 /* See if there are any other bits set. */
14564 if (n == 0 || (range & (0xfff0 << n) & 0xbff0) != 0)
14565 {
14566 /* Use the long form. */
14567 op = 0x8000 | ((range >> 4) & 0xfff);
14568 add_unwind_opcode (op, 2);
14569 }
14570 else
14571 {
14572 /* Use the short form. */
14573 if (range & 0x4000)
14574 op = 0xa8; /* Pop r14. */
14575 else
14576 op = 0xa0; /* Do not pop r14. */
14577 op |= (n - 1);
14578 add_unwind_opcode (op, 1);
14579 }
14580
14581 /* Pop r0-r3. */
14582 if (range & 0xf)
14583 {
14584 op = 0xb100 | (range & 0xf);
14585 add_unwind_opcode (op, 2);
14586 }
14587
14588 /* Record the number of bytes pushed. */
14589 for (n = 0; n < 16; n++)
14590 {
14591 if (range & (1 << n))
14592 unwind.frame_size += 4;
14593 }
14594 }
14595
14596
14597 /* Parse a directive saving FPA registers. */
14598
14599 static void
14600 s_arm_unwind_save_fpa (int reg)
14601 {
14602 expressionS exp;
14603 int num_regs;
14604 valueT op;
14605
14606 /* Get Number of registers to transfer. */
14607 if (skip_past_comma (&input_line_pointer) != FAIL)
14608 expression (&exp);
14609 else
14610 exp.X_op = O_illegal;
14611
14612 if (exp.X_op != O_constant)
14613 {
14614 as_bad (_("expected , <constant>"));
14615 ignore_rest_of_line ();
14616 return;
14617 }
14618
14619 num_regs = exp.X_add_number;
14620
14621 if (num_regs < 1 || num_regs > 4)
14622 {
14623 as_bad (_("number of registers must be in the range [1:4]"));
14624 ignore_rest_of_line ();
14625 return;
14626 }
14627
14628 demand_empty_rest_of_line ();
14629
14630 if (reg == 4)
14631 {
14632 /* Short form. */
14633 op = 0xb4 | (num_regs - 1);
14634 add_unwind_opcode (op, 1);
14635 }
14636 else
14637 {
14638 /* Long form. */
14639 op = 0xc800 | (reg << 4) | (num_regs - 1);
14640 add_unwind_opcode (op, 2);
14641 }
14642 unwind.frame_size += num_regs * 12;
14643 }
14644
14645
14646 /* Parse a directive saving VFP registers. */
14647
14648 static void
14649 s_arm_unwind_save_vfp (void)
14650 {
14651 int count;
14652 int reg;
14653 valueT op;
14654
14655 count = vfp_parse_reg_list (&input_line_pointer, &reg, 1);
14656 if (count == FAIL)
14657 {
14658 as_bad (_("expected register list"));
14659 ignore_rest_of_line ();
14660 return;
14661 }
14662
14663 demand_empty_rest_of_line ();
14664
14665 if (reg == 8)
14666 {
14667 /* Short form. */
14668 op = 0xb8 | (count - 1);
14669 add_unwind_opcode (op, 1);
14670 }
14671 else
14672 {
14673 /* Long form. */
14674 op = 0xb300 | (reg << 4) | (count - 1);
14675 add_unwind_opcode (op, 2);
14676 }
14677 unwind.frame_size += count * 8 + 4;
14678 }
14679
14680
14681 /* Parse a directive saving iWMMXt registers. */
14682
14683 static void
14684 s_arm_unwind_save_wmmx (void)
14685 {
14686 int reg;
14687 int hi_reg;
14688 int i;
14689 unsigned wcg_mask;
14690 unsigned wr_mask;
14691 valueT op;
14692
14693 if (*input_line_pointer == '{')
14694 input_line_pointer++;
14695
14696 wcg_mask = 0;
14697 wr_mask = 0;
14698 do
14699 {
14700 reg = arm_reg_parse (&input_line_pointer,
14701 all_reg_maps[REG_TYPE_IWMMXT].htab);
14702
14703 if (wr_register (reg))
14704 {
14705 i = reg & ~WR_PREFIX;
14706 if (wr_mask >> i)
14707 as_tsktsk (_("register list not in ascending order"));
14708 wr_mask |= 1 << i;
14709 }
14710 else if (wcg_register (reg))
14711 {
14712 i = (reg & ~WC_PREFIX) - 8;
14713 if (wcg_mask >> i)
14714 as_tsktsk (_("register list not in ascending order"));
14715 wcg_mask |= 1 << i;
14716 }
14717 else
14718 {
14719 as_bad (_("expected wr or wcgr"));
14720 goto error;
14721 }
14722
14723 SKIP_WHITESPACE ();
14724 if (*input_line_pointer == '-')
14725 {
14726 hi_reg = arm_reg_parse (&input_line_pointer,
14727 all_reg_maps[REG_TYPE_IWMMXT].htab);
14728 if (wr_register (reg) && wr_register (hi_reg))
14729 {
14730 for (; reg < hi_reg; reg++)
14731 wr_mask |= 1 << (reg & ~WR_PREFIX);
14732 }
14733 else if (wcg_register (reg) && wcg_register (hi_reg))
14734 {
14735 for (; reg < hi_reg; reg++)
14736 wcg_mask |= 1 << ((reg & ~WC_PREFIX) - 8);
14737 }
14738 else
14739 {
14740 as_bad (_("bad register range"));
14741 goto error;
14742 }
14743 }
14744 }
14745 while (skip_past_comma (&input_line_pointer) != FAIL);
14746
14747 SKIP_WHITESPACE ();
14748 if (*input_line_pointer == '}')
14749 input_line_pointer++;
14750
14751 demand_empty_rest_of_line ();
14752
14753 if (wr_mask && wcg_mask)
14754 {
14755 as_bad (_("inconsistent register types"));
14756 goto error;
14757 }
14758
14759 /* Generate any deferred opcodes becuuse we're going to be looking at
14760 the list. */
14761 flush_pending_unwind ();
14762
14763 if (wcg_mask)
14764 {
14765 for (i = 0; i < 16; i++)
14766 {
14767 if (wcg_mask & (1 << i))
14768 unwind.frame_size += 4;
14769 }
14770 op = 0xc700 | wcg_mask;
14771 add_unwind_opcode (op, 2);
14772 }
14773 else
14774 {
14775 for (i = 0; i < 16; i++)
14776 {
14777 if (wr_mask & (1 << i))
14778 unwind.frame_size += 8;
14779 }
14780 /* Attempt to combine with a previous opcode. We do this because gcc
14781 likes to output separate unwind directives for a single block of
14782 registers. */
14783 if (unwind.opcode_count > 0)
14784 {
14785 i = unwind.opcodes[unwind.opcode_count - 1];
14786 if ((i & 0xf8) == 0xc0)
14787 {
14788 i &= 7;
14789 /* Only merge if the blocks are contiguous. */
14790 if (i < 6)
14791 {
14792 if ((wr_mask & 0xfe00) == (1 << 9))
14793 {
14794 wr_mask |= ((1 << (i + 11)) - 1) & 0xfc00;
14795 unwind.opcode_count--;
14796 }
14797 }
14798 else if (i == 6 && unwind.opcode_count >= 2)
14799 {
14800 i = unwind.opcodes[unwind.opcode_count - 2];
14801 reg = i >> 4;
14802 i &= 0xf;
14803
14804 op = 0xffff << (reg - 1);
14805 if (reg > 0
14806 || ((wr_mask & op) == (1u << (reg - 1))))
14807 {
14808 op = (1 << (reg + i + 1)) - 1;
14809 op &= ~((1 << reg) - 1);
14810 wr_mask |= op;
14811 unwind.opcode_count -= 2;
14812 }
14813 }
14814 }
14815 }
14816
14817 hi_reg = 15;
14818 /* We want to generate opcodes in the order the registers have been
14819 saved, ie. descending order. */
14820 for (reg = 15; reg >= -1; reg--)
14821 {
14822 /* Save registers in blocks. */
14823 if (reg < 0
14824 || !(wr_mask & (1 << reg)))
14825 {
14826 /* We found an unsaved reg. Generate opcodes to save the
14827 preceeding block. */
14828 if (reg != hi_reg)
14829 {
14830 if (reg == 9)
14831 {
14832 /* Short form. */
14833 op = 0xc0 | (hi_reg - 10);
14834 add_unwind_opcode (op, 1);
14835 }
14836 else
14837 {
14838 /* Long form. */
14839 op = 0xc600 | ((reg + 1) << 4) | ((hi_reg - reg) - 1);
14840 add_unwind_opcode (op, 2);
14841 }
14842 }
14843 hi_reg = reg - 1;
14844 }
14845 }
14846 }
14847 return;
14848 error:
14849 ignore_rest_of_line ();
14850 }
14851
14852
14853 /* Parse an unwind_save directive. */
14854
14855 static void
14856 s_arm_unwind_save (int ignored ATTRIBUTE_UNUSED)
14857 {
14858 char *saved_ptr;
14859 int reg;
14860
14861 /* Figure out what sort of save we have. */
14862 SKIP_WHITESPACE ();
14863 saved_ptr = input_line_pointer;
14864
14865 reg = arm_reg_parse (&input_line_pointer, all_reg_maps[REG_TYPE_FN].htab);
14866 if (reg != FAIL)
14867 {
14868 s_arm_unwind_save_fpa (reg);
14869 return;
14870 }
14871
14872 if (*input_line_pointer == '{')
14873 input_line_pointer++;
14874
14875 SKIP_WHITESPACE ();
14876
14877 reg = arm_reg_parse (&input_line_pointer, all_reg_maps[REG_TYPE_RN].htab);
14878 if (reg != FAIL)
14879 {
14880 input_line_pointer = saved_ptr;
14881 s_arm_unwind_save_core ();
14882 return;
14883 }
14884
14885 reg = arm_reg_parse (&input_line_pointer, all_reg_maps[REG_TYPE_DN].htab);
14886 if (reg != FAIL)
14887 {
14888 input_line_pointer = saved_ptr;
14889 s_arm_unwind_save_vfp ();
14890 return;
14891 }
14892
14893 reg = arm_reg_parse (&input_line_pointer,
14894 all_reg_maps[REG_TYPE_IWMMXT].htab);
14895 if (reg != FAIL)
14896 {
14897 input_line_pointer = saved_ptr;
14898 s_arm_unwind_save_wmmx ();
14899 return;
14900 }
14901
14902 /* TODO: Maverick registers. */
14903 as_bad (_("unrecognised register"));
14904 }
14905
14906
14907 /* Parse an unwind_movsp directive. */
14908
14909 static void
14910 s_arm_unwind_movsp (int ignored ATTRIBUTE_UNUSED)
14911 {
14912 int reg;
14913 valueT op;
14914
14915 SKIP_WHITESPACE ();
14916 reg = reg_required_here (&input_line_pointer, -1);
14917 if (reg == FAIL)
14918 {
14919 as_bad (_("ARM register expected"));
14920 ignore_rest_of_line ();
14921 return;
14922 }
14923
14924 if (reg == 13 || reg == 15)
14925 {
14926 as_bad (_("r%d not permitted in .unwind_movsp directive"), reg);
14927 ignore_rest_of_line ();
14928 return;
14929 }
14930
14931 if (unwind.fp_reg != 13)
14932 as_bad (_("unexpected .unwind_movsp directive"));
14933
14934 /* Generate opcode to restore the value. */
14935 op = 0x90 | reg;
14936 add_unwind_opcode (op, 1);
14937
14938 /* Record the information for later. */
14939 unwind.fp_reg = reg;
14940 unwind.fp_offset = unwind.frame_size;
14941 unwind.sp_restored = 1;
14942 demand_empty_rest_of_line ();
14943 }
14944
14945
14946 /* Parse #<number>. */
14947
14948 static int
14949 require_hashconst (int * val)
14950 {
14951 expressionS exp;
14952
14953 SKIP_WHITESPACE ();
14954 if (*input_line_pointer == '#')
14955 {
14956 input_line_pointer++;
14957 expression (&exp);
14958 }
14959 else
14960 exp.X_op = O_illegal;
14961
14962 if (exp.X_op != O_constant)
14963 {
14964 as_bad (_("expected #constant"));
14965 ignore_rest_of_line ();
14966 return FAIL;
14967 }
14968 *val = exp.X_add_number;
14969 return SUCCESS;
14970 }
14971
14972 /* Parse an unwind_pad directive. */
14973
14974 static void
14975 s_arm_unwind_pad (int ignored ATTRIBUTE_UNUSED)
14976 {
14977 int offset;
14978
14979 if (require_hashconst (&offset) == FAIL)
14980 return;
14981
14982 if (offset & 3)
14983 {
14984 as_bad (_("stack increment must be multiple of 4"));
14985 ignore_rest_of_line ();
14986 return;
14987 }
14988
14989 /* Don't generate any opcodes, just record the details for later. */
14990 unwind.frame_size += offset;
14991 unwind.pending_offset += offset;
14992
14993 demand_empty_rest_of_line ();
14994 }
14995
14996 /* Parse an unwind_setfp directive. */
14997
14998 static void
14999 s_arm_unwind_setfp (int ignored ATTRIBUTE_UNUSED)
15000 {
15001 int sp_reg;
15002 int fp_reg;
15003 int offset;
15004
15005 fp_reg = reg_required_here (&input_line_pointer, -1);
15006 if (skip_past_comma (&input_line_pointer) == FAIL)
15007 sp_reg = FAIL;
15008 else
15009 sp_reg = reg_required_here (&input_line_pointer, -1);
15010
15011 if (fp_reg == FAIL || sp_reg == FAIL)
15012 {
15013 as_bad (_("expected <reg>, <reg>"));
15014 ignore_rest_of_line ();
15015 return;
15016 }
15017
15018 /* Optonal constant. */
15019 if (skip_past_comma (&input_line_pointer) != FAIL)
15020 {
15021 if (require_hashconst (&offset) == FAIL)
15022 return;
15023 }
15024 else
15025 offset = 0;
15026
15027 demand_empty_rest_of_line ();
15028
15029 if (sp_reg != 13 && sp_reg != unwind.fp_reg)
15030 {
15031 as_bad (_("register must be either sp or set by a previous"
15032 "unwind_movsp directive"));
15033 return;
15034 }
15035
15036 /* Don't generate any opcodes, just record the information for later. */
15037 unwind.fp_reg = fp_reg;
15038 unwind.fp_used = 1;
15039 if (sp_reg == 13)
15040 unwind.fp_offset = unwind.frame_size - offset;
15041 else
15042 unwind.fp_offset -= offset;
15043 }
15044
15045 /* Parse an unwind_raw directive. */
15046
15047 static void
15048 s_arm_unwind_raw (int ignored ATTRIBUTE_UNUSED)
15049 {
15050 expressionS exp;
15051 /* This is an arbitary limit. */
15052 unsigned char op[16];
15053 int count;
15054
15055 SKIP_WHITESPACE ();
15056 expression (&exp);
15057 if (exp.X_op == O_constant
15058 && skip_past_comma (&input_line_pointer) != FAIL)
15059 {
15060 unwind.frame_size += exp.X_add_number;
15061 expression (&exp);
15062 }
15063 else
15064 exp.X_op = O_illegal;
15065
15066 if (exp.X_op != O_constant)
15067 {
15068 as_bad (_("expected <offset>, <opcode>"));
15069 ignore_rest_of_line ();
15070 return;
15071 }
15072
15073 count = 0;
15074
15075 /* Parse the opcode. */
15076 for (;;)
15077 {
15078 if (count >= 16)
15079 {
15080 as_bad (_("unwind opcode too long"));
15081 ignore_rest_of_line ();
15082 }
15083 if (exp.X_op != O_constant || exp.X_add_number & ~0xff)
15084 {
15085 as_bad (_("invalid unwind opcode"));
15086 ignore_rest_of_line ();
15087 return;
15088 }
15089 op[count++] = exp.X_add_number;
15090
15091 /* Parse the next byte. */
15092 if (skip_past_comma (&input_line_pointer) == FAIL)
15093 break;
15094
15095 expression (&exp);
15096 }
15097
15098 /* Add the opcode bytes in reverse order. */
15099 while (count--)
15100 add_unwind_opcode (op[count], 1);
15101
15102 demand_empty_rest_of_line ();
15103 }
15104
15105 #endif /* OBJ_ELF */
15106
15107 /* This is called from HANDLE_ALIGN in write.c. Fill in the contents
15108 of an rs_align_code fragment. */
15109
15110 void
15111 arm_handle_align (fragS * fragP)
15112 {
15113 static char const arm_noop[4] = { 0x00, 0x00, 0xa0, 0xe1 };
15114 static char const thumb_noop[2] = { 0xc0, 0x46 };
15115 static char const arm_bigend_noop[4] = { 0xe1, 0xa0, 0x00, 0x00 };
15116 static char const thumb_bigend_noop[2] = { 0x46, 0xc0 };
15117
15118 int bytes, fix, noop_size;
15119 char * p;
15120 const char * noop;
15121
15122 if (fragP->fr_type != rs_align_code)
15123 return;
15124
15125 bytes = fragP->fr_next->fr_address - fragP->fr_address - fragP->fr_fix;
15126 p = fragP->fr_literal + fragP->fr_fix;
15127 fix = 0;
15128
15129 if (bytes > MAX_MEM_FOR_RS_ALIGN_CODE)
15130 bytes &= MAX_MEM_FOR_RS_ALIGN_CODE;
15131
15132 if (fragP->tc_frag_data)
15133 {
15134 if (target_big_endian)
15135 noop = thumb_bigend_noop;
15136 else
15137 noop = thumb_noop;
15138 noop_size = sizeof (thumb_noop);
15139 }
15140 else
15141 {
15142 if (target_big_endian)
15143 noop = arm_bigend_noop;
15144 else
15145 noop = arm_noop;
15146 noop_size = sizeof (arm_noop);
15147 }
15148
15149 if (bytes & (noop_size - 1))
15150 {
15151 fix = bytes & (noop_size - 1);
15152 memset (p, 0, fix);
15153 p += fix;
15154 bytes -= fix;
15155 }
15156
15157 while (bytes >= noop_size)
15158 {
15159 memcpy (p, noop, noop_size);
15160 p += noop_size;
15161 bytes -= noop_size;
15162 fix += noop_size;
15163 }
15164
15165 fragP->fr_fix += fix;
15166 fragP->fr_var = noop_size;
15167 }
15168
15169 /* Called from md_do_align. Used to create an alignment
15170 frag in a code section. */
15171
15172 void
15173 arm_frag_align_code (int n, int max)
15174 {
15175 char * p;
15176
15177 /* We assume that there will never be a requirement
15178 to support alignments greater than 32 bytes. */
15179 if (max > MAX_MEM_FOR_RS_ALIGN_CODE)
15180 as_fatal (_("alignments greater than 32 bytes not supported in .text sections."));
15181
15182 p = frag_var (rs_align_code,
15183 MAX_MEM_FOR_RS_ALIGN_CODE,
15184 1,
15185 (relax_substateT) max,
15186 (symbolS *) NULL,
15187 (offsetT) n,
15188 (char *) NULL);
15189 *p = 0;
15190 }
15191
15192 /* Perform target specific initialisation of a frag. */
15193
15194 void
15195 arm_init_frag (fragS * fragP)
15196 {
15197 /* Record whether this frag is in an ARM or a THUMB area. */
15198 fragP->tc_frag_data = thumb_mode;
15199 }
15200
15201 #ifdef OBJ_ELF
15202
15203 /* Convert REGNAME to a DWARF-2 register number. */
15204
15205 int
15206 tc_arm_regname_to_dw2regnum (const char *regname)
15207 {
15208 unsigned int i;
15209
15210 for (i = 0; rn_table[i].name; i++)
15211 if (streq (regname, rn_table[i].name))
15212 return rn_table[i].number;
15213
15214 return -1;
15215 }
15216
15217 /* Initialize the DWARF-2 unwind information for this procedure. */
15218
15219 void
15220 tc_arm_frame_initial_instructions (void)
15221 {
15222 cfi_add_CFA_def_cfa (REG_SP, 0);
15223 }
15224 #endif
15225
15226 /* This table describes all the machine specific pseudo-ops the assembler
15227 has to support. The fields are:
15228 pseudo-op name without dot
15229 function to call to execute this pseudo-op
15230 Integer arg to pass to the function. */
15231
15232 const pseudo_typeS md_pseudo_table[] =
15233 {
15234 /* Never called because '.req' does not start a line. */
15235 { "req", s_req, 0 },
15236 { "unreq", s_unreq, 0 },
15237 { "bss", s_bss, 0 },
15238 { "align", s_align, 0 },
15239 { "arm", s_arm, 0 },
15240 { "thumb", s_thumb, 0 },
15241 { "code", s_code, 0 },
15242 { "force_thumb", s_force_thumb, 0 },
15243 { "thumb_func", s_thumb_func, 0 },
15244 { "thumb_set", s_thumb_set, 0 },
15245 { "even", s_even, 0 },
15246 { "ltorg", s_ltorg, 0 },
15247 { "pool", s_ltorg, 0 },
15248 #ifdef OBJ_ELF
15249 { "word", s_arm_elf_cons, 4 },
15250 { "long", s_arm_elf_cons, 4 },
15251 { "rel31", s_arm_rel31, 0 },
15252 { "fnstart", s_arm_unwind_fnstart, 0 },
15253 { "fnend", s_arm_unwind_fnend, 0 },
15254 { "cantunwind", s_arm_unwind_cantunwind, 0 },
15255 { "personality", s_arm_unwind_personality, 0 },
15256 { "personalityindex", s_arm_unwind_personalityindex, 0 },
15257 { "handlerdata", s_arm_unwind_handlerdata, 0 },
15258 { "save", s_arm_unwind_save, 0 },
15259 { "movsp", s_arm_unwind_movsp, 0 },
15260 { "pad", s_arm_unwind_pad, 0 },
15261 { "setfp", s_arm_unwind_setfp, 0 },
15262 { "unwind_raw", s_arm_unwind_raw, 0 },
15263 #else
15264 { "word", cons, 4},
15265 #endif
15266 { "extend", float_cons, 'x' },
15267 { "ldouble", float_cons, 'x' },
15268 { "packed", float_cons, 'p' },
15269 { 0, 0, 0 }
15270 };