* config/tc-mips.c (append_insn): Use fix_new rather than fix_new_exp
[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, 2004
3 Free Software Foundation, Inc.
4 Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org)
5 Modified by David Taylor (dtaylor@armltd.co.uk)
6 Cirrus coprocessor mods by Aldy Hernandez (aldyh@redhat.com)
7 Cirrus coprocessor fixes by Petko Manolov (petkan@nucleusys.com)
8 Cirrus coprocessor fixes by Vladimir Ivanov (vladitx@nucleusys.com)
9
10 This file is part of GAS, the GNU Assembler.
11
12 GAS is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2, or (at your option)
15 any later version.
16
17 GAS is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
21
22 You should have received a copy of the GNU General Public License
23 along with GAS; see the file COPYING. If not, write to the Free
24 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
25 02111-1307, USA. */
26
27 #include <string.h>
28 #define NO_RELOC 0
29 #include "as.h"
30 #include "safe-ctype.h"
31
32 /* Need TARGET_CPU. */
33 #include "config.h"
34 #include "subsegs.h"
35 #include "obstack.h"
36 #include "symbols.h"
37 #include "listing.h"
38
39 #include "opcode/arm.h"
40
41 #ifdef OBJ_ELF
42 #include "elf/arm.h"
43 #include "dwarf2dbg.h"
44 #endif
45
46 /* XXX Set this to 1 after the next binutils release. */
47 #define WARN_DEPRECATED 0
48
49 #ifdef OBJ_ELF
50 /* Must be at least the size of the largest unwind opcode (currently two). */
51 #define ARM_OPCODE_CHUNK_SIZE 8
52
53 /* This structure holds the unwinding state. */
54
55 static struct
56 {
57 symbolS * proc_start;
58 symbolS * table_entry;
59 symbolS * personality_routine;
60 int personality_index;
61 /* The segment containing the function. */
62 segT saved_seg;
63 subsegT saved_subseg;
64 /* Opcodes generated from this function. */
65 unsigned char * opcodes;
66 int opcode_count;
67 int opcode_alloc;
68 /* The number of bytes pushed to the stack. */
69 offsetT frame_size;
70 /* We don't add stack adjustment opcodes immediately so that we can merge
71 multiple adjustments. We can also omit the final adjustment
72 when using a frame pointer. */
73 offsetT pending_offset;
74 /* These two fields are set by both unwind_movsp and unwind_setfp. They
75 hold the reg+offset to use when restoring sp from a frame pointer. */
76 offsetT fp_offset;
77 int fp_reg;
78 /* Nonzero if an unwind_setfp directive has been seen. */
79 unsigned fp_used:1;
80 /* Nonzero if the last opcode restores sp from fp_reg. */
81 unsigned sp_restored:1;
82 } unwind;
83
84 #endif /* OBJ_ELF */
85
86 enum arm_float_abi
87 {
88 ARM_FLOAT_ABI_HARD,
89 ARM_FLOAT_ABI_SOFTFP,
90 ARM_FLOAT_ABI_SOFT
91 };
92
93 /* Types of processor to assemble for. */
94 #define ARM_1 ARM_ARCH_V1
95 #define ARM_2 ARM_ARCH_V2
96 #define ARM_3 ARM_ARCH_V2S
97 #define ARM_250 ARM_ARCH_V2S
98 #define ARM_6 ARM_ARCH_V3
99 #define ARM_7 ARM_ARCH_V3
100 #define ARM_8 ARM_ARCH_V4
101 #define ARM_9 ARM_ARCH_V4T
102 #define ARM_STRONG ARM_ARCH_V4
103 #define ARM_CPU_MASK 0x0000000f /* XXX? */
104
105 #ifndef CPU_DEFAULT
106 #if defined __XSCALE__
107 #define CPU_DEFAULT (ARM_ARCH_XSCALE)
108 #else
109 #if defined __thumb__
110 #define CPU_DEFAULT (ARM_ARCH_V5T)
111 #else
112 #define CPU_DEFAULT ARM_ANY
113 #endif
114 #endif
115 #endif
116
117 #ifdef TE_LINUX
118 #define FPU_DEFAULT FPU_ARCH_FPA
119 #endif
120
121 #ifdef TE_NetBSD
122 #ifdef OBJ_ELF
123 #define FPU_DEFAULT FPU_ARCH_VFP /* Soft-float, but VFP order. */
124 #else
125 /* Legacy a.out format. */
126 #define FPU_DEFAULT FPU_ARCH_FPA /* Soft-float, but FPA order. */
127 #endif
128 #endif
129
130 /* For backwards compatibility we default to the FPA. */
131 #ifndef FPU_DEFAULT
132 #define FPU_DEFAULT FPU_ARCH_FPA
133 #endif
134
135 #define streq(a, b) (strcmp (a, b) == 0)
136 #define skip_whitespace(str) while (*(str) == ' ') ++(str)
137
138 static unsigned long cpu_variant;
139 static int target_oabi = 0;
140
141 /* Flags stored in private area of BFD structure. */
142 static int uses_apcs_26 = FALSE;
143 static int atpcs = FALSE;
144 static int support_interwork = FALSE;
145 static int uses_apcs_float = FALSE;
146 static int pic_code = FALSE;
147
148 /* Variables that we set while parsing command-line options. Once all
149 options have been read we re-process these values to set the real
150 assembly flags. */
151 static int legacy_cpu = -1;
152 static int legacy_fpu = -1;
153
154 static int mcpu_cpu_opt = -1;
155 static int mcpu_fpu_opt = -1;
156 static int march_cpu_opt = -1;
157 static int march_fpu_opt = -1;
158 static int mfpu_opt = -1;
159 static int mfloat_abi_opt = -1;
160 #ifdef OBJ_ELF
161 static int meabi_flags = EF_ARM_EABI_UNKNOWN;
162 #endif
163
164 /* This array holds the chars that always start a comment. If the
165 pre-processor is disabled, these aren't very useful. */
166 const char comment_chars[] = "@";
167
168 /* This array holds the chars that only start a comment at the beginning of
169 a line. If the line seems to have the form '# 123 filename'
170 .line and .file directives will appear in the pre-processed output. */
171 /* Note that input_file.c hand checks for '#' at the beginning of the
172 first line of the input file. This is because the compiler outputs
173 #NO_APP at the beginning of its output. */
174 /* Also note that comments like this one will always work. */
175 const char line_comment_chars[] = "#";
176
177 const char line_separator_chars[] = ";";
178
179 /* Chars that can be used to separate mant
180 from exp in floating point numbers. */
181 const char EXP_CHARS[] = "eE";
182
183 /* Chars that mean this number is a floating point constant. */
184 /* As in 0f12.456 */
185 /* or 0d1.2345e12 */
186
187 const char FLT_CHARS[] = "rRsSfFdDxXeEpP";
188
189 /* Prefix characters that indicate the start of an immediate
190 value. */
191 #define is_immediate_prefix(C) ((C) == '#' || (C) == '$')
192
193 #ifdef OBJ_ELF
194 /* Pre-defined "_GLOBAL_OFFSET_TABLE_" */
195 symbolS * GOT_symbol;
196 #endif
197
198 /* Size of relocation record. */
199 const int md_reloc_size = 8;
200
201 /* 0: assemble for ARM,
202 1: assemble for Thumb,
203 2: assemble for Thumb even though target CPU does not support thumb
204 instructions. */
205 static int thumb_mode = 0;
206
207 typedef struct arm_fix
208 {
209 int thumb_mode;
210 } arm_fix_data;
211
212 struct arm_it
213 {
214 const char * error;
215 unsigned long instruction;
216 int size;
217 struct
218 {
219 bfd_reloc_code_real_type type;
220 expressionS exp;
221 int pc_rel;
222 } reloc;
223 };
224
225 struct arm_it inst;
226
227 enum asm_shift_index
228 {
229 SHIFT_LSL = 0,
230 SHIFT_LSR,
231 SHIFT_ASR,
232 SHIFT_ROR,
233 SHIFT_RRX
234 };
235
236 struct asm_shift_properties
237 {
238 enum asm_shift_index index;
239 unsigned long bit_field;
240 unsigned int allows_0 : 1;
241 unsigned int allows_32 : 1;
242 };
243
244 static const struct asm_shift_properties shift_properties [] =
245 {
246 { SHIFT_LSL, 0, 1, 0},
247 { SHIFT_LSR, 0x20, 0, 1},
248 { SHIFT_ASR, 0x40, 0, 1},
249 { SHIFT_ROR, 0x60, 0, 0},
250 { SHIFT_RRX, 0x60, 0, 0}
251 };
252
253 struct asm_shift_name
254 {
255 const char * name;
256 const struct asm_shift_properties * properties;
257 };
258
259 static const struct asm_shift_name shift_names [] =
260 {
261 { "asl", shift_properties + SHIFT_LSL },
262 { "lsl", shift_properties + SHIFT_LSL },
263 { "lsr", shift_properties + SHIFT_LSR },
264 { "asr", shift_properties + SHIFT_ASR },
265 { "ror", shift_properties + SHIFT_ROR },
266 { "rrx", shift_properties + SHIFT_RRX },
267 { "ASL", shift_properties + SHIFT_LSL },
268 { "LSL", shift_properties + SHIFT_LSL },
269 { "LSR", shift_properties + SHIFT_LSR },
270 { "ASR", shift_properties + SHIFT_ASR },
271 { "ROR", shift_properties + SHIFT_ROR },
272 { "RRX", shift_properties + SHIFT_RRX }
273 };
274
275 /* Any kind of shift is accepted. */
276 #define NO_SHIFT_RESTRICT 1
277 /* The shift operand must be an immediate value, not a register. */
278 #define SHIFT_IMMEDIATE 0
279 /* The shift must be LSL or ASR and the operand must be an immediate. */
280 #define SHIFT_LSL_OR_ASR_IMMEDIATE 2
281 /* The shift must be ASR and the operand must be an immediate. */
282 #define SHIFT_ASR_IMMEDIATE 3
283 /* The shift must be LSL and the operand must be an immediate. */
284 #define SHIFT_LSL_IMMEDIATE 4
285
286 #define NUM_FLOAT_VALS 8
287
288 const char * fp_const[] =
289 {
290 "0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0", 0
291 };
292
293 /* Number of littlenums required to hold an extended precision number. */
294 #define MAX_LITTLENUMS 6
295
296 LITTLENUM_TYPE fp_values[NUM_FLOAT_VALS][MAX_LITTLENUMS];
297
298 #define FAIL (-1)
299 #define SUCCESS (0)
300
301 /* Whether a Co-processor load/store operation accepts write-back forms. */
302 #define CP_WB_OK 1
303 #define CP_NO_WB 0
304
305 #define SUFF_S 1
306 #define SUFF_D 2
307 #define SUFF_E 3
308 #define SUFF_P 4
309
310 #define CP_T_X 0x00008000
311 #define CP_T_Y 0x00400000
312 #define CP_T_Pre 0x01000000
313 #define CP_T_UD 0x00800000
314 #define CP_T_WB 0x00200000
315
316 #define CONDS_BIT 0x00100000
317 #define LOAD_BIT 0x00100000
318
319 #define DOUBLE_LOAD_FLAG 0x00000001
320
321 struct asm_cond
322 {
323 const char * template;
324 unsigned long value;
325 };
326
327 #define COND_ALWAYS 0xe0000000
328 #define COND_MASK 0xf0000000
329
330 static const struct asm_cond conds[] =
331 {
332 {"eq", 0x00000000},
333 {"ne", 0x10000000},
334 {"cs", 0x20000000}, {"hs", 0x20000000},
335 {"cc", 0x30000000}, {"ul", 0x30000000}, {"lo", 0x30000000},
336 {"mi", 0x40000000},
337 {"pl", 0x50000000},
338 {"vs", 0x60000000},
339 {"vc", 0x70000000},
340 {"hi", 0x80000000},
341 {"ls", 0x90000000},
342 {"ge", 0xa0000000},
343 {"lt", 0xb0000000},
344 {"gt", 0xc0000000},
345 {"le", 0xd0000000},
346 {"al", 0xe0000000},
347 {"nv", 0xf0000000}
348 };
349
350 struct asm_psr
351 {
352 const char *template;
353 bfd_boolean cpsr;
354 unsigned long field;
355 };
356
357 /* The bit that distinguishes CPSR and SPSR. */
358 #define SPSR_BIT (1 << 22)
359
360 /* How many bits to shift the PSR_xxx bits up by. */
361 #define PSR_SHIFT 16
362
363 #define PSR_c (1 << 0)
364 #define PSR_x (1 << 1)
365 #define PSR_s (1 << 2)
366 #define PSR_f (1 << 3)
367
368 static const struct asm_psr psrs[] =
369 {
370 {"CPSR", TRUE, PSR_c | PSR_f},
371 {"CPSR_all", TRUE, PSR_c | PSR_f},
372 {"SPSR", FALSE, PSR_c | PSR_f},
373 {"SPSR_all", FALSE, PSR_c | PSR_f},
374 {"CPSR_flg", TRUE, PSR_f},
375 {"CPSR_f", TRUE, PSR_f},
376 {"SPSR_flg", FALSE, PSR_f},
377 {"SPSR_f", FALSE, PSR_f},
378 {"CPSR_c", TRUE, PSR_c},
379 {"CPSR_ctl", TRUE, PSR_c},
380 {"SPSR_c", FALSE, PSR_c},
381 {"SPSR_ctl", FALSE, PSR_c},
382 {"CPSR_x", TRUE, PSR_x},
383 {"CPSR_s", TRUE, PSR_s},
384 {"SPSR_x", FALSE, PSR_x},
385 {"SPSR_s", FALSE, PSR_s},
386 /* Combinations of flags. */
387 {"CPSR_fs", TRUE, PSR_f | PSR_s},
388 {"CPSR_fx", TRUE, PSR_f | PSR_x},
389 {"CPSR_fc", TRUE, PSR_f | PSR_c},
390 {"CPSR_sf", TRUE, PSR_s | PSR_f},
391 {"CPSR_sx", TRUE, PSR_s | PSR_x},
392 {"CPSR_sc", TRUE, PSR_s | PSR_c},
393 {"CPSR_xf", TRUE, PSR_x | PSR_f},
394 {"CPSR_xs", TRUE, PSR_x | PSR_s},
395 {"CPSR_xc", TRUE, PSR_x | PSR_c},
396 {"CPSR_cf", TRUE, PSR_c | PSR_f},
397 {"CPSR_cs", TRUE, PSR_c | PSR_s},
398 {"CPSR_cx", TRUE, PSR_c | PSR_x},
399 {"CPSR_fsx", TRUE, PSR_f | PSR_s | PSR_x},
400 {"CPSR_fsc", TRUE, PSR_f | PSR_s | PSR_c},
401 {"CPSR_fxs", TRUE, PSR_f | PSR_x | PSR_s},
402 {"CPSR_fxc", TRUE, PSR_f | PSR_x | PSR_c},
403 {"CPSR_fcs", TRUE, PSR_f | PSR_c | PSR_s},
404 {"CPSR_fcx", TRUE, PSR_f | PSR_c | PSR_x},
405 {"CPSR_sfx", TRUE, PSR_s | PSR_f | PSR_x},
406 {"CPSR_sfc", TRUE, PSR_s | PSR_f | PSR_c},
407 {"CPSR_sxf", TRUE, PSR_s | PSR_x | PSR_f},
408 {"CPSR_sxc", TRUE, PSR_s | PSR_x | PSR_c},
409 {"CPSR_scf", TRUE, PSR_s | PSR_c | PSR_f},
410 {"CPSR_scx", TRUE, PSR_s | PSR_c | PSR_x},
411 {"CPSR_xfs", TRUE, PSR_x | PSR_f | PSR_s},
412 {"CPSR_xfc", TRUE, PSR_x | PSR_f | PSR_c},
413 {"CPSR_xsf", TRUE, PSR_x | PSR_s | PSR_f},
414 {"CPSR_xsc", TRUE, PSR_x | PSR_s | PSR_c},
415 {"CPSR_xcf", TRUE, PSR_x | PSR_c | PSR_f},
416 {"CPSR_xcs", TRUE, PSR_x | PSR_c | PSR_s},
417 {"CPSR_cfs", TRUE, PSR_c | PSR_f | PSR_s},
418 {"CPSR_cfx", TRUE, PSR_c | PSR_f | PSR_x},
419 {"CPSR_csf", TRUE, PSR_c | PSR_s | PSR_f},
420 {"CPSR_csx", TRUE, PSR_c | PSR_s | PSR_x},
421 {"CPSR_cxf", TRUE, PSR_c | PSR_x | PSR_f},
422 {"CPSR_cxs", TRUE, PSR_c | PSR_x | PSR_s},
423 {"CPSR_fsxc", TRUE, PSR_f | PSR_s | PSR_x | PSR_c},
424 {"CPSR_fscx", TRUE, PSR_f | PSR_s | PSR_c | PSR_x},
425 {"CPSR_fxsc", TRUE, PSR_f | PSR_x | PSR_s | PSR_c},
426 {"CPSR_fxcs", TRUE, PSR_f | PSR_x | PSR_c | PSR_s},
427 {"CPSR_fcsx", TRUE, PSR_f | PSR_c | PSR_s | PSR_x},
428 {"CPSR_fcxs", TRUE, PSR_f | PSR_c | PSR_x | PSR_s},
429 {"CPSR_sfxc", TRUE, PSR_s | PSR_f | PSR_x | PSR_c},
430 {"CPSR_sfcx", TRUE, PSR_s | PSR_f | PSR_c | PSR_x},
431 {"CPSR_sxfc", TRUE, PSR_s | PSR_x | PSR_f | PSR_c},
432 {"CPSR_sxcf", TRUE, PSR_s | PSR_x | PSR_c | PSR_f},
433 {"CPSR_scfx", TRUE, PSR_s | PSR_c | PSR_f | PSR_x},
434 {"CPSR_scxf", TRUE, PSR_s | PSR_c | PSR_x | PSR_f},
435 {"CPSR_xfsc", TRUE, PSR_x | PSR_f | PSR_s | PSR_c},
436 {"CPSR_xfcs", TRUE, PSR_x | PSR_f | PSR_c | PSR_s},
437 {"CPSR_xsfc", TRUE, PSR_x | PSR_s | PSR_f | PSR_c},
438 {"CPSR_xscf", TRUE, PSR_x | PSR_s | PSR_c | PSR_f},
439 {"CPSR_xcfs", TRUE, PSR_x | PSR_c | PSR_f | PSR_s},
440 {"CPSR_xcsf", TRUE, PSR_x | PSR_c | PSR_s | PSR_f},
441 {"CPSR_cfsx", TRUE, PSR_c | PSR_f | PSR_s | PSR_x},
442 {"CPSR_cfxs", TRUE, PSR_c | PSR_f | PSR_x | PSR_s},
443 {"CPSR_csfx", TRUE, PSR_c | PSR_s | PSR_f | PSR_x},
444 {"CPSR_csxf", TRUE, PSR_c | PSR_s | PSR_x | PSR_f},
445 {"CPSR_cxfs", TRUE, PSR_c | PSR_x | PSR_f | PSR_s},
446 {"CPSR_cxsf", TRUE, PSR_c | PSR_x | PSR_s | PSR_f},
447 {"SPSR_fs", FALSE, PSR_f | PSR_s},
448 {"SPSR_fx", FALSE, PSR_f | PSR_x},
449 {"SPSR_fc", FALSE, PSR_f | PSR_c},
450 {"SPSR_sf", FALSE, PSR_s | PSR_f},
451 {"SPSR_sx", FALSE, PSR_s | PSR_x},
452 {"SPSR_sc", FALSE, PSR_s | PSR_c},
453 {"SPSR_xf", FALSE, PSR_x | PSR_f},
454 {"SPSR_xs", FALSE, PSR_x | PSR_s},
455 {"SPSR_xc", FALSE, PSR_x | PSR_c},
456 {"SPSR_cf", FALSE, PSR_c | PSR_f},
457 {"SPSR_cs", FALSE, PSR_c | PSR_s},
458 {"SPSR_cx", FALSE, PSR_c | PSR_x},
459 {"SPSR_fsx", FALSE, PSR_f | PSR_s | PSR_x},
460 {"SPSR_fsc", FALSE, PSR_f | PSR_s | PSR_c},
461 {"SPSR_fxs", FALSE, PSR_f | PSR_x | PSR_s},
462 {"SPSR_fxc", FALSE, PSR_f | PSR_x | PSR_c},
463 {"SPSR_fcs", FALSE, PSR_f | PSR_c | PSR_s},
464 {"SPSR_fcx", FALSE, PSR_f | PSR_c | PSR_x},
465 {"SPSR_sfx", FALSE, PSR_s | PSR_f | PSR_x},
466 {"SPSR_sfc", FALSE, PSR_s | PSR_f | PSR_c},
467 {"SPSR_sxf", FALSE, PSR_s | PSR_x | PSR_f},
468 {"SPSR_sxc", FALSE, PSR_s | PSR_x | PSR_c},
469 {"SPSR_scf", FALSE, PSR_s | PSR_c | PSR_f},
470 {"SPSR_scx", FALSE, PSR_s | PSR_c | PSR_x},
471 {"SPSR_xfs", FALSE, PSR_x | PSR_f | PSR_s},
472 {"SPSR_xfc", FALSE, PSR_x | PSR_f | PSR_c},
473 {"SPSR_xsf", FALSE, PSR_x | PSR_s | PSR_f},
474 {"SPSR_xsc", FALSE, PSR_x | PSR_s | PSR_c},
475 {"SPSR_xcf", FALSE, PSR_x | PSR_c | PSR_f},
476 {"SPSR_xcs", FALSE, PSR_x | PSR_c | PSR_s},
477 {"SPSR_cfs", FALSE, PSR_c | PSR_f | PSR_s},
478 {"SPSR_cfx", FALSE, PSR_c | PSR_f | PSR_x},
479 {"SPSR_csf", FALSE, PSR_c | PSR_s | PSR_f},
480 {"SPSR_csx", FALSE, PSR_c | PSR_s | PSR_x},
481 {"SPSR_cxf", FALSE, PSR_c | PSR_x | PSR_f},
482 {"SPSR_cxs", FALSE, PSR_c | PSR_x | PSR_s},
483 {"SPSR_fsxc", FALSE, PSR_f | PSR_s | PSR_x | PSR_c},
484 {"SPSR_fscx", FALSE, PSR_f | PSR_s | PSR_c | PSR_x},
485 {"SPSR_fxsc", FALSE, PSR_f | PSR_x | PSR_s | PSR_c},
486 {"SPSR_fxcs", FALSE, PSR_f | PSR_x | PSR_c | PSR_s},
487 {"SPSR_fcsx", FALSE, PSR_f | PSR_c | PSR_s | PSR_x},
488 {"SPSR_fcxs", FALSE, PSR_f | PSR_c | PSR_x | PSR_s},
489 {"SPSR_sfxc", FALSE, PSR_s | PSR_f | PSR_x | PSR_c},
490 {"SPSR_sfcx", FALSE, PSR_s | PSR_f | PSR_c | PSR_x},
491 {"SPSR_sxfc", FALSE, PSR_s | PSR_x | PSR_f | PSR_c},
492 {"SPSR_sxcf", FALSE, PSR_s | PSR_x | PSR_c | PSR_f},
493 {"SPSR_scfx", FALSE, PSR_s | PSR_c | PSR_f | PSR_x},
494 {"SPSR_scxf", FALSE, PSR_s | PSR_c | PSR_x | PSR_f},
495 {"SPSR_xfsc", FALSE, PSR_x | PSR_f | PSR_s | PSR_c},
496 {"SPSR_xfcs", FALSE, PSR_x | PSR_f | PSR_c | PSR_s},
497 {"SPSR_xsfc", FALSE, PSR_x | PSR_s | PSR_f | PSR_c},
498 {"SPSR_xscf", FALSE, PSR_x | PSR_s | PSR_c | PSR_f},
499 {"SPSR_xcfs", FALSE, PSR_x | PSR_c | PSR_f | PSR_s},
500 {"SPSR_xcsf", FALSE, PSR_x | PSR_c | PSR_s | PSR_f},
501 {"SPSR_cfsx", FALSE, PSR_c | PSR_f | PSR_s | PSR_x},
502 {"SPSR_cfxs", FALSE, PSR_c | PSR_f | PSR_x | PSR_s},
503 {"SPSR_csfx", FALSE, PSR_c | PSR_s | PSR_f | PSR_x},
504 {"SPSR_csxf", FALSE, PSR_c | PSR_s | PSR_x | PSR_f},
505 {"SPSR_cxfs", FALSE, PSR_c | PSR_x | PSR_f | PSR_s},
506 {"SPSR_cxsf", FALSE, PSR_c | PSR_x | PSR_s | PSR_f},
507 };
508
509 enum wreg_type
510 {
511 IWMMXT_REG_WR = 0,
512 IWMMXT_REG_WC = 1,
513 IWMMXT_REG_WR_OR_WC = 2,
514 IWMMXT_REG_WCG
515 };
516
517 enum iwmmxt_insn_type
518 {
519 check_rd,
520 check_wr,
521 check_wrwr,
522 check_wrwrwr,
523 check_wrwrwcg,
524 check_tbcst,
525 check_tmovmsk,
526 check_tmia,
527 check_tmcrr,
528 check_tmrrc,
529 check_tmcr,
530 check_tmrc,
531 check_tinsr,
532 check_textrc,
533 check_waligni,
534 check_textrm,
535 check_wshufh
536 };
537
538 enum vfp_dp_reg_pos
539 {
540 VFP_REG_Dd, VFP_REG_Dm, VFP_REG_Dn
541 };
542
543 enum vfp_sp_reg_pos
544 {
545 VFP_REG_Sd, VFP_REG_Sm, VFP_REG_Sn
546 };
547
548 enum vfp_ldstm_type
549 {
550 VFP_LDSTMIA, VFP_LDSTMDB, VFP_LDSTMIAX, VFP_LDSTMDBX
551 };
552
553 /* VFP system registers. */
554 struct vfp_reg
555 {
556 const char *name;
557 unsigned long regno;
558 };
559
560 static const struct vfp_reg vfp_regs[] =
561 {
562 {"fpsid", 0x00000000},
563 {"FPSID", 0x00000000},
564 {"fpscr", 0x00010000},
565 {"FPSCR", 0x00010000},
566 {"fpexc", 0x00080000},
567 {"FPEXC", 0x00080000}
568 };
569
570 /* Structure for a hash table entry for a register. */
571 struct reg_entry
572 {
573 const char * name;
574 int number;
575 bfd_boolean builtin;
576 };
577
578 /* Some well known registers that we refer to directly elsewhere. */
579 #define REG_SP 13
580 #define REG_LR 14
581 #define REG_PC 15
582
583 #define wr_register(reg) ((reg ^ WR_PREFIX) >= 0 && (reg ^ WR_PREFIX) <= 15)
584 #define wc_register(reg) ((reg ^ WC_PREFIX) >= 0 && (reg ^ WC_PREFIX) <= 15)
585 #define wcg_register(reg) ((reg ^ WC_PREFIX) >= 8 && (reg ^ WC_PREFIX) <= 11)
586
587 /* These are the standard names. Users can add aliases with .req.
588 and delete them with .unreq. */
589
590 /* Integer Register Numbers. */
591 static const struct reg_entry rn_table[] =
592 {
593 {"r0", 0, TRUE}, {"r1", 1, TRUE}, {"r2", 2, TRUE}, {"r3", 3, TRUE},
594 {"r4", 4, TRUE}, {"r5", 5, TRUE}, {"r6", 6, TRUE}, {"r7", 7, TRUE},
595 {"r8", 8, TRUE}, {"r9", 9, TRUE}, {"r10", 10, TRUE}, {"r11", 11, TRUE},
596 {"r12", 12, TRUE}, {"r13", REG_SP, TRUE}, {"r14", REG_LR, TRUE}, {"r15", REG_PC, TRUE},
597 /* ATPCS Synonyms. */
598 {"a1", 0, TRUE}, {"a2", 1, TRUE}, {"a3", 2, TRUE}, {"a4", 3, TRUE},
599 {"v1", 4, TRUE}, {"v2", 5, TRUE}, {"v3", 6, TRUE}, {"v4", 7, TRUE},
600 {"v5", 8, TRUE}, {"v6", 9, TRUE}, {"v7", 10, TRUE}, {"v8", 11, TRUE},
601 /* Well-known aliases. */
602 {"wr", 7, TRUE}, {"sb", 9, TRUE}, {"sl", 10, TRUE}, {"fp", 11, TRUE},
603 {"ip", 12, TRUE}, {"sp", REG_SP, TRUE}, {"lr", REG_LR, TRUE}, {"pc", REG_PC, TRUE},
604 {NULL, 0, TRUE}
605 };
606
607 #define WR_PREFIX 0x200
608 #define WC_PREFIX 0x400
609
610 static const struct reg_entry iwmmxt_table[] =
611 {
612 /* Intel Wireless MMX technology register names. */
613 { "wr0", 0x0 | WR_PREFIX, TRUE}, {"wr1", 0x1 | WR_PREFIX, TRUE},
614 { "wr2", 0x2 | WR_PREFIX, TRUE}, {"wr3", 0x3 | WR_PREFIX, TRUE},
615 { "wr4", 0x4 | WR_PREFIX, TRUE}, {"wr5", 0x5 | WR_PREFIX, TRUE},
616 { "wr6", 0x6 | WR_PREFIX, TRUE}, {"wr7", 0x7 | WR_PREFIX, TRUE},
617 { "wr8", 0x8 | WR_PREFIX, TRUE}, {"wr9", 0x9 | WR_PREFIX, TRUE},
618 { "wr10", 0xa | WR_PREFIX, TRUE}, {"wr11", 0xb | WR_PREFIX, TRUE},
619 { "wr12", 0xc | WR_PREFIX, TRUE}, {"wr13", 0xd | WR_PREFIX, TRUE},
620 { "wr14", 0xe | WR_PREFIX, TRUE}, {"wr15", 0xf | WR_PREFIX, TRUE},
621 { "wcid", 0x0 | WC_PREFIX, TRUE}, {"wcon", 0x1 | WC_PREFIX, TRUE},
622 {"wcssf", 0x2 | WC_PREFIX, TRUE}, {"wcasf", 0x3 | WC_PREFIX, TRUE},
623 {"wcgr0", 0x8 | WC_PREFIX, TRUE}, {"wcgr1", 0x9 | WC_PREFIX, TRUE},
624 {"wcgr2", 0xa | WC_PREFIX, TRUE}, {"wcgr3", 0xb | WC_PREFIX, TRUE},
625
626 { "wR0", 0x0 | WR_PREFIX, TRUE}, {"wR1", 0x1 | WR_PREFIX, TRUE},
627 { "wR2", 0x2 | WR_PREFIX, TRUE}, {"wR3", 0x3 | WR_PREFIX, TRUE},
628 { "wR4", 0x4 | WR_PREFIX, TRUE}, {"wR5", 0x5 | WR_PREFIX, TRUE},
629 { "wR6", 0x6 | WR_PREFIX, TRUE}, {"wR7", 0x7 | WR_PREFIX, TRUE},
630 { "wR8", 0x8 | WR_PREFIX, TRUE}, {"wR9", 0x9 | WR_PREFIX, TRUE},
631 { "wR10", 0xa | WR_PREFIX, TRUE}, {"wR11", 0xb | WR_PREFIX, TRUE},
632 { "wR12", 0xc | WR_PREFIX, TRUE}, {"wR13", 0xd | WR_PREFIX, TRUE},
633 { "wR14", 0xe | WR_PREFIX, TRUE}, {"wR15", 0xf | WR_PREFIX, TRUE},
634 { "wCID", 0x0 | WC_PREFIX, TRUE}, {"wCon", 0x1 | WC_PREFIX, TRUE},
635 {"wCSSF", 0x2 | WC_PREFIX, TRUE}, {"wCASF", 0x3 | WC_PREFIX, TRUE},
636 {"wCGR0", 0x8 | WC_PREFIX, TRUE}, {"wCGR1", 0x9 | WC_PREFIX, TRUE},
637 {"wCGR2", 0xa | WC_PREFIX, TRUE}, {"wCGR3", 0xb | WC_PREFIX, TRUE},
638 {NULL, 0, TRUE}
639 };
640
641 /* Co-processor Numbers. */
642 static const struct reg_entry cp_table[] =
643 {
644 {"p0", 0, TRUE}, {"p1", 1, TRUE}, {"p2", 2, TRUE}, {"p3", 3, TRUE},
645 {"p4", 4, TRUE}, {"p5", 5, TRUE}, {"p6", 6, TRUE}, {"p7", 7, TRUE},
646 {"p8", 8, TRUE}, {"p9", 9, TRUE}, {"p10", 10, TRUE}, {"p11", 11, TRUE},
647 {"p12", 12, TRUE}, {"p13", 13, TRUE}, {"p14", 14, TRUE}, {"p15", 15, TRUE},
648 {NULL, 0, TRUE}
649 };
650
651 /* Co-processor Register Numbers. */
652 static const struct reg_entry cn_table[] =
653 {
654 {"c0", 0, TRUE}, {"c1", 1, TRUE}, {"c2", 2, TRUE}, {"c3", 3, TRUE},
655 {"c4", 4, TRUE}, {"c5", 5, TRUE}, {"c6", 6, TRUE}, {"c7", 7, TRUE},
656 {"c8", 8, TRUE}, {"c9", 9, TRUE}, {"c10", 10, TRUE}, {"c11", 11, TRUE},
657 {"c12", 12, TRUE}, {"c13", 13, TRUE}, {"c14", 14, TRUE}, {"c15", 15, TRUE},
658 /* Not really valid, but kept for back-wards compatibility. */
659 {"cr0", 0, TRUE}, {"cr1", 1, TRUE}, {"cr2", 2, TRUE}, {"cr3", 3, TRUE},
660 {"cr4", 4, TRUE}, {"cr5", 5, TRUE}, {"cr6", 6, TRUE}, {"cr7", 7, TRUE},
661 {"cr8", 8, TRUE}, {"cr9", 9, TRUE}, {"cr10", 10, TRUE}, {"cr11", 11, TRUE},
662 {"cr12", 12, TRUE}, {"cr13", 13, TRUE}, {"cr14", 14, TRUE}, {"cr15", 15, TRUE},
663 {NULL, 0, TRUE}
664 };
665
666 /* FPA Registers. */
667 static const struct reg_entry fn_table[] =
668 {
669 {"f0", 0, TRUE}, {"f1", 1, TRUE}, {"f2", 2, TRUE}, {"f3", 3, TRUE},
670 {"f4", 4, TRUE}, {"f5", 5, TRUE}, {"f6", 6, TRUE}, {"f7", 7, TRUE},
671 {NULL, 0, TRUE}
672 };
673
674 /* VFP SP Registers. */
675 static const struct reg_entry sn_table[] =
676 {
677 {"s0", 0, TRUE}, {"s1", 1, TRUE}, {"s2", 2, TRUE}, {"s3", 3, TRUE},
678 {"s4", 4, TRUE}, {"s5", 5, TRUE}, {"s6", 6, TRUE}, {"s7", 7, TRUE},
679 {"s8", 8, TRUE}, {"s9", 9, TRUE}, {"s10", 10, TRUE}, {"s11", 11, TRUE},
680 {"s12", 12, TRUE}, {"s13", 13, TRUE}, {"s14", 14, TRUE}, {"s15", 15, TRUE},
681 {"s16", 16, TRUE}, {"s17", 17, TRUE}, {"s18", 18, TRUE}, {"s19", 19, TRUE},
682 {"s20", 20, TRUE}, {"s21", 21, TRUE}, {"s22", 22, TRUE}, {"s23", 23, TRUE},
683 {"s24", 24, TRUE}, {"s25", 25, TRUE}, {"s26", 26, TRUE}, {"s27", 27, TRUE},
684 {"s28", 28, TRUE}, {"s29", 29, TRUE}, {"s30", 30, TRUE}, {"s31", 31, TRUE},
685 {NULL, 0, TRUE}
686 };
687
688 /* VFP DP Registers. */
689 static const struct reg_entry dn_table[] =
690 {
691 {"d0", 0, TRUE}, {"d1", 1, TRUE}, {"d2", 2, TRUE}, {"d3", 3, TRUE},
692 {"d4", 4, TRUE}, {"d5", 5, TRUE}, {"d6", 6, TRUE}, {"d7", 7, TRUE},
693 {"d8", 8, TRUE}, {"d9", 9, TRUE}, {"d10", 10, TRUE}, {"d11", 11, TRUE},
694 {"d12", 12, TRUE}, {"d13", 13, TRUE}, {"d14", 14, TRUE}, {"d15", 15, TRUE},
695 {NULL, 0, TRUE}
696 };
697
698 /* Maverick DSP coprocessor registers. */
699 static const struct reg_entry mav_mvf_table[] =
700 {
701 {"mvf0", 0, TRUE}, {"mvf1", 1, TRUE}, {"mvf2", 2, TRUE}, {"mvf3", 3, TRUE},
702 {"mvf4", 4, TRUE}, {"mvf5", 5, TRUE}, {"mvf6", 6, TRUE}, {"mvf7", 7, TRUE},
703 {"mvf8", 8, TRUE}, {"mvf9", 9, TRUE}, {"mvf10", 10, TRUE}, {"mvf11", 11, TRUE},
704 {"mvf12", 12, TRUE}, {"mvf13", 13, TRUE}, {"mvf14", 14, TRUE}, {"mvf15", 15, TRUE},
705 {NULL, 0, TRUE}
706 };
707
708 static const struct reg_entry mav_mvd_table[] =
709 {
710 {"mvd0", 0, TRUE}, {"mvd1", 1, TRUE}, {"mvd2", 2, TRUE}, {"mvd3", 3, TRUE},
711 {"mvd4", 4, TRUE}, {"mvd5", 5, TRUE}, {"mvd6", 6, TRUE}, {"mvd7", 7, TRUE},
712 {"mvd8", 8, TRUE}, {"mvd9", 9, TRUE}, {"mvd10", 10, TRUE}, {"mvd11", 11, TRUE},
713 {"mvd12", 12, TRUE}, {"mvd13", 13, TRUE}, {"mvd14", 14, TRUE}, {"mvd15", 15, TRUE},
714 {NULL, 0, TRUE}
715 };
716
717 static const struct reg_entry mav_mvfx_table[] =
718 {
719 {"mvfx0", 0, TRUE}, {"mvfx1", 1, TRUE}, {"mvfx2", 2, TRUE}, {"mvfx3", 3, TRUE},
720 {"mvfx4", 4, TRUE}, {"mvfx5", 5, TRUE}, {"mvfx6", 6, TRUE}, {"mvfx7", 7, TRUE},
721 {"mvfx8", 8, TRUE}, {"mvfx9", 9, TRUE}, {"mvfx10", 10, TRUE}, {"mvfx11", 11, TRUE},
722 {"mvfx12", 12, TRUE}, {"mvfx13", 13, TRUE}, {"mvfx14", 14, TRUE}, {"mvfx15", 15, TRUE},
723 {NULL, 0, TRUE}
724 };
725
726 static const struct reg_entry mav_mvdx_table[] =
727 {
728 {"mvdx0", 0, TRUE}, {"mvdx1", 1, TRUE}, {"mvdx2", 2, TRUE}, {"mvdx3", 3, TRUE},
729 {"mvdx4", 4, TRUE}, {"mvdx5", 5, TRUE}, {"mvdx6", 6, TRUE}, {"mvdx7", 7, TRUE},
730 {"mvdx8", 8, TRUE}, {"mvdx9", 9, TRUE}, {"mvdx10", 10, TRUE}, {"mvdx11", 11, TRUE},
731 {"mvdx12", 12, TRUE}, {"mvdx13", 13, TRUE}, {"mvdx14", 14, TRUE}, {"mvdx15", 15, TRUE},
732 {NULL, 0, TRUE}
733 };
734
735 static const struct reg_entry mav_mvax_table[] =
736 {
737 {"mvax0", 0, TRUE}, {"mvax1", 1, TRUE}, {"mvax2", 2, TRUE}, {"mvax3", 3, TRUE},
738 {NULL, 0, TRUE}
739 };
740
741 static const struct reg_entry mav_dspsc_table[] =
742 {
743 {"dspsc", 0, TRUE},
744 {NULL, 0, TRUE}
745 };
746
747 struct reg_map
748 {
749 const struct reg_entry * names;
750 int max_regno;
751 struct hash_control * htab;
752 const char * expected;
753 };
754
755 struct reg_map all_reg_maps[] =
756 {
757 {rn_table, 15, NULL, N_("ARM register expected")},
758 {cp_table, 15, NULL, N_("bad or missing co-processor number")},
759 {cn_table, 15, NULL, N_("co-processor register expected")},
760 {fn_table, 7, NULL, N_("FPA register expected")},
761 {sn_table, 31, NULL, N_("VFP single precision register expected")},
762 {dn_table, 15, NULL, N_("VFP double precision register expected")},
763 {mav_mvf_table, 15, NULL, N_("Maverick MVF register expected")},
764 {mav_mvd_table, 15, NULL, N_("Maverick MVD register expected")},
765 {mav_mvfx_table, 15, NULL, N_("Maverick MVFX register expected")},
766 {mav_mvdx_table, 15, NULL, N_("Maverick MVDX register expected")},
767 {mav_mvax_table, 3, NULL, N_("Maverick MVAX register expected")},
768 {mav_dspsc_table, 0, NULL, N_("Maverick DSPSC register expected")},
769 {iwmmxt_table, 23, NULL, N_("Intel Wireless MMX technology register expected")},
770 };
771
772 /* Enumeration matching entries in table above. */
773 enum arm_reg_type
774 {
775 REG_TYPE_RN = 0,
776 #define REG_TYPE_FIRST REG_TYPE_RN
777 REG_TYPE_CP = 1,
778 REG_TYPE_CN = 2,
779 REG_TYPE_FN = 3,
780 REG_TYPE_SN = 4,
781 REG_TYPE_DN = 5,
782 REG_TYPE_MVF = 6,
783 REG_TYPE_MVD = 7,
784 REG_TYPE_MVFX = 8,
785 REG_TYPE_MVDX = 9,
786 REG_TYPE_MVAX = 10,
787 REG_TYPE_DSPSC = 11,
788 REG_TYPE_IWMMXT = 12,
789
790 REG_TYPE_MAX = 13
791 };
792
793 /* ARM instructions take 4bytes in the object file, Thumb instructions
794 take 2: */
795 #define INSN_SIZE 4
796
797 /* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
798 #define MAV_MODE1 0x100c
799
800 /* "INSN<cond> X,Y" where X:bit16, Y:bit12. */
801 #define MAV_MODE2 0x0c10
802
803 /* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
804 #define MAV_MODE3 0x100c
805
806 /* "INSN<cond> X,Y,Z" where X:16, Y:0, Z:12. */
807 #define MAV_MODE4 0x0c0010
808
809 /* "INSN<cond> X,Y,Z" where X:12, Y:16, Z:0. */
810 #define MAV_MODE5 0x00100c
811
812 /* "INSN<cond> W,X,Y,Z" where W:5, X:12, Y:16, Z:0. */
813 #define MAV_MODE6 0x00100c05
814
815 struct asm_opcode
816 {
817 /* Basic string to match. */
818 const char * template;
819
820 /* Basic instruction code. */
821 unsigned long value;
822
823 /* Offset into the template where the condition code (if any) will be.
824 If zero, then the instruction is never conditional. */
825 unsigned cond_offset;
826
827 /* Which architecture variant provides this instruction. */
828 unsigned long variant;
829
830 /* Function to call to parse args. */
831 void (* parms) (char *);
832 };
833
834 /* Defines for various bits that we will want to toggle. */
835 #define INST_IMMEDIATE 0x02000000
836 #define OFFSET_REG 0x02000000
837 #define HWOFFSET_IMM 0x00400000
838 #define SHIFT_BY_REG 0x00000010
839 #define PRE_INDEX 0x01000000
840 #define INDEX_UP 0x00800000
841 #define WRITE_BACK 0x00200000
842 #define LDM_TYPE_2_OR_3 0x00400000
843
844 #define LITERAL_MASK 0xf000f000
845 #define OPCODE_MASK 0xfe1fffff
846 #define V4_STR_BIT 0x00000020
847
848 #define DATA_OP_SHIFT 21
849
850 /* Codes to distinguish the arithmetic instructions. */
851 #define OPCODE_AND 0
852 #define OPCODE_EOR 1
853 #define OPCODE_SUB 2
854 #define OPCODE_RSB 3
855 #define OPCODE_ADD 4
856 #define OPCODE_ADC 5
857 #define OPCODE_SBC 6
858 #define OPCODE_RSC 7
859 #define OPCODE_TST 8
860 #define OPCODE_TEQ 9
861 #define OPCODE_CMP 10
862 #define OPCODE_CMN 11
863 #define OPCODE_ORR 12
864 #define OPCODE_MOV 13
865 #define OPCODE_BIC 14
866 #define OPCODE_MVN 15
867
868 #define T_OPCODE_MUL 0x4340
869 #define T_OPCODE_TST 0x4200
870 #define T_OPCODE_CMN 0x42c0
871 #define T_OPCODE_NEG 0x4240
872 #define T_OPCODE_MVN 0x43c0
873
874 #define T_OPCODE_ADD_R3 0x1800
875 #define T_OPCODE_SUB_R3 0x1a00
876 #define T_OPCODE_ADD_HI 0x4400
877 #define T_OPCODE_ADD_ST 0xb000
878 #define T_OPCODE_SUB_ST 0xb080
879 #define T_OPCODE_ADD_SP 0xa800
880 #define T_OPCODE_ADD_PC 0xa000
881 #define T_OPCODE_ADD_I8 0x3000
882 #define T_OPCODE_SUB_I8 0x3800
883 #define T_OPCODE_ADD_I3 0x1c00
884 #define T_OPCODE_SUB_I3 0x1e00
885
886 #define T_OPCODE_ASR_R 0x4100
887 #define T_OPCODE_LSL_R 0x4080
888 #define T_OPCODE_LSR_R 0x40c0
889 #define T_OPCODE_ASR_I 0x1000
890 #define T_OPCODE_LSL_I 0x0000
891 #define T_OPCODE_LSR_I 0x0800
892
893 #define T_OPCODE_MOV_I8 0x2000
894 #define T_OPCODE_CMP_I8 0x2800
895 #define T_OPCODE_CMP_LR 0x4280
896 #define T_OPCODE_MOV_HR 0x4600
897 #define T_OPCODE_CMP_HR 0x4500
898
899 #define T_OPCODE_LDR_PC 0x4800
900 #define T_OPCODE_LDR_SP 0x9800
901 #define T_OPCODE_STR_SP 0x9000
902 #define T_OPCODE_LDR_IW 0x6800
903 #define T_OPCODE_STR_IW 0x6000
904 #define T_OPCODE_LDR_IH 0x8800
905 #define T_OPCODE_STR_IH 0x8000
906 #define T_OPCODE_LDR_IB 0x7800
907 #define T_OPCODE_STR_IB 0x7000
908 #define T_OPCODE_LDR_RW 0x5800
909 #define T_OPCODE_STR_RW 0x5000
910 #define T_OPCODE_LDR_RH 0x5a00
911 #define T_OPCODE_STR_RH 0x5200
912 #define T_OPCODE_LDR_RB 0x5c00
913 #define T_OPCODE_STR_RB 0x5400
914
915 #define T_OPCODE_PUSH 0xb400
916 #define T_OPCODE_POP 0xbc00
917
918 #define T_OPCODE_BRANCH 0xe7fe
919
920 #define THUMB_SIZE 2 /* Size of thumb instruction. */
921 #define THUMB_REG_LO 0x1
922 #define THUMB_REG_HI 0x2
923 #define THUMB_REG_ANY 0x3
924
925 #define THUMB_H1 0x0080
926 #define THUMB_H2 0x0040
927
928 #define THUMB_ASR 0
929 #define THUMB_LSL 1
930 #define THUMB_LSR 2
931
932 #define THUMB_MOVE 0
933 #define THUMB_COMPARE 1
934 #define THUMB_CPY 2
935
936 #define THUMB_LOAD 0
937 #define THUMB_STORE 1
938
939 #define THUMB_PP_PC_LR 0x0100
940
941 /* These three are used for immediate shifts, do not alter. */
942 #define THUMB_WORD 2
943 #define THUMB_HALFWORD 1
944 #define THUMB_BYTE 0
945
946 struct thumb_opcode
947 {
948 /* Basic string to match. */
949 const char * template;
950
951 /* Basic instruction code. */
952 unsigned long value;
953
954 int size;
955
956 /* Which CPU variants this exists for. */
957 unsigned long variant;
958
959 /* Function to call to parse args. */
960 void (* parms) (char *);
961 };
962
963 #define BAD_ARGS _("bad arguments to instruction")
964 #define BAD_PC _("r15 not allowed here")
965 #define BAD_COND _("instruction is not conditional")
966 #define ERR_NO_ACCUM _("acc0 expected")
967
968 static struct hash_control * arm_ops_hsh = NULL;
969 static struct hash_control * arm_tops_hsh = NULL;
970 static struct hash_control * arm_cond_hsh = NULL;
971 static struct hash_control * arm_shift_hsh = NULL;
972 static struct hash_control * arm_psr_hsh = NULL;
973
974 /* Stuff needed to resolve the label ambiguity
975 As:
976 ...
977 label: <insn>
978 may differ from:
979 ...
980 label:
981 <insn>
982 */
983
984 symbolS * last_label_seen;
985 static int label_is_thumb_function_name = FALSE;
986 \f
987 /* Literal Pool stuff. */
988
989 #define MAX_LITERAL_POOL_SIZE 1024
990
991 /* Literal pool structure. Held on a per-section
992 and per-sub-section basis. */
993
994 typedef struct literal_pool
995 {
996 expressionS literals [MAX_LITERAL_POOL_SIZE];
997 unsigned int next_free_entry;
998 unsigned int id;
999 symbolS * symbol;
1000 segT section;
1001 subsegT sub_section;
1002 struct literal_pool * next;
1003 } literal_pool;
1004
1005 /* Pointer to a linked list of literal pools. */
1006 literal_pool * list_of_pools = NULL;
1007
1008 static literal_pool *
1009 find_literal_pool (void)
1010 {
1011 literal_pool * pool;
1012
1013 for (pool = list_of_pools; pool != NULL; pool = pool->next)
1014 {
1015 if (pool->section == now_seg
1016 && pool->sub_section == now_subseg)
1017 break;
1018 }
1019
1020 return pool;
1021 }
1022
1023 static literal_pool *
1024 find_or_make_literal_pool (void)
1025 {
1026 /* Next literal pool ID number. */
1027 static unsigned int latest_pool_num = 1;
1028 literal_pool * pool;
1029
1030 pool = find_literal_pool ();
1031
1032 if (pool == NULL)
1033 {
1034 /* Create a new pool. */
1035 pool = xmalloc (sizeof (* pool));
1036 if (! pool)
1037 return NULL;
1038
1039 pool->next_free_entry = 0;
1040 pool->section = now_seg;
1041 pool->sub_section = now_subseg;
1042 pool->next = list_of_pools;
1043 pool->symbol = NULL;
1044
1045 /* Add it to the list. */
1046 list_of_pools = pool;
1047 }
1048
1049 /* New pools, and emptied pools, will have a NULL symbol. */
1050 if (pool->symbol == NULL)
1051 {
1052 pool->symbol = symbol_create (FAKE_LABEL_NAME, undefined_section,
1053 (valueT) 0, &zero_address_frag);
1054 pool->id = latest_pool_num ++;
1055 }
1056
1057 /* Done. */
1058 return pool;
1059 }
1060
1061 /* Add the literal in the global 'inst'
1062 structure to the relevent literal pool. */
1063
1064 static int
1065 add_to_lit_pool (void)
1066 {
1067 literal_pool * pool;
1068 unsigned int entry;
1069
1070 pool = find_or_make_literal_pool ();
1071
1072 /* Check if this literal value is already in the pool. */
1073 for (entry = 0; entry < pool->next_free_entry; entry ++)
1074 {
1075 if ((pool->literals[entry].X_op == inst.reloc.exp.X_op)
1076 && (inst.reloc.exp.X_op == O_constant)
1077 && (pool->literals[entry].X_add_number
1078 == inst.reloc.exp.X_add_number)
1079 && (pool->literals[entry].X_unsigned
1080 == inst.reloc.exp.X_unsigned))
1081 break;
1082
1083 if ((pool->literals[entry].X_op == inst.reloc.exp.X_op)
1084 && (inst.reloc.exp.X_op == O_symbol)
1085 && (pool->literals[entry].X_add_number
1086 == inst.reloc.exp.X_add_number)
1087 && (pool->literals[entry].X_add_symbol
1088 == inst.reloc.exp.X_add_symbol)
1089 && (pool->literals[entry].X_op_symbol
1090 == inst.reloc.exp.X_op_symbol))
1091 break;
1092 }
1093
1094 /* Do we need to create a new entry? */
1095 if (entry == pool->next_free_entry)
1096 {
1097 if (entry >= MAX_LITERAL_POOL_SIZE)
1098 {
1099 inst.error = _("literal pool overflow");
1100 return FAIL;
1101 }
1102
1103 pool->literals[entry] = inst.reloc.exp;
1104 pool->next_free_entry += 1;
1105 }
1106
1107 inst.reloc.exp.X_op = O_symbol;
1108 inst.reloc.exp.X_add_number = ((int) entry) * 4 - 8;
1109 inst.reloc.exp.X_add_symbol = pool->symbol;
1110
1111 return SUCCESS;
1112 }
1113
1114 /* Can't use symbol_new here, so have to create a symbol and then at
1115 a later date assign it a value. Thats what these functions do. */
1116
1117 static void
1118 symbol_locate (symbolS * symbolP,
1119 const char * name, /* It is copied, the caller can modify. */
1120 segT segment, /* Segment identifier (SEG_<something>). */
1121 valueT valu, /* Symbol value. */
1122 fragS * frag) /* Associated fragment. */
1123 {
1124 unsigned int name_length;
1125 char * preserved_copy_of_name;
1126
1127 name_length = strlen (name) + 1; /* +1 for \0. */
1128 obstack_grow (&notes, name, name_length);
1129 preserved_copy_of_name = obstack_finish (&notes);
1130 #ifdef STRIP_UNDERSCORE
1131 if (preserved_copy_of_name[0] == '_')
1132 preserved_copy_of_name++;
1133 #endif
1134
1135 #ifdef tc_canonicalize_symbol_name
1136 preserved_copy_of_name =
1137 tc_canonicalize_symbol_name (preserved_copy_of_name);
1138 #endif
1139
1140 S_SET_NAME (symbolP, preserved_copy_of_name);
1141
1142 S_SET_SEGMENT (symbolP, segment);
1143 S_SET_VALUE (symbolP, valu);
1144 symbol_clear_list_pointers (symbolP);
1145
1146 symbol_set_frag (symbolP, frag);
1147
1148 /* Link to end of symbol chain. */
1149 {
1150 extern int symbol_table_frozen;
1151
1152 if (symbol_table_frozen)
1153 abort ();
1154 }
1155
1156 symbol_append (symbolP, symbol_lastP, & symbol_rootP, & symbol_lastP);
1157
1158 obj_symbol_new_hook (symbolP);
1159
1160 #ifdef tc_symbol_new_hook
1161 tc_symbol_new_hook (symbolP);
1162 #endif
1163
1164 #ifdef DEBUG_SYMS
1165 verify_symbol_chain (symbol_rootP, symbol_lastP);
1166 #endif /* DEBUG_SYMS */
1167 }
1168
1169 /* Check that an immediate is valid.
1170 If so, convert it to the right format. */
1171
1172 static unsigned int
1173 validate_immediate (unsigned int val)
1174 {
1175 unsigned int a;
1176 unsigned int i;
1177
1178 #define rotate_left(v, n) (v << n | v >> (32 - n))
1179
1180 for (i = 0; i < 32; i += 2)
1181 if ((a = rotate_left (val, i)) <= 0xff)
1182 return a | (i << 7); /* 12-bit pack: [shift-cnt,const]. */
1183
1184 return FAIL;
1185 }
1186
1187 /* Check to see if an immediate can be computed as two separate immediate
1188 values, added together. We already know that this value cannot be
1189 computed by just one ARM instruction. */
1190
1191 static unsigned int
1192 validate_immediate_twopart (unsigned int val,
1193 unsigned int * highpart)
1194 {
1195 unsigned int a;
1196 unsigned int i;
1197
1198 for (i = 0; i < 32; i += 2)
1199 if (((a = rotate_left (val, i)) & 0xff) != 0)
1200 {
1201 if (a & 0xff00)
1202 {
1203 if (a & ~ 0xffff)
1204 continue;
1205 * highpart = (a >> 8) | ((i + 24) << 7);
1206 }
1207 else if (a & 0xff0000)
1208 {
1209 if (a & 0xff000000)
1210 continue;
1211 * highpart = (a >> 16) | ((i + 16) << 7);
1212 }
1213 else
1214 {
1215 assert (a & 0xff000000);
1216 * highpart = (a >> 24) | ((i + 8) << 7);
1217 }
1218
1219 return (a & 0xff) | (i << 7);
1220 }
1221
1222 return FAIL;
1223 }
1224
1225 static int
1226 validate_offset_imm (unsigned int val, int hwse)
1227 {
1228 if ((hwse && val > 255) || val > 4095)
1229 return FAIL;
1230 return val;
1231 }
1232
1233 \f
1234 #ifdef OBJ_ELF
1235 /* This code is to handle mapping symbols as defined in the ARM ELF spec.
1236 (This text is taken from version B-02 of the spec):
1237
1238 4.4.7 Mapping and tagging symbols
1239
1240 A section of an ARM ELF file can contain a mixture of ARM code,
1241 Thumb code, and data. There are inline transitions between code
1242 and data at literal pool boundaries. There can also be inline
1243 transitions between ARM code and Thumb code, for example in
1244 ARM-Thumb inter-working veneers. Linkers, machine-level
1245 debuggers, profiling tools, and disassembly tools need to map
1246 images accurately. For example, setting an ARM breakpoint on a
1247 Thumb location, or in a literal pool, can crash the program
1248 being debugged, ruining the debugging session.
1249
1250 ARM ELF entities are mapped (see section 4.4.7.1 below) and
1251 tagged (see section 4.4.7.2 below) using local symbols (with
1252 binding STB_LOCAL). To assist consumers, mapping and tagging
1253 symbols should be collated first in the symbol table, before
1254 other symbols with binding STB_LOCAL.
1255
1256 To allow properly collated mapping and tagging symbols to be
1257 skipped by consumers that have no interest in them, the first
1258 such symbol should have the name $m and its st_value field equal
1259 to the total number of mapping and tagging symbols (including
1260 the $m) in the symbol table.
1261
1262 4.4.7.1 Mapping symbols
1263
1264 $a Labels the first byte of a sequence of ARM instructions.
1265 Its type is STT_FUNC.
1266
1267 $d Labels the first byte of a sequence of data items.
1268 Its type is STT_OBJECT.
1269
1270 $t Labels the first byte of a sequence of Thumb instructions.
1271 Its type is STT_FUNC.
1272
1273 This list of mapping symbols may be extended in the future.
1274
1275 Section-relative mapping symbols
1276
1277 Mapping symbols defined in a section define a sequence of
1278 half-open address intervals that cover the address range of the
1279 section. Each interval starts at the address defined by a
1280 mapping symbol, and continues up to, but not including, the
1281 address defined by the next (in address order) mapping symbol or
1282 the end of the section. A corollary is that there must be a
1283 mapping symbol defined at the beginning of each section.
1284 Consumers can ignore the size of a section-relative mapping
1285 symbol. Producers can set it to 0.
1286
1287 Absolute mapping symbols
1288
1289 Because of the need to crystallize a Thumb address with the
1290 Thumb-bit set, absolute symbol of type STT_FUNC (symbols of type
1291 STT_FUNC defined in section SHN_ABS) need to be mapped with $a
1292 or $t.
1293
1294 The extent of a mapping symbol defined in SHN_ABS is [st_value,
1295 st_value + st_size), or [st_value, st_value + 1) if st_size = 0,
1296 where [x, y) denotes the half-open address range from x,
1297 inclusive, to y, exclusive.
1298
1299 In the absence of a mapping symbol, a consumer can interpret a
1300 function symbol with an odd value as the Thumb code address
1301 obtained by clearing the least significant bit of the
1302 value. This interpretation is deprecated, and it may not work in
1303 the future.
1304
1305 Note - the Tagging symbols ($b, $f, $p $m) have been dropped from
1306 the EABI (which is still under development), so they are not
1307 implemented here. */
1308
1309 static enum mstate mapstate = MAP_UNDEFINED;
1310
1311 static void
1312 mapping_state (enum mstate state)
1313 {
1314 symbolS * symbolP;
1315 const char * symname;
1316 int type;
1317
1318 if (mapstate == state)
1319 /* The mapping symbol has already been emitted.
1320 There is nothing else to do. */
1321 return;
1322
1323 mapstate = state;
1324
1325 switch (state)
1326 {
1327 case MAP_DATA:
1328 symname = "$d";
1329 type = BSF_OBJECT;
1330 break;
1331 case MAP_ARM:
1332 symname = "$a";
1333 type = BSF_FUNCTION;
1334 break;
1335 case MAP_THUMB:
1336 symname = "$t";
1337 type = BSF_FUNCTION;
1338 break;
1339 case MAP_UNDEFINED:
1340 return;
1341 default:
1342 abort ();
1343 }
1344
1345 seg_info (now_seg)->tc_segment_info_data = state;
1346
1347 symbolP = symbol_new (symname, now_seg, (valueT) frag_now_fix (), frag_now);
1348 symbol_table_insert (symbolP);
1349 symbol_get_bfdsym (symbolP)->flags |= type | BSF_LOCAL;
1350
1351 switch (state)
1352 {
1353 case MAP_ARM:
1354 THUMB_SET_FUNC (symbolP, 0);
1355 ARM_SET_THUMB (symbolP, 0);
1356 ARM_SET_INTERWORK (symbolP, support_interwork);
1357 break;
1358
1359 case MAP_THUMB:
1360 THUMB_SET_FUNC (symbolP, 1);
1361 ARM_SET_THUMB (symbolP, 1);
1362 ARM_SET_INTERWORK (symbolP, support_interwork);
1363 break;
1364
1365 case MAP_DATA:
1366 default:
1367 return;
1368 }
1369 }
1370
1371 /* When we change sections we need to issue a new mapping symbol. */
1372
1373 void
1374 arm_elf_change_section (void)
1375 {
1376 flagword flags;
1377
1378 /* Link an unlinked unwind index table section to the .text section. */
1379 if (elf_section_type (now_seg) == SHT_ARM_EXIDX
1380 && elf_linked_to_section (now_seg) == NULL)
1381 elf_linked_to_section (now_seg) = text_section;
1382
1383 if (!SEG_NORMAL (now_seg))
1384 return;
1385
1386 flags = bfd_get_section_flags (stdoutput, now_seg);
1387
1388 /* We can ignore sections that only contain debug info. */
1389 if ((flags & SEC_ALLOC) == 0)
1390 return;
1391
1392 mapstate = seg_info (now_seg)->tc_segment_info_data;
1393 }
1394
1395 int
1396 arm_elf_section_type (const char * str, size_t len)
1397 {
1398 if (len == 5 && strncmp (str, "exidx", 5) == 0)
1399 return SHT_ARM_EXIDX;
1400
1401 return -1;
1402 }
1403 #else
1404 #define mapping_state(a)
1405 #endif /* OBJ_ELF */
1406 \f
1407 /* arm_reg_parse () := if it looks like a register, return its token and
1408 advance the pointer. */
1409
1410 static int
1411 arm_reg_parse (char ** ccp, struct hash_control * htab)
1412 {
1413 char * start = * ccp;
1414 char c;
1415 char * p;
1416 struct reg_entry * reg;
1417
1418 #ifdef REGISTER_PREFIX
1419 if (*start != REGISTER_PREFIX)
1420 return FAIL;
1421 p = start + 1;
1422 #else
1423 p = start;
1424 #ifdef OPTIONAL_REGISTER_PREFIX
1425 if (*p == OPTIONAL_REGISTER_PREFIX)
1426 p++, start++;
1427 #endif
1428 #endif
1429 if (!ISALPHA (*p) || !is_name_beginner (*p))
1430 return FAIL;
1431
1432 c = *p++;
1433 while (ISALPHA (c) || ISDIGIT (c) || c == '_')
1434 c = *p++;
1435
1436 *--p = 0;
1437 reg = (struct reg_entry *) hash_find (htab, start);
1438 *p = c;
1439
1440 if (reg)
1441 {
1442 *ccp = p;
1443 return reg->number;
1444 }
1445
1446 return FAIL;
1447 }
1448
1449 /* Search for the following register name in each of the possible reg name
1450 tables. Return the classification if found, or REG_TYPE_MAX if not
1451 present. */
1452
1453 static enum arm_reg_type
1454 arm_reg_parse_any (char *cp)
1455 {
1456 int i;
1457
1458 for (i = (int) REG_TYPE_FIRST; i < (int) REG_TYPE_MAX; i++)
1459 if (arm_reg_parse (&cp, all_reg_maps[i].htab) != FAIL)
1460 return (enum arm_reg_type) i;
1461
1462 return REG_TYPE_MAX;
1463 }
1464
1465 static void
1466 opcode_select (int width)
1467 {
1468 switch (width)
1469 {
1470 case 16:
1471 if (! thumb_mode)
1472 {
1473 if (! (cpu_variant & ARM_EXT_V4T))
1474 as_bad (_("selected processor does not support THUMB opcodes"));
1475
1476 thumb_mode = 1;
1477 /* No need to force the alignment, since we will have been
1478 coming from ARM mode, which is word-aligned. */
1479 record_alignment (now_seg, 1);
1480 }
1481 mapping_state (MAP_THUMB);
1482 break;
1483
1484 case 32:
1485 if (thumb_mode)
1486 {
1487 if ((cpu_variant & ARM_ALL) == ARM_EXT_V4T)
1488 as_bad (_("selected processor does not support ARM opcodes"));
1489
1490 thumb_mode = 0;
1491
1492 if (!need_pass_2)
1493 frag_align (2, 0, 0);
1494
1495 record_alignment (now_seg, 1);
1496 }
1497 mapping_state (MAP_ARM);
1498 break;
1499
1500 default:
1501 as_bad (_("invalid instruction size selected (%d)"), width);
1502 }
1503 }
1504
1505 static void
1506 s_req (int a ATTRIBUTE_UNUSED)
1507 {
1508 as_bad (_("invalid syntax for .req directive"));
1509 }
1510
1511 /* The .unreq directive deletes an alias which was previously defined
1512 by .req. For example:
1513
1514 my_alias .req r11
1515 .unreq my_alias */
1516
1517 static void
1518 s_unreq (int a ATTRIBUTE_UNUSED)
1519 {
1520 char * name;
1521 char saved_char;
1522
1523 skip_whitespace (input_line_pointer);
1524 name = input_line_pointer;
1525
1526 while (*input_line_pointer != 0
1527 && *input_line_pointer != ' '
1528 && *input_line_pointer != '\n')
1529 ++input_line_pointer;
1530
1531 saved_char = *input_line_pointer;
1532 *input_line_pointer = 0;
1533
1534 if (*name)
1535 {
1536 enum arm_reg_type req_type = arm_reg_parse_any (name);
1537
1538 if (req_type != REG_TYPE_MAX)
1539 {
1540 char *temp_name = name;
1541 int req_no = arm_reg_parse (&temp_name, all_reg_maps[req_type].htab);
1542
1543 if (req_no != FAIL)
1544 {
1545 struct reg_entry *req_entry;
1546
1547 /* Check to see if this alias is a builtin one. */
1548 req_entry = hash_delete (all_reg_maps[req_type].htab, name);
1549
1550 if (!req_entry)
1551 as_bad (_("unreq: missing hash entry for \"%s\""), name);
1552 else if (req_entry->builtin)
1553 /* FIXME: We are deleting a built in register alias which
1554 points to a const data structure, so we only need to
1555 free up the memory used by the key in the hash table.
1556 Unfortunately we have not recorded this value, so this
1557 is a memory leak. */
1558 /* FIXME: Should we issue a warning message ? */
1559 ;
1560 else
1561 {
1562 /* Deleting a user defined alias. We need to free the
1563 key and the value, but fortunately the key is the same
1564 as the value->name field. */
1565 free ((char *) req_entry->name);
1566 free (req_entry);
1567 }
1568 }
1569 else
1570 as_bad (_(".unreq: unrecognized symbol \"%s\""), name);
1571 }
1572 else
1573 as_bad (_(".unreq: unrecognized symbol \"%s\""), name);
1574 }
1575 else
1576 as_bad (_("invalid syntax for .unreq directive"));
1577
1578 *input_line_pointer = saved_char;
1579 demand_empty_rest_of_line ();
1580 }
1581
1582 static void
1583 s_bss (int ignore ATTRIBUTE_UNUSED)
1584 {
1585 /* We don't support putting frags in the BSS segment, we fake it by
1586 marking in_bss, then looking at s_skip for clues. */
1587 subseg_set (bss_section, 0);
1588 demand_empty_rest_of_line ();
1589 mapping_state (MAP_DATA);
1590 }
1591
1592 static void
1593 s_even (int ignore ATTRIBUTE_UNUSED)
1594 {
1595 /* Never make frag if expect extra pass. */
1596 if (!need_pass_2)
1597 frag_align (1, 0, 0);
1598
1599 record_alignment (now_seg, 1);
1600
1601 demand_empty_rest_of_line ();
1602 }
1603
1604 static void
1605 s_ltorg (int ignored ATTRIBUTE_UNUSED)
1606 {
1607 unsigned int entry;
1608 literal_pool * pool;
1609 char sym_name[20];
1610
1611 pool = find_literal_pool ();
1612 if (pool == NULL
1613 || pool->symbol == NULL
1614 || pool->next_free_entry == 0)
1615 return;
1616
1617 mapping_state (MAP_DATA);
1618
1619 /* Align pool as you have word accesses.
1620 Only make a frag if we have to. */
1621 if (!need_pass_2)
1622 frag_align (2, 0, 0);
1623
1624 record_alignment (now_seg, 2);
1625
1626 sprintf (sym_name, "$$lit_\002%x", pool->id);
1627
1628 symbol_locate (pool->symbol, sym_name, now_seg,
1629 (valueT) frag_now_fix (), frag_now);
1630 symbol_table_insert (pool->symbol);
1631
1632 ARM_SET_THUMB (pool->symbol, thumb_mode);
1633
1634 #if defined OBJ_COFF || defined OBJ_ELF
1635 ARM_SET_INTERWORK (pool->symbol, support_interwork);
1636 #endif
1637
1638 for (entry = 0; entry < pool->next_free_entry; entry ++)
1639 /* First output the expression in the instruction to the pool. */
1640 emit_expr (&(pool->literals[entry]), 4); /* .word */
1641
1642 /* Mark the pool as empty. */
1643 pool->next_free_entry = 0;
1644 pool->symbol = NULL;
1645 }
1646
1647 /* Same as s_align_ptwo but align 0 => align 2. */
1648
1649 static void
1650 s_align (int unused ATTRIBUTE_UNUSED)
1651 {
1652 int temp;
1653 long temp_fill;
1654 long max_alignment = 15;
1655
1656 temp = get_absolute_expression ();
1657 if (temp > max_alignment)
1658 as_bad (_("alignment too large: %d assumed"), temp = max_alignment);
1659 else if (temp < 0)
1660 {
1661 as_bad (_("alignment negative. 0 assumed."));
1662 temp = 0;
1663 }
1664
1665 if (*input_line_pointer == ',')
1666 {
1667 input_line_pointer++;
1668 temp_fill = get_absolute_expression ();
1669 }
1670 else
1671 temp_fill = 0;
1672
1673 if (!temp)
1674 temp = 2;
1675
1676 /* Only make a frag if we HAVE to. */
1677 if (temp && !need_pass_2)
1678 frag_align (temp, (int) temp_fill, 0);
1679 demand_empty_rest_of_line ();
1680
1681 record_alignment (now_seg, temp);
1682 }
1683
1684 static void
1685 s_force_thumb (int ignore ATTRIBUTE_UNUSED)
1686 {
1687 /* If we are not already in thumb mode go into it, EVEN if
1688 the target processor does not support thumb instructions.
1689 This is used by gcc/config/arm/lib1funcs.asm for example
1690 to compile interworking support functions even if the
1691 target processor should not support interworking. */
1692 if (! thumb_mode)
1693 {
1694 thumb_mode = 2;
1695
1696 record_alignment (now_seg, 1);
1697 }
1698
1699 demand_empty_rest_of_line ();
1700 }
1701
1702 static void
1703 s_thumb_func (int ignore ATTRIBUTE_UNUSED)
1704 {
1705 if (! thumb_mode)
1706 opcode_select (16);
1707
1708 /* The following label is the name/address of the start of a Thumb function.
1709 We need to know this for the interworking support. */
1710 label_is_thumb_function_name = TRUE;
1711
1712 demand_empty_rest_of_line ();
1713 }
1714
1715 /* Perform a .set directive, but also mark the alias as
1716 being a thumb function. */
1717
1718 static void
1719 s_thumb_set (int equiv)
1720 {
1721 /* XXX the following is a duplicate of the code for s_set() in read.c
1722 We cannot just call that code as we need to get at the symbol that
1723 is created. */
1724 char * name;
1725 char delim;
1726 char * end_name;
1727 symbolS * symbolP;
1728
1729 /* Especial apologies for the random logic:
1730 This just grew, and could be parsed much more simply!
1731 Dean - in haste. */
1732 name = input_line_pointer;
1733 delim = get_symbol_end ();
1734 end_name = input_line_pointer;
1735 *end_name = delim;
1736
1737 SKIP_WHITESPACE ();
1738
1739 if (*input_line_pointer != ',')
1740 {
1741 *end_name = 0;
1742 as_bad (_("expected comma after name \"%s\""), name);
1743 *end_name = delim;
1744 ignore_rest_of_line ();
1745 return;
1746 }
1747
1748 input_line_pointer++;
1749 *end_name = 0;
1750
1751 if (name[0] == '.' && name[1] == '\0')
1752 {
1753 /* XXX - this should not happen to .thumb_set. */
1754 abort ();
1755 }
1756
1757 if ((symbolP = symbol_find (name)) == NULL
1758 && (symbolP = md_undefined_symbol (name)) == NULL)
1759 {
1760 #ifndef NO_LISTING
1761 /* When doing symbol listings, play games with dummy fragments living
1762 outside the normal fragment chain to record the file and line info
1763 for this symbol. */
1764 if (listing & LISTING_SYMBOLS)
1765 {
1766 extern struct list_info_struct * listing_tail;
1767 fragS * dummy_frag = xmalloc (sizeof (fragS));
1768
1769 memset (dummy_frag, 0, sizeof (fragS));
1770 dummy_frag->fr_type = rs_fill;
1771 dummy_frag->line = listing_tail;
1772 symbolP = symbol_new (name, undefined_section, 0, dummy_frag);
1773 dummy_frag->fr_symbol = symbolP;
1774 }
1775 else
1776 #endif
1777 symbolP = symbol_new (name, undefined_section, 0, &zero_address_frag);
1778
1779 #ifdef OBJ_COFF
1780 /* "set" symbols are local unless otherwise specified. */
1781 SF_SET_LOCAL (symbolP);
1782 #endif /* OBJ_COFF */
1783 } /* Make a new symbol. */
1784
1785 symbol_table_insert (symbolP);
1786
1787 * end_name = delim;
1788
1789 if (equiv
1790 && S_IS_DEFINED (symbolP)
1791 && S_GET_SEGMENT (symbolP) != reg_section)
1792 as_bad (_("symbol `%s' already defined"), S_GET_NAME (symbolP));
1793
1794 pseudo_set (symbolP);
1795
1796 demand_empty_rest_of_line ();
1797
1798 /* XXX Now we come to the Thumb specific bit of code. */
1799
1800 THUMB_SET_FUNC (symbolP, 1);
1801 ARM_SET_THUMB (symbolP, 1);
1802 #if defined OBJ_ELF || defined OBJ_COFF
1803 ARM_SET_INTERWORK (symbolP, support_interwork);
1804 #endif
1805 }
1806
1807 static void
1808 s_arm (int ignore ATTRIBUTE_UNUSED)
1809 {
1810 opcode_select (32);
1811 demand_empty_rest_of_line ();
1812 }
1813
1814 static void
1815 s_thumb (int ignore ATTRIBUTE_UNUSED)
1816 {
1817 opcode_select (16);
1818 demand_empty_rest_of_line ();
1819 }
1820
1821 static void
1822 s_code (int unused ATTRIBUTE_UNUSED)
1823 {
1824 int temp;
1825
1826 temp = get_absolute_expression ();
1827 switch (temp)
1828 {
1829 case 16:
1830 case 32:
1831 opcode_select (temp);
1832 break;
1833
1834 default:
1835 as_bad (_("invalid operand to .code directive (%d) (expecting 16 or 32)"), temp);
1836 }
1837 }
1838
1839 static void
1840 end_of_line (char * str)
1841 {
1842 skip_whitespace (str);
1843
1844 if (*str != '\0' && !inst.error)
1845 inst.error = _("garbage following instruction");
1846 }
1847
1848 static int
1849 skip_past_comma (char ** str)
1850 {
1851 char * p = * str, c;
1852 int comma = 0;
1853
1854 while ((c = *p) == ' ' || c == ',')
1855 {
1856 p++;
1857 if (c == ',' && comma++)
1858 return FAIL;
1859 }
1860
1861 if (c == '\0')
1862 return FAIL;
1863
1864 *str = p;
1865 return comma ? SUCCESS : FAIL;
1866 }
1867
1868 /* Return TRUE if anything in the expression is a bignum. */
1869
1870 static int
1871 walk_no_bignums (symbolS * sp)
1872 {
1873 if (symbol_get_value_expression (sp)->X_op == O_big)
1874 return 1;
1875
1876 if (symbol_get_value_expression (sp)->X_add_symbol)
1877 {
1878 return (walk_no_bignums (symbol_get_value_expression (sp)->X_add_symbol)
1879 || (symbol_get_value_expression (sp)->X_op_symbol
1880 && walk_no_bignums (symbol_get_value_expression (sp)->X_op_symbol)));
1881 }
1882
1883 return 0;
1884 }
1885
1886 static int in_my_get_expression = 0;
1887
1888 static int
1889 my_get_expression (expressionS * ep, char ** str)
1890 {
1891 char * save_in;
1892 segT seg;
1893
1894 save_in = input_line_pointer;
1895 input_line_pointer = *str;
1896 in_my_get_expression = 1;
1897 seg = expression (ep);
1898 in_my_get_expression = 0;
1899
1900 if (ep->X_op == O_illegal)
1901 {
1902 /* We found a bad expression in md_operand(). */
1903 *str = input_line_pointer;
1904 input_line_pointer = save_in;
1905 return 1;
1906 }
1907
1908 #ifdef OBJ_AOUT
1909 if (seg != absolute_section
1910 && seg != text_section
1911 && seg != data_section
1912 && seg != bss_section
1913 && seg != undefined_section)
1914 {
1915 inst.error = _("bad_segment");
1916 *str = input_line_pointer;
1917 input_line_pointer = save_in;
1918 return 1;
1919 }
1920 #endif
1921
1922 /* Get rid of any bignums now, so that we don't generate an error for which
1923 we can't establish a line number later on. Big numbers are never valid
1924 in instructions, which is where this routine is always called. */
1925 if (ep->X_op == O_big
1926 || (ep->X_add_symbol
1927 && (walk_no_bignums (ep->X_add_symbol)
1928 || (ep->X_op_symbol
1929 && walk_no_bignums (ep->X_op_symbol)))))
1930 {
1931 inst.error = _("invalid constant");
1932 *str = input_line_pointer;
1933 input_line_pointer = save_in;
1934 return 1;
1935 }
1936
1937 *str = input_line_pointer;
1938 input_line_pointer = save_in;
1939 return 0;
1940 }
1941
1942 /* A standard register must be given at this point.
1943 SHIFT is the place to put it in inst.instruction.
1944 Restores input start point on error.
1945 Returns the reg#, or FAIL. */
1946
1947 static int
1948 reg_required_here (char ** str, int shift)
1949 {
1950 static char buff [128]; /* XXX */
1951 int reg;
1952 char * start = * str;
1953
1954 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_RN].htab)) != FAIL)
1955 {
1956 if (shift >= 0)
1957 inst.instruction |= reg << shift;
1958 return reg;
1959 }
1960
1961 /* Restore the start point, we may have got a reg of the wrong class. */
1962 *str = start;
1963
1964 /* In the few cases where we might be able to accept something else
1965 this error can be overridden. */
1966 sprintf (buff, _("register expected, not '%.100s'"), start);
1967 inst.error = buff;
1968
1969 return FAIL;
1970 }
1971
1972 /* A Intel Wireless MMX technology register
1973 must be given at this point.
1974 Shift is the place to put it in inst.instruction.
1975 Restores input start point on err.
1976 Returns the reg#, or FAIL. */
1977
1978 static int
1979 wreg_required_here (char ** str,
1980 int shift,
1981 enum wreg_type reg_type)
1982 {
1983 static char buff [128];
1984 int reg;
1985 char * start = *str;
1986
1987 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_IWMMXT].htab)) != FAIL)
1988 {
1989 if (wr_register (reg)
1990 && (reg_type == IWMMXT_REG_WR || reg_type == IWMMXT_REG_WR_OR_WC))
1991 {
1992 if (shift >= 0)
1993 inst.instruction |= (reg ^ WR_PREFIX) << shift;
1994 return reg;
1995 }
1996 else if (wc_register (reg)
1997 && (reg_type == IWMMXT_REG_WC || reg_type == IWMMXT_REG_WR_OR_WC))
1998 {
1999 if (shift >= 0)
2000 inst.instruction |= (reg ^ WC_PREFIX) << shift;
2001 return reg;
2002 }
2003 else if ((wcg_register (reg) && reg_type == IWMMXT_REG_WCG))
2004 {
2005 if (shift >= 0)
2006 inst.instruction |= ((reg ^ WC_PREFIX) - 8) << shift;
2007 return reg;
2008 }
2009 }
2010
2011 /* Restore the start point, we may have got a reg of the wrong class. */
2012 *str = start;
2013
2014 /* In the few cases where we might be able to accept
2015 something else this error can be overridden. */
2016 sprintf (buff, _("Intel Wireless MMX technology register expected, not '%.100s'"), start);
2017 inst.error = buff;
2018
2019 return FAIL;
2020 }
2021
2022 static const struct asm_psr *
2023 arm_psr_parse (char ** ccp)
2024 {
2025 char * start = * ccp;
2026 char c;
2027 char * p;
2028 const struct asm_psr * psr;
2029
2030 p = start;
2031
2032 /* Skip to the end of the next word in the input stream. */
2033 do
2034 {
2035 c = *p++;
2036 }
2037 while (ISALPHA (c) || c == '_');
2038
2039 /* Terminate the word. */
2040 *--p = 0;
2041
2042 /* CPSR's and SPSR's can now be lowercase. This is just a convenience
2043 feature for ease of use and backwards compatibility. */
2044 if (!strncmp (start, "cpsr", 4))
2045 strncpy (start, "CPSR", 4);
2046 else if (!strncmp (start, "spsr", 4))
2047 strncpy (start, "SPSR", 4);
2048
2049 /* Now locate the word in the psr hash table. */
2050 psr = (const struct asm_psr *) hash_find (arm_psr_hsh, start);
2051
2052 /* Restore the input stream. */
2053 *p = c;
2054
2055 /* If we found a valid match, advance the
2056 stream pointer past the end of the word. */
2057 *ccp = p;
2058
2059 return psr;
2060 }
2061
2062 /* Parse the input looking for a PSR flag. */
2063
2064 static int
2065 psr_required_here (char ** str)
2066 {
2067 char * start = * str;
2068 const struct asm_psr * psr;
2069
2070 psr = arm_psr_parse (str);
2071
2072 if (psr)
2073 {
2074 /* If this is the SPSR that is being modified, set the R bit. */
2075 if (! psr->cpsr)
2076 inst.instruction |= SPSR_BIT;
2077
2078 /* Set the psr flags in the MSR instruction. */
2079 inst.instruction |= psr->field << PSR_SHIFT;
2080
2081 return SUCCESS;
2082 }
2083
2084 /* In the few cases where we might be able to accept
2085 something else this error can be overridden. */
2086 inst.error = _("flag for {c}psr instruction expected");
2087
2088 /* Restore the start point. */
2089 *str = start;
2090 return FAIL;
2091 }
2092
2093 static int
2094 co_proc_number (char ** str)
2095 {
2096 int processor, pchar;
2097 char *start;
2098
2099 skip_whitespace (*str);
2100 start = *str;
2101
2102 /* The data sheet seems to imply that just a number on its own is valid
2103 here, but the RISC iX assembler seems to accept a prefix 'p'. We will
2104 accept either. */
2105 if ((processor = arm_reg_parse (str, all_reg_maps[REG_TYPE_CP].htab))
2106 == FAIL)
2107 {
2108 *str = start;
2109
2110 pchar = *(*str)++;
2111 if (pchar >= '0' && pchar <= '9')
2112 {
2113 processor = pchar - '0';
2114 if (**str >= '0' && **str <= '9')
2115 {
2116 processor = processor * 10 + *(*str)++ - '0';
2117 if (processor > 15)
2118 {
2119 inst.error = _("illegal co-processor number");
2120 return FAIL;
2121 }
2122 }
2123 }
2124 else
2125 {
2126 inst.error = all_reg_maps[REG_TYPE_CP].expected;
2127 return FAIL;
2128 }
2129 }
2130
2131 inst.instruction |= processor << 8;
2132 return SUCCESS;
2133 }
2134
2135 static int
2136 cp_opc_expr (char ** str, int where, int length)
2137 {
2138 expressionS expr;
2139
2140 skip_whitespace (* str);
2141
2142 memset (&expr, '\0', sizeof (expr));
2143
2144 if (my_get_expression (&expr, str))
2145 return FAIL;
2146 if (expr.X_op != O_constant)
2147 {
2148 inst.error = _("bad or missing expression");
2149 return FAIL;
2150 }
2151
2152 if ((expr.X_add_number & ((1 << length) - 1)) != expr.X_add_number)
2153 {
2154 inst.error = _("immediate co-processor expression too large");
2155 return FAIL;
2156 }
2157
2158 inst.instruction |= expr.X_add_number << where;
2159 return SUCCESS;
2160 }
2161
2162 static int
2163 cp_reg_required_here (char ** str, int where)
2164 {
2165 int reg;
2166 char * start = *str;
2167
2168 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_CN].htab)) != FAIL)
2169 {
2170 inst.instruction |= reg << where;
2171 return reg;
2172 }
2173
2174 /* In the few cases where we might be able to accept something else
2175 this error can be overridden. */
2176 inst.error = all_reg_maps[REG_TYPE_CN].expected;
2177
2178 /* Restore the start point. */
2179 *str = start;
2180 return FAIL;
2181 }
2182
2183 static int
2184 fp_reg_required_here (char ** str, int where)
2185 {
2186 int reg;
2187 char * start = * str;
2188
2189 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_FN].htab)) != FAIL)
2190 {
2191 inst.instruction |= reg << where;
2192 return reg;
2193 }
2194
2195 /* In the few cases where we might be able to accept something else
2196 this error can be overridden. */
2197 inst.error = all_reg_maps[REG_TYPE_FN].expected;
2198
2199 /* Restore the start point. */
2200 *str = start;
2201 return FAIL;
2202 }
2203
2204 static int
2205 cp_address_offset (char ** str)
2206 {
2207 int offset;
2208
2209 skip_whitespace (* str);
2210
2211 if (! is_immediate_prefix (**str))
2212 {
2213 inst.error = _("immediate expression expected");
2214 return FAIL;
2215 }
2216
2217 (*str)++;
2218
2219 if (my_get_expression (& inst.reloc.exp, str))
2220 return FAIL;
2221
2222 if (inst.reloc.exp.X_op == O_constant)
2223 {
2224 offset = inst.reloc.exp.X_add_number;
2225
2226 if (offset & 3)
2227 {
2228 inst.error = _("co-processor address must be word aligned");
2229 return FAIL;
2230 }
2231
2232 if (offset > 1023 || offset < -1023)
2233 {
2234 inst.error = _("offset too large");
2235 return FAIL;
2236 }
2237
2238 if (offset >= 0)
2239 inst.instruction |= INDEX_UP;
2240 else
2241 offset = -offset;
2242
2243 inst.instruction |= offset >> 2;
2244 }
2245 else
2246 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
2247
2248 return SUCCESS;
2249 }
2250
2251 static int
2252 cp_address_required_here (char ** str, int wb_ok)
2253 {
2254 char * p = * str;
2255 int pre_inc = 0;
2256 int write_back = 0;
2257
2258 if (*p == '[')
2259 {
2260 int reg;
2261
2262 p++;
2263 skip_whitespace (p);
2264
2265 if ((reg = reg_required_here (& p, 16)) == FAIL)
2266 return FAIL;
2267
2268 skip_whitespace (p);
2269
2270 if (*p == ']')
2271 {
2272 p++;
2273
2274 skip_whitespace (p);
2275
2276 if (*p == '\0')
2277 {
2278 /* As an extension to the official ARM syntax we allow:
2279 [Rn]
2280 as a short hand for:
2281 [Rn,#0] */
2282 inst.instruction |= PRE_INDEX | INDEX_UP;
2283 *str = p;
2284 return SUCCESS;
2285 }
2286
2287 if (skip_past_comma (& p) == FAIL)
2288 {
2289 inst.error = _("comma expected after closing square bracket");
2290 return FAIL;
2291 }
2292
2293 skip_whitespace (p);
2294
2295 if (*p == '#')
2296 {
2297 if (wb_ok)
2298 {
2299 /* [Rn], #expr */
2300 write_back = WRITE_BACK;
2301
2302 if (reg == REG_PC)
2303 {
2304 inst.error = _("pc may not be used in post-increment");
2305 return FAIL;
2306 }
2307
2308 if (cp_address_offset (& p) == FAIL)
2309 return FAIL;
2310 }
2311 else
2312 pre_inc = PRE_INDEX | INDEX_UP;
2313 }
2314 else if (*p == '{')
2315 {
2316 int option;
2317
2318 /* [Rn], {<expr>} */
2319 p++;
2320
2321 skip_whitespace (p);
2322
2323 if (my_get_expression (& inst.reloc.exp, & p))
2324 return FAIL;
2325
2326 if (inst.reloc.exp.X_op == O_constant)
2327 {
2328 option = inst.reloc.exp.X_add_number;
2329
2330 if (option > 255 || option < 0)
2331 {
2332 inst.error = _("'option' field too large");
2333 return FAIL;
2334 }
2335
2336 skip_whitespace (p);
2337
2338 if (*p != '}')
2339 {
2340 inst.error = _("'}' expected at end of 'option' field");
2341 return FAIL;
2342 }
2343 else
2344 {
2345 p++;
2346 inst.instruction |= option;
2347 inst.instruction |= INDEX_UP;
2348 }
2349 }
2350 else
2351 {
2352 inst.error = _("non-constant expressions for 'option' field not supported");
2353 return FAIL;
2354 }
2355 }
2356 else
2357 {
2358 inst.error = _("# or { expected after comma");
2359 return FAIL;
2360 }
2361 }
2362 else
2363 {
2364 /* '['Rn, #expr']'[!] */
2365
2366 if (skip_past_comma (& p) == FAIL)
2367 {
2368 inst.error = _("pre-indexed expression expected");
2369 return FAIL;
2370 }
2371
2372 pre_inc = PRE_INDEX;
2373
2374 if (cp_address_offset (& p) == FAIL)
2375 return FAIL;
2376
2377 skip_whitespace (p);
2378
2379 if (*p++ != ']')
2380 {
2381 inst.error = _("missing ]");
2382 return FAIL;
2383 }
2384
2385 skip_whitespace (p);
2386
2387 if (wb_ok && *p == '!')
2388 {
2389 if (reg == REG_PC)
2390 {
2391 inst.error = _("pc may not be used with write-back");
2392 return FAIL;
2393 }
2394
2395 p++;
2396 write_back = WRITE_BACK;
2397 }
2398 }
2399 }
2400 else
2401 {
2402 if (my_get_expression (&inst.reloc.exp, &p))
2403 return FAIL;
2404
2405 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
2406 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
2407 inst.reloc.pc_rel = 1;
2408 inst.instruction |= (REG_PC << 16);
2409 pre_inc = PRE_INDEX;
2410 }
2411
2412 inst.instruction |= write_back | pre_inc;
2413 *str = p;
2414 return SUCCESS;
2415 }
2416
2417 static int
2418 cp_byte_address_offset (char ** str)
2419 {
2420 int offset;
2421
2422 skip_whitespace (* str);
2423
2424 if (! is_immediate_prefix (**str))
2425 {
2426 inst.error = _("immediate expression expected");
2427 return FAIL;
2428 }
2429
2430 (*str)++;
2431
2432 if (my_get_expression (& inst.reloc.exp, str))
2433 return FAIL;
2434
2435 if (inst.reloc.exp.X_op == O_constant)
2436 {
2437 offset = inst.reloc.exp.X_add_number;
2438
2439 if (offset > 255 || offset < -255)
2440 {
2441 inst.error = _("offset too large");
2442 return FAIL;
2443 }
2444
2445 if (offset >= 0)
2446 inst.instruction |= INDEX_UP;
2447 else
2448 offset = -offset;
2449
2450 inst.instruction |= offset;
2451 }
2452 else
2453 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM_S2;
2454
2455 return SUCCESS;
2456 }
2457
2458 static int
2459 cp_byte_address_required_here (char ** str)
2460 {
2461 char * p = * str;
2462 int pre_inc = 0;
2463 int write_back = 0;
2464
2465 if (*p == '[')
2466 {
2467 int reg;
2468
2469 p++;
2470 skip_whitespace (p);
2471
2472 if ((reg = reg_required_here (& p, 16)) == FAIL)
2473 return FAIL;
2474
2475 skip_whitespace (p);
2476
2477 if (*p == ']')
2478 {
2479 p++;
2480
2481 if (skip_past_comma (& p) == SUCCESS)
2482 {
2483 /* [Rn], #expr */
2484 write_back = WRITE_BACK;
2485
2486 if (reg == REG_PC)
2487 {
2488 inst.error = _("pc may not be used in post-increment");
2489 return FAIL;
2490 }
2491
2492 if (cp_byte_address_offset (& p) == FAIL)
2493 return FAIL;
2494 }
2495 else
2496 pre_inc = PRE_INDEX | INDEX_UP;
2497 }
2498 else
2499 {
2500 /* '['Rn, #expr']'[!] */
2501
2502 if (skip_past_comma (& p) == FAIL)
2503 {
2504 inst.error = _("pre-indexed expression expected");
2505 return FAIL;
2506 }
2507
2508 pre_inc = PRE_INDEX;
2509
2510 if (cp_byte_address_offset (& p) == FAIL)
2511 return FAIL;
2512
2513 skip_whitespace (p);
2514
2515 if (*p++ != ']')
2516 {
2517 inst.error = _("missing ]");
2518 return FAIL;
2519 }
2520
2521 skip_whitespace (p);
2522
2523 if (*p == '!')
2524 {
2525 if (reg == REG_PC)
2526 {
2527 inst.error = _("pc may not be used with write-back");
2528 return FAIL;
2529 }
2530
2531 p++;
2532 write_back = WRITE_BACK;
2533 }
2534 }
2535 }
2536 else
2537 {
2538 if (my_get_expression (&inst.reloc.exp, &p))
2539 return FAIL;
2540
2541 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM_S2;
2542 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
2543 inst.reloc.pc_rel = 1;
2544 inst.instruction |= (REG_PC << 16);
2545 pre_inc = PRE_INDEX;
2546 }
2547
2548 inst.instruction |= write_back | pre_inc;
2549 *str = p;
2550 return SUCCESS;
2551 }
2552
2553 static void
2554 do_nop (char * str)
2555 {
2556 skip_whitespace (str);
2557 if (*str == '{')
2558 {
2559 str++;
2560
2561 if (my_get_expression (&inst.reloc.exp, &str))
2562 inst.reloc.exp.X_op = O_illegal;
2563 else
2564 {
2565 skip_whitespace (str);
2566 if (*str == '}')
2567 str++;
2568 else
2569 inst.reloc.exp.X_op = O_illegal;
2570 }
2571
2572 if (inst.reloc.exp.X_op != O_constant
2573 || inst.reloc.exp.X_add_number > 255
2574 || inst.reloc.exp.X_add_number < 0)
2575 {
2576 inst.error = _("Invalid NOP hint");
2577 return;
2578 }
2579
2580 /* Arcitectural NOP hints are CPSR sets with no bits selected. */
2581 inst.instruction &= 0xf0000000;
2582 inst.instruction |= 0x0320f000 + inst.reloc.exp.X_add_number;
2583 }
2584
2585 end_of_line (str);
2586 }
2587
2588 static void
2589 do_empty (char * str)
2590 {
2591 /* Do nothing really. */
2592 end_of_line (str);
2593 }
2594
2595 static void
2596 do_mrs (char * str)
2597 {
2598 int skip = 0;
2599
2600 /* Only one syntax. */
2601 skip_whitespace (str);
2602
2603 if (reg_required_here (&str, 12) == FAIL)
2604 {
2605 inst.error = BAD_ARGS;
2606 return;
2607 }
2608
2609 if (skip_past_comma (&str) == FAIL)
2610 {
2611 inst.error = _("comma expected after register name");
2612 return;
2613 }
2614
2615 skip_whitespace (str);
2616
2617 if ( streq (str, "CPSR")
2618 || streq (str, "SPSR")
2619 /* Lower case versions for backwards compatibility. */
2620 || streq (str, "cpsr")
2621 || streq (str, "spsr"))
2622 skip = 4;
2623
2624 /* This is for backwards compatibility with older toolchains. */
2625 else if ( streq (str, "cpsr_all")
2626 || streq (str, "spsr_all"))
2627 skip = 8;
2628 else
2629 {
2630 inst.error = _("CPSR or SPSR expected");
2631 return;
2632 }
2633
2634 if (* str == 's' || * str == 'S')
2635 inst.instruction |= SPSR_BIT;
2636 str += skip;
2637
2638 end_of_line (str);
2639 }
2640
2641 /* Two possible forms:
2642 "{C|S}PSR_<field>, Rm",
2643 "{C|S}PSR_f, #expression". */
2644
2645 static void
2646 do_msr (char * str)
2647 {
2648 skip_whitespace (str);
2649
2650 if (psr_required_here (& str) == FAIL)
2651 return;
2652
2653 if (skip_past_comma (& str) == FAIL)
2654 {
2655 inst.error = _("comma missing after psr flags");
2656 return;
2657 }
2658
2659 skip_whitespace (str);
2660
2661 if (reg_required_here (& str, 0) != FAIL)
2662 {
2663 inst.error = NULL;
2664 end_of_line (str);
2665 return;
2666 }
2667
2668 if (! is_immediate_prefix (* str))
2669 {
2670 inst.error =
2671 _("only a register or immediate value can follow a psr flag");
2672 return;
2673 }
2674
2675 str ++;
2676 inst.error = NULL;
2677
2678 if (my_get_expression (& inst.reloc.exp, & str))
2679 {
2680 inst.error =
2681 _("only a register or immediate value can follow a psr flag");
2682 return;
2683 }
2684
2685 #if 0 /* The first edition of the ARM architecture manual stated that
2686 writing anything other than the flags with an immediate operation
2687 had UNPREDICTABLE effects. This constraint was removed in the
2688 second edition of the specification. */
2689 if ((cpu_variant & ARM_EXT_V5) != ARM_EXT_V5
2690 && inst.instruction & ((PSR_c | PSR_x | PSR_s) << PSR_SHIFT))
2691 {
2692 inst.error = _("immediate value cannot be used to set this field");
2693 return;
2694 }
2695 #endif
2696
2697 inst.instruction |= INST_IMMEDIATE;
2698
2699 if (inst.reloc.exp.X_add_symbol)
2700 {
2701 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
2702 inst.reloc.pc_rel = 0;
2703 }
2704 else
2705 {
2706 unsigned value = validate_immediate (inst.reloc.exp.X_add_number);
2707
2708 if (value == (unsigned) FAIL)
2709 {
2710 inst.error = _("invalid constant");
2711 return;
2712 }
2713
2714 inst.instruction |= value;
2715 }
2716
2717 inst.error = NULL;
2718 end_of_line (str);
2719 }
2720
2721 /* Long Multiply Parser
2722 UMULL RdLo, RdHi, Rm, Rs
2723 SMULL RdLo, RdHi, Rm, Rs
2724 UMLAL RdLo, RdHi, Rm, Rs
2725 SMLAL RdLo, RdHi, Rm, Rs. */
2726
2727 static void
2728 do_mull (char * str)
2729 {
2730 int rdlo, rdhi, rm, rs;
2731
2732 /* Only one format "rdlo, rdhi, rm, rs". */
2733 skip_whitespace (str);
2734
2735 if ((rdlo = reg_required_here (&str, 12)) == FAIL)
2736 {
2737 inst.error = BAD_ARGS;
2738 return;
2739 }
2740
2741 if (skip_past_comma (&str) == FAIL
2742 || (rdhi = reg_required_here (&str, 16)) == FAIL)
2743 {
2744 inst.error = BAD_ARGS;
2745 return;
2746 }
2747
2748 if (skip_past_comma (&str) == FAIL
2749 || (rm = reg_required_here (&str, 0)) == FAIL)
2750 {
2751 inst.error = BAD_ARGS;
2752 return;
2753 }
2754
2755 /* rdhi, rdlo and rm must all be different. */
2756 if (rdlo == rdhi || rdlo == rm || rdhi == rm)
2757 as_tsktsk (_("rdhi, rdlo and rm must all be different"));
2758
2759 if (skip_past_comma (&str) == FAIL
2760 || (rs = reg_required_here (&str, 8)) == FAIL)
2761 {
2762 inst.error = BAD_ARGS;
2763 return;
2764 }
2765
2766 if (rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC)
2767 {
2768 inst.error = BAD_PC;
2769 return;
2770 }
2771
2772 end_of_line (str);
2773 }
2774
2775 static void
2776 do_mul (char * str)
2777 {
2778 int rd, rm;
2779
2780 /* Only one format "rd, rm, rs". */
2781 skip_whitespace (str);
2782
2783 if ((rd = reg_required_here (&str, 16)) == FAIL)
2784 {
2785 inst.error = BAD_ARGS;
2786 return;
2787 }
2788
2789 if (rd == REG_PC)
2790 {
2791 inst.error = BAD_PC;
2792 return;
2793 }
2794
2795 if (skip_past_comma (&str) == FAIL
2796 || (rm = reg_required_here (&str, 0)) == FAIL)
2797 {
2798 inst.error = BAD_ARGS;
2799 return;
2800 }
2801
2802 if (rm == REG_PC)
2803 {
2804 inst.error = BAD_PC;
2805 return;
2806 }
2807
2808 if (rm == rd)
2809 as_tsktsk (_("rd and rm should be different in mul"));
2810
2811 if (skip_past_comma (&str) == FAIL
2812 || (rm = reg_required_here (&str, 8)) == FAIL)
2813 {
2814 inst.error = BAD_ARGS;
2815 return;
2816 }
2817
2818 if (rm == REG_PC)
2819 {
2820 inst.error = BAD_PC;
2821 return;
2822 }
2823
2824 end_of_line (str);
2825 }
2826
2827 static void
2828 do_mla (char * str)
2829 {
2830 int rd, rm;
2831
2832 /* Only one format "rd, rm, rs, rn". */
2833 skip_whitespace (str);
2834
2835 if ((rd = reg_required_here (&str, 16)) == FAIL)
2836 {
2837 inst.error = BAD_ARGS;
2838 return;
2839 }
2840
2841 if (rd == REG_PC)
2842 {
2843 inst.error = BAD_PC;
2844 return;
2845 }
2846
2847 if (skip_past_comma (&str) == FAIL
2848 || (rm = reg_required_here (&str, 0)) == FAIL)
2849 {
2850 inst.error = BAD_ARGS;
2851 return;
2852 }
2853
2854 if (rm == REG_PC)
2855 {
2856 inst.error = BAD_PC;
2857 return;
2858 }
2859
2860 if (rm == rd)
2861 as_tsktsk (_("rd and rm should be different in mla"));
2862
2863 if (skip_past_comma (&str) == FAIL
2864 || (rd = reg_required_here (&str, 8)) == FAIL
2865 || skip_past_comma (&str) == FAIL
2866 || (rm = reg_required_here (&str, 12)) == FAIL)
2867 {
2868 inst.error = BAD_ARGS;
2869 return;
2870 }
2871
2872 if (rd == REG_PC || rm == REG_PC)
2873 {
2874 inst.error = BAD_PC;
2875 return;
2876 }
2877
2878 end_of_line (str);
2879 }
2880
2881 /* Expects *str -> the characters "acc0", possibly with leading blanks.
2882 Advances *str to the next non-alphanumeric.
2883 Returns 0, or else FAIL (in which case sets inst.error).
2884
2885 (In a future XScale, there may be accumulators other than zero.
2886 At that time this routine and its callers can be upgraded to suit.) */
2887
2888 static int
2889 accum0_required_here (char ** str)
2890 {
2891 static char buff [128]; /* Note the address is taken. Hence, static. */
2892 char * p = * str;
2893 char c;
2894 int result = 0; /* The accum number. */
2895
2896 skip_whitespace (p);
2897
2898 *str = p; /* Advance caller's string pointer too. */
2899 c = *p++;
2900 while (ISALNUM (c))
2901 c = *p++;
2902
2903 *--p = 0; /* Aap nul into input buffer at non-alnum. */
2904
2905 if (! ( streq (*str, "acc0") || streq (*str, "ACC0")))
2906 {
2907 sprintf (buff, _("acc0 expected, not '%.100s'"), *str);
2908 inst.error = buff;
2909 result = FAIL;
2910 }
2911
2912 *p = c; /* Unzap. */
2913 *str = p; /* Caller's string pointer to after match. */
2914 return result;
2915 }
2916
2917 static int
2918 ldst_extend_v4 (char ** str)
2919 {
2920 int add = INDEX_UP;
2921
2922 switch (**str)
2923 {
2924 case '#':
2925 case '$':
2926 (*str)++;
2927 if (my_get_expression (& inst.reloc.exp, str))
2928 return FAIL;
2929
2930 if (inst.reloc.exp.X_op == O_constant)
2931 {
2932 int value = inst.reloc.exp.X_add_number;
2933
2934 if (value < -255 || value > 255)
2935 {
2936 inst.error = _("address offset too large");
2937 return FAIL;
2938 }
2939
2940 if (value < 0)
2941 {
2942 value = -value;
2943 add = 0;
2944 }
2945
2946 /* Halfword and signextension instructions have the
2947 immediate value split across bits 11..8 and bits 3..0. */
2948 inst.instruction |= (add | HWOFFSET_IMM
2949 | ((value >> 4) << 8) | (value & 0xF));
2950 }
2951 else
2952 {
2953 inst.instruction |= HWOFFSET_IMM;
2954 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
2955 inst.reloc.pc_rel = 0;
2956 }
2957 return SUCCESS;
2958
2959 case '-':
2960 add = 0;
2961 /* Fall through. */
2962
2963 case '+':
2964 (*str)++;
2965 /* Fall through. */
2966
2967 default:
2968 if (reg_required_here (str, 0) == FAIL)
2969 return FAIL;
2970
2971 inst.instruction |= add;
2972 return SUCCESS;
2973 }
2974 }
2975
2976 /* Expects **str -> after a comma. May be leading blanks.
2977 Advances *str, recognizing a load mode, and setting inst.instruction.
2978 Returns rn, or else FAIL (in which case may set inst.error
2979 and not advance str)
2980
2981 Note: doesn't know Rd, so no err checks that require such knowledge. */
2982
2983 static int
2984 ld_mode_required_here (char ** string)
2985 {
2986 char * str = * string;
2987 int rn;
2988 int pre_inc = 0;
2989
2990 skip_whitespace (str);
2991
2992 if (* str == '[')
2993 {
2994 str++;
2995
2996 skip_whitespace (str);
2997
2998 if ((rn = reg_required_here (& str, 16)) == FAIL)
2999 return FAIL;
3000
3001 skip_whitespace (str);
3002
3003 if (* str == ']')
3004 {
3005 str ++;
3006
3007 if (skip_past_comma (& str) == SUCCESS)
3008 {
3009 /* [Rn],... (post inc) */
3010 if (ldst_extend_v4 (&str) == FAIL)
3011 return FAIL;
3012 }
3013 else /* [Rn] */
3014 {
3015 skip_whitespace (str);
3016
3017 if (* str == '!')
3018 {
3019 str ++;
3020 inst.instruction |= WRITE_BACK;
3021 }
3022
3023 inst.instruction |= INDEX_UP | HWOFFSET_IMM;
3024 pre_inc = 1;
3025 }
3026 }
3027 else /* [Rn,...] */
3028 {
3029 if (skip_past_comma (& str) == FAIL)
3030 {
3031 inst.error = _("pre-indexed expression expected");
3032 return FAIL;
3033 }
3034
3035 pre_inc = 1;
3036
3037 if (ldst_extend_v4 (&str) == FAIL)
3038 return FAIL;
3039
3040 skip_whitespace (str);
3041
3042 if (* str ++ != ']')
3043 {
3044 inst.error = _("missing ]");
3045 return FAIL;
3046 }
3047
3048 skip_whitespace (str);
3049
3050 if (* str == '!')
3051 {
3052 str ++;
3053 inst.instruction |= WRITE_BACK;
3054 }
3055 }
3056 }
3057 else if (* str == '=') /* ldr's "r,=label" syntax */
3058 /* We should never reach here, because <text> = <expression> is
3059 caught gas/read.c read_a_source_file() as a .set operation. */
3060 return FAIL;
3061 else /* PC +- 8 bit immediate offset. */
3062 {
3063 if (my_get_expression (& inst.reloc.exp, & str))
3064 return FAIL;
3065
3066 inst.instruction |= HWOFFSET_IMM; /* The I bit. */
3067 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
3068 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
3069 inst.reloc.pc_rel = 1;
3070 inst.instruction |= (REG_PC << 16);
3071
3072 rn = REG_PC;
3073 pre_inc = 1;
3074 }
3075
3076 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
3077 * string = str;
3078
3079 return rn;
3080 }
3081
3082 /* ARM V5E (El Segundo) signed-multiply-accumulate (argument parse)
3083 SMLAxy{cond} Rd,Rm,Rs,Rn
3084 SMLAWy{cond} Rd,Rm,Rs,Rn
3085 Error if any register is R15. */
3086
3087 static void
3088 do_smla (char * str)
3089 {
3090 int rd, rm, rs, rn;
3091
3092 skip_whitespace (str);
3093
3094 if ((rd = reg_required_here (& str, 16)) == FAIL
3095 || skip_past_comma (& str) == FAIL
3096 || (rm = reg_required_here (& str, 0)) == FAIL
3097 || skip_past_comma (& str) == FAIL
3098 || (rs = reg_required_here (& str, 8)) == FAIL
3099 || skip_past_comma (& str) == FAIL
3100 || (rn = reg_required_here (& str, 12)) == FAIL)
3101 inst.error = BAD_ARGS;
3102
3103 else if (rd == REG_PC || rm == REG_PC || rs == REG_PC || rn == REG_PC)
3104 inst.error = BAD_PC;
3105
3106 else
3107 end_of_line (str);
3108 }
3109
3110 /* ARM V5E (El Segundo) signed-multiply-accumulate-long (argument parse)
3111 SMLALxy{cond} Rdlo,Rdhi,Rm,Rs
3112 Error if any register is R15.
3113 Warning if Rdlo == Rdhi. */
3114
3115 static void
3116 do_smlal (char * str)
3117 {
3118 int rdlo, rdhi, rm, rs;
3119
3120 skip_whitespace (str);
3121
3122 if ((rdlo = reg_required_here (& str, 12)) == FAIL
3123 || skip_past_comma (& str) == FAIL
3124 || (rdhi = reg_required_here (& str, 16)) == FAIL
3125 || skip_past_comma (& str) == FAIL
3126 || (rm = reg_required_here (& str, 0)) == FAIL
3127 || skip_past_comma (& str) == FAIL
3128 || (rs = reg_required_here (& str, 8)) == FAIL)
3129 {
3130 inst.error = BAD_ARGS;
3131 return;
3132 }
3133
3134 if (rdlo == REG_PC || rdhi == REG_PC || rm == REG_PC || rs == REG_PC)
3135 {
3136 inst.error = BAD_PC;
3137 return;
3138 }
3139
3140 if (rdlo == rdhi)
3141 as_tsktsk (_("rdhi and rdlo must be different"));
3142
3143 end_of_line (str);
3144 }
3145
3146 /* ARM V5E (El Segundo) signed-multiply (argument parse)
3147 SMULxy{cond} Rd,Rm,Rs
3148 Error if any register is R15. */
3149
3150 static void
3151 do_smul (char * str)
3152 {
3153 int rd, rm, rs;
3154
3155 skip_whitespace (str);
3156
3157 if ((rd = reg_required_here (& str, 16)) == FAIL
3158 || skip_past_comma (& str) == FAIL
3159 || (rm = reg_required_here (& str, 0)) == FAIL
3160 || skip_past_comma (& str) == FAIL
3161 || (rs = reg_required_here (& str, 8)) == FAIL)
3162 inst.error = BAD_ARGS;
3163
3164 else if (rd == REG_PC || rm == REG_PC || rs == REG_PC)
3165 inst.error = BAD_PC;
3166
3167 else
3168 end_of_line (str);
3169 }
3170
3171 /* ARM V5E (El Segundo) saturating-add/subtract (argument parse)
3172 Q[D]{ADD,SUB}{cond} Rd,Rm,Rn
3173 Error if any register is R15. */
3174
3175 static void
3176 do_qadd (char * str)
3177 {
3178 int rd, rm, rn;
3179
3180 skip_whitespace (str);
3181
3182 if ((rd = reg_required_here (& str, 12)) == FAIL
3183 || skip_past_comma (& str) == FAIL
3184 || (rm = reg_required_here (& str, 0)) == FAIL
3185 || skip_past_comma (& str) == FAIL
3186 || (rn = reg_required_here (& str, 16)) == FAIL)
3187 inst.error = BAD_ARGS;
3188
3189 else if (rd == REG_PC || rm == REG_PC || rn == REG_PC)
3190 inst.error = BAD_PC;
3191
3192 else
3193 end_of_line (str);
3194 }
3195
3196 /* ARM V5E (el Segundo)
3197 MCRRcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
3198 MRRCcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
3199
3200 These are equivalent to the XScale instructions MAR and MRA,
3201 respectively, when coproc == 0, opcode == 0, and CRm == 0.
3202
3203 Result unpredicatable if Rd or Rn is R15. */
3204
3205 static void
3206 do_co_reg2c (char * str)
3207 {
3208 int rd, rn;
3209
3210 skip_whitespace (str);
3211
3212 if (co_proc_number (& str) == FAIL)
3213 {
3214 if (!inst.error)
3215 inst.error = BAD_ARGS;
3216 return;
3217 }
3218
3219 if (skip_past_comma (& str) == FAIL
3220 || cp_opc_expr (& str, 4, 4) == FAIL)
3221 {
3222 if (!inst.error)
3223 inst.error = BAD_ARGS;
3224 return;
3225 }
3226
3227 if (skip_past_comma (& str) == FAIL
3228 || (rd = reg_required_here (& str, 12)) == FAIL)
3229 {
3230 if (!inst.error)
3231 inst.error = BAD_ARGS;
3232 return;
3233 }
3234
3235 if (skip_past_comma (& str) == FAIL
3236 || (rn = reg_required_here (& str, 16)) == FAIL)
3237 {
3238 if (!inst.error)
3239 inst.error = BAD_ARGS;
3240 return;
3241 }
3242
3243 /* Unpredictable result if rd or rn is R15. */
3244 if (rd == REG_PC || rn == REG_PC)
3245 as_tsktsk
3246 (_("Warning: instruction unpredictable when using r15"));
3247
3248 if (skip_past_comma (& str) == FAIL
3249 || cp_reg_required_here (& str, 0) == FAIL)
3250 {
3251 if (!inst.error)
3252 inst.error = BAD_ARGS;
3253 return;
3254 }
3255
3256 end_of_line (str);
3257 }
3258
3259 /* ARM V5 count-leading-zeroes instruction (argument parse)
3260 CLZ{<cond>} <Rd>, <Rm>
3261 Condition defaults to COND_ALWAYS.
3262 Error if Rd or Rm are R15. */
3263
3264 static void
3265 do_clz (char * str)
3266 {
3267 int rd, rm;
3268
3269 skip_whitespace (str);
3270
3271 if (((rd = reg_required_here (& str, 12)) == FAIL)
3272 || (skip_past_comma (& str) == FAIL)
3273 || ((rm = reg_required_here (& str, 0)) == FAIL))
3274 inst.error = BAD_ARGS;
3275
3276 else if (rd == REG_PC || rm == REG_PC )
3277 inst.error = BAD_PC;
3278
3279 else
3280 end_of_line (str);
3281 }
3282
3283 /* ARM V5 (argument parse)
3284 LDC2{L} <coproc>, <CRd>, <addressing mode>
3285 STC2{L} <coproc>, <CRd>, <addressing mode>
3286 Instruction is not conditional, and has 0xf in the condition field.
3287 Otherwise, it's the same as LDC/STC. */
3288
3289 static void
3290 do_lstc2 (char * str)
3291 {
3292 skip_whitespace (str);
3293
3294 if (co_proc_number (& str) == FAIL)
3295 {
3296 if (!inst.error)
3297 inst.error = BAD_ARGS;
3298 }
3299 else if (skip_past_comma (& str) == FAIL
3300 || cp_reg_required_here (& str, 12) == FAIL)
3301 {
3302 if (!inst.error)
3303 inst.error = BAD_ARGS;
3304 }
3305 else if (skip_past_comma (& str) == FAIL
3306 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
3307 {
3308 if (! inst.error)
3309 inst.error = BAD_ARGS;
3310 }
3311 else
3312 end_of_line (str);
3313 }
3314
3315 /* ARM V5 (argument parse)
3316 CDP2 <coproc>, <opcode_1>, <CRd>, <CRn>, <CRm>, <opcode_2>
3317 Instruction is not conditional, and has 0xf in the condition field.
3318 Otherwise, it's the same as CDP. */
3319
3320 static void
3321 do_cdp2 (char * str)
3322 {
3323 skip_whitespace (str);
3324
3325 if (co_proc_number (& str) == FAIL)
3326 {
3327 if (!inst.error)
3328 inst.error = BAD_ARGS;
3329 return;
3330 }
3331
3332 if (skip_past_comma (& str) == FAIL
3333 || cp_opc_expr (& str, 20,4) == FAIL)
3334 {
3335 if (!inst.error)
3336 inst.error = BAD_ARGS;
3337 return;
3338 }
3339
3340 if (skip_past_comma (& str) == FAIL
3341 || cp_reg_required_here (& str, 12) == FAIL)
3342 {
3343 if (!inst.error)
3344 inst.error = BAD_ARGS;
3345 return;
3346 }
3347
3348 if (skip_past_comma (& str) == FAIL
3349 || cp_reg_required_here (& str, 16) == FAIL)
3350 {
3351 if (!inst.error)
3352 inst.error = BAD_ARGS;
3353 return;
3354 }
3355
3356 if (skip_past_comma (& str) == FAIL
3357 || cp_reg_required_here (& str, 0) == FAIL)
3358 {
3359 if (!inst.error)
3360 inst.error = BAD_ARGS;
3361 return;
3362 }
3363
3364 if (skip_past_comma (& str) == SUCCESS)
3365 {
3366 if (cp_opc_expr (& str, 5, 3) == FAIL)
3367 {
3368 if (!inst.error)
3369 inst.error = BAD_ARGS;
3370 return;
3371 }
3372 }
3373
3374 end_of_line (str);
3375 }
3376
3377 /* ARM V5 (argument parse)
3378 MCR2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
3379 MRC2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
3380 Instruction is not conditional, and has 0xf in the condition field.
3381 Otherwise, it's the same as MCR/MRC. */
3382
3383 static void
3384 do_co_reg2 (char * str)
3385 {
3386 skip_whitespace (str);
3387
3388 if (co_proc_number (& str) == FAIL)
3389 {
3390 if (!inst.error)
3391 inst.error = BAD_ARGS;
3392 return;
3393 }
3394
3395 if (skip_past_comma (& str) == FAIL
3396 || cp_opc_expr (& str, 21, 3) == FAIL)
3397 {
3398 if (!inst.error)
3399 inst.error = BAD_ARGS;
3400 return;
3401 }
3402
3403 if (skip_past_comma (& str) == FAIL
3404 || reg_required_here (& str, 12) == FAIL)
3405 {
3406 if (!inst.error)
3407 inst.error = BAD_ARGS;
3408 return;
3409 }
3410
3411 if (skip_past_comma (& str) == FAIL
3412 || cp_reg_required_here (& str, 16) == FAIL)
3413 {
3414 if (!inst.error)
3415 inst.error = BAD_ARGS;
3416 return;
3417 }
3418
3419 if (skip_past_comma (& str) == FAIL
3420 || cp_reg_required_here (& str, 0) == FAIL)
3421 {
3422 if (!inst.error)
3423 inst.error = BAD_ARGS;
3424 return;
3425 }
3426
3427 if (skip_past_comma (& str) == SUCCESS)
3428 {
3429 if (cp_opc_expr (& str, 5, 3) == FAIL)
3430 {
3431 if (!inst.error)
3432 inst.error = BAD_ARGS;
3433 return;
3434 }
3435 }
3436
3437 end_of_line (str);
3438 }
3439
3440 static void
3441 do_bx (char * str)
3442 {
3443 int reg;
3444
3445 skip_whitespace (str);
3446
3447 if ((reg = reg_required_here (&str, 0)) == FAIL)
3448 {
3449 inst.error = BAD_ARGS;
3450 return;
3451 }
3452
3453 /* Note - it is not illegal to do a "bx pc". Useless, but not illegal. */
3454 if (reg == REG_PC)
3455 as_tsktsk (_("use of r15 in bx in ARM mode is not really useful"));
3456
3457 end_of_line (str);
3458 }
3459
3460 /* ARM v5TEJ. Jump to Jazelle code. */
3461
3462 static void
3463 do_bxj (char * str)
3464 {
3465 int reg;
3466
3467 skip_whitespace (str);
3468
3469 if ((reg = reg_required_here (&str, 0)) == FAIL)
3470 {
3471 inst.error = BAD_ARGS;
3472 return;
3473 }
3474
3475 /* Note - it is not illegal to do a "bxj pc". Useless, but not illegal. */
3476 if (reg == REG_PC)
3477 as_tsktsk (_("use of r15 in bxj is not really useful"));
3478
3479 end_of_line (str);
3480 }
3481
3482 /* ARM V6 umaal (argument parse). */
3483
3484 static void
3485 do_umaal (char * str)
3486 {
3487 int rdlo, rdhi, rm, rs;
3488
3489 skip_whitespace (str);
3490 if ((rdlo = reg_required_here (& str, 12)) == FAIL
3491 || skip_past_comma (& str) == FAIL
3492 || (rdhi = reg_required_here (& str, 16)) == FAIL
3493 || skip_past_comma (& str) == FAIL
3494 || (rm = reg_required_here (& str, 0)) == FAIL
3495 || skip_past_comma (& str) == FAIL
3496 || (rs = reg_required_here (& str, 8)) == FAIL)
3497 {
3498 inst.error = BAD_ARGS;
3499 return;
3500 }
3501
3502 if (rdlo == REG_PC || rdhi == REG_PC || rm == REG_PC || rs == REG_PC)
3503 {
3504 inst.error = BAD_PC;
3505 return;
3506 }
3507
3508 end_of_line (str);
3509 }
3510
3511 /* ARM V6 strex (argument parse). */
3512
3513 static void
3514 do_strex (char * str)
3515 {
3516 int rd, rm, rn;
3517
3518 /* Parse Rd, Rm,. */
3519 skip_whitespace (str);
3520 if ((rd = reg_required_here (& str, 12)) == FAIL
3521 || skip_past_comma (& str) == FAIL
3522 || (rm = reg_required_here (& str, 0)) == FAIL
3523 || skip_past_comma (& str) == FAIL)
3524 {
3525 inst.error = BAD_ARGS;
3526 return;
3527 }
3528 if (rd == REG_PC || rm == REG_PC)
3529 {
3530 inst.error = BAD_PC;
3531 return;
3532 }
3533 if (rd == rm)
3534 {
3535 inst.error = _("Rd equal to Rm or Rn yields unpredictable results");
3536 return;
3537 }
3538
3539 /* Skip past '['. */
3540 if ((strlen (str) >= 1)
3541 && strncmp (str, "[", 1) == 0)
3542 str += 1;
3543
3544 skip_whitespace (str);
3545
3546 /* Parse Rn. */
3547 if ((rn = reg_required_here (& str, 16)) == FAIL)
3548 {
3549 inst.error = BAD_ARGS;
3550 return;
3551 }
3552 else if (rn == REG_PC)
3553 {
3554 inst.error = BAD_PC;
3555 return;
3556 }
3557 if (rd == rn)
3558 {
3559 inst.error = _("Rd equal to Rm or Rn yields unpredictable results");
3560 return;
3561 }
3562 skip_whitespace (str);
3563
3564 /* Skip past ']'. */
3565 if ((strlen (str) >= 1)
3566 && strncmp (str, "]", 1) == 0)
3567 str += 1;
3568
3569 end_of_line (str);
3570 }
3571
3572 /* KIND indicates what kind of shifts are accepted. */
3573
3574 static int
3575 decode_shift (char ** str, int kind)
3576 {
3577 const struct asm_shift_name * shift;
3578 char * p;
3579 char c;
3580
3581 skip_whitespace (* str);
3582
3583 for (p = * str; ISALPHA (* p); p ++)
3584 ;
3585
3586 if (p == * str)
3587 {
3588 inst.error = _("shift expression expected");
3589 return FAIL;
3590 }
3591
3592 c = * p;
3593 * p = '\0';
3594 shift = (const struct asm_shift_name *) hash_find (arm_shift_hsh, * str);
3595 * p = c;
3596
3597 if (shift == NULL)
3598 {
3599 inst.error = _("shift expression expected");
3600 return FAIL;
3601 }
3602
3603 assert (shift->properties->index == shift_properties[shift->properties->index].index);
3604
3605 if (kind == SHIFT_LSL_OR_ASR_IMMEDIATE
3606 && shift->properties->index != SHIFT_LSL
3607 && shift->properties->index != SHIFT_ASR)
3608 {
3609 inst.error = _("'LSL' or 'ASR' required");
3610 return FAIL;
3611 }
3612 else if (kind == SHIFT_LSL_IMMEDIATE
3613 && shift->properties->index != SHIFT_LSL)
3614 {
3615 inst.error = _("'LSL' required");
3616 return FAIL;
3617 }
3618 else if (kind == SHIFT_ASR_IMMEDIATE
3619 && shift->properties->index != SHIFT_ASR)
3620 {
3621 inst.error = _("'ASR' required");
3622 return FAIL;
3623 }
3624
3625 if (shift->properties->index == SHIFT_RRX)
3626 {
3627 * str = p;
3628 inst.instruction |= shift->properties->bit_field;
3629 return SUCCESS;
3630 }
3631
3632 skip_whitespace (p);
3633
3634 if (kind == NO_SHIFT_RESTRICT && reg_required_here (& p, 8) != FAIL)
3635 {
3636 inst.instruction |= shift->properties->bit_field | SHIFT_BY_REG;
3637 * str = p;
3638 return SUCCESS;
3639 }
3640 else if (! is_immediate_prefix (* p))
3641 {
3642 inst.error = (NO_SHIFT_RESTRICT
3643 ? _("shift requires register or #expression")
3644 : _("shift requires #expression"));
3645 * str = p;
3646 return FAIL;
3647 }
3648
3649 inst.error = NULL;
3650 p ++;
3651
3652 if (my_get_expression (& inst.reloc.exp, & p))
3653 return FAIL;
3654
3655 /* Validate some simple #expressions. */
3656 if (inst.reloc.exp.X_op == O_constant)
3657 {
3658 unsigned num = inst.reloc.exp.X_add_number;
3659
3660 /* Reject operations greater than 32. */
3661 if (num > 32
3662 /* Reject a shift of 0 unless the mode allows it. */
3663 || (num == 0 && shift->properties->allows_0 == 0)
3664 /* Reject a shift of 32 unless the mode allows it. */
3665 || (num == 32 && shift->properties->allows_32 == 0)
3666 )
3667 {
3668 /* As a special case we allow a shift of zero for
3669 modes that do not support it to be recoded as an
3670 logical shift left of zero (ie nothing). We warn
3671 about this though. */
3672 if (num == 0)
3673 {
3674 as_warn (_("shift of 0 ignored."));
3675 shift = & shift_names[0];
3676 assert (shift->properties->index == SHIFT_LSL);
3677 }
3678 else
3679 {
3680 inst.error = _("invalid immediate shift");
3681 return FAIL;
3682 }
3683 }
3684
3685 /* Shifts of 32 are encoded as 0, for those shifts that
3686 support it. */
3687 if (num == 32)
3688 num = 0;
3689
3690 inst.instruction |= (num << 7) | shift->properties->bit_field;
3691 }
3692 else
3693 {
3694 inst.reloc.type = BFD_RELOC_ARM_SHIFT_IMM;
3695 inst.reloc.pc_rel = 0;
3696 inst.instruction |= shift->properties->bit_field;
3697 }
3698
3699 * str = p;
3700 return SUCCESS;
3701 }
3702
3703 static void
3704 do_sat (char ** str, int bias)
3705 {
3706 int rd, rm;
3707 expressionS expr;
3708
3709 skip_whitespace (*str);
3710
3711 /* Parse <Rd>, field. */
3712 if ((rd = reg_required_here (str, 12)) == FAIL
3713 || skip_past_comma (str) == FAIL)
3714 {
3715 inst.error = BAD_ARGS;
3716 return;
3717 }
3718 if (rd == REG_PC)
3719 {
3720 inst.error = BAD_PC;
3721 return;
3722 }
3723
3724 /* Parse #<immed>, field. */
3725 if (is_immediate_prefix (**str))
3726 (*str)++;
3727 else
3728 {
3729 inst.error = _("immediate expression expected");
3730 return;
3731 }
3732 if (my_get_expression (&expr, str))
3733 {
3734 inst.error = _("bad expression");
3735 return;
3736 }
3737 if (expr.X_op != O_constant)
3738 {
3739 inst.error = _("constant expression expected");
3740 return;
3741 }
3742 if (expr.X_add_number + bias < 0
3743 || expr.X_add_number + bias > 31)
3744 {
3745 inst.error = _("immediate value out of range");
3746 return;
3747 }
3748 inst.instruction |= (expr.X_add_number + bias) << 16;
3749 if (skip_past_comma (str) == FAIL)
3750 {
3751 inst.error = BAD_ARGS;
3752 return;
3753 }
3754
3755 /* Parse <Rm> field. */
3756 if ((rm = reg_required_here (str, 0)) == FAIL)
3757 {
3758 inst.error = BAD_ARGS;
3759 return;
3760 }
3761 if (rm == REG_PC)
3762 {
3763 inst.error = BAD_PC;
3764 return;
3765 }
3766
3767 if (skip_past_comma (str) == SUCCESS)
3768 decode_shift (str, SHIFT_LSL_OR_ASR_IMMEDIATE);
3769 }
3770
3771 /* ARM V6 ssat (argument parse). */
3772
3773 static void
3774 do_ssat (char * str)
3775 {
3776 do_sat (&str, /*bias=*/-1);
3777 end_of_line (str);
3778 }
3779
3780 /* ARM V6 usat (argument parse). */
3781
3782 static void
3783 do_usat (char * str)
3784 {
3785 do_sat (&str, /*bias=*/0);
3786 end_of_line (str);
3787 }
3788
3789 static void
3790 do_sat16 (char ** str, int bias)
3791 {
3792 int rd, rm;
3793 expressionS expr;
3794
3795 skip_whitespace (*str);
3796
3797 /* Parse the <Rd> field. */
3798 if ((rd = reg_required_here (str, 12)) == FAIL
3799 || skip_past_comma (str) == FAIL)
3800 {
3801 inst.error = BAD_ARGS;
3802 return;
3803 }
3804 if (rd == REG_PC)
3805 {
3806 inst.error = BAD_PC;
3807 return;
3808 }
3809
3810 /* Parse #<immed>, field. */
3811 if (is_immediate_prefix (**str))
3812 (*str)++;
3813 else
3814 {
3815 inst.error = _("immediate expression expected");
3816 return;
3817 }
3818 if (my_get_expression (&expr, str))
3819 {
3820 inst.error = _("bad expression");
3821 return;
3822 }
3823 if (expr.X_op != O_constant)
3824 {
3825 inst.error = _("constant expression expected");
3826 return;
3827 }
3828 if (expr.X_add_number + bias < 0
3829 || expr.X_add_number + bias > 15)
3830 {
3831 inst.error = _("immediate value out of range");
3832 return;
3833 }
3834 inst.instruction |= (expr.X_add_number + bias) << 16;
3835 if (skip_past_comma (str) == FAIL)
3836 {
3837 inst.error = BAD_ARGS;
3838 return;
3839 }
3840
3841 /* Parse <Rm> field. */
3842 if ((rm = reg_required_here (str, 0)) == FAIL)
3843 {
3844 inst.error = BAD_ARGS;
3845 return;
3846 }
3847 if (rm == REG_PC)
3848 {
3849 inst.error = BAD_PC;
3850 return;
3851 }
3852 }
3853
3854 /* ARM V6 ssat16 (argument parse). */
3855
3856 static void
3857 do_ssat16 (char * str)
3858 {
3859 do_sat16 (&str, /*bias=*/-1);
3860 end_of_line (str);
3861 }
3862
3863 static void
3864 do_usat16 (char * str)
3865 {
3866 do_sat16 (&str, /*bias=*/0);
3867 end_of_line (str);
3868 }
3869
3870 static void
3871 do_cps_mode (char ** str)
3872 {
3873 expressionS expr;
3874
3875 skip_whitespace (*str);
3876
3877 if (! is_immediate_prefix (**str))
3878 {
3879 inst.error = _("immediate expression expected");
3880 return;
3881 }
3882
3883 (*str)++; /* Strip off the immediate signifier. */
3884 if (my_get_expression (&expr, str))
3885 {
3886 inst.error = _("bad expression");
3887 return;
3888 }
3889
3890 if (expr.X_op != O_constant)
3891 {
3892 inst.error = _("constant expression expected");
3893 return;
3894 }
3895
3896 /* The mode is a 5 bit field. Valid values are 0-31. */
3897 if (((unsigned) expr.X_add_number) > 31
3898 || (inst.reloc.exp.X_add_number) < 0)
3899 {
3900 inst.error = _("invalid constant");
3901 return;
3902 }
3903
3904 inst.instruction |= expr.X_add_number;
3905 }
3906
3907 /* ARM V6 srs (argument parse). */
3908
3909 static void
3910 do_srs (char * str)
3911 {
3912 char *exclam;
3913 skip_whitespace (str);
3914 exclam = strchr (str, '!');
3915 if (exclam)
3916 *exclam = '\0';
3917 do_cps_mode (&str);
3918 if (exclam)
3919 *exclam = '!';
3920 if (*str == '!')
3921 {
3922 inst.instruction |= WRITE_BACK;
3923 str++;
3924 }
3925 end_of_line (str);
3926 }
3927
3928 /* ARM V6 SMMUL (argument parse). */
3929
3930 static void
3931 do_smmul (char * str)
3932 {
3933 int rd, rm, rs;
3934
3935 skip_whitespace (str);
3936 if ((rd = reg_required_here (&str, 16)) == FAIL
3937 || skip_past_comma (&str) == FAIL
3938 || (rm = reg_required_here (&str, 0)) == FAIL
3939 || skip_past_comma (&str) == FAIL
3940 || (rs = reg_required_here (&str, 8)) == FAIL)
3941 {
3942 inst.error = BAD_ARGS;
3943 return;
3944 }
3945
3946 if ( rd == REG_PC
3947 || rm == REG_PC
3948 || rs == REG_PC)
3949 {
3950 inst.error = BAD_PC;
3951 return;
3952 }
3953
3954 end_of_line (str);
3955 }
3956
3957 /* ARM V6 SMLALD (argument parse). */
3958
3959 static void
3960 do_smlald (char * str)
3961 {
3962 int rdlo, rdhi, rm, rs;
3963
3964 skip_whitespace (str);
3965 if ((rdlo = reg_required_here (&str, 12)) == FAIL
3966 || skip_past_comma (&str) == FAIL
3967 || (rdhi = reg_required_here (&str, 16)) == FAIL
3968 || skip_past_comma (&str) == FAIL
3969 || (rm = reg_required_here (&str, 0)) == FAIL
3970 || skip_past_comma (&str) == FAIL
3971 || (rs = reg_required_here (&str, 8)) == FAIL)
3972 {
3973 inst.error = BAD_ARGS;
3974 return;
3975 }
3976
3977 if ( rdlo == REG_PC
3978 || rdhi == REG_PC
3979 || rm == REG_PC
3980 || rs == REG_PC)
3981 {
3982 inst.error = BAD_PC;
3983 return;
3984 }
3985
3986 end_of_line (str);
3987 }
3988
3989 /* ARM V6 SMLAD (argument parse). Signed multiply accumulate dual.
3990 smlad{x}{<cond>} Rd, Rm, Rs, Rn */
3991
3992 static void
3993 do_smlad (char * str)
3994 {
3995 int rd, rm, rs, rn;
3996
3997 skip_whitespace (str);
3998 if ((rd = reg_required_here (&str, 16)) == FAIL
3999 || skip_past_comma (&str) == FAIL
4000 || (rm = reg_required_here (&str, 0)) == FAIL
4001 || skip_past_comma (&str) == FAIL
4002 || (rs = reg_required_here (&str, 8)) == FAIL
4003 || skip_past_comma (&str) == FAIL
4004 || (rn = reg_required_here (&str, 12)) == FAIL)
4005 {
4006 inst.error = BAD_ARGS;
4007 return;
4008 }
4009
4010 if ( rd == REG_PC
4011 || rn == REG_PC
4012 || rs == REG_PC
4013 || rm == REG_PC)
4014 {
4015 inst.error = BAD_PC;
4016 return;
4017 }
4018
4019 end_of_line (str);
4020 }
4021
4022 /* Returns true if the endian-specifier indicates big-endianness. */
4023
4024 static int
4025 do_endian_specifier (char * str)
4026 {
4027 int big_endian = 0;
4028
4029 skip_whitespace (str);
4030 if (strlen (str) < 2)
4031 inst.error = _("missing endian specifier");
4032 else if (strncasecmp (str, "BE", 2) == 0)
4033 {
4034 str += 2;
4035 big_endian = 1;
4036 }
4037 else if (strncasecmp (str, "LE", 2) == 0)
4038 str += 2;
4039 else
4040 inst.error = _("valid endian specifiers are be or le");
4041
4042 end_of_line (str);
4043
4044 return big_endian;
4045 }
4046
4047 /* ARM V6 SETEND (argument parse). Sets the E bit in the CPSR while
4048 preserving the other bits.
4049
4050 setend <endian_specifier>, where <endian_specifier> is either
4051 BE or LE. */
4052
4053 static void
4054 do_setend (char * str)
4055 {
4056 if (do_endian_specifier (str))
4057 inst.instruction |= 0x200;
4058 }
4059
4060 /* ARM V6 SXTH.
4061
4062 SXTH {<cond>} <Rd>, <Rm>{, <rotation>}
4063 Condition defaults to COND_ALWAYS.
4064 Error if any register uses R15. */
4065
4066 static void
4067 do_sxth (char * str)
4068 {
4069 int rd, rm;
4070 expressionS expr;
4071 int rotation_clear_mask = 0xfffff3ff;
4072 int rotation_eight_mask = 0x00000400;
4073 int rotation_sixteen_mask = 0x00000800;
4074 int rotation_twenty_four_mask = 0x00000c00;
4075
4076 skip_whitespace (str);
4077 if ((rd = reg_required_here (&str, 12)) == FAIL
4078 || skip_past_comma (&str) == FAIL
4079 || (rm = reg_required_here (&str, 0)) == FAIL)
4080 {
4081 inst.error = BAD_ARGS;
4082 return;
4083 }
4084
4085 else if (rd == REG_PC || rm == REG_PC)
4086 {
4087 inst.error = BAD_PC;
4088 return;
4089 }
4090
4091 /* Zero out the rotation field. */
4092 inst.instruction &= rotation_clear_mask;
4093
4094 /* Check for lack of optional rotation field. */
4095 if (skip_past_comma (&str) == FAIL)
4096 {
4097 end_of_line (str);
4098 return;
4099 }
4100
4101 /* Move past 'ROR'. */
4102 skip_whitespace (str);
4103 if (strncasecmp (str, "ROR", 3) == 0)
4104 str += 3;
4105 else
4106 {
4107 inst.error = _("missing rotation field after comma");
4108 return;
4109 }
4110
4111 /* Get the immediate constant. */
4112 skip_whitespace (str);
4113 if (is_immediate_prefix (* str))
4114 str++;
4115 else
4116 {
4117 inst.error = _("immediate expression expected");
4118 return;
4119 }
4120
4121 if (my_get_expression (&expr, &str))
4122 {
4123 inst.error = _("bad expression");
4124 return;
4125 }
4126
4127 if (expr.X_op != O_constant)
4128 {
4129 inst.error = _("constant expression expected");
4130 return;
4131 }
4132
4133 switch (expr.X_add_number)
4134 {
4135 case 0:
4136 /* Rotation field has already been zeroed. */
4137 break;
4138 case 8:
4139 inst.instruction |= rotation_eight_mask;
4140 break;
4141
4142 case 16:
4143 inst.instruction |= rotation_sixteen_mask;
4144 break;
4145
4146 case 24:
4147 inst.instruction |= rotation_twenty_four_mask;
4148 break;
4149
4150 default:
4151 inst.error = _("rotation can be 8, 16, 24 or 0 when field is ommited");
4152 break;
4153 }
4154
4155 end_of_line (str);
4156 }
4157
4158 /* ARM V6 SXTAH extracts a 16-bit value from a register, sign
4159 extends it to 32-bits, and adds the result to a value in another
4160 register. You can specify a rotation by 0, 8, 16, or 24 bits
4161 before extracting the 16-bit value.
4162 SXTAH{<cond>} <Rd>, <Rn>, <Rm>{, <rotation>}
4163 Condition defaults to COND_ALWAYS.
4164 Error if any register uses R15. */
4165
4166 static void
4167 do_sxtah (char * str)
4168 {
4169 int rd, rn, rm;
4170 expressionS expr;
4171 int rotation_clear_mask = 0xfffff3ff;
4172 int rotation_eight_mask = 0x00000400;
4173 int rotation_sixteen_mask = 0x00000800;
4174 int rotation_twenty_four_mask = 0x00000c00;
4175
4176 skip_whitespace (str);
4177 if ((rd = reg_required_here (&str, 12)) == FAIL
4178 || skip_past_comma (&str) == FAIL
4179 || (rn = reg_required_here (&str, 16)) == FAIL
4180 || skip_past_comma (&str) == FAIL
4181 || (rm = reg_required_here (&str, 0)) == FAIL)
4182 {
4183 inst.error = BAD_ARGS;
4184 return;
4185 }
4186
4187 else if (rd == REG_PC || rn == REG_PC || rm == REG_PC)
4188 {
4189 inst.error = BAD_PC;
4190 return;
4191 }
4192
4193 /* Zero out the rotation field. */
4194 inst.instruction &= rotation_clear_mask;
4195
4196 /* Check for lack of optional rotation field. */
4197 if (skip_past_comma (&str) == FAIL)
4198 {
4199 end_of_line (str);
4200 return;
4201 }
4202
4203 /* Move past 'ROR'. */
4204 skip_whitespace (str);
4205 if (strncasecmp (str, "ROR", 3) == 0)
4206 str += 3;
4207 else
4208 {
4209 inst.error = _("missing rotation field after comma");
4210 return;
4211 }
4212
4213 /* Get the immediate constant. */
4214 skip_whitespace (str);
4215 if (is_immediate_prefix (* str))
4216 str++;
4217 else
4218 {
4219 inst.error = _("immediate expression expected");
4220 return;
4221 }
4222
4223 if (my_get_expression (&expr, &str))
4224 {
4225 inst.error = _("bad expression");
4226 return;
4227 }
4228
4229 if (expr.X_op != O_constant)
4230 {
4231 inst.error = _("constant expression expected");
4232 return;
4233 }
4234
4235 switch (expr.X_add_number)
4236 {
4237 case 0:
4238 /* Rotation field has already been zeroed. */
4239 break;
4240
4241 case 8:
4242 inst.instruction |= rotation_eight_mask;
4243 break;
4244
4245 case 16:
4246 inst.instruction |= rotation_sixteen_mask;
4247 break;
4248
4249 case 24:
4250 inst.instruction |= rotation_twenty_four_mask;
4251 break;
4252
4253 default:
4254 inst.error = _("rotation can be 8, 16, 24 or 0 when field is ommited");
4255 break;
4256 }
4257
4258 end_of_line (str);
4259 }
4260
4261
4262 /* ARM V6 RFE (Return from Exception) loads the PC and CPSR from the
4263 word at the specified address and the following word
4264 respectively.
4265 Unconditionally executed.
4266 Error if Rn is R15. */
4267
4268 static void
4269 do_rfe (char * str)
4270 {
4271 int rn;
4272
4273 skip_whitespace (str);
4274
4275 if ((rn = reg_required_here (&str, 16)) == FAIL)
4276 return;
4277
4278 if (rn == REG_PC)
4279 {
4280 inst.error = BAD_PC;
4281 return;
4282 }
4283
4284 skip_whitespace (str);
4285
4286 if (*str == '!')
4287 {
4288 inst.instruction |= WRITE_BACK;
4289 str++;
4290 }
4291 end_of_line (str);
4292 }
4293
4294 /* ARM V6 REV (Byte Reverse Word) reverses the byte order in a 32-bit
4295 register (argument parse).
4296 REV{<cond>} Rd, Rm.
4297 Condition defaults to COND_ALWAYS.
4298 Error if Rd or Rm are R15. */
4299
4300 static void
4301 do_rev (char * str)
4302 {
4303 int rd, rm;
4304
4305 skip_whitespace (str);
4306
4307 if ((rd = reg_required_here (&str, 12)) == FAIL
4308 || skip_past_comma (&str) == FAIL
4309 || (rm = reg_required_here (&str, 0)) == FAIL)
4310 inst.error = BAD_ARGS;
4311
4312 else if (rd == REG_PC || rm == REG_PC)
4313 inst.error = BAD_PC;
4314
4315 else
4316 end_of_line (str);
4317 }
4318
4319 /* ARM V6 Perform Two Sixteen Bit Integer Additions. (argument parse).
4320 QADD16{<cond>} <Rd>, <Rn>, <Rm>
4321 Condition defaults to COND_ALWAYS.
4322 Error if Rd, Rn or Rm are R15. */
4323
4324 static void
4325 do_qadd16 (char * str)
4326 {
4327 int rd, rm, rn;
4328
4329 skip_whitespace (str);
4330
4331 if ((rd = reg_required_here (&str, 12)) == FAIL
4332 || skip_past_comma (&str) == FAIL
4333 || (rn = reg_required_here (&str, 16)) == FAIL
4334 || skip_past_comma (&str) == FAIL
4335 || (rm = reg_required_here (&str, 0)) == FAIL)
4336 inst.error = BAD_ARGS;
4337
4338 else if (rd == REG_PC || rm == REG_PC || rn == REG_PC)
4339 inst.error = BAD_PC;
4340
4341 else
4342 end_of_line (str);
4343 }
4344
4345 static void
4346 do_pkh_core (char * str, int shift)
4347 {
4348 int rd, rn, rm;
4349
4350 skip_whitespace (str);
4351 if (((rd = reg_required_here (&str, 12)) == FAIL)
4352 || (skip_past_comma (&str) == FAIL)
4353 || ((rn = reg_required_here (&str, 16)) == FAIL)
4354 || (skip_past_comma (&str) == FAIL)
4355 || ((rm = reg_required_here (&str, 0)) == FAIL))
4356 {
4357 inst.error = BAD_ARGS;
4358 return;
4359 }
4360
4361 else if (rd == REG_PC || rn == REG_PC || rm == REG_PC)
4362 {
4363 inst.error = BAD_PC;
4364 return;
4365 }
4366
4367 /* Check for optional shift immediate constant. */
4368 if (skip_past_comma (&str) == FAIL)
4369 {
4370 if (shift == SHIFT_ASR_IMMEDIATE)
4371 {
4372 /* If the shift specifier is ommited, turn the instruction
4373 into pkhbt rd, rm, rn. First, switch the instruction
4374 code, and clear the rn and rm fields. */
4375 inst.instruction &= 0xfff0f010;
4376 /* Now, re-encode the registers. */
4377 inst.instruction |= (rm << 16) | rn;
4378 }
4379 return;
4380 }
4381
4382 decode_shift (&str, shift);
4383 }
4384
4385 /* ARM V6 Pack Halfword Bottom Top instruction (argument parse).
4386 PKHBT {<cond>} <Rd>, <Rn>, <Rm> {, LSL #<shift_imm>}
4387 Condition defaults to COND_ALWAYS.
4388 Error if Rd, Rn or Rm are R15. */
4389
4390 static void
4391 do_pkhbt (char * str)
4392 {
4393 do_pkh_core (str, SHIFT_LSL_IMMEDIATE);
4394 }
4395
4396 /* ARM V6 PKHTB (Argument Parse). */
4397
4398 static void
4399 do_pkhtb (char * str)
4400 {
4401 do_pkh_core (str, SHIFT_ASR_IMMEDIATE);
4402 }
4403
4404 /* ARM V6 Load Register Exclusive instruction (argument parse).
4405 LDREX{,B,D,H}{<cond>} <Rd, [<Rn>]
4406 Condition defaults to COND_ALWAYS.
4407 Error if Rd or Rn are R15.
4408 See ARMARMv6 A4.1.27: LDREX. */
4409
4410 static void
4411 do_ldrex (char * str)
4412 {
4413 int rd, rn;
4414
4415 skip_whitespace (str);
4416
4417 /* Parse Rd. */
4418 if (((rd = reg_required_here (&str, 12)) == FAIL)
4419 || (skip_past_comma (&str) == FAIL))
4420 {
4421 inst.error = BAD_ARGS;
4422 return;
4423 }
4424 else if (rd == REG_PC)
4425 {
4426 inst.error = BAD_PC;
4427 return;
4428 }
4429 skip_whitespace (str);
4430
4431 /* Skip past '['. */
4432 if ((strlen (str) >= 1)
4433 &&strncmp (str, "[", 1) == 0)
4434 str += 1;
4435 skip_whitespace (str);
4436
4437 /* Parse Rn. */
4438 if ((rn = reg_required_here (&str, 16)) == FAIL)
4439 {
4440 inst.error = BAD_ARGS;
4441 return;
4442 }
4443 else if (rn == REG_PC)
4444 {
4445 inst.error = BAD_PC;
4446 return;
4447 }
4448 skip_whitespace (str);
4449
4450 /* Skip past ']'. */
4451 if ((strlen (str) >= 1)
4452 && strncmp (str, "]", 1) == 0)
4453 str += 1;
4454
4455 end_of_line (str);
4456 }
4457
4458 /* ARM V6 change processor state instruction (argument parse)
4459 CPS, CPSIE, CSPID . */
4460
4461 static void
4462 do_cps (char * str)
4463 {
4464 do_cps_mode (&str);
4465 end_of_line (str);
4466 }
4467
4468 static void
4469 do_cps_flags (char ** str, int thumb_p)
4470 {
4471 struct cps_flag
4472 {
4473 char character;
4474 unsigned long arm_value;
4475 unsigned long thumb_value;
4476 };
4477 static struct cps_flag flag_table[] =
4478 {
4479 {'a', 0x100, 0x4 },
4480 {'i', 0x080, 0x2 },
4481 {'f', 0x040, 0x1 }
4482 };
4483
4484 int saw_a_flag = 0;
4485
4486 skip_whitespace (*str);
4487
4488 /* Get the a, f and i flags. */
4489 while (**str && **str != ',')
4490 {
4491 struct cps_flag *p;
4492 struct cps_flag *q = flag_table + sizeof (flag_table)/sizeof (*p);
4493
4494 for (p = flag_table; p < q; ++p)
4495 if (strncasecmp (*str, &p->character, 1) == 0)
4496 {
4497 inst.instruction |= (thumb_p ? p->thumb_value : p->arm_value);
4498 saw_a_flag = 1;
4499 break;
4500 }
4501 if (p == q)
4502 {
4503 inst.error = _("unrecognized flag");
4504 return;
4505 }
4506 (*str)++;
4507 }
4508
4509 if (!saw_a_flag)
4510 inst.error = _("no 'a', 'i', or 'f' flags for 'cps'");
4511 }
4512
4513 static void
4514 do_cpsi (char * str)
4515 {
4516 do_cps_flags (&str, /*thumb_p=*/0);
4517
4518 if (skip_past_comma (&str) == SUCCESS)
4519 {
4520 skip_whitespace (str);
4521 do_cps_mode (&str);
4522 }
4523 end_of_line (str);
4524 }
4525
4526 /* THUMB V5 breakpoint instruction (argument parse)
4527 BKPT <immed_8>. */
4528
4529 static void
4530 do_t_bkpt (char * str)
4531 {
4532 expressionS expr;
4533 unsigned long number;
4534
4535 skip_whitespace (str);
4536
4537 /* Allow optional leading '#'. */
4538 if (is_immediate_prefix (*str))
4539 str ++;
4540
4541 memset (& expr, '\0', sizeof (expr));
4542 if (my_get_expression (& expr, & str)
4543 || (expr.X_op != O_constant
4544 /* As a convenience we allow 'bkpt' without an operand. */
4545 && expr.X_op != O_absent))
4546 {
4547 inst.error = _("bad expression");
4548 return;
4549 }
4550
4551 number = expr.X_add_number;
4552
4553 /* Check it fits an 8 bit unsigned. */
4554 if (number != (number & 0xff))
4555 {
4556 inst.error = _("immediate value out of range");
4557 return;
4558 }
4559
4560 inst.instruction |= number;
4561
4562 end_of_line (str);
4563 }
4564
4565 static bfd_reloc_code_real_type
4566 arm_parse_reloc (void)
4567 {
4568 char id [16];
4569 char * ip;
4570 unsigned int i;
4571 static struct
4572 {
4573 char * str;
4574 int len;
4575 bfd_reloc_code_real_type reloc;
4576 }
4577 reloc_map[] =
4578 {
4579 #define MAP(str,reloc) { str, sizeof (str) - 1, reloc }
4580 MAP ("(got)", BFD_RELOC_ARM_GOT32),
4581 MAP ("(gotoff)", BFD_RELOC_ARM_GOTOFF),
4582 /* ScottB: Jan 30, 1998 - Added support for parsing "var(PLT)"
4583 branch instructions generated by GCC for PLT relocs. */
4584 MAP ("(plt)", BFD_RELOC_ARM_PLT32),
4585 MAP ("(target1)", BFD_RELOC_ARM_TARGET1),
4586 MAP ("(sbrel)", BFD_RELOC_ARM_SBREL32),
4587 MAP ("(target2)", BFD_RELOC_ARM_TARGET2),
4588 { NULL, 0, BFD_RELOC_UNUSED }
4589 #undef MAP
4590 };
4591
4592 for (i = 0, ip = input_line_pointer;
4593 i < sizeof (id) && (ISALNUM (*ip) || ISPUNCT (*ip));
4594 i++, ip++)
4595 id[i] = TOLOWER (*ip);
4596
4597 for (i = 0; reloc_map[i].str; i++)
4598 if (strncmp (id, reloc_map[i].str, reloc_map[i].len) == 0)
4599 break;
4600
4601 input_line_pointer += reloc_map[i].len;
4602
4603 return reloc_map[i].reloc;
4604 }
4605
4606 /* ARM V5 branch-link-exchange (argument parse) for BLX(1) only.
4607 Expects inst.instruction is set for BLX(1).
4608 Note: this is cloned from do_branch, and the reloc changed to be a
4609 new one that can cope with setting one extra bit (the H bit). */
4610
4611 static void
4612 do_branch25 (char * str)
4613 {
4614 if (my_get_expression (& inst.reloc.exp, & str))
4615 return;
4616
4617 #ifdef OBJ_ELF
4618 {
4619 char * save_in;
4620
4621 /* ScottB: February 5, 1998 */
4622 /* Check to see of PLT32 reloc required for the instruction. */
4623
4624 /* arm_parse_reloc() works on input_line_pointer.
4625 We actually want to parse the operands to the branch instruction
4626 passed in 'str'. Save the input pointer and restore it later. */
4627 save_in = input_line_pointer;
4628 input_line_pointer = str;
4629
4630 if (inst.reloc.exp.X_op == O_symbol
4631 && *str == '('
4632 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
4633 {
4634 inst.reloc.type = BFD_RELOC_ARM_PLT32;
4635 inst.reloc.pc_rel = 0;
4636 /* Modify str to point to after parsed operands, otherwise
4637 end_of_line() will complain about the (PLT) left in str. */
4638 str = input_line_pointer;
4639 }
4640 else
4641 {
4642 inst.reloc.type = BFD_RELOC_ARM_PCREL_BLX;
4643 inst.reloc.pc_rel = 1;
4644 }
4645
4646 input_line_pointer = save_in;
4647 }
4648 #else
4649 inst.reloc.type = BFD_RELOC_ARM_PCREL_BLX;
4650 inst.reloc.pc_rel = 1;
4651 #endif /* OBJ_ELF */
4652
4653 end_of_line (str);
4654 }
4655
4656 /* ARM V5 branch-link-exchange instruction (argument parse)
4657 BLX <target_addr> ie BLX(1)
4658 BLX{<condition>} <Rm> ie BLX(2)
4659 Unfortunately, there are two different opcodes for this mnemonic.
4660 So, the insns[].value is not used, and the code here zaps values
4661 into inst.instruction.
4662 Also, the <target_addr> can be 25 bits, hence has its own reloc. */
4663
4664 static void
4665 do_blx (char * str)
4666 {
4667 char * mystr = str;
4668 int rm;
4669
4670 skip_whitespace (mystr);
4671 rm = reg_required_here (& mystr, 0);
4672
4673 /* The above may set inst.error. Ignore his opinion. */
4674 inst.error = 0;
4675
4676 if (rm != FAIL)
4677 {
4678 /* Arg is a register.
4679 Use the condition code our caller put in inst.instruction.
4680 Pass ourselves off as a BX with a funny opcode. */
4681 inst.instruction |= 0x012fff30;
4682 do_bx (str);
4683 }
4684 else
4685 {
4686 /* This must be is BLX <target address>, no condition allowed. */
4687 if (inst.instruction != COND_ALWAYS)
4688 {
4689 inst.error = BAD_COND;
4690 return;
4691 }
4692
4693 inst.instruction = 0xfafffffe;
4694
4695 /* Process like a B/BL, but with a different reloc.
4696 Note that B/BL expecte fffffe, not 0, offset in the opcode table. */
4697 do_branch25 (str);
4698 }
4699 }
4700
4701 /* ARM V5 Thumb BLX (argument parse)
4702 BLX <target_addr> which is BLX(1)
4703 BLX <Rm> which is BLX(2)
4704 Unfortunately, there are two different opcodes for this mnemonic.
4705 So, the tinsns[].value is not used, and the code here zaps values
4706 into inst.instruction. */
4707
4708 static void
4709 do_t_blx (char * str)
4710 {
4711 char * mystr = str;
4712 int rm;
4713
4714 skip_whitespace (mystr);
4715 inst.instruction = 0x4780;
4716
4717 /* Note that this call is to the ARM register recognizer. BLX(2)
4718 uses the ARM register space, not the Thumb one, so a call to
4719 thumb_reg() would be wrong. */
4720 rm = reg_required_here (& mystr, 3);
4721 inst.error = 0;
4722
4723 if (rm != FAIL)
4724 {
4725 /* It's BLX(2). The .instruction was zapped with rm & is final. */
4726 inst.size = 2;
4727 }
4728 else
4729 {
4730 /* No ARM register. This must be BLX(1). Change the .instruction. */
4731 inst.instruction = 0xf7ffeffe;
4732 inst.size = 4;
4733
4734 if (my_get_expression (& inst.reloc.exp, & mystr))
4735 return;
4736
4737 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BLX;
4738 inst.reloc.pc_rel = 1;
4739 }
4740
4741 end_of_line (mystr);
4742 }
4743
4744 /* ARM V5 breakpoint instruction (argument parse)
4745 BKPT <16 bit unsigned immediate>
4746 Instruction is not conditional.
4747 The bit pattern given in insns[] has the COND_ALWAYS condition,
4748 and it is an error if the caller tried to override that. */
4749
4750 static void
4751 do_bkpt (char * str)
4752 {
4753 expressionS expr;
4754 unsigned long number;
4755
4756 skip_whitespace (str);
4757
4758 /* Allow optional leading '#'. */
4759 if (is_immediate_prefix (* str))
4760 str++;
4761
4762 memset (& expr, '\0', sizeof (expr));
4763
4764 if (my_get_expression (& expr, & str)
4765 || (expr.X_op != O_constant
4766 /* As a convenience we allow 'bkpt' without an operand. */
4767 && expr.X_op != O_absent))
4768 {
4769 inst.error = _("bad expression");
4770 return;
4771 }
4772
4773 number = expr.X_add_number;
4774
4775 /* Check it fits a 16 bit unsigned. */
4776 if (number != (number & 0xffff))
4777 {
4778 inst.error = _("immediate value out of range");
4779 return;
4780 }
4781
4782 /* Top 12 of 16 bits to bits 19:8. */
4783 inst.instruction |= (number & 0xfff0) << 4;
4784
4785 /* Bottom 4 of 16 bits to bits 3:0. */
4786 inst.instruction |= number & 0xf;
4787
4788 end_of_line (str);
4789 }
4790
4791 /* THUMB CPS instruction (argument parse). */
4792
4793 static void
4794 do_t_cps (char * str)
4795 {
4796 do_cps_flags (&str, /*thumb_p=*/1);
4797 end_of_line (str);
4798 }
4799
4800 /* Parse and validate that a register is of the right form, this saves
4801 repeated checking of this information in many similar cases.
4802 Unlike the 32-bit case we do not insert the register into the opcode
4803 here, since the position is often unknown until the full instruction
4804 has been parsed. */
4805
4806 static int
4807 thumb_reg (char ** strp, int hi_lo)
4808 {
4809 int reg;
4810
4811 if ((reg = reg_required_here (strp, -1)) == FAIL)
4812 return FAIL;
4813
4814 switch (hi_lo)
4815 {
4816 case THUMB_REG_LO:
4817 if (reg > 7)
4818 {
4819 inst.error = _("lo register required");
4820 return FAIL;
4821 }
4822 break;
4823
4824 case THUMB_REG_HI:
4825 if (reg < 8)
4826 {
4827 inst.error = _("hi register required");
4828 return FAIL;
4829 }
4830 break;
4831
4832 default:
4833 break;
4834 }
4835
4836 return reg;
4837 }
4838
4839 static void
4840 thumb_mov_compare (char * str, int move)
4841 {
4842 int Rd, Rs = FAIL;
4843
4844 skip_whitespace (str);
4845
4846 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
4847 || skip_past_comma (&str) == FAIL)
4848 {
4849 if (! inst.error)
4850 inst.error = BAD_ARGS;
4851 return;
4852 }
4853
4854 if (move != THUMB_CPY && is_immediate_prefix (*str))
4855 {
4856 str++;
4857 if (my_get_expression (&inst.reloc.exp, &str))
4858 return;
4859 }
4860 else if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
4861 return;
4862
4863 if (Rs != FAIL)
4864 {
4865 if (move != THUMB_CPY && Rs < 8 && Rd < 8)
4866 {
4867 if (move == THUMB_MOVE)
4868 /* A move of two lowregs is encoded as ADD Rd, Rs, #0
4869 since a MOV instruction produces unpredictable results. */
4870 inst.instruction = T_OPCODE_ADD_I3;
4871 else
4872 inst.instruction = T_OPCODE_CMP_LR;
4873 inst.instruction |= Rd | (Rs << 3);
4874 }
4875 else
4876 {
4877 if (move == THUMB_MOVE)
4878 inst.instruction = T_OPCODE_MOV_HR;
4879 else if (move != THUMB_CPY)
4880 inst.instruction = T_OPCODE_CMP_HR;
4881
4882 if (Rd > 7)
4883 inst.instruction |= THUMB_H1;
4884
4885 if (Rs > 7)
4886 inst.instruction |= THUMB_H2;
4887
4888 inst.instruction |= (Rd & 7) | ((Rs & 7) << 3);
4889 }
4890 }
4891 else
4892 {
4893 if (Rd > 7)
4894 {
4895 inst.error = _("only lo regs allowed with immediate");
4896 return;
4897 }
4898
4899 if (move == THUMB_MOVE)
4900 inst.instruction = T_OPCODE_MOV_I8;
4901 else
4902 inst.instruction = T_OPCODE_CMP_I8;
4903
4904 inst.instruction |= Rd << 8;
4905
4906 if (inst.reloc.exp.X_op != O_constant)
4907 inst.reloc.type = BFD_RELOC_ARM_THUMB_IMM;
4908 else
4909 {
4910 unsigned value = inst.reloc.exp.X_add_number;
4911
4912 if (value > 255)
4913 {
4914 inst.error = _("invalid immediate");
4915 return;
4916 }
4917
4918 inst.instruction |= value;
4919 }
4920 }
4921
4922 end_of_line (str);
4923 }
4924
4925 /* THUMB CPY instruction (argument parse). */
4926
4927 static void
4928 do_t_cpy (char * str)
4929 {
4930 thumb_mov_compare (str, THUMB_CPY);
4931 }
4932
4933 /* THUMB SETEND instruction (argument parse). */
4934
4935 static void
4936 do_t_setend (char * str)
4937 {
4938 if (do_endian_specifier (str))
4939 inst.instruction |= 0x8;
4940 }
4941
4942 /* Parse INSN_TYPE insn STR having a possible IMMEDIATE_SIZE immediate. */
4943
4944 static unsigned long
4945 check_iwmmxt_insn (char * str,
4946 enum iwmmxt_insn_type insn_type,
4947 int immediate_size)
4948 {
4949 int reg = 0;
4950 const char * inst_error;
4951 expressionS expr;
4952 unsigned long number;
4953
4954 inst_error = inst.error;
4955 if (!inst.error)
4956 inst.error = BAD_ARGS;
4957 skip_whitespace (str);
4958
4959 switch (insn_type)
4960 {
4961 case check_rd:
4962 if ((reg = reg_required_here (&str, 12)) == FAIL)
4963 return FAIL;
4964 break;
4965
4966 case check_wr:
4967 if ((wreg_required_here (&str, 0, IWMMXT_REG_WR)) == FAIL)
4968 return FAIL;
4969 break;
4970
4971 case check_wrwr:
4972 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
4973 || skip_past_comma (&str) == FAIL
4974 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL))
4975 return FAIL;
4976 break;
4977
4978 case check_wrwrwr:
4979 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
4980 || skip_past_comma (&str) == FAIL
4981 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
4982 || skip_past_comma (&str) == FAIL
4983 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL))
4984 return FAIL;
4985 break;
4986
4987 case check_wrwrwcg:
4988 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
4989 || skip_past_comma (&str) == FAIL
4990 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
4991 || skip_past_comma (&str) == FAIL
4992 || wreg_required_here (&str, 0, IWMMXT_REG_WCG) == FAIL))
4993 return FAIL;
4994 break;
4995
4996 case check_tbcst:
4997 if ((wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
4998 || skip_past_comma (&str) == FAIL
4999 || reg_required_here (&str, 12) == FAIL))
5000 return FAIL;
5001 break;
5002
5003 case check_tmovmsk:
5004 if ((reg_required_here (&str, 12) == FAIL
5005 || skip_past_comma (&str) == FAIL
5006 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL))
5007 return FAIL;
5008 break;
5009
5010 case check_tmia:
5011 if ((wreg_required_here (&str, 5, IWMMXT_REG_WR) == FAIL
5012 || skip_past_comma (&str) == FAIL
5013 || reg_required_here (&str, 0) == FAIL
5014 || skip_past_comma (&str) == FAIL
5015 || reg_required_here (&str, 12) == FAIL))
5016 return FAIL;
5017 break;
5018
5019 case check_tmcrr:
5020 if ((wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL
5021 || skip_past_comma (&str) == FAIL
5022 || reg_required_here (&str, 12) == FAIL
5023 || skip_past_comma (&str) == FAIL
5024 || reg_required_here (&str, 16) == FAIL))
5025 return FAIL;
5026 break;
5027
5028 case check_tmrrc:
5029 if ((reg_required_here (&str, 12) == FAIL
5030 || skip_past_comma (&str) == FAIL
5031 || reg_required_here (&str, 16) == FAIL
5032 || skip_past_comma (&str) == FAIL
5033 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL))
5034 return FAIL;
5035 break;
5036
5037 case check_tmcr:
5038 if ((wreg_required_here (&str, 16, IWMMXT_REG_WC) == FAIL
5039 || skip_past_comma (&str) == FAIL
5040 || reg_required_here (&str, 12) == FAIL))
5041 return FAIL;
5042 break;
5043
5044 case check_tmrc:
5045 if ((reg_required_here (&str, 12) == FAIL
5046 || skip_past_comma (&str) == FAIL
5047 || wreg_required_here (&str, 16, IWMMXT_REG_WC) == FAIL))
5048 return FAIL;
5049 break;
5050
5051 case check_tinsr:
5052 if ((wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5053 || skip_past_comma (&str) == FAIL
5054 || reg_required_here (&str, 12) == FAIL
5055 || skip_past_comma (&str) == FAIL))
5056 return FAIL;
5057 break;
5058
5059 case check_textrc:
5060 if ((reg_required_here (&str, 12) == FAIL
5061 || skip_past_comma (&str) == FAIL))
5062 return FAIL;
5063 break;
5064
5065 case check_waligni:
5066 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
5067 || skip_past_comma (&str) == FAIL
5068 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5069 || skip_past_comma (&str) == FAIL
5070 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL
5071 || skip_past_comma (&str) == FAIL))
5072 return FAIL;
5073 break;
5074
5075 case check_textrm:
5076 if ((reg_required_here (&str, 12) == FAIL
5077 || skip_past_comma (&str) == FAIL
5078 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5079 || skip_past_comma (&str) == FAIL))
5080 return FAIL;
5081 break;
5082
5083 case check_wshufh:
5084 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
5085 || skip_past_comma (&str) == FAIL
5086 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5087 || skip_past_comma (&str) == FAIL))
5088 return FAIL;
5089 break;
5090 }
5091
5092 if (immediate_size == 0)
5093 {
5094 end_of_line (str);
5095 inst.error = inst_error;
5096 return reg;
5097 }
5098 else
5099 {
5100 skip_whitespace (str);
5101
5102 /* Allow optional leading '#'. */
5103 if (is_immediate_prefix (* str))
5104 str++;
5105
5106 memset (& expr, '\0', sizeof (expr));
5107
5108 if (my_get_expression (& expr, & str) || (expr.X_op != O_constant))
5109 {
5110 inst.error = _("bad or missing expression");
5111 return FAIL;
5112 }
5113
5114 number = expr.X_add_number;
5115
5116 if (number != (number & immediate_size))
5117 {
5118 inst.error = _("immediate value out of range");
5119 return FAIL;
5120 }
5121 end_of_line (str);
5122 inst.error = inst_error;
5123 return number;
5124 }
5125 }
5126
5127 static void
5128 do_iwmmxt_byte_addr (char * str)
5129 {
5130 int op = (inst.instruction & 0x300) >> 8;
5131 int reg;
5132
5133 inst.instruction &= ~0x300;
5134 inst.instruction |= (op & 1) << 22 | (op & 2) << 7;
5135
5136 skip_whitespace (str);
5137
5138 if ((reg = wreg_required_here (&str, 12, IWMMXT_REG_WR_OR_WC)) == FAIL
5139 || skip_past_comma (& str) == FAIL
5140 || cp_byte_address_required_here (&str) == FAIL)
5141 {
5142 if (! inst.error)
5143 inst.error = BAD_ARGS;
5144 }
5145 else
5146 end_of_line (str);
5147
5148 if (wc_register (reg))
5149 {
5150 as_bad (_("non-word size not supported with control register"));
5151 inst.instruction |= 0xf0000100;
5152 inst.instruction &= ~0x00400000;
5153 }
5154 }
5155
5156 static void
5157 do_iwmmxt_tandc (char * str)
5158 {
5159 int reg;
5160
5161 reg = check_iwmmxt_insn (str, check_rd, 0);
5162
5163 if (reg != REG_PC && !inst.error)
5164 inst.error = _("only r15 allowed here");
5165 }
5166
5167 static void
5168 do_iwmmxt_tbcst (char * str)
5169 {
5170 check_iwmmxt_insn (str, check_tbcst, 0);
5171 }
5172
5173 static void
5174 do_iwmmxt_textrc (char * str)
5175 {
5176 unsigned long number;
5177
5178 if ((number = check_iwmmxt_insn (str, check_textrc, 7)) == (unsigned long) FAIL)
5179 return;
5180
5181 inst.instruction |= number & 0x7;
5182 }
5183
5184 static void
5185 do_iwmmxt_textrm (char * str)
5186 {
5187 unsigned long number;
5188
5189 if ((number = check_iwmmxt_insn (str, check_textrm, 7)) == (unsigned long) FAIL)
5190 return;
5191
5192 inst.instruction |= number & 0x7;
5193 }
5194
5195 static void
5196 do_iwmmxt_tinsr (char * str)
5197 {
5198 unsigned long number;
5199
5200 if ((number = check_iwmmxt_insn (str, check_tinsr, 7)) == (unsigned long) FAIL)
5201 return;
5202
5203 inst.instruction |= number & 0x7;
5204 }
5205
5206 static void
5207 do_iwmmxt_tmcr (char * str)
5208 {
5209 check_iwmmxt_insn (str, check_tmcr, 0);
5210 }
5211
5212 static void
5213 do_iwmmxt_tmcrr (char * str)
5214 {
5215 check_iwmmxt_insn (str, check_tmcrr, 0);
5216 }
5217
5218 static void
5219 do_iwmmxt_tmia (char * str)
5220 {
5221 check_iwmmxt_insn (str, check_tmia, 0);
5222 }
5223
5224 static void
5225 do_iwmmxt_tmovmsk (char * str)
5226 {
5227 check_iwmmxt_insn (str, check_tmovmsk, 0);
5228 }
5229
5230 static void
5231 do_iwmmxt_tmrc (char * str)
5232 {
5233 check_iwmmxt_insn (str, check_tmrc, 0);
5234 }
5235
5236 static void
5237 do_iwmmxt_tmrrc (char * str)
5238 {
5239 check_iwmmxt_insn (str, check_tmrrc, 0);
5240 }
5241
5242 static void
5243 do_iwmmxt_torc (char * str)
5244 {
5245 check_iwmmxt_insn (str, check_rd, 0);
5246 }
5247
5248 static void
5249 do_iwmmxt_waligni (char * str)
5250 {
5251 unsigned long number;
5252
5253 if ((number = check_iwmmxt_insn (str, check_waligni, 7)) == (unsigned long) FAIL)
5254 return;
5255
5256 inst.instruction |= ((number & 0x7) << 20);
5257 }
5258
5259 static void
5260 do_iwmmxt_wmov (char * str)
5261 {
5262 if (check_iwmmxt_insn (str, check_wrwr, 0) == (unsigned long) FAIL)
5263 return;
5264
5265 inst.instruction |= ((inst.instruction >> 16) & 0xf);
5266 }
5267
5268 static void
5269 do_iwmmxt_word_addr (char * str)
5270 {
5271 int op = (inst.instruction & 0x300) >> 8;
5272 int reg;
5273
5274 inst.instruction &= ~0x300;
5275 inst.instruction |= (op & 1) << 22 | (op & 2) << 7;
5276
5277 skip_whitespace (str);
5278
5279 if ((reg = wreg_required_here (&str, 12, IWMMXT_REG_WR_OR_WC)) == FAIL
5280 || skip_past_comma (& str) == FAIL
5281 || cp_address_required_here (& str, CP_WB_OK) == FAIL)
5282 {
5283 if (! inst.error)
5284 inst.error = BAD_ARGS;
5285 }
5286 else
5287 end_of_line (str);
5288
5289 if (wc_register (reg))
5290 {
5291 if ((inst.instruction & COND_MASK) != COND_ALWAYS)
5292 as_bad (_("conditional execution not supported with control register"));
5293 if (op != 2)
5294 as_bad (_("non-word size not supported with control register"));
5295 inst.instruction |= 0xf0000100;
5296 inst.instruction &= ~0x00400000;
5297 }
5298 }
5299
5300 static void
5301 do_iwmmxt_wrwr (char * str)
5302 {
5303 check_iwmmxt_insn (str, check_wrwr, 0);
5304 }
5305
5306 static void
5307 do_iwmmxt_wrwrwcg (char * str)
5308 {
5309 check_iwmmxt_insn (str, check_wrwrwcg, 0);
5310 }
5311
5312 static void
5313 do_iwmmxt_wrwrwr (char * str)
5314 {
5315 check_iwmmxt_insn (str, check_wrwrwr, 0);
5316 }
5317
5318 static void
5319 do_iwmmxt_wshufh (char * str)
5320 {
5321 unsigned long number;
5322
5323 if ((number = check_iwmmxt_insn (str, check_wshufh, 0xff)) == (unsigned long) FAIL)
5324 return;
5325
5326 inst.instruction |= ((number & 0xf0) << 16) | (number & 0xf);
5327 }
5328
5329 static void
5330 do_iwmmxt_wzero (char * str)
5331 {
5332 if (check_iwmmxt_insn (str, check_wr, 0) == (unsigned long) FAIL)
5333 return;
5334
5335 inst.instruction |= ((inst.instruction & 0xf) << 12) | ((inst.instruction & 0xf) << 16);
5336 }
5337
5338 /* Xscale multiply-accumulate (argument parse)
5339 MIAcc acc0,Rm,Rs
5340 MIAPHcc acc0,Rm,Rs
5341 MIAxycc acc0,Rm,Rs. */
5342
5343 static void
5344 do_xsc_mia (char * str)
5345 {
5346 int rs;
5347 int rm;
5348
5349 if (accum0_required_here (& str) == FAIL)
5350 inst.error = ERR_NO_ACCUM;
5351
5352 else if (skip_past_comma (& str) == FAIL
5353 || (rm = reg_required_here (& str, 0)) == FAIL)
5354 inst.error = BAD_ARGS;
5355
5356 else if (skip_past_comma (& str) == FAIL
5357 || (rs = reg_required_here (& str, 12)) == FAIL)
5358 inst.error = BAD_ARGS;
5359
5360 /* inst.instruction has now been zapped with both rm and rs. */
5361 else if (rm == REG_PC || rs == REG_PC)
5362 inst.error = BAD_PC; /* Undefined result if rm or rs is R15. */
5363
5364 else
5365 end_of_line (str);
5366 }
5367
5368 /* Xscale move-accumulator-register (argument parse)
5369
5370 MARcc acc0,RdLo,RdHi. */
5371
5372 static void
5373 do_xsc_mar (char * str)
5374 {
5375 int rdlo, rdhi;
5376
5377 if (accum0_required_here (& str) == FAIL)
5378 inst.error = ERR_NO_ACCUM;
5379
5380 else if (skip_past_comma (& str) == FAIL
5381 || (rdlo = reg_required_here (& str, 12)) == FAIL)
5382 inst.error = BAD_ARGS;
5383
5384 else if (skip_past_comma (& str) == FAIL
5385 || (rdhi = reg_required_here (& str, 16)) == FAIL)
5386 inst.error = BAD_ARGS;
5387
5388 /* inst.instruction has now been zapped with both rdlo and rdhi. */
5389 else if (rdlo == REG_PC || rdhi == REG_PC)
5390 inst.error = BAD_PC; /* Undefined result if rdlo or rdhi is R15. */
5391
5392 else
5393 end_of_line (str);
5394 }
5395
5396 /* Xscale move-register-accumulator (argument parse)
5397
5398 MRAcc RdLo,RdHi,acc0. */
5399
5400 static void
5401 do_xsc_mra (char * str)
5402 {
5403 int rdlo;
5404 int rdhi;
5405
5406 skip_whitespace (str);
5407
5408 if ((rdlo = reg_required_here (& str, 12)) == FAIL)
5409 inst.error = BAD_ARGS;
5410
5411 else if (skip_past_comma (& str) == FAIL
5412 || (rdhi = reg_required_here (& str, 16)) == FAIL)
5413 inst.error = BAD_ARGS;
5414
5415 else if (skip_past_comma (& str) == FAIL
5416 || accum0_required_here (& str) == FAIL)
5417 inst.error = ERR_NO_ACCUM;
5418
5419 /* inst.instruction has now been zapped with both rdlo and rdhi. */
5420 else if (rdlo == rdhi)
5421 inst.error = BAD_ARGS; /* Undefined result if 2 writes to same reg. */
5422
5423 else if (rdlo == REG_PC || rdhi == REG_PC)
5424 inst.error = BAD_PC; /* Undefined result if rdlo or rdhi is R15. */
5425 else
5426 end_of_line (str);
5427 }
5428
5429 static int
5430 ldst_extend (char ** str)
5431 {
5432 int add = INDEX_UP;
5433
5434 switch (**str)
5435 {
5436 case '#':
5437 case '$':
5438 (*str)++;
5439 if (my_get_expression (& inst.reloc.exp, str))
5440 return FAIL;
5441
5442 if (inst.reloc.exp.X_op == O_constant)
5443 {
5444 int value = inst.reloc.exp.X_add_number;
5445
5446 if (value < -4095 || value > 4095)
5447 {
5448 inst.error = _("address offset too large");
5449 return FAIL;
5450 }
5451
5452 if (value < 0)
5453 {
5454 value = -value;
5455 add = 0;
5456 }
5457
5458 inst.instruction |= add | value;
5459 }
5460 else
5461 {
5462 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
5463 inst.reloc.pc_rel = 0;
5464 }
5465 return SUCCESS;
5466
5467 case '-':
5468 add = 0;
5469 /* Fall through. */
5470
5471 case '+':
5472 (*str)++;
5473 /* Fall through. */
5474
5475 default:
5476 if (reg_required_here (str, 0) == FAIL)
5477 return FAIL;
5478
5479 inst.instruction |= add | OFFSET_REG;
5480 if (skip_past_comma (str) == SUCCESS)
5481 return decode_shift (str, SHIFT_IMMEDIATE);
5482
5483 return SUCCESS;
5484 }
5485 }
5486
5487 /* ARMv5TE: Preload-Cache
5488
5489 PLD <addr_mode>
5490
5491 Syntactically, like LDR with B=1, W=0, L=1. */
5492
5493 static void
5494 do_pld (char * str)
5495 {
5496 int rd;
5497
5498 skip_whitespace (str);
5499
5500 if (* str != '[')
5501 {
5502 inst.error = _("'[' expected after PLD mnemonic");
5503 return;
5504 }
5505
5506 ++str;
5507 skip_whitespace (str);
5508
5509 if ((rd = reg_required_here (& str, 16)) == FAIL)
5510 return;
5511
5512 skip_whitespace (str);
5513
5514 if (*str == ']')
5515 {
5516 /* [Rn], ... ? */
5517 ++str;
5518 skip_whitespace (str);
5519
5520 /* Post-indexed addressing is not allowed with PLD. */
5521 if (skip_past_comma (&str) == SUCCESS)
5522 {
5523 inst.error
5524 = _("post-indexed expression used in preload instruction");
5525 return;
5526 }
5527 else if (*str == '!') /* [Rn]! */
5528 {
5529 inst.error = _("writeback used in preload instruction");
5530 ++str;
5531 }
5532 else /* [Rn] */
5533 inst.instruction |= INDEX_UP | PRE_INDEX;
5534 }
5535 else /* [Rn, ...] */
5536 {
5537 if (skip_past_comma (& str) == FAIL)
5538 {
5539 inst.error = _("pre-indexed expression expected");
5540 return;
5541 }
5542
5543 if (ldst_extend (&str) == FAIL)
5544 return;
5545
5546 skip_whitespace (str);
5547
5548 if (* str != ']')
5549 {
5550 inst.error = _("missing ]");
5551 return;
5552 }
5553
5554 ++ str;
5555 skip_whitespace (str);
5556
5557 if (* str == '!') /* [Rn]! */
5558 {
5559 inst.error = _("writeback used in preload instruction");
5560 ++ str;
5561 }
5562
5563 inst.instruction |= PRE_INDEX;
5564 }
5565
5566 end_of_line (str);
5567 }
5568
5569 /* ARMv5TE load-consecutive (argument parse)
5570 Mode is like LDRH.
5571
5572 LDRccD R, mode
5573 STRccD R, mode. */
5574
5575 static void
5576 do_ldrd (char * str)
5577 {
5578 int rd;
5579 int rn;
5580
5581 skip_whitespace (str);
5582
5583 if ((rd = reg_required_here (& str, 12)) == FAIL)
5584 {
5585 inst.error = BAD_ARGS;
5586 return;
5587 }
5588
5589 if (skip_past_comma (& str) == FAIL
5590 || (rn = ld_mode_required_here (& str)) == FAIL)
5591 {
5592 if (!inst.error)
5593 inst.error = BAD_ARGS;
5594 return;
5595 }
5596
5597 /* inst.instruction has now been zapped with Rd and the addressing mode. */
5598 if (rd & 1) /* Unpredictable result if Rd is odd. */
5599 {
5600 inst.error = _("destination register must be even");
5601 return;
5602 }
5603
5604 if (rd == REG_LR)
5605 {
5606 inst.error = _("r14 not allowed here");
5607 return;
5608 }
5609
5610 if (((rd == rn) || (rd + 1 == rn))
5611 && ((inst.instruction & WRITE_BACK)
5612 || (!(inst.instruction & PRE_INDEX))))
5613 as_warn (_("pre/post-indexing used when modified address register is destination"));
5614
5615 /* For an index-register load, the index register must not overlap the
5616 destination (even if not write-back). */
5617 if ((inst.instruction & V4_STR_BIT) == 0
5618 && (inst.instruction & HWOFFSET_IMM) == 0)
5619 {
5620 int rm = inst.instruction & 0x0000000f;
5621
5622 if (rm == rd || (rm == rd + 1))
5623 as_warn (_("ldrd destination registers must not overlap index register"));
5624 }
5625
5626 end_of_line (str);
5627 }
5628
5629 /* Returns the index into fp_values of a floating point number,
5630 or -1 if not in the table. */
5631
5632 static int
5633 my_get_float_expression (char ** str)
5634 {
5635 LITTLENUM_TYPE words[MAX_LITTLENUMS];
5636 char * save_in;
5637 expressionS exp;
5638 int i;
5639 int j;
5640
5641 memset (words, 0, MAX_LITTLENUMS * sizeof (LITTLENUM_TYPE));
5642
5643 /* Look for a raw floating point number. */
5644 if ((save_in = atof_ieee (*str, 'x', words)) != NULL
5645 && is_end_of_line[(unsigned char) *save_in])
5646 {
5647 for (i = 0; i < NUM_FLOAT_VALS; i++)
5648 {
5649 for (j = 0; j < MAX_LITTLENUMS; j++)
5650 {
5651 if (words[j] != fp_values[i][j])
5652 break;
5653 }
5654
5655 if (j == MAX_LITTLENUMS)
5656 {
5657 *str = save_in;
5658 return i;
5659 }
5660 }
5661 }
5662
5663 /* Try and parse a more complex expression, this will probably fail
5664 unless the code uses a floating point prefix (eg "0f"). */
5665 save_in = input_line_pointer;
5666 input_line_pointer = *str;
5667 if (expression (&exp) == absolute_section
5668 && exp.X_op == O_big
5669 && exp.X_add_number < 0)
5670 {
5671 /* FIXME: 5 = X_PRECISION, should be #define'd where we can use it.
5672 Ditto for 15. */
5673 if (gen_to_words (words, 5, (long) 15) == 0)
5674 {
5675 for (i = 0; i < NUM_FLOAT_VALS; i++)
5676 {
5677 for (j = 0; j < MAX_LITTLENUMS; j++)
5678 {
5679 if (words[j] != fp_values[i][j])
5680 break;
5681 }
5682
5683 if (j == MAX_LITTLENUMS)
5684 {
5685 *str = input_line_pointer;
5686 input_line_pointer = save_in;
5687 return i;
5688 }
5689 }
5690 }
5691 }
5692
5693 *str = input_line_pointer;
5694 input_line_pointer = save_in;
5695 return -1;
5696 }
5697
5698 /* We handle all bad expressions here, so that we can report the faulty
5699 instruction in the error message. */
5700 void
5701 md_operand (expressionS * expr)
5702 {
5703 if (in_my_get_expression)
5704 {
5705 expr->X_op = O_illegal;
5706 if (inst.error == NULL)
5707 inst.error = _("bad expression");
5708 }
5709 }
5710
5711 /* Do those data_ops which can take a negative immediate constant
5712 by altering the instruction. A bit of a hack really.
5713 MOV <-> MVN
5714 AND <-> BIC
5715 ADC <-> SBC
5716 by inverting the second operand, and
5717 ADD <-> SUB
5718 CMP <-> CMN
5719 by negating the second operand. */
5720
5721 static int
5722 negate_data_op (unsigned long * instruction,
5723 unsigned long value)
5724 {
5725 int op, new_inst;
5726 unsigned long negated, inverted;
5727
5728 negated = validate_immediate (-value);
5729 inverted = validate_immediate (~value);
5730
5731 op = (*instruction >> DATA_OP_SHIFT) & 0xf;
5732 switch (op)
5733 {
5734 /* First negates. */
5735 case OPCODE_SUB: /* ADD <-> SUB */
5736 new_inst = OPCODE_ADD;
5737 value = negated;
5738 break;
5739
5740 case OPCODE_ADD:
5741 new_inst = OPCODE_SUB;
5742 value = negated;
5743 break;
5744
5745 case OPCODE_CMP: /* CMP <-> CMN */
5746 new_inst = OPCODE_CMN;
5747 value = negated;
5748 break;
5749
5750 case OPCODE_CMN:
5751 new_inst = OPCODE_CMP;
5752 value = negated;
5753 break;
5754
5755 /* Now Inverted ops. */
5756 case OPCODE_MOV: /* MOV <-> MVN */
5757 new_inst = OPCODE_MVN;
5758 value = inverted;
5759 break;
5760
5761 case OPCODE_MVN:
5762 new_inst = OPCODE_MOV;
5763 value = inverted;
5764 break;
5765
5766 case OPCODE_AND: /* AND <-> BIC */
5767 new_inst = OPCODE_BIC;
5768 value = inverted;
5769 break;
5770
5771 case OPCODE_BIC:
5772 new_inst = OPCODE_AND;
5773 value = inverted;
5774 break;
5775
5776 case OPCODE_ADC: /* ADC <-> SBC */
5777 new_inst = OPCODE_SBC;
5778 value = inverted;
5779 break;
5780
5781 case OPCODE_SBC:
5782 new_inst = OPCODE_ADC;
5783 value = inverted;
5784 break;
5785
5786 /* We cannot do anything. */
5787 default:
5788 return FAIL;
5789 }
5790
5791 if (value == (unsigned) FAIL)
5792 return FAIL;
5793
5794 *instruction &= OPCODE_MASK;
5795 *instruction |= new_inst << DATA_OP_SHIFT;
5796 return value;
5797 }
5798
5799 static int
5800 data_op2 (char ** str)
5801 {
5802 int value;
5803 expressionS expr;
5804
5805 skip_whitespace (* str);
5806
5807 if (reg_required_here (str, 0) != FAIL)
5808 {
5809 if (skip_past_comma (str) == SUCCESS)
5810 /* Shift operation on register. */
5811 return decode_shift (str, NO_SHIFT_RESTRICT);
5812
5813 return SUCCESS;
5814 }
5815 else
5816 {
5817 /* Immediate expression. */
5818 if (is_immediate_prefix (**str))
5819 {
5820 (*str)++;
5821 inst.error = NULL;
5822
5823 if (my_get_expression (&inst.reloc.exp, str))
5824 return FAIL;
5825
5826 if (inst.reloc.exp.X_add_symbol)
5827 {
5828 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
5829 inst.reloc.pc_rel = 0;
5830 }
5831 else
5832 {
5833 if (skip_past_comma (str) == SUCCESS)
5834 {
5835 /* #x, y -- ie explicit rotation by Y. */
5836 if (my_get_expression (&expr, str))
5837 return FAIL;
5838
5839 if (expr.X_op != O_constant)
5840 {
5841 inst.error = _("constant expression expected");
5842 return FAIL;
5843 }
5844
5845 /* Rotate must be a multiple of 2. */
5846 if (((unsigned) expr.X_add_number) > 30
5847 || (expr.X_add_number & 1) != 0
5848 || ((unsigned) inst.reloc.exp.X_add_number) > 255)
5849 {
5850 inst.error = _("invalid constant");
5851 return FAIL;
5852 }
5853 inst.instruction |= INST_IMMEDIATE;
5854 inst.instruction |= inst.reloc.exp.X_add_number;
5855 inst.instruction |= expr.X_add_number << 7;
5856 return SUCCESS;
5857 }
5858
5859 /* Implicit rotation, select a suitable one. */
5860 value = validate_immediate (inst.reloc.exp.X_add_number);
5861
5862 if (value == FAIL)
5863 {
5864 /* Can't be done. Perhaps the code reads something like
5865 "add Rd, Rn, #-n", where "sub Rd, Rn, #n" would be OK. */
5866 if ((value = negate_data_op (&inst.instruction,
5867 inst.reloc.exp.X_add_number))
5868 == FAIL)
5869 {
5870 inst.error = _("invalid constant");
5871 return FAIL;
5872 }
5873 }
5874
5875 inst.instruction |= value;
5876 }
5877
5878 inst.instruction |= INST_IMMEDIATE;
5879 return SUCCESS;
5880 }
5881
5882 (*str)++;
5883 inst.error = _("register or shift expression expected");
5884 return FAIL;
5885 }
5886 }
5887
5888 static int
5889 fp_op2 (char ** str)
5890 {
5891 skip_whitespace (* str);
5892
5893 if (fp_reg_required_here (str, 0) != FAIL)
5894 return SUCCESS;
5895 else
5896 {
5897 /* Immediate expression. */
5898 if (*((*str)++) == '#')
5899 {
5900 int i;
5901
5902 inst.error = NULL;
5903
5904 skip_whitespace (* str);
5905
5906 /* First try and match exact strings, this is to guarantee
5907 that some formats will work even for cross assembly. */
5908
5909 for (i = 0; fp_const[i]; i++)
5910 {
5911 if (strncmp (*str, fp_const[i], strlen (fp_const[i])) == 0)
5912 {
5913 char *start = *str;
5914
5915 *str += strlen (fp_const[i]);
5916 if (is_end_of_line[(unsigned char) **str])
5917 {
5918 inst.instruction |= i + 8;
5919 return SUCCESS;
5920 }
5921 *str = start;
5922 }
5923 }
5924
5925 /* Just because we didn't get a match doesn't mean that the
5926 constant isn't valid, just that it is in a format that we
5927 don't automatically recognize. Try parsing it with
5928 the standard expression routines. */
5929 if ((i = my_get_float_expression (str)) >= 0)
5930 {
5931 inst.instruction |= i + 8;
5932 return SUCCESS;
5933 }
5934
5935 inst.error = _("invalid floating point immediate expression");
5936 return FAIL;
5937 }
5938 inst.error =
5939 _("floating point register or immediate expression expected");
5940 return FAIL;
5941 }
5942 }
5943
5944 static void
5945 do_arit (char * str)
5946 {
5947 skip_whitespace (str);
5948
5949 if (reg_required_here (&str, 12) == FAIL
5950 || skip_past_comma (&str) == FAIL
5951 || reg_required_here (&str, 16) == FAIL
5952 || skip_past_comma (&str) == FAIL
5953 || data_op2 (&str) == FAIL)
5954 {
5955 if (!inst.error)
5956 inst.error = BAD_ARGS;
5957 return;
5958 }
5959
5960 end_of_line (str);
5961 }
5962
5963 static void
5964 do_adr (char * str)
5965 {
5966 /* This is a pseudo-op of the form "adr rd, label" to be converted
5967 into a relative address of the form "add rd, pc, #label-.-8". */
5968 skip_whitespace (str);
5969
5970 if (reg_required_here (&str, 12) == FAIL
5971 || skip_past_comma (&str) == FAIL
5972 || my_get_expression (&inst.reloc.exp, &str))
5973 {
5974 if (!inst.error)
5975 inst.error = BAD_ARGS;
5976 return;
5977 }
5978
5979 /* Frag hacking will turn this into a sub instruction if the offset turns
5980 out to be negative. */
5981 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
5982 #ifndef TE_WINCE
5983 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust. */
5984 #endif
5985 inst.reloc.pc_rel = 1;
5986
5987 end_of_line (str);
5988 }
5989
5990 static void
5991 do_adrl (char * str)
5992 {
5993 /* This is a pseudo-op of the form "adrl rd, label" to be converted
5994 into a relative address of the form:
5995 add rd, pc, #low(label-.-8)"
5996 add rd, rd, #high(label-.-8)" */
5997
5998 skip_whitespace (str);
5999
6000 if (reg_required_here (&str, 12) == FAIL
6001 || skip_past_comma (&str) == FAIL
6002 || my_get_expression (&inst.reloc.exp, &str))
6003 {
6004 if (!inst.error)
6005 inst.error = BAD_ARGS;
6006
6007 return;
6008 }
6009
6010 end_of_line (str);
6011 /* Frag hacking will turn this into a sub instruction if the offset turns
6012 out to be negative. */
6013 inst.reloc.type = BFD_RELOC_ARM_ADRL_IMMEDIATE;
6014 #ifndef TE_WINCE
6015 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust */
6016 #endif
6017 inst.reloc.pc_rel = 1;
6018 inst.size = INSN_SIZE * 2;
6019 }
6020
6021 static void
6022 do_cmp (char * str)
6023 {
6024 skip_whitespace (str);
6025
6026 if (reg_required_here (&str, 16) == FAIL)
6027 {
6028 if (!inst.error)
6029 inst.error = BAD_ARGS;
6030 return;
6031 }
6032
6033 if (skip_past_comma (&str) == FAIL
6034 || data_op2 (&str) == FAIL)
6035 {
6036 if (!inst.error)
6037 inst.error = BAD_ARGS;
6038 return;
6039 }
6040
6041 end_of_line (str);
6042 }
6043
6044 static void
6045 do_mov (char * str)
6046 {
6047 skip_whitespace (str);
6048
6049 if (reg_required_here (&str, 12) == FAIL)
6050 {
6051 if (!inst.error)
6052 inst.error = BAD_ARGS;
6053 return;
6054 }
6055
6056 if (skip_past_comma (&str) == FAIL
6057 || data_op2 (&str) == FAIL)
6058 {
6059 if (!inst.error)
6060 inst.error = BAD_ARGS;
6061 return;
6062 }
6063
6064 end_of_line (str);
6065 }
6066
6067 static void
6068 do_ldst (char * str)
6069 {
6070 int pre_inc = 0;
6071 int conflict_reg;
6072 int value;
6073
6074 skip_whitespace (str);
6075
6076 if ((conflict_reg = reg_required_here (&str, 12)) == FAIL)
6077 {
6078 if (!inst.error)
6079 inst.error = BAD_ARGS;
6080 return;
6081 }
6082
6083 if (skip_past_comma (&str) == FAIL)
6084 {
6085 inst.error = _("address expected");
6086 return;
6087 }
6088
6089 if (*str == '[')
6090 {
6091 int reg;
6092
6093 str++;
6094
6095 skip_whitespace (str);
6096
6097 if ((reg = reg_required_here (&str, 16)) == FAIL)
6098 return;
6099
6100 /* Conflicts can occur on stores as well as loads. */
6101 conflict_reg = (conflict_reg == reg);
6102
6103 skip_whitespace (str);
6104
6105 if (*str == ']')
6106 {
6107 str ++;
6108
6109 if (skip_past_comma (&str) == SUCCESS)
6110 {
6111 /* [Rn],... (post inc) */
6112 if (ldst_extend (&str) == FAIL)
6113 return;
6114 if (conflict_reg)
6115 as_warn (_("%s register same as write-back base"),
6116 ((inst.instruction & LOAD_BIT)
6117 ? _("destination") : _("source")));
6118 }
6119 else
6120 {
6121 /* [Rn] */
6122 skip_whitespace (str);
6123
6124 if (*str == '!')
6125 {
6126 if (conflict_reg)
6127 as_warn (_("%s register same as write-back base"),
6128 ((inst.instruction & LOAD_BIT)
6129 ? _("destination") : _("source")));
6130 str++;
6131 inst.instruction |= WRITE_BACK;
6132 }
6133
6134 inst.instruction |= INDEX_UP;
6135 pre_inc = 1;
6136 }
6137 }
6138 else
6139 {
6140 /* [Rn,...] */
6141 if (skip_past_comma (&str) == FAIL)
6142 {
6143 inst.error = _("pre-indexed expression expected");
6144 return;
6145 }
6146
6147 pre_inc = 1;
6148 if (ldst_extend (&str) == FAIL)
6149 return;
6150
6151 skip_whitespace (str);
6152
6153 if (*str++ != ']')
6154 {
6155 inst.error = _("missing ]");
6156 return;
6157 }
6158
6159 skip_whitespace (str);
6160
6161 if (*str == '!')
6162 {
6163 if (conflict_reg)
6164 as_warn (_("%s register same as write-back base"),
6165 ((inst.instruction & LOAD_BIT)
6166 ? _("destination") : _("source")));
6167 str++;
6168 inst.instruction |= WRITE_BACK;
6169 }
6170 }
6171 }
6172 else if (*str == '=')
6173 {
6174 if ((inst.instruction & LOAD_BIT) == 0)
6175 {
6176 inst.error = _("invalid pseudo operation");
6177 return;
6178 }
6179
6180 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
6181 str++;
6182
6183 skip_whitespace (str);
6184
6185 if (my_get_expression (&inst.reloc.exp, &str))
6186 return;
6187
6188 if (inst.reloc.exp.X_op != O_constant
6189 && inst.reloc.exp.X_op != O_symbol)
6190 {
6191 inst.error = _("constant expression expected");
6192 return;
6193 }
6194
6195 if (inst.reloc.exp.X_op == O_constant)
6196 {
6197 value = validate_immediate (inst.reloc.exp.X_add_number);
6198
6199 if (value != FAIL)
6200 {
6201 /* This can be done with a mov instruction. */
6202 inst.instruction &= LITERAL_MASK;
6203 inst.instruction |= (INST_IMMEDIATE
6204 | (OPCODE_MOV << DATA_OP_SHIFT));
6205 inst.instruction |= value & 0xfff;
6206 end_of_line (str);
6207 return;
6208 }
6209
6210 value = validate_immediate (~inst.reloc.exp.X_add_number);
6211
6212 if (value != FAIL)
6213 {
6214 /* This can be done with a mvn instruction. */
6215 inst.instruction &= LITERAL_MASK;
6216 inst.instruction |= (INST_IMMEDIATE
6217 | (OPCODE_MVN << DATA_OP_SHIFT));
6218 inst.instruction |= value & 0xfff;
6219 end_of_line (str);
6220 return;
6221 }
6222 }
6223
6224 /* Insert into literal pool. */
6225 if (add_to_lit_pool () == FAIL)
6226 {
6227 if (!inst.error)
6228 inst.error = _("literal pool insertion failed");
6229 return;
6230 }
6231
6232 /* Change the instruction exp to point to the pool. */
6233 inst.reloc.type = BFD_RELOC_ARM_LITERAL;
6234 inst.reloc.pc_rel = 1;
6235 inst.instruction |= (REG_PC << 16);
6236 pre_inc = 1;
6237 }
6238 else
6239 {
6240 if (my_get_expression (&inst.reloc.exp, &str))
6241 return;
6242
6243 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
6244 #ifndef TE_WINCE
6245 /* PC rel adjust. */
6246 inst.reloc.exp.X_add_number -= 8;
6247 #endif
6248 inst.reloc.pc_rel = 1;
6249 inst.instruction |= (REG_PC << 16);
6250 pre_inc = 1;
6251 }
6252
6253 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
6254 end_of_line (str);
6255 }
6256
6257 static void
6258 do_ldstt (char * str)
6259 {
6260 int conflict_reg;
6261
6262 skip_whitespace (str);
6263
6264 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
6265 {
6266 if (!inst.error)
6267 inst.error = BAD_ARGS;
6268 return;
6269 }
6270
6271 if (skip_past_comma (& str) == FAIL)
6272 {
6273 inst.error = _("address expected");
6274 return;
6275 }
6276
6277 if (*str == '[')
6278 {
6279 int reg;
6280
6281 str++;
6282
6283 skip_whitespace (str);
6284
6285 if ((reg = reg_required_here (&str, 16)) == FAIL)
6286 return;
6287
6288 /* ldrt/strt always use post-indexed addressing, so if the base is
6289 the same as Rd, we warn. */
6290 if (conflict_reg == reg)
6291 as_warn (_("%s register same as write-back base"),
6292 ((inst.instruction & LOAD_BIT)
6293 ? _("destination") : _("source")));
6294
6295 skip_whitespace (str);
6296
6297 if (*str == ']')
6298 {
6299 str ++;
6300
6301 if (skip_past_comma (&str) == SUCCESS)
6302 {
6303 /* [Rn],... (post inc) */
6304 if (ldst_extend (&str) == FAIL)
6305 return;
6306 }
6307 else
6308 {
6309 /* [Rn] */
6310 skip_whitespace (str);
6311
6312 /* Skip a write-back '!'. */
6313 if (*str == '!')
6314 str++;
6315
6316 inst.instruction |= INDEX_UP;
6317 }
6318 }
6319 else
6320 {
6321 inst.error = _("post-indexed expression expected");
6322 return;
6323 }
6324 }
6325 else
6326 {
6327 inst.error = _("post-indexed expression expected");
6328 return;
6329 }
6330
6331 end_of_line (str);
6332 }
6333
6334 /* Halfword and signed-byte load/store operations. */
6335
6336 static void
6337 do_ldstv4 (char * str)
6338 {
6339 int pre_inc = 0;
6340 int conflict_reg;
6341 int value;
6342
6343 skip_whitespace (str);
6344
6345 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
6346 {
6347 if (!inst.error)
6348 inst.error = BAD_ARGS;
6349 return;
6350 }
6351
6352 if (skip_past_comma (& str) == FAIL)
6353 {
6354 inst.error = _("address expected");
6355 return;
6356 }
6357
6358 if (*str == '[')
6359 {
6360 int reg;
6361
6362 str++;
6363
6364 skip_whitespace (str);
6365
6366 if ((reg = reg_required_here (&str, 16)) == FAIL)
6367 return;
6368
6369 /* Conflicts can occur on stores as well as loads. */
6370 conflict_reg = (conflict_reg == reg);
6371
6372 skip_whitespace (str);
6373
6374 if (*str == ']')
6375 {
6376 str ++;
6377
6378 if (skip_past_comma (&str) == SUCCESS)
6379 {
6380 /* [Rn],... (post inc) */
6381 if (ldst_extend_v4 (&str) == FAIL)
6382 return;
6383 if (conflict_reg)
6384 as_warn (_("%s register same as write-back base"),
6385 ((inst.instruction & LOAD_BIT)
6386 ? _("destination") : _("source")));
6387 }
6388 else
6389 {
6390 /* [Rn] */
6391 inst.instruction |= HWOFFSET_IMM;
6392
6393 skip_whitespace (str);
6394
6395 if (*str == '!')
6396 {
6397 if (conflict_reg)
6398 as_warn (_("%s register same as write-back base"),
6399 ((inst.instruction & LOAD_BIT)
6400 ? _("destination") : _("source")));
6401 str++;
6402 inst.instruction |= WRITE_BACK;
6403 }
6404
6405 inst.instruction |= INDEX_UP;
6406 pre_inc = 1;
6407 }
6408 }
6409 else
6410 {
6411 /* [Rn,...] */
6412 if (skip_past_comma (&str) == FAIL)
6413 {
6414 inst.error = _("pre-indexed expression expected");
6415 return;
6416 }
6417
6418 pre_inc = 1;
6419 if (ldst_extend_v4 (&str) == FAIL)
6420 return;
6421
6422 skip_whitespace (str);
6423
6424 if (*str++ != ']')
6425 {
6426 inst.error = _("missing ]");
6427 return;
6428 }
6429
6430 skip_whitespace (str);
6431
6432 if (*str == '!')
6433 {
6434 if (conflict_reg)
6435 as_warn (_("%s register same as write-back base"),
6436 ((inst.instruction & LOAD_BIT)
6437 ? _("destination") : _("source")));
6438 str++;
6439 inst.instruction |= WRITE_BACK;
6440 }
6441 }
6442 }
6443 else if (*str == '=')
6444 {
6445 if ((inst.instruction & LOAD_BIT) == 0)
6446 {
6447 inst.error = _("invalid pseudo operation");
6448 return;
6449 }
6450
6451 /* XXX Does this work correctly for half-word/byte ops? */
6452 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
6453 str++;
6454
6455 skip_whitespace (str);
6456
6457 if (my_get_expression (&inst.reloc.exp, &str))
6458 return;
6459
6460 if (inst.reloc.exp.X_op != O_constant
6461 && inst.reloc.exp.X_op != O_symbol)
6462 {
6463 inst.error = _("constant expression expected");
6464 return;
6465 }
6466
6467 if (inst.reloc.exp.X_op == O_constant)
6468 {
6469 value = validate_immediate (inst.reloc.exp.X_add_number);
6470
6471 if (value != FAIL)
6472 {
6473 /* This can be done with a mov instruction. */
6474 inst.instruction &= LITERAL_MASK;
6475 inst.instruction |= INST_IMMEDIATE | (OPCODE_MOV << DATA_OP_SHIFT);
6476 inst.instruction |= value & 0xfff;
6477 end_of_line (str);
6478 return;
6479 }
6480
6481 value = validate_immediate (~ inst.reloc.exp.X_add_number);
6482
6483 if (value != FAIL)
6484 {
6485 /* This can be done with a mvn instruction. */
6486 inst.instruction &= LITERAL_MASK;
6487 inst.instruction |= INST_IMMEDIATE | (OPCODE_MVN << DATA_OP_SHIFT);
6488 inst.instruction |= value & 0xfff;
6489 end_of_line (str);
6490 return;
6491 }
6492 }
6493
6494 /* Insert into literal pool. */
6495 if (add_to_lit_pool () == FAIL)
6496 {
6497 if (!inst.error)
6498 inst.error = _("literal pool insertion failed");
6499 return;
6500 }
6501
6502 /* Change the instruction exp to point to the pool. */
6503 inst.instruction |= HWOFFSET_IMM;
6504 inst.reloc.type = BFD_RELOC_ARM_HWLITERAL;
6505 inst.reloc.pc_rel = 1;
6506 inst.instruction |= (REG_PC << 16);
6507 pre_inc = 1;
6508 }
6509 else
6510 {
6511 if (my_get_expression (&inst.reloc.exp, &str))
6512 return;
6513
6514 inst.instruction |= HWOFFSET_IMM;
6515 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
6516 #ifndef TE_WINCE
6517 /* PC rel adjust. */
6518 inst.reloc.exp.X_add_number -= 8;
6519 #endif
6520 inst.reloc.pc_rel = 1;
6521 inst.instruction |= (REG_PC << 16);
6522 pre_inc = 1;
6523 }
6524
6525 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
6526 end_of_line (str);
6527 }
6528
6529 static long
6530 reg_list (char ** strp)
6531 {
6532 char * str = * strp;
6533 long range = 0;
6534 int another_range;
6535
6536 /* We come back here if we get ranges concatenated by '+' or '|'. */
6537 do
6538 {
6539 another_range = 0;
6540
6541 if (*str == '{')
6542 {
6543 int in_range = 0;
6544 int cur_reg = -1;
6545
6546 str++;
6547 do
6548 {
6549 int reg;
6550
6551 skip_whitespace (str);
6552
6553 if ((reg = reg_required_here (& str, -1)) == FAIL)
6554 return FAIL;
6555
6556 if (in_range)
6557 {
6558 int i;
6559
6560 if (reg <= cur_reg)
6561 {
6562 inst.error = _("bad range in register list");
6563 return FAIL;
6564 }
6565
6566 for (i = cur_reg + 1; i < reg; i++)
6567 {
6568 if (range & (1 << i))
6569 as_tsktsk
6570 (_("Warning: duplicated register (r%d) in register list"),
6571 i);
6572 else
6573 range |= 1 << i;
6574 }
6575 in_range = 0;
6576 }
6577
6578 if (range & (1 << reg))
6579 as_tsktsk (_("Warning: duplicated register (r%d) in register list"),
6580 reg);
6581 else if (reg <= cur_reg)
6582 as_tsktsk (_("Warning: register range not in ascending order"));
6583
6584 range |= 1 << reg;
6585 cur_reg = reg;
6586 }
6587 while (skip_past_comma (&str) != FAIL
6588 || (in_range = 1, *str++ == '-'));
6589 str--;
6590 skip_whitespace (str);
6591
6592 if (*str++ != '}')
6593 {
6594 inst.error = _("missing `}'");
6595 return FAIL;
6596 }
6597 }
6598 else
6599 {
6600 expressionS expr;
6601
6602 if (my_get_expression (&expr, &str))
6603 return FAIL;
6604
6605 if (expr.X_op == O_constant)
6606 {
6607 if (expr.X_add_number
6608 != (expr.X_add_number & 0x0000ffff))
6609 {
6610 inst.error = _("invalid register mask");
6611 return FAIL;
6612 }
6613
6614 if ((range & expr.X_add_number) != 0)
6615 {
6616 int regno = range & expr.X_add_number;
6617
6618 regno &= -regno;
6619 regno = (1 << regno) - 1;
6620 as_tsktsk
6621 (_("Warning: duplicated register (r%d) in register list"),
6622 regno);
6623 }
6624
6625 range |= expr.X_add_number;
6626 }
6627 else
6628 {
6629 if (inst.reloc.type != 0)
6630 {
6631 inst.error = _("expression too complex");
6632 return FAIL;
6633 }
6634
6635 memcpy (&inst.reloc.exp, &expr, sizeof (expressionS));
6636 inst.reloc.type = BFD_RELOC_ARM_MULTI;
6637 inst.reloc.pc_rel = 0;
6638 }
6639 }
6640
6641 skip_whitespace (str);
6642
6643 if (*str == '|' || *str == '+')
6644 {
6645 str++;
6646 another_range = 1;
6647 }
6648 }
6649 while (another_range);
6650
6651 *strp = str;
6652 return range;
6653 }
6654
6655 static void
6656 do_ldmstm (char * str)
6657 {
6658 int base_reg;
6659 long range;
6660
6661 skip_whitespace (str);
6662
6663 if ((base_reg = reg_required_here (&str, 16)) == FAIL)
6664 return;
6665
6666 if (base_reg == REG_PC)
6667 {
6668 inst.error = _("r15 not allowed as base register");
6669 return;
6670 }
6671
6672 skip_whitespace (str);
6673
6674 if (*str == '!')
6675 {
6676 inst.instruction |= WRITE_BACK;
6677 str++;
6678 }
6679
6680 if (skip_past_comma (&str) == FAIL
6681 || (range = reg_list (&str)) == FAIL)
6682 {
6683 if (! inst.error)
6684 inst.error = BAD_ARGS;
6685 return;
6686 }
6687
6688 if (*str == '^')
6689 {
6690 str++;
6691 inst.instruction |= LDM_TYPE_2_OR_3;
6692 }
6693
6694 if (inst.instruction & WRITE_BACK)
6695 {
6696 /* Check for unpredictable uses of writeback. */
6697 if (inst.instruction & LOAD_BIT)
6698 {
6699 /* Not allowed in LDM type 2. */
6700 if ((inst.instruction & LDM_TYPE_2_OR_3)
6701 && ((range & (1 << REG_PC)) == 0))
6702 as_warn (_("writeback of base register is UNPREDICTABLE"));
6703 /* Only allowed if base reg not in list for other types. */
6704 else if (range & (1 << base_reg))
6705 as_warn (_("writeback of base register when in register list is UNPREDICTABLE"));
6706 }
6707 else /* STM. */
6708 {
6709 /* Not allowed for type 2. */
6710 if (inst.instruction & LDM_TYPE_2_OR_3)
6711 as_warn (_("writeback of base register is UNPREDICTABLE"));
6712 /* Only allowed if base reg not in list, or first in list. */
6713 else if ((range & (1 << base_reg))
6714 && (range & ((1 << base_reg) - 1)))
6715 as_warn (_("if writeback register is in list, it must be the lowest reg in the list"));
6716 }
6717 }
6718
6719 inst.instruction |= range;
6720 end_of_line (str);
6721 }
6722
6723 static void
6724 do_smi (char * str)
6725 {
6726 skip_whitespace (str);
6727
6728 /* Allow optional leading '#'. */
6729 if (is_immediate_prefix (*str))
6730 str++;
6731
6732 if (my_get_expression (& inst.reloc.exp, & str))
6733 return;
6734
6735 inst.reloc.type = BFD_RELOC_ARM_SMI;
6736 inst.reloc.pc_rel = 0;
6737 end_of_line (str);
6738 }
6739
6740 static void
6741 do_swi (char * str)
6742 {
6743 skip_whitespace (str);
6744
6745 /* Allow optional leading '#'. */
6746 if (is_immediate_prefix (*str))
6747 str++;
6748
6749 if (my_get_expression (& inst.reloc.exp, & str))
6750 return;
6751
6752 inst.reloc.type = BFD_RELOC_ARM_SWI;
6753 inst.reloc.pc_rel = 0;
6754 end_of_line (str);
6755 }
6756
6757 static void
6758 do_swap (char * str)
6759 {
6760 int reg;
6761
6762 skip_whitespace (str);
6763
6764 if ((reg = reg_required_here (&str, 12)) == FAIL)
6765 return;
6766
6767 if (reg == REG_PC)
6768 {
6769 inst.error = _("r15 not allowed in swap");
6770 return;
6771 }
6772
6773 if (skip_past_comma (&str) == FAIL
6774 || (reg = reg_required_here (&str, 0)) == FAIL)
6775 {
6776 if (!inst.error)
6777 inst.error = BAD_ARGS;
6778 return;
6779 }
6780
6781 if (reg == REG_PC)
6782 {
6783 inst.error = _("r15 not allowed in swap");
6784 return;
6785 }
6786
6787 if (skip_past_comma (&str) == FAIL
6788 || *str++ != '[')
6789 {
6790 inst.error = BAD_ARGS;
6791 return;
6792 }
6793
6794 skip_whitespace (str);
6795
6796 if ((reg = reg_required_here (&str, 16)) == FAIL)
6797 return;
6798
6799 if (reg == REG_PC)
6800 {
6801 inst.error = BAD_PC;
6802 return;
6803 }
6804
6805 skip_whitespace (str);
6806
6807 if (*str++ != ']')
6808 {
6809 inst.error = _("missing ]");
6810 return;
6811 }
6812
6813 end_of_line (str);
6814 }
6815
6816 static void
6817 do_branch (char * str)
6818 {
6819 if (my_get_expression (&inst.reloc.exp, &str))
6820 return;
6821
6822 #ifdef OBJ_ELF
6823 {
6824 char * save_in;
6825
6826 /* ScottB: February 5, 1998 - Check to see of PLT32 reloc
6827 required for the instruction. */
6828
6829 /* arm_parse_reloc () works on input_line_pointer.
6830 We actually want to parse the operands to the branch instruction
6831 passed in 'str'. Save the input pointer and restore it later. */
6832 save_in = input_line_pointer;
6833 input_line_pointer = str;
6834 if (inst.reloc.exp.X_op == O_symbol
6835 && *str == '('
6836 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
6837 {
6838 inst.reloc.type = BFD_RELOC_ARM_PLT32;
6839 inst.reloc.pc_rel = 0;
6840 /* Modify str to point to after parsed operands, otherwise
6841 end_of_line() will complain about the (PLT) left in str. */
6842 str = input_line_pointer;
6843 }
6844 else
6845 {
6846 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
6847 inst.reloc.pc_rel = 1;
6848 }
6849 input_line_pointer = save_in;
6850 }
6851 #else
6852 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
6853 inst.reloc.pc_rel = 1;
6854 #endif /* OBJ_ELF */
6855
6856 end_of_line (str);
6857 }
6858
6859 static void
6860 do_cdp (char * str)
6861 {
6862 /* Co-processor data operation.
6863 Format: CDP{cond} CP#,<expr>,CRd,CRn,CRm{,<expr>} */
6864 skip_whitespace (str);
6865
6866 if (co_proc_number (&str) == FAIL)
6867 {
6868 if (!inst.error)
6869 inst.error = BAD_ARGS;
6870 return;
6871 }
6872
6873 if (skip_past_comma (&str) == FAIL
6874 || cp_opc_expr (&str, 20,4) == FAIL)
6875 {
6876 if (!inst.error)
6877 inst.error = BAD_ARGS;
6878 return;
6879 }
6880
6881 if (skip_past_comma (&str) == FAIL
6882 || cp_reg_required_here (&str, 12) == FAIL)
6883 {
6884 if (!inst.error)
6885 inst.error = BAD_ARGS;
6886 return;
6887 }
6888
6889 if (skip_past_comma (&str) == FAIL
6890 || cp_reg_required_here (&str, 16) == FAIL)
6891 {
6892 if (!inst.error)
6893 inst.error = BAD_ARGS;
6894 return;
6895 }
6896
6897 if (skip_past_comma (&str) == FAIL
6898 || cp_reg_required_here (&str, 0) == FAIL)
6899 {
6900 if (!inst.error)
6901 inst.error = BAD_ARGS;
6902 return;
6903 }
6904
6905 if (skip_past_comma (&str) == SUCCESS)
6906 {
6907 if (cp_opc_expr (&str, 5, 3) == FAIL)
6908 {
6909 if (!inst.error)
6910 inst.error = BAD_ARGS;
6911 return;
6912 }
6913 }
6914
6915 end_of_line (str);
6916 }
6917
6918 static void
6919 do_lstc (char * str)
6920 {
6921 /* Co-processor register load/store.
6922 Format: <LDC|STC{cond}[L] CP#,CRd,<address> */
6923
6924 skip_whitespace (str);
6925
6926 if (co_proc_number (&str) == FAIL)
6927 {
6928 if (!inst.error)
6929 inst.error = BAD_ARGS;
6930 return;
6931 }
6932
6933 if (skip_past_comma (&str) == FAIL
6934 || cp_reg_required_here (&str, 12) == FAIL)
6935 {
6936 if (!inst.error)
6937 inst.error = BAD_ARGS;
6938 return;
6939 }
6940
6941 if (skip_past_comma (&str) == FAIL
6942 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
6943 {
6944 if (! inst.error)
6945 inst.error = BAD_ARGS;
6946 return;
6947 }
6948
6949 end_of_line (str);
6950 }
6951
6952 static void
6953 do_co_reg (char * str)
6954 {
6955 /* Co-processor register transfer.
6956 Format: <MCR|MRC>{cond} CP#,<expr1>,Rd,CRn,CRm{,<expr2>} */
6957
6958 skip_whitespace (str);
6959
6960 if (co_proc_number (&str) == FAIL)
6961 {
6962 if (!inst.error)
6963 inst.error = BAD_ARGS;
6964 return;
6965 }
6966
6967 if (skip_past_comma (&str) == FAIL
6968 || cp_opc_expr (&str, 21, 3) == FAIL)
6969 {
6970 if (!inst.error)
6971 inst.error = BAD_ARGS;
6972 return;
6973 }
6974
6975 if (skip_past_comma (&str) == FAIL
6976 || reg_required_here (&str, 12) == FAIL)
6977 {
6978 if (!inst.error)
6979 inst.error = BAD_ARGS;
6980 return;
6981 }
6982
6983 if (skip_past_comma (&str) == FAIL
6984 || cp_reg_required_here (&str, 16) == FAIL)
6985 {
6986 if (!inst.error)
6987 inst.error = BAD_ARGS;
6988 return;
6989 }
6990
6991 if (skip_past_comma (&str) == FAIL
6992 || cp_reg_required_here (&str, 0) == FAIL)
6993 {
6994 if (!inst.error)
6995 inst.error = BAD_ARGS;
6996 return;
6997 }
6998
6999 if (skip_past_comma (&str) == SUCCESS)
7000 {
7001 if (cp_opc_expr (&str, 5, 3) == FAIL)
7002 {
7003 if (!inst.error)
7004 inst.error = BAD_ARGS;
7005 return;
7006 }
7007 }
7008
7009 end_of_line (str);
7010 }
7011
7012 static void
7013 do_fpa_ctrl (char * str)
7014 {
7015 /* FP control registers.
7016 Format: <WFS|RFS|WFC|RFC>{cond} Rn */
7017
7018 skip_whitespace (str);
7019
7020 if (reg_required_here (&str, 12) == FAIL)
7021 {
7022 if (!inst.error)
7023 inst.error = BAD_ARGS;
7024 return;
7025 }
7026
7027 end_of_line (str);
7028 }
7029
7030 static void
7031 do_fpa_ldst (char * str)
7032 {
7033 skip_whitespace (str);
7034
7035 if (fp_reg_required_here (&str, 12) == FAIL)
7036 {
7037 if (!inst.error)
7038 inst.error = BAD_ARGS;
7039 return;
7040 }
7041
7042 if (skip_past_comma (&str) == FAIL
7043 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
7044 {
7045 if (!inst.error)
7046 inst.error = BAD_ARGS;
7047 return;
7048 }
7049
7050 end_of_line (str);
7051 }
7052
7053 static void
7054 do_fpa_ldmstm (char * str)
7055 {
7056 int num_regs;
7057
7058 skip_whitespace (str);
7059
7060 if (fp_reg_required_here (&str, 12) == FAIL)
7061 {
7062 if (! inst.error)
7063 inst.error = BAD_ARGS;
7064 return;
7065 }
7066
7067 /* Get Number of registers to transfer. */
7068 if (skip_past_comma (&str) == FAIL
7069 || my_get_expression (&inst.reloc.exp, &str))
7070 {
7071 if (! inst.error)
7072 inst.error = _("constant expression expected");
7073 return;
7074 }
7075
7076 if (inst.reloc.exp.X_op != O_constant)
7077 {
7078 inst.error = _("constant value required for number of registers");
7079 return;
7080 }
7081
7082 num_regs = inst.reloc.exp.X_add_number;
7083
7084 if (num_regs < 1 || num_regs > 4)
7085 {
7086 inst.error = _("number of registers must be in the range [1:4]");
7087 return;
7088 }
7089
7090 switch (num_regs)
7091 {
7092 case 1:
7093 inst.instruction |= CP_T_X;
7094 break;
7095 case 2:
7096 inst.instruction |= CP_T_Y;
7097 break;
7098 case 3:
7099 inst.instruction |= CP_T_Y | CP_T_X;
7100 break;
7101 case 4:
7102 break;
7103 default:
7104 abort ();
7105 }
7106
7107 if (inst.instruction & (CP_T_Pre | CP_T_UD)) /* ea/fd format. */
7108 {
7109 int reg;
7110 int write_back;
7111 int offset;
7112
7113 /* The instruction specified "ea" or "fd", so we can only accept
7114 [Rn]{!}. The instruction does not really support stacking or
7115 unstacking, so we have to emulate these by setting appropriate
7116 bits and offsets. */
7117 if (skip_past_comma (&str) == FAIL
7118 || *str != '[')
7119 {
7120 if (! inst.error)
7121 inst.error = BAD_ARGS;
7122 return;
7123 }
7124
7125 str++;
7126 skip_whitespace (str);
7127
7128 if ((reg = reg_required_here (&str, 16)) == FAIL)
7129 return;
7130
7131 skip_whitespace (str);
7132
7133 if (*str != ']')
7134 {
7135 inst.error = BAD_ARGS;
7136 return;
7137 }
7138
7139 str++;
7140 if (*str == '!')
7141 {
7142 write_back = 1;
7143 str++;
7144 if (reg == REG_PC)
7145 {
7146 inst.error =
7147 _("r15 not allowed as base register with write-back");
7148 return;
7149 }
7150 }
7151 else
7152 write_back = 0;
7153
7154 if (inst.instruction & CP_T_Pre)
7155 {
7156 /* Pre-decrement. */
7157 offset = 3 * num_regs;
7158 if (write_back)
7159 inst.instruction |= CP_T_WB;
7160 }
7161 else
7162 {
7163 /* Post-increment. */
7164 if (write_back)
7165 {
7166 inst.instruction |= CP_T_WB;
7167 offset = 3 * num_regs;
7168 }
7169 else
7170 {
7171 /* No write-back, so convert this into a standard pre-increment
7172 instruction -- aesthetically more pleasing. */
7173 inst.instruction |= CP_T_Pre | CP_T_UD;
7174 offset = 0;
7175 }
7176 }
7177
7178 inst.instruction |= offset;
7179 }
7180 else if (skip_past_comma (&str) == FAIL
7181 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
7182 {
7183 if (! inst.error)
7184 inst.error = BAD_ARGS;
7185 return;
7186 }
7187
7188 end_of_line (str);
7189 }
7190
7191 static void
7192 do_fpa_dyadic (char * str)
7193 {
7194 skip_whitespace (str);
7195
7196 if (fp_reg_required_here (&str, 12) == FAIL)
7197 {
7198 if (! inst.error)
7199 inst.error = BAD_ARGS;
7200 return;
7201 }
7202
7203 if (skip_past_comma (&str) == FAIL
7204 || fp_reg_required_here (&str, 16) == FAIL)
7205 {
7206 if (! inst.error)
7207 inst.error = BAD_ARGS;
7208 return;
7209 }
7210
7211 if (skip_past_comma (&str) == FAIL
7212 || fp_op2 (&str) == FAIL)
7213 {
7214 if (! inst.error)
7215 inst.error = BAD_ARGS;
7216 return;
7217 }
7218
7219 end_of_line (str);
7220 }
7221
7222 static void
7223 do_fpa_monadic (char * str)
7224 {
7225 skip_whitespace (str);
7226
7227 if (fp_reg_required_here (&str, 12) == FAIL)
7228 {
7229 if (! inst.error)
7230 inst.error = BAD_ARGS;
7231 return;
7232 }
7233
7234 if (skip_past_comma (&str) == FAIL
7235 || fp_op2 (&str) == FAIL)
7236 {
7237 if (! inst.error)
7238 inst.error = BAD_ARGS;
7239 return;
7240 }
7241
7242 end_of_line (str);
7243 }
7244
7245 static void
7246 do_fpa_cmp (char * str)
7247 {
7248 skip_whitespace (str);
7249
7250 if (fp_reg_required_here (&str, 16) == FAIL)
7251 {
7252 if (! inst.error)
7253 inst.error = BAD_ARGS;
7254 return;
7255 }
7256
7257 if (skip_past_comma (&str) == FAIL
7258 || fp_op2 (&str) == FAIL)
7259 {
7260 if (! inst.error)
7261 inst.error = BAD_ARGS;
7262 return;
7263 }
7264
7265 end_of_line (str);
7266 }
7267
7268 static void
7269 do_fpa_from_reg (char * str)
7270 {
7271 skip_whitespace (str);
7272
7273 if (fp_reg_required_here (&str, 16) == FAIL)
7274 {
7275 if (! inst.error)
7276 inst.error = BAD_ARGS;
7277 return;
7278 }
7279
7280 if (skip_past_comma (&str) == FAIL
7281 || reg_required_here (&str, 12) == FAIL)
7282 {
7283 if (! inst.error)
7284 inst.error = BAD_ARGS;
7285 return;
7286 }
7287
7288 end_of_line (str);
7289 }
7290
7291 static void
7292 do_fpa_to_reg (char * str)
7293 {
7294 skip_whitespace (str);
7295
7296 if (reg_required_here (&str, 12) == FAIL)
7297 return;
7298
7299 if (skip_past_comma (&str) == FAIL
7300 || fp_reg_required_here (&str, 0) == FAIL)
7301 {
7302 if (! inst.error)
7303 inst.error = BAD_ARGS;
7304 return;
7305 }
7306
7307 end_of_line (str);
7308 }
7309
7310 /* Encode a VFP SP register number. */
7311
7312 static void
7313 vfp_sp_encode_reg (int reg, enum vfp_sp_reg_pos pos)
7314 {
7315 switch (pos)
7316 {
7317 case VFP_REG_Sd:
7318 inst.instruction |= ((reg >> 1) << 12) | ((reg & 1) << 22);
7319 break;
7320
7321 case VFP_REG_Sn:
7322 inst.instruction |= ((reg >> 1) << 16) | ((reg & 1) << 7);
7323 break;
7324
7325 case VFP_REG_Sm:
7326 inst.instruction |= ((reg >> 1) << 0) | ((reg & 1) << 5);
7327 break;
7328
7329 default:
7330 abort ();
7331 }
7332 }
7333
7334 static int
7335 vfp_sp_reg_required_here (char ** str,
7336 enum vfp_sp_reg_pos pos)
7337 {
7338 int reg;
7339 char * start = *str;
7340
7341 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_SN].htab)) != FAIL)
7342 {
7343 vfp_sp_encode_reg (reg, pos);
7344 return reg;
7345 }
7346
7347 /* In the few cases where we might be able to accept something else
7348 this error can be overridden. */
7349 inst.error = _(all_reg_maps[REG_TYPE_SN].expected);
7350
7351 /* Restore the start point. */
7352 *str = start;
7353 return FAIL;
7354 }
7355
7356 static int
7357 vfp_dp_reg_required_here (char ** str,
7358 enum vfp_dp_reg_pos pos)
7359 {
7360 int reg;
7361 char * start = *str;
7362
7363 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_DN].htab)) != FAIL)
7364 {
7365 switch (pos)
7366 {
7367 case VFP_REG_Dd:
7368 inst.instruction |= reg << 12;
7369 break;
7370
7371 case VFP_REG_Dn:
7372 inst.instruction |= reg << 16;
7373 break;
7374
7375 case VFP_REG_Dm:
7376 inst.instruction |= reg << 0;
7377 break;
7378
7379 default:
7380 abort ();
7381 }
7382 return reg;
7383 }
7384
7385 /* In the few cases where we might be able to accept something else
7386 this error can be overridden. */
7387 inst.error = _(all_reg_maps[REG_TYPE_DN].expected);
7388
7389 /* Restore the start point. */
7390 *str = start;
7391 return FAIL;
7392 }
7393
7394 static void
7395 do_vfp_sp_monadic (char * str)
7396 {
7397 skip_whitespace (str);
7398
7399 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
7400 return;
7401
7402 if (skip_past_comma (&str) == FAIL
7403 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
7404 {
7405 if (! inst.error)
7406 inst.error = BAD_ARGS;
7407 return;
7408 }
7409
7410 end_of_line (str);
7411 }
7412
7413 static void
7414 do_vfp_dp_monadic (char * str)
7415 {
7416 skip_whitespace (str);
7417
7418 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
7419 return;
7420
7421 if (skip_past_comma (&str) == FAIL
7422 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
7423 {
7424 if (! inst.error)
7425 inst.error = BAD_ARGS;
7426 return;
7427 }
7428
7429 end_of_line (str);
7430 }
7431
7432 static void
7433 do_vfp_sp_dyadic (char * str)
7434 {
7435 skip_whitespace (str);
7436
7437 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
7438 return;
7439
7440 if (skip_past_comma (&str) == FAIL
7441 || vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL
7442 || skip_past_comma (&str) == FAIL
7443 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
7444 {
7445 if (! inst.error)
7446 inst.error = BAD_ARGS;
7447 return;
7448 }
7449
7450 end_of_line (str);
7451 }
7452
7453 static void
7454 do_vfp_dp_dyadic (char * str)
7455 {
7456 skip_whitespace (str);
7457
7458 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
7459 return;
7460
7461 if (skip_past_comma (&str) == FAIL
7462 || vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL
7463 || skip_past_comma (&str) == FAIL
7464 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
7465 {
7466 if (! inst.error)
7467 inst.error = BAD_ARGS;
7468 return;
7469 }
7470
7471 end_of_line (str);
7472 }
7473
7474 static void
7475 do_vfp_reg_from_sp (char * str)
7476 {
7477 skip_whitespace (str);
7478
7479 if (reg_required_here (&str, 12) == FAIL)
7480 return;
7481
7482 if (skip_past_comma (&str) == FAIL
7483 || vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL)
7484 {
7485 if (! inst.error)
7486 inst.error = BAD_ARGS;
7487 return;
7488 }
7489
7490 end_of_line (str);
7491 }
7492
7493 /* Parse a VFP register list. If the string is invalid return FAIL.
7494 Otherwise return the number of registers, and set PBASE to the first
7495 register. Double precision registers are matched if DP is nonzero. */
7496
7497 static int
7498 vfp_parse_reg_list (char **str, int *pbase, int dp)
7499 {
7500 int base_reg;
7501 int new_base;
7502 int regtype;
7503 int max_regs;
7504 int count = 0;
7505 int warned = 0;
7506 unsigned long mask = 0;
7507 int i;
7508
7509 if (**str != '{')
7510 return FAIL;
7511
7512 (*str)++;
7513 skip_whitespace (*str);
7514
7515 if (dp)
7516 {
7517 regtype = REG_TYPE_DN;
7518 max_regs = 16;
7519 }
7520 else
7521 {
7522 regtype = REG_TYPE_SN;
7523 max_regs = 32;
7524 }
7525
7526 base_reg = max_regs;
7527
7528 do
7529 {
7530 new_base = arm_reg_parse (str, all_reg_maps[regtype].htab);
7531 if (new_base == FAIL)
7532 {
7533 inst.error = _(all_reg_maps[regtype].expected);
7534 return FAIL;
7535 }
7536
7537 if (new_base < base_reg)
7538 base_reg = new_base;
7539
7540 if (mask & (1 << new_base))
7541 {
7542 inst.error = _("invalid register list");
7543 return FAIL;
7544 }
7545
7546 if ((mask >> new_base) != 0 && ! warned)
7547 {
7548 as_tsktsk (_("register list not in ascending order"));
7549 warned = 1;
7550 }
7551
7552 mask |= 1 << new_base;
7553 count++;
7554
7555 skip_whitespace (*str);
7556
7557 if (**str == '-') /* We have the start of a range expression */
7558 {
7559 int high_range;
7560
7561 (*str)++;
7562
7563 if ((high_range
7564 = arm_reg_parse (str, all_reg_maps[regtype].htab))
7565 == FAIL)
7566 {
7567 inst.error = _(all_reg_maps[regtype].expected);
7568 return FAIL;
7569 }
7570
7571 if (high_range <= new_base)
7572 {
7573 inst.error = _("register range not in ascending order");
7574 return FAIL;
7575 }
7576
7577 for (new_base++; new_base <= high_range; new_base++)
7578 {
7579 if (mask & (1 << new_base))
7580 {
7581 inst.error = _("invalid register list");
7582 return FAIL;
7583 }
7584
7585 mask |= 1 << new_base;
7586 count++;
7587 }
7588 }
7589 }
7590 while (skip_past_comma (str) != FAIL);
7591
7592 (*str)++;
7593
7594 /* Sanity check -- should have raised a parse error above. */
7595 if (count == 0 || count > max_regs)
7596 abort ();
7597
7598 *pbase = base_reg;
7599
7600 /* Final test -- the registers must be consecutive. */
7601 mask >>= base_reg;
7602 for (i = 0; i < count; i++)
7603 {
7604 if ((mask & (1u << i)) == 0)
7605 {
7606 inst.error = _("non-contiguous register range");
7607 return FAIL;
7608 }
7609 }
7610
7611 return count;
7612 }
7613
7614 static void
7615 do_vfp_reg2_from_sp2 (char * str)
7616 {
7617 int reg;
7618
7619 skip_whitespace (str);
7620
7621 if (reg_required_here (&str, 12) == FAIL
7622 || skip_past_comma (&str) == FAIL
7623 || reg_required_here (&str, 16) == FAIL
7624 || skip_past_comma (&str) == FAIL)
7625 {
7626 if (! inst.error)
7627 inst.error = BAD_ARGS;
7628 return;
7629 }
7630
7631 /* We require exactly two consecutive SP registers. */
7632 if (vfp_parse_reg_list (&str, &reg, 0) != 2)
7633 {
7634 if (! inst.error)
7635 inst.error = _("only two consecutive VFP SP registers allowed here");
7636 }
7637 vfp_sp_encode_reg (reg, VFP_REG_Sm);
7638
7639 end_of_line (str);
7640 }
7641
7642 static void
7643 do_vfp_sp_from_reg (char * str)
7644 {
7645 skip_whitespace (str);
7646
7647 if (vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL)
7648 return;
7649
7650 if (skip_past_comma (&str) == FAIL
7651 || reg_required_here (&str, 12) == FAIL)
7652 {
7653 if (! inst.error)
7654 inst.error = BAD_ARGS;
7655 return;
7656 }
7657
7658 end_of_line (str);
7659 }
7660
7661 static void
7662 do_vfp_sp2_from_reg2 (char * str)
7663 {
7664 int reg;
7665
7666 skip_whitespace (str);
7667
7668 /* We require exactly two consecutive SP registers. */
7669 if (vfp_parse_reg_list (&str, &reg, 0) != 2)
7670 {
7671 if (! inst.error)
7672 inst.error = _("only two consecutive VFP SP registers allowed here");
7673 }
7674 vfp_sp_encode_reg (reg, VFP_REG_Sm);
7675
7676 if (skip_past_comma (&str) == FAIL
7677 || reg_required_here (&str, 12) == FAIL
7678 || skip_past_comma (&str) == FAIL
7679 || reg_required_here (&str, 16) == FAIL)
7680 {
7681 if (! inst.error)
7682 inst.error = BAD_ARGS;
7683 return;
7684 }
7685
7686 end_of_line (str);
7687 }
7688
7689 static void
7690 do_vfp_reg_from_dp (char * str)
7691 {
7692 skip_whitespace (str);
7693
7694 if (reg_required_here (&str, 12) == FAIL)
7695 return;
7696
7697 if (skip_past_comma (&str) == FAIL
7698 || vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL)
7699 {
7700 if (! inst.error)
7701 inst.error = BAD_ARGS;
7702 return;
7703 }
7704
7705 end_of_line (str);
7706 }
7707
7708 static void
7709 do_vfp_reg2_from_dp (char * str)
7710 {
7711 skip_whitespace (str);
7712
7713 if (reg_required_here (&str, 12) == FAIL)
7714 return;
7715
7716 if (skip_past_comma (&str) == FAIL
7717 || reg_required_here (&str, 16) == FAIL
7718 || skip_past_comma (&str) == FAIL
7719 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
7720 {
7721 if (! inst.error)
7722 inst.error = BAD_ARGS;
7723 return;
7724 }
7725
7726 end_of_line (str);
7727 }
7728
7729 static void
7730 do_vfp_dp_from_reg (char * str)
7731 {
7732 skip_whitespace (str);
7733
7734 if (vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL)
7735 return;
7736
7737 if (skip_past_comma (&str) == FAIL
7738 || reg_required_here (&str, 12) == FAIL)
7739 {
7740 if (! inst.error)
7741 inst.error = BAD_ARGS;
7742 return;
7743 }
7744
7745 end_of_line (str);
7746 }
7747
7748 static void
7749 do_vfp_dp_from_reg2 (char * str)
7750 {
7751 skip_whitespace (str);
7752
7753 if (vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
7754 return;
7755
7756 if (skip_past_comma (&str) == FAIL
7757 || reg_required_here (&str, 12) == FAIL
7758 || skip_past_comma (&str) == FAIL
7759 || reg_required_here (&str, 16) == FAIL)
7760 {
7761 if (! inst.error)
7762 inst.error = BAD_ARGS;
7763 return;
7764 }
7765
7766 end_of_line (str);
7767 }
7768
7769 static const struct vfp_reg *
7770 vfp_psr_parse (char ** str)
7771 {
7772 char *start = *str;
7773 char c;
7774 char *p;
7775 const struct vfp_reg *vreg;
7776
7777 p = start;
7778
7779 /* Find the end of the current token. */
7780 do
7781 {
7782 c = *p++;
7783 }
7784 while (ISALPHA (c));
7785
7786 /* Mark it. */
7787 *--p = 0;
7788
7789 for (vreg = vfp_regs + 0;
7790 vreg < vfp_regs + sizeof (vfp_regs) / sizeof (struct vfp_reg);
7791 vreg++)
7792 {
7793 if (streq (start, vreg->name))
7794 {
7795 *p = c;
7796 *str = p;
7797 return vreg;
7798 }
7799 }
7800
7801 *p = c;
7802 return NULL;
7803 }
7804
7805 static int
7806 vfp_psr_required_here (char ** str)
7807 {
7808 char *start = *str;
7809 const struct vfp_reg *vreg;
7810
7811 vreg = vfp_psr_parse (str);
7812
7813 if (vreg)
7814 {
7815 inst.instruction |= vreg->regno;
7816 return SUCCESS;
7817 }
7818
7819 inst.error = _("VFP system register expected");
7820
7821 *str = start;
7822 return FAIL;
7823 }
7824
7825 static void
7826 do_vfp_reg_from_ctrl (char * str)
7827 {
7828 skip_whitespace (str);
7829
7830 if (reg_required_here (&str, 12) == FAIL)
7831 return;
7832
7833 if (skip_past_comma (&str) == FAIL
7834 || vfp_psr_required_here (&str) == FAIL)
7835 {
7836 if (! inst.error)
7837 inst.error = BAD_ARGS;
7838 return;
7839 }
7840
7841 end_of_line (str);
7842 }
7843
7844 static void
7845 do_vfp_ctrl_from_reg (char * str)
7846 {
7847 skip_whitespace (str);
7848
7849 if (vfp_psr_required_here (&str) == FAIL)
7850 return;
7851
7852 if (skip_past_comma (&str) == FAIL
7853 || reg_required_here (&str, 12) == FAIL)
7854 {
7855 if (! inst.error)
7856 inst.error = BAD_ARGS;
7857 return;
7858 }
7859
7860 end_of_line (str);
7861 }
7862
7863 static void
7864 do_vfp_sp_ldst (char * str)
7865 {
7866 skip_whitespace (str);
7867
7868 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
7869 {
7870 if (!inst.error)
7871 inst.error = BAD_ARGS;
7872 return;
7873 }
7874
7875 if (skip_past_comma (&str) == FAIL
7876 || cp_address_required_here (&str, CP_NO_WB) == FAIL)
7877 {
7878 if (!inst.error)
7879 inst.error = BAD_ARGS;
7880 return;
7881 }
7882
7883 end_of_line (str);
7884 }
7885
7886 static void
7887 do_vfp_dp_ldst (char * str)
7888 {
7889 skip_whitespace (str);
7890
7891 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
7892 {
7893 if (!inst.error)
7894 inst.error = BAD_ARGS;
7895 return;
7896 }
7897
7898 if (skip_past_comma (&str) == FAIL
7899 || cp_address_required_here (&str, CP_NO_WB) == FAIL)
7900 {
7901 if (!inst.error)
7902 inst.error = BAD_ARGS;
7903 return;
7904 }
7905
7906 end_of_line (str);
7907 }
7908
7909
7910 static void
7911 vfp_sp_ldstm (char * str, enum vfp_ldstm_type ldstm_type)
7912 {
7913 int count;
7914 int reg;
7915
7916 skip_whitespace (str);
7917
7918 if (reg_required_here (&str, 16) == FAIL)
7919 return;
7920
7921 skip_whitespace (str);
7922
7923 if (*str == '!')
7924 {
7925 inst.instruction |= WRITE_BACK;
7926 str++;
7927 }
7928 else if (ldstm_type != VFP_LDSTMIA)
7929 {
7930 inst.error = _("this addressing mode requires base-register writeback");
7931 return;
7932 }
7933
7934 if (skip_past_comma (&str) == FAIL
7935 || (count = vfp_parse_reg_list (&str, &reg, 0)) == FAIL)
7936 {
7937 if (!inst.error)
7938 inst.error = BAD_ARGS;
7939 return;
7940 }
7941 vfp_sp_encode_reg (reg, VFP_REG_Sd);
7942
7943 inst.instruction |= count;
7944 end_of_line (str);
7945 }
7946
7947 static void
7948 vfp_dp_ldstm (char * str, enum vfp_ldstm_type ldstm_type)
7949 {
7950 int count;
7951 int reg;
7952
7953 skip_whitespace (str);
7954
7955 if (reg_required_here (&str, 16) == FAIL)
7956 return;
7957
7958 skip_whitespace (str);
7959
7960 if (*str == '!')
7961 {
7962 inst.instruction |= WRITE_BACK;
7963 str++;
7964 }
7965 else if (ldstm_type != VFP_LDSTMIA && ldstm_type != VFP_LDSTMIAX)
7966 {
7967 inst.error = _("this addressing mode requires base-register writeback");
7968 return;
7969 }
7970
7971 if (skip_past_comma (&str) == FAIL
7972 || (count = vfp_parse_reg_list (&str, &reg, 1)) == FAIL)
7973 {
7974 if (!inst.error)
7975 inst.error = BAD_ARGS;
7976 return;
7977 }
7978
7979 count <<= 1;
7980 if (ldstm_type == VFP_LDSTMIAX || ldstm_type == VFP_LDSTMDBX)
7981 count += 1;
7982
7983 inst.instruction |= (reg << 12) | count;
7984 end_of_line (str);
7985 }
7986
7987 static void
7988 do_vfp_sp_ldstmia (char * str)
7989 {
7990 vfp_sp_ldstm (str, VFP_LDSTMIA);
7991 }
7992
7993 static void
7994 do_vfp_sp_ldstmdb (char * str)
7995 {
7996 vfp_sp_ldstm (str, VFP_LDSTMDB);
7997 }
7998
7999 static void
8000 do_vfp_dp_ldstmia (char * str)
8001 {
8002 vfp_dp_ldstm (str, VFP_LDSTMIA);
8003 }
8004
8005 static void
8006 do_vfp_dp_ldstmdb (char * str)
8007 {
8008 vfp_dp_ldstm (str, VFP_LDSTMDB);
8009 }
8010
8011 static void
8012 do_vfp_xp_ldstmia (char *str)
8013 {
8014 vfp_dp_ldstm (str, VFP_LDSTMIAX);
8015 }
8016
8017 static void
8018 do_vfp_xp_ldstmdb (char * str)
8019 {
8020 vfp_dp_ldstm (str, VFP_LDSTMDBX);
8021 }
8022
8023 static void
8024 do_vfp_sp_compare_z (char * str)
8025 {
8026 skip_whitespace (str);
8027
8028 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
8029 {
8030 if (!inst.error)
8031 inst.error = BAD_ARGS;
8032 return;
8033 }
8034
8035 end_of_line (str);
8036 }
8037
8038 static void
8039 do_vfp_dp_compare_z (char * str)
8040 {
8041 skip_whitespace (str);
8042
8043 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
8044 {
8045 if (!inst.error)
8046 inst.error = BAD_ARGS;
8047 return;
8048 }
8049
8050 end_of_line (str);
8051 }
8052
8053 static void
8054 do_vfp_dp_sp_cvt (char * str)
8055 {
8056 skip_whitespace (str);
8057
8058 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
8059 return;
8060
8061 if (skip_past_comma (&str) == FAIL
8062 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
8063 {
8064 if (! inst.error)
8065 inst.error = BAD_ARGS;
8066 return;
8067 }
8068
8069 end_of_line (str);
8070 }
8071
8072 static void
8073 do_vfp_sp_dp_cvt (char * str)
8074 {
8075 skip_whitespace (str);
8076
8077 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
8078 return;
8079
8080 if (skip_past_comma (&str) == FAIL
8081 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
8082 {
8083 if (! inst.error)
8084 inst.error = BAD_ARGS;
8085 return;
8086 }
8087
8088 end_of_line (str);
8089 }
8090
8091 /* Thumb specific routines. */
8092
8093 /* Parse an add or subtract instruction, SUBTRACT is non-zero if the opcode
8094 was SUB. */
8095
8096 static void
8097 thumb_add_sub (char * str, int subtract)
8098 {
8099 int Rd, Rs, Rn = FAIL;
8100
8101 skip_whitespace (str);
8102
8103 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
8104 || skip_past_comma (&str) == FAIL)
8105 {
8106 if (! inst.error)
8107 inst.error = BAD_ARGS;
8108 return;
8109 }
8110
8111 if (is_immediate_prefix (*str))
8112 {
8113 Rs = Rd;
8114 str++;
8115 if (my_get_expression (&inst.reloc.exp, &str))
8116 return;
8117 }
8118 else
8119 {
8120 if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
8121 return;
8122
8123 if (skip_past_comma (&str) == FAIL)
8124 {
8125 /* Two operand format, shuffle the registers
8126 and pretend there are 3. */
8127 Rn = Rs;
8128 Rs = Rd;
8129 }
8130 else if (is_immediate_prefix (*str))
8131 {
8132 str++;
8133 if (my_get_expression (&inst.reloc.exp, &str))
8134 return;
8135 }
8136 else if ((Rn = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
8137 return;
8138 }
8139
8140 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
8141 for the latter case, EXPR contains the immediate that was found. */
8142 if (Rn != FAIL)
8143 {
8144 /* All register format. */
8145 if (Rd > 7 || Rs > 7 || Rn > 7)
8146 {
8147 if (Rs != Rd)
8148 {
8149 inst.error = _("dest and source1 must be the same register");
8150 return;
8151 }
8152
8153 /* Can't do this for SUB. */
8154 if (subtract)
8155 {
8156 inst.error = _("subtract valid only on lo regs");
8157 return;
8158 }
8159
8160 inst.instruction = (T_OPCODE_ADD_HI
8161 | (Rd > 7 ? THUMB_H1 : 0)
8162 | (Rn > 7 ? THUMB_H2 : 0));
8163 inst.instruction |= (Rd & 7) | ((Rn & 7) << 3);
8164 }
8165 else
8166 {
8167 inst.instruction = subtract ? T_OPCODE_SUB_R3 : T_OPCODE_ADD_R3;
8168 inst.instruction |= Rd | (Rs << 3) | (Rn << 6);
8169 }
8170 }
8171 else
8172 {
8173 /* Immediate expression, now things start to get nasty. */
8174
8175 /* First deal with HI regs, only very restricted cases allowed:
8176 Adjusting SP, and using PC or SP to get an address. */
8177 if ((Rd > 7 && (Rd != REG_SP || Rs != REG_SP))
8178 || (Rs > 7 && Rs != REG_SP && Rs != REG_PC))
8179 {
8180 inst.error = _("invalid Hi register with immediate");
8181 return;
8182 }
8183
8184 if (inst.reloc.exp.X_op != O_constant)
8185 {
8186 /* Value isn't known yet, all we can do is store all the fragments
8187 we know about in the instruction and let the reloc hacking
8188 work it all out. */
8189 inst.instruction = (subtract ? 0x8000 : 0) | (Rd << 4) | Rs;
8190 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
8191 }
8192 else
8193 {
8194 int offset = inst.reloc.exp.X_add_number;
8195
8196 if (subtract)
8197 offset = - offset;
8198
8199 if (offset < 0)
8200 {
8201 offset = - offset;
8202 subtract = 1;
8203
8204 /* Quick check, in case offset is MIN_INT. */
8205 if (offset < 0)
8206 {
8207 inst.error = _("immediate value out of range");
8208 return;
8209 }
8210 }
8211 /* Note - you cannot convert a subtract of 0 into an
8212 add of 0 because the carry flag is set differently. */
8213 else if (offset > 0)
8214 subtract = 0;
8215
8216 if (Rd == REG_SP)
8217 {
8218 if (offset & ~0x1fc)
8219 {
8220 inst.error = _("invalid immediate value for stack adjust");
8221 return;
8222 }
8223 inst.instruction = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
8224 inst.instruction |= offset >> 2;
8225 }
8226 else if (Rs == REG_PC || Rs == REG_SP)
8227 {
8228 if (subtract
8229 || (offset & ~0x3fc))
8230 {
8231 inst.error = _("invalid immediate for address calculation");
8232 return;
8233 }
8234 inst.instruction = (Rs == REG_PC ? T_OPCODE_ADD_PC
8235 : T_OPCODE_ADD_SP);
8236 inst.instruction |= (Rd << 8) | (offset >> 2);
8237 }
8238 else if (Rs == Rd)
8239 {
8240 if (offset & ~0xff)
8241 {
8242 inst.error = _("immediate value out of range");
8243 return;
8244 }
8245 inst.instruction = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
8246 inst.instruction |= (Rd << 8) | offset;
8247 }
8248 else
8249 {
8250 if (offset & ~0x7)
8251 {
8252 inst.error = _("immediate value out of range");
8253 return;
8254 }
8255 inst.instruction = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
8256 inst.instruction |= Rd | (Rs << 3) | (offset << 6);
8257 }
8258 }
8259 }
8260
8261 end_of_line (str);
8262 }
8263
8264 static void
8265 thumb_shift (char * str, int shift)
8266 {
8267 int Rd, Rs, Rn = FAIL;
8268
8269 skip_whitespace (str);
8270
8271 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
8272 || skip_past_comma (&str) == FAIL)
8273 {
8274 if (! inst.error)
8275 inst.error = BAD_ARGS;
8276 return;
8277 }
8278
8279 if (is_immediate_prefix (*str))
8280 {
8281 /* Two operand immediate format, set Rs to Rd. */
8282 Rs = Rd;
8283 str ++;
8284 if (my_get_expression (&inst.reloc.exp, &str))
8285 return;
8286 }
8287 else
8288 {
8289 if ((Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
8290 return;
8291
8292 if (skip_past_comma (&str) == FAIL)
8293 {
8294 /* Two operand format, shuffle the registers
8295 and pretend there are 3. */
8296 Rn = Rs;
8297 Rs = Rd;
8298 }
8299 else if (is_immediate_prefix (*str))
8300 {
8301 str++;
8302 if (my_get_expression (&inst.reloc.exp, &str))
8303 return;
8304 }
8305 else if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
8306 return;
8307 }
8308
8309 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
8310 for the latter case, EXPR contains the immediate that was found. */
8311
8312 if (Rn != FAIL)
8313 {
8314 if (Rs != Rd)
8315 {
8316 inst.error = _("source1 and dest must be same register");
8317 return;
8318 }
8319
8320 switch (shift)
8321 {
8322 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_R; break;
8323 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_R; break;
8324 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_R; break;
8325 }
8326
8327 inst.instruction |= Rd | (Rn << 3);
8328 }
8329 else
8330 {
8331 switch (shift)
8332 {
8333 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_I; break;
8334 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_I; break;
8335 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_I; break;
8336 }
8337
8338 if (inst.reloc.exp.X_op != O_constant)
8339 {
8340 /* Value isn't known yet, create a dummy reloc and let reloc
8341 hacking fix it up. */
8342 inst.reloc.type = BFD_RELOC_ARM_THUMB_SHIFT;
8343 }
8344 else
8345 {
8346 unsigned shift_value = inst.reloc.exp.X_add_number;
8347
8348 if (shift_value > 32 || (shift_value == 32 && shift == THUMB_LSL))
8349 {
8350 inst.error = _("invalid immediate for shift");
8351 return;
8352 }
8353
8354 /* Shifts of zero are handled by converting to LSL. */
8355 if (shift_value == 0)
8356 inst.instruction = T_OPCODE_LSL_I;
8357
8358 /* Shifts of 32 are encoded as a shift of zero. */
8359 if (shift_value == 32)
8360 shift_value = 0;
8361
8362 inst.instruction |= shift_value << 6;
8363 }
8364
8365 inst.instruction |= Rd | (Rs << 3);
8366 }
8367
8368 end_of_line (str);
8369 }
8370
8371 static void
8372 thumb_load_store (char * str, int load_store, int size)
8373 {
8374 int Rd, Rb, Ro = FAIL;
8375
8376 skip_whitespace (str);
8377
8378 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
8379 || skip_past_comma (&str) == FAIL)
8380 {
8381 if (! inst.error)
8382 inst.error = BAD_ARGS;
8383 return;
8384 }
8385
8386 if (*str == '[')
8387 {
8388 str++;
8389 if ((Rb = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
8390 return;
8391
8392 if (skip_past_comma (&str) != FAIL)
8393 {
8394 if (is_immediate_prefix (*str))
8395 {
8396 str++;
8397 if (my_get_expression (&inst.reloc.exp, &str))
8398 return;
8399 }
8400 else if ((Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
8401 return;
8402 }
8403 else
8404 {
8405 inst.reloc.exp.X_op = O_constant;
8406 inst.reloc.exp.X_add_number = 0;
8407 }
8408
8409 if (*str != ']')
8410 {
8411 inst.error = _("expected ']'");
8412 return;
8413 }
8414 str++;
8415 }
8416 else if (*str == '=')
8417 {
8418 if (load_store != THUMB_LOAD)
8419 {
8420 inst.error = _("invalid pseudo operation");
8421 return;
8422 }
8423
8424 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
8425 str++;
8426
8427 skip_whitespace (str);
8428
8429 if (my_get_expression (& inst.reloc.exp, & str))
8430 return;
8431
8432 end_of_line (str);
8433
8434 if ( inst.reloc.exp.X_op != O_constant
8435 && inst.reloc.exp.X_op != O_symbol)
8436 {
8437 inst.error = "Constant expression expected";
8438 return;
8439 }
8440
8441 if (inst.reloc.exp.X_op == O_constant
8442 && ((inst.reloc.exp.X_add_number & ~0xFF) == 0))
8443 {
8444 /* This can be done with a mov instruction. */
8445
8446 inst.instruction = T_OPCODE_MOV_I8 | (Rd << 8);
8447 inst.instruction |= inst.reloc.exp.X_add_number;
8448 return;
8449 }
8450
8451 /* Insert into literal pool. */
8452 if (add_to_lit_pool () == FAIL)
8453 {
8454 if (!inst.error)
8455 inst.error = "literal pool insertion failed";
8456 return;
8457 }
8458
8459 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
8460 inst.reloc.pc_rel = 1;
8461 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
8462 /* Adjust ARM pipeline offset to Thumb. */
8463 inst.reloc.exp.X_add_number += 4;
8464
8465 return;
8466 }
8467 else
8468 {
8469 if (my_get_expression (&inst.reloc.exp, &str))
8470 return;
8471
8472 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
8473 inst.reloc.pc_rel = 1;
8474 inst.reloc.exp.X_add_number -= 4; /* Pipeline offset. */
8475 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
8476 end_of_line (str);
8477 return;
8478 }
8479
8480 if (Rb == REG_PC || Rb == REG_SP)
8481 {
8482 if (size != THUMB_WORD)
8483 {
8484 inst.error = _("byte or halfword not valid for base register");
8485 return;
8486 }
8487 else if (Rb == REG_PC && load_store != THUMB_LOAD)
8488 {
8489 inst.error = _("r15 based store not allowed");
8490 return;
8491 }
8492 else if (Ro != FAIL)
8493 {
8494 inst.error = _("invalid base register for register offset");
8495 return;
8496 }
8497
8498 if (Rb == REG_PC)
8499 inst.instruction = T_OPCODE_LDR_PC;
8500 else if (load_store == THUMB_LOAD)
8501 inst.instruction = T_OPCODE_LDR_SP;
8502 else
8503 inst.instruction = T_OPCODE_STR_SP;
8504
8505 inst.instruction |= Rd << 8;
8506 if (inst.reloc.exp.X_op == O_constant)
8507 {
8508 unsigned offset = inst.reloc.exp.X_add_number;
8509
8510 if (offset & ~0x3fc)
8511 {
8512 inst.error = _("invalid offset");
8513 return;
8514 }
8515
8516 inst.instruction |= offset >> 2;
8517 }
8518 else
8519 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
8520 }
8521 else if (Rb > 7)
8522 {
8523 inst.error = _("invalid base register in load/store");
8524 return;
8525 }
8526 else if (Ro == FAIL)
8527 {
8528 /* Immediate offset. */
8529 if (size == THUMB_WORD)
8530 inst.instruction = (load_store == THUMB_LOAD
8531 ? T_OPCODE_LDR_IW : T_OPCODE_STR_IW);
8532 else if (size == THUMB_HALFWORD)
8533 inst.instruction = (load_store == THUMB_LOAD
8534 ? T_OPCODE_LDR_IH : T_OPCODE_STR_IH);
8535 else
8536 inst.instruction = (load_store == THUMB_LOAD
8537 ? T_OPCODE_LDR_IB : T_OPCODE_STR_IB);
8538
8539 inst.instruction |= Rd | (Rb << 3);
8540
8541 if (inst.reloc.exp.X_op == O_constant)
8542 {
8543 unsigned offset = inst.reloc.exp.X_add_number;
8544
8545 if (offset & ~(0x1f << size))
8546 {
8547 inst.error = _("invalid offset");
8548 return;
8549 }
8550 inst.instruction |= (offset >> size) << 6;
8551 }
8552 else
8553 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
8554 }
8555 else
8556 {
8557 /* Register offset. */
8558 if (size == THUMB_WORD)
8559 inst.instruction = (load_store == THUMB_LOAD
8560 ? T_OPCODE_LDR_RW : T_OPCODE_STR_RW);
8561 else if (size == THUMB_HALFWORD)
8562 inst.instruction = (load_store == THUMB_LOAD
8563 ? T_OPCODE_LDR_RH : T_OPCODE_STR_RH);
8564 else
8565 inst.instruction = (load_store == THUMB_LOAD
8566 ? T_OPCODE_LDR_RB : T_OPCODE_STR_RB);
8567
8568 inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
8569 }
8570
8571 end_of_line (str);
8572 }
8573
8574 /* A register must be given at this point.
8575
8576 Shift is the place to put it in inst.instruction.
8577
8578 Restores input start point on err.
8579 Returns the reg#, or FAIL. */
8580
8581 static int
8582 mav_reg_required_here (char ** str, int shift, enum arm_reg_type regtype)
8583 {
8584 int reg;
8585 char *start = *str;
8586
8587 if ((reg = arm_reg_parse (str, all_reg_maps[regtype].htab)) != FAIL)
8588 {
8589 if (shift >= 0)
8590 inst.instruction |= reg << shift;
8591
8592 return reg;
8593 }
8594
8595 /* Restore the start point. */
8596 *str = start;
8597
8598 /* Try generic coprocessor name if applicable. */
8599 if (regtype == REG_TYPE_MVF ||
8600 regtype == REG_TYPE_MVD ||
8601 regtype == REG_TYPE_MVFX ||
8602 regtype == REG_TYPE_MVDX)
8603 {
8604 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_CN].htab)) != FAIL)
8605 {
8606 if (shift >= 0)
8607 inst.instruction |= reg << shift;
8608
8609 return reg;
8610 }
8611
8612 /* Restore the start point. */
8613 *str = start;
8614 }
8615
8616 /* In the few cases where we might be able to accept something else
8617 this error can be overridden. */
8618 inst.error = _(all_reg_maps[regtype].expected);
8619
8620 return FAIL;
8621 }
8622
8623 /* Cirrus Maverick Instructions. */
8624
8625 /* Isnsn like "foo X,Y". */
8626
8627 static void
8628 do_mav_binops (char * str,
8629 int mode,
8630 enum arm_reg_type reg0,
8631 enum arm_reg_type reg1)
8632 {
8633 int shift0, shift1;
8634
8635 shift0 = mode & 0xff;
8636 shift1 = (mode >> 8) & 0xff;
8637
8638 skip_whitespace (str);
8639
8640 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
8641 || skip_past_comma (&str) == FAIL
8642 || mav_reg_required_here (&str, shift1, reg1) == FAIL)
8643 {
8644 if (!inst.error)
8645 inst.error = BAD_ARGS;
8646 }
8647 else
8648 end_of_line (str);
8649 }
8650
8651 /* Isnsn like "foo X,Y,Z". */
8652
8653 static void
8654 do_mav_triple (char * str,
8655 int mode,
8656 enum arm_reg_type reg0,
8657 enum arm_reg_type reg1,
8658 enum arm_reg_type reg2)
8659 {
8660 int shift0, shift1, shift2;
8661
8662 shift0 = mode & 0xff;
8663 shift1 = (mode >> 8) & 0xff;
8664 shift2 = (mode >> 16) & 0xff;
8665
8666 skip_whitespace (str);
8667
8668 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
8669 || skip_past_comma (&str) == FAIL
8670 || mav_reg_required_here (&str, shift1, reg1) == FAIL
8671 || skip_past_comma (&str) == FAIL
8672 || mav_reg_required_here (&str, shift2, reg2) == FAIL)
8673 {
8674 if (!inst.error)
8675 inst.error = BAD_ARGS;
8676 }
8677 else
8678 end_of_line (str);
8679 }
8680
8681 /* Wrapper functions. */
8682
8683 static void
8684 do_mav_binops_1a (char * str)
8685 {
8686 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVF);
8687 }
8688
8689 static void
8690 do_mav_binops_1b (char * str)
8691 {
8692 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVD);
8693 }
8694
8695 static void
8696 do_mav_binops_1c (char * str)
8697 {
8698 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVDX);
8699 }
8700
8701 static void
8702 do_mav_binops_1d (char * str)
8703 {
8704 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVF);
8705 }
8706
8707 static void
8708 do_mav_binops_1e (char * str)
8709 {
8710 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVD);
8711 }
8712
8713 static void
8714 do_mav_binops_1f (char * str)
8715 {
8716 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVF);
8717 }
8718
8719 static void
8720 do_mav_binops_1g (char * str)
8721 {
8722 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVD);
8723 }
8724
8725 static void
8726 do_mav_binops_1h (char * str)
8727 {
8728 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVFX);
8729 }
8730
8731 static void
8732 do_mav_binops_1i (char * str)
8733 {
8734 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVFX);
8735 }
8736
8737 static void
8738 do_mav_binops_1j (char * str)
8739 {
8740 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVDX);
8741 }
8742
8743 static void
8744 do_mav_binops_1k (char * str)
8745 {
8746 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVDX);
8747 }
8748
8749 static void
8750 do_mav_binops_1l (char * str)
8751 {
8752 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVF);
8753 }
8754
8755 static void
8756 do_mav_binops_1m (char * str)
8757 {
8758 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVD);
8759 }
8760
8761 static void
8762 do_mav_binops_1n (char * str)
8763 {
8764 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVFX);
8765 }
8766
8767 static void
8768 do_mav_binops_1o (char * str)
8769 {
8770 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVDX, REG_TYPE_MVDX);
8771 }
8772
8773 static void
8774 do_mav_binops_2a (char * str)
8775 {
8776 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVF, REG_TYPE_RN);
8777 }
8778
8779 static void
8780 do_mav_binops_2b (char * str)
8781 {
8782 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVD, REG_TYPE_RN);
8783 }
8784
8785 static void
8786 do_mav_binops_2c (char * str)
8787 {
8788 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVDX, REG_TYPE_RN);
8789 }
8790
8791 static void
8792 do_mav_binops_3a (char * str)
8793 {
8794 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVAX, REG_TYPE_MVFX);
8795 }
8796
8797 static void
8798 do_mav_binops_3b (char * str)
8799 {
8800 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVFX, REG_TYPE_MVAX);
8801 }
8802
8803 static void
8804 do_mav_binops_3c (char * str)
8805 {
8806 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVAX, REG_TYPE_MVDX);
8807 }
8808
8809 static void
8810 do_mav_binops_3d (char * str)
8811 {
8812 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVDX, REG_TYPE_MVAX);
8813 }
8814
8815 static void
8816 do_mav_triple_4a (char * str)
8817 {
8818 do_mav_triple (str, MAV_MODE4, REG_TYPE_MVFX, REG_TYPE_MVFX, REG_TYPE_RN);
8819 }
8820
8821 static void
8822 do_mav_triple_4b (char * str)
8823 {
8824 do_mav_triple (str, MAV_MODE4, REG_TYPE_MVDX, REG_TYPE_MVDX, REG_TYPE_RN);
8825 }
8826
8827 static void
8828 do_mav_triple_5a (char * str)
8829 {
8830 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVF, REG_TYPE_MVF);
8831 }
8832
8833 static void
8834 do_mav_triple_5b (char * str)
8835 {
8836 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVD, REG_TYPE_MVD);
8837 }
8838
8839 static void
8840 do_mav_triple_5c (char * str)
8841 {
8842 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVFX, REG_TYPE_MVFX);
8843 }
8844
8845 static void
8846 do_mav_triple_5d (char * str)
8847 {
8848 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVDX, REG_TYPE_MVDX);
8849 }
8850
8851 static void
8852 do_mav_triple_5e (char * str)
8853 {
8854 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVF, REG_TYPE_MVF, REG_TYPE_MVF);
8855 }
8856
8857 static void
8858 do_mav_triple_5f (char * str)
8859 {
8860 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVD, REG_TYPE_MVD, REG_TYPE_MVD);
8861 }
8862
8863 static void
8864 do_mav_triple_5g (char * str)
8865 {
8866 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVFX, REG_TYPE_MVFX, REG_TYPE_MVFX);
8867 }
8868
8869 static void
8870 do_mav_triple_5h (char * str)
8871 {
8872 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVDX, REG_TYPE_MVDX, REG_TYPE_MVDX);
8873 }
8874
8875 /* Isnsn like "foo W,X,Y,Z".
8876 where W=MVAX[0:3] and X,Y,Z=MVFX[0:15]. */
8877
8878 static void
8879 do_mav_quad (char * str,
8880 int mode,
8881 enum arm_reg_type reg0,
8882 enum arm_reg_type reg1,
8883 enum arm_reg_type reg2,
8884 enum arm_reg_type reg3)
8885 {
8886 int shift0, shift1, shift2, shift3;
8887
8888 shift0= mode & 0xff;
8889 shift1 = (mode >> 8) & 0xff;
8890 shift2 = (mode >> 16) & 0xff;
8891 shift3 = (mode >> 24) & 0xff;
8892
8893 skip_whitespace (str);
8894
8895 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
8896 || skip_past_comma (&str) == FAIL
8897 || mav_reg_required_here (&str, shift1, reg1) == FAIL
8898 || skip_past_comma (&str) == FAIL
8899 || mav_reg_required_here (&str, shift2, reg2) == FAIL
8900 || skip_past_comma (&str) == FAIL
8901 || mav_reg_required_here (&str, shift3, reg3) == FAIL)
8902 {
8903 if (!inst.error)
8904 inst.error = BAD_ARGS;
8905 }
8906 else
8907 end_of_line (str);
8908 }
8909
8910 static void
8911 do_mav_quad_6a (char * str)
8912 {
8913 do_mav_quad (str, MAV_MODE6, REG_TYPE_MVAX, REG_TYPE_MVFX, REG_TYPE_MVFX,
8914 REG_TYPE_MVFX);
8915 }
8916
8917 static void
8918 do_mav_quad_6b (char * str)
8919 {
8920 do_mav_quad (str, MAV_MODE6, REG_TYPE_MVAX, REG_TYPE_MVAX, REG_TYPE_MVFX,
8921 REG_TYPE_MVFX);
8922 }
8923
8924 /* cfmvsc32<cond> DSPSC,MVDX[15:0]. */
8925 static void
8926 do_mav_dspsc_1 (char * str)
8927 {
8928 skip_whitespace (str);
8929
8930 /* cfmvsc32. */
8931 if (mav_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL
8932 || skip_past_comma (&str) == FAIL
8933 || mav_reg_required_here (&str, 12, REG_TYPE_MVDX) == FAIL)
8934 {
8935 if (!inst.error)
8936 inst.error = BAD_ARGS;
8937
8938 return;
8939 }
8940
8941 end_of_line (str);
8942 }
8943
8944 /* cfmv32sc<cond> MVDX[15:0],DSPSC. */
8945 static void
8946 do_mav_dspsc_2 (char * str)
8947 {
8948 skip_whitespace (str);
8949
8950 /* cfmv32sc. */
8951 if (mav_reg_required_here (&str, 12, REG_TYPE_MVDX) == FAIL
8952 || skip_past_comma (&str) == FAIL
8953 || mav_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL)
8954 {
8955 if (!inst.error)
8956 inst.error = BAD_ARGS;
8957
8958 return;
8959 }
8960
8961 end_of_line (str);
8962 }
8963
8964 /* Maverick shift immediate instructions.
8965 cfsh32<cond> MVFX[15:0],MVFX[15:0],Shift[6:0].
8966 cfsh64<cond> MVDX[15:0],MVDX[15:0],Shift[6:0]. */
8967
8968 static void
8969 do_mav_shift (char * str,
8970 enum arm_reg_type reg0,
8971 enum arm_reg_type reg1)
8972 {
8973 int error;
8974 int imm, neg = 0;
8975
8976 skip_whitespace (str);
8977
8978 error = 0;
8979
8980 if (mav_reg_required_here (&str, 12, reg0) == FAIL
8981 || skip_past_comma (&str) == FAIL
8982 || mav_reg_required_here (&str, 16, reg1) == FAIL
8983 || skip_past_comma (&str) == FAIL)
8984 {
8985 if (!inst.error)
8986 inst.error = BAD_ARGS;
8987 return;
8988 }
8989
8990 /* Calculate the immediate operand.
8991 The operand is a 7bit signed number. */
8992 skip_whitespace (str);
8993
8994 if (*str == '#')
8995 ++str;
8996
8997 if (!ISDIGIT (*str) && *str != '-')
8998 {
8999 inst.error = _("expecting immediate, 7bit operand");
9000 return;
9001 }
9002
9003 if (*str == '-')
9004 {
9005 neg = 1;
9006 ++str;
9007 }
9008
9009 for (imm = 0; *str && ISDIGIT (*str); ++str)
9010 imm = imm * 10 + *str - '0';
9011
9012 if (imm > 64)
9013 {
9014 inst.error = _("immediate out of range");
9015 return;
9016 }
9017
9018 /* Make negative imm's into 7bit signed numbers. */
9019 if (neg)
9020 {
9021 imm = -imm;
9022 imm &= 0x0000007f;
9023 }
9024
9025 /* Bits 0-3 of the insn should have bits 0-3 of the immediate.
9026 Bits 5-7 of the insn should have bits 4-6 of the immediate.
9027 Bit 4 should be 0. */
9028 imm = (imm & 0xf) | ((imm & 0x70) << 1);
9029
9030 inst.instruction |= imm;
9031 end_of_line (str);
9032 }
9033
9034 static void
9035 do_mav_shift_1 (char * str)
9036 {
9037 do_mav_shift (str, REG_TYPE_MVFX, REG_TYPE_MVFX);
9038 }
9039
9040 static void
9041 do_mav_shift_2 (char * str)
9042 {
9043 do_mav_shift (str, REG_TYPE_MVDX, REG_TYPE_MVDX);
9044 }
9045
9046 static int
9047 mav_parse_offset (char ** str, int * negative)
9048 {
9049 char * p = *str;
9050 int offset;
9051
9052 *negative = 0;
9053
9054 skip_whitespace (p);
9055
9056 if (*p == '#')
9057 ++p;
9058
9059 if (*p == '-')
9060 {
9061 *negative = 1;
9062 ++p;
9063 }
9064
9065 if (!ISDIGIT (*p))
9066 {
9067 inst.error = _("offset expected");
9068 return 0;
9069 }
9070
9071 for (offset = 0; *p && ISDIGIT (*p); ++p)
9072 offset = offset * 10 + *p - '0';
9073
9074 if (offset > 0x3fc)
9075 {
9076 inst.error = _("offset out of range");
9077 return 0;
9078 }
9079 if (offset & 0x3)
9080 {
9081 inst.error = _("offset not a multiple of 4");
9082 return 0;
9083 }
9084
9085 *str = p;
9086
9087 return *negative ? -offset : offset;
9088 }
9089
9090 /* Maverick load/store instructions.
9091 <insn><cond> CRd,[Rn,<offset>]{!}.
9092 <insn><cond> CRd,[Rn],<offset>. */
9093
9094 static void
9095 do_mav_ldst (char * str, enum arm_reg_type reg0)
9096 {
9097 int offset, negative;
9098
9099 skip_whitespace (str);
9100
9101 if (mav_reg_required_here (&str, 12, reg0) == FAIL
9102 || skip_past_comma (&str) == FAIL
9103 || *str++ != '['
9104 || reg_required_here (&str, 16) == FAIL)
9105 goto fail_ldst;
9106
9107 if (skip_past_comma (&str) == SUCCESS)
9108 {
9109 /* You are here: "<offset>]{!}". */
9110 inst.instruction |= PRE_INDEX;
9111
9112 offset = mav_parse_offset (&str, &negative);
9113
9114 if (inst.error)
9115 return;
9116
9117 if (*str++ != ']')
9118 {
9119 inst.error = _("missing ]");
9120 return;
9121 }
9122
9123 if (*str == '!')
9124 {
9125 inst.instruction |= WRITE_BACK;
9126 ++str;
9127 }
9128 }
9129 else
9130 {
9131 /* You are here: "], <offset>". */
9132 if (*str++ != ']')
9133 {
9134 inst.error = _("missing ]");
9135 return;
9136 }
9137
9138 if (skip_past_comma (&str) == FAIL
9139 || (offset = mav_parse_offset (&str, &negative), inst.error))
9140 goto fail_ldst;
9141
9142 inst.instruction |= CP_T_WB; /* Post indexed, set bit W. */
9143 }
9144
9145 if (negative)
9146 offset = -offset;
9147 else
9148 inst.instruction |= CP_T_UD; /* Positive, so set bit U. */
9149
9150 inst.instruction |= offset >> 2;
9151 end_of_line (str);
9152 return;
9153
9154 fail_ldst:
9155 if (!inst.error)
9156 inst.error = BAD_ARGS;
9157 }
9158
9159 static void
9160 do_mav_ldst_1 (char * str)
9161 {
9162 do_mav_ldst (str, REG_TYPE_MVF);
9163 }
9164
9165 static void
9166 do_mav_ldst_2 (char * str)
9167 {
9168 do_mav_ldst (str, REG_TYPE_MVD);
9169 }
9170
9171 static void
9172 do_mav_ldst_3 (char * str)
9173 {
9174 do_mav_ldst (str, REG_TYPE_MVFX);
9175 }
9176
9177 static void
9178 do_mav_ldst_4 (char * str)
9179 {
9180 do_mav_ldst (str, REG_TYPE_MVDX);
9181 }
9182
9183 static void
9184 do_t_nop (char * str)
9185 {
9186 /* Do nothing. */
9187 end_of_line (str);
9188 }
9189
9190 /* Handle the Format 4 instructions that do not have equivalents in other
9191 formats. That is, ADC, AND, EOR, SBC, ROR, TST, NEG, CMN, ORR, MUL,
9192 BIC and MVN. */
9193
9194 static void
9195 do_t_arit (char * str)
9196 {
9197 int Rd, Rs, Rn;
9198
9199 skip_whitespace (str);
9200
9201 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9202 || skip_past_comma (&str) == FAIL
9203 || (Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9204 {
9205 inst.error = BAD_ARGS;
9206 return;
9207 }
9208
9209 if (skip_past_comma (&str) != FAIL)
9210 {
9211 /* Three operand format not allowed for TST, CMN, NEG and MVN.
9212 (It isn't allowed for CMP either, but that isn't handled by this
9213 function.) */
9214 if (inst.instruction == T_OPCODE_TST
9215 || inst.instruction == T_OPCODE_CMN
9216 || inst.instruction == T_OPCODE_NEG
9217 || inst.instruction == T_OPCODE_MVN)
9218 {
9219 inst.error = BAD_ARGS;
9220 return;
9221 }
9222
9223 if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9224 return;
9225
9226 if (Rs != Rd)
9227 {
9228 inst.error = _("dest and source1 must be the same register");
9229 return;
9230 }
9231 Rs = Rn;
9232 }
9233
9234 if (inst.instruction == T_OPCODE_MUL
9235 && Rs == Rd)
9236 as_tsktsk (_("Rs and Rd must be different in MUL"));
9237
9238 inst.instruction |= Rd | (Rs << 3);
9239 end_of_line (str);
9240 }
9241
9242 static void
9243 do_t_add (char * str)
9244 {
9245 thumb_add_sub (str, 0);
9246 }
9247
9248 static void
9249 do_t_asr (char * str)
9250 {
9251 thumb_shift (str, THUMB_ASR);
9252 }
9253
9254 static void
9255 do_t_branch9 (char * str)
9256 {
9257 if (my_get_expression (&inst.reloc.exp, &str))
9258 return;
9259 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH9;
9260 inst.reloc.pc_rel = 1;
9261 end_of_line (str);
9262 }
9263
9264 static void
9265 do_t_branch12 (char * str)
9266 {
9267 if (my_get_expression (&inst.reloc.exp, &str))
9268 return;
9269 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH12;
9270 inst.reloc.pc_rel = 1;
9271 end_of_line (str);
9272 }
9273
9274 /* Find the real, Thumb encoded start of a Thumb function. */
9275
9276 static symbolS *
9277 find_real_start (symbolS * symbolP)
9278 {
9279 char * real_start;
9280 const char * name = S_GET_NAME (symbolP);
9281 symbolS * new_target;
9282
9283 /* This definition must agree with the one in gcc/config/arm/thumb.c. */
9284 #define STUB_NAME ".real_start_of"
9285
9286 if (name == NULL)
9287 abort ();
9288
9289 /* Names that start with '.' are local labels, not function entry points.
9290 The compiler may generate BL instructions to these labels because it
9291 needs to perform a branch to a far away location. */
9292 if (name[0] == '.')
9293 return symbolP;
9294
9295 real_start = malloc (strlen (name) + strlen (STUB_NAME) + 1);
9296 sprintf (real_start, "%s%s", STUB_NAME, name);
9297
9298 new_target = symbol_find (real_start);
9299
9300 if (new_target == NULL)
9301 {
9302 as_warn ("Failed to find real start of function: %s\n", name);
9303 new_target = symbolP;
9304 }
9305
9306 free (real_start);
9307
9308 return new_target;
9309 }
9310
9311 static void
9312 do_t_branch23 (char * str)
9313 {
9314 if (my_get_expression (& inst.reloc.exp, & str))
9315 return;
9316
9317 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH23;
9318 inst.reloc.pc_rel = 1;
9319 end_of_line (str);
9320
9321 /* If the destination of the branch is a defined symbol which does not have
9322 the THUMB_FUNC attribute, then we must be calling a function which has
9323 the (interfacearm) attribute. We look for the Thumb entry point to that
9324 function and change the branch to refer to that function instead. */
9325 if ( inst.reloc.exp.X_op == O_symbol
9326 && inst.reloc.exp.X_add_symbol != NULL
9327 && S_IS_DEFINED (inst.reloc.exp.X_add_symbol)
9328 && ! THUMB_IS_FUNC (inst.reloc.exp.X_add_symbol))
9329 inst.reloc.exp.X_add_symbol =
9330 find_real_start (inst.reloc.exp.X_add_symbol);
9331 }
9332
9333 static void
9334 do_t_bx (char * str)
9335 {
9336 int reg;
9337
9338 skip_whitespace (str);
9339
9340 if ((reg = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
9341 return;
9342
9343 /* This sets THUMB_H2 from the top bit of reg. */
9344 inst.instruction |= reg << 3;
9345
9346 /* ??? FIXME: Should add a hacky reloc here if reg is REG_PC. The reloc
9347 should cause the alignment to be checked once it is known. This is
9348 because BX PC only works if the instruction is word aligned. */
9349
9350 end_of_line (str);
9351 }
9352
9353 static void
9354 do_t_compare (char * str)
9355 {
9356 thumb_mov_compare (str, THUMB_COMPARE);
9357 }
9358
9359 static void
9360 do_t_ldmstm (char * str)
9361 {
9362 int Rb;
9363 long range;
9364
9365 skip_whitespace (str);
9366
9367 if ((Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9368 return;
9369
9370 if (*str != '!')
9371 as_warn (_("inserted missing '!': load/store multiple always writes back base register"));
9372 else
9373 str++;
9374
9375 if (skip_past_comma (&str) == FAIL
9376 || (range = reg_list (&str)) == FAIL)
9377 {
9378 if (! inst.error)
9379 inst.error = BAD_ARGS;
9380 return;
9381 }
9382
9383 if (inst.reloc.type != BFD_RELOC_NONE)
9384 {
9385 /* This really doesn't seem worth it. */
9386 inst.reloc.type = BFD_RELOC_NONE;
9387 inst.error = _("expression too complex");
9388 return;
9389 }
9390
9391 if (range & ~0xff)
9392 {
9393 inst.error = _("only lo-regs valid in load/store multiple");
9394 return;
9395 }
9396
9397 inst.instruction |= (Rb << 8) | range;
9398 end_of_line (str);
9399 }
9400
9401 static void
9402 do_t_ldr (char * str)
9403 {
9404 thumb_load_store (str, THUMB_LOAD, THUMB_WORD);
9405 }
9406
9407 static void
9408 do_t_ldrb (char * str)
9409 {
9410 thumb_load_store (str, THUMB_LOAD, THUMB_BYTE);
9411 }
9412
9413 static void
9414 do_t_ldrh (char * str)
9415 {
9416 thumb_load_store (str, THUMB_LOAD, THUMB_HALFWORD);
9417 }
9418
9419 static void
9420 do_t_lds (char * str)
9421 {
9422 int Rd, Rb, Ro;
9423
9424 skip_whitespace (str);
9425
9426 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9427 || skip_past_comma (&str) == FAIL
9428 || *str++ != '['
9429 || (Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9430 || skip_past_comma (&str) == FAIL
9431 || (Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9432 || *str++ != ']')
9433 {
9434 if (! inst.error)
9435 inst.error = _("syntax: ldrs[b] Rd, [Rb, Ro]");
9436 return;
9437 }
9438
9439 inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
9440 end_of_line (str);
9441 }
9442
9443 static void
9444 do_t_lsl (char * str)
9445 {
9446 thumb_shift (str, THUMB_LSL);
9447 }
9448
9449 static void
9450 do_t_lsr (char * str)
9451 {
9452 thumb_shift (str, THUMB_LSR);
9453 }
9454
9455 static void
9456 do_t_mov (char * str)
9457 {
9458 thumb_mov_compare (str, THUMB_MOVE);
9459 }
9460
9461 static void
9462 do_t_push_pop (char * str)
9463 {
9464 long range;
9465
9466 skip_whitespace (str);
9467
9468 if ((range = reg_list (&str)) == FAIL)
9469 {
9470 if (! inst.error)
9471 inst.error = BAD_ARGS;
9472 return;
9473 }
9474
9475 if (inst.reloc.type != BFD_RELOC_NONE)
9476 {
9477 /* This really doesn't seem worth it. */
9478 inst.reloc.type = BFD_RELOC_NONE;
9479 inst.error = _("expression too complex");
9480 return;
9481 }
9482
9483 if (range & ~0xff)
9484 {
9485 if ((inst.instruction == T_OPCODE_PUSH
9486 && (range & ~0xff) == 1 << REG_LR)
9487 || (inst.instruction == T_OPCODE_POP
9488 && (range & ~0xff) == 1 << REG_PC))
9489 {
9490 inst.instruction |= THUMB_PP_PC_LR;
9491 range &= 0xff;
9492 }
9493 else
9494 {
9495 inst.error = _("invalid register list to push/pop instruction");
9496 return;
9497 }
9498 }
9499
9500 inst.instruction |= range;
9501 end_of_line (str);
9502 }
9503
9504 static void
9505 do_t_str (char * str)
9506 {
9507 thumb_load_store (str, THUMB_STORE, THUMB_WORD);
9508 }
9509
9510 static void
9511 do_t_strb (char * str)
9512 {
9513 thumb_load_store (str, THUMB_STORE, THUMB_BYTE);
9514 }
9515
9516 static void
9517 do_t_strh (char * str)
9518 {
9519 thumb_load_store (str, THUMB_STORE, THUMB_HALFWORD);
9520 }
9521
9522 static void
9523 do_t_sub (char * str)
9524 {
9525 thumb_add_sub (str, 1);
9526 }
9527
9528 static void
9529 do_t_swi (char * str)
9530 {
9531 skip_whitespace (str);
9532
9533 if (my_get_expression (&inst.reloc.exp, &str))
9534 return;
9535
9536 inst.reloc.type = BFD_RELOC_ARM_SWI;
9537 end_of_line (str);
9538 }
9539
9540 static void
9541 do_t_adr (char * str)
9542 {
9543 int reg;
9544
9545 /* This is a pseudo-op of the form "adr rd, label" to be converted
9546 into a relative address of the form "add rd, pc, #label-.-4". */
9547 skip_whitespace (str);
9548
9549 /* Store Rd in temporary location inside instruction. */
9550 if ((reg = reg_required_here (&str, 4)) == FAIL
9551 || (reg > 7) /* For Thumb reg must be r0..r7. */
9552 || skip_past_comma (&str) == FAIL
9553 || my_get_expression (&inst.reloc.exp, &str))
9554 {
9555 if (!inst.error)
9556 inst.error = BAD_ARGS;
9557 return;
9558 }
9559
9560 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
9561 inst.reloc.exp.X_add_number -= 4; /* PC relative adjust. */
9562 inst.reloc.pc_rel = 1;
9563 inst.instruction |= REG_PC; /* Rd is already placed into the instruction. */
9564
9565 end_of_line (str);
9566 }
9567
9568 static void
9569 insert_reg (const struct reg_entry * r,
9570 struct hash_control * htab)
9571 {
9572 int len = strlen (r->name) + 2;
9573 char * buf = xmalloc (len);
9574 char * buf2 = xmalloc (len);
9575 int i = 0;
9576
9577 #ifdef REGISTER_PREFIX
9578 buf[i++] = REGISTER_PREFIX;
9579 #endif
9580
9581 strcpy (buf + i, r->name);
9582
9583 for (i = 0; buf[i]; i++)
9584 buf2[i] = TOUPPER (buf[i]);
9585
9586 buf2[i] = '\0';
9587
9588 hash_insert (htab, buf, (PTR) r);
9589 hash_insert (htab, buf2, (PTR) r);
9590 }
9591
9592 static void
9593 build_reg_hsh (struct reg_map * map)
9594 {
9595 const struct reg_entry *r;
9596
9597 if ((map->htab = hash_new ()) == NULL)
9598 as_fatal (_("virtual memory exhausted"));
9599
9600 for (r = map->names; r->name != NULL; r++)
9601 insert_reg (r, map->htab);
9602 }
9603
9604 static void
9605 insert_reg_alias (char * str,
9606 int regnum,
9607 struct hash_control *htab)
9608 {
9609 const char * error;
9610 struct reg_entry * new = xmalloc (sizeof (struct reg_entry));
9611 const char * name = xmalloc (strlen (str) + 1);
9612
9613 strcpy ((char *) name, str);
9614
9615 new->name = name;
9616 new->number = regnum;
9617 new->builtin = FALSE;
9618
9619 error = hash_insert (htab, name, (PTR) new);
9620 if (error)
9621 {
9622 as_bad (_("failed to create an alias for %s, reason: %s"),
9623 str, error);
9624 free ((char *) name);
9625 free (new);
9626 }
9627 }
9628
9629 /* Look for the .req directive. This is of the form:
9630
9631 new_register_name .req existing_register_name
9632
9633 If we find one, or if it looks sufficiently like one that we want to
9634 handle any error here, return non-zero. Otherwise return zero. */
9635
9636 static int
9637 create_register_alias (char * newname, char * p)
9638 {
9639 char * q;
9640 char c;
9641
9642 q = p;
9643 skip_whitespace (q);
9644
9645 c = *p;
9646 *p = '\0';
9647
9648 if (*q && !strncmp (q, ".req ", 5))
9649 {
9650 char *copy_of_str;
9651 char *r;
9652
9653 #ifndef IGNORE_OPCODE_CASE
9654 newname = original_case_string;
9655 #endif
9656 copy_of_str = newname;
9657
9658 q += 4;
9659 skip_whitespace (q);
9660
9661 for (r = q; *r != '\0'; r++)
9662 if (*r == ' ')
9663 break;
9664
9665 if (r != q)
9666 {
9667 enum arm_reg_type new_type, old_type;
9668 int old_regno;
9669 char d = *r;
9670
9671 *r = '\0';
9672 old_type = arm_reg_parse_any (q);
9673 *r = d;
9674
9675 new_type = arm_reg_parse_any (newname);
9676
9677 if (new_type == REG_TYPE_MAX)
9678 {
9679 if (old_type != REG_TYPE_MAX)
9680 {
9681 old_regno = arm_reg_parse (&q, all_reg_maps[old_type].htab);
9682 insert_reg_alias (newname, old_regno,
9683 all_reg_maps[old_type].htab);
9684 }
9685 else
9686 as_warn (_("register '%s' does not exist\n"), q);
9687 }
9688 else if (old_type == REG_TYPE_MAX)
9689 {
9690 as_warn (_("ignoring redefinition of register alias '%s' to non-existant register '%s'"),
9691 copy_of_str, q);
9692 }
9693 else
9694 {
9695 /* Do not warn about redefinitions to the same alias. */
9696 if (new_type != old_type
9697 || (arm_reg_parse (&q, all_reg_maps[old_type].htab)
9698 != arm_reg_parse (&q, all_reg_maps[new_type].htab)))
9699 as_warn (_("ignoring redefinition of register alias '%s'"),
9700 copy_of_str);
9701
9702 }
9703 }
9704 else
9705 as_warn (_("ignoring incomplete .req pseuso op"));
9706
9707 *p = c;
9708 return 1;
9709 }
9710
9711 *p = c;
9712 return 0;
9713 }
9714
9715 static void
9716 set_constant_flonums (void)
9717 {
9718 int i;
9719
9720 for (i = 0; i < NUM_FLOAT_VALS; i++)
9721 if (atof_ieee ((char *) fp_const[i], 'x', fp_values[i]) == NULL)
9722 abort ();
9723 }
9724
9725 \f
9726 static const struct asm_opcode insns[] =
9727 {
9728 /* Core ARM Instructions. */
9729 {"and", 0xe0000000, 3, ARM_EXT_V1, do_arit},
9730 {"ands", 0xe0100000, 3, ARM_EXT_V1, do_arit},
9731 {"eor", 0xe0200000, 3, ARM_EXT_V1, do_arit},
9732 {"eors", 0xe0300000, 3, ARM_EXT_V1, do_arit},
9733 {"sub", 0xe0400000, 3, ARM_EXT_V1, do_arit},
9734 {"subs", 0xe0500000, 3, ARM_EXT_V1, do_arit},
9735 {"rsb", 0xe0600000, 3, ARM_EXT_V1, do_arit},
9736 {"rsbs", 0xe0700000, 3, ARM_EXT_V1, do_arit},
9737 {"add", 0xe0800000, 3, ARM_EXT_V1, do_arit},
9738 {"adds", 0xe0900000, 3, ARM_EXT_V1, do_arit},
9739 {"adc", 0xe0a00000, 3, ARM_EXT_V1, do_arit},
9740 {"adcs", 0xe0b00000, 3, ARM_EXT_V1, do_arit},
9741 {"sbc", 0xe0c00000, 3, ARM_EXT_V1, do_arit},
9742 {"sbcs", 0xe0d00000, 3, ARM_EXT_V1, do_arit},
9743 {"rsc", 0xe0e00000, 3, ARM_EXT_V1, do_arit},
9744 {"rscs", 0xe0f00000, 3, ARM_EXT_V1, do_arit},
9745 {"orr", 0xe1800000, 3, ARM_EXT_V1, do_arit},
9746 {"orrs", 0xe1900000, 3, ARM_EXT_V1, do_arit},
9747 {"bic", 0xe1c00000, 3, ARM_EXT_V1, do_arit},
9748 {"bics", 0xe1d00000, 3, ARM_EXT_V1, do_arit},
9749
9750 {"tst", 0xe1100000, 3, ARM_EXT_V1, do_cmp},
9751 {"tsts", 0xe1100000, 3, ARM_EXT_V1, do_cmp},
9752 {"tstp", 0xe110f000, 3, ARM_EXT_V1, do_cmp},
9753 {"teq", 0xe1300000, 3, ARM_EXT_V1, do_cmp},
9754 {"teqs", 0xe1300000, 3, ARM_EXT_V1, do_cmp},
9755 {"teqp", 0xe130f000, 3, ARM_EXT_V1, do_cmp},
9756 {"cmp", 0xe1500000, 3, ARM_EXT_V1, do_cmp},
9757 {"cmps", 0xe1500000, 3, ARM_EXT_V1, do_cmp},
9758 {"cmpp", 0xe150f000, 3, ARM_EXT_V1, do_cmp},
9759 {"cmn", 0xe1700000, 3, ARM_EXT_V1, do_cmp},
9760 {"cmns", 0xe1700000, 3, ARM_EXT_V1, do_cmp},
9761 {"cmnp", 0xe170f000, 3, ARM_EXT_V1, do_cmp},
9762
9763 {"mov", 0xe1a00000, 3, ARM_EXT_V1, do_mov},
9764 {"movs", 0xe1b00000, 3, ARM_EXT_V1, do_mov},
9765 {"mvn", 0xe1e00000, 3, ARM_EXT_V1, do_mov},
9766 {"mvns", 0xe1f00000, 3, ARM_EXT_V1, do_mov},
9767
9768 {"ldr", 0xe4100000, 3, ARM_EXT_V1, do_ldst},
9769 {"ldrb", 0xe4500000, 3, ARM_EXT_V1, do_ldst},
9770 {"ldrt", 0xe4300000, 3, ARM_EXT_V1, do_ldstt},
9771 {"ldrbt", 0xe4700000, 3, ARM_EXT_V1, do_ldstt},
9772 {"str", 0xe4000000, 3, ARM_EXT_V1, do_ldst},
9773 {"strb", 0xe4400000, 3, ARM_EXT_V1, do_ldst},
9774 {"strt", 0xe4200000, 3, ARM_EXT_V1, do_ldstt},
9775 {"strbt", 0xe4600000, 3, ARM_EXT_V1, do_ldstt},
9776
9777 {"stmia", 0xe8800000, 3, ARM_EXT_V1, do_ldmstm},
9778 {"stmib", 0xe9800000, 3, ARM_EXT_V1, do_ldmstm},
9779 {"stmda", 0xe8000000, 3, ARM_EXT_V1, do_ldmstm},
9780 {"stmdb", 0xe9000000, 3, ARM_EXT_V1, do_ldmstm},
9781 {"stmfd", 0xe9000000, 3, ARM_EXT_V1, do_ldmstm},
9782 {"stmfa", 0xe9800000, 3, ARM_EXT_V1, do_ldmstm},
9783 {"stmea", 0xe8800000, 3, ARM_EXT_V1, do_ldmstm},
9784 {"stmed", 0xe8000000, 3, ARM_EXT_V1, do_ldmstm},
9785
9786 {"ldmia", 0xe8900000, 3, ARM_EXT_V1, do_ldmstm},
9787 {"ldmib", 0xe9900000, 3, ARM_EXT_V1, do_ldmstm},
9788 {"ldmda", 0xe8100000, 3, ARM_EXT_V1, do_ldmstm},
9789 {"ldmdb", 0xe9100000, 3, ARM_EXT_V1, do_ldmstm},
9790 {"ldmfd", 0xe8900000, 3, ARM_EXT_V1, do_ldmstm},
9791 {"ldmfa", 0xe8100000, 3, ARM_EXT_V1, do_ldmstm},
9792 {"ldmea", 0xe9100000, 3, ARM_EXT_V1, do_ldmstm},
9793 {"ldmed", 0xe9900000, 3, ARM_EXT_V1, do_ldmstm},
9794
9795 {"swi", 0xef000000, 3, ARM_EXT_V1, do_swi},
9796 #ifdef TE_WINCE
9797 /* XXX This is the wrong place to do this. Think multi-arch. */
9798 {"bl", 0xeb000000, 2, ARM_EXT_V1, do_branch},
9799 {"b", 0xea000000, 1, ARM_EXT_V1, do_branch},
9800 #else
9801 {"bl", 0xebfffffe, 2, ARM_EXT_V1, do_branch},
9802 {"b", 0xeafffffe, 1, ARM_EXT_V1, do_branch},
9803 #endif
9804
9805 /* Pseudo ops. */
9806 {"adr", 0xe28f0000, 3, ARM_EXT_V1, do_adr},
9807 {"adrl", 0xe28f0000, 3, ARM_EXT_V1, do_adrl},
9808 {"nop", 0xe1a00000, 3, ARM_EXT_V1, do_nop},
9809
9810 /* ARM 2 multiplies. */
9811 {"mul", 0xe0000090, 3, ARM_EXT_V2, do_mul},
9812 {"muls", 0xe0100090, 3, ARM_EXT_V2, do_mul},
9813 {"mla", 0xe0200090, 3, ARM_EXT_V2, do_mla},
9814 {"mlas", 0xe0300090, 3, ARM_EXT_V2, do_mla},
9815
9816 /* Generic coprocessor instructions. */
9817 {"cdp", 0xee000000, 3, ARM_EXT_V2, do_cdp},
9818 {"ldc", 0xec100000, 3, ARM_EXT_V2, do_lstc},
9819 {"ldcl", 0xec500000, 3, ARM_EXT_V2, do_lstc},
9820 {"stc", 0xec000000, 3, ARM_EXT_V2, do_lstc},
9821 {"stcl", 0xec400000, 3, ARM_EXT_V2, do_lstc},
9822 {"mcr", 0xee000010, 3, ARM_EXT_V2, do_co_reg},
9823 {"mrc", 0xee100010, 3, ARM_EXT_V2, do_co_reg},
9824
9825 /* ARM 3 - swp instructions. */
9826 {"swp", 0xe1000090, 3, ARM_EXT_V2S, do_swap},
9827 {"swpb", 0xe1400090, 3, ARM_EXT_V2S, do_swap},
9828
9829 /* ARM 6 Status register instructions. */
9830 {"mrs", 0xe10f0000, 3, ARM_EXT_V3, do_mrs},
9831 {"msr", 0xe120f000, 3, ARM_EXT_V3, do_msr},
9832 /* ScottB: our code uses 0xe128f000 for msr.
9833 NickC: but this is wrong because the bits 16 through 19 are
9834 handled by the PSR_xxx defines above. */
9835
9836 /* ARM 7M long multiplies. */
9837 {"smull", 0xe0c00090, 5, ARM_EXT_V3M, do_mull},
9838 {"smulls", 0xe0d00090, 5, ARM_EXT_V3M, do_mull},
9839 {"umull", 0xe0800090, 5, ARM_EXT_V3M, do_mull},
9840 {"umulls", 0xe0900090, 5, ARM_EXT_V3M, do_mull},
9841 {"smlal", 0xe0e00090, 5, ARM_EXT_V3M, do_mull},
9842 {"smlals", 0xe0f00090, 5, ARM_EXT_V3M, do_mull},
9843 {"umlal", 0xe0a00090, 5, ARM_EXT_V3M, do_mull},
9844 {"umlals", 0xe0b00090, 5, ARM_EXT_V3M, do_mull},
9845
9846 /* ARM Architecture 4. */
9847 {"ldrh", 0xe01000b0, 3, ARM_EXT_V4, do_ldstv4},
9848 {"ldrsh", 0xe01000f0, 3, ARM_EXT_V4, do_ldstv4},
9849 {"ldrsb", 0xe01000d0, 3, ARM_EXT_V4, do_ldstv4},
9850 {"strh", 0xe00000b0, 3, ARM_EXT_V4, do_ldstv4},
9851
9852 /* ARM Architecture 4T. */
9853 /* Note: bx (and blx) are required on V5, even if the processor does
9854 not support Thumb. */
9855 {"bx", 0xe12fff10, 2, ARM_EXT_V4T | ARM_EXT_V5, do_bx},
9856
9857 /* ARM Architecture 5T. */
9858 /* Note: blx has 2 variants, so the .value is set dynamically.
9859 Only one of the variants has conditional execution. */
9860 {"blx", 0xe0000000, 3, ARM_EXT_V5, do_blx},
9861 {"clz", 0xe16f0f10, 3, ARM_EXT_V5, do_clz},
9862 {"bkpt", 0xe1200070, 0, ARM_EXT_V5, do_bkpt},
9863 {"ldc2", 0xfc100000, 0, ARM_EXT_V5, do_lstc2},
9864 {"ldc2l", 0xfc500000, 0, ARM_EXT_V5, do_lstc2},
9865 {"stc2", 0xfc000000, 0, ARM_EXT_V5, do_lstc2},
9866 {"stc2l", 0xfc400000, 0, ARM_EXT_V5, do_lstc2},
9867 {"cdp2", 0xfe000000, 0, ARM_EXT_V5, do_cdp2},
9868 {"mcr2", 0xfe000010, 0, ARM_EXT_V5, do_co_reg2},
9869 {"mrc2", 0xfe100010, 0, ARM_EXT_V5, do_co_reg2},
9870
9871 /* ARM Architecture 5TExP. */
9872 {"smlabb", 0xe1000080, 6, ARM_EXT_V5ExP, do_smla},
9873 {"smlatb", 0xe10000a0, 6, ARM_EXT_V5ExP, do_smla},
9874 {"smlabt", 0xe10000c0, 6, ARM_EXT_V5ExP, do_smla},
9875 {"smlatt", 0xe10000e0, 6, ARM_EXT_V5ExP, do_smla},
9876
9877 {"smlawb", 0xe1200080, 6, ARM_EXT_V5ExP, do_smla},
9878 {"smlawt", 0xe12000c0, 6, ARM_EXT_V5ExP, do_smla},
9879
9880 {"smlalbb", 0xe1400080, 7, ARM_EXT_V5ExP, do_smlal},
9881 {"smlaltb", 0xe14000a0, 7, ARM_EXT_V5ExP, do_smlal},
9882 {"smlalbt", 0xe14000c0, 7, ARM_EXT_V5ExP, do_smlal},
9883 {"smlaltt", 0xe14000e0, 7, ARM_EXT_V5ExP, do_smlal},
9884
9885 {"smulbb", 0xe1600080, 6, ARM_EXT_V5ExP, do_smul},
9886 {"smultb", 0xe16000a0, 6, ARM_EXT_V5ExP, do_smul},
9887 {"smulbt", 0xe16000c0, 6, ARM_EXT_V5ExP, do_smul},
9888 {"smultt", 0xe16000e0, 6, ARM_EXT_V5ExP, do_smul},
9889
9890 {"smulwb", 0xe12000a0, 6, ARM_EXT_V5ExP, do_smul},
9891 {"smulwt", 0xe12000e0, 6, ARM_EXT_V5ExP, do_smul},
9892
9893 {"qadd", 0xe1000050, 4, ARM_EXT_V5ExP, do_qadd},
9894 {"qdadd", 0xe1400050, 5, ARM_EXT_V5ExP, do_qadd},
9895 {"qsub", 0xe1200050, 4, ARM_EXT_V5ExP, do_qadd},
9896 {"qdsub", 0xe1600050, 5, ARM_EXT_V5ExP, do_qadd},
9897
9898 /* ARM Architecture 5TE. */
9899 {"pld", 0xf450f000, 0, ARM_EXT_V5E, do_pld},
9900 {"ldrd", 0xe00000d0, 3, ARM_EXT_V5E, do_ldrd},
9901 {"strd", 0xe00000f0, 3, ARM_EXT_V5E, do_ldrd},
9902
9903 {"mcrr", 0xec400000, 4, ARM_EXT_V5E, do_co_reg2c},
9904 {"mrrc", 0xec500000, 4, ARM_EXT_V5E, do_co_reg2c},
9905
9906 /* ARM Architecture 5TEJ. */
9907 {"bxj", 0xe12fff20, 3, ARM_EXT_V5J, do_bxj},
9908
9909 /* ARM V6. */
9910 { "cps", 0xf1020000, 0, ARM_EXT_V6, do_cps},
9911 { "cpsie", 0xf1080000, 0, ARM_EXT_V6, do_cpsi},
9912 { "cpsid", 0xf10C0000, 0, ARM_EXT_V6, do_cpsi},
9913 { "ldrex", 0xe1900f9f, 5, ARM_EXT_V6, do_ldrex},
9914 { "mcrr2", 0xfc400000, 0, ARM_EXT_V6, do_co_reg2c},
9915 { "mrrc2", 0xfc500000, 0, ARM_EXT_V6, do_co_reg2c},
9916 { "pkhbt", 0xe6800010, 5, ARM_EXT_V6, do_pkhbt},
9917 { "pkhtb", 0xe6800050, 5, ARM_EXT_V6, do_pkhtb},
9918 { "qadd16", 0xe6200f10, 6, ARM_EXT_V6, do_qadd16},
9919 { "qadd8", 0xe6200f90, 5, ARM_EXT_V6, do_qadd16},
9920 { "qaddsubx", 0xe6200f30, 8, ARM_EXT_V6, do_qadd16},
9921 { "qsub16", 0xe6200f70, 6, ARM_EXT_V6, do_qadd16},
9922 { "qsub8", 0xe6200ff0, 5, ARM_EXT_V6, do_qadd16},
9923 { "qsubaddx", 0xe6200f50, 8, ARM_EXT_V6, do_qadd16},
9924 { "sadd16", 0xe6100f10, 6, ARM_EXT_V6, do_qadd16},
9925 { "sadd8", 0xe6100f90, 5, ARM_EXT_V6, do_qadd16},
9926 { "saddsubx", 0xe6100f30, 8, ARM_EXT_V6, do_qadd16},
9927 { "shadd16", 0xe6300f10, 7, ARM_EXT_V6, do_qadd16},
9928 { "shadd8", 0xe6300f90, 6, ARM_EXT_V6, do_qadd16},
9929 { "shaddsubx", 0xe6300f30, 9, ARM_EXT_V6, do_qadd16},
9930 { "shsub16", 0xe6300f70, 7, ARM_EXT_V6, do_qadd16},
9931 { "shsub8", 0xe6300ff0, 6, ARM_EXT_V6, do_qadd16},
9932 { "shsubaddx", 0xe6300f50, 9, ARM_EXT_V6, do_qadd16},
9933 { "ssub16", 0xe6100f70, 6, ARM_EXT_V6, do_qadd16},
9934 { "ssub8", 0xe6100ff0, 5, ARM_EXT_V6, do_qadd16},
9935 { "ssubaddx", 0xe6100f50, 8, ARM_EXT_V6, do_qadd16},
9936 { "uadd16", 0xe6500f10, 6, ARM_EXT_V6, do_qadd16},
9937 { "uadd8", 0xe6500f90, 5, ARM_EXT_V6, do_qadd16},
9938 { "uaddsubx", 0xe6500f30, 8, ARM_EXT_V6, do_qadd16},
9939 { "uhadd16", 0xe6700f10, 7, ARM_EXT_V6, do_qadd16},
9940 { "uhadd8", 0xe6700f90, 6, ARM_EXT_V6, do_qadd16},
9941 { "uhaddsubx", 0xe6700f30, 9, ARM_EXT_V6, do_qadd16},
9942 { "uhsub16", 0xe6700f70, 7, ARM_EXT_V6, do_qadd16},
9943 { "uhsub8", 0xe6700ff0, 6, ARM_EXT_V6, do_qadd16},
9944 { "uhsubaddx", 0xe6700f50, 9, ARM_EXT_V6, do_qadd16},
9945 { "uqadd16", 0xe6600f10, 7, ARM_EXT_V6, do_qadd16},
9946 { "uqadd8", 0xe6600f90, 6, ARM_EXT_V6, do_qadd16},
9947 { "uqaddsubx", 0xe6600f30, 9, ARM_EXT_V6, do_qadd16},
9948 { "uqsub16", 0xe6600f70, 7, ARM_EXT_V6, do_qadd16},
9949 { "uqsub8", 0xe6600ff0, 6, ARM_EXT_V6, do_qadd16},
9950 { "uqsubaddx", 0xe6600f50, 9, ARM_EXT_V6, do_qadd16},
9951 { "usub16", 0xe6500f70, 6, ARM_EXT_V6, do_qadd16},
9952 { "usub8", 0xe6500ff0, 5, ARM_EXT_V6, do_qadd16},
9953 { "usubaddx", 0xe6500f50, 8, ARM_EXT_V6, do_qadd16},
9954 { "rev", 0xe6bf0f30, 3, ARM_EXT_V6, do_rev},
9955 { "rev16", 0xe6bf0fb0, 5, ARM_EXT_V6, do_rev},
9956 { "revsh", 0xe6ff0fb0, 5, ARM_EXT_V6, do_rev},
9957 { "rfeia", 0xf8900a00, 0, ARM_EXT_V6, do_rfe},
9958 { "rfeib", 0xf9900a00, 0, ARM_EXT_V6, do_rfe},
9959 { "rfeda", 0xf8100a00, 0, ARM_EXT_V6, do_rfe},
9960 { "rfedb", 0xf9100a00, 0, ARM_EXT_V6, do_rfe},
9961 { "rfefd", 0xf8900a00, 0, ARM_EXT_V6, do_rfe},
9962 { "rfefa", 0xf9900a00, 0, ARM_EXT_V6, do_rfe},
9963 { "rfeea", 0xf8100a00, 0, ARM_EXT_V6, do_rfe},
9964 { "rfeed", 0xf9100a00, 0, ARM_EXT_V6, do_rfe},
9965 { "sxtah", 0xe6b00070, 5, ARM_EXT_V6, do_sxtah},
9966 { "sxtab16", 0xe6800070, 7, ARM_EXT_V6, do_sxtah},
9967 { "sxtab", 0xe6a00070, 5, ARM_EXT_V6, do_sxtah},
9968 { "sxth", 0xe6bf0070, 4, ARM_EXT_V6, do_sxth},
9969 { "sxtb16", 0xe68f0070, 6, ARM_EXT_V6, do_sxth},
9970 { "sxtb", 0xe6af0070, 4, ARM_EXT_V6, do_sxth},
9971 { "uxtah", 0xe6f00070, 5, ARM_EXT_V6, do_sxtah},
9972 { "uxtab16", 0xe6c00070, 7, ARM_EXT_V6, do_sxtah},
9973 { "uxtab", 0xe6e00070, 5, ARM_EXT_V6, do_sxtah},
9974 { "uxth", 0xe6ff0070, 4, ARM_EXT_V6, do_sxth},
9975 { "uxtb16", 0xe6cf0070, 6, ARM_EXT_V6, do_sxth},
9976 { "uxtb", 0xe6ef0070, 4, ARM_EXT_V6, do_sxth},
9977 { "sel", 0xe68000b0, 3, ARM_EXT_V6, do_qadd16},
9978 { "setend", 0xf1010000, 0, ARM_EXT_V6, do_setend},
9979 { "smlad", 0xe7000010, 5, ARM_EXT_V6, do_smlad},
9980 { "smladx", 0xe7000030, 6, ARM_EXT_V6, do_smlad},
9981 { "smlald", 0xe7400010, 6, ARM_EXT_V6, do_smlald},
9982 { "smlaldx", 0xe7400030, 7, ARM_EXT_V6, do_smlald},
9983 { "smlsd", 0xe7000050, 5, ARM_EXT_V6, do_smlad},
9984 { "smlsdx", 0xe7000070, 6, ARM_EXT_V6, do_smlad},
9985 { "smlsld", 0xe7400050, 6, ARM_EXT_V6, do_smlald},
9986 { "smlsldx", 0xe7400070, 7, ARM_EXT_V6, do_smlald},
9987 { "smmla", 0xe7500010, 5, ARM_EXT_V6, do_smlad},
9988 { "smmlar", 0xe7500030, 6, ARM_EXT_V6, do_smlad},
9989 { "smmls", 0xe75000d0, 5, ARM_EXT_V6, do_smlad},
9990 { "smmlsr", 0xe75000f0, 6, ARM_EXT_V6, do_smlad},
9991 { "smmul", 0xe750f010, 5, ARM_EXT_V6, do_smmul},
9992 { "smmulr", 0xe750f030, 6, ARM_EXT_V6, do_smmul},
9993 { "smuad", 0xe700f010, 5, ARM_EXT_V6, do_smmul},
9994 { "smuadx", 0xe700f030, 6, ARM_EXT_V6, do_smmul},
9995 { "smusd", 0xe700f050, 5, ARM_EXT_V6, do_smmul},
9996 { "smusdx", 0xe700f070, 6, ARM_EXT_V6, do_smmul},
9997 { "srsia", 0xf8cd0500, 0, ARM_EXT_V6, do_srs},
9998 { "srsib", 0xf9cd0500, 0, ARM_EXT_V6, do_srs},
9999 { "srsda", 0xf84d0500, 0, ARM_EXT_V6, do_srs},
10000 { "srsdb", 0xf94d0500, 0, ARM_EXT_V6, do_srs},
10001 { "ssat", 0xe6a00010, 4, ARM_EXT_V6, do_ssat},
10002 { "ssat16", 0xe6a00f30, 6, ARM_EXT_V6, do_ssat16},
10003 { "strex", 0xe1800f90, 5, ARM_EXT_V6, do_strex},
10004 { "umaal", 0xe0400090, 5, ARM_EXT_V6, do_umaal},
10005 { "usad8", 0xe780f010, 5, ARM_EXT_V6, do_smmul},
10006 { "usada8", 0xe7800010, 6, ARM_EXT_V6, do_smlad},
10007 { "usat", 0xe6e00010, 4, ARM_EXT_V6, do_usat},
10008 { "usat16", 0xe6e00f30, 6, ARM_EXT_V6, do_usat16},
10009
10010 /* ARM V6K. */
10011 { "clrex", 0xf57ff01f, 0, ARM_EXT_V6K, do_empty},
10012 { "ldrexb", 0xe1d00f9f, 6, ARM_EXT_V6K, do_ldrex},
10013 { "ldrexd", 0xe1b00f9f, 6, ARM_EXT_V6K, do_ldrex},
10014 { "ldrexh", 0xe1f00f9f, 6, ARM_EXT_V6K, do_ldrex},
10015 { "sev", 0xe320f004, 3, ARM_EXT_V6K, do_empty},
10016 { "strexb", 0xe1c00f90, 6, ARM_EXT_V6K, do_strex},
10017 { "strexd", 0xe1a00f90, 6, ARM_EXT_V6K, do_strex},
10018 { "strexh", 0xe1e00f90, 6, ARM_EXT_V6K, do_strex},
10019 { "wfe", 0xe320f002, 3, ARM_EXT_V6K, do_empty},
10020 { "wfi", 0xe320f003, 3, ARM_EXT_V6K, do_empty},
10021 { "yield", 0xe320f001, 5, ARM_EXT_V6K, do_empty},
10022
10023 /* ARM V6Z. */
10024 { "smi", 0xe1600070, 3, ARM_EXT_V6Z, do_smi},
10025
10026 /* Core FPA instruction set (V1). */
10027 {"wfs", 0xee200110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
10028 {"rfs", 0xee300110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
10029 {"wfc", 0xee400110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
10030 {"rfc", 0xee500110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
10031
10032 {"ldfs", 0xec100100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10033 {"ldfd", 0xec108100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10034 {"ldfe", 0xec500100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10035 {"ldfp", 0xec508100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10036
10037 {"stfs", 0xec000100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10038 {"stfd", 0xec008100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10039 {"stfe", 0xec400100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10040 {"stfp", 0xec408100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10041
10042 {"mvfs", 0xee008100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10043 {"mvfsp", 0xee008120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10044 {"mvfsm", 0xee008140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10045 {"mvfsz", 0xee008160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10046 {"mvfd", 0xee008180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10047 {"mvfdp", 0xee0081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10048 {"mvfdm", 0xee0081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10049 {"mvfdz", 0xee0081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10050 {"mvfe", 0xee088100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10051 {"mvfep", 0xee088120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10052 {"mvfem", 0xee088140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10053 {"mvfez", 0xee088160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10054
10055 {"mnfs", 0xee108100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10056 {"mnfsp", 0xee108120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10057 {"mnfsm", 0xee108140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10058 {"mnfsz", 0xee108160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10059 {"mnfd", 0xee108180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10060 {"mnfdp", 0xee1081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10061 {"mnfdm", 0xee1081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10062 {"mnfdz", 0xee1081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10063 {"mnfe", 0xee188100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10064 {"mnfep", 0xee188120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10065 {"mnfem", 0xee188140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10066 {"mnfez", 0xee188160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10067
10068 {"abss", 0xee208100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10069 {"abssp", 0xee208120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10070 {"abssm", 0xee208140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10071 {"abssz", 0xee208160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10072 {"absd", 0xee208180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10073 {"absdp", 0xee2081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10074 {"absdm", 0xee2081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10075 {"absdz", 0xee2081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10076 {"abse", 0xee288100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10077 {"absep", 0xee288120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10078 {"absem", 0xee288140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10079 {"absez", 0xee288160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10080
10081 {"rnds", 0xee308100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10082 {"rndsp", 0xee308120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10083 {"rndsm", 0xee308140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10084 {"rndsz", 0xee308160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10085 {"rndd", 0xee308180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10086 {"rnddp", 0xee3081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10087 {"rnddm", 0xee3081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10088 {"rnddz", 0xee3081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10089 {"rnde", 0xee388100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10090 {"rndep", 0xee388120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10091 {"rndem", 0xee388140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10092 {"rndez", 0xee388160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10093
10094 {"sqts", 0xee408100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10095 {"sqtsp", 0xee408120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10096 {"sqtsm", 0xee408140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10097 {"sqtsz", 0xee408160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10098 {"sqtd", 0xee408180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10099 {"sqtdp", 0xee4081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10100 {"sqtdm", 0xee4081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10101 {"sqtdz", 0xee4081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10102 {"sqte", 0xee488100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10103 {"sqtep", 0xee488120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10104 {"sqtem", 0xee488140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10105 {"sqtez", 0xee488160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10106
10107 {"logs", 0xee508100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10108 {"logsp", 0xee508120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10109 {"logsm", 0xee508140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10110 {"logsz", 0xee508160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10111 {"logd", 0xee508180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10112 {"logdp", 0xee5081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10113 {"logdm", 0xee5081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10114 {"logdz", 0xee5081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10115 {"loge", 0xee588100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10116 {"logep", 0xee588120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10117 {"logem", 0xee588140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10118 {"logez", 0xee588160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10119
10120 {"lgns", 0xee608100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10121 {"lgnsp", 0xee608120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10122 {"lgnsm", 0xee608140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10123 {"lgnsz", 0xee608160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10124 {"lgnd", 0xee608180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10125 {"lgndp", 0xee6081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10126 {"lgndm", 0xee6081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10127 {"lgndz", 0xee6081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10128 {"lgne", 0xee688100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10129 {"lgnep", 0xee688120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10130 {"lgnem", 0xee688140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10131 {"lgnez", 0xee688160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10132
10133 {"exps", 0xee708100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10134 {"expsp", 0xee708120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10135 {"expsm", 0xee708140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10136 {"expsz", 0xee708160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10137 {"expd", 0xee708180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10138 {"expdp", 0xee7081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10139 {"expdm", 0xee7081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10140 {"expdz", 0xee7081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10141 {"expe", 0xee788100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10142 {"expep", 0xee788120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10143 {"expem", 0xee788140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10144 {"expdz", 0xee788160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10145
10146 {"sins", 0xee808100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10147 {"sinsp", 0xee808120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10148 {"sinsm", 0xee808140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10149 {"sinsz", 0xee808160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10150 {"sind", 0xee808180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10151 {"sindp", 0xee8081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10152 {"sindm", 0xee8081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10153 {"sindz", 0xee8081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10154 {"sine", 0xee888100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10155 {"sinep", 0xee888120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10156 {"sinem", 0xee888140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10157 {"sinez", 0xee888160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10158
10159 {"coss", 0xee908100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10160 {"cossp", 0xee908120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10161 {"cossm", 0xee908140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10162 {"cossz", 0xee908160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10163 {"cosd", 0xee908180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10164 {"cosdp", 0xee9081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10165 {"cosdm", 0xee9081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10166 {"cosdz", 0xee9081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10167 {"cose", 0xee988100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10168 {"cosep", 0xee988120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10169 {"cosem", 0xee988140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10170 {"cosez", 0xee988160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10171
10172 {"tans", 0xeea08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10173 {"tansp", 0xeea08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10174 {"tansm", 0xeea08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10175 {"tansz", 0xeea08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10176 {"tand", 0xeea08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10177 {"tandp", 0xeea081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10178 {"tandm", 0xeea081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10179 {"tandz", 0xeea081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10180 {"tane", 0xeea88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10181 {"tanep", 0xeea88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10182 {"tanem", 0xeea88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10183 {"tanez", 0xeea88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10184
10185 {"asns", 0xeeb08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10186 {"asnsp", 0xeeb08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10187 {"asnsm", 0xeeb08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10188 {"asnsz", 0xeeb08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10189 {"asnd", 0xeeb08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10190 {"asndp", 0xeeb081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10191 {"asndm", 0xeeb081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10192 {"asndz", 0xeeb081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10193 {"asne", 0xeeb88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10194 {"asnep", 0xeeb88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10195 {"asnem", 0xeeb88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10196 {"asnez", 0xeeb88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10197
10198 {"acss", 0xeec08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10199 {"acssp", 0xeec08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10200 {"acssm", 0xeec08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10201 {"acssz", 0xeec08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10202 {"acsd", 0xeec08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10203 {"acsdp", 0xeec081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10204 {"acsdm", 0xeec081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10205 {"acsdz", 0xeec081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10206 {"acse", 0xeec88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10207 {"acsep", 0xeec88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10208 {"acsem", 0xeec88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10209 {"acsez", 0xeec88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10210
10211 {"atns", 0xeed08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10212 {"atnsp", 0xeed08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10213 {"atnsm", 0xeed08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10214 {"atnsz", 0xeed08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10215 {"atnd", 0xeed08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10216 {"atndp", 0xeed081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10217 {"atndm", 0xeed081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10218 {"atndz", 0xeed081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10219 {"atne", 0xeed88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10220 {"atnep", 0xeed88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10221 {"atnem", 0xeed88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10222 {"atnez", 0xeed88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10223
10224 {"urds", 0xeee08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10225 {"urdsp", 0xeee08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10226 {"urdsm", 0xeee08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10227 {"urdsz", 0xeee08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10228 {"urdd", 0xeee08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10229 {"urddp", 0xeee081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10230 {"urddm", 0xeee081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10231 {"urddz", 0xeee081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10232 {"urde", 0xeee88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10233 {"urdep", 0xeee88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10234 {"urdem", 0xeee88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10235 {"urdez", 0xeee88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10236
10237 {"nrms", 0xeef08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10238 {"nrmsp", 0xeef08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10239 {"nrmsm", 0xeef08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10240 {"nrmsz", 0xeef08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10241 {"nrmd", 0xeef08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10242 {"nrmdp", 0xeef081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10243 {"nrmdm", 0xeef081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10244 {"nrmdz", 0xeef081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10245 {"nrme", 0xeef88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10246 {"nrmep", 0xeef88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10247 {"nrmem", 0xeef88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10248 {"nrmez", 0xeef88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10249
10250 {"adfs", 0xee000100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10251 {"adfsp", 0xee000120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10252 {"adfsm", 0xee000140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10253 {"adfsz", 0xee000160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10254 {"adfd", 0xee000180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10255 {"adfdp", 0xee0001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10256 {"adfdm", 0xee0001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10257 {"adfdz", 0xee0001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10258 {"adfe", 0xee080100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10259 {"adfep", 0xee080120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10260 {"adfem", 0xee080140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10261 {"adfez", 0xee080160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10262
10263 {"sufs", 0xee200100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10264 {"sufsp", 0xee200120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10265 {"sufsm", 0xee200140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10266 {"sufsz", 0xee200160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10267 {"sufd", 0xee200180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10268 {"sufdp", 0xee2001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10269 {"sufdm", 0xee2001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10270 {"sufdz", 0xee2001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10271 {"sufe", 0xee280100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10272 {"sufep", 0xee280120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10273 {"sufem", 0xee280140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10274 {"sufez", 0xee280160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10275
10276 {"rsfs", 0xee300100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10277 {"rsfsp", 0xee300120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10278 {"rsfsm", 0xee300140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10279 {"rsfsz", 0xee300160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10280 {"rsfd", 0xee300180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10281 {"rsfdp", 0xee3001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10282 {"rsfdm", 0xee3001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10283 {"rsfdz", 0xee3001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10284 {"rsfe", 0xee380100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10285 {"rsfep", 0xee380120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10286 {"rsfem", 0xee380140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10287 {"rsfez", 0xee380160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10288
10289 {"mufs", 0xee100100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10290 {"mufsp", 0xee100120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10291 {"mufsm", 0xee100140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10292 {"mufsz", 0xee100160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10293 {"mufd", 0xee100180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10294 {"mufdp", 0xee1001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10295 {"mufdm", 0xee1001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10296 {"mufdz", 0xee1001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10297 {"mufe", 0xee180100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10298 {"mufep", 0xee180120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10299 {"mufem", 0xee180140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10300 {"mufez", 0xee180160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10301
10302 {"dvfs", 0xee400100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10303 {"dvfsp", 0xee400120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10304 {"dvfsm", 0xee400140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10305 {"dvfsz", 0xee400160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10306 {"dvfd", 0xee400180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10307 {"dvfdp", 0xee4001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10308 {"dvfdm", 0xee4001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10309 {"dvfdz", 0xee4001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10310 {"dvfe", 0xee480100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10311 {"dvfep", 0xee480120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10312 {"dvfem", 0xee480140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10313 {"dvfez", 0xee480160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10314
10315 {"rdfs", 0xee500100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10316 {"rdfsp", 0xee500120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10317 {"rdfsm", 0xee500140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10318 {"rdfsz", 0xee500160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10319 {"rdfd", 0xee500180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10320 {"rdfdp", 0xee5001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10321 {"rdfdm", 0xee5001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10322 {"rdfdz", 0xee5001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10323 {"rdfe", 0xee580100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10324 {"rdfep", 0xee580120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10325 {"rdfem", 0xee580140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10326 {"rdfez", 0xee580160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10327
10328 {"pows", 0xee600100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10329 {"powsp", 0xee600120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10330 {"powsm", 0xee600140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10331 {"powsz", 0xee600160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10332 {"powd", 0xee600180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10333 {"powdp", 0xee6001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10334 {"powdm", 0xee6001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10335 {"powdz", 0xee6001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10336 {"powe", 0xee680100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10337 {"powep", 0xee680120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10338 {"powem", 0xee680140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10339 {"powez", 0xee680160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10340
10341 {"rpws", 0xee700100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10342 {"rpwsp", 0xee700120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10343 {"rpwsm", 0xee700140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10344 {"rpwsz", 0xee700160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10345 {"rpwd", 0xee700180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10346 {"rpwdp", 0xee7001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10347 {"rpwdm", 0xee7001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10348 {"rpwdz", 0xee7001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10349 {"rpwe", 0xee780100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10350 {"rpwep", 0xee780120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10351 {"rpwem", 0xee780140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10352 {"rpwez", 0xee780160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10353
10354 {"rmfs", 0xee800100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10355 {"rmfsp", 0xee800120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10356 {"rmfsm", 0xee800140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10357 {"rmfsz", 0xee800160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10358 {"rmfd", 0xee800180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10359 {"rmfdp", 0xee8001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10360 {"rmfdm", 0xee8001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10361 {"rmfdz", 0xee8001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10362 {"rmfe", 0xee880100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10363 {"rmfep", 0xee880120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10364 {"rmfem", 0xee880140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10365 {"rmfez", 0xee880160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10366
10367 {"fmls", 0xee900100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10368 {"fmlsp", 0xee900120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10369 {"fmlsm", 0xee900140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10370 {"fmlsz", 0xee900160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10371 {"fmld", 0xee900180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10372 {"fmldp", 0xee9001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10373 {"fmldm", 0xee9001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10374 {"fmldz", 0xee9001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10375 {"fmle", 0xee980100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10376 {"fmlep", 0xee980120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10377 {"fmlem", 0xee980140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10378 {"fmlez", 0xee980160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10379
10380 {"fdvs", 0xeea00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10381 {"fdvsp", 0xeea00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10382 {"fdvsm", 0xeea00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10383 {"fdvsz", 0xeea00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10384 {"fdvd", 0xeea00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10385 {"fdvdp", 0xeea001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10386 {"fdvdm", 0xeea001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10387 {"fdvdz", 0xeea001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10388 {"fdve", 0xeea80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10389 {"fdvep", 0xeea80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10390 {"fdvem", 0xeea80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10391 {"fdvez", 0xeea80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10392
10393 {"frds", 0xeeb00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10394 {"frdsp", 0xeeb00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10395 {"frdsm", 0xeeb00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10396 {"frdsz", 0xeeb00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10397 {"frdd", 0xeeb00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10398 {"frddp", 0xeeb001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10399 {"frddm", 0xeeb001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10400 {"frddz", 0xeeb001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10401 {"frde", 0xeeb80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10402 {"frdep", 0xeeb80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10403 {"frdem", 0xeeb80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10404 {"frdez", 0xeeb80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10405
10406 {"pols", 0xeec00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10407 {"polsp", 0xeec00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10408 {"polsm", 0xeec00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10409 {"polsz", 0xeec00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10410 {"pold", 0xeec00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10411 {"poldp", 0xeec001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10412 {"poldm", 0xeec001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10413 {"poldz", 0xeec001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10414 {"pole", 0xeec80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10415 {"polep", 0xeec80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10416 {"polem", 0xeec80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10417 {"polez", 0xeec80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10418
10419 {"cmf", 0xee90f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
10420 {"cmfe", 0xeed0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
10421 {"cnf", 0xeeb0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
10422 {"cnfe", 0xeef0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
10423 /* The FPA10 data sheet suggests that the 'E' of cmfe/cnfe should
10424 not be an optional suffix, but part of the instruction. To be
10425 compatible, we accept either. */
10426 {"cmfe", 0xeed0f110, 4, FPU_FPA_EXT_V1, do_fpa_cmp},
10427 {"cnfe", 0xeef0f110, 4, FPU_FPA_EXT_V1, do_fpa_cmp},
10428
10429 {"flts", 0xee000110, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10430 {"fltsp", 0xee000130, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10431 {"fltsm", 0xee000150, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10432 {"fltsz", 0xee000170, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10433 {"fltd", 0xee000190, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10434 {"fltdp", 0xee0001b0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10435 {"fltdm", 0xee0001d0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10436 {"fltdz", 0xee0001f0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10437 {"flte", 0xee080110, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10438 {"fltep", 0xee080130, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10439 {"fltem", 0xee080150, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10440 {"fltez", 0xee080170, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10441
10442 /* The implementation of the FIX instruction is broken on some
10443 assemblers, in that it accepts a precision specifier as well as a
10444 rounding specifier, despite the fact that this is meaningless.
10445 To be more compatible, we accept it as well, though of course it
10446 does not set any bits. */
10447 {"fix", 0xee100110, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10448 {"fixp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10449 {"fixm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10450 {"fixz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10451 {"fixsp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10452 {"fixsm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10453 {"fixsz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10454 {"fixdp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10455 {"fixdm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10456 {"fixdz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10457 {"fixep", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10458 {"fixem", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10459 {"fixez", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10460
10461 /* Instructions that were new with the real FPA, call them V2. */
10462 {"lfm", 0xec100200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10463 {"lfmfd", 0xec900200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10464 {"lfmea", 0xed100200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10465 {"sfm", 0xec000200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10466 {"sfmfd", 0xed000200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10467 {"sfmea", 0xec800200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10468
10469 /* VFP V1xD (single precision). */
10470 /* Moves and type conversions. */
10471 {"fcpys", 0xeeb00a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10472 {"fmrs", 0xee100a10, 4, FPU_VFP_EXT_V1xD, do_vfp_reg_from_sp},
10473 {"fmsr", 0xee000a10, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_from_reg},
10474 {"fmstat", 0xeef1fa10, 6, FPU_VFP_EXT_V1xD, do_empty},
10475 {"fsitos", 0xeeb80ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10476 {"fuitos", 0xeeb80a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10477 {"ftosis", 0xeebd0a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10478 {"ftosizs", 0xeebd0ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10479 {"ftouis", 0xeebc0a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10480 {"ftouizs", 0xeebc0ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10481 {"fmrx", 0xeef00a10, 4, FPU_VFP_EXT_V1xD, do_vfp_reg_from_ctrl},
10482 {"fmxr", 0xeee00a10, 4, FPU_VFP_EXT_V1xD, do_vfp_ctrl_from_reg},
10483
10484 /* Memory operations. */
10485 {"flds", 0xed100a00, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_ldst},
10486 {"fsts", 0xed000a00, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_ldst},
10487 {"fldmias", 0xec900a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
10488 {"fldmfds", 0xec900a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
10489 {"fldmdbs", 0xed300a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
10490 {"fldmeas", 0xed300a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
10491 {"fldmiax", 0xec900b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
10492 {"fldmfdx", 0xec900b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
10493 {"fldmdbx", 0xed300b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
10494 {"fldmeax", 0xed300b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
10495 {"fstmias", 0xec800a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
10496 {"fstmeas", 0xec800a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
10497 {"fstmdbs", 0xed200a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
10498 {"fstmfds", 0xed200a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
10499 {"fstmiax", 0xec800b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
10500 {"fstmeax", 0xec800b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
10501 {"fstmdbx", 0xed200b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
10502 {"fstmfdx", 0xed200b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
10503
10504 /* Monadic operations. */
10505 {"fabss", 0xeeb00ac0, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10506 {"fnegs", 0xeeb10a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10507 {"fsqrts", 0xeeb10ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10508
10509 /* Dyadic operations. */
10510 {"fadds", 0xee300a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10511 {"fsubs", 0xee300a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10512 {"fmuls", 0xee200a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10513 {"fdivs", 0xee800a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10514 {"fmacs", 0xee000a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10515 {"fmscs", 0xee100a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10516 {"fnmuls", 0xee200a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10517 {"fnmacs", 0xee000a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10518 {"fnmscs", 0xee100a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10519
10520 /* Comparisons. */
10521 {"fcmps", 0xeeb40a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10522 {"fcmpzs", 0xeeb50a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_compare_z},
10523 {"fcmpes", 0xeeb40ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10524 {"fcmpezs", 0xeeb50ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_compare_z},
10525
10526 /* VFP V1 (Double precision). */
10527 /* Moves and type conversions. */
10528 {"fcpyd", 0xeeb00b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10529 {"fcvtds", 0xeeb70ac0, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
10530 {"fcvtsd", 0xeeb70bc0, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
10531 {"fmdhr", 0xee200b10, 5, FPU_VFP_EXT_V1, do_vfp_dp_from_reg},
10532 {"fmdlr", 0xee000b10, 5, FPU_VFP_EXT_V1, do_vfp_dp_from_reg},
10533 {"fmrdh", 0xee300b10, 5, FPU_VFP_EXT_V1, do_vfp_reg_from_dp},
10534 {"fmrdl", 0xee100b10, 5, FPU_VFP_EXT_V1, do_vfp_reg_from_dp},
10535 {"fsitod", 0xeeb80bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
10536 {"fuitod", 0xeeb80b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
10537 {"ftosid", 0xeebd0b40, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
10538 {"ftosizd", 0xeebd0bc0, 7, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
10539 {"ftouid", 0xeebc0b40, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
10540 {"ftouizd", 0xeebc0bc0, 7, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
10541
10542 /* Memory operations. */
10543 {"fldd", 0xed100b00, 4, FPU_VFP_EXT_V1, do_vfp_dp_ldst},
10544 {"fstd", 0xed000b00, 4, FPU_VFP_EXT_V1, do_vfp_dp_ldst},
10545 {"fldmiad", 0xec900b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
10546 {"fldmfdd", 0xec900b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
10547 {"fldmdbd", 0xed300b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
10548 {"fldmead", 0xed300b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
10549 {"fstmiad", 0xec800b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
10550 {"fstmead", 0xec800b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
10551 {"fstmdbd", 0xed200b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
10552 {"fstmfdd", 0xed200b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
10553
10554 /* Monadic operations. */
10555 {"fabsd", 0xeeb00bc0, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10556 {"fnegd", 0xeeb10b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10557 {"fsqrtd", 0xeeb10bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10558
10559 /* Dyadic operations. */
10560 {"faddd", 0xee300b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10561 {"fsubd", 0xee300b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10562 {"fmuld", 0xee200b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10563 {"fdivd", 0xee800b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10564 {"fmacd", 0xee000b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10565 {"fmscd", 0xee100b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10566 {"fnmuld", 0xee200b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10567 {"fnmacd", 0xee000b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10568 {"fnmscd", 0xee100b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10569
10570 /* Comparisons. */
10571 {"fcmpd", 0xeeb40b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10572 {"fcmpzd", 0xeeb50b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_compare_z},
10573 {"fcmped", 0xeeb40bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10574 {"fcmpezd", 0xeeb50bc0, 7, FPU_VFP_EXT_V1, do_vfp_dp_compare_z},
10575
10576 /* VFP V2. */
10577 {"fmsrr", 0xec400a10, 5, FPU_VFP_EXT_V2, do_vfp_sp2_from_reg2},
10578 {"fmrrs", 0xec500a10, 5, FPU_VFP_EXT_V2, do_vfp_reg2_from_sp2},
10579 {"fmdrr", 0xec400b10, 5, FPU_VFP_EXT_V2, do_vfp_dp_from_reg2},
10580 {"fmrrd", 0xec500b10, 5, FPU_VFP_EXT_V2, do_vfp_reg2_from_dp},
10581
10582 /* Intel XScale extensions to ARM V5 ISA. (All use CP0). */
10583 {"mia", 0xee200010, 3, ARM_CEXT_XSCALE, do_xsc_mia},
10584 {"miaph", 0xee280010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
10585 {"miabb", 0xee2c0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
10586 {"miabt", 0xee2d0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
10587 {"miatb", 0xee2e0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
10588 {"miatt", 0xee2f0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
10589 {"mar", 0xec400000, 3, ARM_CEXT_XSCALE, do_xsc_mar},
10590 {"mra", 0xec500000, 3, ARM_CEXT_XSCALE, do_xsc_mra},
10591
10592 /* Intel Wireless MMX technology instructions. */
10593 {"tandcb", 0xee130130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
10594 {"tandch", 0xee530130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
10595 {"tandcw", 0xee930130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
10596 {"tbcstb", 0xee400010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
10597 {"tbcsth", 0xee400050, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
10598 {"tbcstw", 0xee400090, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
10599 {"textrcb", 0xee130170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
10600 {"textrch", 0xee530170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
10601 {"textrcw", 0xee930170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
10602 {"textrmub", 0xee100070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10603 {"textrmuh", 0xee500070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10604 {"textrmuw", 0xee900070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10605 {"textrmsb", 0xee100078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10606 {"textrmsh", 0xee500078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10607 {"textrmsw", 0xee900078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10608 {"tinsrb", 0xee600010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
10609 {"tinsrh", 0xee600050, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
10610 {"tinsrw", 0xee600090, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
10611 {"tmcr", 0xee000110, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmcr},
10612 {"tmcrr", 0xec400000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_tmcrr},
10613 {"tmia", 0xee200010, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10614 {"tmiaph", 0xee280010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10615 {"tmiabb", 0xee2c0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10616 {"tmiabt", 0xee2d0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10617 {"tmiatb", 0xee2e0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10618 {"tmiatt", 0xee2f0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10619 {"tmovmskb", 0xee100030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
10620 {"tmovmskh", 0xee500030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
10621 {"tmovmskw", 0xee900030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
10622 {"tmrc", 0xee100110, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmrc},
10623 {"tmrrc", 0xec500000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_tmrrc},
10624 {"torcb", 0xee130150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
10625 {"torch", 0xee530150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
10626 {"torcw", 0xee930150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
10627 {"waccb", 0xee0001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10628 {"wacch", 0xee4001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10629 {"waccw", 0xee8001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10630 {"waddbss", 0xee300180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10631 {"waddb", 0xee000180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10632 {"waddbus", 0xee100180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10633 {"waddhss", 0xee700180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10634 {"waddh", 0xee400180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10635 {"waddhus", 0xee500180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10636 {"waddwss", 0xeeb00180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10637 {"waddw", 0xee800180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10638 {"waddwus", 0xee900180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10639 {"waligni", 0xee000020, 7, ARM_CEXT_IWMMXT, do_iwmmxt_waligni},
10640 {"walignr0", 0xee800020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10641 {"walignr1", 0xee900020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10642 {"walignr2", 0xeea00020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10643 {"walignr3", 0xeeb00020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10644 {"wand", 0xee200000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10645 {"wandn", 0xee300000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10646 {"wavg2b", 0xee800000, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10647 {"wavg2br", 0xee900000, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10648 {"wavg2h", 0xeec00000, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10649 {"wavg2hr", 0xeed00000, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10650 {"wcmpeqb", 0xee000060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10651 {"wcmpeqh", 0xee400060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10652 {"wcmpeqw", 0xee800060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10653 {"wcmpgtub", 0xee100060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10654 {"wcmpgtuh", 0xee500060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10655 {"wcmpgtuw", 0xee900060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10656 {"wcmpgtsb", 0xee300060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10657 {"wcmpgtsh", 0xee700060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10658 {"wcmpgtsw", 0xeeb00060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10659 {"wldrb", 0xec100000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
10660 {"wldrh", 0xec100100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
10661 {"wldrw", 0xec100200, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
10662 {"wldrd", 0xec100300, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
10663 {"wmacs", 0xee600100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10664 {"wmacsz", 0xee700100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10665 {"wmacu", 0xee400100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10666 {"wmacuz", 0xee500100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10667 {"wmadds", 0xeea00100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10668 {"wmaddu", 0xee800100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10669 {"wmaxsb", 0xee200160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10670 {"wmaxsh", 0xee600160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10671 {"wmaxsw", 0xeea00160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10672 {"wmaxub", 0xee000160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10673 {"wmaxuh", 0xee400160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10674 {"wmaxuw", 0xee800160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10675 {"wminsb", 0xee300160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10676 {"wminsh", 0xee700160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10677 {"wminsw", 0xeeb00160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10678 {"wminub", 0xee100160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10679 {"wminuh", 0xee500160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10680 {"wminuw", 0xee900160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10681 {"wmov", 0xee000000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wmov},
10682 {"wmulsm", 0xee300100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10683 {"wmulsl", 0xee200100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10684 {"wmulum", 0xee100100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10685 {"wmulul", 0xee000100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10686 {"wor", 0xee000000, 3, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10687 {"wpackhss", 0xee700080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10688 {"wpackhus", 0xee500080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10689 {"wpackwss", 0xeeb00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10690 {"wpackwus", 0xee900080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10691 {"wpackdss", 0xeef00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10692 {"wpackdus", 0xeed00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10693 {"wrorh", 0xee700040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10694 {"wrorhg", 0xee700148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
10695 {"wrorw", 0xeeb00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10696 {"wrorwg", 0xeeb00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
10697 {"wrord", 0xeef00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10698 {"wrordg", 0xeef00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
10699 {"wsadb", 0xee000120, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10700 {"wsadbz", 0xee100120, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10701 {"wsadh", 0xee400120, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10702 {"wsadhz", 0xee500120, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10703 {"wshufh", 0xee0001e0, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wshufh},
10704 {"wsllh", 0xee500040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10705 {"wsllhg", 0xee500148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
10706 {"wsllw", 0xee900040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10707 {"wsllwg", 0xee900148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
10708 {"wslld", 0xeed00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10709 {"wslldg", 0xeed00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
10710 {"wsrah", 0xee400040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10711 {"wsrahg", 0xee400148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
10712 {"wsraw", 0xee800040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10713 {"wsrawg", 0xee800148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
10714 {"wsrad", 0xeec00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10715 {"wsradg", 0xeec00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
10716 {"wsrlh", 0xee600040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10717 {"wsrlhg", 0xee600148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
10718 {"wsrlw", 0xeea00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10719 {"wsrlwg", 0xeea00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
10720 {"wsrld", 0xeee00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10721 {"wsrldg", 0xeee00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
10722 {"wstrb", 0xec000000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
10723 {"wstrh", 0xec000100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
10724 {"wstrw", 0xec000200, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
10725 {"wstrd", 0xec000300, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
10726 {"wsubbss", 0xee3001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10727 {"wsubb", 0xee0001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10728 {"wsubbus", 0xee1001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10729 {"wsubhss", 0xee7001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10730 {"wsubh", 0xee4001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10731 {"wsubhus", 0xee5001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10732 {"wsubwss", 0xeeb001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10733 {"wsubw", 0xee8001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10734 {"wsubwus", 0xee9001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10735 {"wunpckehub", 0xee0000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10736 {"wunpckehuh", 0xee4000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10737 {"wunpckehuw", 0xee8000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10738 {"wunpckehsb", 0xee2000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10739 {"wunpckehsh", 0xee6000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10740 {"wunpckehsw", 0xeea000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10741 {"wunpckihb", 0xee1000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10742 {"wunpckihh", 0xee5000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10743 {"wunpckihw", 0xee9000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10744 {"wunpckelub", 0xee0000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10745 {"wunpckeluh", 0xee4000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10746 {"wunpckeluw", 0xee8000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10747 {"wunpckelsb", 0xee2000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10748 {"wunpckelsh", 0xee6000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10749 {"wunpckelsw", 0xeea000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10750 {"wunpckilb", 0xee1000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10751 {"wunpckilh", 0xee5000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10752 {"wunpckilw", 0xee9000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10753 {"wxor", 0xee100000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10754 {"wzero", 0xee300000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wzero},
10755
10756 /* Cirrus Maverick instructions. */
10757 {"cfldrs", 0xec100400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_1},
10758 {"cfldrd", 0xec500400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_2},
10759 {"cfldr32", 0xec100500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_3},
10760 {"cfldr64", 0xec500500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_4},
10761 {"cfstrs", 0xec000400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_1},
10762 {"cfstrd", 0xec400400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_2},
10763 {"cfstr32", 0xec000500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_3},
10764 {"cfstr64", 0xec400500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_4},
10765 {"cfmvsr", 0xee000450, 6, ARM_CEXT_MAVERICK, do_mav_binops_2a},
10766 {"cfmvrs", 0xee100450, 6, ARM_CEXT_MAVERICK, do_mav_binops_1a},
10767 {"cfmvdlr", 0xee000410, 7, ARM_CEXT_MAVERICK, do_mav_binops_2b},
10768 {"cfmvrdl", 0xee100410, 7, ARM_CEXT_MAVERICK, do_mav_binops_1b},
10769 {"cfmvdhr", 0xee000430, 7, ARM_CEXT_MAVERICK, do_mav_binops_2b},
10770 {"cfmvrdh", 0xee100430, 7, ARM_CEXT_MAVERICK, do_mav_binops_1b},
10771 {"cfmv64lr", 0xee000510, 8, ARM_CEXT_MAVERICK, do_mav_binops_2c},
10772 {"cfmvr64l", 0xee100510, 8, ARM_CEXT_MAVERICK, do_mav_binops_1c},
10773 {"cfmv64hr", 0xee000530, 8, ARM_CEXT_MAVERICK, do_mav_binops_2c},
10774 {"cfmvr64h", 0xee100530, 8, ARM_CEXT_MAVERICK, do_mav_binops_1c},
10775 {"cfmval32", 0xee200440, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
10776 {"cfmv32al", 0xee100440, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
10777 {"cfmvam32", 0xee200460, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
10778 {"cfmv32am", 0xee100460, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
10779 {"cfmvah32", 0xee200480, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
10780 {"cfmv32ah", 0xee100480, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
10781 {"cfmva32", 0xee2004a0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3a},
10782 {"cfmv32a", 0xee1004a0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3b},
10783 {"cfmva64", 0xee2004c0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3c},
10784 {"cfmv64a", 0xee1004c0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3d},
10785 {"cfmvsc32", 0xee2004e0, 8, ARM_CEXT_MAVERICK, do_mav_dspsc_1},
10786 {"cfmv32sc", 0xee1004e0, 8, ARM_CEXT_MAVERICK, do_mav_dspsc_2},
10787 {"cfcpys", 0xee000400, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
10788 {"cfcpyd", 0xee000420, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
10789 {"cfcvtsd", 0xee000460, 7, ARM_CEXT_MAVERICK, do_mav_binops_1f},
10790 {"cfcvtds", 0xee000440, 7, ARM_CEXT_MAVERICK, do_mav_binops_1g},
10791 {"cfcvt32s", 0xee000480, 8, ARM_CEXT_MAVERICK, do_mav_binops_1h},
10792 {"cfcvt32d", 0xee0004a0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1i},
10793 {"cfcvt64s", 0xee0004c0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1j},
10794 {"cfcvt64d", 0xee0004e0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1k},
10795 {"cfcvts32", 0xee100580, 8, ARM_CEXT_MAVERICK, do_mav_binops_1l},
10796 {"cfcvtd32", 0xee1005a0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1m},
10797 {"cftruncs32", 0xee1005c0, 10, ARM_CEXT_MAVERICK, do_mav_binops_1l},
10798 {"cftruncd32", 0xee1005e0, 10, ARM_CEXT_MAVERICK, do_mav_binops_1m},
10799 {"cfrshl32", 0xee000550, 8, ARM_CEXT_MAVERICK, do_mav_triple_4a},
10800 {"cfrshl64", 0xee000570, 8, ARM_CEXT_MAVERICK, do_mav_triple_4b},
10801 {"cfsh32", 0xee000500, 6, ARM_CEXT_MAVERICK, do_mav_shift_1},
10802 {"cfsh64", 0xee200500, 6, ARM_CEXT_MAVERICK, do_mav_shift_2},
10803 {"cfcmps", 0xee100490, 6, ARM_CEXT_MAVERICK, do_mav_triple_5a},
10804 {"cfcmpd", 0xee1004b0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5b},
10805 {"cfcmp32", 0xee100590, 7, ARM_CEXT_MAVERICK, do_mav_triple_5c},
10806 {"cfcmp64", 0xee1005b0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5d},
10807 {"cfabss", 0xee300400, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
10808 {"cfabsd", 0xee300420, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
10809 {"cfnegs", 0xee300440, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
10810 {"cfnegd", 0xee300460, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
10811 {"cfadds", 0xee300480, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
10812 {"cfaddd", 0xee3004a0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
10813 {"cfsubs", 0xee3004c0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
10814 {"cfsubd", 0xee3004e0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
10815 {"cfmuls", 0xee100400, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
10816 {"cfmuld", 0xee100420, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
10817 {"cfabs32", 0xee300500, 7, ARM_CEXT_MAVERICK, do_mav_binops_1n},
10818 {"cfabs64", 0xee300520, 7, ARM_CEXT_MAVERICK, do_mav_binops_1o},
10819 {"cfneg32", 0xee300540, 7, ARM_CEXT_MAVERICK, do_mav_binops_1n},
10820 {"cfneg64", 0xee300560, 7, ARM_CEXT_MAVERICK, do_mav_binops_1o},
10821 {"cfadd32", 0xee300580, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
10822 {"cfadd64", 0xee3005a0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
10823 {"cfsub32", 0xee3005c0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
10824 {"cfsub64", 0xee3005e0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
10825 {"cfmul32", 0xee100500, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
10826 {"cfmul64", 0xee100520, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
10827 {"cfmac32", 0xee100540, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
10828 {"cfmsc32", 0xee100560, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
10829 {"cfmadd32", 0xee000600, 8, ARM_CEXT_MAVERICK, do_mav_quad_6a},
10830 {"cfmsub32", 0xee100600, 8, ARM_CEXT_MAVERICK, do_mav_quad_6a},
10831 {"cfmadda32", 0xee200600, 9, ARM_CEXT_MAVERICK, do_mav_quad_6b},
10832 {"cfmsuba32", 0xee300600, 9, ARM_CEXT_MAVERICK, do_mav_quad_6b},
10833 };
10834
10835 /* Iterate over the base tables to create the instruction patterns. */
10836
10837 static void
10838 build_arm_ops_hsh (void)
10839 {
10840 unsigned int i;
10841 unsigned int j;
10842 static struct obstack insn_obstack;
10843
10844 obstack_begin (&insn_obstack, 4000);
10845
10846 for (i = 0; i < sizeof (insns) / sizeof (struct asm_opcode); i++)
10847 {
10848 const struct asm_opcode *insn = insns + i;
10849
10850 if (insn->cond_offset != 0)
10851 {
10852 /* Insn supports conditional execution. Build the varaints
10853 and insert them in the hash table. */
10854 for (j = 0; j < sizeof (conds) / sizeof (struct asm_cond); j++)
10855 {
10856 unsigned len = strlen (insn->template);
10857 struct asm_opcode *new;
10858 char *template;
10859
10860 new = obstack_alloc (&insn_obstack, sizeof (struct asm_opcode));
10861 /* All condition codes are two characters. */
10862 template = obstack_alloc (&insn_obstack, len + 3);
10863
10864 strncpy (template, insn->template, insn->cond_offset);
10865 strcpy (template + insn->cond_offset, conds[j].template);
10866 if (len > insn->cond_offset)
10867 strcpy (template + insn->cond_offset + 2,
10868 insn->template + insn->cond_offset);
10869 new->template = template;
10870 new->cond_offset = 0;
10871 new->variant = insn->variant;
10872 new->parms = insn->parms;
10873 new->value = (insn->value & ~COND_MASK) | conds[j].value;
10874
10875 hash_insert (arm_ops_hsh, new->template, (PTR) new);
10876 }
10877 }
10878 /* Finally, insert the unconditional insn in the table directly;
10879 no need to build a copy. */
10880 hash_insert (arm_ops_hsh, insn->template, (PTR) insn);
10881 }
10882 }
10883
10884 #if 0 /* Suppressed - for now. */
10885 #if defined OBJ_ELF || defined OBJ_COFF
10886
10887 #ifdef OBJ_ELF
10888 #define arm_Note Elf_External_Note
10889 #else
10890 typedef struct
10891 {
10892 unsigned char namesz[4]; /* Size of entry's owner string. */
10893 unsigned char descsz[4]; /* Size of the note descriptor. */
10894 unsigned char type[4]; /* Interpretation of the descriptor. */
10895 char name[1]; /* Start of the name+desc data. */
10896 } arm_Note;
10897 #endif
10898
10899 /* The description is kept to a fix sized in order to make updating
10900 it and merging it easier. */
10901 #define ARM_NOTE_DESCRIPTION_LENGTH 8
10902
10903 static void
10904 arm_add_note (const char * name,
10905 const char * description,
10906 unsigned int type)
10907 {
10908 arm_Note note ATTRIBUTE_UNUSED;
10909 char * p;
10910 unsigned int name_len;
10911
10912 name_len = (strlen (name) + 1 + 3) & ~3;
10913
10914 p = frag_more (sizeof (note.namesz));
10915 md_number_to_chars (p, (valueT) name_len, sizeof (note.namesz));
10916
10917 p = frag_more (sizeof (note.descsz));
10918 md_number_to_chars (p, (valueT) ARM_NOTE_DESCRIPTION_LENGTH, sizeof (note.descsz));
10919
10920 p = frag_more (sizeof (note.type));
10921 md_number_to_chars (p, (valueT) type, sizeof (note.type));
10922
10923 p = frag_more (name_len);
10924 strcpy (p, name);
10925
10926 p = frag_more (ARM_NOTE_DESCRIPTION_LENGTH);
10927 strncpy (p, description, ARM_NOTE_DESCRIPTION_LENGTH);
10928 frag_align (2, 0, 0);
10929 }
10930 #endif
10931 #endif
10932
10933 \f
10934 static const struct thumb_opcode tinsns[] =
10935 {
10936 /* Thumb v1 (ARMv4T). */
10937 {"adc", 0x4140, 2, ARM_EXT_V4T, do_t_arit},
10938 {"add", 0x0000, 2, ARM_EXT_V4T, do_t_add},
10939 {"and", 0x4000, 2, ARM_EXT_V4T, do_t_arit},
10940 {"asr", 0x0000, 2, ARM_EXT_V4T, do_t_asr},
10941 {"b", T_OPCODE_BRANCH, 2, ARM_EXT_V4T, do_t_branch12},
10942 {"beq", 0xd0fe, 2, ARM_EXT_V4T, do_t_branch9},
10943 {"bne", 0xd1fe, 2, ARM_EXT_V4T, do_t_branch9},
10944 {"bcs", 0xd2fe, 2, ARM_EXT_V4T, do_t_branch9},
10945 {"bhs", 0xd2fe, 2, ARM_EXT_V4T, do_t_branch9},
10946 {"bcc", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
10947 {"bul", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
10948 {"blo", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
10949 {"bmi", 0xd4fe, 2, ARM_EXT_V4T, do_t_branch9},
10950 {"bpl", 0xd5fe, 2, ARM_EXT_V4T, do_t_branch9},
10951 {"bvs", 0xd6fe, 2, ARM_EXT_V4T, do_t_branch9},
10952 {"bvc", 0xd7fe, 2, ARM_EXT_V4T, do_t_branch9},
10953 {"bhi", 0xd8fe, 2, ARM_EXT_V4T, do_t_branch9},
10954 {"bls", 0xd9fe, 2, ARM_EXT_V4T, do_t_branch9},
10955 {"bge", 0xdafe, 2, ARM_EXT_V4T, do_t_branch9},
10956 {"blt", 0xdbfe, 2, ARM_EXT_V4T, do_t_branch9},
10957 {"bgt", 0xdcfe, 2, ARM_EXT_V4T, do_t_branch9},
10958 {"ble", 0xddfe, 2, ARM_EXT_V4T, do_t_branch9},
10959 {"bal", 0xdefe, 2, ARM_EXT_V4T, do_t_branch9},
10960 {"bic", 0x4380, 2, ARM_EXT_V4T, do_t_arit},
10961 {"bl", 0xf7fffffe, 4, ARM_EXT_V4T, do_t_branch23},
10962 {"bx", 0x4700, 2, ARM_EXT_V4T, do_t_bx},
10963 {"cmn", T_OPCODE_CMN, 2, ARM_EXT_V4T, do_t_arit},
10964 {"cmp", 0x0000, 2, ARM_EXT_V4T, do_t_compare},
10965 {"eor", 0x4040, 2, ARM_EXT_V4T, do_t_arit},
10966 {"ldmia", 0xc800, 2, ARM_EXT_V4T, do_t_ldmstm},
10967 {"ldr", 0x0000, 2, ARM_EXT_V4T, do_t_ldr},
10968 {"ldrb", 0x0000, 2, ARM_EXT_V4T, do_t_ldrb},
10969 {"ldrh", 0x0000, 2, ARM_EXT_V4T, do_t_ldrh},
10970 {"ldrsb", 0x5600, 2, ARM_EXT_V4T, do_t_lds},
10971 {"ldrsh", 0x5e00, 2, ARM_EXT_V4T, do_t_lds},
10972 {"ldsb", 0x5600, 2, ARM_EXT_V4T, do_t_lds},
10973 {"ldsh", 0x5e00, 2, ARM_EXT_V4T, do_t_lds},
10974 {"lsl", 0x0000, 2, ARM_EXT_V4T, do_t_lsl},
10975 {"lsr", 0x0000, 2, ARM_EXT_V4T, do_t_lsr},
10976 {"mov", 0x0000, 2, ARM_EXT_V4T, do_t_mov},
10977 {"mul", T_OPCODE_MUL, 2, ARM_EXT_V4T, do_t_arit},
10978 {"mvn", T_OPCODE_MVN, 2, ARM_EXT_V4T, do_t_arit},
10979 {"neg", T_OPCODE_NEG, 2, ARM_EXT_V4T, do_t_arit},
10980 {"orr", 0x4300, 2, ARM_EXT_V4T, do_t_arit},
10981 {"pop", 0xbc00, 2, ARM_EXT_V4T, do_t_push_pop},
10982 {"push", 0xb400, 2, ARM_EXT_V4T, do_t_push_pop},
10983 {"ror", 0x41c0, 2, ARM_EXT_V4T, do_t_arit},
10984 {"sbc", 0x4180, 2, ARM_EXT_V4T, do_t_arit},
10985 {"stmia", 0xc000, 2, ARM_EXT_V4T, do_t_ldmstm},
10986 {"str", 0x0000, 2, ARM_EXT_V4T, do_t_str},
10987 {"strb", 0x0000, 2, ARM_EXT_V4T, do_t_strb},
10988 {"strh", 0x0000, 2, ARM_EXT_V4T, do_t_strh},
10989 {"swi", 0xdf00, 2, ARM_EXT_V4T, do_t_swi},
10990 {"sub", 0x0000, 2, ARM_EXT_V4T, do_t_sub},
10991 {"tst", T_OPCODE_TST, 2, ARM_EXT_V4T, do_t_arit},
10992 /* Pseudo ops: */
10993 {"adr", 0x0000, 2, ARM_EXT_V4T, do_t_adr},
10994 {"nop", 0x46C0, 2, ARM_EXT_V4T, do_t_nop}, /* mov r8,r8 */
10995 /* Thumb v2 (ARMv5T). */
10996 {"blx", 0, 0, ARM_EXT_V5T, do_t_blx},
10997 {"bkpt", 0xbe00, 2, ARM_EXT_V5T, do_t_bkpt},
10998
10999 /* ARM V6. */
11000 {"cpsie", 0xb660, 2, ARM_EXT_V6, do_t_cps},
11001 {"cpsid", 0xb670, 2, ARM_EXT_V6, do_t_cps},
11002 {"cpy", 0x4600, 2, ARM_EXT_V6, do_t_cpy},
11003 {"rev", 0xba00, 2, ARM_EXT_V6, do_t_arit},
11004 {"rev16", 0xba40, 2, ARM_EXT_V6, do_t_arit},
11005 {"revsh", 0xbac0, 2, ARM_EXT_V6, do_t_arit},
11006 {"setend", 0xb650, 2, ARM_EXT_V6, do_t_setend},
11007 {"sxth", 0xb200, 2, ARM_EXT_V6, do_t_arit},
11008 {"sxtb", 0xb240, 2, ARM_EXT_V6, do_t_arit},
11009 {"uxth", 0xb280, 2, ARM_EXT_V6, do_t_arit},
11010 {"uxtb", 0xb2c0, 2, ARM_EXT_V6, do_t_arit},
11011 };
11012
11013 void
11014 md_begin (void)
11015 {
11016 unsigned mach;
11017 unsigned int i;
11018
11019 if ( (arm_ops_hsh = hash_new ()) == NULL
11020 || (arm_tops_hsh = hash_new ()) == NULL
11021 || (arm_cond_hsh = hash_new ()) == NULL
11022 || (arm_shift_hsh = hash_new ()) == NULL
11023 || (arm_psr_hsh = hash_new ()) == NULL)
11024 as_fatal (_("virtual memory exhausted"));
11025
11026 build_arm_ops_hsh ();
11027 for (i = 0; i < sizeof (tinsns) / sizeof (struct thumb_opcode); i++)
11028 hash_insert (arm_tops_hsh, tinsns[i].template, (PTR) (tinsns + i));
11029 for (i = 0; i < sizeof (conds) / sizeof (struct asm_cond); i++)
11030 hash_insert (arm_cond_hsh, conds[i].template, (PTR) (conds + i));
11031 for (i = 0; i < sizeof (shift_names) / sizeof (struct asm_shift_name); i++)
11032 hash_insert (arm_shift_hsh, shift_names[i].name, (PTR) (shift_names + i));
11033 for (i = 0; i < sizeof (psrs) / sizeof (struct asm_psr); i++)
11034 hash_insert (arm_psr_hsh, psrs[i].template, (PTR) (psrs + i));
11035
11036 for (i = (int) REG_TYPE_FIRST; i < (int) REG_TYPE_MAX; i++)
11037 build_reg_hsh (all_reg_maps + i);
11038
11039 set_constant_flonums ();
11040
11041 /* Set the cpu variant based on the command-line options. We prefer
11042 -mcpu= over -march= if both are set (as for GCC); and we prefer
11043 -mfpu= over any other way of setting the floating point unit.
11044 Use of legacy options with new options are faulted. */
11045 if (legacy_cpu != -1)
11046 {
11047 if (mcpu_cpu_opt != -1 || march_cpu_opt != -1)
11048 as_bad (_("use of old and new-style options to set CPU type"));
11049
11050 mcpu_cpu_opt = legacy_cpu;
11051 }
11052 else if (mcpu_cpu_opt == -1)
11053 mcpu_cpu_opt = march_cpu_opt;
11054
11055 if (legacy_fpu != -1)
11056 {
11057 if (mfpu_opt != -1)
11058 as_bad (_("use of old and new-style options to set FPU type"));
11059
11060 mfpu_opt = legacy_fpu;
11061 }
11062 else if (mfpu_opt == -1)
11063 {
11064 #if !(defined (TE_LINUX) || defined (TE_NetBSD))
11065 /* Some environments specify a default FPU. If they don't, infer it
11066 from the processor. */
11067 if (mcpu_fpu_opt != -1)
11068 mfpu_opt = mcpu_fpu_opt;
11069 else
11070 mfpu_opt = march_fpu_opt;
11071 #else
11072 mfpu_opt = FPU_DEFAULT;
11073 #endif
11074 }
11075
11076 if (mfpu_opt == -1)
11077 {
11078 if (mcpu_cpu_opt == -1)
11079 mfpu_opt = FPU_DEFAULT;
11080 else if (mcpu_cpu_opt & ARM_EXT_V5)
11081 mfpu_opt = FPU_ARCH_VFP_V2;
11082 else
11083 mfpu_opt = FPU_ARCH_FPA;
11084 }
11085
11086 if (mcpu_cpu_opt == -1)
11087 mcpu_cpu_opt = CPU_DEFAULT;
11088
11089 cpu_variant = mcpu_cpu_opt | mfpu_opt;
11090
11091 {
11092 unsigned int flags = 0;
11093
11094 #if defined OBJ_ELF
11095 flags = meabi_flags;
11096
11097 switch (meabi_flags)
11098 {
11099 case EF_ARM_EABI_UNKNOWN:
11100 #endif
11101 #if defined OBJ_COFF || defined OBJ_ELF
11102 /* Set the flags in the private structure. */
11103 if (uses_apcs_26) flags |= F_APCS26;
11104 if (support_interwork) flags |= F_INTERWORK;
11105 if (uses_apcs_float) flags |= F_APCS_FLOAT;
11106 if (pic_code) flags |= F_PIC;
11107 if ((cpu_variant & FPU_ANY) == FPU_NONE
11108 || (cpu_variant & FPU_ANY) == FPU_ARCH_VFP) /* VFP layout only. */
11109 flags |= F_SOFT_FLOAT;
11110
11111 switch (mfloat_abi_opt)
11112 {
11113 case ARM_FLOAT_ABI_SOFT:
11114 case ARM_FLOAT_ABI_SOFTFP:
11115 flags |= F_SOFT_FLOAT;
11116 break;
11117
11118 case ARM_FLOAT_ABI_HARD:
11119 if (flags & F_SOFT_FLOAT)
11120 as_bad (_("hard-float conflicts with specified fpu"));
11121 break;
11122 }
11123
11124 /* Using VFP conventions (even if soft-float). */
11125 if (cpu_variant & FPU_VFP_EXT_NONE)
11126 flags |= F_VFP_FLOAT;
11127 #endif
11128 #if defined OBJ_ELF
11129 if (cpu_variant & FPU_ARCH_MAVERICK)
11130 flags |= EF_ARM_MAVERICK_FLOAT;
11131 break;
11132
11133 case EF_ARM_EABI_VER3:
11134 /* No additional flags to set. */
11135 break;
11136
11137 default:
11138 abort ();
11139 }
11140 #endif
11141 #if defined OBJ_COFF || defined OBJ_ELF
11142 bfd_set_private_flags (stdoutput, flags);
11143
11144 /* We have run out flags in the COFF header to encode the
11145 status of ATPCS support, so instead we create a dummy,
11146 empty, debug section called .arm.atpcs. */
11147 if (atpcs)
11148 {
11149 asection * sec;
11150
11151 sec = bfd_make_section (stdoutput, ".arm.atpcs");
11152
11153 if (sec != NULL)
11154 {
11155 bfd_set_section_flags
11156 (stdoutput, sec, SEC_READONLY | SEC_DEBUGGING /* | SEC_HAS_CONTENTS */);
11157 bfd_set_section_size (stdoutput, sec, 0);
11158 bfd_set_section_contents (stdoutput, sec, NULL, 0, 0);
11159 }
11160 }
11161 #endif
11162 }
11163
11164 /* Record the CPU type as well. */
11165 switch (cpu_variant & ARM_CPU_MASK)
11166 {
11167 case ARM_2:
11168 mach = bfd_mach_arm_2;
11169 break;
11170
11171 case ARM_3: /* Also ARM_250. */
11172 mach = bfd_mach_arm_2a;
11173 break;
11174
11175 case ARM_6: /* Also ARM_7. */
11176 mach = bfd_mach_arm_3;
11177 break;
11178
11179 default:
11180 mach = bfd_mach_arm_unknown;
11181 break;
11182 }
11183
11184 /* Catch special cases. */
11185 if (cpu_variant & ARM_CEXT_IWMMXT)
11186 mach = bfd_mach_arm_iWMMXt;
11187 else if (cpu_variant & ARM_CEXT_XSCALE)
11188 mach = bfd_mach_arm_XScale;
11189 else if (cpu_variant & ARM_CEXT_MAVERICK)
11190 mach = bfd_mach_arm_ep9312;
11191 else if (cpu_variant & ARM_EXT_V5E)
11192 mach = bfd_mach_arm_5TE;
11193 else if (cpu_variant & ARM_EXT_V5)
11194 {
11195 if (cpu_variant & ARM_EXT_V4T)
11196 mach = bfd_mach_arm_5T;
11197 else
11198 mach = bfd_mach_arm_5;
11199 }
11200 else if (cpu_variant & ARM_EXT_V4)
11201 {
11202 if (cpu_variant & ARM_EXT_V4T)
11203 mach = bfd_mach_arm_4T;
11204 else
11205 mach = bfd_mach_arm_4;
11206 }
11207 else if (cpu_variant & ARM_EXT_V3M)
11208 mach = bfd_mach_arm_3M;
11209
11210 #if 0 /* Suppressed - for now. */
11211 #if defined (OBJ_ELF) || defined (OBJ_COFF)
11212
11213 /* Create a .note section to fully identify this arm binary. */
11214
11215 #define NOTE_ARCH_STRING "arch: "
11216
11217 #if defined OBJ_COFF && ! defined NT_VERSION
11218 #define NT_VERSION 1
11219 #define NT_ARCH 2
11220 #endif
11221
11222 {
11223 segT current_seg = now_seg;
11224 subsegT current_subseg = now_subseg;
11225 asection * arm_arch;
11226 const char * arch_string;
11227
11228 arm_arch = bfd_make_section_old_way (stdoutput, ARM_NOTE_SECTION);
11229
11230 #ifdef OBJ_COFF
11231 bfd_set_section_flags (stdoutput, arm_arch,
11232 SEC_DATA | SEC_ALLOC | SEC_LOAD | SEC_LINK_ONCE \
11233 | SEC_HAS_CONTENTS);
11234 #else
11235 bfd_set_section_flags (stdoutput, arm_arch,
11236 SEC_READONLY | SEC_HAS_CONTENTS);
11237 #endif
11238 arm_arch->output_section = arm_arch;
11239 subseg_set (arm_arch, 0);
11240
11241 switch (mach)
11242 {
11243 default:
11244 case bfd_mach_arm_unknown: arch_string = "unknown"; break;
11245 case bfd_mach_arm_2: arch_string = "armv2"; break;
11246 case bfd_mach_arm_2a: arch_string = "armv2a"; break;
11247 case bfd_mach_arm_3: arch_string = "armv3"; break;
11248 case bfd_mach_arm_3M: arch_string = "armv3M"; break;
11249 case bfd_mach_arm_4: arch_string = "armv4"; break;
11250 case bfd_mach_arm_4T: arch_string = "armv4t"; break;
11251 case bfd_mach_arm_5: arch_string = "armv5"; break;
11252 case bfd_mach_arm_5T: arch_string = "armv5t"; break;
11253 case bfd_mach_arm_5TE: arch_string = "armv5te"; break;
11254 case bfd_mach_arm_XScale: arch_string = "XScale"; break;
11255 case bfd_mach_arm_ep9312: arch_string = "ep9312"; break;
11256 case bfd_mach_arm_iWMMXt: arch_string = "iWMMXt"; break;
11257 }
11258
11259 arm_add_note (NOTE_ARCH_STRING, arch_string, NT_ARCH);
11260
11261 subseg_set (current_seg, current_subseg);
11262 }
11263 #endif
11264 #endif /* Suppressed code. */
11265
11266 bfd_set_arch_mach (stdoutput, TARGET_ARCH, mach);
11267 }
11268
11269 /* Turn an integer of n bytes (in val) into a stream of bytes appropriate
11270 for use in the a.out file, and stores them in the array pointed to by buf.
11271 This knows about the endian-ness of the target machine and does
11272 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
11273 2 (short) and 4 (long) Floating numbers are put out as a series of
11274 LITTLENUMS (shorts, here at least). */
11275
11276 void
11277 md_number_to_chars (char * buf, valueT val, int n)
11278 {
11279 if (target_big_endian)
11280 number_to_chars_bigendian (buf, val, n);
11281 else
11282 number_to_chars_littleendian (buf, val, n);
11283 }
11284
11285 static valueT
11286 md_chars_to_number (char * buf, int n)
11287 {
11288 valueT result = 0;
11289 unsigned char * where = (unsigned char *) buf;
11290
11291 if (target_big_endian)
11292 {
11293 while (n--)
11294 {
11295 result <<= 8;
11296 result |= (*where++ & 255);
11297 }
11298 }
11299 else
11300 {
11301 while (n--)
11302 {
11303 result <<= 8;
11304 result |= (where[n] & 255);
11305 }
11306 }
11307
11308 return result;
11309 }
11310
11311 /* Turn a string in input_line_pointer into a floating point constant
11312 of type TYPE, and store the appropriate bytes in *LITP. The number
11313 of LITTLENUMS emitted is stored in *SIZEP. An error message is
11314 returned, or NULL on OK.
11315
11316 Note that fp constants aren't represent in the normal way on the ARM.
11317 In big endian mode, things are as expected. However, in little endian
11318 mode fp constants are big-endian word-wise, and little-endian byte-wise
11319 within the words. For example, (double) 1.1 in big endian mode is
11320 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
11321 the byte sequence 99 99 f1 3f 9a 99 99 99.
11322
11323 ??? The format of 12 byte floats is uncertain according to gcc's arm.h. */
11324
11325 char *
11326 md_atof (int type, char * litP, int * sizeP)
11327 {
11328 int prec;
11329 LITTLENUM_TYPE words[MAX_LITTLENUMS];
11330 char *t;
11331 int i;
11332
11333 switch (type)
11334 {
11335 case 'f':
11336 case 'F':
11337 case 's':
11338 case 'S':
11339 prec = 2;
11340 break;
11341
11342 case 'd':
11343 case 'D':
11344 case 'r':
11345 case 'R':
11346 prec = 4;
11347 break;
11348
11349 case 'x':
11350 case 'X':
11351 prec = 6;
11352 break;
11353
11354 case 'p':
11355 case 'P':
11356 prec = 6;
11357 break;
11358
11359 default:
11360 *sizeP = 0;
11361 return _("bad call to MD_ATOF()");
11362 }
11363
11364 t = atof_ieee (input_line_pointer, type, words);
11365 if (t)
11366 input_line_pointer = t;
11367 *sizeP = prec * 2;
11368
11369 if (target_big_endian)
11370 {
11371 for (i = 0; i < prec; i++)
11372 {
11373 md_number_to_chars (litP, (valueT) words[i], 2);
11374 litP += 2;
11375 }
11376 }
11377 else
11378 {
11379 if (cpu_variant & FPU_ARCH_VFP)
11380 for (i = prec - 1; i >= 0; i--)
11381 {
11382 md_number_to_chars (litP, (valueT) words[i], 2);
11383 litP += 2;
11384 }
11385 else
11386 /* For a 4 byte float the order of elements in `words' is 1 0.
11387 For an 8 byte float the order is 1 0 3 2. */
11388 for (i = 0; i < prec; i += 2)
11389 {
11390 md_number_to_chars (litP, (valueT) words[i + 1], 2);
11391 md_number_to_chars (litP + 2, (valueT) words[i], 2);
11392 litP += 4;
11393 }
11394 }
11395
11396 return 0;
11397 }
11398
11399 /* The knowledge of the PC's pipeline offset is built into the insns
11400 themselves. */
11401
11402 long
11403 md_pcrel_from (fixS * fixP)
11404 {
11405 if (fixP->fx_addsy
11406 && S_GET_SEGMENT (fixP->fx_addsy) == undefined_section
11407 && fixP->fx_subsy == NULL)
11408 return 0;
11409
11410 if (fixP->fx_pcrel && (fixP->fx_r_type == BFD_RELOC_ARM_THUMB_ADD))
11411 {
11412 /* PC relative addressing on the Thumb is slightly odd
11413 as the bottom two bits of the PC are forced to zero
11414 for the calculation. */
11415 return (fixP->fx_where + fixP->fx_frag->fr_address) & ~3;
11416 }
11417
11418 #ifdef TE_WINCE
11419 /* The pattern was adjusted to accommodate CE's off-by-one fixups,
11420 so we un-adjust here to compensate for the accommodation. */
11421 return fixP->fx_where + fixP->fx_frag->fr_address + 8;
11422 #else
11423 return fixP->fx_where + fixP->fx_frag->fr_address;
11424 #endif
11425 }
11426
11427 /* Round up a section size to the appropriate boundary. */
11428
11429 valueT
11430 md_section_align (segT segment ATTRIBUTE_UNUSED,
11431 valueT size)
11432 {
11433 #ifdef OBJ_ELF
11434 return size;
11435 #else
11436 /* Round all sects to multiple of 4. */
11437 return (size + 3) & ~3;
11438 #endif
11439 }
11440
11441 /* Under ELF we need to default _GLOBAL_OFFSET_TABLE.
11442 Otherwise we have no need to default values of symbols. */
11443
11444 symbolS *
11445 md_undefined_symbol (char * name ATTRIBUTE_UNUSED)
11446 {
11447 #ifdef OBJ_ELF
11448 if (name[0] == '_' && name[1] == 'G'
11449 && streq (name, GLOBAL_OFFSET_TABLE_NAME))
11450 {
11451 if (!GOT_symbol)
11452 {
11453 if (symbol_find (name))
11454 as_bad ("GOT already in the symbol table");
11455
11456 GOT_symbol = symbol_new (name, undefined_section,
11457 (valueT) 0, & zero_address_frag);
11458 }
11459
11460 return GOT_symbol;
11461 }
11462 #endif
11463
11464 return 0;
11465 }
11466
11467 void
11468 md_apply_fix3 (fixS * fixP,
11469 valueT * valP,
11470 segT seg)
11471 {
11472 offsetT value = * valP;
11473 offsetT newval;
11474 unsigned int newimm;
11475 unsigned long temp;
11476 int sign;
11477 char * buf = fixP->fx_where + fixP->fx_frag->fr_literal;
11478 arm_fix_data * arm_data = (arm_fix_data *) fixP->tc_fix_data;
11479
11480 assert (fixP->fx_r_type < BFD_RELOC_UNUSED);
11481
11482 /* Note whether this will delete the relocation. */
11483 #if 0
11484 /* Patch from REarnshaw to JDavis (disabled for the moment, since it
11485 doesn't work fully.) */
11486 if ((fixP->fx_addsy == 0 || symbol_constant_p (fixP->fx_addsy))
11487 && !fixP->fx_pcrel)
11488 #else
11489 if (fixP->fx_addsy == 0 && !fixP->fx_pcrel)
11490 #endif
11491 fixP->fx_done = 1;
11492
11493 /* If this symbol is in a different section then we need to leave it for
11494 the linker to deal with. Unfortunately, md_pcrel_from can't tell,
11495 so we have to undo it's effects here. */
11496 if (fixP->fx_pcrel)
11497 {
11498 if (fixP->fx_addsy != NULL
11499 && S_IS_DEFINED (fixP->fx_addsy)
11500 && S_GET_SEGMENT (fixP->fx_addsy) != seg)
11501 {
11502 if (target_oabi
11503 && (fixP->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH
11504 || fixP->fx_r_type == BFD_RELOC_ARM_PCREL_BLX
11505 ))
11506 value = 0;
11507 else
11508 value += md_pcrel_from (fixP);
11509 }
11510 }
11511
11512 /* Remember value for emit_reloc. */
11513 fixP->fx_addnumber = value;
11514
11515 switch (fixP->fx_r_type)
11516 {
11517 case BFD_RELOC_ARM_IMMEDIATE:
11518 /* We claim that this fixup has been processed here,
11519 even if in fact we generate an error because we do
11520 not have a reloc for it, so tc_gen_reloc will reject it. */
11521 fixP->fx_done = 1;
11522
11523 if (fixP->fx_addsy
11524 && ! S_IS_DEFINED (fixP->fx_addsy))
11525 {
11526 as_bad_where (fixP->fx_file, fixP->fx_line,
11527 _("undefined symbol %s used as an immediate value"),
11528 S_GET_NAME (fixP->fx_addsy));
11529 break;
11530 }
11531
11532 newimm = validate_immediate (value);
11533 temp = md_chars_to_number (buf, INSN_SIZE);
11534
11535 /* If the instruction will fail, see if we can fix things up by
11536 changing the opcode. */
11537 if (newimm == (unsigned int) FAIL
11538 && (newimm = negate_data_op (&temp, value)) == (unsigned int) FAIL)
11539 {
11540 as_bad_where (fixP->fx_file, fixP->fx_line,
11541 _("invalid constant (%lx) after fixup"),
11542 (unsigned long) value);
11543 break;
11544 }
11545
11546 newimm |= (temp & 0xfffff000);
11547 md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
11548 break;
11549
11550 case BFD_RELOC_ARM_ADRL_IMMEDIATE:
11551 {
11552 unsigned int highpart = 0;
11553 unsigned int newinsn = 0xe1a00000; /* nop. */
11554
11555 newimm = validate_immediate (value);
11556 temp = md_chars_to_number (buf, INSN_SIZE);
11557
11558 /* If the instruction will fail, see if we can fix things up by
11559 changing the opcode. */
11560 if (newimm == (unsigned int) FAIL
11561 && (newimm = negate_data_op (& temp, value)) == (unsigned int) FAIL)
11562 {
11563 /* No ? OK - try using two ADD instructions to generate
11564 the value. */
11565 newimm = validate_immediate_twopart (value, & highpart);
11566
11567 /* Yes - then make sure that the second instruction is
11568 also an add. */
11569 if (newimm != (unsigned int) FAIL)
11570 newinsn = temp;
11571 /* Still No ? Try using a negated value. */
11572 else if ((newimm = validate_immediate_twopart (- value, & highpart)) != (unsigned int) FAIL)
11573 temp = newinsn = (temp & OPCODE_MASK) | OPCODE_SUB << DATA_OP_SHIFT;
11574 /* Otherwise - give up. */
11575 else
11576 {
11577 as_bad_where (fixP->fx_file, fixP->fx_line,
11578 _("unable to compute ADRL instructions for PC offset of 0x%lx"),
11579 (long) value);
11580 break;
11581 }
11582
11583 /* Replace the first operand in the 2nd instruction (which
11584 is the PC) with the destination register. We have
11585 already added in the PC in the first instruction and we
11586 do not want to do it again. */
11587 newinsn &= ~ 0xf0000;
11588 newinsn |= ((newinsn & 0x0f000) << 4);
11589 }
11590
11591 newimm |= (temp & 0xfffff000);
11592 md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
11593
11594 highpart |= (newinsn & 0xfffff000);
11595 md_number_to_chars (buf + INSN_SIZE, (valueT) highpart, INSN_SIZE);
11596 }
11597 break;
11598
11599 case BFD_RELOC_ARM_OFFSET_IMM:
11600 sign = value >= 0;
11601
11602 if (value < 0)
11603 value = - value;
11604
11605 if (validate_offset_imm (value, 0) == FAIL)
11606 {
11607 as_bad_where (fixP->fx_file, fixP->fx_line,
11608 _("bad immediate value for offset (%ld)"),
11609 (long) value);
11610 break;
11611 }
11612
11613 newval = md_chars_to_number (buf, INSN_SIZE);
11614 newval &= 0xff7ff000;
11615 newval |= value | (sign ? INDEX_UP : 0);
11616 md_number_to_chars (buf, newval, INSN_SIZE);
11617 break;
11618
11619 case BFD_RELOC_ARM_OFFSET_IMM8:
11620 case BFD_RELOC_ARM_HWLITERAL:
11621 sign = value >= 0;
11622
11623 if (value < 0)
11624 value = - value;
11625
11626 if (validate_offset_imm (value, 1) == FAIL)
11627 {
11628 if (fixP->fx_r_type == BFD_RELOC_ARM_HWLITERAL)
11629 as_bad_where (fixP->fx_file, fixP->fx_line,
11630 _("invalid literal constant: pool needs to be closer"));
11631 else
11632 as_bad (_("bad immediate value for half-word offset (%ld)"),
11633 (long) value);
11634 break;
11635 }
11636
11637 newval = md_chars_to_number (buf, INSN_SIZE);
11638 newval &= 0xff7ff0f0;
11639 newval |= ((value >> 4) << 8) | (value & 0xf) | (sign ? INDEX_UP : 0);
11640 md_number_to_chars (buf, newval, INSN_SIZE);
11641 break;
11642
11643 case BFD_RELOC_ARM_LITERAL:
11644 sign = value >= 0;
11645
11646 if (value < 0)
11647 value = - value;
11648
11649 if (validate_offset_imm (value, 0) == FAIL)
11650 {
11651 as_bad_where (fixP->fx_file, fixP->fx_line,
11652 _("invalid literal constant: pool needs to be closer"));
11653 break;
11654 }
11655
11656 newval = md_chars_to_number (buf, INSN_SIZE);
11657 newval &= 0xff7ff000;
11658 newval |= value | (sign ? INDEX_UP : 0);
11659 md_number_to_chars (buf, newval, INSN_SIZE);
11660 break;
11661
11662 case BFD_RELOC_ARM_SHIFT_IMM:
11663 newval = md_chars_to_number (buf, INSN_SIZE);
11664 if (((unsigned long) value) > 32
11665 || (value == 32
11666 && (((newval & 0x60) == 0) || (newval & 0x60) == 0x60)))
11667 {
11668 as_bad_where (fixP->fx_file, fixP->fx_line,
11669 _("shift expression is too large"));
11670 break;
11671 }
11672
11673 if (value == 0)
11674 /* Shifts of zero must be done as lsl. */
11675 newval &= ~0x60;
11676 else if (value == 32)
11677 value = 0;
11678 newval &= 0xfffff07f;
11679 newval |= (value & 0x1f) << 7;
11680 md_number_to_chars (buf, newval, INSN_SIZE);
11681 break;
11682
11683 case BFD_RELOC_ARM_SMI:
11684 if (((unsigned long) value) > 0xffff)
11685 as_bad_where (fixP->fx_file, fixP->fx_line,
11686 _("invalid smi expression"));
11687 newval = md_chars_to_number (buf, INSN_SIZE) & 0xfff000f0;
11688 newval |= (value & 0xf) | ((value & 0xfff0) << 4);
11689 md_number_to_chars (buf, newval, INSN_SIZE);
11690 break;
11691
11692 case BFD_RELOC_ARM_SWI:
11693 if (arm_data->thumb_mode)
11694 {
11695 if (((unsigned long) value) > 0xff)
11696 as_bad_where (fixP->fx_file, fixP->fx_line,
11697 _("invalid swi expression"));
11698 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xff00;
11699 newval |= value;
11700 md_number_to_chars (buf, newval, THUMB_SIZE);
11701 }
11702 else
11703 {
11704 if (((unsigned long) value) > 0x00ffffff)
11705 as_bad_where (fixP->fx_file, fixP->fx_line,
11706 _("invalid swi expression"));
11707 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff000000;
11708 newval |= value;
11709 md_number_to_chars (buf, newval, INSN_SIZE);
11710 }
11711 break;
11712
11713 case BFD_RELOC_ARM_MULTI:
11714 if (((unsigned long) value) > 0xffff)
11715 as_bad_where (fixP->fx_file, fixP->fx_line,
11716 _("invalid expression in load/store multiple"));
11717 newval = value | md_chars_to_number (buf, INSN_SIZE);
11718 md_number_to_chars (buf, newval, INSN_SIZE);
11719 break;
11720
11721 case BFD_RELOC_ARM_PCREL_BRANCH:
11722 newval = md_chars_to_number (buf, INSN_SIZE);
11723
11724 /* Sign-extend a 24-bit number. */
11725 #define SEXT24(x) ((((x) & 0xffffff) ^ (~ 0x7fffff)) + 0x800000)
11726
11727 #ifdef OBJ_ELF
11728 if (! target_oabi)
11729 value = fixP->fx_offset;
11730 #endif
11731
11732 /* We are going to store value (shifted right by two) in the
11733 instruction, in a 24 bit, signed field. Thus we need to check
11734 that none of the top 8 bits of the shifted value (top 7 bits of
11735 the unshifted, unsigned value) are set, or that they are all set. */
11736 if ((value & ~ ((offsetT) 0x1ffffff)) != 0
11737 && ((value & ~ ((offsetT) 0x1ffffff)) != ~ ((offsetT) 0x1ffffff)))
11738 {
11739 #ifdef OBJ_ELF
11740 /* Normally we would be stuck at this point, since we cannot store
11741 the absolute address that is the destination of the branch in the
11742 24 bits of the branch instruction. If however, we happen to know
11743 that the destination of the branch is in the same section as the
11744 branch instruction itself, then we can compute the relocation for
11745 ourselves and not have to bother the linker with it.
11746
11747 FIXME: The tests for OBJ_ELF and ! target_oabi are only here
11748 because I have not worked out how to do this for OBJ_COFF or
11749 target_oabi. */
11750 if (! target_oabi
11751 && fixP->fx_addsy != NULL
11752 && S_IS_DEFINED (fixP->fx_addsy)
11753 && S_GET_SEGMENT (fixP->fx_addsy) == seg)
11754 {
11755 /* Get pc relative value to go into the branch. */
11756 value = * valP;
11757
11758 /* Permit a backward branch provided that enough bits
11759 are set. Allow a forwards branch, provided that
11760 enough bits are clear. */
11761 if ( (value & ~ ((offsetT) 0x1ffffff)) == ~ ((offsetT) 0x1ffffff)
11762 || (value & ~ ((offsetT) 0x1ffffff)) == 0)
11763 fixP->fx_done = 1;
11764 }
11765
11766 if (! fixP->fx_done)
11767 #endif
11768 as_bad_where (fixP->fx_file, fixP->fx_line,
11769 _("GAS can't handle same-section branch dest >= 0x04000000"));
11770 }
11771
11772 value >>= 2;
11773 value += SEXT24 (newval);
11774
11775 if ( (value & ~ ((offsetT) 0xffffff)) != 0
11776 && ((value & ~ ((offsetT) 0xffffff)) != ~ ((offsetT) 0xffffff)))
11777 as_bad_where (fixP->fx_file, fixP->fx_line,
11778 _("out of range branch"));
11779
11780 newval = (value & 0x00ffffff) | (newval & 0xff000000);
11781 md_number_to_chars (buf, newval, INSN_SIZE);
11782 break;
11783
11784 case BFD_RELOC_ARM_PCREL_BLX:
11785 {
11786 offsetT hbit;
11787 newval = md_chars_to_number (buf, INSN_SIZE);
11788
11789 #ifdef OBJ_ELF
11790 if (! target_oabi)
11791 value = fixP->fx_offset;
11792 #endif
11793 hbit = (value >> 1) & 1;
11794 value = (value >> 2) & 0x00ffffff;
11795 value = (value + (newval & 0x00ffffff)) & 0x00ffffff;
11796 newval = value | (newval & 0xfe000000) | (hbit << 24);
11797 md_number_to_chars (buf, newval, INSN_SIZE);
11798 }
11799 break;
11800
11801 case BFD_RELOC_THUMB_PCREL_BRANCH9: /* Conditional branch. */
11802 newval = md_chars_to_number (buf, THUMB_SIZE);
11803 {
11804 addressT diff = (newval & 0xff) << 1;
11805 if (diff & 0x100)
11806 diff |= ~0xff;
11807
11808 value += diff;
11809 if ((value & ~0xff) && ((value & ~0xff) != ~0xff))
11810 as_bad_where (fixP->fx_file, fixP->fx_line,
11811 _("branch out of range"));
11812 newval = (newval & 0xff00) | ((value & 0x1ff) >> 1);
11813 }
11814 md_number_to_chars (buf, newval, THUMB_SIZE);
11815 break;
11816
11817 case BFD_RELOC_THUMB_PCREL_BRANCH12: /* Unconditional branch. */
11818 newval = md_chars_to_number (buf, THUMB_SIZE);
11819 {
11820 addressT diff = (newval & 0x7ff) << 1;
11821 if (diff & 0x800)
11822 diff |= ~0x7ff;
11823
11824 value += diff;
11825 if ((value & ~0x7ff) && ((value & ~0x7ff) != ~0x7ff))
11826 as_bad_where (fixP->fx_file, fixP->fx_line,
11827 _("branch out of range"));
11828 newval = (newval & 0xf800) | ((value & 0xfff) >> 1);
11829 }
11830 md_number_to_chars (buf, newval, THUMB_SIZE);
11831 break;
11832
11833 case BFD_RELOC_THUMB_PCREL_BLX:
11834 case BFD_RELOC_THUMB_PCREL_BRANCH23:
11835 {
11836 offsetT newval2;
11837 addressT diff;
11838
11839 newval = md_chars_to_number (buf, THUMB_SIZE);
11840 newval2 = md_chars_to_number (buf + THUMB_SIZE, THUMB_SIZE);
11841 diff = ((newval & 0x7ff) << 12) | ((newval2 & 0x7ff) << 1);
11842 if (diff & 0x400000)
11843 diff |= ~0x3fffff;
11844 #ifdef OBJ_ELF
11845 value = fixP->fx_offset;
11846 #endif
11847 value += diff;
11848
11849 if ((value & ~0x3fffff) && ((value & ~0x3fffff) != ~0x3fffff))
11850 as_bad_where (fixP->fx_file, fixP->fx_line,
11851 _("branch with link out of range"));
11852
11853 newval = (newval & 0xf800) | ((value & 0x7fffff) >> 12);
11854 newval2 = (newval2 & 0xf800) | ((value & 0xfff) >> 1);
11855 if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX)
11856 /* For a BLX instruction, make sure that the relocation is rounded up
11857 to a word boundary. This follows the semantics of the instruction
11858 which specifies that bit 1 of the target address will come from bit
11859 1 of the base address. */
11860 newval2 = (newval2 + 1) & ~ 1;
11861 md_number_to_chars (buf, newval, THUMB_SIZE);
11862 md_number_to_chars (buf + THUMB_SIZE, newval2, THUMB_SIZE);
11863 }
11864 break;
11865
11866 case BFD_RELOC_8:
11867 if (fixP->fx_done || fixP->fx_pcrel)
11868 md_number_to_chars (buf, value, 1);
11869 #ifdef OBJ_ELF
11870 else if (!target_oabi)
11871 {
11872 value = fixP->fx_offset;
11873 md_number_to_chars (buf, value, 1);
11874 }
11875 #endif
11876 break;
11877
11878 case BFD_RELOC_16:
11879 if (fixP->fx_done || fixP->fx_pcrel)
11880 md_number_to_chars (buf, value, 2);
11881 #ifdef OBJ_ELF
11882 else if (!target_oabi)
11883 {
11884 value = fixP->fx_offset;
11885 md_number_to_chars (buf, value, 2);
11886 }
11887 #endif
11888 break;
11889
11890 #ifdef OBJ_ELF
11891 case BFD_RELOC_ARM_GOT32:
11892 case BFD_RELOC_ARM_GOTOFF:
11893 case BFD_RELOC_ARM_TARGET2:
11894 md_number_to_chars (buf, 0, 4);
11895 break;
11896 #endif
11897
11898 case BFD_RELOC_RVA:
11899 case BFD_RELOC_32:
11900 case BFD_RELOC_ARM_TARGET1:
11901 case BFD_RELOC_ARM_ROSEGREL32:
11902 case BFD_RELOC_ARM_SBREL32:
11903 case BFD_RELOC_32_PCREL:
11904 if (fixP->fx_done || fixP->fx_pcrel)
11905 md_number_to_chars (buf, value, 4);
11906 #ifdef OBJ_ELF
11907 else if (!target_oabi)
11908 {
11909 value = fixP->fx_offset;
11910 md_number_to_chars (buf, value, 4);
11911 }
11912 #endif
11913 break;
11914
11915 #ifdef OBJ_ELF
11916 case BFD_RELOC_ARM_PREL31:
11917 if (fixP->fx_done || fixP->fx_pcrel)
11918 {
11919 newval = md_chars_to_number (buf, 4) & 0x80000000;
11920 if ((value ^ (value >> 1)) & 0x40000000)
11921 {
11922 as_bad_where (fixP->fx_file, fixP->fx_line,
11923 _("rel31 relocation overflow"));
11924 }
11925 newval |= value & 0x7fffffff;
11926 md_number_to_chars (buf, newval, 4);
11927 }
11928 break;
11929
11930 case BFD_RELOC_ARM_PLT32:
11931 /* It appears the instruction is fully prepared at this point. */
11932 break;
11933 #endif
11934
11935 case BFD_RELOC_ARM_CP_OFF_IMM:
11936 sign = value >= 0;
11937 if (value < -1023 || value > 1023 || (value & 3))
11938 as_bad_where (fixP->fx_file, fixP->fx_line,
11939 _("illegal value for co-processor offset"));
11940 if (value < 0)
11941 value = -value;
11942 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
11943 newval |= (value >> 2) | (sign ? INDEX_UP : 0);
11944 md_number_to_chars (buf, newval, INSN_SIZE);
11945 break;
11946
11947 case BFD_RELOC_ARM_CP_OFF_IMM_S2:
11948 sign = value >= 0;
11949 if (value < -255 || value > 255)
11950 as_bad_where (fixP->fx_file, fixP->fx_line,
11951 _("Illegal value for co-processor offset"));
11952 if (value < 0)
11953 value = -value;
11954 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
11955 newval |= value | (sign ? INDEX_UP : 0);
11956 md_number_to_chars (buf, newval , INSN_SIZE);
11957 break;
11958
11959 case BFD_RELOC_ARM_THUMB_OFFSET:
11960 newval = md_chars_to_number (buf, THUMB_SIZE);
11961 /* Exactly what ranges, and where the offset is inserted depends
11962 on the type of instruction, we can establish this from the
11963 top 4 bits. */
11964 switch (newval >> 12)
11965 {
11966 case 4: /* PC load. */
11967 /* Thumb PC loads are somewhat odd, bit 1 of the PC is
11968 forced to zero for these loads, so we will need to round
11969 up the offset if the instruction address is not word
11970 aligned (since the final address produced must be, and
11971 we can only describe word-aligned immediate offsets). */
11972
11973 if ((fixP->fx_frag->fr_address + fixP->fx_where + value) & 3)
11974 as_bad_where (fixP->fx_file, fixP->fx_line,
11975 _("invalid offset, target not word aligned (0x%08X)"),
11976 (unsigned int) (fixP->fx_frag->fr_address
11977 + fixP->fx_where + value));
11978
11979 if ((value + 2) & ~0x3fe)
11980 as_bad_where (fixP->fx_file, fixP->fx_line,
11981 _("invalid offset, value too big (0x%08lX)"),
11982 (long) value);
11983
11984 /* Round up, since pc will be rounded down. */
11985 newval |= (value + 2) >> 2;
11986 break;
11987
11988 case 9: /* SP load/store. */
11989 if (value & ~0x3fc)
11990 as_bad_where (fixP->fx_file, fixP->fx_line,
11991 _("invalid offset, value too big (0x%08lX)"),
11992 (long) value);
11993 newval |= value >> 2;
11994 break;
11995
11996 case 6: /* Word load/store. */
11997 if (value & ~0x7c)
11998 as_bad_where (fixP->fx_file, fixP->fx_line,
11999 _("invalid offset, value too big (0x%08lX)"),
12000 (long) value);
12001 newval |= value << 4; /* 6 - 2. */
12002 break;
12003
12004 case 7: /* Byte load/store. */
12005 if (value & ~0x1f)
12006 as_bad_where (fixP->fx_file, fixP->fx_line,
12007 _("invalid offset, value too big (0x%08lX)"),
12008 (long) value);
12009 newval |= value << 6;
12010 break;
12011
12012 case 8: /* Halfword load/store. */
12013 if (value & ~0x3e)
12014 as_bad_where (fixP->fx_file, fixP->fx_line,
12015 _("invalid offset, value too big (0x%08lX)"),
12016 (long) value);
12017 newval |= value << 5; /* 6 - 1. */
12018 break;
12019
12020 default:
12021 as_bad_where (fixP->fx_file, fixP->fx_line,
12022 "Unable to process relocation for thumb opcode: %lx",
12023 (unsigned long) newval);
12024 break;
12025 }
12026 md_number_to_chars (buf, newval, THUMB_SIZE);
12027 break;
12028
12029 case BFD_RELOC_ARM_THUMB_ADD:
12030 /* This is a complicated relocation, since we use it for all of
12031 the following immediate relocations:
12032
12033 3bit ADD/SUB
12034 8bit ADD/SUB
12035 9bit ADD/SUB SP word-aligned
12036 10bit ADD PC/SP word-aligned
12037
12038 The type of instruction being processed is encoded in the
12039 instruction field:
12040
12041 0x8000 SUB
12042 0x00F0 Rd
12043 0x000F Rs
12044 */
12045 newval = md_chars_to_number (buf, THUMB_SIZE);
12046 {
12047 int rd = (newval >> 4) & 0xf;
12048 int rs = newval & 0xf;
12049 int subtract = newval & 0x8000;
12050
12051 if (rd == REG_SP)
12052 {
12053 if (value & ~0x1fc)
12054 as_bad_where (fixP->fx_file, fixP->fx_line,
12055 _("invalid immediate for stack address calculation"));
12056 newval = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
12057 newval |= value >> 2;
12058 }
12059 else if (rs == REG_PC || rs == REG_SP)
12060 {
12061 if (subtract ||
12062 value & ~0x3fc)
12063 as_bad_where (fixP->fx_file, fixP->fx_line,
12064 _("invalid immediate for address calculation (value = 0x%08lX)"),
12065 (unsigned long) value);
12066 newval = (rs == REG_PC ? T_OPCODE_ADD_PC : T_OPCODE_ADD_SP);
12067 newval |= rd << 8;
12068 newval |= value >> 2;
12069 }
12070 else if (rs == rd)
12071 {
12072 if (value & ~0xff)
12073 as_bad_where (fixP->fx_file, fixP->fx_line,
12074 _("invalid 8bit immediate"));
12075 newval = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
12076 newval |= (rd << 8) | value;
12077 }
12078 else
12079 {
12080 if (value & ~0x7)
12081 as_bad_where (fixP->fx_file, fixP->fx_line,
12082 _("invalid 3bit immediate"));
12083 newval = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
12084 newval |= rd | (rs << 3) | (value << 6);
12085 }
12086 }
12087 md_number_to_chars (buf, newval, THUMB_SIZE);
12088 break;
12089
12090 case BFD_RELOC_ARM_THUMB_IMM:
12091 newval = md_chars_to_number (buf, THUMB_SIZE);
12092 switch (newval >> 11)
12093 {
12094 case 0x04: /* 8bit immediate MOV. */
12095 case 0x05: /* 8bit immediate CMP. */
12096 if (value < 0 || value > 255)
12097 as_bad_where (fixP->fx_file, fixP->fx_line,
12098 _("invalid immediate: %ld is too large"),
12099 (long) value);
12100 newval |= value;
12101 break;
12102
12103 default:
12104 abort ();
12105 }
12106 md_number_to_chars (buf, newval, THUMB_SIZE);
12107 break;
12108
12109 case BFD_RELOC_ARM_THUMB_SHIFT:
12110 /* 5bit shift value (0..31). */
12111 if (value < 0 || value > 31)
12112 as_bad_where (fixP->fx_file, fixP->fx_line,
12113 _("illegal Thumb shift value: %ld"), (long) value);
12114 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xf03f;
12115 newval |= value << 6;
12116 md_number_to_chars (buf, newval, THUMB_SIZE);
12117 break;
12118
12119 case BFD_RELOC_VTABLE_INHERIT:
12120 case BFD_RELOC_VTABLE_ENTRY:
12121 fixP->fx_done = 0;
12122 return;
12123
12124 case BFD_RELOC_NONE:
12125 default:
12126 as_bad_where (fixP->fx_file, fixP->fx_line,
12127 _("bad relocation fixup type (%d)"), fixP->fx_r_type);
12128 }
12129 }
12130
12131 /* Translate internal representation of relocation info to BFD target
12132 format. */
12133
12134 arelent *
12135 tc_gen_reloc (asection * section ATTRIBUTE_UNUSED,
12136 fixS * fixp)
12137 {
12138 arelent * reloc;
12139 bfd_reloc_code_real_type code;
12140
12141 reloc = xmalloc (sizeof (arelent));
12142
12143 reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
12144 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
12145 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
12146
12147 /* @@ Why fx_addnumber sometimes and fx_offset other times? */
12148 #ifndef OBJ_ELF
12149 if (fixp->fx_pcrel == 0)
12150 reloc->addend = fixp->fx_offset;
12151 else
12152 reloc->addend = fixp->fx_offset = reloc->address;
12153 #else /* OBJ_ELF */
12154 reloc->addend = fixp->fx_offset;
12155 #endif
12156
12157 switch (fixp->fx_r_type)
12158 {
12159 case BFD_RELOC_8:
12160 if (fixp->fx_pcrel)
12161 {
12162 code = BFD_RELOC_8_PCREL;
12163 break;
12164 }
12165
12166 case BFD_RELOC_16:
12167 if (fixp->fx_pcrel)
12168 {
12169 code = BFD_RELOC_16_PCREL;
12170 break;
12171 }
12172
12173 case BFD_RELOC_32:
12174 if (fixp->fx_pcrel)
12175 {
12176 code = BFD_RELOC_32_PCREL;
12177 break;
12178 }
12179
12180 case BFD_RELOC_ARM_PCREL_BRANCH:
12181 case BFD_RELOC_ARM_PCREL_BLX:
12182 case BFD_RELOC_RVA:
12183 case BFD_RELOC_THUMB_PCREL_BRANCH9:
12184 case BFD_RELOC_THUMB_PCREL_BRANCH12:
12185 case BFD_RELOC_THUMB_PCREL_BRANCH23:
12186 case BFD_RELOC_THUMB_PCREL_BLX:
12187 case BFD_RELOC_VTABLE_ENTRY:
12188 case BFD_RELOC_VTABLE_INHERIT:
12189 code = fixp->fx_r_type;
12190 break;
12191
12192 case BFD_RELOC_ARM_LITERAL:
12193 case BFD_RELOC_ARM_HWLITERAL:
12194 /* If this is called then the a literal has
12195 been referenced across a section boundary. */
12196 as_bad_where (fixp->fx_file, fixp->fx_line,
12197 _("literal referenced across section boundary"));
12198 return NULL;
12199
12200 #ifdef OBJ_ELF
12201 case BFD_RELOC_ARM_GOT32:
12202 case BFD_RELOC_ARM_GOTOFF:
12203 case BFD_RELOC_ARM_PLT32:
12204 case BFD_RELOC_ARM_TARGET1:
12205 case BFD_RELOC_ARM_ROSEGREL32:
12206 case BFD_RELOC_ARM_SBREL32:
12207 case BFD_RELOC_ARM_PREL31:
12208 case BFD_RELOC_ARM_TARGET2:
12209 code = fixp->fx_r_type;
12210 break;
12211 #endif
12212
12213 case BFD_RELOC_ARM_IMMEDIATE:
12214 as_bad_where (fixp->fx_file, fixp->fx_line,
12215 _("internal relocation (type: IMMEDIATE) not fixed up"));
12216 return NULL;
12217
12218 case BFD_RELOC_ARM_ADRL_IMMEDIATE:
12219 as_bad_where (fixp->fx_file, fixp->fx_line,
12220 _("ADRL used for a symbol not defined in the same file"));
12221 return NULL;
12222
12223 case BFD_RELOC_ARM_OFFSET_IMM:
12224 if (fixp->fx_addsy != NULL
12225 && !S_IS_DEFINED (fixp->fx_addsy)
12226 && S_IS_LOCAL (fixp->fx_addsy))
12227 {
12228 as_bad_where (fixp->fx_file, fixp->fx_line,
12229 _("undefined local label `%s'"),
12230 S_GET_NAME (fixp->fx_addsy));
12231 return NULL;
12232 }
12233
12234 as_bad_where (fixp->fx_file, fixp->fx_line,
12235 _("internal_relocation (type: OFFSET_IMM) not fixed up"));
12236 return NULL;
12237
12238 default:
12239 {
12240 char * type;
12241
12242 switch (fixp->fx_r_type)
12243 {
12244 case BFD_RELOC_ARM_OFFSET_IMM8: type = "OFFSET_IMM8"; break;
12245 case BFD_RELOC_ARM_SHIFT_IMM: type = "SHIFT_IMM"; break;
12246 case BFD_RELOC_ARM_SMI: type = "SMI"; break;
12247 case BFD_RELOC_ARM_SWI: type = "SWI"; break;
12248 case BFD_RELOC_ARM_MULTI: type = "MULTI"; break;
12249 case BFD_RELOC_ARM_CP_OFF_IMM: type = "CP_OFF_IMM"; break;
12250 case BFD_RELOC_ARM_THUMB_ADD: type = "THUMB_ADD"; break;
12251 case BFD_RELOC_ARM_THUMB_SHIFT: type = "THUMB_SHIFT"; break;
12252 case BFD_RELOC_ARM_THUMB_IMM: type = "THUMB_IMM"; break;
12253 case BFD_RELOC_ARM_THUMB_OFFSET: type = "THUMB_OFFSET"; break;
12254 default: type = _("<unknown>"); break;
12255 }
12256 as_bad_where (fixp->fx_file, fixp->fx_line,
12257 _("cannot represent %s relocation in this object file format"),
12258 type);
12259 return NULL;
12260 }
12261 }
12262
12263 #ifdef OBJ_ELF
12264 if ((code == BFD_RELOC_32_PCREL || code == BFD_RELOC_32)
12265 && GOT_symbol
12266 && fixp->fx_addsy == GOT_symbol)
12267 {
12268 code = BFD_RELOC_ARM_GOTPC;
12269 reloc->addend = fixp->fx_offset = reloc->address;
12270 }
12271 #endif
12272
12273 reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
12274
12275 if (reloc->howto == NULL)
12276 {
12277 as_bad_where (fixp->fx_file, fixp->fx_line,
12278 _("cannot represent %s relocation in this object file format"),
12279 bfd_get_reloc_code_name (code));
12280 return NULL;
12281 }
12282
12283 /* HACK: Since arm ELF uses Rel instead of Rela, encode the
12284 vtable entry to be used in the relocation's section offset. */
12285 if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
12286 reloc->address = fixp->fx_offset;
12287
12288 return reloc;
12289 }
12290
12291 int
12292 md_estimate_size_before_relax (fragS * fragP ATTRIBUTE_UNUSED,
12293 segT segtype ATTRIBUTE_UNUSED)
12294 {
12295 as_fatal (_("md_estimate_size_before_relax\n"));
12296 return 1;
12297 }
12298
12299 /* We need to be able to fix up arbitrary expressions in some statements.
12300 This is so that we can handle symbols that are an arbitrary distance from
12301 the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
12302 which returns part of an address in a form which will be valid for
12303 a data instruction. We do this by pushing the expression into a symbol
12304 in the expr_section, and creating a fix for that. */
12305
12306 static void
12307 fix_new_arm (fragS * frag,
12308 int where,
12309 short int size,
12310 expressionS * exp,
12311 int pc_rel,
12312 int reloc)
12313 {
12314 fixS * new_fix;
12315 arm_fix_data * arm_data;
12316
12317 switch (exp->X_op)
12318 {
12319 case O_constant:
12320 case O_symbol:
12321 case O_add:
12322 case O_subtract:
12323 new_fix = fix_new_exp (frag, where, size, exp, pc_rel, reloc);
12324 break;
12325
12326 default:
12327 new_fix = fix_new (frag, where, size, make_expr_symbol (exp), 0,
12328 pc_rel, reloc);
12329 break;
12330 }
12331
12332 /* Mark whether the fix is to a THUMB instruction, or an ARM
12333 instruction. */
12334 arm_data = obstack_alloc (& notes, sizeof (arm_fix_data));
12335 new_fix->tc_fix_data = (PTR) arm_data;
12336 arm_data->thumb_mode = thumb_mode;
12337 }
12338
12339 static void
12340 output_inst (const char * str)
12341 {
12342 char * to = NULL;
12343
12344 if (inst.error)
12345 {
12346 as_bad ("%s -- `%s'", inst.error, str);
12347 return;
12348 }
12349
12350 to = frag_more (inst.size);
12351
12352 if (thumb_mode && (inst.size > THUMB_SIZE))
12353 {
12354 assert (inst.size == (2 * THUMB_SIZE));
12355 md_number_to_chars (to, inst.instruction >> 16, THUMB_SIZE);
12356 md_number_to_chars (to + THUMB_SIZE, inst.instruction, THUMB_SIZE);
12357 }
12358 else if (inst.size > INSN_SIZE)
12359 {
12360 assert (inst.size == (2 * INSN_SIZE));
12361 md_number_to_chars (to, inst.instruction, INSN_SIZE);
12362 md_number_to_chars (to + INSN_SIZE, inst.instruction, INSN_SIZE);
12363 }
12364 else
12365 md_number_to_chars (to, inst.instruction, inst.size);
12366
12367 if (inst.reloc.type != BFD_RELOC_NONE)
12368 fix_new_arm (frag_now, to - frag_now->fr_literal,
12369 inst.size, & inst.reloc.exp, inst.reloc.pc_rel,
12370 inst.reloc.type);
12371
12372 #ifdef OBJ_ELF
12373 dwarf2_emit_insn (inst.size);
12374 #endif
12375 }
12376
12377 void
12378 md_assemble (char * str)
12379 {
12380 char c;
12381 char *p;
12382 char *start;
12383
12384 /* Align the instruction.
12385 This may not be the right thing to do but ... */
12386 #if 0
12387 arm_align (2, 0);
12388 #endif
12389
12390 /* Align the previous label if needed. */
12391 if (last_label_seen != NULL)
12392 {
12393 symbol_set_frag (last_label_seen, frag_now);
12394 S_SET_VALUE (last_label_seen, (valueT) frag_now_fix ());
12395 S_SET_SEGMENT (last_label_seen, now_seg);
12396 }
12397
12398 memset (&inst, '\0', sizeof (inst));
12399 inst.reloc.type = BFD_RELOC_NONE;
12400
12401 skip_whitespace (str);
12402
12403 /* Scan up to the end of the op-code, which must end in white space or
12404 end of string. */
12405 for (start = p = str; *p != '\0'; p++)
12406 if (*p == ' ')
12407 break;
12408
12409 if (p == str)
12410 {
12411 as_bad (_("no operator -- statement `%s'\n"), str);
12412 return;
12413 }
12414
12415 if (thumb_mode)
12416 {
12417 const struct thumb_opcode * opcode;
12418
12419 c = *p;
12420 *p = '\0';
12421 opcode = (const struct thumb_opcode *) hash_find (arm_tops_hsh, str);
12422 *p = c;
12423
12424 if (opcode)
12425 {
12426 /* Check that this instruction is supported for this CPU. */
12427 if (thumb_mode == 1 && (opcode->variant & cpu_variant) == 0)
12428 {
12429 as_bad (_("selected processor does not support `%s'"), str);
12430 return;
12431 }
12432
12433 mapping_state (MAP_THUMB);
12434 inst.instruction = opcode->value;
12435 inst.size = opcode->size;
12436 opcode->parms (p);
12437 output_inst (str);
12438 return;
12439 }
12440 }
12441 else
12442 {
12443 const struct asm_opcode * opcode;
12444
12445 c = *p;
12446 *p = '\0';
12447 opcode = (const struct asm_opcode *) hash_find (arm_ops_hsh, str);
12448 *p = c;
12449
12450 if (opcode)
12451 {
12452 /* Check that this instruction is supported for this CPU. */
12453 if ((opcode->variant & cpu_variant) == 0)
12454 {
12455 as_bad (_("selected processor does not support `%s'"), str);
12456 return;
12457 }
12458
12459 mapping_state (MAP_ARM);
12460 inst.instruction = opcode->value;
12461 inst.size = INSN_SIZE;
12462 opcode->parms (p);
12463 output_inst (str);
12464 return;
12465 }
12466 }
12467
12468 /* It wasn't an instruction, but it might be a register alias of the form
12469 alias .req reg. */
12470 if (create_register_alias (str, p))
12471 return;
12472
12473 as_bad (_("bad instruction `%s'"), start);
12474 }
12475
12476 /* md_parse_option
12477 Invocation line includes a switch not recognized by the base assembler.
12478 See if it's a processor-specific option.
12479
12480 This routine is somewhat complicated by the need for backwards
12481 compatibility (since older releases of gcc can't be changed).
12482 The new options try to make the interface as compatible as
12483 possible with GCC.
12484
12485 New options (supported) are:
12486
12487 -mcpu=<cpu name> Assemble for selected processor
12488 -march=<architecture name> Assemble for selected architecture
12489 -mfpu=<fpu architecture> Assemble for selected FPU.
12490 -EB/-mbig-endian Big-endian
12491 -EL/-mlittle-endian Little-endian
12492 -k Generate PIC code
12493 -mthumb Start in Thumb mode
12494 -mthumb-interwork Code supports ARM/Thumb interworking
12495
12496 For now we will also provide support for:
12497
12498 -mapcs-32 32-bit Program counter
12499 -mapcs-26 26-bit Program counter
12500 -macps-float Floats passed in FP registers
12501 -mapcs-reentrant Reentrant code
12502 -matpcs
12503 (sometime these will probably be replaced with -mapcs=<list of options>
12504 and -matpcs=<list of options>)
12505
12506 The remaining options are only supported for back-wards compatibility.
12507 Cpu variants, the arm part is optional:
12508 -m[arm]1 Currently not supported.
12509 -m[arm]2, -m[arm]250 Arm 2 and Arm 250 processor
12510 -m[arm]3 Arm 3 processor
12511 -m[arm]6[xx], Arm 6 processors
12512 -m[arm]7[xx][t][[d]m] Arm 7 processors
12513 -m[arm]8[10] Arm 8 processors
12514 -m[arm]9[20][tdmi] Arm 9 processors
12515 -mstrongarm[110[0]] StrongARM processors
12516 -mxscale XScale processors
12517 -m[arm]v[2345[t[e]]] Arm architectures
12518 -mall All (except the ARM1)
12519 FP variants:
12520 -mfpa10, -mfpa11 FPA10 and 11 co-processor instructions
12521 -mfpe-old (No float load/store multiples)
12522 -mvfpxd VFP Single precision
12523 -mvfp All VFP
12524 -mno-fpu Disable all floating point instructions
12525
12526 The following CPU names are recognized:
12527 arm1, arm2, arm250, arm3, arm6, arm600, arm610, arm620,
12528 arm7, arm7m, arm7d, arm7dm, arm7di, arm7dmi, arm70, arm700,
12529 arm700i, arm710 arm710t, arm720, arm720t, arm740t, arm710c,
12530 arm7100, arm7500, arm7500fe, arm7tdmi, arm8, arm810, arm9,
12531 arm920, arm920t, arm940t, arm946, arm966, arm9tdmi, arm9e,
12532 arm10t arm10e, arm1020t, arm1020e, arm10200e,
12533 strongarm, strongarm110, strongarm1100, strongarm1110, xscale.
12534
12535 */
12536
12537 const char * md_shortopts = "m:k";
12538
12539 #ifdef ARM_BI_ENDIAN
12540 #define OPTION_EB (OPTION_MD_BASE + 0)
12541 #define OPTION_EL (OPTION_MD_BASE + 1)
12542 #else
12543 #if TARGET_BYTES_BIG_ENDIAN
12544 #define OPTION_EB (OPTION_MD_BASE + 0)
12545 #else
12546 #define OPTION_EL (OPTION_MD_BASE + 1)
12547 #endif
12548 #endif
12549
12550 struct option md_longopts[] =
12551 {
12552 #ifdef OPTION_EB
12553 {"EB", no_argument, NULL, OPTION_EB},
12554 #endif
12555 #ifdef OPTION_EL
12556 {"EL", no_argument, NULL, OPTION_EL},
12557 #endif
12558 {NULL, no_argument, NULL, 0}
12559 };
12560
12561 size_t md_longopts_size = sizeof (md_longopts);
12562
12563 struct arm_option_table
12564 {
12565 char *option; /* Option name to match. */
12566 char *help; /* Help information. */
12567 int *var; /* Variable to change. */
12568 int value; /* What to change it to. */
12569 char *deprecated; /* If non-null, print this message. */
12570 };
12571
12572 struct arm_option_table arm_opts[] =
12573 {
12574 {"k", N_("generate PIC code"), &pic_code, 1, NULL},
12575 {"mthumb", N_("assemble Thumb code"), &thumb_mode, 1, NULL},
12576 {"mthumb-interwork", N_("support ARM/Thumb interworking"),
12577 &support_interwork, 1, NULL},
12578 {"moabi", N_("use old ABI (ELF only)"), &target_oabi, 1, NULL},
12579 {"mapcs-32", N_("code uses 32-bit program counter"), &uses_apcs_26, 0, NULL},
12580 {"mapcs-26", N_("code uses 26-bit program counter"), &uses_apcs_26, 1, NULL},
12581 {"mapcs-float", N_("floating point args are in fp regs"), &uses_apcs_float,
12582 1, NULL},
12583 {"mapcs-reentrant", N_("re-entrant code"), &pic_code, 1, NULL},
12584 {"matpcs", N_("code is ATPCS conformant"), &atpcs, 1, NULL},
12585 {"mbig-endian", N_("assemble for big-endian"), &target_big_endian, 1, NULL},
12586 {"mlittle-endian", N_("assemble for little-endian"), &target_big_endian, 1,
12587 NULL},
12588
12589 /* These are recognized by the assembler, but have no affect on code. */
12590 {"mapcs-frame", N_("use frame pointer"), NULL, 0, NULL},
12591 {"mapcs-stack-check", N_("use stack size checking"), NULL, 0, NULL},
12592
12593 /* DON'T add any new processors to this list -- we want the whole list
12594 to go away... Add them to the processors table instead. */
12595 {"marm1", NULL, &legacy_cpu, ARM_ARCH_V1, N_("use -mcpu=arm1")},
12596 {"m1", NULL, &legacy_cpu, ARM_ARCH_V1, N_("use -mcpu=arm1")},
12597 {"marm2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -mcpu=arm2")},
12598 {"m2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -mcpu=arm2")},
12599 {"marm250", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm250")},
12600 {"m250", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm250")},
12601 {"marm3", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm3")},
12602 {"m3", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm3")},
12603 {"marm6", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm6")},
12604 {"m6", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm6")},
12605 {"marm600", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm600")},
12606 {"m600", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm600")},
12607 {"marm610", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm610")},
12608 {"m610", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm610")},
12609 {"marm620", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm620")},
12610 {"m620", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm620")},
12611 {"marm7", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7")},
12612 {"m7", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7")},
12613 {"marm70", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm70")},
12614 {"m70", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm70")},
12615 {"marm700", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700")},
12616 {"m700", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700")},
12617 {"marm700i", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700i")},
12618 {"m700i", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700i")},
12619 {"marm710", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710")},
12620 {"m710", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710")},
12621 {"marm710c", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710c")},
12622 {"m710c", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710c")},
12623 {"marm720", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm720")},
12624 {"m720", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm720")},
12625 {"marm7d", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7d")},
12626 {"m7d", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7d")},
12627 {"marm7di", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7di")},
12628 {"m7di", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7di")},
12629 {"marm7m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7m")},
12630 {"m7m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7m")},
12631 {"marm7dm", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dm")},
12632 {"m7dm", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dm")},
12633 {"marm7dmi", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dmi")},
12634 {"m7dmi", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dmi")},
12635 {"marm7100", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7100")},
12636 {"m7100", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7100")},
12637 {"marm7500", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500")},
12638 {"m7500", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500")},
12639 {"marm7500fe", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500fe")},
12640 {"m7500fe", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500fe")},
12641 {"marm7t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
12642 {"m7t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
12643 {"marm7tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
12644 {"m7tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
12645 {"marm710t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm710t")},
12646 {"m710t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm710t")},
12647 {"marm720t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm720t")},
12648 {"m720t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm720t")},
12649 {"marm740t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm740t")},
12650 {"m740t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm740t")},
12651 {"marm8", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm8")},
12652 {"m8", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm8")},
12653 {"marm810", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm810")},
12654 {"m810", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm810")},
12655 {"marm9", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9")},
12656 {"m9", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9")},
12657 {"marm9tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9tdmi")},
12658 {"m9tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9tdmi")},
12659 {"marm920", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm920")},
12660 {"m920", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm920")},
12661 {"marm940", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm940")},
12662 {"m940", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm940")},
12663 {"mstrongarm", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=strongarm")},
12664 {"mstrongarm110", NULL, &legacy_cpu, ARM_ARCH_V4,
12665 N_("use -mcpu=strongarm110")},
12666 {"mstrongarm1100", NULL, &legacy_cpu, ARM_ARCH_V4,
12667 N_("use -mcpu=strongarm1100")},
12668 {"mstrongarm1110", NULL, &legacy_cpu, ARM_ARCH_V4,
12669 N_("use -mcpu=strongarm1110")},
12670 {"mxscale", NULL, &legacy_cpu, ARM_ARCH_XSCALE, N_("use -mcpu=xscale")},
12671 {"miwmmxt", NULL, &legacy_cpu, ARM_ARCH_IWMMXT, N_("use -mcpu=iwmmxt")},
12672 {"mall", NULL, &legacy_cpu, ARM_ANY, N_("use -mcpu=all")},
12673
12674 /* Architecture variants -- don't add any more to this list either. */
12675 {"mv2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -march=armv2")},
12676 {"marmv2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -march=armv2")},
12677 {"mv2a", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -march=armv2a")},
12678 {"marmv2a", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -march=armv2a")},
12679 {"mv3", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -march=armv3")},
12680 {"marmv3", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -march=armv3")},
12681 {"mv3m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -march=armv3m")},
12682 {"marmv3m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -march=armv3m")},
12683 {"mv4", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -march=armv4")},
12684 {"marmv4", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -march=armv4")},
12685 {"mv4t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -march=armv4t")},
12686 {"marmv4t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -march=armv4t")},
12687 {"mv5", NULL, &legacy_cpu, ARM_ARCH_V5, N_("use -march=armv5")},
12688 {"marmv5", NULL, &legacy_cpu, ARM_ARCH_V5, N_("use -march=armv5")},
12689 {"mv5t", NULL, &legacy_cpu, ARM_ARCH_V5T, N_("use -march=armv5t")},
12690 {"marmv5t", NULL, &legacy_cpu, ARM_ARCH_V5T, N_("use -march=armv5t")},
12691 {"mv5e", NULL, &legacy_cpu, ARM_ARCH_V5TE, N_("use -march=armv5te")},
12692 {"marmv5e", NULL, &legacy_cpu, ARM_ARCH_V5TE, N_("use -march=armv5te")},
12693
12694 /* Floating point variants -- don't add any more to this list either. */
12695 {"mfpe-old", NULL, &legacy_fpu, FPU_ARCH_FPE, N_("use -mfpu=fpe")},
12696 {"mfpa10", NULL, &legacy_fpu, FPU_ARCH_FPA, N_("use -mfpu=fpa10")},
12697 {"mfpa11", NULL, &legacy_fpu, FPU_ARCH_FPA, N_("use -mfpu=fpa11")},
12698 {"mno-fpu", NULL, &legacy_fpu, 0,
12699 N_("use either -mfpu=softfpa or -mfpu=softvfp")},
12700
12701 {NULL, NULL, NULL, 0, NULL}
12702 };
12703
12704 struct arm_cpu_option_table
12705 {
12706 char *name;
12707 int value;
12708 /* For some CPUs we assume an FPU unless the user explicitly sets
12709 -mfpu=... */
12710 int default_fpu;
12711 };
12712
12713 /* This list should, at a minimum, contain all the cpu names
12714 recognized by GCC. */
12715 static struct arm_cpu_option_table arm_cpus[] =
12716 {
12717 {"all", ARM_ANY, FPU_ARCH_FPA},
12718 {"arm1", ARM_ARCH_V1, FPU_ARCH_FPA},
12719 {"arm2", ARM_ARCH_V2, FPU_ARCH_FPA},
12720 {"arm250", ARM_ARCH_V2S, FPU_ARCH_FPA},
12721 {"arm3", ARM_ARCH_V2S, FPU_ARCH_FPA},
12722 {"arm6", ARM_ARCH_V3, FPU_ARCH_FPA},
12723 {"arm60", ARM_ARCH_V3, FPU_ARCH_FPA},
12724 {"arm600", ARM_ARCH_V3, FPU_ARCH_FPA},
12725 {"arm610", ARM_ARCH_V3, FPU_ARCH_FPA},
12726 {"arm620", ARM_ARCH_V3, FPU_ARCH_FPA},
12727 {"arm7", ARM_ARCH_V3, FPU_ARCH_FPA},
12728 {"arm7m", ARM_ARCH_V3M, FPU_ARCH_FPA},
12729 {"arm7d", ARM_ARCH_V3, FPU_ARCH_FPA},
12730 {"arm7dm", ARM_ARCH_V3M, FPU_ARCH_FPA},
12731 {"arm7di", ARM_ARCH_V3, FPU_ARCH_FPA},
12732 {"arm7dmi", ARM_ARCH_V3M, FPU_ARCH_FPA},
12733 {"arm70", ARM_ARCH_V3, FPU_ARCH_FPA},
12734 {"arm700", ARM_ARCH_V3, FPU_ARCH_FPA},
12735 {"arm700i", ARM_ARCH_V3, FPU_ARCH_FPA},
12736 {"arm710", ARM_ARCH_V3, FPU_ARCH_FPA},
12737 {"arm710t", ARM_ARCH_V4T, FPU_ARCH_FPA},
12738 {"arm720", ARM_ARCH_V3, FPU_ARCH_FPA},
12739 {"arm720t", ARM_ARCH_V4T, FPU_ARCH_FPA},
12740 {"arm740t", ARM_ARCH_V4T, FPU_ARCH_FPA},
12741 {"arm710c", ARM_ARCH_V3, FPU_ARCH_FPA},
12742 {"arm7100", ARM_ARCH_V3, FPU_ARCH_FPA},
12743 {"arm7500", ARM_ARCH_V3, FPU_ARCH_FPA},
12744 {"arm7500fe", ARM_ARCH_V3, FPU_ARCH_FPA},
12745 {"arm7t", ARM_ARCH_V4T, FPU_ARCH_FPA},
12746 {"arm7tdmi", ARM_ARCH_V4T, FPU_ARCH_FPA},
12747 {"arm7tdmi-s", ARM_ARCH_V4T, FPU_ARCH_FPA},
12748 {"arm8", ARM_ARCH_V4, FPU_ARCH_FPA},
12749 {"arm810", ARM_ARCH_V4, FPU_ARCH_FPA},
12750 {"strongarm", ARM_ARCH_V4, FPU_ARCH_FPA},
12751 {"strongarm1", ARM_ARCH_V4, FPU_ARCH_FPA},
12752 {"strongarm110", ARM_ARCH_V4, FPU_ARCH_FPA},
12753 {"strongarm1100", ARM_ARCH_V4, FPU_ARCH_FPA},
12754 {"strongarm1110", ARM_ARCH_V4, FPU_ARCH_FPA},
12755 {"arm9", ARM_ARCH_V4T, FPU_ARCH_FPA},
12756 {"arm920", ARM_ARCH_V4T, FPU_ARCH_FPA},
12757 {"arm920t", ARM_ARCH_V4T, FPU_ARCH_FPA},
12758 {"arm922t", ARM_ARCH_V4T, FPU_ARCH_FPA},
12759 {"arm940t", ARM_ARCH_V4T, FPU_ARCH_FPA},
12760 {"arm9tdmi", ARM_ARCH_V4T, FPU_ARCH_FPA},
12761 /* For V5 or later processors we default to using VFP; but the user
12762 should really set the FPU type explicitly. */
12763 {"arm9e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
12764 {"arm9e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
12765 {"arm926ej", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
12766 {"arm926ejs", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
12767 {"arm926ej-s", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
12768 {"arm946e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
12769 {"arm946e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
12770 {"arm966e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
12771 {"arm966e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
12772 {"arm10t", ARM_ARCH_V5T, FPU_ARCH_VFP_V1},
12773 {"arm10e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
12774 {"arm1020", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
12775 {"arm1020t", ARM_ARCH_V5T, FPU_ARCH_VFP_V1},
12776 {"arm1020e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
12777 {"arm1026ejs", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
12778 {"arm1026ej-s", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
12779 {"arm1136js", ARM_ARCH_V6, FPU_NONE},
12780 {"arm1136j-s", ARM_ARCH_V6, FPU_NONE},
12781 {"arm1136jfs", ARM_ARCH_V6, FPU_ARCH_VFP_V2},
12782 {"arm1136jf-s", ARM_ARCH_V6, FPU_ARCH_VFP_V2},
12783 {"mpcore", ARM_ARCH_V6K, FPU_ARCH_VFP_V2},
12784 {"mpcorenovfp", ARM_ARCH_V6K, FPU_NONE},
12785 {"arm1176jz-s", ARM_ARCH_V6ZK, FPU_NONE},
12786 {"arm1176jzf-s", ARM_ARCH_V6ZK, FPU_ARCH_VFP_V2},
12787 /* ??? XSCALE is really an architecture. */
12788 {"xscale", ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2},
12789 /* ??? iwmmxt is not a processor. */
12790 {"iwmmxt", ARM_ARCH_IWMMXT, FPU_ARCH_VFP_V2},
12791 {"i80200", ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2},
12792 /* Maverick */
12793 {"ep9312", ARM_ARCH_V4T | ARM_CEXT_MAVERICK, FPU_ARCH_MAVERICK},
12794 {NULL, 0, 0}
12795 };
12796
12797 struct arm_arch_option_table
12798 {
12799 char *name;
12800 int value;
12801 int default_fpu;
12802 };
12803
12804 /* This list should, at a minimum, contain all the architecture names
12805 recognized by GCC. */
12806 static struct arm_arch_option_table arm_archs[] =
12807 {
12808 {"all", ARM_ANY, FPU_ARCH_FPA},
12809 {"armv1", ARM_ARCH_V1, FPU_ARCH_FPA},
12810 {"armv2", ARM_ARCH_V2, FPU_ARCH_FPA},
12811 {"armv2a", ARM_ARCH_V2S, FPU_ARCH_FPA},
12812 {"armv2s", ARM_ARCH_V2S, FPU_ARCH_FPA},
12813 {"armv3", ARM_ARCH_V3, FPU_ARCH_FPA},
12814 {"armv3m", ARM_ARCH_V3M, FPU_ARCH_FPA},
12815 {"armv4", ARM_ARCH_V4, FPU_ARCH_FPA},
12816 {"armv4xm", ARM_ARCH_V4xM, FPU_ARCH_FPA},
12817 {"armv4t", ARM_ARCH_V4T, FPU_ARCH_FPA},
12818 {"armv4txm", ARM_ARCH_V4TxM, FPU_ARCH_FPA},
12819 {"armv5", ARM_ARCH_V5, FPU_ARCH_VFP},
12820 {"armv5t", ARM_ARCH_V5T, FPU_ARCH_VFP},
12821 {"armv5txm", ARM_ARCH_V5TxM, FPU_ARCH_VFP},
12822 {"armv5te", ARM_ARCH_V5TE, FPU_ARCH_VFP},
12823 {"armv5texp", ARM_ARCH_V5TExP, FPU_ARCH_VFP},
12824 {"armv5tej", ARM_ARCH_V5TEJ, FPU_ARCH_VFP},
12825 {"armv6", ARM_ARCH_V6, FPU_ARCH_VFP},
12826 {"armv6j", ARM_ARCH_V6, FPU_ARCH_VFP},
12827 {"armv6k", ARM_ARCH_V6K, FPU_ARCH_VFP},
12828 {"armv6z", ARM_ARCH_V6Z, FPU_ARCH_VFP},
12829 {"armv6zk", ARM_ARCH_V6ZK, FPU_ARCH_VFP},
12830 {"xscale", ARM_ARCH_XSCALE, FPU_ARCH_VFP},
12831 {"iwmmxt", ARM_ARCH_IWMMXT, FPU_ARCH_VFP},
12832 {NULL, 0, 0}
12833 };
12834
12835 /* ISA extensions in the co-processor space. */
12836 struct arm_arch_extension_table
12837 {
12838 char *name;
12839 int value;
12840 };
12841
12842 static struct arm_arch_extension_table arm_extensions[] =
12843 {
12844 {"maverick", ARM_CEXT_MAVERICK},
12845 {"xscale", ARM_CEXT_XSCALE},
12846 {"iwmmxt", ARM_CEXT_IWMMXT},
12847 {NULL, 0}
12848 };
12849
12850 struct arm_fpu_option_table
12851 {
12852 char *name;
12853 int value;
12854 };
12855
12856 /* This list should, at a minimum, contain all the fpu names
12857 recognized by GCC. */
12858 static struct arm_fpu_option_table arm_fpus[] =
12859 {
12860 {"softfpa", FPU_NONE},
12861 {"fpe", FPU_ARCH_FPE},
12862 {"fpe2", FPU_ARCH_FPE},
12863 {"fpe3", FPU_ARCH_FPA}, /* Third release supports LFM/SFM. */
12864 {"fpa", FPU_ARCH_FPA},
12865 {"fpa10", FPU_ARCH_FPA},
12866 {"fpa11", FPU_ARCH_FPA},
12867 {"arm7500fe", FPU_ARCH_FPA},
12868 {"softvfp", FPU_ARCH_VFP},
12869 {"softvfp+vfp", FPU_ARCH_VFP_V2},
12870 {"vfp", FPU_ARCH_VFP_V2},
12871 {"vfp9", FPU_ARCH_VFP_V2},
12872 {"vfp10", FPU_ARCH_VFP_V2},
12873 {"vfp10-r0", FPU_ARCH_VFP_V1},
12874 {"vfpxd", FPU_ARCH_VFP_V1xD},
12875 {"arm1020t", FPU_ARCH_VFP_V1},
12876 {"arm1020e", FPU_ARCH_VFP_V2},
12877 {"arm1136jfs", FPU_ARCH_VFP_V2},
12878 {"arm1136jf-s", FPU_ARCH_VFP_V2},
12879 {"maverick", FPU_ARCH_MAVERICK},
12880 {NULL, 0}
12881 };
12882
12883 struct arm_float_abi_option_table
12884 {
12885 char *name;
12886 int value;
12887 };
12888
12889 static struct arm_float_abi_option_table arm_float_abis[] =
12890 {
12891 {"hard", ARM_FLOAT_ABI_HARD},
12892 {"softfp", ARM_FLOAT_ABI_SOFTFP},
12893 {"soft", ARM_FLOAT_ABI_SOFT},
12894 {NULL, 0}
12895 };
12896
12897 struct arm_eabi_option_table
12898 {
12899 char *name;
12900 unsigned int value;
12901 };
12902
12903 #ifdef OBJ_ELF
12904 /* We only know hot to output GNU and ver 3 (AAELF) formats. */
12905 static struct arm_eabi_option_table arm_eabis[] =
12906 {
12907 {"gnu", EF_ARM_EABI_UNKNOWN},
12908 {"3", EF_ARM_EABI_VER3},
12909 {NULL, 0}
12910 };
12911 #endif
12912
12913 struct arm_long_option_table
12914 {
12915 char * option; /* Substring to match. */
12916 char * help; /* Help information. */
12917 int (* func) (char * subopt); /* Function to decode sub-option. */
12918 char * deprecated; /* If non-null, print this message. */
12919 };
12920
12921 static int
12922 arm_parse_extension (char * str, int * opt_p)
12923 {
12924 while (str != NULL && *str != 0)
12925 {
12926 struct arm_arch_extension_table * opt;
12927 char * ext;
12928 int optlen;
12929
12930 if (*str != '+')
12931 {
12932 as_bad (_("invalid architectural extension"));
12933 return 0;
12934 }
12935
12936 str++;
12937 ext = strchr (str, '+');
12938
12939 if (ext != NULL)
12940 optlen = ext - str;
12941 else
12942 optlen = strlen (str);
12943
12944 if (optlen == 0)
12945 {
12946 as_bad (_("missing architectural extension"));
12947 return 0;
12948 }
12949
12950 for (opt = arm_extensions; opt->name != NULL; opt++)
12951 if (strncmp (opt->name, str, optlen) == 0)
12952 {
12953 *opt_p |= opt->value;
12954 break;
12955 }
12956
12957 if (opt->name == NULL)
12958 {
12959 as_bad (_("unknown architectural extnsion `%s'"), str);
12960 return 0;
12961 }
12962
12963 str = ext;
12964 };
12965
12966 return 1;
12967 }
12968
12969 static int
12970 arm_parse_cpu (char * str)
12971 {
12972 struct arm_cpu_option_table * opt;
12973 char * ext = strchr (str, '+');
12974 int optlen;
12975
12976 if (ext != NULL)
12977 optlen = ext - str;
12978 else
12979 optlen = strlen (str);
12980
12981 if (optlen == 0)
12982 {
12983 as_bad (_("missing cpu name `%s'"), str);
12984 return 0;
12985 }
12986
12987 for (opt = arm_cpus; opt->name != NULL; opt++)
12988 if (strncmp (opt->name, str, optlen) == 0)
12989 {
12990 mcpu_cpu_opt = opt->value;
12991 mcpu_fpu_opt = opt->default_fpu;
12992
12993 if (ext != NULL)
12994 return arm_parse_extension (ext, &mcpu_cpu_opt);
12995
12996 return 1;
12997 }
12998
12999 as_bad (_("unknown cpu `%s'"), str);
13000 return 0;
13001 }
13002
13003 static int
13004 arm_parse_arch (char * str)
13005 {
13006 struct arm_arch_option_table *opt;
13007 char *ext = strchr (str, '+');
13008 int optlen;
13009
13010 if (ext != NULL)
13011 optlen = ext - str;
13012 else
13013 optlen = strlen (str);
13014
13015 if (optlen == 0)
13016 {
13017 as_bad (_("missing architecture name `%s'"), str);
13018 return 0;
13019 }
13020
13021
13022 for (opt = arm_archs; opt->name != NULL; opt++)
13023 if (streq (opt->name, str))
13024 {
13025 march_cpu_opt = opt->value;
13026 march_fpu_opt = opt->default_fpu;
13027
13028 if (ext != NULL)
13029 return arm_parse_extension (ext, &march_cpu_opt);
13030
13031 return 1;
13032 }
13033
13034 as_bad (_("unknown architecture `%s'\n"), str);
13035 return 0;
13036 }
13037
13038 static int
13039 arm_parse_fpu (char * str)
13040 {
13041 struct arm_fpu_option_table * opt;
13042
13043 for (opt = arm_fpus; opt->name != NULL; opt++)
13044 if (streq (opt->name, str))
13045 {
13046 mfpu_opt = opt->value;
13047 return 1;
13048 }
13049
13050 as_bad (_("unknown floating point format `%s'\n"), str);
13051 return 0;
13052 }
13053
13054 static int
13055 arm_parse_float_abi (char * str)
13056 {
13057 struct arm_float_abi_option_table * opt;
13058
13059 for (opt = arm_float_abis; opt->name != NULL; opt++)
13060 if (streq (opt->name, str))
13061 {
13062 mfloat_abi_opt = opt->value;
13063 return 1;
13064 }
13065
13066 as_bad (_("unknown floating point abi `%s'\n"), str);
13067 return 0;
13068 }
13069
13070 #ifdef OBJ_ELF
13071 static int
13072 arm_parse_eabi (char * str)
13073 {
13074 struct arm_eabi_option_table *opt;
13075
13076 for (opt = arm_eabis; opt->name != NULL; opt++)
13077 if (streq (opt->name, str))
13078 {
13079 meabi_flags = opt->value;
13080 return 1;
13081 }
13082 as_bad (_("unknown EABI `%s'\n"), str);
13083 return 0;
13084 }
13085 #endif
13086
13087 struct arm_long_option_table arm_long_opts[] =
13088 {
13089 {"mcpu=", N_("<cpu name>\t assemble for CPU <cpu name>"),
13090 arm_parse_cpu, NULL},
13091 {"march=", N_("<arch name>\t assemble for architecture <arch name>"),
13092 arm_parse_arch, NULL},
13093 {"mfpu=", N_("<fpu name>\t assemble for FPU architecture <fpu name>"),
13094 arm_parse_fpu, NULL},
13095 {"mfloat-abi=", N_("<abi>\t assemble for floating point ABI <abi>"),
13096 arm_parse_float_abi, NULL},
13097 #ifdef OBJ_ELF
13098 {"meabi=", N_("<ver>\t assemble for eabi version <ver>"),
13099 arm_parse_eabi, NULL},
13100 #endif
13101 {NULL, NULL, 0, NULL}
13102 };
13103
13104 int
13105 md_parse_option (int c, char * arg)
13106 {
13107 struct arm_option_table *opt;
13108 struct arm_long_option_table *lopt;
13109
13110 switch (c)
13111 {
13112 #ifdef OPTION_EB
13113 case OPTION_EB:
13114 target_big_endian = 1;
13115 break;
13116 #endif
13117
13118 #ifdef OPTION_EL
13119 case OPTION_EL:
13120 target_big_endian = 0;
13121 break;
13122 #endif
13123
13124 case 'a':
13125 /* Listing option. Just ignore these, we don't support additional
13126 ones. */
13127 return 0;
13128
13129 default:
13130 for (opt = arm_opts; opt->option != NULL; opt++)
13131 {
13132 if (c == opt->option[0]
13133 && ((arg == NULL && opt->option[1] == 0)
13134 || streq (arg, opt->option + 1)))
13135 {
13136 #if WARN_DEPRECATED
13137 /* If the option is deprecated, tell the user. */
13138 if (opt->deprecated != NULL)
13139 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c,
13140 arg ? arg : "", _(opt->deprecated));
13141 #endif
13142
13143 if (opt->var != NULL)
13144 *opt->var = opt->value;
13145
13146 return 1;
13147 }
13148 }
13149
13150 for (lopt = arm_long_opts; lopt->option != NULL; lopt++)
13151 {
13152 /* These options are expected to have an argument. */
13153 if (c == lopt->option[0]
13154 && arg != NULL
13155 && strncmp (arg, lopt->option + 1,
13156 strlen (lopt->option + 1)) == 0)
13157 {
13158 #if WARN_DEPRECATED
13159 /* If the option is deprecated, tell the user. */
13160 if (lopt->deprecated != NULL)
13161 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c, arg,
13162 _(lopt->deprecated));
13163 #endif
13164
13165 /* Call the sup-option parser. */
13166 return lopt->func (arg + strlen (lopt->option) - 1);
13167 }
13168 }
13169
13170 return 0;
13171 }
13172
13173 return 1;
13174 }
13175
13176 void
13177 md_show_usage (FILE * fp)
13178 {
13179 struct arm_option_table *opt;
13180 struct arm_long_option_table *lopt;
13181
13182 fprintf (fp, _(" ARM-specific assembler options:\n"));
13183
13184 for (opt = arm_opts; opt->option != NULL; opt++)
13185 if (opt->help != NULL)
13186 fprintf (fp, " -%-23s%s\n", opt->option, _(opt->help));
13187
13188 for (lopt = arm_long_opts; lopt->option != NULL; lopt++)
13189 if (lopt->help != NULL)
13190 fprintf (fp, " -%s%s\n", lopt->option, _(lopt->help));
13191
13192 #ifdef OPTION_EB
13193 fprintf (fp, _("\
13194 -EB assemble code for a big-endian cpu\n"));
13195 #endif
13196
13197 #ifdef OPTION_EL
13198 fprintf (fp, _("\
13199 -EL assemble code for a little-endian cpu\n"));
13200 #endif
13201 }
13202
13203 /* This fix_new is called by cons via TC_CONS_FIX_NEW. */
13204
13205 void
13206 cons_fix_new_arm (fragS * frag,
13207 int where,
13208 int size,
13209 expressionS * exp)
13210 {
13211 bfd_reloc_code_real_type type;
13212 int pcrel = 0;
13213
13214 /* Pick a reloc.
13215 FIXME: @@ Should look at CPU word size. */
13216 switch (size)
13217 {
13218 case 1:
13219 type = BFD_RELOC_8;
13220 break;
13221 case 2:
13222 type = BFD_RELOC_16;
13223 break;
13224 case 4:
13225 default:
13226 type = BFD_RELOC_32;
13227 break;
13228 case 8:
13229 type = BFD_RELOC_64;
13230 break;
13231 }
13232
13233 fix_new_exp (frag, where, (int) size, exp, pcrel, type);
13234 }
13235
13236 /* A good place to do this, although this was probably not intended
13237 for this kind of use. We need to dump the literal pool before
13238 references are made to a null symbol pointer. */
13239
13240 void
13241 arm_cleanup (void)
13242 {
13243 literal_pool * pool;
13244
13245 for (pool = list_of_pools; pool; pool = pool->next)
13246 {
13247 /* Put it at the end of the relevent section. */
13248 subseg_set (pool->section, pool->sub_section);
13249 #ifdef OBJ_ELF
13250 arm_elf_change_section ();
13251 #endif
13252 s_ltorg (0);
13253 }
13254 }
13255
13256 void
13257 arm_start_line_hook (void)
13258 {
13259 last_label_seen = NULL;
13260 }
13261
13262 void
13263 arm_frob_label (symbolS * sym)
13264 {
13265 last_label_seen = sym;
13266
13267 ARM_SET_THUMB (sym, thumb_mode);
13268
13269 #if defined OBJ_COFF || defined OBJ_ELF
13270 ARM_SET_INTERWORK (sym, support_interwork);
13271 #endif
13272
13273 /* Note - do not allow local symbols (.Lxxx) to be labeled
13274 as Thumb functions. This is because these labels, whilst
13275 they exist inside Thumb code, are not the entry points for
13276 possible ARM->Thumb calls. Also, these labels can be used
13277 as part of a computed goto or switch statement. eg gcc
13278 can generate code that looks like this:
13279
13280 ldr r2, [pc, .Laaa]
13281 lsl r3, r3, #2
13282 ldr r2, [r3, r2]
13283 mov pc, r2
13284
13285 .Lbbb: .word .Lxxx
13286 .Lccc: .word .Lyyy
13287 ..etc...
13288 .Laaa: .word Lbbb
13289
13290 The first instruction loads the address of the jump table.
13291 The second instruction converts a table index into a byte offset.
13292 The third instruction gets the jump address out of the table.
13293 The fourth instruction performs the jump.
13294
13295 If the address stored at .Laaa is that of a symbol which has the
13296 Thumb_Func bit set, then the linker will arrange for this address
13297 to have the bottom bit set, which in turn would mean that the
13298 address computation performed by the third instruction would end
13299 up with the bottom bit set. Since the ARM is capable of unaligned
13300 word loads, the instruction would then load the incorrect address
13301 out of the jump table, and chaos would ensue. */
13302 if (label_is_thumb_function_name
13303 && (S_GET_NAME (sym)[0] != '.' || S_GET_NAME (sym)[1] != 'L')
13304 && (bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
13305 {
13306 /* When the address of a Thumb function is taken the bottom
13307 bit of that address should be set. This will allow
13308 interworking between Arm and Thumb functions to work
13309 correctly. */
13310
13311 THUMB_SET_FUNC (sym, 1);
13312
13313 label_is_thumb_function_name = FALSE;
13314 }
13315 }
13316
13317 /* Adjust the symbol table. This marks Thumb symbols as distinct from
13318 ARM ones. */
13319
13320 void
13321 arm_adjust_symtab (void)
13322 {
13323 #ifdef OBJ_COFF
13324 symbolS * sym;
13325
13326 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
13327 {
13328 if (ARM_IS_THUMB (sym))
13329 {
13330 if (THUMB_IS_FUNC (sym))
13331 {
13332 /* Mark the symbol as a Thumb function. */
13333 if ( S_GET_STORAGE_CLASS (sym) == C_STAT
13334 || S_GET_STORAGE_CLASS (sym) == C_LABEL) /* This can happen! */
13335 S_SET_STORAGE_CLASS (sym, C_THUMBSTATFUNC);
13336
13337 else if (S_GET_STORAGE_CLASS (sym) == C_EXT)
13338 S_SET_STORAGE_CLASS (sym, C_THUMBEXTFUNC);
13339 else
13340 as_bad (_("%s: unexpected function type: %d"),
13341 S_GET_NAME (sym), S_GET_STORAGE_CLASS (sym));
13342 }
13343 else switch (S_GET_STORAGE_CLASS (sym))
13344 {
13345 case C_EXT:
13346 S_SET_STORAGE_CLASS (sym, C_THUMBEXT);
13347 break;
13348 case C_STAT:
13349 S_SET_STORAGE_CLASS (sym, C_THUMBSTAT);
13350 break;
13351 case C_LABEL:
13352 S_SET_STORAGE_CLASS (sym, C_THUMBLABEL);
13353 break;
13354 default:
13355 /* Do nothing. */
13356 break;
13357 }
13358 }
13359
13360 if (ARM_IS_INTERWORK (sym))
13361 coffsymbol (symbol_get_bfdsym (sym))->native->u.syment.n_flags = 0xFF;
13362 }
13363 #endif
13364 #ifdef OBJ_ELF
13365 symbolS * sym;
13366 char bind;
13367
13368 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
13369 {
13370 if (ARM_IS_THUMB (sym))
13371 {
13372 elf_symbol_type * elf_sym;
13373
13374 elf_sym = elf_symbol (symbol_get_bfdsym (sym));
13375 bind = ELF_ST_BIND (elf_sym);
13376
13377 /* If it's a .thumb_func, declare it as so,
13378 otherwise tag label as .code 16. */
13379 if (THUMB_IS_FUNC (sym))
13380 elf_sym->internal_elf_sym.st_info =
13381 ELF_ST_INFO (bind, STT_ARM_TFUNC);
13382 else
13383 elf_sym->internal_elf_sym.st_info =
13384 ELF_ST_INFO (bind, STT_ARM_16BIT);
13385 }
13386 }
13387 #endif
13388 }
13389
13390 int
13391 arm_data_in_code (void)
13392 {
13393 if (thumb_mode && ! strncmp (input_line_pointer + 1, "data:", 5))
13394 {
13395 *input_line_pointer = '/';
13396 input_line_pointer += 5;
13397 *input_line_pointer = 0;
13398 return 1;
13399 }
13400
13401 return 0;
13402 }
13403
13404 char *
13405 arm_canonicalize_symbol_name (char * name)
13406 {
13407 int len;
13408
13409 if (thumb_mode && (len = strlen (name)) > 5
13410 && streq (name + len - 5, "/data"))
13411 *(name + len - 5) = 0;
13412
13413 return name;
13414 }
13415
13416 #if defined OBJ_COFF || defined OBJ_ELF
13417 void
13418 arm_validate_fix (fixS * fixP)
13419 {
13420 /* If the destination of the branch is a defined symbol which does not have
13421 the THUMB_FUNC attribute, then we must be calling a function which has
13422 the (interfacearm) attribute. We look for the Thumb entry point to that
13423 function and change the branch to refer to that function instead. */
13424 if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23
13425 && fixP->fx_addsy != NULL
13426 && S_IS_DEFINED (fixP->fx_addsy)
13427 && ! THUMB_IS_FUNC (fixP->fx_addsy))
13428 {
13429 fixP->fx_addsy = find_real_start (fixP->fx_addsy);
13430 }
13431 }
13432 #endif
13433
13434 int
13435 arm_force_relocation (struct fix * fixp)
13436 {
13437 #if defined (OBJ_COFF) && defined (TE_PE)
13438 if (fixp->fx_r_type == BFD_RELOC_RVA)
13439 return 1;
13440 #endif
13441 #ifdef OBJ_ELF
13442 if (fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH
13443 || fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BLX
13444 || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX
13445 || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23)
13446 return 1;
13447 #endif
13448
13449 /* Resolve these relocations even if the symbol is extern or weak. */
13450 if (fixp->fx_r_type == BFD_RELOC_ARM_IMMEDIATE
13451 || fixp->fx_r_type == BFD_RELOC_ARM_OFFSET_IMM
13452 || fixp->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE)
13453 return 0;
13454
13455 return generic_force_reloc (fixp);
13456 }
13457
13458 #ifdef OBJ_COFF
13459 /* This is a little hack to help the gas/arm/adrl.s test. It prevents
13460 local labels from being added to the output symbol table when they
13461 are used with the ADRL pseudo op. The ADRL relocation should always
13462 be resolved before the binbary is emitted, so it is safe to say that
13463 it is adjustable. */
13464
13465 bfd_boolean
13466 arm_fix_adjustable (fixS * fixP)
13467 {
13468 if (fixP->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE)
13469 return 1;
13470 return 0;
13471 }
13472 #endif
13473
13474 #ifdef OBJ_ELF
13475 /* Relocations against Thumb function names must be left unadjusted,
13476 so that the linker can use this information to correctly set the
13477 bottom bit of their addresses. The MIPS version of this function
13478 also prevents relocations that are mips-16 specific, but I do not
13479 know why it does this.
13480
13481 FIXME:
13482 There is one other problem that ought to be addressed here, but
13483 which currently is not: Taking the address of a label (rather
13484 than a function) and then later jumping to that address. Such
13485 addresses also ought to have their bottom bit set (assuming that
13486 they reside in Thumb code), but at the moment they will not. */
13487
13488 bfd_boolean
13489 arm_fix_adjustable (fixS * fixP)
13490 {
13491 if (fixP->fx_addsy == NULL)
13492 return 1;
13493
13494 if (THUMB_IS_FUNC (fixP->fx_addsy)
13495 && fixP->fx_subsy == NULL)
13496 return 0;
13497
13498 /* We need the symbol name for the VTABLE entries. */
13499 if ( fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
13500 || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
13501 return 0;
13502
13503 /* Don't allow symbols to be discarded on GOT related relocs. */
13504 if (fixP->fx_r_type == BFD_RELOC_ARM_PLT32
13505 || fixP->fx_r_type == BFD_RELOC_ARM_GOT32
13506 || fixP->fx_r_type == BFD_RELOC_ARM_GOTOFF
13507 || fixP->fx_r_type == BFD_RELOC_ARM_TARGET2)
13508 return 0;
13509
13510 return 1;
13511 }
13512
13513 const char *
13514 elf32_arm_target_format (void)
13515 {
13516 #ifdef TE_SYMBIAN
13517 return (target_big_endian
13518 ? "elf32-bigarm-symbian"
13519 : "elf32-littlearm-symbian");
13520 #else
13521 if (target_big_endian)
13522 {
13523 if (target_oabi)
13524 return "elf32-bigarm-oabi";
13525 else
13526 return "elf32-bigarm";
13527 }
13528 else
13529 {
13530 if (target_oabi)
13531 return "elf32-littlearm-oabi";
13532 else
13533 return "elf32-littlearm";
13534 }
13535 #endif
13536 }
13537
13538 void
13539 armelf_frob_symbol (symbolS * symp,
13540 int * puntp)
13541 {
13542 elf_frob_symbol (symp, puntp);
13543 }
13544
13545 static void
13546 s_arm_elf_cons (int nbytes)
13547 {
13548 expressionS exp;
13549
13550 #ifdef md_flush_pending_output
13551 md_flush_pending_output ();
13552 #endif
13553
13554 if (is_it_end_of_statement ())
13555 {
13556 demand_empty_rest_of_line ();
13557 return;
13558 }
13559
13560 #ifdef md_cons_align
13561 md_cons_align (nbytes);
13562 #endif
13563
13564 mapping_state (MAP_DATA);
13565 do
13566 {
13567 bfd_reloc_code_real_type reloc;
13568
13569 expression (& exp);
13570
13571 if (exp.X_op == O_symbol
13572 && * input_line_pointer == '('
13573 && (reloc = arm_parse_reloc ()) != BFD_RELOC_UNUSED)
13574 {
13575 reloc_howto_type *howto = bfd_reloc_type_lookup (stdoutput, reloc);
13576 int size = bfd_get_reloc_size (howto);
13577
13578 if (size > nbytes)
13579 as_bad ("%s relocations do not fit in %d bytes",
13580 howto->name, nbytes);
13581 else
13582 {
13583 char *p = frag_more ((int) nbytes);
13584 int offset = nbytes - size;
13585
13586 fix_new_exp (frag_now, p - frag_now->fr_literal + offset, size,
13587 &exp, 0, reloc);
13588 }
13589 }
13590 else
13591 emit_expr (&exp, (unsigned int) nbytes);
13592 }
13593 while (*input_line_pointer++ == ',');
13594
13595 /* Put terminator back into stream. */
13596 input_line_pointer --;
13597 demand_empty_rest_of_line ();
13598 }
13599
13600
13601 /* Parse a .rel31 directive. */
13602
13603 static void
13604 s_arm_rel31 (int ignored ATTRIBUTE_UNUSED)
13605 {
13606 expressionS exp;
13607 char *p;
13608 valueT highbit;
13609
13610 SKIP_WHITESPACE ();
13611
13612 highbit = 0;
13613 if (*input_line_pointer == '1')
13614 highbit = 0x80000000;
13615 else if (*input_line_pointer != '0')
13616 as_bad (_("expected 0 or 1"));
13617
13618 input_line_pointer++;
13619 SKIP_WHITESPACE ();
13620 if (*input_line_pointer != ',')
13621 as_bad (_("missing comma"));
13622 input_line_pointer++;
13623
13624 #ifdef md_flush_pending_output
13625 md_flush_pending_output ();
13626 #endif
13627
13628 #ifdef md_cons_align
13629 md_cons_align (4);
13630 #endif
13631
13632 mapping_state (MAP_DATA);
13633
13634 expression (&exp);
13635
13636 p = frag_more (4);
13637 md_number_to_chars (p, highbit, 4);
13638 fix_new_arm (frag_now, p - frag_now->fr_literal, 4, &exp, 1,
13639 BFD_RELOC_ARM_PREL31);
13640
13641 demand_empty_rest_of_line ();
13642 }
13643 \f
13644 /* Code to deal with unwinding tables. */
13645
13646 static void add_unwind_adjustsp (offsetT);
13647
13648 /* Switch to section NAME and create section if necessary. It's
13649 rather ugly that we have to manipulate input_line_pointer but I
13650 don't see any other way to accomplish the same thing without
13651 changing obj-elf.c (which may be the Right Thing, in the end).
13652 Copied from tc-ia64.c. */
13653
13654 static void
13655 set_section (char *name)
13656 {
13657 char *saved_input_line_pointer;
13658
13659 saved_input_line_pointer = input_line_pointer;
13660 input_line_pointer = name;
13661 obj_elf_section (0);
13662 input_line_pointer = saved_input_line_pointer;
13663 }
13664
13665 /* Cenerate and deferred unwind frame offset. */
13666
13667 static void
13668 flush_pending_unwind (void)
13669 {
13670 offsetT offset;
13671
13672 offset = unwind.pending_offset;
13673 unwind.pending_offset = 0;
13674 if (offset != 0)
13675 add_unwind_adjustsp (offset);
13676 }
13677
13678 /* Add an opcode to this list for this function. Two-byte opcodes should
13679 be passed as op[0] << 8 | op[1]. The list of opcodes is built in reverse
13680 order. */
13681
13682 static void
13683 add_unwind_opcode (valueT op, int length)
13684 {
13685 /* Add any deferred stack adjustment. */
13686 if (unwind.pending_offset)
13687 flush_pending_unwind ();
13688
13689 unwind.sp_restored = 0;
13690
13691 if (unwind.opcode_count + length > unwind.opcode_alloc)
13692 {
13693 unwind.opcode_alloc += ARM_OPCODE_CHUNK_SIZE;
13694 if (unwind.opcodes)
13695 unwind.opcodes = xrealloc (unwind.opcodes,
13696 unwind.opcode_alloc);
13697 else
13698 unwind.opcodes = xmalloc (unwind.opcode_alloc);
13699 }
13700 while (length > 0)
13701 {
13702 length--;
13703 unwind.opcodes[unwind.opcode_count] = op & 0xff;
13704 op >>= 8;
13705 unwind.opcode_count++;
13706 }
13707 }
13708
13709 /* Add unwind opcodes to adjust the stack pointer. */
13710
13711 static void
13712 add_unwind_adjustsp (offsetT offset)
13713 {
13714 valueT op;
13715
13716 if (offset > 0x200)
13717 {
13718 /* We need at most 5 bytes to hold a 32-bit value in a uleb128. */
13719 char bytes[5];
13720 int n;
13721 valueT o;
13722
13723 /* Long form: 0xb2, uleb128. */
13724 /* This might not fit in a word so add the individual bytes,
13725 remembering the list is built in reverse order. */
13726 o = (valueT) ((offset - 0x204) >> 2);
13727 if (o == 0)
13728 add_unwind_opcode (0, 1);
13729
13730 /* Calculate the uleb128 encoding of the offset. */
13731 n = 0;
13732 while (o)
13733 {
13734 bytes[n] = o & 0x7f;
13735 o >>= 7;
13736 if (o)
13737 bytes[n] |= 0x80;
13738 n++;
13739 }
13740 /* Add the insn. */
13741 for (; n; n--)
13742 add_unwind_opcode (bytes[n - 1], 1);
13743 add_unwind_opcode (0xb2, 1);
13744 }
13745 else if (offset > 0x100)
13746 {
13747 /* Two short opcodes. */
13748 add_unwind_opcode (0x3f, 1);
13749 op = (offset - 0x104) >> 2;
13750 add_unwind_opcode (op, 1);
13751 }
13752 else if (offset > 0)
13753 {
13754 /* Short opcode. */
13755 op = (offset - 4) >> 2;
13756 add_unwind_opcode (op, 1);
13757 }
13758 else if (offset < 0)
13759 {
13760 offset = -offset;
13761 while (offset > 0x100)
13762 {
13763 add_unwind_opcode (0x7f, 1);
13764 offset -= 0x100;
13765 }
13766 op = ((offset - 4) >> 2) | 0x40;
13767 add_unwind_opcode (op, 1);
13768 }
13769 }
13770
13771 /* Finish the list of unwind opcodes for this function. */
13772 static void
13773 finish_unwind_opcodes (void)
13774 {
13775 valueT op;
13776
13777 if (unwind.fp_used)
13778 {
13779 /* Adjust sp as neccessary. */
13780 unwind.pending_offset += unwind.fp_offset - unwind.frame_size;
13781 flush_pending_unwind ();
13782
13783 /* After restoring sp from the frame pointer. */
13784 op = 0x90 | unwind.fp_reg;
13785 add_unwind_opcode (op, 1);
13786 }
13787 else
13788 flush_pending_unwind ();
13789 }
13790
13791
13792 /* Start an exception table entry. If idx is nonzero this is an index table
13793 entry. */
13794
13795 static void
13796 start_unwind_section (const segT text_seg, int idx)
13797 {
13798 const char * text_name;
13799 const char * prefix;
13800 const char * prefix_once;
13801 size_t prefix_len;
13802 size_t text_len;
13803 char * sec_name;
13804 size_t sec_name_len;
13805
13806 if (idx)
13807 {
13808 prefix = ELF_STRING_ARM_unwind;
13809 prefix_once = ELF_STRING_ARM_unwind_once;
13810 }
13811 else
13812 {
13813 prefix = ELF_STRING_ARM_unwind_info;
13814 prefix_once = ELF_STRING_ARM_unwind_info_once;
13815 }
13816
13817 text_name = segment_name (text_seg);
13818 if (streq (text_name, ".text"))
13819 text_name = "";
13820
13821 if (strncmp (text_name, ".gnu.linkonce.t.",
13822 strlen (".gnu.linkonce.t.")) == 0)
13823 {
13824 prefix = prefix_once;
13825 text_name += strlen (".gnu.linkonce.t.");
13826 }
13827
13828 prefix_len = strlen (prefix);
13829 text_len = strlen (text_name);
13830 sec_name_len = prefix_len + text_len;
13831 sec_name = alloca (sec_name_len + 1);
13832 memcpy (sec_name, prefix, prefix_len);
13833 memcpy (sec_name + prefix_len, text_name, text_len);
13834 sec_name[prefix_len + text_len] = '\0';
13835
13836 /* Handle COMDAT group. */
13837 if (prefix != prefix_once && (text_seg->flags & SEC_LINK_ONCE) != 0)
13838 {
13839 char *section;
13840 size_t len, group_name_len;
13841 const char *group_name = elf_group_name (text_seg);
13842
13843 if (group_name == NULL)
13844 {
13845 as_bad ("Group section `%s' has no group signature",
13846 segment_name (text_seg));
13847 ignore_rest_of_line ();
13848 return;
13849 }
13850 /* We have to construct a fake section directive. */
13851 group_name_len = strlen (group_name);
13852 if (idx)
13853 prefix_len = 13;
13854 else
13855 prefix_len = 16;
13856
13857 len = (sec_name_len
13858 + prefix_len /* ,"aG",%sectiontype, */
13859 + group_name_len /* ,group_name */
13860 + 7); /* ,comdat */
13861
13862 section = alloca (len + 1);
13863 memcpy (section, sec_name, sec_name_len);
13864 if (idx)
13865 memcpy (section + sec_name_len, ",\"aG\",%exidx,", 13);
13866 else
13867 memcpy (section + sec_name_len, ",\"aG\",%progbits,", 16);
13868 memcpy (section + sec_name_len + prefix_len, group_name, group_name_len);
13869 memcpy (section + len - 7, ",comdat", 7);
13870 section [len] = '\0';
13871 set_section (section);
13872 }
13873 else
13874 {
13875 set_section (sec_name);
13876 bfd_set_section_flags (stdoutput, now_seg,
13877 SEC_LOAD | SEC_ALLOC | SEC_READONLY);
13878 }
13879
13880 /* Set the setion link for index tables. */
13881 if (idx)
13882 elf_linked_to_section (now_seg) = text_seg;
13883 }
13884
13885
13886 /* Start an unwind table entry. HAVE_DATA is nonzero if we have additional
13887 personality routine data. Returns zero, or the index table value for
13888 and inline entry. */
13889
13890 static valueT
13891 create_unwind_entry (int have_data)
13892 {
13893 int size;
13894 addressT where;
13895 unsigned char *ptr;
13896 /* The current word of data. */
13897 valueT data;
13898 /* The number of bytes left in this word. */
13899 int n;
13900
13901 finish_unwind_opcodes ();
13902
13903 /* Remember the current text section. */
13904 unwind.saved_seg = now_seg;
13905 unwind.saved_subseg = now_subseg;
13906
13907 start_unwind_section (now_seg, 0);
13908
13909 if (unwind.personality_routine == NULL)
13910 {
13911 if (unwind.personality_index == -2)
13912 {
13913 if (have_data)
13914 as_bad (_("handerdata in cantunwind frame"));
13915 return 1; /* EXIDX_CANTUNWIND. */
13916 }
13917
13918 /* Use a default personality routine if none is specified. */
13919 if (unwind.personality_index == -1)
13920 {
13921 if (unwind.opcode_count > 3)
13922 unwind.personality_index = 1;
13923 else
13924 unwind.personality_index = 0;
13925 }
13926
13927 /* Space for the personality routine entry. */
13928 if (unwind.personality_index == 0)
13929 {
13930 if (unwind.opcode_count > 3)
13931 as_bad (_("too many unwind opcodes for personality routine 0"));
13932
13933 if (!have_data)
13934 {
13935 /* All the data is inline in the index table. */
13936 data = 0x80;
13937 n = 3;
13938 while (unwind.opcode_count > 0)
13939 {
13940 unwind.opcode_count--;
13941 data = (data << 8) | unwind.opcodes[unwind.opcode_count];
13942 n--;
13943 }
13944
13945 /* Pad with "finish" opcodes. */
13946 while (n--)
13947 data = (data << 8) | 0xb0;
13948
13949 return data;
13950 }
13951 size = 0;
13952 }
13953 else
13954 /* We get two opcodes "free" in the first word. */
13955 size = unwind.opcode_count - 2;
13956 }
13957 else
13958 /* An extra byte is required for the opcode count. */
13959 size = unwind.opcode_count + 1;
13960
13961 size = (size + 3) >> 2;
13962 if (size > 0xff)
13963 as_bad (_("too many unwind opcodes"));
13964
13965 frag_align (2, 0, 0);
13966 record_alignment (now_seg, 2);
13967 unwind.table_entry = expr_build_dot ();
13968
13969 /* Allocate the table entry. */
13970 ptr = frag_more ((size << 2) + 4);
13971 where = frag_now_fix () - ((size << 2) + 4);
13972
13973 switch (unwind.personality_index)
13974 {
13975 case -1:
13976 /* ??? Should this be a PLT generating relocation? */
13977 /* Custom personality routine. */
13978 fix_new (frag_now, where, 4, unwind.personality_routine, 0, 1,
13979 BFD_RELOC_ARM_PREL31);
13980 where += 4;
13981 ptr += 4;
13982
13983 /* Set the first byte to the number of additional words. */
13984 data = size - 1;
13985 n = 3;
13986 break;
13987
13988 /* ABI defined personality routines. */
13989 /* TODO: Emit R_ARM_NONE to the personality routine. */
13990 case 0:
13991 /* Three opcodes bytes are packed into the first word. */
13992 data = 0x80;
13993 n = 3;
13994 break;
13995
13996 case 1:
13997 case 2:
13998 /* The size and first two opcode bytes go in the first word. */
13999 data = ((0x80 + unwind.personality_index) << 8) | size;
14000 n = 2;
14001 break;
14002
14003 default:
14004 /* Should never happen. */
14005 abort ();
14006 }
14007
14008 /* Pack the opcodes into words (MSB first), reversing the list at the same
14009 time. */
14010 while (unwind.opcode_count > 0)
14011 {
14012 if (n == 0)
14013 {
14014 md_number_to_chars (ptr, data, 4);
14015 ptr += 4;
14016 n = 4;
14017 data = 0;
14018 }
14019 unwind.opcode_count--;
14020 n--;
14021 data = (data << 8) | unwind.opcodes[unwind.opcode_count];
14022 }
14023
14024 /* Finish off the last word. */
14025 if (n < 4)
14026 {
14027 /* Pad with "finish" opcodes. */
14028 while (n--)
14029 data = (data << 8) | 0xb0;
14030
14031 md_number_to_chars (ptr, data, 4);
14032 }
14033
14034 if (!have_data)
14035 {
14036 /* Add an empty descriptor if there is no user-specified data. */
14037 ptr = frag_more (4);
14038 md_number_to_chars (ptr, 0, 4);
14039 }
14040
14041 return 0;
14042 }
14043
14044
14045 /* Parse an unwind_fnstart directive. Simply records the current location. */
14046
14047 static void
14048 s_arm_unwind_fnstart (int ignored ATTRIBUTE_UNUSED)
14049 {
14050 demand_empty_rest_of_line ();
14051 /* Mark the start of the function. */
14052 unwind.proc_start = expr_build_dot ();
14053
14054 /* Reset the rest of the unwind info. */
14055 unwind.opcode_count = 0;
14056 unwind.table_entry = NULL;
14057 unwind.personality_routine = NULL;
14058 unwind.personality_index = -1;
14059 unwind.frame_size = 0;
14060 unwind.fp_offset = 0;
14061 unwind.fp_reg = 13;
14062 unwind.fp_used = 0;
14063 unwind.sp_restored = 0;
14064 }
14065
14066
14067 /* Parse a handlerdata directive. Creates the exception handling table entry
14068 for the function. */
14069
14070 static void
14071 s_arm_unwind_handlerdata (int ignored ATTRIBUTE_UNUSED)
14072 {
14073 demand_empty_rest_of_line ();
14074 if (unwind.table_entry)
14075 as_bad (_("dupicate .handlerdata directive"));
14076
14077 create_unwind_entry (1);
14078 }
14079
14080 /* Parse an unwind_fnend directive. Generates the index table entry. */
14081
14082 static void
14083 s_arm_unwind_fnend (int ignored ATTRIBUTE_UNUSED)
14084 {
14085 long where;
14086 unsigned char *ptr;
14087 valueT val;
14088
14089 demand_empty_rest_of_line ();
14090
14091 /* Add eh table entry. */
14092 if (unwind.table_entry == NULL)
14093 val = create_unwind_entry (0);
14094 else
14095 val = 0;
14096
14097 /* Add index table entry. This is two words. */
14098 start_unwind_section (unwind.saved_seg, 1);
14099 frag_align (2, 0, 0);
14100 record_alignment (now_seg, 2);
14101
14102 ptr = frag_more (8);
14103 where = frag_now_fix () - 8;
14104
14105 /* Self relative offset of the function start. */
14106 fix_new (frag_now, where, 4, unwind.proc_start, 0, 1,
14107 BFD_RELOC_32);
14108
14109 if (val)
14110 /* Inline exception table entry. */
14111 md_number_to_chars (ptr + 4, val, 4);
14112 else
14113 /* Self relative offset of the table entry. */
14114 fix_new (frag_now, where + 4, 4, unwind.table_entry, 0, 1,
14115 BFD_RELOC_ARM_PREL31);
14116
14117 /* Restore the original section. */
14118 subseg_set (unwind.saved_seg, unwind.saved_subseg);
14119 }
14120
14121
14122 /* Parse an unwind_cantunwind directive. */
14123
14124 static void
14125 s_arm_unwind_cantunwind (int ignored ATTRIBUTE_UNUSED)
14126 {
14127 demand_empty_rest_of_line ();
14128 if (unwind.personality_routine || unwind.personality_index != -1)
14129 as_bad (_("personality routine specified for cantunwind frame"));
14130
14131 unwind.personality_index = -2;
14132 }
14133
14134
14135 /* Parse a personalityindex directive. */
14136
14137 static void
14138 s_arm_unwind_personalityindex (int ignored ATTRIBUTE_UNUSED)
14139 {
14140 expressionS exp;
14141
14142 if (unwind.personality_routine || unwind.personality_index != -1)
14143 as_bad (_("duplicate .personalityindex directive"));
14144
14145 SKIP_WHITESPACE ();
14146
14147 expression (&exp);
14148
14149 if (exp.X_op != O_constant
14150 || exp.X_add_number < 0 || exp.X_add_number > 15)
14151 {
14152 as_bad (_("bad personality routine number"));
14153 ignore_rest_of_line ();
14154 return;
14155 }
14156
14157 unwind.personality_index = exp.X_add_number;
14158
14159 demand_empty_rest_of_line ();
14160 }
14161
14162
14163 /* Parse a personality directive. */
14164
14165 static void
14166 s_arm_unwind_personality (int ignored ATTRIBUTE_UNUSED)
14167 {
14168 char *name, *p, c;
14169
14170 if (unwind.personality_routine || unwind.personality_index != -1)
14171 as_bad (_("duplicate .personality directive"));
14172
14173 SKIP_WHITESPACE ();
14174 name = input_line_pointer;
14175 c = get_symbol_end ();
14176 p = input_line_pointer;
14177 unwind.personality_routine = symbol_find_or_make (name);
14178 *p = c;
14179 SKIP_WHITESPACE ();
14180 demand_empty_rest_of_line ();
14181 }
14182
14183
14184 /* Parse a directive saving core registers. */
14185
14186 static void
14187 s_arm_unwind_save_core (void)
14188 {
14189 valueT op;
14190 long range;
14191 int n;
14192
14193 SKIP_WHITESPACE ();
14194 range = reg_list (&input_line_pointer);
14195 if (range == FAIL)
14196 {
14197 as_bad (_("expected register list"));
14198 ignore_rest_of_line ();
14199 return;
14200 }
14201
14202 demand_empty_rest_of_line ();
14203
14204 /* Turn .unwind_movsp ip followed by .unwind_save {..., ip, ...}
14205 into .unwind_save {..., sp...}. We aren't bothered about the value of
14206 ip because it is clobbered by calls. */
14207 if (unwind.sp_restored && unwind.fp_reg == 12
14208 && (range & 0x3000) == 0x1000)
14209 {
14210 unwind.opcode_count--;
14211 unwind.sp_restored = 0;
14212 range = (range | 0x2000) & ~0x1000;
14213 unwind.pending_offset = 0;
14214 }
14215
14216 /* See if we can use the short opcodes. These pop a block of upto 8
14217 registers starting with r4, plus maybe r14. */
14218 for (n = 0; n < 8; n++)
14219 {
14220 /* Break at the first non-saved register. */
14221 if ((range & (1 << (n + 4))) == 0)
14222 break;
14223 }
14224 /* See if there are any other bits set. */
14225 if (n == 0 || (range & (0xfff0 << n) & 0xbff0) != 0)
14226 {
14227 /* Use the long form. */
14228 op = 0x8000 | ((range >> 4) & 0xfff);
14229 add_unwind_opcode (op, 2);
14230 }
14231 else
14232 {
14233 /* Use the short form. */
14234 if (range & 0x4000)
14235 op = 0xa8; /* Pop r14. */
14236 else
14237 op = 0xa0; /* Do not pop r14. */
14238 op |= (n - 1);
14239 add_unwind_opcode (op, 1);
14240 }
14241
14242 /* Pop r0-r3. */
14243 if (range & 0xf)
14244 {
14245 op = 0xb100 | (range & 0xf);
14246 add_unwind_opcode (op, 2);
14247 }
14248
14249 /* Record the number of bytes pushed. */
14250 for (n = 0; n < 16; n++)
14251 {
14252 if (range & (1 << n))
14253 unwind.frame_size += 4;
14254 }
14255 }
14256
14257
14258 /* Parse a directive saving FPA registers. */
14259
14260 static void
14261 s_arm_unwind_save_fpa (int reg)
14262 {
14263 expressionS exp;
14264 int num_regs;
14265 valueT op;
14266
14267 /* Get Number of registers to transfer. */
14268 if (skip_past_comma (&input_line_pointer) != FAIL)
14269 expression (&exp);
14270 else
14271 exp.X_op = O_illegal;
14272
14273 if (exp.X_op != O_constant)
14274 {
14275 as_bad (_("expected , <constant>"));
14276 ignore_rest_of_line ();
14277 return;
14278 }
14279
14280 num_regs = exp.X_add_number;
14281
14282 if (num_regs < 1 || num_regs > 4)
14283 {
14284 as_bad (_("number of registers must be in the range [1:4]"));
14285 ignore_rest_of_line ();
14286 return;
14287 }
14288
14289 demand_empty_rest_of_line ();
14290
14291 if (reg == 4)
14292 {
14293 /* Short form. */
14294 op = 0xb4 | (num_regs - 1);
14295 add_unwind_opcode (op, 1);
14296 }
14297 else
14298 {
14299 /* Long form. */
14300 op = 0xc800 | (reg << 4) | (num_regs - 1);
14301 add_unwind_opcode (op, 2);
14302 }
14303 unwind.frame_size += num_regs * 12;
14304 }
14305
14306
14307 /* Parse a directive saving VFP registers. */
14308
14309 static void
14310 s_arm_unwind_save_vfp (void)
14311 {
14312 int count;
14313 int reg;
14314 valueT op;
14315
14316 count = vfp_parse_reg_list (&input_line_pointer, &reg, 1);
14317 if (count == FAIL)
14318 {
14319 as_bad (_("expected register list"));
14320 ignore_rest_of_line ();
14321 return;
14322 }
14323
14324 demand_empty_rest_of_line ();
14325
14326 if (reg == 8)
14327 {
14328 /* Short form. */
14329 op = 0xb8 | (count - 1);
14330 add_unwind_opcode (op, 1);
14331 }
14332 else
14333 {
14334 /* Long form. */
14335 op = 0xb300 | (reg << 4) | (count - 1);
14336 add_unwind_opcode (op, 2);
14337 }
14338 unwind.frame_size += count * 8 + 4;
14339 }
14340
14341
14342 /* Parse a directive saving iWMMXt registers. */
14343
14344 static void
14345 s_arm_unwind_save_wmmx (void)
14346 {
14347 int reg;
14348 int hi_reg;
14349 int i;
14350 unsigned wcg_mask;
14351 unsigned wr_mask;
14352 valueT op;
14353
14354 if (*input_line_pointer == '{')
14355 input_line_pointer++;
14356
14357 wcg_mask = 0;
14358 wr_mask = 0;
14359 do
14360 {
14361 reg = arm_reg_parse (&input_line_pointer,
14362 all_reg_maps[REG_TYPE_IWMMXT].htab);
14363
14364 if (wr_register (reg))
14365 {
14366 i = reg & ~WR_PREFIX;
14367 if (wr_mask >> i)
14368 as_tsktsk (_("register list not in ascending order"));
14369 wr_mask |= 1 << i;
14370 }
14371 else if (wcg_register (reg))
14372 {
14373 i = (reg & ~WC_PREFIX) - 8;
14374 if (wcg_mask >> i)
14375 as_tsktsk (_("register list not in ascending order"));
14376 wcg_mask |= 1 << i;
14377 }
14378 else
14379 {
14380 as_bad (_("expected wr or wcgr"));
14381 goto error;
14382 }
14383
14384 SKIP_WHITESPACE ();
14385 if (*input_line_pointer == '-')
14386 {
14387 hi_reg = arm_reg_parse (&input_line_pointer,
14388 all_reg_maps[REG_TYPE_IWMMXT].htab);
14389 if (wr_register (reg) && wr_register (hi_reg))
14390 {
14391 for (; reg < hi_reg; reg++)
14392 wr_mask |= 1 << (reg & ~WR_PREFIX);
14393 }
14394 else if (wcg_register (reg) && wcg_register (hi_reg))
14395 {
14396 for (; reg < hi_reg; reg++)
14397 wcg_mask |= 1 << ((reg & ~WC_PREFIX) - 8);
14398 }
14399 else
14400 {
14401 as_bad (_("bad register range"));
14402 goto error;
14403 }
14404 }
14405 }
14406 while (skip_past_comma (&input_line_pointer) != FAIL);
14407
14408 SKIP_WHITESPACE ();
14409 if (*input_line_pointer == '}')
14410 input_line_pointer++;
14411
14412 demand_empty_rest_of_line ();
14413
14414 if (wr_mask && wcg_mask)
14415 {
14416 as_bad (_("inconsistent register types"));
14417 goto error;
14418 }
14419
14420 /* Generate any deferred opcodes becuuse we're going to be looking at
14421 the list. */
14422 flush_pending_unwind ();
14423
14424 if (wcg_mask)
14425 {
14426 for (i = 0; i < 16; i++)
14427 {
14428 if (wcg_mask & (1 << i))
14429 unwind.frame_size += 4;
14430 }
14431 op = 0xc700 | wcg_mask;
14432 add_unwind_opcode (op, 2);
14433 }
14434 else
14435 {
14436 for (i = 0; i < 16; i++)
14437 {
14438 if (wr_mask & (1 << i))
14439 unwind.frame_size += 8;
14440 }
14441 /* Attempt to combine with a previous opcode. We do this because gcc
14442 likes to output separate unwind directives for a single block of
14443 registers. */
14444 if (unwind.opcode_count > 0)
14445 {
14446 i = unwind.opcodes[unwind.opcode_count - 1];
14447 if ((i & 0xf8) == 0xc0)
14448 {
14449 i &= 7;
14450 /* Only merge if the blocks are contiguous. */
14451 if (i < 6)
14452 {
14453 if ((wr_mask & 0xfe00) == (1 << 9))
14454 {
14455 wr_mask |= ((1 << (i + 11)) - 1) & 0xfc00;
14456 unwind.opcode_count--;
14457 }
14458 }
14459 else if (i == 6 && unwind.opcode_count >= 2)
14460 {
14461 i = unwind.opcodes[unwind.opcode_count - 2];
14462 reg = i >> 4;
14463 i &= 0xf;
14464
14465 op = 0xffff << (reg - 1);
14466 if (reg > 0
14467 || ((wr_mask & op) == (1u << (reg - 1))))
14468 {
14469 op = (1 << (reg + i + 1)) - 1;
14470 op &= ~((1 << reg) - 1);
14471 wr_mask |= op;
14472 unwind.opcode_count -= 2;
14473 }
14474 }
14475 }
14476 }
14477
14478 hi_reg = 15;
14479 /* We want to generate opcodes in the order the registers have been
14480 saved, ie. descending order. */
14481 for (reg = 15; reg >= -1; reg--)
14482 {
14483 /* Save registers in blocks. */
14484 if (reg < 0
14485 || !(wr_mask & (1 << reg)))
14486 {
14487 /* We found an unsaved reg. Generate opcodes to save the
14488 preceeding block. */
14489 if (reg != hi_reg)
14490 {
14491 if (reg == 9)
14492 {
14493 /* Short form. */
14494 op = 0xc0 | (hi_reg - 10);
14495 add_unwind_opcode (op, 1);
14496 }
14497 else
14498 {
14499 /* Long form. */
14500 op = 0xc600 | ((reg + 1) << 4) | ((hi_reg - reg) - 1);
14501 add_unwind_opcode (op, 2);
14502 }
14503 }
14504 hi_reg = reg - 1;
14505 }
14506 }
14507 }
14508 return;
14509 error:
14510 ignore_rest_of_line ();
14511 }
14512
14513
14514 /* Parse an unwind_save directive. */
14515
14516 static void
14517 s_arm_unwind_save (int ignored ATTRIBUTE_UNUSED)
14518 {
14519 char *saved_ptr;
14520 int reg;
14521
14522 /* Figure out what sort of save we have. */
14523 SKIP_WHITESPACE ();
14524 saved_ptr = input_line_pointer;
14525
14526 reg = arm_reg_parse (&input_line_pointer, all_reg_maps[REG_TYPE_FN].htab);
14527 if (reg != FAIL)
14528 {
14529 s_arm_unwind_save_fpa (reg);
14530 return;
14531 }
14532
14533 if (*input_line_pointer == '{')
14534 input_line_pointer++;
14535
14536 SKIP_WHITESPACE ();
14537
14538 reg = arm_reg_parse (&input_line_pointer, all_reg_maps[REG_TYPE_RN].htab);
14539 if (reg != FAIL)
14540 {
14541 input_line_pointer = saved_ptr;
14542 s_arm_unwind_save_core ();
14543 return;
14544 }
14545
14546 reg = arm_reg_parse (&input_line_pointer, all_reg_maps[REG_TYPE_DN].htab);
14547 if (reg != FAIL)
14548 {
14549 input_line_pointer = saved_ptr;
14550 s_arm_unwind_save_vfp ();
14551 return;
14552 }
14553
14554 reg = arm_reg_parse (&input_line_pointer,
14555 all_reg_maps[REG_TYPE_IWMMXT].htab);
14556 if (reg != FAIL)
14557 {
14558 input_line_pointer = saved_ptr;
14559 s_arm_unwind_save_wmmx ();
14560 return;
14561 }
14562
14563 /* TODO: Maverick registers. */
14564 as_bad (_("unrecognised register"));
14565 }
14566
14567
14568 /* Parse an unwind_movsp directive. */
14569
14570 static void
14571 s_arm_unwind_movsp (int ignored ATTRIBUTE_UNUSED)
14572 {
14573 int reg;
14574 valueT op;
14575
14576 SKIP_WHITESPACE ();
14577 reg = reg_required_here (&input_line_pointer, -1);
14578 if (reg == FAIL)
14579 {
14580 as_bad (_("ARM register expected"));
14581 ignore_rest_of_line ();
14582 return;
14583 }
14584
14585 if (reg == 13 || reg == 15)
14586 {
14587 as_bad (_("r%d not permitted in .unwind_movsp directive"), reg);
14588 ignore_rest_of_line ();
14589 return;
14590 }
14591
14592 if (unwind.fp_reg != 13)
14593 as_bad (_("unexpected .unwind_movsp directive"));
14594
14595 /* Generate opcode to restore the value. */
14596 op = 0x90 | reg;
14597 add_unwind_opcode (op, 1);
14598
14599 /* Record the information for later. */
14600 unwind.fp_reg = reg;
14601 unwind.fp_offset = unwind.frame_size;
14602 unwind.sp_restored = 1;
14603 demand_empty_rest_of_line ();
14604 }
14605
14606
14607 /* Parse #<number>. */
14608
14609 static int
14610 require_hashconst (int * val)
14611 {
14612 expressionS exp;
14613
14614 SKIP_WHITESPACE ();
14615 if (*input_line_pointer == '#')
14616 {
14617 input_line_pointer++;
14618 expression (&exp);
14619 }
14620 else
14621 exp.X_op = O_illegal;
14622
14623 if (exp.X_op != O_constant)
14624 {
14625 as_bad (_("expected #constant"));
14626 ignore_rest_of_line ();
14627 return FAIL;
14628 }
14629 *val = exp.X_add_number;
14630 return SUCCESS;
14631 }
14632
14633 /* Parse an unwind_pad directive. */
14634
14635 static void
14636 s_arm_unwind_pad (int ignored ATTRIBUTE_UNUSED)
14637 {
14638 int offset;
14639
14640 if (require_hashconst (&offset) == FAIL)
14641 return;
14642
14643 if (offset & 3)
14644 {
14645 as_bad (_("stack increment must be multiple of 4"));
14646 ignore_rest_of_line ();
14647 return;
14648 }
14649
14650 /* Don't generate any opcodes, just record the details for later. */
14651 unwind.frame_size += offset;
14652 unwind.pending_offset += offset;
14653
14654 demand_empty_rest_of_line ();
14655 }
14656
14657 /* Parse an unwind_setfp directive. */
14658
14659 static void
14660 s_arm_unwind_setfp (int ignored ATTRIBUTE_UNUSED)
14661 {
14662 int sp_reg;
14663 int fp_reg;
14664 int offset;
14665
14666 fp_reg = reg_required_here (&input_line_pointer, -1);
14667 if (skip_past_comma (&input_line_pointer) == FAIL)
14668 sp_reg = FAIL;
14669 else
14670 sp_reg = reg_required_here (&input_line_pointer, -1);
14671
14672 if (fp_reg == FAIL || sp_reg == FAIL)
14673 {
14674 as_bad (_("expected <reg>, <reg>"));
14675 ignore_rest_of_line ();
14676 return;
14677 }
14678
14679 /* Optonal constant. */
14680 if (skip_past_comma (&input_line_pointer) != FAIL)
14681 {
14682 if (require_hashconst (&offset) == FAIL)
14683 return;
14684 }
14685 else
14686 offset = 0;
14687
14688 demand_empty_rest_of_line ();
14689
14690 if (sp_reg != 13 && sp_reg != unwind.fp_reg)
14691 {
14692 as_bad (_("register must be either sp or set by a previous"
14693 "unwind_movsp directive"));
14694 return;
14695 }
14696
14697 /* Don't generate any opcodes, just record the information for later. */
14698 unwind.fp_reg = fp_reg;
14699 unwind.fp_used = 1;
14700 if (sp_reg == 13)
14701 unwind.fp_offset = unwind.frame_size - offset;
14702 else
14703 unwind.fp_offset -= offset;
14704 }
14705
14706 /* Parse an unwind_raw directive. */
14707
14708 static void
14709 s_arm_unwind_raw (int ignored ATTRIBUTE_UNUSED)
14710 {
14711 expressionS exp;
14712 /* This is an arbitary limit. */
14713 unsigned char op[16];
14714 int count;
14715
14716 SKIP_WHITESPACE ();
14717 expression (&exp);
14718 if (exp.X_op == O_constant
14719 && skip_past_comma (&input_line_pointer) != FAIL)
14720 {
14721 unwind.frame_size += exp.X_add_number;
14722 expression (&exp);
14723 }
14724 else
14725 exp.X_op = O_illegal;
14726
14727 if (exp.X_op != O_constant)
14728 {
14729 as_bad (_("expected <offset>, <opcode>"));
14730 ignore_rest_of_line ();
14731 return;
14732 }
14733
14734 count = 0;
14735
14736 /* Parse the opcode. */
14737 for (;;)
14738 {
14739 if (count >= 16)
14740 {
14741 as_bad (_("unwind opcode too long"));
14742 ignore_rest_of_line ();
14743 }
14744 if (exp.X_op != O_constant || exp.X_add_number & ~0xff)
14745 {
14746 as_bad (_("invalid unwind opcode"));
14747 ignore_rest_of_line ();
14748 return;
14749 }
14750 op[count++] = exp.X_add_number;
14751
14752 /* Parse the next byte. */
14753 if (skip_past_comma (&input_line_pointer) == FAIL)
14754 break;
14755
14756 expression (&exp);
14757 }
14758
14759 /* Add the opcode bytes in reverse order. */
14760 while (count--)
14761 add_unwind_opcode (op[count], 1);
14762
14763 demand_empty_rest_of_line ();
14764 }
14765
14766 #endif /* OBJ_ELF */
14767
14768 /* This is called from HANDLE_ALIGN in write.c. Fill in the contents
14769 of an rs_align_code fragment. */
14770
14771 void
14772 arm_handle_align (fragS * fragP)
14773 {
14774 static char const arm_noop[4] = { 0x00, 0x00, 0xa0, 0xe1 };
14775 static char const thumb_noop[2] = { 0xc0, 0x46 };
14776 static char const arm_bigend_noop[4] = { 0xe1, 0xa0, 0x00, 0x00 };
14777 static char const thumb_bigend_noop[2] = { 0x46, 0xc0 };
14778
14779 int bytes, fix, noop_size;
14780 char * p;
14781 const char * noop;
14782
14783 if (fragP->fr_type != rs_align_code)
14784 return;
14785
14786 bytes = fragP->fr_next->fr_address - fragP->fr_address - fragP->fr_fix;
14787 p = fragP->fr_literal + fragP->fr_fix;
14788 fix = 0;
14789
14790 if (bytes > MAX_MEM_FOR_RS_ALIGN_CODE)
14791 bytes &= MAX_MEM_FOR_RS_ALIGN_CODE;
14792
14793 if (fragP->tc_frag_data)
14794 {
14795 if (target_big_endian)
14796 noop = thumb_bigend_noop;
14797 else
14798 noop = thumb_noop;
14799 noop_size = sizeof (thumb_noop);
14800 }
14801 else
14802 {
14803 if (target_big_endian)
14804 noop = arm_bigend_noop;
14805 else
14806 noop = arm_noop;
14807 noop_size = sizeof (arm_noop);
14808 }
14809
14810 if (bytes & (noop_size - 1))
14811 {
14812 fix = bytes & (noop_size - 1);
14813 memset (p, 0, fix);
14814 p += fix;
14815 bytes -= fix;
14816 }
14817
14818 while (bytes >= noop_size)
14819 {
14820 memcpy (p, noop, noop_size);
14821 p += noop_size;
14822 bytes -= noop_size;
14823 fix += noop_size;
14824 }
14825
14826 fragP->fr_fix += fix;
14827 fragP->fr_var = noop_size;
14828 }
14829
14830 /* Called from md_do_align. Used to create an alignment
14831 frag in a code section. */
14832
14833 void
14834 arm_frag_align_code (int n, int max)
14835 {
14836 char * p;
14837
14838 /* We assume that there will never be a requirement
14839 to support alignments greater than 32 bytes. */
14840 if (max > MAX_MEM_FOR_RS_ALIGN_CODE)
14841 as_fatal (_("alignments greater than 32 bytes not supported in .text sections."));
14842
14843 p = frag_var (rs_align_code,
14844 MAX_MEM_FOR_RS_ALIGN_CODE,
14845 1,
14846 (relax_substateT) max,
14847 (symbolS *) NULL,
14848 (offsetT) n,
14849 (char *) NULL);
14850 *p = 0;
14851 }
14852
14853 /* Perform target specific initialisation of a frag. */
14854
14855 void
14856 arm_init_frag (fragS * fragP)
14857 {
14858 /* Record whether this frag is in an ARM or a THUMB area. */
14859 fragP->tc_frag_data = thumb_mode;
14860 }
14861
14862 /* This table describes all the machine specific pseudo-ops the assembler
14863 has to support. The fields are:
14864 pseudo-op name without dot
14865 function to call to execute this pseudo-op
14866 Integer arg to pass to the function. */
14867
14868 const pseudo_typeS md_pseudo_table[] =
14869 {
14870 /* Never called because '.req' does not start a line. */
14871 { "req", s_req, 0 },
14872 { "unreq", s_unreq, 0 },
14873 { "bss", s_bss, 0 },
14874 { "align", s_align, 0 },
14875 { "arm", s_arm, 0 },
14876 { "thumb", s_thumb, 0 },
14877 { "code", s_code, 0 },
14878 { "force_thumb", s_force_thumb, 0 },
14879 { "thumb_func", s_thumb_func, 0 },
14880 { "thumb_set", s_thumb_set, 0 },
14881 { "even", s_even, 0 },
14882 { "ltorg", s_ltorg, 0 },
14883 { "pool", s_ltorg, 0 },
14884 #ifdef OBJ_ELF
14885 { "word", s_arm_elf_cons, 4 },
14886 { "long", s_arm_elf_cons, 4 },
14887 { "rel31", s_arm_rel31, 0 },
14888 { "fnstart", s_arm_unwind_fnstart, 0 },
14889 { "fnend", s_arm_unwind_fnend, 0 },
14890 { "cantunwind", s_arm_unwind_cantunwind, 0 },
14891 { "personality", s_arm_unwind_personality, 0 },
14892 { "personalityindex", s_arm_unwind_personalityindex, 0 },
14893 { "handlerdata", s_arm_unwind_handlerdata, 0 },
14894 { "save", s_arm_unwind_save, 0 },
14895 { "movsp", s_arm_unwind_movsp, 0 },
14896 { "pad", s_arm_unwind_pad, 0 },
14897 { "setfp", s_arm_unwind_setfp, 0 },
14898 { "unwind_raw", s_arm_unwind_raw, 0 },
14899 #else
14900 { "word", cons, 4},
14901 #endif
14902 { "extend", float_cons, 'x' },
14903 { "ldouble", float_cons, 'x' },
14904 { "packed", float_cons, 'p' },
14905 { 0, 0, 0 }
14906 };