gas/
[deliverable/binutils-gdb.git] / gas / config / tc-arm.c
1 /* tc-arm.c -- Assemble for the ARM
2 Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
3 2004, 2005
4 Free Software Foundation, Inc.
5 Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org)
6 Modified by David Taylor (dtaylor@armltd.co.uk)
7 Cirrus coprocessor mods by Aldy Hernandez (aldyh@redhat.com)
8 Cirrus coprocessor fixes by Petko Manolov (petkan@nucleusys.com)
9 Cirrus coprocessor fixes by Vladimir Ivanov (vladitx@nucleusys.com)
10
11 This file is part of GAS, the GNU Assembler.
12
13 GAS is free software; you can redistribute it and/or modify
14 it under the terms of the GNU General Public License as published by
15 the Free Software Foundation; either version 2, or (at your option)
16 any later version.
17
18 GAS is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with GAS; see the file COPYING. If not, write to the Free
25 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
26 02111-1307, USA. */
27
28 #include <string.h>
29 #define NO_RELOC 0
30 #include "as.h"
31 #include "safe-ctype.h"
32
33 /* Need TARGET_CPU. */
34 #include "config.h"
35 #include "subsegs.h"
36 #include "obstack.h"
37 #include "symbols.h"
38 #include "listing.h"
39
40 #include "opcode/arm.h"
41
42 #ifdef OBJ_ELF
43 #include "elf/arm.h"
44 #include "dwarf2dbg.h"
45 #include "dw2gencfi.h"
46 #endif
47
48 /* XXX Set this to 1 after the next binutils release. */
49 #define WARN_DEPRECATED 0
50
51 #ifdef OBJ_ELF
52 /* Must be at least the size of the largest unwind opcode (currently two). */
53 #define ARM_OPCODE_CHUNK_SIZE 8
54
55 /* This structure holds the unwinding state. */
56
57 static struct
58 {
59 symbolS * proc_start;
60 symbolS * table_entry;
61 symbolS * personality_routine;
62 int personality_index;
63 /* The segment containing the function. */
64 segT saved_seg;
65 subsegT saved_subseg;
66 /* Opcodes generated from this function. */
67 unsigned char * opcodes;
68 int opcode_count;
69 int opcode_alloc;
70 /* The number of bytes pushed to the stack. */
71 offsetT frame_size;
72 /* We don't add stack adjustment opcodes immediately so that we can merge
73 multiple adjustments. We can also omit the final adjustment
74 when using a frame pointer. */
75 offsetT pending_offset;
76 /* These two fields are set by both unwind_movsp and unwind_setfp. They
77 hold the reg+offset to use when restoring sp from a frame pointer. */
78 offsetT fp_offset;
79 int fp_reg;
80 /* Nonzero if an unwind_setfp directive has been seen. */
81 unsigned fp_used:1;
82 /* Nonzero if the last opcode restores sp from fp_reg. */
83 unsigned sp_restored:1;
84 } unwind;
85
86 #endif /* OBJ_ELF */
87
88 enum arm_float_abi
89 {
90 ARM_FLOAT_ABI_HARD,
91 ARM_FLOAT_ABI_SOFTFP,
92 ARM_FLOAT_ABI_SOFT
93 };
94
95 /* Types of processor to assemble for. */
96 #define ARM_1 ARM_ARCH_V1
97 #define ARM_2 ARM_ARCH_V2
98 #define ARM_3 ARM_ARCH_V2S
99 #define ARM_250 ARM_ARCH_V2S
100 #define ARM_6 ARM_ARCH_V3
101 #define ARM_7 ARM_ARCH_V3
102 #define ARM_8 ARM_ARCH_V4
103 #define ARM_9 ARM_ARCH_V4T
104 #define ARM_STRONG ARM_ARCH_V4
105 #define ARM_CPU_MASK 0x0000000f /* XXX? */
106
107 #ifndef CPU_DEFAULT
108 #if defined __XSCALE__
109 #define CPU_DEFAULT (ARM_ARCH_XSCALE)
110 #else
111 #if defined __thumb__
112 #define CPU_DEFAULT (ARM_ARCH_V5T)
113 #else
114 #define CPU_DEFAULT ARM_ANY
115 #endif
116 #endif
117 #endif
118
119 #ifndef FPU_DEFAULT
120 # ifdef TE_LINUX
121 # define FPU_DEFAULT FPU_ARCH_FPA
122 # elif defined (TE_NetBSD)
123 # ifdef OBJ_ELF
124 # define FPU_DEFAULT FPU_ARCH_VFP /* Soft-float, but VFP order. */
125 # else
126 /* Legacy a.out format. */
127 # define FPU_DEFAULT FPU_ARCH_FPA /* Soft-float, but FPA order. */
128 # endif
129 # elif defined (TE_VXWORKS)
130 # define FPU_DEFAULT FPU_ARCH_VFP /* Soft-float, VFP order. */
131 # else
132 /* For backwards compatibility, default to FPA. */
133 # define FPU_DEFAULT FPU_ARCH_FPA
134 # endif
135 #endif /* ifndef FPU_DEFAULT */
136
137 #define streq(a, b) (strcmp (a, b) == 0)
138 #define skip_whitespace(str) while (*(str) == ' ') ++(str)
139
140 static unsigned long cpu_variant;
141
142 /* Flags stored in private area of BFD structure. */
143 static int uses_apcs_26 = FALSE;
144 static int atpcs = FALSE;
145 static int support_interwork = FALSE;
146 static int uses_apcs_float = FALSE;
147 static int pic_code = FALSE;
148
149 /* Variables that we set while parsing command-line options. Once all
150 options have been read we re-process these values to set the real
151 assembly flags. */
152 static int legacy_cpu = -1;
153 static int legacy_fpu = -1;
154
155 static int mcpu_cpu_opt = -1;
156 static int mcpu_fpu_opt = -1;
157 static int march_cpu_opt = -1;
158 static int march_fpu_opt = -1;
159 static int mfpu_opt = -1;
160 static int mfloat_abi_opt = -1;
161 #ifdef OBJ_ELF
162 # ifdef EABI_DEFAULT
163 static int meabi_flags = EABI_DEFAULT;
164 # else
165 static int meabi_flags = EF_ARM_EABI_UNKNOWN;
166 # endif
167 #endif
168
169 /* This array holds the chars that always start a comment. If the
170 pre-processor is disabled, these aren't very useful. */
171 const char comment_chars[] = "@";
172
173 /* This array holds the chars that only start a comment at the beginning of
174 a line. If the line seems to have the form '# 123 filename'
175 .line and .file directives will appear in the pre-processed output. */
176 /* Note that input_file.c hand checks for '#' at the beginning of the
177 first line of the input file. This is because the compiler outputs
178 #NO_APP at the beginning of its output. */
179 /* Also note that comments like this one will always work. */
180 const char line_comment_chars[] = "#";
181
182 const char line_separator_chars[] = ";";
183
184 /* Chars that can be used to separate mant
185 from exp in floating point numbers. */
186 const char EXP_CHARS[] = "eE";
187
188 /* Chars that mean this number is a floating point constant. */
189 /* As in 0f12.456 */
190 /* or 0d1.2345e12 */
191
192 const char FLT_CHARS[] = "rRsSfFdDxXeEpP";
193
194 /* Prefix characters that indicate the start of an immediate
195 value. */
196 #define is_immediate_prefix(C) ((C) == '#' || (C) == '$')
197
198 #ifdef OBJ_ELF
199 /* Pre-defined "_GLOBAL_OFFSET_TABLE_" */
200 symbolS * GOT_symbol;
201 #endif
202
203 /* Size of relocation record. */
204 const int md_reloc_size = 8;
205
206 /* 0: assemble for ARM,
207 1: assemble for Thumb,
208 2: assemble for Thumb even though target CPU does not support thumb
209 instructions. */
210 static int thumb_mode = 0;
211
212 typedef struct arm_fix
213 {
214 int thumb_mode;
215 } arm_fix_data;
216
217 struct arm_it
218 {
219 const char * error;
220 unsigned long instruction;
221 int size;
222 struct
223 {
224 bfd_reloc_code_real_type type;
225 expressionS exp;
226 int pc_rel;
227 } reloc;
228 };
229
230 struct arm_it inst;
231
232 enum asm_shift_index
233 {
234 SHIFT_LSL = 0,
235 SHIFT_LSR,
236 SHIFT_ASR,
237 SHIFT_ROR,
238 SHIFT_RRX
239 };
240
241 struct asm_shift_properties
242 {
243 enum asm_shift_index index;
244 unsigned long bit_field;
245 unsigned int allows_0 : 1;
246 unsigned int allows_32 : 1;
247 };
248
249 static const struct asm_shift_properties shift_properties [] =
250 {
251 { SHIFT_LSL, 0, 1, 0},
252 { SHIFT_LSR, 0x20, 0, 1},
253 { SHIFT_ASR, 0x40, 0, 1},
254 { SHIFT_ROR, 0x60, 0, 0},
255 { SHIFT_RRX, 0x60, 0, 0}
256 };
257
258 struct asm_shift_name
259 {
260 const char * name;
261 const struct asm_shift_properties * properties;
262 };
263
264 static const struct asm_shift_name shift_names [] =
265 {
266 { "asl", shift_properties + SHIFT_LSL },
267 { "lsl", shift_properties + SHIFT_LSL },
268 { "lsr", shift_properties + SHIFT_LSR },
269 { "asr", shift_properties + SHIFT_ASR },
270 { "ror", shift_properties + SHIFT_ROR },
271 { "rrx", shift_properties + SHIFT_RRX },
272 { "ASL", shift_properties + SHIFT_LSL },
273 { "LSL", shift_properties + SHIFT_LSL },
274 { "LSR", shift_properties + SHIFT_LSR },
275 { "ASR", shift_properties + SHIFT_ASR },
276 { "ROR", shift_properties + SHIFT_ROR },
277 { "RRX", shift_properties + SHIFT_RRX }
278 };
279
280 /* Any kind of shift is accepted. */
281 #define NO_SHIFT_RESTRICT 1
282 /* The shift operand must be an immediate value, not a register. */
283 #define SHIFT_IMMEDIATE 0
284 /* The shift must be LSL or ASR and the operand must be an immediate. */
285 #define SHIFT_LSL_OR_ASR_IMMEDIATE 2
286 /* The shift must be ASR and the operand must be an immediate. */
287 #define SHIFT_ASR_IMMEDIATE 3
288 /* The shift must be LSL and the operand must be an immediate. */
289 #define SHIFT_LSL_IMMEDIATE 4
290
291 #define NUM_FLOAT_VALS 8
292
293 const char * fp_const[] =
294 {
295 "0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0", 0
296 };
297
298 /* Number of littlenums required to hold an extended precision number. */
299 #define MAX_LITTLENUMS 6
300
301 LITTLENUM_TYPE fp_values[NUM_FLOAT_VALS][MAX_LITTLENUMS];
302
303 #define FAIL (-1)
304 #define SUCCESS (0)
305
306 /* Whether a Co-processor load/store operation accepts write-back forms. */
307 #define CP_WB_OK 1
308 #define CP_NO_WB 0
309
310 #define SUFF_S 1
311 #define SUFF_D 2
312 #define SUFF_E 3
313 #define SUFF_P 4
314
315 #define CP_T_X 0x00008000
316 #define CP_T_Y 0x00400000
317 #define CP_T_Pre 0x01000000
318 #define CP_T_UD 0x00800000
319 #define CP_T_WB 0x00200000
320
321 #define CONDS_BIT 0x00100000
322 #define LOAD_BIT 0x00100000
323
324 #define DOUBLE_LOAD_FLAG 0x00000001
325
326 struct asm_cond
327 {
328 const char * template;
329 unsigned long value;
330 };
331
332 #define COND_ALWAYS 0xe0000000
333 #define COND_MASK 0xf0000000
334
335 static const struct asm_cond conds[] =
336 {
337 {"eq", 0x00000000},
338 {"ne", 0x10000000},
339 {"cs", 0x20000000}, {"hs", 0x20000000},
340 {"cc", 0x30000000}, {"ul", 0x30000000}, {"lo", 0x30000000},
341 {"mi", 0x40000000},
342 {"pl", 0x50000000},
343 {"vs", 0x60000000},
344 {"vc", 0x70000000},
345 {"hi", 0x80000000},
346 {"ls", 0x90000000},
347 {"ge", 0xa0000000},
348 {"lt", 0xb0000000},
349 {"gt", 0xc0000000},
350 {"le", 0xd0000000},
351 {"al", 0xe0000000},
352 {"nv", 0xf0000000}
353 };
354
355 struct asm_psr
356 {
357 const char *template;
358 bfd_boolean cpsr;
359 unsigned long field;
360 };
361
362 /* The bit that distinguishes CPSR and SPSR. */
363 #define SPSR_BIT (1 << 22)
364
365 /* How many bits to shift the PSR_xxx bits up by. */
366 #define PSR_SHIFT 16
367
368 #define PSR_c (1 << 0)
369 #define PSR_x (1 << 1)
370 #define PSR_s (1 << 2)
371 #define PSR_f (1 << 3)
372
373 static const struct asm_psr psrs[] =
374 {
375 {"CPSR", TRUE, PSR_c | PSR_f},
376 {"CPSR_all", TRUE, PSR_c | PSR_f},
377 {"SPSR", FALSE, PSR_c | PSR_f},
378 {"SPSR_all", FALSE, PSR_c | PSR_f},
379 {"CPSR_flg", TRUE, PSR_f},
380 {"CPSR_f", TRUE, PSR_f},
381 {"SPSR_flg", FALSE, PSR_f},
382 {"SPSR_f", FALSE, PSR_f},
383 {"CPSR_c", TRUE, PSR_c},
384 {"CPSR_ctl", TRUE, PSR_c},
385 {"SPSR_c", FALSE, PSR_c},
386 {"SPSR_ctl", FALSE, PSR_c},
387 {"CPSR_x", TRUE, PSR_x},
388 {"CPSR_s", TRUE, PSR_s},
389 {"SPSR_x", FALSE, PSR_x},
390 {"SPSR_s", FALSE, PSR_s},
391 /* Combinations of flags. */
392 {"CPSR_fs", TRUE, PSR_f | PSR_s},
393 {"CPSR_fx", TRUE, PSR_f | PSR_x},
394 {"CPSR_fc", TRUE, PSR_f | PSR_c},
395 {"CPSR_sf", TRUE, PSR_s | PSR_f},
396 {"CPSR_sx", TRUE, PSR_s | PSR_x},
397 {"CPSR_sc", TRUE, PSR_s | PSR_c},
398 {"CPSR_xf", TRUE, PSR_x | PSR_f},
399 {"CPSR_xs", TRUE, PSR_x | PSR_s},
400 {"CPSR_xc", TRUE, PSR_x | PSR_c},
401 {"CPSR_cf", TRUE, PSR_c | PSR_f},
402 {"CPSR_cs", TRUE, PSR_c | PSR_s},
403 {"CPSR_cx", TRUE, PSR_c | PSR_x},
404 {"CPSR_fsx", TRUE, PSR_f | PSR_s | PSR_x},
405 {"CPSR_fsc", TRUE, PSR_f | PSR_s | PSR_c},
406 {"CPSR_fxs", TRUE, PSR_f | PSR_x | PSR_s},
407 {"CPSR_fxc", TRUE, PSR_f | PSR_x | PSR_c},
408 {"CPSR_fcs", TRUE, PSR_f | PSR_c | PSR_s},
409 {"CPSR_fcx", TRUE, PSR_f | PSR_c | PSR_x},
410 {"CPSR_sfx", TRUE, PSR_s | PSR_f | PSR_x},
411 {"CPSR_sfc", TRUE, PSR_s | PSR_f | PSR_c},
412 {"CPSR_sxf", TRUE, PSR_s | PSR_x | PSR_f},
413 {"CPSR_sxc", TRUE, PSR_s | PSR_x | PSR_c},
414 {"CPSR_scf", TRUE, PSR_s | PSR_c | PSR_f},
415 {"CPSR_scx", TRUE, PSR_s | PSR_c | PSR_x},
416 {"CPSR_xfs", TRUE, PSR_x | PSR_f | PSR_s},
417 {"CPSR_xfc", TRUE, PSR_x | PSR_f | PSR_c},
418 {"CPSR_xsf", TRUE, PSR_x | PSR_s | PSR_f},
419 {"CPSR_xsc", TRUE, PSR_x | PSR_s | PSR_c},
420 {"CPSR_xcf", TRUE, PSR_x | PSR_c | PSR_f},
421 {"CPSR_xcs", TRUE, PSR_x | PSR_c | PSR_s},
422 {"CPSR_cfs", TRUE, PSR_c | PSR_f | PSR_s},
423 {"CPSR_cfx", TRUE, PSR_c | PSR_f | PSR_x},
424 {"CPSR_csf", TRUE, PSR_c | PSR_s | PSR_f},
425 {"CPSR_csx", TRUE, PSR_c | PSR_s | PSR_x},
426 {"CPSR_cxf", TRUE, PSR_c | PSR_x | PSR_f},
427 {"CPSR_cxs", TRUE, PSR_c | PSR_x | PSR_s},
428 {"CPSR_fsxc", TRUE, PSR_f | PSR_s | PSR_x | PSR_c},
429 {"CPSR_fscx", TRUE, PSR_f | PSR_s | PSR_c | PSR_x},
430 {"CPSR_fxsc", TRUE, PSR_f | PSR_x | PSR_s | PSR_c},
431 {"CPSR_fxcs", TRUE, PSR_f | PSR_x | PSR_c | PSR_s},
432 {"CPSR_fcsx", TRUE, PSR_f | PSR_c | PSR_s | PSR_x},
433 {"CPSR_fcxs", TRUE, PSR_f | PSR_c | PSR_x | PSR_s},
434 {"CPSR_sfxc", TRUE, PSR_s | PSR_f | PSR_x | PSR_c},
435 {"CPSR_sfcx", TRUE, PSR_s | PSR_f | PSR_c | PSR_x},
436 {"CPSR_sxfc", TRUE, PSR_s | PSR_x | PSR_f | PSR_c},
437 {"CPSR_sxcf", TRUE, PSR_s | PSR_x | PSR_c | PSR_f},
438 {"CPSR_scfx", TRUE, PSR_s | PSR_c | PSR_f | PSR_x},
439 {"CPSR_scxf", TRUE, PSR_s | PSR_c | PSR_x | PSR_f},
440 {"CPSR_xfsc", TRUE, PSR_x | PSR_f | PSR_s | PSR_c},
441 {"CPSR_xfcs", TRUE, PSR_x | PSR_f | PSR_c | PSR_s},
442 {"CPSR_xsfc", TRUE, PSR_x | PSR_s | PSR_f | PSR_c},
443 {"CPSR_xscf", TRUE, PSR_x | PSR_s | PSR_c | PSR_f},
444 {"CPSR_xcfs", TRUE, PSR_x | PSR_c | PSR_f | PSR_s},
445 {"CPSR_xcsf", TRUE, PSR_x | PSR_c | PSR_s | PSR_f},
446 {"CPSR_cfsx", TRUE, PSR_c | PSR_f | PSR_s | PSR_x},
447 {"CPSR_cfxs", TRUE, PSR_c | PSR_f | PSR_x | PSR_s},
448 {"CPSR_csfx", TRUE, PSR_c | PSR_s | PSR_f | PSR_x},
449 {"CPSR_csxf", TRUE, PSR_c | PSR_s | PSR_x | PSR_f},
450 {"CPSR_cxfs", TRUE, PSR_c | PSR_x | PSR_f | PSR_s},
451 {"CPSR_cxsf", TRUE, PSR_c | PSR_x | PSR_s | PSR_f},
452 {"SPSR_fs", FALSE, PSR_f | PSR_s},
453 {"SPSR_fx", FALSE, PSR_f | PSR_x},
454 {"SPSR_fc", FALSE, PSR_f | PSR_c},
455 {"SPSR_sf", FALSE, PSR_s | PSR_f},
456 {"SPSR_sx", FALSE, PSR_s | PSR_x},
457 {"SPSR_sc", FALSE, PSR_s | PSR_c},
458 {"SPSR_xf", FALSE, PSR_x | PSR_f},
459 {"SPSR_xs", FALSE, PSR_x | PSR_s},
460 {"SPSR_xc", FALSE, PSR_x | PSR_c},
461 {"SPSR_cf", FALSE, PSR_c | PSR_f},
462 {"SPSR_cs", FALSE, PSR_c | PSR_s},
463 {"SPSR_cx", FALSE, PSR_c | PSR_x},
464 {"SPSR_fsx", FALSE, PSR_f | PSR_s | PSR_x},
465 {"SPSR_fsc", FALSE, PSR_f | PSR_s | PSR_c},
466 {"SPSR_fxs", FALSE, PSR_f | PSR_x | PSR_s},
467 {"SPSR_fxc", FALSE, PSR_f | PSR_x | PSR_c},
468 {"SPSR_fcs", FALSE, PSR_f | PSR_c | PSR_s},
469 {"SPSR_fcx", FALSE, PSR_f | PSR_c | PSR_x},
470 {"SPSR_sfx", FALSE, PSR_s | PSR_f | PSR_x},
471 {"SPSR_sfc", FALSE, PSR_s | PSR_f | PSR_c},
472 {"SPSR_sxf", FALSE, PSR_s | PSR_x | PSR_f},
473 {"SPSR_sxc", FALSE, PSR_s | PSR_x | PSR_c},
474 {"SPSR_scf", FALSE, PSR_s | PSR_c | PSR_f},
475 {"SPSR_scx", FALSE, PSR_s | PSR_c | PSR_x},
476 {"SPSR_xfs", FALSE, PSR_x | PSR_f | PSR_s},
477 {"SPSR_xfc", FALSE, PSR_x | PSR_f | PSR_c},
478 {"SPSR_xsf", FALSE, PSR_x | PSR_s | PSR_f},
479 {"SPSR_xsc", FALSE, PSR_x | PSR_s | PSR_c},
480 {"SPSR_xcf", FALSE, PSR_x | PSR_c | PSR_f},
481 {"SPSR_xcs", FALSE, PSR_x | PSR_c | PSR_s},
482 {"SPSR_cfs", FALSE, PSR_c | PSR_f | PSR_s},
483 {"SPSR_cfx", FALSE, PSR_c | PSR_f | PSR_x},
484 {"SPSR_csf", FALSE, PSR_c | PSR_s | PSR_f},
485 {"SPSR_csx", FALSE, PSR_c | PSR_s | PSR_x},
486 {"SPSR_cxf", FALSE, PSR_c | PSR_x | PSR_f},
487 {"SPSR_cxs", FALSE, PSR_c | PSR_x | PSR_s},
488 {"SPSR_fsxc", FALSE, PSR_f | PSR_s | PSR_x | PSR_c},
489 {"SPSR_fscx", FALSE, PSR_f | PSR_s | PSR_c | PSR_x},
490 {"SPSR_fxsc", FALSE, PSR_f | PSR_x | PSR_s | PSR_c},
491 {"SPSR_fxcs", FALSE, PSR_f | PSR_x | PSR_c | PSR_s},
492 {"SPSR_fcsx", FALSE, PSR_f | PSR_c | PSR_s | PSR_x},
493 {"SPSR_fcxs", FALSE, PSR_f | PSR_c | PSR_x | PSR_s},
494 {"SPSR_sfxc", FALSE, PSR_s | PSR_f | PSR_x | PSR_c},
495 {"SPSR_sfcx", FALSE, PSR_s | PSR_f | PSR_c | PSR_x},
496 {"SPSR_sxfc", FALSE, PSR_s | PSR_x | PSR_f | PSR_c},
497 {"SPSR_sxcf", FALSE, PSR_s | PSR_x | PSR_c | PSR_f},
498 {"SPSR_scfx", FALSE, PSR_s | PSR_c | PSR_f | PSR_x},
499 {"SPSR_scxf", FALSE, PSR_s | PSR_c | PSR_x | PSR_f},
500 {"SPSR_xfsc", FALSE, PSR_x | PSR_f | PSR_s | PSR_c},
501 {"SPSR_xfcs", FALSE, PSR_x | PSR_f | PSR_c | PSR_s},
502 {"SPSR_xsfc", FALSE, PSR_x | PSR_s | PSR_f | PSR_c},
503 {"SPSR_xscf", FALSE, PSR_x | PSR_s | PSR_c | PSR_f},
504 {"SPSR_xcfs", FALSE, PSR_x | PSR_c | PSR_f | PSR_s},
505 {"SPSR_xcsf", FALSE, PSR_x | PSR_c | PSR_s | PSR_f},
506 {"SPSR_cfsx", FALSE, PSR_c | PSR_f | PSR_s | PSR_x},
507 {"SPSR_cfxs", FALSE, PSR_c | PSR_f | PSR_x | PSR_s},
508 {"SPSR_csfx", FALSE, PSR_c | PSR_s | PSR_f | PSR_x},
509 {"SPSR_csxf", FALSE, PSR_c | PSR_s | PSR_x | PSR_f},
510 {"SPSR_cxfs", FALSE, PSR_c | PSR_x | PSR_f | PSR_s},
511 {"SPSR_cxsf", FALSE, PSR_c | PSR_x | PSR_s | PSR_f},
512 };
513
514 enum wreg_type
515 {
516 IWMMXT_REG_WR = 0,
517 IWMMXT_REG_WC = 1,
518 IWMMXT_REG_WR_OR_WC = 2,
519 IWMMXT_REG_WCG
520 };
521
522 enum iwmmxt_insn_type
523 {
524 check_rd,
525 check_wr,
526 check_wrwr,
527 check_wrwrwr,
528 check_wrwrwcg,
529 check_tbcst,
530 check_tmovmsk,
531 check_tmia,
532 check_tmcrr,
533 check_tmrrc,
534 check_tmcr,
535 check_tmrc,
536 check_tinsr,
537 check_textrc,
538 check_waligni,
539 check_textrm,
540 check_wshufh
541 };
542
543 enum vfp_dp_reg_pos
544 {
545 VFP_REG_Dd, VFP_REG_Dm, VFP_REG_Dn
546 };
547
548 enum vfp_sp_reg_pos
549 {
550 VFP_REG_Sd, VFP_REG_Sm, VFP_REG_Sn
551 };
552
553 enum vfp_ldstm_type
554 {
555 VFP_LDSTMIA, VFP_LDSTMDB, VFP_LDSTMIAX, VFP_LDSTMDBX
556 };
557
558 /* VFP system registers. */
559 struct vfp_reg
560 {
561 const char *name;
562 unsigned long regno;
563 };
564
565 static const struct vfp_reg vfp_regs[] =
566 {
567 {"fpsid", 0x00000000},
568 {"FPSID", 0x00000000},
569 {"fpscr", 0x00010000},
570 {"FPSCR", 0x00010000},
571 {"fpexc", 0x00080000},
572 {"FPEXC", 0x00080000}
573 };
574
575 /* Structure for a hash table entry for a register. */
576 struct reg_entry
577 {
578 const char * name;
579 int number;
580 bfd_boolean builtin;
581 };
582
583 /* Some well known registers that we refer to directly elsewhere. */
584 #define REG_SP 13
585 #define REG_LR 14
586 #define REG_PC 15
587
588 #define wr_register(reg) ((reg ^ WR_PREFIX) >= 0 && (reg ^ WR_PREFIX) <= 15)
589 #define wc_register(reg) ((reg ^ WC_PREFIX) >= 0 && (reg ^ WC_PREFIX) <= 15)
590 #define wcg_register(reg) ((reg ^ WC_PREFIX) >= 8 && (reg ^ WC_PREFIX) <= 11)
591
592 /* These are the standard names. Users can add aliases with .req.
593 and delete them with .unreq. */
594
595 /* Integer Register Numbers. */
596 static const struct reg_entry rn_table[] =
597 {
598 {"r0", 0, TRUE}, {"r1", 1, TRUE}, {"r2", 2, TRUE}, {"r3", 3, TRUE},
599 {"r4", 4, TRUE}, {"r5", 5, TRUE}, {"r6", 6, TRUE}, {"r7", 7, TRUE},
600 {"r8", 8, TRUE}, {"r9", 9, TRUE}, {"r10", 10, TRUE}, {"r11", 11, TRUE},
601 {"r12", 12, TRUE}, {"r13", REG_SP, TRUE}, {"r14", REG_LR, TRUE}, {"r15", REG_PC, TRUE},
602 /* ATPCS Synonyms. */
603 {"a1", 0, TRUE}, {"a2", 1, TRUE}, {"a3", 2, TRUE}, {"a4", 3, TRUE},
604 {"v1", 4, TRUE}, {"v2", 5, TRUE}, {"v3", 6, TRUE}, {"v4", 7, TRUE},
605 {"v5", 8, TRUE}, {"v6", 9, TRUE}, {"v7", 10, TRUE}, {"v8", 11, TRUE},
606 /* Well-known aliases. */
607 {"wr", 7, TRUE}, {"sb", 9, TRUE}, {"sl", 10, TRUE}, {"fp", 11, TRUE},
608 {"ip", 12, TRUE}, {"sp", REG_SP, TRUE}, {"lr", REG_LR, TRUE}, {"pc", REG_PC, TRUE},
609 {NULL, 0, TRUE}
610 };
611
612 #define WR_PREFIX 0x200
613 #define WC_PREFIX 0x400
614
615 static const struct reg_entry iwmmxt_table[] =
616 {
617 /* Intel Wireless MMX technology register names. */
618 { "wr0", 0x0 | WR_PREFIX, TRUE}, {"wr1", 0x1 | WR_PREFIX, TRUE},
619 { "wr2", 0x2 | WR_PREFIX, TRUE}, {"wr3", 0x3 | WR_PREFIX, TRUE},
620 { "wr4", 0x4 | WR_PREFIX, TRUE}, {"wr5", 0x5 | WR_PREFIX, TRUE},
621 { "wr6", 0x6 | WR_PREFIX, TRUE}, {"wr7", 0x7 | WR_PREFIX, TRUE},
622 { "wr8", 0x8 | WR_PREFIX, TRUE}, {"wr9", 0x9 | WR_PREFIX, TRUE},
623 { "wr10", 0xa | WR_PREFIX, TRUE}, {"wr11", 0xb | WR_PREFIX, TRUE},
624 { "wr12", 0xc | WR_PREFIX, TRUE}, {"wr13", 0xd | WR_PREFIX, TRUE},
625 { "wr14", 0xe | WR_PREFIX, TRUE}, {"wr15", 0xf | WR_PREFIX, TRUE},
626 { "wcid", 0x0 | WC_PREFIX, TRUE}, {"wcon", 0x1 | WC_PREFIX, TRUE},
627 {"wcssf", 0x2 | WC_PREFIX, TRUE}, {"wcasf", 0x3 | WC_PREFIX, TRUE},
628 {"wcgr0", 0x8 | WC_PREFIX, TRUE}, {"wcgr1", 0x9 | WC_PREFIX, TRUE},
629 {"wcgr2", 0xa | WC_PREFIX, TRUE}, {"wcgr3", 0xb | WC_PREFIX, TRUE},
630
631 { "wR0", 0x0 | WR_PREFIX, TRUE}, {"wR1", 0x1 | WR_PREFIX, TRUE},
632 { "wR2", 0x2 | WR_PREFIX, TRUE}, {"wR3", 0x3 | WR_PREFIX, TRUE},
633 { "wR4", 0x4 | WR_PREFIX, TRUE}, {"wR5", 0x5 | WR_PREFIX, TRUE},
634 { "wR6", 0x6 | WR_PREFIX, TRUE}, {"wR7", 0x7 | WR_PREFIX, TRUE},
635 { "wR8", 0x8 | WR_PREFIX, TRUE}, {"wR9", 0x9 | WR_PREFIX, TRUE},
636 { "wR10", 0xa | WR_PREFIX, TRUE}, {"wR11", 0xb | WR_PREFIX, TRUE},
637 { "wR12", 0xc | WR_PREFIX, TRUE}, {"wR13", 0xd | WR_PREFIX, TRUE},
638 { "wR14", 0xe | WR_PREFIX, TRUE}, {"wR15", 0xf | WR_PREFIX, TRUE},
639 { "wCID", 0x0 | WC_PREFIX, TRUE}, {"wCon", 0x1 | WC_PREFIX, TRUE},
640 {"wCSSF", 0x2 | WC_PREFIX, TRUE}, {"wCASF", 0x3 | WC_PREFIX, TRUE},
641 {"wCGR0", 0x8 | WC_PREFIX, TRUE}, {"wCGR1", 0x9 | WC_PREFIX, TRUE},
642 {"wCGR2", 0xa | WC_PREFIX, TRUE}, {"wCGR3", 0xb | WC_PREFIX, TRUE},
643 {NULL, 0, TRUE}
644 };
645
646 /* Co-processor Numbers. */
647 static const struct reg_entry cp_table[] =
648 {
649 {"p0", 0, TRUE}, {"p1", 1, TRUE}, {"p2", 2, TRUE}, {"p3", 3, TRUE},
650 {"p4", 4, TRUE}, {"p5", 5, TRUE}, {"p6", 6, TRUE}, {"p7", 7, TRUE},
651 {"p8", 8, TRUE}, {"p9", 9, TRUE}, {"p10", 10, TRUE}, {"p11", 11, TRUE},
652 {"p12", 12, TRUE}, {"p13", 13, TRUE}, {"p14", 14, TRUE}, {"p15", 15, TRUE},
653 {NULL, 0, TRUE}
654 };
655
656 /* Co-processor Register Numbers. */
657 static const struct reg_entry cn_table[] =
658 {
659 {"c0", 0, TRUE}, {"c1", 1, TRUE}, {"c2", 2, TRUE}, {"c3", 3, TRUE},
660 {"c4", 4, TRUE}, {"c5", 5, TRUE}, {"c6", 6, TRUE}, {"c7", 7, TRUE},
661 {"c8", 8, TRUE}, {"c9", 9, TRUE}, {"c10", 10, TRUE}, {"c11", 11, TRUE},
662 {"c12", 12, TRUE}, {"c13", 13, TRUE}, {"c14", 14, TRUE}, {"c15", 15, TRUE},
663 /* Not really valid, but kept for back-wards compatibility. */
664 {"cr0", 0, TRUE}, {"cr1", 1, TRUE}, {"cr2", 2, TRUE}, {"cr3", 3, TRUE},
665 {"cr4", 4, TRUE}, {"cr5", 5, TRUE}, {"cr6", 6, TRUE}, {"cr7", 7, TRUE},
666 {"cr8", 8, TRUE}, {"cr9", 9, TRUE}, {"cr10", 10, TRUE}, {"cr11", 11, TRUE},
667 {"cr12", 12, TRUE}, {"cr13", 13, TRUE}, {"cr14", 14, TRUE}, {"cr15", 15, TRUE},
668 {NULL, 0, TRUE}
669 };
670
671 /* FPA Registers. */
672 static const struct reg_entry fn_table[] =
673 {
674 {"f0", 0, TRUE}, {"f1", 1, TRUE}, {"f2", 2, TRUE}, {"f3", 3, TRUE},
675 {"f4", 4, TRUE}, {"f5", 5, TRUE}, {"f6", 6, TRUE}, {"f7", 7, TRUE},
676 {NULL, 0, TRUE}
677 };
678
679 /* VFP SP Registers. */
680 static const struct reg_entry sn_table[] =
681 {
682 {"s0", 0, TRUE}, {"s1", 1, TRUE}, {"s2", 2, TRUE}, {"s3", 3, TRUE},
683 {"s4", 4, TRUE}, {"s5", 5, TRUE}, {"s6", 6, TRUE}, {"s7", 7, TRUE},
684 {"s8", 8, TRUE}, {"s9", 9, TRUE}, {"s10", 10, TRUE}, {"s11", 11, TRUE},
685 {"s12", 12, TRUE}, {"s13", 13, TRUE}, {"s14", 14, TRUE}, {"s15", 15, TRUE},
686 {"s16", 16, TRUE}, {"s17", 17, TRUE}, {"s18", 18, TRUE}, {"s19", 19, TRUE},
687 {"s20", 20, TRUE}, {"s21", 21, TRUE}, {"s22", 22, TRUE}, {"s23", 23, TRUE},
688 {"s24", 24, TRUE}, {"s25", 25, TRUE}, {"s26", 26, TRUE}, {"s27", 27, TRUE},
689 {"s28", 28, TRUE}, {"s29", 29, TRUE}, {"s30", 30, TRUE}, {"s31", 31, TRUE},
690 {NULL, 0, TRUE}
691 };
692
693 /* VFP DP Registers. */
694 static const struct reg_entry dn_table[] =
695 {
696 {"d0", 0, TRUE}, {"d1", 1, TRUE}, {"d2", 2, TRUE}, {"d3", 3, TRUE},
697 {"d4", 4, TRUE}, {"d5", 5, TRUE}, {"d6", 6, TRUE}, {"d7", 7, TRUE},
698 {"d8", 8, TRUE}, {"d9", 9, TRUE}, {"d10", 10, TRUE}, {"d11", 11, TRUE},
699 {"d12", 12, TRUE}, {"d13", 13, TRUE}, {"d14", 14, TRUE}, {"d15", 15, TRUE},
700 {NULL, 0, TRUE}
701 };
702
703 /* Maverick DSP coprocessor registers. */
704 static const struct reg_entry mav_mvf_table[] =
705 {
706 {"mvf0", 0, TRUE}, {"mvf1", 1, TRUE}, {"mvf2", 2, TRUE}, {"mvf3", 3, TRUE},
707 {"mvf4", 4, TRUE}, {"mvf5", 5, TRUE}, {"mvf6", 6, TRUE}, {"mvf7", 7, TRUE},
708 {"mvf8", 8, TRUE}, {"mvf9", 9, TRUE}, {"mvf10", 10, TRUE}, {"mvf11", 11, TRUE},
709 {"mvf12", 12, TRUE}, {"mvf13", 13, TRUE}, {"mvf14", 14, TRUE}, {"mvf15", 15, TRUE},
710 {NULL, 0, TRUE}
711 };
712
713 static const struct reg_entry mav_mvd_table[] =
714 {
715 {"mvd0", 0, TRUE}, {"mvd1", 1, TRUE}, {"mvd2", 2, TRUE}, {"mvd3", 3, TRUE},
716 {"mvd4", 4, TRUE}, {"mvd5", 5, TRUE}, {"mvd6", 6, TRUE}, {"mvd7", 7, TRUE},
717 {"mvd8", 8, TRUE}, {"mvd9", 9, TRUE}, {"mvd10", 10, TRUE}, {"mvd11", 11, TRUE},
718 {"mvd12", 12, TRUE}, {"mvd13", 13, TRUE}, {"mvd14", 14, TRUE}, {"mvd15", 15, TRUE},
719 {NULL, 0, TRUE}
720 };
721
722 static const struct reg_entry mav_mvfx_table[] =
723 {
724 {"mvfx0", 0, TRUE}, {"mvfx1", 1, TRUE}, {"mvfx2", 2, TRUE}, {"mvfx3", 3, TRUE},
725 {"mvfx4", 4, TRUE}, {"mvfx5", 5, TRUE}, {"mvfx6", 6, TRUE}, {"mvfx7", 7, TRUE},
726 {"mvfx8", 8, TRUE}, {"mvfx9", 9, TRUE}, {"mvfx10", 10, TRUE}, {"mvfx11", 11, TRUE},
727 {"mvfx12", 12, TRUE}, {"mvfx13", 13, TRUE}, {"mvfx14", 14, TRUE}, {"mvfx15", 15, TRUE},
728 {NULL, 0, TRUE}
729 };
730
731 static const struct reg_entry mav_mvdx_table[] =
732 {
733 {"mvdx0", 0, TRUE}, {"mvdx1", 1, TRUE}, {"mvdx2", 2, TRUE}, {"mvdx3", 3, TRUE},
734 {"mvdx4", 4, TRUE}, {"mvdx5", 5, TRUE}, {"mvdx6", 6, TRUE}, {"mvdx7", 7, TRUE},
735 {"mvdx8", 8, TRUE}, {"mvdx9", 9, TRUE}, {"mvdx10", 10, TRUE}, {"mvdx11", 11, TRUE},
736 {"mvdx12", 12, TRUE}, {"mvdx13", 13, TRUE}, {"mvdx14", 14, TRUE}, {"mvdx15", 15, TRUE},
737 {NULL, 0, TRUE}
738 };
739
740 static const struct reg_entry mav_mvax_table[] =
741 {
742 {"mvax0", 0, TRUE}, {"mvax1", 1, TRUE}, {"mvax2", 2, TRUE}, {"mvax3", 3, TRUE},
743 {NULL, 0, TRUE}
744 };
745
746 static const struct reg_entry mav_dspsc_table[] =
747 {
748 {"dspsc", 0, TRUE},
749 {NULL, 0, TRUE}
750 };
751
752 struct reg_map
753 {
754 const struct reg_entry * names;
755 int max_regno;
756 struct hash_control * htab;
757 const char * expected;
758 };
759
760 struct reg_map all_reg_maps[] =
761 {
762 {rn_table, 15, NULL, N_("ARM register expected")},
763 {cp_table, 15, NULL, N_("bad or missing co-processor number")},
764 {cn_table, 15, NULL, N_("co-processor register expected")},
765 {fn_table, 7, NULL, N_("FPA register expected")},
766 {sn_table, 31, NULL, N_("VFP single precision register expected")},
767 {dn_table, 15, NULL, N_("VFP double precision register expected")},
768 {mav_mvf_table, 15, NULL, N_("Maverick MVF register expected")},
769 {mav_mvd_table, 15, NULL, N_("Maverick MVD register expected")},
770 {mav_mvfx_table, 15, NULL, N_("Maverick MVFX register expected")},
771 {mav_mvdx_table, 15, NULL, N_("Maverick MVDX register expected")},
772 {mav_mvax_table, 3, NULL, N_("Maverick MVAX register expected")},
773 {mav_dspsc_table, 0, NULL, N_("Maverick DSPSC register expected")},
774 {iwmmxt_table, 23, NULL, N_("Intel Wireless MMX technology register expected")},
775 };
776
777 /* Enumeration matching entries in table above. */
778 enum arm_reg_type
779 {
780 REG_TYPE_RN = 0,
781 #define REG_TYPE_FIRST REG_TYPE_RN
782 REG_TYPE_CP = 1,
783 REG_TYPE_CN = 2,
784 REG_TYPE_FN = 3,
785 REG_TYPE_SN = 4,
786 REG_TYPE_DN = 5,
787 REG_TYPE_MVF = 6,
788 REG_TYPE_MVD = 7,
789 REG_TYPE_MVFX = 8,
790 REG_TYPE_MVDX = 9,
791 REG_TYPE_MVAX = 10,
792 REG_TYPE_DSPSC = 11,
793 REG_TYPE_IWMMXT = 12,
794
795 REG_TYPE_MAX = 13
796 };
797
798 /* ARM instructions take 4bytes in the object file, Thumb instructions
799 take 2: */
800 #define INSN_SIZE 4
801
802 /* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
803 #define MAV_MODE1 0x100c
804
805 /* "INSN<cond> X,Y" where X:bit16, Y:bit12. */
806 #define MAV_MODE2 0x0c10
807
808 /* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
809 #define MAV_MODE3 0x100c
810
811 /* "INSN<cond> X,Y,Z" where X:16, Y:0, Z:12. */
812 #define MAV_MODE4 0x0c0010
813
814 /* "INSN<cond> X,Y,Z" where X:12, Y:16, Z:0. */
815 #define MAV_MODE5 0x00100c
816
817 /* "INSN<cond> W,X,Y,Z" where W:5, X:12, Y:16, Z:0. */
818 #define MAV_MODE6 0x00100c05
819
820 struct asm_opcode
821 {
822 /* Basic string to match. */
823 const char * template;
824
825 /* Basic instruction code. */
826 unsigned long value;
827
828 /* Offset into the template where the condition code (if any) will be.
829 If zero, then the instruction is never conditional. */
830 unsigned cond_offset;
831
832 /* Which architecture variant provides this instruction. */
833 unsigned long variant;
834
835 /* Function to call to parse args. */
836 void (* parms) (char *);
837 };
838
839 /* Defines for various bits that we will want to toggle. */
840 #define INST_IMMEDIATE 0x02000000
841 #define OFFSET_REG 0x02000000
842 #define HWOFFSET_IMM 0x00400000
843 #define SHIFT_BY_REG 0x00000010
844 #define PRE_INDEX 0x01000000
845 #define INDEX_UP 0x00800000
846 #define WRITE_BACK 0x00200000
847 #define LDM_TYPE_2_OR_3 0x00400000
848
849 #define LITERAL_MASK 0xf000f000
850 #define OPCODE_MASK 0xfe1fffff
851 #define V4_STR_BIT 0x00000020
852
853 #define DATA_OP_SHIFT 21
854
855 /* Codes to distinguish the arithmetic instructions. */
856 #define OPCODE_AND 0
857 #define OPCODE_EOR 1
858 #define OPCODE_SUB 2
859 #define OPCODE_RSB 3
860 #define OPCODE_ADD 4
861 #define OPCODE_ADC 5
862 #define OPCODE_SBC 6
863 #define OPCODE_RSC 7
864 #define OPCODE_TST 8
865 #define OPCODE_TEQ 9
866 #define OPCODE_CMP 10
867 #define OPCODE_CMN 11
868 #define OPCODE_ORR 12
869 #define OPCODE_MOV 13
870 #define OPCODE_BIC 14
871 #define OPCODE_MVN 15
872
873 #define T_OPCODE_MUL 0x4340
874 #define T_OPCODE_TST 0x4200
875 #define T_OPCODE_CMN 0x42c0
876 #define T_OPCODE_NEG 0x4240
877 #define T_OPCODE_MVN 0x43c0
878
879 #define T_OPCODE_ADD_R3 0x1800
880 #define T_OPCODE_SUB_R3 0x1a00
881 #define T_OPCODE_ADD_HI 0x4400
882 #define T_OPCODE_ADD_ST 0xb000
883 #define T_OPCODE_SUB_ST 0xb080
884 #define T_OPCODE_ADD_SP 0xa800
885 #define T_OPCODE_ADD_PC 0xa000
886 #define T_OPCODE_ADD_I8 0x3000
887 #define T_OPCODE_SUB_I8 0x3800
888 #define T_OPCODE_ADD_I3 0x1c00
889 #define T_OPCODE_SUB_I3 0x1e00
890
891 #define T_OPCODE_ASR_R 0x4100
892 #define T_OPCODE_LSL_R 0x4080
893 #define T_OPCODE_LSR_R 0x40c0
894 #define T_OPCODE_ASR_I 0x1000
895 #define T_OPCODE_LSL_I 0x0000
896 #define T_OPCODE_LSR_I 0x0800
897
898 #define T_OPCODE_MOV_I8 0x2000
899 #define T_OPCODE_CMP_I8 0x2800
900 #define T_OPCODE_CMP_LR 0x4280
901 #define T_OPCODE_MOV_HR 0x4600
902 #define T_OPCODE_CMP_HR 0x4500
903
904 #define T_OPCODE_LDR_PC 0x4800
905 #define T_OPCODE_LDR_SP 0x9800
906 #define T_OPCODE_STR_SP 0x9000
907 #define T_OPCODE_LDR_IW 0x6800
908 #define T_OPCODE_STR_IW 0x6000
909 #define T_OPCODE_LDR_IH 0x8800
910 #define T_OPCODE_STR_IH 0x8000
911 #define T_OPCODE_LDR_IB 0x7800
912 #define T_OPCODE_STR_IB 0x7000
913 #define T_OPCODE_LDR_RW 0x5800
914 #define T_OPCODE_STR_RW 0x5000
915 #define T_OPCODE_LDR_RH 0x5a00
916 #define T_OPCODE_STR_RH 0x5200
917 #define T_OPCODE_LDR_RB 0x5c00
918 #define T_OPCODE_STR_RB 0x5400
919
920 #define T_OPCODE_PUSH 0xb400
921 #define T_OPCODE_POP 0xbc00
922
923 #define T_OPCODE_BRANCH 0xe7fe
924
925 #define THUMB_SIZE 2 /* Size of thumb instruction. */
926 #define THUMB_REG_LO 0x1
927 #define THUMB_REG_HI 0x2
928 #define THUMB_REG_ANY 0x3
929
930 #define THUMB_H1 0x0080
931 #define THUMB_H2 0x0040
932
933 #define THUMB_ASR 0
934 #define THUMB_LSL 1
935 #define THUMB_LSR 2
936
937 #define THUMB_MOVE 0
938 #define THUMB_COMPARE 1
939 #define THUMB_CPY 2
940
941 #define THUMB_LOAD 0
942 #define THUMB_STORE 1
943
944 #define THUMB_PP_PC_LR 0x0100
945
946 /* These three are used for immediate shifts, do not alter. */
947 #define THUMB_WORD 2
948 #define THUMB_HALFWORD 1
949 #define THUMB_BYTE 0
950
951 struct thumb_opcode
952 {
953 /* Basic string to match. */
954 const char * template;
955
956 /* Basic instruction code. */
957 unsigned long value;
958
959 int size;
960
961 /* Which CPU variants this exists for. */
962 unsigned long variant;
963
964 /* Function to call to parse args. */
965 void (* parms) (char *);
966 };
967
968 #define BAD_ARGS _("bad arguments to instruction")
969 #define BAD_PC _("r15 not allowed here")
970 #define BAD_COND _("instruction is not conditional")
971 #define ERR_NO_ACCUM _("acc0 expected")
972
973 static struct hash_control * arm_ops_hsh = NULL;
974 static struct hash_control * arm_tops_hsh = NULL;
975 static struct hash_control * arm_cond_hsh = NULL;
976 static struct hash_control * arm_shift_hsh = NULL;
977 static struct hash_control * arm_psr_hsh = NULL;
978
979 /* Stuff needed to resolve the label ambiguity
980 As:
981 ...
982 label: <insn>
983 may differ from:
984 ...
985 label:
986 <insn>
987 */
988
989 symbolS * last_label_seen;
990 static int label_is_thumb_function_name = FALSE;
991 \f
992 /* Literal Pool stuff. */
993
994 #define MAX_LITERAL_POOL_SIZE 1024
995
996 /* Literal pool structure. Held on a per-section
997 and per-sub-section basis. */
998
999 typedef struct literal_pool
1000 {
1001 expressionS literals [MAX_LITERAL_POOL_SIZE];
1002 unsigned int next_free_entry;
1003 unsigned int id;
1004 symbolS * symbol;
1005 segT section;
1006 subsegT sub_section;
1007 struct literal_pool * next;
1008 } literal_pool;
1009
1010 /* Pointer to a linked list of literal pools. */
1011 literal_pool * list_of_pools = NULL;
1012
1013 static literal_pool *
1014 find_literal_pool (void)
1015 {
1016 literal_pool * pool;
1017
1018 for (pool = list_of_pools; pool != NULL; pool = pool->next)
1019 {
1020 if (pool->section == now_seg
1021 && pool->sub_section == now_subseg)
1022 break;
1023 }
1024
1025 return pool;
1026 }
1027
1028 static literal_pool *
1029 find_or_make_literal_pool (void)
1030 {
1031 /* Next literal pool ID number. */
1032 static unsigned int latest_pool_num = 1;
1033 literal_pool * pool;
1034
1035 pool = find_literal_pool ();
1036
1037 if (pool == NULL)
1038 {
1039 /* Create a new pool. */
1040 pool = xmalloc (sizeof (* pool));
1041 if (! pool)
1042 return NULL;
1043
1044 pool->next_free_entry = 0;
1045 pool->section = now_seg;
1046 pool->sub_section = now_subseg;
1047 pool->next = list_of_pools;
1048 pool->symbol = NULL;
1049
1050 /* Add it to the list. */
1051 list_of_pools = pool;
1052 }
1053
1054 /* New pools, and emptied pools, will have a NULL symbol. */
1055 if (pool->symbol == NULL)
1056 {
1057 pool->symbol = symbol_create (FAKE_LABEL_NAME, undefined_section,
1058 (valueT) 0, &zero_address_frag);
1059 pool->id = latest_pool_num ++;
1060 }
1061
1062 /* Done. */
1063 return pool;
1064 }
1065
1066 /* Add the literal in the global 'inst'
1067 structure to the relevent literal pool. */
1068
1069 static int
1070 add_to_lit_pool (void)
1071 {
1072 literal_pool * pool;
1073 unsigned int entry;
1074
1075 pool = find_or_make_literal_pool ();
1076
1077 /* Check if this literal value is already in the pool. */
1078 for (entry = 0; entry < pool->next_free_entry; entry ++)
1079 {
1080 if ((pool->literals[entry].X_op == inst.reloc.exp.X_op)
1081 && (inst.reloc.exp.X_op == O_constant)
1082 && (pool->literals[entry].X_add_number
1083 == inst.reloc.exp.X_add_number)
1084 && (pool->literals[entry].X_unsigned
1085 == inst.reloc.exp.X_unsigned))
1086 break;
1087
1088 if ((pool->literals[entry].X_op == inst.reloc.exp.X_op)
1089 && (inst.reloc.exp.X_op == O_symbol)
1090 && (pool->literals[entry].X_add_number
1091 == inst.reloc.exp.X_add_number)
1092 && (pool->literals[entry].X_add_symbol
1093 == inst.reloc.exp.X_add_symbol)
1094 && (pool->literals[entry].X_op_symbol
1095 == inst.reloc.exp.X_op_symbol))
1096 break;
1097 }
1098
1099 /* Do we need to create a new entry? */
1100 if (entry == pool->next_free_entry)
1101 {
1102 if (entry >= MAX_LITERAL_POOL_SIZE)
1103 {
1104 inst.error = _("literal pool overflow");
1105 return FAIL;
1106 }
1107
1108 pool->literals[entry] = inst.reloc.exp;
1109 pool->next_free_entry += 1;
1110 }
1111
1112 inst.reloc.exp.X_op = O_symbol;
1113 inst.reloc.exp.X_add_number = ((int) entry) * 4 - 8;
1114 inst.reloc.exp.X_add_symbol = pool->symbol;
1115
1116 return SUCCESS;
1117 }
1118
1119 /* Can't use symbol_new here, so have to create a symbol and then at
1120 a later date assign it a value. Thats what these functions do. */
1121
1122 static void
1123 symbol_locate (symbolS * symbolP,
1124 const char * name, /* It is copied, the caller can modify. */
1125 segT segment, /* Segment identifier (SEG_<something>). */
1126 valueT valu, /* Symbol value. */
1127 fragS * frag) /* Associated fragment. */
1128 {
1129 unsigned int name_length;
1130 char * preserved_copy_of_name;
1131
1132 name_length = strlen (name) + 1; /* +1 for \0. */
1133 obstack_grow (&notes, name, name_length);
1134 preserved_copy_of_name = obstack_finish (&notes);
1135 #ifdef STRIP_UNDERSCORE
1136 if (preserved_copy_of_name[0] == '_')
1137 preserved_copy_of_name++;
1138 #endif
1139
1140 #ifdef tc_canonicalize_symbol_name
1141 preserved_copy_of_name =
1142 tc_canonicalize_symbol_name (preserved_copy_of_name);
1143 #endif
1144
1145 S_SET_NAME (symbolP, preserved_copy_of_name);
1146
1147 S_SET_SEGMENT (symbolP, segment);
1148 S_SET_VALUE (symbolP, valu);
1149 symbol_clear_list_pointers (symbolP);
1150
1151 symbol_set_frag (symbolP, frag);
1152
1153 /* Link to end of symbol chain. */
1154 {
1155 extern int symbol_table_frozen;
1156
1157 if (symbol_table_frozen)
1158 abort ();
1159 }
1160
1161 symbol_append (symbolP, symbol_lastP, & symbol_rootP, & symbol_lastP);
1162
1163 obj_symbol_new_hook (symbolP);
1164
1165 #ifdef tc_symbol_new_hook
1166 tc_symbol_new_hook (symbolP);
1167 #endif
1168
1169 #ifdef DEBUG_SYMS
1170 verify_symbol_chain (symbol_rootP, symbol_lastP);
1171 #endif /* DEBUG_SYMS */
1172 }
1173
1174 /* Check that an immediate is valid.
1175 If so, convert it to the right format. */
1176
1177 static unsigned int
1178 validate_immediate (unsigned int val)
1179 {
1180 unsigned int a;
1181 unsigned int i;
1182
1183 #define rotate_left(v, n) (v << n | v >> (32 - n))
1184
1185 for (i = 0; i < 32; i += 2)
1186 if ((a = rotate_left (val, i)) <= 0xff)
1187 return a | (i << 7); /* 12-bit pack: [shift-cnt,const]. */
1188
1189 return FAIL;
1190 }
1191
1192 /* Check to see if an immediate can be computed as two separate immediate
1193 values, added together. We already know that this value cannot be
1194 computed by just one ARM instruction. */
1195
1196 static unsigned int
1197 validate_immediate_twopart (unsigned int val,
1198 unsigned int * highpart)
1199 {
1200 unsigned int a;
1201 unsigned int i;
1202
1203 for (i = 0; i < 32; i += 2)
1204 if (((a = rotate_left (val, i)) & 0xff) != 0)
1205 {
1206 if (a & 0xff00)
1207 {
1208 if (a & ~ 0xffff)
1209 continue;
1210 * highpart = (a >> 8) | ((i + 24) << 7);
1211 }
1212 else if (a & 0xff0000)
1213 {
1214 if (a & 0xff000000)
1215 continue;
1216 * highpart = (a >> 16) | ((i + 16) << 7);
1217 }
1218 else
1219 {
1220 assert (a & 0xff000000);
1221 * highpart = (a >> 24) | ((i + 8) << 7);
1222 }
1223
1224 return (a & 0xff) | (i << 7);
1225 }
1226
1227 return FAIL;
1228 }
1229
1230 static int
1231 validate_offset_imm (unsigned int val, int hwse)
1232 {
1233 if ((hwse && val > 255) || val > 4095)
1234 return FAIL;
1235 return val;
1236 }
1237
1238 \f
1239 #ifdef OBJ_ELF
1240 /* This code is to handle mapping symbols as defined in the ARM ELF spec.
1241 (This text is taken from version B-02 of the spec):
1242
1243 4.4.7 Mapping and tagging symbols
1244
1245 A section of an ARM ELF file can contain a mixture of ARM code,
1246 Thumb code, and data. There are inline transitions between code
1247 and data at literal pool boundaries. There can also be inline
1248 transitions between ARM code and Thumb code, for example in
1249 ARM-Thumb inter-working veneers. Linkers, machine-level
1250 debuggers, profiling tools, and disassembly tools need to map
1251 images accurately. For example, setting an ARM breakpoint on a
1252 Thumb location, or in a literal pool, can crash the program
1253 being debugged, ruining the debugging session.
1254
1255 ARM ELF entities are mapped (see section 4.4.7.1 below) and
1256 tagged (see section 4.4.7.2 below) using local symbols (with
1257 binding STB_LOCAL). To assist consumers, mapping and tagging
1258 symbols should be collated first in the symbol table, before
1259 other symbols with binding STB_LOCAL.
1260
1261 To allow properly collated mapping and tagging symbols to be
1262 skipped by consumers that have no interest in them, the first
1263 such symbol should have the name $m and its st_value field equal
1264 to the total number of mapping and tagging symbols (including
1265 the $m) in the symbol table.
1266
1267 4.4.7.1 Mapping symbols
1268
1269 $a Labels the first byte of a sequence of ARM instructions.
1270 Its type is STT_FUNC.
1271
1272 $d Labels the first byte of a sequence of data items.
1273 Its type is STT_OBJECT.
1274
1275 $t Labels the first byte of a sequence of Thumb instructions.
1276 Its type is STT_FUNC.
1277
1278 This list of mapping symbols may be extended in the future.
1279
1280 Section-relative mapping symbols
1281
1282 Mapping symbols defined in a section define a sequence of
1283 half-open address intervals that cover the address range of the
1284 section. Each interval starts at the address defined by a
1285 mapping symbol, and continues up to, but not including, the
1286 address defined by the next (in address order) mapping symbol or
1287 the end of the section. A corollary is that there must be a
1288 mapping symbol defined at the beginning of each section.
1289 Consumers can ignore the size of a section-relative mapping
1290 symbol. Producers can set it to 0.
1291
1292 Absolute mapping symbols
1293
1294 Because of the need to crystallize a Thumb address with the
1295 Thumb-bit set, absolute symbol of type STT_FUNC (symbols of type
1296 STT_FUNC defined in section SHN_ABS) need to be mapped with $a
1297 or $t.
1298
1299 The extent of a mapping symbol defined in SHN_ABS is [st_value,
1300 st_value + st_size), or [st_value, st_value + 1) if st_size = 0,
1301 where [x, y) denotes the half-open address range from x,
1302 inclusive, to y, exclusive.
1303
1304 In the absence of a mapping symbol, a consumer can interpret a
1305 function symbol with an odd value as the Thumb code address
1306 obtained by clearing the least significant bit of the
1307 value. This interpretation is deprecated, and it may not work in
1308 the future.
1309
1310 Note - the Tagging symbols ($b, $f, $p $m) have been dropped from
1311 the EABI (which is still under development), so they are not
1312 implemented here. */
1313
1314 static enum mstate mapstate = MAP_UNDEFINED;
1315
1316 static void
1317 mapping_state (enum mstate state)
1318 {
1319 symbolS * symbolP;
1320 const char * symname;
1321 int type;
1322
1323 if (mapstate == state)
1324 /* The mapping symbol has already been emitted.
1325 There is nothing else to do. */
1326 return;
1327
1328 mapstate = state;
1329
1330 switch (state)
1331 {
1332 case MAP_DATA:
1333 symname = "$d";
1334 type = BSF_OBJECT;
1335 break;
1336 case MAP_ARM:
1337 symname = "$a";
1338 type = BSF_FUNCTION;
1339 break;
1340 case MAP_THUMB:
1341 symname = "$t";
1342 type = BSF_FUNCTION;
1343 break;
1344 case MAP_UNDEFINED:
1345 return;
1346 default:
1347 abort ();
1348 }
1349
1350 seg_info (now_seg)->tc_segment_info_data = state;
1351
1352 symbolP = symbol_new (symname, now_seg, (valueT) frag_now_fix (), frag_now);
1353 symbol_table_insert (symbolP);
1354 symbol_get_bfdsym (symbolP)->flags |= type | BSF_LOCAL;
1355
1356 switch (state)
1357 {
1358 case MAP_ARM:
1359 THUMB_SET_FUNC (symbolP, 0);
1360 ARM_SET_THUMB (symbolP, 0);
1361 ARM_SET_INTERWORK (symbolP, support_interwork);
1362 break;
1363
1364 case MAP_THUMB:
1365 THUMB_SET_FUNC (symbolP, 1);
1366 ARM_SET_THUMB (symbolP, 1);
1367 ARM_SET_INTERWORK (symbolP, support_interwork);
1368 break;
1369
1370 case MAP_DATA:
1371 default:
1372 return;
1373 }
1374 }
1375
1376 /* When we change sections we need to issue a new mapping symbol. */
1377
1378 void
1379 arm_elf_change_section (void)
1380 {
1381 flagword flags;
1382
1383 /* Link an unlinked unwind index table section to the .text section. */
1384 if (elf_section_type (now_seg) == SHT_ARM_EXIDX
1385 && elf_linked_to_section (now_seg) == NULL)
1386 elf_linked_to_section (now_seg) = text_section;
1387
1388 if (!SEG_NORMAL (now_seg))
1389 return;
1390
1391 flags = bfd_get_section_flags (stdoutput, now_seg);
1392
1393 /* We can ignore sections that only contain debug info. */
1394 if ((flags & SEC_ALLOC) == 0)
1395 return;
1396
1397 mapstate = seg_info (now_seg)->tc_segment_info_data;
1398 }
1399
1400 int
1401 arm_elf_section_type (const char * str, size_t len)
1402 {
1403 if (len == 5 && strncmp (str, "exidx", 5) == 0)
1404 return SHT_ARM_EXIDX;
1405
1406 return -1;
1407 }
1408 #else
1409 #define mapping_state(a)
1410 #endif /* OBJ_ELF */
1411 \f
1412 /* arm_reg_parse () := if it looks like a register, return its token and
1413 advance the pointer. */
1414
1415 static int
1416 arm_reg_parse (char ** ccp, struct hash_control * htab)
1417 {
1418 char * start = * ccp;
1419 char c;
1420 char * p;
1421 struct reg_entry * reg;
1422
1423 #ifdef REGISTER_PREFIX
1424 if (*start != REGISTER_PREFIX)
1425 return FAIL;
1426 p = start + 1;
1427 #else
1428 p = start;
1429 #ifdef OPTIONAL_REGISTER_PREFIX
1430 if (*p == OPTIONAL_REGISTER_PREFIX)
1431 p++, start++;
1432 #endif
1433 #endif
1434 if (!ISALPHA (*p) || !is_name_beginner (*p))
1435 return FAIL;
1436
1437 c = *p++;
1438 while (ISALPHA (c) || ISDIGIT (c) || c == '_')
1439 c = *p++;
1440
1441 *--p = 0;
1442 reg = (struct reg_entry *) hash_find (htab, start);
1443 *p = c;
1444
1445 if (reg)
1446 {
1447 *ccp = p;
1448 return reg->number;
1449 }
1450
1451 return FAIL;
1452 }
1453
1454 /* Search for the following register name in each of the possible reg name
1455 tables. Return the classification if found, or REG_TYPE_MAX if not
1456 present. */
1457
1458 static enum arm_reg_type
1459 arm_reg_parse_any (char *cp)
1460 {
1461 int i;
1462
1463 for (i = (int) REG_TYPE_FIRST; i < (int) REG_TYPE_MAX; i++)
1464 if (arm_reg_parse (&cp, all_reg_maps[i].htab) != FAIL)
1465 return (enum arm_reg_type) i;
1466
1467 return REG_TYPE_MAX;
1468 }
1469
1470 static void
1471 opcode_select (int width)
1472 {
1473 switch (width)
1474 {
1475 case 16:
1476 if (! thumb_mode)
1477 {
1478 if (! (cpu_variant & ARM_EXT_V4T))
1479 as_bad (_("selected processor does not support THUMB opcodes"));
1480
1481 thumb_mode = 1;
1482 /* No need to force the alignment, since we will have been
1483 coming from ARM mode, which is word-aligned. */
1484 record_alignment (now_seg, 1);
1485 }
1486 mapping_state (MAP_THUMB);
1487 break;
1488
1489 case 32:
1490 if (thumb_mode)
1491 {
1492 if ((cpu_variant & ARM_ALL) == ARM_EXT_V4T)
1493 as_bad (_("selected processor does not support ARM opcodes"));
1494
1495 thumb_mode = 0;
1496
1497 if (!need_pass_2)
1498 frag_align (2, 0, 0);
1499
1500 record_alignment (now_seg, 1);
1501 }
1502 mapping_state (MAP_ARM);
1503 break;
1504
1505 default:
1506 as_bad (_("invalid instruction size selected (%d)"), width);
1507 }
1508 }
1509
1510 static void
1511 s_req (int a ATTRIBUTE_UNUSED)
1512 {
1513 as_bad (_("invalid syntax for .req directive"));
1514 }
1515
1516 /* The .unreq directive deletes an alias which was previously defined
1517 by .req. For example:
1518
1519 my_alias .req r11
1520 .unreq my_alias */
1521
1522 static void
1523 s_unreq (int a ATTRIBUTE_UNUSED)
1524 {
1525 char * name;
1526 char saved_char;
1527
1528 skip_whitespace (input_line_pointer);
1529 name = input_line_pointer;
1530
1531 while (*input_line_pointer != 0
1532 && *input_line_pointer != ' '
1533 && *input_line_pointer != '\n')
1534 ++input_line_pointer;
1535
1536 saved_char = *input_line_pointer;
1537 *input_line_pointer = 0;
1538
1539 if (*name)
1540 {
1541 enum arm_reg_type req_type = arm_reg_parse_any (name);
1542
1543 if (req_type != REG_TYPE_MAX)
1544 {
1545 char *temp_name = name;
1546 int req_no = arm_reg_parse (&temp_name, all_reg_maps[req_type].htab);
1547
1548 if (req_no != FAIL)
1549 {
1550 struct reg_entry *req_entry;
1551
1552 /* Check to see if this alias is a builtin one. */
1553 req_entry = hash_delete (all_reg_maps[req_type].htab, name);
1554
1555 if (!req_entry)
1556 as_bad (_("unreq: missing hash entry for \"%s\""), name);
1557 else if (req_entry->builtin)
1558 /* FIXME: We are deleting a built in register alias which
1559 points to a const data structure, so we only need to
1560 free up the memory used by the key in the hash table.
1561 Unfortunately we have not recorded this value, so this
1562 is a memory leak. */
1563 /* FIXME: Should we issue a warning message ? */
1564 ;
1565 else
1566 {
1567 /* Deleting a user defined alias. We need to free the
1568 key and the value, but fortunately the key is the same
1569 as the value->name field. */
1570 free ((char *) req_entry->name);
1571 free (req_entry);
1572 }
1573 }
1574 else
1575 as_bad (_(".unreq: unrecognized symbol \"%s\""), name);
1576 }
1577 else
1578 as_bad (_(".unreq: unrecognized symbol \"%s\""), name);
1579 }
1580 else
1581 as_bad (_("invalid syntax for .unreq directive"));
1582
1583 *input_line_pointer = saved_char;
1584 demand_empty_rest_of_line ();
1585 }
1586
1587 static void
1588 s_bss (int ignore ATTRIBUTE_UNUSED)
1589 {
1590 /* We don't support putting frags in the BSS segment, we fake it by
1591 marking in_bss, then looking at s_skip for clues. */
1592 subseg_set (bss_section, 0);
1593 demand_empty_rest_of_line ();
1594 mapping_state (MAP_DATA);
1595 }
1596
1597 static void
1598 s_even (int ignore ATTRIBUTE_UNUSED)
1599 {
1600 /* Never make frag if expect extra pass. */
1601 if (!need_pass_2)
1602 frag_align (1, 0, 0);
1603
1604 record_alignment (now_seg, 1);
1605
1606 demand_empty_rest_of_line ();
1607 }
1608
1609 static void
1610 s_ltorg (int ignored ATTRIBUTE_UNUSED)
1611 {
1612 unsigned int entry;
1613 literal_pool * pool;
1614 char sym_name[20];
1615
1616 pool = find_literal_pool ();
1617 if (pool == NULL
1618 || pool->symbol == NULL
1619 || pool->next_free_entry == 0)
1620 return;
1621
1622 mapping_state (MAP_DATA);
1623
1624 /* Align pool as you have word accesses.
1625 Only make a frag if we have to. */
1626 if (!need_pass_2)
1627 frag_align (2, 0, 0);
1628
1629 record_alignment (now_seg, 2);
1630
1631 sprintf (sym_name, "$$lit_\002%x", pool->id);
1632
1633 symbol_locate (pool->symbol, sym_name, now_seg,
1634 (valueT) frag_now_fix (), frag_now);
1635 symbol_table_insert (pool->symbol);
1636
1637 ARM_SET_THUMB (pool->symbol, thumb_mode);
1638
1639 #if defined OBJ_COFF || defined OBJ_ELF
1640 ARM_SET_INTERWORK (pool->symbol, support_interwork);
1641 #endif
1642
1643 for (entry = 0; entry < pool->next_free_entry; entry ++)
1644 /* First output the expression in the instruction to the pool. */
1645 emit_expr (&(pool->literals[entry]), 4); /* .word */
1646
1647 /* Mark the pool as empty. */
1648 pool->next_free_entry = 0;
1649 pool->symbol = NULL;
1650 }
1651
1652 /* Same as s_align_ptwo but align 0 => align 2. */
1653
1654 static void
1655 s_align (int unused ATTRIBUTE_UNUSED)
1656 {
1657 int temp;
1658 long temp_fill;
1659 long max_alignment = 15;
1660
1661 temp = get_absolute_expression ();
1662 if (temp > max_alignment)
1663 as_bad (_("alignment too large: %d assumed"), temp = max_alignment);
1664 else if (temp < 0)
1665 {
1666 as_bad (_("alignment negative. 0 assumed."));
1667 temp = 0;
1668 }
1669
1670 if (*input_line_pointer == ',')
1671 {
1672 input_line_pointer++;
1673 temp_fill = get_absolute_expression ();
1674 }
1675 else
1676 temp_fill = 0;
1677
1678 if (!temp)
1679 temp = 2;
1680
1681 /* Only make a frag if we HAVE to. */
1682 if (temp && !need_pass_2)
1683 frag_align (temp, (int) temp_fill, 0);
1684 demand_empty_rest_of_line ();
1685
1686 record_alignment (now_seg, temp);
1687 }
1688
1689 static void
1690 s_force_thumb (int ignore ATTRIBUTE_UNUSED)
1691 {
1692 /* If we are not already in thumb mode go into it, EVEN if
1693 the target processor does not support thumb instructions.
1694 This is used by gcc/config/arm/lib1funcs.asm for example
1695 to compile interworking support functions even if the
1696 target processor should not support interworking. */
1697 if (! thumb_mode)
1698 {
1699 thumb_mode = 2;
1700
1701 record_alignment (now_seg, 1);
1702 }
1703
1704 demand_empty_rest_of_line ();
1705 }
1706
1707 static void
1708 s_thumb_func (int ignore ATTRIBUTE_UNUSED)
1709 {
1710 if (! thumb_mode)
1711 opcode_select (16);
1712
1713 /* The following label is the name/address of the start of a Thumb function.
1714 We need to know this for the interworking support. */
1715 label_is_thumb_function_name = TRUE;
1716
1717 demand_empty_rest_of_line ();
1718 }
1719
1720 /* Perform a .set directive, but also mark the alias as
1721 being a thumb function. */
1722
1723 static void
1724 s_thumb_set (int equiv)
1725 {
1726 /* XXX the following is a duplicate of the code for s_set() in read.c
1727 We cannot just call that code as we need to get at the symbol that
1728 is created. */
1729 char * name;
1730 char delim;
1731 char * end_name;
1732 symbolS * symbolP;
1733
1734 /* Especial apologies for the random logic:
1735 This just grew, and could be parsed much more simply!
1736 Dean - in haste. */
1737 name = input_line_pointer;
1738 delim = get_symbol_end ();
1739 end_name = input_line_pointer;
1740 *end_name = delim;
1741
1742 SKIP_WHITESPACE ();
1743
1744 if (*input_line_pointer != ',')
1745 {
1746 *end_name = 0;
1747 as_bad (_("expected comma after name \"%s\""), name);
1748 *end_name = delim;
1749 ignore_rest_of_line ();
1750 return;
1751 }
1752
1753 input_line_pointer++;
1754 *end_name = 0;
1755
1756 if (name[0] == '.' && name[1] == '\0')
1757 {
1758 /* XXX - this should not happen to .thumb_set. */
1759 abort ();
1760 }
1761
1762 if ((symbolP = symbol_find (name)) == NULL
1763 && (symbolP = md_undefined_symbol (name)) == NULL)
1764 {
1765 #ifndef NO_LISTING
1766 /* When doing symbol listings, play games with dummy fragments living
1767 outside the normal fragment chain to record the file and line info
1768 for this symbol. */
1769 if (listing & LISTING_SYMBOLS)
1770 {
1771 extern struct list_info_struct * listing_tail;
1772 fragS * dummy_frag = xmalloc (sizeof (fragS));
1773
1774 memset (dummy_frag, 0, sizeof (fragS));
1775 dummy_frag->fr_type = rs_fill;
1776 dummy_frag->line = listing_tail;
1777 symbolP = symbol_new (name, undefined_section, 0, dummy_frag);
1778 dummy_frag->fr_symbol = symbolP;
1779 }
1780 else
1781 #endif
1782 symbolP = symbol_new (name, undefined_section, 0, &zero_address_frag);
1783
1784 #ifdef OBJ_COFF
1785 /* "set" symbols are local unless otherwise specified. */
1786 SF_SET_LOCAL (symbolP);
1787 #endif /* OBJ_COFF */
1788 } /* Make a new symbol. */
1789
1790 symbol_table_insert (symbolP);
1791
1792 * end_name = delim;
1793
1794 if (equiv
1795 && S_IS_DEFINED (symbolP)
1796 && S_GET_SEGMENT (symbolP) != reg_section)
1797 as_bad (_("symbol `%s' already defined"), S_GET_NAME (symbolP));
1798
1799 pseudo_set (symbolP);
1800
1801 demand_empty_rest_of_line ();
1802
1803 /* XXX Now we come to the Thumb specific bit of code. */
1804
1805 THUMB_SET_FUNC (symbolP, 1);
1806 ARM_SET_THUMB (symbolP, 1);
1807 #if defined OBJ_ELF || defined OBJ_COFF
1808 ARM_SET_INTERWORK (symbolP, support_interwork);
1809 #endif
1810 }
1811
1812 static void
1813 s_arm (int ignore ATTRIBUTE_UNUSED)
1814 {
1815 opcode_select (32);
1816 demand_empty_rest_of_line ();
1817 }
1818
1819 static void
1820 s_thumb (int ignore ATTRIBUTE_UNUSED)
1821 {
1822 opcode_select (16);
1823 demand_empty_rest_of_line ();
1824 }
1825
1826 static void
1827 s_code (int unused ATTRIBUTE_UNUSED)
1828 {
1829 int temp;
1830
1831 temp = get_absolute_expression ();
1832 switch (temp)
1833 {
1834 case 16:
1835 case 32:
1836 opcode_select (temp);
1837 break;
1838
1839 default:
1840 as_bad (_("invalid operand to .code directive (%d) (expecting 16 or 32)"), temp);
1841 }
1842 }
1843
1844 static void
1845 end_of_line (char * str)
1846 {
1847 skip_whitespace (str);
1848
1849 if (*str != '\0' && !inst.error)
1850 inst.error = _("garbage following instruction");
1851 }
1852
1853 static int
1854 skip_past_comma (char ** str)
1855 {
1856 char * p = * str, c;
1857 int comma = 0;
1858
1859 while ((c = *p) == ' ' || c == ',')
1860 {
1861 p++;
1862 if (c == ',' && comma++)
1863 return FAIL;
1864 }
1865
1866 if (c == '\0')
1867 return FAIL;
1868
1869 *str = p;
1870 return comma ? SUCCESS : FAIL;
1871 }
1872
1873 /* Return TRUE if anything in the expression is a bignum. */
1874
1875 static int
1876 walk_no_bignums (symbolS * sp)
1877 {
1878 if (symbol_get_value_expression (sp)->X_op == O_big)
1879 return 1;
1880
1881 if (symbol_get_value_expression (sp)->X_add_symbol)
1882 {
1883 return (walk_no_bignums (symbol_get_value_expression (sp)->X_add_symbol)
1884 || (symbol_get_value_expression (sp)->X_op_symbol
1885 && walk_no_bignums (symbol_get_value_expression (sp)->X_op_symbol)));
1886 }
1887
1888 return 0;
1889 }
1890
1891 static int in_my_get_expression = 0;
1892
1893 static int
1894 my_get_expression (expressionS * ep, char ** str)
1895 {
1896 char * save_in;
1897 segT seg;
1898
1899 save_in = input_line_pointer;
1900 input_line_pointer = *str;
1901 in_my_get_expression = 1;
1902 seg = expression (ep);
1903 in_my_get_expression = 0;
1904
1905 if (ep->X_op == O_illegal)
1906 {
1907 /* We found a bad expression in md_operand(). */
1908 *str = input_line_pointer;
1909 input_line_pointer = save_in;
1910 return 1;
1911 }
1912
1913 #ifdef OBJ_AOUT
1914 if (seg != absolute_section
1915 && seg != text_section
1916 && seg != data_section
1917 && seg != bss_section
1918 && seg != undefined_section)
1919 {
1920 inst.error = _("bad_segment");
1921 *str = input_line_pointer;
1922 input_line_pointer = save_in;
1923 return 1;
1924 }
1925 #endif
1926
1927 /* Get rid of any bignums now, so that we don't generate an error for which
1928 we can't establish a line number later on. Big numbers are never valid
1929 in instructions, which is where this routine is always called. */
1930 if (ep->X_op == O_big
1931 || (ep->X_add_symbol
1932 && (walk_no_bignums (ep->X_add_symbol)
1933 || (ep->X_op_symbol
1934 && walk_no_bignums (ep->X_op_symbol)))))
1935 {
1936 inst.error = _("invalid constant");
1937 *str = input_line_pointer;
1938 input_line_pointer = save_in;
1939 return 1;
1940 }
1941
1942 *str = input_line_pointer;
1943 input_line_pointer = save_in;
1944 return 0;
1945 }
1946
1947 /* A standard register must be given at this point.
1948 SHIFT is the place to put it in inst.instruction.
1949 Restores input start point on error.
1950 Returns the reg#, or FAIL. */
1951
1952 static int
1953 reg_required_here (char ** str, int shift)
1954 {
1955 static char buff [128]; /* XXX */
1956 int reg;
1957 char * start = * str;
1958
1959 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_RN].htab)) != FAIL)
1960 {
1961 if (shift >= 0)
1962 inst.instruction |= reg << shift;
1963 return reg;
1964 }
1965
1966 /* Restore the start point, we may have got a reg of the wrong class. */
1967 *str = start;
1968
1969 /* In the few cases where we might be able to accept something else
1970 this error can be overridden. */
1971 sprintf (buff, _("register expected, not '%.100s'"), start);
1972 inst.error = buff;
1973
1974 return FAIL;
1975 }
1976
1977 /* A Intel Wireless MMX technology register
1978 must be given at this point.
1979 Shift is the place to put it in inst.instruction.
1980 Restores input start point on err.
1981 Returns the reg#, or FAIL. */
1982
1983 static int
1984 wreg_required_here (char ** str,
1985 int shift,
1986 enum wreg_type reg_type)
1987 {
1988 static char buff [128];
1989 int reg;
1990 char * start = *str;
1991
1992 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_IWMMXT].htab)) != FAIL)
1993 {
1994 if (wr_register (reg)
1995 && (reg_type == IWMMXT_REG_WR || reg_type == IWMMXT_REG_WR_OR_WC))
1996 {
1997 if (shift >= 0)
1998 inst.instruction |= (reg ^ WR_PREFIX) << shift;
1999 return reg;
2000 }
2001 else if (wc_register (reg)
2002 && (reg_type == IWMMXT_REG_WC || reg_type == IWMMXT_REG_WR_OR_WC))
2003 {
2004 if (shift >= 0)
2005 inst.instruction |= (reg ^ WC_PREFIX) << shift;
2006 return reg;
2007 }
2008 else if ((wcg_register (reg) && reg_type == IWMMXT_REG_WCG))
2009 {
2010 if (shift >= 0)
2011 inst.instruction |= ((reg ^ WC_PREFIX) - 8) << shift;
2012 return reg;
2013 }
2014 }
2015
2016 /* Restore the start point, we may have got a reg of the wrong class. */
2017 *str = start;
2018
2019 /* In the few cases where we might be able to accept
2020 something else this error can be overridden. */
2021 sprintf (buff, _("Intel Wireless MMX technology register expected, not '%.100s'"), start);
2022 inst.error = buff;
2023
2024 return FAIL;
2025 }
2026
2027 static const struct asm_psr *
2028 arm_psr_parse (char ** ccp)
2029 {
2030 char * start = * ccp;
2031 char c;
2032 char * p;
2033 const struct asm_psr * psr;
2034
2035 p = start;
2036
2037 /* Skip to the end of the next word in the input stream. */
2038 do
2039 {
2040 c = *p++;
2041 }
2042 while (ISALPHA (c) || c == '_');
2043
2044 /* Terminate the word. */
2045 *--p = 0;
2046
2047 /* CPSR's and SPSR's can now be lowercase. This is just a convenience
2048 feature for ease of use and backwards compatibility. */
2049 if (!strncmp (start, "cpsr", 4))
2050 strncpy (start, "CPSR", 4);
2051 else if (!strncmp (start, "spsr", 4))
2052 strncpy (start, "SPSR", 4);
2053
2054 /* Now locate the word in the psr hash table. */
2055 psr = (const struct asm_psr *) hash_find (arm_psr_hsh, start);
2056
2057 /* Restore the input stream. */
2058 *p = c;
2059
2060 /* If we found a valid match, advance the
2061 stream pointer past the end of the word. */
2062 *ccp = p;
2063
2064 return psr;
2065 }
2066
2067 /* Parse the input looking for a PSR flag. */
2068
2069 static int
2070 psr_required_here (char ** str)
2071 {
2072 char * start = * str;
2073 const struct asm_psr * psr;
2074
2075 psr = arm_psr_parse (str);
2076
2077 if (psr)
2078 {
2079 /* If this is the SPSR that is being modified, set the R bit. */
2080 if (! psr->cpsr)
2081 inst.instruction |= SPSR_BIT;
2082
2083 /* Set the psr flags in the MSR instruction. */
2084 inst.instruction |= psr->field << PSR_SHIFT;
2085
2086 return SUCCESS;
2087 }
2088
2089 /* In the few cases where we might be able to accept
2090 something else this error can be overridden. */
2091 inst.error = _("flag for {c}psr instruction expected");
2092
2093 /* Restore the start point. */
2094 *str = start;
2095 return FAIL;
2096 }
2097
2098 static int
2099 co_proc_number (char ** str)
2100 {
2101 int processor, pchar;
2102 char *start;
2103
2104 skip_whitespace (*str);
2105 start = *str;
2106
2107 /* The data sheet seems to imply that just a number on its own is valid
2108 here, but the RISC iX assembler seems to accept a prefix 'p'. We will
2109 accept either. */
2110 if ((processor = arm_reg_parse (str, all_reg_maps[REG_TYPE_CP].htab))
2111 == FAIL)
2112 {
2113 *str = start;
2114
2115 pchar = *(*str)++;
2116 if (pchar >= '0' && pchar <= '9')
2117 {
2118 processor = pchar - '0';
2119 if (**str >= '0' && **str <= '9')
2120 {
2121 processor = processor * 10 + *(*str)++ - '0';
2122 if (processor > 15)
2123 {
2124 inst.error = _("illegal co-processor number");
2125 return FAIL;
2126 }
2127 }
2128 }
2129 else
2130 {
2131 inst.error = all_reg_maps[REG_TYPE_CP].expected;
2132 return FAIL;
2133 }
2134 }
2135
2136 inst.instruction |= processor << 8;
2137 return SUCCESS;
2138 }
2139
2140 static int
2141 cp_opc_expr (char ** str, int where, int length)
2142 {
2143 expressionS expr;
2144
2145 skip_whitespace (* str);
2146
2147 memset (&expr, '\0', sizeof (expr));
2148
2149 if (my_get_expression (&expr, str))
2150 return FAIL;
2151 if (expr.X_op != O_constant)
2152 {
2153 inst.error = _("bad or missing expression");
2154 return FAIL;
2155 }
2156
2157 if ((expr.X_add_number & ((1 << length) - 1)) != expr.X_add_number)
2158 {
2159 inst.error = _("immediate co-processor expression too large");
2160 return FAIL;
2161 }
2162
2163 inst.instruction |= expr.X_add_number << where;
2164 return SUCCESS;
2165 }
2166
2167 static int
2168 cp_reg_required_here (char ** str, int where)
2169 {
2170 int reg;
2171 char * start = *str;
2172
2173 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_CN].htab)) != FAIL)
2174 {
2175 inst.instruction |= reg << where;
2176 return reg;
2177 }
2178
2179 /* In the few cases where we might be able to accept something else
2180 this error can be overridden. */
2181 inst.error = all_reg_maps[REG_TYPE_CN].expected;
2182
2183 /* Restore the start point. */
2184 *str = start;
2185 return FAIL;
2186 }
2187
2188 static int
2189 fp_reg_required_here (char ** str, int where)
2190 {
2191 int reg;
2192 char * start = * str;
2193
2194 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_FN].htab)) != FAIL)
2195 {
2196 inst.instruction |= reg << where;
2197 return reg;
2198 }
2199
2200 /* In the few cases where we might be able to accept something else
2201 this error can be overridden. */
2202 inst.error = all_reg_maps[REG_TYPE_FN].expected;
2203
2204 /* Restore the start point. */
2205 *str = start;
2206 return FAIL;
2207 }
2208
2209 static int
2210 cp_address_offset (char ** str)
2211 {
2212 int offset;
2213
2214 skip_whitespace (* str);
2215
2216 if (! is_immediate_prefix (**str))
2217 {
2218 inst.error = _("immediate expression expected");
2219 return FAIL;
2220 }
2221
2222 (*str)++;
2223
2224 if (my_get_expression (& inst.reloc.exp, str))
2225 return FAIL;
2226
2227 if (inst.reloc.exp.X_op == O_constant)
2228 {
2229 offset = inst.reloc.exp.X_add_number;
2230
2231 if (offset & 3)
2232 {
2233 inst.error = _("co-processor address must be word aligned");
2234 return FAIL;
2235 }
2236
2237 if (offset > 1023 || offset < -1023)
2238 {
2239 inst.error = _("offset too large");
2240 return FAIL;
2241 }
2242
2243 if (offset >= 0)
2244 inst.instruction |= INDEX_UP;
2245 else
2246 offset = -offset;
2247
2248 inst.instruction |= offset >> 2;
2249 }
2250 else
2251 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
2252
2253 return SUCCESS;
2254 }
2255
2256 static int
2257 cp_address_required_here (char ** str, int wb_ok)
2258 {
2259 char * p = * str;
2260 int pre_inc = 0;
2261 int write_back = 0;
2262
2263 if (*p == '[')
2264 {
2265 int reg;
2266
2267 p++;
2268 skip_whitespace (p);
2269
2270 if ((reg = reg_required_here (& p, 16)) == FAIL)
2271 return FAIL;
2272
2273 skip_whitespace (p);
2274
2275 if (*p == ']')
2276 {
2277 p++;
2278
2279 skip_whitespace (p);
2280
2281 if (*p == '\0')
2282 {
2283 /* As an extension to the official ARM syntax we allow:
2284 [Rn]
2285 as a short hand for:
2286 [Rn,#0] */
2287 inst.instruction |= PRE_INDEX | INDEX_UP;
2288 *str = p;
2289 return SUCCESS;
2290 }
2291
2292 if (skip_past_comma (& p) == FAIL)
2293 {
2294 inst.error = _("comma expected after closing square bracket");
2295 return FAIL;
2296 }
2297
2298 skip_whitespace (p);
2299
2300 if (*p == '#')
2301 {
2302 if (wb_ok)
2303 {
2304 /* [Rn], #expr */
2305 write_back = WRITE_BACK;
2306
2307 if (reg == REG_PC)
2308 {
2309 inst.error = _("pc may not be used in post-increment");
2310 return FAIL;
2311 }
2312
2313 if (cp_address_offset (& p) == FAIL)
2314 return FAIL;
2315 }
2316 else
2317 pre_inc = PRE_INDEX | INDEX_UP;
2318 }
2319 else if (*p == '{')
2320 {
2321 int option;
2322
2323 /* [Rn], {<expr>} */
2324 p++;
2325
2326 skip_whitespace (p);
2327
2328 if (my_get_expression (& inst.reloc.exp, & p))
2329 return FAIL;
2330
2331 if (inst.reloc.exp.X_op == O_constant)
2332 {
2333 option = inst.reloc.exp.X_add_number;
2334
2335 if (option > 255 || option < 0)
2336 {
2337 inst.error = _("'option' field too large");
2338 return FAIL;
2339 }
2340
2341 skip_whitespace (p);
2342
2343 if (*p != '}')
2344 {
2345 inst.error = _("'}' expected at end of 'option' field");
2346 return FAIL;
2347 }
2348 else
2349 {
2350 p++;
2351 inst.instruction |= option;
2352 inst.instruction |= INDEX_UP;
2353 }
2354 }
2355 else
2356 {
2357 inst.error = _("non-constant expressions for 'option' field not supported");
2358 return FAIL;
2359 }
2360 }
2361 else
2362 {
2363 inst.error = _("# or { expected after comma");
2364 return FAIL;
2365 }
2366 }
2367 else
2368 {
2369 /* '['Rn, #expr']'[!] */
2370
2371 if (skip_past_comma (& p) == FAIL)
2372 {
2373 inst.error = _("pre-indexed expression expected");
2374 return FAIL;
2375 }
2376
2377 pre_inc = PRE_INDEX;
2378
2379 if (cp_address_offset (& p) == FAIL)
2380 return FAIL;
2381
2382 skip_whitespace (p);
2383
2384 if (*p++ != ']')
2385 {
2386 inst.error = _("missing ]");
2387 return FAIL;
2388 }
2389
2390 skip_whitespace (p);
2391
2392 if (wb_ok && *p == '!')
2393 {
2394 if (reg == REG_PC)
2395 {
2396 inst.error = _("pc may not be used with write-back");
2397 return FAIL;
2398 }
2399
2400 p++;
2401 write_back = WRITE_BACK;
2402 }
2403 }
2404 }
2405 else
2406 {
2407 if (my_get_expression (&inst.reloc.exp, &p))
2408 return FAIL;
2409
2410 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
2411 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
2412 inst.reloc.pc_rel = 1;
2413 inst.instruction |= (REG_PC << 16);
2414 pre_inc = PRE_INDEX;
2415 }
2416
2417 inst.instruction |= write_back | pre_inc;
2418 *str = p;
2419 return SUCCESS;
2420 }
2421
2422 static int
2423 cp_byte_address_offset (char ** str)
2424 {
2425 int offset;
2426
2427 skip_whitespace (* str);
2428
2429 if (! is_immediate_prefix (**str))
2430 {
2431 inst.error = _("immediate expression expected");
2432 return FAIL;
2433 }
2434
2435 (*str)++;
2436
2437 if (my_get_expression (& inst.reloc.exp, str))
2438 return FAIL;
2439
2440 if (inst.reloc.exp.X_op == O_constant)
2441 {
2442 offset = inst.reloc.exp.X_add_number;
2443
2444 if (offset > 255 || offset < -255)
2445 {
2446 inst.error = _("offset too large");
2447 return FAIL;
2448 }
2449
2450 if (offset >= 0)
2451 inst.instruction |= INDEX_UP;
2452 else
2453 offset = -offset;
2454
2455 inst.instruction |= offset;
2456 }
2457 else
2458 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM_S2;
2459
2460 return SUCCESS;
2461 }
2462
2463 static int
2464 cp_byte_address_required_here (char ** str)
2465 {
2466 char * p = * str;
2467 int pre_inc = 0;
2468 int write_back = 0;
2469
2470 if (*p == '[')
2471 {
2472 int reg;
2473
2474 p++;
2475 skip_whitespace (p);
2476
2477 if ((reg = reg_required_here (& p, 16)) == FAIL)
2478 return FAIL;
2479
2480 skip_whitespace (p);
2481
2482 if (*p == ']')
2483 {
2484 p++;
2485
2486 if (skip_past_comma (& p) == SUCCESS)
2487 {
2488 /* [Rn], #expr */
2489 write_back = WRITE_BACK;
2490
2491 if (reg == REG_PC)
2492 {
2493 inst.error = _("pc may not be used in post-increment");
2494 return FAIL;
2495 }
2496
2497 if (cp_byte_address_offset (& p) == FAIL)
2498 return FAIL;
2499 }
2500 else
2501 pre_inc = PRE_INDEX | INDEX_UP;
2502 }
2503 else
2504 {
2505 /* '['Rn, #expr']'[!] */
2506
2507 if (skip_past_comma (& p) == FAIL)
2508 {
2509 inst.error = _("pre-indexed expression expected");
2510 return FAIL;
2511 }
2512
2513 pre_inc = PRE_INDEX;
2514
2515 if (cp_byte_address_offset (& p) == FAIL)
2516 return FAIL;
2517
2518 skip_whitespace (p);
2519
2520 if (*p++ != ']')
2521 {
2522 inst.error = _("missing ]");
2523 return FAIL;
2524 }
2525
2526 skip_whitespace (p);
2527
2528 if (*p == '!')
2529 {
2530 if (reg == REG_PC)
2531 {
2532 inst.error = _("pc may not be used with write-back");
2533 return FAIL;
2534 }
2535
2536 p++;
2537 write_back = WRITE_BACK;
2538 }
2539 }
2540 }
2541 else
2542 {
2543 if (my_get_expression (&inst.reloc.exp, &p))
2544 return FAIL;
2545
2546 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM_S2;
2547 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
2548 inst.reloc.pc_rel = 1;
2549 inst.instruction |= (REG_PC << 16);
2550 pre_inc = PRE_INDEX;
2551 }
2552
2553 inst.instruction |= write_back | pre_inc;
2554 *str = p;
2555 return SUCCESS;
2556 }
2557
2558 static void
2559 do_nop (char * str)
2560 {
2561 skip_whitespace (str);
2562 if (*str == '{')
2563 {
2564 str++;
2565
2566 if (my_get_expression (&inst.reloc.exp, &str))
2567 inst.reloc.exp.X_op = O_illegal;
2568 else
2569 {
2570 skip_whitespace (str);
2571 if (*str == '}')
2572 str++;
2573 else
2574 inst.reloc.exp.X_op = O_illegal;
2575 }
2576
2577 if (inst.reloc.exp.X_op != O_constant
2578 || inst.reloc.exp.X_add_number > 255
2579 || inst.reloc.exp.X_add_number < 0)
2580 {
2581 inst.error = _("Invalid NOP hint");
2582 return;
2583 }
2584
2585 /* Arcitectural NOP hints are CPSR sets with no bits selected. */
2586 inst.instruction &= 0xf0000000;
2587 inst.instruction |= 0x0320f000 + inst.reloc.exp.X_add_number;
2588 }
2589
2590 end_of_line (str);
2591 }
2592
2593 static void
2594 do_empty (char * str)
2595 {
2596 /* Do nothing really. */
2597 end_of_line (str);
2598 }
2599
2600 static void
2601 do_mrs (char * str)
2602 {
2603 int skip = 0;
2604
2605 /* Only one syntax. */
2606 skip_whitespace (str);
2607
2608 if (reg_required_here (&str, 12) == FAIL)
2609 {
2610 inst.error = BAD_ARGS;
2611 return;
2612 }
2613
2614 if (skip_past_comma (&str) == FAIL)
2615 {
2616 inst.error = _("comma expected after register name");
2617 return;
2618 }
2619
2620 skip_whitespace (str);
2621
2622 if ( streq (str, "CPSR")
2623 || streq (str, "SPSR")
2624 /* Lower case versions for backwards compatibility. */
2625 || streq (str, "cpsr")
2626 || streq (str, "spsr"))
2627 skip = 4;
2628
2629 /* This is for backwards compatibility with older toolchains. */
2630 else if ( streq (str, "cpsr_all")
2631 || streq (str, "spsr_all"))
2632 skip = 8;
2633 else
2634 {
2635 inst.error = _("CPSR or SPSR expected");
2636 return;
2637 }
2638
2639 if (* str == 's' || * str == 'S')
2640 inst.instruction |= SPSR_BIT;
2641 str += skip;
2642
2643 end_of_line (str);
2644 }
2645
2646 /* Two possible forms:
2647 "{C|S}PSR_<field>, Rm",
2648 "{C|S}PSR_f, #expression". */
2649
2650 static void
2651 do_msr (char * str)
2652 {
2653 skip_whitespace (str);
2654
2655 if (psr_required_here (& str) == FAIL)
2656 return;
2657
2658 if (skip_past_comma (& str) == FAIL)
2659 {
2660 inst.error = _("comma missing after psr flags");
2661 return;
2662 }
2663
2664 skip_whitespace (str);
2665
2666 if (reg_required_here (& str, 0) != FAIL)
2667 {
2668 inst.error = NULL;
2669 end_of_line (str);
2670 return;
2671 }
2672
2673 if (! is_immediate_prefix (* str))
2674 {
2675 inst.error =
2676 _("only a register or immediate value can follow a psr flag");
2677 return;
2678 }
2679
2680 str ++;
2681 inst.error = NULL;
2682
2683 if (my_get_expression (& inst.reloc.exp, & str))
2684 {
2685 inst.error =
2686 _("only a register or immediate value can follow a psr flag");
2687 return;
2688 }
2689
2690 inst.instruction |= INST_IMMEDIATE;
2691
2692 if (inst.reloc.exp.X_add_symbol)
2693 {
2694 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
2695 inst.reloc.pc_rel = 0;
2696 }
2697 else
2698 {
2699 unsigned value = validate_immediate (inst.reloc.exp.X_add_number);
2700
2701 if (value == (unsigned) FAIL)
2702 {
2703 inst.error = _("invalid constant");
2704 return;
2705 }
2706
2707 inst.instruction |= value;
2708 }
2709
2710 inst.error = NULL;
2711 end_of_line (str);
2712 }
2713
2714 /* Long Multiply Parser
2715 UMULL RdLo, RdHi, Rm, Rs
2716 SMULL RdLo, RdHi, Rm, Rs
2717 UMLAL RdLo, RdHi, Rm, Rs
2718 SMLAL RdLo, RdHi, Rm, Rs. */
2719
2720 static void
2721 do_mull (char * str)
2722 {
2723 int rdlo, rdhi, rm, rs;
2724
2725 /* Only one format "rdlo, rdhi, rm, rs". */
2726 skip_whitespace (str);
2727
2728 if ((rdlo = reg_required_here (&str, 12)) == FAIL)
2729 {
2730 inst.error = BAD_ARGS;
2731 return;
2732 }
2733
2734 if (skip_past_comma (&str) == FAIL
2735 || (rdhi = reg_required_here (&str, 16)) == FAIL)
2736 {
2737 inst.error = BAD_ARGS;
2738 return;
2739 }
2740
2741 if (skip_past_comma (&str) == FAIL
2742 || (rm = reg_required_here (&str, 0)) == FAIL)
2743 {
2744 inst.error = BAD_ARGS;
2745 return;
2746 }
2747
2748 /* rdhi, rdlo and rm must all be different. */
2749 if (rdlo == rdhi || rdlo == rm || rdhi == rm)
2750 as_tsktsk (_("rdhi, rdlo and rm must all be different"));
2751
2752 if (skip_past_comma (&str) == FAIL
2753 || (rs = reg_required_here (&str, 8)) == FAIL)
2754 {
2755 inst.error = BAD_ARGS;
2756 return;
2757 }
2758
2759 if (rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC)
2760 {
2761 inst.error = BAD_PC;
2762 return;
2763 }
2764
2765 end_of_line (str);
2766 }
2767
2768 static void
2769 do_mul (char * str)
2770 {
2771 int rd, rm;
2772
2773 /* Only one format "rd, rm, rs". */
2774 skip_whitespace (str);
2775
2776 if ((rd = reg_required_here (&str, 16)) == FAIL)
2777 {
2778 inst.error = BAD_ARGS;
2779 return;
2780 }
2781
2782 if (rd == REG_PC)
2783 {
2784 inst.error = BAD_PC;
2785 return;
2786 }
2787
2788 if (skip_past_comma (&str) == FAIL
2789 || (rm = reg_required_here (&str, 0)) == FAIL)
2790 {
2791 inst.error = BAD_ARGS;
2792 return;
2793 }
2794
2795 if (rm == REG_PC)
2796 {
2797 inst.error = BAD_PC;
2798 return;
2799 }
2800
2801 if (rm == rd)
2802 as_tsktsk (_("rd and rm should be different in mul"));
2803
2804 if (skip_past_comma (&str) == FAIL
2805 || (rm = reg_required_here (&str, 8)) == FAIL)
2806 {
2807 inst.error = BAD_ARGS;
2808 return;
2809 }
2810
2811 if (rm == REG_PC)
2812 {
2813 inst.error = BAD_PC;
2814 return;
2815 }
2816
2817 end_of_line (str);
2818 }
2819
2820 static void
2821 do_mlas (char * str, bfd_boolean is_mls)
2822 {
2823 int rd, rm;
2824
2825 /* Only one format "rd, rm, rs, rn". */
2826 skip_whitespace (str);
2827
2828 if ((rd = reg_required_here (&str, 16)) == FAIL)
2829 {
2830 inst.error = BAD_ARGS;
2831 return;
2832 }
2833
2834 if (rd == REG_PC)
2835 {
2836 inst.error = BAD_PC;
2837 return;
2838 }
2839
2840 if (skip_past_comma (&str) == FAIL
2841 || (rm = reg_required_here (&str, 0)) == FAIL)
2842 {
2843 inst.error = BAD_ARGS;
2844 return;
2845 }
2846
2847 if (rm == REG_PC)
2848 {
2849 inst.error = BAD_PC;
2850 return;
2851 }
2852
2853 /* This restriction does not apply to mls (nor to mla in v6, but
2854 that's hard to detect at present). */
2855 if (rm == rd && !is_mls)
2856 as_tsktsk (_("rd and rm should be different in mla"));
2857
2858 if (skip_past_comma (&str) == FAIL
2859 || (rd = reg_required_here (&str, 8)) == FAIL
2860 || skip_past_comma (&str) == FAIL
2861 || (rm = reg_required_here (&str, 12)) == FAIL)
2862 {
2863 inst.error = BAD_ARGS;
2864 return;
2865 }
2866
2867 if (rd == REG_PC || rm == REG_PC)
2868 {
2869 inst.error = BAD_PC;
2870 return;
2871 }
2872
2873 end_of_line (str);
2874 }
2875
2876 static void
2877 do_mla (char *str)
2878 {
2879 do_mlas (str, FALSE);
2880 }
2881
2882 static void
2883 do_mls (char *str)
2884 {
2885 do_mlas (str, TRUE);
2886 }
2887
2888 /* Expects *str -> the characters "acc0", possibly with leading blanks.
2889 Advances *str to the next non-alphanumeric.
2890 Returns 0, or else FAIL (in which case sets inst.error).
2891
2892 (In a future XScale, there may be accumulators other than zero.
2893 At that time this routine and its callers can be upgraded to suit.) */
2894
2895 static int
2896 accum0_required_here (char ** str)
2897 {
2898 static char buff [128]; /* Note the address is taken. Hence, static. */
2899 char * p = * str;
2900 char c;
2901 int result = 0; /* The accum number. */
2902
2903 skip_whitespace (p);
2904
2905 *str = p; /* Advance caller's string pointer too. */
2906 c = *p++;
2907 while (ISALNUM (c))
2908 c = *p++;
2909
2910 *--p = 0; /* Aap nul into input buffer at non-alnum. */
2911
2912 if (! ( streq (*str, "acc0") || streq (*str, "ACC0")))
2913 {
2914 sprintf (buff, _("acc0 expected, not '%.100s'"), *str);
2915 inst.error = buff;
2916 result = FAIL;
2917 }
2918
2919 *p = c; /* Unzap. */
2920 *str = p; /* Caller's string pointer to after match. */
2921 return result;
2922 }
2923
2924 static int
2925 ldst_extend_v4 (char ** str)
2926 {
2927 int add = INDEX_UP;
2928
2929 switch (**str)
2930 {
2931 case '#':
2932 case '$':
2933 (*str)++;
2934 if (my_get_expression (& inst.reloc.exp, str))
2935 return FAIL;
2936
2937 if (inst.reloc.exp.X_op == O_constant)
2938 {
2939 int value = inst.reloc.exp.X_add_number;
2940
2941 if (value < -255 || value > 255)
2942 {
2943 inst.error = _("address offset too large");
2944 return FAIL;
2945 }
2946
2947 if (value < 0)
2948 {
2949 value = -value;
2950 add = 0;
2951 }
2952
2953 /* Halfword and signextension instructions have the
2954 immediate value split across bits 11..8 and bits 3..0. */
2955 inst.instruction |= (add | HWOFFSET_IMM
2956 | ((value >> 4) << 8) | (value & 0xF));
2957 }
2958 else
2959 {
2960 inst.instruction |= HWOFFSET_IMM;
2961 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
2962 inst.reloc.pc_rel = 0;
2963 }
2964 return SUCCESS;
2965
2966 case '-':
2967 add = 0;
2968 /* Fall through. */
2969
2970 case '+':
2971 (*str)++;
2972 /* Fall through. */
2973
2974 default:
2975 if (reg_required_here (str, 0) == FAIL)
2976 return FAIL;
2977
2978 inst.instruction |= add;
2979 return SUCCESS;
2980 }
2981 }
2982
2983 /* Expects **str -> after a comma. May be leading blanks.
2984 Advances *str, recognizing a load mode, and setting inst.instruction.
2985 Returns rn, or else FAIL (in which case may set inst.error
2986 and not advance str)
2987
2988 Note: doesn't know Rd, so no err checks that require such knowledge. */
2989
2990 static int
2991 ld_mode_required_here (char ** string)
2992 {
2993 char * str = * string;
2994 int rn;
2995 int pre_inc = 0;
2996
2997 skip_whitespace (str);
2998
2999 if (* str == '[')
3000 {
3001 str++;
3002
3003 skip_whitespace (str);
3004
3005 if ((rn = reg_required_here (& str, 16)) == FAIL)
3006 return FAIL;
3007
3008 skip_whitespace (str);
3009
3010 if (* str == ']')
3011 {
3012 str ++;
3013
3014 if (skip_past_comma (& str) == SUCCESS)
3015 {
3016 /* [Rn],... (post inc) */
3017 if (ldst_extend_v4 (&str) == FAIL)
3018 return FAIL;
3019 }
3020 else /* [Rn] */
3021 {
3022 skip_whitespace (str);
3023
3024 if (* str == '!')
3025 {
3026 str ++;
3027 inst.instruction |= WRITE_BACK;
3028 }
3029
3030 inst.instruction |= INDEX_UP | HWOFFSET_IMM;
3031 pre_inc = 1;
3032 }
3033 }
3034 else /* [Rn,...] */
3035 {
3036 if (skip_past_comma (& str) == FAIL)
3037 {
3038 inst.error = _("pre-indexed expression expected");
3039 return FAIL;
3040 }
3041
3042 pre_inc = 1;
3043
3044 if (ldst_extend_v4 (&str) == FAIL)
3045 return FAIL;
3046
3047 skip_whitespace (str);
3048
3049 if (* str ++ != ']')
3050 {
3051 inst.error = _("missing ]");
3052 return FAIL;
3053 }
3054
3055 skip_whitespace (str);
3056
3057 if (* str == '!')
3058 {
3059 str ++;
3060 inst.instruction |= WRITE_BACK;
3061 }
3062 }
3063 }
3064 else if (* str == '=') /* ldr's "r,=label" syntax */
3065 /* We should never reach here, because <text> = <expression> is
3066 caught gas/read.c read_a_source_file() as a .set operation. */
3067 return FAIL;
3068 else /* PC +- 8 bit immediate offset. */
3069 {
3070 if (my_get_expression (& inst.reloc.exp, & str))
3071 return FAIL;
3072
3073 inst.instruction |= HWOFFSET_IMM; /* The I bit. */
3074 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
3075 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
3076 inst.reloc.pc_rel = 1;
3077 inst.instruction |= (REG_PC << 16);
3078
3079 rn = REG_PC;
3080 pre_inc = 1;
3081 }
3082
3083 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
3084 * string = str;
3085
3086 return rn;
3087 }
3088
3089 /* ARM V5E (El Segundo) signed-multiply-accumulate (argument parse)
3090 SMLAxy{cond} Rd,Rm,Rs,Rn
3091 SMLAWy{cond} Rd,Rm,Rs,Rn
3092 Error if any register is R15. */
3093
3094 static void
3095 do_smla (char * str)
3096 {
3097 int rd, rm, rs, rn;
3098
3099 skip_whitespace (str);
3100
3101 if ((rd = reg_required_here (& str, 16)) == FAIL
3102 || skip_past_comma (& str) == FAIL
3103 || (rm = reg_required_here (& str, 0)) == FAIL
3104 || skip_past_comma (& str) == FAIL
3105 || (rs = reg_required_here (& str, 8)) == FAIL
3106 || skip_past_comma (& str) == FAIL
3107 || (rn = reg_required_here (& str, 12)) == FAIL)
3108 inst.error = BAD_ARGS;
3109
3110 else if (rd == REG_PC || rm == REG_PC || rs == REG_PC || rn == REG_PC)
3111 inst.error = BAD_PC;
3112
3113 else
3114 end_of_line (str);
3115 }
3116
3117 /* ARM V5E (El Segundo) signed-multiply-accumulate-long (argument parse)
3118 SMLALxy{cond} Rdlo,Rdhi,Rm,Rs
3119 Error if any register is R15.
3120 Warning if Rdlo == Rdhi. */
3121
3122 static void
3123 do_smlal (char * str)
3124 {
3125 int rdlo, rdhi, rm, rs;
3126
3127 skip_whitespace (str);
3128
3129 if ((rdlo = reg_required_here (& str, 12)) == FAIL
3130 || skip_past_comma (& str) == FAIL
3131 || (rdhi = reg_required_here (& str, 16)) == FAIL
3132 || skip_past_comma (& str) == FAIL
3133 || (rm = reg_required_here (& str, 0)) == FAIL
3134 || skip_past_comma (& str) == FAIL
3135 || (rs = reg_required_here (& str, 8)) == FAIL)
3136 {
3137 inst.error = BAD_ARGS;
3138 return;
3139 }
3140
3141 if (rdlo == REG_PC || rdhi == REG_PC || rm == REG_PC || rs == REG_PC)
3142 {
3143 inst.error = BAD_PC;
3144 return;
3145 }
3146
3147 if (rdlo == rdhi)
3148 as_tsktsk (_("rdhi and rdlo must be different"));
3149
3150 end_of_line (str);
3151 }
3152
3153 /* ARM V5E (El Segundo) signed-multiply (argument parse)
3154 SMULxy{cond} Rd,Rm,Rs
3155 Error if any register is R15. */
3156
3157 static void
3158 do_smul (char * str)
3159 {
3160 int rd, rm, rs;
3161
3162 skip_whitespace (str);
3163
3164 if ((rd = reg_required_here (& str, 16)) == FAIL
3165 || skip_past_comma (& str) == FAIL
3166 || (rm = reg_required_here (& str, 0)) == FAIL
3167 || skip_past_comma (& str) == FAIL
3168 || (rs = reg_required_here (& str, 8)) == FAIL)
3169 inst.error = BAD_ARGS;
3170
3171 else if (rd == REG_PC || rm == REG_PC || rs == REG_PC)
3172 inst.error = BAD_PC;
3173
3174 else
3175 end_of_line (str);
3176 }
3177
3178 /* ARM V5E (El Segundo) saturating-add/subtract (argument parse)
3179 Q[D]{ADD,SUB}{cond} Rd,Rm,Rn
3180 Error if any register is R15. */
3181
3182 static void
3183 do_qadd (char * str)
3184 {
3185 int rd, rm, rn;
3186
3187 skip_whitespace (str);
3188
3189 if ((rd = reg_required_here (& str, 12)) == FAIL
3190 || skip_past_comma (& str) == FAIL
3191 || (rm = reg_required_here (& str, 0)) == FAIL
3192 || skip_past_comma (& str) == FAIL
3193 || (rn = reg_required_here (& str, 16)) == FAIL)
3194 inst.error = BAD_ARGS;
3195
3196 else if (rd == REG_PC || rm == REG_PC || rn == REG_PC)
3197 inst.error = BAD_PC;
3198
3199 else
3200 end_of_line (str);
3201 }
3202
3203 /* ARM V5E (el Segundo)
3204 MCRRcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
3205 MRRCcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
3206
3207 These are equivalent to the XScale instructions MAR and MRA,
3208 respectively, when coproc == 0, opcode == 0, and CRm == 0.
3209
3210 Result unpredicatable if Rd or Rn is R15. */
3211
3212 static void
3213 do_co_reg2c (char * str)
3214 {
3215 int rd, rn;
3216
3217 skip_whitespace (str);
3218
3219 if (co_proc_number (& str) == FAIL)
3220 {
3221 if (!inst.error)
3222 inst.error = BAD_ARGS;
3223 return;
3224 }
3225
3226 if (skip_past_comma (& str) == FAIL
3227 || cp_opc_expr (& str, 4, 4) == FAIL)
3228 {
3229 if (!inst.error)
3230 inst.error = BAD_ARGS;
3231 return;
3232 }
3233
3234 if (skip_past_comma (& str) == FAIL
3235 || (rd = reg_required_here (& str, 12)) == FAIL)
3236 {
3237 if (!inst.error)
3238 inst.error = BAD_ARGS;
3239 return;
3240 }
3241
3242 if (skip_past_comma (& str) == FAIL
3243 || (rn = reg_required_here (& str, 16)) == FAIL)
3244 {
3245 if (!inst.error)
3246 inst.error = BAD_ARGS;
3247 return;
3248 }
3249
3250 /* Unpredictable result if rd or rn is R15. */
3251 if (rd == REG_PC || rn == REG_PC)
3252 as_tsktsk
3253 (_("Warning: instruction unpredictable when using r15"));
3254
3255 if (skip_past_comma (& str) == FAIL
3256 || cp_reg_required_here (& str, 0) == FAIL)
3257 {
3258 if (!inst.error)
3259 inst.error = BAD_ARGS;
3260 return;
3261 }
3262
3263 end_of_line (str);
3264 }
3265
3266 /* ARM V5 count-leading-zeroes instruction (argument parse)
3267 CLZ{<cond>} <Rd>, <Rm>
3268 Condition defaults to COND_ALWAYS.
3269 Error if Rd or Rm are R15. */
3270
3271 static void
3272 do_clz (char * str)
3273 {
3274 int rd, rm;
3275
3276 skip_whitespace (str);
3277
3278 if (((rd = reg_required_here (& str, 12)) == FAIL)
3279 || (skip_past_comma (& str) == FAIL)
3280 || ((rm = reg_required_here (& str, 0)) == FAIL))
3281 inst.error = BAD_ARGS;
3282
3283 else if (rd == REG_PC || rm == REG_PC )
3284 inst.error = BAD_PC;
3285
3286 else
3287 end_of_line (str);
3288 }
3289
3290 /* ARM V5 (argument parse)
3291 LDC2{L} <coproc>, <CRd>, <addressing mode>
3292 STC2{L} <coproc>, <CRd>, <addressing mode>
3293 Instruction is not conditional, and has 0xf in the condition field.
3294 Otherwise, it's the same as LDC/STC. */
3295
3296 static void
3297 do_lstc2 (char * str)
3298 {
3299 skip_whitespace (str);
3300
3301 if (co_proc_number (& str) == FAIL)
3302 {
3303 if (!inst.error)
3304 inst.error = BAD_ARGS;
3305 }
3306 else if (skip_past_comma (& str) == FAIL
3307 || cp_reg_required_here (& str, 12) == FAIL)
3308 {
3309 if (!inst.error)
3310 inst.error = BAD_ARGS;
3311 }
3312 else if (skip_past_comma (& str) == FAIL
3313 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
3314 {
3315 if (! inst.error)
3316 inst.error = BAD_ARGS;
3317 }
3318 else
3319 end_of_line (str);
3320 }
3321
3322 /* ARM V5 (argument parse)
3323 CDP2 <coproc>, <opcode_1>, <CRd>, <CRn>, <CRm>, <opcode_2>
3324 Instruction is not conditional, and has 0xf in the condition field.
3325 Otherwise, it's the same as CDP. */
3326
3327 static void
3328 do_cdp2 (char * str)
3329 {
3330 skip_whitespace (str);
3331
3332 if (co_proc_number (& str) == FAIL)
3333 {
3334 if (!inst.error)
3335 inst.error = BAD_ARGS;
3336 return;
3337 }
3338
3339 if (skip_past_comma (& str) == FAIL
3340 || cp_opc_expr (& str, 20,4) == FAIL)
3341 {
3342 if (!inst.error)
3343 inst.error = BAD_ARGS;
3344 return;
3345 }
3346
3347 if (skip_past_comma (& str) == FAIL
3348 || cp_reg_required_here (& str, 12) == FAIL)
3349 {
3350 if (!inst.error)
3351 inst.error = BAD_ARGS;
3352 return;
3353 }
3354
3355 if (skip_past_comma (& str) == FAIL
3356 || cp_reg_required_here (& str, 16) == FAIL)
3357 {
3358 if (!inst.error)
3359 inst.error = BAD_ARGS;
3360 return;
3361 }
3362
3363 if (skip_past_comma (& str) == FAIL
3364 || cp_reg_required_here (& str, 0) == FAIL)
3365 {
3366 if (!inst.error)
3367 inst.error = BAD_ARGS;
3368 return;
3369 }
3370
3371 if (skip_past_comma (& str) == SUCCESS)
3372 {
3373 if (cp_opc_expr (& str, 5, 3) == FAIL)
3374 {
3375 if (!inst.error)
3376 inst.error = BAD_ARGS;
3377 return;
3378 }
3379 }
3380
3381 end_of_line (str);
3382 }
3383
3384 /* ARM V5 (argument parse)
3385 MCR2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
3386 MRC2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
3387 Instruction is not conditional, and has 0xf in the condition field.
3388 Otherwise, it's the same as MCR/MRC. */
3389
3390 static void
3391 do_co_reg2 (char * str)
3392 {
3393 skip_whitespace (str);
3394
3395 if (co_proc_number (& str) == FAIL)
3396 {
3397 if (!inst.error)
3398 inst.error = BAD_ARGS;
3399 return;
3400 }
3401
3402 if (skip_past_comma (& str) == FAIL
3403 || cp_opc_expr (& str, 21, 3) == FAIL)
3404 {
3405 if (!inst.error)
3406 inst.error = BAD_ARGS;
3407 return;
3408 }
3409
3410 if (skip_past_comma (& str) == FAIL
3411 || reg_required_here (& str, 12) == FAIL)
3412 {
3413 if (!inst.error)
3414 inst.error = BAD_ARGS;
3415 return;
3416 }
3417
3418 if (skip_past_comma (& str) == FAIL
3419 || cp_reg_required_here (& str, 16) == FAIL)
3420 {
3421 if (!inst.error)
3422 inst.error = BAD_ARGS;
3423 return;
3424 }
3425
3426 if (skip_past_comma (& str) == FAIL
3427 || cp_reg_required_here (& str, 0) == FAIL)
3428 {
3429 if (!inst.error)
3430 inst.error = BAD_ARGS;
3431 return;
3432 }
3433
3434 if (skip_past_comma (& str) == SUCCESS)
3435 {
3436 if (cp_opc_expr (& str, 5, 3) == FAIL)
3437 {
3438 if (!inst.error)
3439 inst.error = BAD_ARGS;
3440 return;
3441 }
3442 }
3443
3444 end_of_line (str);
3445 }
3446
3447 static void
3448 do_bx (char * str)
3449 {
3450 int reg;
3451
3452 skip_whitespace (str);
3453
3454 if ((reg = reg_required_here (&str, 0)) == FAIL)
3455 {
3456 inst.error = BAD_ARGS;
3457 return;
3458 }
3459
3460 /* Note - it is not illegal to do a "bx pc". Useless, but not illegal. */
3461 if (reg == REG_PC)
3462 as_tsktsk (_("use of r15 in bx in ARM mode is not really useful"));
3463
3464 end_of_line (str);
3465 }
3466
3467 /* ARM v5TEJ. Jump to Jazelle code. */
3468
3469 static void
3470 do_bxj (char * str)
3471 {
3472 int reg;
3473
3474 skip_whitespace (str);
3475
3476 if ((reg = reg_required_here (&str, 0)) == FAIL)
3477 {
3478 inst.error = BAD_ARGS;
3479 return;
3480 }
3481
3482 /* Note - it is not illegal to do a "bxj pc". Useless, but not illegal. */
3483 if (reg == REG_PC)
3484 as_tsktsk (_("use of r15 in bxj is not really useful"));
3485
3486 end_of_line (str);
3487 }
3488
3489 /* ARM V6 umaal (argument parse). */
3490
3491 static void
3492 do_umaal (char * str)
3493 {
3494 int rdlo, rdhi, rm, rs;
3495
3496 skip_whitespace (str);
3497 if ((rdlo = reg_required_here (& str, 12)) == FAIL
3498 || skip_past_comma (& str) == FAIL
3499 || (rdhi = reg_required_here (& str, 16)) == FAIL
3500 || skip_past_comma (& str) == FAIL
3501 || (rm = reg_required_here (& str, 0)) == FAIL
3502 || skip_past_comma (& str) == FAIL
3503 || (rs = reg_required_here (& str, 8)) == FAIL)
3504 {
3505 inst.error = BAD_ARGS;
3506 return;
3507 }
3508
3509 if (rdlo == REG_PC || rdhi == REG_PC || rm == REG_PC || rs == REG_PC)
3510 {
3511 inst.error = BAD_PC;
3512 return;
3513 }
3514
3515 end_of_line (str);
3516 }
3517
3518 /* ARM V6 strex (argument parse). */
3519
3520 static void
3521 do_strex (char * str)
3522 {
3523 int rd, rm, rn;
3524
3525 /* Parse Rd, Rm,. */
3526 skip_whitespace (str);
3527 if ((rd = reg_required_here (& str, 12)) == FAIL
3528 || skip_past_comma (& str) == FAIL
3529 || (rm = reg_required_here (& str, 0)) == FAIL
3530 || skip_past_comma (& str) == FAIL)
3531 {
3532 inst.error = BAD_ARGS;
3533 return;
3534 }
3535 if (rd == REG_PC || rm == REG_PC)
3536 {
3537 inst.error = BAD_PC;
3538 return;
3539 }
3540 if (rd == rm)
3541 {
3542 inst.error = _("Rd equal to Rm or Rn yields unpredictable results");
3543 return;
3544 }
3545
3546 /* Skip past '['. */
3547 if ((strlen (str) >= 1)
3548 && strncmp (str, "[", 1) == 0)
3549 str += 1;
3550
3551 skip_whitespace (str);
3552
3553 /* Parse Rn. */
3554 if ((rn = reg_required_here (& str, 16)) == FAIL)
3555 {
3556 inst.error = BAD_ARGS;
3557 return;
3558 }
3559 else if (rn == REG_PC)
3560 {
3561 inst.error = BAD_PC;
3562 return;
3563 }
3564 if (rd == rn)
3565 {
3566 inst.error = _("Rd equal to Rm or Rn yields unpredictable results");
3567 return;
3568 }
3569 skip_whitespace (str);
3570
3571 /* Skip past ']'. */
3572 if ((strlen (str) >= 1)
3573 && strncmp (str, "]", 1) == 0)
3574 str += 1;
3575
3576 end_of_line (str);
3577 }
3578
3579 /* KIND indicates what kind of shifts are accepted. */
3580
3581 static int
3582 decode_shift (char ** str, int kind)
3583 {
3584 const struct asm_shift_name * shift;
3585 char * p;
3586 char c;
3587
3588 skip_whitespace (* str);
3589
3590 for (p = * str; ISALPHA (* p); p ++)
3591 ;
3592
3593 if (p == * str)
3594 {
3595 inst.error = _("shift expression expected");
3596 return FAIL;
3597 }
3598
3599 c = * p;
3600 * p = '\0';
3601 shift = (const struct asm_shift_name *) hash_find (arm_shift_hsh, * str);
3602 * p = c;
3603
3604 if (shift == NULL)
3605 {
3606 inst.error = _("shift expression expected");
3607 return FAIL;
3608 }
3609
3610 assert (shift->properties->index == shift_properties[shift->properties->index].index);
3611
3612 if (kind == SHIFT_LSL_OR_ASR_IMMEDIATE
3613 && shift->properties->index != SHIFT_LSL
3614 && shift->properties->index != SHIFT_ASR)
3615 {
3616 inst.error = _("'LSL' or 'ASR' required");
3617 return FAIL;
3618 }
3619 else if (kind == SHIFT_LSL_IMMEDIATE
3620 && shift->properties->index != SHIFT_LSL)
3621 {
3622 inst.error = _("'LSL' required");
3623 return FAIL;
3624 }
3625 else if (kind == SHIFT_ASR_IMMEDIATE
3626 && shift->properties->index != SHIFT_ASR)
3627 {
3628 inst.error = _("'ASR' required");
3629 return FAIL;
3630 }
3631
3632 if (shift->properties->index == SHIFT_RRX)
3633 {
3634 * str = p;
3635 inst.instruction |= shift->properties->bit_field;
3636 return SUCCESS;
3637 }
3638
3639 skip_whitespace (p);
3640
3641 if (kind == NO_SHIFT_RESTRICT && reg_required_here (& p, 8) != FAIL)
3642 {
3643 inst.instruction |= shift->properties->bit_field | SHIFT_BY_REG;
3644 * str = p;
3645 return SUCCESS;
3646 }
3647 else if (! is_immediate_prefix (* p))
3648 {
3649 inst.error = (NO_SHIFT_RESTRICT
3650 ? _("shift requires register or #expression")
3651 : _("shift requires #expression"));
3652 * str = p;
3653 return FAIL;
3654 }
3655
3656 inst.error = NULL;
3657 p ++;
3658
3659 if (my_get_expression (& inst.reloc.exp, & p))
3660 return FAIL;
3661
3662 /* Validate some simple #expressions. */
3663 if (inst.reloc.exp.X_op == O_constant)
3664 {
3665 unsigned num = inst.reloc.exp.X_add_number;
3666
3667 /* Reject operations greater than 32. */
3668 if (num > 32
3669 /* Reject a shift of 0 unless the mode allows it. */
3670 || (num == 0 && shift->properties->allows_0 == 0)
3671 /* Reject a shift of 32 unless the mode allows it. */
3672 || (num == 32 && shift->properties->allows_32 == 0)
3673 )
3674 {
3675 /* As a special case we allow a shift of zero for
3676 modes that do not support it to be recoded as an
3677 logical shift left of zero (ie nothing). We warn
3678 about this though. */
3679 if (num == 0)
3680 {
3681 as_warn (_("shift of 0 ignored."));
3682 shift = & shift_names[0];
3683 assert (shift->properties->index == SHIFT_LSL);
3684 }
3685 else
3686 {
3687 inst.error = _("invalid immediate shift");
3688 return FAIL;
3689 }
3690 }
3691
3692 /* Shifts of 32 are encoded as 0, for those shifts that
3693 support it. */
3694 if (num == 32)
3695 num = 0;
3696
3697 inst.instruction |= (num << 7) | shift->properties->bit_field;
3698 }
3699 else
3700 {
3701 inst.reloc.type = BFD_RELOC_ARM_SHIFT_IMM;
3702 inst.reloc.pc_rel = 0;
3703 inst.instruction |= shift->properties->bit_field;
3704 }
3705
3706 * str = p;
3707 return SUCCESS;
3708 }
3709
3710 static void
3711 do_sat (char ** str, int bias)
3712 {
3713 int rd, rm;
3714 expressionS expr;
3715
3716 skip_whitespace (*str);
3717
3718 /* Parse <Rd>, field. */
3719 if ((rd = reg_required_here (str, 12)) == FAIL
3720 || skip_past_comma (str) == FAIL)
3721 {
3722 inst.error = BAD_ARGS;
3723 return;
3724 }
3725 if (rd == REG_PC)
3726 {
3727 inst.error = BAD_PC;
3728 return;
3729 }
3730
3731 /* Parse #<immed>, field. */
3732 if (is_immediate_prefix (**str))
3733 (*str)++;
3734 else
3735 {
3736 inst.error = _("immediate expression expected");
3737 return;
3738 }
3739 if (my_get_expression (&expr, str))
3740 {
3741 inst.error = _("bad expression");
3742 return;
3743 }
3744 if (expr.X_op != O_constant)
3745 {
3746 inst.error = _("constant expression expected");
3747 return;
3748 }
3749 if (expr.X_add_number + bias < 0
3750 || expr.X_add_number + bias > 31)
3751 {
3752 inst.error = _("immediate value out of range");
3753 return;
3754 }
3755 inst.instruction |= (expr.X_add_number + bias) << 16;
3756 if (skip_past_comma (str) == FAIL)
3757 {
3758 inst.error = BAD_ARGS;
3759 return;
3760 }
3761
3762 /* Parse <Rm> field. */
3763 if ((rm = reg_required_here (str, 0)) == FAIL)
3764 {
3765 inst.error = BAD_ARGS;
3766 return;
3767 }
3768 if (rm == REG_PC)
3769 {
3770 inst.error = BAD_PC;
3771 return;
3772 }
3773
3774 if (skip_past_comma (str) == SUCCESS)
3775 decode_shift (str, SHIFT_LSL_OR_ASR_IMMEDIATE);
3776 }
3777
3778 /* ARM V6 ssat (argument parse). */
3779
3780 static void
3781 do_ssat (char * str)
3782 {
3783 do_sat (&str, /*bias=*/-1);
3784 end_of_line (str);
3785 }
3786
3787 /* ARM V6 usat (argument parse). */
3788
3789 static void
3790 do_usat (char * str)
3791 {
3792 do_sat (&str, /*bias=*/0);
3793 end_of_line (str);
3794 }
3795
3796 static void
3797 do_sat16 (char ** str, int bias)
3798 {
3799 int rd, rm;
3800 expressionS expr;
3801
3802 skip_whitespace (*str);
3803
3804 /* Parse the <Rd> field. */
3805 if ((rd = reg_required_here (str, 12)) == FAIL
3806 || skip_past_comma (str) == FAIL)
3807 {
3808 inst.error = BAD_ARGS;
3809 return;
3810 }
3811 if (rd == REG_PC)
3812 {
3813 inst.error = BAD_PC;
3814 return;
3815 }
3816
3817 /* Parse #<immed>, field. */
3818 if (is_immediate_prefix (**str))
3819 (*str)++;
3820 else
3821 {
3822 inst.error = _("immediate expression expected");
3823 return;
3824 }
3825 if (my_get_expression (&expr, str))
3826 {
3827 inst.error = _("bad expression");
3828 return;
3829 }
3830 if (expr.X_op != O_constant)
3831 {
3832 inst.error = _("constant expression expected");
3833 return;
3834 }
3835 if (expr.X_add_number + bias < 0
3836 || expr.X_add_number + bias > 15)
3837 {
3838 inst.error = _("immediate value out of range");
3839 return;
3840 }
3841 inst.instruction |= (expr.X_add_number + bias) << 16;
3842 if (skip_past_comma (str) == FAIL)
3843 {
3844 inst.error = BAD_ARGS;
3845 return;
3846 }
3847
3848 /* Parse <Rm> field. */
3849 if ((rm = reg_required_here (str, 0)) == FAIL)
3850 {
3851 inst.error = BAD_ARGS;
3852 return;
3853 }
3854 if (rm == REG_PC)
3855 {
3856 inst.error = BAD_PC;
3857 return;
3858 }
3859 }
3860
3861 /* ARM V6 ssat16 (argument parse). */
3862
3863 static void
3864 do_ssat16 (char * str)
3865 {
3866 do_sat16 (&str, /*bias=*/-1);
3867 end_of_line (str);
3868 }
3869
3870 static void
3871 do_usat16 (char * str)
3872 {
3873 do_sat16 (&str, /*bias=*/0);
3874 end_of_line (str);
3875 }
3876
3877 static void
3878 do_cps_mode (char ** str)
3879 {
3880 expressionS expr;
3881
3882 skip_whitespace (*str);
3883
3884 if (! is_immediate_prefix (**str))
3885 {
3886 inst.error = _("immediate expression expected");
3887 return;
3888 }
3889
3890 (*str)++; /* Strip off the immediate signifier. */
3891 if (my_get_expression (&expr, str))
3892 {
3893 inst.error = _("bad expression");
3894 return;
3895 }
3896
3897 if (expr.X_op != O_constant)
3898 {
3899 inst.error = _("constant expression expected");
3900 return;
3901 }
3902
3903 /* The mode is a 5 bit field. Valid values are 0-31. */
3904 if (((unsigned) expr.X_add_number) > 31
3905 || (inst.reloc.exp.X_add_number) < 0)
3906 {
3907 inst.error = _("invalid constant");
3908 return;
3909 }
3910
3911 inst.instruction |= expr.X_add_number;
3912 }
3913
3914 /* ARM V6 srs (argument parse). */
3915
3916 static void
3917 do_srs (char * str)
3918 {
3919 char *exclam;
3920 skip_whitespace (str);
3921 exclam = strchr (str, '!');
3922 if (exclam)
3923 *exclam = '\0';
3924 do_cps_mode (&str);
3925 if (exclam)
3926 *exclam = '!';
3927 if (*str == '!')
3928 {
3929 inst.instruction |= WRITE_BACK;
3930 str++;
3931 }
3932 end_of_line (str);
3933 }
3934
3935 /* ARM V6 SMMUL (argument parse). */
3936
3937 static void
3938 do_smmul (char * str)
3939 {
3940 int rd, rm, rs;
3941
3942 skip_whitespace (str);
3943 if ((rd = reg_required_here (&str, 16)) == FAIL
3944 || skip_past_comma (&str) == FAIL
3945 || (rm = reg_required_here (&str, 0)) == FAIL
3946 || skip_past_comma (&str) == FAIL
3947 || (rs = reg_required_here (&str, 8)) == FAIL)
3948 {
3949 inst.error = BAD_ARGS;
3950 return;
3951 }
3952
3953 if ( rd == REG_PC
3954 || rm == REG_PC
3955 || rs == REG_PC)
3956 {
3957 inst.error = BAD_PC;
3958 return;
3959 }
3960
3961 end_of_line (str);
3962 }
3963
3964 /* ARM V6 SMLALD (argument parse). */
3965
3966 static void
3967 do_smlald (char * str)
3968 {
3969 int rdlo, rdhi, rm, rs;
3970
3971 skip_whitespace (str);
3972 if ((rdlo = reg_required_here (&str, 12)) == FAIL
3973 || skip_past_comma (&str) == FAIL
3974 || (rdhi = reg_required_here (&str, 16)) == FAIL
3975 || skip_past_comma (&str) == FAIL
3976 || (rm = reg_required_here (&str, 0)) == FAIL
3977 || skip_past_comma (&str) == FAIL
3978 || (rs = reg_required_here (&str, 8)) == FAIL)
3979 {
3980 inst.error = BAD_ARGS;
3981 return;
3982 }
3983
3984 if ( rdlo == REG_PC
3985 || rdhi == REG_PC
3986 || rm == REG_PC
3987 || rs == REG_PC)
3988 {
3989 inst.error = BAD_PC;
3990 return;
3991 }
3992
3993 end_of_line (str);
3994 }
3995
3996 /* ARM V6 SMLAD (argument parse). Signed multiply accumulate dual.
3997 smlad{x}{<cond>} Rd, Rm, Rs, Rn */
3998
3999 static void
4000 do_smlad (char * str)
4001 {
4002 int rd, rm, rs, rn;
4003
4004 skip_whitespace (str);
4005 if ((rd = reg_required_here (&str, 16)) == FAIL
4006 || skip_past_comma (&str) == FAIL
4007 || (rm = reg_required_here (&str, 0)) == FAIL
4008 || skip_past_comma (&str) == FAIL
4009 || (rs = reg_required_here (&str, 8)) == FAIL
4010 || skip_past_comma (&str) == FAIL
4011 || (rn = reg_required_here (&str, 12)) == FAIL)
4012 {
4013 inst.error = BAD_ARGS;
4014 return;
4015 }
4016
4017 if ( rd == REG_PC
4018 || rn == REG_PC
4019 || rs == REG_PC
4020 || rm == REG_PC)
4021 {
4022 inst.error = BAD_PC;
4023 return;
4024 }
4025
4026 end_of_line (str);
4027 }
4028
4029 /* Returns true if the endian-specifier indicates big-endianness. */
4030
4031 static int
4032 do_endian_specifier (char * str)
4033 {
4034 int big_endian = 0;
4035
4036 skip_whitespace (str);
4037 if (strlen (str) < 2)
4038 inst.error = _("missing endian specifier");
4039 else if (strncasecmp (str, "BE", 2) == 0)
4040 {
4041 str += 2;
4042 big_endian = 1;
4043 }
4044 else if (strncasecmp (str, "LE", 2) == 0)
4045 str += 2;
4046 else
4047 inst.error = _("valid endian specifiers are be or le");
4048
4049 end_of_line (str);
4050
4051 return big_endian;
4052 }
4053
4054 /* ARM V6 SETEND (argument parse). Sets the E bit in the CPSR while
4055 preserving the other bits.
4056
4057 setend <endian_specifier>, where <endian_specifier> is either
4058 BE or LE. */
4059
4060 static void
4061 do_setend (char * str)
4062 {
4063 if (do_endian_specifier (str))
4064 inst.instruction |= 0x200;
4065 }
4066
4067 /* ARM V6 SXTH.
4068
4069 SXTH {<cond>} <Rd>, <Rm>{, <rotation>}
4070 Condition defaults to COND_ALWAYS.
4071 Error if any register uses R15. */
4072
4073 static void
4074 do_sxth (char * str)
4075 {
4076 int rd, rm;
4077 expressionS expr;
4078 int rotation_clear_mask = 0xfffff3ff;
4079 int rotation_eight_mask = 0x00000400;
4080 int rotation_sixteen_mask = 0x00000800;
4081 int rotation_twenty_four_mask = 0x00000c00;
4082
4083 skip_whitespace (str);
4084 if ((rd = reg_required_here (&str, 12)) == FAIL
4085 || skip_past_comma (&str) == FAIL
4086 || (rm = reg_required_here (&str, 0)) == FAIL)
4087 {
4088 inst.error = BAD_ARGS;
4089 return;
4090 }
4091
4092 else if (rd == REG_PC || rm == REG_PC)
4093 {
4094 inst.error = BAD_PC;
4095 return;
4096 }
4097
4098 /* Zero out the rotation field. */
4099 inst.instruction &= rotation_clear_mask;
4100
4101 /* Check for lack of optional rotation field. */
4102 if (skip_past_comma (&str) == FAIL)
4103 {
4104 end_of_line (str);
4105 return;
4106 }
4107
4108 /* Move past 'ROR'. */
4109 skip_whitespace (str);
4110 if (strncasecmp (str, "ROR", 3) == 0)
4111 str += 3;
4112 else
4113 {
4114 inst.error = _("missing rotation field after comma");
4115 return;
4116 }
4117
4118 /* Get the immediate constant. */
4119 skip_whitespace (str);
4120 if (is_immediate_prefix (* str))
4121 str++;
4122 else
4123 {
4124 inst.error = _("immediate expression expected");
4125 return;
4126 }
4127
4128 if (my_get_expression (&expr, &str))
4129 {
4130 inst.error = _("bad expression");
4131 return;
4132 }
4133
4134 if (expr.X_op != O_constant)
4135 {
4136 inst.error = _("constant expression expected");
4137 return;
4138 }
4139
4140 switch (expr.X_add_number)
4141 {
4142 case 0:
4143 /* Rotation field has already been zeroed. */
4144 break;
4145 case 8:
4146 inst.instruction |= rotation_eight_mask;
4147 break;
4148
4149 case 16:
4150 inst.instruction |= rotation_sixteen_mask;
4151 break;
4152
4153 case 24:
4154 inst.instruction |= rotation_twenty_four_mask;
4155 break;
4156
4157 default:
4158 inst.error = _("rotation can be 8, 16, 24 or 0 when field is ommited");
4159 break;
4160 }
4161
4162 end_of_line (str);
4163 }
4164
4165 /* ARM V6 SXTAH extracts a 16-bit value from a register, sign
4166 extends it to 32-bits, and adds the result to a value in another
4167 register. You can specify a rotation by 0, 8, 16, or 24 bits
4168 before extracting the 16-bit value.
4169 SXTAH{<cond>} <Rd>, <Rn>, <Rm>{, <rotation>}
4170 Condition defaults to COND_ALWAYS.
4171 Error if any register uses R15. */
4172
4173 static void
4174 do_sxtah (char * str)
4175 {
4176 int rd, rn, rm;
4177 expressionS expr;
4178 int rotation_clear_mask = 0xfffff3ff;
4179 int rotation_eight_mask = 0x00000400;
4180 int rotation_sixteen_mask = 0x00000800;
4181 int rotation_twenty_four_mask = 0x00000c00;
4182
4183 skip_whitespace (str);
4184 if ((rd = reg_required_here (&str, 12)) == FAIL
4185 || skip_past_comma (&str) == FAIL
4186 || (rn = reg_required_here (&str, 16)) == FAIL
4187 || skip_past_comma (&str) == FAIL
4188 || (rm = reg_required_here (&str, 0)) == FAIL)
4189 {
4190 inst.error = BAD_ARGS;
4191 return;
4192 }
4193
4194 else if (rd == REG_PC || rn == REG_PC || rm == REG_PC)
4195 {
4196 inst.error = BAD_PC;
4197 return;
4198 }
4199
4200 /* Zero out the rotation field. */
4201 inst.instruction &= rotation_clear_mask;
4202
4203 /* Check for lack of optional rotation field. */
4204 if (skip_past_comma (&str) == FAIL)
4205 {
4206 end_of_line (str);
4207 return;
4208 }
4209
4210 /* Move past 'ROR'. */
4211 skip_whitespace (str);
4212 if (strncasecmp (str, "ROR", 3) == 0)
4213 str += 3;
4214 else
4215 {
4216 inst.error = _("missing rotation field after comma");
4217 return;
4218 }
4219
4220 /* Get the immediate constant. */
4221 skip_whitespace (str);
4222 if (is_immediate_prefix (* str))
4223 str++;
4224 else
4225 {
4226 inst.error = _("immediate expression expected");
4227 return;
4228 }
4229
4230 if (my_get_expression (&expr, &str))
4231 {
4232 inst.error = _("bad expression");
4233 return;
4234 }
4235
4236 if (expr.X_op != O_constant)
4237 {
4238 inst.error = _("constant expression expected");
4239 return;
4240 }
4241
4242 switch (expr.X_add_number)
4243 {
4244 case 0:
4245 /* Rotation field has already been zeroed. */
4246 break;
4247
4248 case 8:
4249 inst.instruction |= rotation_eight_mask;
4250 break;
4251
4252 case 16:
4253 inst.instruction |= rotation_sixteen_mask;
4254 break;
4255
4256 case 24:
4257 inst.instruction |= rotation_twenty_four_mask;
4258 break;
4259
4260 default:
4261 inst.error = _("rotation can be 8, 16, 24 or 0 when field is ommited");
4262 break;
4263 }
4264
4265 end_of_line (str);
4266 }
4267
4268
4269 /* ARM V6 RFE (Return from Exception) loads the PC and CPSR from the
4270 word at the specified address and the following word
4271 respectively.
4272 Unconditionally executed.
4273 Error if Rn is R15. */
4274
4275 static void
4276 do_rfe (char * str)
4277 {
4278 int rn;
4279
4280 skip_whitespace (str);
4281
4282 if ((rn = reg_required_here (&str, 16)) == FAIL)
4283 return;
4284
4285 if (rn == REG_PC)
4286 {
4287 inst.error = BAD_PC;
4288 return;
4289 }
4290
4291 skip_whitespace (str);
4292
4293 if (*str == '!')
4294 {
4295 inst.instruction |= WRITE_BACK;
4296 str++;
4297 }
4298 end_of_line (str);
4299 }
4300
4301 /* ARM V6 REV (Byte Reverse Word) reverses the byte order in a 32-bit
4302 register (argument parse).
4303 REV{<cond>} Rd, Rm.
4304 Condition defaults to COND_ALWAYS.
4305 Error if Rd or Rm are R15. */
4306
4307 static void
4308 do_rev (char * str)
4309 {
4310 int rd, rm;
4311
4312 skip_whitespace (str);
4313
4314 if ((rd = reg_required_here (&str, 12)) == FAIL
4315 || skip_past_comma (&str) == FAIL
4316 || (rm = reg_required_here (&str, 0)) == FAIL)
4317 inst.error = BAD_ARGS;
4318
4319 else if (rd == REG_PC || rm == REG_PC)
4320 inst.error = BAD_PC;
4321
4322 else
4323 end_of_line (str);
4324 }
4325
4326 /* ARM V6 Perform Two Sixteen Bit Integer Additions. (argument parse).
4327 QADD16{<cond>} <Rd>, <Rn>, <Rm>
4328 Condition defaults to COND_ALWAYS.
4329 Error if Rd, Rn or Rm are R15. */
4330
4331 static void
4332 do_qadd16 (char * str)
4333 {
4334 int rd, rm, rn;
4335
4336 skip_whitespace (str);
4337
4338 if ((rd = reg_required_here (&str, 12)) == FAIL
4339 || skip_past_comma (&str) == FAIL
4340 || (rn = reg_required_here (&str, 16)) == FAIL
4341 || skip_past_comma (&str) == FAIL
4342 || (rm = reg_required_here (&str, 0)) == FAIL)
4343 inst.error = BAD_ARGS;
4344
4345 else if (rd == REG_PC || rm == REG_PC || rn == REG_PC)
4346 inst.error = BAD_PC;
4347
4348 else
4349 end_of_line (str);
4350 }
4351
4352 static void
4353 do_pkh_core (char * str, int shift)
4354 {
4355 int rd, rn, rm;
4356
4357 skip_whitespace (str);
4358 if (((rd = reg_required_here (&str, 12)) == FAIL)
4359 || (skip_past_comma (&str) == FAIL)
4360 || ((rn = reg_required_here (&str, 16)) == FAIL)
4361 || (skip_past_comma (&str) == FAIL)
4362 || ((rm = reg_required_here (&str, 0)) == FAIL))
4363 {
4364 inst.error = BAD_ARGS;
4365 return;
4366 }
4367
4368 else if (rd == REG_PC || rn == REG_PC || rm == REG_PC)
4369 {
4370 inst.error = BAD_PC;
4371 return;
4372 }
4373
4374 /* Check for optional shift immediate constant. */
4375 if (skip_past_comma (&str) == FAIL)
4376 {
4377 if (shift == SHIFT_ASR_IMMEDIATE)
4378 {
4379 /* If the shift specifier is ommited, turn the instruction
4380 into pkhbt rd, rm, rn. First, switch the instruction
4381 code, and clear the rn and rm fields. */
4382 inst.instruction &= 0xfff0f010;
4383 /* Now, re-encode the registers. */
4384 inst.instruction |= (rm << 16) | rn;
4385 }
4386 return;
4387 }
4388
4389 decode_shift (&str, shift);
4390 }
4391
4392 /* ARM V6 Pack Halfword Bottom Top instruction (argument parse).
4393 PKHBT {<cond>} <Rd>, <Rn>, <Rm> {, LSL #<shift_imm>}
4394 Condition defaults to COND_ALWAYS.
4395 Error if Rd, Rn or Rm are R15. */
4396
4397 static void
4398 do_pkhbt (char * str)
4399 {
4400 do_pkh_core (str, SHIFT_LSL_IMMEDIATE);
4401 }
4402
4403 /* ARM V6 PKHTB (Argument Parse). */
4404
4405 static void
4406 do_pkhtb (char * str)
4407 {
4408 do_pkh_core (str, SHIFT_ASR_IMMEDIATE);
4409 }
4410
4411 /* ARM V6 Load Register Exclusive instruction (argument parse).
4412 LDREX{,B,D,H}{<cond>} <Rd, [<Rn>]
4413 Condition defaults to COND_ALWAYS.
4414 Error if Rd or Rn are R15.
4415 See ARMARMv6 A4.1.27: LDREX. */
4416
4417 static void
4418 do_ldrex (char * str)
4419 {
4420 int rd, rn;
4421
4422 skip_whitespace (str);
4423
4424 /* Parse Rd. */
4425 if (((rd = reg_required_here (&str, 12)) == FAIL)
4426 || (skip_past_comma (&str) == FAIL))
4427 {
4428 inst.error = BAD_ARGS;
4429 return;
4430 }
4431 else if (rd == REG_PC)
4432 {
4433 inst.error = BAD_PC;
4434 return;
4435 }
4436 skip_whitespace (str);
4437
4438 /* Skip past '['. */
4439 if ((strlen (str) >= 1)
4440 &&strncmp (str, "[", 1) == 0)
4441 str += 1;
4442 skip_whitespace (str);
4443
4444 /* Parse Rn. */
4445 if ((rn = reg_required_here (&str, 16)) == FAIL)
4446 {
4447 inst.error = BAD_ARGS;
4448 return;
4449 }
4450 else if (rn == REG_PC)
4451 {
4452 inst.error = BAD_PC;
4453 return;
4454 }
4455 skip_whitespace (str);
4456
4457 /* Skip past ']'. */
4458 if ((strlen (str) >= 1)
4459 && strncmp (str, "]", 1) == 0)
4460 str += 1;
4461
4462 end_of_line (str);
4463 }
4464
4465 /* ARM V6 change processor state instruction (argument parse)
4466 CPS, CPSIE, CSPID . */
4467
4468 static void
4469 do_cps (char * str)
4470 {
4471 do_cps_mode (&str);
4472 end_of_line (str);
4473 }
4474
4475 static void
4476 do_cps_flags (char ** str, int thumb_p)
4477 {
4478 struct cps_flag
4479 {
4480 char character;
4481 unsigned long arm_value;
4482 unsigned long thumb_value;
4483 };
4484 static struct cps_flag flag_table[] =
4485 {
4486 {'a', 0x100, 0x4 },
4487 {'i', 0x080, 0x2 },
4488 {'f', 0x040, 0x1 }
4489 };
4490
4491 int saw_a_flag = 0;
4492
4493 skip_whitespace (*str);
4494
4495 /* Get the a, f and i flags. */
4496 while (**str && **str != ',')
4497 {
4498 struct cps_flag *p;
4499 struct cps_flag *q = flag_table + sizeof (flag_table)/sizeof (*p);
4500
4501 for (p = flag_table; p < q; ++p)
4502 if (strncasecmp (*str, &p->character, 1) == 0)
4503 {
4504 inst.instruction |= (thumb_p ? p->thumb_value : p->arm_value);
4505 saw_a_flag = 1;
4506 break;
4507 }
4508 if (p == q)
4509 {
4510 inst.error = _("unrecognized flag");
4511 return;
4512 }
4513 (*str)++;
4514 }
4515
4516 if (!saw_a_flag)
4517 inst.error = _("no 'a', 'i', or 'f' flags for 'cps'");
4518 }
4519
4520 static void
4521 do_cpsi (char * str)
4522 {
4523 do_cps_flags (&str, /*thumb_p=*/0);
4524
4525 if (skip_past_comma (&str) == SUCCESS)
4526 {
4527 skip_whitespace (str);
4528 do_cps_mode (&str);
4529 }
4530 end_of_line (str);
4531 }
4532
4533 /* ARM V6T2 bitfield manipulation instructions. */
4534
4535 static int
4536 five_bit_unsigned_immediate (char **str)
4537 {
4538 expressionS expr;
4539
4540 skip_whitespace (*str);
4541 if (!is_immediate_prefix (**str))
4542 {
4543 inst.error = _("immediate expression expected");
4544 return -1;
4545 }
4546 (*str)++;
4547 if (my_get_expression (&expr, str))
4548 {
4549 inst.error = _("bad expression");
4550 return -1;
4551 }
4552 if (expr.X_op != O_constant)
4553 {
4554 inst.error = _("constant expression expected");
4555 return -1;
4556 }
4557 if (expr.X_add_number < 0 || expr.X_add_number > 32)
4558 {
4559 inst.error = _("immediate value out of range");
4560 return -1;
4561 }
4562
4563 return expr.X_add_number;
4564 }
4565
4566 static void
4567 bfci_lsb_and_width (char *str)
4568 {
4569 int lsb, width;
4570
4571 if ((lsb = five_bit_unsigned_immediate (&str)) == -1)
4572 return;
4573
4574 if (skip_past_comma (&str) == FAIL)
4575 {
4576 inst.error = BAD_ARGS;
4577 return;
4578 }
4579 if ((width = five_bit_unsigned_immediate (&str)) == -1)
4580 return;
4581
4582 end_of_line (str);
4583
4584 if (width == 0 || lsb == 32)
4585 {
4586 inst.error = _("immediate value out of range");
4587 return;
4588 }
4589 else if (width + lsb > 32)
4590 {
4591 inst.error = _("bit-field extends past end of register");
4592 return;
4593 }
4594
4595 /* Convert to LSB/MSB and write to register. */
4596 inst.instruction |= lsb << 7;
4597 inst.instruction |= (width + lsb - 1) << 16;
4598 }
4599
4600 static void
4601 do_bfc (char *str)
4602 {
4603 int rd;
4604
4605 /* Rd. */
4606 skip_whitespace (str);
4607 if (((rd = reg_required_here (&str, 12)) == FAIL)
4608 || (skip_past_comma (&str) == FAIL))
4609 {
4610 inst.error = BAD_ARGS;
4611 return;
4612 }
4613 else if (rd == REG_PC)
4614 {
4615 inst.error = BAD_PC;
4616 return;
4617 }
4618
4619 bfci_lsb_and_width (str);
4620 }
4621
4622 static void
4623 do_bfi (char *str)
4624 {
4625 int rd, rm;
4626
4627 /* Rd. */
4628 skip_whitespace (str);
4629 if (((rd = reg_required_here (&str, 12)) == FAIL)
4630 || (skip_past_comma (&str) == FAIL))
4631 {
4632 inst.error = BAD_ARGS;
4633 return;
4634 }
4635 else if (rd == REG_PC)
4636 {
4637 inst.error = BAD_PC;
4638 return;
4639 }
4640
4641 /* Rm. Accept #0 in this position as an alternative syntax for bfc. */
4642 skip_whitespace (str);
4643 if (is_immediate_prefix (*str))
4644 {
4645 expressionS expr;
4646 str++;
4647 if (my_get_expression (&expr, &str))
4648 {
4649 inst.error = _("bad expression");
4650 return;
4651 }
4652 if (expr.X_op != O_constant)
4653 {
4654 inst.error = _("constant expression expected");
4655 return;
4656 }
4657 if (expr.X_add_number != 0)
4658 {
4659 inst.error = _("immediate value out of range");
4660 return;
4661 }
4662 inst.instruction |= 0x0000000f; /* Rm = PC -> bfc, not bfi. */
4663 }
4664 else
4665 {
4666 if ((rm = reg_required_here (&str, 0)) == FAIL)
4667 {
4668 inst.error = BAD_ARGS;
4669 return;
4670 }
4671 else if (rm == REG_PC)
4672 {
4673 inst.error = BAD_PC;
4674 return;
4675 }
4676 }
4677 if (skip_past_comma (&str) == FAIL)
4678 {
4679 inst.error = BAD_ARGS;
4680 return;
4681 }
4682
4683 bfci_lsb_and_width (str);
4684 }
4685
4686 static void
4687 do_bfx (char *str)
4688 {
4689 int lsb, width;
4690
4691 /* Rd. */
4692 skip_whitespace (str);
4693 if (reg_required_here (&str, 12) == FAIL
4694 || skip_past_comma (&str) == FAIL)
4695 {
4696 inst.error = BAD_ARGS;
4697 return;
4698 }
4699
4700 /* Rm. */
4701 skip_whitespace (str);
4702 if (reg_required_here (&str, 0) == FAIL
4703 || skip_past_comma (&str) == FAIL)
4704 {
4705 inst.error = BAD_ARGS;
4706 return;
4707 }
4708
4709 if ((lsb = five_bit_unsigned_immediate (&str)) == -1)
4710 return;
4711
4712 if (skip_past_comma (&str) == FAIL)
4713 {
4714 inst.error = BAD_ARGS;
4715 return;
4716 }
4717 if ((width = five_bit_unsigned_immediate (&str)) == -1)
4718 return;
4719
4720 end_of_line (str);
4721
4722 if (width == 0 || lsb == 32)
4723 {
4724 inst.error = _("immediate value out of range");
4725 return;
4726 }
4727 else if (width + lsb > 32)
4728 {
4729 inst.error = _("bit-field extends past end of register");
4730 return;
4731 }
4732
4733 inst.instruction |= lsb << 7;
4734 inst.instruction |= (width - 1) << 16;
4735 }
4736
4737 static void
4738 do_rbit (char *str)
4739 {
4740 /* Rd. */
4741 skip_whitespace (str);
4742 if (reg_required_here (&str, 12) == FAIL
4743 || skip_past_comma (&str) == FAIL)
4744 {
4745 inst.error = BAD_ARGS;
4746 return;
4747 }
4748
4749 /* Rm. */
4750 skip_whitespace (str);
4751 if (reg_required_here (&str, 0) == FAIL)
4752 {
4753 inst.error = BAD_ARGS;
4754 return;
4755 }
4756
4757 end_of_line (str);
4758 }
4759
4760 /* ARM V6T2 16-bit immediate register load: MOV[WT]{cond} Rd, #<imm16>. */
4761 static void
4762 do_mov16 (char *str)
4763 {
4764 int rd;
4765 expressionS expr;
4766
4767 /* Rd. */
4768 skip_whitespace (str);
4769 if (((rd = reg_required_here (&str, 12)) == FAIL)
4770 || (skip_past_comma (&str) == FAIL))
4771 {
4772 inst.error = BAD_ARGS;
4773 return;
4774 }
4775 else if (rd == REG_PC)
4776 {
4777 inst.error = BAD_PC;
4778 return;
4779 }
4780
4781 /* Imm16. */
4782 skip_whitespace (str);
4783 if (!is_immediate_prefix (*str))
4784 {
4785 inst.error = _("immediate expression expected");
4786 return;
4787 }
4788 str++;
4789 if (my_get_expression (&expr, &str))
4790 {
4791 inst.error = _("bad expression");
4792 return;
4793 }
4794 if (expr.X_op != O_constant)
4795 {
4796 inst.error = _("constant expression expected");
4797 return;
4798 }
4799 if (expr.X_add_number < 0 || expr.X_add_number > 65535)
4800 {
4801 inst.error = _("immediate value out of range");
4802 return;
4803 }
4804
4805 end_of_line (str);
4806
4807 /* The value is in two pieces: 0:11, 16:19. */
4808 inst.instruction |= (expr.X_add_number & 0x00000fff);
4809 inst.instruction |= (expr.X_add_number & 0x0000f000) << 4;
4810 }
4811
4812
4813 /* THUMB V5 breakpoint instruction (argument parse)
4814 BKPT <immed_8>. */
4815
4816 static void
4817 do_t_bkpt (char * str)
4818 {
4819 expressionS expr;
4820 unsigned long number;
4821
4822 skip_whitespace (str);
4823
4824 /* Allow optional leading '#'. */
4825 if (is_immediate_prefix (*str))
4826 str ++;
4827
4828 memset (& expr, '\0', sizeof (expr));
4829 if (my_get_expression (& expr, & str)
4830 || (expr.X_op != O_constant
4831 /* As a convenience we allow 'bkpt' without an operand. */
4832 && expr.X_op != O_absent))
4833 {
4834 inst.error = _("bad expression");
4835 return;
4836 }
4837
4838 number = expr.X_add_number;
4839
4840 /* Check it fits an 8 bit unsigned. */
4841 if (number != (number & 0xff))
4842 {
4843 inst.error = _("immediate value out of range");
4844 return;
4845 }
4846
4847 inst.instruction |= number;
4848
4849 end_of_line (str);
4850 }
4851
4852 #ifdef OBJ_ELF
4853 static bfd_reloc_code_real_type
4854 arm_parse_reloc (void)
4855 {
4856 char id [16];
4857 char * ip;
4858 unsigned int i;
4859 static struct
4860 {
4861 char * str;
4862 int len;
4863 bfd_reloc_code_real_type reloc;
4864 }
4865 reloc_map[] =
4866 {
4867 #define MAP(str,reloc) { str, sizeof (str) - 1, reloc }
4868 MAP ("(got)", BFD_RELOC_ARM_GOT32),
4869 MAP ("(gotoff)", BFD_RELOC_ARM_GOTOFF),
4870 /* ScottB: Jan 30, 1998 - Added support for parsing "var(PLT)"
4871 branch instructions generated by GCC for PLT relocs. */
4872 MAP ("(plt)", BFD_RELOC_ARM_PLT32),
4873 MAP ("(target1)", BFD_RELOC_ARM_TARGET1),
4874 MAP ("(sbrel)", BFD_RELOC_ARM_SBREL32),
4875 MAP ("(target2)", BFD_RELOC_ARM_TARGET2),
4876 { NULL, 0, BFD_RELOC_UNUSED }
4877 #undef MAP
4878 };
4879
4880 for (i = 0, ip = input_line_pointer;
4881 i < sizeof (id) && (ISALNUM (*ip) || ISPUNCT (*ip));
4882 i++, ip++)
4883 id[i] = TOLOWER (*ip);
4884
4885 for (i = 0; reloc_map[i].str; i++)
4886 if (strncmp (id, reloc_map[i].str, reloc_map[i].len) == 0)
4887 break;
4888
4889 input_line_pointer += reloc_map[i].len;
4890
4891 return reloc_map[i].reloc;
4892 }
4893 #endif
4894
4895 /* ARM V5 branch-link-exchange (argument parse) for BLX(1) only.
4896 Expects inst.instruction is set for BLX(1).
4897 Note: this is cloned from do_branch, and the reloc changed to be a
4898 new one that can cope with setting one extra bit (the H bit). */
4899
4900 static void
4901 do_branch25 (char * str)
4902 {
4903 if (my_get_expression (& inst.reloc.exp, & str))
4904 return;
4905
4906 #ifdef OBJ_ELF
4907 {
4908 char * save_in;
4909
4910 /* ScottB: February 5, 1998 */
4911 /* Check to see of PLT32 reloc required for the instruction. */
4912
4913 /* arm_parse_reloc() works on input_line_pointer.
4914 We actually want to parse the operands to the branch instruction
4915 passed in 'str'. Save the input pointer and restore it later. */
4916 save_in = input_line_pointer;
4917 input_line_pointer = str;
4918
4919 if (inst.reloc.exp.X_op == O_symbol
4920 && *str == '('
4921 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
4922 {
4923 inst.reloc.type = BFD_RELOC_ARM_PLT32;
4924 inst.reloc.pc_rel = 0;
4925 /* Modify str to point to after parsed operands, otherwise
4926 end_of_line() will complain about the (PLT) left in str. */
4927 str = input_line_pointer;
4928 }
4929 else
4930 {
4931 inst.reloc.type = BFD_RELOC_ARM_PCREL_BLX;
4932 inst.reloc.pc_rel = 1;
4933 }
4934
4935 input_line_pointer = save_in;
4936 }
4937 #else
4938 inst.reloc.type = BFD_RELOC_ARM_PCREL_BLX;
4939 inst.reloc.pc_rel = 1;
4940 #endif /* OBJ_ELF */
4941
4942 end_of_line (str);
4943 }
4944
4945 /* ARM V5 branch-link-exchange instruction (argument parse)
4946 BLX <target_addr> ie BLX(1)
4947 BLX{<condition>} <Rm> ie BLX(2)
4948 Unfortunately, there are two different opcodes for this mnemonic.
4949 So, the insns[].value is not used, and the code here zaps values
4950 into inst.instruction.
4951 Also, the <target_addr> can be 25 bits, hence has its own reloc. */
4952
4953 static void
4954 do_blx (char * str)
4955 {
4956 char * mystr = str;
4957 int rm;
4958
4959 skip_whitespace (mystr);
4960 rm = reg_required_here (& mystr, 0);
4961
4962 /* The above may set inst.error. Ignore his opinion. */
4963 inst.error = 0;
4964
4965 if (rm != FAIL)
4966 {
4967 /* Arg is a register.
4968 Use the condition code our caller put in inst.instruction.
4969 Pass ourselves off as a BX with a funny opcode. */
4970 inst.instruction |= 0x012fff30;
4971 do_bx (str);
4972 }
4973 else
4974 {
4975 /* This must be is BLX <target address>, no condition allowed. */
4976 if (inst.instruction != COND_ALWAYS)
4977 {
4978 inst.error = BAD_COND;
4979 return;
4980 }
4981
4982 inst.instruction = 0xfafffffe;
4983
4984 /* Process like a B/BL, but with a different reloc.
4985 Note that B/BL expecte fffffe, not 0, offset in the opcode table. */
4986 do_branch25 (str);
4987 }
4988 }
4989
4990 /* ARM V5 Thumb BLX (argument parse)
4991 BLX <target_addr> which is BLX(1)
4992 BLX <Rm> which is BLX(2)
4993 Unfortunately, there are two different opcodes for this mnemonic.
4994 So, the tinsns[].value is not used, and the code here zaps values
4995 into inst.instruction. */
4996
4997 static void
4998 do_t_blx (char * str)
4999 {
5000 char * mystr = str;
5001 int rm;
5002
5003 skip_whitespace (mystr);
5004 inst.instruction = 0x4780;
5005
5006 /* Note that this call is to the ARM register recognizer. BLX(2)
5007 uses the ARM register space, not the Thumb one, so a call to
5008 thumb_reg() would be wrong. */
5009 rm = reg_required_here (& mystr, 3);
5010 inst.error = 0;
5011
5012 if (rm != FAIL)
5013 {
5014 /* It's BLX(2). The .instruction was zapped with rm & is final. */
5015 inst.size = 2;
5016 }
5017 else
5018 {
5019 /* No ARM register. This must be BLX(1). Change the .instruction. */
5020 inst.instruction = 0xf7ffeffe;
5021 inst.size = 4;
5022
5023 if (my_get_expression (& inst.reloc.exp, & mystr))
5024 return;
5025
5026 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BLX;
5027 inst.reloc.pc_rel = 1;
5028 }
5029
5030 end_of_line (mystr);
5031 }
5032
5033 /* ARM V5 breakpoint instruction (argument parse)
5034 BKPT <16 bit unsigned immediate>
5035 Instruction is not conditional.
5036 The bit pattern given in insns[] has the COND_ALWAYS condition,
5037 and it is an error if the caller tried to override that. */
5038
5039 static void
5040 do_bkpt (char * str)
5041 {
5042 expressionS expr;
5043 unsigned long number;
5044
5045 skip_whitespace (str);
5046
5047 /* Allow optional leading '#'. */
5048 if (is_immediate_prefix (* str))
5049 str++;
5050
5051 memset (& expr, '\0', sizeof (expr));
5052
5053 if (my_get_expression (& expr, & str)
5054 || (expr.X_op != O_constant
5055 /* As a convenience we allow 'bkpt' without an operand. */
5056 && expr.X_op != O_absent))
5057 {
5058 inst.error = _("bad expression");
5059 return;
5060 }
5061
5062 number = expr.X_add_number;
5063
5064 /* Check it fits a 16 bit unsigned. */
5065 if (number != (number & 0xffff))
5066 {
5067 inst.error = _("immediate value out of range");
5068 return;
5069 }
5070
5071 /* Top 12 of 16 bits to bits 19:8. */
5072 inst.instruction |= (number & 0xfff0) << 4;
5073
5074 /* Bottom 4 of 16 bits to bits 3:0. */
5075 inst.instruction |= number & 0xf;
5076
5077 end_of_line (str);
5078 }
5079
5080 /* THUMB CPS instruction (argument parse). */
5081
5082 static void
5083 do_t_cps (char * str)
5084 {
5085 do_cps_flags (&str, /*thumb_p=*/1);
5086 end_of_line (str);
5087 }
5088
5089 /* Parse and validate that a register is of the right form, this saves
5090 repeated checking of this information in many similar cases.
5091 Unlike the 32-bit case we do not insert the register into the opcode
5092 here, since the position is often unknown until the full instruction
5093 has been parsed. */
5094
5095 static int
5096 thumb_reg (char ** strp, int hi_lo)
5097 {
5098 int reg;
5099
5100 if ((reg = reg_required_here (strp, -1)) == FAIL)
5101 return FAIL;
5102
5103 switch (hi_lo)
5104 {
5105 case THUMB_REG_LO:
5106 if (reg > 7)
5107 {
5108 inst.error = _("lo register required");
5109 return FAIL;
5110 }
5111 break;
5112
5113 case THUMB_REG_HI:
5114 if (reg < 8)
5115 {
5116 inst.error = _("hi register required");
5117 return FAIL;
5118 }
5119 break;
5120
5121 default:
5122 break;
5123 }
5124
5125 return reg;
5126 }
5127
5128 static void
5129 thumb_mov_compare (char * str, int move)
5130 {
5131 int Rd, Rs = FAIL;
5132
5133 skip_whitespace (str);
5134
5135 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
5136 || skip_past_comma (&str) == FAIL)
5137 {
5138 if (! inst.error)
5139 inst.error = BAD_ARGS;
5140 return;
5141 }
5142
5143 if (move != THUMB_CPY && is_immediate_prefix (*str))
5144 {
5145 str++;
5146 if (my_get_expression (&inst.reloc.exp, &str))
5147 return;
5148 }
5149 else if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
5150 return;
5151
5152 if (Rs != FAIL)
5153 {
5154 if (move != THUMB_CPY && Rs < 8 && Rd < 8)
5155 {
5156 if (move == THUMB_MOVE)
5157 /* A move of two lowregs is encoded as ADD Rd, Rs, #0
5158 since a MOV instruction produces unpredictable results. */
5159 inst.instruction = T_OPCODE_ADD_I3;
5160 else
5161 inst.instruction = T_OPCODE_CMP_LR;
5162 inst.instruction |= Rd | (Rs << 3);
5163 }
5164 else
5165 {
5166 if (move == THUMB_MOVE)
5167 inst.instruction = T_OPCODE_MOV_HR;
5168 else if (move != THUMB_CPY)
5169 inst.instruction = T_OPCODE_CMP_HR;
5170
5171 if (Rd > 7)
5172 inst.instruction |= THUMB_H1;
5173
5174 if (Rs > 7)
5175 inst.instruction |= THUMB_H2;
5176
5177 inst.instruction |= (Rd & 7) | ((Rs & 7) << 3);
5178 }
5179 }
5180 else
5181 {
5182 if (Rd > 7)
5183 {
5184 inst.error = _("only lo regs allowed with immediate");
5185 return;
5186 }
5187
5188 if (move == THUMB_MOVE)
5189 inst.instruction = T_OPCODE_MOV_I8;
5190 else
5191 inst.instruction = T_OPCODE_CMP_I8;
5192
5193 inst.instruction |= Rd << 8;
5194
5195 if (inst.reloc.exp.X_op != O_constant)
5196 inst.reloc.type = BFD_RELOC_ARM_THUMB_IMM;
5197 else
5198 {
5199 unsigned value = inst.reloc.exp.X_add_number;
5200
5201 if (value > 255)
5202 {
5203 inst.error = _("invalid immediate");
5204 return;
5205 }
5206
5207 inst.instruction |= value;
5208 }
5209 }
5210
5211 end_of_line (str);
5212 }
5213
5214 /* THUMB CPY instruction (argument parse). */
5215
5216 static void
5217 do_t_cpy (char * str)
5218 {
5219 thumb_mov_compare (str, THUMB_CPY);
5220 }
5221
5222 /* THUMB SETEND instruction (argument parse). */
5223
5224 static void
5225 do_t_setend (char * str)
5226 {
5227 if (do_endian_specifier (str))
5228 inst.instruction |= 0x8;
5229 }
5230
5231 /* Parse INSN_TYPE insn STR having a possible IMMEDIATE_SIZE immediate. */
5232
5233 static unsigned long
5234 check_iwmmxt_insn (char * str,
5235 enum iwmmxt_insn_type insn_type,
5236 int immediate_size)
5237 {
5238 int reg = 0;
5239 const char * inst_error;
5240 expressionS expr;
5241 unsigned long number;
5242
5243 inst_error = inst.error;
5244 if (!inst.error)
5245 inst.error = BAD_ARGS;
5246 skip_whitespace (str);
5247
5248 switch (insn_type)
5249 {
5250 case check_rd:
5251 if ((reg = reg_required_here (&str, 12)) == FAIL)
5252 return FAIL;
5253 break;
5254
5255 case check_wr:
5256 if ((wreg_required_here (&str, 0, IWMMXT_REG_WR)) == FAIL)
5257 return FAIL;
5258 break;
5259
5260 case check_wrwr:
5261 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
5262 || skip_past_comma (&str) == FAIL
5263 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL))
5264 return FAIL;
5265 break;
5266
5267 case check_wrwrwr:
5268 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
5269 || skip_past_comma (&str) == FAIL
5270 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5271 || skip_past_comma (&str) == FAIL
5272 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL))
5273 return FAIL;
5274 break;
5275
5276 case check_wrwrwcg:
5277 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
5278 || skip_past_comma (&str) == FAIL
5279 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5280 || skip_past_comma (&str) == FAIL
5281 || wreg_required_here (&str, 0, IWMMXT_REG_WCG) == FAIL))
5282 return FAIL;
5283 break;
5284
5285 case check_tbcst:
5286 if ((wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5287 || skip_past_comma (&str) == FAIL
5288 || reg_required_here (&str, 12) == FAIL))
5289 return FAIL;
5290 break;
5291
5292 case check_tmovmsk:
5293 if ((reg_required_here (&str, 12) == FAIL
5294 || skip_past_comma (&str) == FAIL
5295 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL))
5296 return FAIL;
5297 break;
5298
5299 case check_tmia:
5300 if ((wreg_required_here (&str, 5, IWMMXT_REG_WR) == FAIL
5301 || skip_past_comma (&str) == FAIL
5302 || reg_required_here (&str, 0) == FAIL
5303 || skip_past_comma (&str) == FAIL
5304 || reg_required_here (&str, 12) == FAIL))
5305 return FAIL;
5306 break;
5307
5308 case check_tmcrr:
5309 if ((wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL
5310 || skip_past_comma (&str) == FAIL
5311 || reg_required_here (&str, 12) == FAIL
5312 || skip_past_comma (&str) == FAIL
5313 || reg_required_here (&str, 16) == FAIL))
5314 return FAIL;
5315 break;
5316
5317 case check_tmrrc:
5318 if ((reg_required_here (&str, 12) == FAIL
5319 || skip_past_comma (&str) == FAIL
5320 || reg_required_here (&str, 16) == FAIL
5321 || skip_past_comma (&str) == FAIL
5322 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL))
5323 return FAIL;
5324 break;
5325
5326 case check_tmcr:
5327 if ((wreg_required_here (&str, 16, IWMMXT_REG_WC) == FAIL
5328 || skip_past_comma (&str) == FAIL
5329 || reg_required_here (&str, 12) == FAIL))
5330 return FAIL;
5331 break;
5332
5333 case check_tmrc:
5334 if ((reg_required_here (&str, 12) == FAIL
5335 || skip_past_comma (&str) == FAIL
5336 || wreg_required_here (&str, 16, IWMMXT_REG_WC) == FAIL))
5337 return FAIL;
5338 break;
5339
5340 case check_tinsr:
5341 if ((wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5342 || skip_past_comma (&str) == FAIL
5343 || reg_required_here (&str, 12) == FAIL
5344 || skip_past_comma (&str) == FAIL))
5345 return FAIL;
5346 break;
5347
5348 case check_textrc:
5349 if ((reg_required_here (&str, 12) == FAIL
5350 || skip_past_comma (&str) == FAIL))
5351 return FAIL;
5352 break;
5353
5354 case check_waligni:
5355 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
5356 || skip_past_comma (&str) == FAIL
5357 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5358 || skip_past_comma (&str) == FAIL
5359 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL
5360 || skip_past_comma (&str) == FAIL))
5361 return FAIL;
5362 break;
5363
5364 case check_textrm:
5365 if ((reg_required_here (&str, 12) == FAIL
5366 || skip_past_comma (&str) == FAIL
5367 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5368 || skip_past_comma (&str) == FAIL))
5369 return FAIL;
5370 break;
5371
5372 case check_wshufh:
5373 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
5374 || skip_past_comma (&str) == FAIL
5375 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5376 || skip_past_comma (&str) == FAIL))
5377 return FAIL;
5378 break;
5379 }
5380
5381 if (immediate_size == 0)
5382 {
5383 end_of_line (str);
5384 inst.error = inst_error;
5385 return reg;
5386 }
5387 else
5388 {
5389 skip_whitespace (str);
5390
5391 /* Allow optional leading '#'. */
5392 if (is_immediate_prefix (* str))
5393 str++;
5394
5395 memset (& expr, '\0', sizeof (expr));
5396
5397 if (my_get_expression (& expr, & str) || (expr.X_op != O_constant))
5398 {
5399 inst.error = _("bad or missing expression");
5400 return FAIL;
5401 }
5402
5403 number = expr.X_add_number;
5404
5405 if (number != (number & immediate_size))
5406 {
5407 inst.error = _("immediate value out of range");
5408 return FAIL;
5409 }
5410 end_of_line (str);
5411 inst.error = inst_error;
5412 return number;
5413 }
5414 }
5415
5416 static void
5417 do_iwmmxt_byte_addr (char * str)
5418 {
5419 int op = (inst.instruction & 0x300) >> 8;
5420 int reg;
5421
5422 inst.instruction &= ~0x300;
5423 inst.instruction |= (op & 1) << 22 | (op & 2) << 7;
5424
5425 skip_whitespace (str);
5426
5427 if ((reg = wreg_required_here (&str, 12, IWMMXT_REG_WR_OR_WC)) == FAIL
5428 || skip_past_comma (& str) == FAIL
5429 || cp_byte_address_required_here (&str) == FAIL)
5430 {
5431 if (! inst.error)
5432 inst.error = BAD_ARGS;
5433 }
5434 else
5435 end_of_line (str);
5436
5437 if (wc_register (reg))
5438 {
5439 as_bad (_("non-word size not supported with control register"));
5440 inst.instruction |= 0xf0000100;
5441 inst.instruction &= ~0x00400000;
5442 }
5443 }
5444
5445 static void
5446 do_iwmmxt_tandc (char * str)
5447 {
5448 int reg;
5449
5450 reg = check_iwmmxt_insn (str, check_rd, 0);
5451
5452 if (reg != REG_PC && !inst.error)
5453 inst.error = _("only r15 allowed here");
5454 }
5455
5456 static void
5457 do_iwmmxt_tbcst (char * str)
5458 {
5459 check_iwmmxt_insn (str, check_tbcst, 0);
5460 }
5461
5462 static void
5463 do_iwmmxt_textrc (char * str)
5464 {
5465 unsigned long number;
5466
5467 if ((number = check_iwmmxt_insn (str, check_textrc, 7)) == (unsigned long) FAIL)
5468 return;
5469
5470 inst.instruction |= number & 0x7;
5471 }
5472
5473 static void
5474 do_iwmmxt_textrm (char * str)
5475 {
5476 unsigned long number;
5477
5478 if ((number = check_iwmmxt_insn (str, check_textrm, 7)) == (unsigned long) FAIL)
5479 return;
5480
5481 inst.instruction |= number & 0x7;
5482 }
5483
5484 static void
5485 do_iwmmxt_tinsr (char * str)
5486 {
5487 unsigned long number;
5488
5489 if ((number = check_iwmmxt_insn (str, check_tinsr, 7)) == (unsigned long) FAIL)
5490 return;
5491
5492 inst.instruction |= number & 0x7;
5493 }
5494
5495 static void
5496 do_iwmmxt_tmcr (char * str)
5497 {
5498 check_iwmmxt_insn (str, check_tmcr, 0);
5499 }
5500
5501 static void
5502 do_iwmmxt_tmcrr (char * str)
5503 {
5504 check_iwmmxt_insn (str, check_tmcrr, 0);
5505 }
5506
5507 static void
5508 do_iwmmxt_tmia (char * str)
5509 {
5510 check_iwmmxt_insn (str, check_tmia, 0);
5511 }
5512
5513 static void
5514 do_iwmmxt_tmovmsk (char * str)
5515 {
5516 check_iwmmxt_insn (str, check_tmovmsk, 0);
5517 }
5518
5519 static void
5520 do_iwmmxt_tmrc (char * str)
5521 {
5522 check_iwmmxt_insn (str, check_tmrc, 0);
5523 }
5524
5525 static void
5526 do_iwmmxt_tmrrc (char * str)
5527 {
5528 check_iwmmxt_insn (str, check_tmrrc, 0);
5529 }
5530
5531 static void
5532 do_iwmmxt_torc (char * str)
5533 {
5534 check_iwmmxt_insn (str, check_rd, 0);
5535 }
5536
5537 static void
5538 do_iwmmxt_waligni (char * str)
5539 {
5540 unsigned long number;
5541
5542 if ((number = check_iwmmxt_insn (str, check_waligni, 7)) == (unsigned long) FAIL)
5543 return;
5544
5545 inst.instruction |= ((number & 0x7) << 20);
5546 }
5547
5548 static void
5549 do_iwmmxt_wmov (char * str)
5550 {
5551 if (check_iwmmxt_insn (str, check_wrwr, 0) == (unsigned long) FAIL)
5552 return;
5553
5554 inst.instruction |= ((inst.instruction >> 16) & 0xf);
5555 }
5556
5557 static void
5558 do_iwmmxt_word_addr (char * str)
5559 {
5560 int op = (inst.instruction & 0x300) >> 8;
5561 int reg;
5562
5563 inst.instruction &= ~0x300;
5564 inst.instruction |= (op & 1) << 22 | (op & 2) << 7;
5565
5566 skip_whitespace (str);
5567
5568 if ((reg = wreg_required_here (&str, 12, IWMMXT_REG_WR_OR_WC)) == FAIL
5569 || skip_past_comma (& str) == FAIL
5570 || cp_address_required_here (& str, CP_WB_OK) == FAIL)
5571 {
5572 if (! inst.error)
5573 inst.error = BAD_ARGS;
5574 }
5575 else
5576 end_of_line (str);
5577
5578 if (wc_register (reg))
5579 {
5580 if ((inst.instruction & COND_MASK) != COND_ALWAYS)
5581 as_bad (_("conditional execution not supported with control register"));
5582 if (op != 2)
5583 as_bad (_("non-word size not supported with control register"));
5584 inst.instruction |= 0xf0000100;
5585 inst.instruction &= ~0x00400000;
5586 }
5587 }
5588
5589 static void
5590 do_iwmmxt_wrwr (char * str)
5591 {
5592 check_iwmmxt_insn (str, check_wrwr, 0);
5593 }
5594
5595 static void
5596 do_iwmmxt_wrwrwcg (char * str)
5597 {
5598 check_iwmmxt_insn (str, check_wrwrwcg, 0);
5599 }
5600
5601 static void
5602 do_iwmmxt_wrwrwr (char * str)
5603 {
5604 check_iwmmxt_insn (str, check_wrwrwr, 0);
5605 }
5606
5607 static void
5608 do_iwmmxt_wshufh (char * str)
5609 {
5610 unsigned long number;
5611
5612 if ((number = check_iwmmxt_insn (str, check_wshufh, 0xff)) == (unsigned long) FAIL)
5613 return;
5614
5615 inst.instruction |= ((number & 0xf0) << 16) | (number & 0xf);
5616 }
5617
5618 static void
5619 do_iwmmxt_wzero (char * str)
5620 {
5621 if (check_iwmmxt_insn (str, check_wr, 0) == (unsigned long) FAIL)
5622 return;
5623
5624 inst.instruction |= ((inst.instruction & 0xf) << 12) | ((inst.instruction & 0xf) << 16);
5625 }
5626
5627 /* Xscale multiply-accumulate (argument parse)
5628 MIAcc acc0,Rm,Rs
5629 MIAPHcc acc0,Rm,Rs
5630 MIAxycc acc0,Rm,Rs. */
5631
5632 static void
5633 do_xsc_mia (char * str)
5634 {
5635 int rs;
5636 int rm;
5637
5638 if (accum0_required_here (& str) == FAIL)
5639 inst.error = ERR_NO_ACCUM;
5640
5641 else if (skip_past_comma (& str) == FAIL
5642 || (rm = reg_required_here (& str, 0)) == FAIL)
5643 inst.error = BAD_ARGS;
5644
5645 else if (skip_past_comma (& str) == FAIL
5646 || (rs = reg_required_here (& str, 12)) == FAIL)
5647 inst.error = BAD_ARGS;
5648
5649 /* inst.instruction has now been zapped with both rm and rs. */
5650 else if (rm == REG_PC || rs == REG_PC)
5651 inst.error = BAD_PC; /* Undefined result if rm or rs is R15. */
5652
5653 else
5654 end_of_line (str);
5655 }
5656
5657 /* Xscale move-accumulator-register (argument parse)
5658
5659 MARcc acc0,RdLo,RdHi. */
5660
5661 static void
5662 do_xsc_mar (char * str)
5663 {
5664 int rdlo, rdhi;
5665
5666 if (accum0_required_here (& str) == FAIL)
5667 inst.error = ERR_NO_ACCUM;
5668
5669 else if (skip_past_comma (& str) == FAIL
5670 || (rdlo = reg_required_here (& str, 12)) == FAIL)
5671 inst.error = BAD_ARGS;
5672
5673 else if (skip_past_comma (& str) == FAIL
5674 || (rdhi = reg_required_here (& str, 16)) == FAIL)
5675 inst.error = BAD_ARGS;
5676
5677 /* inst.instruction has now been zapped with both rdlo and rdhi. */
5678 else if (rdlo == REG_PC || rdhi == REG_PC)
5679 inst.error = BAD_PC; /* Undefined result if rdlo or rdhi is R15. */
5680
5681 else
5682 end_of_line (str);
5683 }
5684
5685 /* Xscale move-register-accumulator (argument parse)
5686
5687 MRAcc RdLo,RdHi,acc0. */
5688
5689 static void
5690 do_xsc_mra (char * str)
5691 {
5692 int rdlo;
5693 int rdhi;
5694
5695 skip_whitespace (str);
5696
5697 if ((rdlo = reg_required_here (& str, 12)) == FAIL)
5698 inst.error = BAD_ARGS;
5699
5700 else if (skip_past_comma (& str) == FAIL
5701 || (rdhi = reg_required_here (& str, 16)) == FAIL)
5702 inst.error = BAD_ARGS;
5703
5704 else if (skip_past_comma (& str) == FAIL
5705 || accum0_required_here (& str) == FAIL)
5706 inst.error = ERR_NO_ACCUM;
5707
5708 /* inst.instruction has now been zapped with both rdlo and rdhi. */
5709 else if (rdlo == rdhi)
5710 inst.error = BAD_ARGS; /* Undefined result if 2 writes to same reg. */
5711
5712 else if (rdlo == REG_PC || rdhi == REG_PC)
5713 inst.error = BAD_PC; /* Undefined result if rdlo or rdhi is R15. */
5714 else
5715 end_of_line (str);
5716 }
5717
5718 static int
5719 ldst_extend (char ** str)
5720 {
5721 int add = INDEX_UP;
5722
5723 switch (**str)
5724 {
5725 case '#':
5726 case '$':
5727 (*str)++;
5728 if (my_get_expression (& inst.reloc.exp, str))
5729 return FAIL;
5730
5731 if (inst.reloc.exp.X_op == O_constant)
5732 {
5733 int value = inst.reloc.exp.X_add_number;
5734
5735 if (value < -4095 || value > 4095)
5736 {
5737 inst.error = _("address offset too large");
5738 return FAIL;
5739 }
5740
5741 if (value < 0)
5742 {
5743 value = -value;
5744 add = 0;
5745 }
5746
5747 inst.instruction |= add | value;
5748 }
5749 else
5750 {
5751 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
5752 inst.reloc.pc_rel = 0;
5753 }
5754 return SUCCESS;
5755
5756 case '-':
5757 add = 0;
5758 /* Fall through. */
5759
5760 case '+':
5761 (*str)++;
5762 /* Fall through. */
5763
5764 default:
5765 if (reg_required_here (str, 0) == FAIL)
5766 return FAIL;
5767
5768 inst.instruction |= add | OFFSET_REG;
5769 if (skip_past_comma (str) == SUCCESS)
5770 return decode_shift (str, SHIFT_IMMEDIATE);
5771
5772 return SUCCESS;
5773 }
5774 }
5775
5776 /* ARMv5TE: Preload-Cache
5777
5778 PLD <addr_mode>
5779
5780 Syntactically, like LDR with B=1, W=0, L=1. */
5781
5782 static void
5783 do_pld (char * str)
5784 {
5785 int rd;
5786
5787 skip_whitespace (str);
5788
5789 if (* str != '[')
5790 {
5791 inst.error = _("'[' expected after PLD mnemonic");
5792 return;
5793 }
5794
5795 ++str;
5796 skip_whitespace (str);
5797
5798 if ((rd = reg_required_here (& str, 16)) == FAIL)
5799 return;
5800
5801 skip_whitespace (str);
5802
5803 if (*str == ']')
5804 {
5805 /* [Rn], ... ? */
5806 ++str;
5807 skip_whitespace (str);
5808
5809 /* Post-indexed addressing is not allowed with PLD. */
5810 if (skip_past_comma (&str) == SUCCESS)
5811 {
5812 inst.error
5813 = _("post-indexed expression used in preload instruction");
5814 return;
5815 }
5816 else if (*str == '!') /* [Rn]! */
5817 {
5818 inst.error = _("writeback used in preload instruction");
5819 ++str;
5820 }
5821 else /* [Rn] */
5822 inst.instruction |= INDEX_UP | PRE_INDEX;
5823 }
5824 else /* [Rn, ...] */
5825 {
5826 if (skip_past_comma (& str) == FAIL)
5827 {
5828 inst.error = _("pre-indexed expression expected");
5829 return;
5830 }
5831
5832 if (ldst_extend (&str) == FAIL)
5833 return;
5834
5835 skip_whitespace (str);
5836
5837 if (* str != ']')
5838 {
5839 inst.error = _("missing ]");
5840 return;
5841 }
5842
5843 ++ str;
5844 skip_whitespace (str);
5845
5846 if (* str == '!') /* [Rn]! */
5847 {
5848 inst.error = _("writeback used in preload instruction");
5849 ++ str;
5850 }
5851
5852 inst.instruction |= PRE_INDEX;
5853 }
5854
5855 end_of_line (str);
5856 }
5857
5858 /* ARMv5TE load-consecutive (argument parse)
5859 Mode is like LDRH.
5860
5861 LDRccD R, mode
5862 STRccD R, mode. */
5863
5864 static void
5865 do_ldrd (char * str)
5866 {
5867 int rd;
5868 int rn;
5869
5870 skip_whitespace (str);
5871
5872 if ((rd = reg_required_here (& str, 12)) == FAIL)
5873 {
5874 inst.error = BAD_ARGS;
5875 return;
5876 }
5877
5878 if (skip_past_comma (& str) == FAIL
5879 || (rn = ld_mode_required_here (& str)) == FAIL)
5880 {
5881 if (!inst.error)
5882 inst.error = BAD_ARGS;
5883 return;
5884 }
5885
5886 /* inst.instruction has now been zapped with Rd and the addressing mode. */
5887 if (rd & 1) /* Unpredictable result if Rd is odd. */
5888 {
5889 inst.error = _("destination register must be even");
5890 return;
5891 }
5892
5893 if (rd == REG_LR)
5894 {
5895 inst.error = _("r14 not allowed here");
5896 return;
5897 }
5898
5899 if (((rd == rn) || (rd + 1 == rn))
5900 && ((inst.instruction & WRITE_BACK)
5901 || (!(inst.instruction & PRE_INDEX))))
5902 as_warn (_("pre/post-indexing used when modified address register is destination"));
5903
5904 /* For an index-register load, the index register must not overlap the
5905 destination (even if not write-back). */
5906 if ((inst.instruction & V4_STR_BIT) == 0
5907 && (inst.instruction & HWOFFSET_IMM) == 0)
5908 {
5909 int rm = inst.instruction & 0x0000000f;
5910
5911 if (rm == rd || (rm == rd + 1))
5912 as_warn (_("ldrd destination registers must not overlap index register"));
5913 }
5914
5915 end_of_line (str);
5916 }
5917
5918 /* Returns the index into fp_values of a floating point number,
5919 or -1 if not in the table. */
5920
5921 static int
5922 my_get_float_expression (char ** str)
5923 {
5924 LITTLENUM_TYPE words[MAX_LITTLENUMS];
5925 char * save_in;
5926 expressionS exp;
5927 int i;
5928 int j;
5929
5930 memset (words, 0, MAX_LITTLENUMS * sizeof (LITTLENUM_TYPE));
5931
5932 /* Look for a raw floating point number. */
5933 if ((save_in = atof_ieee (*str, 'x', words)) != NULL
5934 && is_end_of_line[(unsigned char) *save_in])
5935 {
5936 for (i = 0; i < NUM_FLOAT_VALS; i++)
5937 {
5938 for (j = 0; j < MAX_LITTLENUMS; j++)
5939 {
5940 if (words[j] != fp_values[i][j])
5941 break;
5942 }
5943
5944 if (j == MAX_LITTLENUMS)
5945 {
5946 *str = save_in;
5947 return i;
5948 }
5949 }
5950 }
5951
5952 /* Try and parse a more complex expression, this will probably fail
5953 unless the code uses a floating point prefix (eg "0f"). */
5954 save_in = input_line_pointer;
5955 input_line_pointer = *str;
5956 if (expression (&exp) == absolute_section
5957 && exp.X_op == O_big
5958 && exp.X_add_number < 0)
5959 {
5960 /* FIXME: 5 = X_PRECISION, should be #define'd where we can use it.
5961 Ditto for 15. */
5962 if (gen_to_words (words, 5, (long) 15) == 0)
5963 {
5964 for (i = 0; i < NUM_FLOAT_VALS; i++)
5965 {
5966 for (j = 0; j < MAX_LITTLENUMS; j++)
5967 {
5968 if (words[j] != fp_values[i][j])
5969 break;
5970 }
5971
5972 if (j == MAX_LITTLENUMS)
5973 {
5974 *str = input_line_pointer;
5975 input_line_pointer = save_in;
5976 return i;
5977 }
5978 }
5979 }
5980 }
5981
5982 *str = input_line_pointer;
5983 input_line_pointer = save_in;
5984 return -1;
5985 }
5986
5987 /* We handle all bad expressions here, so that we can report the faulty
5988 instruction in the error message. */
5989 void
5990 md_operand (expressionS * expr)
5991 {
5992 if (in_my_get_expression)
5993 {
5994 expr->X_op = O_illegal;
5995 if (inst.error == NULL)
5996 inst.error = _("bad expression");
5997 }
5998 }
5999
6000 /* Do those data_ops which can take a negative immediate constant
6001 by altering the instruction. A bit of a hack really.
6002 MOV <-> MVN
6003 AND <-> BIC
6004 ADC <-> SBC
6005 by inverting the second operand, and
6006 ADD <-> SUB
6007 CMP <-> CMN
6008 by negating the second operand. */
6009
6010 static int
6011 negate_data_op (unsigned long * instruction,
6012 unsigned long value)
6013 {
6014 int op, new_inst;
6015 unsigned long negated, inverted;
6016
6017 negated = validate_immediate (-value);
6018 inverted = validate_immediate (~value);
6019
6020 op = (*instruction >> DATA_OP_SHIFT) & 0xf;
6021 switch (op)
6022 {
6023 /* First negates. */
6024 case OPCODE_SUB: /* ADD <-> SUB */
6025 new_inst = OPCODE_ADD;
6026 value = negated;
6027 break;
6028
6029 case OPCODE_ADD:
6030 new_inst = OPCODE_SUB;
6031 value = negated;
6032 break;
6033
6034 case OPCODE_CMP: /* CMP <-> CMN */
6035 new_inst = OPCODE_CMN;
6036 value = negated;
6037 break;
6038
6039 case OPCODE_CMN:
6040 new_inst = OPCODE_CMP;
6041 value = negated;
6042 break;
6043
6044 /* Now Inverted ops. */
6045 case OPCODE_MOV: /* MOV <-> MVN */
6046 new_inst = OPCODE_MVN;
6047 value = inverted;
6048 break;
6049
6050 case OPCODE_MVN:
6051 new_inst = OPCODE_MOV;
6052 value = inverted;
6053 break;
6054
6055 case OPCODE_AND: /* AND <-> BIC */
6056 new_inst = OPCODE_BIC;
6057 value = inverted;
6058 break;
6059
6060 case OPCODE_BIC:
6061 new_inst = OPCODE_AND;
6062 value = inverted;
6063 break;
6064
6065 case OPCODE_ADC: /* ADC <-> SBC */
6066 new_inst = OPCODE_SBC;
6067 value = inverted;
6068 break;
6069
6070 case OPCODE_SBC:
6071 new_inst = OPCODE_ADC;
6072 value = inverted;
6073 break;
6074
6075 /* We cannot do anything. */
6076 default:
6077 return FAIL;
6078 }
6079
6080 if (value == (unsigned) FAIL)
6081 return FAIL;
6082
6083 *instruction &= OPCODE_MASK;
6084 *instruction |= new_inst << DATA_OP_SHIFT;
6085 return value;
6086 }
6087
6088 static int
6089 data_op2 (char ** str)
6090 {
6091 int value;
6092 expressionS expr;
6093
6094 skip_whitespace (* str);
6095
6096 if (reg_required_here (str, 0) != FAIL)
6097 {
6098 if (skip_past_comma (str) == SUCCESS)
6099 /* Shift operation on register. */
6100 return decode_shift (str, NO_SHIFT_RESTRICT);
6101
6102 return SUCCESS;
6103 }
6104 else
6105 {
6106 /* Immediate expression. */
6107 if (is_immediate_prefix (**str))
6108 {
6109 (*str)++;
6110 inst.error = NULL;
6111
6112 if (my_get_expression (&inst.reloc.exp, str))
6113 return FAIL;
6114
6115 if (inst.reloc.exp.X_add_symbol)
6116 {
6117 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
6118 inst.reloc.pc_rel = 0;
6119 }
6120 else
6121 {
6122 if (skip_past_comma (str) == SUCCESS)
6123 {
6124 /* #x, y -- ie explicit rotation by Y. */
6125 if (my_get_expression (&expr, str))
6126 return FAIL;
6127
6128 if (expr.X_op != O_constant)
6129 {
6130 inst.error = _("constant expression expected");
6131 return FAIL;
6132 }
6133
6134 /* Rotate must be a multiple of 2. */
6135 if (((unsigned) expr.X_add_number) > 30
6136 || (expr.X_add_number & 1) != 0
6137 || ((unsigned) inst.reloc.exp.X_add_number) > 255)
6138 {
6139 inst.error = _("invalid constant");
6140 return FAIL;
6141 }
6142 inst.instruction |= INST_IMMEDIATE;
6143 inst.instruction |= inst.reloc.exp.X_add_number;
6144 inst.instruction |= expr.X_add_number << 7;
6145 return SUCCESS;
6146 }
6147
6148 /* Implicit rotation, select a suitable one. */
6149 value = validate_immediate (inst.reloc.exp.X_add_number);
6150
6151 if (value == FAIL)
6152 {
6153 /* Can't be done. Perhaps the code reads something like
6154 "add Rd, Rn, #-n", where "sub Rd, Rn, #n" would be OK. */
6155 if ((value = negate_data_op (&inst.instruction,
6156 inst.reloc.exp.X_add_number))
6157 == FAIL)
6158 {
6159 inst.error = _("invalid constant");
6160 return FAIL;
6161 }
6162 }
6163
6164 inst.instruction |= value;
6165 }
6166
6167 inst.instruction |= INST_IMMEDIATE;
6168 return SUCCESS;
6169 }
6170
6171 (*str)++;
6172 inst.error = _("register or shift expression expected");
6173 return FAIL;
6174 }
6175 }
6176
6177 static int
6178 fp_op2 (char ** str)
6179 {
6180 skip_whitespace (* str);
6181
6182 if (fp_reg_required_here (str, 0) != FAIL)
6183 return SUCCESS;
6184 else
6185 {
6186 /* Immediate expression. */
6187 if (*((*str)++) == '#')
6188 {
6189 int i;
6190
6191 inst.error = NULL;
6192
6193 skip_whitespace (* str);
6194
6195 /* First try and match exact strings, this is to guarantee
6196 that some formats will work even for cross assembly. */
6197
6198 for (i = 0; fp_const[i]; i++)
6199 {
6200 if (strncmp (*str, fp_const[i], strlen (fp_const[i])) == 0)
6201 {
6202 char *start = *str;
6203
6204 *str += strlen (fp_const[i]);
6205 if (is_end_of_line[(unsigned char) **str])
6206 {
6207 inst.instruction |= i + 8;
6208 return SUCCESS;
6209 }
6210 *str = start;
6211 }
6212 }
6213
6214 /* Just because we didn't get a match doesn't mean that the
6215 constant isn't valid, just that it is in a format that we
6216 don't automatically recognize. Try parsing it with
6217 the standard expression routines. */
6218 if ((i = my_get_float_expression (str)) >= 0)
6219 {
6220 inst.instruction |= i + 8;
6221 return SUCCESS;
6222 }
6223
6224 inst.error = _("invalid floating point immediate expression");
6225 return FAIL;
6226 }
6227 inst.error =
6228 _("floating point register or immediate expression expected");
6229 return FAIL;
6230 }
6231 }
6232
6233 static void
6234 do_arit (char * str)
6235 {
6236 skip_whitespace (str);
6237
6238 if (reg_required_here (&str, 12) == FAIL
6239 || skip_past_comma (&str) == FAIL
6240 || reg_required_here (&str, 16) == FAIL
6241 || skip_past_comma (&str) == FAIL
6242 || data_op2 (&str) == FAIL)
6243 {
6244 if (!inst.error)
6245 inst.error = BAD_ARGS;
6246 return;
6247 }
6248
6249 end_of_line (str);
6250 }
6251
6252 static void
6253 do_adr (char * str)
6254 {
6255 /* This is a pseudo-op of the form "adr rd, label" to be converted
6256 into a relative address of the form "add rd, pc, #label-.-8". */
6257 skip_whitespace (str);
6258
6259 if (reg_required_here (&str, 12) == FAIL
6260 || skip_past_comma (&str) == FAIL
6261 || my_get_expression (&inst.reloc.exp, &str))
6262 {
6263 if (!inst.error)
6264 inst.error = BAD_ARGS;
6265 return;
6266 }
6267
6268 /* Frag hacking will turn this into a sub instruction if the offset turns
6269 out to be negative. */
6270 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
6271 #ifndef TE_WINCE
6272 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust. */
6273 #endif
6274 inst.reloc.pc_rel = 1;
6275
6276 end_of_line (str);
6277 }
6278
6279 static void
6280 do_adrl (char * str)
6281 {
6282 /* This is a pseudo-op of the form "adrl rd, label" to be converted
6283 into a relative address of the form:
6284 add rd, pc, #low(label-.-8)"
6285 add rd, rd, #high(label-.-8)" */
6286
6287 skip_whitespace (str);
6288
6289 if (reg_required_here (&str, 12) == FAIL
6290 || skip_past_comma (&str) == FAIL
6291 || my_get_expression (&inst.reloc.exp, &str))
6292 {
6293 if (!inst.error)
6294 inst.error = BAD_ARGS;
6295
6296 return;
6297 }
6298
6299 end_of_line (str);
6300 /* Frag hacking will turn this into a sub instruction if the offset turns
6301 out to be negative. */
6302 inst.reloc.type = BFD_RELOC_ARM_ADRL_IMMEDIATE;
6303 #ifndef TE_WINCE
6304 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust */
6305 #endif
6306 inst.reloc.pc_rel = 1;
6307 inst.size = INSN_SIZE * 2;
6308 }
6309
6310 static void
6311 do_cmp (char * str)
6312 {
6313 skip_whitespace (str);
6314
6315 if (reg_required_here (&str, 16) == FAIL)
6316 {
6317 if (!inst.error)
6318 inst.error = BAD_ARGS;
6319 return;
6320 }
6321
6322 if (skip_past_comma (&str) == FAIL
6323 || data_op2 (&str) == FAIL)
6324 {
6325 if (!inst.error)
6326 inst.error = BAD_ARGS;
6327 return;
6328 }
6329
6330 end_of_line (str);
6331 }
6332
6333 static void
6334 do_mov (char * str)
6335 {
6336 skip_whitespace (str);
6337
6338 if (reg_required_here (&str, 12) == FAIL)
6339 {
6340 if (!inst.error)
6341 inst.error = BAD_ARGS;
6342 return;
6343 }
6344
6345 if (skip_past_comma (&str) == FAIL
6346 || data_op2 (&str) == FAIL)
6347 {
6348 if (!inst.error)
6349 inst.error = BAD_ARGS;
6350 return;
6351 }
6352
6353 end_of_line (str);
6354 }
6355
6356 static void
6357 do_ldst (char * str)
6358 {
6359 int pre_inc = 0;
6360 int conflict_reg;
6361 int value;
6362
6363 skip_whitespace (str);
6364
6365 if ((conflict_reg = reg_required_here (&str, 12)) == FAIL)
6366 {
6367 if (!inst.error)
6368 inst.error = BAD_ARGS;
6369 return;
6370 }
6371
6372 if (skip_past_comma (&str) == FAIL)
6373 {
6374 inst.error = _("address expected");
6375 return;
6376 }
6377
6378 if (*str == '[')
6379 {
6380 int reg;
6381
6382 str++;
6383
6384 skip_whitespace (str);
6385
6386 if ((reg = reg_required_here (&str, 16)) == FAIL)
6387 return;
6388
6389 /* Conflicts can occur on stores as well as loads. */
6390 conflict_reg = (conflict_reg == reg);
6391
6392 skip_whitespace (str);
6393
6394 if (*str == ']')
6395 {
6396 str ++;
6397
6398 if (skip_past_comma (&str) == SUCCESS)
6399 {
6400 /* [Rn],... (post inc) */
6401 if (ldst_extend (&str) == FAIL)
6402 return;
6403 if (conflict_reg)
6404 as_warn (_("%s register same as write-back base"),
6405 ((inst.instruction & LOAD_BIT)
6406 ? _("destination") : _("source")));
6407 }
6408 else
6409 {
6410 /* [Rn] */
6411 skip_whitespace (str);
6412
6413 if (*str == '!')
6414 {
6415 if (conflict_reg)
6416 as_warn (_("%s register same as write-back base"),
6417 ((inst.instruction & LOAD_BIT)
6418 ? _("destination") : _("source")));
6419 str++;
6420 inst.instruction |= WRITE_BACK;
6421 }
6422
6423 inst.instruction |= INDEX_UP;
6424 pre_inc = 1;
6425 }
6426 }
6427 else
6428 {
6429 /* [Rn,...] */
6430 if (skip_past_comma (&str) == FAIL)
6431 {
6432 inst.error = _("pre-indexed expression expected");
6433 return;
6434 }
6435
6436 pre_inc = 1;
6437 if (ldst_extend (&str) == FAIL)
6438 return;
6439
6440 skip_whitespace (str);
6441
6442 if (*str++ != ']')
6443 {
6444 inst.error = _("missing ]");
6445 return;
6446 }
6447
6448 skip_whitespace (str);
6449
6450 if (*str == '!')
6451 {
6452 if (conflict_reg)
6453 as_warn (_("%s register same as write-back base"),
6454 ((inst.instruction & LOAD_BIT)
6455 ? _("destination") : _("source")));
6456 str++;
6457 inst.instruction |= WRITE_BACK;
6458 }
6459 }
6460 }
6461 else if (*str == '=')
6462 {
6463 if ((inst.instruction & LOAD_BIT) == 0)
6464 {
6465 inst.error = _("invalid pseudo operation");
6466 return;
6467 }
6468
6469 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
6470 str++;
6471
6472 skip_whitespace (str);
6473
6474 if (my_get_expression (&inst.reloc.exp, &str))
6475 return;
6476
6477 if (inst.reloc.exp.X_op != O_constant
6478 && inst.reloc.exp.X_op != O_symbol)
6479 {
6480 inst.error = _("constant expression expected");
6481 return;
6482 }
6483
6484 if (inst.reloc.exp.X_op == O_constant)
6485 {
6486 value = validate_immediate (inst.reloc.exp.X_add_number);
6487
6488 if (value != FAIL)
6489 {
6490 /* This can be done with a mov instruction. */
6491 inst.instruction &= LITERAL_MASK;
6492 inst.instruction |= (INST_IMMEDIATE
6493 | (OPCODE_MOV << DATA_OP_SHIFT));
6494 inst.instruction |= value & 0xfff;
6495 end_of_line (str);
6496 return;
6497 }
6498
6499 value = validate_immediate (~inst.reloc.exp.X_add_number);
6500
6501 if (value != FAIL)
6502 {
6503 /* This can be done with a mvn instruction. */
6504 inst.instruction &= LITERAL_MASK;
6505 inst.instruction |= (INST_IMMEDIATE
6506 | (OPCODE_MVN << DATA_OP_SHIFT));
6507 inst.instruction |= value & 0xfff;
6508 end_of_line (str);
6509 return;
6510 }
6511 }
6512
6513 /* Insert into literal pool. */
6514 if (add_to_lit_pool () == FAIL)
6515 {
6516 if (!inst.error)
6517 inst.error = _("literal pool insertion failed");
6518 return;
6519 }
6520
6521 /* Change the instruction exp to point to the pool. */
6522 inst.reloc.type = BFD_RELOC_ARM_LITERAL;
6523 inst.reloc.pc_rel = 1;
6524 inst.instruction |= (REG_PC << 16);
6525 pre_inc = 1;
6526 }
6527 else
6528 {
6529 if (my_get_expression (&inst.reloc.exp, &str))
6530 return;
6531
6532 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
6533 #ifndef TE_WINCE
6534 /* PC rel adjust. */
6535 inst.reloc.exp.X_add_number -= 8;
6536 #endif
6537 inst.reloc.pc_rel = 1;
6538 inst.instruction |= (REG_PC << 16);
6539 pre_inc = 1;
6540 }
6541
6542 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
6543 end_of_line (str);
6544 }
6545
6546 static void
6547 do_ldstt (char * str)
6548 {
6549 int conflict_reg;
6550
6551 skip_whitespace (str);
6552
6553 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
6554 {
6555 if (!inst.error)
6556 inst.error = BAD_ARGS;
6557 return;
6558 }
6559
6560 if (skip_past_comma (& str) == FAIL)
6561 {
6562 inst.error = _("address expected");
6563 return;
6564 }
6565
6566 if (*str == '[')
6567 {
6568 int reg;
6569
6570 str++;
6571
6572 skip_whitespace (str);
6573
6574 if ((reg = reg_required_here (&str, 16)) == FAIL)
6575 return;
6576
6577 /* ldrt/strt always use post-indexed addressing, so if the base is
6578 the same as Rd, we warn. */
6579 if (conflict_reg == reg)
6580 as_warn (_("%s register same as write-back base"),
6581 ((inst.instruction & LOAD_BIT)
6582 ? _("destination") : _("source")));
6583
6584 skip_whitespace (str);
6585
6586 if (*str == ']')
6587 {
6588 str ++;
6589
6590 if (skip_past_comma (&str) == SUCCESS)
6591 {
6592 /* [Rn],... (post inc) */
6593 if (ldst_extend (&str) == FAIL)
6594 return;
6595 }
6596 else
6597 {
6598 /* [Rn] */
6599 skip_whitespace (str);
6600
6601 /* Skip a write-back '!'. */
6602 if (*str == '!')
6603 str++;
6604
6605 inst.instruction |= INDEX_UP;
6606 }
6607 }
6608 else
6609 {
6610 inst.error = _("post-indexed expression expected");
6611 return;
6612 }
6613 }
6614 else
6615 {
6616 inst.error = _("post-indexed expression expected");
6617 return;
6618 }
6619
6620 end_of_line (str);
6621 }
6622
6623 /* Halfword and signed-byte load/store operations. */
6624
6625 static void
6626 do_ldstv4 (char * str)
6627 {
6628 int pre_inc = 0;
6629 int conflict_reg;
6630 int value;
6631
6632 skip_whitespace (str);
6633
6634 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
6635 {
6636 if (!inst.error)
6637 inst.error = BAD_ARGS;
6638 return;
6639 }
6640
6641 if (skip_past_comma (& str) == FAIL)
6642 {
6643 inst.error = _("address expected");
6644 return;
6645 }
6646
6647 if (*str == '[')
6648 {
6649 int reg;
6650
6651 str++;
6652
6653 skip_whitespace (str);
6654
6655 if ((reg = reg_required_here (&str, 16)) == FAIL)
6656 return;
6657
6658 /* Conflicts can occur on stores as well as loads. */
6659 conflict_reg = (conflict_reg == reg);
6660
6661 skip_whitespace (str);
6662
6663 if (*str == ']')
6664 {
6665 str ++;
6666
6667 if (skip_past_comma (&str) == SUCCESS)
6668 {
6669 /* [Rn],... (post inc) */
6670 if (ldst_extend_v4 (&str) == FAIL)
6671 return;
6672 if (conflict_reg)
6673 as_warn (_("%s register same as write-back base"),
6674 ((inst.instruction & LOAD_BIT)
6675 ? _("destination") : _("source")));
6676 }
6677 else
6678 {
6679 /* [Rn] */
6680 inst.instruction |= HWOFFSET_IMM;
6681
6682 skip_whitespace (str);
6683
6684 if (*str == '!')
6685 {
6686 if (conflict_reg)
6687 as_warn (_("%s register same as write-back base"),
6688 ((inst.instruction & LOAD_BIT)
6689 ? _("destination") : _("source")));
6690 str++;
6691 inst.instruction |= WRITE_BACK;
6692 }
6693
6694 inst.instruction |= INDEX_UP;
6695 pre_inc = 1;
6696 }
6697 }
6698 else
6699 {
6700 /* [Rn,...] */
6701 if (skip_past_comma (&str) == FAIL)
6702 {
6703 inst.error = _("pre-indexed expression expected");
6704 return;
6705 }
6706
6707 pre_inc = 1;
6708 if (ldst_extend_v4 (&str) == FAIL)
6709 return;
6710
6711 skip_whitespace (str);
6712
6713 if (*str++ != ']')
6714 {
6715 inst.error = _("missing ]");
6716 return;
6717 }
6718
6719 skip_whitespace (str);
6720
6721 if (*str == '!')
6722 {
6723 if (conflict_reg)
6724 as_warn (_("%s register same as write-back base"),
6725 ((inst.instruction & LOAD_BIT)
6726 ? _("destination") : _("source")));
6727 str++;
6728 inst.instruction |= WRITE_BACK;
6729 }
6730 }
6731 }
6732 else if (*str == '=')
6733 {
6734 if ((inst.instruction & LOAD_BIT) == 0)
6735 {
6736 inst.error = _("invalid pseudo operation");
6737 return;
6738 }
6739
6740 /* XXX Does this work correctly for half-word/byte ops? */
6741 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
6742 str++;
6743
6744 skip_whitespace (str);
6745
6746 if (my_get_expression (&inst.reloc.exp, &str))
6747 return;
6748
6749 if (inst.reloc.exp.X_op != O_constant
6750 && inst.reloc.exp.X_op != O_symbol)
6751 {
6752 inst.error = _("constant expression expected");
6753 return;
6754 }
6755
6756 if (inst.reloc.exp.X_op == O_constant)
6757 {
6758 value = validate_immediate (inst.reloc.exp.X_add_number);
6759
6760 if (value != FAIL)
6761 {
6762 /* This can be done with a mov instruction. */
6763 inst.instruction &= LITERAL_MASK;
6764 inst.instruction |= INST_IMMEDIATE | (OPCODE_MOV << DATA_OP_SHIFT);
6765 inst.instruction |= value & 0xfff;
6766 end_of_line (str);
6767 return;
6768 }
6769
6770 value = validate_immediate (~ inst.reloc.exp.X_add_number);
6771
6772 if (value != FAIL)
6773 {
6774 /* This can be done with a mvn instruction. */
6775 inst.instruction &= LITERAL_MASK;
6776 inst.instruction |= INST_IMMEDIATE | (OPCODE_MVN << DATA_OP_SHIFT);
6777 inst.instruction |= value & 0xfff;
6778 end_of_line (str);
6779 return;
6780 }
6781 }
6782
6783 /* Insert into literal pool. */
6784 if (add_to_lit_pool () == FAIL)
6785 {
6786 if (!inst.error)
6787 inst.error = _("literal pool insertion failed");
6788 return;
6789 }
6790
6791 /* Change the instruction exp to point to the pool. */
6792 inst.instruction |= HWOFFSET_IMM;
6793 inst.reloc.type = BFD_RELOC_ARM_HWLITERAL;
6794 inst.reloc.pc_rel = 1;
6795 inst.instruction |= (REG_PC << 16);
6796 pre_inc = 1;
6797 }
6798 else
6799 {
6800 if (my_get_expression (&inst.reloc.exp, &str))
6801 return;
6802
6803 inst.instruction |= HWOFFSET_IMM;
6804 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
6805 #ifndef TE_WINCE
6806 /* PC rel adjust. */
6807 inst.reloc.exp.X_add_number -= 8;
6808 #endif
6809 inst.reloc.pc_rel = 1;
6810 inst.instruction |= (REG_PC << 16);
6811 pre_inc = 1;
6812 }
6813
6814 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
6815 end_of_line (str);
6816 }
6817
6818 static void
6819 do_ldsttv4 (char * str)
6820 {
6821 int conflict_reg;
6822
6823 skip_whitespace (str);
6824
6825 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
6826 {
6827 if (!inst.error)
6828 inst.error = BAD_ARGS;
6829 return;
6830 }
6831
6832 if (skip_past_comma (& str) == FAIL)
6833 {
6834 inst.error = _("address expected");
6835 return;
6836 }
6837
6838 if (*str == '[')
6839 {
6840 int reg;
6841
6842 str++;
6843
6844 skip_whitespace (str);
6845
6846 if ((reg = reg_required_here (&str, 16)) == FAIL)
6847 return;
6848
6849 /* ldrt/strt always use post-indexed addressing, so if the base is
6850 the same as Rd, we warn. */
6851 if (conflict_reg == reg)
6852 as_warn (_("%s register same as write-back base"),
6853 ((inst.instruction & LOAD_BIT)
6854 ? _("destination") : _("source")));
6855
6856 skip_whitespace (str);
6857
6858 if (*str == ']')
6859 {
6860 str ++;
6861
6862 if (skip_past_comma (&str) == SUCCESS)
6863 {
6864 /* [Rn],... (post inc) */
6865 if (ldst_extend_v4 (&str) == FAIL)
6866 return;
6867 }
6868 else
6869 {
6870 /* [Rn] */
6871 skip_whitespace (str);
6872
6873 /* Skip a write-back '!'. */
6874 if (*str == '!')
6875 str++;
6876
6877 inst.instruction |= (INDEX_UP|HWOFFSET_IMM);
6878 }
6879 }
6880 else
6881 {
6882 inst.error = _("post-indexed expression expected");
6883 return;
6884 }
6885 }
6886 else
6887 {
6888 inst.error = _("post-indexed expression expected");
6889 return;
6890 }
6891
6892 end_of_line (str);
6893 }
6894
6895
6896 static long
6897 reg_list (char ** strp)
6898 {
6899 char * str = * strp;
6900 long range = 0;
6901 int another_range;
6902
6903 /* We come back here if we get ranges concatenated by '+' or '|'. */
6904 do
6905 {
6906 another_range = 0;
6907
6908 if (*str == '{')
6909 {
6910 int in_range = 0;
6911 int cur_reg = -1;
6912
6913 str++;
6914 do
6915 {
6916 int reg;
6917
6918 skip_whitespace (str);
6919
6920 if ((reg = reg_required_here (& str, -1)) == FAIL)
6921 return FAIL;
6922
6923 if (in_range)
6924 {
6925 int i;
6926
6927 if (reg <= cur_reg)
6928 {
6929 inst.error = _("bad range in register list");
6930 return FAIL;
6931 }
6932
6933 for (i = cur_reg + 1; i < reg; i++)
6934 {
6935 if (range & (1 << i))
6936 as_tsktsk
6937 (_("Warning: duplicated register (r%d) in register list"),
6938 i);
6939 else
6940 range |= 1 << i;
6941 }
6942 in_range = 0;
6943 }
6944
6945 if (range & (1 << reg))
6946 as_tsktsk (_("Warning: duplicated register (r%d) in register list"),
6947 reg);
6948 else if (reg <= cur_reg)
6949 as_tsktsk (_("Warning: register range not in ascending order"));
6950
6951 range |= 1 << reg;
6952 cur_reg = reg;
6953 }
6954 while (skip_past_comma (&str) != FAIL
6955 || (in_range = 1, *str++ == '-'));
6956 str--;
6957 skip_whitespace (str);
6958
6959 if (*str++ != '}')
6960 {
6961 inst.error = _("missing `}'");
6962 return FAIL;
6963 }
6964 }
6965 else
6966 {
6967 expressionS expr;
6968
6969 if (my_get_expression (&expr, &str))
6970 return FAIL;
6971
6972 if (expr.X_op == O_constant)
6973 {
6974 if (expr.X_add_number
6975 != (expr.X_add_number & 0x0000ffff))
6976 {
6977 inst.error = _("invalid register mask");
6978 return FAIL;
6979 }
6980
6981 if ((range & expr.X_add_number) != 0)
6982 {
6983 int regno = range & expr.X_add_number;
6984
6985 regno &= -regno;
6986 regno = (1 << regno) - 1;
6987 as_tsktsk
6988 (_("Warning: duplicated register (r%d) in register list"),
6989 regno);
6990 }
6991
6992 range |= expr.X_add_number;
6993 }
6994 else
6995 {
6996 if (inst.reloc.type != 0)
6997 {
6998 inst.error = _("expression too complex");
6999 return FAIL;
7000 }
7001
7002 memcpy (&inst.reloc.exp, &expr, sizeof (expressionS));
7003 inst.reloc.type = BFD_RELOC_ARM_MULTI;
7004 inst.reloc.pc_rel = 0;
7005 }
7006 }
7007
7008 skip_whitespace (str);
7009
7010 if (*str == '|' || *str == '+')
7011 {
7012 str++;
7013 another_range = 1;
7014 }
7015 }
7016 while (another_range);
7017
7018 *strp = str;
7019 return range;
7020 }
7021
7022 static void
7023 do_ldmstm (char * str)
7024 {
7025 int base_reg;
7026 long range;
7027
7028 skip_whitespace (str);
7029
7030 if ((base_reg = reg_required_here (&str, 16)) == FAIL)
7031 return;
7032
7033 if (base_reg == REG_PC)
7034 {
7035 inst.error = _("r15 not allowed as base register");
7036 return;
7037 }
7038
7039 skip_whitespace (str);
7040
7041 if (*str == '!')
7042 {
7043 inst.instruction |= WRITE_BACK;
7044 str++;
7045 }
7046
7047 if (skip_past_comma (&str) == FAIL
7048 || (range = reg_list (&str)) == FAIL)
7049 {
7050 if (! inst.error)
7051 inst.error = BAD_ARGS;
7052 return;
7053 }
7054
7055 if (*str == '^')
7056 {
7057 str++;
7058 inst.instruction |= LDM_TYPE_2_OR_3;
7059 }
7060
7061 if (inst.instruction & WRITE_BACK)
7062 {
7063 /* Check for unpredictable uses of writeback. */
7064 if (inst.instruction & LOAD_BIT)
7065 {
7066 /* Not allowed in LDM type 2. */
7067 if ((inst.instruction & LDM_TYPE_2_OR_3)
7068 && ((range & (1 << REG_PC)) == 0))
7069 as_warn (_("writeback of base register is UNPREDICTABLE"));
7070 /* Only allowed if base reg not in list for other types. */
7071 else if (range & (1 << base_reg))
7072 as_warn (_("writeback of base register when in register list is UNPREDICTABLE"));
7073 }
7074 else /* STM. */
7075 {
7076 /* Not allowed for type 2. */
7077 if (inst.instruction & LDM_TYPE_2_OR_3)
7078 as_warn (_("writeback of base register is UNPREDICTABLE"));
7079 /* Only allowed if base reg not in list, or first in list. */
7080 else if ((range & (1 << base_reg))
7081 && (range & ((1 << base_reg) - 1)))
7082 as_warn (_("if writeback register is in list, it must be the lowest reg in the list"));
7083 }
7084 }
7085
7086 inst.instruction |= range;
7087 end_of_line (str);
7088 }
7089
7090 static void
7091 do_smi (char * str)
7092 {
7093 skip_whitespace (str);
7094
7095 /* Allow optional leading '#'. */
7096 if (is_immediate_prefix (*str))
7097 str++;
7098
7099 if (my_get_expression (& inst.reloc.exp, & str))
7100 return;
7101
7102 inst.reloc.type = BFD_RELOC_ARM_SMI;
7103 inst.reloc.pc_rel = 0;
7104 end_of_line (str);
7105 }
7106
7107 static void
7108 do_swi (char * str)
7109 {
7110 skip_whitespace (str);
7111
7112 /* Allow optional leading '#'. */
7113 if (is_immediate_prefix (*str))
7114 str++;
7115
7116 if (my_get_expression (& inst.reloc.exp, & str))
7117 return;
7118
7119 inst.reloc.type = BFD_RELOC_ARM_SWI;
7120 inst.reloc.pc_rel = 0;
7121 end_of_line (str);
7122 }
7123
7124 static void
7125 do_swap (char * str)
7126 {
7127 int reg;
7128
7129 skip_whitespace (str);
7130
7131 if ((reg = reg_required_here (&str, 12)) == FAIL)
7132 return;
7133
7134 if (reg == REG_PC)
7135 {
7136 inst.error = _("r15 not allowed in swap");
7137 return;
7138 }
7139
7140 if (skip_past_comma (&str) == FAIL
7141 || (reg = reg_required_here (&str, 0)) == FAIL)
7142 {
7143 if (!inst.error)
7144 inst.error = BAD_ARGS;
7145 return;
7146 }
7147
7148 if (reg == REG_PC)
7149 {
7150 inst.error = _("r15 not allowed in swap");
7151 return;
7152 }
7153
7154 if (skip_past_comma (&str) == FAIL
7155 || *str++ != '[')
7156 {
7157 inst.error = BAD_ARGS;
7158 return;
7159 }
7160
7161 skip_whitespace (str);
7162
7163 if ((reg = reg_required_here (&str, 16)) == FAIL)
7164 return;
7165
7166 if (reg == REG_PC)
7167 {
7168 inst.error = BAD_PC;
7169 return;
7170 }
7171
7172 skip_whitespace (str);
7173
7174 if (*str++ != ']')
7175 {
7176 inst.error = _("missing ]");
7177 return;
7178 }
7179
7180 end_of_line (str);
7181 }
7182
7183 static void
7184 do_branch (char * str)
7185 {
7186 if (my_get_expression (&inst.reloc.exp, &str))
7187 return;
7188
7189 #ifdef OBJ_ELF
7190 {
7191 char * save_in;
7192
7193 /* ScottB: February 5, 1998 - Check to see of PLT32 reloc
7194 required for the instruction. */
7195
7196 /* arm_parse_reloc () works on input_line_pointer.
7197 We actually want to parse the operands to the branch instruction
7198 passed in 'str'. Save the input pointer and restore it later. */
7199 save_in = input_line_pointer;
7200 input_line_pointer = str;
7201 if (inst.reloc.exp.X_op == O_symbol
7202 && *str == '('
7203 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
7204 {
7205 inst.reloc.type = BFD_RELOC_ARM_PLT32;
7206 inst.reloc.pc_rel = 0;
7207 /* Modify str to point to after parsed operands, otherwise
7208 end_of_line() will complain about the (PLT) left in str. */
7209 str = input_line_pointer;
7210 }
7211 else
7212 {
7213 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
7214 inst.reloc.pc_rel = 1;
7215 }
7216 input_line_pointer = save_in;
7217 }
7218 #else
7219 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
7220 inst.reloc.pc_rel = 1;
7221 #endif /* OBJ_ELF */
7222
7223 end_of_line (str);
7224 }
7225
7226 static void
7227 do_cdp (char * str)
7228 {
7229 /* Co-processor data operation.
7230 Format: CDP{cond} CP#,<expr>,CRd,CRn,CRm{,<expr>} */
7231 skip_whitespace (str);
7232
7233 if (co_proc_number (&str) == FAIL)
7234 {
7235 if (!inst.error)
7236 inst.error = BAD_ARGS;
7237 return;
7238 }
7239
7240 if (skip_past_comma (&str) == FAIL
7241 || cp_opc_expr (&str, 20,4) == FAIL)
7242 {
7243 if (!inst.error)
7244 inst.error = BAD_ARGS;
7245 return;
7246 }
7247
7248 if (skip_past_comma (&str) == FAIL
7249 || cp_reg_required_here (&str, 12) == FAIL)
7250 {
7251 if (!inst.error)
7252 inst.error = BAD_ARGS;
7253 return;
7254 }
7255
7256 if (skip_past_comma (&str) == FAIL
7257 || cp_reg_required_here (&str, 16) == FAIL)
7258 {
7259 if (!inst.error)
7260 inst.error = BAD_ARGS;
7261 return;
7262 }
7263
7264 if (skip_past_comma (&str) == FAIL
7265 || cp_reg_required_here (&str, 0) == FAIL)
7266 {
7267 if (!inst.error)
7268 inst.error = BAD_ARGS;
7269 return;
7270 }
7271
7272 if (skip_past_comma (&str) == SUCCESS)
7273 {
7274 if (cp_opc_expr (&str, 5, 3) == FAIL)
7275 {
7276 if (!inst.error)
7277 inst.error = BAD_ARGS;
7278 return;
7279 }
7280 }
7281
7282 end_of_line (str);
7283 }
7284
7285 static void
7286 do_lstc (char * str)
7287 {
7288 /* Co-processor register load/store.
7289 Format: <LDC|STC{cond}[L] CP#,CRd,<address> */
7290
7291 skip_whitespace (str);
7292
7293 if (co_proc_number (&str) == FAIL)
7294 {
7295 if (!inst.error)
7296 inst.error = BAD_ARGS;
7297 return;
7298 }
7299
7300 if (skip_past_comma (&str) == FAIL
7301 || cp_reg_required_here (&str, 12) == FAIL)
7302 {
7303 if (!inst.error)
7304 inst.error = BAD_ARGS;
7305 return;
7306 }
7307
7308 if (skip_past_comma (&str) == FAIL
7309 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
7310 {
7311 if (! inst.error)
7312 inst.error = BAD_ARGS;
7313 return;
7314 }
7315
7316 end_of_line (str);
7317 }
7318
7319 static void
7320 do_co_reg (char * str)
7321 {
7322 /* Co-processor register transfer.
7323 Format: <MCR|MRC>{cond} CP#,<expr1>,Rd,CRn,CRm{,<expr2>} */
7324
7325 skip_whitespace (str);
7326
7327 if (co_proc_number (&str) == FAIL)
7328 {
7329 if (!inst.error)
7330 inst.error = BAD_ARGS;
7331 return;
7332 }
7333
7334 if (skip_past_comma (&str) == FAIL
7335 || cp_opc_expr (&str, 21, 3) == FAIL)
7336 {
7337 if (!inst.error)
7338 inst.error = BAD_ARGS;
7339 return;
7340 }
7341
7342 if (skip_past_comma (&str) == FAIL
7343 || reg_required_here (&str, 12) == FAIL)
7344 {
7345 if (!inst.error)
7346 inst.error = BAD_ARGS;
7347 return;
7348 }
7349
7350 if (skip_past_comma (&str) == FAIL
7351 || cp_reg_required_here (&str, 16) == FAIL)
7352 {
7353 if (!inst.error)
7354 inst.error = BAD_ARGS;
7355 return;
7356 }
7357
7358 if (skip_past_comma (&str) == FAIL
7359 || cp_reg_required_here (&str, 0) == FAIL)
7360 {
7361 if (!inst.error)
7362 inst.error = BAD_ARGS;
7363 return;
7364 }
7365
7366 if (skip_past_comma (&str) == SUCCESS)
7367 {
7368 if (cp_opc_expr (&str, 5, 3) == FAIL)
7369 {
7370 if (!inst.error)
7371 inst.error = BAD_ARGS;
7372 return;
7373 }
7374 }
7375
7376 end_of_line (str);
7377 }
7378
7379 static void
7380 do_fpa_ctrl (char * str)
7381 {
7382 /* FP control registers.
7383 Format: <WFS|RFS|WFC|RFC>{cond} Rn */
7384
7385 skip_whitespace (str);
7386
7387 if (reg_required_here (&str, 12) == FAIL)
7388 {
7389 if (!inst.error)
7390 inst.error = BAD_ARGS;
7391 return;
7392 }
7393
7394 end_of_line (str);
7395 }
7396
7397 static void
7398 do_fpa_ldst (char * str)
7399 {
7400 skip_whitespace (str);
7401
7402 if (fp_reg_required_here (&str, 12) == FAIL)
7403 {
7404 if (!inst.error)
7405 inst.error = BAD_ARGS;
7406 return;
7407 }
7408
7409 if (skip_past_comma (&str) == FAIL
7410 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
7411 {
7412 if (!inst.error)
7413 inst.error = BAD_ARGS;
7414 return;
7415 }
7416
7417 end_of_line (str);
7418 }
7419
7420 static void
7421 do_fpa_ldmstm (char * str)
7422 {
7423 int num_regs;
7424
7425 skip_whitespace (str);
7426
7427 if (fp_reg_required_here (&str, 12) == FAIL)
7428 {
7429 if (! inst.error)
7430 inst.error = BAD_ARGS;
7431 return;
7432 }
7433
7434 /* Get Number of registers to transfer. */
7435 if (skip_past_comma (&str) == FAIL
7436 || my_get_expression (&inst.reloc.exp, &str))
7437 {
7438 if (! inst.error)
7439 inst.error = _("constant expression expected");
7440 return;
7441 }
7442
7443 if (inst.reloc.exp.X_op != O_constant)
7444 {
7445 inst.error = _("constant value required for number of registers");
7446 return;
7447 }
7448
7449 num_regs = inst.reloc.exp.X_add_number;
7450
7451 if (num_regs < 1 || num_regs > 4)
7452 {
7453 inst.error = _("number of registers must be in the range [1:4]");
7454 return;
7455 }
7456
7457 switch (num_regs)
7458 {
7459 case 1:
7460 inst.instruction |= CP_T_X;
7461 break;
7462 case 2:
7463 inst.instruction |= CP_T_Y;
7464 break;
7465 case 3:
7466 inst.instruction |= CP_T_Y | CP_T_X;
7467 break;
7468 case 4:
7469 break;
7470 default:
7471 abort ();
7472 }
7473
7474 if (inst.instruction & (CP_T_Pre | CP_T_UD)) /* ea/fd format. */
7475 {
7476 int reg;
7477 int write_back;
7478 int offset;
7479
7480 /* The instruction specified "ea" or "fd", so we can only accept
7481 [Rn]{!}. The instruction does not really support stacking or
7482 unstacking, so we have to emulate these by setting appropriate
7483 bits and offsets. */
7484 if (skip_past_comma (&str) == FAIL
7485 || *str != '[')
7486 {
7487 if (! inst.error)
7488 inst.error = BAD_ARGS;
7489 return;
7490 }
7491
7492 str++;
7493 skip_whitespace (str);
7494
7495 if ((reg = reg_required_here (&str, 16)) == FAIL)
7496 return;
7497
7498 skip_whitespace (str);
7499
7500 if (*str != ']')
7501 {
7502 inst.error = BAD_ARGS;
7503 return;
7504 }
7505
7506 str++;
7507 if (*str == '!')
7508 {
7509 write_back = 1;
7510 str++;
7511 if (reg == REG_PC)
7512 {
7513 inst.error =
7514 _("r15 not allowed as base register with write-back");
7515 return;
7516 }
7517 }
7518 else
7519 write_back = 0;
7520
7521 if (inst.instruction & CP_T_Pre)
7522 {
7523 /* Pre-decrement. */
7524 offset = 3 * num_regs;
7525 if (write_back)
7526 inst.instruction |= CP_T_WB;
7527 }
7528 else
7529 {
7530 /* Post-increment. */
7531 if (write_back)
7532 {
7533 inst.instruction |= CP_T_WB;
7534 offset = 3 * num_regs;
7535 }
7536 else
7537 {
7538 /* No write-back, so convert this into a standard pre-increment
7539 instruction -- aesthetically more pleasing. */
7540 inst.instruction |= CP_T_Pre | CP_T_UD;
7541 offset = 0;
7542 }
7543 }
7544
7545 inst.instruction |= offset;
7546 }
7547 else if (skip_past_comma (&str) == FAIL
7548 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
7549 {
7550 if (! inst.error)
7551 inst.error = BAD_ARGS;
7552 return;
7553 }
7554
7555 end_of_line (str);
7556 }
7557
7558 static void
7559 do_fpa_dyadic (char * str)
7560 {
7561 skip_whitespace (str);
7562
7563 if (fp_reg_required_here (&str, 12) == FAIL)
7564 {
7565 if (! inst.error)
7566 inst.error = BAD_ARGS;
7567 return;
7568 }
7569
7570 if (skip_past_comma (&str) == FAIL
7571 || fp_reg_required_here (&str, 16) == FAIL)
7572 {
7573 if (! inst.error)
7574 inst.error = BAD_ARGS;
7575 return;
7576 }
7577
7578 if (skip_past_comma (&str) == FAIL
7579 || fp_op2 (&str) == FAIL)
7580 {
7581 if (! inst.error)
7582 inst.error = BAD_ARGS;
7583 return;
7584 }
7585
7586 end_of_line (str);
7587 }
7588
7589 static void
7590 do_fpa_monadic (char * str)
7591 {
7592 skip_whitespace (str);
7593
7594 if (fp_reg_required_here (&str, 12) == FAIL)
7595 {
7596 if (! inst.error)
7597 inst.error = BAD_ARGS;
7598 return;
7599 }
7600
7601 if (skip_past_comma (&str) == FAIL
7602 || fp_op2 (&str) == FAIL)
7603 {
7604 if (! inst.error)
7605 inst.error = BAD_ARGS;
7606 return;
7607 }
7608
7609 end_of_line (str);
7610 }
7611
7612 static void
7613 do_fpa_cmp (char * str)
7614 {
7615 skip_whitespace (str);
7616
7617 if (fp_reg_required_here (&str, 16) == FAIL)
7618 {
7619 if (! inst.error)
7620 inst.error = BAD_ARGS;
7621 return;
7622 }
7623
7624 if (skip_past_comma (&str) == FAIL
7625 || fp_op2 (&str) == FAIL)
7626 {
7627 if (! inst.error)
7628 inst.error = BAD_ARGS;
7629 return;
7630 }
7631
7632 end_of_line (str);
7633 }
7634
7635 static void
7636 do_fpa_from_reg (char * str)
7637 {
7638 skip_whitespace (str);
7639
7640 if (fp_reg_required_here (&str, 16) == FAIL)
7641 {
7642 if (! inst.error)
7643 inst.error = BAD_ARGS;
7644 return;
7645 }
7646
7647 if (skip_past_comma (&str) == FAIL
7648 || reg_required_here (&str, 12) == FAIL)
7649 {
7650 if (! inst.error)
7651 inst.error = BAD_ARGS;
7652 return;
7653 }
7654
7655 end_of_line (str);
7656 }
7657
7658 static void
7659 do_fpa_to_reg (char * str)
7660 {
7661 skip_whitespace (str);
7662
7663 if (reg_required_here (&str, 12) == FAIL)
7664 return;
7665
7666 if (skip_past_comma (&str) == FAIL
7667 || fp_reg_required_here (&str, 0) == FAIL)
7668 {
7669 if (! inst.error)
7670 inst.error = BAD_ARGS;
7671 return;
7672 }
7673
7674 end_of_line (str);
7675 }
7676
7677 /* Encode a VFP SP register number. */
7678
7679 static void
7680 vfp_sp_encode_reg (int reg, enum vfp_sp_reg_pos pos)
7681 {
7682 switch (pos)
7683 {
7684 case VFP_REG_Sd:
7685 inst.instruction |= ((reg >> 1) << 12) | ((reg & 1) << 22);
7686 break;
7687
7688 case VFP_REG_Sn:
7689 inst.instruction |= ((reg >> 1) << 16) | ((reg & 1) << 7);
7690 break;
7691
7692 case VFP_REG_Sm:
7693 inst.instruction |= ((reg >> 1) << 0) | ((reg & 1) << 5);
7694 break;
7695
7696 default:
7697 abort ();
7698 }
7699 }
7700
7701 static int
7702 vfp_sp_reg_required_here (char ** str,
7703 enum vfp_sp_reg_pos pos)
7704 {
7705 int reg;
7706 char * start = *str;
7707
7708 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_SN].htab)) != FAIL)
7709 {
7710 vfp_sp_encode_reg (reg, pos);
7711 return reg;
7712 }
7713
7714 /* In the few cases where we might be able to accept something else
7715 this error can be overridden. */
7716 inst.error = _(all_reg_maps[REG_TYPE_SN].expected);
7717
7718 /* Restore the start point. */
7719 *str = start;
7720 return FAIL;
7721 }
7722
7723 static int
7724 vfp_dp_reg_required_here (char ** str,
7725 enum vfp_dp_reg_pos pos)
7726 {
7727 int reg;
7728 char * start = *str;
7729
7730 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_DN].htab)) != FAIL)
7731 {
7732 switch (pos)
7733 {
7734 case VFP_REG_Dd:
7735 inst.instruction |= reg << 12;
7736 break;
7737
7738 case VFP_REG_Dn:
7739 inst.instruction |= reg << 16;
7740 break;
7741
7742 case VFP_REG_Dm:
7743 inst.instruction |= reg << 0;
7744 break;
7745
7746 default:
7747 abort ();
7748 }
7749 return reg;
7750 }
7751
7752 /* In the few cases where we might be able to accept something else
7753 this error can be overridden. */
7754 inst.error = _(all_reg_maps[REG_TYPE_DN].expected);
7755
7756 /* Restore the start point. */
7757 *str = start;
7758 return FAIL;
7759 }
7760
7761 static void
7762 do_vfp_sp_monadic (char * str)
7763 {
7764 skip_whitespace (str);
7765
7766 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
7767 return;
7768
7769 if (skip_past_comma (&str) == FAIL
7770 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
7771 {
7772 if (! inst.error)
7773 inst.error = BAD_ARGS;
7774 return;
7775 }
7776
7777 end_of_line (str);
7778 }
7779
7780 static void
7781 do_vfp_dp_monadic (char * str)
7782 {
7783 skip_whitespace (str);
7784
7785 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
7786 return;
7787
7788 if (skip_past_comma (&str) == FAIL
7789 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
7790 {
7791 if (! inst.error)
7792 inst.error = BAD_ARGS;
7793 return;
7794 }
7795
7796 end_of_line (str);
7797 }
7798
7799 static void
7800 do_vfp_sp_dyadic (char * str)
7801 {
7802 skip_whitespace (str);
7803
7804 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
7805 return;
7806
7807 if (skip_past_comma (&str) == FAIL
7808 || vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL
7809 || skip_past_comma (&str) == FAIL
7810 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
7811 {
7812 if (! inst.error)
7813 inst.error = BAD_ARGS;
7814 return;
7815 }
7816
7817 end_of_line (str);
7818 }
7819
7820 static void
7821 do_vfp_dp_dyadic (char * str)
7822 {
7823 skip_whitespace (str);
7824
7825 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
7826 return;
7827
7828 if (skip_past_comma (&str) == FAIL
7829 || vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL
7830 || skip_past_comma (&str) == FAIL
7831 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
7832 {
7833 if (! inst.error)
7834 inst.error = BAD_ARGS;
7835 return;
7836 }
7837
7838 end_of_line (str);
7839 }
7840
7841 static void
7842 do_vfp_reg_from_sp (char * str)
7843 {
7844 skip_whitespace (str);
7845
7846 if (reg_required_here (&str, 12) == FAIL)
7847 return;
7848
7849 if (skip_past_comma (&str) == FAIL
7850 || vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL)
7851 {
7852 if (! inst.error)
7853 inst.error = BAD_ARGS;
7854 return;
7855 }
7856
7857 end_of_line (str);
7858 }
7859
7860 /* Parse a VFP register list. If the string is invalid return FAIL.
7861 Otherwise return the number of registers, and set PBASE to the first
7862 register. Double precision registers are matched if DP is nonzero. */
7863
7864 static int
7865 vfp_parse_reg_list (char **str, int *pbase, int dp)
7866 {
7867 int base_reg;
7868 int new_base;
7869 int regtype;
7870 int max_regs;
7871 int count = 0;
7872 int warned = 0;
7873 unsigned long mask = 0;
7874 int i;
7875
7876 if (**str != '{')
7877 return FAIL;
7878
7879 (*str)++;
7880 skip_whitespace (*str);
7881
7882 if (dp)
7883 {
7884 regtype = REG_TYPE_DN;
7885 max_regs = 16;
7886 }
7887 else
7888 {
7889 regtype = REG_TYPE_SN;
7890 max_regs = 32;
7891 }
7892
7893 base_reg = max_regs;
7894
7895 do
7896 {
7897 new_base = arm_reg_parse (str, all_reg_maps[regtype].htab);
7898 if (new_base == FAIL)
7899 {
7900 inst.error = _(all_reg_maps[regtype].expected);
7901 return FAIL;
7902 }
7903
7904 if (new_base < base_reg)
7905 base_reg = new_base;
7906
7907 if (mask & (1 << new_base))
7908 {
7909 inst.error = _("invalid register list");
7910 return FAIL;
7911 }
7912
7913 if ((mask >> new_base) != 0 && ! warned)
7914 {
7915 as_tsktsk (_("register list not in ascending order"));
7916 warned = 1;
7917 }
7918
7919 mask |= 1 << new_base;
7920 count++;
7921
7922 skip_whitespace (*str);
7923
7924 if (**str == '-') /* We have the start of a range expression */
7925 {
7926 int high_range;
7927
7928 (*str)++;
7929
7930 if ((high_range
7931 = arm_reg_parse (str, all_reg_maps[regtype].htab))
7932 == FAIL)
7933 {
7934 inst.error = _(all_reg_maps[regtype].expected);
7935 return FAIL;
7936 }
7937
7938 if (high_range <= new_base)
7939 {
7940 inst.error = _("register range not in ascending order");
7941 return FAIL;
7942 }
7943
7944 for (new_base++; new_base <= high_range; new_base++)
7945 {
7946 if (mask & (1 << new_base))
7947 {
7948 inst.error = _("invalid register list");
7949 return FAIL;
7950 }
7951
7952 mask |= 1 << new_base;
7953 count++;
7954 }
7955 }
7956 }
7957 while (skip_past_comma (str) != FAIL);
7958
7959 (*str)++;
7960
7961 /* Sanity check -- should have raised a parse error above. */
7962 if (count == 0 || count > max_regs)
7963 abort ();
7964
7965 *pbase = base_reg;
7966
7967 /* Final test -- the registers must be consecutive. */
7968 mask >>= base_reg;
7969 for (i = 0; i < count; i++)
7970 {
7971 if ((mask & (1u << i)) == 0)
7972 {
7973 inst.error = _("non-contiguous register range");
7974 return FAIL;
7975 }
7976 }
7977
7978 return count;
7979 }
7980
7981 static void
7982 do_vfp_reg2_from_sp2 (char * str)
7983 {
7984 int reg;
7985
7986 skip_whitespace (str);
7987
7988 if (reg_required_here (&str, 12) == FAIL
7989 || skip_past_comma (&str) == FAIL
7990 || reg_required_here (&str, 16) == FAIL
7991 || skip_past_comma (&str) == FAIL)
7992 {
7993 if (! inst.error)
7994 inst.error = BAD_ARGS;
7995 return;
7996 }
7997
7998 /* We require exactly two consecutive SP registers. */
7999 if (vfp_parse_reg_list (&str, &reg, 0) != 2)
8000 {
8001 if (! inst.error)
8002 inst.error = _("only two consecutive VFP SP registers allowed here");
8003 }
8004 vfp_sp_encode_reg (reg, VFP_REG_Sm);
8005
8006 end_of_line (str);
8007 }
8008
8009 static void
8010 do_vfp_sp_from_reg (char * str)
8011 {
8012 skip_whitespace (str);
8013
8014 if (vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL)
8015 return;
8016
8017 if (skip_past_comma (&str) == FAIL
8018 || reg_required_here (&str, 12) == FAIL)
8019 {
8020 if (! inst.error)
8021 inst.error = BAD_ARGS;
8022 return;
8023 }
8024
8025 end_of_line (str);
8026 }
8027
8028 static void
8029 do_vfp_sp2_from_reg2 (char * str)
8030 {
8031 int reg;
8032
8033 skip_whitespace (str);
8034
8035 /* We require exactly two consecutive SP registers. */
8036 if (vfp_parse_reg_list (&str, &reg, 0) != 2)
8037 {
8038 if (! inst.error)
8039 inst.error = _("only two consecutive VFP SP registers allowed here");
8040 }
8041 vfp_sp_encode_reg (reg, VFP_REG_Sm);
8042
8043 if (skip_past_comma (&str) == FAIL
8044 || reg_required_here (&str, 12) == FAIL
8045 || skip_past_comma (&str) == FAIL
8046 || reg_required_here (&str, 16) == FAIL)
8047 {
8048 if (! inst.error)
8049 inst.error = BAD_ARGS;
8050 return;
8051 }
8052
8053 end_of_line (str);
8054 }
8055
8056 static void
8057 do_vfp_reg_from_dp (char * str)
8058 {
8059 skip_whitespace (str);
8060
8061 if (reg_required_here (&str, 12) == FAIL)
8062 return;
8063
8064 if (skip_past_comma (&str) == FAIL
8065 || vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL)
8066 {
8067 if (! inst.error)
8068 inst.error = BAD_ARGS;
8069 return;
8070 }
8071
8072 end_of_line (str);
8073 }
8074
8075 static void
8076 do_vfp_reg2_from_dp (char * str)
8077 {
8078 skip_whitespace (str);
8079
8080 if (reg_required_here (&str, 12) == FAIL)
8081 return;
8082
8083 if (skip_past_comma (&str) == FAIL
8084 || reg_required_here (&str, 16) == FAIL
8085 || skip_past_comma (&str) == FAIL
8086 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
8087 {
8088 if (! inst.error)
8089 inst.error = BAD_ARGS;
8090 return;
8091 }
8092
8093 end_of_line (str);
8094 }
8095
8096 static void
8097 do_vfp_dp_from_reg (char * str)
8098 {
8099 skip_whitespace (str);
8100
8101 if (vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL)
8102 return;
8103
8104 if (skip_past_comma (&str) == FAIL
8105 || reg_required_here (&str, 12) == FAIL)
8106 {
8107 if (! inst.error)
8108 inst.error = BAD_ARGS;
8109 return;
8110 }
8111
8112 end_of_line (str);
8113 }
8114
8115 static void
8116 do_vfp_dp_from_reg2 (char * str)
8117 {
8118 skip_whitespace (str);
8119
8120 if (vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
8121 return;
8122
8123 if (skip_past_comma (&str) == FAIL
8124 || reg_required_here (&str, 12) == FAIL
8125 || skip_past_comma (&str) == FAIL
8126 || reg_required_here (&str, 16) == FAIL)
8127 {
8128 if (! inst.error)
8129 inst.error = BAD_ARGS;
8130 return;
8131 }
8132
8133 end_of_line (str);
8134 }
8135
8136 static const struct vfp_reg *
8137 vfp_psr_parse (char ** str)
8138 {
8139 char *start = *str;
8140 char c;
8141 char *p;
8142 const struct vfp_reg *vreg;
8143
8144 p = start;
8145
8146 /* Find the end of the current token. */
8147 do
8148 {
8149 c = *p++;
8150 }
8151 while (ISALPHA (c));
8152
8153 /* Mark it. */
8154 *--p = 0;
8155
8156 for (vreg = vfp_regs + 0;
8157 vreg < vfp_regs + sizeof (vfp_regs) / sizeof (struct vfp_reg);
8158 vreg++)
8159 {
8160 if (streq (start, vreg->name))
8161 {
8162 *p = c;
8163 *str = p;
8164 return vreg;
8165 }
8166 }
8167
8168 *p = c;
8169 return NULL;
8170 }
8171
8172 static int
8173 vfp_psr_required_here (char ** str)
8174 {
8175 char *start = *str;
8176 const struct vfp_reg *vreg;
8177
8178 vreg = vfp_psr_parse (str);
8179
8180 if (vreg)
8181 {
8182 inst.instruction |= vreg->regno;
8183 return SUCCESS;
8184 }
8185
8186 inst.error = _("VFP system register expected");
8187
8188 *str = start;
8189 return FAIL;
8190 }
8191
8192 static void
8193 do_vfp_reg_from_ctrl (char * str)
8194 {
8195 skip_whitespace (str);
8196
8197 if (reg_required_here (&str, 12) == FAIL)
8198 return;
8199
8200 if (skip_past_comma (&str) == FAIL
8201 || vfp_psr_required_here (&str) == FAIL)
8202 {
8203 if (! inst.error)
8204 inst.error = BAD_ARGS;
8205 return;
8206 }
8207
8208 end_of_line (str);
8209 }
8210
8211 static void
8212 do_vfp_ctrl_from_reg (char * str)
8213 {
8214 skip_whitespace (str);
8215
8216 if (vfp_psr_required_here (&str) == FAIL)
8217 return;
8218
8219 if (skip_past_comma (&str) == FAIL
8220 || reg_required_here (&str, 12) == FAIL)
8221 {
8222 if (! inst.error)
8223 inst.error = BAD_ARGS;
8224 return;
8225 }
8226
8227 end_of_line (str);
8228 }
8229
8230 static void
8231 do_vfp_sp_ldst (char * str)
8232 {
8233 skip_whitespace (str);
8234
8235 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
8236 {
8237 if (!inst.error)
8238 inst.error = BAD_ARGS;
8239 return;
8240 }
8241
8242 if (skip_past_comma (&str) == FAIL
8243 || cp_address_required_here (&str, CP_NO_WB) == FAIL)
8244 {
8245 if (!inst.error)
8246 inst.error = BAD_ARGS;
8247 return;
8248 }
8249
8250 end_of_line (str);
8251 }
8252
8253 static void
8254 do_vfp_dp_ldst (char * str)
8255 {
8256 skip_whitespace (str);
8257
8258 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
8259 {
8260 if (!inst.error)
8261 inst.error = BAD_ARGS;
8262 return;
8263 }
8264
8265 if (skip_past_comma (&str) == FAIL
8266 || cp_address_required_here (&str, CP_NO_WB) == FAIL)
8267 {
8268 if (!inst.error)
8269 inst.error = BAD_ARGS;
8270 return;
8271 }
8272
8273 end_of_line (str);
8274 }
8275
8276
8277 static void
8278 vfp_sp_ldstm (char * str, enum vfp_ldstm_type ldstm_type)
8279 {
8280 int count;
8281 int reg;
8282
8283 skip_whitespace (str);
8284
8285 if (reg_required_here (&str, 16) == FAIL)
8286 return;
8287
8288 skip_whitespace (str);
8289
8290 if (*str == '!')
8291 {
8292 inst.instruction |= WRITE_BACK;
8293 str++;
8294 }
8295 else if (ldstm_type != VFP_LDSTMIA)
8296 {
8297 inst.error = _("this addressing mode requires base-register writeback");
8298 return;
8299 }
8300
8301 if (skip_past_comma (&str) == FAIL
8302 || (count = vfp_parse_reg_list (&str, &reg, 0)) == FAIL)
8303 {
8304 if (!inst.error)
8305 inst.error = BAD_ARGS;
8306 return;
8307 }
8308 vfp_sp_encode_reg (reg, VFP_REG_Sd);
8309
8310 inst.instruction |= count;
8311 end_of_line (str);
8312 }
8313
8314 static void
8315 vfp_dp_ldstm (char * str, enum vfp_ldstm_type ldstm_type)
8316 {
8317 int count;
8318 int reg;
8319
8320 skip_whitespace (str);
8321
8322 if (reg_required_here (&str, 16) == FAIL)
8323 return;
8324
8325 skip_whitespace (str);
8326
8327 if (*str == '!')
8328 {
8329 inst.instruction |= WRITE_BACK;
8330 str++;
8331 }
8332 else if (ldstm_type != VFP_LDSTMIA && ldstm_type != VFP_LDSTMIAX)
8333 {
8334 inst.error = _("this addressing mode requires base-register writeback");
8335 return;
8336 }
8337
8338 if (skip_past_comma (&str) == FAIL
8339 || (count = vfp_parse_reg_list (&str, &reg, 1)) == FAIL)
8340 {
8341 if (!inst.error)
8342 inst.error = BAD_ARGS;
8343 return;
8344 }
8345
8346 count <<= 1;
8347 if (ldstm_type == VFP_LDSTMIAX || ldstm_type == VFP_LDSTMDBX)
8348 count += 1;
8349
8350 inst.instruction |= (reg << 12) | count;
8351 end_of_line (str);
8352 }
8353
8354 static void
8355 do_vfp_sp_ldstmia (char * str)
8356 {
8357 vfp_sp_ldstm (str, VFP_LDSTMIA);
8358 }
8359
8360 static void
8361 do_vfp_sp_ldstmdb (char * str)
8362 {
8363 vfp_sp_ldstm (str, VFP_LDSTMDB);
8364 }
8365
8366 static void
8367 do_vfp_dp_ldstmia (char * str)
8368 {
8369 vfp_dp_ldstm (str, VFP_LDSTMIA);
8370 }
8371
8372 static void
8373 do_vfp_dp_ldstmdb (char * str)
8374 {
8375 vfp_dp_ldstm (str, VFP_LDSTMDB);
8376 }
8377
8378 static void
8379 do_vfp_xp_ldstmia (char *str)
8380 {
8381 vfp_dp_ldstm (str, VFP_LDSTMIAX);
8382 }
8383
8384 static void
8385 do_vfp_xp_ldstmdb (char * str)
8386 {
8387 vfp_dp_ldstm (str, VFP_LDSTMDBX);
8388 }
8389
8390 static void
8391 do_vfp_sp_compare_z (char * str)
8392 {
8393 skip_whitespace (str);
8394
8395 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
8396 {
8397 if (!inst.error)
8398 inst.error = BAD_ARGS;
8399 return;
8400 }
8401
8402 end_of_line (str);
8403 }
8404
8405 static void
8406 do_vfp_dp_compare_z (char * str)
8407 {
8408 skip_whitespace (str);
8409
8410 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
8411 {
8412 if (!inst.error)
8413 inst.error = BAD_ARGS;
8414 return;
8415 }
8416
8417 end_of_line (str);
8418 }
8419
8420 static void
8421 do_vfp_dp_sp_cvt (char * str)
8422 {
8423 skip_whitespace (str);
8424
8425 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
8426 return;
8427
8428 if (skip_past_comma (&str) == FAIL
8429 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
8430 {
8431 if (! inst.error)
8432 inst.error = BAD_ARGS;
8433 return;
8434 }
8435
8436 end_of_line (str);
8437 }
8438
8439 static void
8440 do_vfp_sp_dp_cvt (char * str)
8441 {
8442 skip_whitespace (str);
8443
8444 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
8445 return;
8446
8447 if (skip_past_comma (&str) == FAIL
8448 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
8449 {
8450 if (! inst.error)
8451 inst.error = BAD_ARGS;
8452 return;
8453 }
8454
8455 end_of_line (str);
8456 }
8457
8458 /* Thumb specific routines. */
8459
8460 /* Parse an add or subtract instruction, SUBTRACT is non-zero if the opcode
8461 was SUB. */
8462
8463 static void
8464 thumb_add_sub (char * str, int subtract)
8465 {
8466 int Rd, Rs, Rn = FAIL;
8467
8468 skip_whitespace (str);
8469
8470 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
8471 || skip_past_comma (&str) == FAIL)
8472 {
8473 if (! inst.error)
8474 inst.error = BAD_ARGS;
8475 return;
8476 }
8477
8478 if (is_immediate_prefix (*str))
8479 {
8480 Rs = Rd;
8481 str++;
8482 if (my_get_expression (&inst.reloc.exp, &str))
8483 return;
8484 }
8485 else
8486 {
8487 if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
8488 return;
8489
8490 if (skip_past_comma (&str) == FAIL)
8491 {
8492 /* Two operand format, shuffle the registers
8493 and pretend there are 3. */
8494 Rn = Rs;
8495 Rs = Rd;
8496 }
8497 else if (is_immediate_prefix (*str))
8498 {
8499 str++;
8500 if (my_get_expression (&inst.reloc.exp, &str))
8501 return;
8502 }
8503 else if ((Rn = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
8504 return;
8505 }
8506
8507 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
8508 for the latter case, EXPR contains the immediate that was found. */
8509 if (Rn != FAIL)
8510 {
8511 /* All register format. */
8512 if (Rd > 7 || Rs > 7 || Rn > 7)
8513 {
8514 if (Rs != Rd)
8515 {
8516 inst.error = _("dest and source1 must be the same register");
8517 return;
8518 }
8519
8520 /* Can't do this for SUB. */
8521 if (subtract)
8522 {
8523 inst.error = _("subtract valid only on lo regs");
8524 return;
8525 }
8526
8527 inst.instruction = (T_OPCODE_ADD_HI
8528 | (Rd > 7 ? THUMB_H1 : 0)
8529 | (Rn > 7 ? THUMB_H2 : 0));
8530 inst.instruction |= (Rd & 7) | ((Rn & 7) << 3);
8531 }
8532 else
8533 {
8534 inst.instruction = subtract ? T_OPCODE_SUB_R3 : T_OPCODE_ADD_R3;
8535 inst.instruction |= Rd | (Rs << 3) | (Rn << 6);
8536 }
8537 }
8538 else
8539 {
8540 /* Immediate expression, now things start to get nasty. */
8541
8542 /* First deal with HI regs, only very restricted cases allowed:
8543 Adjusting SP, and using PC or SP to get an address. */
8544 if ((Rd > 7 && (Rd != REG_SP || Rs != REG_SP))
8545 || (Rs > 7 && Rs != REG_SP && Rs != REG_PC))
8546 {
8547 inst.error = _("invalid Hi register with immediate");
8548 return;
8549 }
8550
8551 if (inst.reloc.exp.X_op != O_constant)
8552 {
8553 /* Value isn't known yet, all we can do is store all the fragments
8554 we know about in the instruction and let the reloc hacking
8555 work it all out. */
8556 inst.instruction = (subtract ? 0x8000 : 0) | (Rd << 4) | Rs;
8557 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
8558 }
8559 else
8560 {
8561 int offset = inst.reloc.exp.X_add_number;
8562
8563 if (subtract)
8564 offset = - offset;
8565
8566 if (offset < 0)
8567 {
8568 offset = - offset;
8569 subtract = 1;
8570
8571 /* Quick check, in case offset is MIN_INT. */
8572 if (offset < 0)
8573 {
8574 inst.error = _("immediate value out of range");
8575 return;
8576 }
8577 }
8578 /* Note - you cannot convert a subtract of 0 into an
8579 add of 0 because the carry flag is set differently. */
8580 else if (offset > 0)
8581 subtract = 0;
8582
8583 if (Rd == REG_SP)
8584 {
8585 if (offset & ~0x1fc)
8586 {
8587 inst.error = _("invalid immediate value for stack adjust");
8588 return;
8589 }
8590 inst.instruction = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
8591 inst.instruction |= offset >> 2;
8592 }
8593 else if (Rs == REG_PC || Rs == REG_SP)
8594 {
8595 if (subtract
8596 || (offset & ~0x3fc))
8597 {
8598 inst.error = _("invalid immediate for address calculation");
8599 return;
8600 }
8601 inst.instruction = (Rs == REG_PC ? T_OPCODE_ADD_PC
8602 : T_OPCODE_ADD_SP);
8603 inst.instruction |= (Rd << 8) | (offset >> 2);
8604 }
8605 else if (Rs == Rd)
8606 {
8607 if (offset & ~0xff)
8608 {
8609 inst.error = _("immediate value out of range");
8610 return;
8611 }
8612 inst.instruction = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
8613 inst.instruction |= (Rd << 8) | offset;
8614 }
8615 else
8616 {
8617 if (offset & ~0x7)
8618 {
8619 inst.error = _("immediate value out of range");
8620 return;
8621 }
8622 inst.instruction = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
8623 inst.instruction |= Rd | (Rs << 3) | (offset << 6);
8624 }
8625 }
8626 }
8627
8628 end_of_line (str);
8629 }
8630
8631 static void
8632 thumb_shift (char * str, int shift)
8633 {
8634 int Rd, Rs, Rn = FAIL;
8635
8636 skip_whitespace (str);
8637
8638 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
8639 || skip_past_comma (&str) == FAIL)
8640 {
8641 if (! inst.error)
8642 inst.error = BAD_ARGS;
8643 return;
8644 }
8645
8646 if (is_immediate_prefix (*str))
8647 {
8648 /* Two operand immediate format, set Rs to Rd. */
8649 Rs = Rd;
8650 str ++;
8651 if (my_get_expression (&inst.reloc.exp, &str))
8652 return;
8653 }
8654 else
8655 {
8656 if ((Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
8657 return;
8658
8659 if (skip_past_comma (&str) == FAIL)
8660 {
8661 /* Two operand format, shuffle the registers
8662 and pretend there are 3. */
8663 Rn = Rs;
8664 Rs = Rd;
8665 }
8666 else if (is_immediate_prefix (*str))
8667 {
8668 str++;
8669 if (my_get_expression (&inst.reloc.exp, &str))
8670 return;
8671 }
8672 else if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
8673 return;
8674 }
8675
8676 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
8677 for the latter case, EXPR contains the immediate that was found. */
8678
8679 if (Rn != FAIL)
8680 {
8681 if (Rs != Rd)
8682 {
8683 inst.error = _("source1 and dest must be same register");
8684 return;
8685 }
8686
8687 switch (shift)
8688 {
8689 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_R; break;
8690 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_R; break;
8691 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_R; break;
8692 }
8693
8694 inst.instruction |= Rd | (Rn << 3);
8695 }
8696 else
8697 {
8698 switch (shift)
8699 {
8700 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_I; break;
8701 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_I; break;
8702 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_I; break;
8703 }
8704
8705 if (inst.reloc.exp.X_op != O_constant)
8706 {
8707 /* Value isn't known yet, create a dummy reloc and let reloc
8708 hacking fix it up. */
8709 inst.reloc.type = BFD_RELOC_ARM_THUMB_SHIFT;
8710 }
8711 else
8712 {
8713 unsigned shift_value = inst.reloc.exp.X_add_number;
8714
8715 if (shift_value > 32 || (shift_value == 32 && shift == THUMB_LSL))
8716 {
8717 inst.error = _("invalid immediate for shift");
8718 return;
8719 }
8720
8721 /* Shifts of zero are handled by converting to LSL. */
8722 if (shift_value == 0)
8723 inst.instruction = T_OPCODE_LSL_I;
8724
8725 /* Shifts of 32 are encoded as a shift of zero. */
8726 if (shift_value == 32)
8727 shift_value = 0;
8728
8729 inst.instruction |= shift_value << 6;
8730 }
8731
8732 inst.instruction |= Rd | (Rs << 3);
8733 }
8734
8735 end_of_line (str);
8736 }
8737
8738 static void
8739 thumb_load_store (char * str, int load_store, int size)
8740 {
8741 int Rd, Rb, Ro = FAIL;
8742
8743 skip_whitespace (str);
8744
8745 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
8746 || skip_past_comma (&str) == FAIL)
8747 {
8748 if (! inst.error)
8749 inst.error = BAD_ARGS;
8750 return;
8751 }
8752
8753 if (*str == '[')
8754 {
8755 str++;
8756 if ((Rb = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
8757 return;
8758
8759 if (skip_past_comma (&str) != FAIL)
8760 {
8761 if (is_immediate_prefix (*str))
8762 {
8763 str++;
8764 if (my_get_expression (&inst.reloc.exp, &str))
8765 return;
8766 }
8767 else if ((Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
8768 return;
8769 }
8770 else
8771 {
8772 inst.reloc.exp.X_op = O_constant;
8773 inst.reloc.exp.X_add_number = 0;
8774 }
8775
8776 if (*str != ']')
8777 {
8778 inst.error = _("expected ']'");
8779 return;
8780 }
8781 str++;
8782 }
8783 else if (*str == '=')
8784 {
8785 if (load_store != THUMB_LOAD)
8786 {
8787 inst.error = _("invalid pseudo operation");
8788 return;
8789 }
8790
8791 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
8792 str++;
8793
8794 skip_whitespace (str);
8795
8796 if (my_get_expression (& inst.reloc.exp, & str))
8797 return;
8798
8799 end_of_line (str);
8800
8801 if ( inst.reloc.exp.X_op != O_constant
8802 && inst.reloc.exp.X_op != O_symbol)
8803 {
8804 inst.error = "Constant expression expected";
8805 return;
8806 }
8807
8808 if (inst.reloc.exp.X_op == O_constant
8809 && ((inst.reloc.exp.X_add_number & ~0xFF) == 0))
8810 {
8811 /* This can be done with a mov instruction. */
8812
8813 inst.instruction = T_OPCODE_MOV_I8 | (Rd << 8);
8814 inst.instruction |= inst.reloc.exp.X_add_number;
8815 return;
8816 }
8817
8818 /* Insert into literal pool. */
8819 if (add_to_lit_pool () == FAIL)
8820 {
8821 if (!inst.error)
8822 inst.error = "literal pool insertion failed";
8823 return;
8824 }
8825
8826 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
8827 inst.reloc.pc_rel = 1;
8828 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
8829 /* Adjust ARM pipeline offset to Thumb. */
8830 inst.reloc.exp.X_add_number += 4;
8831
8832 return;
8833 }
8834 else
8835 {
8836 if (my_get_expression (&inst.reloc.exp, &str))
8837 return;
8838
8839 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
8840 inst.reloc.pc_rel = 1;
8841 inst.reloc.exp.X_add_number -= 4; /* Pipeline offset. */
8842 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
8843 end_of_line (str);
8844 return;
8845 }
8846
8847 if (Rb == REG_PC || Rb == REG_SP)
8848 {
8849 if (size != THUMB_WORD)
8850 {
8851 inst.error = _("byte or halfword not valid for base register");
8852 return;
8853 }
8854 else if (Rb == REG_PC && load_store != THUMB_LOAD)
8855 {
8856 inst.error = _("r15 based store not allowed");
8857 return;
8858 }
8859 else if (Ro != FAIL)
8860 {
8861 inst.error = _("invalid base register for register offset");
8862 return;
8863 }
8864
8865 if (Rb == REG_PC)
8866 inst.instruction = T_OPCODE_LDR_PC;
8867 else if (load_store == THUMB_LOAD)
8868 inst.instruction = T_OPCODE_LDR_SP;
8869 else
8870 inst.instruction = T_OPCODE_STR_SP;
8871
8872 inst.instruction |= Rd << 8;
8873 if (inst.reloc.exp.X_op == O_constant)
8874 {
8875 unsigned offset = inst.reloc.exp.X_add_number;
8876
8877 if (offset & ~0x3fc)
8878 {
8879 inst.error = _("invalid offset");
8880 return;
8881 }
8882
8883 inst.instruction |= offset >> 2;
8884 }
8885 else
8886 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
8887 }
8888 else if (Rb > 7)
8889 {
8890 inst.error = _("invalid base register in load/store");
8891 return;
8892 }
8893 else if (Ro == FAIL)
8894 {
8895 /* Immediate offset. */
8896 if (size == THUMB_WORD)
8897 inst.instruction = (load_store == THUMB_LOAD
8898 ? T_OPCODE_LDR_IW : T_OPCODE_STR_IW);
8899 else if (size == THUMB_HALFWORD)
8900 inst.instruction = (load_store == THUMB_LOAD
8901 ? T_OPCODE_LDR_IH : T_OPCODE_STR_IH);
8902 else
8903 inst.instruction = (load_store == THUMB_LOAD
8904 ? T_OPCODE_LDR_IB : T_OPCODE_STR_IB);
8905
8906 inst.instruction |= Rd | (Rb << 3);
8907
8908 if (inst.reloc.exp.X_op == O_constant)
8909 {
8910 unsigned offset = inst.reloc.exp.X_add_number;
8911
8912 if (offset & ~(0x1f << size))
8913 {
8914 inst.error = _("invalid offset");
8915 return;
8916 }
8917 inst.instruction |= (offset >> size) << 6;
8918 }
8919 else
8920 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
8921 }
8922 else
8923 {
8924 /* Register offset. */
8925 if (size == THUMB_WORD)
8926 inst.instruction = (load_store == THUMB_LOAD
8927 ? T_OPCODE_LDR_RW : T_OPCODE_STR_RW);
8928 else if (size == THUMB_HALFWORD)
8929 inst.instruction = (load_store == THUMB_LOAD
8930 ? T_OPCODE_LDR_RH : T_OPCODE_STR_RH);
8931 else
8932 inst.instruction = (load_store == THUMB_LOAD
8933 ? T_OPCODE_LDR_RB : T_OPCODE_STR_RB);
8934
8935 inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
8936 }
8937
8938 end_of_line (str);
8939 }
8940
8941 /* A register must be given at this point.
8942
8943 Shift is the place to put it in inst.instruction.
8944
8945 Restores input start point on err.
8946 Returns the reg#, or FAIL. */
8947
8948 static int
8949 mav_reg_required_here (char ** str, int shift, enum arm_reg_type regtype)
8950 {
8951 int reg;
8952 char *start = *str;
8953
8954 if ((reg = arm_reg_parse (str, all_reg_maps[regtype].htab)) != FAIL)
8955 {
8956 if (shift >= 0)
8957 inst.instruction |= reg << shift;
8958
8959 return reg;
8960 }
8961
8962 /* Restore the start point. */
8963 *str = start;
8964
8965 /* Try generic coprocessor name if applicable. */
8966 if (regtype == REG_TYPE_MVF ||
8967 regtype == REG_TYPE_MVD ||
8968 regtype == REG_TYPE_MVFX ||
8969 regtype == REG_TYPE_MVDX)
8970 {
8971 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_CN].htab)) != FAIL)
8972 {
8973 if (shift >= 0)
8974 inst.instruction |= reg << shift;
8975
8976 return reg;
8977 }
8978
8979 /* Restore the start point. */
8980 *str = start;
8981 }
8982
8983 /* In the few cases where we might be able to accept something else
8984 this error can be overridden. */
8985 inst.error = _(all_reg_maps[regtype].expected);
8986
8987 return FAIL;
8988 }
8989
8990 /* Cirrus Maverick Instructions. */
8991
8992 /* Isnsn like "foo X,Y". */
8993
8994 static void
8995 do_mav_binops (char * str,
8996 int mode,
8997 enum arm_reg_type reg0,
8998 enum arm_reg_type reg1)
8999 {
9000 int shift0, shift1;
9001
9002 shift0 = mode & 0xff;
9003 shift1 = (mode >> 8) & 0xff;
9004
9005 skip_whitespace (str);
9006
9007 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
9008 || skip_past_comma (&str) == FAIL
9009 || mav_reg_required_here (&str, shift1, reg1) == FAIL)
9010 {
9011 if (!inst.error)
9012 inst.error = BAD_ARGS;
9013 }
9014 else
9015 end_of_line (str);
9016 }
9017
9018 /* Isnsn like "foo X,Y,Z". */
9019
9020 static void
9021 do_mav_triple (char * str,
9022 int mode,
9023 enum arm_reg_type reg0,
9024 enum arm_reg_type reg1,
9025 enum arm_reg_type reg2)
9026 {
9027 int shift0, shift1, shift2;
9028
9029 shift0 = mode & 0xff;
9030 shift1 = (mode >> 8) & 0xff;
9031 shift2 = (mode >> 16) & 0xff;
9032
9033 skip_whitespace (str);
9034
9035 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
9036 || skip_past_comma (&str) == FAIL
9037 || mav_reg_required_here (&str, shift1, reg1) == FAIL
9038 || skip_past_comma (&str) == FAIL
9039 || mav_reg_required_here (&str, shift2, reg2) == FAIL)
9040 {
9041 if (!inst.error)
9042 inst.error = BAD_ARGS;
9043 }
9044 else
9045 end_of_line (str);
9046 }
9047
9048 /* Wrapper functions. */
9049
9050 static void
9051 do_mav_binops_1a (char * str)
9052 {
9053 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVF);
9054 }
9055
9056 static void
9057 do_mav_binops_1b (char * str)
9058 {
9059 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVD);
9060 }
9061
9062 static void
9063 do_mav_binops_1c (char * str)
9064 {
9065 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVDX);
9066 }
9067
9068 static void
9069 do_mav_binops_1d (char * str)
9070 {
9071 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVF);
9072 }
9073
9074 static void
9075 do_mav_binops_1e (char * str)
9076 {
9077 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVD);
9078 }
9079
9080 static void
9081 do_mav_binops_1f (char * str)
9082 {
9083 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVF);
9084 }
9085
9086 static void
9087 do_mav_binops_1g (char * str)
9088 {
9089 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVD);
9090 }
9091
9092 static void
9093 do_mav_binops_1h (char * str)
9094 {
9095 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVFX);
9096 }
9097
9098 static void
9099 do_mav_binops_1i (char * str)
9100 {
9101 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVFX);
9102 }
9103
9104 static void
9105 do_mav_binops_1j (char * str)
9106 {
9107 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVDX);
9108 }
9109
9110 static void
9111 do_mav_binops_1k (char * str)
9112 {
9113 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVDX);
9114 }
9115
9116 static void
9117 do_mav_binops_1l (char * str)
9118 {
9119 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVF);
9120 }
9121
9122 static void
9123 do_mav_binops_1m (char * str)
9124 {
9125 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVD);
9126 }
9127
9128 static void
9129 do_mav_binops_1n (char * str)
9130 {
9131 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVFX);
9132 }
9133
9134 static void
9135 do_mav_binops_1o (char * str)
9136 {
9137 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVDX, REG_TYPE_MVDX);
9138 }
9139
9140 static void
9141 do_mav_binops_2a (char * str)
9142 {
9143 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVF, REG_TYPE_RN);
9144 }
9145
9146 static void
9147 do_mav_binops_2b (char * str)
9148 {
9149 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVD, REG_TYPE_RN);
9150 }
9151
9152 static void
9153 do_mav_binops_2c (char * str)
9154 {
9155 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVDX, REG_TYPE_RN);
9156 }
9157
9158 static void
9159 do_mav_binops_3a (char * str)
9160 {
9161 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVAX, REG_TYPE_MVFX);
9162 }
9163
9164 static void
9165 do_mav_binops_3b (char * str)
9166 {
9167 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVFX, REG_TYPE_MVAX);
9168 }
9169
9170 static void
9171 do_mav_binops_3c (char * str)
9172 {
9173 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVAX, REG_TYPE_MVDX);
9174 }
9175
9176 static void
9177 do_mav_binops_3d (char * str)
9178 {
9179 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVDX, REG_TYPE_MVAX);
9180 }
9181
9182 static void
9183 do_mav_triple_4a (char * str)
9184 {
9185 do_mav_triple (str, MAV_MODE4, REG_TYPE_MVFX, REG_TYPE_MVFX, REG_TYPE_RN);
9186 }
9187
9188 static void
9189 do_mav_triple_4b (char * str)
9190 {
9191 do_mav_triple (str, MAV_MODE4, REG_TYPE_MVDX, REG_TYPE_MVDX, REG_TYPE_RN);
9192 }
9193
9194 static void
9195 do_mav_triple_5a (char * str)
9196 {
9197 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVF, REG_TYPE_MVF);
9198 }
9199
9200 static void
9201 do_mav_triple_5b (char * str)
9202 {
9203 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVD, REG_TYPE_MVD);
9204 }
9205
9206 static void
9207 do_mav_triple_5c (char * str)
9208 {
9209 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVFX, REG_TYPE_MVFX);
9210 }
9211
9212 static void
9213 do_mav_triple_5d (char * str)
9214 {
9215 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVDX, REG_TYPE_MVDX);
9216 }
9217
9218 static void
9219 do_mav_triple_5e (char * str)
9220 {
9221 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVF, REG_TYPE_MVF, REG_TYPE_MVF);
9222 }
9223
9224 static void
9225 do_mav_triple_5f (char * str)
9226 {
9227 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVD, REG_TYPE_MVD, REG_TYPE_MVD);
9228 }
9229
9230 static void
9231 do_mav_triple_5g (char * str)
9232 {
9233 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVFX, REG_TYPE_MVFX, REG_TYPE_MVFX);
9234 }
9235
9236 static void
9237 do_mav_triple_5h (char * str)
9238 {
9239 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVDX, REG_TYPE_MVDX, REG_TYPE_MVDX);
9240 }
9241
9242 /* Isnsn like "foo W,X,Y,Z".
9243 where W=MVAX[0:3] and X,Y,Z=MVFX[0:15]. */
9244
9245 static void
9246 do_mav_quad (char * str,
9247 int mode,
9248 enum arm_reg_type reg0,
9249 enum arm_reg_type reg1,
9250 enum arm_reg_type reg2,
9251 enum arm_reg_type reg3)
9252 {
9253 int shift0, shift1, shift2, shift3;
9254
9255 shift0= mode & 0xff;
9256 shift1 = (mode >> 8) & 0xff;
9257 shift2 = (mode >> 16) & 0xff;
9258 shift3 = (mode >> 24) & 0xff;
9259
9260 skip_whitespace (str);
9261
9262 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
9263 || skip_past_comma (&str) == FAIL
9264 || mav_reg_required_here (&str, shift1, reg1) == FAIL
9265 || skip_past_comma (&str) == FAIL
9266 || mav_reg_required_here (&str, shift2, reg2) == FAIL
9267 || skip_past_comma (&str) == FAIL
9268 || mav_reg_required_here (&str, shift3, reg3) == FAIL)
9269 {
9270 if (!inst.error)
9271 inst.error = BAD_ARGS;
9272 }
9273 else
9274 end_of_line (str);
9275 }
9276
9277 static void
9278 do_mav_quad_6a (char * str)
9279 {
9280 do_mav_quad (str, MAV_MODE6, REG_TYPE_MVAX, REG_TYPE_MVFX, REG_TYPE_MVFX,
9281 REG_TYPE_MVFX);
9282 }
9283
9284 static void
9285 do_mav_quad_6b (char * str)
9286 {
9287 do_mav_quad (str, MAV_MODE6, REG_TYPE_MVAX, REG_TYPE_MVAX, REG_TYPE_MVFX,
9288 REG_TYPE_MVFX);
9289 }
9290
9291 /* cfmvsc32<cond> DSPSC,MVDX[15:0]. */
9292 static void
9293 do_mav_dspsc_1 (char * str)
9294 {
9295 skip_whitespace (str);
9296
9297 /* cfmvsc32. */
9298 if (mav_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL
9299 || skip_past_comma (&str) == FAIL
9300 || mav_reg_required_here (&str, 12, REG_TYPE_MVDX) == FAIL)
9301 {
9302 if (!inst.error)
9303 inst.error = BAD_ARGS;
9304
9305 return;
9306 }
9307
9308 end_of_line (str);
9309 }
9310
9311 /* cfmv32sc<cond> MVDX[15:0],DSPSC. */
9312 static void
9313 do_mav_dspsc_2 (char * str)
9314 {
9315 skip_whitespace (str);
9316
9317 /* cfmv32sc. */
9318 if (mav_reg_required_here (&str, 12, REG_TYPE_MVDX) == FAIL
9319 || skip_past_comma (&str) == FAIL
9320 || mav_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL)
9321 {
9322 if (!inst.error)
9323 inst.error = BAD_ARGS;
9324
9325 return;
9326 }
9327
9328 end_of_line (str);
9329 }
9330
9331 /* Maverick shift immediate instructions.
9332 cfsh32<cond> MVFX[15:0],MVFX[15:0],Shift[6:0].
9333 cfsh64<cond> MVDX[15:0],MVDX[15:0],Shift[6:0]. */
9334
9335 static void
9336 do_mav_shift (char * str,
9337 enum arm_reg_type reg0,
9338 enum arm_reg_type reg1)
9339 {
9340 int error;
9341 int imm, neg = 0;
9342
9343 skip_whitespace (str);
9344
9345 error = 0;
9346
9347 if (mav_reg_required_here (&str, 12, reg0) == FAIL
9348 || skip_past_comma (&str) == FAIL
9349 || mav_reg_required_here (&str, 16, reg1) == FAIL
9350 || skip_past_comma (&str) == FAIL)
9351 {
9352 if (!inst.error)
9353 inst.error = BAD_ARGS;
9354 return;
9355 }
9356
9357 /* Calculate the immediate operand.
9358 The operand is a 7bit signed number. */
9359 skip_whitespace (str);
9360
9361 if (*str == '#')
9362 ++str;
9363
9364 if (!ISDIGIT (*str) && *str != '-')
9365 {
9366 inst.error = _("expecting immediate, 7bit operand");
9367 return;
9368 }
9369
9370 if (*str == '-')
9371 {
9372 neg = 1;
9373 ++str;
9374 }
9375
9376 for (imm = 0; *str && ISDIGIT (*str); ++str)
9377 imm = imm * 10 + *str - '0';
9378
9379 if (imm > 64)
9380 {
9381 inst.error = _("immediate out of range");
9382 return;
9383 }
9384
9385 /* Make negative imm's into 7bit signed numbers. */
9386 if (neg)
9387 {
9388 imm = -imm;
9389 imm &= 0x0000007f;
9390 }
9391
9392 /* Bits 0-3 of the insn should have bits 0-3 of the immediate.
9393 Bits 5-7 of the insn should have bits 4-6 of the immediate.
9394 Bit 4 should be 0. */
9395 imm = (imm & 0xf) | ((imm & 0x70) << 1);
9396
9397 inst.instruction |= imm;
9398 end_of_line (str);
9399 }
9400
9401 static void
9402 do_mav_shift_1 (char * str)
9403 {
9404 do_mav_shift (str, REG_TYPE_MVFX, REG_TYPE_MVFX);
9405 }
9406
9407 static void
9408 do_mav_shift_2 (char * str)
9409 {
9410 do_mav_shift (str, REG_TYPE_MVDX, REG_TYPE_MVDX);
9411 }
9412
9413 static int
9414 mav_parse_offset (char ** str, int * negative)
9415 {
9416 char * p = *str;
9417 int offset;
9418
9419 *negative = 0;
9420
9421 skip_whitespace (p);
9422
9423 if (*p == '#')
9424 ++p;
9425
9426 if (*p == '-')
9427 {
9428 *negative = 1;
9429 ++p;
9430 }
9431
9432 if (!ISDIGIT (*p))
9433 {
9434 inst.error = _("offset expected");
9435 return 0;
9436 }
9437
9438 for (offset = 0; *p && ISDIGIT (*p); ++p)
9439 offset = offset * 10 + *p - '0';
9440
9441 if (offset > 0x3fc)
9442 {
9443 inst.error = _("offset out of range");
9444 return 0;
9445 }
9446 if (offset & 0x3)
9447 {
9448 inst.error = _("offset not a multiple of 4");
9449 return 0;
9450 }
9451
9452 *str = p;
9453
9454 return *negative ? -offset : offset;
9455 }
9456
9457 /* Maverick load/store instructions.
9458 <insn><cond> CRd,[Rn,<offset>]{!}.
9459 <insn><cond> CRd,[Rn],<offset>. */
9460
9461 static void
9462 do_mav_ldst (char * str, enum arm_reg_type reg0)
9463 {
9464 int offset, negative;
9465
9466 skip_whitespace (str);
9467
9468 if (mav_reg_required_here (&str, 12, reg0) == FAIL
9469 || skip_past_comma (&str) == FAIL
9470 || *str++ != '['
9471 || reg_required_here (&str, 16) == FAIL)
9472 goto fail_ldst;
9473
9474 if (skip_past_comma (&str) == SUCCESS)
9475 {
9476 /* You are here: "<offset>]{!}". */
9477 inst.instruction |= PRE_INDEX;
9478
9479 offset = mav_parse_offset (&str, &negative);
9480
9481 if (inst.error)
9482 return;
9483
9484 if (*str++ != ']')
9485 {
9486 inst.error = _("missing ]");
9487 return;
9488 }
9489
9490 if (*str == '!')
9491 {
9492 inst.instruction |= WRITE_BACK;
9493 ++str;
9494 }
9495 }
9496 else
9497 {
9498 /* You are here: "], <offset>". */
9499 if (*str++ != ']')
9500 {
9501 inst.error = _("missing ]");
9502 return;
9503 }
9504
9505 if (skip_past_comma (&str) == FAIL
9506 || (offset = mav_parse_offset (&str, &negative), inst.error))
9507 goto fail_ldst;
9508
9509 inst.instruction |= CP_T_WB; /* Post indexed, set bit W. */
9510 }
9511
9512 if (negative)
9513 offset = -offset;
9514 else
9515 inst.instruction |= CP_T_UD; /* Positive, so set bit U. */
9516
9517 inst.instruction |= offset >> 2;
9518 end_of_line (str);
9519 return;
9520
9521 fail_ldst:
9522 if (!inst.error)
9523 inst.error = BAD_ARGS;
9524 }
9525
9526 static void
9527 do_mav_ldst_1 (char * str)
9528 {
9529 do_mav_ldst (str, REG_TYPE_MVF);
9530 }
9531
9532 static void
9533 do_mav_ldst_2 (char * str)
9534 {
9535 do_mav_ldst (str, REG_TYPE_MVD);
9536 }
9537
9538 static void
9539 do_mav_ldst_3 (char * str)
9540 {
9541 do_mav_ldst (str, REG_TYPE_MVFX);
9542 }
9543
9544 static void
9545 do_mav_ldst_4 (char * str)
9546 {
9547 do_mav_ldst (str, REG_TYPE_MVDX);
9548 }
9549
9550 static void
9551 do_t_nop (char * str)
9552 {
9553 /* Do nothing. */
9554 end_of_line (str);
9555 }
9556
9557 /* Handle the Format 4 instructions that do not have equivalents in other
9558 formats. That is, ADC, AND, EOR, SBC, ROR, TST, NEG, CMN, ORR, MUL,
9559 BIC and MVN. */
9560
9561 static void
9562 do_t_arit (char * str)
9563 {
9564 int Rd, Rs, Rn;
9565
9566 skip_whitespace (str);
9567
9568 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9569 || skip_past_comma (&str) == FAIL
9570 || (Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9571 {
9572 inst.error = BAD_ARGS;
9573 return;
9574 }
9575
9576 if (skip_past_comma (&str) != FAIL)
9577 {
9578 /* Three operand format not allowed for TST, CMN, NEG and MVN.
9579 (It isn't allowed for CMP either, but that isn't handled by this
9580 function.) */
9581 if (inst.instruction == T_OPCODE_TST
9582 || inst.instruction == T_OPCODE_CMN
9583 || inst.instruction == T_OPCODE_NEG
9584 || inst.instruction == T_OPCODE_MVN)
9585 {
9586 inst.error = BAD_ARGS;
9587 return;
9588 }
9589
9590 if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9591 return;
9592
9593 if (Rs != Rd)
9594 {
9595 inst.error = _("dest and source1 must be the same register");
9596 return;
9597 }
9598 Rs = Rn;
9599 }
9600
9601 if (inst.instruction == T_OPCODE_MUL
9602 && Rs == Rd)
9603 as_tsktsk (_("Rs and Rd must be different in MUL"));
9604
9605 inst.instruction |= Rd | (Rs << 3);
9606 end_of_line (str);
9607 }
9608
9609 static void
9610 do_t_add (char * str)
9611 {
9612 thumb_add_sub (str, 0);
9613 }
9614
9615 static void
9616 do_t_asr (char * str)
9617 {
9618 thumb_shift (str, THUMB_ASR);
9619 }
9620
9621 static void
9622 do_t_branch9 (char * str)
9623 {
9624 if (my_get_expression (&inst.reloc.exp, &str))
9625 return;
9626 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH9;
9627 inst.reloc.pc_rel = 1;
9628 end_of_line (str);
9629 }
9630
9631 static void
9632 do_t_branch12 (char * str)
9633 {
9634 if (my_get_expression (&inst.reloc.exp, &str))
9635 return;
9636 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH12;
9637 inst.reloc.pc_rel = 1;
9638 end_of_line (str);
9639 }
9640
9641 /* Find the real, Thumb encoded start of a Thumb function. */
9642
9643 static symbolS *
9644 find_real_start (symbolS * symbolP)
9645 {
9646 char * real_start;
9647 const char * name = S_GET_NAME (symbolP);
9648 symbolS * new_target;
9649
9650 /* This definition must agree with the one in gcc/config/arm/thumb.c. */
9651 #define STUB_NAME ".real_start_of"
9652
9653 if (name == NULL)
9654 abort ();
9655
9656 /* Names that start with '.' are local labels, not function entry points.
9657 The compiler may generate BL instructions to these labels because it
9658 needs to perform a branch to a far away location. */
9659 if (name[0] == '.')
9660 return symbolP;
9661
9662 real_start = malloc (strlen (name) + strlen (STUB_NAME) + 1);
9663 sprintf (real_start, "%s%s", STUB_NAME, name);
9664
9665 new_target = symbol_find (real_start);
9666
9667 if (new_target == NULL)
9668 {
9669 as_warn ("Failed to find real start of function: %s\n", name);
9670 new_target = symbolP;
9671 }
9672
9673 free (real_start);
9674
9675 return new_target;
9676 }
9677
9678 static void
9679 do_t_branch23 (char * str)
9680 {
9681 if (my_get_expression (& inst.reloc.exp, & str))
9682 return;
9683
9684 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH23;
9685 inst.reloc.pc_rel = 1;
9686 end_of_line (str);
9687
9688 /* If the destination of the branch is a defined symbol which does not have
9689 the THUMB_FUNC attribute, then we must be calling a function which has
9690 the (interfacearm) attribute. We look for the Thumb entry point to that
9691 function and change the branch to refer to that function instead. */
9692 if ( inst.reloc.exp.X_op == O_symbol
9693 && inst.reloc.exp.X_add_symbol != NULL
9694 && S_IS_DEFINED (inst.reloc.exp.X_add_symbol)
9695 && ! THUMB_IS_FUNC (inst.reloc.exp.X_add_symbol))
9696 inst.reloc.exp.X_add_symbol =
9697 find_real_start (inst.reloc.exp.X_add_symbol);
9698 }
9699
9700 static void
9701 do_t_bx (char * str)
9702 {
9703 int reg;
9704
9705 skip_whitespace (str);
9706
9707 if ((reg = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
9708 return;
9709
9710 /* This sets THUMB_H2 from the top bit of reg. */
9711 inst.instruction |= reg << 3;
9712
9713 /* ??? FIXME: Should add a hacky reloc here if reg is REG_PC. The reloc
9714 should cause the alignment to be checked once it is known. This is
9715 because BX PC only works if the instruction is word aligned. */
9716
9717 end_of_line (str);
9718 }
9719
9720 static void
9721 do_t_compare (char * str)
9722 {
9723 thumb_mov_compare (str, THUMB_COMPARE);
9724 }
9725
9726 static void
9727 do_t_ldmstm (char * str)
9728 {
9729 int Rb;
9730 long range;
9731
9732 skip_whitespace (str);
9733
9734 if ((Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9735 return;
9736
9737 if (*str != '!')
9738 as_warn (_("inserted missing '!': load/store multiple always writes back base register"));
9739 else
9740 str++;
9741
9742 if (skip_past_comma (&str) == FAIL
9743 || (range = reg_list (&str)) == FAIL)
9744 {
9745 if (! inst.error)
9746 inst.error = BAD_ARGS;
9747 return;
9748 }
9749
9750 if (inst.reloc.type != BFD_RELOC_UNUSED)
9751 {
9752 /* This really doesn't seem worth it. */
9753 inst.reloc.type = BFD_RELOC_UNUSED;
9754 inst.error = _("expression too complex");
9755 return;
9756 }
9757
9758 if (range & ~0xff)
9759 {
9760 inst.error = _("only lo-regs valid in load/store multiple");
9761 return;
9762 }
9763
9764 inst.instruction |= (Rb << 8) | range;
9765 end_of_line (str);
9766 }
9767
9768 static void
9769 do_t_ldr (char * str)
9770 {
9771 thumb_load_store (str, THUMB_LOAD, THUMB_WORD);
9772 }
9773
9774 static void
9775 do_t_ldrb (char * str)
9776 {
9777 thumb_load_store (str, THUMB_LOAD, THUMB_BYTE);
9778 }
9779
9780 static void
9781 do_t_ldrh (char * str)
9782 {
9783 thumb_load_store (str, THUMB_LOAD, THUMB_HALFWORD);
9784 }
9785
9786 static void
9787 do_t_lds (char * str)
9788 {
9789 int Rd, Rb, Ro;
9790
9791 skip_whitespace (str);
9792
9793 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9794 || skip_past_comma (&str) == FAIL
9795 || *str++ != '['
9796 || (Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9797 || skip_past_comma (&str) == FAIL
9798 || (Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9799 || *str++ != ']')
9800 {
9801 if (! inst.error)
9802 inst.error = _("syntax: ldrs[b] Rd, [Rb, Ro]");
9803 return;
9804 }
9805
9806 inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
9807 end_of_line (str);
9808 }
9809
9810 static void
9811 do_t_lsl (char * str)
9812 {
9813 thumb_shift (str, THUMB_LSL);
9814 }
9815
9816 static void
9817 do_t_lsr (char * str)
9818 {
9819 thumb_shift (str, THUMB_LSR);
9820 }
9821
9822 static void
9823 do_t_mov (char * str)
9824 {
9825 thumb_mov_compare (str, THUMB_MOVE);
9826 }
9827
9828 static void
9829 do_t_push_pop (char * str)
9830 {
9831 long range;
9832
9833 skip_whitespace (str);
9834
9835 if ((range = reg_list (&str)) == FAIL)
9836 {
9837 if (! inst.error)
9838 inst.error = BAD_ARGS;
9839 return;
9840 }
9841
9842 if (inst.reloc.type != BFD_RELOC_UNUSED)
9843 {
9844 /* This really doesn't seem worth it. */
9845 inst.reloc.type = BFD_RELOC_UNUSED;
9846 inst.error = _("expression too complex");
9847 return;
9848 }
9849
9850 if (range & ~0xff)
9851 {
9852 if ((inst.instruction == T_OPCODE_PUSH
9853 && (range & ~0xff) == 1 << REG_LR)
9854 || (inst.instruction == T_OPCODE_POP
9855 && (range & ~0xff) == 1 << REG_PC))
9856 {
9857 inst.instruction |= THUMB_PP_PC_LR;
9858 range &= 0xff;
9859 }
9860 else
9861 {
9862 inst.error = _("invalid register list to push/pop instruction");
9863 return;
9864 }
9865 }
9866
9867 inst.instruction |= range;
9868 end_of_line (str);
9869 }
9870
9871 static void
9872 do_t_str (char * str)
9873 {
9874 thumb_load_store (str, THUMB_STORE, THUMB_WORD);
9875 }
9876
9877 static void
9878 do_t_strb (char * str)
9879 {
9880 thumb_load_store (str, THUMB_STORE, THUMB_BYTE);
9881 }
9882
9883 static void
9884 do_t_strh (char * str)
9885 {
9886 thumb_load_store (str, THUMB_STORE, THUMB_HALFWORD);
9887 }
9888
9889 static void
9890 do_t_sub (char * str)
9891 {
9892 thumb_add_sub (str, 1);
9893 }
9894
9895 static void
9896 do_t_swi (char * str)
9897 {
9898 skip_whitespace (str);
9899
9900 if (my_get_expression (&inst.reloc.exp, &str))
9901 return;
9902
9903 inst.reloc.type = BFD_RELOC_ARM_SWI;
9904 end_of_line (str);
9905 }
9906
9907 static void
9908 do_t_adr (char * str)
9909 {
9910 int reg;
9911
9912 /* This is a pseudo-op of the form "adr rd, label" to be converted
9913 into a relative address of the form "add rd, pc, #label-.-4". */
9914 skip_whitespace (str);
9915
9916 /* Store Rd in temporary location inside instruction. */
9917 if ((reg = reg_required_here (&str, 4)) == FAIL
9918 || (reg > 7) /* For Thumb reg must be r0..r7. */
9919 || skip_past_comma (&str) == FAIL
9920 || my_get_expression (&inst.reloc.exp, &str))
9921 {
9922 if (!inst.error)
9923 inst.error = BAD_ARGS;
9924 return;
9925 }
9926
9927 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
9928 inst.reloc.exp.X_add_number -= 4; /* PC relative adjust. */
9929 inst.reloc.pc_rel = 1;
9930 inst.instruction |= REG_PC; /* Rd is already placed into the instruction. */
9931
9932 end_of_line (str);
9933 }
9934
9935 static void
9936 insert_reg (const struct reg_entry * r,
9937 struct hash_control * htab)
9938 {
9939 int len = strlen (r->name) + 2;
9940 char * buf = xmalloc (len);
9941 char * buf2 = xmalloc (len);
9942 int i = 0;
9943
9944 #ifdef REGISTER_PREFIX
9945 buf[i++] = REGISTER_PREFIX;
9946 #endif
9947
9948 strcpy (buf + i, r->name);
9949
9950 for (i = 0; buf[i]; i++)
9951 buf2[i] = TOUPPER (buf[i]);
9952
9953 buf2[i] = '\0';
9954
9955 hash_insert (htab, buf, (PTR) r);
9956 hash_insert (htab, buf2, (PTR) r);
9957 }
9958
9959 static void
9960 build_reg_hsh (struct reg_map * map)
9961 {
9962 const struct reg_entry *r;
9963
9964 if ((map->htab = hash_new ()) == NULL)
9965 as_fatal (_("virtual memory exhausted"));
9966
9967 for (r = map->names; r->name != NULL; r++)
9968 insert_reg (r, map->htab);
9969 }
9970
9971 static void
9972 insert_reg_alias (char * str,
9973 int regnum,
9974 struct hash_control *htab)
9975 {
9976 const char * error;
9977 struct reg_entry * new = xmalloc (sizeof (struct reg_entry));
9978 const char * name = xmalloc (strlen (str) + 1);
9979
9980 strcpy ((char *) name, str);
9981
9982 new->name = name;
9983 new->number = regnum;
9984 new->builtin = FALSE;
9985
9986 error = hash_insert (htab, name, (PTR) new);
9987 if (error)
9988 {
9989 as_bad (_("failed to create an alias for %s, reason: %s"),
9990 str, error);
9991 free ((char *) name);
9992 free (new);
9993 }
9994 }
9995
9996 /* Look for the .req directive. This is of the form:
9997
9998 new_register_name .req existing_register_name
9999
10000 If we find one, or if it looks sufficiently like one that we want to
10001 handle any error here, return non-zero. Otherwise return zero. */
10002
10003 static int
10004 create_register_alias (char * newname, char * p)
10005 {
10006 char * q;
10007 char c;
10008
10009 q = p;
10010 skip_whitespace (q);
10011
10012 c = *p;
10013 *p = '\0';
10014
10015 if (*q && !strncmp (q, ".req ", 5))
10016 {
10017 char *copy_of_str;
10018 char *r;
10019
10020 #ifndef IGNORE_OPCODE_CASE
10021 newname = original_case_string;
10022 #endif
10023 copy_of_str = newname;
10024
10025 q += 4;
10026 skip_whitespace (q);
10027
10028 for (r = q; *r != '\0'; r++)
10029 if (*r == ' ')
10030 break;
10031
10032 if (r != q)
10033 {
10034 enum arm_reg_type new_type, old_type;
10035 int old_regno;
10036 char d = *r;
10037
10038 *r = '\0';
10039 old_type = arm_reg_parse_any (q);
10040 *r = d;
10041
10042 new_type = arm_reg_parse_any (newname);
10043
10044 if (new_type == REG_TYPE_MAX)
10045 {
10046 if (old_type != REG_TYPE_MAX)
10047 {
10048 old_regno = arm_reg_parse (&q, all_reg_maps[old_type].htab);
10049 insert_reg_alias (newname, old_regno,
10050 all_reg_maps[old_type].htab);
10051 }
10052 else
10053 as_warn (_("register '%s' does not exist\n"), q);
10054 }
10055 else if (old_type == REG_TYPE_MAX)
10056 {
10057 as_warn (_("ignoring redefinition of register alias '%s' to non-existant register '%s'"),
10058 copy_of_str, q);
10059 }
10060 else
10061 {
10062 /* Do not warn about redefinitions to the same alias. */
10063 if (new_type != old_type
10064 || (arm_reg_parse (&q, all_reg_maps[old_type].htab)
10065 != arm_reg_parse (&q, all_reg_maps[new_type].htab)))
10066 as_warn (_("ignoring redefinition of register alias '%s'"),
10067 copy_of_str);
10068
10069 }
10070 }
10071 else
10072 as_warn (_("ignoring incomplete .req pseuso op"));
10073
10074 *p = c;
10075 return 1;
10076 }
10077
10078 *p = c;
10079 return 0;
10080 }
10081
10082 static void
10083 set_constant_flonums (void)
10084 {
10085 int i;
10086
10087 for (i = 0; i < NUM_FLOAT_VALS; i++)
10088 if (atof_ieee ((char *) fp_const[i], 'x', fp_values[i]) == NULL)
10089 abort ();
10090 }
10091
10092 \f
10093 static const struct asm_opcode insns[] =
10094 {
10095 /* Core ARM Instructions. */
10096 {"and", 0xe0000000, 3, ARM_EXT_V1, do_arit},
10097 {"ands", 0xe0100000, 3, ARM_EXT_V1, do_arit},
10098 {"eor", 0xe0200000, 3, ARM_EXT_V1, do_arit},
10099 {"eors", 0xe0300000, 3, ARM_EXT_V1, do_arit},
10100 {"sub", 0xe0400000, 3, ARM_EXT_V1, do_arit},
10101 {"subs", 0xe0500000, 3, ARM_EXT_V1, do_arit},
10102 {"rsb", 0xe0600000, 3, ARM_EXT_V1, do_arit},
10103 {"rsbs", 0xe0700000, 3, ARM_EXT_V1, do_arit},
10104 {"add", 0xe0800000, 3, ARM_EXT_V1, do_arit},
10105 {"adds", 0xe0900000, 3, ARM_EXT_V1, do_arit},
10106 {"adc", 0xe0a00000, 3, ARM_EXT_V1, do_arit},
10107 {"adcs", 0xe0b00000, 3, ARM_EXT_V1, do_arit},
10108 {"sbc", 0xe0c00000, 3, ARM_EXT_V1, do_arit},
10109 {"sbcs", 0xe0d00000, 3, ARM_EXT_V1, do_arit},
10110 {"rsc", 0xe0e00000, 3, ARM_EXT_V1, do_arit},
10111 {"rscs", 0xe0f00000, 3, ARM_EXT_V1, do_arit},
10112 {"orr", 0xe1800000, 3, ARM_EXT_V1, do_arit},
10113 {"orrs", 0xe1900000, 3, ARM_EXT_V1, do_arit},
10114 {"bic", 0xe1c00000, 3, ARM_EXT_V1, do_arit},
10115 {"bics", 0xe1d00000, 3, ARM_EXT_V1, do_arit},
10116
10117 {"tst", 0xe1100000, 3, ARM_EXT_V1, do_cmp},
10118 {"tsts", 0xe1100000, 3, ARM_EXT_V1, do_cmp},
10119 {"tstp", 0xe110f000, 3, ARM_EXT_V1, do_cmp},
10120 {"teq", 0xe1300000, 3, ARM_EXT_V1, do_cmp},
10121 {"teqs", 0xe1300000, 3, ARM_EXT_V1, do_cmp},
10122 {"teqp", 0xe130f000, 3, ARM_EXT_V1, do_cmp},
10123 {"cmp", 0xe1500000, 3, ARM_EXT_V1, do_cmp},
10124 {"cmps", 0xe1500000, 3, ARM_EXT_V1, do_cmp},
10125 {"cmpp", 0xe150f000, 3, ARM_EXT_V1, do_cmp},
10126 {"cmn", 0xe1700000, 3, ARM_EXT_V1, do_cmp},
10127 {"cmns", 0xe1700000, 3, ARM_EXT_V1, do_cmp},
10128 {"cmnp", 0xe170f000, 3, ARM_EXT_V1, do_cmp},
10129
10130 {"mov", 0xe1a00000, 3, ARM_EXT_V1, do_mov},
10131 {"movs", 0xe1b00000, 3, ARM_EXT_V1, do_mov},
10132 {"mvn", 0xe1e00000, 3, ARM_EXT_V1, do_mov},
10133 {"mvns", 0xe1f00000, 3, ARM_EXT_V1, do_mov},
10134
10135 {"ldr", 0xe4100000, 3, ARM_EXT_V1, do_ldst},
10136 {"ldrb", 0xe4500000, 3, ARM_EXT_V1, do_ldst},
10137 {"ldrt", 0xe4300000, 3, ARM_EXT_V1, do_ldstt},
10138 {"ldrbt", 0xe4700000, 3, ARM_EXT_V1, do_ldstt},
10139 {"str", 0xe4000000, 3, ARM_EXT_V1, do_ldst},
10140 {"strb", 0xe4400000, 3, ARM_EXT_V1, do_ldst},
10141 {"strt", 0xe4200000, 3, ARM_EXT_V1, do_ldstt},
10142 {"strbt", 0xe4600000, 3, ARM_EXT_V1, do_ldstt},
10143
10144 {"stmia", 0xe8800000, 3, ARM_EXT_V1, do_ldmstm},
10145 {"stmib", 0xe9800000, 3, ARM_EXT_V1, do_ldmstm},
10146 {"stmda", 0xe8000000, 3, ARM_EXT_V1, do_ldmstm},
10147 {"stmdb", 0xe9000000, 3, ARM_EXT_V1, do_ldmstm},
10148 {"stmfd", 0xe9000000, 3, ARM_EXT_V1, do_ldmstm},
10149 {"stmfa", 0xe9800000, 3, ARM_EXT_V1, do_ldmstm},
10150 {"stmea", 0xe8800000, 3, ARM_EXT_V1, do_ldmstm},
10151 {"stmed", 0xe8000000, 3, ARM_EXT_V1, do_ldmstm},
10152
10153 {"ldmia", 0xe8900000, 3, ARM_EXT_V1, do_ldmstm},
10154 {"ldmib", 0xe9900000, 3, ARM_EXT_V1, do_ldmstm},
10155 {"ldmda", 0xe8100000, 3, ARM_EXT_V1, do_ldmstm},
10156 {"ldmdb", 0xe9100000, 3, ARM_EXT_V1, do_ldmstm},
10157 {"ldmfd", 0xe8900000, 3, ARM_EXT_V1, do_ldmstm},
10158 {"ldmfa", 0xe8100000, 3, ARM_EXT_V1, do_ldmstm},
10159 {"ldmea", 0xe9100000, 3, ARM_EXT_V1, do_ldmstm},
10160 {"ldmed", 0xe9900000, 3, ARM_EXT_V1, do_ldmstm},
10161
10162 {"swi", 0xef000000, 3, ARM_EXT_V1, do_swi},
10163 #ifdef TE_WINCE
10164 /* XXX This is the wrong place to do this. Think multi-arch. */
10165 {"bl", 0xeb000000, 2, ARM_EXT_V1, do_branch},
10166 {"b", 0xea000000, 1, ARM_EXT_V1, do_branch},
10167 #else
10168 {"bl", 0xebfffffe, 2, ARM_EXT_V1, do_branch},
10169 {"b", 0xeafffffe, 1, ARM_EXT_V1, do_branch},
10170 #endif
10171
10172 /* Pseudo ops. */
10173 {"adr", 0xe28f0000, 3, ARM_EXT_V1, do_adr},
10174 {"adrl", 0xe28f0000, 3, ARM_EXT_V1, do_adrl},
10175 {"nop", 0xe1a00000, 3, ARM_EXT_V1, do_nop},
10176
10177 /* ARM 2 multiplies. */
10178 {"mul", 0xe0000090, 3, ARM_EXT_V2, do_mul},
10179 {"muls", 0xe0100090, 3, ARM_EXT_V2, do_mul},
10180 {"mla", 0xe0200090, 3, ARM_EXT_V2, do_mla},
10181 {"mlas", 0xe0300090, 3, ARM_EXT_V2, do_mla},
10182
10183 /* Generic coprocessor instructions. */
10184 {"cdp", 0xee000000, 3, ARM_EXT_V2, do_cdp},
10185 {"ldc", 0xec100000, 3, ARM_EXT_V2, do_lstc},
10186 {"ldcl", 0xec500000, 3, ARM_EXT_V2, do_lstc},
10187 {"stc", 0xec000000, 3, ARM_EXT_V2, do_lstc},
10188 {"stcl", 0xec400000, 3, ARM_EXT_V2, do_lstc},
10189 {"mcr", 0xee000010, 3, ARM_EXT_V2, do_co_reg},
10190 {"mrc", 0xee100010, 3, ARM_EXT_V2, do_co_reg},
10191
10192 /* ARM 3 - swp instructions. */
10193 {"swp", 0xe1000090, 3, ARM_EXT_V2S, do_swap},
10194 {"swpb", 0xe1400090, 3, ARM_EXT_V2S, do_swap},
10195
10196 /* ARM 6 Status register instructions. */
10197 {"mrs", 0xe10f0000, 3, ARM_EXT_V3, do_mrs},
10198 {"msr", 0xe120f000, 3, ARM_EXT_V3, do_msr},
10199 /* ScottB: our code uses 0xe128f000 for msr.
10200 NickC: but this is wrong because the bits 16 through 19 are
10201 handled by the PSR_xxx defines above. */
10202
10203 /* ARM 7M long multiplies. */
10204 {"smull", 0xe0c00090, 5, ARM_EXT_V3M, do_mull},
10205 {"smulls", 0xe0d00090, 5, ARM_EXT_V3M, do_mull},
10206 {"umull", 0xe0800090, 5, ARM_EXT_V3M, do_mull},
10207 {"umulls", 0xe0900090, 5, ARM_EXT_V3M, do_mull},
10208 {"smlal", 0xe0e00090, 5, ARM_EXT_V3M, do_mull},
10209 {"smlals", 0xe0f00090, 5, ARM_EXT_V3M, do_mull},
10210 {"umlal", 0xe0a00090, 5, ARM_EXT_V3M, do_mull},
10211 {"umlals", 0xe0b00090, 5, ARM_EXT_V3M, do_mull},
10212
10213 /* ARM Architecture 4. */
10214 {"ldrh", 0xe01000b0, 3, ARM_EXT_V4, do_ldstv4},
10215 {"ldrsh", 0xe01000f0, 3, ARM_EXT_V4, do_ldstv4},
10216 {"ldrsb", 0xe01000d0, 3, ARM_EXT_V4, do_ldstv4},
10217 {"strh", 0xe00000b0, 3, ARM_EXT_V4, do_ldstv4},
10218
10219 /* ARM Architecture 4T. */
10220 /* Note: bx (and blx) are required on V5, even if the processor does
10221 not support Thumb. */
10222 {"bx", 0xe12fff10, 2, ARM_EXT_V4T | ARM_EXT_V5, do_bx},
10223
10224 /* ARM Architecture 5T. */
10225 /* Note: blx has 2 variants, so the .value is set dynamically.
10226 Only one of the variants has conditional execution. */
10227 {"blx", 0xe0000000, 3, ARM_EXT_V5, do_blx},
10228 {"clz", 0xe16f0f10, 3, ARM_EXT_V5, do_clz},
10229 {"bkpt", 0xe1200070, 0, ARM_EXT_V5, do_bkpt},
10230 {"ldc2", 0xfc100000, 0, ARM_EXT_V5, do_lstc2},
10231 {"ldc2l", 0xfc500000, 0, ARM_EXT_V5, do_lstc2},
10232 {"stc2", 0xfc000000, 0, ARM_EXT_V5, do_lstc2},
10233 {"stc2l", 0xfc400000, 0, ARM_EXT_V5, do_lstc2},
10234 {"cdp2", 0xfe000000, 0, ARM_EXT_V5, do_cdp2},
10235 {"mcr2", 0xfe000010, 0, ARM_EXT_V5, do_co_reg2},
10236 {"mrc2", 0xfe100010, 0, ARM_EXT_V5, do_co_reg2},
10237
10238 /* ARM Architecture 5TExP. */
10239 {"smlabb", 0xe1000080, 6, ARM_EXT_V5ExP, do_smla},
10240 {"smlatb", 0xe10000a0, 6, ARM_EXT_V5ExP, do_smla},
10241 {"smlabt", 0xe10000c0, 6, ARM_EXT_V5ExP, do_smla},
10242 {"smlatt", 0xe10000e0, 6, ARM_EXT_V5ExP, do_smla},
10243
10244 {"smlawb", 0xe1200080, 6, ARM_EXT_V5ExP, do_smla},
10245 {"smlawt", 0xe12000c0, 6, ARM_EXT_V5ExP, do_smla},
10246
10247 {"smlalbb", 0xe1400080, 7, ARM_EXT_V5ExP, do_smlal},
10248 {"smlaltb", 0xe14000a0, 7, ARM_EXT_V5ExP, do_smlal},
10249 {"smlalbt", 0xe14000c0, 7, ARM_EXT_V5ExP, do_smlal},
10250 {"smlaltt", 0xe14000e0, 7, ARM_EXT_V5ExP, do_smlal},
10251
10252 {"smulbb", 0xe1600080, 6, ARM_EXT_V5ExP, do_smul},
10253 {"smultb", 0xe16000a0, 6, ARM_EXT_V5ExP, do_smul},
10254 {"smulbt", 0xe16000c0, 6, ARM_EXT_V5ExP, do_smul},
10255 {"smultt", 0xe16000e0, 6, ARM_EXT_V5ExP, do_smul},
10256
10257 {"smulwb", 0xe12000a0, 6, ARM_EXT_V5ExP, do_smul},
10258 {"smulwt", 0xe12000e0, 6, ARM_EXT_V5ExP, do_smul},
10259
10260 {"qadd", 0xe1000050, 4, ARM_EXT_V5ExP, do_qadd},
10261 {"qdadd", 0xe1400050, 5, ARM_EXT_V5ExP, do_qadd},
10262 {"qsub", 0xe1200050, 4, ARM_EXT_V5ExP, do_qadd},
10263 {"qdsub", 0xe1600050, 5, ARM_EXT_V5ExP, do_qadd},
10264
10265 /* ARM Architecture 5TE. */
10266 {"pld", 0xf450f000, 0, ARM_EXT_V5E, do_pld},
10267 {"ldrd", 0xe00000d0, 3, ARM_EXT_V5E, do_ldrd},
10268 {"strd", 0xe00000f0, 3, ARM_EXT_V5E, do_ldrd},
10269
10270 {"mcrr", 0xec400000, 4, ARM_EXT_V5E, do_co_reg2c},
10271 {"mrrc", 0xec500000, 4, ARM_EXT_V5E, do_co_reg2c},
10272
10273 /* ARM Architecture 5TEJ. */
10274 {"bxj", 0xe12fff20, 3, ARM_EXT_V5J, do_bxj},
10275
10276 /* ARM V6. */
10277 { "cps", 0xf1020000, 0, ARM_EXT_V6, do_cps},
10278 { "cpsie", 0xf1080000, 0, ARM_EXT_V6, do_cpsi},
10279 { "cpsid", 0xf10C0000, 0, ARM_EXT_V6, do_cpsi},
10280 { "ldrex", 0xe1900f9f, 5, ARM_EXT_V6, do_ldrex},
10281 { "mcrr2", 0xfc400000, 0, ARM_EXT_V6, do_co_reg2c},
10282 { "mrrc2", 0xfc500000, 0, ARM_EXT_V6, do_co_reg2c},
10283 { "pkhbt", 0xe6800010, 5, ARM_EXT_V6, do_pkhbt},
10284 { "pkhtb", 0xe6800050, 5, ARM_EXT_V6, do_pkhtb},
10285 { "qadd16", 0xe6200f10, 6, ARM_EXT_V6, do_qadd16},
10286 { "qadd8", 0xe6200f90, 5, ARM_EXT_V6, do_qadd16},
10287 { "qaddsubx", 0xe6200f30, 8, ARM_EXT_V6, do_qadd16},
10288 { "qsub16", 0xe6200f70, 6, ARM_EXT_V6, do_qadd16},
10289 { "qsub8", 0xe6200ff0, 5, ARM_EXT_V6, do_qadd16},
10290 { "qsubaddx", 0xe6200f50, 8, ARM_EXT_V6, do_qadd16},
10291 { "sadd16", 0xe6100f10, 6, ARM_EXT_V6, do_qadd16},
10292 { "sadd8", 0xe6100f90, 5, ARM_EXT_V6, do_qadd16},
10293 { "saddsubx", 0xe6100f30, 8, ARM_EXT_V6, do_qadd16},
10294 { "shadd16", 0xe6300f10, 7, ARM_EXT_V6, do_qadd16},
10295 { "shadd8", 0xe6300f90, 6, ARM_EXT_V6, do_qadd16},
10296 { "shaddsubx", 0xe6300f30, 9, ARM_EXT_V6, do_qadd16},
10297 { "shsub16", 0xe6300f70, 7, ARM_EXT_V6, do_qadd16},
10298 { "shsub8", 0xe6300ff0, 6, ARM_EXT_V6, do_qadd16},
10299 { "shsubaddx", 0xe6300f50, 9, ARM_EXT_V6, do_qadd16},
10300 { "ssub16", 0xe6100f70, 6, ARM_EXT_V6, do_qadd16},
10301 { "ssub8", 0xe6100ff0, 5, ARM_EXT_V6, do_qadd16},
10302 { "ssubaddx", 0xe6100f50, 8, ARM_EXT_V6, do_qadd16},
10303 { "uadd16", 0xe6500f10, 6, ARM_EXT_V6, do_qadd16},
10304 { "uadd8", 0xe6500f90, 5, ARM_EXT_V6, do_qadd16},
10305 { "uaddsubx", 0xe6500f30, 8, ARM_EXT_V6, do_qadd16},
10306 { "uhadd16", 0xe6700f10, 7, ARM_EXT_V6, do_qadd16},
10307 { "uhadd8", 0xe6700f90, 6, ARM_EXT_V6, do_qadd16},
10308 { "uhaddsubx", 0xe6700f30, 9, ARM_EXT_V6, do_qadd16},
10309 { "uhsub16", 0xe6700f70, 7, ARM_EXT_V6, do_qadd16},
10310 { "uhsub8", 0xe6700ff0, 6, ARM_EXT_V6, do_qadd16},
10311 { "uhsubaddx", 0xe6700f50, 9, ARM_EXT_V6, do_qadd16},
10312 { "uqadd16", 0xe6600f10, 7, ARM_EXT_V6, do_qadd16},
10313 { "uqadd8", 0xe6600f90, 6, ARM_EXT_V6, do_qadd16},
10314 { "uqaddsubx", 0xe6600f30, 9, ARM_EXT_V6, do_qadd16},
10315 { "uqsub16", 0xe6600f70, 7, ARM_EXT_V6, do_qadd16},
10316 { "uqsub8", 0xe6600ff0, 6, ARM_EXT_V6, do_qadd16},
10317 { "uqsubaddx", 0xe6600f50, 9, ARM_EXT_V6, do_qadd16},
10318 { "usub16", 0xe6500f70, 6, ARM_EXT_V6, do_qadd16},
10319 { "usub8", 0xe6500ff0, 5, ARM_EXT_V6, do_qadd16},
10320 { "usubaddx", 0xe6500f50, 8, ARM_EXT_V6, do_qadd16},
10321 { "rev", 0xe6bf0f30, 3, ARM_EXT_V6, do_rev},
10322 { "rev16", 0xe6bf0fb0, 5, ARM_EXT_V6, do_rev},
10323 { "revsh", 0xe6ff0fb0, 5, ARM_EXT_V6, do_rev},
10324 { "rfeia", 0xf8900a00, 0, ARM_EXT_V6, do_rfe},
10325 { "rfeib", 0xf9900a00, 0, ARM_EXT_V6, do_rfe},
10326 { "rfeda", 0xf8100a00, 0, ARM_EXT_V6, do_rfe},
10327 { "rfedb", 0xf9100a00, 0, ARM_EXT_V6, do_rfe},
10328 { "rfefd", 0xf8900a00, 0, ARM_EXT_V6, do_rfe},
10329 { "rfefa", 0xf9900a00, 0, ARM_EXT_V6, do_rfe},
10330 { "rfeea", 0xf8100a00, 0, ARM_EXT_V6, do_rfe},
10331 { "rfeed", 0xf9100a00, 0, ARM_EXT_V6, do_rfe},
10332 { "sxtah", 0xe6b00070, 5, ARM_EXT_V6, do_sxtah},
10333 { "sxtab16", 0xe6800070, 7, ARM_EXT_V6, do_sxtah},
10334 { "sxtab", 0xe6a00070, 5, ARM_EXT_V6, do_sxtah},
10335 { "sxth", 0xe6bf0070, 4, ARM_EXT_V6, do_sxth},
10336 { "sxtb16", 0xe68f0070, 6, ARM_EXT_V6, do_sxth},
10337 { "sxtb", 0xe6af0070, 4, ARM_EXT_V6, do_sxth},
10338 { "uxtah", 0xe6f00070, 5, ARM_EXT_V6, do_sxtah},
10339 { "uxtab16", 0xe6c00070, 7, ARM_EXT_V6, do_sxtah},
10340 { "uxtab", 0xe6e00070, 5, ARM_EXT_V6, do_sxtah},
10341 { "uxth", 0xe6ff0070, 4, ARM_EXT_V6, do_sxth},
10342 { "uxtb16", 0xe6cf0070, 6, ARM_EXT_V6, do_sxth},
10343 { "uxtb", 0xe6ef0070, 4, ARM_EXT_V6, do_sxth},
10344 { "sel", 0xe68000b0, 3, ARM_EXT_V6, do_qadd16},
10345 { "setend", 0xf1010000, 0, ARM_EXT_V6, do_setend},
10346 { "smlad", 0xe7000010, 5, ARM_EXT_V6, do_smlad},
10347 { "smladx", 0xe7000030, 6, ARM_EXT_V6, do_smlad},
10348 { "smlald", 0xe7400010, 6, ARM_EXT_V6, do_smlald},
10349 { "smlaldx", 0xe7400030, 7, ARM_EXT_V6, do_smlald},
10350 { "smlsd", 0xe7000050, 5, ARM_EXT_V6, do_smlad},
10351 { "smlsdx", 0xe7000070, 6, ARM_EXT_V6, do_smlad},
10352 { "smlsld", 0xe7400050, 6, ARM_EXT_V6, do_smlald},
10353 { "smlsldx", 0xe7400070, 7, ARM_EXT_V6, do_smlald},
10354 { "smmla", 0xe7500010, 5, ARM_EXT_V6, do_smlad},
10355 { "smmlar", 0xe7500030, 6, ARM_EXT_V6, do_smlad},
10356 { "smmls", 0xe75000d0, 5, ARM_EXT_V6, do_smlad},
10357 { "smmlsr", 0xe75000f0, 6, ARM_EXT_V6, do_smlad},
10358 { "smmul", 0xe750f010, 5, ARM_EXT_V6, do_smmul},
10359 { "smmulr", 0xe750f030, 6, ARM_EXT_V6, do_smmul},
10360 { "smuad", 0xe700f010, 5, ARM_EXT_V6, do_smmul},
10361 { "smuadx", 0xe700f030, 6, ARM_EXT_V6, do_smmul},
10362 { "smusd", 0xe700f050, 5, ARM_EXT_V6, do_smmul},
10363 { "smusdx", 0xe700f070, 6, ARM_EXT_V6, do_smmul},
10364 { "srsia", 0xf8cd0500, 0, ARM_EXT_V6, do_srs},
10365 { "srsib", 0xf9cd0500, 0, ARM_EXT_V6, do_srs},
10366 { "srsda", 0xf84d0500, 0, ARM_EXT_V6, do_srs},
10367 { "srsdb", 0xf94d0500, 0, ARM_EXT_V6, do_srs},
10368 { "ssat", 0xe6a00010, 4, ARM_EXT_V6, do_ssat},
10369 { "ssat16", 0xe6a00f30, 6, ARM_EXT_V6, do_ssat16},
10370 { "strex", 0xe1800f90, 5, ARM_EXT_V6, do_strex},
10371 { "umaal", 0xe0400090, 5, ARM_EXT_V6, do_umaal},
10372 { "usad8", 0xe780f010, 5, ARM_EXT_V6, do_smmul},
10373 { "usada8", 0xe7800010, 6, ARM_EXT_V6, do_smlad},
10374 { "usat", 0xe6e00010, 4, ARM_EXT_V6, do_usat},
10375 { "usat16", 0xe6e00f30, 6, ARM_EXT_V6, do_usat16},
10376
10377 /* ARM V6K. */
10378 { "clrex", 0xf57ff01f, 0, ARM_EXT_V6K, do_empty},
10379 { "ldrexb", 0xe1d00f9f, 6, ARM_EXT_V6K, do_ldrex},
10380 { "ldrexd", 0xe1b00f9f, 6, ARM_EXT_V6K, do_ldrex},
10381 { "ldrexh", 0xe1f00f9f, 6, ARM_EXT_V6K, do_ldrex},
10382 { "sev", 0xe320f004, 3, ARM_EXT_V6K, do_empty},
10383 { "strexb", 0xe1c00f90, 6, ARM_EXT_V6K, do_strex},
10384 { "strexd", 0xe1a00f90, 6, ARM_EXT_V6K, do_strex},
10385 { "strexh", 0xe1e00f90, 6, ARM_EXT_V6K, do_strex},
10386 { "wfe", 0xe320f002, 3, ARM_EXT_V6K, do_empty},
10387 { "wfi", 0xe320f003, 3, ARM_EXT_V6K, do_empty},
10388 { "yield", 0xe320f001, 5, ARM_EXT_V6K, do_empty},
10389
10390 /* ARM V6Z. */
10391 { "smi", 0xe1600070, 3, ARM_EXT_V6Z, do_smi},
10392
10393 /* ARM V6T2. */
10394 { "bfc", 0xe7c0001f, 3, ARM_EXT_V6T2, do_bfc},
10395 { "bfi", 0xe7c00010, 3, ARM_EXT_V6T2, do_bfi},
10396 { "mls", 0xe0600090, 3, ARM_EXT_V6T2, do_mls},
10397 { "movw", 0xe3000000, 4, ARM_EXT_V6T2, do_mov16},
10398 { "movt", 0xe3400000, 4, ARM_EXT_V6T2, do_mov16},
10399 { "rbit", 0xe3ff0f30, 4, ARM_EXT_V6T2, do_rbit},
10400 { "sbfx", 0xe7a00050, 4, ARM_EXT_V6T2, do_bfx},
10401 { "ubfx", 0xe7e00050, 4, ARM_EXT_V6T2, do_bfx},
10402
10403 { "ldrht", 0xe03000b0, 3, ARM_EXT_V6T2, do_ldsttv4},
10404 { "ldrsht", 0xe03000f0, 3, ARM_EXT_V6T2, do_ldsttv4},
10405 { "ldrsbt", 0xe03000d0, 3, ARM_EXT_V6T2, do_ldsttv4},
10406 { "strht", 0xe02000b0, 3, ARM_EXT_V6T2, do_ldsttv4},
10407
10408 /* Core FPA instruction set (V1). */
10409 {"wfs", 0xee200110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
10410 {"rfs", 0xee300110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
10411 {"wfc", 0xee400110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
10412 {"rfc", 0xee500110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
10413
10414 {"ldfs", 0xec100100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10415 {"ldfd", 0xec108100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10416 {"ldfe", 0xec500100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10417 {"ldfp", 0xec508100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10418
10419 {"stfs", 0xec000100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10420 {"stfd", 0xec008100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10421 {"stfe", 0xec400100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10422 {"stfp", 0xec408100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10423
10424 {"mvfs", 0xee008100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10425 {"mvfsp", 0xee008120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10426 {"mvfsm", 0xee008140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10427 {"mvfsz", 0xee008160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10428 {"mvfd", 0xee008180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10429 {"mvfdp", 0xee0081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10430 {"mvfdm", 0xee0081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10431 {"mvfdz", 0xee0081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10432 {"mvfe", 0xee088100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10433 {"mvfep", 0xee088120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10434 {"mvfem", 0xee088140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10435 {"mvfez", 0xee088160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10436
10437 {"mnfs", 0xee108100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10438 {"mnfsp", 0xee108120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10439 {"mnfsm", 0xee108140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10440 {"mnfsz", 0xee108160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10441 {"mnfd", 0xee108180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10442 {"mnfdp", 0xee1081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10443 {"mnfdm", 0xee1081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10444 {"mnfdz", 0xee1081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10445 {"mnfe", 0xee188100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10446 {"mnfep", 0xee188120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10447 {"mnfem", 0xee188140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10448 {"mnfez", 0xee188160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10449
10450 {"abss", 0xee208100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10451 {"abssp", 0xee208120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10452 {"abssm", 0xee208140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10453 {"abssz", 0xee208160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10454 {"absd", 0xee208180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10455 {"absdp", 0xee2081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10456 {"absdm", 0xee2081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10457 {"absdz", 0xee2081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10458 {"abse", 0xee288100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10459 {"absep", 0xee288120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10460 {"absem", 0xee288140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10461 {"absez", 0xee288160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10462
10463 {"rnds", 0xee308100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10464 {"rndsp", 0xee308120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10465 {"rndsm", 0xee308140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10466 {"rndsz", 0xee308160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10467 {"rndd", 0xee308180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10468 {"rnddp", 0xee3081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10469 {"rnddm", 0xee3081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10470 {"rnddz", 0xee3081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10471 {"rnde", 0xee388100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10472 {"rndep", 0xee388120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10473 {"rndem", 0xee388140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10474 {"rndez", 0xee388160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10475
10476 {"sqts", 0xee408100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10477 {"sqtsp", 0xee408120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10478 {"sqtsm", 0xee408140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10479 {"sqtsz", 0xee408160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10480 {"sqtd", 0xee408180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10481 {"sqtdp", 0xee4081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10482 {"sqtdm", 0xee4081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10483 {"sqtdz", 0xee4081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10484 {"sqte", 0xee488100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10485 {"sqtep", 0xee488120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10486 {"sqtem", 0xee488140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10487 {"sqtez", 0xee488160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10488
10489 {"logs", 0xee508100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10490 {"logsp", 0xee508120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10491 {"logsm", 0xee508140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10492 {"logsz", 0xee508160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10493 {"logd", 0xee508180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10494 {"logdp", 0xee5081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10495 {"logdm", 0xee5081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10496 {"logdz", 0xee5081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10497 {"loge", 0xee588100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10498 {"logep", 0xee588120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10499 {"logem", 0xee588140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10500 {"logez", 0xee588160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10501
10502 {"lgns", 0xee608100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10503 {"lgnsp", 0xee608120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10504 {"lgnsm", 0xee608140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10505 {"lgnsz", 0xee608160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10506 {"lgnd", 0xee608180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10507 {"lgndp", 0xee6081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10508 {"lgndm", 0xee6081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10509 {"lgndz", 0xee6081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10510 {"lgne", 0xee688100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10511 {"lgnep", 0xee688120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10512 {"lgnem", 0xee688140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10513 {"lgnez", 0xee688160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10514
10515 {"exps", 0xee708100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10516 {"expsp", 0xee708120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10517 {"expsm", 0xee708140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10518 {"expsz", 0xee708160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10519 {"expd", 0xee708180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10520 {"expdp", 0xee7081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10521 {"expdm", 0xee7081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10522 {"expdz", 0xee7081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10523 {"expe", 0xee788100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10524 {"expep", 0xee788120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10525 {"expem", 0xee788140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10526 {"expdz", 0xee788160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10527
10528 {"sins", 0xee808100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10529 {"sinsp", 0xee808120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10530 {"sinsm", 0xee808140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10531 {"sinsz", 0xee808160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10532 {"sind", 0xee808180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10533 {"sindp", 0xee8081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10534 {"sindm", 0xee8081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10535 {"sindz", 0xee8081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10536 {"sine", 0xee888100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10537 {"sinep", 0xee888120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10538 {"sinem", 0xee888140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10539 {"sinez", 0xee888160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10540
10541 {"coss", 0xee908100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10542 {"cossp", 0xee908120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10543 {"cossm", 0xee908140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10544 {"cossz", 0xee908160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10545 {"cosd", 0xee908180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10546 {"cosdp", 0xee9081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10547 {"cosdm", 0xee9081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10548 {"cosdz", 0xee9081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10549 {"cose", 0xee988100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10550 {"cosep", 0xee988120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10551 {"cosem", 0xee988140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10552 {"cosez", 0xee988160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10553
10554 {"tans", 0xeea08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10555 {"tansp", 0xeea08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10556 {"tansm", 0xeea08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10557 {"tansz", 0xeea08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10558 {"tand", 0xeea08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10559 {"tandp", 0xeea081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10560 {"tandm", 0xeea081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10561 {"tandz", 0xeea081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10562 {"tane", 0xeea88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10563 {"tanep", 0xeea88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10564 {"tanem", 0xeea88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10565 {"tanez", 0xeea88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10566
10567 {"asns", 0xeeb08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10568 {"asnsp", 0xeeb08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10569 {"asnsm", 0xeeb08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10570 {"asnsz", 0xeeb08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10571 {"asnd", 0xeeb08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10572 {"asndp", 0xeeb081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10573 {"asndm", 0xeeb081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10574 {"asndz", 0xeeb081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10575 {"asne", 0xeeb88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10576 {"asnep", 0xeeb88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10577 {"asnem", 0xeeb88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10578 {"asnez", 0xeeb88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10579
10580 {"acss", 0xeec08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10581 {"acssp", 0xeec08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10582 {"acssm", 0xeec08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10583 {"acssz", 0xeec08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10584 {"acsd", 0xeec08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10585 {"acsdp", 0xeec081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10586 {"acsdm", 0xeec081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10587 {"acsdz", 0xeec081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10588 {"acse", 0xeec88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10589 {"acsep", 0xeec88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10590 {"acsem", 0xeec88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10591 {"acsez", 0xeec88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10592
10593 {"atns", 0xeed08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10594 {"atnsp", 0xeed08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10595 {"atnsm", 0xeed08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10596 {"atnsz", 0xeed08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10597 {"atnd", 0xeed08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10598 {"atndp", 0xeed081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10599 {"atndm", 0xeed081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10600 {"atndz", 0xeed081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10601 {"atne", 0xeed88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10602 {"atnep", 0xeed88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10603 {"atnem", 0xeed88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10604 {"atnez", 0xeed88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10605
10606 {"urds", 0xeee08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10607 {"urdsp", 0xeee08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10608 {"urdsm", 0xeee08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10609 {"urdsz", 0xeee08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10610 {"urdd", 0xeee08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10611 {"urddp", 0xeee081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10612 {"urddm", 0xeee081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10613 {"urddz", 0xeee081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10614 {"urde", 0xeee88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10615 {"urdep", 0xeee88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10616 {"urdem", 0xeee88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10617 {"urdez", 0xeee88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10618
10619 {"nrms", 0xeef08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10620 {"nrmsp", 0xeef08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10621 {"nrmsm", 0xeef08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10622 {"nrmsz", 0xeef08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10623 {"nrmd", 0xeef08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10624 {"nrmdp", 0xeef081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10625 {"nrmdm", 0xeef081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10626 {"nrmdz", 0xeef081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10627 {"nrme", 0xeef88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10628 {"nrmep", 0xeef88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10629 {"nrmem", 0xeef88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10630 {"nrmez", 0xeef88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10631
10632 {"adfs", 0xee000100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10633 {"adfsp", 0xee000120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10634 {"adfsm", 0xee000140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10635 {"adfsz", 0xee000160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10636 {"adfd", 0xee000180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10637 {"adfdp", 0xee0001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10638 {"adfdm", 0xee0001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10639 {"adfdz", 0xee0001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10640 {"adfe", 0xee080100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10641 {"adfep", 0xee080120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10642 {"adfem", 0xee080140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10643 {"adfez", 0xee080160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10644
10645 {"sufs", 0xee200100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10646 {"sufsp", 0xee200120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10647 {"sufsm", 0xee200140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10648 {"sufsz", 0xee200160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10649 {"sufd", 0xee200180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10650 {"sufdp", 0xee2001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10651 {"sufdm", 0xee2001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10652 {"sufdz", 0xee2001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10653 {"sufe", 0xee280100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10654 {"sufep", 0xee280120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10655 {"sufem", 0xee280140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10656 {"sufez", 0xee280160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10657
10658 {"rsfs", 0xee300100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10659 {"rsfsp", 0xee300120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10660 {"rsfsm", 0xee300140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10661 {"rsfsz", 0xee300160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10662 {"rsfd", 0xee300180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10663 {"rsfdp", 0xee3001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10664 {"rsfdm", 0xee3001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10665 {"rsfdz", 0xee3001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10666 {"rsfe", 0xee380100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10667 {"rsfep", 0xee380120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10668 {"rsfem", 0xee380140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10669 {"rsfez", 0xee380160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10670
10671 {"mufs", 0xee100100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10672 {"mufsp", 0xee100120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10673 {"mufsm", 0xee100140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10674 {"mufsz", 0xee100160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10675 {"mufd", 0xee100180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10676 {"mufdp", 0xee1001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10677 {"mufdm", 0xee1001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10678 {"mufdz", 0xee1001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10679 {"mufe", 0xee180100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10680 {"mufep", 0xee180120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10681 {"mufem", 0xee180140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10682 {"mufez", 0xee180160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10683
10684 {"dvfs", 0xee400100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10685 {"dvfsp", 0xee400120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10686 {"dvfsm", 0xee400140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10687 {"dvfsz", 0xee400160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10688 {"dvfd", 0xee400180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10689 {"dvfdp", 0xee4001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10690 {"dvfdm", 0xee4001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10691 {"dvfdz", 0xee4001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10692 {"dvfe", 0xee480100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10693 {"dvfep", 0xee480120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10694 {"dvfem", 0xee480140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10695 {"dvfez", 0xee480160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10696
10697 {"rdfs", 0xee500100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10698 {"rdfsp", 0xee500120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10699 {"rdfsm", 0xee500140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10700 {"rdfsz", 0xee500160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10701 {"rdfd", 0xee500180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10702 {"rdfdp", 0xee5001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10703 {"rdfdm", 0xee5001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10704 {"rdfdz", 0xee5001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10705 {"rdfe", 0xee580100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10706 {"rdfep", 0xee580120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10707 {"rdfem", 0xee580140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10708 {"rdfez", 0xee580160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10709
10710 {"pows", 0xee600100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10711 {"powsp", 0xee600120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10712 {"powsm", 0xee600140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10713 {"powsz", 0xee600160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10714 {"powd", 0xee600180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10715 {"powdp", 0xee6001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10716 {"powdm", 0xee6001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10717 {"powdz", 0xee6001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10718 {"powe", 0xee680100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10719 {"powep", 0xee680120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10720 {"powem", 0xee680140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10721 {"powez", 0xee680160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10722
10723 {"rpws", 0xee700100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10724 {"rpwsp", 0xee700120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10725 {"rpwsm", 0xee700140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10726 {"rpwsz", 0xee700160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10727 {"rpwd", 0xee700180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10728 {"rpwdp", 0xee7001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10729 {"rpwdm", 0xee7001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10730 {"rpwdz", 0xee7001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10731 {"rpwe", 0xee780100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10732 {"rpwep", 0xee780120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10733 {"rpwem", 0xee780140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10734 {"rpwez", 0xee780160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10735
10736 {"rmfs", 0xee800100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10737 {"rmfsp", 0xee800120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10738 {"rmfsm", 0xee800140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10739 {"rmfsz", 0xee800160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10740 {"rmfd", 0xee800180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10741 {"rmfdp", 0xee8001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10742 {"rmfdm", 0xee8001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10743 {"rmfdz", 0xee8001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10744 {"rmfe", 0xee880100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10745 {"rmfep", 0xee880120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10746 {"rmfem", 0xee880140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10747 {"rmfez", 0xee880160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10748
10749 {"fmls", 0xee900100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10750 {"fmlsp", 0xee900120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10751 {"fmlsm", 0xee900140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10752 {"fmlsz", 0xee900160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10753 {"fmld", 0xee900180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10754 {"fmldp", 0xee9001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10755 {"fmldm", 0xee9001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10756 {"fmldz", 0xee9001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10757 {"fmle", 0xee980100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10758 {"fmlep", 0xee980120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10759 {"fmlem", 0xee980140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10760 {"fmlez", 0xee980160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10761
10762 {"fdvs", 0xeea00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10763 {"fdvsp", 0xeea00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10764 {"fdvsm", 0xeea00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10765 {"fdvsz", 0xeea00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10766 {"fdvd", 0xeea00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10767 {"fdvdp", 0xeea001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10768 {"fdvdm", 0xeea001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10769 {"fdvdz", 0xeea001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10770 {"fdve", 0xeea80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10771 {"fdvep", 0xeea80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10772 {"fdvem", 0xeea80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10773 {"fdvez", 0xeea80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10774
10775 {"frds", 0xeeb00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10776 {"frdsp", 0xeeb00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10777 {"frdsm", 0xeeb00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10778 {"frdsz", 0xeeb00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10779 {"frdd", 0xeeb00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10780 {"frddp", 0xeeb001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10781 {"frddm", 0xeeb001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10782 {"frddz", 0xeeb001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10783 {"frde", 0xeeb80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10784 {"frdep", 0xeeb80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10785 {"frdem", 0xeeb80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10786 {"frdez", 0xeeb80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10787
10788 {"pols", 0xeec00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10789 {"polsp", 0xeec00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10790 {"polsm", 0xeec00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10791 {"polsz", 0xeec00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10792 {"pold", 0xeec00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10793 {"poldp", 0xeec001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10794 {"poldm", 0xeec001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10795 {"poldz", 0xeec001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10796 {"pole", 0xeec80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10797 {"polep", 0xeec80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10798 {"polem", 0xeec80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10799 {"polez", 0xeec80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10800
10801 {"cmf", 0xee90f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
10802 {"cmfe", 0xeed0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
10803 {"cnf", 0xeeb0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
10804 {"cnfe", 0xeef0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
10805 /* The FPA10 data sheet suggests that the 'E' of cmfe/cnfe should
10806 not be an optional suffix, but part of the instruction. To be
10807 compatible, we accept either. */
10808 {"cmfe", 0xeed0f110, 4, FPU_FPA_EXT_V1, do_fpa_cmp},
10809 {"cnfe", 0xeef0f110, 4, FPU_FPA_EXT_V1, do_fpa_cmp},
10810
10811 {"flts", 0xee000110, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10812 {"fltsp", 0xee000130, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10813 {"fltsm", 0xee000150, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10814 {"fltsz", 0xee000170, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10815 {"fltd", 0xee000190, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10816 {"fltdp", 0xee0001b0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10817 {"fltdm", 0xee0001d0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10818 {"fltdz", 0xee0001f0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10819 {"flte", 0xee080110, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10820 {"fltep", 0xee080130, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10821 {"fltem", 0xee080150, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10822 {"fltez", 0xee080170, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10823
10824 /* The implementation of the FIX instruction is broken on some
10825 assemblers, in that it accepts a precision specifier as well as a
10826 rounding specifier, despite the fact that this is meaningless.
10827 To be more compatible, we accept it as well, though of course it
10828 does not set any bits. */
10829 {"fix", 0xee100110, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10830 {"fixp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10831 {"fixm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10832 {"fixz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10833 {"fixsp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10834 {"fixsm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10835 {"fixsz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10836 {"fixdp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10837 {"fixdm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10838 {"fixdz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10839 {"fixep", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10840 {"fixem", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10841 {"fixez", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10842
10843 /* Instructions that were new with the real FPA, call them V2. */
10844 {"lfm", 0xec100200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10845 {"lfmfd", 0xec900200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10846 {"lfmea", 0xed100200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10847 {"sfm", 0xec000200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10848 {"sfmfd", 0xed000200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10849 {"sfmea", 0xec800200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10850
10851 /* VFP V1xD (single precision). */
10852 /* Moves and type conversions. */
10853 {"fcpys", 0xeeb00a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10854 {"fmrs", 0xee100a10, 4, FPU_VFP_EXT_V1xD, do_vfp_reg_from_sp},
10855 {"fmsr", 0xee000a10, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_from_reg},
10856 {"fmstat", 0xeef1fa10, 6, FPU_VFP_EXT_V1xD, do_empty},
10857 {"fsitos", 0xeeb80ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10858 {"fuitos", 0xeeb80a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10859 {"ftosis", 0xeebd0a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10860 {"ftosizs", 0xeebd0ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10861 {"ftouis", 0xeebc0a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10862 {"ftouizs", 0xeebc0ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10863 {"fmrx", 0xeef00a10, 4, FPU_VFP_EXT_V1xD, do_vfp_reg_from_ctrl},
10864 {"fmxr", 0xeee00a10, 4, FPU_VFP_EXT_V1xD, do_vfp_ctrl_from_reg},
10865
10866 /* Memory operations. */
10867 {"flds", 0xed100a00, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_ldst},
10868 {"fsts", 0xed000a00, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_ldst},
10869 {"fldmias", 0xec900a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
10870 {"fldmfds", 0xec900a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
10871 {"fldmdbs", 0xed300a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
10872 {"fldmeas", 0xed300a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
10873 {"fldmiax", 0xec900b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
10874 {"fldmfdx", 0xec900b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
10875 {"fldmdbx", 0xed300b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
10876 {"fldmeax", 0xed300b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
10877 {"fstmias", 0xec800a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
10878 {"fstmeas", 0xec800a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
10879 {"fstmdbs", 0xed200a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
10880 {"fstmfds", 0xed200a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
10881 {"fstmiax", 0xec800b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
10882 {"fstmeax", 0xec800b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
10883 {"fstmdbx", 0xed200b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
10884 {"fstmfdx", 0xed200b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
10885
10886 /* Monadic operations. */
10887 {"fabss", 0xeeb00ac0, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10888 {"fnegs", 0xeeb10a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10889 {"fsqrts", 0xeeb10ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10890
10891 /* Dyadic operations. */
10892 {"fadds", 0xee300a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10893 {"fsubs", 0xee300a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10894 {"fmuls", 0xee200a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10895 {"fdivs", 0xee800a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10896 {"fmacs", 0xee000a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10897 {"fmscs", 0xee100a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10898 {"fnmuls", 0xee200a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10899 {"fnmacs", 0xee000a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10900 {"fnmscs", 0xee100a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10901
10902 /* Comparisons. */
10903 {"fcmps", 0xeeb40a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10904 {"fcmpzs", 0xeeb50a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_compare_z},
10905 {"fcmpes", 0xeeb40ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10906 {"fcmpezs", 0xeeb50ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_compare_z},
10907
10908 /* VFP V1 (Double precision). */
10909 /* Moves and type conversions. */
10910 {"fcpyd", 0xeeb00b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10911 {"fcvtds", 0xeeb70ac0, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
10912 {"fcvtsd", 0xeeb70bc0, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
10913 {"fmdhr", 0xee200b10, 5, FPU_VFP_EXT_V1, do_vfp_dp_from_reg},
10914 {"fmdlr", 0xee000b10, 5, FPU_VFP_EXT_V1, do_vfp_dp_from_reg},
10915 {"fmrdh", 0xee300b10, 5, FPU_VFP_EXT_V1, do_vfp_reg_from_dp},
10916 {"fmrdl", 0xee100b10, 5, FPU_VFP_EXT_V1, do_vfp_reg_from_dp},
10917 {"fsitod", 0xeeb80bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
10918 {"fuitod", 0xeeb80b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
10919 {"ftosid", 0xeebd0b40, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
10920 {"ftosizd", 0xeebd0bc0, 7, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
10921 {"ftouid", 0xeebc0b40, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
10922 {"ftouizd", 0xeebc0bc0, 7, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
10923
10924 /* Memory operations. */
10925 {"fldd", 0xed100b00, 4, FPU_VFP_EXT_V1, do_vfp_dp_ldst},
10926 {"fstd", 0xed000b00, 4, FPU_VFP_EXT_V1, do_vfp_dp_ldst},
10927 {"fldmiad", 0xec900b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
10928 {"fldmfdd", 0xec900b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
10929 {"fldmdbd", 0xed300b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
10930 {"fldmead", 0xed300b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
10931 {"fstmiad", 0xec800b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
10932 {"fstmead", 0xec800b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
10933 {"fstmdbd", 0xed200b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
10934 {"fstmfdd", 0xed200b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
10935
10936 /* Monadic operations. */
10937 {"fabsd", 0xeeb00bc0, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10938 {"fnegd", 0xeeb10b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10939 {"fsqrtd", 0xeeb10bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10940
10941 /* Dyadic operations. */
10942 {"faddd", 0xee300b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10943 {"fsubd", 0xee300b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10944 {"fmuld", 0xee200b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10945 {"fdivd", 0xee800b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10946 {"fmacd", 0xee000b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10947 {"fmscd", 0xee100b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10948 {"fnmuld", 0xee200b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10949 {"fnmacd", 0xee000b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10950 {"fnmscd", 0xee100b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10951
10952 /* Comparisons. */
10953 {"fcmpd", 0xeeb40b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10954 {"fcmpzd", 0xeeb50b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_compare_z},
10955 {"fcmped", 0xeeb40bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10956 {"fcmpezd", 0xeeb50bc0, 7, FPU_VFP_EXT_V1, do_vfp_dp_compare_z},
10957
10958 /* VFP V2. */
10959 {"fmsrr", 0xec400a10, 5, FPU_VFP_EXT_V2, do_vfp_sp2_from_reg2},
10960 {"fmrrs", 0xec500a10, 5, FPU_VFP_EXT_V2, do_vfp_reg2_from_sp2},
10961 {"fmdrr", 0xec400b10, 5, FPU_VFP_EXT_V2, do_vfp_dp_from_reg2},
10962 {"fmrrd", 0xec500b10, 5, FPU_VFP_EXT_V2, do_vfp_reg2_from_dp},
10963
10964 /* Intel XScale extensions to ARM V5 ISA. (All use CP0). */
10965 {"mia", 0xee200010, 3, ARM_CEXT_XSCALE, do_xsc_mia},
10966 {"miaph", 0xee280010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
10967 {"miabb", 0xee2c0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
10968 {"miabt", 0xee2d0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
10969 {"miatb", 0xee2e0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
10970 {"miatt", 0xee2f0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
10971 {"mar", 0xec400000, 3, ARM_CEXT_XSCALE, do_xsc_mar},
10972 {"mra", 0xec500000, 3, ARM_CEXT_XSCALE, do_xsc_mra},
10973
10974 /* Intel Wireless MMX technology instructions. */
10975 {"tandcb", 0xee130130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
10976 {"tandch", 0xee530130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
10977 {"tandcw", 0xee930130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
10978 {"tbcstb", 0xee400010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
10979 {"tbcsth", 0xee400050, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
10980 {"tbcstw", 0xee400090, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
10981 {"textrcb", 0xee130170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
10982 {"textrch", 0xee530170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
10983 {"textrcw", 0xee930170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
10984 {"textrmub", 0xee100070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10985 {"textrmuh", 0xee500070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10986 {"textrmuw", 0xee900070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10987 {"textrmsb", 0xee100078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10988 {"textrmsh", 0xee500078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10989 {"textrmsw", 0xee900078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10990 {"tinsrb", 0xee600010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
10991 {"tinsrh", 0xee600050, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
10992 {"tinsrw", 0xee600090, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
10993 {"tmcr", 0xee000110, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmcr},
10994 {"tmcrr", 0xec400000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_tmcrr},
10995 {"tmia", 0xee200010, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10996 {"tmiaph", 0xee280010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10997 {"tmiabb", 0xee2c0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10998 {"tmiabt", 0xee2d0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10999 {"tmiatb", 0xee2e0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
11000 {"tmiatt", 0xee2f0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
11001 {"tmovmskb", 0xee100030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
11002 {"tmovmskh", 0xee500030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
11003 {"tmovmskw", 0xee900030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
11004 {"tmrc", 0xee100110, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmrc},
11005 {"tmrrc", 0xec500000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_tmrrc},
11006 {"torcb", 0xee130150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
11007 {"torch", 0xee530150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
11008 {"torcw", 0xee930150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
11009 {"waccb", 0xee0001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11010 {"wacch", 0xee4001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11011 {"waccw", 0xee8001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11012 {"waddbss", 0xee300180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11013 {"waddb", 0xee000180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11014 {"waddbus", 0xee100180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11015 {"waddhss", 0xee700180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11016 {"waddh", 0xee400180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11017 {"waddhus", 0xee500180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11018 {"waddwss", 0xeeb00180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11019 {"waddw", 0xee800180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11020 {"waddwus", 0xee900180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11021 {"waligni", 0xee000020, 7, ARM_CEXT_IWMMXT, do_iwmmxt_waligni},
11022 {"walignr0", 0xee800020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11023 {"walignr1", 0xee900020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11024 {"walignr2", 0xeea00020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11025 {"walignr3", 0xeeb00020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11026 {"wand", 0xee200000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11027 {"wandn", 0xee300000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11028 {"wavg2b", 0xee800000, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11029 {"wavg2br", 0xee900000, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11030 {"wavg2h", 0xeec00000, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11031 {"wavg2hr", 0xeed00000, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11032 {"wcmpeqb", 0xee000060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11033 {"wcmpeqh", 0xee400060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11034 {"wcmpeqw", 0xee800060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11035 {"wcmpgtub", 0xee100060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11036 {"wcmpgtuh", 0xee500060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11037 {"wcmpgtuw", 0xee900060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11038 {"wcmpgtsb", 0xee300060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11039 {"wcmpgtsh", 0xee700060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11040 {"wcmpgtsw", 0xeeb00060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11041 {"wldrb", 0xec100000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
11042 {"wldrh", 0xec100100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
11043 {"wldrw", 0xec100200, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
11044 {"wldrd", 0xec100300, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
11045 {"wmacs", 0xee600100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11046 {"wmacsz", 0xee700100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11047 {"wmacu", 0xee400100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11048 {"wmacuz", 0xee500100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11049 {"wmadds", 0xeea00100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11050 {"wmaddu", 0xee800100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11051 {"wmaxsb", 0xee200160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11052 {"wmaxsh", 0xee600160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11053 {"wmaxsw", 0xeea00160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11054 {"wmaxub", 0xee000160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11055 {"wmaxuh", 0xee400160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11056 {"wmaxuw", 0xee800160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11057 {"wminsb", 0xee300160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11058 {"wminsh", 0xee700160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11059 {"wminsw", 0xeeb00160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11060 {"wminub", 0xee100160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11061 {"wminuh", 0xee500160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11062 {"wminuw", 0xee900160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11063 {"wmov", 0xee000000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wmov},
11064 {"wmulsm", 0xee300100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11065 {"wmulsl", 0xee200100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11066 {"wmulum", 0xee100100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11067 {"wmulul", 0xee000100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11068 {"wor", 0xee000000, 3, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11069 {"wpackhss", 0xee700080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11070 {"wpackhus", 0xee500080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11071 {"wpackwss", 0xeeb00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11072 {"wpackwus", 0xee900080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11073 {"wpackdss", 0xeef00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11074 {"wpackdus", 0xeed00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11075 {"wrorh", 0xee700040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11076 {"wrorhg", 0xee700148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11077 {"wrorw", 0xeeb00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11078 {"wrorwg", 0xeeb00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11079 {"wrord", 0xeef00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11080 {"wrordg", 0xeef00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11081 {"wsadb", 0xee000120, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11082 {"wsadbz", 0xee100120, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11083 {"wsadh", 0xee400120, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11084 {"wsadhz", 0xee500120, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11085 {"wshufh", 0xee0001e0, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wshufh},
11086 {"wsllh", 0xee500040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11087 {"wsllhg", 0xee500148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11088 {"wsllw", 0xee900040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11089 {"wsllwg", 0xee900148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11090 {"wslld", 0xeed00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11091 {"wslldg", 0xeed00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11092 {"wsrah", 0xee400040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11093 {"wsrahg", 0xee400148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11094 {"wsraw", 0xee800040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11095 {"wsrawg", 0xee800148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11096 {"wsrad", 0xeec00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11097 {"wsradg", 0xeec00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11098 {"wsrlh", 0xee600040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11099 {"wsrlhg", 0xee600148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11100 {"wsrlw", 0xeea00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11101 {"wsrlwg", 0xeea00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11102 {"wsrld", 0xeee00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11103 {"wsrldg", 0xeee00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11104 {"wstrb", 0xec000000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
11105 {"wstrh", 0xec000100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
11106 {"wstrw", 0xec000200, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
11107 {"wstrd", 0xec000300, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
11108 {"wsubbss", 0xee3001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11109 {"wsubb", 0xee0001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11110 {"wsubbus", 0xee1001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11111 {"wsubhss", 0xee7001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11112 {"wsubh", 0xee4001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11113 {"wsubhus", 0xee5001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11114 {"wsubwss", 0xeeb001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11115 {"wsubw", 0xee8001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11116 {"wsubwus", 0xee9001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11117 {"wunpckehub", 0xee0000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11118 {"wunpckehuh", 0xee4000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11119 {"wunpckehuw", 0xee8000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11120 {"wunpckehsb", 0xee2000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11121 {"wunpckehsh", 0xee6000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11122 {"wunpckehsw", 0xeea000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11123 {"wunpckihb", 0xee1000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11124 {"wunpckihh", 0xee5000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11125 {"wunpckihw", 0xee9000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11126 {"wunpckelub", 0xee0000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11127 {"wunpckeluh", 0xee4000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11128 {"wunpckeluw", 0xee8000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11129 {"wunpckelsb", 0xee2000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11130 {"wunpckelsh", 0xee6000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11131 {"wunpckelsw", 0xeea000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11132 {"wunpckilb", 0xee1000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11133 {"wunpckilh", 0xee5000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11134 {"wunpckilw", 0xee9000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11135 {"wxor", 0xee100000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11136 {"wzero", 0xee300000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wzero},
11137
11138 /* Cirrus Maverick instructions. */
11139 {"cfldrs", 0xec100400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_1},
11140 {"cfldrd", 0xec500400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_2},
11141 {"cfldr32", 0xec100500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_3},
11142 {"cfldr64", 0xec500500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_4},
11143 {"cfstrs", 0xec000400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_1},
11144 {"cfstrd", 0xec400400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_2},
11145 {"cfstr32", 0xec000500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_3},
11146 {"cfstr64", 0xec400500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_4},
11147 {"cfmvsr", 0xee000450, 6, ARM_CEXT_MAVERICK, do_mav_binops_2a},
11148 {"cfmvrs", 0xee100450, 6, ARM_CEXT_MAVERICK, do_mav_binops_1a},
11149 {"cfmvdlr", 0xee000410, 7, ARM_CEXT_MAVERICK, do_mav_binops_2b},
11150 {"cfmvrdl", 0xee100410, 7, ARM_CEXT_MAVERICK, do_mav_binops_1b},
11151 {"cfmvdhr", 0xee000430, 7, ARM_CEXT_MAVERICK, do_mav_binops_2b},
11152 {"cfmvrdh", 0xee100430, 7, ARM_CEXT_MAVERICK, do_mav_binops_1b},
11153 {"cfmv64lr", 0xee000510, 8, ARM_CEXT_MAVERICK, do_mav_binops_2c},
11154 {"cfmvr64l", 0xee100510, 8, ARM_CEXT_MAVERICK, do_mav_binops_1c},
11155 {"cfmv64hr", 0xee000530, 8, ARM_CEXT_MAVERICK, do_mav_binops_2c},
11156 {"cfmvr64h", 0xee100530, 8, ARM_CEXT_MAVERICK, do_mav_binops_1c},
11157 {"cfmval32", 0xee200440, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
11158 {"cfmv32al", 0xee100440, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
11159 {"cfmvam32", 0xee200460, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
11160 {"cfmv32am", 0xee100460, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
11161 {"cfmvah32", 0xee200480, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
11162 {"cfmv32ah", 0xee100480, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
11163 {"cfmva32", 0xee2004a0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3a},
11164 {"cfmv32a", 0xee1004a0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3b},
11165 {"cfmva64", 0xee2004c0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3c},
11166 {"cfmv64a", 0xee1004c0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3d},
11167 {"cfmvsc32", 0xee2004e0, 8, ARM_CEXT_MAVERICK, do_mav_dspsc_1},
11168 {"cfmv32sc", 0xee1004e0, 8, ARM_CEXT_MAVERICK, do_mav_dspsc_2},
11169 {"cfcpys", 0xee000400, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
11170 {"cfcpyd", 0xee000420, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
11171 {"cfcvtsd", 0xee000460, 7, ARM_CEXT_MAVERICK, do_mav_binops_1f},
11172 {"cfcvtds", 0xee000440, 7, ARM_CEXT_MAVERICK, do_mav_binops_1g},
11173 {"cfcvt32s", 0xee000480, 8, ARM_CEXT_MAVERICK, do_mav_binops_1h},
11174 {"cfcvt32d", 0xee0004a0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1i},
11175 {"cfcvt64s", 0xee0004c0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1j},
11176 {"cfcvt64d", 0xee0004e0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1k},
11177 {"cfcvts32", 0xee100580, 8, ARM_CEXT_MAVERICK, do_mav_binops_1l},
11178 {"cfcvtd32", 0xee1005a0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1m},
11179 {"cftruncs32", 0xee1005c0, 10, ARM_CEXT_MAVERICK, do_mav_binops_1l},
11180 {"cftruncd32", 0xee1005e0, 10, ARM_CEXT_MAVERICK, do_mav_binops_1m},
11181 {"cfrshl32", 0xee000550, 8, ARM_CEXT_MAVERICK, do_mav_triple_4a},
11182 {"cfrshl64", 0xee000570, 8, ARM_CEXT_MAVERICK, do_mav_triple_4b},
11183 {"cfsh32", 0xee000500, 6, ARM_CEXT_MAVERICK, do_mav_shift_1},
11184 {"cfsh64", 0xee200500, 6, ARM_CEXT_MAVERICK, do_mav_shift_2},
11185 {"cfcmps", 0xee100490, 6, ARM_CEXT_MAVERICK, do_mav_triple_5a},
11186 {"cfcmpd", 0xee1004b0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5b},
11187 {"cfcmp32", 0xee100590, 7, ARM_CEXT_MAVERICK, do_mav_triple_5c},
11188 {"cfcmp64", 0xee1005b0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5d},
11189 {"cfabss", 0xee300400, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
11190 {"cfabsd", 0xee300420, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
11191 {"cfnegs", 0xee300440, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
11192 {"cfnegd", 0xee300460, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
11193 {"cfadds", 0xee300480, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
11194 {"cfaddd", 0xee3004a0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
11195 {"cfsubs", 0xee3004c0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
11196 {"cfsubd", 0xee3004e0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
11197 {"cfmuls", 0xee100400, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
11198 {"cfmuld", 0xee100420, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
11199 {"cfabs32", 0xee300500, 7, ARM_CEXT_MAVERICK, do_mav_binops_1n},
11200 {"cfabs64", 0xee300520, 7, ARM_CEXT_MAVERICK, do_mav_binops_1o},
11201 {"cfneg32", 0xee300540, 7, ARM_CEXT_MAVERICK, do_mav_binops_1n},
11202 {"cfneg64", 0xee300560, 7, ARM_CEXT_MAVERICK, do_mav_binops_1o},
11203 {"cfadd32", 0xee300580, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
11204 {"cfadd64", 0xee3005a0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
11205 {"cfsub32", 0xee3005c0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
11206 {"cfsub64", 0xee3005e0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
11207 {"cfmul32", 0xee100500, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
11208 {"cfmul64", 0xee100520, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
11209 {"cfmac32", 0xee100540, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
11210 {"cfmsc32", 0xee100560, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
11211 {"cfmadd32", 0xee000600, 8, ARM_CEXT_MAVERICK, do_mav_quad_6a},
11212 {"cfmsub32", 0xee100600, 8, ARM_CEXT_MAVERICK, do_mav_quad_6a},
11213 {"cfmadda32", 0xee200600, 9, ARM_CEXT_MAVERICK, do_mav_quad_6b},
11214 {"cfmsuba32", 0xee300600, 9, ARM_CEXT_MAVERICK, do_mav_quad_6b},
11215 };
11216
11217 /* Iterate over the base tables to create the instruction patterns. */
11218
11219 static void
11220 build_arm_ops_hsh (void)
11221 {
11222 unsigned int i;
11223 unsigned int j;
11224 static struct obstack insn_obstack;
11225
11226 obstack_begin (&insn_obstack, 4000);
11227
11228 for (i = 0; i < sizeof (insns) / sizeof (struct asm_opcode); i++)
11229 {
11230 const struct asm_opcode *insn = insns + i;
11231
11232 if (insn->cond_offset != 0)
11233 {
11234 /* Insn supports conditional execution. Build the varaints
11235 and insert them in the hash table. */
11236 for (j = 0; j < sizeof (conds) / sizeof (struct asm_cond); j++)
11237 {
11238 unsigned len = strlen (insn->template);
11239 struct asm_opcode *new;
11240 char *template;
11241
11242 new = obstack_alloc (&insn_obstack, sizeof (struct asm_opcode));
11243 /* All condition codes are two characters. */
11244 template = obstack_alloc (&insn_obstack, len + 3);
11245
11246 strncpy (template, insn->template, insn->cond_offset);
11247 strcpy (template + insn->cond_offset, conds[j].template);
11248 if (len > insn->cond_offset)
11249 strcpy (template + insn->cond_offset + 2,
11250 insn->template + insn->cond_offset);
11251 new->template = template;
11252 new->cond_offset = 0;
11253 new->variant = insn->variant;
11254 new->parms = insn->parms;
11255 new->value = (insn->value & ~COND_MASK) | conds[j].value;
11256
11257 hash_insert (arm_ops_hsh, new->template, (PTR) new);
11258 }
11259 }
11260 /* Finally, insert the unconditional insn in the table directly;
11261 no need to build a copy. */
11262 hash_insert (arm_ops_hsh, insn->template, (PTR) insn);
11263 }
11264 }
11265
11266 \f
11267 static const struct thumb_opcode tinsns[] =
11268 {
11269 /* Thumb v1 (ARMv4T). */
11270 {"adc", 0x4140, 2, ARM_EXT_V4T, do_t_arit},
11271 {"add", 0x0000, 2, ARM_EXT_V4T, do_t_add},
11272 {"and", 0x4000, 2, ARM_EXT_V4T, do_t_arit},
11273 {"asr", 0x0000, 2, ARM_EXT_V4T, do_t_asr},
11274 {"b", T_OPCODE_BRANCH, 2, ARM_EXT_V4T, do_t_branch12},
11275 {"beq", 0xd0fe, 2, ARM_EXT_V4T, do_t_branch9},
11276 {"bne", 0xd1fe, 2, ARM_EXT_V4T, do_t_branch9},
11277 {"bcs", 0xd2fe, 2, ARM_EXT_V4T, do_t_branch9},
11278 {"bhs", 0xd2fe, 2, ARM_EXT_V4T, do_t_branch9},
11279 {"bcc", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
11280 {"bul", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
11281 {"blo", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
11282 {"bmi", 0xd4fe, 2, ARM_EXT_V4T, do_t_branch9},
11283 {"bpl", 0xd5fe, 2, ARM_EXT_V4T, do_t_branch9},
11284 {"bvs", 0xd6fe, 2, ARM_EXT_V4T, do_t_branch9},
11285 {"bvc", 0xd7fe, 2, ARM_EXT_V4T, do_t_branch9},
11286 {"bhi", 0xd8fe, 2, ARM_EXT_V4T, do_t_branch9},
11287 {"bls", 0xd9fe, 2, ARM_EXT_V4T, do_t_branch9},
11288 {"bge", 0xdafe, 2, ARM_EXT_V4T, do_t_branch9},
11289 {"blt", 0xdbfe, 2, ARM_EXT_V4T, do_t_branch9},
11290 {"bgt", 0xdcfe, 2, ARM_EXT_V4T, do_t_branch9},
11291 {"ble", 0xddfe, 2, ARM_EXT_V4T, do_t_branch9},
11292 {"bal", 0xdefe, 2, ARM_EXT_V4T, do_t_branch9},
11293 {"bic", 0x4380, 2, ARM_EXT_V4T, do_t_arit},
11294 {"bl", 0xf7fffffe, 4, ARM_EXT_V4T, do_t_branch23},
11295 {"bx", 0x4700, 2, ARM_EXT_V4T, do_t_bx},
11296 {"cmn", T_OPCODE_CMN, 2, ARM_EXT_V4T, do_t_arit},
11297 {"cmp", 0x0000, 2, ARM_EXT_V4T, do_t_compare},
11298 {"eor", 0x4040, 2, ARM_EXT_V4T, do_t_arit},
11299 {"ldmia", 0xc800, 2, ARM_EXT_V4T, do_t_ldmstm},
11300 {"ldr", 0x0000, 2, ARM_EXT_V4T, do_t_ldr},
11301 {"ldrb", 0x0000, 2, ARM_EXT_V4T, do_t_ldrb},
11302 {"ldrh", 0x0000, 2, ARM_EXT_V4T, do_t_ldrh},
11303 {"ldrsb", 0x5600, 2, ARM_EXT_V4T, do_t_lds},
11304 {"ldrsh", 0x5e00, 2, ARM_EXT_V4T, do_t_lds},
11305 {"ldsb", 0x5600, 2, ARM_EXT_V4T, do_t_lds},
11306 {"ldsh", 0x5e00, 2, ARM_EXT_V4T, do_t_lds},
11307 {"lsl", 0x0000, 2, ARM_EXT_V4T, do_t_lsl},
11308 {"lsr", 0x0000, 2, ARM_EXT_V4T, do_t_lsr},
11309 {"mov", 0x0000, 2, ARM_EXT_V4T, do_t_mov},
11310 {"mul", T_OPCODE_MUL, 2, ARM_EXT_V4T, do_t_arit},
11311 {"mvn", T_OPCODE_MVN, 2, ARM_EXT_V4T, do_t_arit},
11312 {"neg", T_OPCODE_NEG, 2, ARM_EXT_V4T, do_t_arit},
11313 {"orr", 0x4300, 2, ARM_EXT_V4T, do_t_arit},
11314 {"pop", 0xbc00, 2, ARM_EXT_V4T, do_t_push_pop},
11315 {"push", 0xb400, 2, ARM_EXT_V4T, do_t_push_pop},
11316 {"ror", 0x41c0, 2, ARM_EXT_V4T, do_t_arit},
11317 {"sbc", 0x4180, 2, ARM_EXT_V4T, do_t_arit},
11318 {"stmia", 0xc000, 2, ARM_EXT_V4T, do_t_ldmstm},
11319 {"str", 0x0000, 2, ARM_EXT_V4T, do_t_str},
11320 {"strb", 0x0000, 2, ARM_EXT_V4T, do_t_strb},
11321 {"strh", 0x0000, 2, ARM_EXT_V4T, do_t_strh},
11322 {"swi", 0xdf00, 2, ARM_EXT_V4T, do_t_swi},
11323 {"sub", 0x0000, 2, ARM_EXT_V4T, do_t_sub},
11324 {"tst", T_OPCODE_TST, 2, ARM_EXT_V4T, do_t_arit},
11325 /* Pseudo ops: */
11326 {"adr", 0x0000, 2, ARM_EXT_V4T, do_t_adr},
11327 {"nop", 0x46C0, 2, ARM_EXT_V4T, do_t_nop}, /* mov r8,r8 */
11328 /* Thumb v2 (ARMv5T). */
11329 {"blx", 0, 0, ARM_EXT_V5T, do_t_blx},
11330 {"bkpt", 0xbe00, 2, ARM_EXT_V5T, do_t_bkpt},
11331
11332 /* ARM V6. */
11333 {"cpsie", 0xb660, 2, ARM_EXT_V6, do_t_cps},
11334 {"cpsid", 0xb670, 2, ARM_EXT_V6, do_t_cps},
11335 {"cpy", 0x4600, 2, ARM_EXT_V6, do_t_cpy},
11336 {"rev", 0xba00, 2, ARM_EXT_V6, do_t_arit},
11337 {"rev16", 0xba40, 2, ARM_EXT_V6, do_t_arit},
11338 {"revsh", 0xbac0, 2, ARM_EXT_V6, do_t_arit},
11339 {"setend", 0xb650, 2, ARM_EXT_V6, do_t_setend},
11340 {"sxth", 0xb200, 2, ARM_EXT_V6, do_t_arit},
11341 {"sxtb", 0xb240, 2, ARM_EXT_V6, do_t_arit},
11342 {"uxth", 0xb280, 2, ARM_EXT_V6, do_t_arit},
11343 {"uxtb", 0xb2c0, 2, ARM_EXT_V6, do_t_arit},
11344
11345 /* ARM V6K. */
11346 {"sev", 0xbf40, 2, ARM_EXT_V6K, do_empty},
11347 {"wfe", 0xbf20, 2, ARM_EXT_V6K, do_empty},
11348 {"wfi", 0xbf30, 2, ARM_EXT_V6K, do_empty},
11349 {"yield", 0xbf10, 2, ARM_EXT_V6K, do_empty},
11350 };
11351
11352 void
11353 md_begin (void)
11354 {
11355 unsigned mach;
11356 unsigned int i;
11357
11358 if ( (arm_ops_hsh = hash_new ()) == NULL
11359 || (arm_tops_hsh = hash_new ()) == NULL
11360 || (arm_cond_hsh = hash_new ()) == NULL
11361 || (arm_shift_hsh = hash_new ()) == NULL
11362 || (arm_psr_hsh = hash_new ()) == NULL)
11363 as_fatal (_("virtual memory exhausted"));
11364
11365 build_arm_ops_hsh ();
11366 for (i = 0; i < sizeof (tinsns) / sizeof (struct thumb_opcode); i++)
11367 hash_insert (arm_tops_hsh, tinsns[i].template, (PTR) (tinsns + i));
11368 for (i = 0; i < sizeof (conds) / sizeof (struct asm_cond); i++)
11369 hash_insert (arm_cond_hsh, conds[i].template, (PTR) (conds + i));
11370 for (i = 0; i < sizeof (shift_names) / sizeof (struct asm_shift_name); i++)
11371 hash_insert (arm_shift_hsh, shift_names[i].name, (PTR) (shift_names + i));
11372 for (i = 0; i < sizeof (psrs) / sizeof (struct asm_psr); i++)
11373 hash_insert (arm_psr_hsh, psrs[i].template, (PTR) (psrs + i));
11374
11375 for (i = (int) REG_TYPE_FIRST; i < (int) REG_TYPE_MAX; i++)
11376 build_reg_hsh (all_reg_maps + i);
11377
11378 set_constant_flonums ();
11379
11380 /* Set the cpu variant based on the command-line options. We prefer
11381 -mcpu= over -march= if both are set (as for GCC); and we prefer
11382 -mfpu= over any other way of setting the floating point unit.
11383 Use of legacy options with new options are faulted. */
11384 if (legacy_cpu != -1)
11385 {
11386 if (mcpu_cpu_opt != -1 || march_cpu_opt != -1)
11387 as_bad (_("use of old and new-style options to set CPU type"));
11388
11389 mcpu_cpu_opt = legacy_cpu;
11390 }
11391 else if (mcpu_cpu_opt == -1)
11392 mcpu_cpu_opt = march_cpu_opt;
11393
11394 if (legacy_fpu != -1)
11395 {
11396 if (mfpu_opt != -1)
11397 as_bad (_("use of old and new-style options to set FPU type"));
11398
11399 mfpu_opt = legacy_fpu;
11400 }
11401 else if (mfpu_opt == -1)
11402 {
11403 #if !(defined (TE_LINUX) || defined (TE_NetBSD) || defined (TE_VXWORKS))
11404 /* Some environments specify a default FPU. If they don't, infer it
11405 from the processor. */
11406 if (mcpu_fpu_opt != -1)
11407 mfpu_opt = mcpu_fpu_opt;
11408 else
11409 mfpu_opt = march_fpu_opt;
11410 #else
11411 mfpu_opt = FPU_DEFAULT;
11412 #endif
11413 }
11414
11415 if (mfpu_opt == -1)
11416 {
11417 if (mcpu_cpu_opt == -1)
11418 mfpu_opt = FPU_DEFAULT;
11419 else if (mcpu_cpu_opt & ARM_EXT_V5)
11420 mfpu_opt = FPU_ARCH_VFP_V2;
11421 else
11422 mfpu_opt = FPU_ARCH_FPA;
11423 }
11424
11425 if (mcpu_cpu_opt == -1)
11426 mcpu_cpu_opt = CPU_DEFAULT;
11427
11428 cpu_variant = mcpu_cpu_opt | mfpu_opt;
11429
11430 #if defined OBJ_COFF || defined OBJ_ELF
11431 {
11432 unsigned int flags = 0;
11433
11434 #if defined OBJ_ELF
11435 flags = meabi_flags;
11436
11437 switch (meabi_flags)
11438 {
11439 case EF_ARM_EABI_UNKNOWN:
11440 #endif
11441 /* Set the flags in the private structure. */
11442 if (uses_apcs_26) flags |= F_APCS26;
11443 if (support_interwork) flags |= F_INTERWORK;
11444 if (uses_apcs_float) flags |= F_APCS_FLOAT;
11445 if (pic_code) flags |= F_PIC;
11446 if ((cpu_variant & FPU_ANY) == FPU_NONE
11447 || (cpu_variant & FPU_ANY) == FPU_ARCH_VFP) /* VFP layout only. */
11448 flags |= F_SOFT_FLOAT;
11449
11450 switch (mfloat_abi_opt)
11451 {
11452 case ARM_FLOAT_ABI_SOFT:
11453 case ARM_FLOAT_ABI_SOFTFP:
11454 flags |= F_SOFT_FLOAT;
11455 break;
11456
11457 case ARM_FLOAT_ABI_HARD:
11458 if (flags & F_SOFT_FLOAT)
11459 as_bad (_("hard-float conflicts with specified fpu"));
11460 break;
11461 }
11462
11463 /* Using VFP conventions (even if soft-float). */
11464 if (cpu_variant & FPU_VFP_EXT_NONE)
11465 flags |= F_VFP_FLOAT;
11466
11467 #if defined OBJ_ELF
11468 if (cpu_variant & FPU_ARCH_MAVERICK)
11469 flags |= EF_ARM_MAVERICK_FLOAT;
11470 break;
11471
11472 case EF_ARM_EABI_VER4:
11473 /* No additional flags to set. */
11474 break;
11475
11476 default:
11477 abort ();
11478 }
11479 #endif
11480 bfd_set_private_flags (stdoutput, flags);
11481
11482 /* We have run out flags in the COFF header to encode the
11483 status of ATPCS support, so instead we create a dummy,
11484 empty, debug section called .arm.atpcs. */
11485 if (atpcs)
11486 {
11487 asection * sec;
11488
11489 sec = bfd_make_section (stdoutput, ".arm.atpcs");
11490
11491 if (sec != NULL)
11492 {
11493 bfd_set_section_flags
11494 (stdoutput, sec, SEC_READONLY | SEC_DEBUGGING /* | SEC_HAS_CONTENTS */);
11495 bfd_set_section_size (stdoutput, sec, 0);
11496 bfd_set_section_contents (stdoutput, sec, NULL, 0, 0);
11497 }
11498 }
11499 }
11500 #endif
11501
11502 /* Record the CPU type as well. */
11503 switch (cpu_variant & ARM_CPU_MASK)
11504 {
11505 case ARM_2:
11506 mach = bfd_mach_arm_2;
11507 break;
11508
11509 case ARM_3: /* Also ARM_250. */
11510 mach = bfd_mach_arm_2a;
11511 break;
11512
11513 case ARM_6: /* Also ARM_7. */
11514 mach = bfd_mach_arm_3;
11515 break;
11516
11517 default:
11518 mach = bfd_mach_arm_unknown;
11519 break;
11520 }
11521
11522 /* Catch special cases. */
11523 if (cpu_variant & ARM_CEXT_IWMMXT)
11524 mach = bfd_mach_arm_iWMMXt;
11525 else if (cpu_variant & ARM_CEXT_XSCALE)
11526 mach = bfd_mach_arm_XScale;
11527 else if (cpu_variant & ARM_CEXT_MAVERICK)
11528 mach = bfd_mach_arm_ep9312;
11529 else if (cpu_variant & ARM_EXT_V5E)
11530 mach = bfd_mach_arm_5TE;
11531 else if (cpu_variant & ARM_EXT_V5)
11532 {
11533 if (cpu_variant & ARM_EXT_V4T)
11534 mach = bfd_mach_arm_5T;
11535 else
11536 mach = bfd_mach_arm_5;
11537 }
11538 else if (cpu_variant & ARM_EXT_V4)
11539 {
11540 if (cpu_variant & ARM_EXT_V4T)
11541 mach = bfd_mach_arm_4T;
11542 else
11543 mach = bfd_mach_arm_4;
11544 }
11545 else if (cpu_variant & ARM_EXT_V3M)
11546 mach = bfd_mach_arm_3M;
11547
11548 bfd_set_arch_mach (stdoutput, TARGET_ARCH, mach);
11549 }
11550
11551 /* Turn an integer of n bytes (in val) into a stream of bytes appropriate
11552 for use in the a.out file, and stores them in the array pointed to by buf.
11553 This knows about the endian-ness of the target machine and does
11554 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
11555 2 (short) and 4 (long) Floating numbers are put out as a series of
11556 LITTLENUMS (shorts, here at least). */
11557
11558 void
11559 md_number_to_chars (char * buf, valueT val, int n)
11560 {
11561 if (target_big_endian)
11562 number_to_chars_bigendian (buf, val, n);
11563 else
11564 number_to_chars_littleendian (buf, val, n);
11565 }
11566
11567 static valueT
11568 md_chars_to_number (char * buf, int n)
11569 {
11570 valueT result = 0;
11571 unsigned char * where = (unsigned char *) buf;
11572
11573 if (target_big_endian)
11574 {
11575 while (n--)
11576 {
11577 result <<= 8;
11578 result |= (*where++ & 255);
11579 }
11580 }
11581 else
11582 {
11583 while (n--)
11584 {
11585 result <<= 8;
11586 result |= (where[n] & 255);
11587 }
11588 }
11589
11590 return result;
11591 }
11592
11593 /* Turn a string in input_line_pointer into a floating point constant
11594 of type TYPE, and store the appropriate bytes in *LITP. The number
11595 of LITTLENUMS emitted is stored in *SIZEP. An error message is
11596 returned, or NULL on OK.
11597
11598 Note that fp constants aren't represent in the normal way on the ARM.
11599 In big endian mode, things are as expected. However, in little endian
11600 mode fp constants are big-endian word-wise, and little-endian byte-wise
11601 within the words. For example, (double) 1.1 in big endian mode is
11602 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
11603 the byte sequence 99 99 f1 3f 9a 99 99 99.
11604
11605 ??? The format of 12 byte floats is uncertain according to gcc's arm.h. */
11606
11607 char *
11608 md_atof (int type, char * litP, int * sizeP)
11609 {
11610 int prec;
11611 LITTLENUM_TYPE words[MAX_LITTLENUMS];
11612 char *t;
11613 int i;
11614
11615 switch (type)
11616 {
11617 case 'f':
11618 case 'F':
11619 case 's':
11620 case 'S':
11621 prec = 2;
11622 break;
11623
11624 case 'd':
11625 case 'D':
11626 case 'r':
11627 case 'R':
11628 prec = 4;
11629 break;
11630
11631 case 'x':
11632 case 'X':
11633 prec = 6;
11634 break;
11635
11636 case 'p':
11637 case 'P':
11638 prec = 6;
11639 break;
11640
11641 default:
11642 *sizeP = 0;
11643 return _("bad call to MD_ATOF()");
11644 }
11645
11646 t = atof_ieee (input_line_pointer, type, words);
11647 if (t)
11648 input_line_pointer = t;
11649 *sizeP = prec * 2;
11650
11651 if (target_big_endian)
11652 {
11653 for (i = 0; i < prec; i++)
11654 {
11655 md_number_to_chars (litP, (valueT) words[i], 2);
11656 litP += 2;
11657 }
11658 }
11659 else
11660 {
11661 if (cpu_variant & FPU_ARCH_VFP)
11662 for (i = prec - 1; i >= 0; i--)
11663 {
11664 md_number_to_chars (litP, (valueT) words[i], 2);
11665 litP += 2;
11666 }
11667 else
11668 /* For a 4 byte float the order of elements in `words' is 1 0.
11669 For an 8 byte float the order is 1 0 3 2. */
11670 for (i = 0; i < prec; i += 2)
11671 {
11672 md_number_to_chars (litP, (valueT) words[i + 1], 2);
11673 md_number_to_chars (litP + 2, (valueT) words[i], 2);
11674 litP += 4;
11675 }
11676 }
11677
11678 return 0;
11679 }
11680
11681 /* The knowledge of the PC's pipeline offset is built into the insns
11682 themselves. */
11683
11684 long
11685 md_pcrel_from (fixS * fixP)
11686 {
11687 if (fixP->fx_addsy
11688 && S_GET_SEGMENT (fixP->fx_addsy) == undefined_section
11689 && fixP->fx_subsy == NULL)
11690 return 0;
11691
11692 if (fixP->fx_pcrel && (fixP->fx_r_type == BFD_RELOC_ARM_THUMB_ADD))
11693 {
11694 /* PC relative addressing on the Thumb is slightly odd
11695 as the bottom two bits of the PC are forced to zero
11696 for the calculation. */
11697 return (fixP->fx_where + fixP->fx_frag->fr_address) & ~3;
11698 }
11699
11700 #ifdef TE_WINCE
11701 /* The pattern was adjusted to accommodate CE's off-by-one fixups,
11702 so we un-adjust here to compensate for the accommodation. */
11703 return fixP->fx_where + fixP->fx_frag->fr_address + 8;
11704 #else
11705 return fixP->fx_where + fixP->fx_frag->fr_address;
11706 #endif
11707 }
11708
11709 /* Round up a section size to the appropriate boundary. */
11710
11711 valueT
11712 md_section_align (segT segment ATTRIBUTE_UNUSED,
11713 valueT size)
11714 {
11715 #ifdef OBJ_ELF
11716 return size;
11717 #else
11718 /* Round all sects to multiple of 4. */
11719 return (size + 3) & ~3;
11720 #endif
11721 }
11722
11723 /* Under ELF we need to default _GLOBAL_OFFSET_TABLE.
11724 Otherwise we have no need to default values of symbols. */
11725
11726 symbolS *
11727 md_undefined_symbol (char * name ATTRIBUTE_UNUSED)
11728 {
11729 #ifdef OBJ_ELF
11730 if (name[0] == '_' && name[1] == 'G'
11731 && streq (name, GLOBAL_OFFSET_TABLE_NAME))
11732 {
11733 if (!GOT_symbol)
11734 {
11735 if (symbol_find (name))
11736 as_bad ("GOT already in the symbol table");
11737
11738 GOT_symbol = symbol_new (name, undefined_section,
11739 (valueT) 0, & zero_address_frag);
11740 }
11741
11742 return GOT_symbol;
11743 }
11744 #endif
11745
11746 return 0;
11747 }
11748
11749 void
11750 md_apply_fix3 (fixS * fixP,
11751 valueT * valP,
11752 segT seg)
11753 {
11754 offsetT value = * valP;
11755 offsetT newval;
11756 unsigned int newimm;
11757 unsigned long temp;
11758 int sign;
11759 char * buf = fixP->fx_where + fixP->fx_frag->fr_literal;
11760 arm_fix_data * arm_data = (arm_fix_data *) fixP->tc_fix_data;
11761
11762 assert (fixP->fx_r_type <= BFD_RELOC_UNUSED);
11763
11764 /* Note whether this will delete the relocation. */
11765 if (fixP->fx_addsy == 0 && !fixP->fx_pcrel)
11766 fixP->fx_done = 1;
11767
11768 /* If this symbol is in a different section then we need to leave it for
11769 the linker to deal with. Unfortunately, md_pcrel_from can't tell,
11770 so we have to undo it's effects here. */
11771 if (fixP->fx_pcrel)
11772 {
11773 if (fixP->fx_addsy != NULL
11774 && S_IS_DEFINED (fixP->fx_addsy)
11775 && S_GET_SEGMENT (fixP->fx_addsy) != seg)
11776 value += md_pcrel_from (fixP);
11777 }
11778
11779 /* Remember value for emit_reloc. */
11780 fixP->fx_addnumber = value;
11781
11782 switch (fixP->fx_r_type)
11783 {
11784 case BFD_RELOC_NONE:
11785 /* This will need to go in the object file. */
11786 fixP->fx_done = 0;
11787 break;
11788
11789 case BFD_RELOC_ARM_IMMEDIATE:
11790 /* We claim that this fixup has been processed here,
11791 even if in fact we generate an error because we do
11792 not have a reloc for it, so tc_gen_reloc will reject it. */
11793 fixP->fx_done = 1;
11794
11795 if (fixP->fx_addsy
11796 && ! S_IS_DEFINED (fixP->fx_addsy))
11797 {
11798 as_bad_where (fixP->fx_file, fixP->fx_line,
11799 _("undefined symbol %s used as an immediate value"),
11800 S_GET_NAME (fixP->fx_addsy));
11801 break;
11802 }
11803
11804 newimm = validate_immediate (value);
11805 temp = md_chars_to_number (buf, INSN_SIZE);
11806
11807 /* If the instruction will fail, see if we can fix things up by
11808 changing the opcode. */
11809 if (newimm == (unsigned int) FAIL
11810 && (newimm = negate_data_op (&temp, value)) == (unsigned int) FAIL)
11811 {
11812 as_bad_where (fixP->fx_file, fixP->fx_line,
11813 _("invalid constant (%lx) after fixup"),
11814 (unsigned long) value);
11815 break;
11816 }
11817
11818 newimm |= (temp & 0xfffff000);
11819 md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
11820 break;
11821
11822 case BFD_RELOC_ARM_ADRL_IMMEDIATE:
11823 {
11824 unsigned int highpart = 0;
11825 unsigned int newinsn = 0xe1a00000; /* nop. */
11826
11827 newimm = validate_immediate (value);
11828 temp = md_chars_to_number (buf, INSN_SIZE);
11829
11830 /* If the instruction will fail, see if we can fix things up by
11831 changing the opcode. */
11832 if (newimm == (unsigned int) FAIL
11833 && (newimm = negate_data_op (& temp, value)) == (unsigned int) FAIL)
11834 {
11835 /* No ? OK - try using two ADD instructions to generate
11836 the value. */
11837 newimm = validate_immediate_twopart (value, & highpart);
11838
11839 /* Yes - then make sure that the second instruction is
11840 also an add. */
11841 if (newimm != (unsigned int) FAIL)
11842 newinsn = temp;
11843 /* Still No ? Try using a negated value. */
11844 else if ((newimm = validate_immediate_twopart (- value, & highpart)) != (unsigned int) FAIL)
11845 temp = newinsn = (temp & OPCODE_MASK) | OPCODE_SUB << DATA_OP_SHIFT;
11846 /* Otherwise - give up. */
11847 else
11848 {
11849 as_bad_where (fixP->fx_file, fixP->fx_line,
11850 _("unable to compute ADRL instructions for PC offset of 0x%lx"),
11851 (long) value);
11852 break;
11853 }
11854
11855 /* Replace the first operand in the 2nd instruction (which
11856 is the PC) with the destination register. We have
11857 already added in the PC in the first instruction and we
11858 do not want to do it again. */
11859 newinsn &= ~ 0xf0000;
11860 newinsn |= ((newinsn & 0x0f000) << 4);
11861 }
11862
11863 newimm |= (temp & 0xfffff000);
11864 md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
11865
11866 highpart |= (newinsn & 0xfffff000);
11867 md_number_to_chars (buf + INSN_SIZE, (valueT) highpart, INSN_SIZE);
11868 }
11869 break;
11870
11871 case BFD_RELOC_ARM_OFFSET_IMM:
11872 sign = value >= 0;
11873
11874 if (value < 0)
11875 value = - value;
11876
11877 if (validate_offset_imm (value, 0) == FAIL)
11878 {
11879 as_bad_where (fixP->fx_file, fixP->fx_line,
11880 _("bad immediate value for offset (%ld)"),
11881 (long) value);
11882 break;
11883 }
11884
11885 newval = md_chars_to_number (buf, INSN_SIZE);
11886 newval &= 0xff7ff000;
11887 newval |= value | (sign ? INDEX_UP : 0);
11888 md_number_to_chars (buf, newval, INSN_SIZE);
11889 break;
11890
11891 case BFD_RELOC_ARM_OFFSET_IMM8:
11892 case BFD_RELOC_ARM_HWLITERAL:
11893 sign = value >= 0;
11894
11895 if (value < 0)
11896 value = - value;
11897
11898 if (validate_offset_imm (value, 1) == FAIL)
11899 {
11900 if (fixP->fx_r_type == BFD_RELOC_ARM_HWLITERAL)
11901 as_bad_where (fixP->fx_file, fixP->fx_line,
11902 _("invalid literal constant: pool needs to be closer"));
11903 else
11904 as_bad (_("bad immediate value for half-word offset (%ld)"),
11905 (long) value);
11906 break;
11907 }
11908
11909 newval = md_chars_to_number (buf, INSN_SIZE);
11910 newval &= 0xff7ff0f0;
11911 newval |= ((value >> 4) << 8) | (value & 0xf) | (sign ? INDEX_UP : 0);
11912 md_number_to_chars (buf, newval, INSN_SIZE);
11913 break;
11914
11915 case BFD_RELOC_ARM_LITERAL:
11916 sign = value >= 0;
11917
11918 if (value < 0)
11919 value = - value;
11920
11921 if (validate_offset_imm (value, 0) == FAIL)
11922 {
11923 as_bad_where (fixP->fx_file, fixP->fx_line,
11924 _("invalid literal constant: pool needs to be closer"));
11925 break;
11926 }
11927
11928 newval = md_chars_to_number (buf, INSN_SIZE);
11929 newval &= 0xff7ff000;
11930 newval |= value | (sign ? INDEX_UP : 0);
11931 md_number_to_chars (buf, newval, INSN_SIZE);
11932 break;
11933
11934 case BFD_RELOC_ARM_SHIFT_IMM:
11935 newval = md_chars_to_number (buf, INSN_SIZE);
11936 if (((unsigned long) value) > 32
11937 || (value == 32
11938 && (((newval & 0x60) == 0) || (newval & 0x60) == 0x60)))
11939 {
11940 as_bad_where (fixP->fx_file, fixP->fx_line,
11941 _("shift expression is too large"));
11942 break;
11943 }
11944
11945 if (value == 0)
11946 /* Shifts of zero must be done as lsl. */
11947 newval &= ~0x60;
11948 else if (value == 32)
11949 value = 0;
11950 newval &= 0xfffff07f;
11951 newval |= (value & 0x1f) << 7;
11952 md_number_to_chars (buf, newval, INSN_SIZE);
11953 break;
11954
11955 case BFD_RELOC_ARM_SMI:
11956 if (((unsigned long) value) > 0xffff)
11957 as_bad_where (fixP->fx_file, fixP->fx_line,
11958 _("invalid smi expression"));
11959 newval = md_chars_to_number (buf, INSN_SIZE) & 0xfff000f0;
11960 newval |= (value & 0xf) | ((value & 0xfff0) << 4);
11961 md_number_to_chars (buf, newval, INSN_SIZE);
11962 break;
11963
11964 case BFD_RELOC_ARM_SWI:
11965 if (arm_data->thumb_mode)
11966 {
11967 if (((unsigned long) value) > 0xff)
11968 as_bad_where (fixP->fx_file, fixP->fx_line,
11969 _("invalid swi expression"));
11970 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xff00;
11971 newval |= value;
11972 md_number_to_chars (buf, newval, THUMB_SIZE);
11973 }
11974 else
11975 {
11976 if (((unsigned long) value) > 0x00ffffff)
11977 as_bad_where (fixP->fx_file, fixP->fx_line,
11978 _("invalid swi expression"));
11979 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff000000;
11980 newval |= value;
11981 md_number_to_chars (buf, newval, INSN_SIZE);
11982 }
11983 break;
11984
11985 case BFD_RELOC_ARM_MULTI:
11986 if (((unsigned long) value) > 0xffff)
11987 as_bad_where (fixP->fx_file, fixP->fx_line,
11988 _("invalid expression in load/store multiple"));
11989 newval = value | md_chars_to_number (buf, INSN_SIZE);
11990 md_number_to_chars (buf, newval, INSN_SIZE);
11991 break;
11992
11993 case BFD_RELOC_ARM_PCREL_BRANCH:
11994 newval = md_chars_to_number (buf, INSN_SIZE);
11995
11996 /* Sign-extend a 24-bit number. */
11997 #define SEXT24(x) ((((x) & 0xffffff) ^ (~ 0x7fffff)) + 0x800000)
11998
11999 #ifdef OBJ_ELF
12000 value = fixP->fx_offset;
12001 #endif
12002
12003 /* We are going to store value (shifted right by two) in the
12004 instruction, in a 24 bit, signed field. Thus we need to check
12005 that none of the top 8 bits of the shifted value (top 7 bits of
12006 the unshifted, unsigned value) are set, or that they are all set. */
12007 if ((value & ~ ((offsetT) 0x1ffffff)) != 0
12008 && ((value & ~ ((offsetT) 0x1ffffff)) != ~ ((offsetT) 0x1ffffff)))
12009 {
12010 #ifdef OBJ_ELF
12011 /* Normally we would be stuck at this point, since we cannot store
12012 the absolute address that is the destination of the branch in the
12013 24 bits of the branch instruction. If however, we happen to know
12014 that the destination of the branch is in the same section as the
12015 branch instruction itself, then we can compute the relocation for
12016 ourselves and not have to bother the linker with it.
12017
12018 FIXME: The test for OBJ_ELF is only here because I have not
12019 worked out how to do this for OBJ_COFF. */
12020 if (fixP->fx_addsy != NULL
12021 && S_IS_DEFINED (fixP->fx_addsy)
12022 && S_GET_SEGMENT (fixP->fx_addsy) == seg)
12023 {
12024 /* Get pc relative value to go into the branch. */
12025 value = * valP;
12026
12027 /* Permit a backward branch provided that enough bits
12028 are set. Allow a forwards branch, provided that
12029 enough bits are clear. */
12030 if ( (value & ~ ((offsetT) 0x1ffffff)) == ~ ((offsetT) 0x1ffffff)
12031 || (value & ~ ((offsetT) 0x1ffffff)) == 0)
12032 fixP->fx_done = 1;
12033 }
12034
12035 if (! fixP->fx_done)
12036 #endif
12037 as_bad_where (fixP->fx_file, fixP->fx_line,
12038 _("GAS can't handle same-section branch dest >= 0x04000000"));
12039 }
12040
12041 value >>= 2;
12042 value += SEXT24 (newval);
12043
12044 if ( (value & ~ ((offsetT) 0xffffff)) != 0
12045 && ((value & ~ ((offsetT) 0xffffff)) != ~ ((offsetT) 0xffffff)))
12046 as_bad_where (fixP->fx_file, fixP->fx_line,
12047 _("out of range branch"));
12048
12049 if (seg->use_rela_p && !fixP->fx_done)
12050 {
12051 /* Must unshift the value before storing it in the addend. */
12052 value <<= 2;
12053 #ifdef OBJ_ELF
12054 fixP->fx_offset = value;
12055 #endif
12056 fixP->fx_addnumber = value;
12057 newval = newval & 0xff000000;
12058 }
12059 else
12060 newval = (value & 0x00ffffff) | (newval & 0xff000000);
12061 md_number_to_chars (buf, newval, INSN_SIZE);
12062 break;
12063
12064 case BFD_RELOC_ARM_PCREL_BLX:
12065 {
12066 offsetT hbit;
12067 newval = md_chars_to_number (buf, INSN_SIZE);
12068
12069 #ifdef OBJ_ELF
12070 value = fixP->fx_offset;
12071 #endif
12072 hbit = (value >> 1) & 1;
12073 value = (value >> 2) & 0x00ffffff;
12074 value = (value + (newval & 0x00ffffff)) & 0x00ffffff;
12075
12076 if (seg->use_rela_p && !fixP->fx_done)
12077 {
12078 /* Must sign-extend and unshift the value before storing
12079 it in the addend. */
12080 value = SEXT24 (value);
12081 value = (value << 2) | hbit;
12082 #ifdef OBJ_ELF
12083 fixP->fx_offset = value;
12084 #endif
12085 fixP->fx_addnumber = value;
12086 newval = newval & 0xfe000000;
12087 }
12088 else
12089 newval = value | (newval & 0xfe000000) | (hbit << 24);
12090 md_number_to_chars (buf, newval, INSN_SIZE);
12091 }
12092 break;
12093
12094 case BFD_RELOC_THUMB_PCREL_BRANCH9: /* Conditional branch. */
12095 newval = md_chars_to_number (buf, THUMB_SIZE);
12096 {
12097 addressT diff = (newval & 0xff) << 1;
12098 if (diff & 0x100)
12099 diff |= ~0xff;
12100
12101 value += diff;
12102 if ((value & ~0xff) && ((value & ~0xff) != ~0xff))
12103 as_bad_where (fixP->fx_file, fixP->fx_line,
12104 _("branch out of range"));
12105 if (seg->use_rela_p && !fixP->fx_done)
12106 {
12107 #ifdef OBJ_ELF
12108 fixP->fx_offset = value;
12109 #endif
12110 fixP->fx_addnumber = value;
12111 newval = newval & 0xff00;
12112 }
12113 else
12114 newval = (newval & 0xff00) | ((value & 0x1ff) >> 1);
12115 }
12116 md_number_to_chars (buf, newval, THUMB_SIZE);
12117 break;
12118
12119 case BFD_RELOC_THUMB_PCREL_BRANCH12: /* Unconditional branch. */
12120 newval = md_chars_to_number (buf, THUMB_SIZE);
12121 {
12122 addressT diff = (newval & 0x7ff) << 1;
12123 if (diff & 0x800)
12124 diff |= ~0x7ff;
12125
12126 value += diff;
12127 if ((value & ~0x7ff) && ((value & ~0x7ff) != ~0x7ff))
12128 as_bad_where (fixP->fx_file, fixP->fx_line,
12129 _("branch out of range"));
12130 if (seg->use_rela_p && !fixP->fx_done)
12131 {
12132 #ifdef OBJ_ELF
12133 fixP->fx_offset = value;
12134 #endif
12135 fixP->fx_addnumber = value;
12136 newval = newval & 0xf800;
12137 }
12138 else
12139 newval = (newval & 0xf800) | ((value & 0xfff) >> 1);
12140 }
12141 md_number_to_chars (buf, newval, THUMB_SIZE);
12142 break;
12143
12144 case BFD_RELOC_THUMB_PCREL_BLX:
12145 case BFD_RELOC_THUMB_PCREL_BRANCH23:
12146 {
12147 offsetT newval2;
12148 addressT diff;
12149
12150 newval = md_chars_to_number (buf, THUMB_SIZE);
12151 newval2 = md_chars_to_number (buf + THUMB_SIZE, THUMB_SIZE);
12152 diff = ((newval & 0x7ff) << 12) | ((newval2 & 0x7ff) << 1);
12153 if (diff & 0x400000)
12154 diff |= ~0x3fffff;
12155 #ifdef OBJ_ELF
12156 value = fixP->fx_offset;
12157 #endif
12158 value += diff;
12159
12160 if ((value & ~0x3fffff) && ((value & ~0x3fffff) != ~0x3fffff))
12161 as_bad_where (fixP->fx_file, fixP->fx_line,
12162 _("branch with link out of range"));
12163
12164 if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX)
12165 /* For a BLX instruction, make sure that the relocation is rounded up
12166 to a word boundary. This follows the semantics of the instruction
12167 which specifies that bit 1 of the target address will come from bit
12168 1 of the base address. */
12169 value = (value + 1) & ~ 1;
12170
12171 if (seg->use_rela_p && !fixP->fx_done)
12172 {
12173 #ifdef OBJ_ELF
12174 fixP->fx_offset = value;
12175 #endif
12176 fixP->fx_addnumber = value;
12177 newval = newval & 0xf800;
12178 newval2 = newval2 & 0xf800;
12179 }
12180 else
12181 {
12182 newval = (newval & 0xf800) | ((value & 0x7fffff) >> 12);
12183 newval2 = (newval2 & 0xf800) | ((value & 0xfff) >> 1);
12184 }
12185 md_number_to_chars (buf, newval, THUMB_SIZE);
12186 md_number_to_chars (buf + THUMB_SIZE, newval2, THUMB_SIZE);
12187 }
12188 break;
12189
12190 case BFD_RELOC_8:
12191 if (seg->use_rela_p && !fixP->fx_done)
12192 break;
12193 if (fixP->fx_done || fixP->fx_pcrel)
12194 md_number_to_chars (buf, value, 1);
12195 #ifdef OBJ_ELF
12196 else
12197 {
12198 value = fixP->fx_offset;
12199 md_number_to_chars (buf, value, 1);
12200 }
12201 #endif
12202 break;
12203
12204 case BFD_RELOC_16:
12205 if (seg->use_rela_p && !fixP->fx_done)
12206 break;
12207 if (fixP->fx_done || fixP->fx_pcrel)
12208 md_number_to_chars (buf, value, 2);
12209 #ifdef OBJ_ELF
12210 else
12211 {
12212 value = fixP->fx_offset;
12213 md_number_to_chars (buf, value, 2);
12214 }
12215 #endif
12216 break;
12217
12218 #ifdef OBJ_ELF
12219 case BFD_RELOC_ARM_GOT32:
12220 case BFD_RELOC_ARM_GOTOFF:
12221 case BFD_RELOC_ARM_TARGET2:
12222 if (seg->use_rela_p && !fixP->fx_done)
12223 break;
12224 md_number_to_chars (buf, 0, 4);
12225 break;
12226 #endif
12227
12228 case BFD_RELOC_RVA:
12229 case BFD_RELOC_32:
12230 case BFD_RELOC_ARM_TARGET1:
12231 case BFD_RELOC_ARM_ROSEGREL32:
12232 case BFD_RELOC_ARM_SBREL32:
12233 case BFD_RELOC_32_PCREL:
12234 if (seg->use_rela_p && !fixP->fx_done)
12235 break;
12236 if (fixP->fx_done || fixP->fx_pcrel)
12237 md_number_to_chars (buf, value, 4);
12238 #ifdef OBJ_ELF
12239 else
12240 {
12241 value = fixP->fx_offset;
12242 md_number_to_chars (buf, value, 4);
12243 }
12244 #endif
12245 break;
12246
12247 #ifdef OBJ_ELF
12248 case BFD_RELOC_ARM_PREL31:
12249 if (fixP->fx_done || fixP->fx_pcrel)
12250 {
12251 newval = md_chars_to_number (buf, 4) & 0x80000000;
12252 if ((value ^ (value >> 1)) & 0x40000000)
12253 {
12254 as_bad_where (fixP->fx_file, fixP->fx_line,
12255 _("rel31 relocation overflow"));
12256 }
12257 newval |= value & 0x7fffffff;
12258 md_number_to_chars (buf, newval, 4);
12259 }
12260 break;
12261
12262 case BFD_RELOC_ARM_PLT32:
12263 /* It appears the instruction is fully prepared at this point. */
12264 break;
12265 #endif
12266
12267 case BFD_RELOC_ARM_CP_OFF_IMM:
12268 sign = value >= 0;
12269 if (value < -1023 || value > 1023 || (value & 3))
12270 as_bad_where (fixP->fx_file, fixP->fx_line,
12271 _("illegal value for co-processor offset"));
12272 if (value < 0)
12273 value = -value;
12274 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
12275 newval |= (value >> 2) | (sign ? INDEX_UP : 0);
12276 md_number_to_chars (buf, newval, INSN_SIZE);
12277 break;
12278
12279 case BFD_RELOC_ARM_CP_OFF_IMM_S2:
12280 sign = value >= 0;
12281 if (value < -255 || value > 255)
12282 as_bad_where (fixP->fx_file, fixP->fx_line,
12283 _("Illegal value for co-processor offset"));
12284 if (value < 0)
12285 value = -value;
12286 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
12287 newval |= value | (sign ? INDEX_UP : 0);
12288 md_number_to_chars (buf, newval , INSN_SIZE);
12289 break;
12290
12291 case BFD_RELOC_ARM_THUMB_OFFSET:
12292 newval = md_chars_to_number (buf, THUMB_SIZE);
12293 /* Exactly what ranges, and where the offset is inserted depends
12294 on the type of instruction, we can establish this from the
12295 top 4 bits. */
12296 switch (newval >> 12)
12297 {
12298 case 4: /* PC load. */
12299 /* Thumb PC loads are somewhat odd, bit 1 of the PC is
12300 forced to zero for these loads, so we will need to round
12301 up the offset if the instruction address is not word
12302 aligned (since the final address produced must be, and
12303 we can only describe word-aligned immediate offsets). */
12304
12305 if ((fixP->fx_frag->fr_address + fixP->fx_where + value) & 3)
12306 as_bad_where (fixP->fx_file, fixP->fx_line,
12307 _("invalid offset, target not word aligned (0x%08X)"),
12308 (unsigned int) (fixP->fx_frag->fr_address
12309 + fixP->fx_where + value));
12310
12311 if ((value + 2) & ~0x3fe)
12312 as_bad_where (fixP->fx_file, fixP->fx_line,
12313 _("invalid offset, value too big (0x%08lX)"),
12314 (long) value);
12315
12316 /* Round up, since pc will be rounded down. */
12317 newval |= (value + 2) >> 2;
12318 break;
12319
12320 case 9: /* SP load/store. */
12321 if (value & ~0x3fc)
12322 as_bad_where (fixP->fx_file, fixP->fx_line,
12323 _("invalid offset, value too big (0x%08lX)"),
12324 (long) value);
12325 newval |= value >> 2;
12326 break;
12327
12328 case 6: /* Word load/store. */
12329 if (value & ~0x7c)
12330 as_bad_where (fixP->fx_file, fixP->fx_line,
12331 _("invalid offset, value too big (0x%08lX)"),
12332 (long) value);
12333 newval |= value << 4; /* 6 - 2. */
12334 break;
12335
12336 case 7: /* Byte load/store. */
12337 if (value & ~0x1f)
12338 as_bad_where (fixP->fx_file, fixP->fx_line,
12339 _("invalid offset, value too big (0x%08lX)"),
12340 (long) value);
12341 newval |= value << 6;
12342 break;
12343
12344 case 8: /* Halfword load/store. */
12345 if (value & ~0x3e)
12346 as_bad_where (fixP->fx_file, fixP->fx_line,
12347 _("invalid offset, value too big (0x%08lX)"),
12348 (long) value);
12349 newval |= value << 5; /* 6 - 1. */
12350 break;
12351
12352 default:
12353 as_bad_where (fixP->fx_file, fixP->fx_line,
12354 "Unable to process relocation for thumb opcode: %lx",
12355 (unsigned long) newval);
12356 break;
12357 }
12358 md_number_to_chars (buf, newval, THUMB_SIZE);
12359 break;
12360
12361 case BFD_RELOC_ARM_THUMB_ADD:
12362 /* This is a complicated relocation, since we use it for all of
12363 the following immediate relocations:
12364
12365 3bit ADD/SUB
12366 8bit ADD/SUB
12367 9bit ADD/SUB SP word-aligned
12368 10bit ADD PC/SP word-aligned
12369
12370 The type of instruction being processed is encoded in the
12371 instruction field:
12372
12373 0x8000 SUB
12374 0x00F0 Rd
12375 0x000F Rs
12376 */
12377 newval = md_chars_to_number (buf, THUMB_SIZE);
12378 {
12379 int rd = (newval >> 4) & 0xf;
12380 int rs = newval & 0xf;
12381 int subtract = newval & 0x8000;
12382
12383 if (rd == REG_SP)
12384 {
12385 if (value & ~0x1fc)
12386 as_bad_where (fixP->fx_file, fixP->fx_line,
12387 _("invalid immediate for stack address calculation"));
12388 newval = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
12389 newval |= value >> 2;
12390 }
12391 else if (rs == REG_PC || rs == REG_SP)
12392 {
12393 if (subtract ||
12394 value & ~0x3fc)
12395 as_bad_where (fixP->fx_file, fixP->fx_line,
12396 _("invalid immediate for address calculation (value = 0x%08lX)"),
12397 (unsigned long) value);
12398 newval = (rs == REG_PC ? T_OPCODE_ADD_PC : T_OPCODE_ADD_SP);
12399 newval |= rd << 8;
12400 newval |= value >> 2;
12401 }
12402 else if (rs == rd)
12403 {
12404 if (value & ~0xff)
12405 as_bad_where (fixP->fx_file, fixP->fx_line,
12406 _("invalid 8bit immediate"));
12407 newval = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
12408 newval |= (rd << 8) | value;
12409 }
12410 else
12411 {
12412 if (value & ~0x7)
12413 as_bad_where (fixP->fx_file, fixP->fx_line,
12414 _("invalid 3bit immediate"));
12415 newval = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
12416 newval |= rd | (rs << 3) | (value << 6);
12417 }
12418 }
12419 md_number_to_chars (buf, newval, THUMB_SIZE);
12420 break;
12421
12422 case BFD_RELOC_ARM_THUMB_IMM:
12423 newval = md_chars_to_number (buf, THUMB_SIZE);
12424 switch (newval >> 11)
12425 {
12426 case 0x04: /* 8bit immediate MOV. */
12427 case 0x05: /* 8bit immediate CMP. */
12428 if (value < 0 || value > 255)
12429 as_bad_where (fixP->fx_file, fixP->fx_line,
12430 _("invalid immediate: %ld is too large"),
12431 (long) value);
12432 newval |= value;
12433 break;
12434
12435 default:
12436 abort ();
12437 }
12438 md_number_to_chars (buf, newval, THUMB_SIZE);
12439 break;
12440
12441 case BFD_RELOC_ARM_THUMB_SHIFT:
12442 /* 5bit shift value (0..31). */
12443 if (value < 0 || value > 31)
12444 as_bad_where (fixP->fx_file, fixP->fx_line,
12445 _("illegal Thumb shift value: %ld"), (long) value);
12446 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xf03f;
12447 newval |= value << 6;
12448 md_number_to_chars (buf, newval, THUMB_SIZE);
12449 break;
12450
12451 case BFD_RELOC_VTABLE_INHERIT:
12452 case BFD_RELOC_VTABLE_ENTRY:
12453 fixP->fx_done = 0;
12454 return;
12455
12456 case BFD_RELOC_UNUSED:
12457 default:
12458 as_bad_where (fixP->fx_file, fixP->fx_line,
12459 _("bad relocation fixup type (%d)"), fixP->fx_r_type);
12460 }
12461 }
12462
12463 /* Translate internal representation of relocation info to BFD target
12464 format. */
12465
12466 arelent *
12467 tc_gen_reloc (asection * section ATTRIBUTE_UNUSED,
12468 fixS * fixp)
12469 {
12470 arelent * reloc;
12471 bfd_reloc_code_real_type code;
12472
12473 reloc = xmalloc (sizeof (arelent));
12474
12475 reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
12476 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
12477 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
12478
12479 /* @@ Why fx_addnumber sometimes and fx_offset other times? */
12480 #ifndef OBJ_ELF
12481 if (fixp->fx_pcrel == 0)
12482 reloc->addend = fixp->fx_offset;
12483 else
12484 reloc->addend = fixp->fx_offset = reloc->address;
12485 #else /* OBJ_ELF */
12486 reloc->addend = fixp->fx_offset;
12487 #endif
12488
12489 switch (fixp->fx_r_type)
12490 {
12491 case BFD_RELOC_8:
12492 if (fixp->fx_pcrel)
12493 {
12494 code = BFD_RELOC_8_PCREL;
12495 break;
12496 }
12497
12498 case BFD_RELOC_16:
12499 if (fixp->fx_pcrel)
12500 {
12501 code = BFD_RELOC_16_PCREL;
12502 break;
12503 }
12504
12505 case BFD_RELOC_32:
12506 if (fixp->fx_pcrel)
12507 {
12508 code = BFD_RELOC_32_PCREL;
12509 break;
12510 }
12511
12512 case BFD_RELOC_NONE:
12513 case BFD_RELOC_ARM_PCREL_BRANCH:
12514 case BFD_RELOC_ARM_PCREL_BLX:
12515 case BFD_RELOC_RVA:
12516 case BFD_RELOC_THUMB_PCREL_BRANCH9:
12517 case BFD_RELOC_THUMB_PCREL_BRANCH12:
12518 case BFD_RELOC_THUMB_PCREL_BRANCH23:
12519 case BFD_RELOC_THUMB_PCREL_BLX:
12520 case BFD_RELOC_VTABLE_ENTRY:
12521 case BFD_RELOC_VTABLE_INHERIT:
12522 code = fixp->fx_r_type;
12523 break;
12524
12525 case BFD_RELOC_ARM_LITERAL:
12526 case BFD_RELOC_ARM_HWLITERAL:
12527 /* If this is called then the a literal has
12528 been referenced across a section boundary. */
12529 as_bad_where (fixp->fx_file, fixp->fx_line,
12530 _("literal referenced across section boundary"));
12531 return NULL;
12532
12533 #ifdef OBJ_ELF
12534 case BFD_RELOC_ARM_GOT32:
12535 case BFD_RELOC_ARM_GOTOFF:
12536 case BFD_RELOC_ARM_PLT32:
12537 case BFD_RELOC_ARM_TARGET1:
12538 case BFD_RELOC_ARM_ROSEGREL32:
12539 case BFD_RELOC_ARM_SBREL32:
12540 case BFD_RELOC_ARM_PREL31:
12541 case BFD_RELOC_ARM_TARGET2:
12542 code = fixp->fx_r_type;
12543 break;
12544 #endif
12545
12546 case BFD_RELOC_ARM_IMMEDIATE:
12547 as_bad_where (fixp->fx_file, fixp->fx_line,
12548 _("internal relocation (type: IMMEDIATE) not fixed up"));
12549 return NULL;
12550
12551 case BFD_RELOC_ARM_ADRL_IMMEDIATE:
12552 as_bad_where (fixp->fx_file, fixp->fx_line,
12553 _("ADRL used for a symbol not defined in the same file"));
12554 return NULL;
12555
12556 case BFD_RELOC_ARM_OFFSET_IMM:
12557 if (fixp->fx_addsy != NULL
12558 && !S_IS_DEFINED (fixp->fx_addsy)
12559 && S_IS_LOCAL (fixp->fx_addsy))
12560 {
12561 as_bad_where (fixp->fx_file, fixp->fx_line,
12562 _("undefined local label `%s'"),
12563 S_GET_NAME (fixp->fx_addsy));
12564 return NULL;
12565 }
12566
12567 as_bad_where (fixp->fx_file, fixp->fx_line,
12568 _("internal_relocation (type: OFFSET_IMM) not fixed up"));
12569 return NULL;
12570
12571 default:
12572 {
12573 char * type;
12574
12575 switch (fixp->fx_r_type)
12576 {
12577 case BFD_RELOC_NONE: type = "NONE"; break;
12578 case BFD_RELOC_ARM_OFFSET_IMM8: type = "OFFSET_IMM8"; break;
12579 case BFD_RELOC_ARM_SHIFT_IMM: type = "SHIFT_IMM"; break;
12580 case BFD_RELOC_ARM_SMI: type = "SMI"; break;
12581 case BFD_RELOC_ARM_SWI: type = "SWI"; break;
12582 case BFD_RELOC_ARM_MULTI: type = "MULTI"; break;
12583 case BFD_RELOC_ARM_CP_OFF_IMM: type = "CP_OFF_IMM"; break;
12584 case BFD_RELOC_ARM_THUMB_ADD: type = "THUMB_ADD"; break;
12585 case BFD_RELOC_ARM_THUMB_SHIFT: type = "THUMB_SHIFT"; break;
12586 case BFD_RELOC_ARM_THUMB_IMM: type = "THUMB_IMM"; break;
12587 case BFD_RELOC_ARM_THUMB_OFFSET: type = "THUMB_OFFSET"; break;
12588 default: type = _("<unknown>"); break;
12589 }
12590 as_bad_where (fixp->fx_file, fixp->fx_line,
12591 _("cannot represent %s relocation in this object file format"),
12592 type);
12593 return NULL;
12594 }
12595 }
12596
12597 #ifdef OBJ_ELF
12598 if ((code == BFD_RELOC_32_PCREL || code == BFD_RELOC_32)
12599 && GOT_symbol
12600 && fixp->fx_addsy == GOT_symbol)
12601 {
12602 code = BFD_RELOC_ARM_GOTPC;
12603 reloc->addend = fixp->fx_offset = reloc->address;
12604 }
12605 #endif
12606
12607 reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
12608
12609 if (reloc->howto == NULL)
12610 {
12611 as_bad_where (fixp->fx_file, fixp->fx_line,
12612 _("cannot represent %s relocation in this object file format"),
12613 bfd_get_reloc_code_name (code));
12614 return NULL;
12615 }
12616
12617 /* HACK: Since arm ELF uses Rel instead of Rela, encode the
12618 vtable entry to be used in the relocation's section offset. */
12619 if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
12620 reloc->address = fixp->fx_offset;
12621
12622 return reloc;
12623 }
12624
12625 int
12626 md_estimate_size_before_relax (fragS * fragP ATTRIBUTE_UNUSED,
12627 segT segtype ATTRIBUTE_UNUSED)
12628 {
12629 as_fatal (_("md_estimate_size_before_relax\n"));
12630 return 1;
12631 }
12632
12633 /* We need to be able to fix up arbitrary expressions in some statements.
12634 This is so that we can handle symbols that are an arbitrary distance from
12635 the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
12636 which returns part of an address in a form which will be valid for
12637 a data instruction. We do this by pushing the expression into a symbol
12638 in the expr_section, and creating a fix for that. */
12639
12640 static void
12641 fix_new_arm (fragS * frag,
12642 int where,
12643 short int size,
12644 expressionS * exp,
12645 int pc_rel,
12646 int reloc)
12647 {
12648 fixS * new_fix;
12649 arm_fix_data * arm_data;
12650
12651 switch (exp->X_op)
12652 {
12653 case O_constant:
12654 case O_symbol:
12655 case O_add:
12656 case O_subtract:
12657 new_fix = fix_new_exp (frag, where, size, exp, pc_rel, reloc);
12658 break;
12659
12660 default:
12661 new_fix = fix_new (frag, where, size, make_expr_symbol (exp), 0,
12662 pc_rel, reloc);
12663 break;
12664 }
12665
12666 /* Mark whether the fix is to a THUMB instruction, or an ARM
12667 instruction. */
12668 arm_data = obstack_alloc (& notes, sizeof (arm_fix_data));
12669 new_fix->tc_fix_data = (PTR) arm_data;
12670 arm_data->thumb_mode = thumb_mode;
12671 }
12672
12673 static void
12674 output_inst (const char * str)
12675 {
12676 char * to = NULL;
12677
12678 if (inst.error)
12679 {
12680 as_bad ("%s -- `%s'", inst.error, str);
12681 return;
12682 }
12683
12684 to = frag_more (inst.size);
12685
12686 if (thumb_mode && (inst.size > THUMB_SIZE))
12687 {
12688 assert (inst.size == (2 * THUMB_SIZE));
12689 md_number_to_chars (to, inst.instruction >> 16, THUMB_SIZE);
12690 md_number_to_chars (to + THUMB_SIZE, inst.instruction, THUMB_SIZE);
12691 }
12692 else if (inst.size > INSN_SIZE)
12693 {
12694 assert (inst.size == (2 * INSN_SIZE));
12695 md_number_to_chars (to, inst.instruction, INSN_SIZE);
12696 md_number_to_chars (to + INSN_SIZE, inst.instruction, INSN_SIZE);
12697 }
12698 else
12699 md_number_to_chars (to, inst.instruction, inst.size);
12700
12701 if (inst.reloc.type != BFD_RELOC_UNUSED)
12702 fix_new_arm (frag_now, to - frag_now->fr_literal,
12703 inst.size, & inst.reloc.exp, inst.reloc.pc_rel,
12704 inst.reloc.type);
12705
12706 #ifdef OBJ_ELF
12707 dwarf2_emit_insn (inst.size);
12708 #endif
12709 }
12710
12711 void
12712 md_assemble (char * str)
12713 {
12714 char c;
12715 char *p;
12716 char *start;
12717
12718 /* Align the previous label if needed. */
12719 if (last_label_seen != NULL)
12720 {
12721 symbol_set_frag (last_label_seen, frag_now);
12722 S_SET_VALUE (last_label_seen, (valueT) frag_now_fix ());
12723 S_SET_SEGMENT (last_label_seen, now_seg);
12724 }
12725
12726 memset (&inst, '\0', sizeof (inst));
12727 inst.reloc.type = BFD_RELOC_UNUSED;
12728
12729 skip_whitespace (str);
12730
12731 /* Scan up to the end of the op-code, which must end in white space or
12732 end of string. */
12733 for (start = p = str; *p != '\0'; p++)
12734 if (*p == ' ')
12735 break;
12736
12737 if (p == str)
12738 {
12739 as_bad (_("no operator -- statement `%s'\n"), str);
12740 return;
12741 }
12742
12743 if (thumb_mode)
12744 {
12745 const struct thumb_opcode * opcode;
12746
12747 c = *p;
12748 *p = '\0';
12749 opcode = (const struct thumb_opcode *) hash_find (arm_tops_hsh, str);
12750 *p = c;
12751
12752 if (opcode)
12753 {
12754 /* Check that this instruction is supported for this CPU. */
12755 if (thumb_mode == 1 && (opcode->variant & cpu_variant) == 0)
12756 {
12757 as_bad (_("selected processor does not support `%s'"), str);
12758 return;
12759 }
12760
12761 mapping_state (MAP_THUMB);
12762 inst.instruction = opcode->value;
12763 inst.size = opcode->size;
12764 opcode->parms (p);
12765 output_inst (str);
12766 return;
12767 }
12768 }
12769 else
12770 {
12771 const struct asm_opcode * opcode;
12772
12773 c = *p;
12774 *p = '\0';
12775 opcode = (const struct asm_opcode *) hash_find (arm_ops_hsh, str);
12776 *p = c;
12777
12778 if (opcode)
12779 {
12780 /* Check that this instruction is supported for this CPU. */
12781 if ((opcode->variant & cpu_variant) == 0)
12782 {
12783 as_bad (_("selected processor does not support `%s'"), str);
12784 return;
12785 }
12786
12787 mapping_state (MAP_ARM);
12788 inst.instruction = opcode->value;
12789 inst.size = INSN_SIZE;
12790 opcode->parms (p);
12791 output_inst (str);
12792 return;
12793 }
12794 }
12795
12796 /* It wasn't an instruction, but it might be a register alias of the form
12797 alias .req reg. */
12798 if (create_register_alias (str, p))
12799 return;
12800
12801 as_bad (_("bad instruction `%s'"), start);
12802 }
12803
12804 /* md_parse_option
12805 Invocation line includes a switch not recognized by the base assembler.
12806 See if it's a processor-specific option.
12807
12808 This routine is somewhat complicated by the need for backwards
12809 compatibility (since older releases of gcc can't be changed).
12810 The new options try to make the interface as compatible as
12811 possible with GCC.
12812
12813 New options (supported) are:
12814
12815 -mcpu=<cpu name> Assemble for selected processor
12816 -march=<architecture name> Assemble for selected architecture
12817 -mfpu=<fpu architecture> Assemble for selected FPU.
12818 -EB/-mbig-endian Big-endian
12819 -EL/-mlittle-endian Little-endian
12820 -k Generate PIC code
12821 -mthumb Start in Thumb mode
12822 -mthumb-interwork Code supports ARM/Thumb interworking
12823
12824 For now we will also provide support for:
12825
12826 -mapcs-32 32-bit Program counter
12827 -mapcs-26 26-bit Program counter
12828 -macps-float Floats passed in FP registers
12829 -mapcs-reentrant Reentrant code
12830 -matpcs
12831 (sometime these will probably be replaced with -mapcs=<list of options>
12832 and -matpcs=<list of options>)
12833
12834 The remaining options are only supported for back-wards compatibility.
12835 Cpu variants, the arm part is optional:
12836 -m[arm]1 Currently not supported.
12837 -m[arm]2, -m[arm]250 Arm 2 and Arm 250 processor
12838 -m[arm]3 Arm 3 processor
12839 -m[arm]6[xx], Arm 6 processors
12840 -m[arm]7[xx][t][[d]m] Arm 7 processors
12841 -m[arm]8[10] Arm 8 processors
12842 -m[arm]9[20][tdmi] Arm 9 processors
12843 -mstrongarm[110[0]] StrongARM processors
12844 -mxscale XScale processors
12845 -m[arm]v[2345[t[e]]] Arm architectures
12846 -mall All (except the ARM1)
12847 FP variants:
12848 -mfpa10, -mfpa11 FPA10 and 11 co-processor instructions
12849 -mfpe-old (No float load/store multiples)
12850 -mvfpxd VFP Single precision
12851 -mvfp All VFP
12852 -mno-fpu Disable all floating point instructions
12853
12854 The following CPU names are recognized:
12855 arm1, arm2, arm250, arm3, arm6, arm600, arm610, arm620,
12856 arm7, arm7m, arm7d, arm7dm, arm7di, arm7dmi, arm70, arm700,
12857 arm700i, arm710 arm710t, arm720, arm720t, arm740t, arm710c,
12858 arm7100, arm7500, arm7500fe, arm7tdmi, arm8, arm810, arm9,
12859 arm920, arm920t, arm940t, arm946, arm966, arm9tdmi, arm9e,
12860 arm10t arm10e, arm1020t, arm1020e, arm10200e,
12861 strongarm, strongarm110, strongarm1100, strongarm1110, xscale.
12862
12863 */
12864
12865 const char * md_shortopts = "m:k";
12866
12867 #ifdef ARM_BI_ENDIAN
12868 #define OPTION_EB (OPTION_MD_BASE + 0)
12869 #define OPTION_EL (OPTION_MD_BASE + 1)
12870 #else
12871 #if TARGET_BYTES_BIG_ENDIAN
12872 #define OPTION_EB (OPTION_MD_BASE + 0)
12873 #else
12874 #define OPTION_EL (OPTION_MD_BASE + 1)
12875 #endif
12876 #endif
12877
12878 struct option md_longopts[] =
12879 {
12880 #ifdef OPTION_EB
12881 {"EB", no_argument, NULL, OPTION_EB},
12882 #endif
12883 #ifdef OPTION_EL
12884 {"EL", no_argument, NULL, OPTION_EL},
12885 #endif
12886 {NULL, no_argument, NULL, 0}
12887 };
12888
12889 size_t md_longopts_size = sizeof (md_longopts);
12890
12891 struct arm_option_table
12892 {
12893 char *option; /* Option name to match. */
12894 char *help; /* Help information. */
12895 int *var; /* Variable to change. */
12896 int value; /* What to change it to. */
12897 char *deprecated; /* If non-null, print this message. */
12898 };
12899
12900 struct arm_option_table arm_opts[] =
12901 {
12902 {"k", N_("generate PIC code"), &pic_code, 1, NULL},
12903 {"mthumb", N_("assemble Thumb code"), &thumb_mode, 1, NULL},
12904 {"mthumb-interwork", N_("support ARM/Thumb interworking"),
12905 &support_interwork, 1, NULL},
12906 {"mapcs-32", N_("code uses 32-bit program counter"), &uses_apcs_26, 0, NULL},
12907 {"mapcs-26", N_("code uses 26-bit program counter"), &uses_apcs_26, 1, NULL},
12908 {"mapcs-float", N_("floating point args are in fp regs"), &uses_apcs_float,
12909 1, NULL},
12910 {"mapcs-reentrant", N_("re-entrant code"), &pic_code, 1, NULL},
12911 {"matpcs", N_("code is ATPCS conformant"), &atpcs, 1, NULL},
12912 {"mbig-endian", N_("assemble for big-endian"), &target_big_endian, 1, NULL},
12913 {"mlittle-endian", N_("assemble for little-endian"), &target_big_endian, 1,
12914 NULL},
12915
12916 /* These are recognized by the assembler, but have no affect on code. */
12917 {"mapcs-frame", N_("use frame pointer"), NULL, 0, NULL},
12918 {"mapcs-stack-check", N_("use stack size checking"), NULL, 0, NULL},
12919
12920 /* DON'T add any new processors to this list -- we want the whole list
12921 to go away... Add them to the processors table instead. */
12922 {"marm1", NULL, &legacy_cpu, ARM_ARCH_V1, N_("use -mcpu=arm1")},
12923 {"m1", NULL, &legacy_cpu, ARM_ARCH_V1, N_("use -mcpu=arm1")},
12924 {"marm2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -mcpu=arm2")},
12925 {"m2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -mcpu=arm2")},
12926 {"marm250", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm250")},
12927 {"m250", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm250")},
12928 {"marm3", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm3")},
12929 {"m3", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm3")},
12930 {"marm6", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm6")},
12931 {"m6", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm6")},
12932 {"marm600", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm600")},
12933 {"m600", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm600")},
12934 {"marm610", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm610")},
12935 {"m610", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm610")},
12936 {"marm620", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm620")},
12937 {"m620", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm620")},
12938 {"marm7", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7")},
12939 {"m7", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7")},
12940 {"marm70", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm70")},
12941 {"m70", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm70")},
12942 {"marm700", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700")},
12943 {"m700", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700")},
12944 {"marm700i", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700i")},
12945 {"m700i", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700i")},
12946 {"marm710", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710")},
12947 {"m710", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710")},
12948 {"marm710c", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710c")},
12949 {"m710c", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710c")},
12950 {"marm720", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm720")},
12951 {"m720", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm720")},
12952 {"marm7d", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7d")},
12953 {"m7d", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7d")},
12954 {"marm7di", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7di")},
12955 {"m7di", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7di")},
12956 {"marm7m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7m")},
12957 {"m7m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7m")},
12958 {"marm7dm", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dm")},
12959 {"m7dm", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dm")},
12960 {"marm7dmi", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dmi")},
12961 {"m7dmi", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dmi")},
12962 {"marm7100", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7100")},
12963 {"m7100", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7100")},
12964 {"marm7500", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500")},
12965 {"m7500", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500")},
12966 {"marm7500fe", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500fe")},
12967 {"m7500fe", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500fe")},
12968 {"marm7t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
12969 {"m7t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
12970 {"marm7tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
12971 {"m7tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
12972 {"marm710t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm710t")},
12973 {"m710t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm710t")},
12974 {"marm720t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm720t")},
12975 {"m720t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm720t")},
12976 {"marm740t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm740t")},
12977 {"m740t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm740t")},
12978 {"marm8", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm8")},
12979 {"m8", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm8")},
12980 {"marm810", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm810")},
12981 {"m810", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm810")},
12982 {"marm9", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9")},
12983 {"m9", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9")},
12984 {"marm9tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9tdmi")},
12985 {"m9tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9tdmi")},
12986 {"marm920", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm920")},
12987 {"m920", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm920")},
12988 {"marm940", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm940")},
12989 {"m940", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm940")},
12990 {"mstrongarm", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=strongarm")},
12991 {"mstrongarm110", NULL, &legacy_cpu, ARM_ARCH_V4,
12992 N_("use -mcpu=strongarm110")},
12993 {"mstrongarm1100", NULL, &legacy_cpu, ARM_ARCH_V4,
12994 N_("use -mcpu=strongarm1100")},
12995 {"mstrongarm1110", NULL, &legacy_cpu, ARM_ARCH_V4,
12996 N_("use -mcpu=strongarm1110")},
12997 {"mxscale", NULL, &legacy_cpu, ARM_ARCH_XSCALE, N_("use -mcpu=xscale")},
12998 {"miwmmxt", NULL, &legacy_cpu, ARM_ARCH_IWMMXT, N_("use -mcpu=iwmmxt")},
12999 {"mall", NULL, &legacy_cpu, ARM_ANY, N_("use -mcpu=all")},
13000
13001 /* Architecture variants -- don't add any more to this list either. */
13002 {"mv2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -march=armv2")},
13003 {"marmv2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -march=armv2")},
13004 {"mv2a", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -march=armv2a")},
13005 {"marmv2a", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -march=armv2a")},
13006 {"mv3", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -march=armv3")},
13007 {"marmv3", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -march=armv3")},
13008 {"mv3m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -march=armv3m")},
13009 {"marmv3m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -march=armv3m")},
13010 {"mv4", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -march=armv4")},
13011 {"marmv4", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -march=armv4")},
13012 {"mv4t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -march=armv4t")},
13013 {"marmv4t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -march=armv4t")},
13014 {"mv5", NULL, &legacy_cpu, ARM_ARCH_V5, N_("use -march=armv5")},
13015 {"marmv5", NULL, &legacy_cpu, ARM_ARCH_V5, N_("use -march=armv5")},
13016 {"mv5t", NULL, &legacy_cpu, ARM_ARCH_V5T, N_("use -march=armv5t")},
13017 {"marmv5t", NULL, &legacy_cpu, ARM_ARCH_V5T, N_("use -march=armv5t")},
13018 {"mv5e", NULL, &legacy_cpu, ARM_ARCH_V5TE, N_("use -march=armv5te")},
13019 {"marmv5e", NULL, &legacy_cpu, ARM_ARCH_V5TE, N_("use -march=armv5te")},
13020
13021 /* Floating point variants -- don't add any more to this list either. */
13022 {"mfpe-old", NULL, &legacy_fpu, FPU_ARCH_FPE, N_("use -mfpu=fpe")},
13023 {"mfpa10", NULL, &legacy_fpu, FPU_ARCH_FPA, N_("use -mfpu=fpa10")},
13024 {"mfpa11", NULL, &legacy_fpu, FPU_ARCH_FPA, N_("use -mfpu=fpa11")},
13025 {"mno-fpu", NULL, &legacy_fpu, 0,
13026 N_("use either -mfpu=softfpa or -mfpu=softvfp")},
13027
13028 {NULL, NULL, NULL, 0, NULL}
13029 };
13030
13031 struct arm_cpu_option_table
13032 {
13033 char *name;
13034 int value;
13035 /* For some CPUs we assume an FPU unless the user explicitly sets
13036 -mfpu=... */
13037 int default_fpu;
13038 };
13039
13040 /* This list should, at a minimum, contain all the cpu names
13041 recognized by GCC. */
13042 static struct arm_cpu_option_table arm_cpus[] =
13043 {
13044 {"all", ARM_ANY, FPU_ARCH_FPA},
13045 {"arm1", ARM_ARCH_V1, FPU_ARCH_FPA},
13046 {"arm2", ARM_ARCH_V2, FPU_ARCH_FPA},
13047 {"arm250", ARM_ARCH_V2S, FPU_ARCH_FPA},
13048 {"arm3", ARM_ARCH_V2S, FPU_ARCH_FPA},
13049 {"arm6", ARM_ARCH_V3, FPU_ARCH_FPA},
13050 {"arm60", ARM_ARCH_V3, FPU_ARCH_FPA},
13051 {"arm600", ARM_ARCH_V3, FPU_ARCH_FPA},
13052 {"arm610", ARM_ARCH_V3, FPU_ARCH_FPA},
13053 {"arm620", ARM_ARCH_V3, FPU_ARCH_FPA},
13054 {"arm7", ARM_ARCH_V3, FPU_ARCH_FPA},
13055 {"arm7m", ARM_ARCH_V3M, FPU_ARCH_FPA},
13056 {"arm7d", ARM_ARCH_V3, FPU_ARCH_FPA},
13057 {"arm7dm", ARM_ARCH_V3M, FPU_ARCH_FPA},
13058 {"arm7di", ARM_ARCH_V3, FPU_ARCH_FPA},
13059 {"arm7dmi", ARM_ARCH_V3M, FPU_ARCH_FPA},
13060 {"arm70", ARM_ARCH_V3, FPU_ARCH_FPA},
13061 {"arm700", ARM_ARCH_V3, FPU_ARCH_FPA},
13062 {"arm700i", ARM_ARCH_V3, FPU_ARCH_FPA},
13063 {"arm710", ARM_ARCH_V3, FPU_ARCH_FPA},
13064 {"arm710t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13065 {"arm720", ARM_ARCH_V3, FPU_ARCH_FPA},
13066 {"arm720t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13067 {"arm740t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13068 {"arm710c", ARM_ARCH_V3, FPU_ARCH_FPA},
13069 {"arm7100", ARM_ARCH_V3, FPU_ARCH_FPA},
13070 {"arm7500", ARM_ARCH_V3, FPU_ARCH_FPA},
13071 {"arm7500fe", ARM_ARCH_V3, FPU_ARCH_FPA},
13072 {"arm7t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13073 {"arm7tdmi", ARM_ARCH_V4T, FPU_ARCH_FPA},
13074 {"arm7tdmi-s", ARM_ARCH_V4T, FPU_ARCH_FPA},
13075 {"arm8", ARM_ARCH_V4, FPU_ARCH_FPA},
13076 {"arm810", ARM_ARCH_V4, FPU_ARCH_FPA},
13077 {"strongarm", ARM_ARCH_V4, FPU_ARCH_FPA},
13078 {"strongarm1", ARM_ARCH_V4, FPU_ARCH_FPA},
13079 {"strongarm110", ARM_ARCH_V4, FPU_ARCH_FPA},
13080 {"strongarm1100", ARM_ARCH_V4, FPU_ARCH_FPA},
13081 {"strongarm1110", ARM_ARCH_V4, FPU_ARCH_FPA},
13082 {"arm9", ARM_ARCH_V4T, FPU_ARCH_FPA},
13083 {"arm920", ARM_ARCH_V4T, FPU_ARCH_FPA},
13084 {"arm920t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13085 {"arm922t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13086 {"arm940t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13087 {"arm9tdmi", ARM_ARCH_V4T, FPU_ARCH_FPA},
13088 /* For V5 or later processors we default to using VFP; but the user
13089 should really set the FPU type explicitly. */
13090 {"arm9e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
13091 {"arm9e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13092 {"arm926ej", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
13093 {"arm926ejs", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
13094 {"arm926ej-s", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
13095 {"arm946e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
13096 {"arm946e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13097 {"arm966e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
13098 {"arm966e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13099 {"arm10t", ARM_ARCH_V5T, FPU_ARCH_VFP_V1},
13100 {"arm10e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13101 {"arm1020", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13102 {"arm1020t", ARM_ARCH_V5T, FPU_ARCH_VFP_V1},
13103 {"arm1020e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13104 {"arm1026ejs", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
13105 {"arm1026ej-s", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
13106 {"arm1136js", ARM_ARCH_V6, FPU_NONE},
13107 {"arm1136j-s", ARM_ARCH_V6, FPU_NONE},
13108 {"arm1136jfs", ARM_ARCH_V6, FPU_ARCH_VFP_V2},
13109 {"arm1136jf-s", ARM_ARCH_V6, FPU_ARCH_VFP_V2},
13110 {"mpcore", ARM_ARCH_V6K, FPU_ARCH_VFP_V2},
13111 {"mpcorenovfp", ARM_ARCH_V6K, FPU_NONE},
13112 {"arm1176jz-s", ARM_ARCH_V6ZK, FPU_NONE},
13113 {"arm1176jzf-s", ARM_ARCH_V6ZK, FPU_ARCH_VFP_V2},
13114 /* ??? XSCALE is really an architecture. */
13115 {"xscale", ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2},
13116 /* ??? iwmmxt is not a processor. */
13117 {"iwmmxt", ARM_ARCH_IWMMXT, FPU_ARCH_VFP_V2},
13118 {"i80200", ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2},
13119 /* Maverick */
13120 {"ep9312", ARM_ARCH_V4T | ARM_CEXT_MAVERICK, FPU_ARCH_MAVERICK},
13121 {NULL, 0, 0}
13122 };
13123
13124 struct arm_arch_option_table
13125 {
13126 char *name;
13127 int value;
13128 int default_fpu;
13129 };
13130
13131 /* This list should, at a minimum, contain all the architecture names
13132 recognized by GCC. */
13133 static struct arm_arch_option_table arm_archs[] =
13134 {
13135 {"all", ARM_ANY, FPU_ARCH_FPA},
13136 {"armv1", ARM_ARCH_V1, FPU_ARCH_FPA},
13137 {"armv2", ARM_ARCH_V2, FPU_ARCH_FPA},
13138 {"armv2a", ARM_ARCH_V2S, FPU_ARCH_FPA},
13139 {"armv2s", ARM_ARCH_V2S, FPU_ARCH_FPA},
13140 {"armv3", ARM_ARCH_V3, FPU_ARCH_FPA},
13141 {"armv3m", ARM_ARCH_V3M, FPU_ARCH_FPA},
13142 {"armv4", ARM_ARCH_V4, FPU_ARCH_FPA},
13143 {"armv4xm", ARM_ARCH_V4xM, FPU_ARCH_FPA},
13144 {"armv4t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13145 {"armv4txm", ARM_ARCH_V4TxM, FPU_ARCH_FPA},
13146 {"armv5", ARM_ARCH_V5, FPU_ARCH_VFP},
13147 {"armv5t", ARM_ARCH_V5T, FPU_ARCH_VFP},
13148 {"armv5txm", ARM_ARCH_V5TxM, FPU_ARCH_VFP},
13149 {"armv5te", ARM_ARCH_V5TE, FPU_ARCH_VFP},
13150 {"armv5texp", ARM_ARCH_V5TExP, FPU_ARCH_VFP},
13151 {"armv5tej", ARM_ARCH_V5TEJ, FPU_ARCH_VFP},
13152 {"armv6", ARM_ARCH_V6, FPU_ARCH_VFP},
13153 {"armv6j", ARM_ARCH_V6, FPU_ARCH_VFP},
13154 {"armv6k", ARM_ARCH_V6K, FPU_ARCH_VFP},
13155 {"armv6z", ARM_ARCH_V6Z, FPU_ARCH_VFP},
13156 {"armv6zk", ARM_ARCH_V6ZK, FPU_ARCH_VFP},
13157 {"armv6t2", ARM_ARCH_V6T2, FPU_ARCH_VFP},
13158 {"armv6kt2", ARM_ARCH_V6KT2, FPU_ARCH_VFP},
13159 {"armv6zt2", ARM_ARCH_V6ZT2, FPU_ARCH_VFP},
13160 {"armv6zkt2", ARM_ARCH_V6ZKT2, FPU_ARCH_VFP},
13161 {"xscale", ARM_ARCH_XSCALE, FPU_ARCH_VFP},
13162 {"iwmmxt", ARM_ARCH_IWMMXT, FPU_ARCH_VFP},
13163 {NULL, 0, 0}
13164 };
13165
13166 /* ISA extensions in the co-processor space. */
13167 struct arm_arch_extension_table
13168 {
13169 char *name;
13170 int value;
13171 };
13172
13173 static struct arm_arch_extension_table arm_extensions[] =
13174 {
13175 {"maverick", ARM_CEXT_MAVERICK},
13176 {"xscale", ARM_CEXT_XSCALE},
13177 {"iwmmxt", ARM_CEXT_IWMMXT},
13178 {NULL, 0}
13179 };
13180
13181 struct arm_fpu_option_table
13182 {
13183 char *name;
13184 int value;
13185 };
13186
13187 /* This list should, at a minimum, contain all the fpu names
13188 recognized by GCC. */
13189 static struct arm_fpu_option_table arm_fpus[] =
13190 {
13191 {"softfpa", FPU_NONE},
13192 {"fpe", FPU_ARCH_FPE},
13193 {"fpe2", FPU_ARCH_FPE},
13194 {"fpe3", FPU_ARCH_FPA}, /* Third release supports LFM/SFM. */
13195 {"fpa", FPU_ARCH_FPA},
13196 {"fpa10", FPU_ARCH_FPA},
13197 {"fpa11", FPU_ARCH_FPA},
13198 {"arm7500fe", FPU_ARCH_FPA},
13199 {"softvfp", FPU_ARCH_VFP},
13200 {"softvfp+vfp", FPU_ARCH_VFP_V2},
13201 {"vfp", FPU_ARCH_VFP_V2},
13202 {"vfp9", FPU_ARCH_VFP_V2},
13203 {"vfp10", FPU_ARCH_VFP_V2},
13204 {"vfp10-r0", FPU_ARCH_VFP_V1},
13205 {"vfpxd", FPU_ARCH_VFP_V1xD},
13206 {"arm1020t", FPU_ARCH_VFP_V1},
13207 {"arm1020e", FPU_ARCH_VFP_V2},
13208 {"arm1136jfs", FPU_ARCH_VFP_V2},
13209 {"arm1136jf-s", FPU_ARCH_VFP_V2},
13210 {"maverick", FPU_ARCH_MAVERICK},
13211 {NULL, 0}
13212 };
13213
13214 struct arm_float_abi_option_table
13215 {
13216 char *name;
13217 int value;
13218 };
13219
13220 static struct arm_float_abi_option_table arm_float_abis[] =
13221 {
13222 {"hard", ARM_FLOAT_ABI_HARD},
13223 {"softfp", ARM_FLOAT_ABI_SOFTFP},
13224 {"soft", ARM_FLOAT_ABI_SOFT},
13225 {NULL, 0}
13226 };
13227
13228 struct arm_eabi_option_table
13229 {
13230 char *name;
13231 unsigned int value;
13232 };
13233
13234 #ifdef OBJ_ELF
13235 /* We only know how to output GNU and ver 4 (AAELF) formats. */
13236 static struct arm_eabi_option_table arm_eabis[] =
13237 {
13238 {"gnu", EF_ARM_EABI_UNKNOWN},
13239 {"4", EF_ARM_EABI_VER4},
13240 {NULL, 0}
13241 };
13242 #endif
13243
13244 struct arm_long_option_table
13245 {
13246 char * option; /* Substring to match. */
13247 char * help; /* Help information. */
13248 int (* func) (char * subopt); /* Function to decode sub-option. */
13249 char * deprecated; /* If non-null, print this message. */
13250 };
13251
13252 static int
13253 arm_parse_extension (char * str, int * opt_p)
13254 {
13255 while (str != NULL && *str != 0)
13256 {
13257 struct arm_arch_extension_table * opt;
13258 char * ext;
13259 int optlen;
13260
13261 if (*str != '+')
13262 {
13263 as_bad (_("invalid architectural extension"));
13264 return 0;
13265 }
13266
13267 str++;
13268 ext = strchr (str, '+');
13269
13270 if (ext != NULL)
13271 optlen = ext - str;
13272 else
13273 optlen = strlen (str);
13274
13275 if (optlen == 0)
13276 {
13277 as_bad (_("missing architectural extension"));
13278 return 0;
13279 }
13280
13281 for (opt = arm_extensions; opt->name != NULL; opt++)
13282 if (strncmp (opt->name, str, optlen) == 0)
13283 {
13284 *opt_p |= opt->value;
13285 break;
13286 }
13287
13288 if (opt->name == NULL)
13289 {
13290 as_bad (_("unknown architectural extnsion `%s'"), str);
13291 return 0;
13292 }
13293
13294 str = ext;
13295 };
13296
13297 return 1;
13298 }
13299
13300 static int
13301 arm_parse_cpu (char * str)
13302 {
13303 struct arm_cpu_option_table * opt;
13304 char * ext = strchr (str, '+');
13305 int optlen;
13306
13307 if (ext != NULL)
13308 optlen = ext - str;
13309 else
13310 optlen = strlen (str);
13311
13312 if (optlen == 0)
13313 {
13314 as_bad (_("missing cpu name `%s'"), str);
13315 return 0;
13316 }
13317
13318 for (opt = arm_cpus; opt->name != NULL; opt++)
13319 if (strncmp (opt->name, str, optlen) == 0)
13320 {
13321 mcpu_cpu_opt = opt->value;
13322 mcpu_fpu_opt = opt->default_fpu;
13323
13324 if (ext != NULL)
13325 return arm_parse_extension (ext, &mcpu_cpu_opt);
13326
13327 return 1;
13328 }
13329
13330 as_bad (_("unknown cpu `%s'"), str);
13331 return 0;
13332 }
13333
13334 static int
13335 arm_parse_arch (char * str)
13336 {
13337 struct arm_arch_option_table *opt;
13338 char *ext = strchr (str, '+');
13339 int optlen;
13340
13341 if (ext != NULL)
13342 optlen = ext - str;
13343 else
13344 optlen = strlen (str);
13345
13346 if (optlen == 0)
13347 {
13348 as_bad (_("missing architecture name `%s'"), str);
13349 return 0;
13350 }
13351
13352
13353 for (opt = arm_archs; opt->name != NULL; opt++)
13354 if (streq (opt->name, str))
13355 {
13356 march_cpu_opt = opt->value;
13357 march_fpu_opt = opt->default_fpu;
13358
13359 if (ext != NULL)
13360 return arm_parse_extension (ext, &march_cpu_opt);
13361
13362 return 1;
13363 }
13364
13365 as_bad (_("unknown architecture `%s'\n"), str);
13366 return 0;
13367 }
13368
13369 static int
13370 arm_parse_fpu (char * str)
13371 {
13372 struct arm_fpu_option_table * opt;
13373
13374 for (opt = arm_fpus; opt->name != NULL; opt++)
13375 if (streq (opt->name, str))
13376 {
13377 mfpu_opt = opt->value;
13378 return 1;
13379 }
13380
13381 as_bad (_("unknown floating point format `%s'\n"), str);
13382 return 0;
13383 }
13384
13385 static int
13386 arm_parse_float_abi (char * str)
13387 {
13388 struct arm_float_abi_option_table * opt;
13389
13390 for (opt = arm_float_abis; opt->name != NULL; opt++)
13391 if (streq (opt->name, str))
13392 {
13393 mfloat_abi_opt = opt->value;
13394 return 1;
13395 }
13396
13397 as_bad (_("unknown floating point abi `%s'\n"), str);
13398 return 0;
13399 }
13400
13401 #ifdef OBJ_ELF
13402 static int
13403 arm_parse_eabi (char * str)
13404 {
13405 struct arm_eabi_option_table *opt;
13406
13407 for (opt = arm_eabis; opt->name != NULL; opt++)
13408 if (streq (opt->name, str))
13409 {
13410 meabi_flags = opt->value;
13411 return 1;
13412 }
13413 as_bad (_("unknown EABI `%s'\n"), str);
13414 return 0;
13415 }
13416 #endif
13417
13418 struct arm_long_option_table arm_long_opts[] =
13419 {
13420 {"mcpu=", N_("<cpu name>\t assemble for CPU <cpu name>"),
13421 arm_parse_cpu, NULL},
13422 {"march=", N_("<arch name>\t assemble for architecture <arch name>"),
13423 arm_parse_arch, NULL},
13424 {"mfpu=", N_("<fpu name>\t assemble for FPU architecture <fpu name>"),
13425 arm_parse_fpu, NULL},
13426 {"mfloat-abi=", N_("<abi>\t assemble for floating point ABI <abi>"),
13427 arm_parse_float_abi, NULL},
13428 #ifdef OBJ_ELF
13429 {"meabi=", N_("<ver>\t assemble for eabi version <ver>"),
13430 arm_parse_eabi, NULL},
13431 #endif
13432 {NULL, NULL, 0, NULL}
13433 };
13434
13435 int
13436 md_parse_option (int c, char * arg)
13437 {
13438 struct arm_option_table *opt;
13439 struct arm_long_option_table *lopt;
13440
13441 switch (c)
13442 {
13443 #ifdef OPTION_EB
13444 case OPTION_EB:
13445 target_big_endian = 1;
13446 break;
13447 #endif
13448
13449 #ifdef OPTION_EL
13450 case OPTION_EL:
13451 target_big_endian = 0;
13452 break;
13453 #endif
13454
13455 case 'a':
13456 /* Listing option. Just ignore these, we don't support additional
13457 ones. */
13458 return 0;
13459
13460 default:
13461 for (opt = arm_opts; opt->option != NULL; opt++)
13462 {
13463 if (c == opt->option[0]
13464 && ((arg == NULL && opt->option[1] == 0)
13465 || streq (arg, opt->option + 1)))
13466 {
13467 #if WARN_DEPRECATED
13468 /* If the option is deprecated, tell the user. */
13469 if (opt->deprecated != NULL)
13470 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c,
13471 arg ? arg : "", _(opt->deprecated));
13472 #endif
13473
13474 if (opt->var != NULL)
13475 *opt->var = opt->value;
13476
13477 return 1;
13478 }
13479 }
13480
13481 for (lopt = arm_long_opts; lopt->option != NULL; lopt++)
13482 {
13483 /* These options are expected to have an argument. */
13484 if (c == lopt->option[0]
13485 && arg != NULL
13486 && strncmp (arg, lopt->option + 1,
13487 strlen (lopt->option + 1)) == 0)
13488 {
13489 #if WARN_DEPRECATED
13490 /* If the option is deprecated, tell the user. */
13491 if (lopt->deprecated != NULL)
13492 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c, arg,
13493 _(lopt->deprecated));
13494 #endif
13495
13496 /* Call the sup-option parser. */
13497 return lopt->func (arg + strlen (lopt->option) - 1);
13498 }
13499 }
13500
13501 return 0;
13502 }
13503
13504 return 1;
13505 }
13506
13507 void
13508 md_show_usage (FILE * fp)
13509 {
13510 struct arm_option_table *opt;
13511 struct arm_long_option_table *lopt;
13512
13513 fprintf (fp, _(" ARM-specific assembler options:\n"));
13514
13515 for (opt = arm_opts; opt->option != NULL; opt++)
13516 if (opt->help != NULL)
13517 fprintf (fp, " -%-23s%s\n", opt->option, _(opt->help));
13518
13519 for (lopt = arm_long_opts; lopt->option != NULL; lopt++)
13520 if (lopt->help != NULL)
13521 fprintf (fp, " -%s%s\n", lopt->option, _(lopt->help));
13522
13523 #ifdef OPTION_EB
13524 fprintf (fp, _("\
13525 -EB assemble code for a big-endian cpu\n"));
13526 #endif
13527
13528 #ifdef OPTION_EL
13529 fprintf (fp, _("\
13530 -EL assemble code for a little-endian cpu\n"));
13531 #endif
13532 }
13533
13534 /* This fix_new is called by cons via TC_CONS_FIX_NEW. */
13535
13536 void
13537 cons_fix_new_arm (fragS * frag,
13538 int where,
13539 int size,
13540 expressionS * exp)
13541 {
13542 bfd_reloc_code_real_type type;
13543 int pcrel = 0;
13544
13545 /* Pick a reloc.
13546 FIXME: @@ Should look at CPU word size. */
13547 switch (size)
13548 {
13549 case 1:
13550 type = BFD_RELOC_8;
13551 break;
13552 case 2:
13553 type = BFD_RELOC_16;
13554 break;
13555 case 4:
13556 default:
13557 type = BFD_RELOC_32;
13558 break;
13559 case 8:
13560 type = BFD_RELOC_64;
13561 break;
13562 }
13563
13564 fix_new_exp (frag, where, (int) size, exp, pcrel, type);
13565 }
13566
13567 /* A good place to do this, although this was probably not intended
13568 for this kind of use. We need to dump the literal pool before
13569 references are made to a null symbol pointer. */
13570
13571 void
13572 arm_cleanup (void)
13573 {
13574 literal_pool * pool;
13575
13576 for (pool = list_of_pools; pool; pool = pool->next)
13577 {
13578 /* Put it at the end of the relevent section. */
13579 subseg_set (pool->section, pool->sub_section);
13580 #ifdef OBJ_ELF
13581 arm_elf_change_section ();
13582 #endif
13583 s_ltorg (0);
13584 }
13585 }
13586
13587 void
13588 arm_start_line_hook (void)
13589 {
13590 last_label_seen = NULL;
13591 }
13592
13593 void
13594 arm_frob_label (symbolS * sym)
13595 {
13596 last_label_seen = sym;
13597
13598 ARM_SET_THUMB (sym, thumb_mode);
13599
13600 #if defined OBJ_COFF || defined OBJ_ELF
13601 ARM_SET_INTERWORK (sym, support_interwork);
13602 #endif
13603
13604 /* Note - do not allow local symbols (.Lxxx) to be labeled
13605 as Thumb functions. This is because these labels, whilst
13606 they exist inside Thumb code, are not the entry points for
13607 possible ARM->Thumb calls. Also, these labels can be used
13608 as part of a computed goto or switch statement. eg gcc
13609 can generate code that looks like this:
13610
13611 ldr r2, [pc, .Laaa]
13612 lsl r3, r3, #2
13613 ldr r2, [r3, r2]
13614 mov pc, r2
13615
13616 .Lbbb: .word .Lxxx
13617 .Lccc: .word .Lyyy
13618 ..etc...
13619 .Laaa: .word Lbbb
13620
13621 The first instruction loads the address of the jump table.
13622 The second instruction converts a table index into a byte offset.
13623 The third instruction gets the jump address out of the table.
13624 The fourth instruction performs the jump.
13625
13626 If the address stored at .Laaa is that of a symbol which has the
13627 Thumb_Func bit set, then the linker will arrange for this address
13628 to have the bottom bit set, which in turn would mean that the
13629 address computation performed by the third instruction would end
13630 up with the bottom bit set. Since the ARM is capable of unaligned
13631 word loads, the instruction would then load the incorrect address
13632 out of the jump table, and chaos would ensue. */
13633 if (label_is_thumb_function_name
13634 && (S_GET_NAME (sym)[0] != '.' || S_GET_NAME (sym)[1] != 'L')
13635 && (bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
13636 {
13637 /* When the address of a Thumb function is taken the bottom
13638 bit of that address should be set. This will allow
13639 interworking between Arm and Thumb functions to work
13640 correctly. */
13641
13642 THUMB_SET_FUNC (sym, 1);
13643
13644 label_is_thumb_function_name = FALSE;
13645 }
13646 }
13647
13648 /* Adjust the symbol table. This marks Thumb symbols as distinct from
13649 ARM ones. */
13650
13651 void
13652 arm_adjust_symtab (void)
13653 {
13654 #ifdef OBJ_COFF
13655 symbolS * sym;
13656
13657 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
13658 {
13659 if (ARM_IS_THUMB (sym))
13660 {
13661 if (THUMB_IS_FUNC (sym))
13662 {
13663 /* Mark the symbol as a Thumb function. */
13664 if ( S_GET_STORAGE_CLASS (sym) == C_STAT
13665 || S_GET_STORAGE_CLASS (sym) == C_LABEL) /* This can happen! */
13666 S_SET_STORAGE_CLASS (sym, C_THUMBSTATFUNC);
13667
13668 else if (S_GET_STORAGE_CLASS (sym) == C_EXT)
13669 S_SET_STORAGE_CLASS (sym, C_THUMBEXTFUNC);
13670 else
13671 as_bad (_("%s: unexpected function type: %d"),
13672 S_GET_NAME (sym), S_GET_STORAGE_CLASS (sym));
13673 }
13674 else switch (S_GET_STORAGE_CLASS (sym))
13675 {
13676 case C_EXT:
13677 S_SET_STORAGE_CLASS (sym, C_THUMBEXT);
13678 break;
13679 case C_STAT:
13680 S_SET_STORAGE_CLASS (sym, C_THUMBSTAT);
13681 break;
13682 case C_LABEL:
13683 S_SET_STORAGE_CLASS (sym, C_THUMBLABEL);
13684 break;
13685 default:
13686 /* Do nothing. */
13687 break;
13688 }
13689 }
13690
13691 if (ARM_IS_INTERWORK (sym))
13692 coffsymbol (symbol_get_bfdsym (sym))->native->u.syment.n_flags = 0xFF;
13693 }
13694 #endif
13695 #ifdef OBJ_ELF
13696 symbolS * sym;
13697 char bind;
13698
13699 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
13700 {
13701 if (ARM_IS_THUMB (sym))
13702 {
13703 elf_symbol_type * elf_sym;
13704
13705 elf_sym = elf_symbol (symbol_get_bfdsym (sym));
13706 bind = ELF_ST_BIND (elf_sym->internal_elf_sym.st_info);
13707
13708 /* If it's a .thumb_func, declare it as so,
13709 otherwise tag label as .code 16. */
13710 if (THUMB_IS_FUNC (sym))
13711 elf_sym->internal_elf_sym.st_info =
13712 ELF_ST_INFO (bind, STT_ARM_TFUNC);
13713 else
13714 elf_sym->internal_elf_sym.st_info =
13715 ELF_ST_INFO (bind, STT_ARM_16BIT);
13716 }
13717 }
13718 #endif
13719 }
13720
13721 int
13722 arm_data_in_code (void)
13723 {
13724 if (thumb_mode && ! strncmp (input_line_pointer + 1, "data:", 5))
13725 {
13726 *input_line_pointer = '/';
13727 input_line_pointer += 5;
13728 *input_line_pointer = 0;
13729 return 1;
13730 }
13731
13732 return 0;
13733 }
13734
13735 char *
13736 arm_canonicalize_symbol_name (char * name)
13737 {
13738 int len;
13739
13740 if (thumb_mode && (len = strlen (name)) > 5
13741 && streq (name + len - 5, "/data"))
13742 *(name + len - 5) = 0;
13743
13744 return name;
13745 }
13746
13747 #if defined OBJ_COFF || defined OBJ_ELF
13748 void
13749 arm_validate_fix (fixS * fixP)
13750 {
13751 /* If the destination of the branch is a defined symbol which does not have
13752 the THUMB_FUNC attribute, then we must be calling a function which has
13753 the (interfacearm) attribute. We look for the Thumb entry point to that
13754 function and change the branch to refer to that function instead. */
13755 if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23
13756 && fixP->fx_addsy != NULL
13757 && S_IS_DEFINED (fixP->fx_addsy)
13758 && ! THUMB_IS_FUNC (fixP->fx_addsy))
13759 {
13760 fixP->fx_addsy = find_real_start (fixP->fx_addsy);
13761 }
13762 }
13763 #endif
13764
13765 int
13766 arm_force_relocation (struct fix * fixp)
13767 {
13768 #if defined (OBJ_COFF) && defined (TE_PE)
13769 if (fixp->fx_r_type == BFD_RELOC_RVA)
13770 return 1;
13771 #endif
13772 #ifdef OBJ_ELF
13773 if (fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH
13774 || fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BLX
13775 || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX
13776 || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23)
13777 return 1;
13778 #endif
13779
13780 /* Resolve these relocations even if the symbol is extern or weak. */
13781 if (fixp->fx_r_type == BFD_RELOC_ARM_IMMEDIATE
13782 || fixp->fx_r_type == BFD_RELOC_ARM_OFFSET_IMM
13783 || fixp->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE)
13784 return 0;
13785
13786 return generic_force_reloc (fixp);
13787 }
13788
13789 #ifdef OBJ_COFF
13790 /* This is a little hack to help the gas/arm/adrl.s test. It prevents
13791 local labels from being added to the output symbol table when they
13792 are used with the ADRL pseudo op. The ADRL relocation should always
13793 be resolved before the binbary is emitted, so it is safe to say that
13794 it is adjustable. */
13795
13796 bfd_boolean
13797 arm_fix_adjustable (fixS * fixP)
13798 {
13799 if (fixP->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE)
13800 return 1;
13801 return 0;
13802 }
13803 #endif
13804
13805 #ifdef OBJ_ELF
13806 /* Relocations against Thumb function names must be left unadjusted,
13807 so that the linker can use this information to correctly set the
13808 bottom bit of their addresses. The MIPS version of this function
13809 also prevents relocations that are mips-16 specific, but I do not
13810 know why it does this.
13811
13812 FIXME:
13813 There is one other problem that ought to be addressed here, but
13814 which currently is not: Taking the address of a label (rather
13815 than a function) and then later jumping to that address. Such
13816 addresses also ought to have their bottom bit set (assuming that
13817 they reside in Thumb code), but at the moment they will not. */
13818
13819 bfd_boolean
13820 arm_fix_adjustable (fixS * fixP)
13821 {
13822 if (fixP->fx_addsy == NULL)
13823 return 1;
13824
13825 if (THUMB_IS_FUNC (fixP->fx_addsy)
13826 && fixP->fx_subsy == NULL)
13827 return 0;
13828
13829 /* We need the symbol name for the VTABLE entries. */
13830 if ( fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
13831 || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
13832 return 0;
13833
13834 /* Don't allow symbols to be discarded on GOT related relocs. */
13835 if (fixP->fx_r_type == BFD_RELOC_ARM_PLT32
13836 || fixP->fx_r_type == BFD_RELOC_ARM_GOT32
13837 || fixP->fx_r_type == BFD_RELOC_ARM_GOTOFF
13838 || fixP->fx_r_type == BFD_RELOC_ARM_TARGET2)
13839 return 0;
13840
13841 return 1;
13842 }
13843
13844 const char *
13845 elf32_arm_target_format (void)
13846 {
13847 #ifdef TE_SYMBIAN
13848 return (target_big_endian
13849 ? "elf32-bigarm-symbian"
13850 : "elf32-littlearm-symbian");
13851 #elif defined (TE_VXWORKS)
13852 return (target_big_endian
13853 ? "elf32-bigarm-vxworks"
13854 : "elf32-littlearm-vxworks");
13855 #else
13856 if (target_big_endian)
13857 return "elf32-bigarm";
13858 else
13859 return "elf32-littlearm";
13860 #endif
13861 }
13862
13863 void
13864 armelf_frob_symbol (symbolS * symp,
13865 int * puntp)
13866 {
13867 elf_frob_symbol (symp, puntp);
13868 }
13869
13870 static void
13871 s_arm_elf_cons (int nbytes)
13872 {
13873 expressionS exp;
13874
13875 #ifdef md_flush_pending_output
13876 md_flush_pending_output ();
13877 #endif
13878
13879 if (is_it_end_of_statement ())
13880 {
13881 demand_empty_rest_of_line ();
13882 return;
13883 }
13884
13885 #ifdef md_cons_align
13886 md_cons_align (nbytes);
13887 #endif
13888
13889 mapping_state (MAP_DATA);
13890 do
13891 {
13892 bfd_reloc_code_real_type reloc;
13893
13894 expression (& exp);
13895
13896 if (exp.X_op == O_symbol
13897 && * input_line_pointer == '('
13898 && (reloc = arm_parse_reloc ()) != BFD_RELOC_UNUSED)
13899 {
13900 reloc_howto_type *howto = bfd_reloc_type_lookup (stdoutput, reloc);
13901 int size = bfd_get_reloc_size (howto);
13902
13903 if (size > nbytes)
13904 as_bad ("%s relocations do not fit in %d bytes",
13905 howto->name, nbytes);
13906 else
13907 {
13908 char *p = frag_more ((int) nbytes);
13909 int offset = nbytes - size;
13910
13911 fix_new_exp (frag_now, p - frag_now->fr_literal + offset, size,
13912 &exp, 0, reloc);
13913 }
13914 }
13915 else
13916 emit_expr (&exp, (unsigned int) nbytes);
13917 }
13918 while (*input_line_pointer++ == ',');
13919
13920 /* Put terminator back into stream. */
13921 input_line_pointer --;
13922 demand_empty_rest_of_line ();
13923 }
13924
13925
13926 /* Parse a .rel31 directive. */
13927
13928 static void
13929 s_arm_rel31 (int ignored ATTRIBUTE_UNUSED)
13930 {
13931 expressionS exp;
13932 char *p;
13933 valueT highbit;
13934
13935 SKIP_WHITESPACE ();
13936
13937 highbit = 0;
13938 if (*input_line_pointer == '1')
13939 highbit = 0x80000000;
13940 else if (*input_line_pointer != '0')
13941 as_bad (_("expected 0 or 1"));
13942
13943 input_line_pointer++;
13944 SKIP_WHITESPACE ();
13945 if (*input_line_pointer != ',')
13946 as_bad (_("missing comma"));
13947 input_line_pointer++;
13948
13949 #ifdef md_flush_pending_output
13950 md_flush_pending_output ();
13951 #endif
13952
13953 #ifdef md_cons_align
13954 md_cons_align (4);
13955 #endif
13956
13957 mapping_state (MAP_DATA);
13958
13959 expression (&exp);
13960
13961 p = frag_more (4);
13962 md_number_to_chars (p, highbit, 4);
13963 fix_new_arm (frag_now, p - frag_now->fr_literal, 4, &exp, 1,
13964 BFD_RELOC_ARM_PREL31);
13965
13966 demand_empty_rest_of_line ();
13967 }
13968 \f
13969 /* Code to deal with unwinding tables. */
13970
13971 static void add_unwind_adjustsp (offsetT);
13972
13973 /* Switch to section NAME and create section if necessary. It's
13974 rather ugly that we have to manipulate input_line_pointer but I
13975 don't see any other way to accomplish the same thing without
13976 changing obj-elf.c (which may be the Right Thing, in the end).
13977 Copied from tc-ia64.c. */
13978
13979 static void
13980 set_section (char *name)
13981 {
13982 char *saved_input_line_pointer;
13983
13984 saved_input_line_pointer = input_line_pointer;
13985 input_line_pointer = name;
13986 obj_elf_section (0);
13987 input_line_pointer = saved_input_line_pointer;
13988 }
13989
13990 /* Cenerate and deferred unwind frame offset. */
13991
13992 static void
13993 flush_pending_unwind (void)
13994 {
13995 offsetT offset;
13996
13997 offset = unwind.pending_offset;
13998 unwind.pending_offset = 0;
13999 if (offset != 0)
14000 add_unwind_adjustsp (offset);
14001 }
14002
14003 /* Add an opcode to this list for this function. Two-byte opcodes should
14004 be passed as op[0] << 8 | op[1]. The list of opcodes is built in reverse
14005 order. */
14006
14007 static void
14008 add_unwind_opcode (valueT op, int length)
14009 {
14010 /* Add any deferred stack adjustment. */
14011 if (unwind.pending_offset)
14012 flush_pending_unwind ();
14013
14014 unwind.sp_restored = 0;
14015
14016 if (unwind.opcode_count + length > unwind.opcode_alloc)
14017 {
14018 unwind.opcode_alloc += ARM_OPCODE_CHUNK_SIZE;
14019 if (unwind.opcodes)
14020 unwind.opcodes = xrealloc (unwind.opcodes,
14021 unwind.opcode_alloc);
14022 else
14023 unwind.opcodes = xmalloc (unwind.opcode_alloc);
14024 }
14025 while (length > 0)
14026 {
14027 length--;
14028 unwind.opcodes[unwind.opcode_count] = op & 0xff;
14029 op >>= 8;
14030 unwind.opcode_count++;
14031 }
14032 }
14033
14034 /* Add unwind opcodes to adjust the stack pointer. */
14035
14036 static void
14037 add_unwind_adjustsp (offsetT offset)
14038 {
14039 valueT op;
14040
14041 if (offset > 0x200)
14042 {
14043 /* We need at most 5 bytes to hold a 32-bit value in a uleb128. */
14044 char bytes[5];
14045 int n;
14046 valueT o;
14047
14048 /* Long form: 0xb2, uleb128. */
14049 /* This might not fit in a word so add the individual bytes,
14050 remembering the list is built in reverse order. */
14051 o = (valueT) ((offset - 0x204) >> 2);
14052 if (o == 0)
14053 add_unwind_opcode (0, 1);
14054
14055 /* Calculate the uleb128 encoding of the offset. */
14056 n = 0;
14057 while (o)
14058 {
14059 bytes[n] = o & 0x7f;
14060 o >>= 7;
14061 if (o)
14062 bytes[n] |= 0x80;
14063 n++;
14064 }
14065 /* Add the insn. */
14066 for (; n; n--)
14067 add_unwind_opcode (bytes[n - 1], 1);
14068 add_unwind_opcode (0xb2, 1);
14069 }
14070 else if (offset > 0x100)
14071 {
14072 /* Two short opcodes. */
14073 add_unwind_opcode (0x3f, 1);
14074 op = (offset - 0x104) >> 2;
14075 add_unwind_opcode (op, 1);
14076 }
14077 else if (offset > 0)
14078 {
14079 /* Short opcode. */
14080 op = (offset - 4) >> 2;
14081 add_unwind_opcode (op, 1);
14082 }
14083 else if (offset < 0)
14084 {
14085 offset = -offset;
14086 while (offset > 0x100)
14087 {
14088 add_unwind_opcode (0x7f, 1);
14089 offset -= 0x100;
14090 }
14091 op = ((offset - 4) >> 2) | 0x40;
14092 add_unwind_opcode (op, 1);
14093 }
14094 }
14095
14096 /* Finish the list of unwind opcodes for this function. */
14097 static void
14098 finish_unwind_opcodes (void)
14099 {
14100 valueT op;
14101
14102 if (unwind.fp_used)
14103 {
14104 /* Adjust sp as neccessary. */
14105 unwind.pending_offset += unwind.fp_offset - unwind.frame_size;
14106 flush_pending_unwind ();
14107
14108 /* After restoring sp from the frame pointer. */
14109 op = 0x90 | unwind.fp_reg;
14110 add_unwind_opcode (op, 1);
14111 }
14112 else
14113 flush_pending_unwind ();
14114 }
14115
14116
14117 /* Start an exception table entry. If idx is nonzero this is an index table
14118 entry. */
14119
14120 static void
14121 start_unwind_section (const segT text_seg, int idx)
14122 {
14123 const char * text_name;
14124 const char * prefix;
14125 const char * prefix_once;
14126 size_t prefix_len;
14127 size_t text_len;
14128 char * sec_name;
14129 size_t sec_name_len;
14130
14131 if (idx)
14132 {
14133 prefix = ELF_STRING_ARM_unwind;
14134 prefix_once = ELF_STRING_ARM_unwind_once;
14135 }
14136 else
14137 {
14138 prefix = ELF_STRING_ARM_unwind_info;
14139 prefix_once = ELF_STRING_ARM_unwind_info_once;
14140 }
14141
14142 text_name = segment_name (text_seg);
14143 if (streq (text_name, ".text"))
14144 text_name = "";
14145
14146 if (strncmp (text_name, ".gnu.linkonce.t.",
14147 strlen (".gnu.linkonce.t.")) == 0)
14148 {
14149 prefix = prefix_once;
14150 text_name += strlen (".gnu.linkonce.t.");
14151 }
14152
14153 prefix_len = strlen (prefix);
14154 text_len = strlen (text_name);
14155 sec_name_len = prefix_len + text_len;
14156 sec_name = alloca (sec_name_len + 1);
14157 memcpy (sec_name, prefix, prefix_len);
14158 memcpy (sec_name + prefix_len, text_name, text_len);
14159 sec_name[prefix_len + text_len] = '\0';
14160
14161 /* Handle COMDAT group. */
14162 if (prefix != prefix_once && (text_seg->flags & SEC_LINK_ONCE) != 0)
14163 {
14164 char *section;
14165 size_t len, group_name_len;
14166 const char *group_name = elf_group_name (text_seg);
14167
14168 if (group_name == NULL)
14169 {
14170 as_bad ("Group section `%s' has no group signature",
14171 segment_name (text_seg));
14172 ignore_rest_of_line ();
14173 return;
14174 }
14175 /* We have to construct a fake section directive. */
14176 group_name_len = strlen (group_name);
14177 if (idx)
14178 prefix_len = 13;
14179 else
14180 prefix_len = 16;
14181
14182 len = (sec_name_len
14183 + prefix_len /* ,"aG",%sectiontype, */
14184 + group_name_len /* ,group_name */
14185 + 7); /* ,comdat */
14186
14187 section = alloca (len + 1);
14188 memcpy (section, sec_name, sec_name_len);
14189 if (idx)
14190 memcpy (section + sec_name_len, ",\"aG\",%exidx,", 13);
14191 else
14192 memcpy (section + sec_name_len, ",\"aG\",%progbits,", 16);
14193 memcpy (section + sec_name_len + prefix_len, group_name, group_name_len);
14194 memcpy (section + len - 7, ",comdat", 7);
14195 section [len] = '\0';
14196 set_section (section);
14197 }
14198 else
14199 {
14200 set_section (sec_name);
14201 bfd_set_section_flags (stdoutput, now_seg,
14202 SEC_LOAD | SEC_ALLOC | SEC_READONLY);
14203 }
14204
14205 /* Set the setion link for index tables. */
14206 if (idx)
14207 elf_linked_to_section (now_seg) = text_seg;
14208 }
14209
14210
14211 /* Start an unwind table entry. HAVE_DATA is nonzero if we have additional
14212 personality routine data. Returns zero, or the index table value for
14213 and inline entry. */
14214
14215 static valueT
14216 create_unwind_entry (int have_data)
14217 {
14218 int size;
14219 addressT where;
14220 char *ptr;
14221 /* The current word of data. */
14222 valueT data;
14223 /* The number of bytes left in this word. */
14224 int n;
14225
14226 finish_unwind_opcodes ();
14227
14228 /* Remember the current text section. */
14229 unwind.saved_seg = now_seg;
14230 unwind.saved_subseg = now_subseg;
14231
14232 start_unwind_section (now_seg, 0);
14233
14234 if (unwind.personality_routine == NULL)
14235 {
14236 if (unwind.personality_index == -2)
14237 {
14238 if (have_data)
14239 as_bad (_("handerdata in cantunwind frame"));
14240 return 1; /* EXIDX_CANTUNWIND. */
14241 }
14242
14243 /* Use a default personality routine if none is specified. */
14244 if (unwind.personality_index == -1)
14245 {
14246 if (unwind.opcode_count > 3)
14247 unwind.personality_index = 1;
14248 else
14249 unwind.personality_index = 0;
14250 }
14251
14252 /* Space for the personality routine entry. */
14253 if (unwind.personality_index == 0)
14254 {
14255 if (unwind.opcode_count > 3)
14256 as_bad (_("too many unwind opcodes for personality routine 0"));
14257
14258 if (!have_data)
14259 {
14260 /* All the data is inline in the index table. */
14261 data = 0x80;
14262 n = 3;
14263 while (unwind.opcode_count > 0)
14264 {
14265 unwind.opcode_count--;
14266 data = (data << 8) | unwind.opcodes[unwind.opcode_count];
14267 n--;
14268 }
14269
14270 /* Pad with "finish" opcodes. */
14271 while (n--)
14272 data = (data << 8) | 0xb0;
14273
14274 return data;
14275 }
14276 size = 0;
14277 }
14278 else
14279 /* We get two opcodes "free" in the first word. */
14280 size = unwind.opcode_count - 2;
14281 }
14282 else
14283 /* An extra byte is required for the opcode count. */
14284 size = unwind.opcode_count + 1;
14285
14286 size = (size + 3) >> 2;
14287 if (size > 0xff)
14288 as_bad (_("too many unwind opcodes"));
14289
14290 frag_align (2, 0, 0);
14291 record_alignment (now_seg, 2);
14292 unwind.table_entry = expr_build_dot ();
14293
14294 /* Allocate the table entry. */
14295 ptr = frag_more ((size << 2) + 4);
14296 where = frag_now_fix () - ((size << 2) + 4);
14297
14298 switch (unwind.personality_index)
14299 {
14300 case -1:
14301 /* ??? Should this be a PLT generating relocation? */
14302 /* Custom personality routine. */
14303 fix_new (frag_now, where, 4, unwind.personality_routine, 0, 1,
14304 BFD_RELOC_ARM_PREL31);
14305
14306 /* Indicate dependency to linker. */
14307 {
14308 char *name = "__aeabi_unwind_cpp_pr0";
14309 symbolS *pr = symbol_find_or_make (name);
14310 fix_new (frag_now, where, 4, pr, 0, 1, BFD_RELOC_NONE);
14311 }
14312
14313 where += 4;
14314 ptr += 4;
14315
14316 /* Set the first byte to the number of additional words. */
14317 data = size - 1;
14318 n = 3;
14319 break;
14320
14321 /* ABI defined personality routines. */
14322 case 0:
14323 /* Three opcodes bytes are packed into the first word. */
14324 data = 0x80;
14325 n = 3;
14326 goto emit_reloc;
14327
14328 case 1:
14329 case 2:
14330 /* The size and first two opcode bytes go in the first word. */
14331 data = ((0x80 + unwind.personality_index) << 8) | size;
14332 n = 2;
14333 goto emit_reloc;
14334
14335 emit_reloc:
14336 {
14337 /* Indicate dependency to linker. */
14338 char *name[] = { "__aeabi_unwind_cpp_pr0",
14339 "__aeabi_unwind_cpp_pr1",
14340 "__aeabi_unwind_cpp_pr2" };
14341 symbolS *pr = symbol_find_or_make (name[unwind.personality_index]);
14342 fix_new (frag_now, where, 4, pr, 0, 1, BFD_RELOC_NONE);
14343 }
14344 break;
14345
14346 default:
14347 /* Should never happen. */
14348 abort ();
14349 }
14350
14351 /* Pack the opcodes into words (MSB first), reversing the list at the same
14352 time. */
14353 while (unwind.opcode_count > 0)
14354 {
14355 if (n == 0)
14356 {
14357 md_number_to_chars (ptr, data, 4);
14358 ptr += 4;
14359 n = 4;
14360 data = 0;
14361 }
14362 unwind.opcode_count--;
14363 n--;
14364 data = (data << 8) | unwind.opcodes[unwind.opcode_count];
14365 }
14366
14367 /* Finish off the last word. */
14368 if (n < 4)
14369 {
14370 /* Pad with "finish" opcodes. */
14371 while (n--)
14372 data = (data << 8) | 0xb0;
14373
14374 md_number_to_chars (ptr, data, 4);
14375 }
14376
14377 if (!have_data)
14378 {
14379 /* Add an empty descriptor if there is no user-specified data. */
14380 ptr = frag_more (4);
14381 md_number_to_chars (ptr, 0, 4);
14382 }
14383
14384 return 0;
14385 }
14386
14387
14388 /* Parse an unwind_fnstart directive. Simply records the current location. */
14389
14390 static void
14391 s_arm_unwind_fnstart (int ignored ATTRIBUTE_UNUSED)
14392 {
14393 demand_empty_rest_of_line ();
14394 /* Mark the start of the function. */
14395 unwind.proc_start = expr_build_dot ();
14396
14397 /* Reset the rest of the unwind info. */
14398 unwind.opcode_count = 0;
14399 unwind.table_entry = NULL;
14400 unwind.personality_routine = NULL;
14401 unwind.personality_index = -1;
14402 unwind.frame_size = 0;
14403 unwind.fp_offset = 0;
14404 unwind.fp_reg = 13;
14405 unwind.fp_used = 0;
14406 unwind.sp_restored = 0;
14407 }
14408
14409
14410 /* Parse a handlerdata directive. Creates the exception handling table entry
14411 for the function. */
14412
14413 static void
14414 s_arm_unwind_handlerdata (int ignored ATTRIBUTE_UNUSED)
14415 {
14416 demand_empty_rest_of_line ();
14417 if (unwind.table_entry)
14418 as_bad (_("dupicate .handlerdata directive"));
14419
14420 create_unwind_entry (1);
14421 }
14422
14423 /* Parse an unwind_fnend directive. Generates the index table entry. */
14424
14425 static void
14426 s_arm_unwind_fnend (int ignored ATTRIBUTE_UNUSED)
14427 {
14428 long where;
14429 char *ptr;
14430 valueT val;
14431
14432 demand_empty_rest_of_line ();
14433
14434 /* Add eh table entry. */
14435 if (unwind.table_entry == NULL)
14436 val = create_unwind_entry (0);
14437 else
14438 val = 0;
14439
14440 /* Add index table entry. This is two words. */
14441 start_unwind_section (unwind.saved_seg, 1);
14442 frag_align (2, 0, 0);
14443 record_alignment (now_seg, 2);
14444
14445 ptr = frag_more (8);
14446 where = frag_now_fix () - 8;
14447
14448 /* Self relative offset of the function start. */
14449 fix_new (frag_now, where, 4, unwind.proc_start, 0, 1,
14450 BFD_RELOC_ARM_PREL31);
14451
14452 if (val)
14453 /* Inline exception table entry. */
14454 md_number_to_chars (ptr + 4, val, 4);
14455 else
14456 /* Self relative offset of the table entry. */
14457 fix_new (frag_now, where + 4, 4, unwind.table_entry, 0, 1,
14458 BFD_RELOC_ARM_PREL31);
14459
14460 /* Restore the original section. */
14461 subseg_set (unwind.saved_seg, unwind.saved_subseg);
14462 }
14463
14464
14465 /* Parse an unwind_cantunwind directive. */
14466
14467 static void
14468 s_arm_unwind_cantunwind (int ignored ATTRIBUTE_UNUSED)
14469 {
14470 demand_empty_rest_of_line ();
14471 if (unwind.personality_routine || unwind.personality_index != -1)
14472 as_bad (_("personality routine specified for cantunwind frame"));
14473
14474 unwind.personality_index = -2;
14475 }
14476
14477
14478 /* Parse a personalityindex directive. */
14479
14480 static void
14481 s_arm_unwind_personalityindex (int ignored ATTRIBUTE_UNUSED)
14482 {
14483 expressionS exp;
14484
14485 if (unwind.personality_routine || unwind.personality_index != -1)
14486 as_bad (_("duplicate .personalityindex directive"));
14487
14488 SKIP_WHITESPACE ();
14489
14490 expression (&exp);
14491
14492 if (exp.X_op != O_constant
14493 || exp.X_add_number < 0 || exp.X_add_number > 15)
14494 {
14495 as_bad (_("bad personality routine number"));
14496 ignore_rest_of_line ();
14497 return;
14498 }
14499
14500 unwind.personality_index = exp.X_add_number;
14501
14502 demand_empty_rest_of_line ();
14503 }
14504
14505
14506 /* Parse a personality directive. */
14507
14508 static void
14509 s_arm_unwind_personality (int ignored ATTRIBUTE_UNUSED)
14510 {
14511 char *name, *p, c;
14512
14513 if (unwind.personality_routine || unwind.personality_index != -1)
14514 as_bad (_("duplicate .personality directive"));
14515
14516 SKIP_WHITESPACE ();
14517 name = input_line_pointer;
14518 c = get_symbol_end ();
14519 p = input_line_pointer;
14520 unwind.personality_routine = symbol_find_or_make (name);
14521 *p = c;
14522 SKIP_WHITESPACE ();
14523 demand_empty_rest_of_line ();
14524 }
14525
14526
14527 /* Parse a directive saving core registers. */
14528
14529 static void
14530 s_arm_unwind_save_core (void)
14531 {
14532 valueT op;
14533 long range;
14534 int n;
14535
14536 SKIP_WHITESPACE ();
14537 range = reg_list (&input_line_pointer);
14538 if (range == FAIL)
14539 {
14540 as_bad (_("expected register list"));
14541 ignore_rest_of_line ();
14542 return;
14543 }
14544
14545 demand_empty_rest_of_line ();
14546
14547 /* Turn .unwind_movsp ip followed by .unwind_save {..., ip, ...}
14548 into .unwind_save {..., sp...}. We aren't bothered about the value of
14549 ip because it is clobbered by calls. */
14550 if (unwind.sp_restored && unwind.fp_reg == 12
14551 && (range & 0x3000) == 0x1000)
14552 {
14553 unwind.opcode_count--;
14554 unwind.sp_restored = 0;
14555 range = (range | 0x2000) & ~0x1000;
14556 unwind.pending_offset = 0;
14557 }
14558
14559 /* See if we can use the short opcodes. These pop a block of upto 8
14560 registers starting with r4, plus maybe r14. */
14561 for (n = 0; n < 8; n++)
14562 {
14563 /* Break at the first non-saved register. */
14564 if ((range & (1 << (n + 4))) == 0)
14565 break;
14566 }
14567 /* See if there are any other bits set. */
14568 if (n == 0 || (range & (0xfff0 << n) & 0xbff0) != 0)
14569 {
14570 /* Use the long form. */
14571 op = 0x8000 | ((range >> 4) & 0xfff);
14572 add_unwind_opcode (op, 2);
14573 }
14574 else
14575 {
14576 /* Use the short form. */
14577 if (range & 0x4000)
14578 op = 0xa8; /* Pop r14. */
14579 else
14580 op = 0xa0; /* Do not pop r14. */
14581 op |= (n - 1);
14582 add_unwind_opcode (op, 1);
14583 }
14584
14585 /* Pop r0-r3. */
14586 if (range & 0xf)
14587 {
14588 op = 0xb100 | (range & 0xf);
14589 add_unwind_opcode (op, 2);
14590 }
14591
14592 /* Record the number of bytes pushed. */
14593 for (n = 0; n < 16; n++)
14594 {
14595 if (range & (1 << n))
14596 unwind.frame_size += 4;
14597 }
14598 }
14599
14600
14601 /* Parse a directive saving FPA registers. */
14602
14603 static void
14604 s_arm_unwind_save_fpa (int reg)
14605 {
14606 expressionS exp;
14607 int num_regs;
14608 valueT op;
14609
14610 /* Get Number of registers to transfer. */
14611 if (skip_past_comma (&input_line_pointer) != FAIL)
14612 expression (&exp);
14613 else
14614 exp.X_op = O_illegal;
14615
14616 if (exp.X_op != O_constant)
14617 {
14618 as_bad (_("expected , <constant>"));
14619 ignore_rest_of_line ();
14620 return;
14621 }
14622
14623 num_regs = exp.X_add_number;
14624
14625 if (num_regs < 1 || num_regs > 4)
14626 {
14627 as_bad (_("number of registers must be in the range [1:4]"));
14628 ignore_rest_of_line ();
14629 return;
14630 }
14631
14632 demand_empty_rest_of_line ();
14633
14634 if (reg == 4)
14635 {
14636 /* Short form. */
14637 op = 0xb4 | (num_regs - 1);
14638 add_unwind_opcode (op, 1);
14639 }
14640 else
14641 {
14642 /* Long form. */
14643 op = 0xc800 | (reg << 4) | (num_regs - 1);
14644 add_unwind_opcode (op, 2);
14645 }
14646 unwind.frame_size += num_regs * 12;
14647 }
14648
14649
14650 /* Parse a directive saving VFP registers. */
14651
14652 static void
14653 s_arm_unwind_save_vfp (void)
14654 {
14655 int count;
14656 int reg;
14657 valueT op;
14658
14659 count = vfp_parse_reg_list (&input_line_pointer, &reg, 1);
14660 if (count == FAIL)
14661 {
14662 as_bad (_("expected register list"));
14663 ignore_rest_of_line ();
14664 return;
14665 }
14666
14667 demand_empty_rest_of_line ();
14668
14669 if (reg == 8)
14670 {
14671 /* Short form. */
14672 op = 0xb8 | (count - 1);
14673 add_unwind_opcode (op, 1);
14674 }
14675 else
14676 {
14677 /* Long form. */
14678 op = 0xb300 | (reg << 4) | (count - 1);
14679 add_unwind_opcode (op, 2);
14680 }
14681 unwind.frame_size += count * 8 + 4;
14682 }
14683
14684
14685 /* Parse a directive saving iWMMXt registers. */
14686
14687 static void
14688 s_arm_unwind_save_wmmx (void)
14689 {
14690 int reg;
14691 int hi_reg;
14692 int i;
14693 unsigned wcg_mask;
14694 unsigned wr_mask;
14695 valueT op;
14696
14697 if (*input_line_pointer == '{')
14698 input_line_pointer++;
14699
14700 wcg_mask = 0;
14701 wr_mask = 0;
14702 do
14703 {
14704 reg = arm_reg_parse (&input_line_pointer,
14705 all_reg_maps[REG_TYPE_IWMMXT].htab);
14706
14707 if (wr_register (reg))
14708 {
14709 i = reg & ~WR_PREFIX;
14710 if (wr_mask >> i)
14711 as_tsktsk (_("register list not in ascending order"));
14712 wr_mask |= 1 << i;
14713 }
14714 else if (wcg_register (reg))
14715 {
14716 i = (reg & ~WC_PREFIX) - 8;
14717 if (wcg_mask >> i)
14718 as_tsktsk (_("register list not in ascending order"));
14719 wcg_mask |= 1 << i;
14720 }
14721 else
14722 {
14723 as_bad (_("expected wr or wcgr"));
14724 goto error;
14725 }
14726
14727 SKIP_WHITESPACE ();
14728 if (*input_line_pointer == '-')
14729 {
14730 hi_reg = arm_reg_parse (&input_line_pointer,
14731 all_reg_maps[REG_TYPE_IWMMXT].htab);
14732 if (wr_register (reg) && wr_register (hi_reg))
14733 {
14734 for (; reg < hi_reg; reg++)
14735 wr_mask |= 1 << (reg & ~WR_PREFIX);
14736 }
14737 else if (wcg_register (reg) && wcg_register (hi_reg))
14738 {
14739 for (; reg < hi_reg; reg++)
14740 wcg_mask |= 1 << ((reg & ~WC_PREFIX) - 8);
14741 }
14742 else
14743 {
14744 as_bad (_("bad register range"));
14745 goto error;
14746 }
14747 }
14748 }
14749 while (skip_past_comma (&input_line_pointer) != FAIL);
14750
14751 SKIP_WHITESPACE ();
14752 if (*input_line_pointer == '}')
14753 input_line_pointer++;
14754
14755 demand_empty_rest_of_line ();
14756
14757 if (wr_mask && wcg_mask)
14758 {
14759 as_bad (_("inconsistent register types"));
14760 goto error;
14761 }
14762
14763 /* Generate any deferred opcodes becuuse we're going to be looking at
14764 the list. */
14765 flush_pending_unwind ();
14766
14767 if (wcg_mask)
14768 {
14769 for (i = 0; i < 16; i++)
14770 {
14771 if (wcg_mask & (1 << i))
14772 unwind.frame_size += 4;
14773 }
14774 op = 0xc700 | wcg_mask;
14775 add_unwind_opcode (op, 2);
14776 }
14777 else
14778 {
14779 for (i = 0; i < 16; i++)
14780 {
14781 if (wr_mask & (1 << i))
14782 unwind.frame_size += 8;
14783 }
14784 /* Attempt to combine with a previous opcode. We do this because gcc
14785 likes to output separate unwind directives for a single block of
14786 registers. */
14787 if (unwind.opcode_count > 0)
14788 {
14789 i = unwind.opcodes[unwind.opcode_count - 1];
14790 if ((i & 0xf8) == 0xc0)
14791 {
14792 i &= 7;
14793 /* Only merge if the blocks are contiguous. */
14794 if (i < 6)
14795 {
14796 if ((wr_mask & 0xfe00) == (1 << 9))
14797 {
14798 wr_mask |= ((1 << (i + 11)) - 1) & 0xfc00;
14799 unwind.opcode_count--;
14800 }
14801 }
14802 else if (i == 6 && unwind.opcode_count >= 2)
14803 {
14804 i = unwind.opcodes[unwind.opcode_count - 2];
14805 reg = i >> 4;
14806 i &= 0xf;
14807
14808 op = 0xffff << (reg - 1);
14809 if (reg > 0
14810 || ((wr_mask & op) == (1u << (reg - 1))))
14811 {
14812 op = (1 << (reg + i + 1)) - 1;
14813 op &= ~((1 << reg) - 1);
14814 wr_mask |= op;
14815 unwind.opcode_count -= 2;
14816 }
14817 }
14818 }
14819 }
14820
14821 hi_reg = 15;
14822 /* We want to generate opcodes in the order the registers have been
14823 saved, ie. descending order. */
14824 for (reg = 15; reg >= -1; reg--)
14825 {
14826 /* Save registers in blocks. */
14827 if (reg < 0
14828 || !(wr_mask & (1 << reg)))
14829 {
14830 /* We found an unsaved reg. Generate opcodes to save the
14831 preceeding block. */
14832 if (reg != hi_reg)
14833 {
14834 if (reg == 9)
14835 {
14836 /* Short form. */
14837 op = 0xc0 | (hi_reg - 10);
14838 add_unwind_opcode (op, 1);
14839 }
14840 else
14841 {
14842 /* Long form. */
14843 op = 0xc600 | ((reg + 1) << 4) | ((hi_reg - reg) - 1);
14844 add_unwind_opcode (op, 2);
14845 }
14846 }
14847 hi_reg = reg - 1;
14848 }
14849 }
14850 }
14851 return;
14852 error:
14853 ignore_rest_of_line ();
14854 }
14855
14856
14857 /* Parse an unwind_save directive. */
14858
14859 static void
14860 s_arm_unwind_save (int ignored ATTRIBUTE_UNUSED)
14861 {
14862 char *saved_ptr;
14863 int reg;
14864
14865 /* Figure out what sort of save we have. */
14866 SKIP_WHITESPACE ();
14867 saved_ptr = input_line_pointer;
14868
14869 reg = arm_reg_parse (&input_line_pointer, all_reg_maps[REG_TYPE_FN].htab);
14870 if (reg != FAIL)
14871 {
14872 s_arm_unwind_save_fpa (reg);
14873 return;
14874 }
14875
14876 if (*input_line_pointer == '{')
14877 input_line_pointer++;
14878
14879 SKIP_WHITESPACE ();
14880
14881 reg = arm_reg_parse (&input_line_pointer, all_reg_maps[REG_TYPE_RN].htab);
14882 if (reg != FAIL)
14883 {
14884 input_line_pointer = saved_ptr;
14885 s_arm_unwind_save_core ();
14886 return;
14887 }
14888
14889 reg = arm_reg_parse (&input_line_pointer, all_reg_maps[REG_TYPE_DN].htab);
14890 if (reg != FAIL)
14891 {
14892 input_line_pointer = saved_ptr;
14893 s_arm_unwind_save_vfp ();
14894 return;
14895 }
14896
14897 reg = arm_reg_parse (&input_line_pointer,
14898 all_reg_maps[REG_TYPE_IWMMXT].htab);
14899 if (reg != FAIL)
14900 {
14901 input_line_pointer = saved_ptr;
14902 s_arm_unwind_save_wmmx ();
14903 return;
14904 }
14905
14906 /* TODO: Maverick registers. */
14907 as_bad (_("unrecognised register"));
14908 }
14909
14910
14911 /* Parse an unwind_movsp directive. */
14912
14913 static void
14914 s_arm_unwind_movsp (int ignored ATTRIBUTE_UNUSED)
14915 {
14916 int reg;
14917 valueT op;
14918
14919 SKIP_WHITESPACE ();
14920 reg = reg_required_here (&input_line_pointer, -1);
14921 if (reg == FAIL)
14922 {
14923 as_bad (_("ARM register expected"));
14924 ignore_rest_of_line ();
14925 return;
14926 }
14927
14928 if (reg == 13 || reg == 15)
14929 {
14930 as_bad (_("r%d not permitted in .unwind_movsp directive"), reg);
14931 ignore_rest_of_line ();
14932 return;
14933 }
14934
14935 if (unwind.fp_reg != 13)
14936 as_bad (_("unexpected .unwind_movsp directive"));
14937
14938 /* Generate opcode to restore the value. */
14939 op = 0x90 | reg;
14940 add_unwind_opcode (op, 1);
14941
14942 /* Record the information for later. */
14943 unwind.fp_reg = reg;
14944 unwind.fp_offset = unwind.frame_size;
14945 unwind.sp_restored = 1;
14946 demand_empty_rest_of_line ();
14947 }
14948
14949
14950 /* Parse #<number>. */
14951
14952 static int
14953 require_hashconst (int * val)
14954 {
14955 expressionS exp;
14956
14957 SKIP_WHITESPACE ();
14958 if (*input_line_pointer == '#')
14959 {
14960 input_line_pointer++;
14961 expression (&exp);
14962 }
14963 else
14964 exp.X_op = O_illegal;
14965
14966 if (exp.X_op != O_constant)
14967 {
14968 as_bad (_("expected #constant"));
14969 ignore_rest_of_line ();
14970 return FAIL;
14971 }
14972 *val = exp.X_add_number;
14973 return SUCCESS;
14974 }
14975
14976 /* Parse an unwind_pad directive. */
14977
14978 static void
14979 s_arm_unwind_pad (int ignored ATTRIBUTE_UNUSED)
14980 {
14981 int offset;
14982
14983 if (require_hashconst (&offset) == FAIL)
14984 return;
14985
14986 if (offset & 3)
14987 {
14988 as_bad (_("stack increment must be multiple of 4"));
14989 ignore_rest_of_line ();
14990 return;
14991 }
14992
14993 /* Don't generate any opcodes, just record the details for later. */
14994 unwind.frame_size += offset;
14995 unwind.pending_offset += offset;
14996
14997 demand_empty_rest_of_line ();
14998 }
14999
15000 /* Parse an unwind_setfp directive. */
15001
15002 static void
15003 s_arm_unwind_setfp (int ignored ATTRIBUTE_UNUSED)
15004 {
15005 int sp_reg;
15006 int fp_reg;
15007 int offset;
15008
15009 fp_reg = reg_required_here (&input_line_pointer, -1);
15010 if (skip_past_comma (&input_line_pointer) == FAIL)
15011 sp_reg = FAIL;
15012 else
15013 sp_reg = reg_required_here (&input_line_pointer, -1);
15014
15015 if (fp_reg == FAIL || sp_reg == FAIL)
15016 {
15017 as_bad (_("expected <reg>, <reg>"));
15018 ignore_rest_of_line ();
15019 return;
15020 }
15021
15022 /* Optonal constant. */
15023 if (skip_past_comma (&input_line_pointer) != FAIL)
15024 {
15025 if (require_hashconst (&offset) == FAIL)
15026 return;
15027 }
15028 else
15029 offset = 0;
15030
15031 demand_empty_rest_of_line ();
15032
15033 if (sp_reg != 13 && sp_reg != unwind.fp_reg)
15034 {
15035 as_bad (_("register must be either sp or set by a previous"
15036 "unwind_movsp directive"));
15037 return;
15038 }
15039
15040 /* Don't generate any opcodes, just record the information for later. */
15041 unwind.fp_reg = fp_reg;
15042 unwind.fp_used = 1;
15043 if (sp_reg == 13)
15044 unwind.fp_offset = unwind.frame_size - offset;
15045 else
15046 unwind.fp_offset -= offset;
15047 }
15048
15049 /* Parse an unwind_raw directive. */
15050
15051 static void
15052 s_arm_unwind_raw (int ignored ATTRIBUTE_UNUSED)
15053 {
15054 expressionS exp;
15055 /* This is an arbitary limit. */
15056 unsigned char op[16];
15057 int count;
15058
15059 SKIP_WHITESPACE ();
15060 expression (&exp);
15061 if (exp.X_op == O_constant
15062 && skip_past_comma (&input_line_pointer) != FAIL)
15063 {
15064 unwind.frame_size += exp.X_add_number;
15065 expression (&exp);
15066 }
15067 else
15068 exp.X_op = O_illegal;
15069
15070 if (exp.X_op != O_constant)
15071 {
15072 as_bad (_("expected <offset>, <opcode>"));
15073 ignore_rest_of_line ();
15074 return;
15075 }
15076
15077 count = 0;
15078
15079 /* Parse the opcode. */
15080 for (;;)
15081 {
15082 if (count >= 16)
15083 {
15084 as_bad (_("unwind opcode too long"));
15085 ignore_rest_of_line ();
15086 }
15087 if (exp.X_op != O_constant || exp.X_add_number & ~0xff)
15088 {
15089 as_bad (_("invalid unwind opcode"));
15090 ignore_rest_of_line ();
15091 return;
15092 }
15093 op[count++] = exp.X_add_number;
15094
15095 /* Parse the next byte. */
15096 if (skip_past_comma (&input_line_pointer) == FAIL)
15097 break;
15098
15099 expression (&exp);
15100 }
15101
15102 /* Add the opcode bytes in reverse order. */
15103 while (count--)
15104 add_unwind_opcode (op[count], 1);
15105
15106 demand_empty_rest_of_line ();
15107 }
15108
15109 #endif /* OBJ_ELF */
15110
15111 /* This is called from HANDLE_ALIGN in write.c. Fill in the contents
15112 of an rs_align_code fragment. */
15113
15114 void
15115 arm_handle_align (fragS * fragP)
15116 {
15117 static char const arm_noop[4] = { 0x00, 0x00, 0xa0, 0xe1 };
15118 static char const thumb_noop[2] = { 0xc0, 0x46 };
15119 static char const arm_bigend_noop[4] = { 0xe1, 0xa0, 0x00, 0x00 };
15120 static char const thumb_bigend_noop[2] = { 0x46, 0xc0 };
15121
15122 int bytes, fix, noop_size;
15123 char * p;
15124 const char * noop;
15125
15126 if (fragP->fr_type != rs_align_code)
15127 return;
15128
15129 bytes = fragP->fr_next->fr_address - fragP->fr_address - fragP->fr_fix;
15130 p = fragP->fr_literal + fragP->fr_fix;
15131 fix = 0;
15132
15133 if (bytes > MAX_MEM_FOR_RS_ALIGN_CODE)
15134 bytes &= MAX_MEM_FOR_RS_ALIGN_CODE;
15135
15136 if (fragP->tc_frag_data)
15137 {
15138 if (target_big_endian)
15139 noop = thumb_bigend_noop;
15140 else
15141 noop = thumb_noop;
15142 noop_size = sizeof (thumb_noop);
15143 }
15144 else
15145 {
15146 if (target_big_endian)
15147 noop = arm_bigend_noop;
15148 else
15149 noop = arm_noop;
15150 noop_size = sizeof (arm_noop);
15151 }
15152
15153 if (bytes & (noop_size - 1))
15154 {
15155 fix = bytes & (noop_size - 1);
15156 memset (p, 0, fix);
15157 p += fix;
15158 bytes -= fix;
15159 }
15160
15161 while (bytes >= noop_size)
15162 {
15163 memcpy (p, noop, noop_size);
15164 p += noop_size;
15165 bytes -= noop_size;
15166 fix += noop_size;
15167 }
15168
15169 fragP->fr_fix += fix;
15170 fragP->fr_var = noop_size;
15171 }
15172
15173 /* Called from md_do_align. Used to create an alignment
15174 frag in a code section. */
15175
15176 void
15177 arm_frag_align_code (int n, int max)
15178 {
15179 char * p;
15180
15181 /* We assume that there will never be a requirement
15182 to support alignments greater than 32 bytes. */
15183 if (max > MAX_MEM_FOR_RS_ALIGN_CODE)
15184 as_fatal (_("alignments greater than 32 bytes not supported in .text sections."));
15185
15186 p = frag_var (rs_align_code,
15187 MAX_MEM_FOR_RS_ALIGN_CODE,
15188 1,
15189 (relax_substateT) max,
15190 (symbolS *) NULL,
15191 (offsetT) n,
15192 (char *) NULL);
15193 *p = 0;
15194 }
15195
15196 /* Perform target specific initialisation of a frag. */
15197
15198 void
15199 arm_init_frag (fragS * fragP)
15200 {
15201 /* Record whether this frag is in an ARM or a THUMB area. */
15202 fragP->tc_frag_data = thumb_mode;
15203 }
15204
15205 #ifdef OBJ_ELF
15206
15207 /* Convert REGNAME to a DWARF-2 register number. */
15208
15209 int
15210 tc_arm_regname_to_dw2regnum (const char *regname)
15211 {
15212 unsigned int i;
15213
15214 for (i = 0; rn_table[i].name; i++)
15215 if (streq (regname, rn_table[i].name))
15216 return rn_table[i].number;
15217
15218 return -1;
15219 }
15220
15221 /* Initialize the DWARF-2 unwind information for this procedure. */
15222
15223 void
15224 tc_arm_frame_initial_instructions (void)
15225 {
15226 cfi_add_CFA_def_cfa (REG_SP, 0);
15227 }
15228 #endif
15229
15230 /* This table describes all the machine specific pseudo-ops the assembler
15231 has to support. The fields are:
15232 pseudo-op name without dot
15233 function to call to execute this pseudo-op
15234 Integer arg to pass to the function. */
15235
15236 const pseudo_typeS md_pseudo_table[] =
15237 {
15238 /* Never called because '.req' does not start a line. */
15239 { "req", s_req, 0 },
15240 { "unreq", s_unreq, 0 },
15241 { "bss", s_bss, 0 },
15242 { "align", s_align, 0 },
15243 { "arm", s_arm, 0 },
15244 { "thumb", s_thumb, 0 },
15245 { "code", s_code, 0 },
15246 { "force_thumb", s_force_thumb, 0 },
15247 { "thumb_func", s_thumb_func, 0 },
15248 { "thumb_set", s_thumb_set, 0 },
15249 { "even", s_even, 0 },
15250 { "ltorg", s_ltorg, 0 },
15251 { "pool", s_ltorg, 0 },
15252 #ifdef OBJ_ELF
15253 { "word", s_arm_elf_cons, 4 },
15254 { "long", s_arm_elf_cons, 4 },
15255 { "rel31", s_arm_rel31, 0 },
15256 { "fnstart", s_arm_unwind_fnstart, 0 },
15257 { "fnend", s_arm_unwind_fnend, 0 },
15258 { "cantunwind", s_arm_unwind_cantunwind, 0 },
15259 { "personality", s_arm_unwind_personality, 0 },
15260 { "personalityindex", s_arm_unwind_personalityindex, 0 },
15261 { "handlerdata", s_arm_unwind_handlerdata, 0 },
15262 { "save", s_arm_unwind_save, 0 },
15263 { "movsp", s_arm_unwind_movsp, 0 },
15264 { "pad", s_arm_unwind_pad, 0 },
15265 { "setfp", s_arm_unwind_setfp, 0 },
15266 { "unwind_raw", s_arm_unwind_raw, 0 },
15267 #else
15268 { "word", cons, 4},
15269 #endif
15270 { "extend", float_cons, 'x' },
15271 { "ldouble", float_cons, 'x' },
15272 { "packed", float_cons, 'p' },
15273 { 0, 0, 0 }
15274 };
This page took 0.381458 seconds and 4 git commands to generate.