Make -mlittle-endian switch set the target_big_endian variable to false.
[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, 51 Franklin Street - Fifth Floor, Boston, MA
26 02110-1301, 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 /* Bit N indicates that an R_ARM_NONE relocation has been output for
87 __aeabi_unwind_cpp_prN already if set. This enables dependencies to be
88 emitted only once per section, to save unnecessary bloat. */
89 static unsigned int marked_pr_dependency = 0;
90
91 #endif /* OBJ_ELF */
92
93 enum arm_float_abi
94 {
95 ARM_FLOAT_ABI_HARD,
96 ARM_FLOAT_ABI_SOFTFP,
97 ARM_FLOAT_ABI_SOFT
98 };
99
100 /* Types of processor to assemble for. */
101 #define ARM_1 ARM_ARCH_V1
102 #define ARM_2 ARM_ARCH_V2
103 #define ARM_3 ARM_ARCH_V2S
104 #define ARM_250 ARM_ARCH_V2S
105 #define ARM_6 ARM_ARCH_V3
106 #define ARM_7 ARM_ARCH_V3
107 #define ARM_8 ARM_ARCH_V4
108 #define ARM_9 ARM_ARCH_V4T
109 #define ARM_STRONG ARM_ARCH_V4
110 #define ARM_CPU_MASK 0x0000000f /* XXX? */
111
112 #ifndef CPU_DEFAULT
113 #if defined __XSCALE__
114 #define CPU_DEFAULT (ARM_ARCH_XSCALE)
115 #else
116 #if defined __thumb__
117 #define CPU_DEFAULT (ARM_ARCH_V5T)
118 #else
119 #define CPU_DEFAULT ARM_ANY
120 #endif
121 #endif
122 #endif
123
124 #ifndef FPU_DEFAULT
125 # ifdef TE_LINUX
126 # define FPU_DEFAULT FPU_ARCH_FPA
127 # elif defined (TE_NetBSD)
128 # ifdef OBJ_ELF
129 # define FPU_DEFAULT FPU_ARCH_VFP /* Soft-float, but VFP order. */
130 # else
131 /* Legacy a.out format. */
132 # define FPU_DEFAULT FPU_ARCH_FPA /* Soft-float, but FPA order. */
133 # endif
134 # elif defined (TE_VXWORKS)
135 # define FPU_DEFAULT FPU_ARCH_VFP /* Soft-float, VFP order. */
136 # else
137 /* For backwards compatibility, default to FPA. */
138 # define FPU_DEFAULT FPU_ARCH_FPA
139 # endif
140 #endif /* ifndef FPU_DEFAULT */
141
142 #define streq(a, b) (strcmp (a, b) == 0)
143 #define skip_whitespace(str) while (*(str) == ' ') ++(str)
144
145 static unsigned long cpu_variant;
146
147 /* Flags stored in private area of BFD structure. */
148 static int uses_apcs_26 = FALSE;
149 static int atpcs = FALSE;
150 static int support_interwork = FALSE;
151 static int uses_apcs_float = FALSE;
152 static int pic_code = FALSE;
153
154 /* Variables that we set while parsing command-line options. Once all
155 options have been read we re-process these values to set the real
156 assembly flags. */
157 static int legacy_cpu = -1;
158 static int legacy_fpu = -1;
159
160 static int mcpu_cpu_opt = -1;
161 static int mcpu_fpu_opt = -1;
162 static int march_cpu_opt = -1;
163 static int march_fpu_opt = -1;
164 static int mfpu_opt = -1;
165 static int mfloat_abi_opt = -1;
166 #ifdef OBJ_ELF
167 # ifdef EABI_DEFAULT
168 static int meabi_flags = EABI_DEFAULT;
169 # else
170 static int meabi_flags = EF_ARM_EABI_UNKNOWN;
171 # endif
172 #endif
173
174 /* This array holds the chars that always start a comment. If the
175 pre-processor is disabled, these aren't very useful. */
176 const char comment_chars[] = "@";
177
178 /* This array holds the chars that only start a comment at the beginning of
179 a line. If the line seems to have the form '# 123 filename'
180 .line and .file directives will appear in the pre-processed output. */
181 /* Note that input_file.c hand checks for '#' at the beginning of the
182 first line of the input file. This is because the compiler outputs
183 #NO_APP at the beginning of its output. */
184 /* Also note that comments like this one will always work. */
185 const char line_comment_chars[] = "#";
186
187 const char line_separator_chars[] = ";";
188
189 /* Chars that can be used to separate mant
190 from exp in floating point numbers. */
191 const char EXP_CHARS[] = "eE";
192
193 /* Chars that mean this number is a floating point constant. */
194 /* As in 0f12.456 */
195 /* or 0d1.2345e12 */
196
197 const char FLT_CHARS[] = "rRsSfFdDxXeEpP";
198
199 /* Prefix characters that indicate the start of an immediate
200 value. */
201 #define is_immediate_prefix(C) ((C) == '#' || (C) == '$')
202
203 #ifdef OBJ_ELF
204 /* Pre-defined "_GLOBAL_OFFSET_TABLE_" */
205 symbolS * GOT_symbol;
206 #endif
207
208 /* Size of relocation record. */
209 const int md_reloc_size = 8;
210
211 /* 0: assemble for ARM,
212 1: assemble for Thumb,
213 2: assemble for Thumb even though target CPU does not support thumb
214 instructions. */
215 static int thumb_mode = 0;
216
217 typedef struct arm_fix
218 {
219 int thumb_mode;
220 } arm_fix_data;
221
222 struct arm_it
223 {
224 const char * error;
225 unsigned long instruction;
226 int size;
227 struct
228 {
229 bfd_reloc_code_real_type type;
230 expressionS exp;
231 int pc_rel;
232 } reloc;
233 };
234
235 struct arm_it inst;
236
237 enum asm_shift_index
238 {
239 SHIFT_LSL = 0,
240 SHIFT_LSR,
241 SHIFT_ASR,
242 SHIFT_ROR,
243 SHIFT_RRX
244 };
245
246 struct asm_shift_properties
247 {
248 enum asm_shift_index index;
249 unsigned long bit_field;
250 unsigned int allows_0 : 1;
251 unsigned int allows_32 : 1;
252 };
253
254 static const struct asm_shift_properties shift_properties [] =
255 {
256 { SHIFT_LSL, 0, 1, 0},
257 { SHIFT_LSR, 0x20, 0, 1},
258 { SHIFT_ASR, 0x40, 0, 1},
259 { SHIFT_ROR, 0x60, 0, 0},
260 { SHIFT_RRX, 0x60, 0, 0}
261 };
262
263 struct asm_shift_name
264 {
265 const char * name;
266 const struct asm_shift_properties * properties;
267 };
268
269 static const struct asm_shift_name shift_names [] =
270 {
271 { "asl", shift_properties + SHIFT_LSL },
272 { "lsl", shift_properties + SHIFT_LSL },
273 { "lsr", shift_properties + SHIFT_LSR },
274 { "asr", shift_properties + SHIFT_ASR },
275 { "ror", shift_properties + SHIFT_ROR },
276 { "rrx", shift_properties + SHIFT_RRX },
277 { "ASL", shift_properties + SHIFT_LSL },
278 { "LSL", shift_properties + SHIFT_LSL },
279 { "LSR", shift_properties + SHIFT_LSR },
280 { "ASR", shift_properties + SHIFT_ASR },
281 { "ROR", shift_properties + SHIFT_ROR },
282 { "RRX", shift_properties + SHIFT_RRX }
283 };
284
285 /* Any kind of shift is accepted. */
286 #define NO_SHIFT_RESTRICT 1
287 /* The shift operand must be an immediate value, not a register. */
288 #define SHIFT_IMMEDIATE 0
289 /* The shift must be LSL or ASR and the operand must be an immediate. */
290 #define SHIFT_LSL_OR_ASR_IMMEDIATE 2
291 /* The shift must be ASR and the operand must be an immediate. */
292 #define SHIFT_ASR_IMMEDIATE 3
293 /* The shift must be LSL and the operand must be an immediate. */
294 #define SHIFT_LSL_IMMEDIATE 4
295
296 #define NUM_FLOAT_VALS 8
297
298 const char * fp_const[] =
299 {
300 "0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0", 0
301 };
302
303 /* Number of littlenums required to hold an extended precision number. */
304 #define MAX_LITTLENUMS 6
305
306 LITTLENUM_TYPE fp_values[NUM_FLOAT_VALS][MAX_LITTLENUMS];
307
308 #define FAIL (-1)
309 #define SUCCESS (0)
310
311 /* Whether a Co-processor load/store operation accepts write-back forms. */
312 #define CP_WB_OK 1
313 #define CP_NO_WB 0
314
315 #define SUFF_S 1
316 #define SUFF_D 2
317 #define SUFF_E 3
318 #define SUFF_P 4
319
320 #define CP_T_X 0x00008000
321 #define CP_T_Y 0x00400000
322 #define CP_T_Pre 0x01000000
323 #define CP_T_UD 0x00800000
324 #define CP_T_WB 0x00200000
325
326 #define CONDS_BIT 0x00100000
327 #define LOAD_BIT 0x00100000
328
329 #define DOUBLE_LOAD_FLAG 0x00000001
330
331 struct asm_cond
332 {
333 const char * template;
334 unsigned long value;
335 };
336
337 #define COND_ALWAYS 0xe0000000
338 #define COND_MASK 0xf0000000
339
340 static const struct asm_cond conds[] =
341 {
342 {"eq", 0x00000000},
343 {"ne", 0x10000000},
344 {"cs", 0x20000000}, {"hs", 0x20000000},
345 {"cc", 0x30000000}, {"ul", 0x30000000}, {"lo", 0x30000000},
346 {"mi", 0x40000000},
347 {"pl", 0x50000000},
348 {"vs", 0x60000000},
349 {"vc", 0x70000000},
350 {"hi", 0x80000000},
351 {"ls", 0x90000000},
352 {"ge", 0xa0000000},
353 {"lt", 0xb0000000},
354 {"gt", 0xc0000000},
355 {"le", 0xd0000000},
356 {"al", 0xe0000000},
357 {"nv", 0xf0000000}
358 };
359
360 struct asm_psr
361 {
362 const char *template;
363 bfd_boolean cpsr;
364 unsigned long field;
365 };
366
367 /* The bit that distinguishes CPSR and SPSR. */
368 #define SPSR_BIT (1 << 22)
369
370 /* How many bits to shift the PSR_xxx bits up by. */
371 #define PSR_SHIFT 16
372
373 #define PSR_c (1 << 0)
374 #define PSR_x (1 << 1)
375 #define PSR_s (1 << 2)
376 #define PSR_f (1 << 3)
377
378 static const struct asm_psr psrs[] =
379 {
380 {"CPSR", TRUE, PSR_c | PSR_f},
381 {"CPSR_all", TRUE, PSR_c | PSR_f},
382 {"SPSR", FALSE, PSR_c | PSR_f},
383 {"SPSR_all", FALSE, PSR_c | PSR_f},
384 {"CPSR_flg", TRUE, PSR_f},
385 {"CPSR_f", TRUE, PSR_f},
386 {"SPSR_flg", FALSE, PSR_f},
387 {"SPSR_f", FALSE, PSR_f},
388 {"CPSR_c", TRUE, PSR_c},
389 {"CPSR_ctl", TRUE, PSR_c},
390 {"SPSR_c", FALSE, PSR_c},
391 {"SPSR_ctl", FALSE, PSR_c},
392 {"CPSR_x", TRUE, PSR_x},
393 {"CPSR_s", TRUE, PSR_s},
394 {"SPSR_x", FALSE, PSR_x},
395 {"SPSR_s", FALSE, PSR_s},
396 /* Combinations of flags. */
397 {"CPSR_fs", TRUE, PSR_f | PSR_s},
398 {"CPSR_fx", TRUE, PSR_f | PSR_x},
399 {"CPSR_fc", TRUE, PSR_f | PSR_c},
400 {"CPSR_sf", TRUE, PSR_s | PSR_f},
401 {"CPSR_sx", TRUE, PSR_s | PSR_x},
402 {"CPSR_sc", TRUE, PSR_s | PSR_c},
403 {"CPSR_xf", TRUE, PSR_x | PSR_f},
404 {"CPSR_xs", TRUE, PSR_x | PSR_s},
405 {"CPSR_xc", TRUE, PSR_x | PSR_c},
406 {"CPSR_cf", TRUE, PSR_c | PSR_f},
407 {"CPSR_cs", TRUE, PSR_c | PSR_s},
408 {"CPSR_cx", TRUE, PSR_c | PSR_x},
409 {"CPSR_fsx", TRUE, PSR_f | PSR_s | PSR_x},
410 {"CPSR_fsc", TRUE, PSR_f | PSR_s | PSR_c},
411 {"CPSR_fxs", TRUE, PSR_f | PSR_x | PSR_s},
412 {"CPSR_fxc", TRUE, PSR_f | PSR_x | PSR_c},
413 {"CPSR_fcs", TRUE, PSR_f | PSR_c | PSR_s},
414 {"CPSR_fcx", TRUE, PSR_f | PSR_c | PSR_x},
415 {"CPSR_sfx", TRUE, PSR_s | PSR_f | PSR_x},
416 {"CPSR_sfc", TRUE, PSR_s | PSR_f | PSR_c},
417 {"CPSR_sxf", TRUE, PSR_s | PSR_x | PSR_f},
418 {"CPSR_sxc", TRUE, PSR_s | PSR_x | PSR_c},
419 {"CPSR_scf", TRUE, PSR_s | PSR_c | PSR_f},
420 {"CPSR_scx", TRUE, PSR_s | PSR_c | PSR_x},
421 {"CPSR_xfs", TRUE, PSR_x | PSR_f | PSR_s},
422 {"CPSR_xfc", TRUE, PSR_x | PSR_f | PSR_c},
423 {"CPSR_xsf", TRUE, PSR_x | PSR_s | PSR_f},
424 {"CPSR_xsc", TRUE, PSR_x | PSR_s | PSR_c},
425 {"CPSR_xcf", TRUE, PSR_x | PSR_c | PSR_f},
426 {"CPSR_xcs", TRUE, PSR_x | PSR_c | PSR_s},
427 {"CPSR_cfs", TRUE, PSR_c | PSR_f | PSR_s},
428 {"CPSR_cfx", TRUE, PSR_c | PSR_f | PSR_x},
429 {"CPSR_csf", TRUE, PSR_c | PSR_s | PSR_f},
430 {"CPSR_csx", TRUE, PSR_c | PSR_s | PSR_x},
431 {"CPSR_cxf", TRUE, PSR_c | PSR_x | PSR_f},
432 {"CPSR_cxs", TRUE, PSR_c | PSR_x | PSR_s},
433 {"CPSR_fsxc", TRUE, PSR_f | PSR_s | PSR_x | PSR_c},
434 {"CPSR_fscx", TRUE, PSR_f | PSR_s | PSR_c | PSR_x},
435 {"CPSR_fxsc", TRUE, PSR_f | PSR_x | PSR_s | PSR_c},
436 {"CPSR_fxcs", TRUE, PSR_f | PSR_x | PSR_c | PSR_s},
437 {"CPSR_fcsx", TRUE, PSR_f | PSR_c | PSR_s | PSR_x},
438 {"CPSR_fcxs", TRUE, PSR_f | PSR_c | PSR_x | PSR_s},
439 {"CPSR_sfxc", TRUE, PSR_s | PSR_f | PSR_x | PSR_c},
440 {"CPSR_sfcx", TRUE, PSR_s | PSR_f | PSR_c | PSR_x},
441 {"CPSR_sxfc", TRUE, PSR_s | PSR_x | PSR_f | PSR_c},
442 {"CPSR_sxcf", TRUE, PSR_s | PSR_x | PSR_c | PSR_f},
443 {"CPSR_scfx", TRUE, PSR_s | PSR_c | PSR_f | PSR_x},
444 {"CPSR_scxf", TRUE, PSR_s | PSR_c | PSR_x | PSR_f},
445 {"CPSR_xfsc", TRUE, PSR_x | PSR_f | PSR_s | PSR_c},
446 {"CPSR_xfcs", TRUE, PSR_x | PSR_f | PSR_c | PSR_s},
447 {"CPSR_xsfc", TRUE, PSR_x | PSR_s | PSR_f | PSR_c},
448 {"CPSR_xscf", TRUE, PSR_x | PSR_s | PSR_c | PSR_f},
449 {"CPSR_xcfs", TRUE, PSR_x | PSR_c | PSR_f | PSR_s},
450 {"CPSR_xcsf", TRUE, PSR_x | PSR_c | PSR_s | PSR_f},
451 {"CPSR_cfsx", TRUE, PSR_c | PSR_f | PSR_s | PSR_x},
452 {"CPSR_cfxs", TRUE, PSR_c | PSR_f | PSR_x | PSR_s},
453 {"CPSR_csfx", TRUE, PSR_c | PSR_s | PSR_f | PSR_x},
454 {"CPSR_csxf", TRUE, PSR_c | PSR_s | PSR_x | PSR_f},
455 {"CPSR_cxfs", TRUE, PSR_c | PSR_x | PSR_f | PSR_s},
456 {"CPSR_cxsf", TRUE, PSR_c | PSR_x | PSR_s | PSR_f},
457 {"SPSR_fs", FALSE, PSR_f | PSR_s},
458 {"SPSR_fx", FALSE, PSR_f | PSR_x},
459 {"SPSR_fc", FALSE, PSR_f | PSR_c},
460 {"SPSR_sf", FALSE, PSR_s | PSR_f},
461 {"SPSR_sx", FALSE, PSR_s | PSR_x},
462 {"SPSR_sc", FALSE, PSR_s | PSR_c},
463 {"SPSR_xf", FALSE, PSR_x | PSR_f},
464 {"SPSR_xs", FALSE, PSR_x | PSR_s},
465 {"SPSR_xc", FALSE, PSR_x | PSR_c},
466 {"SPSR_cf", FALSE, PSR_c | PSR_f},
467 {"SPSR_cs", FALSE, PSR_c | PSR_s},
468 {"SPSR_cx", FALSE, PSR_c | PSR_x},
469 {"SPSR_fsx", FALSE, PSR_f | PSR_s | PSR_x},
470 {"SPSR_fsc", FALSE, PSR_f | PSR_s | PSR_c},
471 {"SPSR_fxs", FALSE, PSR_f | PSR_x | PSR_s},
472 {"SPSR_fxc", FALSE, PSR_f | PSR_x | PSR_c},
473 {"SPSR_fcs", FALSE, PSR_f | PSR_c | PSR_s},
474 {"SPSR_fcx", FALSE, PSR_f | PSR_c | PSR_x},
475 {"SPSR_sfx", FALSE, PSR_s | PSR_f | PSR_x},
476 {"SPSR_sfc", FALSE, PSR_s | PSR_f | PSR_c},
477 {"SPSR_sxf", FALSE, PSR_s | PSR_x | PSR_f},
478 {"SPSR_sxc", FALSE, PSR_s | PSR_x | PSR_c},
479 {"SPSR_scf", FALSE, PSR_s | PSR_c | PSR_f},
480 {"SPSR_scx", FALSE, PSR_s | PSR_c | PSR_x},
481 {"SPSR_xfs", FALSE, PSR_x | PSR_f | PSR_s},
482 {"SPSR_xfc", FALSE, PSR_x | PSR_f | PSR_c},
483 {"SPSR_xsf", FALSE, PSR_x | PSR_s | PSR_f},
484 {"SPSR_xsc", FALSE, PSR_x | PSR_s | PSR_c},
485 {"SPSR_xcf", FALSE, PSR_x | PSR_c | PSR_f},
486 {"SPSR_xcs", FALSE, PSR_x | PSR_c | PSR_s},
487 {"SPSR_cfs", FALSE, PSR_c | PSR_f | PSR_s},
488 {"SPSR_cfx", FALSE, PSR_c | PSR_f | PSR_x},
489 {"SPSR_csf", FALSE, PSR_c | PSR_s | PSR_f},
490 {"SPSR_csx", FALSE, PSR_c | PSR_s | PSR_x},
491 {"SPSR_cxf", FALSE, PSR_c | PSR_x | PSR_f},
492 {"SPSR_cxs", FALSE, PSR_c | PSR_x | PSR_s},
493 {"SPSR_fsxc", FALSE, PSR_f | PSR_s | PSR_x | PSR_c},
494 {"SPSR_fscx", FALSE, PSR_f | PSR_s | PSR_c | PSR_x},
495 {"SPSR_fxsc", FALSE, PSR_f | PSR_x | PSR_s | PSR_c},
496 {"SPSR_fxcs", FALSE, PSR_f | PSR_x | PSR_c | PSR_s},
497 {"SPSR_fcsx", FALSE, PSR_f | PSR_c | PSR_s | PSR_x},
498 {"SPSR_fcxs", FALSE, PSR_f | PSR_c | PSR_x | PSR_s},
499 {"SPSR_sfxc", FALSE, PSR_s | PSR_f | PSR_x | PSR_c},
500 {"SPSR_sfcx", FALSE, PSR_s | PSR_f | PSR_c | PSR_x},
501 {"SPSR_sxfc", FALSE, PSR_s | PSR_x | PSR_f | PSR_c},
502 {"SPSR_sxcf", FALSE, PSR_s | PSR_x | PSR_c | PSR_f},
503 {"SPSR_scfx", FALSE, PSR_s | PSR_c | PSR_f | PSR_x},
504 {"SPSR_scxf", FALSE, PSR_s | PSR_c | PSR_x | PSR_f},
505 {"SPSR_xfsc", FALSE, PSR_x | PSR_f | PSR_s | PSR_c},
506 {"SPSR_xfcs", FALSE, PSR_x | PSR_f | PSR_c | PSR_s},
507 {"SPSR_xsfc", FALSE, PSR_x | PSR_s | PSR_f | PSR_c},
508 {"SPSR_xscf", FALSE, PSR_x | PSR_s | PSR_c | PSR_f},
509 {"SPSR_xcfs", FALSE, PSR_x | PSR_c | PSR_f | PSR_s},
510 {"SPSR_xcsf", FALSE, PSR_x | PSR_c | PSR_s | PSR_f},
511 {"SPSR_cfsx", FALSE, PSR_c | PSR_f | PSR_s | PSR_x},
512 {"SPSR_cfxs", FALSE, PSR_c | PSR_f | PSR_x | PSR_s},
513 {"SPSR_csfx", FALSE, PSR_c | PSR_s | PSR_f | PSR_x},
514 {"SPSR_csxf", FALSE, PSR_c | PSR_s | PSR_x | PSR_f},
515 {"SPSR_cxfs", FALSE, PSR_c | PSR_x | PSR_f | PSR_s},
516 {"SPSR_cxsf", FALSE, PSR_c | PSR_x | PSR_s | PSR_f},
517 };
518
519 enum wreg_type
520 {
521 IWMMXT_REG_WR = 0,
522 IWMMXT_REG_WC = 1,
523 IWMMXT_REG_WR_OR_WC = 2,
524 IWMMXT_REG_WCG
525 };
526
527 enum iwmmxt_insn_type
528 {
529 check_rd,
530 check_wr,
531 check_wrwr,
532 check_wrwrwr,
533 check_wrwrwcg,
534 check_tbcst,
535 check_tmovmsk,
536 check_tmia,
537 check_tmcrr,
538 check_tmrrc,
539 check_tmcr,
540 check_tmrc,
541 check_tinsr,
542 check_textrc,
543 check_waligni,
544 check_textrm,
545 check_wshufh
546 };
547
548 enum vfp_dp_reg_pos
549 {
550 VFP_REG_Dd, VFP_REG_Dm, VFP_REG_Dn
551 };
552
553 enum vfp_sp_reg_pos
554 {
555 VFP_REG_Sd, VFP_REG_Sm, VFP_REG_Sn
556 };
557
558 enum vfp_ldstm_type
559 {
560 VFP_LDSTMIA, VFP_LDSTMDB, VFP_LDSTMIAX, VFP_LDSTMDBX
561 };
562
563 /* VFP system registers. */
564 struct vfp_reg
565 {
566 const char *name;
567 unsigned long regno;
568 };
569
570 static const struct vfp_reg vfp_regs[] =
571 {
572 {"fpsid", 0x00000000},
573 {"FPSID", 0x00000000},
574 {"fpscr", 0x00010000},
575 {"FPSCR", 0x00010000},
576 {"fpexc", 0x00080000},
577 {"FPEXC", 0x00080000}
578 };
579
580 /* Structure for a hash table entry for a register. */
581 struct reg_entry
582 {
583 const char * name;
584 int number;
585 bfd_boolean builtin;
586 };
587
588 /* Some well known registers that we refer to directly elsewhere. */
589 #define REG_SP 13
590 #define REG_LR 14
591 #define REG_PC 15
592
593 #define wr_register(reg) ((reg ^ WR_PREFIX) >= 0 && (reg ^ WR_PREFIX) <= 15)
594 #define wc_register(reg) ((reg ^ WC_PREFIX) >= 0 && (reg ^ WC_PREFIX) <= 15)
595 #define wcg_register(reg) ((reg ^ WC_PREFIX) >= 8 && (reg ^ WC_PREFIX) <= 11)
596
597 /* These are the standard names. Users can add aliases with .req.
598 and delete them with .unreq. */
599
600 /* Integer Register Numbers. */
601 static const struct reg_entry rn_table[] =
602 {
603 {"r0", 0, TRUE}, {"r1", 1, TRUE}, {"r2", 2, TRUE}, {"r3", 3, TRUE},
604 {"r4", 4, TRUE}, {"r5", 5, TRUE}, {"r6", 6, TRUE}, {"r7", 7, TRUE},
605 {"r8", 8, TRUE}, {"r9", 9, TRUE}, {"r10", 10, TRUE}, {"r11", 11, TRUE},
606 {"r12", 12, TRUE}, {"r13", REG_SP, TRUE}, {"r14", REG_LR, TRUE}, {"r15", REG_PC, TRUE},
607 /* ATPCS Synonyms. */
608 {"a1", 0, TRUE}, {"a2", 1, TRUE}, {"a3", 2, TRUE}, {"a4", 3, TRUE},
609 {"v1", 4, TRUE}, {"v2", 5, TRUE}, {"v3", 6, TRUE}, {"v4", 7, TRUE},
610 {"v5", 8, TRUE}, {"v6", 9, TRUE}, {"v7", 10, TRUE}, {"v8", 11, TRUE},
611 /* Well-known aliases. */
612 {"wr", 7, TRUE}, {"sb", 9, TRUE}, {"sl", 10, TRUE}, {"fp", 11, TRUE},
613 {"ip", 12, TRUE}, {"sp", REG_SP, TRUE}, {"lr", REG_LR, TRUE}, {"pc", REG_PC, TRUE},
614 {NULL, 0, TRUE}
615 };
616
617 #define WR_PREFIX 0x200
618 #define WC_PREFIX 0x400
619
620 static const struct reg_entry iwmmxt_table[] =
621 {
622 /* Intel Wireless MMX technology register names. */
623 { "wr0", 0x0 | WR_PREFIX, TRUE}, {"wr1", 0x1 | WR_PREFIX, TRUE},
624 { "wr2", 0x2 | WR_PREFIX, TRUE}, {"wr3", 0x3 | WR_PREFIX, TRUE},
625 { "wr4", 0x4 | WR_PREFIX, TRUE}, {"wr5", 0x5 | WR_PREFIX, TRUE},
626 { "wr6", 0x6 | WR_PREFIX, TRUE}, {"wr7", 0x7 | WR_PREFIX, TRUE},
627 { "wr8", 0x8 | WR_PREFIX, TRUE}, {"wr9", 0x9 | WR_PREFIX, TRUE},
628 { "wr10", 0xa | WR_PREFIX, TRUE}, {"wr11", 0xb | WR_PREFIX, TRUE},
629 { "wr12", 0xc | WR_PREFIX, TRUE}, {"wr13", 0xd | WR_PREFIX, TRUE},
630 { "wr14", 0xe | WR_PREFIX, TRUE}, {"wr15", 0xf | WR_PREFIX, TRUE},
631 { "wcid", 0x0 | WC_PREFIX, TRUE}, {"wcon", 0x1 | WC_PREFIX, TRUE},
632 {"wcssf", 0x2 | WC_PREFIX, TRUE}, {"wcasf", 0x3 | WC_PREFIX, TRUE},
633 {"wcgr0", 0x8 | WC_PREFIX, TRUE}, {"wcgr1", 0x9 | WC_PREFIX, TRUE},
634 {"wcgr2", 0xa | WC_PREFIX, TRUE}, {"wcgr3", 0xb | WC_PREFIX, TRUE},
635
636 { "wR0", 0x0 | WR_PREFIX, TRUE}, {"wR1", 0x1 | WR_PREFIX, TRUE},
637 { "wR2", 0x2 | WR_PREFIX, TRUE}, {"wR3", 0x3 | WR_PREFIX, TRUE},
638 { "wR4", 0x4 | WR_PREFIX, TRUE}, {"wR5", 0x5 | WR_PREFIX, TRUE},
639 { "wR6", 0x6 | WR_PREFIX, TRUE}, {"wR7", 0x7 | WR_PREFIX, TRUE},
640 { "wR8", 0x8 | WR_PREFIX, TRUE}, {"wR9", 0x9 | WR_PREFIX, TRUE},
641 { "wR10", 0xa | WR_PREFIX, TRUE}, {"wR11", 0xb | WR_PREFIX, TRUE},
642 { "wR12", 0xc | WR_PREFIX, TRUE}, {"wR13", 0xd | WR_PREFIX, TRUE},
643 { "wR14", 0xe | WR_PREFIX, TRUE}, {"wR15", 0xf | WR_PREFIX, TRUE},
644 { "wCID", 0x0 | WC_PREFIX, TRUE}, {"wCon", 0x1 | WC_PREFIX, TRUE},
645 {"wCSSF", 0x2 | WC_PREFIX, TRUE}, {"wCASF", 0x3 | WC_PREFIX, TRUE},
646 {"wCGR0", 0x8 | WC_PREFIX, TRUE}, {"wCGR1", 0x9 | WC_PREFIX, TRUE},
647 {"wCGR2", 0xa | WC_PREFIX, TRUE}, {"wCGR3", 0xb | WC_PREFIX, TRUE},
648 {NULL, 0, TRUE}
649 };
650
651 /* Co-processor Numbers. */
652 static const struct reg_entry cp_table[] =
653 {
654 {"p0", 0, TRUE}, {"p1", 1, TRUE}, {"p2", 2, TRUE}, {"p3", 3, TRUE},
655 {"p4", 4, TRUE}, {"p5", 5, TRUE}, {"p6", 6, TRUE}, {"p7", 7, TRUE},
656 {"p8", 8, TRUE}, {"p9", 9, TRUE}, {"p10", 10, TRUE}, {"p11", 11, TRUE},
657 {"p12", 12, TRUE}, {"p13", 13, TRUE}, {"p14", 14, TRUE}, {"p15", 15, TRUE},
658 {NULL, 0, TRUE}
659 };
660
661 /* Co-processor Register Numbers. */
662 static const struct reg_entry cn_table[] =
663 {
664 {"c0", 0, TRUE}, {"c1", 1, TRUE}, {"c2", 2, TRUE}, {"c3", 3, TRUE},
665 {"c4", 4, TRUE}, {"c5", 5, TRUE}, {"c6", 6, TRUE}, {"c7", 7, TRUE},
666 {"c8", 8, TRUE}, {"c9", 9, TRUE}, {"c10", 10, TRUE}, {"c11", 11, TRUE},
667 {"c12", 12, TRUE}, {"c13", 13, TRUE}, {"c14", 14, TRUE}, {"c15", 15, TRUE},
668 /* Not really valid, but kept for back-wards compatibility. */
669 {"cr0", 0, TRUE}, {"cr1", 1, TRUE}, {"cr2", 2, TRUE}, {"cr3", 3, TRUE},
670 {"cr4", 4, TRUE}, {"cr5", 5, TRUE}, {"cr6", 6, TRUE}, {"cr7", 7, TRUE},
671 {"cr8", 8, TRUE}, {"cr9", 9, TRUE}, {"cr10", 10, TRUE}, {"cr11", 11, TRUE},
672 {"cr12", 12, TRUE}, {"cr13", 13, TRUE}, {"cr14", 14, TRUE}, {"cr15", 15, TRUE},
673 {NULL, 0, TRUE}
674 };
675
676 /* FPA Registers. */
677 static const struct reg_entry fn_table[] =
678 {
679 {"f0", 0, TRUE}, {"f1", 1, TRUE}, {"f2", 2, TRUE}, {"f3", 3, TRUE},
680 {"f4", 4, TRUE}, {"f5", 5, TRUE}, {"f6", 6, TRUE}, {"f7", 7, TRUE},
681 {NULL, 0, TRUE}
682 };
683
684 /* VFP SP Registers. */
685 static const struct reg_entry sn_table[] =
686 {
687 {"s0", 0, TRUE}, {"s1", 1, TRUE}, {"s2", 2, TRUE}, {"s3", 3, TRUE},
688 {"s4", 4, TRUE}, {"s5", 5, TRUE}, {"s6", 6, TRUE}, {"s7", 7, TRUE},
689 {"s8", 8, TRUE}, {"s9", 9, TRUE}, {"s10", 10, TRUE}, {"s11", 11, TRUE},
690 {"s12", 12, TRUE}, {"s13", 13, TRUE}, {"s14", 14, TRUE}, {"s15", 15, TRUE},
691 {"s16", 16, TRUE}, {"s17", 17, TRUE}, {"s18", 18, TRUE}, {"s19", 19, TRUE},
692 {"s20", 20, TRUE}, {"s21", 21, TRUE}, {"s22", 22, TRUE}, {"s23", 23, TRUE},
693 {"s24", 24, TRUE}, {"s25", 25, TRUE}, {"s26", 26, TRUE}, {"s27", 27, TRUE},
694 {"s28", 28, TRUE}, {"s29", 29, TRUE}, {"s30", 30, TRUE}, {"s31", 31, TRUE},
695 {NULL, 0, TRUE}
696 };
697
698 /* VFP DP Registers. */
699 static const struct reg_entry dn_table[] =
700 {
701 {"d0", 0, TRUE}, {"d1", 1, TRUE}, {"d2", 2, TRUE}, {"d3", 3, TRUE},
702 {"d4", 4, TRUE}, {"d5", 5, TRUE}, {"d6", 6, TRUE}, {"d7", 7, TRUE},
703 {"d8", 8, TRUE}, {"d9", 9, TRUE}, {"d10", 10, TRUE}, {"d11", 11, TRUE},
704 {"d12", 12, TRUE}, {"d13", 13, TRUE}, {"d14", 14, TRUE}, {"d15", 15, TRUE},
705 {NULL, 0, TRUE}
706 };
707
708 /* Maverick DSP coprocessor registers. */
709 static const struct reg_entry mav_mvf_table[] =
710 {
711 {"mvf0", 0, TRUE}, {"mvf1", 1, TRUE}, {"mvf2", 2, TRUE}, {"mvf3", 3, TRUE},
712 {"mvf4", 4, TRUE}, {"mvf5", 5, TRUE}, {"mvf6", 6, TRUE}, {"mvf7", 7, TRUE},
713 {"mvf8", 8, TRUE}, {"mvf9", 9, TRUE}, {"mvf10", 10, TRUE}, {"mvf11", 11, TRUE},
714 {"mvf12", 12, TRUE}, {"mvf13", 13, TRUE}, {"mvf14", 14, TRUE}, {"mvf15", 15, TRUE},
715 {NULL, 0, TRUE}
716 };
717
718 static const struct reg_entry mav_mvd_table[] =
719 {
720 {"mvd0", 0, TRUE}, {"mvd1", 1, TRUE}, {"mvd2", 2, TRUE}, {"mvd3", 3, TRUE},
721 {"mvd4", 4, TRUE}, {"mvd5", 5, TRUE}, {"mvd6", 6, TRUE}, {"mvd7", 7, TRUE},
722 {"mvd8", 8, TRUE}, {"mvd9", 9, TRUE}, {"mvd10", 10, TRUE}, {"mvd11", 11, TRUE},
723 {"mvd12", 12, TRUE}, {"mvd13", 13, TRUE}, {"mvd14", 14, TRUE}, {"mvd15", 15, TRUE},
724 {NULL, 0, TRUE}
725 };
726
727 static const struct reg_entry mav_mvfx_table[] =
728 {
729 {"mvfx0", 0, TRUE}, {"mvfx1", 1, TRUE}, {"mvfx2", 2, TRUE}, {"mvfx3", 3, TRUE},
730 {"mvfx4", 4, TRUE}, {"mvfx5", 5, TRUE}, {"mvfx6", 6, TRUE}, {"mvfx7", 7, TRUE},
731 {"mvfx8", 8, TRUE}, {"mvfx9", 9, TRUE}, {"mvfx10", 10, TRUE}, {"mvfx11", 11, TRUE},
732 {"mvfx12", 12, TRUE}, {"mvfx13", 13, TRUE}, {"mvfx14", 14, TRUE}, {"mvfx15", 15, TRUE},
733 {NULL, 0, TRUE}
734 };
735
736 static const struct reg_entry mav_mvdx_table[] =
737 {
738 {"mvdx0", 0, TRUE}, {"mvdx1", 1, TRUE}, {"mvdx2", 2, TRUE}, {"mvdx3", 3, TRUE},
739 {"mvdx4", 4, TRUE}, {"mvdx5", 5, TRUE}, {"mvdx6", 6, TRUE}, {"mvdx7", 7, TRUE},
740 {"mvdx8", 8, TRUE}, {"mvdx9", 9, TRUE}, {"mvdx10", 10, TRUE}, {"mvdx11", 11, TRUE},
741 {"mvdx12", 12, TRUE}, {"mvdx13", 13, TRUE}, {"mvdx14", 14, TRUE}, {"mvdx15", 15, TRUE},
742 {NULL, 0, TRUE}
743 };
744
745 static const struct reg_entry mav_mvax_table[] =
746 {
747 {"mvax0", 0, TRUE}, {"mvax1", 1, TRUE}, {"mvax2", 2, TRUE}, {"mvax3", 3, TRUE},
748 {NULL, 0, TRUE}
749 };
750
751 static const struct reg_entry mav_dspsc_table[] =
752 {
753 {"dspsc", 0, TRUE},
754 {NULL, 0, TRUE}
755 };
756
757 struct reg_map
758 {
759 const struct reg_entry * names;
760 int max_regno;
761 struct hash_control * htab;
762 const char * expected;
763 };
764
765 struct reg_map all_reg_maps[] =
766 {
767 {rn_table, 15, NULL, N_("ARM register expected")},
768 {cp_table, 15, NULL, N_("bad or missing co-processor number")},
769 {cn_table, 15, NULL, N_("co-processor register expected")},
770 {fn_table, 7, NULL, N_("FPA register expected")},
771 {sn_table, 31, NULL, N_("VFP single precision register expected")},
772 {dn_table, 15, NULL, N_("VFP double precision register expected")},
773 {mav_mvf_table, 15, NULL, N_("Maverick MVF register expected")},
774 {mav_mvd_table, 15, NULL, N_("Maverick MVD register expected")},
775 {mav_mvfx_table, 15, NULL, N_("Maverick MVFX register expected")},
776 {mav_mvdx_table, 15, NULL, N_("Maverick MVDX register expected")},
777 {mav_mvax_table, 3, NULL, N_("Maverick MVAX register expected")},
778 {mav_dspsc_table, 0, NULL, N_("Maverick DSPSC register expected")},
779 {iwmmxt_table, 23, NULL, N_("Intel Wireless MMX technology register expected")},
780 };
781
782 /* Enumeration matching entries in table above. */
783 enum arm_reg_type
784 {
785 REG_TYPE_RN = 0,
786 #define REG_TYPE_FIRST REG_TYPE_RN
787 REG_TYPE_CP = 1,
788 REG_TYPE_CN = 2,
789 REG_TYPE_FN = 3,
790 REG_TYPE_SN = 4,
791 REG_TYPE_DN = 5,
792 REG_TYPE_MVF = 6,
793 REG_TYPE_MVD = 7,
794 REG_TYPE_MVFX = 8,
795 REG_TYPE_MVDX = 9,
796 REG_TYPE_MVAX = 10,
797 REG_TYPE_DSPSC = 11,
798 REG_TYPE_IWMMXT = 12,
799
800 REG_TYPE_MAX = 13
801 };
802
803 /* ARM instructions take 4bytes in the object file, Thumb instructions
804 take 2: */
805 #define INSN_SIZE 4
806
807 /* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
808 #define MAV_MODE1 0x100c
809
810 /* "INSN<cond> X,Y" where X:bit16, Y:bit12. */
811 #define MAV_MODE2 0x0c10
812
813 /* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
814 #define MAV_MODE3 0x100c
815
816 /* "INSN<cond> X,Y,Z" where X:16, Y:0, Z:12. */
817 #define MAV_MODE4 0x0c0010
818
819 /* "INSN<cond> X,Y,Z" where X:12, Y:16, Z:0. */
820 #define MAV_MODE5 0x00100c
821
822 /* "INSN<cond> W,X,Y,Z" where W:5, X:12, Y:16, Z:0. */
823 #define MAV_MODE6 0x00100c05
824
825 struct asm_opcode
826 {
827 /* Basic string to match. */
828 const char * template;
829
830 /* Basic instruction code. */
831 unsigned long value;
832
833 /* Offset into the template where the condition code (if any) will be.
834 If zero, then the instruction is never conditional. */
835 unsigned cond_offset;
836
837 /* Which architecture variant provides this instruction. */
838 unsigned long variant;
839
840 /* Function to call to parse args. */
841 void (* parms) (char *);
842 };
843
844 /* Defines for various bits that we will want to toggle. */
845 #define INST_IMMEDIATE 0x02000000
846 #define OFFSET_REG 0x02000000
847 #define HWOFFSET_IMM 0x00400000
848 #define SHIFT_BY_REG 0x00000010
849 #define PRE_INDEX 0x01000000
850 #define INDEX_UP 0x00800000
851 #define WRITE_BACK 0x00200000
852 #define LDM_TYPE_2_OR_3 0x00400000
853
854 #define LITERAL_MASK 0xf000f000
855 #define OPCODE_MASK 0xfe1fffff
856 #define V4_STR_BIT 0x00000020
857
858 #define DATA_OP_SHIFT 21
859
860 /* Codes to distinguish the arithmetic instructions. */
861 #define OPCODE_AND 0
862 #define OPCODE_EOR 1
863 #define OPCODE_SUB 2
864 #define OPCODE_RSB 3
865 #define OPCODE_ADD 4
866 #define OPCODE_ADC 5
867 #define OPCODE_SBC 6
868 #define OPCODE_RSC 7
869 #define OPCODE_TST 8
870 #define OPCODE_TEQ 9
871 #define OPCODE_CMP 10
872 #define OPCODE_CMN 11
873 #define OPCODE_ORR 12
874 #define OPCODE_MOV 13
875 #define OPCODE_BIC 14
876 #define OPCODE_MVN 15
877
878 #define T_OPCODE_MUL 0x4340
879 #define T_OPCODE_TST 0x4200
880 #define T_OPCODE_CMN 0x42c0
881 #define T_OPCODE_NEG 0x4240
882 #define T_OPCODE_MVN 0x43c0
883
884 #define T_OPCODE_ADD_R3 0x1800
885 #define T_OPCODE_SUB_R3 0x1a00
886 #define T_OPCODE_ADD_HI 0x4400
887 #define T_OPCODE_ADD_ST 0xb000
888 #define T_OPCODE_SUB_ST 0xb080
889 #define T_OPCODE_ADD_SP 0xa800
890 #define T_OPCODE_ADD_PC 0xa000
891 #define T_OPCODE_ADD_I8 0x3000
892 #define T_OPCODE_SUB_I8 0x3800
893 #define T_OPCODE_ADD_I3 0x1c00
894 #define T_OPCODE_SUB_I3 0x1e00
895
896 #define T_OPCODE_ASR_R 0x4100
897 #define T_OPCODE_LSL_R 0x4080
898 #define T_OPCODE_LSR_R 0x40c0
899 #define T_OPCODE_ASR_I 0x1000
900 #define T_OPCODE_LSL_I 0x0000
901 #define T_OPCODE_LSR_I 0x0800
902
903 #define T_OPCODE_MOV_I8 0x2000
904 #define T_OPCODE_CMP_I8 0x2800
905 #define T_OPCODE_CMP_LR 0x4280
906 #define T_OPCODE_MOV_HR 0x4600
907 #define T_OPCODE_CMP_HR 0x4500
908
909 #define T_OPCODE_LDR_PC 0x4800
910 #define T_OPCODE_LDR_SP 0x9800
911 #define T_OPCODE_STR_SP 0x9000
912 #define T_OPCODE_LDR_IW 0x6800
913 #define T_OPCODE_STR_IW 0x6000
914 #define T_OPCODE_LDR_IH 0x8800
915 #define T_OPCODE_STR_IH 0x8000
916 #define T_OPCODE_LDR_IB 0x7800
917 #define T_OPCODE_STR_IB 0x7000
918 #define T_OPCODE_LDR_RW 0x5800
919 #define T_OPCODE_STR_RW 0x5000
920 #define T_OPCODE_LDR_RH 0x5a00
921 #define T_OPCODE_STR_RH 0x5200
922 #define T_OPCODE_LDR_RB 0x5c00
923 #define T_OPCODE_STR_RB 0x5400
924
925 #define T_OPCODE_PUSH 0xb400
926 #define T_OPCODE_POP 0xbc00
927
928 #define T_OPCODE_BRANCH 0xe7fe
929
930 #define THUMB_SIZE 2 /* Size of thumb instruction. */
931 #define THUMB_REG_LO 0x1
932 #define THUMB_REG_HI 0x2
933 #define THUMB_REG_ANY 0x3
934
935 #define THUMB_H1 0x0080
936 #define THUMB_H2 0x0040
937
938 #define THUMB_ASR 0
939 #define THUMB_LSL 1
940 #define THUMB_LSR 2
941
942 #define THUMB_MOVE 0
943 #define THUMB_COMPARE 1
944 #define THUMB_CPY 2
945
946 #define THUMB_LOAD 0
947 #define THUMB_STORE 1
948
949 #define THUMB_PP_PC_LR 0x0100
950
951 /* These three are used for immediate shifts, do not alter. */
952 #define THUMB_WORD 2
953 #define THUMB_HALFWORD 1
954 #define THUMB_BYTE 0
955
956 struct thumb_opcode
957 {
958 /* Basic string to match. */
959 const char * template;
960
961 /* Basic instruction code. */
962 unsigned long value;
963
964 int size;
965
966 /* Which CPU variants this exists for. */
967 unsigned long variant;
968
969 /* Function to call to parse args. */
970 void (* parms) (char *);
971 };
972
973 #define BAD_ARGS _("bad arguments to instruction")
974 #define BAD_PC _("r15 not allowed here")
975 #define BAD_COND _("instruction is not conditional")
976 #define ERR_NO_ACCUM _("acc0 expected")
977
978 static struct hash_control * arm_ops_hsh = NULL;
979 static struct hash_control * arm_tops_hsh = NULL;
980 static struct hash_control * arm_cond_hsh = NULL;
981 static struct hash_control * arm_shift_hsh = NULL;
982 static struct hash_control * arm_psr_hsh = NULL;
983
984 /* Stuff needed to resolve the label ambiguity
985 As:
986 ...
987 label: <insn>
988 may differ from:
989 ...
990 label:
991 <insn>
992 */
993
994 symbolS * last_label_seen;
995 static int label_is_thumb_function_name = FALSE;
996 \f
997 /* Literal Pool stuff. */
998
999 #define MAX_LITERAL_POOL_SIZE 1024
1000
1001 /* Literal pool structure. Held on a per-section
1002 and per-sub-section basis. */
1003
1004 typedef struct literal_pool
1005 {
1006 expressionS literals [MAX_LITERAL_POOL_SIZE];
1007 unsigned int next_free_entry;
1008 unsigned int id;
1009 symbolS * symbol;
1010 segT section;
1011 subsegT sub_section;
1012 struct literal_pool * next;
1013 } literal_pool;
1014
1015 /* Pointer to a linked list of literal pools. */
1016 literal_pool * list_of_pools = NULL;
1017
1018 static literal_pool *
1019 find_literal_pool (void)
1020 {
1021 literal_pool * pool;
1022
1023 for (pool = list_of_pools; pool != NULL; pool = pool->next)
1024 {
1025 if (pool->section == now_seg
1026 && pool->sub_section == now_subseg)
1027 break;
1028 }
1029
1030 return pool;
1031 }
1032
1033 static literal_pool *
1034 find_or_make_literal_pool (void)
1035 {
1036 /* Next literal pool ID number. */
1037 static unsigned int latest_pool_num = 1;
1038 literal_pool * pool;
1039
1040 pool = find_literal_pool ();
1041
1042 if (pool == NULL)
1043 {
1044 /* Create a new pool. */
1045 pool = xmalloc (sizeof (* pool));
1046 if (! pool)
1047 return NULL;
1048
1049 pool->next_free_entry = 0;
1050 pool->section = now_seg;
1051 pool->sub_section = now_subseg;
1052 pool->next = list_of_pools;
1053 pool->symbol = NULL;
1054
1055 /* Add it to the list. */
1056 list_of_pools = pool;
1057 }
1058
1059 /* New pools, and emptied pools, will have a NULL symbol. */
1060 if (pool->symbol == NULL)
1061 {
1062 pool->symbol = symbol_create (FAKE_LABEL_NAME, undefined_section,
1063 (valueT) 0, &zero_address_frag);
1064 pool->id = latest_pool_num ++;
1065 }
1066
1067 /* Done. */
1068 return pool;
1069 }
1070
1071 /* Add the literal in the global 'inst'
1072 structure to the relevent literal pool. */
1073
1074 static int
1075 add_to_lit_pool (void)
1076 {
1077 literal_pool * pool;
1078 unsigned int entry;
1079
1080 pool = find_or_make_literal_pool ();
1081
1082 /* Check if this literal value is already in the pool. */
1083 for (entry = 0; entry < pool->next_free_entry; entry ++)
1084 {
1085 if ((pool->literals[entry].X_op == inst.reloc.exp.X_op)
1086 && (inst.reloc.exp.X_op == O_constant)
1087 && (pool->literals[entry].X_add_number
1088 == inst.reloc.exp.X_add_number)
1089 && (pool->literals[entry].X_unsigned
1090 == inst.reloc.exp.X_unsigned))
1091 break;
1092
1093 if ((pool->literals[entry].X_op == inst.reloc.exp.X_op)
1094 && (inst.reloc.exp.X_op == O_symbol)
1095 && (pool->literals[entry].X_add_number
1096 == inst.reloc.exp.X_add_number)
1097 && (pool->literals[entry].X_add_symbol
1098 == inst.reloc.exp.X_add_symbol)
1099 && (pool->literals[entry].X_op_symbol
1100 == inst.reloc.exp.X_op_symbol))
1101 break;
1102 }
1103
1104 /* Do we need to create a new entry? */
1105 if (entry == pool->next_free_entry)
1106 {
1107 if (entry >= MAX_LITERAL_POOL_SIZE)
1108 {
1109 inst.error = _("literal pool overflow");
1110 return FAIL;
1111 }
1112
1113 pool->literals[entry] = inst.reloc.exp;
1114 pool->next_free_entry += 1;
1115 }
1116
1117 inst.reloc.exp.X_op = O_symbol;
1118 inst.reloc.exp.X_add_number = ((int) entry) * 4 - 8;
1119 inst.reloc.exp.X_add_symbol = pool->symbol;
1120
1121 return SUCCESS;
1122 }
1123
1124 /* Can't use symbol_new here, so have to create a symbol and then at
1125 a later date assign it a value. Thats what these functions do. */
1126
1127 static void
1128 symbol_locate (symbolS * symbolP,
1129 const char * name, /* It is copied, the caller can modify. */
1130 segT segment, /* Segment identifier (SEG_<something>). */
1131 valueT valu, /* Symbol value. */
1132 fragS * frag) /* Associated fragment. */
1133 {
1134 unsigned int name_length;
1135 char * preserved_copy_of_name;
1136
1137 name_length = strlen (name) + 1; /* +1 for \0. */
1138 obstack_grow (&notes, name, name_length);
1139 preserved_copy_of_name = obstack_finish (&notes);
1140
1141 #ifdef tc_canonicalize_symbol_name
1142 preserved_copy_of_name =
1143 tc_canonicalize_symbol_name (preserved_copy_of_name);
1144 #endif
1145
1146 S_SET_NAME (symbolP, preserved_copy_of_name);
1147
1148 S_SET_SEGMENT (symbolP, segment);
1149 S_SET_VALUE (symbolP, valu);
1150 symbol_clear_list_pointers (symbolP);
1151
1152 symbol_set_frag (symbolP, frag);
1153
1154 /* Link to end of symbol chain. */
1155 {
1156 extern int symbol_table_frozen;
1157
1158 if (symbol_table_frozen)
1159 abort ();
1160 }
1161
1162 symbol_append (symbolP, symbol_lastP, & symbol_rootP, & symbol_lastP);
1163
1164 obj_symbol_new_hook (symbolP);
1165
1166 #ifdef tc_symbol_new_hook
1167 tc_symbol_new_hook (symbolP);
1168 #endif
1169
1170 #ifdef DEBUG_SYMS
1171 verify_symbol_chain (symbol_rootP, symbol_lastP);
1172 #endif /* DEBUG_SYMS */
1173 }
1174
1175 /* Check that an immediate is valid.
1176 If so, convert it to the right format. */
1177
1178 static unsigned int
1179 validate_immediate (unsigned int val)
1180 {
1181 unsigned int a;
1182 unsigned int i;
1183
1184 #define rotate_left(v, n) (v << n | v >> (32 - n))
1185
1186 for (i = 0; i < 32; i += 2)
1187 if ((a = rotate_left (val, i)) <= 0xff)
1188 return a | (i << 7); /* 12-bit pack: [shift-cnt,const]. */
1189
1190 return FAIL;
1191 }
1192
1193 /* Check to see if an immediate can be computed as two separate immediate
1194 values, added together. We already know that this value cannot be
1195 computed by just one ARM instruction. */
1196
1197 static unsigned int
1198 validate_immediate_twopart (unsigned int val,
1199 unsigned int * highpart)
1200 {
1201 unsigned int a;
1202 unsigned int i;
1203
1204 for (i = 0; i < 32; i += 2)
1205 if (((a = rotate_left (val, i)) & 0xff) != 0)
1206 {
1207 if (a & 0xff00)
1208 {
1209 if (a & ~ 0xffff)
1210 continue;
1211 * highpart = (a >> 8) | ((i + 24) << 7);
1212 }
1213 else if (a & 0xff0000)
1214 {
1215 if (a & 0xff000000)
1216 continue;
1217 * highpart = (a >> 16) | ((i + 16) << 7);
1218 }
1219 else
1220 {
1221 assert (a & 0xff000000);
1222 * highpart = (a >> 24) | ((i + 8) << 7);
1223 }
1224
1225 return (a & 0xff) | (i << 7);
1226 }
1227
1228 return FAIL;
1229 }
1230
1231 static int
1232 validate_offset_imm (unsigned int val, int hwse)
1233 {
1234 if ((hwse && val > 255) || val > 4095)
1235 return FAIL;
1236 return val;
1237 }
1238
1239 \f
1240 #ifdef OBJ_ELF
1241 /* This code is to handle mapping symbols as defined in the ARM ELF spec.
1242 (See "Mapping symbols", section 4.5.5, ARM AAELF version 1.0).
1243 Note that previously, $a and $t has type STT_FUNC (BSF_OBJECT flag),
1244 and $d has type STT_OBJECT (BSF_OBJECT flag). Now all three are untyped. */
1245
1246 static enum mstate mapstate = MAP_UNDEFINED;
1247
1248 static void
1249 mapping_state (enum mstate state)
1250 {
1251 symbolS * symbolP;
1252 const char * symname;
1253 int type;
1254
1255 if (mapstate == state)
1256 /* The mapping symbol has already been emitted.
1257 There is nothing else to do. */
1258 return;
1259
1260 mapstate = state;
1261
1262 switch (state)
1263 {
1264 case MAP_DATA:
1265 symname = "$d";
1266 type = BSF_NO_FLAGS;
1267 break;
1268 case MAP_ARM:
1269 symname = "$a";
1270 type = BSF_NO_FLAGS;
1271 break;
1272 case MAP_THUMB:
1273 symname = "$t";
1274 type = BSF_NO_FLAGS;
1275 break;
1276 case MAP_UNDEFINED:
1277 return;
1278 default:
1279 abort ();
1280 }
1281
1282 seg_info (now_seg)->tc_segment_info_data.mapstate = state;
1283
1284 symbolP = symbol_new (symname, now_seg, (valueT) frag_now_fix (), frag_now);
1285 symbol_table_insert (symbolP);
1286 symbol_get_bfdsym (symbolP)->flags |= type | BSF_LOCAL;
1287
1288 switch (state)
1289 {
1290 case MAP_ARM:
1291 THUMB_SET_FUNC (symbolP, 0);
1292 ARM_SET_THUMB (symbolP, 0);
1293 ARM_SET_INTERWORK (symbolP, support_interwork);
1294 break;
1295
1296 case MAP_THUMB:
1297 THUMB_SET_FUNC (symbolP, 1);
1298 ARM_SET_THUMB (symbolP, 1);
1299 ARM_SET_INTERWORK (symbolP, support_interwork);
1300 break;
1301
1302 case MAP_DATA:
1303 default:
1304 return;
1305 }
1306 }
1307
1308 /* When we change sections we need to issue a new mapping symbol. */
1309
1310 void
1311 arm_elf_change_section (void)
1312 {
1313 flagword flags;
1314 segment_info_type *seginfo;
1315
1316 /* Link an unlinked unwind index table section to the .text section. */
1317 if (elf_section_type (now_seg) == SHT_ARM_EXIDX
1318 && elf_linked_to_section (now_seg) == NULL)
1319 elf_linked_to_section (now_seg) = text_section;
1320
1321 if (!SEG_NORMAL (now_seg))
1322 return;
1323
1324 flags = bfd_get_section_flags (stdoutput, now_seg);
1325
1326 /* We can ignore sections that only contain debug info. */
1327 if ((flags & SEC_ALLOC) == 0)
1328 return;
1329
1330 seginfo = seg_info (now_seg);
1331 mapstate = seginfo->tc_segment_info_data.mapstate;
1332 marked_pr_dependency = seginfo->tc_segment_info_data.marked_pr_dependency;
1333 }
1334
1335 int
1336 arm_elf_section_type (const char * str, size_t len)
1337 {
1338 if (len == 5 && strncmp (str, "exidx", 5) == 0)
1339 return SHT_ARM_EXIDX;
1340
1341 return -1;
1342 }
1343 #else
1344 #define mapping_state(a)
1345 #endif /* OBJ_ELF */
1346 \f
1347 /* arm_reg_parse () := if it looks like a register, return its token and
1348 advance the pointer. */
1349
1350 static int
1351 arm_reg_parse (char ** ccp, struct hash_control * htab)
1352 {
1353 char * start = * ccp;
1354 char c;
1355 char * p;
1356 struct reg_entry * reg;
1357
1358 #ifdef REGISTER_PREFIX
1359 if (*start != REGISTER_PREFIX)
1360 return FAIL;
1361 p = start + 1;
1362 #else
1363 p = start;
1364 #ifdef OPTIONAL_REGISTER_PREFIX
1365 if (*p == OPTIONAL_REGISTER_PREFIX)
1366 p++, start++;
1367 #endif
1368 #endif
1369 if (!ISALPHA (*p) || !is_name_beginner (*p))
1370 return FAIL;
1371
1372 c = *p++;
1373 while (ISALPHA (c) || ISDIGIT (c) || c == '_')
1374 c = *p++;
1375
1376 *--p = 0;
1377 reg = (struct reg_entry *) hash_find (htab, start);
1378 *p = c;
1379
1380 if (reg)
1381 {
1382 *ccp = p;
1383 return reg->number;
1384 }
1385
1386 return FAIL;
1387 }
1388
1389 /* Search for the following register name in each of the possible reg name
1390 tables. Return the classification if found, or REG_TYPE_MAX if not
1391 present. */
1392
1393 static enum arm_reg_type
1394 arm_reg_parse_any (char *cp)
1395 {
1396 int i;
1397
1398 for (i = (int) REG_TYPE_FIRST; i < (int) REG_TYPE_MAX; i++)
1399 if (arm_reg_parse (&cp, all_reg_maps[i].htab) != FAIL)
1400 return (enum arm_reg_type) i;
1401
1402 return REG_TYPE_MAX;
1403 }
1404
1405 static void
1406 opcode_select (int width)
1407 {
1408 switch (width)
1409 {
1410 case 16:
1411 if (! thumb_mode)
1412 {
1413 if (! (cpu_variant & ARM_EXT_V4T))
1414 as_bad (_("selected processor does not support THUMB opcodes"));
1415
1416 thumb_mode = 1;
1417 /* No need to force the alignment, since we will have been
1418 coming from ARM mode, which is word-aligned. */
1419 record_alignment (now_seg, 1);
1420 }
1421 mapping_state (MAP_THUMB);
1422 break;
1423
1424 case 32:
1425 if (thumb_mode)
1426 {
1427 if ((cpu_variant & ARM_ALL) == ARM_EXT_V4T)
1428 as_bad (_("selected processor does not support ARM opcodes"));
1429
1430 thumb_mode = 0;
1431
1432 if (!need_pass_2)
1433 frag_align (2, 0, 0);
1434
1435 record_alignment (now_seg, 1);
1436 }
1437 mapping_state (MAP_ARM);
1438 break;
1439
1440 default:
1441 as_bad (_("invalid instruction size selected (%d)"), width);
1442 }
1443 }
1444
1445 static void
1446 s_req (int a ATTRIBUTE_UNUSED)
1447 {
1448 as_bad (_("invalid syntax for .req directive"));
1449 }
1450
1451 /* The .unreq directive deletes an alias which was previously defined
1452 by .req. For example:
1453
1454 my_alias .req r11
1455 .unreq my_alias */
1456
1457 static void
1458 s_unreq (int a ATTRIBUTE_UNUSED)
1459 {
1460 char * name;
1461 char saved_char;
1462
1463 skip_whitespace (input_line_pointer);
1464 name = input_line_pointer;
1465
1466 while (*input_line_pointer != 0
1467 && *input_line_pointer != ' '
1468 && *input_line_pointer != '\n')
1469 ++input_line_pointer;
1470
1471 saved_char = *input_line_pointer;
1472 *input_line_pointer = 0;
1473
1474 if (*name)
1475 {
1476 enum arm_reg_type req_type = arm_reg_parse_any (name);
1477
1478 if (req_type != REG_TYPE_MAX)
1479 {
1480 char *temp_name = name;
1481 int req_no = arm_reg_parse (&temp_name, all_reg_maps[req_type].htab);
1482
1483 if (req_no != FAIL)
1484 {
1485 struct reg_entry *req_entry;
1486
1487 /* Check to see if this alias is a builtin one. */
1488 req_entry = hash_delete (all_reg_maps[req_type].htab, name);
1489
1490 if (!req_entry)
1491 as_bad (_("unreq: missing hash entry for \"%s\""), name);
1492 else if (req_entry->builtin)
1493 /* FIXME: We are deleting a built in register alias which
1494 points to a const data structure, so we only need to
1495 free up the memory used by the key in the hash table.
1496 Unfortunately we have not recorded this value, so this
1497 is a memory leak. */
1498 /* FIXME: Should we issue a warning message ? */
1499 ;
1500 else
1501 {
1502 /* Deleting a user defined alias. We need to free the
1503 key and the value, but fortunately the key is the same
1504 as the value->name field. */
1505 free ((char *) req_entry->name);
1506 free (req_entry);
1507 }
1508 }
1509 else
1510 as_bad (_(".unreq: unrecognized symbol \"%s\""), name);
1511 }
1512 else
1513 as_bad (_(".unreq: unrecognized symbol \"%s\""), name);
1514 }
1515 else
1516 as_bad (_("invalid syntax for .unreq directive"));
1517
1518 *input_line_pointer = saved_char;
1519 demand_empty_rest_of_line ();
1520 }
1521
1522 static void
1523 s_bss (int ignore ATTRIBUTE_UNUSED)
1524 {
1525 /* We don't support putting frags in the BSS segment, we fake it by
1526 marking in_bss, then looking at s_skip for clues. */
1527 subseg_set (bss_section, 0);
1528 demand_empty_rest_of_line ();
1529 mapping_state (MAP_DATA);
1530 }
1531
1532 static void
1533 s_even (int ignore ATTRIBUTE_UNUSED)
1534 {
1535 /* Never make frag if expect extra pass. */
1536 if (!need_pass_2)
1537 frag_align (1, 0, 0);
1538
1539 record_alignment (now_seg, 1);
1540
1541 demand_empty_rest_of_line ();
1542 }
1543
1544 static void
1545 s_ltorg (int ignored ATTRIBUTE_UNUSED)
1546 {
1547 unsigned int entry;
1548 literal_pool * pool;
1549 char sym_name[20];
1550
1551 pool = find_literal_pool ();
1552 if (pool == NULL
1553 || pool->symbol == NULL
1554 || pool->next_free_entry == 0)
1555 return;
1556
1557 mapping_state (MAP_DATA);
1558
1559 /* Align pool as you have word accesses.
1560 Only make a frag if we have to. */
1561 if (!need_pass_2)
1562 frag_align (2, 0, 0);
1563
1564 record_alignment (now_seg, 2);
1565
1566 sprintf (sym_name, "$$lit_\002%x", pool->id);
1567
1568 symbol_locate (pool->symbol, sym_name, now_seg,
1569 (valueT) frag_now_fix (), frag_now);
1570 symbol_table_insert (pool->symbol);
1571
1572 ARM_SET_THUMB (pool->symbol, thumb_mode);
1573
1574 #if defined OBJ_COFF || defined OBJ_ELF
1575 ARM_SET_INTERWORK (pool->symbol, support_interwork);
1576 #endif
1577
1578 for (entry = 0; entry < pool->next_free_entry; entry ++)
1579 /* First output the expression in the instruction to the pool. */
1580 emit_expr (&(pool->literals[entry]), 4); /* .word */
1581
1582 /* Mark the pool as empty. */
1583 pool->next_free_entry = 0;
1584 pool->symbol = NULL;
1585 }
1586
1587 /* Same as s_align_ptwo but align 0 => align 2. */
1588
1589 static void
1590 s_align (int unused ATTRIBUTE_UNUSED)
1591 {
1592 int temp;
1593 long temp_fill;
1594 long max_alignment = 15;
1595
1596 temp = get_absolute_expression ();
1597 if (temp > max_alignment)
1598 as_bad (_("alignment too large: %d assumed"), temp = max_alignment);
1599 else if (temp < 0)
1600 {
1601 as_bad (_("alignment negative. 0 assumed."));
1602 temp = 0;
1603 }
1604
1605 if (*input_line_pointer == ',')
1606 {
1607 input_line_pointer++;
1608 temp_fill = get_absolute_expression ();
1609 }
1610 else
1611 temp_fill = 0;
1612
1613 if (!temp)
1614 temp = 2;
1615
1616 /* Only make a frag if we HAVE to. */
1617 if (temp && !need_pass_2)
1618 frag_align (temp, (int) temp_fill, 0);
1619 demand_empty_rest_of_line ();
1620
1621 record_alignment (now_seg, temp);
1622 }
1623
1624 static void
1625 s_force_thumb (int ignore ATTRIBUTE_UNUSED)
1626 {
1627 /* If we are not already in thumb mode go into it, EVEN if
1628 the target processor does not support thumb instructions.
1629 This is used by gcc/config/arm/lib1funcs.asm for example
1630 to compile interworking support functions even if the
1631 target processor should not support interworking. */
1632 if (! thumb_mode)
1633 {
1634 thumb_mode = 2;
1635
1636 record_alignment (now_seg, 1);
1637 }
1638
1639 demand_empty_rest_of_line ();
1640 }
1641
1642 static void
1643 s_thumb_func (int ignore ATTRIBUTE_UNUSED)
1644 {
1645 if (! thumb_mode)
1646 opcode_select (16);
1647
1648 /* The following label is the name/address of the start of a Thumb function.
1649 We need to know this for the interworking support. */
1650 label_is_thumb_function_name = TRUE;
1651
1652 demand_empty_rest_of_line ();
1653 }
1654
1655 /* Perform a .set directive, but also mark the alias as
1656 being a thumb function. */
1657
1658 static void
1659 s_thumb_set (int equiv)
1660 {
1661 /* XXX the following is a duplicate of the code for s_set() in read.c
1662 We cannot just call that code as we need to get at the symbol that
1663 is created. */
1664 char * name;
1665 char delim;
1666 char * end_name;
1667 symbolS * symbolP;
1668
1669 /* Especial apologies for the random logic:
1670 This just grew, and could be parsed much more simply!
1671 Dean - in haste. */
1672 name = input_line_pointer;
1673 delim = get_symbol_end ();
1674 end_name = input_line_pointer;
1675 *end_name = delim;
1676
1677 SKIP_WHITESPACE ();
1678
1679 if (*input_line_pointer != ',')
1680 {
1681 *end_name = 0;
1682 as_bad (_("expected comma after name \"%s\""), name);
1683 *end_name = delim;
1684 ignore_rest_of_line ();
1685 return;
1686 }
1687
1688 input_line_pointer++;
1689 *end_name = 0;
1690
1691 if (name[0] == '.' && name[1] == '\0')
1692 {
1693 /* XXX - this should not happen to .thumb_set. */
1694 abort ();
1695 }
1696
1697 if ((symbolP = symbol_find (name)) == NULL
1698 && (symbolP = md_undefined_symbol (name)) == NULL)
1699 {
1700 #ifndef NO_LISTING
1701 /* When doing symbol listings, play games with dummy fragments living
1702 outside the normal fragment chain to record the file and line info
1703 for this symbol. */
1704 if (listing & LISTING_SYMBOLS)
1705 {
1706 extern struct list_info_struct * listing_tail;
1707 fragS * dummy_frag = xmalloc (sizeof (fragS));
1708
1709 memset (dummy_frag, 0, sizeof (fragS));
1710 dummy_frag->fr_type = rs_fill;
1711 dummy_frag->line = listing_tail;
1712 symbolP = symbol_new (name, undefined_section, 0, dummy_frag);
1713 dummy_frag->fr_symbol = symbolP;
1714 }
1715 else
1716 #endif
1717 symbolP = symbol_new (name, undefined_section, 0, &zero_address_frag);
1718
1719 #ifdef OBJ_COFF
1720 /* "set" symbols are local unless otherwise specified. */
1721 SF_SET_LOCAL (symbolP);
1722 #endif /* OBJ_COFF */
1723 } /* Make a new symbol. */
1724
1725 symbol_table_insert (symbolP);
1726
1727 * end_name = delim;
1728
1729 if (equiv
1730 && S_IS_DEFINED (symbolP)
1731 && S_GET_SEGMENT (symbolP) != reg_section)
1732 as_bad (_("symbol `%s' already defined"), S_GET_NAME (symbolP));
1733
1734 pseudo_set (symbolP);
1735
1736 demand_empty_rest_of_line ();
1737
1738 /* XXX Now we come to the Thumb specific bit of code. */
1739
1740 THUMB_SET_FUNC (symbolP, 1);
1741 ARM_SET_THUMB (symbolP, 1);
1742 #if defined OBJ_ELF || defined OBJ_COFF
1743 ARM_SET_INTERWORK (symbolP, support_interwork);
1744 #endif
1745 }
1746
1747 static void
1748 s_arm (int ignore ATTRIBUTE_UNUSED)
1749 {
1750 opcode_select (32);
1751 demand_empty_rest_of_line ();
1752 }
1753
1754 static void
1755 s_thumb (int ignore ATTRIBUTE_UNUSED)
1756 {
1757 opcode_select (16);
1758 demand_empty_rest_of_line ();
1759 }
1760
1761 static void
1762 s_code (int unused ATTRIBUTE_UNUSED)
1763 {
1764 int temp;
1765
1766 temp = get_absolute_expression ();
1767 switch (temp)
1768 {
1769 case 16:
1770 case 32:
1771 opcode_select (temp);
1772 break;
1773
1774 default:
1775 as_bad (_("invalid operand to .code directive (%d) (expecting 16 or 32)"), temp);
1776 }
1777 }
1778
1779 static void
1780 end_of_line (char * str)
1781 {
1782 skip_whitespace (str);
1783
1784 if (*str != '\0' && !inst.error)
1785 inst.error = _("garbage following instruction");
1786 }
1787
1788 static int
1789 skip_past_comma (char ** str)
1790 {
1791 char * p = * str, c;
1792 int comma = 0;
1793
1794 while ((c = *p) == ' ' || c == ',')
1795 {
1796 p++;
1797 if (c == ',' && comma++)
1798 return FAIL;
1799 }
1800
1801 if (c == '\0')
1802 return FAIL;
1803
1804 *str = p;
1805 return comma ? SUCCESS : FAIL;
1806 }
1807
1808 /* Return TRUE if anything in the expression is a bignum. */
1809
1810 static int
1811 walk_no_bignums (symbolS * sp)
1812 {
1813 if (symbol_get_value_expression (sp)->X_op == O_big)
1814 return 1;
1815
1816 if (symbol_get_value_expression (sp)->X_add_symbol)
1817 {
1818 return (walk_no_bignums (symbol_get_value_expression (sp)->X_add_symbol)
1819 || (symbol_get_value_expression (sp)->X_op_symbol
1820 && walk_no_bignums (symbol_get_value_expression (sp)->X_op_symbol)));
1821 }
1822
1823 return 0;
1824 }
1825
1826 static int in_my_get_expression = 0;
1827
1828 static int
1829 my_get_expression (expressionS * ep, char ** str)
1830 {
1831 char * save_in;
1832 segT seg;
1833
1834 save_in = input_line_pointer;
1835 input_line_pointer = *str;
1836 in_my_get_expression = 1;
1837 seg = expression (ep);
1838 in_my_get_expression = 0;
1839
1840 if (ep->X_op == O_illegal)
1841 {
1842 /* We found a bad expression in md_operand(). */
1843 *str = input_line_pointer;
1844 input_line_pointer = save_in;
1845 return 1;
1846 }
1847
1848 #ifdef OBJ_AOUT
1849 if (seg != absolute_section
1850 && seg != text_section
1851 && seg != data_section
1852 && seg != bss_section
1853 && seg != undefined_section)
1854 {
1855 inst.error = _("bad_segment");
1856 *str = input_line_pointer;
1857 input_line_pointer = save_in;
1858 return 1;
1859 }
1860 #endif
1861
1862 /* Get rid of any bignums now, so that we don't generate an error for which
1863 we can't establish a line number later on. Big numbers are never valid
1864 in instructions, which is where this routine is always called. */
1865 if (ep->X_op == O_big
1866 || (ep->X_add_symbol
1867 && (walk_no_bignums (ep->X_add_symbol)
1868 || (ep->X_op_symbol
1869 && walk_no_bignums (ep->X_op_symbol)))))
1870 {
1871 inst.error = _("invalid constant");
1872 *str = input_line_pointer;
1873 input_line_pointer = save_in;
1874 return 1;
1875 }
1876
1877 *str = input_line_pointer;
1878 input_line_pointer = save_in;
1879 return 0;
1880 }
1881
1882 /* A standard register must be given at this point.
1883 SHIFT is the place to put it in inst.instruction.
1884 Restores input start point on error.
1885 Returns the reg#, or FAIL. */
1886
1887 static int
1888 reg_required_here (char ** str, int shift)
1889 {
1890 static char buff [128]; /* XXX */
1891 int reg;
1892 char * start = * str;
1893
1894 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_RN].htab)) != FAIL)
1895 {
1896 if (shift >= 0)
1897 inst.instruction |= reg << shift;
1898 return reg;
1899 }
1900
1901 /* Restore the start point, we may have got a reg of the wrong class. */
1902 *str = start;
1903
1904 /* In the few cases where we might be able to accept something else
1905 this error can be overridden. */
1906 sprintf (buff, _("register expected, not '%.100s'"), start);
1907 inst.error = buff;
1908
1909 return FAIL;
1910 }
1911
1912 /* A Intel Wireless MMX technology register
1913 must be given at this point.
1914 Shift is the place to put it in inst.instruction.
1915 Restores input start point on err.
1916 Returns the reg#, or FAIL. */
1917
1918 static int
1919 wreg_required_here (char ** str,
1920 int shift,
1921 enum wreg_type reg_type)
1922 {
1923 static char buff [128];
1924 int reg;
1925 char * start = *str;
1926
1927 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_IWMMXT].htab)) != FAIL)
1928 {
1929 if (wr_register (reg)
1930 && (reg_type == IWMMXT_REG_WR || reg_type == IWMMXT_REG_WR_OR_WC))
1931 {
1932 if (shift >= 0)
1933 inst.instruction |= (reg ^ WR_PREFIX) << shift;
1934 return reg;
1935 }
1936 else if (wc_register (reg)
1937 && (reg_type == IWMMXT_REG_WC || reg_type == IWMMXT_REG_WR_OR_WC))
1938 {
1939 if (shift >= 0)
1940 inst.instruction |= (reg ^ WC_PREFIX) << shift;
1941 return reg;
1942 }
1943 else if ((wcg_register (reg) && reg_type == IWMMXT_REG_WCG))
1944 {
1945 if (shift >= 0)
1946 inst.instruction |= ((reg ^ WC_PREFIX) - 8) << shift;
1947 return reg;
1948 }
1949 }
1950
1951 /* Restore the start point, we may have got a reg of the wrong class. */
1952 *str = start;
1953
1954 /* In the few cases where we might be able to accept
1955 something else this error can be overridden. */
1956 sprintf (buff, _("Intel Wireless MMX technology register expected, not '%.100s'"), start);
1957 inst.error = buff;
1958
1959 return FAIL;
1960 }
1961
1962 static const struct asm_psr *
1963 arm_psr_parse (char ** ccp)
1964 {
1965 char * start = * ccp;
1966 char c;
1967 char * p;
1968 const struct asm_psr * psr;
1969
1970 p = start;
1971
1972 /* Skip to the end of the next word in the input stream. */
1973 do
1974 {
1975 c = *p++;
1976 }
1977 while (ISALPHA (c) || c == '_');
1978
1979 /* Terminate the word. */
1980 *--p = 0;
1981
1982 /* CPSR's and SPSR's can now be lowercase. This is just a convenience
1983 feature for ease of use and backwards compatibility. */
1984 if (!strncmp (start, "cpsr", 4))
1985 strncpy (start, "CPSR", 4);
1986 else if (!strncmp (start, "spsr", 4))
1987 strncpy (start, "SPSR", 4);
1988
1989 /* Now locate the word in the psr hash table. */
1990 psr = (const struct asm_psr *) hash_find (arm_psr_hsh, start);
1991
1992 /* Restore the input stream. */
1993 *p = c;
1994
1995 /* If we found a valid match, advance the
1996 stream pointer past the end of the word. */
1997 *ccp = p;
1998
1999 return psr;
2000 }
2001
2002 /* Parse the input looking for a PSR flag. */
2003
2004 static int
2005 psr_required_here (char ** str)
2006 {
2007 char * start = * str;
2008 const struct asm_psr * psr;
2009
2010 psr = arm_psr_parse (str);
2011
2012 if (psr)
2013 {
2014 /* If this is the SPSR that is being modified, set the R bit. */
2015 if (! psr->cpsr)
2016 inst.instruction |= SPSR_BIT;
2017
2018 /* Set the psr flags in the MSR instruction. */
2019 inst.instruction |= psr->field << PSR_SHIFT;
2020
2021 return SUCCESS;
2022 }
2023
2024 /* In the few cases where we might be able to accept
2025 something else this error can be overridden. */
2026 inst.error = _("flag for {c}psr instruction expected");
2027
2028 /* Restore the start point. */
2029 *str = start;
2030 return FAIL;
2031 }
2032
2033 static int
2034 co_proc_number (char ** str)
2035 {
2036 int processor, pchar;
2037 char *start;
2038
2039 skip_whitespace (*str);
2040 start = *str;
2041
2042 /* The data sheet seems to imply that just a number on its own is valid
2043 here, but the RISC iX assembler seems to accept a prefix 'p'. We will
2044 accept either. */
2045 if ((processor = arm_reg_parse (str, all_reg_maps[REG_TYPE_CP].htab))
2046 == FAIL)
2047 {
2048 *str = start;
2049
2050 pchar = *(*str)++;
2051 if (pchar >= '0' && pchar <= '9')
2052 {
2053 processor = pchar - '0';
2054 if (**str >= '0' && **str <= '9')
2055 {
2056 processor = processor * 10 + *(*str)++ - '0';
2057 if (processor > 15)
2058 {
2059 inst.error = _("illegal co-processor number");
2060 return FAIL;
2061 }
2062 }
2063 }
2064 else
2065 {
2066 inst.error = all_reg_maps[REG_TYPE_CP].expected;
2067 return FAIL;
2068 }
2069 }
2070
2071 inst.instruction |= processor << 8;
2072 return SUCCESS;
2073 }
2074
2075 static int
2076 cp_opc_expr (char ** str, int where, int length)
2077 {
2078 expressionS expr;
2079
2080 skip_whitespace (* str);
2081
2082 memset (&expr, '\0', sizeof (expr));
2083
2084 if (my_get_expression (&expr, str))
2085 return FAIL;
2086 if (expr.X_op != O_constant)
2087 {
2088 inst.error = _("bad or missing expression");
2089 return FAIL;
2090 }
2091
2092 if ((expr.X_add_number & ((1 << length) - 1)) != expr.X_add_number)
2093 {
2094 inst.error = _("immediate co-processor expression too large");
2095 return FAIL;
2096 }
2097
2098 inst.instruction |= expr.X_add_number << where;
2099 return SUCCESS;
2100 }
2101
2102 static int
2103 cp_reg_required_here (char ** str, int where)
2104 {
2105 int reg;
2106 char * start = *str;
2107
2108 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_CN].htab)) != FAIL)
2109 {
2110 inst.instruction |= reg << where;
2111 return reg;
2112 }
2113
2114 /* In the few cases where we might be able to accept something else
2115 this error can be overridden. */
2116 inst.error = all_reg_maps[REG_TYPE_CN].expected;
2117
2118 /* Restore the start point. */
2119 *str = start;
2120 return FAIL;
2121 }
2122
2123 static int
2124 fp_reg_required_here (char ** str, int where)
2125 {
2126 int reg;
2127 char * start = * str;
2128
2129 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_FN].htab)) != FAIL)
2130 {
2131 inst.instruction |= reg << where;
2132 return reg;
2133 }
2134
2135 /* In the few cases where we might be able to accept something else
2136 this error can be overridden. */
2137 inst.error = all_reg_maps[REG_TYPE_FN].expected;
2138
2139 /* Restore the start point. */
2140 *str = start;
2141 return FAIL;
2142 }
2143
2144 static int
2145 cp_address_offset (char ** str)
2146 {
2147 int offset;
2148
2149 skip_whitespace (* str);
2150
2151 if (! is_immediate_prefix (**str))
2152 {
2153 inst.error = _("immediate expression expected");
2154 return FAIL;
2155 }
2156
2157 (*str)++;
2158
2159 if (my_get_expression (& inst.reloc.exp, str))
2160 return FAIL;
2161
2162 if (inst.reloc.exp.X_op == O_constant)
2163 {
2164 offset = inst.reloc.exp.X_add_number;
2165
2166 if (offset & 3)
2167 {
2168 inst.error = _("co-processor address must be word aligned");
2169 return FAIL;
2170 }
2171
2172 if (offset > 1023 || offset < -1023)
2173 {
2174 inst.error = _("offset too large");
2175 return FAIL;
2176 }
2177
2178 if (offset >= 0)
2179 inst.instruction |= INDEX_UP;
2180 else
2181 offset = -offset;
2182
2183 inst.instruction |= offset >> 2;
2184 }
2185 else
2186 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
2187
2188 return SUCCESS;
2189 }
2190
2191 static int
2192 cp_address_required_here (char ** str, int wb_ok)
2193 {
2194 char * p = * str;
2195 int pre_inc = 0;
2196 int write_back = 0;
2197
2198 if (*p == '[')
2199 {
2200 int reg;
2201
2202 p++;
2203 skip_whitespace (p);
2204
2205 if ((reg = reg_required_here (& p, 16)) == FAIL)
2206 return FAIL;
2207
2208 skip_whitespace (p);
2209
2210 if (*p == ']')
2211 {
2212 p++;
2213
2214 skip_whitespace (p);
2215
2216 if (*p == '\0')
2217 {
2218 /* As an extension to the official ARM syntax we allow:
2219 [Rn]
2220 as a short hand for:
2221 [Rn,#0] */
2222 inst.instruction |= PRE_INDEX | INDEX_UP;
2223 *str = p;
2224 return SUCCESS;
2225 }
2226
2227 if (skip_past_comma (& p) == FAIL)
2228 {
2229 inst.error = _("comma expected after closing square bracket");
2230 return FAIL;
2231 }
2232
2233 skip_whitespace (p);
2234
2235 if (*p == '#')
2236 {
2237 if (wb_ok)
2238 {
2239 /* [Rn], #expr */
2240 write_back = WRITE_BACK;
2241
2242 if (reg == REG_PC)
2243 {
2244 inst.error = _("pc may not be used in post-increment");
2245 return FAIL;
2246 }
2247
2248 if (cp_address_offset (& p) == FAIL)
2249 return FAIL;
2250 }
2251 else
2252 pre_inc = PRE_INDEX | INDEX_UP;
2253 }
2254 else if (*p == '{')
2255 {
2256 int option;
2257
2258 /* [Rn], {<expr>} */
2259 p++;
2260
2261 skip_whitespace (p);
2262
2263 if (my_get_expression (& inst.reloc.exp, & p))
2264 return FAIL;
2265
2266 if (inst.reloc.exp.X_op == O_constant)
2267 {
2268 option = inst.reloc.exp.X_add_number;
2269
2270 if (option > 255 || option < 0)
2271 {
2272 inst.error = _("'option' field too large");
2273 return FAIL;
2274 }
2275
2276 skip_whitespace (p);
2277
2278 if (*p != '}')
2279 {
2280 inst.error = _("'}' expected at end of 'option' field");
2281 return FAIL;
2282 }
2283 else
2284 {
2285 p++;
2286 inst.instruction |= option;
2287 inst.instruction |= INDEX_UP;
2288 }
2289 }
2290 else
2291 {
2292 inst.error = _("non-constant expressions for 'option' field not supported");
2293 return FAIL;
2294 }
2295 }
2296 else
2297 {
2298 inst.error = _("# or { expected after comma");
2299 return FAIL;
2300 }
2301 }
2302 else
2303 {
2304 /* '['Rn, #expr']'[!] */
2305
2306 if (skip_past_comma (& p) == FAIL)
2307 {
2308 inst.error = _("pre-indexed expression expected");
2309 return FAIL;
2310 }
2311
2312 pre_inc = PRE_INDEX;
2313
2314 if (cp_address_offset (& p) == FAIL)
2315 return FAIL;
2316
2317 skip_whitespace (p);
2318
2319 if (*p++ != ']')
2320 {
2321 inst.error = _("missing ]");
2322 return FAIL;
2323 }
2324
2325 skip_whitespace (p);
2326
2327 if (wb_ok && *p == '!')
2328 {
2329 if (reg == REG_PC)
2330 {
2331 inst.error = _("pc may not be used with write-back");
2332 return FAIL;
2333 }
2334
2335 p++;
2336 write_back = WRITE_BACK;
2337 }
2338 }
2339 }
2340 else
2341 {
2342 if (my_get_expression (&inst.reloc.exp, &p))
2343 return FAIL;
2344
2345 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
2346 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
2347 inst.reloc.pc_rel = 1;
2348 inst.instruction |= (REG_PC << 16);
2349 pre_inc = PRE_INDEX;
2350 }
2351
2352 inst.instruction |= write_back | pre_inc;
2353 *str = p;
2354 return SUCCESS;
2355 }
2356
2357 static int
2358 cp_byte_address_offset (char ** str)
2359 {
2360 int offset;
2361
2362 skip_whitespace (* str);
2363
2364 if (! is_immediate_prefix (**str))
2365 {
2366 inst.error = _("immediate expression expected");
2367 return FAIL;
2368 }
2369
2370 (*str)++;
2371
2372 if (my_get_expression (& inst.reloc.exp, str))
2373 return FAIL;
2374
2375 if (inst.reloc.exp.X_op == O_constant)
2376 {
2377 offset = inst.reloc.exp.X_add_number;
2378
2379 if (offset > 255 || offset < -255)
2380 {
2381 inst.error = _("offset too large");
2382 return FAIL;
2383 }
2384
2385 if (offset >= 0)
2386 inst.instruction |= INDEX_UP;
2387 else
2388 offset = -offset;
2389
2390 inst.instruction |= offset;
2391 }
2392 else
2393 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM_S2;
2394
2395 return SUCCESS;
2396 }
2397
2398 static int
2399 cp_byte_address_required_here (char ** str)
2400 {
2401 char * p = * str;
2402 int pre_inc = 0;
2403 int write_back = 0;
2404
2405 if (*p == '[')
2406 {
2407 int reg;
2408
2409 p++;
2410 skip_whitespace (p);
2411
2412 if ((reg = reg_required_here (& p, 16)) == FAIL)
2413 return FAIL;
2414
2415 skip_whitespace (p);
2416
2417 if (*p == ']')
2418 {
2419 p++;
2420
2421 if (skip_past_comma (& p) == SUCCESS)
2422 {
2423 /* [Rn], #expr */
2424 write_back = WRITE_BACK;
2425
2426 if (reg == REG_PC)
2427 {
2428 inst.error = _("pc may not be used in post-increment");
2429 return FAIL;
2430 }
2431
2432 if (cp_byte_address_offset (& p) == FAIL)
2433 return FAIL;
2434 }
2435 else
2436 pre_inc = PRE_INDEX | INDEX_UP;
2437 }
2438 else
2439 {
2440 /* '['Rn, #expr']'[!] */
2441
2442 if (skip_past_comma (& p) == FAIL)
2443 {
2444 inst.error = _("pre-indexed expression expected");
2445 return FAIL;
2446 }
2447
2448 pre_inc = PRE_INDEX;
2449
2450 if (cp_byte_address_offset (& p) == FAIL)
2451 return FAIL;
2452
2453 skip_whitespace (p);
2454
2455 if (*p++ != ']')
2456 {
2457 inst.error = _("missing ]");
2458 return FAIL;
2459 }
2460
2461 skip_whitespace (p);
2462
2463 if (*p == '!')
2464 {
2465 if (reg == REG_PC)
2466 {
2467 inst.error = _("pc may not be used with write-back");
2468 return FAIL;
2469 }
2470
2471 p++;
2472 write_back = WRITE_BACK;
2473 }
2474 }
2475 }
2476 else
2477 {
2478 if (my_get_expression (&inst.reloc.exp, &p))
2479 return FAIL;
2480
2481 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM_S2;
2482 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
2483 inst.reloc.pc_rel = 1;
2484 inst.instruction |= (REG_PC << 16);
2485 pre_inc = PRE_INDEX;
2486 }
2487
2488 inst.instruction |= write_back | pre_inc;
2489 *str = p;
2490 return SUCCESS;
2491 }
2492
2493 static void
2494 do_nop (char * str)
2495 {
2496 skip_whitespace (str);
2497 if (*str == '{')
2498 {
2499 str++;
2500
2501 if (my_get_expression (&inst.reloc.exp, &str))
2502 inst.reloc.exp.X_op = O_illegal;
2503 else
2504 {
2505 skip_whitespace (str);
2506 if (*str == '}')
2507 str++;
2508 else
2509 inst.reloc.exp.X_op = O_illegal;
2510 }
2511
2512 if (inst.reloc.exp.X_op != O_constant
2513 || inst.reloc.exp.X_add_number > 255
2514 || inst.reloc.exp.X_add_number < 0)
2515 {
2516 inst.error = _("Invalid NOP hint");
2517 return;
2518 }
2519
2520 /* Arcitectural NOP hints are CPSR sets with no bits selected. */
2521 inst.instruction &= 0xf0000000;
2522 inst.instruction |= 0x0320f000 + inst.reloc.exp.X_add_number;
2523 }
2524
2525 end_of_line (str);
2526 }
2527
2528 static void
2529 do_empty (char * str)
2530 {
2531 /* Do nothing really. */
2532 end_of_line (str);
2533 }
2534
2535 static void
2536 do_mrs (char * str)
2537 {
2538 int skip = 0;
2539
2540 /* Only one syntax. */
2541 skip_whitespace (str);
2542
2543 if (reg_required_here (&str, 12) == FAIL)
2544 {
2545 inst.error = BAD_ARGS;
2546 return;
2547 }
2548
2549 if (skip_past_comma (&str) == FAIL)
2550 {
2551 inst.error = _("comma expected after register name");
2552 return;
2553 }
2554
2555 skip_whitespace (str);
2556
2557 if ( streq (str, "CPSR")
2558 || streq (str, "SPSR")
2559 /* Lower case versions for backwards compatibility. */
2560 || streq (str, "cpsr")
2561 || streq (str, "spsr"))
2562 skip = 4;
2563
2564 /* This is for backwards compatibility with older toolchains. */
2565 else if ( streq (str, "cpsr_all")
2566 || streq (str, "spsr_all"))
2567 skip = 8;
2568 else
2569 {
2570 inst.error = _("CPSR or SPSR expected");
2571 return;
2572 }
2573
2574 if (* str == 's' || * str == 'S')
2575 inst.instruction |= SPSR_BIT;
2576 str += skip;
2577
2578 end_of_line (str);
2579 }
2580
2581 /* Two possible forms:
2582 "{C|S}PSR_<field>, Rm",
2583 "{C|S}PSR_f, #expression". */
2584
2585 static void
2586 do_msr (char * str)
2587 {
2588 skip_whitespace (str);
2589
2590 if (psr_required_here (& str) == FAIL)
2591 return;
2592
2593 if (skip_past_comma (& str) == FAIL)
2594 {
2595 inst.error = _("comma missing after psr flags");
2596 return;
2597 }
2598
2599 skip_whitespace (str);
2600
2601 if (reg_required_here (& str, 0) != FAIL)
2602 {
2603 inst.error = NULL;
2604 end_of_line (str);
2605 return;
2606 }
2607
2608 if (! is_immediate_prefix (* str))
2609 {
2610 inst.error =
2611 _("only a register or immediate value can follow a psr flag");
2612 return;
2613 }
2614
2615 str ++;
2616 inst.error = NULL;
2617
2618 if (my_get_expression (& inst.reloc.exp, & str))
2619 {
2620 inst.error =
2621 _("only a register or immediate value can follow a psr flag");
2622 return;
2623 }
2624
2625 inst.instruction |= INST_IMMEDIATE;
2626
2627 if (inst.reloc.exp.X_add_symbol)
2628 {
2629 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
2630 inst.reloc.pc_rel = 0;
2631 }
2632 else
2633 {
2634 unsigned value = validate_immediate (inst.reloc.exp.X_add_number);
2635
2636 if (value == (unsigned) FAIL)
2637 {
2638 inst.error = _("invalid constant");
2639 return;
2640 }
2641
2642 inst.instruction |= value;
2643 }
2644
2645 inst.error = NULL;
2646 end_of_line (str);
2647 }
2648
2649 /* Long Multiply Parser
2650 UMULL RdLo, RdHi, Rm, Rs
2651 SMULL RdLo, RdHi, Rm, Rs
2652 UMLAL RdLo, RdHi, Rm, Rs
2653 SMLAL RdLo, RdHi, Rm, Rs. */
2654
2655 static void
2656 do_mull (char * str)
2657 {
2658 int rdlo, rdhi, rm, rs;
2659
2660 /* Only one format "rdlo, rdhi, rm, rs". */
2661 skip_whitespace (str);
2662
2663 if ((rdlo = reg_required_here (&str, 12)) == FAIL)
2664 {
2665 inst.error = BAD_ARGS;
2666 return;
2667 }
2668
2669 if (skip_past_comma (&str) == FAIL
2670 || (rdhi = reg_required_here (&str, 16)) == FAIL)
2671 {
2672 inst.error = BAD_ARGS;
2673 return;
2674 }
2675
2676 if (skip_past_comma (&str) == FAIL
2677 || (rm = reg_required_here (&str, 0)) == FAIL)
2678 {
2679 inst.error = BAD_ARGS;
2680 return;
2681 }
2682
2683 /* rdhi, rdlo and rm must all be different. */
2684 if (rdlo == rdhi || rdlo == rm || rdhi == rm)
2685 as_tsktsk (_("rdhi, rdlo and rm must all be different"));
2686
2687 if (skip_past_comma (&str) == FAIL
2688 || (rs = reg_required_here (&str, 8)) == FAIL)
2689 {
2690 inst.error = BAD_ARGS;
2691 return;
2692 }
2693
2694 if (rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC)
2695 {
2696 inst.error = BAD_PC;
2697 return;
2698 }
2699
2700 end_of_line (str);
2701 }
2702
2703 static void
2704 do_mul (char * str)
2705 {
2706 int rd, rm;
2707
2708 /* Only one format "rd, rm, rs". */
2709 skip_whitespace (str);
2710
2711 if ((rd = reg_required_here (&str, 16)) == FAIL)
2712 {
2713 inst.error = BAD_ARGS;
2714 return;
2715 }
2716
2717 if (rd == REG_PC)
2718 {
2719 inst.error = BAD_PC;
2720 return;
2721 }
2722
2723 if (skip_past_comma (&str) == FAIL
2724 || (rm = reg_required_here (&str, 0)) == FAIL)
2725 {
2726 inst.error = BAD_ARGS;
2727 return;
2728 }
2729
2730 if (rm == REG_PC)
2731 {
2732 inst.error = BAD_PC;
2733 return;
2734 }
2735
2736 if (rm == rd)
2737 as_tsktsk (_("rd and rm should be different in mul"));
2738
2739 if (skip_past_comma (&str) == FAIL
2740 || (rm = reg_required_here (&str, 8)) == FAIL)
2741 {
2742 inst.error = BAD_ARGS;
2743 return;
2744 }
2745
2746 if (rm == REG_PC)
2747 {
2748 inst.error = BAD_PC;
2749 return;
2750 }
2751
2752 end_of_line (str);
2753 }
2754
2755 static void
2756 do_mlas (char * str, bfd_boolean is_mls)
2757 {
2758 int rd, rm;
2759
2760 /* Only one format "rd, rm, rs, rn". */
2761 skip_whitespace (str);
2762
2763 if ((rd = reg_required_here (&str, 16)) == FAIL)
2764 {
2765 inst.error = BAD_ARGS;
2766 return;
2767 }
2768
2769 if (rd == REG_PC)
2770 {
2771 inst.error = BAD_PC;
2772 return;
2773 }
2774
2775 if (skip_past_comma (&str) == FAIL
2776 || (rm = reg_required_here (&str, 0)) == FAIL)
2777 {
2778 inst.error = BAD_ARGS;
2779 return;
2780 }
2781
2782 if (rm == REG_PC)
2783 {
2784 inst.error = BAD_PC;
2785 return;
2786 }
2787
2788 /* This restriction does not apply to mls (nor to mla in v6, but
2789 that's hard to detect at present). */
2790 if (rm == rd && !is_mls)
2791 as_tsktsk (_("rd and rm should be different in mla"));
2792
2793 if (skip_past_comma (&str) == FAIL
2794 || (rd = reg_required_here (&str, 8)) == FAIL
2795 || skip_past_comma (&str) == FAIL
2796 || (rm = reg_required_here (&str, 12)) == FAIL)
2797 {
2798 inst.error = BAD_ARGS;
2799 return;
2800 }
2801
2802 if (rd == REG_PC || rm == REG_PC)
2803 {
2804 inst.error = BAD_PC;
2805 return;
2806 }
2807
2808 end_of_line (str);
2809 }
2810
2811 static void
2812 do_mla (char *str)
2813 {
2814 do_mlas (str, FALSE);
2815 }
2816
2817 static void
2818 do_mls (char *str)
2819 {
2820 do_mlas (str, TRUE);
2821 }
2822
2823 /* Expects *str -> the characters "acc0", possibly with leading blanks.
2824 Advances *str to the next non-alphanumeric.
2825 Returns 0, or else FAIL (in which case sets inst.error).
2826
2827 (In a future XScale, there may be accumulators other than zero.
2828 At that time this routine and its callers can be upgraded to suit.) */
2829
2830 static int
2831 accum0_required_here (char ** str)
2832 {
2833 static char buff [128]; /* Note the address is taken. Hence, static. */
2834 char * p = * str;
2835 char c;
2836 int result = 0; /* The accum number. */
2837
2838 skip_whitespace (p);
2839
2840 *str = p; /* Advance caller's string pointer too. */
2841 c = *p++;
2842 while (ISALNUM (c))
2843 c = *p++;
2844
2845 *--p = 0; /* Aap nul into input buffer at non-alnum. */
2846
2847 if (! ( streq (*str, "acc0") || streq (*str, "ACC0")))
2848 {
2849 sprintf (buff, _("acc0 expected, not '%.100s'"), *str);
2850 inst.error = buff;
2851 result = FAIL;
2852 }
2853
2854 *p = c; /* Unzap. */
2855 *str = p; /* Caller's string pointer to after match. */
2856 return result;
2857 }
2858
2859 static int
2860 ldst_extend_v4 (char ** str)
2861 {
2862 int add = INDEX_UP;
2863
2864 switch (**str)
2865 {
2866 case '#':
2867 case '$':
2868 (*str)++;
2869 if (my_get_expression (& inst.reloc.exp, str))
2870 return FAIL;
2871
2872 if (inst.reloc.exp.X_op == O_constant)
2873 {
2874 int value = inst.reloc.exp.X_add_number;
2875
2876 if (value < -255 || value > 255)
2877 {
2878 inst.error = _("address offset too large");
2879 return FAIL;
2880 }
2881
2882 if (value < 0)
2883 {
2884 value = -value;
2885 add = 0;
2886 }
2887
2888 /* Halfword and signextension instructions have the
2889 immediate value split across bits 11..8 and bits 3..0. */
2890 inst.instruction |= (add | HWOFFSET_IMM
2891 | ((value >> 4) << 8) | (value & 0xF));
2892 }
2893 else
2894 {
2895 inst.instruction |= HWOFFSET_IMM;
2896 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
2897 inst.reloc.pc_rel = 0;
2898 }
2899 return SUCCESS;
2900
2901 case '-':
2902 add = 0;
2903 /* Fall through. */
2904
2905 case '+':
2906 (*str)++;
2907 /* Fall through. */
2908
2909 default:
2910 if (reg_required_here (str, 0) == FAIL)
2911 return FAIL;
2912
2913 inst.instruction |= add;
2914 return SUCCESS;
2915 }
2916 }
2917
2918 /* Expects **str -> after a comma. May be leading blanks.
2919 Advances *str, recognizing a load mode, and setting inst.instruction.
2920 Returns rn, or else FAIL (in which case may set inst.error
2921 and not advance str)
2922
2923 Note: doesn't know Rd, so no err checks that require such knowledge. */
2924
2925 static int
2926 ld_mode_required_here (char ** string)
2927 {
2928 char * str = * string;
2929 int rn;
2930 int pre_inc = 0;
2931
2932 skip_whitespace (str);
2933
2934 if (* str == '[')
2935 {
2936 str++;
2937
2938 skip_whitespace (str);
2939
2940 if ((rn = reg_required_here (& str, 16)) == FAIL)
2941 return FAIL;
2942
2943 skip_whitespace (str);
2944
2945 if (* str == ']')
2946 {
2947 str ++;
2948
2949 if (skip_past_comma (& str) == SUCCESS)
2950 {
2951 /* [Rn],... (post inc) */
2952 if (ldst_extend_v4 (&str) == FAIL)
2953 return FAIL;
2954 }
2955 else /* [Rn] */
2956 {
2957 skip_whitespace (str);
2958
2959 if (* str == '!')
2960 {
2961 str ++;
2962 inst.instruction |= WRITE_BACK;
2963 }
2964
2965 inst.instruction |= INDEX_UP | HWOFFSET_IMM;
2966 pre_inc = 1;
2967 }
2968 }
2969 else /* [Rn,...] */
2970 {
2971 if (skip_past_comma (& str) == FAIL)
2972 {
2973 inst.error = _("pre-indexed expression expected");
2974 return FAIL;
2975 }
2976
2977 pre_inc = 1;
2978
2979 if (ldst_extend_v4 (&str) == FAIL)
2980 return FAIL;
2981
2982 skip_whitespace (str);
2983
2984 if (* str ++ != ']')
2985 {
2986 inst.error = _("missing ]");
2987 return FAIL;
2988 }
2989
2990 skip_whitespace (str);
2991
2992 if (* str == '!')
2993 {
2994 str ++;
2995 inst.instruction |= WRITE_BACK;
2996 }
2997 }
2998 }
2999 else if (* str == '=') /* ldr's "r,=label" syntax */
3000 /* We should never reach here, because <text> = <expression> is
3001 caught gas/read.c read_a_source_file() as a .set operation. */
3002 return FAIL;
3003 else /* PC +- 8 bit immediate offset. */
3004 {
3005 if (my_get_expression (& inst.reloc.exp, & str))
3006 return FAIL;
3007
3008 inst.instruction |= HWOFFSET_IMM; /* The I bit. */
3009 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
3010 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
3011 inst.reloc.pc_rel = 1;
3012 inst.instruction |= (REG_PC << 16);
3013
3014 rn = REG_PC;
3015 pre_inc = 1;
3016 }
3017
3018 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
3019 * string = str;
3020
3021 return rn;
3022 }
3023
3024 /* ARM V5E (El Segundo) signed-multiply-accumulate (argument parse)
3025 SMLAxy{cond} Rd,Rm,Rs,Rn
3026 SMLAWy{cond} Rd,Rm,Rs,Rn
3027 Error if any register is R15. */
3028
3029 static void
3030 do_smla (char * str)
3031 {
3032 int rd, rm, rs, rn;
3033
3034 skip_whitespace (str);
3035
3036 if ((rd = reg_required_here (& str, 16)) == FAIL
3037 || skip_past_comma (& str) == FAIL
3038 || (rm = reg_required_here (& str, 0)) == FAIL
3039 || skip_past_comma (& str) == FAIL
3040 || (rs = reg_required_here (& str, 8)) == FAIL
3041 || skip_past_comma (& str) == FAIL
3042 || (rn = reg_required_here (& str, 12)) == FAIL)
3043 inst.error = BAD_ARGS;
3044
3045 else if (rd == REG_PC || rm == REG_PC || rs == REG_PC || rn == REG_PC)
3046 inst.error = BAD_PC;
3047
3048 else
3049 end_of_line (str);
3050 }
3051
3052 /* ARM V5E (El Segundo) signed-multiply-accumulate-long (argument parse)
3053 SMLALxy{cond} Rdlo,Rdhi,Rm,Rs
3054 Error if any register is R15.
3055 Warning if Rdlo == Rdhi. */
3056
3057 static void
3058 do_smlal (char * str)
3059 {
3060 int rdlo, rdhi, rm, rs;
3061
3062 skip_whitespace (str);
3063
3064 if ((rdlo = reg_required_here (& str, 12)) == FAIL
3065 || skip_past_comma (& str) == FAIL
3066 || (rdhi = reg_required_here (& str, 16)) == FAIL
3067 || skip_past_comma (& str) == FAIL
3068 || (rm = reg_required_here (& str, 0)) == FAIL
3069 || skip_past_comma (& str) == FAIL
3070 || (rs = reg_required_here (& str, 8)) == FAIL)
3071 {
3072 inst.error = BAD_ARGS;
3073 return;
3074 }
3075
3076 if (rdlo == REG_PC || rdhi == REG_PC || rm == REG_PC || rs == REG_PC)
3077 {
3078 inst.error = BAD_PC;
3079 return;
3080 }
3081
3082 if (rdlo == rdhi)
3083 as_tsktsk (_("rdhi and rdlo must be different"));
3084
3085 end_of_line (str);
3086 }
3087
3088 /* ARM V5E (El Segundo) signed-multiply (argument parse)
3089 SMULxy{cond} Rd,Rm,Rs
3090 Error if any register is R15. */
3091
3092 static void
3093 do_smul (char * str)
3094 {
3095 int rd, rm, rs;
3096
3097 skip_whitespace (str);
3098
3099 if ((rd = reg_required_here (& str, 16)) == FAIL
3100 || skip_past_comma (& str) == FAIL
3101 || (rm = reg_required_here (& str, 0)) == FAIL
3102 || skip_past_comma (& str) == FAIL
3103 || (rs = reg_required_here (& str, 8)) == FAIL)
3104 inst.error = BAD_ARGS;
3105
3106 else if (rd == REG_PC || rm == REG_PC || rs == REG_PC)
3107 inst.error = BAD_PC;
3108
3109 else
3110 end_of_line (str);
3111 }
3112
3113 /* ARM V5E (El Segundo) saturating-add/subtract (argument parse)
3114 Q[D]{ADD,SUB}{cond} Rd,Rm,Rn
3115 Error if any register is R15. */
3116
3117 static void
3118 do_qadd (char * str)
3119 {
3120 int rd, rm, rn;
3121
3122 skip_whitespace (str);
3123
3124 if ((rd = reg_required_here (& str, 12)) == FAIL
3125 || skip_past_comma (& str) == FAIL
3126 || (rm = reg_required_here (& str, 0)) == FAIL
3127 || skip_past_comma (& str) == FAIL
3128 || (rn = reg_required_here (& str, 16)) == FAIL)
3129 inst.error = BAD_ARGS;
3130
3131 else if (rd == REG_PC || rm == REG_PC || rn == REG_PC)
3132 inst.error = BAD_PC;
3133
3134 else
3135 end_of_line (str);
3136 }
3137
3138 /* ARM V5E (el Segundo)
3139 MCRRcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
3140 MRRCcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
3141
3142 These are equivalent to the XScale instructions MAR and MRA,
3143 respectively, when coproc == 0, opcode == 0, and CRm == 0.
3144
3145 Result unpredicatable if Rd or Rn is R15. */
3146
3147 static void
3148 do_co_reg2c (char * str)
3149 {
3150 int rd, rn;
3151
3152 skip_whitespace (str);
3153
3154 if (co_proc_number (& str) == FAIL)
3155 {
3156 if (!inst.error)
3157 inst.error = BAD_ARGS;
3158 return;
3159 }
3160
3161 if (skip_past_comma (& str) == FAIL
3162 || cp_opc_expr (& str, 4, 4) == FAIL)
3163 {
3164 if (!inst.error)
3165 inst.error = BAD_ARGS;
3166 return;
3167 }
3168
3169 if (skip_past_comma (& str) == FAIL
3170 || (rd = reg_required_here (& str, 12)) == FAIL)
3171 {
3172 if (!inst.error)
3173 inst.error = BAD_ARGS;
3174 return;
3175 }
3176
3177 if (skip_past_comma (& str) == FAIL
3178 || (rn = reg_required_here (& str, 16)) == FAIL)
3179 {
3180 if (!inst.error)
3181 inst.error = BAD_ARGS;
3182 return;
3183 }
3184
3185 /* Unpredictable result if rd or rn is R15. */
3186 if (rd == REG_PC || rn == REG_PC)
3187 as_tsktsk
3188 (_("Warning: instruction unpredictable when using r15"));
3189
3190 if (skip_past_comma (& str) == FAIL
3191 || cp_reg_required_here (& str, 0) == FAIL)
3192 {
3193 if (!inst.error)
3194 inst.error = BAD_ARGS;
3195 return;
3196 }
3197
3198 end_of_line (str);
3199 }
3200
3201 /* ARM V5 count-leading-zeroes instruction (argument parse)
3202 CLZ{<cond>} <Rd>, <Rm>
3203 Condition defaults to COND_ALWAYS.
3204 Error if Rd or Rm are R15. */
3205
3206 static void
3207 do_clz (char * str)
3208 {
3209 int rd, rm;
3210
3211 skip_whitespace (str);
3212
3213 if (((rd = reg_required_here (& str, 12)) == FAIL)
3214 || (skip_past_comma (& str) == FAIL)
3215 || ((rm = reg_required_here (& str, 0)) == FAIL))
3216 inst.error = BAD_ARGS;
3217
3218 else if (rd == REG_PC || rm == REG_PC )
3219 inst.error = BAD_PC;
3220
3221 else
3222 end_of_line (str);
3223 }
3224
3225 /* ARM V5 (argument parse)
3226 LDC2{L} <coproc>, <CRd>, <addressing mode>
3227 STC2{L} <coproc>, <CRd>, <addressing mode>
3228 Instruction is not conditional, and has 0xf in the condition field.
3229 Otherwise, it's the same as LDC/STC. */
3230
3231 static void
3232 do_lstc2 (char * str)
3233 {
3234 skip_whitespace (str);
3235
3236 if (co_proc_number (& str) == FAIL)
3237 {
3238 if (!inst.error)
3239 inst.error = BAD_ARGS;
3240 }
3241 else if (skip_past_comma (& str) == FAIL
3242 || cp_reg_required_here (& str, 12) == FAIL)
3243 {
3244 if (!inst.error)
3245 inst.error = BAD_ARGS;
3246 }
3247 else if (skip_past_comma (& str) == FAIL
3248 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
3249 {
3250 if (! inst.error)
3251 inst.error = BAD_ARGS;
3252 }
3253 else
3254 end_of_line (str);
3255 }
3256
3257 /* ARM V5 (argument parse)
3258 CDP2 <coproc>, <opcode_1>, <CRd>, <CRn>, <CRm>, <opcode_2>
3259 Instruction is not conditional, and has 0xf in the condition field.
3260 Otherwise, it's the same as CDP. */
3261
3262 static void
3263 do_cdp2 (char * str)
3264 {
3265 skip_whitespace (str);
3266
3267 if (co_proc_number (& str) == FAIL)
3268 {
3269 if (!inst.error)
3270 inst.error = BAD_ARGS;
3271 return;
3272 }
3273
3274 if (skip_past_comma (& str) == FAIL
3275 || cp_opc_expr (& str, 20,4) == FAIL)
3276 {
3277 if (!inst.error)
3278 inst.error = BAD_ARGS;
3279 return;
3280 }
3281
3282 if (skip_past_comma (& str) == FAIL
3283 || cp_reg_required_here (& str, 12) == FAIL)
3284 {
3285 if (!inst.error)
3286 inst.error = BAD_ARGS;
3287 return;
3288 }
3289
3290 if (skip_past_comma (& str) == FAIL
3291 || cp_reg_required_here (& str, 16) == FAIL)
3292 {
3293 if (!inst.error)
3294 inst.error = BAD_ARGS;
3295 return;
3296 }
3297
3298 if (skip_past_comma (& str) == FAIL
3299 || cp_reg_required_here (& str, 0) == FAIL)
3300 {
3301 if (!inst.error)
3302 inst.error = BAD_ARGS;
3303 return;
3304 }
3305
3306 if (skip_past_comma (& str) == SUCCESS)
3307 {
3308 if (cp_opc_expr (& str, 5, 3) == FAIL)
3309 {
3310 if (!inst.error)
3311 inst.error = BAD_ARGS;
3312 return;
3313 }
3314 }
3315
3316 end_of_line (str);
3317 }
3318
3319 /* ARM V5 (argument parse)
3320 MCR2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
3321 MRC2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
3322 Instruction is not conditional, and has 0xf in the condition field.
3323 Otherwise, it's the same as MCR/MRC. */
3324
3325 static void
3326 do_co_reg2 (char * str)
3327 {
3328 skip_whitespace (str);
3329
3330 if (co_proc_number (& str) == FAIL)
3331 {
3332 if (!inst.error)
3333 inst.error = BAD_ARGS;
3334 return;
3335 }
3336
3337 if (skip_past_comma (& str) == FAIL
3338 || cp_opc_expr (& str, 21, 3) == FAIL)
3339 {
3340 if (!inst.error)
3341 inst.error = BAD_ARGS;
3342 return;
3343 }
3344
3345 if (skip_past_comma (& str) == FAIL
3346 || reg_required_here (& str, 12) == FAIL)
3347 {
3348 if (!inst.error)
3349 inst.error = BAD_ARGS;
3350 return;
3351 }
3352
3353 if (skip_past_comma (& str) == FAIL
3354 || cp_reg_required_here (& str, 16) == FAIL)
3355 {
3356 if (!inst.error)
3357 inst.error = BAD_ARGS;
3358 return;
3359 }
3360
3361 if (skip_past_comma (& str) == FAIL
3362 || cp_reg_required_here (& str, 0) == FAIL)
3363 {
3364 if (!inst.error)
3365 inst.error = BAD_ARGS;
3366 return;
3367 }
3368
3369 if (skip_past_comma (& str) == SUCCESS)
3370 {
3371 if (cp_opc_expr (& str, 5, 3) == FAIL)
3372 {
3373 if (!inst.error)
3374 inst.error = BAD_ARGS;
3375 return;
3376 }
3377 }
3378
3379 end_of_line (str);
3380 }
3381
3382 static void
3383 do_bx (char * str)
3384 {
3385 int reg;
3386
3387 skip_whitespace (str);
3388
3389 if ((reg = reg_required_here (&str, 0)) == FAIL)
3390 {
3391 inst.error = BAD_ARGS;
3392 return;
3393 }
3394
3395 /* Note - it is not illegal to do a "bx pc". Useless, but not illegal. */
3396 if (reg == REG_PC)
3397 as_tsktsk (_("use of r15 in bx in ARM mode is not really useful"));
3398
3399 end_of_line (str);
3400 }
3401
3402 /* ARM v5TEJ. Jump to Jazelle code. */
3403
3404 static void
3405 do_bxj (char * str)
3406 {
3407 int reg;
3408
3409 skip_whitespace (str);
3410
3411 if ((reg = reg_required_here (&str, 0)) == FAIL)
3412 {
3413 inst.error = BAD_ARGS;
3414 return;
3415 }
3416
3417 /* Note - it is not illegal to do a "bxj pc". Useless, but not illegal. */
3418 if (reg == REG_PC)
3419 as_tsktsk (_("use of r15 in bxj is not really useful"));
3420
3421 end_of_line (str);
3422 }
3423
3424 /* ARM V6 umaal (argument parse). */
3425
3426 static void
3427 do_umaal (char * str)
3428 {
3429 int rdlo, rdhi, rm, rs;
3430
3431 skip_whitespace (str);
3432 if ((rdlo = reg_required_here (& str, 12)) == FAIL
3433 || skip_past_comma (& str) == FAIL
3434 || (rdhi = reg_required_here (& str, 16)) == FAIL
3435 || skip_past_comma (& str) == FAIL
3436 || (rm = reg_required_here (& str, 0)) == FAIL
3437 || skip_past_comma (& str) == FAIL
3438 || (rs = reg_required_here (& str, 8)) == FAIL)
3439 {
3440 inst.error = BAD_ARGS;
3441 return;
3442 }
3443
3444 if (rdlo == REG_PC || rdhi == REG_PC || rm == REG_PC || rs == REG_PC)
3445 {
3446 inst.error = BAD_PC;
3447 return;
3448 }
3449
3450 end_of_line (str);
3451 }
3452
3453 /* ARM V6 strex (argument parse). */
3454
3455 static void
3456 do_strex (char * str)
3457 {
3458 int rd, rm, rn;
3459
3460 /* Parse Rd, Rm,. */
3461 skip_whitespace (str);
3462 if ((rd = reg_required_here (& str, 12)) == FAIL
3463 || skip_past_comma (& str) == FAIL
3464 || (rm = reg_required_here (& str, 0)) == FAIL
3465 || skip_past_comma (& str) == FAIL)
3466 {
3467 inst.error = BAD_ARGS;
3468 return;
3469 }
3470 if (rd == REG_PC || rm == REG_PC)
3471 {
3472 inst.error = BAD_PC;
3473 return;
3474 }
3475 if (rd == rm)
3476 {
3477 inst.error = _("Rd equal to Rm or Rn yields unpredictable results");
3478 return;
3479 }
3480
3481 /* Skip past '['. */
3482 if ((strlen (str) >= 1)
3483 && strncmp (str, "[", 1) == 0)
3484 str += 1;
3485
3486 skip_whitespace (str);
3487
3488 /* Parse Rn. */
3489 if ((rn = reg_required_here (& str, 16)) == FAIL)
3490 {
3491 inst.error = BAD_ARGS;
3492 return;
3493 }
3494 else if (rn == REG_PC)
3495 {
3496 inst.error = BAD_PC;
3497 return;
3498 }
3499 if (rd == rn)
3500 {
3501 inst.error = _("Rd equal to Rm or Rn yields unpredictable results");
3502 return;
3503 }
3504 skip_whitespace (str);
3505
3506 /* Skip past ']'. */
3507 if ((strlen (str) >= 1)
3508 && strncmp (str, "]", 1) == 0)
3509 str += 1;
3510
3511 end_of_line (str);
3512 }
3513
3514 /* KIND indicates what kind of shifts are accepted. */
3515
3516 static int
3517 decode_shift (char ** str, int kind)
3518 {
3519 const struct asm_shift_name * shift;
3520 char * p;
3521 char c;
3522
3523 skip_whitespace (* str);
3524
3525 for (p = * str; ISALPHA (* p); p ++)
3526 ;
3527
3528 if (p == * str)
3529 {
3530 inst.error = _("shift expression expected");
3531 return FAIL;
3532 }
3533
3534 c = * p;
3535 * p = '\0';
3536 shift = (const struct asm_shift_name *) hash_find (arm_shift_hsh, * str);
3537 * p = c;
3538
3539 if (shift == NULL)
3540 {
3541 inst.error = _("shift expression expected");
3542 return FAIL;
3543 }
3544
3545 assert (shift->properties->index == shift_properties[shift->properties->index].index);
3546
3547 if (kind == SHIFT_LSL_OR_ASR_IMMEDIATE
3548 && shift->properties->index != SHIFT_LSL
3549 && shift->properties->index != SHIFT_ASR)
3550 {
3551 inst.error = _("'LSL' or 'ASR' required");
3552 return FAIL;
3553 }
3554 else if (kind == SHIFT_LSL_IMMEDIATE
3555 && shift->properties->index != SHIFT_LSL)
3556 {
3557 inst.error = _("'LSL' required");
3558 return FAIL;
3559 }
3560 else if (kind == SHIFT_ASR_IMMEDIATE
3561 && shift->properties->index != SHIFT_ASR)
3562 {
3563 inst.error = _("'ASR' required");
3564 return FAIL;
3565 }
3566
3567 if (shift->properties->index == SHIFT_RRX)
3568 {
3569 * str = p;
3570 inst.instruction |= shift->properties->bit_field;
3571 return SUCCESS;
3572 }
3573
3574 skip_whitespace (p);
3575
3576 if (kind == NO_SHIFT_RESTRICT && reg_required_here (& p, 8) != FAIL)
3577 {
3578 inst.instruction |= shift->properties->bit_field | SHIFT_BY_REG;
3579 * str = p;
3580 return SUCCESS;
3581 }
3582 else if (! is_immediate_prefix (* p))
3583 {
3584 inst.error = (NO_SHIFT_RESTRICT
3585 ? _("shift requires register or #expression")
3586 : _("shift requires #expression"));
3587 * str = p;
3588 return FAIL;
3589 }
3590
3591 inst.error = NULL;
3592 p ++;
3593
3594 if (my_get_expression (& inst.reloc.exp, & p))
3595 return FAIL;
3596
3597 /* Validate some simple #expressions. */
3598 if (inst.reloc.exp.X_op == O_constant)
3599 {
3600 unsigned num = inst.reloc.exp.X_add_number;
3601
3602 /* Reject operations greater than 32. */
3603 if (num > 32
3604 /* Reject a shift of 0 unless the mode allows it. */
3605 || (num == 0 && shift->properties->allows_0 == 0)
3606 /* Reject a shift of 32 unless the mode allows it. */
3607 || (num == 32 && shift->properties->allows_32 == 0)
3608 )
3609 {
3610 /* As a special case we allow a shift of zero for
3611 modes that do not support it to be recoded as an
3612 logical shift left of zero (ie nothing). We warn
3613 about this though. */
3614 if (num == 0)
3615 {
3616 as_warn (_("shift of 0 ignored."));
3617 shift = & shift_names[0];
3618 assert (shift->properties->index == SHIFT_LSL);
3619 }
3620 else
3621 {
3622 inst.error = _("invalid immediate shift");
3623 return FAIL;
3624 }
3625 }
3626
3627 /* Shifts of 32 are encoded as 0, for those shifts that
3628 support it. */
3629 if (num == 32)
3630 num = 0;
3631
3632 inst.instruction |= (num << 7) | shift->properties->bit_field;
3633 }
3634 else
3635 {
3636 inst.reloc.type = BFD_RELOC_ARM_SHIFT_IMM;
3637 inst.reloc.pc_rel = 0;
3638 inst.instruction |= shift->properties->bit_field;
3639 }
3640
3641 * str = p;
3642 return SUCCESS;
3643 }
3644
3645 static void
3646 do_sat (char ** str, int bias)
3647 {
3648 int rd, rm;
3649 expressionS expr;
3650
3651 skip_whitespace (*str);
3652
3653 /* Parse <Rd>, field. */
3654 if ((rd = reg_required_here (str, 12)) == FAIL
3655 || skip_past_comma (str) == FAIL)
3656 {
3657 inst.error = BAD_ARGS;
3658 return;
3659 }
3660 if (rd == REG_PC)
3661 {
3662 inst.error = BAD_PC;
3663 return;
3664 }
3665
3666 /* Parse #<immed>, field. */
3667 if (is_immediate_prefix (**str))
3668 (*str)++;
3669 else
3670 {
3671 inst.error = _("immediate expression expected");
3672 return;
3673 }
3674 if (my_get_expression (&expr, str))
3675 {
3676 inst.error = _("bad expression");
3677 return;
3678 }
3679 if (expr.X_op != O_constant)
3680 {
3681 inst.error = _("constant expression expected");
3682 return;
3683 }
3684 if (expr.X_add_number + bias < 0
3685 || expr.X_add_number + bias > 31)
3686 {
3687 inst.error = _("immediate value out of range");
3688 return;
3689 }
3690 inst.instruction |= (expr.X_add_number + bias) << 16;
3691 if (skip_past_comma (str) == FAIL)
3692 {
3693 inst.error = BAD_ARGS;
3694 return;
3695 }
3696
3697 /* Parse <Rm> field. */
3698 if ((rm = reg_required_here (str, 0)) == FAIL)
3699 {
3700 inst.error = BAD_ARGS;
3701 return;
3702 }
3703 if (rm == REG_PC)
3704 {
3705 inst.error = BAD_PC;
3706 return;
3707 }
3708
3709 if (skip_past_comma (str) == SUCCESS)
3710 decode_shift (str, SHIFT_LSL_OR_ASR_IMMEDIATE);
3711 }
3712
3713 /* ARM V6 ssat (argument parse). */
3714
3715 static void
3716 do_ssat (char * str)
3717 {
3718 do_sat (&str, /*bias=*/-1);
3719 end_of_line (str);
3720 }
3721
3722 /* ARM V6 usat (argument parse). */
3723
3724 static void
3725 do_usat (char * str)
3726 {
3727 do_sat (&str, /*bias=*/0);
3728 end_of_line (str);
3729 }
3730
3731 static void
3732 do_sat16 (char ** str, int bias)
3733 {
3734 int rd, rm;
3735 expressionS expr;
3736
3737 skip_whitespace (*str);
3738
3739 /* Parse the <Rd> field. */
3740 if ((rd = reg_required_here (str, 12)) == FAIL
3741 || skip_past_comma (str) == FAIL)
3742 {
3743 inst.error = BAD_ARGS;
3744 return;
3745 }
3746 if (rd == REG_PC)
3747 {
3748 inst.error = BAD_PC;
3749 return;
3750 }
3751
3752 /* Parse #<immed>, field. */
3753 if (is_immediate_prefix (**str))
3754 (*str)++;
3755 else
3756 {
3757 inst.error = _("immediate expression expected");
3758 return;
3759 }
3760 if (my_get_expression (&expr, str))
3761 {
3762 inst.error = _("bad expression");
3763 return;
3764 }
3765 if (expr.X_op != O_constant)
3766 {
3767 inst.error = _("constant expression expected");
3768 return;
3769 }
3770 if (expr.X_add_number + bias < 0
3771 || expr.X_add_number + bias > 15)
3772 {
3773 inst.error = _("immediate value out of range");
3774 return;
3775 }
3776 inst.instruction |= (expr.X_add_number + bias) << 16;
3777 if (skip_past_comma (str) == FAIL)
3778 {
3779 inst.error = BAD_ARGS;
3780 return;
3781 }
3782
3783 /* Parse <Rm> field. */
3784 if ((rm = reg_required_here (str, 0)) == FAIL)
3785 {
3786 inst.error = BAD_ARGS;
3787 return;
3788 }
3789 if (rm == REG_PC)
3790 {
3791 inst.error = BAD_PC;
3792 return;
3793 }
3794 }
3795
3796 /* ARM V6 ssat16 (argument parse). */
3797
3798 static void
3799 do_ssat16 (char * str)
3800 {
3801 do_sat16 (&str, /*bias=*/-1);
3802 end_of_line (str);
3803 }
3804
3805 static void
3806 do_usat16 (char * str)
3807 {
3808 do_sat16 (&str, /*bias=*/0);
3809 end_of_line (str);
3810 }
3811
3812 static void
3813 do_cps_mode (char ** str)
3814 {
3815 expressionS expr;
3816
3817 skip_whitespace (*str);
3818
3819 if (! is_immediate_prefix (**str))
3820 {
3821 inst.error = _("immediate expression expected");
3822 return;
3823 }
3824
3825 (*str)++; /* Strip off the immediate signifier. */
3826 if (my_get_expression (&expr, str))
3827 {
3828 inst.error = _("bad expression");
3829 return;
3830 }
3831
3832 if (expr.X_op != O_constant)
3833 {
3834 inst.error = _("constant expression expected");
3835 return;
3836 }
3837
3838 /* The mode is a 5 bit field. Valid values are 0-31. */
3839 if (((unsigned) expr.X_add_number) > 31
3840 || (inst.reloc.exp.X_add_number) < 0)
3841 {
3842 inst.error = _("invalid constant");
3843 return;
3844 }
3845
3846 inst.instruction |= expr.X_add_number;
3847 }
3848
3849 /* ARM V6 srs (argument parse). */
3850
3851 static void
3852 do_srs (char * str)
3853 {
3854 char *exclam;
3855 skip_whitespace (str);
3856 exclam = strchr (str, '!');
3857 if (exclam)
3858 *exclam = '\0';
3859 do_cps_mode (&str);
3860 if (exclam)
3861 *exclam = '!';
3862 if (*str == '!')
3863 {
3864 inst.instruction |= WRITE_BACK;
3865 str++;
3866 }
3867 end_of_line (str);
3868 }
3869
3870 /* ARM V6 SMMUL (argument parse). */
3871
3872 static void
3873 do_smmul (char * str)
3874 {
3875 int rd, rm, rs;
3876
3877 skip_whitespace (str);
3878 if ((rd = reg_required_here (&str, 16)) == FAIL
3879 || skip_past_comma (&str) == FAIL
3880 || (rm = reg_required_here (&str, 0)) == FAIL
3881 || skip_past_comma (&str) == FAIL
3882 || (rs = reg_required_here (&str, 8)) == FAIL)
3883 {
3884 inst.error = BAD_ARGS;
3885 return;
3886 }
3887
3888 if ( rd == REG_PC
3889 || rm == REG_PC
3890 || rs == REG_PC)
3891 {
3892 inst.error = BAD_PC;
3893 return;
3894 }
3895
3896 end_of_line (str);
3897 }
3898
3899 /* ARM V6 SMLALD (argument parse). */
3900
3901 static void
3902 do_smlald (char * str)
3903 {
3904 int rdlo, rdhi, rm, rs;
3905
3906 skip_whitespace (str);
3907 if ((rdlo = reg_required_here (&str, 12)) == FAIL
3908 || skip_past_comma (&str) == FAIL
3909 || (rdhi = reg_required_here (&str, 16)) == FAIL
3910 || skip_past_comma (&str) == FAIL
3911 || (rm = reg_required_here (&str, 0)) == FAIL
3912 || skip_past_comma (&str) == FAIL
3913 || (rs = reg_required_here (&str, 8)) == FAIL)
3914 {
3915 inst.error = BAD_ARGS;
3916 return;
3917 }
3918
3919 if ( rdlo == REG_PC
3920 || rdhi == REG_PC
3921 || rm == REG_PC
3922 || rs == REG_PC)
3923 {
3924 inst.error = BAD_PC;
3925 return;
3926 }
3927
3928 end_of_line (str);
3929 }
3930
3931 /* ARM V6 SMLAD (argument parse). Signed multiply accumulate dual.
3932 smlad{x}{<cond>} Rd, Rm, Rs, Rn */
3933
3934 static void
3935 do_smlad (char * str)
3936 {
3937 int rd, rm, rs, rn;
3938
3939 skip_whitespace (str);
3940 if ((rd = reg_required_here (&str, 16)) == FAIL
3941 || skip_past_comma (&str) == FAIL
3942 || (rm = reg_required_here (&str, 0)) == FAIL
3943 || skip_past_comma (&str) == FAIL
3944 || (rs = reg_required_here (&str, 8)) == FAIL
3945 || skip_past_comma (&str) == FAIL
3946 || (rn = reg_required_here (&str, 12)) == FAIL)
3947 {
3948 inst.error = BAD_ARGS;
3949 return;
3950 }
3951
3952 if ( rd == REG_PC
3953 || rn == REG_PC
3954 || rs == REG_PC
3955 || rm == REG_PC)
3956 {
3957 inst.error = BAD_PC;
3958 return;
3959 }
3960
3961 end_of_line (str);
3962 }
3963
3964 /* Returns true if the endian-specifier indicates big-endianness. */
3965
3966 static int
3967 do_endian_specifier (char * str)
3968 {
3969 int big_endian = 0;
3970
3971 skip_whitespace (str);
3972 if (strlen (str) < 2)
3973 inst.error = _("missing endian specifier");
3974 else if (strncasecmp (str, "BE", 2) == 0)
3975 {
3976 str += 2;
3977 big_endian = 1;
3978 }
3979 else if (strncasecmp (str, "LE", 2) == 0)
3980 str += 2;
3981 else
3982 inst.error = _("valid endian specifiers are be or le");
3983
3984 end_of_line (str);
3985
3986 return big_endian;
3987 }
3988
3989 /* ARM V6 SETEND (argument parse). Sets the E bit in the CPSR while
3990 preserving the other bits.
3991
3992 setend <endian_specifier>, where <endian_specifier> is either
3993 BE or LE. */
3994
3995 static void
3996 do_setend (char * str)
3997 {
3998 if (do_endian_specifier (str))
3999 inst.instruction |= 0x200;
4000 }
4001
4002 /* ARM V6 SXTH.
4003
4004 SXTH {<cond>} <Rd>, <Rm>{, <rotation>}
4005 Condition defaults to COND_ALWAYS.
4006 Error if any register uses R15. */
4007
4008 static void
4009 do_sxth (char * str)
4010 {
4011 int rd, rm;
4012 expressionS expr;
4013 int rotation_clear_mask = 0xfffff3ff;
4014 int rotation_eight_mask = 0x00000400;
4015 int rotation_sixteen_mask = 0x00000800;
4016 int rotation_twenty_four_mask = 0x00000c00;
4017
4018 skip_whitespace (str);
4019 if ((rd = reg_required_here (&str, 12)) == FAIL
4020 || skip_past_comma (&str) == FAIL
4021 || (rm = reg_required_here (&str, 0)) == FAIL)
4022 {
4023 inst.error = BAD_ARGS;
4024 return;
4025 }
4026
4027 else if (rd == REG_PC || rm == REG_PC)
4028 {
4029 inst.error = BAD_PC;
4030 return;
4031 }
4032
4033 /* Zero out the rotation field. */
4034 inst.instruction &= rotation_clear_mask;
4035
4036 /* Check for lack of optional rotation field. */
4037 if (skip_past_comma (&str) == FAIL)
4038 {
4039 end_of_line (str);
4040 return;
4041 }
4042
4043 /* Move past 'ROR'. */
4044 skip_whitespace (str);
4045 if (strncasecmp (str, "ROR", 3) == 0)
4046 str += 3;
4047 else
4048 {
4049 inst.error = _("missing rotation field after comma");
4050 return;
4051 }
4052
4053 /* Get the immediate constant. */
4054 skip_whitespace (str);
4055 if (is_immediate_prefix (* str))
4056 str++;
4057 else
4058 {
4059 inst.error = _("immediate expression expected");
4060 return;
4061 }
4062
4063 if (my_get_expression (&expr, &str))
4064 {
4065 inst.error = _("bad expression");
4066 return;
4067 }
4068
4069 if (expr.X_op != O_constant)
4070 {
4071 inst.error = _("constant expression expected");
4072 return;
4073 }
4074
4075 switch (expr.X_add_number)
4076 {
4077 case 0:
4078 /* Rotation field has already been zeroed. */
4079 break;
4080 case 8:
4081 inst.instruction |= rotation_eight_mask;
4082 break;
4083
4084 case 16:
4085 inst.instruction |= rotation_sixteen_mask;
4086 break;
4087
4088 case 24:
4089 inst.instruction |= rotation_twenty_four_mask;
4090 break;
4091
4092 default:
4093 inst.error = _("rotation can be 8, 16, 24 or 0 when field is ommited");
4094 break;
4095 }
4096
4097 end_of_line (str);
4098 }
4099
4100 /* ARM V6 SXTAH extracts a 16-bit value from a register, sign
4101 extends it to 32-bits, and adds the result to a value in another
4102 register. You can specify a rotation by 0, 8, 16, or 24 bits
4103 before extracting the 16-bit value.
4104 SXTAH{<cond>} <Rd>, <Rn>, <Rm>{, <rotation>}
4105 Condition defaults to COND_ALWAYS.
4106 Error if any register uses R15. */
4107
4108 static void
4109 do_sxtah (char * str)
4110 {
4111 int rd, rn, rm;
4112 expressionS expr;
4113 int rotation_clear_mask = 0xfffff3ff;
4114 int rotation_eight_mask = 0x00000400;
4115 int rotation_sixteen_mask = 0x00000800;
4116 int rotation_twenty_four_mask = 0x00000c00;
4117
4118 skip_whitespace (str);
4119 if ((rd = reg_required_here (&str, 12)) == FAIL
4120 || skip_past_comma (&str) == FAIL
4121 || (rn = reg_required_here (&str, 16)) == FAIL
4122 || skip_past_comma (&str) == FAIL
4123 || (rm = reg_required_here (&str, 0)) == FAIL)
4124 {
4125 inst.error = BAD_ARGS;
4126 return;
4127 }
4128
4129 else if (rd == REG_PC || rn == REG_PC || rm == REG_PC)
4130 {
4131 inst.error = BAD_PC;
4132 return;
4133 }
4134
4135 /* Zero out the rotation field. */
4136 inst.instruction &= rotation_clear_mask;
4137
4138 /* Check for lack of optional rotation field. */
4139 if (skip_past_comma (&str) == FAIL)
4140 {
4141 end_of_line (str);
4142 return;
4143 }
4144
4145 /* Move past 'ROR'. */
4146 skip_whitespace (str);
4147 if (strncasecmp (str, "ROR", 3) == 0)
4148 str += 3;
4149 else
4150 {
4151 inst.error = _("missing rotation field after comma");
4152 return;
4153 }
4154
4155 /* Get the immediate constant. */
4156 skip_whitespace (str);
4157 if (is_immediate_prefix (* str))
4158 str++;
4159 else
4160 {
4161 inst.error = _("immediate expression expected");
4162 return;
4163 }
4164
4165 if (my_get_expression (&expr, &str))
4166 {
4167 inst.error = _("bad expression");
4168 return;
4169 }
4170
4171 if (expr.X_op != O_constant)
4172 {
4173 inst.error = _("constant expression expected");
4174 return;
4175 }
4176
4177 switch (expr.X_add_number)
4178 {
4179 case 0:
4180 /* Rotation field has already been zeroed. */
4181 break;
4182
4183 case 8:
4184 inst.instruction |= rotation_eight_mask;
4185 break;
4186
4187 case 16:
4188 inst.instruction |= rotation_sixteen_mask;
4189 break;
4190
4191 case 24:
4192 inst.instruction |= rotation_twenty_four_mask;
4193 break;
4194
4195 default:
4196 inst.error = _("rotation can be 8, 16, 24 or 0 when field is ommited");
4197 break;
4198 }
4199
4200 end_of_line (str);
4201 }
4202
4203
4204 /* ARM V6 RFE (Return from Exception) loads the PC and CPSR from the
4205 word at the specified address and the following word
4206 respectively.
4207 Unconditionally executed.
4208 Error if Rn is R15. */
4209
4210 static void
4211 do_rfe (char * str)
4212 {
4213 int rn;
4214
4215 skip_whitespace (str);
4216
4217 if ((rn = reg_required_here (&str, 16)) == FAIL)
4218 return;
4219
4220 if (rn == REG_PC)
4221 {
4222 inst.error = BAD_PC;
4223 return;
4224 }
4225
4226 skip_whitespace (str);
4227
4228 if (*str == '!')
4229 {
4230 inst.instruction |= WRITE_BACK;
4231 str++;
4232 }
4233 end_of_line (str);
4234 }
4235
4236 /* ARM V6 REV (Byte Reverse Word) reverses the byte order in a 32-bit
4237 register (argument parse).
4238 REV{<cond>} Rd, Rm.
4239 Condition defaults to COND_ALWAYS.
4240 Error if Rd or Rm are R15. */
4241
4242 static void
4243 do_rev (char * str)
4244 {
4245 int rd, rm;
4246
4247 skip_whitespace (str);
4248
4249 if ((rd = reg_required_here (&str, 12)) == FAIL
4250 || skip_past_comma (&str) == FAIL
4251 || (rm = reg_required_here (&str, 0)) == FAIL)
4252 inst.error = BAD_ARGS;
4253
4254 else if (rd == REG_PC || rm == REG_PC)
4255 inst.error = BAD_PC;
4256
4257 else
4258 end_of_line (str);
4259 }
4260
4261 /* ARM V6 Perform Two Sixteen Bit Integer Additions. (argument parse).
4262 QADD16{<cond>} <Rd>, <Rn>, <Rm>
4263 Condition defaults to COND_ALWAYS.
4264 Error if Rd, Rn or Rm are R15. */
4265
4266 static void
4267 do_qadd16 (char * str)
4268 {
4269 int rd, rm, rn;
4270
4271 skip_whitespace (str);
4272
4273 if ((rd = reg_required_here (&str, 12)) == FAIL
4274 || skip_past_comma (&str) == FAIL
4275 || (rn = reg_required_here (&str, 16)) == FAIL
4276 || skip_past_comma (&str) == FAIL
4277 || (rm = reg_required_here (&str, 0)) == FAIL)
4278 inst.error = BAD_ARGS;
4279
4280 else if (rd == REG_PC || rm == REG_PC || rn == REG_PC)
4281 inst.error = BAD_PC;
4282
4283 else
4284 end_of_line (str);
4285 }
4286
4287 static void
4288 do_pkh_core (char * str, int shift)
4289 {
4290 int rd, rn, rm;
4291
4292 skip_whitespace (str);
4293 if (((rd = reg_required_here (&str, 12)) == FAIL)
4294 || (skip_past_comma (&str) == FAIL)
4295 || ((rn = reg_required_here (&str, 16)) == FAIL)
4296 || (skip_past_comma (&str) == FAIL)
4297 || ((rm = reg_required_here (&str, 0)) == FAIL))
4298 {
4299 inst.error = BAD_ARGS;
4300 return;
4301 }
4302
4303 else if (rd == REG_PC || rn == REG_PC || rm == REG_PC)
4304 {
4305 inst.error = BAD_PC;
4306 return;
4307 }
4308
4309 /* Check for optional shift immediate constant. */
4310 if (skip_past_comma (&str) == FAIL)
4311 {
4312 if (shift == SHIFT_ASR_IMMEDIATE)
4313 {
4314 /* If the shift specifier is ommited, turn the instruction
4315 into pkhbt rd, rm, rn. First, switch the instruction
4316 code, and clear the rn and rm fields. */
4317 inst.instruction &= 0xfff0f010;
4318 /* Now, re-encode the registers. */
4319 inst.instruction |= (rm << 16) | rn;
4320 }
4321 return;
4322 }
4323
4324 decode_shift (&str, shift);
4325 }
4326
4327 /* ARM V6 Pack Halfword Bottom Top instruction (argument parse).
4328 PKHBT {<cond>} <Rd>, <Rn>, <Rm> {, LSL #<shift_imm>}
4329 Condition defaults to COND_ALWAYS.
4330 Error if Rd, Rn or Rm are R15. */
4331
4332 static void
4333 do_pkhbt (char * str)
4334 {
4335 do_pkh_core (str, SHIFT_LSL_IMMEDIATE);
4336 }
4337
4338 /* ARM V6 PKHTB (Argument Parse). */
4339
4340 static void
4341 do_pkhtb (char * str)
4342 {
4343 do_pkh_core (str, SHIFT_ASR_IMMEDIATE);
4344 }
4345
4346 /* ARM V6 Load Register Exclusive instruction (argument parse).
4347 LDREX{,B,D,H}{<cond>} <Rd, [<Rn>]
4348 Condition defaults to COND_ALWAYS.
4349 Error if Rd or Rn are R15.
4350 See ARMARMv6 A4.1.27: LDREX. */
4351
4352 static void
4353 do_ldrex (char * str)
4354 {
4355 int rd, rn;
4356
4357 skip_whitespace (str);
4358
4359 /* Parse Rd. */
4360 if (((rd = reg_required_here (&str, 12)) == FAIL)
4361 || (skip_past_comma (&str) == FAIL))
4362 {
4363 inst.error = BAD_ARGS;
4364 return;
4365 }
4366 else if (rd == REG_PC)
4367 {
4368 inst.error = BAD_PC;
4369 return;
4370 }
4371 skip_whitespace (str);
4372
4373 /* Skip past '['. */
4374 if ((strlen (str) >= 1)
4375 &&strncmp (str, "[", 1) == 0)
4376 str += 1;
4377 skip_whitespace (str);
4378
4379 /* Parse Rn. */
4380 if ((rn = reg_required_here (&str, 16)) == FAIL)
4381 {
4382 inst.error = BAD_ARGS;
4383 return;
4384 }
4385 else if (rn == REG_PC)
4386 {
4387 inst.error = BAD_PC;
4388 return;
4389 }
4390 skip_whitespace (str);
4391
4392 /* Skip past ']'. */
4393 if ((strlen (str) >= 1)
4394 && strncmp (str, "]", 1) == 0)
4395 str += 1;
4396
4397 end_of_line (str);
4398 }
4399
4400 /* ARM V6 change processor state instruction (argument parse)
4401 CPS, CPSIE, CSPID . */
4402
4403 static void
4404 do_cps (char * str)
4405 {
4406 do_cps_mode (&str);
4407 end_of_line (str);
4408 }
4409
4410 static void
4411 do_cps_flags (char ** str, int thumb_p)
4412 {
4413 struct cps_flag
4414 {
4415 char character;
4416 unsigned long arm_value;
4417 unsigned long thumb_value;
4418 };
4419 static struct cps_flag flag_table[] =
4420 {
4421 {'a', 0x100, 0x4 },
4422 {'i', 0x080, 0x2 },
4423 {'f', 0x040, 0x1 }
4424 };
4425
4426 int saw_a_flag = 0;
4427
4428 skip_whitespace (*str);
4429
4430 /* Get the a, f and i flags. */
4431 while (**str && **str != ',')
4432 {
4433 struct cps_flag *p;
4434 struct cps_flag *q = flag_table + sizeof (flag_table)/sizeof (*p);
4435
4436 for (p = flag_table; p < q; ++p)
4437 if (strncasecmp (*str, &p->character, 1) == 0)
4438 {
4439 inst.instruction |= (thumb_p ? p->thumb_value : p->arm_value);
4440 saw_a_flag = 1;
4441 break;
4442 }
4443 if (p == q)
4444 {
4445 inst.error = _("unrecognized flag");
4446 return;
4447 }
4448 (*str)++;
4449 }
4450
4451 if (!saw_a_flag)
4452 inst.error = _("no 'a', 'i', or 'f' flags for 'cps'");
4453 }
4454
4455 static void
4456 do_cpsi (char * str)
4457 {
4458 do_cps_flags (&str, /*thumb_p=*/0);
4459
4460 if (skip_past_comma (&str) == SUCCESS)
4461 {
4462 skip_whitespace (str);
4463 do_cps_mode (&str);
4464 }
4465 end_of_line (str);
4466 }
4467
4468 /* ARM V6T2 bitfield manipulation instructions. */
4469
4470 static int
4471 five_bit_unsigned_immediate (char **str)
4472 {
4473 expressionS expr;
4474
4475 skip_whitespace (*str);
4476 if (!is_immediate_prefix (**str))
4477 {
4478 inst.error = _("immediate expression expected");
4479 return -1;
4480 }
4481 (*str)++;
4482 if (my_get_expression (&expr, str))
4483 {
4484 inst.error = _("bad expression");
4485 return -1;
4486 }
4487 if (expr.X_op != O_constant)
4488 {
4489 inst.error = _("constant expression expected");
4490 return -1;
4491 }
4492 if (expr.X_add_number < 0 || expr.X_add_number > 32)
4493 {
4494 inst.error = _("immediate value out of range");
4495 return -1;
4496 }
4497
4498 return expr.X_add_number;
4499 }
4500
4501 static void
4502 bfci_lsb_and_width (char *str)
4503 {
4504 int lsb, width;
4505
4506 if ((lsb = five_bit_unsigned_immediate (&str)) == -1)
4507 return;
4508
4509 if (skip_past_comma (&str) == FAIL)
4510 {
4511 inst.error = BAD_ARGS;
4512 return;
4513 }
4514 if ((width = five_bit_unsigned_immediate (&str)) == -1)
4515 return;
4516
4517 end_of_line (str);
4518
4519 if (width == 0 || lsb == 32)
4520 {
4521 inst.error = _("immediate value out of range");
4522 return;
4523 }
4524 else if (width + lsb > 32)
4525 {
4526 inst.error = _("bit-field extends past end of register");
4527 return;
4528 }
4529
4530 /* Convert to LSB/MSB and write to register. */
4531 inst.instruction |= lsb << 7;
4532 inst.instruction |= (width + lsb - 1) << 16;
4533 }
4534
4535 static void
4536 do_bfc (char *str)
4537 {
4538 int rd;
4539
4540 /* Rd. */
4541 skip_whitespace (str);
4542 if (((rd = reg_required_here (&str, 12)) == FAIL)
4543 || (skip_past_comma (&str) == FAIL))
4544 {
4545 inst.error = BAD_ARGS;
4546 return;
4547 }
4548 else if (rd == REG_PC)
4549 {
4550 inst.error = BAD_PC;
4551 return;
4552 }
4553
4554 bfci_lsb_and_width (str);
4555 }
4556
4557 static void
4558 do_bfi (char *str)
4559 {
4560 int rd, rm;
4561
4562 /* Rd. */
4563 skip_whitespace (str);
4564 if (((rd = reg_required_here (&str, 12)) == FAIL)
4565 || (skip_past_comma (&str) == FAIL))
4566 {
4567 inst.error = BAD_ARGS;
4568 return;
4569 }
4570 else if (rd == REG_PC)
4571 {
4572 inst.error = BAD_PC;
4573 return;
4574 }
4575
4576 /* Rm. Accept #0 in this position as an alternative syntax for bfc. */
4577 skip_whitespace (str);
4578 if (is_immediate_prefix (*str))
4579 {
4580 expressionS expr;
4581 str++;
4582 if (my_get_expression (&expr, &str))
4583 {
4584 inst.error = _("bad expression");
4585 return;
4586 }
4587 if (expr.X_op != O_constant)
4588 {
4589 inst.error = _("constant expression expected");
4590 return;
4591 }
4592 if (expr.X_add_number != 0)
4593 {
4594 inst.error = _("immediate value out of range");
4595 return;
4596 }
4597 inst.instruction |= 0x0000000f; /* Rm = PC -> bfc, not bfi. */
4598 }
4599 else
4600 {
4601 if ((rm = reg_required_here (&str, 0)) == FAIL)
4602 {
4603 inst.error = BAD_ARGS;
4604 return;
4605 }
4606 else if (rm == REG_PC)
4607 {
4608 inst.error = BAD_PC;
4609 return;
4610 }
4611 }
4612 if (skip_past_comma (&str) == FAIL)
4613 {
4614 inst.error = BAD_ARGS;
4615 return;
4616 }
4617
4618 bfci_lsb_and_width (str);
4619 }
4620
4621 static void
4622 do_bfx (char *str)
4623 {
4624 int lsb, width;
4625
4626 /* Rd. */
4627 skip_whitespace (str);
4628 if (reg_required_here (&str, 12) == FAIL
4629 || skip_past_comma (&str) == FAIL)
4630 {
4631 inst.error = BAD_ARGS;
4632 return;
4633 }
4634
4635 /* Rm. */
4636 skip_whitespace (str);
4637 if (reg_required_here (&str, 0) == FAIL
4638 || skip_past_comma (&str) == FAIL)
4639 {
4640 inst.error = BAD_ARGS;
4641 return;
4642 }
4643
4644 if ((lsb = five_bit_unsigned_immediate (&str)) == -1)
4645 return;
4646
4647 if (skip_past_comma (&str) == FAIL)
4648 {
4649 inst.error = BAD_ARGS;
4650 return;
4651 }
4652 if ((width = five_bit_unsigned_immediate (&str)) == -1)
4653 return;
4654
4655 end_of_line (str);
4656
4657 if (width == 0 || lsb == 32)
4658 {
4659 inst.error = _("immediate value out of range");
4660 return;
4661 }
4662 else if (width + lsb > 32)
4663 {
4664 inst.error = _("bit-field extends past end of register");
4665 return;
4666 }
4667
4668 inst.instruction |= lsb << 7;
4669 inst.instruction |= (width - 1) << 16;
4670 }
4671
4672 static void
4673 do_rbit (char *str)
4674 {
4675 /* Rd. */
4676 skip_whitespace (str);
4677 if (reg_required_here (&str, 12) == FAIL
4678 || skip_past_comma (&str) == FAIL)
4679 {
4680 inst.error = BAD_ARGS;
4681 return;
4682 }
4683
4684 /* Rm. */
4685 skip_whitespace (str);
4686 if (reg_required_here (&str, 0) == FAIL)
4687 {
4688 inst.error = BAD_ARGS;
4689 return;
4690 }
4691
4692 end_of_line (str);
4693 }
4694
4695 /* ARM V6T2 16-bit immediate register load: MOV[WT]{cond} Rd, #<imm16>. */
4696 static void
4697 do_mov16 (char *str)
4698 {
4699 int rd;
4700 expressionS expr;
4701
4702 /* Rd. */
4703 skip_whitespace (str);
4704 if (((rd = reg_required_here (&str, 12)) == FAIL)
4705 || (skip_past_comma (&str) == FAIL))
4706 {
4707 inst.error = BAD_ARGS;
4708 return;
4709 }
4710 else if (rd == REG_PC)
4711 {
4712 inst.error = BAD_PC;
4713 return;
4714 }
4715
4716 /* Imm16. */
4717 skip_whitespace (str);
4718 if (!is_immediate_prefix (*str))
4719 {
4720 inst.error = _("immediate expression expected");
4721 return;
4722 }
4723 str++;
4724 if (my_get_expression (&expr, &str))
4725 {
4726 inst.error = _("bad expression");
4727 return;
4728 }
4729 if (expr.X_op != O_constant)
4730 {
4731 inst.error = _("constant expression expected");
4732 return;
4733 }
4734 if (expr.X_add_number < 0 || expr.X_add_number > 65535)
4735 {
4736 inst.error = _("immediate value out of range");
4737 return;
4738 }
4739
4740 end_of_line (str);
4741
4742 /* The value is in two pieces: 0:11, 16:19. */
4743 inst.instruction |= (expr.X_add_number & 0x00000fff);
4744 inst.instruction |= (expr.X_add_number & 0x0000f000) << 4;
4745 }
4746
4747
4748 /* THUMB V5 breakpoint instruction (argument parse)
4749 BKPT <immed_8>. */
4750
4751 static void
4752 do_t_bkpt (char * str)
4753 {
4754 expressionS expr;
4755 unsigned long number;
4756
4757 skip_whitespace (str);
4758
4759 /* Allow optional leading '#'. */
4760 if (is_immediate_prefix (*str))
4761 str ++;
4762
4763 memset (& expr, '\0', sizeof (expr));
4764 if (my_get_expression (& expr, & str)
4765 || (expr.X_op != O_constant
4766 /* As a convenience we allow 'bkpt' without an operand. */
4767 && expr.X_op != O_absent))
4768 {
4769 inst.error = _("bad expression");
4770 return;
4771 }
4772
4773 number = expr.X_add_number;
4774
4775 /* Check it fits an 8 bit unsigned. */
4776 if (number != (number & 0xff))
4777 {
4778 inst.error = _("immediate value out of range");
4779 return;
4780 }
4781
4782 inst.instruction |= number;
4783
4784 end_of_line (str);
4785 }
4786
4787 #ifdef OBJ_ELF
4788 static bfd_reloc_code_real_type
4789 arm_parse_reloc (void)
4790 {
4791 char id [16];
4792 char * ip;
4793 unsigned int i;
4794 static struct
4795 {
4796 char * str;
4797 int len;
4798 bfd_reloc_code_real_type reloc;
4799 }
4800 reloc_map[] =
4801 {
4802 #define MAP(str,reloc) { str, sizeof (str) - 1, reloc }
4803 MAP ("(got)", BFD_RELOC_ARM_GOT32),
4804 MAP ("(gotoff)", BFD_RELOC_ARM_GOTOFF),
4805 /* ScottB: Jan 30, 1998 - Added support for parsing "var(PLT)"
4806 branch instructions generated by GCC for PLT relocs. */
4807 MAP ("(plt)", BFD_RELOC_ARM_PLT32),
4808 MAP ("(target1)", BFD_RELOC_ARM_TARGET1),
4809 MAP ("(sbrel)", BFD_RELOC_ARM_SBREL32),
4810 MAP ("(target2)", BFD_RELOC_ARM_TARGET2),
4811 MAP ("(tlsgd)", BFD_RELOC_ARM_TLS_GD32),
4812 MAP ("(tlsldm)", BFD_RELOC_ARM_TLS_LDM32),
4813 MAP ("(tlsldo)", BFD_RELOC_ARM_TLS_LDO32),
4814 MAP ("(gottpoff)", BFD_RELOC_ARM_TLS_IE32),
4815 MAP ("(tpoff)", BFD_RELOC_ARM_TLS_LE32),
4816 { NULL, 0, BFD_RELOC_UNUSED }
4817 #undef MAP
4818 };
4819
4820 for (i = 0, ip = input_line_pointer;
4821 i < sizeof (id) && (ISALNUM (*ip) || ISPUNCT (*ip));
4822 i++, ip++)
4823 id[i] = TOLOWER (*ip);
4824
4825 for (i = 0; reloc_map[i].str; i++)
4826 if (strncmp (id, reloc_map[i].str, reloc_map[i].len) == 0)
4827 break;
4828
4829 input_line_pointer += reloc_map[i].len;
4830
4831 return reloc_map[i].reloc;
4832 }
4833 #endif
4834
4835 /* ARM V5 branch-link-exchange (argument parse) for BLX(1) only.
4836 Expects inst.instruction is set for BLX(1).
4837 Note: this is cloned from do_branch, and the reloc changed to be a
4838 new one that can cope with setting one extra bit (the H bit). */
4839
4840 static void
4841 do_branch25 (char * str)
4842 {
4843 if (my_get_expression (& inst.reloc.exp, & str))
4844 return;
4845
4846 #ifdef OBJ_ELF
4847 {
4848 char * save_in;
4849
4850 /* ScottB: February 5, 1998 */
4851 /* Check to see of PLT32 reloc required for the instruction. */
4852
4853 /* arm_parse_reloc() works on input_line_pointer.
4854 We actually want to parse the operands to the branch instruction
4855 passed in 'str'. Save the input pointer and restore it later. */
4856 save_in = input_line_pointer;
4857 input_line_pointer = str;
4858
4859 if (inst.reloc.exp.X_op == O_symbol
4860 && *str == '('
4861 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
4862 {
4863 inst.reloc.type = BFD_RELOC_ARM_PLT32;
4864 inst.reloc.pc_rel = 0;
4865 /* Modify str to point to after parsed operands, otherwise
4866 end_of_line() will complain about the (PLT) left in str. */
4867 str = input_line_pointer;
4868 }
4869 else
4870 {
4871 inst.reloc.type = BFD_RELOC_ARM_PCREL_BLX;
4872 inst.reloc.pc_rel = 1;
4873 }
4874
4875 input_line_pointer = save_in;
4876 }
4877 #else
4878 inst.reloc.type = BFD_RELOC_ARM_PCREL_BLX;
4879 inst.reloc.pc_rel = 1;
4880 #endif /* OBJ_ELF */
4881
4882 end_of_line (str);
4883 }
4884
4885 /* ARM V5 branch-link-exchange instruction (argument parse)
4886 BLX <target_addr> ie BLX(1)
4887 BLX{<condition>} <Rm> ie BLX(2)
4888 Unfortunately, there are two different opcodes for this mnemonic.
4889 So, the insns[].value is not used, and the code here zaps values
4890 into inst.instruction.
4891 Also, the <target_addr> can be 25 bits, hence has its own reloc. */
4892
4893 static void
4894 do_blx (char * str)
4895 {
4896 char * mystr = str;
4897 int rm;
4898
4899 skip_whitespace (mystr);
4900 rm = reg_required_here (& mystr, 0);
4901
4902 /* The above may set inst.error. Ignore his opinion. */
4903 inst.error = 0;
4904
4905 if (rm != FAIL)
4906 {
4907 /* Arg is a register.
4908 Use the condition code our caller put in inst.instruction.
4909 Pass ourselves off as a BX with a funny opcode. */
4910 inst.instruction |= 0x012fff30;
4911 do_bx (str);
4912 }
4913 else
4914 {
4915 /* This must be is BLX <target address>, no condition allowed. */
4916 if (inst.instruction != COND_ALWAYS)
4917 {
4918 inst.error = BAD_COND;
4919 return;
4920 }
4921
4922 inst.instruction = 0xfafffffe;
4923
4924 /* Process like a B/BL, but with a different reloc.
4925 Note that B/BL expecte fffffe, not 0, offset in the opcode table. */
4926 do_branch25 (str);
4927 }
4928 }
4929
4930 /* ARM V5 Thumb BLX (argument parse)
4931 BLX <target_addr> which is BLX(1)
4932 BLX <Rm> which is BLX(2)
4933 Unfortunately, there are two different opcodes for this mnemonic.
4934 So, the tinsns[].value is not used, and the code here zaps values
4935 into inst.instruction. */
4936
4937 static void
4938 do_t_blx (char * str)
4939 {
4940 char * mystr = str;
4941 int rm;
4942
4943 skip_whitespace (mystr);
4944 inst.instruction = 0x4780;
4945
4946 /* Note that this call is to the ARM register recognizer. BLX(2)
4947 uses the ARM register space, not the Thumb one, so a call to
4948 thumb_reg() would be wrong. */
4949 rm = reg_required_here (& mystr, 3);
4950 inst.error = 0;
4951
4952 if (rm != FAIL)
4953 {
4954 /* It's BLX(2). The .instruction was zapped with rm & is final. */
4955 inst.size = 2;
4956 }
4957 else
4958 {
4959 /* No ARM register. This must be BLX(1). Change the .instruction. */
4960 inst.instruction = 0xf7ffeffe;
4961 inst.size = 4;
4962
4963 if (my_get_expression (& inst.reloc.exp, & mystr))
4964 return;
4965
4966 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BLX;
4967 inst.reloc.pc_rel = 1;
4968 }
4969
4970 end_of_line (mystr);
4971 }
4972
4973 /* ARM V5 breakpoint instruction (argument parse)
4974 BKPT <16 bit unsigned immediate>
4975 Instruction is not conditional.
4976 The bit pattern given in insns[] has the COND_ALWAYS condition,
4977 and it is an error if the caller tried to override that. */
4978
4979 static void
4980 do_bkpt (char * str)
4981 {
4982 expressionS expr;
4983 unsigned long number;
4984
4985 skip_whitespace (str);
4986
4987 /* Allow optional leading '#'. */
4988 if (is_immediate_prefix (* str))
4989 str++;
4990
4991 memset (& expr, '\0', sizeof (expr));
4992
4993 if (my_get_expression (& expr, & str)
4994 || (expr.X_op != O_constant
4995 /* As a convenience we allow 'bkpt' without an operand. */
4996 && expr.X_op != O_absent))
4997 {
4998 inst.error = _("bad expression");
4999 return;
5000 }
5001
5002 number = expr.X_add_number;
5003
5004 /* Check it fits a 16 bit unsigned. */
5005 if (number != (number & 0xffff))
5006 {
5007 inst.error = _("immediate value out of range");
5008 return;
5009 }
5010
5011 /* Top 12 of 16 bits to bits 19:8. */
5012 inst.instruction |= (number & 0xfff0) << 4;
5013
5014 /* Bottom 4 of 16 bits to bits 3:0. */
5015 inst.instruction |= number & 0xf;
5016
5017 end_of_line (str);
5018 }
5019
5020 /* THUMB CPS instruction (argument parse). */
5021
5022 static void
5023 do_t_cps (char * str)
5024 {
5025 do_cps_flags (&str, /*thumb_p=*/1);
5026 end_of_line (str);
5027 }
5028
5029 /* Parse and validate that a register is of the right form, this saves
5030 repeated checking of this information in many similar cases.
5031 Unlike the 32-bit case we do not insert the register into the opcode
5032 here, since the position is often unknown until the full instruction
5033 has been parsed. */
5034
5035 static int
5036 thumb_reg (char ** strp, int hi_lo)
5037 {
5038 int reg;
5039
5040 if ((reg = reg_required_here (strp, -1)) == FAIL)
5041 return FAIL;
5042
5043 switch (hi_lo)
5044 {
5045 case THUMB_REG_LO:
5046 if (reg > 7)
5047 {
5048 inst.error = _("lo register required");
5049 return FAIL;
5050 }
5051 break;
5052
5053 case THUMB_REG_HI:
5054 if (reg < 8)
5055 {
5056 inst.error = _("hi register required");
5057 return FAIL;
5058 }
5059 break;
5060
5061 default:
5062 break;
5063 }
5064
5065 return reg;
5066 }
5067
5068 static void
5069 thumb_mov_compare (char * str, int move)
5070 {
5071 int Rd, Rs = FAIL;
5072
5073 skip_whitespace (str);
5074
5075 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
5076 || skip_past_comma (&str) == FAIL)
5077 {
5078 if (! inst.error)
5079 inst.error = BAD_ARGS;
5080 return;
5081 }
5082
5083 if (move != THUMB_CPY && is_immediate_prefix (*str))
5084 {
5085 str++;
5086 if (my_get_expression (&inst.reloc.exp, &str))
5087 return;
5088 }
5089 else if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
5090 return;
5091
5092 if (Rs != FAIL)
5093 {
5094 if (move != THUMB_CPY && Rs < 8 && Rd < 8)
5095 {
5096 if (move == THUMB_MOVE)
5097 /* A move of two lowregs is encoded as ADD Rd, Rs, #0
5098 since a MOV instruction produces unpredictable results. */
5099 inst.instruction = T_OPCODE_ADD_I3;
5100 else
5101 inst.instruction = T_OPCODE_CMP_LR;
5102 inst.instruction |= Rd | (Rs << 3);
5103 }
5104 else
5105 {
5106 if (move == THUMB_MOVE)
5107 inst.instruction = T_OPCODE_MOV_HR;
5108 else if (move != THUMB_CPY)
5109 inst.instruction = T_OPCODE_CMP_HR;
5110
5111 if (Rd > 7)
5112 inst.instruction |= THUMB_H1;
5113
5114 if (Rs > 7)
5115 inst.instruction |= THUMB_H2;
5116
5117 inst.instruction |= (Rd & 7) | ((Rs & 7) << 3);
5118 }
5119 }
5120 else
5121 {
5122 if (Rd > 7)
5123 {
5124 inst.error = _("only lo regs allowed with immediate");
5125 return;
5126 }
5127
5128 if (move == THUMB_MOVE)
5129 inst.instruction = T_OPCODE_MOV_I8;
5130 else
5131 inst.instruction = T_OPCODE_CMP_I8;
5132
5133 inst.instruction |= Rd << 8;
5134
5135 if (inst.reloc.exp.X_op != O_constant)
5136 inst.reloc.type = BFD_RELOC_ARM_THUMB_IMM;
5137 else
5138 {
5139 unsigned value = inst.reloc.exp.X_add_number;
5140
5141 if (value > 255)
5142 {
5143 inst.error = _("invalid immediate");
5144 return;
5145 }
5146
5147 inst.instruction |= value;
5148 }
5149 }
5150
5151 end_of_line (str);
5152 }
5153
5154 /* THUMB CPY instruction (argument parse). */
5155
5156 static void
5157 do_t_cpy (char * str)
5158 {
5159 thumb_mov_compare (str, THUMB_CPY);
5160 }
5161
5162 /* THUMB SETEND instruction (argument parse). */
5163
5164 static void
5165 do_t_setend (char * str)
5166 {
5167 if (do_endian_specifier (str))
5168 inst.instruction |= 0x8;
5169 }
5170
5171 /* Parse INSN_TYPE insn STR having a possible IMMEDIATE_SIZE immediate. */
5172
5173 static unsigned long
5174 check_iwmmxt_insn (char * str,
5175 enum iwmmxt_insn_type insn_type,
5176 int immediate_size)
5177 {
5178 int reg = 0;
5179 const char * inst_error;
5180 expressionS expr;
5181 unsigned long number;
5182
5183 inst_error = inst.error;
5184 if (!inst.error)
5185 inst.error = BAD_ARGS;
5186 skip_whitespace (str);
5187
5188 switch (insn_type)
5189 {
5190 case check_rd:
5191 if ((reg = reg_required_here (&str, 12)) == FAIL)
5192 return FAIL;
5193 break;
5194
5195 case check_wr:
5196 if ((wreg_required_here (&str, 0, IWMMXT_REG_WR)) == FAIL)
5197 return FAIL;
5198 break;
5199
5200 case check_wrwr:
5201 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
5202 || skip_past_comma (&str) == FAIL
5203 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL))
5204 return FAIL;
5205 break;
5206
5207 case check_wrwrwr:
5208 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
5209 || skip_past_comma (&str) == FAIL
5210 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5211 || skip_past_comma (&str) == FAIL
5212 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL))
5213 return FAIL;
5214 break;
5215
5216 case check_wrwrwcg:
5217 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
5218 || skip_past_comma (&str) == FAIL
5219 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5220 || skip_past_comma (&str) == FAIL
5221 || wreg_required_here (&str, 0, IWMMXT_REG_WCG) == FAIL))
5222 return FAIL;
5223 break;
5224
5225 case check_tbcst:
5226 if ((wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5227 || skip_past_comma (&str) == FAIL
5228 || reg_required_here (&str, 12) == FAIL))
5229 return FAIL;
5230 break;
5231
5232 case check_tmovmsk:
5233 if ((reg_required_here (&str, 12) == FAIL
5234 || skip_past_comma (&str) == FAIL
5235 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL))
5236 return FAIL;
5237 break;
5238
5239 case check_tmia:
5240 if ((wreg_required_here (&str, 5, IWMMXT_REG_WR) == FAIL
5241 || skip_past_comma (&str) == FAIL
5242 || reg_required_here (&str, 0) == FAIL
5243 || skip_past_comma (&str) == FAIL
5244 || reg_required_here (&str, 12) == FAIL))
5245 return FAIL;
5246 break;
5247
5248 case check_tmcrr:
5249 if ((wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL
5250 || skip_past_comma (&str) == FAIL
5251 || reg_required_here (&str, 12) == FAIL
5252 || skip_past_comma (&str) == FAIL
5253 || reg_required_here (&str, 16) == FAIL))
5254 return FAIL;
5255 break;
5256
5257 case check_tmrrc:
5258 if ((reg_required_here (&str, 12) == FAIL
5259 || skip_past_comma (&str) == FAIL
5260 || reg_required_here (&str, 16) == FAIL
5261 || skip_past_comma (&str) == FAIL
5262 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL))
5263 return FAIL;
5264 break;
5265
5266 case check_tmcr:
5267 if ((wreg_required_here (&str, 16, IWMMXT_REG_WC) == FAIL
5268 || skip_past_comma (&str) == FAIL
5269 || reg_required_here (&str, 12) == FAIL))
5270 return FAIL;
5271 break;
5272
5273 case check_tmrc:
5274 if ((reg_required_here (&str, 12) == FAIL
5275 || skip_past_comma (&str) == FAIL
5276 || wreg_required_here (&str, 16, IWMMXT_REG_WC) == FAIL))
5277 return FAIL;
5278 break;
5279
5280 case check_tinsr:
5281 if ((wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5282 || skip_past_comma (&str) == FAIL
5283 || reg_required_here (&str, 12) == FAIL
5284 || skip_past_comma (&str) == FAIL))
5285 return FAIL;
5286 break;
5287
5288 case check_textrc:
5289 if ((reg_required_here (&str, 12) == FAIL
5290 || skip_past_comma (&str) == FAIL))
5291 return FAIL;
5292 break;
5293
5294 case check_waligni:
5295 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
5296 || skip_past_comma (&str) == FAIL
5297 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5298 || skip_past_comma (&str) == FAIL
5299 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL
5300 || skip_past_comma (&str) == FAIL))
5301 return FAIL;
5302 break;
5303
5304 case check_textrm:
5305 if ((reg_required_here (&str, 12) == FAIL
5306 || skip_past_comma (&str) == FAIL
5307 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5308 || skip_past_comma (&str) == FAIL))
5309 return FAIL;
5310 break;
5311
5312 case check_wshufh:
5313 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
5314 || skip_past_comma (&str) == FAIL
5315 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5316 || skip_past_comma (&str) == FAIL))
5317 return FAIL;
5318 break;
5319 }
5320
5321 if (immediate_size == 0)
5322 {
5323 end_of_line (str);
5324 inst.error = inst_error;
5325 return reg;
5326 }
5327 else
5328 {
5329 skip_whitespace (str);
5330
5331 /* Allow optional leading '#'. */
5332 if (is_immediate_prefix (* str))
5333 str++;
5334
5335 memset (& expr, '\0', sizeof (expr));
5336
5337 if (my_get_expression (& expr, & str) || (expr.X_op != O_constant))
5338 {
5339 inst.error = _("bad or missing expression");
5340 return FAIL;
5341 }
5342
5343 number = expr.X_add_number;
5344
5345 if (number != (number & immediate_size))
5346 {
5347 inst.error = _("immediate value out of range");
5348 return FAIL;
5349 }
5350 end_of_line (str);
5351 inst.error = inst_error;
5352 return number;
5353 }
5354 }
5355
5356 static void
5357 do_iwmmxt_byte_addr (char * str)
5358 {
5359 int op = (inst.instruction & 0x300) >> 8;
5360 int reg;
5361
5362 inst.instruction &= ~0x300;
5363 inst.instruction |= (op & 1) << 22 | (op & 2) << 7;
5364
5365 skip_whitespace (str);
5366
5367 if ((reg = wreg_required_here (&str, 12, IWMMXT_REG_WR_OR_WC)) == FAIL
5368 || skip_past_comma (& str) == FAIL
5369 || cp_byte_address_required_here (&str) == FAIL)
5370 {
5371 if (! inst.error)
5372 inst.error = BAD_ARGS;
5373 }
5374 else
5375 end_of_line (str);
5376
5377 if (wc_register (reg))
5378 {
5379 as_bad (_("non-word size not supported with control register"));
5380 inst.instruction |= 0xf0000100;
5381 inst.instruction &= ~0x00400000;
5382 }
5383 }
5384
5385 static void
5386 do_iwmmxt_tandc (char * str)
5387 {
5388 int reg;
5389
5390 reg = check_iwmmxt_insn (str, check_rd, 0);
5391
5392 if (reg != REG_PC && !inst.error)
5393 inst.error = _("only r15 allowed here");
5394 }
5395
5396 static void
5397 do_iwmmxt_tbcst (char * str)
5398 {
5399 check_iwmmxt_insn (str, check_tbcst, 0);
5400 }
5401
5402 static void
5403 do_iwmmxt_textrc (char * str)
5404 {
5405 unsigned long number;
5406
5407 if ((number = check_iwmmxt_insn (str, check_textrc, 7)) == (unsigned long) FAIL)
5408 return;
5409
5410 inst.instruction |= number & 0x7;
5411 }
5412
5413 static void
5414 do_iwmmxt_textrm (char * str)
5415 {
5416 unsigned long number;
5417
5418 if ((number = check_iwmmxt_insn (str, check_textrm, 7)) == (unsigned long) FAIL)
5419 return;
5420
5421 inst.instruction |= number & 0x7;
5422 }
5423
5424 static void
5425 do_iwmmxt_tinsr (char * str)
5426 {
5427 unsigned long number;
5428
5429 if ((number = check_iwmmxt_insn (str, check_tinsr, 7)) == (unsigned long) FAIL)
5430 return;
5431
5432 inst.instruction |= number & 0x7;
5433 }
5434
5435 static void
5436 do_iwmmxt_tmcr (char * str)
5437 {
5438 check_iwmmxt_insn (str, check_tmcr, 0);
5439 }
5440
5441 static void
5442 do_iwmmxt_tmcrr (char * str)
5443 {
5444 check_iwmmxt_insn (str, check_tmcrr, 0);
5445 }
5446
5447 static void
5448 do_iwmmxt_tmia (char * str)
5449 {
5450 check_iwmmxt_insn (str, check_tmia, 0);
5451 }
5452
5453 static void
5454 do_iwmmxt_tmovmsk (char * str)
5455 {
5456 check_iwmmxt_insn (str, check_tmovmsk, 0);
5457 }
5458
5459 static void
5460 do_iwmmxt_tmrc (char * str)
5461 {
5462 check_iwmmxt_insn (str, check_tmrc, 0);
5463 }
5464
5465 static void
5466 do_iwmmxt_tmrrc (char * str)
5467 {
5468 check_iwmmxt_insn (str, check_tmrrc, 0);
5469 }
5470
5471 static void
5472 do_iwmmxt_torc (char * str)
5473 {
5474 check_iwmmxt_insn (str, check_rd, 0);
5475 }
5476
5477 static void
5478 do_iwmmxt_waligni (char * str)
5479 {
5480 unsigned long number;
5481
5482 if ((number = check_iwmmxt_insn (str, check_waligni, 7)) == (unsigned long) FAIL)
5483 return;
5484
5485 inst.instruction |= ((number & 0x7) << 20);
5486 }
5487
5488 static void
5489 do_iwmmxt_wmov (char * str)
5490 {
5491 if (check_iwmmxt_insn (str, check_wrwr, 0) == (unsigned long) FAIL)
5492 return;
5493
5494 inst.instruction |= ((inst.instruction >> 16) & 0xf);
5495 }
5496
5497 static void
5498 do_iwmmxt_word_addr (char * str)
5499 {
5500 int op = (inst.instruction & 0x300) >> 8;
5501 int reg;
5502
5503 inst.instruction &= ~0x300;
5504 inst.instruction |= (op & 1) << 22 | (op & 2) << 7;
5505
5506 skip_whitespace (str);
5507
5508 if ((reg = wreg_required_here (&str, 12, IWMMXT_REG_WR_OR_WC)) == FAIL
5509 || skip_past_comma (& str) == FAIL
5510 || cp_address_required_here (& str, CP_WB_OK) == FAIL)
5511 {
5512 if (! inst.error)
5513 inst.error = BAD_ARGS;
5514 }
5515 else
5516 end_of_line (str);
5517
5518 if (wc_register (reg))
5519 {
5520 if ((inst.instruction & COND_MASK) != COND_ALWAYS)
5521 as_bad (_("conditional execution not supported with control register"));
5522 if (op != 2)
5523 as_bad (_("non-word size not supported with control register"));
5524 inst.instruction |= 0xf0000100;
5525 inst.instruction &= ~0x00400000;
5526 }
5527 }
5528
5529 static void
5530 do_iwmmxt_wrwr (char * str)
5531 {
5532 check_iwmmxt_insn (str, check_wrwr, 0);
5533 }
5534
5535 static void
5536 do_iwmmxt_wrwrwcg (char * str)
5537 {
5538 check_iwmmxt_insn (str, check_wrwrwcg, 0);
5539 }
5540
5541 static void
5542 do_iwmmxt_wrwrwr (char * str)
5543 {
5544 check_iwmmxt_insn (str, check_wrwrwr, 0);
5545 }
5546
5547 static void
5548 do_iwmmxt_wshufh (char * str)
5549 {
5550 unsigned long number;
5551
5552 if ((number = check_iwmmxt_insn (str, check_wshufh, 0xff)) == (unsigned long) FAIL)
5553 return;
5554
5555 inst.instruction |= ((number & 0xf0) << 16) | (number & 0xf);
5556 }
5557
5558 static void
5559 do_iwmmxt_wzero (char * str)
5560 {
5561 if (check_iwmmxt_insn (str, check_wr, 0) == (unsigned long) FAIL)
5562 return;
5563
5564 inst.instruction |= ((inst.instruction & 0xf) << 12) | ((inst.instruction & 0xf) << 16);
5565 }
5566
5567 /* Xscale multiply-accumulate (argument parse)
5568 MIAcc acc0,Rm,Rs
5569 MIAPHcc acc0,Rm,Rs
5570 MIAxycc acc0,Rm,Rs. */
5571
5572 static void
5573 do_xsc_mia (char * str)
5574 {
5575 int rs;
5576 int rm;
5577
5578 if (accum0_required_here (& str) == FAIL)
5579 inst.error = ERR_NO_ACCUM;
5580
5581 else if (skip_past_comma (& str) == FAIL
5582 || (rm = reg_required_here (& str, 0)) == FAIL)
5583 inst.error = BAD_ARGS;
5584
5585 else if (skip_past_comma (& str) == FAIL
5586 || (rs = reg_required_here (& str, 12)) == FAIL)
5587 inst.error = BAD_ARGS;
5588
5589 /* inst.instruction has now been zapped with both rm and rs. */
5590 else if (rm == REG_PC || rs == REG_PC)
5591 inst.error = BAD_PC; /* Undefined result if rm or rs is R15. */
5592
5593 else
5594 end_of_line (str);
5595 }
5596
5597 /* Xscale move-accumulator-register (argument parse)
5598
5599 MARcc acc0,RdLo,RdHi. */
5600
5601 static void
5602 do_xsc_mar (char * str)
5603 {
5604 int rdlo, rdhi;
5605
5606 if (accum0_required_here (& str) == FAIL)
5607 inst.error = ERR_NO_ACCUM;
5608
5609 else if (skip_past_comma (& str) == FAIL
5610 || (rdlo = reg_required_here (& str, 12)) == FAIL)
5611 inst.error = BAD_ARGS;
5612
5613 else if (skip_past_comma (& str) == FAIL
5614 || (rdhi = reg_required_here (& str, 16)) == FAIL)
5615 inst.error = BAD_ARGS;
5616
5617 /* inst.instruction has now been zapped with both rdlo and rdhi. */
5618 else if (rdlo == REG_PC || rdhi == REG_PC)
5619 inst.error = BAD_PC; /* Undefined result if rdlo or rdhi is R15. */
5620
5621 else
5622 end_of_line (str);
5623 }
5624
5625 /* Xscale move-register-accumulator (argument parse)
5626
5627 MRAcc RdLo,RdHi,acc0. */
5628
5629 static void
5630 do_xsc_mra (char * str)
5631 {
5632 int rdlo;
5633 int rdhi;
5634
5635 skip_whitespace (str);
5636
5637 if ((rdlo = reg_required_here (& str, 12)) == FAIL)
5638 inst.error = BAD_ARGS;
5639
5640 else if (skip_past_comma (& str) == FAIL
5641 || (rdhi = reg_required_here (& str, 16)) == FAIL)
5642 inst.error = BAD_ARGS;
5643
5644 else if (skip_past_comma (& str) == FAIL
5645 || accum0_required_here (& str) == FAIL)
5646 inst.error = ERR_NO_ACCUM;
5647
5648 /* inst.instruction has now been zapped with both rdlo and rdhi. */
5649 else if (rdlo == rdhi)
5650 inst.error = BAD_ARGS; /* Undefined result if 2 writes to same reg. */
5651
5652 else if (rdlo == REG_PC || rdhi == REG_PC)
5653 inst.error = BAD_PC; /* Undefined result if rdlo or rdhi is R15. */
5654 else
5655 end_of_line (str);
5656 }
5657
5658 static int
5659 ldst_extend (char ** str)
5660 {
5661 int add = INDEX_UP;
5662
5663 switch (**str)
5664 {
5665 case '#':
5666 case '$':
5667 (*str)++;
5668 if (my_get_expression (& inst.reloc.exp, str))
5669 return FAIL;
5670
5671 if (inst.reloc.exp.X_op == O_constant)
5672 {
5673 int value = inst.reloc.exp.X_add_number;
5674
5675 if (value < -4095 || value > 4095)
5676 {
5677 inst.error = _("address offset too large");
5678 return FAIL;
5679 }
5680
5681 if (value < 0)
5682 {
5683 value = -value;
5684 add = 0;
5685 }
5686
5687 inst.instruction |= add | value;
5688 }
5689 else
5690 {
5691 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
5692 inst.reloc.pc_rel = 0;
5693 }
5694 return SUCCESS;
5695
5696 case '-':
5697 add = 0;
5698 /* Fall through. */
5699
5700 case '+':
5701 (*str)++;
5702 /* Fall through. */
5703
5704 default:
5705 if (reg_required_here (str, 0) == FAIL)
5706 return FAIL;
5707
5708 inst.instruction |= add | OFFSET_REG;
5709 if (skip_past_comma (str) == SUCCESS)
5710 return decode_shift (str, SHIFT_IMMEDIATE);
5711
5712 return SUCCESS;
5713 }
5714 }
5715
5716 /* ARMv5TE: Preload-Cache
5717
5718 PLD <addr_mode>
5719
5720 Syntactically, like LDR with B=1, W=0, L=1. */
5721
5722 static void
5723 do_pld (char * str)
5724 {
5725 int rd;
5726
5727 skip_whitespace (str);
5728
5729 if (* str != '[')
5730 {
5731 inst.error = _("'[' expected after PLD mnemonic");
5732 return;
5733 }
5734
5735 ++str;
5736 skip_whitespace (str);
5737
5738 if ((rd = reg_required_here (& str, 16)) == FAIL)
5739 return;
5740
5741 skip_whitespace (str);
5742
5743 if (*str == ']')
5744 {
5745 /* [Rn], ... ? */
5746 ++str;
5747 skip_whitespace (str);
5748
5749 /* Post-indexed addressing is not allowed with PLD. */
5750 if (skip_past_comma (&str) == SUCCESS)
5751 {
5752 inst.error
5753 = _("post-indexed expression used in preload instruction");
5754 return;
5755 }
5756 else if (*str == '!') /* [Rn]! */
5757 {
5758 inst.error = _("writeback used in preload instruction");
5759 ++str;
5760 }
5761 else /* [Rn] */
5762 inst.instruction |= INDEX_UP | PRE_INDEX;
5763 }
5764 else /* [Rn, ...] */
5765 {
5766 if (skip_past_comma (& str) == FAIL)
5767 {
5768 inst.error = _("pre-indexed expression expected");
5769 return;
5770 }
5771
5772 if (ldst_extend (&str) == FAIL)
5773 return;
5774
5775 skip_whitespace (str);
5776
5777 if (* str != ']')
5778 {
5779 inst.error = _("missing ]");
5780 return;
5781 }
5782
5783 ++ str;
5784 skip_whitespace (str);
5785
5786 if (* str == '!') /* [Rn]! */
5787 {
5788 inst.error = _("writeback used in preload instruction");
5789 ++ str;
5790 }
5791
5792 inst.instruction |= PRE_INDEX;
5793 }
5794
5795 end_of_line (str);
5796 }
5797
5798 /* ARMv5TE load-consecutive (argument parse)
5799 Mode is like LDRH.
5800
5801 LDRccD R, mode
5802 STRccD R, mode. */
5803
5804 static void
5805 do_ldrd (char * str)
5806 {
5807 int rd;
5808 int rn;
5809
5810 skip_whitespace (str);
5811
5812 if ((rd = reg_required_here (& str, 12)) == FAIL)
5813 {
5814 inst.error = BAD_ARGS;
5815 return;
5816 }
5817
5818 if (skip_past_comma (& str) == FAIL
5819 || (rn = ld_mode_required_here (& str)) == FAIL)
5820 {
5821 if (!inst.error)
5822 inst.error = BAD_ARGS;
5823 return;
5824 }
5825
5826 /* inst.instruction has now been zapped with Rd and the addressing mode. */
5827 if (rd & 1) /* Unpredictable result if Rd is odd. */
5828 {
5829 inst.error = _("destination register must be even");
5830 return;
5831 }
5832
5833 if (rd == REG_LR)
5834 {
5835 inst.error = _("r14 not allowed here");
5836 return;
5837 }
5838
5839 if (((rd == rn) || (rd + 1 == rn))
5840 && ((inst.instruction & WRITE_BACK)
5841 || (!(inst.instruction & PRE_INDEX))))
5842 as_warn (_("pre/post-indexing used when modified address register is destination"));
5843
5844 /* For an index-register load, the index register must not overlap the
5845 destination (even if not write-back). */
5846 if ((inst.instruction & V4_STR_BIT) == 0
5847 && (inst.instruction & HWOFFSET_IMM) == 0)
5848 {
5849 int rm = inst.instruction & 0x0000000f;
5850
5851 if (rm == rd || (rm == rd + 1))
5852 as_warn (_("ldrd destination registers must not overlap index register"));
5853 }
5854
5855 end_of_line (str);
5856 }
5857
5858 /* Returns the index into fp_values of a floating point number,
5859 or -1 if not in the table. */
5860
5861 static int
5862 my_get_float_expression (char ** str)
5863 {
5864 LITTLENUM_TYPE words[MAX_LITTLENUMS];
5865 char * save_in;
5866 expressionS exp;
5867 int i;
5868 int j;
5869
5870 memset (words, 0, MAX_LITTLENUMS * sizeof (LITTLENUM_TYPE));
5871
5872 /* Look for a raw floating point number. */
5873 if ((save_in = atof_ieee (*str, 'x', words)) != NULL
5874 && is_end_of_line[(unsigned char) *save_in])
5875 {
5876 for (i = 0; i < NUM_FLOAT_VALS; i++)
5877 {
5878 for (j = 0; j < MAX_LITTLENUMS; j++)
5879 {
5880 if (words[j] != fp_values[i][j])
5881 break;
5882 }
5883
5884 if (j == MAX_LITTLENUMS)
5885 {
5886 *str = save_in;
5887 return i;
5888 }
5889 }
5890 }
5891
5892 /* Try and parse a more complex expression, this will probably fail
5893 unless the code uses a floating point prefix (eg "0f"). */
5894 save_in = input_line_pointer;
5895 input_line_pointer = *str;
5896 if (expression (&exp) == absolute_section
5897 && exp.X_op == O_big
5898 && exp.X_add_number < 0)
5899 {
5900 /* FIXME: 5 = X_PRECISION, should be #define'd where we can use it.
5901 Ditto for 15. */
5902 if (gen_to_words (words, 5, (long) 15) == 0)
5903 {
5904 for (i = 0; i < NUM_FLOAT_VALS; i++)
5905 {
5906 for (j = 0; j < MAX_LITTLENUMS; j++)
5907 {
5908 if (words[j] != fp_values[i][j])
5909 break;
5910 }
5911
5912 if (j == MAX_LITTLENUMS)
5913 {
5914 *str = input_line_pointer;
5915 input_line_pointer = save_in;
5916 return i;
5917 }
5918 }
5919 }
5920 }
5921
5922 *str = input_line_pointer;
5923 input_line_pointer = save_in;
5924 return -1;
5925 }
5926
5927 /* We handle all bad expressions here, so that we can report the faulty
5928 instruction in the error message. */
5929 void
5930 md_operand (expressionS * expr)
5931 {
5932 if (in_my_get_expression)
5933 {
5934 expr->X_op = O_illegal;
5935 if (inst.error == NULL)
5936 inst.error = _("bad expression");
5937 }
5938 }
5939
5940 /* Do those data_ops which can take a negative immediate constant
5941 by altering the instruction. A bit of a hack really.
5942 MOV <-> MVN
5943 AND <-> BIC
5944 ADC <-> SBC
5945 by inverting the second operand, and
5946 ADD <-> SUB
5947 CMP <-> CMN
5948 by negating the second operand. */
5949
5950 static int
5951 negate_data_op (unsigned long * instruction,
5952 unsigned long value)
5953 {
5954 int op, new_inst;
5955 unsigned long negated, inverted;
5956
5957 negated = validate_immediate (-value);
5958 inverted = validate_immediate (~value);
5959
5960 op = (*instruction >> DATA_OP_SHIFT) & 0xf;
5961 switch (op)
5962 {
5963 /* First negates. */
5964 case OPCODE_SUB: /* ADD <-> SUB */
5965 new_inst = OPCODE_ADD;
5966 value = negated;
5967 break;
5968
5969 case OPCODE_ADD:
5970 new_inst = OPCODE_SUB;
5971 value = negated;
5972 break;
5973
5974 case OPCODE_CMP: /* CMP <-> CMN */
5975 new_inst = OPCODE_CMN;
5976 value = negated;
5977 break;
5978
5979 case OPCODE_CMN:
5980 new_inst = OPCODE_CMP;
5981 value = negated;
5982 break;
5983
5984 /* Now Inverted ops. */
5985 case OPCODE_MOV: /* MOV <-> MVN */
5986 new_inst = OPCODE_MVN;
5987 value = inverted;
5988 break;
5989
5990 case OPCODE_MVN:
5991 new_inst = OPCODE_MOV;
5992 value = inverted;
5993 break;
5994
5995 case OPCODE_AND: /* AND <-> BIC */
5996 new_inst = OPCODE_BIC;
5997 value = inverted;
5998 break;
5999
6000 case OPCODE_BIC:
6001 new_inst = OPCODE_AND;
6002 value = inverted;
6003 break;
6004
6005 case OPCODE_ADC: /* ADC <-> SBC */
6006 new_inst = OPCODE_SBC;
6007 value = inverted;
6008 break;
6009
6010 case OPCODE_SBC:
6011 new_inst = OPCODE_ADC;
6012 value = inverted;
6013 break;
6014
6015 /* We cannot do anything. */
6016 default:
6017 return FAIL;
6018 }
6019
6020 if (value == (unsigned) FAIL)
6021 return FAIL;
6022
6023 *instruction &= OPCODE_MASK;
6024 *instruction |= new_inst << DATA_OP_SHIFT;
6025 return value;
6026 }
6027
6028 static int
6029 data_op2 (char ** str)
6030 {
6031 int value;
6032 expressionS expr;
6033
6034 skip_whitespace (* str);
6035
6036 if (reg_required_here (str, 0) != FAIL)
6037 {
6038 if (skip_past_comma (str) == SUCCESS)
6039 /* Shift operation on register. */
6040 return decode_shift (str, NO_SHIFT_RESTRICT);
6041
6042 return SUCCESS;
6043 }
6044 else
6045 {
6046 /* Immediate expression. */
6047 if (is_immediate_prefix (**str))
6048 {
6049 (*str)++;
6050 inst.error = NULL;
6051
6052 if (my_get_expression (&inst.reloc.exp, str))
6053 return FAIL;
6054
6055 if (inst.reloc.exp.X_add_symbol)
6056 {
6057 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
6058 inst.reloc.pc_rel = 0;
6059 }
6060 else
6061 {
6062 if (skip_past_comma (str) == SUCCESS)
6063 {
6064 /* #x, y -- ie explicit rotation by Y. */
6065 if (my_get_expression (&expr, str))
6066 return FAIL;
6067
6068 if (expr.X_op != O_constant)
6069 {
6070 inst.error = _("constant expression expected");
6071 return FAIL;
6072 }
6073
6074 /* Rotate must be a multiple of 2. */
6075 if (((unsigned) expr.X_add_number) > 30
6076 || (expr.X_add_number & 1) != 0
6077 || ((unsigned) inst.reloc.exp.X_add_number) > 255)
6078 {
6079 inst.error = _("invalid constant");
6080 return FAIL;
6081 }
6082 inst.instruction |= INST_IMMEDIATE;
6083 inst.instruction |= inst.reloc.exp.X_add_number;
6084 inst.instruction |= expr.X_add_number << 7;
6085 return SUCCESS;
6086 }
6087
6088 /* Implicit rotation, select a suitable one. */
6089 value = validate_immediate (inst.reloc.exp.X_add_number);
6090
6091 if (value == FAIL)
6092 {
6093 /* Can't be done. Perhaps the code reads something like
6094 "add Rd, Rn, #-n", where "sub Rd, Rn, #n" would be OK. */
6095 if ((value = negate_data_op (&inst.instruction,
6096 inst.reloc.exp.X_add_number))
6097 == FAIL)
6098 {
6099 inst.error = _("invalid constant");
6100 return FAIL;
6101 }
6102 }
6103
6104 inst.instruction |= value;
6105 }
6106
6107 inst.instruction |= INST_IMMEDIATE;
6108 return SUCCESS;
6109 }
6110
6111 (*str)++;
6112 inst.error = _("register or shift expression expected");
6113 return FAIL;
6114 }
6115 }
6116
6117 static int
6118 fp_op2 (char ** str)
6119 {
6120 skip_whitespace (* str);
6121
6122 if (fp_reg_required_here (str, 0) != FAIL)
6123 return SUCCESS;
6124 else
6125 {
6126 /* Immediate expression. */
6127 if (*((*str)++) == '#')
6128 {
6129 int i;
6130
6131 inst.error = NULL;
6132
6133 skip_whitespace (* str);
6134
6135 /* First try and match exact strings, this is to guarantee
6136 that some formats will work even for cross assembly. */
6137
6138 for (i = 0; fp_const[i]; i++)
6139 {
6140 if (strncmp (*str, fp_const[i], strlen (fp_const[i])) == 0)
6141 {
6142 char *start = *str;
6143
6144 *str += strlen (fp_const[i]);
6145 if (is_end_of_line[(unsigned char) **str])
6146 {
6147 inst.instruction |= i + 8;
6148 return SUCCESS;
6149 }
6150 *str = start;
6151 }
6152 }
6153
6154 /* Just because we didn't get a match doesn't mean that the
6155 constant isn't valid, just that it is in a format that we
6156 don't automatically recognize. Try parsing it with
6157 the standard expression routines. */
6158 if ((i = my_get_float_expression (str)) >= 0)
6159 {
6160 inst.instruction |= i + 8;
6161 return SUCCESS;
6162 }
6163
6164 inst.error = _("invalid floating point immediate expression");
6165 return FAIL;
6166 }
6167 inst.error =
6168 _("floating point register or immediate expression expected");
6169 return FAIL;
6170 }
6171 }
6172
6173 static void
6174 do_arit (char * str)
6175 {
6176 skip_whitespace (str);
6177
6178 if (reg_required_here (&str, 12) == FAIL
6179 || skip_past_comma (&str) == FAIL
6180 || reg_required_here (&str, 16) == FAIL
6181 || skip_past_comma (&str) == FAIL
6182 || data_op2 (&str) == FAIL)
6183 {
6184 if (!inst.error)
6185 inst.error = BAD_ARGS;
6186 return;
6187 }
6188
6189 end_of_line (str);
6190 }
6191
6192 static void
6193 do_adr (char * str)
6194 {
6195 /* This is a pseudo-op of the form "adr rd, label" to be converted
6196 into a relative address of the form "add rd, pc, #label-.-8". */
6197 skip_whitespace (str);
6198
6199 if (reg_required_here (&str, 12) == FAIL
6200 || skip_past_comma (&str) == FAIL
6201 || my_get_expression (&inst.reloc.exp, &str))
6202 {
6203 if (!inst.error)
6204 inst.error = BAD_ARGS;
6205 return;
6206 }
6207
6208 /* Frag hacking will turn this into a sub instruction if the offset turns
6209 out to be negative. */
6210 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
6211 #ifndef TE_WINCE
6212 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust. */
6213 #endif
6214 inst.reloc.pc_rel = 1;
6215
6216 end_of_line (str);
6217 }
6218
6219 static void
6220 do_adrl (char * str)
6221 {
6222 /* This is a pseudo-op of the form "adrl rd, label" to be converted
6223 into a relative address of the form:
6224 add rd, pc, #low(label-.-8)"
6225 add rd, rd, #high(label-.-8)" */
6226
6227 skip_whitespace (str);
6228
6229 if (reg_required_here (&str, 12) == FAIL
6230 || skip_past_comma (&str) == FAIL
6231 || my_get_expression (&inst.reloc.exp, &str))
6232 {
6233 if (!inst.error)
6234 inst.error = BAD_ARGS;
6235
6236 return;
6237 }
6238
6239 end_of_line (str);
6240 /* Frag hacking will turn this into a sub instruction if the offset turns
6241 out to be negative. */
6242 inst.reloc.type = BFD_RELOC_ARM_ADRL_IMMEDIATE;
6243 #ifndef TE_WINCE
6244 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust */
6245 #endif
6246 inst.reloc.pc_rel = 1;
6247 inst.size = INSN_SIZE * 2;
6248 }
6249
6250 static void
6251 do_cmp (char * str)
6252 {
6253 skip_whitespace (str);
6254
6255 if (reg_required_here (&str, 16) == FAIL)
6256 {
6257 if (!inst.error)
6258 inst.error = BAD_ARGS;
6259 return;
6260 }
6261
6262 if (skip_past_comma (&str) == FAIL
6263 || data_op2 (&str) == FAIL)
6264 {
6265 if (!inst.error)
6266 inst.error = BAD_ARGS;
6267 return;
6268 }
6269
6270 end_of_line (str);
6271 }
6272
6273 static void
6274 do_mov (char * str)
6275 {
6276 skip_whitespace (str);
6277
6278 if (reg_required_here (&str, 12) == FAIL)
6279 {
6280 if (!inst.error)
6281 inst.error = BAD_ARGS;
6282 return;
6283 }
6284
6285 if (skip_past_comma (&str) == FAIL
6286 || data_op2 (&str) == FAIL)
6287 {
6288 if (!inst.error)
6289 inst.error = BAD_ARGS;
6290 return;
6291 }
6292
6293 end_of_line (str);
6294 }
6295
6296 static void
6297 do_ldst (char * str)
6298 {
6299 int pre_inc = 0;
6300 int conflict_reg;
6301 int value;
6302
6303 skip_whitespace (str);
6304
6305 if ((conflict_reg = reg_required_here (&str, 12)) == FAIL)
6306 {
6307 if (!inst.error)
6308 inst.error = BAD_ARGS;
6309 return;
6310 }
6311
6312 if (skip_past_comma (&str) == FAIL)
6313 {
6314 inst.error = _("address expected");
6315 return;
6316 }
6317
6318 if (*str == '[')
6319 {
6320 int reg;
6321
6322 str++;
6323
6324 skip_whitespace (str);
6325
6326 if ((reg = reg_required_here (&str, 16)) == FAIL)
6327 return;
6328
6329 /* Conflicts can occur on stores as well as loads. */
6330 conflict_reg = (conflict_reg == reg);
6331
6332 skip_whitespace (str);
6333
6334 if (*str == ']')
6335 {
6336 str ++;
6337
6338 if (skip_past_comma (&str) == SUCCESS)
6339 {
6340 /* [Rn],... (post inc) */
6341 if (ldst_extend (&str) == FAIL)
6342 return;
6343 if (conflict_reg)
6344 as_warn (_("%s register same as write-back base"),
6345 ((inst.instruction & LOAD_BIT)
6346 ? _("destination") : _("source")));
6347 }
6348 else
6349 {
6350 /* [Rn] */
6351 skip_whitespace (str);
6352
6353 if (*str == '!')
6354 {
6355 if (conflict_reg)
6356 as_warn (_("%s register same as write-back base"),
6357 ((inst.instruction & LOAD_BIT)
6358 ? _("destination") : _("source")));
6359 str++;
6360 inst.instruction |= WRITE_BACK;
6361 }
6362
6363 inst.instruction |= INDEX_UP;
6364 pre_inc = 1;
6365 }
6366 }
6367 else
6368 {
6369 /* [Rn,...] */
6370 if (skip_past_comma (&str) == FAIL)
6371 {
6372 inst.error = _("pre-indexed expression expected");
6373 return;
6374 }
6375
6376 pre_inc = 1;
6377 if (ldst_extend (&str) == FAIL)
6378 return;
6379
6380 skip_whitespace (str);
6381
6382 if (*str++ != ']')
6383 {
6384 inst.error = _("missing ]");
6385 return;
6386 }
6387
6388 skip_whitespace (str);
6389
6390 if (*str == '!')
6391 {
6392 if (conflict_reg)
6393 as_warn (_("%s register same as write-back base"),
6394 ((inst.instruction & LOAD_BIT)
6395 ? _("destination") : _("source")));
6396 str++;
6397 inst.instruction |= WRITE_BACK;
6398 }
6399 }
6400 }
6401 else if (*str == '=')
6402 {
6403 if ((inst.instruction & LOAD_BIT) == 0)
6404 {
6405 inst.error = _("invalid pseudo operation");
6406 return;
6407 }
6408
6409 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
6410 str++;
6411
6412 skip_whitespace (str);
6413
6414 if (my_get_expression (&inst.reloc.exp, &str))
6415 return;
6416
6417 if (inst.reloc.exp.X_op != O_constant
6418 && inst.reloc.exp.X_op != O_symbol)
6419 {
6420 inst.error = _("constant expression expected");
6421 return;
6422 }
6423
6424 if (inst.reloc.exp.X_op == O_constant)
6425 {
6426 value = validate_immediate (inst.reloc.exp.X_add_number);
6427
6428 if (value != FAIL)
6429 {
6430 /* This can be done with a mov instruction. */
6431 inst.instruction &= LITERAL_MASK;
6432 inst.instruction |= (INST_IMMEDIATE
6433 | (OPCODE_MOV << DATA_OP_SHIFT));
6434 inst.instruction |= value & 0xfff;
6435 end_of_line (str);
6436 return;
6437 }
6438
6439 value = validate_immediate (~inst.reloc.exp.X_add_number);
6440
6441 if (value != FAIL)
6442 {
6443 /* This can be done with a mvn instruction. */
6444 inst.instruction &= LITERAL_MASK;
6445 inst.instruction |= (INST_IMMEDIATE
6446 | (OPCODE_MVN << DATA_OP_SHIFT));
6447 inst.instruction |= value & 0xfff;
6448 end_of_line (str);
6449 return;
6450 }
6451 }
6452
6453 /* Insert into literal pool. */
6454 if (add_to_lit_pool () == FAIL)
6455 {
6456 if (!inst.error)
6457 inst.error = _("literal pool insertion failed");
6458 return;
6459 }
6460
6461 /* Change the instruction exp to point to the pool. */
6462 inst.reloc.type = BFD_RELOC_ARM_LITERAL;
6463 inst.reloc.pc_rel = 1;
6464 inst.instruction |= (REG_PC << 16);
6465 pre_inc = 1;
6466 }
6467 else
6468 {
6469 if (my_get_expression (&inst.reloc.exp, &str))
6470 return;
6471
6472 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
6473 #ifndef TE_WINCE
6474 /* PC rel adjust. */
6475 inst.reloc.exp.X_add_number -= 8;
6476 #endif
6477 inst.reloc.pc_rel = 1;
6478 inst.instruction |= (REG_PC << 16);
6479 pre_inc = 1;
6480 }
6481
6482 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
6483 end_of_line (str);
6484 }
6485
6486 static void
6487 do_ldstt (char * str)
6488 {
6489 int conflict_reg;
6490
6491 skip_whitespace (str);
6492
6493 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
6494 {
6495 if (!inst.error)
6496 inst.error = BAD_ARGS;
6497 return;
6498 }
6499
6500 if (skip_past_comma (& str) == FAIL)
6501 {
6502 inst.error = _("address expected");
6503 return;
6504 }
6505
6506 if (*str == '[')
6507 {
6508 int reg;
6509
6510 str++;
6511
6512 skip_whitespace (str);
6513
6514 if ((reg = reg_required_here (&str, 16)) == FAIL)
6515 return;
6516
6517 /* ldrt/strt always use post-indexed addressing, so if the base is
6518 the same as Rd, we warn. */
6519 if (conflict_reg == reg)
6520 as_warn (_("%s register same as write-back base"),
6521 ((inst.instruction & LOAD_BIT)
6522 ? _("destination") : _("source")));
6523
6524 skip_whitespace (str);
6525
6526 if (*str == ']')
6527 {
6528 str ++;
6529
6530 if (skip_past_comma (&str) == SUCCESS)
6531 {
6532 /* [Rn],... (post inc) */
6533 if (ldst_extend (&str) == FAIL)
6534 return;
6535 }
6536 else
6537 {
6538 /* [Rn] */
6539 skip_whitespace (str);
6540
6541 /* Skip a write-back '!'. */
6542 if (*str == '!')
6543 str++;
6544
6545 inst.instruction |= INDEX_UP;
6546 }
6547 }
6548 else
6549 {
6550 inst.error = _("post-indexed expression expected");
6551 return;
6552 }
6553 }
6554 else
6555 {
6556 inst.error = _("post-indexed expression expected");
6557 return;
6558 }
6559
6560 end_of_line (str);
6561 }
6562
6563 /* Halfword and signed-byte load/store operations. */
6564
6565 static void
6566 do_ldstv4 (char * str)
6567 {
6568 int pre_inc = 0;
6569 int conflict_reg;
6570 int value;
6571
6572 skip_whitespace (str);
6573
6574 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
6575 {
6576 if (!inst.error)
6577 inst.error = BAD_ARGS;
6578 return;
6579 }
6580
6581 if (skip_past_comma (& str) == FAIL)
6582 {
6583 inst.error = _("address expected");
6584 return;
6585 }
6586
6587 if (*str == '[')
6588 {
6589 int reg;
6590
6591 str++;
6592
6593 skip_whitespace (str);
6594
6595 if ((reg = reg_required_here (&str, 16)) == FAIL)
6596 return;
6597
6598 /* Conflicts can occur on stores as well as loads. */
6599 conflict_reg = (conflict_reg == reg);
6600
6601 skip_whitespace (str);
6602
6603 if (*str == ']')
6604 {
6605 str ++;
6606
6607 if (skip_past_comma (&str) == SUCCESS)
6608 {
6609 /* [Rn],... (post inc) */
6610 if (ldst_extend_v4 (&str) == FAIL)
6611 return;
6612 if (conflict_reg)
6613 as_warn (_("%s register same as write-back base"),
6614 ((inst.instruction & LOAD_BIT)
6615 ? _("destination") : _("source")));
6616 }
6617 else
6618 {
6619 /* [Rn] */
6620 inst.instruction |= HWOFFSET_IMM;
6621
6622 skip_whitespace (str);
6623
6624 if (*str == '!')
6625 {
6626 if (conflict_reg)
6627 as_warn (_("%s register same as write-back base"),
6628 ((inst.instruction & LOAD_BIT)
6629 ? _("destination") : _("source")));
6630 str++;
6631 inst.instruction |= WRITE_BACK;
6632 }
6633
6634 inst.instruction |= INDEX_UP;
6635 pre_inc = 1;
6636 }
6637 }
6638 else
6639 {
6640 /* [Rn,...] */
6641 if (skip_past_comma (&str) == FAIL)
6642 {
6643 inst.error = _("pre-indexed expression expected");
6644 return;
6645 }
6646
6647 pre_inc = 1;
6648 if (ldst_extend_v4 (&str) == FAIL)
6649 return;
6650
6651 skip_whitespace (str);
6652
6653 if (*str++ != ']')
6654 {
6655 inst.error = _("missing ]");
6656 return;
6657 }
6658
6659 skip_whitespace (str);
6660
6661 if (*str == '!')
6662 {
6663 if (conflict_reg)
6664 as_warn (_("%s register same as write-back base"),
6665 ((inst.instruction & LOAD_BIT)
6666 ? _("destination") : _("source")));
6667 str++;
6668 inst.instruction |= WRITE_BACK;
6669 }
6670 }
6671 }
6672 else if (*str == '=')
6673 {
6674 if ((inst.instruction & LOAD_BIT) == 0)
6675 {
6676 inst.error = _("invalid pseudo operation");
6677 return;
6678 }
6679
6680 /* XXX Does this work correctly for half-word/byte ops? */
6681 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
6682 str++;
6683
6684 skip_whitespace (str);
6685
6686 if (my_get_expression (&inst.reloc.exp, &str))
6687 return;
6688
6689 if (inst.reloc.exp.X_op != O_constant
6690 && inst.reloc.exp.X_op != O_symbol)
6691 {
6692 inst.error = _("constant expression expected");
6693 return;
6694 }
6695
6696 if (inst.reloc.exp.X_op == O_constant)
6697 {
6698 value = validate_immediate (inst.reloc.exp.X_add_number);
6699
6700 if (value != FAIL)
6701 {
6702 /* This can be done with a mov instruction. */
6703 inst.instruction &= LITERAL_MASK;
6704 inst.instruction |= INST_IMMEDIATE | (OPCODE_MOV << DATA_OP_SHIFT);
6705 inst.instruction |= value & 0xfff;
6706 end_of_line (str);
6707 return;
6708 }
6709
6710 value = validate_immediate (~ inst.reloc.exp.X_add_number);
6711
6712 if (value != FAIL)
6713 {
6714 /* This can be done with a mvn instruction. */
6715 inst.instruction &= LITERAL_MASK;
6716 inst.instruction |= INST_IMMEDIATE | (OPCODE_MVN << DATA_OP_SHIFT);
6717 inst.instruction |= value & 0xfff;
6718 end_of_line (str);
6719 return;
6720 }
6721 }
6722
6723 /* Insert into literal pool. */
6724 if (add_to_lit_pool () == FAIL)
6725 {
6726 if (!inst.error)
6727 inst.error = _("literal pool insertion failed");
6728 return;
6729 }
6730
6731 /* Change the instruction exp to point to the pool. */
6732 inst.instruction |= HWOFFSET_IMM;
6733 inst.reloc.type = BFD_RELOC_ARM_HWLITERAL;
6734 inst.reloc.pc_rel = 1;
6735 inst.instruction |= (REG_PC << 16);
6736 pre_inc = 1;
6737 }
6738 else
6739 {
6740 if (my_get_expression (&inst.reloc.exp, &str))
6741 return;
6742
6743 inst.instruction |= HWOFFSET_IMM;
6744 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
6745 #ifndef TE_WINCE
6746 /* PC rel adjust. */
6747 inst.reloc.exp.X_add_number -= 8;
6748 #endif
6749 inst.reloc.pc_rel = 1;
6750 inst.instruction |= (REG_PC << 16);
6751 pre_inc = 1;
6752 }
6753
6754 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
6755 end_of_line (str);
6756 }
6757
6758 static void
6759 do_ldsttv4 (char * str)
6760 {
6761 int conflict_reg;
6762
6763 skip_whitespace (str);
6764
6765 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
6766 {
6767 if (!inst.error)
6768 inst.error = BAD_ARGS;
6769 return;
6770 }
6771
6772 if (skip_past_comma (& str) == FAIL)
6773 {
6774 inst.error = _("address expected");
6775 return;
6776 }
6777
6778 if (*str == '[')
6779 {
6780 int reg;
6781
6782 str++;
6783
6784 skip_whitespace (str);
6785
6786 if ((reg = reg_required_here (&str, 16)) == FAIL)
6787 return;
6788
6789 /* ldrt/strt always use post-indexed addressing, so if the base is
6790 the same as Rd, we warn. */
6791 if (conflict_reg == reg)
6792 as_warn (_("%s register same as write-back base"),
6793 ((inst.instruction & LOAD_BIT)
6794 ? _("destination") : _("source")));
6795
6796 skip_whitespace (str);
6797
6798 if (*str == ']')
6799 {
6800 str ++;
6801
6802 if (skip_past_comma (&str) == SUCCESS)
6803 {
6804 /* [Rn],... (post inc) */
6805 if (ldst_extend_v4 (&str) == FAIL)
6806 return;
6807 }
6808 else
6809 {
6810 /* [Rn] */
6811 skip_whitespace (str);
6812
6813 /* Skip a write-back '!'. */
6814 if (*str == '!')
6815 str++;
6816
6817 inst.instruction |= (INDEX_UP|HWOFFSET_IMM);
6818 }
6819 }
6820 else
6821 {
6822 inst.error = _("post-indexed expression expected");
6823 return;
6824 }
6825 }
6826 else
6827 {
6828 inst.error = _("post-indexed expression expected");
6829 return;
6830 }
6831
6832 end_of_line (str);
6833 }
6834
6835
6836 static long
6837 reg_list (char ** strp)
6838 {
6839 char * str = * strp;
6840 long range = 0;
6841 int another_range;
6842
6843 /* We come back here if we get ranges concatenated by '+' or '|'. */
6844 do
6845 {
6846 another_range = 0;
6847
6848 if (*str == '{')
6849 {
6850 int in_range = 0;
6851 int cur_reg = -1;
6852
6853 str++;
6854 do
6855 {
6856 int reg;
6857
6858 skip_whitespace (str);
6859
6860 if ((reg = reg_required_here (& str, -1)) == FAIL)
6861 return FAIL;
6862
6863 if (in_range)
6864 {
6865 int i;
6866
6867 if (reg <= cur_reg)
6868 {
6869 inst.error = _("bad range in register list");
6870 return FAIL;
6871 }
6872
6873 for (i = cur_reg + 1; i < reg; i++)
6874 {
6875 if (range & (1 << i))
6876 as_tsktsk
6877 (_("Warning: duplicated register (r%d) in register list"),
6878 i);
6879 else
6880 range |= 1 << i;
6881 }
6882 in_range = 0;
6883 }
6884
6885 if (range & (1 << reg))
6886 as_tsktsk (_("Warning: duplicated register (r%d) in register list"),
6887 reg);
6888 else if (reg <= cur_reg)
6889 as_tsktsk (_("Warning: register range not in ascending order"));
6890
6891 range |= 1 << reg;
6892 cur_reg = reg;
6893 }
6894 while (skip_past_comma (&str) != FAIL
6895 || (in_range = 1, *str++ == '-'));
6896 str--;
6897 skip_whitespace (str);
6898
6899 if (*str++ != '}')
6900 {
6901 inst.error = _("missing `}'");
6902 return FAIL;
6903 }
6904 }
6905 else
6906 {
6907 expressionS expr;
6908
6909 if (my_get_expression (&expr, &str))
6910 return FAIL;
6911
6912 if (expr.X_op == O_constant)
6913 {
6914 if (expr.X_add_number
6915 != (expr.X_add_number & 0x0000ffff))
6916 {
6917 inst.error = _("invalid register mask");
6918 return FAIL;
6919 }
6920
6921 if ((range & expr.X_add_number) != 0)
6922 {
6923 int regno = range & expr.X_add_number;
6924
6925 regno &= -regno;
6926 regno = (1 << regno) - 1;
6927 as_tsktsk
6928 (_("Warning: duplicated register (r%d) in register list"),
6929 regno);
6930 }
6931
6932 range |= expr.X_add_number;
6933 }
6934 else
6935 {
6936 if (inst.reloc.type != 0)
6937 {
6938 inst.error = _("expression too complex");
6939 return FAIL;
6940 }
6941
6942 memcpy (&inst.reloc.exp, &expr, sizeof (expressionS));
6943 inst.reloc.type = BFD_RELOC_ARM_MULTI;
6944 inst.reloc.pc_rel = 0;
6945 }
6946 }
6947
6948 skip_whitespace (str);
6949
6950 if (*str == '|' || *str == '+')
6951 {
6952 str++;
6953 another_range = 1;
6954 }
6955 }
6956 while (another_range);
6957
6958 *strp = str;
6959 return range;
6960 }
6961
6962 static void
6963 do_ldmstm (char * str)
6964 {
6965 int base_reg;
6966 long range;
6967
6968 skip_whitespace (str);
6969
6970 if ((base_reg = reg_required_here (&str, 16)) == FAIL)
6971 return;
6972
6973 if (base_reg == REG_PC)
6974 {
6975 inst.error = _("r15 not allowed as base register");
6976 return;
6977 }
6978
6979 skip_whitespace (str);
6980
6981 if (*str == '!')
6982 {
6983 inst.instruction |= WRITE_BACK;
6984 str++;
6985 }
6986
6987 if (skip_past_comma (&str) == FAIL
6988 || (range = reg_list (&str)) == FAIL)
6989 {
6990 if (! inst.error)
6991 inst.error = BAD_ARGS;
6992 return;
6993 }
6994
6995 if (*str == '^')
6996 {
6997 str++;
6998 inst.instruction |= LDM_TYPE_2_OR_3;
6999 }
7000
7001 if (inst.instruction & WRITE_BACK)
7002 {
7003 /* Check for unpredictable uses of writeback. */
7004 if (inst.instruction & LOAD_BIT)
7005 {
7006 /* Not allowed in LDM type 2. */
7007 if ((inst.instruction & LDM_TYPE_2_OR_3)
7008 && ((range & (1 << REG_PC)) == 0))
7009 as_warn (_("writeback of base register is UNPREDICTABLE"));
7010 /* Only allowed if base reg not in list for other types. */
7011 else if (range & (1 << base_reg))
7012 as_warn (_("writeback of base register when in register list is UNPREDICTABLE"));
7013 }
7014 else /* STM. */
7015 {
7016 /* Not allowed for type 2. */
7017 if (inst.instruction & LDM_TYPE_2_OR_3)
7018 as_warn (_("writeback of base register is UNPREDICTABLE"));
7019 /* Only allowed if base reg not in list, or first in list. */
7020 else if ((range & (1 << base_reg))
7021 && (range & ((1 << base_reg) - 1)))
7022 as_warn (_("if writeback register is in list, it must be the lowest reg in the list"));
7023 }
7024 }
7025
7026 inst.instruction |= range;
7027 end_of_line (str);
7028 }
7029
7030 static void
7031 do_smi (char * str)
7032 {
7033 skip_whitespace (str);
7034
7035 /* Allow optional leading '#'. */
7036 if (is_immediate_prefix (*str))
7037 str++;
7038
7039 if (my_get_expression (& inst.reloc.exp, & str))
7040 return;
7041
7042 inst.reloc.type = BFD_RELOC_ARM_SMI;
7043 inst.reloc.pc_rel = 0;
7044 end_of_line (str);
7045 }
7046
7047 static void
7048 do_swi (char * str)
7049 {
7050 skip_whitespace (str);
7051
7052 /* Allow optional leading '#'. */
7053 if (is_immediate_prefix (*str))
7054 str++;
7055
7056 if (my_get_expression (& inst.reloc.exp, & str))
7057 return;
7058
7059 inst.reloc.type = BFD_RELOC_ARM_SWI;
7060 inst.reloc.pc_rel = 0;
7061 end_of_line (str);
7062 }
7063
7064 static void
7065 do_swap (char * str)
7066 {
7067 int reg;
7068
7069 skip_whitespace (str);
7070
7071 if ((reg = reg_required_here (&str, 12)) == FAIL)
7072 return;
7073
7074 if (reg == REG_PC)
7075 {
7076 inst.error = _("r15 not allowed in swap");
7077 return;
7078 }
7079
7080 if (skip_past_comma (&str) == FAIL
7081 || (reg = reg_required_here (&str, 0)) == FAIL)
7082 {
7083 if (!inst.error)
7084 inst.error = BAD_ARGS;
7085 return;
7086 }
7087
7088 if (reg == REG_PC)
7089 {
7090 inst.error = _("r15 not allowed in swap");
7091 return;
7092 }
7093
7094 if (skip_past_comma (&str) == FAIL
7095 || *str++ != '[')
7096 {
7097 inst.error = BAD_ARGS;
7098 return;
7099 }
7100
7101 skip_whitespace (str);
7102
7103 if ((reg = reg_required_here (&str, 16)) == FAIL)
7104 return;
7105
7106 if (reg == REG_PC)
7107 {
7108 inst.error = BAD_PC;
7109 return;
7110 }
7111
7112 skip_whitespace (str);
7113
7114 if (*str++ != ']')
7115 {
7116 inst.error = _("missing ]");
7117 return;
7118 }
7119
7120 end_of_line (str);
7121 }
7122
7123 static void
7124 do_branch (char * str)
7125 {
7126 if (my_get_expression (&inst.reloc.exp, &str))
7127 return;
7128
7129 #ifdef OBJ_ELF
7130 {
7131 char * save_in;
7132
7133 /* ScottB: February 5, 1998 - Check to see of PLT32 reloc
7134 required for the instruction. */
7135
7136 /* arm_parse_reloc () works on input_line_pointer.
7137 We actually want to parse the operands to the branch instruction
7138 passed in 'str'. Save the input pointer and restore it later. */
7139 save_in = input_line_pointer;
7140 input_line_pointer = str;
7141 if (inst.reloc.exp.X_op == O_symbol
7142 && *str == '('
7143 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
7144 {
7145 inst.reloc.type = BFD_RELOC_ARM_PLT32;
7146 inst.reloc.pc_rel = 0;
7147 /* Modify str to point to after parsed operands, otherwise
7148 end_of_line() will complain about the (PLT) left in str. */
7149 str = input_line_pointer;
7150 }
7151 else
7152 {
7153 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
7154 inst.reloc.pc_rel = 1;
7155 }
7156 input_line_pointer = save_in;
7157 }
7158 #else
7159 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
7160 inst.reloc.pc_rel = 1;
7161 #endif /* OBJ_ELF */
7162
7163 end_of_line (str);
7164 }
7165
7166 static void
7167 do_cdp (char * str)
7168 {
7169 /* Co-processor data operation.
7170 Format: CDP{cond} CP#,<expr>,CRd,CRn,CRm{,<expr>} */
7171 skip_whitespace (str);
7172
7173 if (co_proc_number (&str) == FAIL)
7174 {
7175 if (!inst.error)
7176 inst.error = BAD_ARGS;
7177 return;
7178 }
7179
7180 if (skip_past_comma (&str) == FAIL
7181 || cp_opc_expr (&str, 20,4) == FAIL)
7182 {
7183 if (!inst.error)
7184 inst.error = BAD_ARGS;
7185 return;
7186 }
7187
7188 if (skip_past_comma (&str) == FAIL
7189 || cp_reg_required_here (&str, 12) == FAIL)
7190 {
7191 if (!inst.error)
7192 inst.error = BAD_ARGS;
7193 return;
7194 }
7195
7196 if (skip_past_comma (&str) == FAIL
7197 || cp_reg_required_here (&str, 16) == FAIL)
7198 {
7199 if (!inst.error)
7200 inst.error = BAD_ARGS;
7201 return;
7202 }
7203
7204 if (skip_past_comma (&str) == FAIL
7205 || cp_reg_required_here (&str, 0) == FAIL)
7206 {
7207 if (!inst.error)
7208 inst.error = BAD_ARGS;
7209 return;
7210 }
7211
7212 if (skip_past_comma (&str) == SUCCESS)
7213 {
7214 if (cp_opc_expr (&str, 5, 3) == FAIL)
7215 {
7216 if (!inst.error)
7217 inst.error = BAD_ARGS;
7218 return;
7219 }
7220 }
7221
7222 end_of_line (str);
7223 }
7224
7225 static void
7226 do_lstc (char * str)
7227 {
7228 /* Co-processor register load/store.
7229 Format: <LDC|STC{cond}[L] CP#,CRd,<address> */
7230
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_reg_required_here (&str, 12) == FAIL)
7242 {
7243 if (!inst.error)
7244 inst.error = BAD_ARGS;
7245 return;
7246 }
7247
7248 if (skip_past_comma (&str) == FAIL
7249 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
7250 {
7251 if (! inst.error)
7252 inst.error = BAD_ARGS;
7253 return;
7254 }
7255
7256 end_of_line (str);
7257 }
7258
7259 static void
7260 do_co_reg (char * str)
7261 {
7262 /* Co-processor register transfer.
7263 Format: <MCR|MRC>{cond} CP#,<expr1>,Rd,CRn,CRm{,<expr2>} */
7264
7265 skip_whitespace (str);
7266
7267 if (co_proc_number (&str) == FAIL)
7268 {
7269 if (!inst.error)
7270 inst.error = BAD_ARGS;
7271 return;
7272 }
7273
7274 if (skip_past_comma (&str) == FAIL
7275 || cp_opc_expr (&str, 21, 3) == FAIL)
7276 {
7277 if (!inst.error)
7278 inst.error = BAD_ARGS;
7279 return;
7280 }
7281
7282 if (skip_past_comma (&str) == FAIL
7283 || reg_required_here (&str, 12) == FAIL)
7284 {
7285 if (!inst.error)
7286 inst.error = BAD_ARGS;
7287 return;
7288 }
7289
7290 if (skip_past_comma (&str) == FAIL
7291 || cp_reg_required_here (&str, 16) == FAIL)
7292 {
7293 if (!inst.error)
7294 inst.error = BAD_ARGS;
7295 return;
7296 }
7297
7298 if (skip_past_comma (&str) == FAIL
7299 || cp_reg_required_here (&str, 0) == FAIL)
7300 {
7301 if (!inst.error)
7302 inst.error = BAD_ARGS;
7303 return;
7304 }
7305
7306 if (skip_past_comma (&str) == SUCCESS)
7307 {
7308 if (cp_opc_expr (&str, 5, 3) == FAIL)
7309 {
7310 if (!inst.error)
7311 inst.error = BAD_ARGS;
7312 return;
7313 }
7314 }
7315
7316 end_of_line (str);
7317 }
7318
7319 static void
7320 do_fpa_ctrl (char * str)
7321 {
7322 /* FP control registers.
7323 Format: <WFS|RFS|WFC|RFC>{cond} Rn */
7324
7325 skip_whitespace (str);
7326
7327 if (reg_required_here (&str, 12) == FAIL)
7328 {
7329 if (!inst.error)
7330 inst.error = BAD_ARGS;
7331 return;
7332 }
7333
7334 end_of_line (str);
7335 }
7336
7337 static void
7338 do_fpa_ldst (char * str)
7339 {
7340 skip_whitespace (str);
7341
7342 if (fp_reg_required_here (&str, 12) == FAIL)
7343 {
7344 if (!inst.error)
7345 inst.error = BAD_ARGS;
7346 return;
7347 }
7348
7349 if (skip_past_comma (&str) == FAIL
7350 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
7351 {
7352 if (!inst.error)
7353 inst.error = BAD_ARGS;
7354 return;
7355 }
7356
7357 end_of_line (str);
7358 }
7359
7360 static void
7361 do_fpa_ldmstm (char * str)
7362 {
7363 int num_regs;
7364
7365 skip_whitespace (str);
7366
7367 if (fp_reg_required_here (&str, 12) == FAIL)
7368 {
7369 if (! inst.error)
7370 inst.error = BAD_ARGS;
7371 return;
7372 }
7373
7374 /* Get Number of registers to transfer. */
7375 if (skip_past_comma (&str) == FAIL
7376 || my_get_expression (&inst.reloc.exp, &str))
7377 {
7378 if (! inst.error)
7379 inst.error = _("constant expression expected");
7380 return;
7381 }
7382
7383 if (inst.reloc.exp.X_op != O_constant)
7384 {
7385 inst.error = _("constant value required for number of registers");
7386 return;
7387 }
7388
7389 num_regs = inst.reloc.exp.X_add_number;
7390
7391 if (num_regs < 1 || num_regs > 4)
7392 {
7393 inst.error = _("number of registers must be in the range [1:4]");
7394 return;
7395 }
7396
7397 switch (num_regs)
7398 {
7399 case 1:
7400 inst.instruction |= CP_T_X;
7401 break;
7402 case 2:
7403 inst.instruction |= CP_T_Y;
7404 break;
7405 case 3:
7406 inst.instruction |= CP_T_Y | CP_T_X;
7407 break;
7408 case 4:
7409 break;
7410 default:
7411 abort ();
7412 }
7413
7414 if (inst.instruction & (CP_T_Pre | CP_T_UD)) /* ea/fd format. */
7415 {
7416 int reg;
7417 int write_back;
7418 int offset;
7419
7420 /* The instruction specified "ea" or "fd", so we can only accept
7421 [Rn]{!}. The instruction does not really support stacking or
7422 unstacking, so we have to emulate these by setting appropriate
7423 bits and offsets. */
7424 if (skip_past_comma (&str) == FAIL
7425 || *str != '[')
7426 {
7427 if (! inst.error)
7428 inst.error = BAD_ARGS;
7429 return;
7430 }
7431
7432 str++;
7433 skip_whitespace (str);
7434
7435 if ((reg = reg_required_here (&str, 16)) == FAIL)
7436 return;
7437
7438 skip_whitespace (str);
7439
7440 if (*str != ']')
7441 {
7442 inst.error = BAD_ARGS;
7443 return;
7444 }
7445
7446 str++;
7447 if (*str == '!')
7448 {
7449 write_back = 1;
7450 str++;
7451 if (reg == REG_PC)
7452 {
7453 inst.error =
7454 _("r15 not allowed as base register with write-back");
7455 return;
7456 }
7457 }
7458 else
7459 write_back = 0;
7460
7461 if (inst.instruction & CP_T_Pre)
7462 {
7463 /* Pre-decrement. */
7464 offset = 3 * num_regs;
7465 if (write_back)
7466 inst.instruction |= CP_T_WB;
7467 }
7468 else
7469 {
7470 /* Post-increment. */
7471 if (write_back)
7472 {
7473 inst.instruction |= CP_T_WB;
7474 offset = 3 * num_regs;
7475 }
7476 else
7477 {
7478 /* No write-back, so convert this into a standard pre-increment
7479 instruction -- aesthetically more pleasing. */
7480 inst.instruction |= CP_T_Pre | CP_T_UD;
7481 offset = 0;
7482 }
7483 }
7484
7485 inst.instruction |= offset;
7486 }
7487 else if (skip_past_comma (&str) == FAIL
7488 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
7489 {
7490 if (! inst.error)
7491 inst.error = BAD_ARGS;
7492 return;
7493 }
7494
7495 end_of_line (str);
7496 }
7497
7498 static void
7499 do_fpa_dyadic (char * str)
7500 {
7501 skip_whitespace (str);
7502
7503 if (fp_reg_required_here (&str, 12) == FAIL)
7504 {
7505 if (! inst.error)
7506 inst.error = BAD_ARGS;
7507 return;
7508 }
7509
7510 if (skip_past_comma (&str) == FAIL
7511 || fp_reg_required_here (&str, 16) == FAIL)
7512 {
7513 if (! inst.error)
7514 inst.error = BAD_ARGS;
7515 return;
7516 }
7517
7518 if (skip_past_comma (&str) == FAIL
7519 || fp_op2 (&str) == FAIL)
7520 {
7521 if (! inst.error)
7522 inst.error = BAD_ARGS;
7523 return;
7524 }
7525
7526 end_of_line (str);
7527 }
7528
7529 static void
7530 do_fpa_monadic (char * str)
7531 {
7532 skip_whitespace (str);
7533
7534 if (fp_reg_required_here (&str, 12) == FAIL)
7535 {
7536 if (! inst.error)
7537 inst.error = BAD_ARGS;
7538 return;
7539 }
7540
7541 if (skip_past_comma (&str) == FAIL
7542 || fp_op2 (&str) == FAIL)
7543 {
7544 if (! inst.error)
7545 inst.error = BAD_ARGS;
7546 return;
7547 }
7548
7549 end_of_line (str);
7550 }
7551
7552 static void
7553 do_fpa_cmp (char * str)
7554 {
7555 skip_whitespace (str);
7556
7557 if (fp_reg_required_here (&str, 16) == FAIL)
7558 {
7559 if (! inst.error)
7560 inst.error = BAD_ARGS;
7561 return;
7562 }
7563
7564 if (skip_past_comma (&str) == FAIL
7565 || fp_op2 (&str) == FAIL)
7566 {
7567 if (! inst.error)
7568 inst.error = BAD_ARGS;
7569 return;
7570 }
7571
7572 end_of_line (str);
7573 }
7574
7575 static void
7576 do_fpa_from_reg (char * str)
7577 {
7578 skip_whitespace (str);
7579
7580 if (fp_reg_required_here (&str, 16) == FAIL)
7581 {
7582 if (! inst.error)
7583 inst.error = BAD_ARGS;
7584 return;
7585 }
7586
7587 if (skip_past_comma (&str) == FAIL
7588 || reg_required_here (&str, 12) == FAIL)
7589 {
7590 if (! inst.error)
7591 inst.error = BAD_ARGS;
7592 return;
7593 }
7594
7595 end_of_line (str);
7596 }
7597
7598 static void
7599 do_fpa_to_reg (char * str)
7600 {
7601 skip_whitespace (str);
7602
7603 if (reg_required_here (&str, 12) == FAIL)
7604 return;
7605
7606 if (skip_past_comma (&str) == FAIL
7607 || fp_reg_required_here (&str, 0) == FAIL)
7608 {
7609 if (! inst.error)
7610 inst.error = BAD_ARGS;
7611 return;
7612 }
7613
7614 end_of_line (str);
7615 }
7616
7617 /* Encode a VFP SP register number. */
7618
7619 static void
7620 vfp_sp_encode_reg (int reg, enum vfp_sp_reg_pos pos)
7621 {
7622 switch (pos)
7623 {
7624 case VFP_REG_Sd:
7625 inst.instruction |= ((reg >> 1) << 12) | ((reg & 1) << 22);
7626 break;
7627
7628 case VFP_REG_Sn:
7629 inst.instruction |= ((reg >> 1) << 16) | ((reg & 1) << 7);
7630 break;
7631
7632 case VFP_REG_Sm:
7633 inst.instruction |= ((reg >> 1) << 0) | ((reg & 1) << 5);
7634 break;
7635
7636 default:
7637 abort ();
7638 }
7639 }
7640
7641 static int
7642 vfp_sp_reg_required_here (char ** str,
7643 enum vfp_sp_reg_pos pos)
7644 {
7645 int reg;
7646 char * start = *str;
7647
7648 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_SN].htab)) != FAIL)
7649 {
7650 vfp_sp_encode_reg (reg, pos);
7651 return reg;
7652 }
7653
7654 /* In the few cases where we might be able to accept something else
7655 this error can be overridden. */
7656 inst.error = _(all_reg_maps[REG_TYPE_SN].expected);
7657
7658 /* Restore the start point. */
7659 *str = start;
7660 return FAIL;
7661 }
7662
7663 static int
7664 vfp_dp_reg_required_here (char ** str,
7665 enum vfp_dp_reg_pos pos)
7666 {
7667 int reg;
7668 char * start = *str;
7669
7670 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_DN].htab)) != FAIL)
7671 {
7672 switch (pos)
7673 {
7674 case VFP_REG_Dd:
7675 inst.instruction |= reg << 12;
7676 break;
7677
7678 case VFP_REG_Dn:
7679 inst.instruction |= reg << 16;
7680 break;
7681
7682 case VFP_REG_Dm:
7683 inst.instruction |= reg << 0;
7684 break;
7685
7686 default:
7687 abort ();
7688 }
7689 return reg;
7690 }
7691
7692 /* In the few cases where we might be able to accept something else
7693 this error can be overridden. */
7694 inst.error = _(all_reg_maps[REG_TYPE_DN].expected);
7695
7696 /* Restore the start point. */
7697 *str = start;
7698 return FAIL;
7699 }
7700
7701 static void
7702 do_vfp_sp_monadic (char * str)
7703 {
7704 skip_whitespace (str);
7705
7706 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
7707 return;
7708
7709 if (skip_past_comma (&str) == FAIL
7710 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
7711 {
7712 if (! inst.error)
7713 inst.error = BAD_ARGS;
7714 return;
7715 }
7716
7717 end_of_line (str);
7718 }
7719
7720 static void
7721 do_vfp_dp_monadic (char * str)
7722 {
7723 skip_whitespace (str);
7724
7725 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
7726 return;
7727
7728 if (skip_past_comma (&str) == FAIL
7729 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
7730 {
7731 if (! inst.error)
7732 inst.error = BAD_ARGS;
7733 return;
7734 }
7735
7736 end_of_line (str);
7737 }
7738
7739 static void
7740 do_vfp_sp_dyadic (char * str)
7741 {
7742 skip_whitespace (str);
7743
7744 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
7745 return;
7746
7747 if (skip_past_comma (&str) == FAIL
7748 || vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL
7749 || skip_past_comma (&str) == FAIL
7750 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
7751 {
7752 if (! inst.error)
7753 inst.error = BAD_ARGS;
7754 return;
7755 }
7756
7757 end_of_line (str);
7758 }
7759
7760 static void
7761 do_vfp_dp_dyadic (char * str)
7762 {
7763 skip_whitespace (str);
7764
7765 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
7766 return;
7767
7768 if (skip_past_comma (&str) == FAIL
7769 || vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL
7770 || skip_past_comma (&str) == FAIL
7771 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
7772 {
7773 if (! inst.error)
7774 inst.error = BAD_ARGS;
7775 return;
7776 }
7777
7778 end_of_line (str);
7779 }
7780
7781 static void
7782 do_vfp_reg_from_sp (char * str)
7783 {
7784 skip_whitespace (str);
7785
7786 if (reg_required_here (&str, 12) == FAIL)
7787 return;
7788
7789 if (skip_past_comma (&str) == FAIL
7790 || vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL)
7791 {
7792 if (! inst.error)
7793 inst.error = BAD_ARGS;
7794 return;
7795 }
7796
7797 end_of_line (str);
7798 }
7799
7800 /* Parse a VFP register list. If the string is invalid return FAIL.
7801 Otherwise return the number of registers, and set PBASE to the first
7802 register. Double precision registers are matched if DP is nonzero. */
7803
7804 static int
7805 vfp_parse_reg_list (char **str, int *pbase, int dp)
7806 {
7807 int base_reg;
7808 int new_base;
7809 int regtype;
7810 int max_regs;
7811 int count = 0;
7812 int warned = 0;
7813 unsigned long mask = 0;
7814 int i;
7815
7816 if (**str != '{')
7817 return FAIL;
7818
7819 (*str)++;
7820 skip_whitespace (*str);
7821
7822 if (dp)
7823 {
7824 regtype = REG_TYPE_DN;
7825 max_regs = 16;
7826 }
7827 else
7828 {
7829 regtype = REG_TYPE_SN;
7830 max_regs = 32;
7831 }
7832
7833 base_reg = max_regs;
7834
7835 do
7836 {
7837 new_base = arm_reg_parse (str, all_reg_maps[regtype].htab);
7838 if (new_base == FAIL)
7839 {
7840 inst.error = _(all_reg_maps[regtype].expected);
7841 return FAIL;
7842 }
7843
7844 if (new_base < base_reg)
7845 base_reg = new_base;
7846
7847 if (mask & (1 << new_base))
7848 {
7849 inst.error = _("invalid register list");
7850 return FAIL;
7851 }
7852
7853 if ((mask >> new_base) != 0 && ! warned)
7854 {
7855 as_tsktsk (_("register list not in ascending order"));
7856 warned = 1;
7857 }
7858
7859 mask |= 1 << new_base;
7860 count++;
7861
7862 skip_whitespace (*str);
7863
7864 if (**str == '-') /* We have the start of a range expression */
7865 {
7866 int high_range;
7867
7868 (*str)++;
7869
7870 if ((high_range
7871 = arm_reg_parse (str, all_reg_maps[regtype].htab))
7872 == FAIL)
7873 {
7874 inst.error = _(all_reg_maps[regtype].expected);
7875 return FAIL;
7876 }
7877
7878 if (high_range <= new_base)
7879 {
7880 inst.error = _("register range not in ascending order");
7881 return FAIL;
7882 }
7883
7884 for (new_base++; new_base <= high_range; new_base++)
7885 {
7886 if (mask & (1 << new_base))
7887 {
7888 inst.error = _("invalid register list");
7889 return FAIL;
7890 }
7891
7892 mask |= 1 << new_base;
7893 count++;
7894 }
7895 }
7896 }
7897 while (skip_past_comma (str) != FAIL);
7898
7899 (*str)++;
7900
7901 /* Sanity check -- should have raised a parse error above. */
7902 if (count == 0 || count > max_regs)
7903 abort ();
7904
7905 *pbase = base_reg;
7906
7907 /* Final test -- the registers must be consecutive. */
7908 mask >>= base_reg;
7909 for (i = 0; i < count; i++)
7910 {
7911 if ((mask & (1u << i)) == 0)
7912 {
7913 inst.error = _("non-contiguous register range");
7914 return FAIL;
7915 }
7916 }
7917
7918 return count;
7919 }
7920
7921 static void
7922 do_vfp_reg2_from_sp2 (char * str)
7923 {
7924 int reg;
7925
7926 skip_whitespace (str);
7927
7928 if (reg_required_here (&str, 12) == FAIL
7929 || skip_past_comma (&str) == FAIL
7930 || reg_required_here (&str, 16) == FAIL
7931 || skip_past_comma (&str) == FAIL)
7932 {
7933 if (! inst.error)
7934 inst.error = BAD_ARGS;
7935 return;
7936 }
7937
7938 /* We require exactly two consecutive SP registers. */
7939 if (vfp_parse_reg_list (&str, &reg, 0) != 2)
7940 {
7941 if (! inst.error)
7942 inst.error = _("only two consecutive VFP SP registers allowed here");
7943 }
7944 vfp_sp_encode_reg (reg, VFP_REG_Sm);
7945
7946 end_of_line (str);
7947 }
7948
7949 static void
7950 do_vfp_sp_from_reg (char * str)
7951 {
7952 skip_whitespace (str);
7953
7954 if (vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL)
7955 return;
7956
7957 if (skip_past_comma (&str) == FAIL
7958 || reg_required_here (&str, 12) == FAIL)
7959 {
7960 if (! inst.error)
7961 inst.error = BAD_ARGS;
7962 return;
7963 }
7964
7965 end_of_line (str);
7966 }
7967
7968 static void
7969 do_vfp_sp2_from_reg2 (char * str)
7970 {
7971 int reg;
7972
7973 skip_whitespace (str);
7974
7975 /* We require exactly two consecutive SP registers. */
7976 if (vfp_parse_reg_list (&str, &reg, 0) != 2)
7977 {
7978 if (! inst.error)
7979 inst.error = _("only two consecutive VFP SP registers allowed here");
7980 }
7981 vfp_sp_encode_reg (reg, VFP_REG_Sm);
7982
7983 if (skip_past_comma (&str) == FAIL
7984 || reg_required_here (&str, 12) == FAIL
7985 || skip_past_comma (&str) == FAIL
7986 || reg_required_here (&str, 16) == FAIL)
7987 {
7988 if (! inst.error)
7989 inst.error = BAD_ARGS;
7990 return;
7991 }
7992
7993 end_of_line (str);
7994 }
7995
7996 static void
7997 do_vfp_reg_from_dp (char * str)
7998 {
7999 skip_whitespace (str);
8000
8001 if (reg_required_here (&str, 12) == FAIL)
8002 return;
8003
8004 if (skip_past_comma (&str) == FAIL
8005 || vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL)
8006 {
8007 if (! inst.error)
8008 inst.error = BAD_ARGS;
8009 return;
8010 }
8011
8012 end_of_line (str);
8013 }
8014
8015 static void
8016 do_vfp_reg2_from_dp (char * str)
8017 {
8018 skip_whitespace (str);
8019
8020 if (reg_required_here (&str, 12) == FAIL)
8021 return;
8022
8023 if (skip_past_comma (&str) == FAIL
8024 || reg_required_here (&str, 16) == FAIL
8025 || skip_past_comma (&str) == FAIL
8026 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
8027 {
8028 if (! inst.error)
8029 inst.error = BAD_ARGS;
8030 return;
8031 }
8032
8033 end_of_line (str);
8034 }
8035
8036 static void
8037 do_vfp_dp_from_reg (char * str)
8038 {
8039 skip_whitespace (str);
8040
8041 if (vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL)
8042 return;
8043
8044 if (skip_past_comma (&str) == FAIL
8045 || reg_required_here (&str, 12) == FAIL)
8046 {
8047 if (! inst.error)
8048 inst.error = BAD_ARGS;
8049 return;
8050 }
8051
8052 end_of_line (str);
8053 }
8054
8055 static void
8056 do_vfp_dp_from_reg2 (char * str)
8057 {
8058 skip_whitespace (str);
8059
8060 if (vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
8061 return;
8062
8063 if (skip_past_comma (&str) == FAIL
8064 || reg_required_here (&str, 12) == FAIL
8065 || skip_past_comma (&str) == FAIL
8066 || reg_required_here (&str, 16) == FAIL)
8067 {
8068 if (! inst.error)
8069 inst.error = BAD_ARGS;
8070 return;
8071 }
8072
8073 end_of_line (str);
8074 }
8075
8076 static const struct vfp_reg *
8077 vfp_psr_parse (char ** str)
8078 {
8079 char *start = *str;
8080 char c;
8081 char *p;
8082 const struct vfp_reg *vreg;
8083
8084 p = start;
8085
8086 /* Find the end of the current token. */
8087 do
8088 {
8089 c = *p++;
8090 }
8091 while (ISALPHA (c));
8092
8093 /* Mark it. */
8094 *--p = 0;
8095
8096 for (vreg = vfp_regs + 0;
8097 vreg < vfp_regs + sizeof (vfp_regs) / sizeof (struct vfp_reg);
8098 vreg++)
8099 {
8100 if (streq (start, vreg->name))
8101 {
8102 *p = c;
8103 *str = p;
8104 return vreg;
8105 }
8106 }
8107
8108 *p = c;
8109 return NULL;
8110 }
8111
8112 static int
8113 vfp_psr_required_here (char ** str)
8114 {
8115 char *start = *str;
8116 const struct vfp_reg *vreg;
8117
8118 vreg = vfp_psr_parse (str);
8119
8120 if (vreg)
8121 {
8122 inst.instruction |= vreg->regno;
8123 return SUCCESS;
8124 }
8125
8126 inst.error = _("VFP system register expected");
8127
8128 *str = start;
8129 return FAIL;
8130 }
8131
8132 static void
8133 do_vfp_reg_from_ctrl (char * str)
8134 {
8135 skip_whitespace (str);
8136
8137 if (reg_required_here (&str, 12) == FAIL)
8138 return;
8139
8140 if (skip_past_comma (&str) == FAIL
8141 || vfp_psr_required_here (&str) == FAIL)
8142 {
8143 if (! inst.error)
8144 inst.error = BAD_ARGS;
8145 return;
8146 }
8147
8148 end_of_line (str);
8149 }
8150
8151 static void
8152 do_vfp_ctrl_from_reg (char * str)
8153 {
8154 skip_whitespace (str);
8155
8156 if (vfp_psr_required_here (&str) == FAIL)
8157 return;
8158
8159 if (skip_past_comma (&str) == FAIL
8160 || reg_required_here (&str, 12) == FAIL)
8161 {
8162 if (! inst.error)
8163 inst.error = BAD_ARGS;
8164 return;
8165 }
8166
8167 end_of_line (str);
8168 }
8169
8170 static void
8171 do_vfp_sp_ldst (char * str)
8172 {
8173 skip_whitespace (str);
8174
8175 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
8176 {
8177 if (!inst.error)
8178 inst.error = BAD_ARGS;
8179 return;
8180 }
8181
8182 if (skip_past_comma (&str) == FAIL
8183 || cp_address_required_here (&str, CP_NO_WB) == FAIL)
8184 {
8185 if (!inst.error)
8186 inst.error = BAD_ARGS;
8187 return;
8188 }
8189
8190 end_of_line (str);
8191 }
8192
8193 static void
8194 do_vfp_dp_ldst (char * str)
8195 {
8196 skip_whitespace (str);
8197
8198 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
8199 {
8200 if (!inst.error)
8201 inst.error = BAD_ARGS;
8202 return;
8203 }
8204
8205 if (skip_past_comma (&str) == FAIL
8206 || cp_address_required_here (&str, CP_NO_WB) == FAIL)
8207 {
8208 if (!inst.error)
8209 inst.error = BAD_ARGS;
8210 return;
8211 }
8212
8213 end_of_line (str);
8214 }
8215
8216
8217 static void
8218 vfp_sp_ldstm (char * str, enum vfp_ldstm_type ldstm_type)
8219 {
8220 int count;
8221 int reg;
8222
8223 skip_whitespace (str);
8224
8225 if (reg_required_here (&str, 16) == FAIL)
8226 return;
8227
8228 skip_whitespace (str);
8229
8230 if (*str == '!')
8231 {
8232 inst.instruction |= WRITE_BACK;
8233 str++;
8234 }
8235 else if (ldstm_type != VFP_LDSTMIA)
8236 {
8237 inst.error = _("this addressing mode requires base-register writeback");
8238 return;
8239 }
8240
8241 if (skip_past_comma (&str) == FAIL
8242 || (count = vfp_parse_reg_list (&str, &reg, 0)) == FAIL)
8243 {
8244 if (!inst.error)
8245 inst.error = BAD_ARGS;
8246 return;
8247 }
8248 vfp_sp_encode_reg (reg, VFP_REG_Sd);
8249
8250 inst.instruction |= count;
8251 end_of_line (str);
8252 }
8253
8254 static void
8255 vfp_dp_ldstm (char * str, enum vfp_ldstm_type ldstm_type)
8256 {
8257 int count;
8258 int reg;
8259
8260 skip_whitespace (str);
8261
8262 if (reg_required_here (&str, 16) == FAIL)
8263 return;
8264
8265 skip_whitespace (str);
8266
8267 if (*str == '!')
8268 {
8269 inst.instruction |= WRITE_BACK;
8270 str++;
8271 }
8272 else if (ldstm_type != VFP_LDSTMIA && ldstm_type != VFP_LDSTMIAX)
8273 {
8274 inst.error = _("this addressing mode requires base-register writeback");
8275 return;
8276 }
8277
8278 if (skip_past_comma (&str) == FAIL
8279 || (count = vfp_parse_reg_list (&str, &reg, 1)) == FAIL)
8280 {
8281 if (!inst.error)
8282 inst.error = BAD_ARGS;
8283 return;
8284 }
8285
8286 count <<= 1;
8287 if (ldstm_type == VFP_LDSTMIAX || ldstm_type == VFP_LDSTMDBX)
8288 count += 1;
8289
8290 inst.instruction |= (reg << 12) | count;
8291 end_of_line (str);
8292 }
8293
8294 static void
8295 do_vfp_sp_ldstmia (char * str)
8296 {
8297 vfp_sp_ldstm (str, VFP_LDSTMIA);
8298 }
8299
8300 static void
8301 do_vfp_sp_ldstmdb (char * str)
8302 {
8303 vfp_sp_ldstm (str, VFP_LDSTMDB);
8304 }
8305
8306 static void
8307 do_vfp_dp_ldstmia (char * str)
8308 {
8309 vfp_dp_ldstm (str, VFP_LDSTMIA);
8310 }
8311
8312 static void
8313 do_vfp_dp_ldstmdb (char * str)
8314 {
8315 vfp_dp_ldstm (str, VFP_LDSTMDB);
8316 }
8317
8318 static void
8319 do_vfp_xp_ldstmia (char *str)
8320 {
8321 vfp_dp_ldstm (str, VFP_LDSTMIAX);
8322 }
8323
8324 static void
8325 do_vfp_xp_ldstmdb (char * str)
8326 {
8327 vfp_dp_ldstm (str, VFP_LDSTMDBX);
8328 }
8329
8330 static void
8331 do_vfp_sp_compare_z (char * str)
8332 {
8333 skip_whitespace (str);
8334
8335 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
8336 {
8337 if (!inst.error)
8338 inst.error = BAD_ARGS;
8339 return;
8340 }
8341
8342 end_of_line (str);
8343 }
8344
8345 static void
8346 do_vfp_dp_compare_z (char * str)
8347 {
8348 skip_whitespace (str);
8349
8350 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
8351 {
8352 if (!inst.error)
8353 inst.error = BAD_ARGS;
8354 return;
8355 }
8356
8357 end_of_line (str);
8358 }
8359
8360 static void
8361 do_vfp_dp_sp_cvt (char * str)
8362 {
8363 skip_whitespace (str);
8364
8365 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
8366 return;
8367
8368 if (skip_past_comma (&str) == FAIL
8369 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
8370 {
8371 if (! inst.error)
8372 inst.error = BAD_ARGS;
8373 return;
8374 }
8375
8376 end_of_line (str);
8377 }
8378
8379 static void
8380 do_vfp_sp_dp_cvt (char * str)
8381 {
8382 skip_whitespace (str);
8383
8384 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
8385 return;
8386
8387 if (skip_past_comma (&str) == FAIL
8388 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
8389 {
8390 if (! inst.error)
8391 inst.error = BAD_ARGS;
8392 return;
8393 }
8394
8395 end_of_line (str);
8396 }
8397
8398 /* Thumb specific routines. */
8399
8400 /* Parse an add or subtract instruction, SUBTRACT is non-zero if the opcode
8401 was SUB. */
8402
8403 static void
8404 thumb_add_sub (char * str, int subtract)
8405 {
8406 int Rd, Rs, Rn = FAIL;
8407
8408 skip_whitespace (str);
8409
8410 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
8411 || skip_past_comma (&str) == FAIL)
8412 {
8413 if (! inst.error)
8414 inst.error = BAD_ARGS;
8415 return;
8416 }
8417
8418 if (is_immediate_prefix (*str))
8419 {
8420 Rs = Rd;
8421 str++;
8422 if (my_get_expression (&inst.reloc.exp, &str))
8423 return;
8424 }
8425 else
8426 {
8427 if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
8428 return;
8429
8430 if (skip_past_comma (&str) == FAIL)
8431 {
8432 /* Two operand format, shuffle the registers
8433 and pretend there are 3. */
8434 Rn = Rs;
8435 Rs = Rd;
8436 }
8437 else if (is_immediate_prefix (*str))
8438 {
8439 str++;
8440 if (my_get_expression (&inst.reloc.exp, &str))
8441 return;
8442 }
8443 else if ((Rn = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
8444 return;
8445 }
8446
8447 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
8448 for the latter case, EXPR contains the immediate that was found. */
8449 if (Rn != FAIL)
8450 {
8451 /* All register format. */
8452 if (Rd > 7 || Rs > 7 || Rn > 7)
8453 {
8454 if (Rs != Rd)
8455 {
8456 inst.error = _("dest and source1 must be the same register");
8457 return;
8458 }
8459
8460 /* Can't do this for SUB. */
8461 if (subtract)
8462 {
8463 inst.error = _("subtract valid only on lo regs");
8464 return;
8465 }
8466
8467 inst.instruction = (T_OPCODE_ADD_HI
8468 | (Rd > 7 ? THUMB_H1 : 0)
8469 | (Rn > 7 ? THUMB_H2 : 0));
8470 inst.instruction |= (Rd & 7) | ((Rn & 7) << 3);
8471 }
8472 else
8473 {
8474 inst.instruction = subtract ? T_OPCODE_SUB_R3 : T_OPCODE_ADD_R3;
8475 inst.instruction |= Rd | (Rs << 3) | (Rn << 6);
8476 }
8477 }
8478 else
8479 {
8480 /* Immediate expression, now things start to get nasty. */
8481
8482 /* First deal with HI regs, only very restricted cases allowed:
8483 Adjusting SP, and using PC or SP to get an address. */
8484 if ((Rd > 7 && (Rd != REG_SP || Rs != REG_SP))
8485 || (Rs > 7 && Rs != REG_SP && Rs != REG_PC))
8486 {
8487 inst.error = _("invalid Hi register with immediate");
8488 return;
8489 }
8490
8491 if (inst.reloc.exp.X_op != O_constant)
8492 {
8493 /* Value isn't known yet, all we can do is store all the fragments
8494 we know about in the instruction and let the reloc hacking
8495 work it all out. */
8496 inst.instruction = (subtract ? 0x8000 : 0) | (Rd << 4) | Rs;
8497 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
8498 }
8499 else
8500 {
8501 int offset = inst.reloc.exp.X_add_number;
8502
8503 if (subtract)
8504 offset = - offset;
8505
8506 if (offset < 0)
8507 {
8508 offset = - offset;
8509 subtract = 1;
8510
8511 /* Quick check, in case offset is MIN_INT. */
8512 if (offset < 0)
8513 {
8514 inst.error = _("immediate value out of range");
8515 return;
8516 }
8517 }
8518 /* Note - you cannot convert a subtract of 0 into an
8519 add of 0 because the carry flag is set differently. */
8520 else if (offset > 0)
8521 subtract = 0;
8522
8523 if (Rd == REG_SP)
8524 {
8525 if (offset & ~0x1fc)
8526 {
8527 inst.error = _("invalid immediate value for stack adjust");
8528 return;
8529 }
8530 inst.instruction = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
8531 inst.instruction |= offset >> 2;
8532 }
8533 else if (Rs == REG_PC || Rs == REG_SP)
8534 {
8535 if (subtract
8536 || (offset & ~0x3fc))
8537 {
8538 inst.error = _("invalid immediate for address calculation");
8539 return;
8540 }
8541 inst.instruction = (Rs == REG_PC ? T_OPCODE_ADD_PC
8542 : T_OPCODE_ADD_SP);
8543 inst.instruction |= (Rd << 8) | (offset >> 2);
8544 }
8545 else if (Rs == Rd)
8546 {
8547 if (offset & ~0xff)
8548 {
8549 inst.error = _("immediate value out of range");
8550 return;
8551 }
8552 inst.instruction = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
8553 inst.instruction |= (Rd << 8) | offset;
8554 }
8555 else
8556 {
8557 if (offset & ~0x7)
8558 {
8559 inst.error = _("immediate value out of range");
8560 return;
8561 }
8562 inst.instruction = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
8563 inst.instruction |= Rd | (Rs << 3) | (offset << 6);
8564 }
8565 }
8566 }
8567
8568 end_of_line (str);
8569 }
8570
8571 static void
8572 thumb_shift (char * str, int shift)
8573 {
8574 int Rd, Rs, Rn = FAIL;
8575
8576 skip_whitespace (str);
8577
8578 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
8579 || skip_past_comma (&str) == FAIL)
8580 {
8581 if (! inst.error)
8582 inst.error = BAD_ARGS;
8583 return;
8584 }
8585
8586 if (is_immediate_prefix (*str))
8587 {
8588 /* Two operand immediate format, set Rs to Rd. */
8589 Rs = Rd;
8590 str ++;
8591 if (my_get_expression (&inst.reloc.exp, &str))
8592 return;
8593 }
8594 else
8595 {
8596 if ((Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
8597 return;
8598
8599 if (skip_past_comma (&str) == FAIL)
8600 {
8601 /* Two operand format, shuffle the registers
8602 and pretend there are 3. */
8603 Rn = Rs;
8604 Rs = Rd;
8605 }
8606 else if (is_immediate_prefix (*str))
8607 {
8608 str++;
8609 if (my_get_expression (&inst.reloc.exp, &str))
8610 return;
8611 }
8612 else if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
8613 return;
8614 }
8615
8616 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
8617 for the latter case, EXPR contains the immediate that was found. */
8618
8619 if (Rn != FAIL)
8620 {
8621 if (Rs != Rd)
8622 {
8623 inst.error = _("source1 and dest must be same register");
8624 return;
8625 }
8626
8627 switch (shift)
8628 {
8629 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_R; break;
8630 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_R; break;
8631 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_R; break;
8632 }
8633
8634 inst.instruction |= Rd | (Rn << 3);
8635 }
8636 else
8637 {
8638 switch (shift)
8639 {
8640 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_I; break;
8641 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_I; break;
8642 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_I; break;
8643 }
8644
8645 if (inst.reloc.exp.X_op != O_constant)
8646 {
8647 /* Value isn't known yet, create a dummy reloc and let reloc
8648 hacking fix it up. */
8649 inst.reloc.type = BFD_RELOC_ARM_THUMB_SHIFT;
8650 }
8651 else
8652 {
8653 unsigned shift_value = inst.reloc.exp.X_add_number;
8654
8655 if (shift_value > 32 || (shift_value == 32 && shift == THUMB_LSL))
8656 {
8657 inst.error = _("invalid immediate for shift");
8658 return;
8659 }
8660
8661 /* Shifts of zero are handled by converting to LSL. */
8662 if (shift_value == 0)
8663 inst.instruction = T_OPCODE_LSL_I;
8664
8665 /* Shifts of 32 are encoded as a shift of zero. */
8666 if (shift_value == 32)
8667 shift_value = 0;
8668
8669 inst.instruction |= shift_value << 6;
8670 }
8671
8672 inst.instruction |= Rd | (Rs << 3);
8673 }
8674
8675 end_of_line (str);
8676 }
8677
8678 static void
8679 thumb_load_store (char * str, int load_store, int size)
8680 {
8681 int Rd, Rb, Ro = FAIL;
8682
8683 skip_whitespace (str);
8684
8685 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
8686 || skip_past_comma (&str) == FAIL)
8687 {
8688 if (! inst.error)
8689 inst.error = BAD_ARGS;
8690 return;
8691 }
8692
8693 if (*str == '[')
8694 {
8695 str++;
8696 if ((Rb = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
8697 return;
8698
8699 if (skip_past_comma (&str) != FAIL)
8700 {
8701 if (is_immediate_prefix (*str))
8702 {
8703 str++;
8704 if (my_get_expression (&inst.reloc.exp, &str))
8705 return;
8706 }
8707 else if ((Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
8708 return;
8709 }
8710 else
8711 {
8712 inst.reloc.exp.X_op = O_constant;
8713 inst.reloc.exp.X_add_number = 0;
8714 }
8715
8716 if (*str != ']')
8717 {
8718 inst.error = _("expected ']'");
8719 return;
8720 }
8721 str++;
8722 }
8723 else if (*str == '=')
8724 {
8725 if (load_store != THUMB_LOAD)
8726 {
8727 inst.error = _("invalid pseudo operation");
8728 return;
8729 }
8730
8731 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
8732 str++;
8733
8734 skip_whitespace (str);
8735
8736 if (my_get_expression (& inst.reloc.exp, & str))
8737 return;
8738
8739 end_of_line (str);
8740
8741 if ( inst.reloc.exp.X_op != O_constant
8742 && inst.reloc.exp.X_op != O_symbol)
8743 {
8744 inst.error = "Constant expression expected";
8745 return;
8746 }
8747
8748 if (inst.reloc.exp.X_op == O_constant
8749 && ((inst.reloc.exp.X_add_number & ~0xFF) == 0))
8750 {
8751 /* This can be done with a mov instruction. */
8752
8753 inst.instruction = T_OPCODE_MOV_I8 | (Rd << 8);
8754 inst.instruction |= inst.reloc.exp.X_add_number;
8755 return;
8756 }
8757
8758 /* Insert into literal pool. */
8759 if (add_to_lit_pool () == FAIL)
8760 {
8761 if (!inst.error)
8762 inst.error = "literal pool insertion failed";
8763 return;
8764 }
8765
8766 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
8767 inst.reloc.pc_rel = 1;
8768 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
8769 /* Adjust ARM pipeline offset to Thumb. */
8770 inst.reloc.exp.X_add_number += 4;
8771
8772 return;
8773 }
8774 else
8775 {
8776 if (my_get_expression (&inst.reloc.exp, &str))
8777 return;
8778
8779 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
8780 inst.reloc.pc_rel = 1;
8781 inst.reloc.exp.X_add_number -= 4; /* Pipeline offset. */
8782 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
8783 end_of_line (str);
8784 return;
8785 }
8786
8787 if (Rb == REG_PC || Rb == REG_SP)
8788 {
8789 if (size != THUMB_WORD)
8790 {
8791 inst.error = _("byte or halfword not valid for base register");
8792 return;
8793 }
8794 else if (Rb == REG_PC && load_store != THUMB_LOAD)
8795 {
8796 inst.error = _("r15 based store not allowed");
8797 return;
8798 }
8799 else if (Ro != FAIL)
8800 {
8801 inst.error = _("invalid base register for register offset");
8802 return;
8803 }
8804
8805 if (Rb == REG_PC)
8806 inst.instruction = T_OPCODE_LDR_PC;
8807 else if (load_store == THUMB_LOAD)
8808 inst.instruction = T_OPCODE_LDR_SP;
8809 else
8810 inst.instruction = T_OPCODE_STR_SP;
8811
8812 inst.instruction |= Rd << 8;
8813 if (inst.reloc.exp.X_op == O_constant)
8814 {
8815 unsigned offset = inst.reloc.exp.X_add_number;
8816
8817 if (offset & ~0x3fc)
8818 {
8819 inst.error = _("invalid offset");
8820 return;
8821 }
8822
8823 inst.instruction |= offset >> 2;
8824 }
8825 else
8826 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
8827 }
8828 else if (Rb > 7)
8829 {
8830 inst.error = _("invalid base register in load/store");
8831 return;
8832 }
8833 else if (Ro == FAIL)
8834 {
8835 /* Immediate offset. */
8836 if (size == THUMB_WORD)
8837 inst.instruction = (load_store == THUMB_LOAD
8838 ? T_OPCODE_LDR_IW : T_OPCODE_STR_IW);
8839 else if (size == THUMB_HALFWORD)
8840 inst.instruction = (load_store == THUMB_LOAD
8841 ? T_OPCODE_LDR_IH : T_OPCODE_STR_IH);
8842 else
8843 inst.instruction = (load_store == THUMB_LOAD
8844 ? T_OPCODE_LDR_IB : T_OPCODE_STR_IB);
8845
8846 inst.instruction |= Rd | (Rb << 3);
8847
8848 if (inst.reloc.exp.X_op == O_constant)
8849 {
8850 unsigned offset = inst.reloc.exp.X_add_number;
8851
8852 if (offset & ~(0x1f << size))
8853 {
8854 inst.error = _("invalid offset");
8855 return;
8856 }
8857 inst.instruction |= (offset >> size) << 6;
8858 }
8859 else
8860 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
8861 }
8862 else
8863 {
8864 /* Register offset. */
8865 if (size == THUMB_WORD)
8866 inst.instruction = (load_store == THUMB_LOAD
8867 ? T_OPCODE_LDR_RW : T_OPCODE_STR_RW);
8868 else if (size == THUMB_HALFWORD)
8869 inst.instruction = (load_store == THUMB_LOAD
8870 ? T_OPCODE_LDR_RH : T_OPCODE_STR_RH);
8871 else
8872 inst.instruction = (load_store == THUMB_LOAD
8873 ? T_OPCODE_LDR_RB : T_OPCODE_STR_RB);
8874
8875 inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
8876 }
8877
8878 end_of_line (str);
8879 }
8880
8881 /* A register must be given at this point.
8882
8883 Shift is the place to put it in inst.instruction.
8884
8885 Restores input start point on err.
8886 Returns the reg#, or FAIL. */
8887
8888 static int
8889 mav_reg_required_here (char ** str, int shift, enum arm_reg_type regtype)
8890 {
8891 int reg;
8892 char *start = *str;
8893
8894 if ((reg = arm_reg_parse (str, all_reg_maps[regtype].htab)) != FAIL)
8895 {
8896 if (shift >= 0)
8897 inst.instruction |= reg << shift;
8898
8899 return reg;
8900 }
8901
8902 /* Restore the start point. */
8903 *str = start;
8904
8905 /* Try generic coprocessor name if applicable. */
8906 if (regtype == REG_TYPE_MVF ||
8907 regtype == REG_TYPE_MVD ||
8908 regtype == REG_TYPE_MVFX ||
8909 regtype == REG_TYPE_MVDX)
8910 {
8911 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_CN].htab)) != FAIL)
8912 {
8913 if (shift >= 0)
8914 inst.instruction |= reg << shift;
8915
8916 return reg;
8917 }
8918
8919 /* Restore the start point. */
8920 *str = start;
8921 }
8922
8923 /* In the few cases where we might be able to accept something else
8924 this error can be overridden. */
8925 inst.error = _(all_reg_maps[regtype].expected);
8926
8927 return FAIL;
8928 }
8929
8930 /* Cirrus Maverick Instructions. */
8931
8932 /* Isnsn like "foo X,Y". */
8933
8934 static void
8935 do_mav_binops (char * str,
8936 int mode,
8937 enum arm_reg_type reg0,
8938 enum arm_reg_type reg1)
8939 {
8940 int shift0, shift1;
8941
8942 shift0 = mode & 0xff;
8943 shift1 = (mode >> 8) & 0xff;
8944
8945 skip_whitespace (str);
8946
8947 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
8948 || skip_past_comma (&str) == FAIL
8949 || mav_reg_required_here (&str, shift1, reg1) == FAIL)
8950 {
8951 if (!inst.error)
8952 inst.error = BAD_ARGS;
8953 }
8954 else
8955 end_of_line (str);
8956 }
8957
8958 /* Isnsn like "foo X,Y,Z". */
8959
8960 static void
8961 do_mav_triple (char * str,
8962 int mode,
8963 enum arm_reg_type reg0,
8964 enum arm_reg_type reg1,
8965 enum arm_reg_type reg2)
8966 {
8967 int shift0, shift1, shift2;
8968
8969 shift0 = mode & 0xff;
8970 shift1 = (mode >> 8) & 0xff;
8971 shift2 = (mode >> 16) & 0xff;
8972
8973 skip_whitespace (str);
8974
8975 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
8976 || skip_past_comma (&str) == FAIL
8977 || mav_reg_required_here (&str, shift1, reg1) == FAIL
8978 || skip_past_comma (&str) == FAIL
8979 || mav_reg_required_here (&str, shift2, reg2) == FAIL)
8980 {
8981 if (!inst.error)
8982 inst.error = BAD_ARGS;
8983 }
8984 else
8985 end_of_line (str);
8986 }
8987
8988 /* Wrapper functions. */
8989
8990 static void
8991 do_mav_binops_1a (char * str)
8992 {
8993 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVF);
8994 }
8995
8996 static void
8997 do_mav_binops_1b (char * str)
8998 {
8999 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVD);
9000 }
9001
9002 static void
9003 do_mav_binops_1c (char * str)
9004 {
9005 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVDX);
9006 }
9007
9008 static void
9009 do_mav_binops_1d (char * str)
9010 {
9011 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVF);
9012 }
9013
9014 static void
9015 do_mav_binops_1e (char * str)
9016 {
9017 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVD);
9018 }
9019
9020 static void
9021 do_mav_binops_1f (char * str)
9022 {
9023 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVF);
9024 }
9025
9026 static void
9027 do_mav_binops_1g (char * str)
9028 {
9029 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVD);
9030 }
9031
9032 static void
9033 do_mav_binops_1h (char * str)
9034 {
9035 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVFX);
9036 }
9037
9038 static void
9039 do_mav_binops_1i (char * str)
9040 {
9041 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVFX);
9042 }
9043
9044 static void
9045 do_mav_binops_1j (char * str)
9046 {
9047 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVDX);
9048 }
9049
9050 static void
9051 do_mav_binops_1k (char * str)
9052 {
9053 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVDX);
9054 }
9055
9056 static void
9057 do_mav_binops_1l (char * str)
9058 {
9059 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVF);
9060 }
9061
9062 static void
9063 do_mav_binops_1m (char * str)
9064 {
9065 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVD);
9066 }
9067
9068 static void
9069 do_mav_binops_1n (char * str)
9070 {
9071 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVFX);
9072 }
9073
9074 static void
9075 do_mav_binops_1o (char * str)
9076 {
9077 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVDX, REG_TYPE_MVDX);
9078 }
9079
9080 static void
9081 do_mav_binops_2a (char * str)
9082 {
9083 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVF, REG_TYPE_RN);
9084 }
9085
9086 static void
9087 do_mav_binops_2b (char * str)
9088 {
9089 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVD, REG_TYPE_RN);
9090 }
9091
9092 static void
9093 do_mav_binops_2c (char * str)
9094 {
9095 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVDX, REG_TYPE_RN);
9096 }
9097
9098 static void
9099 do_mav_binops_3a (char * str)
9100 {
9101 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVAX, REG_TYPE_MVFX);
9102 }
9103
9104 static void
9105 do_mav_binops_3b (char * str)
9106 {
9107 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVFX, REG_TYPE_MVAX);
9108 }
9109
9110 static void
9111 do_mav_binops_3c (char * str)
9112 {
9113 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVAX, REG_TYPE_MVDX);
9114 }
9115
9116 static void
9117 do_mav_binops_3d (char * str)
9118 {
9119 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVDX, REG_TYPE_MVAX);
9120 }
9121
9122 static void
9123 do_mav_triple_4a (char * str)
9124 {
9125 do_mav_triple (str, MAV_MODE4, REG_TYPE_MVFX, REG_TYPE_MVFX, REG_TYPE_RN);
9126 }
9127
9128 static void
9129 do_mav_triple_4b (char * str)
9130 {
9131 do_mav_triple (str, MAV_MODE4, REG_TYPE_MVDX, REG_TYPE_MVDX, REG_TYPE_RN);
9132 }
9133
9134 static void
9135 do_mav_triple_5a (char * str)
9136 {
9137 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVF, REG_TYPE_MVF);
9138 }
9139
9140 static void
9141 do_mav_triple_5b (char * str)
9142 {
9143 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVD, REG_TYPE_MVD);
9144 }
9145
9146 static void
9147 do_mav_triple_5c (char * str)
9148 {
9149 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVFX, REG_TYPE_MVFX);
9150 }
9151
9152 static void
9153 do_mav_triple_5d (char * str)
9154 {
9155 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVDX, REG_TYPE_MVDX);
9156 }
9157
9158 static void
9159 do_mav_triple_5e (char * str)
9160 {
9161 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVF, REG_TYPE_MVF, REG_TYPE_MVF);
9162 }
9163
9164 static void
9165 do_mav_triple_5f (char * str)
9166 {
9167 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVD, REG_TYPE_MVD, REG_TYPE_MVD);
9168 }
9169
9170 static void
9171 do_mav_triple_5g (char * str)
9172 {
9173 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVFX, REG_TYPE_MVFX, REG_TYPE_MVFX);
9174 }
9175
9176 static void
9177 do_mav_triple_5h (char * str)
9178 {
9179 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVDX, REG_TYPE_MVDX, REG_TYPE_MVDX);
9180 }
9181
9182 /* Isnsn like "foo W,X,Y,Z".
9183 where W=MVAX[0:3] and X,Y,Z=MVFX[0:15]. */
9184
9185 static void
9186 do_mav_quad (char * str,
9187 int mode,
9188 enum arm_reg_type reg0,
9189 enum arm_reg_type reg1,
9190 enum arm_reg_type reg2,
9191 enum arm_reg_type reg3)
9192 {
9193 int shift0, shift1, shift2, shift3;
9194
9195 shift0= mode & 0xff;
9196 shift1 = (mode >> 8) & 0xff;
9197 shift2 = (mode >> 16) & 0xff;
9198 shift3 = (mode >> 24) & 0xff;
9199
9200 skip_whitespace (str);
9201
9202 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
9203 || skip_past_comma (&str) == FAIL
9204 || mav_reg_required_here (&str, shift1, reg1) == FAIL
9205 || skip_past_comma (&str) == FAIL
9206 || mav_reg_required_here (&str, shift2, reg2) == FAIL
9207 || skip_past_comma (&str) == FAIL
9208 || mav_reg_required_here (&str, shift3, reg3) == FAIL)
9209 {
9210 if (!inst.error)
9211 inst.error = BAD_ARGS;
9212 }
9213 else
9214 end_of_line (str);
9215 }
9216
9217 static void
9218 do_mav_quad_6a (char * str)
9219 {
9220 do_mav_quad (str, MAV_MODE6, REG_TYPE_MVAX, REG_TYPE_MVFX, REG_TYPE_MVFX,
9221 REG_TYPE_MVFX);
9222 }
9223
9224 static void
9225 do_mav_quad_6b (char * str)
9226 {
9227 do_mav_quad (str, MAV_MODE6, REG_TYPE_MVAX, REG_TYPE_MVAX, REG_TYPE_MVFX,
9228 REG_TYPE_MVFX);
9229 }
9230
9231 /* cfmvsc32<cond> DSPSC,MVDX[15:0]. */
9232 static void
9233 do_mav_dspsc_1 (char * str)
9234 {
9235 skip_whitespace (str);
9236
9237 /* cfmvsc32. */
9238 if (mav_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL
9239 || skip_past_comma (&str) == FAIL
9240 || mav_reg_required_here (&str, 12, REG_TYPE_MVDX) == FAIL)
9241 {
9242 if (!inst.error)
9243 inst.error = BAD_ARGS;
9244
9245 return;
9246 }
9247
9248 end_of_line (str);
9249 }
9250
9251 /* cfmv32sc<cond> MVDX[15:0],DSPSC. */
9252 static void
9253 do_mav_dspsc_2 (char * str)
9254 {
9255 skip_whitespace (str);
9256
9257 /* cfmv32sc. */
9258 if (mav_reg_required_here (&str, 12, REG_TYPE_MVDX) == FAIL
9259 || skip_past_comma (&str) == FAIL
9260 || mav_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL)
9261 {
9262 if (!inst.error)
9263 inst.error = BAD_ARGS;
9264
9265 return;
9266 }
9267
9268 end_of_line (str);
9269 }
9270
9271 /* Maverick shift immediate instructions.
9272 cfsh32<cond> MVFX[15:0],MVFX[15:0],Shift[6:0].
9273 cfsh64<cond> MVDX[15:0],MVDX[15:0],Shift[6:0]. */
9274
9275 static void
9276 do_mav_shift (char * str,
9277 enum arm_reg_type reg0,
9278 enum arm_reg_type reg1)
9279 {
9280 int error;
9281 int imm, neg = 0;
9282
9283 skip_whitespace (str);
9284
9285 error = 0;
9286
9287 if (mav_reg_required_here (&str, 12, reg0) == FAIL
9288 || skip_past_comma (&str) == FAIL
9289 || mav_reg_required_here (&str, 16, reg1) == FAIL
9290 || skip_past_comma (&str) == FAIL)
9291 {
9292 if (!inst.error)
9293 inst.error = BAD_ARGS;
9294 return;
9295 }
9296
9297 /* Calculate the immediate operand.
9298 The operand is a 7bit signed number. */
9299 skip_whitespace (str);
9300
9301 if (*str == '#')
9302 ++str;
9303
9304 if (!ISDIGIT (*str) && *str != '-')
9305 {
9306 inst.error = _("expecting immediate, 7bit operand");
9307 return;
9308 }
9309
9310 if (*str == '-')
9311 {
9312 neg = 1;
9313 ++str;
9314 }
9315
9316 for (imm = 0; *str && ISDIGIT (*str); ++str)
9317 imm = imm * 10 + *str - '0';
9318
9319 if (imm > 64)
9320 {
9321 inst.error = _("immediate out of range");
9322 return;
9323 }
9324
9325 /* Make negative imm's into 7bit signed numbers. */
9326 if (neg)
9327 {
9328 imm = -imm;
9329 imm &= 0x0000007f;
9330 }
9331
9332 /* Bits 0-3 of the insn should have bits 0-3 of the immediate.
9333 Bits 5-7 of the insn should have bits 4-6 of the immediate.
9334 Bit 4 should be 0. */
9335 imm = (imm & 0xf) | ((imm & 0x70) << 1);
9336
9337 inst.instruction |= imm;
9338 end_of_line (str);
9339 }
9340
9341 static void
9342 do_mav_shift_1 (char * str)
9343 {
9344 do_mav_shift (str, REG_TYPE_MVFX, REG_TYPE_MVFX);
9345 }
9346
9347 static void
9348 do_mav_shift_2 (char * str)
9349 {
9350 do_mav_shift (str, REG_TYPE_MVDX, REG_TYPE_MVDX);
9351 }
9352
9353 static int
9354 mav_parse_offset (char ** str, int * negative)
9355 {
9356 char * p = *str;
9357 int offset;
9358
9359 *negative = 0;
9360
9361 skip_whitespace (p);
9362
9363 if (*p == '#')
9364 ++p;
9365
9366 if (*p == '-')
9367 {
9368 *negative = 1;
9369 ++p;
9370 }
9371
9372 if (!ISDIGIT (*p))
9373 {
9374 inst.error = _("offset expected");
9375 return 0;
9376 }
9377
9378 for (offset = 0; *p && ISDIGIT (*p); ++p)
9379 offset = offset * 10 + *p - '0';
9380
9381 if (offset > 0x3fc)
9382 {
9383 inst.error = _("offset out of range");
9384 return 0;
9385 }
9386 if (offset & 0x3)
9387 {
9388 inst.error = _("offset not a multiple of 4");
9389 return 0;
9390 }
9391
9392 *str = p;
9393
9394 return *negative ? -offset : offset;
9395 }
9396
9397 /* Maverick load/store instructions.
9398 <insn><cond> CRd,[Rn,<offset>]{!}.
9399 <insn><cond> CRd,[Rn],<offset>. */
9400
9401 static void
9402 do_mav_ldst (char * str, enum arm_reg_type reg0)
9403 {
9404 int offset, negative;
9405
9406 skip_whitespace (str);
9407
9408 if (mav_reg_required_here (&str, 12, reg0) == FAIL
9409 || skip_past_comma (&str) == FAIL
9410 || *str++ != '['
9411 || reg_required_here (&str, 16) == FAIL)
9412 goto fail_ldst;
9413
9414 if (skip_past_comma (&str) == SUCCESS)
9415 {
9416 /* You are here: "<offset>]{!}". */
9417 inst.instruction |= PRE_INDEX;
9418
9419 offset = mav_parse_offset (&str, &negative);
9420
9421 if (inst.error)
9422 return;
9423
9424 if (*str++ != ']')
9425 {
9426 inst.error = _("missing ]");
9427 return;
9428 }
9429
9430 if (*str == '!')
9431 {
9432 inst.instruction |= WRITE_BACK;
9433 ++str;
9434 }
9435 }
9436 else
9437 {
9438 /* You are here: "], <offset>". */
9439 if (*str++ != ']')
9440 {
9441 inst.error = _("missing ]");
9442 return;
9443 }
9444
9445 if (skip_past_comma (&str) == FAIL
9446 || (offset = mav_parse_offset (&str, &negative), inst.error))
9447 goto fail_ldst;
9448
9449 inst.instruction |= CP_T_WB; /* Post indexed, set bit W. */
9450 }
9451
9452 if (negative)
9453 offset = -offset;
9454 else
9455 inst.instruction |= CP_T_UD; /* Positive, so set bit U. */
9456
9457 inst.instruction |= offset >> 2;
9458 end_of_line (str);
9459 return;
9460
9461 fail_ldst:
9462 if (!inst.error)
9463 inst.error = BAD_ARGS;
9464 }
9465
9466 static void
9467 do_mav_ldst_1 (char * str)
9468 {
9469 do_mav_ldst (str, REG_TYPE_MVF);
9470 }
9471
9472 static void
9473 do_mav_ldst_2 (char * str)
9474 {
9475 do_mav_ldst (str, REG_TYPE_MVD);
9476 }
9477
9478 static void
9479 do_mav_ldst_3 (char * str)
9480 {
9481 do_mav_ldst (str, REG_TYPE_MVFX);
9482 }
9483
9484 static void
9485 do_mav_ldst_4 (char * str)
9486 {
9487 do_mav_ldst (str, REG_TYPE_MVDX);
9488 }
9489
9490 static void
9491 do_t_nop (char * str)
9492 {
9493 /* Do nothing. */
9494 end_of_line (str);
9495 }
9496
9497 /* Handle the Format 4 instructions that do not have equivalents in other
9498 formats. That is, ADC, AND, EOR, SBC, ROR, TST, NEG, CMN, ORR, MUL,
9499 BIC and MVN. */
9500
9501 static void
9502 do_t_arit (char * str)
9503 {
9504 int Rd, Rs, Rn;
9505
9506 skip_whitespace (str);
9507
9508 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9509 || skip_past_comma (&str) == FAIL
9510 || (Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9511 {
9512 inst.error = BAD_ARGS;
9513 return;
9514 }
9515
9516 if (skip_past_comma (&str) != FAIL)
9517 {
9518 /* Three operand format not allowed for TST, CMN, NEG and MVN.
9519 (It isn't allowed for CMP either, but that isn't handled by this
9520 function.) */
9521 if (inst.instruction == T_OPCODE_TST
9522 || inst.instruction == T_OPCODE_CMN
9523 || inst.instruction == T_OPCODE_NEG
9524 || inst.instruction == T_OPCODE_MVN)
9525 {
9526 inst.error = BAD_ARGS;
9527 return;
9528 }
9529
9530 if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9531 return;
9532
9533 if (Rs != Rd)
9534 {
9535 inst.error = _("dest and source1 must be the same register");
9536 return;
9537 }
9538 Rs = Rn;
9539 }
9540
9541 if (inst.instruction == T_OPCODE_MUL
9542 && Rs == Rd)
9543 as_tsktsk (_("Rs and Rd must be different in MUL"));
9544
9545 inst.instruction |= Rd | (Rs << 3);
9546 end_of_line (str);
9547 }
9548
9549 static void
9550 do_t_add (char * str)
9551 {
9552 thumb_add_sub (str, 0);
9553 }
9554
9555 static void
9556 do_t_asr (char * str)
9557 {
9558 thumb_shift (str, THUMB_ASR);
9559 }
9560
9561 static void
9562 do_t_branch9 (char * str)
9563 {
9564 if (my_get_expression (&inst.reloc.exp, &str))
9565 return;
9566 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH9;
9567 inst.reloc.pc_rel = 1;
9568 end_of_line (str);
9569 }
9570
9571 static void
9572 do_t_branch12 (char * str)
9573 {
9574 if (my_get_expression (&inst.reloc.exp, &str))
9575 return;
9576 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH12;
9577 inst.reloc.pc_rel = 1;
9578 end_of_line (str);
9579 }
9580
9581 /* Find the real, Thumb encoded start of a Thumb function. */
9582
9583 static symbolS *
9584 find_real_start (symbolS * symbolP)
9585 {
9586 char * real_start;
9587 const char * name = S_GET_NAME (symbolP);
9588 symbolS * new_target;
9589
9590 /* This definition must agree with the one in gcc/config/arm/thumb.c. */
9591 #define STUB_NAME ".real_start_of"
9592
9593 if (name == NULL)
9594 abort ();
9595
9596 /* Names that start with '.' are local labels, not function entry points.
9597 The compiler may generate BL instructions to these labels because it
9598 needs to perform a branch to a far away location. */
9599 if (name[0] == '.')
9600 return symbolP;
9601
9602 real_start = malloc (strlen (name) + strlen (STUB_NAME) + 1);
9603 sprintf (real_start, "%s%s", STUB_NAME, name);
9604
9605 new_target = symbol_find (real_start);
9606
9607 if (new_target == NULL)
9608 {
9609 as_warn ("Failed to find real start of function: %s\n", name);
9610 new_target = symbolP;
9611 }
9612
9613 free (real_start);
9614
9615 return new_target;
9616 }
9617
9618 static void
9619 do_t_branch23 (char * str)
9620 {
9621 if (my_get_expression (& inst.reloc.exp, & str))
9622 return;
9623
9624 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH23;
9625 inst.reloc.pc_rel = 1;
9626 end_of_line (str);
9627
9628 /* If the destination of the branch is a defined symbol which does not have
9629 the THUMB_FUNC attribute, then we must be calling a function which has
9630 the (interfacearm) attribute. We look for the Thumb entry point to that
9631 function and change the branch to refer to that function instead. */
9632 if ( inst.reloc.exp.X_op == O_symbol
9633 && inst.reloc.exp.X_add_symbol != NULL
9634 && S_IS_DEFINED (inst.reloc.exp.X_add_symbol)
9635 && ! THUMB_IS_FUNC (inst.reloc.exp.X_add_symbol))
9636 inst.reloc.exp.X_add_symbol =
9637 find_real_start (inst.reloc.exp.X_add_symbol);
9638 }
9639
9640 static void
9641 do_t_bx (char * str)
9642 {
9643 int reg;
9644
9645 skip_whitespace (str);
9646
9647 if ((reg = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
9648 return;
9649
9650 /* This sets THUMB_H2 from the top bit of reg. */
9651 inst.instruction |= reg << 3;
9652
9653 /* ??? FIXME: Should add a hacky reloc here if reg is REG_PC. The reloc
9654 should cause the alignment to be checked once it is known. This is
9655 because BX PC only works if the instruction is word aligned. */
9656
9657 end_of_line (str);
9658 }
9659
9660 static void
9661 do_t_compare (char * str)
9662 {
9663 thumb_mov_compare (str, THUMB_COMPARE);
9664 }
9665
9666 static void
9667 do_t_ldmstm (char * str)
9668 {
9669 int Rb;
9670 long range;
9671
9672 skip_whitespace (str);
9673
9674 if ((Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9675 return;
9676
9677 if (*str != '!')
9678 as_warn (_("inserted missing '!': load/store multiple always writes back base register"));
9679 else
9680 str++;
9681
9682 if (skip_past_comma (&str) == FAIL
9683 || (range = reg_list (&str)) == FAIL)
9684 {
9685 if (! inst.error)
9686 inst.error = BAD_ARGS;
9687 return;
9688 }
9689
9690 if (inst.reloc.type != BFD_RELOC_UNUSED)
9691 {
9692 /* This really doesn't seem worth it. */
9693 inst.reloc.type = BFD_RELOC_UNUSED;
9694 inst.error = _("expression too complex");
9695 return;
9696 }
9697
9698 if (range & ~0xff)
9699 {
9700 inst.error = _("only lo-regs valid in load/store multiple");
9701 return;
9702 }
9703
9704 inst.instruction |= (Rb << 8) | range;
9705 end_of_line (str);
9706 }
9707
9708 static void
9709 do_t_ldr (char * str)
9710 {
9711 thumb_load_store (str, THUMB_LOAD, THUMB_WORD);
9712 }
9713
9714 static void
9715 do_t_ldrb (char * str)
9716 {
9717 thumb_load_store (str, THUMB_LOAD, THUMB_BYTE);
9718 }
9719
9720 static void
9721 do_t_ldrh (char * str)
9722 {
9723 thumb_load_store (str, THUMB_LOAD, THUMB_HALFWORD);
9724 }
9725
9726 static void
9727 do_t_lds (char * str)
9728 {
9729 int Rd, Rb, Ro;
9730
9731 skip_whitespace (str);
9732
9733 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9734 || skip_past_comma (&str) == FAIL
9735 || *str++ != '['
9736 || (Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9737 || skip_past_comma (&str) == FAIL
9738 || (Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9739 || *str++ != ']')
9740 {
9741 if (! inst.error)
9742 inst.error = _("syntax: ldrs[b] Rd, [Rb, Ro]");
9743 return;
9744 }
9745
9746 inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
9747 end_of_line (str);
9748 }
9749
9750 static void
9751 do_t_lsl (char * str)
9752 {
9753 thumb_shift (str, THUMB_LSL);
9754 }
9755
9756 static void
9757 do_t_lsr (char * str)
9758 {
9759 thumb_shift (str, THUMB_LSR);
9760 }
9761
9762 static void
9763 do_t_mov (char * str)
9764 {
9765 thumb_mov_compare (str, THUMB_MOVE);
9766 }
9767
9768 static void
9769 do_t_push_pop (char * str)
9770 {
9771 long range;
9772
9773 skip_whitespace (str);
9774
9775 if ((range = reg_list (&str)) == FAIL)
9776 {
9777 if (! inst.error)
9778 inst.error = BAD_ARGS;
9779 return;
9780 }
9781
9782 if (inst.reloc.type != BFD_RELOC_UNUSED)
9783 {
9784 /* This really doesn't seem worth it. */
9785 inst.reloc.type = BFD_RELOC_UNUSED;
9786 inst.error = _("expression too complex");
9787 return;
9788 }
9789
9790 if (range & ~0xff)
9791 {
9792 if ((inst.instruction == T_OPCODE_PUSH
9793 && (range & ~0xff) == 1 << REG_LR)
9794 || (inst.instruction == T_OPCODE_POP
9795 && (range & ~0xff) == 1 << REG_PC))
9796 {
9797 inst.instruction |= THUMB_PP_PC_LR;
9798 range &= 0xff;
9799 }
9800 else
9801 {
9802 inst.error = _("invalid register list to push/pop instruction");
9803 return;
9804 }
9805 }
9806
9807 inst.instruction |= range;
9808 end_of_line (str);
9809 }
9810
9811 static void
9812 do_t_str (char * str)
9813 {
9814 thumb_load_store (str, THUMB_STORE, THUMB_WORD);
9815 }
9816
9817 static void
9818 do_t_strb (char * str)
9819 {
9820 thumb_load_store (str, THUMB_STORE, THUMB_BYTE);
9821 }
9822
9823 static void
9824 do_t_strh (char * str)
9825 {
9826 thumb_load_store (str, THUMB_STORE, THUMB_HALFWORD);
9827 }
9828
9829 static void
9830 do_t_sub (char * str)
9831 {
9832 thumb_add_sub (str, 1);
9833 }
9834
9835 static void
9836 do_t_swi (char * str)
9837 {
9838 skip_whitespace (str);
9839
9840 if (my_get_expression (&inst.reloc.exp, &str))
9841 return;
9842
9843 inst.reloc.type = BFD_RELOC_ARM_SWI;
9844 end_of_line (str);
9845 }
9846
9847 static void
9848 do_t_adr (char * str)
9849 {
9850 int reg;
9851
9852 /* This is a pseudo-op of the form "adr rd, label" to be converted
9853 into a relative address of the form "add rd, pc, #label-.-4". */
9854 skip_whitespace (str);
9855
9856 /* Store Rd in temporary location inside instruction. */
9857 if ((reg = reg_required_here (&str, 4)) == FAIL
9858 || (reg > 7) /* For Thumb reg must be r0..r7. */
9859 || skip_past_comma (&str) == FAIL
9860 || my_get_expression (&inst.reloc.exp, &str))
9861 {
9862 if (!inst.error)
9863 inst.error = BAD_ARGS;
9864 return;
9865 }
9866
9867 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
9868 inst.reloc.exp.X_add_number -= 4; /* PC relative adjust. */
9869 inst.reloc.pc_rel = 1;
9870 inst.instruction |= REG_PC; /* Rd is already placed into the instruction. */
9871
9872 end_of_line (str);
9873 }
9874
9875 static void
9876 insert_reg (const struct reg_entry * r,
9877 struct hash_control * htab)
9878 {
9879 int len = strlen (r->name) + 2;
9880 char * buf = xmalloc (len);
9881 char * buf2 = xmalloc (len);
9882 int i = 0;
9883
9884 #ifdef REGISTER_PREFIX
9885 buf[i++] = REGISTER_PREFIX;
9886 #endif
9887
9888 strcpy (buf + i, r->name);
9889
9890 for (i = 0; buf[i]; i++)
9891 buf2[i] = TOUPPER (buf[i]);
9892
9893 buf2[i] = '\0';
9894
9895 hash_insert (htab, buf, (PTR) r);
9896 hash_insert (htab, buf2, (PTR) r);
9897 }
9898
9899 static void
9900 build_reg_hsh (struct reg_map * map)
9901 {
9902 const struct reg_entry *r;
9903
9904 if ((map->htab = hash_new ()) == NULL)
9905 as_fatal (_("virtual memory exhausted"));
9906
9907 for (r = map->names; r->name != NULL; r++)
9908 insert_reg (r, map->htab);
9909 }
9910
9911 static void
9912 insert_reg_alias (char * str,
9913 int regnum,
9914 struct hash_control *htab)
9915 {
9916 const char * error;
9917 struct reg_entry * new = xmalloc (sizeof (struct reg_entry));
9918 const char * name = xmalloc (strlen (str) + 1);
9919
9920 strcpy ((char *) name, str);
9921
9922 new->name = name;
9923 new->number = regnum;
9924 new->builtin = FALSE;
9925
9926 error = hash_insert (htab, name, (PTR) new);
9927 if (error)
9928 {
9929 as_bad (_("failed to create an alias for %s, reason: %s"),
9930 str, error);
9931 free ((char *) name);
9932 free (new);
9933 }
9934 }
9935
9936 /* Look for the .req directive. This is of the form:
9937
9938 new_register_name .req existing_register_name
9939
9940 If we find one, or if it looks sufficiently like one that we want to
9941 handle any error here, return non-zero. Otherwise return zero. */
9942
9943 static int
9944 create_register_alias (char * newname, char * p)
9945 {
9946 char * q;
9947 char c;
9948
9949 q = p;
9950 skip_whitespace (q);
9951
9952 c = *p;
9953 *p = '\0';
9954
9955 if (*q && !strncmp (q, ".req ", 5))
9956 {
9957 char *copy_of_str;
9958 char *r;
9959
9960 #ifndef IGNORE_OPCODE_CASE
9961 newname = original_case_string;
9962 #endif
9963 copy_of_str = newname;
9964
9965 q += 4;
9966 skip_whitespace (q);
9967
9968 for (r = q; *r != '\0'; r++)
9969 if (*r == ' ')
9970 break;
9971
9972 if (r != q)
9973 {
9974 enum arm_reg_type new_type, old_type;
9975 int old_regno;
9976 char d = *r;
9977
9978 *r = '\0';
9979 old_type = arm_reg_parse_any (q);
9980 *r = d;
9981
9982 new_type = arm_reg_parse_any (newname);
9983
9984 if (new_type == REG_TYPE_MAX)
9985 {
9986 if (old_type != REG_TYPE_MAX)
9987 {
9988 old_regno = arm_reg_parse (&q, all_reg_maps[old_type].htab);
9989 insert_reg_alias (newname, old_regno,
9990 all_reg_maps[old_type].htab);
9991 }
9992 else
9993 as_warn (_("register '%s' does not exist\n"), q);
9994 }
9995 else if (old_type == REG_TYPE_MAX)
9996 {
9997 as_warn (_("ignoring redefinition of register alias '%s' to non-existant register '%s'"),
9998 copy_of_str, q);
9999 }
10000 else
10001 {
10002 /* Do not warn about redefinitions to the same alias. */
10003 if (new_type != old_type
10004 || (arm_reg_parse (&q, all_reg_maps[old_type].htab)
10005 != arm_reg_parse (&q, all_reg_maps[new_type].htab)))
10006 as_warn (_("ignoring redefinition of register alias '%s'"),
10007 copy_of_str);
10008
10009 }
10010 }
10011 else
10012 as_warn (_("ignoring incomplete .req pseuso op"));
10013
10014 *p = c;
10015 return 1;
10016 }
10017
10018 *p = c;
10019 return 0;
10020 }
10021
10022 static void
10023 set_constant_flonums (void)
10024 {
10025 int i;
10026
10027 for (i = 0; i < NUM_FLOAT_VALS; i++)
10028 if (atof_ieee ((char *) fp_const[i], 'x', fp_values[i]) == NULL)
10029 abort ();
10030 }
10031
10032 \f
10033 static const struct asm_opcode insns[] =
10034 {
10035 /* Core ARM Instructions. */
10036 {"and", 0xe0000000, 3, ARM_EXT_V1, do_arit},
10037 {"ands", 0xe0100000, 3, ARM_EXT_V1, do_arit},
10038 {"eor", 0xe0200000, 3, ARM_EXT_V1, do_arit},
10039 {"eors", 0xe0300000, 3, ARM_EXT_V1, do_arit},
10040 {"sub", 0xe0400000, 3, ARM_EXT_V1, do_arit},
10041 {"subs", 0xe0500000, 3, ARM_EXT_V1, do_arit},
10042 {"rsb", 0xe0600000, 3, ARM_EXT_V1, do_arit},
10043 {"rsbs", 0xe0700000, 3, ARM_EXT_V1, do_arit},
10044 {"add", 0xe0800000, 3, ARM_EXT_V1, do_arit},
10045 {"adds", 0xe0900000, 3, ARM_EXT_V1, do_arit},
10046 {"adc", 0xe0a00000, 3, ARM_EXT_V1, do_arit},
10047 {"adcs", 0xe0b00000, 3, ARM_EXT_V1, do_arit},
10048 {"sbc", 0xe0c00000, 3, ARM_EXT_V1, do_arit},
10049 {"sbcs", 0xe0d00000, 3, ARM_EXT_V1, do_arit},
10050 {"rsc", 0xe0e00000, 3, ARM_EXT_V1, do_arit},
10051 {"rscs", 0xe0f00000, 3, ARM_EXT_V1, do_arit},
10052 {"orr", 0xe1800000, 3, ARM_EXT_V1, do_arit},
10053 {"orrs", 0xe1900000, 3, ARM_EXT_V1, do_arit},
10054 {"bic", 0xe1c00000, 3, ARM_EXT_V1, do_arit},
10055 {"bics", 0xe1d00000, 3, ARM_EXT_V1, do_arit},
10056
10057 {"tst", 0xe1100000, 3, ARM_EXT_V1, do_cmp},
10058 {"tsts", 0xe1100000, 3, ARM_EXT_V1, do_cmp},
10059 {"tstp", 0xe110f000, 3, ARM_EXT_V1, do_cmp},
10060 {"teq", 0xe1300000, 3, ARM_EXT_V1, do_cmp},
10061 {"teqs", 0xe1300000, 3, ARM_EXT_V1, do_cmp},
10062 {"teqp", 0xe130f000, 3, ARM_EXT_V1, do_cmp},
10063 {"cmp", 0xe1500000, 3, ARM_EXT_V1, do_cmp},
10064 {"cmps", 0xe1500000, 3, ARM_EXT_V1, do_cmp},
10065 {"cmpp", 0xe150f000, 3, ARM_EXT_V1, do_cmp},
10066 {"cmn", 0xe1700000, 3, ARM_EXT_V1, do_cmp},
10067 {"cmns", 0xe1700000, 3, ARM_EXT_V1, do_cmp},
10068 {"cmnp", 0xe170f000, 3, ARM_EXT_V1, do_cmp},
10069
10070 {"mov", 0xe1a00000, 3, ARM_EXT_V1, do_mov},
10071 {"movs", 0xe1b00000, 3, ARM_EXT_V1, do_mov},
10072 {"mvn", 0xe1e00000, 3, ARM_EXT_V1, do_mov},
10073 {"mvns", 0xe1f00000, 3, ARM_EXT_V1, do_mov},
10074
10075 {"ldr", 0xe4100000, 3, ARM_EXT_V1, do_ldst},
10076 {"ldrb", 0xe4500000, 3, ARM_EXT_V1, do_ldst},
10077 {"ldrt", 0xe4300000, 3, ARM_EXT_V1, do_ldstt},
10078 {"ldrbt", 0xe4700000, 3, ARM_EXT_V1, do_ldstt},
10079 {"str", 0xe4000000, 3, ARM_EXT_V1, do_ldst},
10080 {"strb", 0xe4400000, 3, ARM_EXT_V1, do_ldst},
10081 {"strt", 0xe4200000, 3, ARM_EXT_V1, do_ldstt},
10082 {"strbt", 0xe4600000, 3, ARM_EXT_V1, do_ldstt},
10083
10084 {"stmia", 0xe8800000, 3, ARM_EXT_V1, do_ldmstm},
10085 {"stmib", 0xe9800000, 3, ARM_EXT_V1, do_ldmstm},
10086 {"stmda", 0xe8000000, 3, ARM_EXT_V1, do_ldmstm},
10087 {"stmdb", 0xe9000000, 3, ARM_EXT_V1, do_ldmstm},
10088 {"stmfd", 0xe9000000, 3, ARM_EXT_V1, do_ldmstm},
10089 {"stmfa", 0xe9800000, 3, ARM_EXT_V1, do_ldmstm},
10090 {"stmea", 0xe8800000, 3, ARM_EXT_V1, do_ldmstm},
10091 {"stmed", 0xe8000000, 3, ARM_EXT_V1, do_ldmstm},
10092
10093 {"ldmia", 0xe8900000, 3, ARM_EXT_V1, do_ldmstm},
10094 {"ldmib", 0xe9900000, 3, ARM_EXT_V1, do_ldmstm},
10095 {"ldmda", 0xe8100000, 3, ARM_EXT_V1, do_ldmstm},
10096 {"ldmdb", 0xe9100000, 3, ARM_EXT_V1, do_ldmstm},
10097 {"ldmfd", 0xe8900000, 3, ARM_EXT_V1, do_ldmstm},
10098 {"ldmfa", 0xe8100000, 3, ARM_EXT_V1, do_ldmstm},
10099 {"ldmea", 0xe9100000, 3, ARM_EXT_V1, do_ldmstm},
10100 {"ldmed", 0xe9900000, 3, ARM_EXT_V1, do_ldmstm},
10101
10102 {"swi", 0xef000000, 3, ARM_EXT_V1, do_swi},
10103 #ifdef TE_WINCE
10104 /* XXX This is the wrong place to do this. Think multi-arch. */
10105 {"bl", 0xeb000000, 2, ARM_EXT_V1, do_branch},
10106 {"b", 0xea000000, 1, ARM_EXT_V1, do_branch},
10107 #else
10108 {"bl", 0xebfffffe, 2, ARM_EXT_V1, do_branch},
10109 {"b", 0xeafffffe, 1, ARM_EXT_V1, do_branch},
10110 #endif
10111
10112 /* Pseudo ops. */
10113 {"adr", 0xe28f0000, 3, ARM_EXT_V1, do_adr},
10114 {"adrl", 0xe28f0000, 3, ARM_EXT_V1, do_adrl},
10115 {"nop", 0xe1a00000, 3, ARM_EXT_V1, do_nop},
10116
10117 /* ARM 2 multiplies. */
10118 {"mul", 0xe0000090, 3, ARM_EXT_V2, do_mul},
10119 {"muls", 0xe0100090, 3, ARM_EXT_V2, do_mul},
10120 {"mla", 0xe0200090, 3, ARM_EXT_V2, do_mla},
10121 {"mlas", 0xe0300090, 3, ARM_EXT_V2, do_mla},
10122
10123 /* Generic coprocessor instructions. */
10124 {"cdp", 0xee000000, 3, ARM_EXT_V2, do_cdp},
10125 {"ldc", 0xec100000, 3, ARM_EXT_V2, do_lstc},
10126 {"ldcl", 0xec500000, 3, ARM_EXT_V2, do_lstc},
10127 {"stc", 0xec000000, 3, ARM_EXT_V2, do_lstc},
10128 {"stcl", 0xec400000, 3, ARM_EXT_V2, do_lstc},
10129 {"mcr", 0xee000010, 3, ARM_EXT_V2, do_co_reg},
10130 {"mrc", 0xee100010, 3, ARM_EXT_V2, do_co_reg},
10131
10132 /* ARM 3 - swp instructions. */
10133 {"swp", 0xe1000090, 3, ARM_EXT_V2S, do_swap},
10134 {"swpb", 0xe1400090, 3, ARM_EXT_V2S, do_swap},
10135
10136 /* ARM 6 Status register instructions. */
10137 {"mrs", 0xe10f0000, 3, ARM_EXT_V3, do_mrs},
10138 {"msr", 0xe120f000, 3, ARM_EXT_V3, do_msr},
10139 /* ScottB: our code uses 0xe128f000 for msr.
10140 NickC: but this is wrong because the bits 16 through 19 are
10141 handled by the PSR_xxx defines above. */
10142
10143 /* ARM 7M long multiplies. */
10144 {"smull", 0xe0c00090, 5, ARM_EXT_V3M, do_mull},
10145 {"smulls", 0xe0d00090, 5, ARM_EXT_V3M, do_mull},
10146 {"umull", 0xe0800090, 5, ARM_EXT_V3M, do_mull},
10147 {"umulls", 0xe0900090, 5, ARM_EXT_V3M, do_mull},
10148 {"smlal", 0xe0e00090, 5, ARM_EXT_V3M, do_mull},
10149 {"smlals", 0xe0f00090, 5, ARM_EXT_V3M, do_mull},
10150 {"umlal", 0xe0a00090, 5, ARM_EXT_V3M, do_mull},
10151 {"umlals", 0xe0b00090, 5, ARM_EXT_V3M, do_mull},
10152
10153 /* ARM Architecture 4. */
10154 {"ldrh", 0xe01000b0, 3, ARM_EXT_V4, do_ldstv4},
10155 {"ldrsh", 0xe01000f0, 3, ARM_EXT_V4, do_ldstv4},
10156 {"ldrsb", 0xe01000d0, 3, ARM_EXT_V4, do_ldstv4},
10157 {"strh", 0xe00000b0, 3, ARM_EXT_V4, do_ldstv4},
10158
10159 /* ARM Architecture 4T. */
10160 /* Note: bx (and blx) are required on V5, even if the processor does
10161 not support Thumb. */
10162 {"bx", 0xe12fff10, 2, ARM_EXT_V4T | ARM_EXT_V5, do_bx},
10163
10164 /* ARM Architecture 5T. */
10165 /* Note: blx has 2 variants, so the .value is set dynamically.
10166 Only one of the variants has conditional execution. */
10167 {"blx", 0xe0000000, 3, ARM_EXT_V5, do_blx},
10168 {"clz", 0xe16f0f10, 3, ARM_EXT_V5, do_clz},
10169 {"bkpt", 0xe1200070, 0, ARM_EXT_V5, do_bkpt},
10170 {"ldc2", 0xfc100000, 0, ARM_EXT_V5, do_lstc2},
10171 {"ldc2l", 0xfc500000, 0, ARM_EXT_V5, do_lstc2},
10172 {"stc2", 0xfc000000, 0, ARM_EXT_V5, do_lstc2},
10173 {"stc2l", 0xfc400000, 0, ARM_EXT_V5, do_lstc2},
10174 {"cdp2", 0xfe000000, 0, ARM_EXT_V5, do_cdp2},
10175 {"mcr2", 0xfe000010, 0, ARM_EXT_V5, do_co_reg2},
10176 {"mrc2", 0xfe100010, 0, ARM_EXT_V5, do_co_reg2},
10177
10178 /* ARM Architecture 5TExP. */
10179 {"smlabb", 0xe1000080, 6, ARM_EXT_V5ExP, do_smla},
10180 {"smlatb", 0xe10000a0, 6, ARM_EXT_V5ExP, do_smla},
10181 {"smlabt", 0xe10000c0, 6, ARM_EXT_V5ExP, do_smla},
10182 {"smlatt", 0xe10000e0, 6, ARM_EXT_V5ExP, do_smla},
10183
10184 {"smlawb", 0xe1200080, 6, ARM_EXT_V5ExP, do_smla},
10185 {"smlawt", 0xe12000c0, 6, ARM_EXT_V5ExP, do_smla},
10186
10187 {"smlalbb", 0xe1400080, 7, ARM_EXT_V5ExP, do_smlal},
10188 {"smlaltb", 0xe14000a0, 7, ARM_EXT_V5ExP, do_smlal},
10189 {"smlalbt", 0xe14000c0, 7, ARM_EXT_V5ExP, do_smlal},
10190 {"smlaltt", 0xe14000e0, 7, ARM_EXT_V5ExP, do_smlal},
10191
10192 {"smulbb", 0xe1600080, 6, ARM_EXT_V5ExP, do_smul},
10193 {"smultb", 0xe16000a0, 6, ARM_EXT_V5ExP, do_smul},
10194 {"smulbt", 0xe16000c0, 6, ARM_EXT_V5ExP, do_smul},
10195 {"smultt", 0xe16000e0, 6, ARM_EXT_V5ExP, do_smul},
10196
10197 {"smulwb", 0xe12000a0, 6, ARM_EXT_V5ExP, do_smul},
10198 {"smulwt", 0xe12000e0, 6, ARM_EXT_V5ExP, do_smul},
10199
10200 {"qadd", 0xe1000050, 4, ARM_EXT_V5ExP, do_qadd},
10201 {"qdadd", 0xe1400050, 5, ARM_EXT_V5ExP, do_qadd},
10202 {"qsub", 0xe1200050, 4, ARM_EXT_V5ExP, do_qadd},
10203 {"qdsub", 0xe1600050, 5, ARM_EXT_V5ExP, do_qadd},
10204
10205 /* ARM Architecture 5TE. */
10206 {"pld", 0xf450f000, 0, ARM_EXT_V5E, do_pld},
10207 {"ldrd", 0xe00000d0, 3, ARM_EXT_V5E, do_ldrd},
10208 {"strd", 0xe00000f0, 3, ARM_EXT_V5E, do_ldrd},
10209
10210 {"mcrr", 0xec400000, 4, ARM_EXT_V5E, do_co_reg2c},
10211 {"mrrc", 0xec500000, 4, ARM_EXT_V5E, do_co_reg2c},
10212
10213 /* ARM Architecture 5TEJ. */
10214 {"bxj", 0xe12fff20, 3, ARM_EXT_V5J, do_bxj},
10215
10216 /* ARM V6. */
10217 { "cps", 0xf1020000, 0, ARM_EXT_V6, do_cps},
10218 { "cpsie", 0xf1080000, 0, ARM_EXT_V6, do_cpsi},
10219 { "cpsid", 0xf10C0000, 0, ARM_EXT_V6, do_cpsi},
10220 { "ldrex", 0xe1900f9f, 5, ARM_EXT_V6, do_ldrex},
10221 { "mcrr2", 0xfc400000, 0, ARM_EXT_V6, do_co_reg2c},
10222 { "mrrc2", 0xfc500000, 0, ARM_EXT_V6, do_co_reg2c},
10223 { "pkhbt", 0xe6800010, 5, ARM_EXT_V6, do_pkhbt},
10224 { "pkhtb", 0xe6800050, 5, ARM_EXT_V6, do_pkhtb},
10225 { "qadd16", 0xe6200f10, 6, ARM_EXT_V6, do_qadd16},
10226 { "qadd8", 0xe6200f90, 5, ARM_EXT_V6, do_qadd16},
10227 { "qaddsubx", 0xe6200f30, 8, ARM_EXT_V6, do_qadd16},
10228 { "qsub16", 0xe6200f70, 6, ARM_EXT_V6, do_qadd16},
10229 { "qsub8", 0xe6200ff0, 5, ARM_EXT_V6, do_qadd16},
10230 { "qsubaddx", 0xe6200f50, 8, ARM_EXT_V6, do_qadd16},
10231 { "sadd16", 0xe6100f10, 6, ARM_EXT_V6, do_qadd16},
10232 { "sadd8", 0xe6100f90, 5, ARM_EXT_V6, do_qadd16},
10233 { "saddsubx", 0xe6100f30, 8, ARM_EXT_V6, do_qadd16},
10234 { "shadd16", 0xe6300f10, 7, ARM_EXT_V6, do_qadd16},
10235 { "shadd8", 0xe6300f90, 6, ARM_EXT_V6, do_qadd16},
10236 { "shaddsubx", 0xe6300f30, 9, ARM_EXT_V6, do_qadd16},
10237 { "shsub16", 0xe6300f70, 7, ARM_EXT_V6, do_qadd16},
10238 { "shsub8", 0xe6300ff0, 6, ARM_EXT_V6, do_qadd16},
10239 { "shsubaddx", 0xe6300f50, 9, ARM_EXT_V6, do_qadd16},
10240 { "ssub16", 0xe6100f70, 6, ARM_EXT_V6, do_qadd16},
10241 { "ssub8", 0xe6100ff0, 5, ARM_EXT_V6, do_qadd16},
10242 { "ssubaddx", 0xe6100f50, 8, ARM_EXT_V6, do_qadd16},
10243 { "uadd16", 0xe6500f10, 6, ARM_EXT_V6, do_qadd16},
10244 { "uadd8", 0xe6500f90, 5, ARM_EXT_V6, do_qadd16},
10245 { "uaddsubx", 0xe6500f30, 8, ARM_EXT_V6, do_qadd16},
10246 { "uhadd16", 0xe6700f10, 7, ARM_EXT_V6, do_qadd16},
10247 { "uhadd8", 0xe6700f90, 6, ARM_EXT_V6, do_qadd16},
10248 { "uhaddsubx", 0xe6700f30, 9, ARM_EXT_V6, do_qadd16},
10249 { "uhsub16", 0xe6700f70, 7, ARM_EXT_V6, do_qadd16},
10250 { "uhsub8", 0xe6700ff0, 6, ARM_EXT_V6, do_qadd16},
10251 { "uhsubaddx", 0xe6700f50, 9, ARM_EXT_V6, do_qadd16},
10252 { "uqadd16", 0xe6600f10, 7, ARM_EXT_V6, do_qadd16},
10253 { "uqadd8", 0xe6600f90, 6, ARM_EXT_V6, do_qadd16},
10254 { "uqaddsubx", 0xe6600f30, 9, ARM_EXT_V6, do_qadd16},
10255 { "uqsub16", 0xe6600f70, 7, ARM_EXT_V6, do_qadd16},
10256 { "uqsub8", 0xe6600ff0, 6, ARM_EXT_V6, do_qadd16},
10257 { "uqsubaddx", 0xe6600f50, 9, ARM_EXT_V6, do_qadd16},
10258 { "usub16", 0xe6500f70, 6, ARM_EXT_V6, do_qadd16},
10259 { "usub8", 0xe6500ff0, 5, ARM_EXT_V6, do_qadd16},
10260 { "usubaddx", 0xe6500f50, 8, ARM_EXT_V6, do_qadd16},
10261 { "rev", 0xe6bf0f30, 3, ARM_EXT_V6, do_rev},
10262 { "rev16", 0xe6bf0fb0, 5, ARM_EXT_V6, do_rev},
10263 { "revsh", 0xe6ff0fb0, 5, ARM_EXT_V6, do_rev},
10264 { "rfeia", 0xf8900a00, 0, ARM_EXT_V6, do_rfe},
10265 { "rfeib", 0xf9900a00, 0, ARM_EXT_V6, do_rfe},
10266 { "rfeda", 0xf8100a00, 0, ARM_EXT_V6, do_rfe},
10267 { "rfedb", 0xf9100a00, 0, ARM_EXT_V6, do_rfe},
10268 { "rfefd", 0xf8900a00, 0, ARM_EXT_V6, do_rfe},
10269 { "rfefa", 0xf9900a00, 0, ARM_EXT_V6, do_rfe},
10270 { "rfeea", 0xf8100a00, 0, ARM_EXT_V6, do_rfe},
10271 { "rfeed", 0xf9100a00, 0, ARM_EXT_V6, do_rfe},
10272 { "sxtah", 0xe6b00070, 5, ARM_EXT_V6, do_sxtah},
10273 { "sxtab16", 0xe6800070, 7, ARM_EXT_V6, do_sxtah},
10274 { "sxtab", 0xe6a00070, 5, ARM_EXT_V6, do_sxtah},
10275 { "sxth", 0xe6bf0070, 4, ARM_EXT_V6, do_sxth},
10276 { "sxtb16", 0xe68f0070, 6, ARM_EXT_V6, do_sxth},
10277 { "sxtb", 0xe6af0070, 4, ARM_EXT_V6, do_sxth},
10278 { "uxtah", 0xe6f00070, 5, ARM_EXT_V6, do_sxtah},
10279 { "uxtab16", 0xe6c00070, 7, ARM_EXT_V6, do_sxtah},
10280 { "uxtab", 0xe6e00070, 5, ARM_EXT_V6, do_sxtah},
10281 { "uxth", 0xe6ff0070, 4, ARM_EXT_V6, do_sxth},
10282 { "uxtb16", 0xe6cf0070, 6, ARM_EXT_V6, do_sxth},
10283 { "uxtb", 0xe6ef0070, 4, ARM_EXT_V6, do_sxth},
10284 { "sel", 0xe68000b0, 3, ARM_EXT_V6, do_qadd16},
10285 { "setend", 0xf1010000, 0, ARM_EXT_V6, do_setend},
10286 { "smlad", 0xe7000010, 5, ARM_EXT_V6, do_smlad},
10287 { "smladx", 0xe7000030, 6, ARM_EXT_V6, do_smlad},
10288 { "smlald", 0xe7400010, 6, ARM_EXT_V6, do_smlald},
10289 { "smlaldx", 0xe7400030, 7, ARM_EXT_V6, do_smlald},
10290 { "smlsd", 0xe7000050, 5, ARM_EXT_V6, do_smlad},
10291 { "smlsdx", 0xe7000070, 6, ARM_EXT_V6, do_smlad},
10292 { "smlsld", 0xe7400050, 6, ARM_EXT_V6, do_smlald},
10293 { "smlsldx", 0xe7400070, 7, ARM_EXT_V6, do_smlald},
10294 { "smmla", 0xe7500010, 5, ARM_EXT_V6, do_smlad},
10295 { "smmlar", 0xe7500030, 6, ARM_EXT_V6, do_smlad},
10296 { "smmls", 0xe75000d0, 5, ARM_EXT_V6, do_smlad},
10297 { "smmlsr", 0xe75000f0, 6, ARM_EXT_V6, do_smlad},
10298 { "smmul", 0xe750f010, 5, ARM_EXT_V6, do_smmul},
10299 { "smmulr", 0xe750f030, 6, ARM_EXT_V6, do_smmul},
10300 { "smuad", 0xe700f010, 5, ARM_EXT_V6, do_smmul},
10301 { "smuadx", 0xe700f030, 6, ARM_EXT_V6, do_smmul},
10302 { "smusd", 0xe700f050, 5, ARM_EXT_V6, do_smmul},
10303 { "smusdx", 0xe700f070, 6, ARM_EXT_V6, do_smmul},
10304 { "srsia", 0xf8cd0500, 0, ARM_EXT_V6, do_srs},
10305 { "srsib", 0xf9cd0500, 0, ARM_EXT_V6, do_srs},
10306 { "srsda", 0xf84d0500, 0, ARM_EXT_V6, do_srs},
10307 { "srsdb", 0xf94d0500, 0, ARM_EXT_V6, do_srs},
10308 { "ssat", 0xe6a00010, 4, ARM_EXT_V6, do_ssat},
10309 { "ssat16", 0xe6a00f30, 6, ARM_EXT_V6, do_ssat16},
10310 { "strex", 0xe1800f90, 5, ARM_EXT_V6, do_strex},
10311 { "umaal", 0xe0400090, 5, ARM_EXT_V6, do_umaal},
10312 { "usad8", 0xe780f010, 5, ARM_EXT_V6, do_smmul},
10313 { "usada8", 0xe7800010, 6, ARM_EXT_V6, do_smlad},
10314 { "usat", 0xe6e00010, 4, ARM_EXT_V6, do_usat},
10315 { "usat16", 0xe6e00f30, 6, ARM_EXT_V6, do_usat16},
10316
10317 /* ARM V6K. */
10318 { "clrex", 0xf57ff01f, 0, ARM_EXT_V6K, do_empty},
10319 { "ldrexb", 0xe1d00f9f, 6, ARM_EXT_V6K, do_ldrex},
10320 { "ldrexd", 0xe1b00f9f, 6, ARM_EXT_V6K, do_ldrex},
10321 { "ldrexh", 0xe1f00f9f, 6, ARM_EXT_V6K, do_ldrex},
10322 { "sev", 0xe320f004, 3, ARM_EXT_V6K, do_empty},
10323 { "strexb", 0xe1c00f90, 6, ARM_EXT_V6K, do_strex},
10324 { "strexd", 0xe1a00f90, 6, ARM_EXT_V6K, do_strex},
10325 { "strexh", 0xe1e00f90, 6, ARM_EXT_V6K, do_strex},
10326 { "wfe", 0xe320f002, 3, ARM_EXT_V6K, do_empty},
10327 { "wfi", 0xe320f003, 3, ARM_EXT_V6K, do_empty},
10328 { "yield", 0xe320f001, 5, ARM_EXT_V6K, do_empty},
10329
10330 /* ARM V6Z. */
10331 { "smi", 0xe1600070, 3, ARM_EXT_V6Z, do_smi},
10332
10333 /* ARM V6T2. */
10334 { "bfc", 0xe7c0001f, 3, ARM_EXT_V6T2, do_bfc},
10335 { "bfi", 0xe7c00010, 3, ARM_EXT_V6T2, do_bfi},
10336 { "mls", 0xe0600090, 3, ARM_EXT_V6T2, do_mls},
10337 { "movw", 0xe3000000, 4, ARM_EXT_V6T2, do_mov16},
10338 { "movt", 0xe3400000, 4, ARM_EXT_V6T2, do_mov16},
10339 { "rbit", 0xe3ff0f30, 4, ARM_EXT_V6T2, do_rbit},
10340 { "sbfx", 0xe7a00050, 4, ARM_EXT_V6T2, do_bfx},
10341 { "ubfx", 0xe7e00050, 4, ARM_EXT_V6T2, do_bfx},
10342
10343 { "ldrht", 0xe03000b0, 3, ARM_EXT_V6T2, do_ldsttv4},
10344 { "ldrsht", 0xe03000f0, 3, ARM_EXT_V6T2, do_ldsttv4},
10345 { "ldrsbt", 0xe03000d0, 3, ARM_EXT_V6T2, do_ldsttv4},
10346 { "strht", 0xe02000b0, 3, ARM_EXT_V6T2, do_ldsttv4},
10347
10348 /* Core FPA instruction set (V1). */
10349 {"wfs", 0xee200110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
10350 {"rfs", 0xee300110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
10351 {"wfc", 0xee400110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
10352 {"rfc", 0xee500110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
10353
10354 {"ldfs", 0xec100100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10355 {"ldfd", 0xec108100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10356 {"ldfe", 0xec500100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10357 {"ldfp", 0xec508100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10358
10359 {"stfs", 0xec000100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10360 {"stfd", 0xec008100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10361 {"stfe", 0xec400100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10362 {"stfp", 0xec408100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10363
10364 {"mvfs", 0xee008100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10365 {"mvfsp", 0xee008120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10366 {"mvfsm", 0xee008140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10367 {"mvfsz", 0xee008160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10368 {"mvfd", 0xee008180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10369 {"mvfdp", 0xee0081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10370 {"mvfdm", 0xee0081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10371 {"mvfdz", 0xee0081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10372 {"mvfe", 0xee088100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10373 {"mvfep", 0xee088120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10374 {"mvfem", 0xee088140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10375 {"mvfez", 0xee088160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10376
10377 {"mnfs", 0xee108100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10378 {"mnfsp", 0xee108120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10379 {"mnfsm", 0xee108140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10380 {"mnfsz", 0xee108160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10381 {"mnfd", 0xee108180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10382 {"mnfdp", 0xee1081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10383 {"mnfdm", 0xee1081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10384 {"mnfdz", 0xee1081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10385 {"mnfe", 0xee188100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10386 {"mnfep", 0xee188120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10387 {"mnfem", 0xee188140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10388 {"mnfez", 0xee188160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10389
10390 {"abss", 0xee208100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10391 {"abssp", 0xee208120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10392 {"abssm", 0xee208140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10393 {"abssz", 0xee208160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10394 {"absd", 0xee208180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10395 {"absdp", 0xee2081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10396 {"absdm", 0xee2081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10397 {"absdz", 0xee2081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10398 {"abse", 0xee288100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10399 {"absep", 0xee288120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10400 {"absem", 0xee288140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10401 {"absez", 0xee288160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10402
10403 {"rnds", 0xee308100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10404 {"rndsp", 0xee308120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10405 {"rndsm", 0xee308140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10406 {"rndsz", 0xee308160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10407 {"rndd", 0xee308180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10408 {"rnddp", 0xee3081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10409 {"rnddm", 0xee3081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10410 {"rnddz", 0xee3081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10411 {"rnde", 0xee388100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10412 {"rndep", 0xee388120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10413 {"rndem", 0xee388140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10414 {"rndez", 0xee388160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10415
10416 {"sqts", 0xee408100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10417 {"sqtsp", 0xee408120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10418 {"sqtsm", 0xee408140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10419 {"sqtsz", 0xee408160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10420 {"sqtd", 0xee408180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10421 {"sqtdp", 0xee4081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10422 {"sqtdm", 0xee4081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10423 {"sqtdz", 0xee4081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10424 {"sqte", 0xee488100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10425 {"sqtep", 0xee488120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10426 {"sqtem", 0xee488140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10427 {"sqtez", 0xee488160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10428
10429 {"logs", 0xee508100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10430 {"logsp", 0xee508120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10431 {"logsm", 0xee508140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10432 {"logsz", 0xee508160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10433 {"logd", 0xee508180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10434 {"logdp", 0xee5081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10435 {"logdm", 0xee5081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10436 {"logdz", 0xee5081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10437 {"loge", 0xee588100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10438 {"logep", 0xee588120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10439 {"logem", 0xee588140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10440 {"logez", 0xee588160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10441
10442 {"lgns", 0xee608100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10443 {"lgnsp", 0xee608120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10444 {"lgnsm", 0xee608140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10445 {"lgnsz", 0xee608160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10446 {"lgnd", 0xee608180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10447 {"lgndp", 0xee6081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10448 {"lgndm", 0xee6081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10449 {"lgndz", 0xee6081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10450 {"lgne", 0xee688100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10451 {"lgnep", 0xee688120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10452 {"lgnem", 0xee688140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10453 {"lgnez", 0xee688160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10454
10455 {"exps", 0xee708100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10456 {"expsp", 0xee708120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10457 {"expsm", 0xee708140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10458 {"expsz", 0xee708160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10459 {"expd", 0xee708180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10460 {"expdp", 0xee7081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10461 {"expdm", 0xee7081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10462 {"expdz", 0xee7081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10463 {"expe", 0xee788100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10464 {"expep", 0xee788120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10465 {"expem", 0xee788140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10466 {"expdz", 0xee788160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10467
10468 {"sins", 0xee808100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10469 {"sinsp", 0xee808120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10470 {"sinsm", 0xee808140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10471 {"sinsz", 0xee808160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10472 {"sind", 0xee808180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10473 {"sindp", 0xee8081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10474 {"sindm", 0xee8081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10475 {"sindz", 0xee8081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10476 {"sine", 0xee888100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10477 {"sinep", 0xee888120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10478 {"sinem", 0xee888140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10479 {"sinez", 0xee888160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10480
10481 {"coss", 0xee908100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10482 {"cossp", 0xee908120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10483 {"cossm", 0xee908140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10484 {"cossz", 0xee908160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10485 {"cosd", 0xee908180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10486 {"cosdp", 0xee9081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10487 {"cosdm", 0xee9081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10488 {"cosdz", 0xee9081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10489 {"cose", 0xee988100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10490 {"cosep", 0xee988120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10491 {"cosem", 0xee988140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10492 {"cosez", 0xee988160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10493
10494 {"tans", 0xeea08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10495 {"tansp", 0xeea08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10496 {"tansm", 0xeea08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10497 {"tansz", 0xeea08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10498 {"tand", 0xeea08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10499 {"tandp", 0xeea081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10500 {"tandm", 0xeea081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10501 {"tandz", 0xeea081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10502 {"tane", 0xeea88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10503 {"tanep", 0xeea88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10504 {"tanem", 0xeea88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10505 {"tanez", 0xeea88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10506
10507 {"asns", 0xeeb08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10508 {"asnsp", 0xeeb08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10509 {"asnsm", 0xeeb08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10510 {"asnsz", 0xeeb08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10511 {"asnd", 0xeeb08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10512 {"asndp", 0xeeb081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10513 {"asndm", 0xeeb081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10514 {"asndz", 0xeeb081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10515 {"asne", 0xeeb88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10516 {"asnep", 0xeeb88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10517 {"asnem", 0xeeb88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10518 {"asnez", 0xeeb88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10519
10520 {"acss", 0xeec08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10521 {"acssp", 0xeec08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10522 {"acssm", 0xeec08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10523 {"acssz", 0xeec08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10524 {"acsd", 0xeec08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10525 {"acsdp", 0xeec081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10526 {"acsdm", 0xeec081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10527 {"acsdz", 0xeec081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10528 {"acse", 0xeec88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10529 {"acsep", 0xeec88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10530 {"acsem", 0xeec88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10531 {"acsez", 0xeec88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10532
10533 {"atns", 0xeed08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10534 {"atnsp", 0xeed08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10535 {"atnsm", 0xeed08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10536 {"atnsz", 0xeed08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10537 {"atnd", 0xeed08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10538 {"atndp", 0xeed081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10539 {"atndm", 0xeed081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10540 {"atndz", 0xeed081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10541 {"atne", 0xeed88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10542 {"atnep", 0xeed88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10543 {"atnem", 0xeed88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10544 {"atnez", 0xeed88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10545
10546 {"urds", 0xeee08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10547 {"urdsp", 0xeee08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10548 {"urdsm", 0xeee08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10549 {"urdsz", 0xeee08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10550 {"urdd", 0xeee08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10551 {"urddp", 0xeee081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10552 {"urddm", 0xeee081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10553 {"urddz", 0xeee081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10554 {"urde", 0xeee88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10555 {"urdep", 0xeee88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10556 {"urdem", 0xeee88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10557 {"urdez", 0xeee88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10558
10559 {"nrms", 0xeef08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10560 {"nrmsp", 0xeef08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10561 {"nrmsm", 0xeef08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10562 {"nrmsz", 0xeef08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10563 {"nrmd", 0xeef08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10564 {"nrmdp", 0xeef081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10565 {"nrmdm", 0xeef081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10566 {"nrmdz", 0xeef081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10567 {"nrme", 0xeef88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10568 {"nrmep", 0xeef88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10569 {"nrmem", 0xeef88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10570 {"nrmez", 0xeef88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10571
10572 {"adfs", 0xee000100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10573 {"adfsp", 0xee000120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10574 {"adfsm", 0xee000140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10575 {"adfsz", 0xee000160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10576 {"adfd", 0xee000180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10577 {"adfdp", 0xee0001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10578 {"adfdm", 0xee0001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10579 {"adfdz", 0xee0001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10580 {"adfe", 0xee080100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10581 {"adfep", 0xee080120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10582 {"adfem", 0xee080140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10583 {"adfez", 0xee080160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10584
10585 {"sufs", 0xee200100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10586 {"sufsp", 0xee200120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10587 {"sufsm", 0xee200140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10588 {"sufsz", 0xee200160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10589 {"sufd", 0xee200180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10590 {"sufdp", 0xee2001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10591 {"sufdm", 0xee2001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10592 {"sufdz", 0xee2001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10593 {"sufe", 0xee280100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10594 {"sufep", 0xee280120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10595 {"sufem", 0xee280140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10596 {"sufez", 0xee280160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10597
10598 {"rsfs", 0xee300100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10599 {"rsfsp", 0xee300120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10600 {"rsfsm", 0xee300140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10601 {"rsfsz", 0xee300160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10602 {"rsfd", 0xee300180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10603 {"rsfdp", 0xee3001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10604 {"rsfdm", 0xee3001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10605 {"rsfdz", 0xee3001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10606 {"rsfe", 0xee380100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10607 {"rsfep", 0xee380120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10608 {"rsfem", 0xee380140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10609 {"rsfez", 0xee380160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10610
10611 {"mufs", 0xee100100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10612 {"mufsp", 0xee100120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10613 {"mufsm", 0xee100140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10614 {"mufsz", 0xee100160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10615 {"mufd", 0xee100180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10616 {"mufdp", 0xee1001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10617 {"mufdm", 0xee1001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10618 {"mufdz", 0xee1001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10619 {"mufe", 0xee180100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10620 {"mufep", 0xee180120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10621 {"mufem", 0xee180140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10622 {"mufez", 0xee180160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10623
10624 {"dvfs", 0xee400100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10625 {"dvfsp", 0xee400120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10626 {"dvfsm", 0xee400140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10627 {"dvfsz", 0xee400160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10628 {"dvfd", 0xee400180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10629 {"dvfdp", 0xee4001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10630 {"dvfdm", 0xee4001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10631 {"dvfdz", 0xee4001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10632 {"dvfe", 0xee480100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10633 {"dvfep", 0xee480120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10634 {"dvfem", 0xee480140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10635 {"dvfez", 0xee480160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10636
10637 {"rdfs", 0xee500100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10638 {"rdfsp", 0xee500120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10639 {"rdfsm", 0xee500140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10640 {"rdfsz", 0xee500160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10641 {"rdfd", 0xee500180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10642 {"rdfdp", 0xee5001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10643 {"rdfdm", 0xee5001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10644 {"rdfdz", 0xee5001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10645 {"rdfe", 0xee580100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10646 {"rdfep", 0xee580120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10647 {"rdfem", 0xee580140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10648 {"rdfez", 0xee580160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10649
10650 {"pows", 0xee600100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10651 {"powsp", 0xee600120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10652 {"powsm", 0xee600140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10653 {"powsz", 0xee600160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10654 {"powd", 0xee600180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10655 {"powdp", 0xee6001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10656 {"powdm", 0xee6001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10657 {"powdz", 0xee6001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10658 {"powe", 0xee680100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10659 {"powep", 0xee680120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10660 {"powem", 0xee680140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10661 {"powez", 0xee680160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10662
10663 {"rpws", 0xee700100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10664 {"rpwsp", 0xee700120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10665 {"rpwsm", 0xee700140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10666 {"rpwsz", 0xee700160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10667 {"rpwd", 0xee700180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10668 {"rpwdp", 0xee7001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10669 {"rpwdm", 0xee7001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10670 {"rpwdz", 0xee7001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10671 {"rpwe", 0xee780100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10672 {"rpwep", 0xee780120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10673 {"rpwem", 0xee780140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10674 {"rpwez", 0xee780160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10675
10676 {"rmfs", 0xee800100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10677 {"rmfsp", 0xee800120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10678 {"rmfsm", 0xee800140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10679 {"rmfsz", 0xee800160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10680 {"rmfd", 0xee800180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10681 {"rmfdp", 0xee8001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10682 {"rmfdm", 0xee8001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10683 {"rmfdz", 0xee8001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10684 {"rmfe", 0xee880100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10685 {"rmfep", 0xee880120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10686 {"rmfem", 0xee880140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10687 {"rmfez", 0xee880160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10688
10689 {"fmls", 0xee900100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10690 {"fmlsp", 0xee900120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10691 {"fmlsm", 0xee900140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10692 {"fmlsz", 0xee900160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10693 {"fmld", 0xee900180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10694 {"fmldp", 0xee9001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10695 {"fmldm", 0xee9001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10696 {"fmldz", 0xee9001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10697 {"fmle", 0xee980100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10698 {"fmlep", 0xee980120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10699 {"fmlem", 0xee980140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10700 {"fmlez", 0xee980160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10701
10702 {"fdvs", 0xeea00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10703 {"fdvsp", 0xeea00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10704 {"fdvsm", 0xeea00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10705 {"fdvsz", 0xeea00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10706 {"fdvd", 0xeea00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10707 {"fdvdp", 0xeea001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10708 {"fdvdm", 0xeea001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10709 {"fdvdz", 0xeea001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10710 {"fdve", 0xeea80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10711 {"fdvep", 0xeea80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10712 {"fdvem", 0xeea80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10713 {"fdvez", 0xeea80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10714
10715 {"frds", 0xeeb00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10716 {"frdsp", 0xeeb00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10717 {"frdsm", 0xeeb00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10718 {"frdsz", 0xeeb00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10719 {"frdd", 0xeeb00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10720 {"frddp", 0xeeb001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10721 {"frddm", 0xeeb001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10722 {"frddz", 0xeeb001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10723 {"frde", 0xeeb80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10724 {"frdep", 0xeeb80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10725 {"frdem", 0xeeb80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10726 {"frdez", 0xeeb80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10727
10728 {"pols", 0xeec00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10729 {"polsp", 0xeec00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10730 {"polsm", 0xeec00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10731 {"polsz", 0xeec00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10732 {"pold", 0xeec00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10733 {"poldp", 0xeec001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10734 {"poldm", 0xeec001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10735 {"poldz", 0xeec001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10736 {"pole", 0xeec80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10737 {"polep", 0xeec80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10738 {"polem", 0xeec80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10739 {"polez", 0xeec80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10740
10741 {"cmf", 0xee90f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
10742 {"cmfe", 0xeed0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
10743 {"cnf", 0xeeb0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
10744 {"cnfe", 0xeef0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
10745 /* The FPA10 data sheet suggests that the 'E' of cmfe/cnfe should
10746 not be an optional suffix, but part of the instruction. To be
10747 compatible, we accept either. */
10748 {"cmfe", 0xeed0f110, 4, FPU_FPA_EXT_V1, do_fpa_cmp},
10749 {"cnfe", 0xeef0f110, 4, FPU_FPA_EXT_V1, do_fpa_cmp},
10750
10751 {"flts", 0xee000110, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10752 {"fltsp", 0xee000130, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10753 {"fltsm", 0xee000150, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10754 {"fltsz", 0xee000170, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10755 {"fltd", 0xee000190, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10756 {"fltdp", 0xee0001b0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10757 {"fltdm", 0xee0001d0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10758 {"fltdz", 0xee0001f0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10759 {"flte", 0xee080110, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10760 {"fltep", 0xee080130, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10761 {"fltem", 0xee080150, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10762 {"fltez", 0xee080170, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10763
10764 /* The implementation of the FIX instruction is broken on some
10765 assemblers, in that it accepts a precision specifier as well as a
10766 rounding specifier, despite the fact that this is meaningless.
10767 To be more compatible, we accept it as well, though of course it
10768 does not set any bits. */
10769 {"fix", 0xee100110, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10770 {"fixp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10771 {"fixm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10772 {"fixz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10773 {"fixsp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10774 {"fixsm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10775 {"fixsz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10776 {"fixdp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10777 {"fixdm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10778 {"fixdz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10779 {"fixep", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10780 {"fixem", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10781 {"fixez", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10782
10783 /* Instructions that were new with the real FPA, call them V2. */
10784 {"lfm", 0xec100200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10785 {"lfmfd", 0xec900200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10786 {"lfmea", 0xed100200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10787 {"sfm", 0xec000200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10788 {"sfmfd", 0xed000200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10789 {"sfmea", 0xec800200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10790
10791 /* VFP V1xD (single precision). */
10792 /* Moves and type conversions. */
10793 {"fcpys", 0xeeb00a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10794 {"fmrs", 0xee100a10, 4, FPU_VFP_EXT_V1xD, do_vfp_reg_from_sp},
10795 {"fmsr", 0xee000a10, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_from_reg},
10796 {"fmstat", 0xeef1fa10, 6, FPU_VFP_EXT_V1xD, do_empty},
10797 {"fsitos", 0xeeb80ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10798 {"fuitos", 0xeeb80a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10799 {"ftosis", 0xeebd0a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10800 {"ftosizs", 0xeebd0ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10801 {"ftouis", 0xeebc0a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10802 {"ftouizs", 0xeebc0ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10803 {"fmrx", 0xeef00a10, 4, FPU_VFP_EXT_V1xD, do_vfp_reg_from_ctrl},
10804 {"fmxr", 0xeee00a10, 4, FPU_VFP_EXT_V1xD, do_vfp_ctrl_from_reg},
10805
10806 /* Memory operations. */
10807 {"flds", 0xed100a00, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_ldst},
10808 {"fsts", 0xed000a00, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_ldst},
10809 {"fldmias", 0xec900a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
10810 {"fldmfds", 0xec900a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
10811 {"fldmdbs", 0xed300a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
10812 {"fldmeas", 0xed300a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
10813 {"fldmiax", 0xec900b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
10814 {"fldmfdx", 0xec900b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
10815 {"fldmdbx", 0xed300b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
10816 {"fldmeax", 0xed300b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
10817 {"fstmias", 0xec800a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
10818 {"fstmeas", 0xec800a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
10819 {"fstmdbs", 0xed200a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
10820 {"fstmfds", 0xed200a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
10821 {"fstmiax", 0xec800b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
10822 {"fstmeax", 0xec800b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
10823 {"fstmdbx", 0xed200b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
10824 {"fstmfdx", 0xed200b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
10825
10826 /* Monadic operations. */
10827 {"fabss", 0xeeb00ac0, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10828 {"fnegs", 0xeeb10a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10829 {"fsqrts", 0xeeb10ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10830
10831 /* Dyadic operations. */
10832 {"fadds", 0xee300a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10833 {"fsubs", 0xee300a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10834 {"fmuls", 0xee200a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10835 {"fdivs", 0xee800a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10836 {"fmacs", 0xee000a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10837 {"fmscs", 0xee100a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10838 {"fnmuls", 0xee200a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10839 {"fnmacs", 0xee000a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10840 {"fnmscs", 0xee100a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10841
10842 /* Comparisons. */
10843 {"fcmps", 0xeeb40a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10844 {"fcmpzs", 0xeeb50a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_compare_z},
10845 {"fcmpes", 0xeeb40ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10846 {"fcmpezs", 0xeeb50ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_compare_z},
10847
10848 /* VFP V1 (Double precision). */
10849 /* Moves and type conversions. */
10850 {"fcpyd", 0xeeb00b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10851 {"fcvtds", 0xeeb70ac0, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
10852 {"fcvtsd", 0xeeb70bc0, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
10853 {"fmdhr", 0xee200b10, 5, FPU_VFP_EXT_V1, do_vfp_dp_from_reg},
10854 {"fmdlr", 0xee000b10, 5, FPU_VFP_EXT_V1, do_vfp_dp_from_reg},
10855 {"fmrdh", 0xee300b10, 5, FPU_VFP_EXT_V1, do_vfp_reg_from_dp},
10856 {"fmrdl", 0xee100b10, 5, FPU_VFP_EXT_V1, do_vfp_reg_from_dp},
10857 {"fsitod", 0xeeb80bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
10858 {"fuitod", 0xeeb80b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
10859 {"ftosid", 0xeebd0b40, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
10860 {"ftosizd", 0xeebd0bc0, 7, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
10861 {"ftouid", 0xeebc0b40, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
10862 {"ftouizd", 0xeebc0bc0, 7, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
10863
10864 /* Memory operations. */
10865 {"fldd", 0xed100b00, 4, FPU_VFP_EXT_V1, do_vfp_dp_ldst},
10866 {"fstd", 0xed000b00, 4, FPU_VFP_EXT_V1, do_vfp_dp_ldst},
10867 {"fldmiad", 0xec900b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
10868 {"fldmfdd", 0xec900b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
10869 {"fldmdbd", 0xed300b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
10870 {"fldmead", 0xed300b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
10871 {"fstmiad", 0xec800b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
10872 {"fstmead", 0xec800b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
10873 {"fstmdbd", 0xed200b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
10874 {"fstmfdd", 0xed200b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
10875
10876 /* Monadic operations. */
10877 {"fabsd", 0xeeb00bc0, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10878 {"fnegd", 0xeeb10b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10879 {"fsqrtd", 0xeeb10bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10880
10881 /* Dyadic operations. */
10882 {"faddd", 0xee300b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10883 {"fsubd", 0xee300b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10884 {"fmuld", 0xee200b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10885 {"fdivd", 0xee800b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10886 {"fmacd", 0xee000b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10887 {"fmscd", 0xee100b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10888 {"fnmuld", 0xee200b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10889 {"fnmacd", 0xee000b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10890 {"fnmscd", 0xee100b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10891
10892 /* Comparisons. */
10893 {"fcmpd", 0xeeb40b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10894 {"fcmpzd", 0xeeb50b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_compare_z},
10895 {"fcmped", 0xeeb40bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10896 {"fcmpezd", 0xeeb50bc0, 7, FPU_VFP_EXT_V1, do_vfp_dp_compare_z},
10897
10898 /* VFP V2. */
10899 {"fmsrr", 0xec400a10, 5, FPU_VFP_EXT_V2, do_vfp_sp2_from_reg2},
10900 {"fmrrs", 0xec500a10, 5, FPU_VFP_EXT_V2, do_vfp_reg2_from_sp2},
10901 {"fmdrr", 0xec400b10, 5, FPU_VFP_EXT_V2, do_vfp_dp_from_reg2},
10902 {"fmrrd", 0xec500b10, 5, FPU_VFP_EXT_V2, do_vfp_reg2_from_dp},
10903
10904 /* Intel XScale extensions to ARM V5 ISA. (All use CP0). */
10905 {"mia", 0xee200010, 3, ARM_CEXT_XSCALE, do_xsc_mia},
10906 {"miaph", 0xee280010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
10907 {"miabb", 0xee2c0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
10908 {"miabt", 0xee2d0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
10909 {"miatb", 0xee2e0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
10910 {"miatt", 0xee2f0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
10911 {"mar", 0xec400000, 3, ARM_CEXT_XSCALE, do_xsc_mar},
10912 {"mra", 0xec500000, 3, ARM_CEXT_XSCALE, do_xsc_mra},
10913
10914 /* Intel Wireless MMX technology instructions. */
10915 {"tandcb", 0xee130130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
10916 {"tandch", 0xee530130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
10917 {"tandcw", 0xee930130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
10918 {"tbcstb", 0xee400010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
10919 {"tbcsth", 0xee400050, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
10920 {"tbcstw", 0xee400090, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
10921 {"textrcb", 0xee130170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
10922 {"textrch", 0xee530170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
10923 {"textrcw", 0xee930170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
10924 {"textrmub", 0xee100070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10925 {"textrmuh", 0xee500070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10926 {"textrmuw", 0xee900070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10927 {"textrmsb", 0xee100078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10928 {"textrmsh", 0xee500078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10929 {"textrmsw", 0xee900078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10930 {"tinsrb", 0xee600010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
10931 {"tinsrh", 0xee600050, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
10932 {"tinsrw", 0xee600090, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
10933 {"tmcr", 0xee000110, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmcr},
10934 {"tmcrr", 0xec400000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_tmcrr},
10935 {"tmia", 0xee200010, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10936 {"tmiaph", 0xee280010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10937 {"tmiabb", 0xee2c0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10938 {"tmiabt", 0xee2d0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10939 {"tmiatb", 0xee2e0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10940 {"tmiatt", 0xee2f0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10941 {"tmovmskb", 0xee100030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
10942 {"tmovmskh", 0xee500030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
10943 {"tmovmskw", 0xee900030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
10944 {"tmrc", 0xee100110, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmrc},
10945 {"tmrrc", 0xec500000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_tmrrc},
10946 {"torcb", 0xee130150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
10947 {"torch", 0xee530150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
10948 {"torcw", 0xee930150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
10949 {"waccb", 0xee0001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10950 {"wacch", 0xee4001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10951 {"waccw", 0xee8001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10952 {"waddbss", 0xee300180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10953 {"waddb", 0xee000180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10954 {"waddbus", 0xee100180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10955 {"waddhss", 0xee700180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10956 {"waddh", 0xee400180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10957 {"waddhus", 0xee500180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10958 {"waddwss", 0xeeb00180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10959 {"waddw", 0xee800180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10960 {"waddwus", 0xee900180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10961 {"waligni", 0xee000020, 7, ARM_CEXT_IWMMXT, do_iwmmxt_waligni},
10962 {"walignr0", 0xee800020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10963 {"walignr1", 0xee900020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10964 {"walignr2", 0xeea00020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10965 {"walignr3", 0xeeb00020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10966 {"wand", 0xee200000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10967 {"wandn", 0xee300000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10968 {"wavg2b", 0xee800000, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10969 {"wavg2br", 0xee900000, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10970 {"wavg2h", 0xeec00000, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10971 {"wavg2hr", 0xeed00000, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10972 {"wcmpeqb", 0xee000060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10973 {"wcmpeqh", 0xee400060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10974 {"wcmpeqw", 0xee800060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10975 {"wcmpgtub", 0xee100060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10976 {"wcmpgtuh", 0xee500060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10977 {"wcmpgtuw", 0xee900060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10978 {"wcmpgtsb", 0xee300060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10979 {"wcmpgtsh", 0xee700060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10980 {"wcmpgtsw", 0xeeb00060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10981 {"wldrb", 0xec100000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
10982 {"wldrh", 0xec100100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
10983 {"wldrw", 0xec100200, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
10984 {"wldrd", 0xec100300, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
10985 {"wmacs", 0xee600100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10986 {"wmacsz", 0xee700100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10987 {"wmacu", 0xee400100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10988 {"wmacuz", 0xee500100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10989 {"wmadds", 0xeea00100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10990 {"wmaddu", 0xee800100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10991 {"wmaxsb", 0xee200160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10992 {"wmaxsh", 0xee600160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10993 {"wmaxsw", 0xeea00160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10994 {"wmaxub", 0xee000160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10995 {"wmaxuh", 0xee400160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10996 {"wmaxuw", 0xee800160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10997 {"wminsb", 0xee300160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10998 {"wminsh", 0xee700160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10999 {"wminsw", 0xeeb00160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11000 {"wminub", 0xee100160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11001 {"wminuh", 0xee500160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11002 {"wminuw", 0xee900160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11003 {"wmov", 0xee000000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wmov},
11004 {"wmulsm", 0xee300100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11005 {"wmulsl", 0xee200100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11006 {"wmulum", 0xee100100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11007 {"wmulul", 0xee000100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11008 {"wor", 0xee000000, 3, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11009 {"wpackhss", 0xee700080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11010 {"wpackhus", 0xee500080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11011 {"wpackwss", 0xeeb00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11012 {"wpackwus", 0xee900080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11013 {"wpackdss", 0xeef00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11014 {"wpackdus", 0xeed00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11015 {"wrorh", 0xee700040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11016 {"wrorhg", 0xee700148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11017 {"wrorw", 0xeeb00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11018 {"wrorwg", 0xeeb00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11019 {"wrord", 0xeef00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11020 {"wrordg", 0xeef00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11021 {"wsadb", 0xee000120, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11022 {"wsadbz", 0xee100120, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11023 {"wsadh", 0xee400120, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11024 {"wsadhz", 0xee500120, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11025 {"wshufh", 0xee0001e0, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wshufh},
11026 {"wsllh", 0xee500040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11027 {"wsllhg", 0xee500148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11028 {"wsllw", 0xee900040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11029 {"wsllwg", 0xee900148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11030 {"wslld", 0xeed00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11031 {"wslldg", 0xeed00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11032 {"wsrah", 0xee400040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11033 {"wsrahg", 0xee400148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11034 {"wsraw", 0xee800040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11035 {"wsrawg", 0xee800148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11036 {"wsrad", 0xeec00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11037 {"wsradg", 0xeec00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11038 {"wsrlh", 0xee600040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11039 {"wsrlhg", 0xee600148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11040 {"wsrlw", 0xeea00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11041 {"wsrlwg", 0xeea00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11042 {"wsrld", 0xeee00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11043 {"wsrldg", 0xeee00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11044 {"wstrb", 0xec000000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
11045 {"wstrh", 0xec000100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
11046 {"wstrw", 0xec000200, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
11047 {"wstrd", 0xec000300, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
11048 {"wsubbss", 0xee3001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11049 {"wsubb", 0xee0001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11050 {"wsubbus", 0xee1001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11051 {"wsubhss", 0xee7001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11052 {"wsubh", 0xee4001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11053 {"wsubhus", 0xee5001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11054 {"wsubwss", 0xeeb001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11055 {"wsubw", 0xee8001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11056 {"wsubwus", 0xee9001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11057 {"wunpckehub", 0xee0000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11058 {"wunpckehuh", 0xee4000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11059 {"wunpckehuw", 0xee8000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11060 {"wunpckehsb", 0xee2000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11061 {"wunpckehsh", 0xee6000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11062 {"wunpckehsw", 0xeea000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11063 {"wunpckihb", 0xee1000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11064 {"wunpckihh", 0xee5000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11065 {"wunpckihw", 0xee9000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11066 {"wunpckelub", 0xee0000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11067 {"wunpckeluh", 0xee4000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11068 {"wunpckeluw", 0xee8000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11069 {"wunpckelsb", 0xee2000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11070 {"wunpckelsh", 0xee6000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11071 {"wunpckelsw", 0xeea000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11072 {"wunpckilb", 0xee1000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11073 {"wunpckilh", 0xee5000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11074 {"wunpckilw", 0xee9000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11075 {"wxor", 0xee100000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11076 {"wzero", 0xee300000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wzero},
11077
11078 /* Cirrus Maverick instructions. */
11079 {"cfldrs", 0xec100400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_1},
11080 {"cfldrd", 0xec500400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_2},
11081 {"cfldr32", 0xec100500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_3},
11082 {"cfldr64", 0xec500500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_4},
11083 {"cfstrs", 0xec000400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_1},
11084 {"cfstrd", 0xec400400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_2},
11085 {"cfstr32", 0xec000500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_3},
11086 {"cfstr64", 0xec400500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_4},
11087 {"cfmvsr", 0xee000450, 6, ARM_CEXT_MAVERICK, do_mav_binops_2a},
11088 {"cfmvrs", 0xee100450, 6, ARM_CEXT_MAVERICK, do_mav_binops_1a},
11089 {"cfmvdlr", 0xee000410, 7, ARM_CEXT_MAVERICK, do_mav_binops_2b},
11090 {"cfmvrdl", 0xee100410, 7, ARM_CEXT_MAVERICK, do_mav_binops_1b},
11091 {"cfmvdhr", 0xee000430, 7, ARM_CEXT_MAVERICK, do_mav_binops_2b},
11092 {"cfmvrdh", 0xee100430, 7, ARM_CEXT_MAVERICK, do_mav_binops_1b},
11093 {"cfmv64lr", 0xee000510, 8, ARM_CEXT_MAVERICK, do_mav_binops_2c},
11094 {"cfmvr64l", 0xee100510, 8, ARM_CEXT_MAVERICK, do_mav_binops_1c},
11095 {"cfmv64hr", 0xee000530, 8, ARM_CEXT_MAVERICK, do_mav_binops_2c},
11096 {"cfmvr64h", 0xee100530, 8, ARM_CEXT_MAVERICK, do_mav_binops_1c},
11097 {"cfmval32", 0xee200440, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
11098 {"cfmv32al", 0xee100440, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
11099 {"cfmvam32", 0xee200460, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
11100 {"cfmv32am", 0xee100460, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
11101 {"cfmvah32", 0xee200480, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
11102 {"cfmv32ah", 0xee100480, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
11103 {"cfmva32", 0xee2004a0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3a},
11104 {"cfmv32a", 0xee1004a0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3b},
11105 {"cfmva64", 0xee2004c0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3c},
11106 {"cfmv64a", 0xee1004c0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3d},
11107 {"cfmvsc32", 0xee2004e0, 8, ARM_CEXT_MAVERICK, do_mav_dspsc_1},
11108 {"cfmv32sc", 0xee1004e0, 8, ARM_CEXT_MAVERICK, do_mav_dspsc_2},
11109 {"cfcpys", 0xee000400, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
11110 {"cfcpyd", 0xee000420, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
11111 {"cfcvtsd", 0xee000460, 7, ARM_CEXT_MAVERICK, do_mav_binops_1f},
11112 {"cfcvtds", 0xee000440, 7, ARM_CEXT_MAVERICK, do_mav_binops_1g},
11113 {"cfcvt32s", 0xee000480, 8, ARM_CEXT_MAVERICK, do_mav_binops_1h},
11114 {"cfcvt32d", 0xee0004a0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1i},
11115 {"cfcvt64s", 0xee0004c0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1j},
11116 {"cfcvt64d", 0xee0004e0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1k},
11117 {"cfcvts32", 0xee100580, 8, ARM_CEXT_MAVERICK, do_mav_binops_1l},
11118 {"cfcvtd32", 0xee1005a0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1m},
11119 {"cftruncs32", 0xee1005c0, 10, ARM_CEXT_MAVERICK, do_mav_binops_1l},
11120 {"cftruncd32", 0xee1005e0, 10, ARM_CEXT_MAVERICK, do_mav_binops_1m},
11121 {"cfrshl32", 0xee000550, 8, ARM_CEXT_MAVERICK, do_mav_triple_4a},
11122 {"cfrshl64", 0xee000570, 8, ARM_CEXT_MAVERICK, do_mav_triple_4b},
11123 {"cfsh32", 0xee000500, 6, ARM_CEXT_MAVERICK, do_mav_shift_1},
11124 {"cfsh64", 0xee200500, 6, ARM_CEXT_MAVERICK, do_mav_shift_2},
11125 {"cfcmps", 0xee100490, 6, ARM_CEXT_MAVERICK, do_mav_triple_5a},
11126 {"cfcmpd", 0xee1004b0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5b},
11127 {"cfcmp32", 0xee100590, 7, ARM_CEXT_MAVERICK, do_mav_triple_5c},
11128 {"cfcmp64", 0xee1005b0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5d},
11129 {"cfabss", 0xee300400, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
11130 {"cfabsd", 0xee300420, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
11131 {"cfnegs", 0xee300440, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
11132 {"cfnegd", 0xee300460, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
11133 {"cfadds", 0xee300480, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
11134 {"cfaddd", 0xee3004a0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
11135 {"cfsubs", 0xee3004c0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
11136 {"cfsubd", 0xee3004e0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
11137 {"cfmuls", 0xee100400, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
11138 {"cfmuld", 0xee100420, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
11139 {"cfabs32", 0xee300500, 7, ARM_CEXT_MAVERICK, do_mav_binops_1n},
11140 {"cfabs64", 0xee300520, 7, ARM_CEXT_MAVERICK, do_mav_binops_1o},
11141 {"cfneg32", 0xee300540, 7, ARM_CEXT_MAVERICK, do_mav_binops_1n},
11142 {"cfneg64", 0xee300560, 7, ARM_CEXT_MAVERICK, do_mav_binops_1o},
11143 {"cfadd32", 0xee300580, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
11144 {"cfadd64", 0xee3005a0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
11145 {"cfsub32", 0xee3005c0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
11146 {"cfsub64", 0xee3005e0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
11147 {"cfmul32", 0xee100500, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
11148 {"cfmul64", 0xee100520, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
11149 {"cfmac32", 0xee100540, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
11150 {"cfmsc32", 0xee100560, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
11151 {"cfmadd32", 0xee000600, 8, ARM_CEXT_MAVERICK, do_mav_quad_6a},
11152 {"cfmsub32", 0xee100600, 8, ARM_CEXT_MAVERICK, do_mav_quad_6a},
11153 {"cfmadda32", 0xee200600, 9, ARM_CEXT_MAVERICK, do_mav_quad_6b},
11154 {"cfmsuba32", 0xee300600, 9, ARM_CEXT_MAVERICK, do_mav_quad_6b},
11155 };
11156
11157 /* Iterate over the base tables to create the instruction patterns. */
11158
11159 static void
11160 build_arm_ops_hsh (void)
11161 {
11162 unsigned int i;
11163 unsigned int j;
11164 static struct obstack insn_obstack;
11165
11166 obstack_begin (&insn_obstack, 4000);
11167
11168 for (i = 0; i < sizeof (insns) / sizeof (struct asm_opcode); i++)
11169 {
11170 const struct asm_opcode *insn = insns + i;
11171
11172 if (insn->cond_offset != 0)
11173 {
11174 /* Insn supports conditional execution. Build the varaints
11175 and insert them in the hash table. */
11176 for (j = 0; j < sizeof (conds) / sizeof (struct asm_cond); j++)
11177 {
11178 unsigned len = strlen (insn->template);
11179 struct asm_opcode *new;
11180 char *template;
11181
11182 new = obstack_alloc (&insn_obstack, sizeof (struct asm_opcode));
11183 /* All condition codes are two characters. */
11184 template = obstack_alloc (&insn_obstack, len + 3);
11185
11186 strncpy (template, insn->template, insn->cond_offset);
11187 strcpy (template + insn->cond_offset, conds[j].template);
11188 if (len > insn->cond_offset)
11189 strcpy (template + insn->cond_offset + 2,
11190 insn->template + insn->cond_offset);
11191 new->template = template;
11192 new->cond_offset = 0;
11193 new->variant = insn->variant;
11194 new->parms = insn->parms;
11195 new->value = (insn->value & ~COND_MASK) | conds[j].value;
11196
11197 hash_insert (arm_ops_hsh, new->template, (PTR) new);
11198 }
11199 }
11200 /* Finally, insert the unconditional insn in the table directly;
11201 no need to build a copy. */
11202 hash_insert (arm_ops_hsh, insn->template, (PTR) insn);
11203 }
11204 }
11205
11206 \f
11207 static const struct thumb_opcode tinsns[] =
11208 {
11209 /* Thumb v1 (ARMv4T). */
11210 {"adc", 0x4140, 2, ARM_EXT_V4T, do_t_arit},
11211 {"add", 0x0000, 2, ARM_EXT_V4T, do_t_add},
11212 {"and", 0x4000, 2, ARM_EXT_V4T, do_t_arit},
11213 {"asr", 0x0000, 2, ARM_EXT_V4T, do_t_asr},
11214 {"b", T_OPCODE_BRANCH, 2, ARM_EXT_V4T, do_t_branch12},
11215 {"beq", 0xd0fe, 2, ARM_EXT_V4T, do_t_branch9},
11216 {"bne", 0xd1fe, 2, ARM_EXT_V4T, do_t_branch9},
11217 {"bcs", 0xd2fe, 2, ARM_EXT_V4T, do_t_branch9},
11218 {"bhs", 0xd2fe, 2, ARM_EXT_V4T, do_t_branch9},
11219 {"bcc", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
11220 {"bul", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
11221 {"blo", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
11222 {"bmi", 0xd4fe, 2, ARM_EXT_V4T, do_t_branch9},
11223 {"bpl", 0xd5fe, 2, ARM_EXT_V4T, do_t_branch9},
11224 {"bvs", 0xd6fe, 2, ARM_EXT_V4T, do_t_branch9},
11225 {"bvc", 0xd7fe, 2, ARM_EXT_V4T, do_t_branch9},
11226 {"bhi", 0xd8fe, 2, ARM_EXT_V4T, do_t_branch9},
11227 {"bls", 0xd9fe, 2, ARM_EXT_V4T, do_t_branch9},
11228 {"bge", 0xdafe, 2, ARM_EXT_V4T, do_t_branch9},
11229 {"blt", 0xdbfe, 2, ARM_EXT_V4T, do_t_branch9},
11230 {"bgt", 0xdcfe, 2, ARM_EXT_V4T, do_t_branch9},
11231 {"ble", 0xddfe, 2, ARM_EXT_V4T, do_t_branch9},
11232 {"bal", 0xdefe, 2, ARM_EXT_V4T, do_t_branch9},
11233 {"bic", 0x4380, 2, ARM_EXT_V4T, do_t_arit},
11234 {"bl", 0xf7fffffe, 4, ARM_EXT_V4T, do_t_branch23},
11235 {"bx", 0x4700, 2, ARM_EXT_V4T, do_t_bx},
11236 {"cmn", T_OPCODE_CMN, 2, ARM_EXT_V4T, do_t_arit},
11237 {"cmp", 0x0000, 2, ARM_EXT_V4T, do_t_compare},
11238 {"eor", 0x4040, 2, ARM_EXT_V4T, do_t_arit},
11239 {"ldmia", 0xc800, 2, ARM_EXT_V4T, do_t_ldmstm},
11240 {"ldr", 0x0000, 2, ARM_EXT_V4T, do_t_ldr},
11241 {"ldrb", 0x0000, 2, ARM_EXT_V4T, do_t_ldrb},
11242 {"ldrh", 0x0000, 2, ARM_EXT_V4T, do_t_ldrh},
11243 {"ldrsb", 0x5600, 2, ARM_EXT_V4T, do_t_lds},
11244 {"ldrsh", 0x5e00, 2, ARM_EXT_V4T, do_t_lds},
11245 {"ldsb", 0x5600, 2, ARM_EXT_V4T, do_t_lds},
11246 {"ldsh", 0x5e00, 2, ARM_EXT_V4T, do_t_lds},
11247 {"lsl", 0x0000, 2, ARM_EXT_V4T, do_t_lsl},
11248 {"lsr", 0x0000, 2, ARM_EXT_V4T, do_t_lsr},
11249 {"mov", 0x0000, 2, ARM_EXT_V4T, do_t_mov},
11250 {"mul", T_OPCODE_MUL, 2, ARM_EXT_V4T, do_t_arit},
11251 {"mvn", T_OPCODE_MVN, 2, ARM_EXT_V4T, do_t_arit},
11252 {"neg", T_OPCODE_NEG, 2, ARM_EXT_V4T, do_t_arit},
11253 {"orr", 0x4300, 2, ARM_EXT_V4T, do_t_arit},
11254 {"pop", 0xbc00, 2, ARM_EXT_V4T, do_t_push_pop},
11255 {"push", 0xb400, 2, ARM_EXT_V4T, do_t_push_pop},
11256 {"ror", 0x41c0, 2, ARM_EXT_V4T, do_t_arit},
11257 {"sbc", 0x4180, 2, ARM_EXT_V4T, do_t_arit},
11258 {"stmia", 0xc000, 2, ARM_EXT_V4T, do_t_ldmstm},
11259 {"str", 0x0000, 2, ARM_EXT_V4T, do_t_str},
11260 {"strb", 0x0000, 2, ARM_EXT_V4T, do_t_strb},
11261 {"strh", 0x0000, 2, ARM_EXT_V4T, do_t_strh},
11262 {"swi", 0xdf00, 2, ARM_EXT_V4T, do_t_swi},
11263 {"sub", 0x0000, 2, ARM_EXT_V4T, do_t_sub},
11264 {"tst", T_OPCODE_TST, 2, ARM_EXT_V4T, do_t_arit},
11265 /* Pseudo ops: */
11266 {"adr", 0x0000, 2, ARM_EXT_V4T, do_t_adr},
11267 {"nop", 0x46C0, 2, ARM_EXT_V4T, do_t_nop}, /* mov r8,r8 */
11268 /* Thumb v2 (ARMv5T). */
11269 {"blx", 0, 0, ARM_EXT_V5T, do_t_blx},
11270 {"bkpt", 0xbe00, 2, ARM_EXT_V5T, do_t_bkpt},
11271
11272 /* ARM V6. */
11273 {"cpsie", 0xb660, 2, ARM_EXT_V6, do_t_cps},
11274 {"cpsid", 0xb670, 2, ARM_EXT_V6, do_t_cps},
11275 {"cpy", 0x4600, 2, ARM_EXT_V6, do_t_cpy},
11276 {"rev", 0xba00, 2, ARM_EXT_V6, do_t_arit},
11277 {"rev16", 0xba40, 2, ARM_EXT_V6, do_t_arit},
11278 {"revsh", 0xbac0, 2, ARM_EXT_V6, do_t_arit},
11279 {"setend", 0xb650, 2, ARM_EXT_V6, do_t_setend},
11280 {"sxth", 0xb200, 2, ARM_EXT_V6, do_t_arit},
11281 {"sxtb", 0xb240, 2, ARM_EXT_V6, do_t_arit},
11282 {"uxth", 0xb280, 2, ARM_EXT_V6, do_t_arit},
11283 {"uxtb", 0xb2c0, 2, ARM_EXT_V6, do_t_arit},
11284
11285 /* ARM V6K. */
11286 {"sev", 0xbf40, 2, ARM_EXT_V6K, do_empty},
11287 {"wfe", 0xbf20, 2, ARM_EXT_V6K, do_empty},
11288 {"wfi", 0xbf30, 2, ARM_EXT_V6K, do_empty},
11289 {"yield", 0xbf10, 2, ARM_EXT_V6K, do_empty},
11290 };
11291
11292 void
11293 md_begin (void)
11294 {
11295 unsigned mach;
11296 unsigned int i;
11297
11298 if ( (arm_ops_hsh = hash_new ()) == NULL
11299 || (arm_tops_hsh = hash_new ()) == NULL
11300 || (arm_cond_hsh = hash_new ()) == NULL
11301 || (arm_shift_hsh = hash_new ()) == NULL
11302 || (arm_psr_hsh = hash_new ()) == NULL)
11303 as_fatal (_("virtual memory exhausted"));
11304
11305 build_arm_ops_hsh ();
11306 for (i = 0; i < sizeof (tinsns) / sizeof (struct thumb_opcode); i++)
11307 hash_insert (arm_tops_hsh, tinsns[i].template, (PTR) (tinsns + i));
11308 for (i = 0; i < sizeof (conds) / sizeof (struct asm_cond); i++)
11309 hash_insert (arm_cond_hsh, conds[i].template, (PTR) (conds + i));
11310 for (i = 0; i < sizeof (shift_names) / sizeof (struct asm_shift_name); i++)
11311 hash_insert (arm_shift_hsh, shift_names[i].name, (PTR) (shift_names + i));
11312 for (i = 0; i < sizeof (psrs) / sizeof (struct asm_psr); i++)
11313 hash_insert (arm_psr_hsh, psrs[i].template, (PTR) (psrs + i));
11314
11315 for (i = (int) REG_TYPE_FIRST; i < (int) REG_TYPE_MAX; i++)
11316 build_reg_hsh (all_reg_maps + i);
11317
11318 set_constant_flonums ();
11319
11320 /* Set the cpu variant based on the command-line options. We prefer
11321 -mcpu= over -march= if both are set (as for GCC); and we prefer
11322 -mfpu= over any other way of setting the floating point unit.
11323 Use of legacy options with new options are faulted. */
11324 if (legacy_cpu != -1)
11325 {
11326 if (mcpu_cpu_opt != -1 || march_cpu_opt != -1)
11327 as_bad (_("use of old and new-style options to set CPU type"));
11328
11329 mcpu_cpu_opt = legacy_cpu;
11330 }
11331 else if (mcpu_cpu_opt == -1)
11332 mcpu_cpu_opt = march_cpu_opt;
11333
11334 if (legacy_fpu != -1)
11335 {
11336 if (mfpu_opt != -1)
11337 as_bad (_("use of old and new-style options to set FPU type"));
11338
11339 mfpu_opt = legacy_fpu;
11340 }
11341 else if (mfpu_opt == -1)
11342 {
11343 #if !(defined (TE_LINUX) || defined (TE_NetBSD) || defined (TE_VXWORKS))
11344 /* Some environments specify a default FPU. If they don't, infer it
11345 from the processor. */
11346 if (mcpu_fpu_opt != -1)
11347 mfpu_opt = mcpu_fpu_opt;
11348 else
11349 mfpu_opt = march_fpu_opt;
11350 #else
11351 mfpu_opt = FPU_DEFAULT;
11352 #endif
11353 }
11354
11355 if (mfpu_opt == -1)
11356 {
11357 if (mcpu_cpu_opt == -1)
11358 mfpu_opt = FPU_DEFAULT;
11359 else if (mcpu_cpu_opt & ARM_EXT_V5)
11360 mfpu_opt = FPU_ARCH_VFP_V2;
11361 else
11362 mfpu_opt = FPU_ARCH_FPA;
11363 }
11364
11365 if (mcpu_cpu_opt == -1)
11366 mcpu_cpu_opt = CPU_DEFAULT;
11367
11368 cpu_variant = mcpu_cpu_opt | mfpu_opt;
11369
11370 #if defined OBJ_COFF || defined OBJ_ELF
11371 {
11372 unsigned int flags = 0;
11373
11374 #if defined OBJ_ELF
11375 flags = meabi_flags;
11376
11377 switch (meabi_flags)
11378 {
11379 case EF_ARM_EABI_UNKNOWN:
11380 #endif
11381 /* Set the flags in the private structure. */
11382 if (uses_apcs_26) flags |= F_APCS26;
11383 if (support_interwork) flags |= F_INTERWORK;
11384 if (uses_apcs_float) flags |= F_APCS_FLOAT;
11385 if (pic_code) flags |= F_PIC;
11386 if ((cpu_variant & FPU_ANY) == FPU_NONE
11387 || (cpu_variant & FPU_ANY) == FPU_ARCH_VFP) /* VFP layout only. */
11388 flags |= F_SOFT_FLOAT;
11389
11390 switch (mfloat_abi_opt)
11391 {
11392 case ARM_FLOAT_ABI_SOFT:
11393 case ARM_FLOAT_ABI_SOFTFP:
11394 flags |= F_SOFT_FLOAT;
11395 break;
11396
11397 case ARM_FLOAT_ABI_HARD:
11398 if (flags & F_SOFT_FLOAT)
11399 as_bad (_("hard-float conflicts with specified fpu"));
11400 break;
11401 }
11402
11403 /* Using VFP conventions (even if soft-float). */
11404 if (cpu_variant & FPU_VFP_EXT_NONE)
11405 flags |= F_VFP_FLOAT;
11406
11407 #if defined OBJ_ELF
11408 if (cpu_variant & FPU_ARCH_MAVERICK)
11409 flags |= EF_ARM_MAVERICK_FLOAT;
11410 break;
11411
11412 case EF_ARM_EABI_VER4:
11413 /* No additional flags to set. */
11414 break;
11415
11416 default:
11417 abort ();
11418 }
11419 #endif
11420 bfd_set_private_flags (stdoutput, flags);
11421
11422 /* We have run out flags in the COFF header to encode the
11423 status of ATPCS support, so instead we create a dummy,
11424 empty, debug section called .arm.atpcs. */
11425 if (atpcs)
11426 {
11427 asection * sec;
11428
11429 sec = bfd_make_section (stdoutput, ".arm.atpcs");
11430
11431 if (sec != NULL)
11432 {
11433 bfd_set_section_flags
11434 (stdoutput, sec, SEC_READONLY | SEC_DEBUGGING /* | SEC_HAS_CONTENTS */);
11435 bfd_set_section_size (stdoutput, sec, 0);
11436 bfd_set_section_contents (stdoutput, sec, NULL, 0, 0);
11437 }
11438 }
11439 }
11440 #endif
11441
11442 /* Record the CPU type as well. */
11443 switch (cpu_variant & ARM_CPU_MASK)
11444 {
11445 case ARM_2:
11446 mach = bfd_mach_arm_2;
11447 break;
11448
11449 case ARM_3: /* Also ARM_250. */
11450 mach = bfd_mach_arm_2a;
11451 break;
11452
11453 case ARM_6: /* Also ARM_7. */
11454 mach = bfd_mach_arm_3;
11455 break;
11456
11457 default:
11458 mach = bfd_mach_arm_unknown;
11459 break;
11460 }
11461
11462 /* Catch special cases. */
11463 if (cpu_variant & ARM_CEXT_IWMMXT)
11464 mach = bfd_mach_arm_iWMMXt;
11465 else if (cpu_variant & ARM_CEXT_XSCALE)
11466 mach = bfd_mach_arm_XScale;
11467 else if (cpu_variant & ARM_CEXT_MAVERICK)
11468 mach = bfd_mach_arm_ep9312;
11469 else if (cpu_variant & ARM_EXT_V5E)
11470 mach = bfd_mach_arm_5TE;
11471 else if (cpu_variant & ARM_EXT_V5)
11472 {
11473 if (cpu_variant & ARM_EXT_V4T)
11474 mach = bfd_mach_arm_5T;
11475 else
11476 mach = bfd_mach_arm_5;
11477 }
11478 else if (cpu_variant & ARM_EXT_V4)
11479 {
11480 if (cpu_variant & ARM_EXT_V4T)
11481 mach = bfd_mach_arm_4T;
11482 else
11483 mach = bfd_mach_arm_4;
11484 }
11485 else if (cpu_variant & ARM_EXT_V3M)
11486 mach = bfd_mach_arm_3M;
11487
11488 bfd_set_arch_mach (stdoutput, TARGET_ARCH, mach);
11489 }
11490
11491 /* Turn an integer of n bytes (in val) into a stream of bytes appropriate
11492 for use in the a.out file, and stores them in the array pointed to by buf.
11493 This knows about the endian-ness of the target machine and does
11494 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
11495 2 (short) and 4 (long) Floating numbers are put out as a series of
11496 LITTLENUMS (shorts, here at least). */
11497
11498 void
11499 md_number_to_chars (char * buf, valueT val, int n)
11500 {
11501 if (target_big_endian)
11502 number_to_chars_bigendian (buf, val, n);
11503 else
11504 number_to_chars_littleendian (buf, val, n);
11505 }
11506
11507 static valueT
11508 md_chars_to_number (char * buf, int n)
11509 {
11510 valueT result = 0;
11511 unsigned char * where = (unsigned char *) buf;
11512
11513 if (target_big_endian)
11514 {
11515 while (n--)
11516 {
11517 result <<= 8;
11518 result |= (*where++ & 255);
11519 }
11520 }
11521 else
11522 {
11523 while (n--)
11524 {
11525 result <<= 8;
11526 result |= (where[n] & 255);
11527 }
11528 }
11529
11530 return result;
11531 }
11532
11533 /* Turn a string in input_line_pointer into a floating point constant
11534 of type TYPE, and store the appropriate bytes in *LITP. The number
11535 of LITTLENUMS emitted is stored in *SIZEP. An error message is
11536 returned, or NULL on OK.
11537
11538 Note that fp constants aren't represent in the normal way on the ARM.
11539 In big endian mode, things are as expected. However, in little endian
11540 mode fp constants are big-endian word-wise, and little-endian byte-wise
11541 within the words. For example, (double) 1.1 in big endian mode is
11542 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
11543 the byte sequence 99 99 f1 3f 9a 99 99 99.
11544
11545 ??? The format of 12 byte floats is uncertain according to gcc's arm.h. */
11546
11547 char *
11548 md_atof (int type, char * litP, int * sizeP)
11549 {
11550 int prec;
11551 LITTLENUM_TYPE words[MAX_LITTLENUMS];
11552 char *t;
11553 int i;
11554
11555 switch (type)
11556 {
11557 case 'f':
11558 case 'F':
11559 case 's':
11560 case 'S':
11561 prec = 2;
11562 break;
11563
11564 case 'd':
11565 case 'D':
11566 case 'r':
11567 case 'R':
11568 prec = 4;
11569 break;
11570
11571 case 'x':
11572 case 'X':
11573 prec = 6;
11574 break;
11575
11576 case 'p':
11577 case 'P':
11578 prec = 6;
11579 break;
11580
11581 default:
11582 *sizeP = 0;
11583 return _("bad call to MD_ATOF()");
11584 }
11585
11586 t = atof_ieee (input_line_pointer, type, words);
11587 if (t)
11588 input_line_pointer = t;
11589 *sizeP = prec * 2;
11590
11591 if (target_big_endian)
11592 {
11593 for (i = 0; i < prec; i++)
11594 {
11595 md_number_to_chars (litP, (valueT) words[i], 2);
11596 litP += 2;
11597 }
11598 }
11599 else
11600 {
11601 if (cpu_variant & FPU_ARCH_VFP)
11602 for (i = prec - 1; i >= 0; i--)
11603 {
11604 md_number_to_chars (litP, (valueT) words[i], 2);
11605 litP += 2;
11606 }
11607 else
11608 /* For a 4 byte float the order of elements in `words' is 1 0.
11609 For an 8 byte float the order is 1 0 3 2. */
11610 for (i = 0; i < prec; i += 2)
11611 {
11612 md_number_to_chars (litP, (valueT) words[i + 1], 2);
11613 md_number_to_chars (litP + 2, (valueT) words[i], 2);
11614 litP += 4;
11615 }
11616 }
11617
11618 return 0;
11619 }
11620
11621 /* The knowledge of the PC's pipeline offset is built into the insns
11622 themselves. */
11623
11624 long
11625 md_pcrel_from (fixS * fixP)
11626 {
11627 if (fixP->fx_addsy
11628 && S_GET_SEGMENT (fixP->fx_addsy) == undefined_section
11629 && fixP->fx_subsy == NULL)
11630 return 0;
11631
11632 if (fixP->fx_pcrel && (fixP->fx_r_type == BFD_RELOC_ARM_THUMB_ADD))
11633 {
11634 /* PC relative addressing on the Thumb is slightly odd
11635 as the bottom two bits of the PC are forced to zero
11636 for the calculation. */
11637 return (fixP->fx_where + fixP->fx_frag->fr_address) & ~3;
11638 }
11639
11640 #ifdef TE_WINCE
11641 /* The pattern was adjusted to accommodate CE's off-by-one fixups,
11642 so we un-adjust here to compensate for the accommodation. */
11643 return fixP->fx_where + fixP->fx_frag->fr_address + 8;
11644 #else
11645 return fixP->fx_where + fixP->fx_frag->fr_address;
11646 #endif
11647 }
11648
11649 /* Round up a section size to the appropriate boundary. */
11650
11651 valueT
11652 md_section_align (segT segment ATTRIBUTE_UNUSED,
11653 valueT size)
11654 {
11655 #ifdef OBJ_ELF
11656 return size;
11657 #else
11658 /* Round all sects to multiple of 4. */
11659 return (size + 3) & ~3;
11660 #endif
11661 }
11662
11663 /* Under ELF we need to default _GLOBAL_OFFSET_TABLE.
11664 Otherwise we have no need to default values of symbols. */
11665
11666 symbolS *
11667 md_undefined_symbol (char * name ATTRIBUTE_UNUSED)
11668 {
11669 #ifdef OBJ_ELF
11670 if (name[0] == '_' && name[1] == 'G'
11671 && streq (name, GLOBAL_OFFSET_TABLE_NAME))
11672 {
11673 if (!GOT_symbol)
11674 {
11675 if (symbol_find (name))
11676 as_bad ("GOT already in the symbol table");
11677
11678 GOT_symbol = symbol_new (name, undefined_section,
11679 (valueT) 0, & zero_address_frag);
11680 }
11681
11682 return GOT_symbol;
11683 }
11684 #endif
11685
11686 return 0;
11687 }
11688
11689 void
11690 md_apply_fix3 (fixS * fixP,
11691 valueT * valP,
11692 segT seg)
11693 {
11694 offsetT value = * valP;
11695 offsetT newval;
11696 unsigned int newimm;
11697 unsigned long temp;
11698 int sign;
11699 char * buf = fixP->fx_where + fixP->fx_frag->fr_literal;
11700 arm_fix_data * arm_data = (arm_fix_data *) fixP->tc_fix_data;
11701
11702 assert (fixP->fx_r_type <= BFD_RELOC_UNUSED);
11703
11704 /* Note whether this will delete the relocation. */
11705 if (fixP->fx_addsy == 0 && !fixP->fx_pcrel)
11706 fixP->fx_done = 1;
11707
11708 /* If this symbol is in a different section then we need to leave it for
11709 the linker to deal with. Unfortunately, md_pcrel_from can't tell,
11710 so we have to undo it's effects here. */
11711 if (fixP->fx_pcrel)
11712 {
11713 if (fixP->fx_addsy != NULL
11714 && S_IS_DEFINED (fixP->fx_addsy)
11715 && S_GET_SEGMENT (fixP->fx_addsy) != seg)
11716 value += md_pcrel_from (fixP);
11717 }
11718
11719 /* Remember value for emit_reloc. */
11720 fixP->fx_addnumber = value;
11721
11722 switch (fixP->fx_r_type)
11723 {
11724 case BFD_RELOC_NONE:
11725 /* This will need to go in the object file. */
11726 fixP->fx_done = 0;
11727 break;
11728
11729 case BFD_RELOC_ARM_IMMEDIATE:
11730 /* We claim that this fixup has been processed here,
11731 even if in fact we generate an error because we do
11732 not have a reloc for it, so tc_gen_reloc will reject it. */
11733 fixP->fx_done = 1;
11734
11735 if (fixP->fx_addsy
11736 && ! S_IS_DEFINED (fixP->fx_addsy))
11737 {
11738 as_bad_where (fixP->fx_file, fixP->fx_line,
11739 _("undefined symbol %s used as an immediate value"),
11740 S_GET_NAME (fixP->fx_addsy));
11741 break;
11742 }
11743
11744 newimm = validate_immediate (value);
11745 temp = md_chars_to_number (buf, INSN_SIZE);
11746
11747 /* If the instruction will fail, see if we can fix things up by
11748 changing the opcode. */
11749 if (newimm == (unsigned int) FAIL
11750 && (newimm = negate_data_op (&temp, value)) == (unsigned int) FAIL)
11751 {
11752 as_bad_where (fixP->fx_file, fixP->fx_line,
11753 _("invalid constant (%lx) after fixup"),
11754 (unsigned long) value);
11755 break;
11756 }
11757
11758 newimm |= (temp & 0xfffff000);
11759 md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
11760 break;
11761
11762 case BFD_RELOC_ARM_ADRL_IMMEDIATE:
11763 {
11764 unsigned int highpart = 0;
11765 unsigned int newinsn = 0xe1a00000; /* nop. */
11766
11767 newimm = validate_immediate (value);
11768 temp = md_chars_to_number (buf, INSN_SIZE);
11769
11770 /* If the instruction will fail, see if we can fix things up by
11771 changing the opcode. */
11772 if (newimm == (unsigned int) FAIL
11773 && (newimm = negate_data_op (& temp, value)) == (unsigned int) FAIL)
11774 {
11775 /* No ? OK - try using two ADD instructions to generate
11776 the value. */
11777 newimm = validate_immediate_twopart (value, & highpart);
11778
11779 /* Yes - then make sure that the second instruction is
11780 also an add. */
11781 if (newimm != (unsigned int) FAIL)
11782 newinsn = temp;
11783 /* Still No ? Try using a negated value. */
11784 else if ((newimm = validate_immediate_twopart (- value, & highpart)) != (unsigned int) FAIL)
11785 temp = newinsn = (temp & OPCODE_MASK) | OPCODE_SUB << DATA_OP_SHIFT;
11786 /* Otherwise - give up. */
11787 else
11788 {
11789 as_bad_where (fixP->fx_file, fixP->fx_line,
11790 _("unable to compute ADRL instructions for PC offset of 0x%lx"),
11791 (long) value);
11792 break;
11793 }
11794
11795 /* Replace the first operand in the 2nd instruction (which
11796 is the PC) with the destination register. We have
11797 already added in the PC in the first instruction and we
11798 do not want to do it again. */
11799 newinsn &= ~ 0xf0000;
11800 newinsn |= ((newinsn & 0x0f000) << 4);
11801 }
11802
11803 newimm |= (temp & 0xfffff000);
11804 md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
11805
11806 highpart |= (newinsn & 0xfffff000);
11807 md_number_to_chars (buf + INSN_SIZE, (valueT) highpart, INSN_SIZE);
11808 }
11809 break;
11810
11811 case BFD_RELOC_ARM_OFFSET_IMM:
11812 sign = value >= 0;
11813
11814 if (value < 0)
11815 value = - value;
11816
11817 if (validate_offset_imm (value, 0) == FAIL)
11818 {
11819 as_bad_where (fixP->fx_file, fixP->fx_line,
11820 _("bad immediate value for offset (%ld)"),
11821 (long) value);
11822 break;
11823 }
11824
11825 newval = md_chars_to_number (buf, INSN_SIZE);
11826 newval &= 0xff7ff000;
11827 newval |= value | (sign ? INDEX_UP : 0);
11828 md_number_to_chars (buf, newval, INSN_SIZE);
11829 break;
11830
11831 case BFD_RELOC_ARM_OFFSET_IMM8:
11832 case BFD_RELOC_ARM_HWLITERAL:
11833 sign = value >= 0;
11834
11835 if (value < 0)
11836 value = - value;
11837
11838 if (validate_offset_imm (value, 1) == FAIL)
11839 {
11840 if (fixP->fx_r_type == BFD_RELOC_ARM_HWLITERAL)
11841 as_bad_where (fixP->fx_file, fixP->fx_line,
11842 _("invalid literal constant: pool needs to be closer"));
11843 else
11844 as_bad (_("bad immediate value for half-word offset (%ld)"),
11845 (long) value);
11846 break;
11847 }
11848
11849 newval = md_chars_to_number (buf, INSN_SIZE);
11850 newval &= 0xff7ff0f0;
11851 newval |= ((value >> 4) << 8) | (value & 0xf) | (sign ? INDEX_UP : 0);
11852 md_number_to_chars (buf, newval, INSN_SIZE);
11853 break;
11854
11855 case BFD_RELOC_ARM_LITERAL:
11856 sign = value >= 0;
11857
11858 if (value < 0)
11859 value = - value;
11860
11861 if (validate_offset_imm (value, 0) == FAIL)
11862 {
11863 as_bad_where (fixP->fx_file, fixP->fx_line,
11864 _("invalid literal constant: pool needs to be closer"));
11865 break;
11866 }
11867
11868 newval = md_chars_to_number (buf, INSN_SIZE);
11869 newval &= 0xff7ff000;
11870 newval |= value | (sign ? INDEX_UP : 0);
11871 md_number_to_chars (buf, newval, INSN_SIZE);
11872 break;
11873
11874 case BFD_RELOC_ARM_SHIFT_IMM:
11875 newval = md_chars_to_number (buf, INSN_SIZE);
11876 if (((unsigned long) value) > 32
11877 || (value == 32
11878 && (((newval & 0x60) == 0) || (newval & 0x60) == 0x60)))
11879 {
11880 as_bad_where (fixP->fx_file, fixP->fx_line,
11881 _("shift expression is too large"));
11882 break;
11883 }
11884
11885 if (value == 0)
11886 /* Shifts of zero must be done as lsl. */
11887 newval &= ~0x60;
11888 else if (value == 32)
11889 value = 0;
11890 newval &= 0xfffff07f;
11891 newval |= (value & 0x1f) << 7;
11892 md_number_to_chars (buf, newval, INSN_SIZE);
11893 break;
11894
11895 case BFD_RELOC_ARM_SMI:
11896 if (((unsigned long) value) > 0xffff)
11897 as_bad_where (fixP->fx_file, fixP->fx_line,
11898 _("invalid smi expression"));
11899 newval = md_chars_to_number (buf, INSN_SIZE) & 0xfff000f0;
11900 newval |= (value & 0xf) | ((value & 0xfff0) << 4);
11901 md_number_to_chars (buf, newval, INSN_SIZE);
11902 break;
11903
11904 case BFD_RELOC_ARM_SWI:
11905 if (arm_data->thumb_mode)
11906 {
11907 if (((unsigned long) value) > 0xff)
11908 as_bad_where (fixP->fx_file, fixP->fx_line,
11909 _("invalid swi expression"));
11910 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xff00;
11911 newval |= value;
11912 md_number_to_chars (buf, newval, THUMB_SIZE);
11913 }
11914 else
11915 {
11916 if (((unsigned long) value) > 0x00ffffff)
11917 as_bad_where (fixP->fx_file, fixP->fx_line,
11918 _("invalid swi expression"));
11919 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff000000;
11920 newval |= value;
11921 md_number_to_chars (buf, newval, INSN_SIZE);
11922 }
11923 break;
11924
11925 case BFD_RELOC_ARM_MULTI:
11926 if (((unsigned long) value) > 0xffff)
11927 as_bad_where (fixP->fx_file, fixP->fx_line,
11928 _("invalid expression in load/store multiple"));
11929 newval = value | md_chars_to_number (buf, INSN_SIZE);
11930 md_number_to_chars (buf, newval, INSN_SIZE);
11931 break;
11932
11933 case BFD_RELOC_ARM_PCREL_BRANCH:
11934 newval = md_chars_to_number (buf, INSN_SIZE);
11935
11936 /* Sign-extend a 24-bit number. */
11937 #define SEXT24(x) ((((x) & 0xffffff) ^ (~ 0x7fffff)) + 0x800000)
11938
11939 #ifdef OBJ_ELF
11940 value = fixP->fx_offset;
11941 #endif
11942
11943 /* We are going to store value (shifted right by two) in the
11944 instruction, in a 24 bit, signed field. Thus we need to check
11945 that none of the top 8 bits of the shifted value (top 7 bits of
11946 the unshifted, unsigned value) are set, or that they are all set. */
11947 if ((value & ~ ((offsetT) 0x1ffffff)) != 0
11948 && ((value & ~ ((offsetT) 0x1ffffff)) != ~ ((offsetT) 0x1ffffff)))
11949 {
11950 #ifdef OBJ_ELF
11951 /* Normally we would be stuck at this point, since we cannot store
11952 the absolute address that is the destination of the branch in the
11953 24 bits of the branch instruction. If however, we happen to know
11954 that the destination of the branch is in the same section as the
11955 branch instruction itself, then we can compute the relocation for
11956 ourselves and not have to bother the linker with it.
11957
11958 FIXME: The test for OBJ_ELF is only here because I have not
11959 worked out how to do this for OBJ_COFF. */
11960 if (fixP->fx_addsy != NULL
11961 && S_IS_DEFINED (fixP->fx_addsy)
11962 && S_GET_SEGMENT (fixP->fx_addsy) == seg)
11963 {
11964 /* Get pc relative value to go into the branch. */
11965 value = * valP;
11966
11967 /* Permit a backward branch provided that enough bits
11968 are set. Allow a forwards branch, provided that
11969 enough bits are clear. */
11970 if ( (value & ~ ((offsetT) 0x1ffffff)) == ~ ((offsetT) 0x1ffffff)
11971 || (value & ~ ((offsetT) 0x1ffffff)) == 0)
11972 fixP->fx_done = 1;
11973 }
11974
11975 if (! fixP->fx_done)
11976 #endif
11977 as_bad_where (fixP->fx_file, fixP->fx_line,
11978 _("GAS can't handle same-section branch dest >= 0x04000000"));
11979 }
11980
11981 value >>= 2;
11982 value += SEXT24 (newval);
11983
11984 if ( (value & ~ ((offsetT) 0xffffff)) != 0
11985 && ((value & ~ ((offsetT) 0xffffff)) != ~ ((offsetT) 0xffffff)))
11986 as_bad_where (fixP->fx_file, fixP->fx_line,
11987 _("out of range branch"));
11988
11989 if (seg->use_rela_p && !fixP->fx_done)
11990 {
11991 /* Must unshift the value before storing it in the addend. */
11992 value <<= 2;
11993 #ifdef OBJ_ELF
11994 fixP->fx_offset = value;
11995 #endif
11996 fixP->fx_addnumber = value;
11997 newval = newval & 0xff000000;
11998 }
11999 else
12000 newval = (value & 0x00ffffff) | (newval & 0xff000000);
12001 md_number_to_chars (buf, newval, INSN_SIZE);
12002 break;
12003
12004 case BFD_RELOC_ARM_PCREL_BLX:
12005 {
12006 offsetT hbit;
12007 newval = md_chars_to_number (buf, INSN_SIZE);
12008
12009 #ifdef OBJ_ELF
12010 value = fixP->fx_offset;
12011 #endif
12012 hbit = (value >> 1) & 1;
12013 value = (value >> 2) & 0x00ffffff;
12014 value = (value + (newval & 0x00ffffff)) & 0x00ffffff;
12015
12016 if (seg->use_rela_p && !fixP->fx_done)
12017 {
12018 /* Must sign-extend and unshift the value before storing
12019 it in the addend. */
12020 value = SEXT24 (value);
12021 value = (value << 2) | hbit;
12022 #ifdef OBJ_ELF
12023 fixP->fx_offset = value;
12024 #endif
12025 fixP->fx_addnumber = value;
12026 newval = newval & 0xfe000000;
12027 }
12028 else
12029 newval = value | (newval & 0xfe000000) | (hbit << 24);
12030 md_number_to_chars (buf, newval, INSN_SIZE);
12031 }
12032 break;
12033
12034 case BFD_RELOC_THUMB_PCREL_BRANCH9: /* Conditional branch. */
12035 newval = md_chars_to_number (buf, THUMB_SIZE);
12036 {
12037 addressT diff = (newval & 0xff) << 1;
12038 if (diff & 0x100)
12039 diff |= ~0xff;
12040
12041 value += diff;
12042 if ((value & ~0xff) && ((value & ~0xff) != ~0xff))
12043 as_bad_where (fixP->fx_file, fixP->fx_line,
12044 _("branch out of range"));
12045 if (seg->use_rela_p && !fixP->fx_done)
12046 {
12047 #ifdef OBJ_ELF
12048 fixP->fx_offset = value;
12049 #endif
12050 fixP->fx_addnumber = value;
12051 newval = newval & 0xff00;
12052 }
12053 else
12054 newval = (newval & 0xff00) | ((value & 0x1ff) >> 1);
12055 }
12056 md_number_to_chars (buf, newval, THUMB_SIZE);
12057 break;
12058
12059 case BFD_RELOC_THUMB_PCREL_BRANCH12: /* Unconditional branch. */
12060 newval = md_chars_to_number (buf, THUMB_SIZE);
12061 {
12062 addressT diff = (newval & 0x7ff) << 1;
12063 if (diff & 0x800)
12064 diff |= ~0x7ff;
12065
12066 value += diff;
12067 if ((value & ~0x7ff) && ((value & ~0x7ff) != ~0x7ff))
12068 as_bad_where (fixP->fx_file, fixP->fx_line,
12069 _("branch out of range"));
12070 if (seg->use_rela_p && !fixP->fx_done)
12071 {
12072 #ifdef OBJ_ELF
12073 fixP->fx_offset = value;
12074 #endif
12075 fixP->fx_addnumber = value;
12076 newval = newval & 0xf800;
12077 }
12078 else
12079 newval = (newval & 0xf800) | ((value & 0xfff) >> 1);
12080 }
12081 md_number_to_chars (buf, newval, THUMB_SIZE);
12082 break;
12083
12084 case BFD_RELOC_THUMB_PCREL_BLX:
12085 case BFD_RELOC_THUMB_PCREL_BRANCH23:
12086 {
12087 offsetT newval2;
12088 addressT diff;
12089
12090 newval = md_chars_to_number (buf, THUMB_SIZE);
12091 newval2 = md_chars_to_number (buf + THUMB_SIZE, THUMB_SIZE);
12092 diff = ((newval & 0x7ff) << 12) | ((newval2 & 0x7ff) << 1);
12093 if (diff & 0x400000)
12094 diff |= ~0x3fffff;
12095 #ifdef OBJ_ELF
12096 value = fixP->fx_offset;
12097 #endif
12098 value += diff;
12099
12100 if ((value & ~0x3fffff) && ((value & ~0x3fffff) != ~0x3fffff))
12101 as_bad_where (fixP->fx_file, fixP->fx_line,
12102 _("branch with link out of range"));
12103
12104 if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX)
12105 /* For a BLX instruction, make sure that the relocation is rounded up
12106 to a word boundary. This follows the semantics of the instruction
12107 which specifies that bit 1 of the target address will come from bit
12108 1 of the base address. */
12109 value = (value + 1) & ~ 1;
12110
12111 if (seg->use_rela_p && !fixP->fx_done)
12112 {
12113 #ifdef OBJ_ELF
12114 fixP->fx_offset = value;
12115 #endif
12116 fixP->fx_addnumber = value;
12117 newval = newval & 0xf800;
12118 newval2 = newval2 & 0xf800;
12119 }
12120 else
12121 {
12122 newval = (newval & 0xf800) | ((value & 0x7fffff) >> 12);
12123 newval2 = (newval2 & 0xf800) | ((value & 0xfff) >> 1);
12124 }
12125 md_number_to_chars (buf, newval, THUMB_SIZE);
12126 md_number_to_chars (buf + THUMB_SIZE, newval2, THUMB_SIZE);
12127 }
12128 break;
12129
12130 case BFD_RELOC_8:
12131 if (seg->use_rela_p && !fixP->fx_done)
12132 break;
12133 if (fixP->fx_done || fixP->fx_pcrel)
12134 md_number_to_chars (buf, value, 1);
12135 #ifdef OBJ_ELF
12136 else
12137 {
12138 value = fixP->fx_offset;
12139 md_number_to_chars (buf, value, 1);
12140 }
12141 #endif
12142 break;
12143
12144 case BFD_RELOC_16:
12145 if (seg->use_rela_p && !fixP->fx_done)
12146 break;
12147 if (fixP->fx_done || fixP->fx_pcrel)
12148 md_number_to_chars (buf, value, 2);
12149 #ifdef OBJ_ELF
12150 else
12151 {
12152 value = fixP->fx_offset;
12153 md_number_to_chars (buf, value, 2);
12154 }
12155 #endif
12156 break;
12157
12158 #ifdef OBJ_ELF
12159 case BFD_RELOC_ARM_TLS_GD32:
12160 case BFD_RELOC_ARM_TLS_LE32:
12161 case BFD_RELOC_ARM_TLS_IE32:
12162 case BFD_RELOC_ARM_TLS_LDM32:
12163 case BFD_RELOC_ARM_TLS_LDO32:
12164 S_SET_THREAD_LOCAL (fixP->fx_addsy);
12165 /* fall through */
12166
12167 case BFD_RELOC_ARM_GOT32:
12168 case BFD_RELOC_ARM_GOTOFF:
12169 case BFD_RELOC_ARM_TARGET2:
12170 if (seg->use_rela_p && !fixP->fx_done)
12171 break;
12172 md_number_to_chars (buf, 0, 4);
12173 break;
12174 #endif
12175
12176 case BFD_RELOC_RVA:
12177 case BFD_RELOC_32:
12178 case BFD_RELOC_ARM_TARGET1:
12179 case BFD_RELOC_ARM_ROSEGREL32:
12180 case BFD_RELOC_ARM_SBREL32:
12181 case BFD_RELOC_32_PCREL:
12182 if (seg->use_rela_p && !fixP->fx_done)
12183 break;
12184 if (fixP->fx_done || fixP->fx_pcrel)
12185 md_number_to_chars (buf, value, 4);
12186 #ifdef OBJ_ELF
12187 else
12188 {
12189 value = fixP->fx_offset;
12190 md_number_to_chars (buf, value, 4);
12191 }
12192 #endif
12193 break;
12194
12195 #ifdef OBJ_ELF
12196 case BFD_RELOC_ARM_PREL31:
12197 if (fixP->fx_done || fixP->fx_pcrel)
12198 {
12199 newval = md_chars_to_number (buf, 4) & 0x80000000;
12200 if ((value ^ (value >> 1)) & 0x40000000)
12201 {
12202 as_bad_where (fixP->fx_file, fixP->fx_line,
12203 _("rel31 relocation overflow"));
12204 }
12205 newval |= value & 0x7fffffff;
12206 md_number_to_chars (buf, newval, 4);
12207 }
12208 break;
12209
12210 case BFD_RELOC_ARM_PLT32:
12211 /* It appears the instruction is fully prepared at this point. */
12212 break;
12213 #endif
12214
12215 case BFD_RELOC_ARM_CP_OFF_IMM:
12216 sign = value >= 0;
12217 if (value < -1023 || value > 1023 || (value & 3))
12218 as_bad_where (fixP->fx_file, fixP->fx_line,
12219 _("illegal value for co-processor offset"));
12220 if (value < 0)
12221 value = -value;
12222 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
12223 newval |= (value >> 2) | (sign ? INDEX_UP : 0);
12224 md_number_to_chars (buf, newval, INSN_SIZE);
12225 break;
12226
12227 case BFD_RELOC_ARM_CP_OFF_IMM_S2:
12228 sign = value >= 0;
12229 if (value < -255 || value > 255)
12230 as_bad_where (fixP->fx_file, fixP->fx_line,
12231 _("Illegal value for co-processor offset"));
12232 if (value < 0)
12233 value = -value;
12234 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
12235 newval |= value | (sign ? INDEX_UP : 0);
12236 md_number_to_chars (buf, newval , INSN_SIZE);
12237 break;
12238
12239 case BFD_RELOC_ARM_THUMB_OFFSET:
12240 newval = md_chars_to_number (buf, THUMB_SIZE);
12241 /* Exactly what ranges, and where the offset is inserted depends
12242 on the type of instruction, we can establish this from the
12243 top 4 bits. */
12244 switch (newval >> 12)
12245 {
12246 case 4: /* PC load. */
12247 /* Thumb PC loads are somewhat odd, bit 1 of the PC is
12248 forced to zero for these loads, so we will need to round
12249 up the offset if the instruction address is not word
12250 aligned (since the final address produced must be, and
12251 we can only describe word-aligned immediate offsets). */
12252
12253 if ((fixP->fx_frag->fr_address + fixP->fx_where + value) & 3)
12254 as_bad_where (fixP->fx_file, fixP->fx_line,
12255 _("invalid offset, target not word aligned (0x%08X)"),
12256 (unsigned int) (fixP->fx_frag->fr_address
12257 + fixP->fx_where + value));
12258
12259 if ((value + 2) & ~0x3fe)
12260 as_bad_where (fixP->fx_file, fixP->fx_line,
12261 _("invalid offset, value too big (0x%08lX)"),
12262 (long) value);
12263
12264 /* Round up, since pc will be rounded down. */
12265 newval |= (value + 2) >> 2;
12266 break;
12267
12268 case 9: /* SP load/store. */
12269 if (value & ~0x3fc)
12270 as_bad_where (fixP->fx_file, fixP->fx_line,
12271 _("invalid offset, value too big (0x%08lX)"),
12272 (long) value);
12273 newval |= value >> 2;
12274 break;
12275
12276 case 6: /* Word load/store. */
12277 if (value & ~0x7c)
12278 as_bad_where (fixP->fx_file, fixP->fx_line,
12279 _("invalid offset, value too big (0x%08lX)"),
12280 (long) value);
12281 newval |= value << 4; /* 6 - 2. */
12282 break;
12283
12284 case 7: /* Byte load/store. */
12285 if (value & ~0x1f)
12286 as_bad_where (fixP->fx_file, fixP->fx_line,
12287 _("invalid offset, value too big (0x%08lX)"),
12288 (long) value);
12289 newval |= value << 6;
12290 break;
12291
12292 case 8: /* Halfword load/store. */
12293 if (value & ~0x3e)
12294 as_bad_where (fixP->fx_file, fixP->fx_line,
12295 _("invalid offset, value too big (0x%08lX)"),
12296 (long) value);
12297 newval |= value << 5; /* 6 - 1. */
12298 break;
12299
12300 default:
12301 as_bad_where (fixP->fx_file, fixP->fx_line,
12302 "Unable to process relocation for thumb opcode: %lx",
12303 (unsigned long) newval);
12304 break;
12305 }
12306 md_number_to_chars (buf, newval, THUMB_SIZE);
12307 break;
12308
12309 case BFD_RELOC_ARM_THUMB_ADD:
12310 /* This is a complicated relocation, since we use it for all of
12311 the following immediate relocations:
12312
12313 3bit ADD/SUB
12314 8bit ADD/SUB
12315 9bit ADD/SUB SP word-aligned
12316 10bit ADD PC/SP word-aligned
12317
12318 The type of instruction being processed is encoded in the
12319 instruction field:
12320
12321 0x8000 SUB
12322 0x00F0 Rd
12323 0x000F Rs
12324 */
12325 newval = md_chars_to_number (buf, THUMB_SIZE);
12326 {
12327 int rd = (newval >> 4) & 0xf;
12328 int rs = newval & 0xf;
12329 int subtract = newval & 0x8000;
12330
12331 if (rd == REG_SP)
12332 {
12333 if (value & ~0x1fc)
12334 as_bad_where (fixP->fx_file, fixP->fx_line,
12335 _("invalid immediate for stack address calculation"));
12336 newval = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
12337 newval |= value >> 2;
12338 }
12339 else if (rs == REG_PC || rs == REG_SP)
12340 {
12341 if (subtract ||
12342 value & ~0x3fc)
12343 as_bad_where (fixP->fx_file, fixP->fx_line,
12344 _("invalid immediate for address calculation (value = 0x%08lX)"),
12345 (unsigned long) value);
12346 newval = (rs == REG_PC ? T_OPCODE_ADD_PC : T_OPCODE_ADD_SP);
12347 newval |= rd << 8;
12348 newval |= value >> 2;
12349 }
12350 else if (rs == rd)
12351 {
12352 if (value & ~0xff)
12353 as_bad_where (fixP->fx_file, fixP->fx_line,
12354 _("invalid 8bit immediate"));
12355 newval = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
12356 newval |= (rd << 8) | value;
12357 }
12358 else
12359 {
12360 if (value & ~0x7)
12361 as_bad_where (fixP->fx_file, fixP->fx_line,
12362 _("invalid 3bit immediate"));
12363 newval = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
12364 newval |= rd | (rs << 3) | (value << 6);
12365 }
12366 }
12367 md_number_to_chars (buf, newval, THUMB_SIZE);
12368 break;
12369
12370 case BFD_RELOC_ARM_THUMB_IMM:
12371 newval = md_chars_to_number (buf, THUMB_SIZE);
12372 switch (newval >> 11)
12373 {
12374 case 0x04: /* 8bit immediate MOV. */
12375 case 0x05: /* 8bit immediate CMP. */
12376 if (value < 0 || value > 255)
12377 as_bad_where (fixP->fx_file, fixP->fx_line,
12378 _("invalid immediate: %ld is too large"),
12379 (long) value);
12380 newval |= value;
12381 break;
12382
12383 default:
12384 abort ();
12385 }
12386 md_number_to_chars (buf, newval, THUMB_SIZE);
12387 break;
12388
12389 case BFD_RELOC_ARM_THUMB_SHIFT:
12390 /* 5bit shift value (0..31). */
12391 if (value < 0 || value > 31)
12392 as_bad_where (fixP->fx_file, fixP->fx_line,
12393 _("illegal Thumb shift value: %ld"), (long) value);
12394 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xf03f;
12395 newval |= value << 6;
12396 md_number_to_chars (buf, newval, THUMB_SIZE);
12397 break;
12398
12399 case BFD_RELOC_VTABLE_INHERIT:
12400 case BFD_RELOC_VTABLE_ENTRY:
12401 fixP->fx_done = 0;
12402 return;
12403
12404 case BFD_RELOC_UNUSED:
12405 default:
12406 as_bad_where (fixP->fx_file, fixP->fx_line,
12407 _("bad relocation fixup type (%d)"), fixP->fx_r_type);
12408 }
12409 }
12410
12411 /* Translate internal representation of relocation info to BFD target
12412 format. */
12413
12414 arelent *
12415 tc_gen_reloc (asection * section ATTRIBUTE_UNUSED,
12416 fixS * fixp)
12417 {
12418 arelent * reloc;
12419 bfd_reloc_code_real_type code;
12420
12421 reloc = xmalloc (sizeof (arelent));
12422
12423 reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
12424 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
12425 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
12426
12427 /* @@ Why fx_addnumber sometimes and fx_offset other times? */
12428 #ifndef OBJ_ELF
12429 if (fixp->fx_pcrel == 0)
12430 reloc->addend = fixp->fx_offset;
12431 else
12432 reloc->addend = fixp->fx_offset = reloc->address;
12433 #else /* OBJ_ELF */
12434 reloc->addend = fixp->fx_offset;
12435 #endif
12436
12437 switch (fixp->fx_r_type)
12438 {
12439 case BFD_RELOC_8:
12440 if (fixp->fx_pcrel)
12441 {
12442 code = BFD_RELOC_8_PCREL;
12443 break;
12444 }
12445
12446 case BFD_RELOC_16:
12447 if (fixp->fx_pcrel)
12448 {
12449 code = BFD_RELOC_16_PCREL;
12450 break;
12451 }
12452
12453 case BFD_RELOC_32:
12454 if (fixp->fx_pcrel)
12455 {
12456 code = BFD_RELOC_32_PCREL;
12457 break;
12458 }
12459
12460 case BFD_RELOC_NONE:
12461 case BFD_RELOC_ARM_PCREL_BRANCH:
12462 case BFD_RELOC_ARM_PCREL_BLX:
12463 case BFD_RELOC_RVA:
12464 case BFD_RELOC_THUMB_PCREL_BRANCH9:
12465 case BFD_RELOC_THUMB_PCREL_BRANCH12:
12466 case BFD_RELOC_THUMB_PCREL_BRANCH23:
12467 case BFD_RELOC_THUMB_PCREL_BLX:
12468 case BFD_RELOC_VTABLE_ENTRY:
12469 case BFD_RELOC_VTABLE_INHERIT:
12470 code = fixp->fx_r_type;
12471 break;
12472
12473 case BFD_RELOC_ARM_LITERAL:
12474 case BFD_RELOC_ARM_HWLITERAL:
12475 /* If this is called then the a literal has
12476 been referenced across a section boundary. */
12477 as_bad_where (fixp->fx_file, fixp->fx_line,
12478 _("literal referenced across section boundary"));
12479 return NULL;
12480
12481 #ifdef OBJ_ELF
12482 case BFD_RELOC_ARM_GOT32:
12483 case BFD_RELOC_ARM_GOTOFF:
12484 case BFD_RELOC_ARM_PLT32:
12485 case BFD_RELOC_ARM_TARGET1:
12486 case BFD_RELOC_ARM_ROSEGREL32:
12487 case BFD_RELOC_ARM_SBREL32:
12488 case BFD_RELOC_ARM_PREL31:
12489 case BFD_RELOC_ARM_TARGET2:
12490 case BFD_RELOC_ARM_TLS_LE32:
12491 case BFD_RELOC_ARM_TLS_LDO32:
12492 code = fixp->fx_r_type;
12493 break;
12494
12495 case BFD_RELOC_ARM_TLS_GD32:
12496 case BFD_RELOC_ARM_TLS_IE32:
12497 case BFD_RELOC_ARM_TLS_LDM32:
12498 /* BFD will include the symbol's address in the addend.
12499 But we don't want that, so subtract it out again here. */
12500 if (!S_IS_COMMON (fixp->fx_addsy))
12501 reloc->addend -= (*reloc->sym_ptr_ptr)->value;
12502 code = fixp->fx_r_type;
12503 break;
12504 #endif
12505
12506 case BFD_RELOC_ARM_IMMEDIATE:
12507 as_bad_where (fixp->fx_file, fixp->fx_line,
12508 _("internal relocation (type: IMMEDIATE) not fixed up"));
12509 return NULL;
12510
12511 case BFD_RELOC_ARM_ADRL_IMMEDIATE:
12512 as_bad_where (fixp->fx_file, fixp->fx_line,
12513 _("ADRL used for a symbol not defined in the same file"));
12514 return NULL;
12515
12516 case BFD_RELOC_ARM_OFFSET_IMM:
12517 if (fixp->fx_addsy != NULL
12518 && !S_IS_DEFINED (fixp->fx_addsy)
12519 && S_IS_LOCAL (fixp->fx_addsy))
12520 {
12521 as_bad_where (fixp->fx_file, fixp->fx_line,
12522 _("undefined local label `%s'"),
12523 S_GET_NAME (fixp->fx_addsy));
12524 return NULL;
12525 }
12526
12527 as_bad_where (fixp->fx_file, fixp->fx_line,
12528 _("internal_relocation (type: OFFSET_IMM) not fixed up"));
12529 return NULL;
12530
12531 default:
12532 {
12533 char * type;
12534
12535 switch (fixp->fx_r_type)
12536 {
12537 case BFD_RELOC_NONE: type = "NONE"; break;
12538 case BFD_RELOC_ARM_OFFSET_IMM8: type = "OFFSET_IMM8"; break;
12539 case BFD_RELOC_ARM_SHIFT_IMM: type = "SHIFT_IMM"; break;
12540 case BFD_RELOC_ARM_SMI: type = "SMI"; break;
12541 case BFD_RELOC_ARM_SWI: type = "SWI"; break;
12542 case BFD_RELOC_ARM_MULTI: type = "MULTI"; break;
12543 case BFD_RELOC_ARM_CP_OFF_IMM: type = "CP_OFF_IMM"; break;
12544 case BFD_RELOC_ARM_THUMB_ADD: type = "THUMB_ADD"; break;
12545 case BFD_RELOC_ARM_THUMB_SHIFT: type = "THUMB_SHIFT"; break;
12546 case BFD_RELOC_ARM_THUMB_IMM: type = "THUMB_IMM"; break;
12547 case BFD_RELOC_ARM_THUMB_OFFSET: type = "THUMB_OFFSET"; break;
12548 default: type = _("<unknown>"); break;
12549 }
12550 as_bad_where (fixp->fx_file, fixp->fx_line,
12551 _("cannot represent %s relocation in this object file format"),
12552 type);
12553 return NULL;
12554 }
12555 }
12556
12557 #ifdef OBJ_ELF
12558 if ((code == BFD_RELOC_32_PCREL || code == BFD_RELOC_32)
12559 && GOT_symbol
12560 && fixp->fx_addsy == GOT_symbol)
12561 {
12562 code = BFD_RELOC_ARM_GOTPC;
12563 reloc->addend = fixp->fx_offset = reloc->address;
12564 }
12565 #endif
12566
12567 reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
12568
12569 if (reloc->howto == NULL)
12570 {
12571 as_bad_where (fixp->fx_file, fixp->fx_line,
12572 _("cannot represent %s relocation in this object file format"),
12573 bfd_get_reloc_code_name (code));
12574 return NULL;
12575 }
12576
12577 /* HACK: Since arm ELF uses Rel instead of Rela, encode the
12578 vtable entry to be used in the relocation's section offset. */
12579 if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
12580 reloc->address = fixp->fx_offset;
12581
12582 return reloc;
12583 }
12584
12585 int
12586 md_estimate_size_before_relax (fragS * fragP ATTRIBUTE_UNUSED,
12587 segT segtype ATTRIBUTE_UNUSED)
12588 {
12589 as_fatal (_("md_estimate_size_before_relax\n"));
12590 return 1;
12591 }
12592
12593 /* We need to be able to fix up arbitrary expressions in some statements.
12594 This is so that we can handle symbols that are an arbitrary distance from
12595 the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
12596 which returns part of an address in a form which will be valid for
12597 a data instruction. We do this by pushing the expression into a symbol
12598 in the expr_section, and creating a fix for that. */
12599
12600 static void
12601 fix_new_arm (fragS * frag,
12602 int where,
12603 short int size,
12604 expressionS * exp,
12605 int pc_rel,
12606 int reloc)
12607 {
12608 fixS * new_fix;
12609 arm_fix_data * arm_data;
12610
12611 switch (exp->X_op)
12612 {
12613 case O_constant:
12614 case O_symbol:
12615 case O_add:
12616 case O_subtract:
12617 new_fix = fix_new_exp (frag, where, size, exp, pc_rel, reloc);
12618 break;
12619
12620 default:
12621 new_fix = fix_new (frag, where, size, make_expr_symbol (exp), 0,
12622 pc_rel, reloc);
12623 break;
12624 }
12625
12626 /* Mark whether the fix is to a THUMB instruction, or an ARM
12627 instruction. */
12628 arm_data = obstack_alloc (& notes, sizeof (arm_fix_data));
12629 new_fix->tc_fix_data = (PTR) arm_data;
12630 arm_data->thumb_mode = thumb_mode;
12631 }
12632
12633 static void
12634 output_inst (const char * str)
12635 {
12636 char * to = NULL;
12637
12638 if (inst.error)
12639 {
12640 as_bad ("%s -- `%s'", inst.error, str);
12641 return;
12642 }
12643
12644 to = frag_more (inst.size);
12645
12646 if (thumb_mode && (inst.size > THUMB_SIZE))
12647 {
12648 assert (inst.size == (2 * THUMB_SIZE));
12649 md_number_to_chars (to, inst.instruction >> 16, THUMB_SIZE);
12650 md_number_to_chars (to + THUMB_SIZE, inst.instruction, THUMB_SIZE);
12651 }
12652 else if (inst.size > INSN_SIZE)
12653 {
12654 assert (inst.size == (2 * INSN_SIZE));
12655 md_number_to_chars (to, inst.instruction, INSN_SIZE);
12656 md_number_to_chars (to + INSN_SIZE, inst.instruction, INSN_SIZE);
12657 }
12658 else
12659 md_number_to_chars (to, inst.instruction, inst.size);
12660
12661 if (inst.reloc.type != BFD_RELOC_UNUSED)
12662 fix_new_arm (frag_now, to - frag_now->fr_literal,
12663 inst.size, & inst.reloc.exp, inst.reloc.pc_rel,
12664 inst.reloc.type);
12665
12666 #ifdef OBJ_ELF
12667 dwarf2_emit_insn (inst.size);
12668 #endif
12669 }
12670
12671 void
12672 md_assemble (char * str)
12673 {
12674 char c;
12675 char *p;
12676 char *start;
12677
12678 /* Align the previous label if needed. */
12679 if (last_label_seen != NULL)
12680 {
12681 symbol_set_frag (last_label_seen, frag_now);
12682 S_SET_VALUE (last_label_seen, (valueT) frag_now_fix ());
12683 S_SET_SEGMENT (last_label_seen, now_seg);
12684 }
12685
12686 memset (&inst, '\0', sizeof (inst));
12687 inst.reloc.type = BFD_RELOC_UNUSED;
12688
12689 skip_whitespace (str);
12690
12691 /* Scan up to the end of the op-code, which must end in white space or
12692 end of string. */
12693 for (start = p = str; *p != '\0'; p++)
12694 if (*p == ' ')
12695 break;
12696
12697 if (p == str)
12698 {
12699 as_bad (_("no operator -- statement `%s'\n"), str);
12700 return;
12701 }
12702
12703 if (thumb_mode)
12704 {
12705 const struct thumb_opcode * opcode;
12706
12707 c = *p;
12708 *p = '\0';
12709 opcode = (const struct thumb_opcode *) hash_find (arm_tops_hsh, str);
12710 *p = c;
12711
12712 if (opcode)
12713 {
12714 /* Check that this instruction is supported for this CPU. */
12715 if (thumb_mode == 1 && (opcode->variant & cpu_variant) == 0)
12716 {
12717 as_bad (_("selected processor does not support `%s'"), str);
12718 return;
12719 }
12720
12721 mapping_state (MAP_THUMB);
12722 inst.instruction = opcode->value;
12723 inst.size = opcode->size;
12724 opcode->parms (p);
12725 output_inst (str);
12726 return;
12727 }
12728 }
12729 else
12730 {
12731 const struct asm_opcode * opcode;
12732
12733 c = *p;
12734 *p = '\0';
12735 opcode = (const struct asm_opcode *) hash_find (arm_ops_hsh, str);
12736 *p = c;
12737
12738 if (opcode)
12739 {
12740 /* Check that this instruction is supported for this CPU. */
12741 if ((opcode->variant & cpu_variant) == 0)
12742 {
12743 as_bad (_("selected processor does not support `%s'"), str);
12744 return;
12745 }
12746
12747 mapping_state (MAP_ARM);
12748 inst.instruction = opcode->value;
12749 inst.size = INSN_SIZE;
12750 opcode->parms (p);
12751 output_inst (str);
12752 return;
12753 }
12754 }
12755
12756 /* It wasn't an instruction, but it might be a register alias of the form
12757 alias .req reg. */
12758 if (create_register_alias (str, p))
12759 return;
12760
12761 as_bad (_("bad instruction `%s'"), start);
12762 }
12763
12764 /* md_parse_option
12765 Invocation line includes a switch not recognized by the base assembler.
12766 See if it's a processor-specific option.
12767
12768 This routine is somewhat complicated by the need for backwards
12769 compatibility (since older releases of gcc can't be changed).
12770 The new options try to make the interface as compatible as
12771 possible with GCC.
12772
12773 New options (supported) are:
12774
12775 -mcpu=<cpu name> Assemble for selected processor
12776 -march=<architecture name> Assemble for selected architecture
12777 -mfpu=<fpu architecture> Assemble for selected FPU.
12778 -EB/-mbig-endian Big-endian
12779 -EL/-mlittle-endian Little-endian
12780 -k Generate PIC code
12781 -mthumb Start in Thumb mode
12782 -mthumb-interwork Code supports ARM/Thumb interworking
12783
12784 For now we will also provide support for:
12785
12786 -mapcs-32 32-bit Program counter
12787 -mapcs-26 26-bit Program counter
12788 -macps-float Floats passed in FP registers
12789 -mapcs-reentrant Reentrant code
12790 -matpcs
12791 (sometime these will probably be replaced with -mapcs=<list of options>
12792 and -matpcs=<list of options>)
12793
12794 The remaining options are only supported for back-wards compatibility.
12795 Cpu variants, the arm part is optional:
12796 -m[arm]1 Currently not supported.
12797 -m[arm]2, -m[arm]250 Arm 2 and Arm 250 processor
12798 -m[arm]3 Arm 3 processor
12799 -m[arm]6[xx], Arm 6 processors
12800 -m[arm]7[xx][t][[d]m] Arm 7 processors
12801 -m[arm]8[10] Arm 8 processors
12802 -m[arm]9[20][tdmi] Arm 9 processors
12803 -mstrongarm[110[0]] StrongARM processors
12804 -mxscale XScale processors
12805 -m[arm]v[2345[t[e]]] Arm architectures
12806 -mall All (except the ARM1)
12807 FP variants:
12808 -mfpa10, -mfpa11 FPA10 and 11 co-processor instructions
12809 -mfpe-old (No float load/store multiples)
12810 -mvfpxd VFP Single precision
12811 -mvfp All VFP
12812 -mno-fpu Disable all floating point instructions
12813
12814 The following CPU names are recognized:
12815 arm1, arm2, arm250, arm3, arm6, arm600, arm610, arm620,
12816 arm7, arm7m, arm7d, arm7dm, arm7di, arm7dmi, arm70, arm700,
12817 arm700i, arm710 arm710t, arm720, arm720t, arm740t, arm710c,
12818 arm7100, arm7500, arm7500fe, arm7tdmi, arm8, arm810, arm9,
12819 arm920, arm920t, arm940t, arm946, arm966, arm9tdmi, arm9e,
12820 arm10t arm10e, arm1020t, arm1020e, arm10200e,
12821 strongarm, strongarm110, strongarm1100, strongarm1110, xscale.
12822
12823 */
12824
12825 const char * md_shortopts = "m:k";
12826
12827 #ifdef ARM_BI_ENDIAN
12828 #define OPTION_EB (OPTION_MD_BASE + 0)
12829 #define OPTION_EL (OPTION_MD_BASE + 1)
12830 #else
12831 #if TARGET_BYTES_BIG_ENDIAN
12832 #define OPTION_EB (OPTION_MD_BASE + 0)
12833 #else
12834 #define OPTION_EL (OPTION_MD_BASE + 1)
12835 #endif
12836 #endif
12837
12838 struct option md_longopts[] =
12839 {
12840 #ifdef OPTION_EB
12841 {"EB", no_argument, NULL, OPTION_EB},
12842 #endif
12843 #ifdef OPTION_EL
12844 {"EL", no_argument, NULL, OPTION_EL},
12845 #endif
12846 {NULL, no_argument, NULL, 0}
12847 };
12848
12849 size_t md_longopts_size = sizeof (md_longopts);
12850
12851 struct arm_option_table
12852 {
12853 char *option; /* Option name to match. */
12854 char *help; /* Help information. */
12855 int *var; /* Variable to change. */
12856 int value; /* What to change it to. */
12857 char *deprecated; /* If non-null, print this message. */
12858 };
12859
12860 struct arm_option_table arm_opts[] =
12861 {
12862 {"k", N_("generate PIC code"), &pic_code, 1, NULL},
12863 {"mthumb", N_("assemble Thumb code"), &thumb_mode, 1, NULL},
12864 {"mthumb-interwork", N_("support ARM/Thumb interworking"),
12865 &support_interwork, 1, NULL},
12866 {"mapcs-32", N_("code uses 32-bit program counter"), &uses_apcs_26, 0, NULL},
12867 {"mapcs-26", N_("code uses 26-bit program counter"), &uses_apcs_26, 1, NULL},
12868 {"mapcs-float", N_("floating point args are in fp regs"), &uses_apcs_float,
12869 1, NULL},
12870 {"mapcs-reentrant", N_("re-entrant code"), &pic_code, 1, NULL},
12871 {"matpcs", N_("code is ATPCS conformant"), &atpcs, 1, NULL},
12872 {"mbig-endian", N_("assemble for big-endian"), &target_big_endian, 1, NULL},
12873 {"mlittle-endian", N_("assemble for little-endian"), &target_big_endian, 0,
12874 NULL},
12875
12876 /* These are recognized by the assembler, but have no affect on code. */
12877 {"mapcs-frame", N_("use frame pointer"), NULL, 0, NULL},
12878 {"mapcs-stack-check", N_("use stack size checking"), NULL, 0, NULL},
12879
12880 /* DON'T add any new processors to this list -- we want the whole list
12881 to go away... Add them to the processors table instead. */
12882 {"marm1", NULL, &legacy_cpu, ARM_ARCH_V1, N_("use -mcpu=arm1")},
12883 {"m1", NULL, &legacy_cpu, ARM_ARCH_V1, N_("use -mcpu=arm1")},
12884 {"marm2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -mcpu=arm2")},
12885 {"m2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -mcpu=arm2")},
12886 {"marm250", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm250")},
12887 {"m250", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm250")},
12888 {"marm3", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm3")},
12889 {"m3", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm3")},
12890 {"marm6", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm6")},
12891 {"m6", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm6")},
12892 {"marm600", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm600")},
12893 {"m600", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm600")},
12894 {"marm610", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm610")},
12895 {"m610", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm610")},
12896 {"marm620", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm620")},
12897 {"m620", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm620")},
12898 {"marm7", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7")},
12899 {"m7", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7")},
12900 {"marm70", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm70")},
12901 {"m70", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm70")},
12902 {"marm700", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700")},
12903 {"m700", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700")},
12904 {"marm700i", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700i")},
12905 {"m700i", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700i")},
12906 {"marm710", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710")},
12907 {"m710", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710")},
12908 {"marm710c", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710c")},
12909 {"m710c", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710c")},
12910 {"marm720", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm720")},
12911 {"m720", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm720")},
12912 {"marm7d", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7d")},
12913 {"m7d", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7d")},
12914 {"marm7di", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7di")},
12915 {"m7di", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7di")},
12916 {"marm7m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7m")},
12917 {"m7m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7m")},
12918 {"marm7dm", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dm")},
12919 {"m7dm", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dm")},
12920 {"marm7dmi", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dmi")},
12921 {"m7dmi", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dmi")},
12922 {"marm7100", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7100")},
12923 {"m7100", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7100")},
12924 {"marm7500", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500")},
12925 {"m7500", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500")},
12926 {"marm7500fe", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500fe")},
12927 {"m7500fe", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500fe")},
12928 {"marm7t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
12929 {"m7t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
12930 {"marm7tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
12931 {"m7tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
12932 {"marm710t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm710t")},
12933 {"m710t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm710t")},
12934 {"marm720t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm720t")},
12935 {"m720t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm720t")},
12936 {"marm740t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm740t")},
12937 {"m740t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm740t")},
12938 {"marm8", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm8")},
12939 {"m8", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm8")},
12940 {"marm810", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm810")},
12941 {"m810", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm810")},
12942 {"marm9", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9")},
12943 {"m9", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9")},
12944 {"marm9tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9tdmi")},
12945 {"m9tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9tdmi")},
12946 {"marm920", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm920")},
12947 {"m920", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm920")},
12948 {"marm940", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm940")},
12949 {"m940", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm940")},
12950 {"mstrongarm", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=strongarm")},
12951 {"mstrongarm110", NULL, &legacy_cpu, ARM_ARCH_V4,
12952 N_("use -mcpu=strongarm110")},
12953 {"mstrongarm1100", NULL, &legacy_cpu, ARM_ARCH_V4,
12954 N_("use -mcpu=strongarm1100")},
12955 {"mstrongarm1110", NULL, &legacy_cpu, ARM_ARCH_V4,
12956 N_("use -mcpu=strongarm1110")},
12957 {"mxscale", NULL, &legacy_cpu, ARM_ARCH_XSCALE, N_("use -mcpu=xscale")},
12958 {"miwmmxt", NULL, &legacy_cpu, ARM_ARCH_IWMMXT, N_("use -mcpu=iwmmxt")},
12959 {"mall", NULL, &legacy_cpu, ARM_ANY, N_("use -mcpu=all")},
12960
12961 /* Architecture variants -- don't add any more to this list either. */
12962 {"mv2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -march=armv2")},
12963 {"marmv2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -march=armv2")},
12964 {"mv2a", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -march=armv2a")},
12965 {"marmv2a", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -march=armv2a")},
12966 {"mv3", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -march=armv3")},
12967 {"marmv3", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -march=armv3")},
12968 {"mv3m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -march=armv3m")},
12969 {"marmv3m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -march=armv3m")},
12970 {"mv4", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -march=armv4")},
12971 {"marmv4", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -march=armv4")},
12972 {"mv4t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -march=armv4t")},
12973 {"marmv4t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -march=armv4t")},
12974 {"mv5", NULL, &legacy_cpu, ARM_ARCH_V5, N_("use -march=armv5")},
12975 {"marmv5", NULL, &legacy_cpu, ARM_ARCH_V5, N_("use -march=armv5")},
12976 {"mv5t", NULL, &legacy_cpu, ARM_ARCH_V5T, N_("use -march=armv5t")},
12977 {"marmv5t", NULL, &legacy_cpu, ARM_ARCH_V5T, N_("use -march=armv5t")},
12978 {"mv5e", NULL, &legacy_cpu, ARM_ARCH_V5TE, N_("use -march=armv5te")},
12979 {"marmv5e", NULL, &legacy_cpu, ARM_ARCH_V5TE, N_("use -march=armv5te")},
12980
12981 /* Floating point variants -- don't add any more to this list either. */
12982 {"mfpe-old", NULL, &legacy_fpu, FPU_ARCH_FPE, N_("use -mfpu=fpe")},
12983 {"mfpa10", NULL, &legacy_fpu, FPU_ARCH_FPA, N_("use -mfpu=fpa10")},
12984 {"mfpa11", NULL, &legacy_fpu, FPU_ARCH_FPA, N_("use -mfpu=fpa11")},
12985 {"mno-fpu", NULL, &legacy_fpu, 0,
12986 N_("use either -mfpu=softfpa or -mfpu=softvfp")},
12987
12988 {NULL, NULL, NULL, 0, NULL}
12989 };
12990
12991 struct arm_cpu_option_table
12992 {
12993 char *name;
12994 int value;
12995 /* For some CPUs we assume an FPU unless the user explicitly sets
12996 -mfpu=... */
12997 int default_fpu;
12998 };
12999
13000 /* This list should, at a minimum, contain all the cpu names
13001 recognized by GCC. */
13002 static struct arm_cpu_option_table arm_cpus[] =
13003 {
13004 {"all", ARM_ANY, FPU_ARCH_FPA},
13005 {"arm1", ARM_ARCH_V1, FPU_ARCH_FPA},
13006 {"arm2", ARM_ARCH_V2, FPU_ARCH_FPA},
13007 {"arm250", ARM_ARCH_V2S, FPU_ARCH_FPA},
13008 {"arm3", ARM_ARCH_V2S, FPU_ARCH_FPA},
13009 {"arm6", ARM_ARCH_V3, FPU_ARCH_FPA},
13010 {"arm60", ARM_ARCH_V3, FPU_ARCH_FPA},
13011 {"arm600", ARM_ARCH_V3, FPU_ARCH_FPA},
13012 {"arm610", ARM_ARCH_V3, FPU_ARCH_FPA},
13013 {"arm620", ARM_ARCH_V3, FPU_ARCH_FPA},
13014 {"arm7", ARM_ARCH_V3, FPU_ARCH_FPA},
13015 {"arm7m", ARM_ARCH_V3M, FPU_ARCH_FPA},
13016 {"arm7d", ARM_ARCH_V3, FPU_ARCH_FPA},
13017 {"arm7dm", ARM_ARCH_V3M, FPU_ARCH_FPA},
13018 {"arm7di", ARM_ARCH_V3, FPU_ARCH_FPA},
13019 {"arm7dmi", ARM_ARCH_V3M, FPU_ARCH_FPA},
13020 {"arm70", ARM_ARCH_V3, FPU_ARCH_FPA},
13021 {"arm700", ARM_ARCH_V3, FPU_ARCH_FPA},
13022 {"arm700i", ARM_ARCH_V3, FPU_ARCH_FPA},
13023 {"arm710", ARM_ARCH_V3, FPU_ARCH_FPA},
13024 {"arm710t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13025 {"arm720", ARM_ARCH_V3, FPU_ARCH_FPA},
13026 {"arm720t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13027 {"arm740t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13028 {"arm710c", ARM_ARCH_V3, FPU_ARCH_FPA},
13029 {"arm7100", ARM_ARCH_V3, FPU_ARCH_FPA},
13030 {"arm7500", ARM_ARCH_V3, FPU_ARCH_FPA},
13031 {"arm7500fe", ARM_ARCH_V3, FPU_ARCH_FPA},
13032 {"arm7t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13033 {"arm7tdmi", ARM_ARCH_V4T, FPU_ARCH_FPA},
13034 {"arm7tdmi-s", ARM_ARCH_V4T, FPU_ARCH_FPA},
13035 {"arm8", ARM_ARCH_V4, FPU_ARCH_FPA},
13036 {"arm810", ARM_ARCH_V4, FPU_ARCH_FPA},
13037 {"strongarm", ARM_ARCH_V4, FPU_ARCH_FPA},
13038 {"strongarm1", ARM_ARCH_V4, FPU_ARCH_FPA},
13039 {"strongarm110", ARM_ARCH_V4, FPU_ARCH_FPA},
13040 {"strongarm1100", ARM_ARCH_V4, FPU_ARCH_FPA},
13041 {"strongarm1110", ARM_ARCH_V4, FPU_ARCH_FPA},
13042 {"arm9", ARM_ARCH_V4T, FPU_ARCH_FPA},
13043 {"arm920", ARM_ARCH_V4T, FPU_ARCH_FPA},
13044 {"arm920t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13045 {"arm922t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13046 {"arm940t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13047 {"arm9tdmi", ARM_ARCH_V4T, FPU_ARCH_FPA},
13048 /* For V5 or later processors we default to using VFP; but the user
13049 should really set the FPU type explicitly. */
13050 {"arm9e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
13051 {"arm9e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13052 {"arm926ej", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
13053 {"arm926ejs", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
13054 {"arm926ej-s", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
13055 {"arm946e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
13056 {"arm946e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13057 {"arm966e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
13058 {"arm966e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13059 {"arm10t", ARM_ARCH_V5T, FPU_ARCH_VFP_V1},
13060 {"arm10e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13061 {"arm1020", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13062 {"arm1020t", ARM_ARCH_V5T, FPU_ARCH_VFP_V1},
13063 {"arm1020e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13064 {"arm1026ejs", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
13065 {"arm1026ej-s", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
13066 {"arm1136js", ARM_ARCH_V6, FPU_NONE},
13067 {"arm1136j-s", ARM_ARCH_V6, FPU_NONE},
13068 {"arm1136jfs", ARM_ARCH_V6, FPU_ARCH_VFP_V2},
13069 {"arm1136jf-s", ARM_ARCH_V6, FPU_ARCH_VFP_V2},
13070 {"mpcore", ARM_ARCH_V6K, FPU_ARCH_VFP_V2},
13071 {"mpcorenovfp", ARM_ARCH_V6K, FPU_NONE},
13072 {"arm1176jz-s", ARM_ARCH_V6ZK, FPU_NONE},
13073 {"arm1176jzf-s", ARM_ARCH_V6ZK, FPU_ARCH_VFP_V2},
13074 /* ??? XSCALE is really an architecture. */
13075 {"xscale", ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2},
13076 /* ??? iwmmxt is not a processor. */
13077 {"iwmmxt", ARM_ARCH_IWMMXT, FPU_ARCH_VFP_V2},
13078 {"i80200", ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2},
13079 /* Maverick */
13080 {"ep9312", ARM_ARCH_V4T | ARM_CEXT_MAVERICK, FPU_ARCH_MAVERICK},
13081 {NULL, 0, 0}
13082 };
13083
13084 struct arm_arch_option_table
13085 {
13086 char *name;
13087 int value;
13088 int default_fpu;
13089 };
13090
13091 /* This list should, at a minimum, contain all the architecture names
13092 recognized by GCC. */
13093 static struct arm_arch_option_table arm_archs[] =
13094 {
13095 {"all", ARM_ANY, FPU_ARCH_FPA},
13096 {"armv1", ARM_ARCH_V1, FPU_ARCH_FPA},
13097 {"armv2", ARM_ARCH_V2, FPU_ARCH_FPA},
13098 {"armv2a", ARM_ARCH_V2S, FPU_ARCH_FPA},
13099 {"armv2s", ARM_ARCH_V2S, FPU_ARCH_FPA},
13100 {"armv3", ARM_ARCH_V3, FPU_ARCH_FPA},
13101 {"armv3m", ARM_ARCH_V3M, FPU_ARCH_FPA},
13102 {"armv4", ARM_ARCH_V4, FPU_ARCH_FPA},
13103 {"armv4xm", ARM_ARCH_V4xM, FPU_ARCH_FPA},
13104 {"armv4t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13105 {"armv4txm", ARM_ARCH_V4TxM, FPU_ARCH_FPA},
13106 {"armv5", ARM_ARCH_V5, FPU_ARCH_VFP},
13107 {"armv5t", ARM_ARCH_V5T, FPU_ARCH_VFP},
13108 {"armv5txm", ARM_ARCH_V5TxM, FPU_ARCH_VFP},
13109 {"armv5te", ARM_ARCH_V5TE, FPU_ARCH_VFP},
13110 {"armv5texp", ARM_ARCH_V5TExP, FPU_ARCH_VFP},
13111 {"armv5tej", ARM_ARCH_V5TEJ, FPU_ARCH_VFP},
13112 {"armv6", ARM_ARCH_V6, FPU_ARCH_VFP},
13113 {"armv6j", ARM_ARCH_V6, FPU_ARCH_VFP},
13114 {"armv6k", ARM_ARCH_V6K, FPU_ARCH_VFP},
13115 {"armv6z", ARM_ARCH_V6Z, FPU_ARCH_VFP},
13116 {"armv6zk", ARM_ARCH_V6ZK, FPU_ARCH_VFP},
13117 {"armv6t2", ARM_ARCH_V6T2, FPU_ARCH_VFP},
13118 {"armv6kt2", ARM_ARCH_V6KT2, FPU_ARCH_VFP},
13119 {"armv6zt2", ARM_ARCH_V6ZT2, FPU_ARCH_VFP},
13120 {"armv6zkt2", ARM_ARCH_V6ZKT2, FPU_ARCH_VFP},
13121 {"xscale", ARM_ARCH_XSCALE, FPU_ARCH_VFP},
13122 {"iwmmxt", ARM_ARCH_IWMMXT, FPU_ARCH_VFP},
13123 {NULL, 0, 0}
13124 };
13125
13126 /* ISA extensions in the co-processor space. */
13127 struct arm_arch_extension_table
13128 {
13129 char *name;
13130 int value;
13131 };
13132
13133 static struct arm_arch_extension_table arm_extensions[] =
13134 {
13135 {"maverick", ARM_CEXT_MAVERICK},
13136 {"xscale", ARM_CEXT_XSCALE},
13137 {"iwmmxt", ARM_CEXT_IWMMXT},
13138 {NULL, 0}
13139 };
13140
13141 struct arm_fpu_option_table
13142 {
13143 char *name;
13144 int value;
13145 };
13146
13147 /* This list should, at a minimum, contain all the fpu names
13148 recognized by GCC. */
13149 static struct arm_fpu_option_table arm_fpus[] =
13150 {
13151 {"softfpa", FPU_NONE},
13152 {"fpe", FPU_ARCH_FPE},
13153 {"fpe2", FPU_ARCH_FPE},
13154 {"fpe3", FPU_ARCH_FPA}, /* Third release supports LFM/SFM. */
13155 {"fpa", FPU_ARCH_FPA},
13156 {"fpa10", FPU_ARCH_FPA},
13157 {"fpa11", FPU_ARCH_FPA},
13158 {"arm7500fe", FPU_ARCH_FPA},
13159 {"softvfp", FPU_ARCH_VFP},
13160 {"softvfp+vfp", FPU_ARCH_VFP_V2},
13161 {"vfp", FPU_ARCH_VFP_V2},
13162 {"vfp9", FPU_ARCH_VFP_V2},
13163 {"vfp10", FPU_ARCH_VFP_V2},
13164 {"vfp10-r0", FPU_ARCH_VFP_V1},
13165 {"vfpxd", FPU_ARCH_VFP_V1xD},
13166 {"arm1020t", FPU_ARCH_VFP_V1},
13167 {"arm1020e", FPU_ARCH_VFP_V2},
13168 {"arm1136jfs", FPU_ARCH_VFP_V2},
13169 {"arm1136jf-s", FPU_ARCH_VFP_V2},
13170 {"maverick", FPU_ARCH_MAVERICK},
13171 {NULL, 0}
13172 };
13173
13174 struct arm_float_abi_option_table
13175 {
13176 char *name;
13177 int value;
13178 };
13179
13180 static struct arm_float_abi_option_table arm_float_abis[] =
13181 {
13182 {"hard", ARM_FLOAT_ABI_HARD},
13183 {"softfp", ARM_FLOAT_ABI_SOFTFP},
13184 {"soft", ARM_FLOAT_ABI_SOFT},
13185 {NULL, 0}
13186 };
13187
13188 struct arm_eabi_option_table
13189 {
13190 char *name;
13191 unsigned int value;
13192 };
13193
13194 #ifdef OBJ_ELF
13195 /* We only know how to output GNU and ver 4 (AAELF) formats. */
13196 static struct arm_eabi_option_table arm_eabis[] =
13197 {
13198 {"gnu", EF_ARM_EABI_UNKNOWN},
13199 {"4", EF_ARM_EABI_VER4},
13200 {NULL, 0}
13201 };
13202 #endif
13203
13204 struct arm_long_option_table
13205 {
13206 char * option; /* Substring to match. */
13207 char * help; /* Help information. */
13208 int (* func) (char * subopt); /* Function to decode sub-option. */
13209 char * deprecated; /* If non-null, print this message. */
13210 };
13211
13212 static int
13213 arm_parse_extension (char * str, int * opt_p)
13214 {
13215 while (str != NULL && *str != 0)
13216 {
13217 struct arm_arch_extension_table * opt;
13218 char * ext;
13219 int optlen;
13220
13221 if (*str != '+')
13222 {
13223 as_bad (_("invalid architectural extension"));
13224 return 0;
13225 }
13226
13227 str++;
13228 ext = strchr (str, '+');
13229
13230 if (ext != NULL)
13231 optlen = ext - str;
13232 else
13233 optlen = strlen (str);
13234
13235 if (optlen == 0)
13236 {
13237 as_bad (_("missing architectural extension"));
13238 return 0;
13239 }
13240
13241 for (opt = arm_extensions; opt->name != NULL; opt++)
13242 if (strncmp (opt->name, str, optlen) == 0)
13243 {
13244 *opt_p |= opt->value;
13245 break;
13246 }
13247
13248 if (opt->name == NULL)
13249 {
13250 as_bad (_("unknown architectural extnsion `%s'"), str);
13251 return 0;
13252 }
13253
13254 str = ext;
13255 };
13256
13257 return 1;
13258 }
13259
13260 static int
13261 arm_parse_cpu (char * str)
13262 {
13263 struct arm_cpu_option_table * opt;
13264 char * ext = strchr (str, '+');
13265 int optlen;
13266
13267 if (ext != NULL)
13268 optlen = ext - str;
13269 else
13270 optlen = strlen (str);
13271
13272 if (optlen == 0)
13273 {
13274 as_bad (_("missing cpu name `%s'"), str);
13275 return 0;
13276 }
13277
13278 for (opt = arm_cpus; opt->name != NULL; opt++)
13279 if (strncmp (opt->name, str, optlen) == 0)
13280 {
13281 mcpu_cpu_opt = opt->value;
13282 mcpu_fpu_opt = opt->default_fpu;
13283
13284 if (ext != NULL)
13285 return arm_parse_extension (ext, &mcpu_cpu_opt);
13286
13287 return 1;
13288 }
13289
13290 as_bad (_("unknown cpu `%s'"), str);
13291 return 0;
13292 }
13293
13294 static int
13295 arm_parse_arch (char * str)
13296 {
13297 struct arm_arch_option_table *opt;
13298 char *ext = strchr (str, '+');
13299 int optlen;
13300
13301 if (ext != NULL)
13302 optlen = ext - str;
13303 else
13304 optlen = strlen (str);
13305
13306 if (optlen == 0)
13307 {
13308 as_bad (_("missing architecture name `%s'"), str);
13309 return 0;
13310 }
13311
13312
13313 for (opt = arm_archs; opt->name != NULL; opt++)
13314 if (streq (opt->name, str))
13315 {
13316 march_cpu_opt = opt->value;
13317 march_fpu_opt = opt->default_fpu;
13318
13319 if (ext != NULL)
13320 return arm_parse_extension (ext, &march_cpu_opt);
13321
13322 return 1;
13323 }
13324
13325 as_bad (_("unknown architecture `%s'\n"), str);
13326 return 0;
13327 }
13328
13329 static int
13330 arm_parse_fpu (char * str)
13331 {
13332 struct arm_fpu_option_table * opt;
13333
13334 for (opt = arm_fpus; opt->name != NULL; opt++)
13335 if (streq (opt->name, str))
13336 {
13337 mfpu_opt = opt->value;
13338 return 1;
13339 }
13340
13341 as_bad (_("unknown floating point format `%s'\n"), str);
13342 return 0;
13343 }
13344
13345 static int
13346 arm_parse_float_abi (char * str)
13347 {
13348 struct arm_float_abi_option_table * opt;
13349
13350 for (opt = arm_float_abis; opt->name != NULL; opt++)
13351 if (streq (opt->name, str))
13352 {
13353 mfloat_abi_opt = opt->value;
13354 return 1;
13355 }
13356
13357 as_bad (_("unknown floating point abi `%s'\n"), str);
13358 return 0;
13359 }
13360
13361 #ifdef OBJ_ELF
13362 static int
13363 arm_parse_eabi (char * str)
13364 {
13365 struct arm_eabi_option_table *opt;
13366
13367 for (opt = arm_eabis; opt->name != NULL; opt++)
13368 if (streq (opt->name, str))
13369 {
13370 meabi_flags = opt->value;
13371 return 1;
13372 }
13373 as_bad (_("unknown EABI `%s'\n"), str);
13374 return 0;
13375 }
13376 #endif
13377
13378 struct arm_long_option_table arm_long_opts[] =
13379 {
13380 {"mcpu=", N_("<cpu name>\t assemble for CPU <cpu name>"),
13381 arm_parse_cpu, NULL},
13382 {"march=", N_("<arch name>\t assemble for architecture <arch name>"),
13383 arm_parse_arch, NULL},
13384 {"mfpu=", N_("<fpu name>\t assemble for FPU architecture <fpu name>"),
13385 arm_parse_fpu, NULL},
13386 {"mfloat-abi=", N_("<abi>\t assemble for floating point ABI <abi>"),
13387 arm_parse_float_abi, NULL},
13388 #ifdef OBJ_ELF
13389 {"meabi=", N_("<ver>\t assemble for eabi version <ver>"),
13390 arm_parse_eabi, NULL},
13391 #endif
13392 {NULL, NULL, 0, NULL}
13393 };
13394
13395 int
13396 md_parse_option (int c, char * arg)
13397 {
13398 struct arm_option_table *opt;
13399 struct arm_long_option_table *lopt;
13400
13401 switch (c)
13402 {
13403 #ifdef OPTION_EB
13404 case OPTION_EB:
13405 target_big_endian = 1;
13406 break;
13407 #endif
13408
13409 #ifdef OPTION_EL
13410 case OPTION_EL:
13411 target_big_endian = 0;
13412 break;
13413 #endif
13414
13415 case 'a':
13416 /* Listing option. Just ignore these, we don't support additional
13417 ones. */
13418 return 0;
13419
13420 default:
13421 for (opt = arm_opts; opt->option != NULL; opt++)
13422 {
13423 if (c == opt->option[0]
13424 && ((arg == NULL && opt->option[1] == 0)
13425 || streq (arg, opt->option + 1)))
13426 {
13427 #if WARN_DEPRECATED
13428 /* If the option is deprecated, tell the user. */
13429 if (opt->deprecated != NULL)
13430 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c,
13431 arg ? arg : "", _(opt->deprecated));
13432 #endif
13433
13434 if (opt->var != NULL)
13435 *opt->var = opt->value;
13436
13437 return 1;
13438 }
13439 }
13440
13441 for (lopt = arm_long_opts; lopt->option != NULL; lopt++)
13442 {
13443 /* These options are expected to have an argument. */
13444 if (c == lopt->option[0]
13445 && arg != NULL
13446 && strncmp (arg, lopt->option + 1,
13447 strlen (lopt->option + 1)) == 0)
13448 {
13449 #if WARN_DEPRECATED
13450 /* If the option is deprecated, tell the user. */
13451 if (lopt->deprecated != NULL)
13452 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c, arg,
13453 _(lopt->deprecated));
13454 #endif
13455
13456 /* Call the sup-option parser. */
13457 return lopt->func (arg + strlen (lopt->option) - 1);
13458 }
13459 }
13460
13461 return 0;
13462 }
13463
13464 return 1;
13465 }
13466
13467 void
13468 md_show_usage (FILE * fp)
13469 {
13470 struct arm_option_table *opt;
13471 struct arm_long_option_table *lopt;
13472
13473 fprintf (fp, _(" ARM-specific assembler options:\n"));
13474
13475 for (opt = arm_opts; opt->option != NULL; opt++)
13476 if (opt->help != NULL)
13477 fprintf (fp, " -%-23s%s\n", opt->option, _(opt->help));
13478
13479 for (lopt = arm_long_opts; lopt->option != NULL; lopt++)
13480 if (lopt->help != NULL)
13481 fprintf (fp, " -%s%s\n", lopt->option, _(lopt->help));
13482
13483 #ifdef OPTION_EB
13484 fprintf (fp, _("\
13485 -EB assemble code for a big-endian cpu\n"));
13486 #endif
13487
13488 #ifdef OPTION_EL
13489 fprintf (fp, _("\
13490 -EL assemble code for a little-endian cpu\n"));
13491 #endif
13492 }
13493
13494 /* This fix_new is called by cons via TC_CONS_FIX_NEW. */
13495
13496 void
13497 cons_fix_new_arm (fragS * frag,
13498 int where,
13499 int size,
13500 expressionS * exp)
13501 {
13502 bfd_reloc_code_real_type type;
13503 int pcrel = 0;
13504
13505 /* Pick a reloc.
13506 FIXME: @@ Should look at CPU word size. */
13507 switch (size)
13508 {
13509 case 1:
13510 type = BFD_RELOC_8;
13511 break;
13512 case 2:
13513 type = BFD_RELOC_16;
13514 break;
13515 case 4:
13516 default:
13517 type = BFD_RELOC_32;
13518 break;
13519 case 8:
13520 type = BFD_RELOC_64;
13521 break;
13522 }
13523
13524 fix_new_exp (frag, where, (int) size, exp, pcrel, type);
13525 }
13526
13527 /* A good place to do this, although this was probably not intended
13528 for this kind of use. We need to dump the literal pool before
13529 references are made to a null symbol pointer. */
13530
13531 void
13532 arm_cleanup (void)
13533 {
13534 literal_pool * pool;
13535
13536 for (pool = list_of_pools; pool; pool = pool->next)
13537 {
13538 /* Put it at the end of the relevent section. */
13539 subseg_set (pool->section, pool->sub_section);
13540 #ifdef OBJ_ELF
13541 arm_elf_change_section ();
13542 #endif
13543 s_ltorg (0);
13544 }
13545 }
13546
13547 void
13548 arm_start_line_hook (void)
13549 {
13550 last_label_seen = NULL;
13551 }
13552
13553 void
13554 arm_frob_label (symbolS * sym)
13555 {
13556 last_label_seen = sym;
13557
13558 ARM_SET_THUMB (sym, thumb_mode);
13559
13560 #if defined OBJ_COFF || defined OBJ_ELF
13561 ARM_SET_INTERWORK (sym, support_interwork);
13562 #endif
13563
13564 /* Note - do not allow local symbols (.Lxxx) to be labeled
13565 as Thumb functions. This is because these labels, whilst
13566 they exist inside Thumb code, are not the entry points for
13567 possible ARM->Thumb calls. Also, these labels can be used
13568 as part of a computed goto or switch statement. eg gcc
13569 can generate code that looks like this:
13570
13571 ldr r2, [pc, .Laaa]
13572 lsl r3, r3, #2
13573 ldr r2, [r3, r2]
13574 mov pc, r2
13575
13576 .Lbbb: .word .Lxxx
13577 .Lccc: .word .Lyyy
13578 ..etc...
13579 .Laaa: .word Lbbb
13580
13581 The first instruction loads the address of the jump table.
13582 The second instruction converts a table index into a byte offset.
13583 The third instruction gets the jump address out of the table.
13584 The fourth instruction performs the jump.
13585
13586 If the address stored at .Laaa is that of a symbol which has the
13587 Thumb_Func bit set, then the linker will arrange for this address
13588 to have the bottom bit set, which in turn would mean that the
13589 address computation performed by the third instruction would end
13590 up with the bottom bit set. Since the ARM is capable of unaligned
13591 word loads, the instruction would then load the incorrect address
13592 out of the jump table, and chaos would ensue. */
13593 if (label_is_thumb_function_name
13594 && (S_GET_NAME (sym)[0] != '.' || S_GET_NAME (sym)[1] != 'L')
13595 && (bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
13596 {
13597 /* When the address of a Thumb function is taken the bottom
13598 bit of that address should be set. This will allow
13599 interworking between Arm and Thumb functions to work
13600 correctly. */
13601
13602 THUMB_SET_FUNC (sym, 1);
13603
13604 label_is_thumb_function_name = FALSE;
13605 }
13606 }
13607
13608 /* Adjust the symbol table. This marks Thumb symbols as distinct from
13609 ARM ones. */
13610
13611 void
13612 arm_adjust_symtab (void)
13613 {
13614 #ifdef OBJ_COFF
13615 symbolS * sym;
13616
13617 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
13618 {
13619 if (ARM_IS_THUMB (sym))
13620 {
13621 if (THUMB_IS_FUNC (sym))
13622 {
13623 /* Mark the symbol as a Thumb function. */
13624 if ( S_GET_STORAGE_CLASS (sym) == C_STAT
13625 || S_GET_STORAGE_CLASS (sym) == C_LABEL) /* This can happen! */
13626 S_SET_STORAGE_CLASS (sym, C_THUMBSTATFUNC);
13627
13628 else if (S_GET_STORAGE_CLASS (sym) == C_EXT)
13629 S_SET_STORAGE_CLASS (sym, C_THUMBEXTFUNC);
13630 else
13631 as_bad (_("%s: unexpected function type: %d"),
13632 S_GET_NAME (sym), S_GET_STORAGE_CLASS (sym));
13633 }
13634 else switch (S_GET_STORAGE_CLASS (sym))
13635 {
13636 case C_EXT:
13637 S_SET_STORAGE_CLASS (sym, C_THUMBEXT);
13638 break;
13639 case C_STAT:
13640 S_SET_STORAGE_CLASS (sym, C_THUMBSTAT);
13641 break;
13642 case C_LABEL:
13643 S_SET_STORAGE_CLASS (sym, C_THUMBLABEL);
13644 break;
13645 default:
13646 /* Do nothing. */
13647 break;
13648 }
13649 }
13650
13651 if (ARM_IS_INTERWORK (sym))
13652 coffsymbol (symbol_get_bfdsym (sym))->native->u.syment.n_flags = 0xFF;
13653 }
13654 #endif
13655 #ifdef OBJ_ELF
13656 symbolS * sym;
13657 char bind;
13658
13659 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
13660 {
13661 if (ARM_IS_THUMB (sym))
13662 {
13663 elf_symbol_type * elf_sym;
13664
13665 elf_sym = elf_symbol (symbol_get_bfdsym (sym));
13666 bind = ELF_ST_BIND (elf_sym->internal_elf_sym.st_info);
13667
13668 if (! bfd_is_arm_mapping_symbol_name (elf_sym->symbol.name))
13669 {
13670 /* If it's a .thumb_func, declare it as so,
13671 otherwise tag label as .code 16. */
13672 if (THUMB_IS_FUNC (sym))
13673 elf_sym->internal_elf_sym.st_info =
13674 ELF_ST_INFO (bind, STT_ARM_TFUNC);
13675 else
13676 elf_sym->internal_elf_sym.st_info =
13677 ELF_ST_INFO (bind, STT_ARM_16BIT);
13678 }
13679 }
13680 }
13681 #endif
13682 }
13683
13684 int
13685 arm_data_in_code (void)
13686 {
13687 if (thumb_mode && ! strncmp (input_line_pointer + 1, "data:", 5))
13688 {
13689 *input_line_pointer = '/';
13690 input_line_pointer += 5;
13691 *input_line_pointer = 0;
13692 return 1;
13693 }
13694
13695 return 0;
13696 }
13697
13698 char *
13699 arm_canonicalize_symbol_name (char * name)
13700 {
13701 int len;
13702
13703 if (thumb_mode && (len = strlen (name)) > 5
13704 && streq (name + len - 5, "/data"))
13705 *(name + len - 5) = 0;
13706
13707 return name;
13708 }
13709
13710 #if defined OBJ_COFF || defined OBJ_ELF
13711 void
13712 arm_validate_fix (fixS * fixP)
13713 {
13714 /* If the destination of the branch is a defined symbol which does not have
13715 the THUMB_FUNC attribute, then we must be calling a function which has
13716 the (interfacearm) attribute. We look for the Thumb entry point to that
13717 function and change the branch to refer to that function instead. */
13718 if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23
13719 && fixP->fx_addsy != NULL
13720 && S_IS_DEFINED (fixP->fx_addsy)
13721 && ! THUMB_IS_FUNC (fixP->fx_addsy))
13722 {
13723 fixP->fx_addsy = find_real_start (fixP->fx_addsy);
13724 }
13725 }
13726 #endif
13727
13728 int
13729 arm_force_relocation (struct fix * fixp)
13730 {
13731 #if defined (OBJ_COFF) && defined (TE_PE)
13732 if (fixp->fx_r_type == BFD_RELOC_RVA)
13733 return 1;
13734 #endif
13735 #ifdef OBJ_ELF
13736 if (fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH
13737 || fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BLX
13738 || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX
13739 || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23)
13740 return 1;
13741 #endif
13742
13743 /* Resolve these relocations even if the symbol is extern or weak. */
13744 if (fixp->fx_r_type == BFD_RELOC_ARM_IMMEDIATE
13745 || fixp->fx_r_type == BFD_RELOC_ARM_OFFSET_IMM
13746 || fixp->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE)
13747 return 0;
13748
13749 return generic_force_reloc (fixp);
13750 }
13751
13752 #ifdef OBJ_COFF
13753 /* This is a little hack to help the gas/arm/adrl.s test. It prevents
13754 local labels from being added to the output symbol table when they
13755 are used with the ADRL pseudo op. The ADRL relocation should always
13756 be resolved before the binbary is emitted, so it is safe to say that
13757 it is adjustable. */
13758
13759 bfd_boolean
13760 arm_fix_adjustable (fixS * fixP)
13761 {
13762 if (fixP->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE)
13763 return 1;
13764 return 0;
13765 }
13766 #endif
13767
13768 #ifdef OBJ_ELF
13769 /* Relocations against Thumb function names must be left unadjusted,
13770 so that the linker can use this information to correctly set the
13771 bottom bit of their addresses. The MIPS version of this function
13772 also prevents relocations that are mips-16 specific, but I do not
13773 know why it does this.
13774
13775 FIXME:
13776 There is one other problem that ought to be addressed here, but
13777 which currently is not: Taking the address of a label (rather
13778 than a function) and then later jumping to that address. Such
13779 addresses also ought to have their bottom bit set (assuming that
13780 they reside in Thumb code), but at the moment they will not. */
13781
13782 bfd_boolean
13783 arm_fix_adjustable (fixS * fixP)
13784 {
13785 if (fixP->fx_addsy == NULL)
13786 return 1;
13787
13788 if (THUMB_IS_FUNC (fixP->fx_addsy)
13789 && fixP->fx_subsy == NULL)
13790 return 0;
13791
13792 /* We need the symbol name for the VTABLE entries. */
13793 if ( fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
13794 || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
13795 return 0;
13796
13797 /* Don't allow symbols to be discarded on GOT related relocs. */
13798 if (fixP->fx_r_type == BFD_RELOC_ARM_PLT32
13799 || fixP->fx_r_type == BFD_RELOC_ARM_GOT32
13800 || fixP->fx_r_type == BFD_RELOC_ARM_GOTOFF
13801 || fixP->fx_r_type == BFD_RELOC_ARM_TLS_GD32
13802 || fixP->fx_r_type == BFD_RELOC_ARM_TLS_LE32
13803 || fixP->fx_r_type == BFD_RELOC_ARM_TLS_IE32
13804 || fixP->fx_r_type == BFD_RELOC_ARM_TLS_LDM32
13805 || fixP->fx_r_type == BFD_RELOC_ARM_TLS_LDO32
13806 || fixP->fx_r_type == BFD_RELOC_ARM_TARGET2)
13807 return 0;
13808
13809 return 1;
13810 }
13811
13812 const char *
13813 elf32_arm_target_format (void)
13814 {
13815 #ifdef TE_SYMBIAN
13816 return (target_big_endian
13817 ? "elf32-bigarm-symbian"
13818 : "elf32-littlearm-symbian");
13819 #elif defined (TE_VXWORKS)
13820 return (target_big_endian
13821 ? "elf32-bigarm-vxworks"
13822 : "elf32-littlearm-vxworks");
13823 #else
13824 if (target_big_endian)
13825 return "elf32-bigarm";
13826 else
13827 return "elf32-littlearm";
13828 #endif
13829 }
13830
13831 void
13832 armelf_frob_symbol (symbolS * symp,
13833 int * puntp)
13834 {
13835 elf_frob_symbol (symp, puntp);
13836 }
13837
13838 static void
13839 s_arm_elf_cons (int nbytes)
13840 {
13841 expressionS exp;
13842
13843 #ifdef md_flush_pending_output
13844 md_flush_pending_output ();
13845 #endif
13846
13847 if (is_it_end_of_statement ())
13848 {
13849 demand_empty_rest_of_line ();
13850 return;
13851 }
13852
13853 #ifdef md_cons_align
13854 md_cons_align (nbytes);
13855 #endif
13856
13857 mapping_state (MAP_DATA);
13858 do
13859 {
13860 bfd_reloc_code_real_type reloc;
13861 char *sym_start;
13862 int sym_len;
13863
13864 sym_start = input_line_pointer;
13865 expression (& exp);
13866 sym_len = input_line_pointer - sym_start;
13867
13868 if (exp.X_op == O_symbol
13869 && * input_line_pointer == '('
13870 && (reloc = arm_parse_reloc ()) != BFD_RELOC_UNUSED)
13871 {
13872 reloc_howto_type *howto = bfd_reloc_type_lookup (stdoutput, reloc);
13873 int size = bfd_get_reloc_size (howto);
13874
13875 if (size > nbytes)
13876 as_bad ("%s relocations do not fit in %d bytes",
13877 howto->name, nbytes);
13878 else
13879 {
13880 char *p;
13881 int offset = nbytes - size;
13882 char *saved_buf = alloca (sym_len), *saved_input;
13883
13884 /* We've parsed an expression stopping at O_symbol. But there
13885 may be more expression left now that we have parsed the
13886 relocation marker. Parse it again. */
13887 saved_input = input_line_pointer - sym_len;
13888 memcpy (saved_buf, saved_input, sym_len);
13889 memmove (saved_input, sym_start, sym_len);
13890 input_line_pointer = saved_input;
13891 expression (& exp);
13892 memcpy (saved_input, saved_buf, sym_len);
13893 assert (input_line_pointer >= saved_input + sym_len);
13894
13895 p = frag_more ((int) nbytes);
13896 fix_new_exp (frag_now, p - frag_now->fr_literal + offset, size,
13897 &exp, 0, reloc);
13898 }
13899 }
13900 else
13901 emit_expr (&exp, (unsigned int) nbytes);
13902 }
13903 while (*input_line_pointer++ == ',');
13904
13905 /* Put terminator back into stream. */
13906 input_line_pointer --;
13907 demand_empty_rest_of_line ();
13908 }
13909
13910
13911 /* Parse a .rel31 directive. */
13912
13913 static void
13914 s_arm_rel31 (int ignored ATTRIBUTE_UNUSED)
13915 {
13916 expressionS exp;
13917 char *p;
13918 valueT highbit;
13919
13920 SKIP_WHITESPACE ();
13921
13922 highbit = 0;
13923 if (*input_line_pointer == '1')
13924 highbit = 0x80000000;
13925 else if (*input_line_pointer != '0')
13926 as_bad (_("expected 0 or 1"));
13927
13928 input_line_pointer++;
13929 SKIP_WHITESPACE ();
13930 if (*input_line_pointer != ',')
13931 as_bad (_("missing comma"));
13932 input_line_pointer++;
13933
13934 #ifdef md_flush_pending_output
13935 md_flush_pending_output ();
13936 #endif
13937
13938 #ifdef md_cons_align
13939 md_cons_align (4);
13940 #endif
13941
13942 mapping_state (MAP_DATA);
13943
13944 expression (&exp);
13945
13946 p = frag_more (4);
13947 md_number_to_chars (p, highbit, 4);
13948 fix_new_arm (frag_now, p - frag_now->fr_literal, 4, &exp, 1,
13949 BFD_RELOC_ARM_PREL31);
13950
13951 demand_empty_rest_of_line ();
13952 }
13953 \f
13954 /* Code to deal with unwinding tables. */
13955
13956 static void add_unwind_adjustsp (offsetT);
13957
13958 /* Switch to section NAME and create section if necessary. It's
13959 rather ugly that we have to manipulate input_line_pointer but I
13960 don't see any other way to accomplish the same thing without
13961 changing obj-elf.c (which may be the Right Thing, in the end).
13962 Copied from tc-ia64.c. */
13963
13964 static void
13965 set_section (char *name)
13966 {
13967 char *saved_input_line_pointer;
13968
13969 saved_input_line_pointer = input_line_pointer;
13970 input_line_pointer = name;
13971 obj_elf_section (0);
13972 input_line_pointer = saved_input_line_pointer;
13973 }
13974
13975 /* Cenerate and deferred unwind frame offset. */
13976
13977 static void
13978 flush_pending_unwind (void)
13979 {
13980 offsetT offset;
13981
13982 offset = unwind.pending_offset;
13983 unwind.pending_offset = 0;
13984 if (offset != 0)
13985 add_unwind_adjustsp (offset);
13986 }
13987
13988 /* Add an opcode to this list for this function. Two-byte opcodes should
13989 be passed as op[0] << 8 | op[1]. The list of opcodes is built in reverse
13990 order. */
13991
13992 static void
13993 add_unwind_opcode (valueT op, int length)
13994 {
13995 /* Add any deferred stack adjustment. */
13996 if (unwind.pending_offset)
13997 flush_pending_unwind ();
13998
13999 unwind.sp_restored = 0;
14000
14001 if (unwind.opcode_count + length > unwind.opcode_alloc)
14002 {
14003 unwind.opcode_alloc += ARM_OPCODE_CHUNK_SIZE;
14004 if (unwind.opcodes)
14005 unwind.opcodes = xrealloc (unwind.opcodes,
14006 unwind.opcode_alloc);
14007 else
14008 unwind.opcodes = xmalloc (unwind.opcode_alloc);
14009 }
14010 while (length > 0)
14011 {
14012 length--;
14013 unwind.opcodes[unwind.opcode_count] = op & 0xff;
14014 op >>= 8;
14015 unwind.opcode_count++;
14016 }
14017 }
14018
14019 /* Add unwind opcodes to adjust the stack pointer. */
14020
14021 static void
14022 add_unwind_adjustsp (offsetT offset)
14023 {
14024 valueT op;
14025
14026 if (offset > 0x200)
14027 {
14028 /* We need at most 5 bytes to hold a 32-bit value in a uleb128. */
14029 char bytes[5];
14030 int n;
14031 valueT o;
14032
14033 /* Long form: 0xb2, uleb128. */
14034 /* This might not fit in a word so add the individual bytes,
14035 remembering the list is built in reverse order. */
14036 o = (valueT) ((offset - 0x204) >> 2);
14037 if (o == 0)
14038 add_unwind_opcode (0, 1);
14039
14040 /* Calculate the uleb128 encoding of the offset. */
14041 n = 0;
14042 while (o)
14043 {
14044 bytes[n] = o & 0x7f;
14045 o >>= 7;
14046 if (o)
14047 bytes[n] |= 0x80;
14048 n++;
14049 }
14050 /* Add the insn. */
14051 for (; n; n--)
14052 add_unwind_opcode (bytes[n - 1], 1);
14053 add_unwind_opcode (0xb2, 1);
14054 }
14055 else if (offset > 0x100)
14056 {
14057 /* Two short opcodes. */
14058 add_unwind_opcode (0x3f, 1);
14059 op = (offset - 0x104) >> 2;
14060 add_unwind_opcode (op, 1);
14061 }
14062 else if (offset > 0)
14063 {
14064 /* Short opcode. */
14065 op = (offset - 4) >> 2;
14066 add_unwind_opcode (op, 1);
14067 }
14068 else if (offset < 0)
14069 {
14070 offset = -offset;
14071 while (offset > 0x100)
14072 {
14073 add_unwind_opcode (0x7f, 1);
14074 offset -= 0x100;
14075 }
14076 op = ((offset - 4) >> 2) | 0x40;
14077 add_unwind_opcode (op, 1);
14078 }
14079 }
14080
14081 /* Finish the list of unwind opcodes for this function. */
14082 static void
14083 finish_unwind_opcodes (void)
14084 {
14085 valueT op;
14086
14087 if (unwind.fp_used)
14088 {
14089 /* Adjust sp as neccessary. */
14090 unwind.pending_offset += unwind.fp_offset - unwind.frame_size;
14091 flush_pending_unwind ();
14092
14093 /* After restoring sp from the frame pointer. */
14094 op = 0x90 | unwind.fp_reg;
14095 add_unwind_opcode (op, 1);
14096 }
14097 else
14098 flush_pending_unwind ();
14099 }
14100
14101
14102 /* Start an exception table entry. If idx is nonzero this is an index table
14103 entry. */
14104
14105 static void
14106 start_unwind_section (const segT text_seg, int idx)
14107 {
14108 const char * text_name;
14109 const char * prefix;
14110 const char * prefix_once;
14111 size_t prefix_len;
14112 size_t text_len;
14113 char * sec_name;
14114 size_t sec_name_len;
14115
14116 if (idx)
14117 {
14118 prefix = ELF_STRING_ARM_unwind;
14119 prefix_once = ELF_STRING_ARM_unwind_once;
14120 }
14121 else
14122 {
14123 prefix = ELF_STRING_ARM_unwind_info;
14124 prefix_once = ELF_STRING_ARM_unwind_info_once;
14125 }
14126
14127 text_name = segment_name (text_seg);
14128 if (streq (text_name, ".text"))
14129 text_name = "";
14130
14131 if (strncmp (text_name, ".gnu.linkonce.t.",
14132 strlen (".gnu.linkonce.t.")) == 0)
14133 {
14134 prefix = prefix_once;
14135 text_name += strlen (".gnu.linkonce.t.");
14136 }
14137
14138 prefix_len = strlen (prefix);
14139 text_len = strlen (text_name);
14140 sec_name_len = prefix_len + text_len;
14141 sec_name = alloca (sec_name_len + 1);
14142 memcpy (sec_name, prefix, prefix_len);
14143 memcpy (sec_name + prefix_len, text_name, text_len);
14144 sec_name[prefix_len + text_len] = '\0';
14145
14146 /* Handle COMDAT group. */
14147 if (prefix != prefix_once && (text_seg->flags & SEC_LINK_ONCE) != 0)
14148 {
14149 char *section;
14150 size_t len, group_name_len;
14151 const char *group_name = elf_group_name (text_seg);
14152
14153 if (group_name == NULL)
14154 {
14155 as_bad ("Group section `%s' has no group signature",
14156 segment_name (text_seg));
14157 ignore_rest_of_line ();
14158 return;
14159 }
14160 /* We have to construct a fake section directive. */
14161 group_name_len = strlen (group_name);
14162 if (idx)
14163 prefix_len = 13;
14164 else
14165 prefix_len = 16;
14166
14167 len = (sec_name_len
14168 + prefix_len /* ,"aG",%sectiontype, */
14169 + group_name_len /* ,group_name */
14170 + 7); /* ,comdat */
14171
14172 section = alloca (len + 1);
14173 memcpy (section, sec_name, sec_name_len);
14174 if (idx)
14175 memcpy (section + sec_name_len, ",\"aG\",%exidx,", 13);
14176 else
14177 memcpy (section + sec_name_len, ",\"aG\",%progbits,", 16);
14178 memcpy (section + sec_name_len + prefix_len, group_name, group_name_len);
14179 memcpy (section + len - 7, ",comdat", 7);
14180 section [len] = '\0';
14181 set_section (section);
14182 }
14183 else
14184 {
14185 set_section (sec_name);
14186 bfd_set_section_flags (stdoutput, now_seg,
14187 SEC_LOAD | SEC_ALLOC | SEC_READONLY);
14188 }
14189
14190 /* Set the setion link for index tables. */
14191 if (idx)
14192 elf_linked_to_section (now_seg) = text_seg;
14193 }
14194
14195
14196 /* Start an unwind table entry. HAVE_DATA is nonzero if we have additional
14197 personality routine data. Returns zero, or the index table value for
14198 and inline entry. */
14199
14200 static valueT
14201 create_unwind_entry (int have_data)
14202 {
14203 int size;
14204 addressT where;
14205 char *ptr;
14206 /* The current word of data. */
14207 valueT data;
14208 /* The number of bytes left in this word. */
14209 int n;
14210
14211 finish_unwind_opcodes ();
14212
14213 /* Remember the current text section. */
14214 unwind.saved_seg = now_seg;
14215 unwind.saved_subseg = now_subseg;
14216
14217 start_unwind_section (now_seg, 0);
14218
14219 if (unwind.personality_routine == NULL)
14220 {
14221 if (unwind.personality_index == -2)
14222 {
14223 if (have_data)
14224 as_bad (_("handerdata in cantunwind frame"));
14225 return 1; /* EXIDX_CANTUNWIND. */
14226 }
14227
14228 /* Use a default personality routine if none is specified. */
14229 if (unwind.personality_index == -1)
14230 {
14231 if (unwind.opcode_count > 3)
14232 unwind.personality_index = 1;
14233 else
14234 unwind.personality_index = 0;
14235 }
14236
14237 /* Space for the personality routine entry. */
14238 if (unwind.personality_index == 0)
14239 {
14240 if (unwind.opcode_count > 3)
14241 as_bad (_("too many unwind opcodes for personality routine 0"));
14242
14243 if (!have_data)
14244 {
14245 /* All the data is inline in the index table. */
14246 data = 0x80;
14247 n = 3;
14248 while (unwind.opcode_count > 0)
14249 {
14250 unwind.opcode_count--;
14251 data = (data << 8) | unwind.opcodes[unwind.opcode_count];
14252 n--;
14253 }
14254
14255 /* Pad with "finish" opcodes. */
14256 while (n--)
14257 data = (data << 8) | 0xb0;
14258
14259 return data;
14260 }
14261 size = 0;
14262 }
14263 else
14264 /* We get two opcodes "free" in the first word. */
14265 size = unwind.opcode_count - 2;
14266 }
14267 else
14268 /* An extra byte is required for the opcode count. */
14269 size = unwind.opcode_count + 1;
14270
14271 size = (size + 3) >> 2;
14272 if (size > 0xff)
14273 as_bad (_("too many unwind opcodes"));
14274
14275 frag_align (2, 0, 0);
14276 record_alignment (now_seg, 2);
14277 unwind.table_entry = expr_build_dot ();
14278
14279 /* Allocate the table entry. */
14280 ptr = frag_more ((size << 2) + 4);
14281 where = frag_now_fix () - ((size << 2) + 4);
14282
14283 switch (unwind.personality_index)
14284 {
14285 case -1:
14286 /* ??? Should this be a PLT generating relocation? */
14287 /* Custom personality routine. */
14288 fix_new (frag_now, where, 4, unwind.personality_routine, 0, 1,
14289 BFD_RELOC_ARM_PREL31);
14290
14291 where += 4;
14292 ptr += 4;
14293
14294 /* Set the first byte to the number of additional words. */
14295 data = size - 1;
14296 n = 3;
14297 break;
14298
14299 /* ABI defined personality routines. */
14300 case 0:
14301 /* Three opcodes bytes are packed into the first word. */
14302 data = 0x80;
14303 n = 3;
14304 break;
14305
14306 case 1:
14307 case 2:
14308 /* The size and first two opcode bytes go in the first word. */
14309 data = ((0x80 + unwind.personality_index) << 8) | size;
14310 n = 2;
14311 break;
14312
14313 default:
14314 /* Should never happen. */
14315 abort ();
14316 }
14317
14318 /* Pack the opcodes into words (MSB first), reversing the list at the same
14319 time. */
14320 while (unwind.opcode_count > 0)
14321 {
14322 if (n == 0)
14323 {
14324 md_number_to_chars (ptr, data, 4);
14325 ptr += 4;
14326 n = 4;
14327 data = 0;
14328 }
14329 unwind.opcode_count--;
14330 n--;
14331 data = (data << 8) | unwind.opcodes[unwind.opcode_count];
14332 }
14333
14334 /* Finish off the last word. */
14335 if (n < 4)
14336 {
14337 /* Pad with "finish" opcodes. */
14338 while (n--)
14339 data = (data << 8) | 0xb0;
14340
14341 md_number_to_chars (ptr, data, 4);
14342 }
14343
14344 if (!have_data)
14345 {
14346 /* Add an empty descriptor if there is no user-specified data. */
14347 ptr = frag_more (4);
14348 md_number_to_chars (ptr, 0, 4);
14349 }
14350
14351 return 0;
14352 }
14353
14354
14355 /* Parse an unwind_fnstart directive. Simply records the current location. */
14356
14357 static void
14358 s_arm_unwind_fnstart (int ignored ATTRIBUTE_UNUSED)
14359 {
14360 demand_empty_rest_of_line ();
14361 /* Mark the start of the function. */
14362 unwind.proc_start = expr_build_dot ();
14363
14364 /* Reset the rest of the unwind info. */
14365 unwind.opcode_count = 0;
14366 unwind.table_entry = NULL;
14367 unwind.personality_routine = NULL;
14368 unwind.personality_index = -1;
14369 unwind.frame_size = 0;
14370 unwind.fp_offset = 0;
14371 unwind.fp_reg = 13;
14372 unwind.fp_used = 0;
14373 unwind.sp_restored = 0;
14374 }
14375
14376
14377 /* Parse a handlerdata directive. Creates the exception handling table entry
14378 for the function. */
14379
14380 static void
14381 s_arm_unwind_handlerdata (int ignored ATTRIBUTE_UNUSED)
14382 {
14383 demand_empty_rest_of_line ();
14384 if (unwind.table_entry)
14385 as_bad (_("dupicate .handlerdata directive"));
14386
14387 create_unwind_entry (1);
14388 }
14389
14390 /* Parse an unwind_fnend directive. Generates the index table entry. */
14391
14392 static void
14393 s_arm_unwind_fnend (int ignored ATTRIBUTE_UNUSED)
14394 {
14395 long where;
14396 char *ptr;
14397 valueT val;
14398
14399 demand_empty_rest_of_line ();
14400
14401 /* Add eh table entry. */
14402 if (unwind.table_entry == NULL)
14403 val = create_unwind_entry (0);
14404 else
14405 val = 0;
14406
14407 /* Add index table entry. This is two words. */
14408 start_unwind_section (unwind.saved_seg, 1);
14409 frag_align (2, 0, 0);
14410 record_alignment (now_seg, 2);
14411
14412 ptr = frag_more (8);
14413 where = frag_now_fix () - 8;
14414
14415 /* Self relative offset of the function start. */
14416 fix_new (frag_now, where, 4, unwind.proc_start, 0, 1,
14417 BFD_RELOC_ARM_PREL31);
14418
14419 /* Indicate dependency on EHABI-defined personality routines to the
14420 linker, if it hasn't been done already. */
14421 if (unwind.personality_index >= 0 && unwind.personality_index < 3)
14422 {
14423 char *name[] = { "__aeabi_unwind_cpp_pr0",
14424 "__aeabi_unwind_cpp_pr1",
14425 "__aeabi_unwind_cpp_pr2" };
14426 if (!(marked_pr_dependency & (1 << unwind.personality_index)))
14427 {
14428 symbolS *pr = symbol_find_or_make (name[unwind.personality_index]);
14429 fix_new (frag_now, where, 0, pr, 0, 1, BFD_RELOC_NONE);
14430 marked_pr_dependency |= 1 << unwind.personality_index;
14431 seg_info (now_seg)->tc_segment_info_data.marked_pr_dependency
14432 = marked_pr_dependency;
14433 }
14434 }
14435
14436 if (val)
14437 /* Inline exception table entry. */
14438 md_number_to_chars (ptr + 4, val, 4);
14439 else
14440 /* Self relative offset of the table entry. */
14441 fix_new (frag_now, where + 4, 4, unwind.table_entry, 0, 1,
14442 BFD_RELOC_ARM_PREL31);
14443
14444 /* Restore the original section. */
14445 subseg_set (unwind.saved_seg, unwind.saved_subseg);
14446 }
14447
14448
14449 /* Parse an unwind_cantunwind directive. */
14450
14451 static void
14452 s_arm_unwind_cantunwind (int ignored ATTRIBUTE_UNUSED)
14453 {
14454 demand_empty_rest_of_line ();
14455 if (unwind.personality_routine || unwind.personality_index != -1)
14456 as_bad (_("personality routine specified for cantunwind frame"));
14457
14458 unwind.personality_index = -2;
14459 }
14460
14461
14462 /* Parse a personalityindex directive. */
14463
14464 static void
14465 s_arm_unwind_personalityindex (int ignored ATTRIBUTE_UNUSED)
14466 {
14467 expressionS exp;
14468
14469 if (unwind.personality_routine || unwind.personality_index != -1)
14470 as_bad (_("duplicate .personalityindex directive"));
14471
14472 SKIP_WHITESPACE ();
14473
14474 expression (&exp);
14475
14476 if (exp.X_op != O_constant
14477 || exp.X_add_number < 0 || exp.X_add_number > 15)
14478 {
14479 as_bad (_("bad personality routine number"));
14480 ignore_rest_of_line ();
14481 return;
14482 }
14483
14484 unwind.personality_index = exp.X_add_number;
14485
14486 demand_empty_rest_of_line ();
14487 }
14488
14489
14490 /* Parse a personality directive. */
14491
14492 static void
14493 s_arm_unwind_personality (int ignored ATTRIBUTE_UNUSED)
14494 {
14495 char *name, *p, c;
14496
14497 if (unwind.personality_routine || unwind.personality_index != -1)
14498 as_bad (_("duplicate .personality directive"));
14499
14500 SKIP_WHITESPACE ();
14501 name = input_line_pointer;
14502 c = get_symbol_end ();
14503 p = input_line_pointer;
14504 unwind.personality_routine = symbol_find_or_make (name);
14505 *p = c;
14506 SKIP_WHITESPACE ();
14507 demand_empty_rest_of_line ();
14508 }
14509
14510
14511 /* Parse a directive saving core registers. */
14512
14513 static void
14514 s_arm_unwind_save_core (void)
14515 {
14516 valueT op;
14517 long range;
14518 int n;
14519
14520 SKIP_WHITESPACE ();
14521 range = reg_list (&input_line_pointer);
14522 if (range == FAIL)
14523 {
14524 as_bad (_("expected register list"));
14525 ignore_rest_of_line ();
14526 return;
14527 }
14528
14529 demand_empty_rest_of_line ();
14530
14531 /* Turn .unwind_movsp ip followed by .unwind_save {..., ip, ...}
14532 into .unwind_save {..., sp...}. We aren't bothered about the value of
14533 ip because it is clobbered by calls. */
14534 if (unwind.sp_restored && unwind.fp_reg == 12
14535 && (range & 0x3000) == 0x1000)
14536 {
14537 unwind.opcode_count--;
14538 unwind.sp_restored = 0;
14539 range = (range | 0x2000) & ~0x1000;
14540 unwind.pending_offset = 0;
14541 }
14542
14543 /* See if we can use the short opcodes. These pop a block of upto 8
14544 registers starting with r4, plus maybe r14. */
14545 for (n = 0; n < 8; n++)
14546 {
14547 /* Break at the first non-saved register. */
14548 if ((range & (1 << (n + 4))) == 0)
14549 break;
14550 }
14551 /* See if there are any other bits set. */
14552 if (n == 0 || (range & (0xfff0 << n) & 0xbff0) != 0)
14553 {
14554 /* Use the long form. */
14555 op = 0x8000 | ((range >> 4) & 0xfff);
14556 add_unwind_opcode (op, 2);
14557 }
14558 else
14559 {
14560 /* Use the short form. */
14561 if (range & 0x4000)
14562 op = 0xa8; /* Pop r14. */
14563 else
14564 op = 0xa0; /* Do not pop r14. */
14565 op |= (n - 1);
14566 add_unwind_opcode (op, 1);
14567 }
14568
14569 /* Pop r0-r3. */
14570 if (range & 0xf)
14571 {
14572 op = 0xb100 | (range & 0xf);
14573 add_unwind_opcode (op, 2);
14574 }
14575
14576 /* Record the number of bytes pushed. */
14577 for (n = 0; n < 16; n++)
14578 {
14579 if (range & (1 << n))
14580 unwind.frame_size += 4;
14581 }
14582 }
14583
14584
14585 /* Parse a directive saving FPA registers. */
14586
14587 static void
14588 s_arm_unwind_save_fpa (int reg)
14589 {
14590 expressionS exp;
14591 int num_regs;
14592 valueT op;
14593
14594 /* Get Number of registers to transfer. */
14595 if (skip_past_comma (&input_line_pointer) != FAIL)
14596 expression (&exp);
14597 else
14598 exp.X_op = O_illegal;
14599
14600 if (exp.X_op != O_constant)
14601 {
14602 as_bad (_("expected , <constant>"));
14603 ignore_rest_of_line ();
14604 return;
14605 }
14606
14607 num_regs = exp.X_add_number;
14608
14609 if (num_regs < 1 || num_regs > 4)
14610 {
14611 as_bad (_("number of registers must be in the range [1:4]"));
14612 ignore_rest_of_line ();
14613 return;
14614 }
14615
14616 demand_empty_rest_of_line ();
14617
14618 if (reg == 4)
14619 {
14620 /* Short form. */
14621 op = 0xb4 | (num_regs - 1);
14622 add_unwind_opcode (op, 1);
14623 }
14624 else
14625 {
14626 /* Long form. */
14627 op = 0xc800 | (reg << 4) | (num_regs - 1);
14628 add_unwind_opcode (op, 2);
14629 }
14630 unwind.frame_size += num_regs * 12;
14631 }
14632
14633
14634 /* Parse a directive saving VFP registers. */
14635
14636 static void
14637 s_arm_unwind_save_vfp (void)
14638 {
14639 int count;
14640 int reg;
14641 valueT op;
14642
14643 count = vfp_parse_reg_list (&input_line_pointer, &reg, 1);
14644 if (count == FAIL)
14645 {
14646 as_bad (_("expected register list"));
14647 ignore_rest_of_line ();
14648 return;
14649 }
14650
14651 demand_empty_rest_of_line ();
14652
14653 if (reg == 8)
14654 {
14655 /* Short form. */
14656 op = 0xb8 | (count - 1);
14657 add_unwind_opcode (op, 1);
14658 }
14659 else
14660 {
14661 /* Long form. */
14662 op = 0xb300 | (reg << 4) | (count - 1);
14663 add_unwind_opcode (op, 2);
14664 }
14665 unwind.frame_size += count * 8 + 4;
14666 }
14667
14668
14669 /* Parse a directive saving iWMMXt registers. */
14670
14671 static void
14672 s_arm_unwind_save_wmmx (void)
14673 {
14674 int reg;
14675 int hi_reg;
14676 int i;
14677 unsigned wcg_mask;
14678 unsigned wr_mask;
14679 valueT op;
14680
14681 if (*input_line_pointer == '{')
14682 input_line_pointer++;
14683
14684 wcg_mask = 0;
14685 wr_mask = 0;
14686 do
14687 {
14688 reg = arm_reg_parse (&input_line_pointer,
14689 all_reg_maps[REG_TYPE_IWMMXT].htab);
14690
14691 if (wr_register (reg))
14692 {
14693 i = reg & ~WR_PREFIX;
14694 if (wr_mask >> i)
14695 as_tsktsk (_("register list not in ascending order"));
14696 wr_mask |= 1 << i;
14697 }
14698 else if (wcg_register (reg))
14699 {
14700 i = (reg & ~WC_PREFIX) - 8;
14701 if (wcg_mask >> i)
14702 as_tsktsk (_("register list not in ascending order"));
14703 wcg_mask |= 1 << i;
14704 }
14705 else
14706 {
14707 as_bad (_("expected wr or wcgr"));
14708 goto error;
14709 }
14710
14711 SKIP_WHITESPACE ();
14712 if (*input_line_pointer == '-')
14713 {
14714 hi_reg = arm_reg_parse (&input_line_pointer,
14715 all_reg_maps[REG_TYPE_IWMMXT].htab);
14716 if (wr_register (reg) && wr_register (hi_reg))
14717 {
14718 for (; reg < hi_reg; reg++)
14719 wr_mask |= 1 << (reg & ~WR_PREFIX);
14720 }
14721 else if (wcg_register (reg) && wcg_register (hi_reg))
14722 {
14723 for (; reg < hi_reg; reg++)
14724 wcg_mask |= 1 << ((reg & ~WC_PREFIX) - 8);
14725 }
14726 else
14727 {
14728 as_bad (_("bad register range"));
14729 goto error;
14730 }
14731 }
14732 }
14733 while (skip_past_comma (&input_line_pointer) != FAIL);
14734
14735 SKIP_WHITESPACE ();
14736 if (*input_line_pointer == '}')
14737 input_line_pointer++;
14738
14739 demand_empty_rest_of_line ();
14740
14741 if (wr_mask && wcg_mask)
14742 {
14743 as_bad (_("inconsistent register types"));
14744 goto error;
14745 }
14746
14747 /* Generate any deferred opcodes becuuse we're going to be looking at
14748 the list. */
14749 flush_pending_unwind ();
14750
14751 if (wcg_mask)
14752 {
14753 for (i = 0; i < 16; i++)
14754 {
14755 if (wcg_mask & (1 << i))
14756 unwind.frame_size += 4;
14757 }
14758 op = 0xc700 | wcg_mask;
14759 add_unwind_opcode (op, 2);
14760 }
14761 else
14762 {
14763 for (i = 0; i < 16; i++)
14764 {
14765 if (wr_mask & (1 << i))
14766 unwind.frame_size += 8;
14767 }
14768 /* Attempt to combine with a previous opcode. We do this because gcc
14769 likes to output separate unwind directives for a single block of
14770 registers. */
14771 if (unwind.opcode_count > 0)
14772 {
14773 i = unwind.opcodes[unwind.opcode_count - 1];
14774 if ((i & 0xf8) == 0xc0)
14775 {
14776 i &= 7;
14777 /* Only merge if the blocks are contiguous. */
14778 if (i < 6)
14779 {
14780 if ((wr_mask & 0xfe00) == (1 << 9))
14781 {
14782 wr_mask |= ((1 << (i + 11)) - 1) & 0xfc00;
14783 unwind.opcode_count--;
14784 }
14785 }
14786 else if (i == 6 && unwind.opcode_count >= 2)
14787 {
14788 i = unwind.opcodes[unwind.opcode_count - 2];
14789 reg = i >> 4;
14790 i &= 0xf;
14791
14792 op = 0xffff << (reg - 1);
14793 if (reg > 0
14794 || ((wr_mask & op) == (1u << (reg - 1))))
14795 {
14796 op = (1 << (reg + i + 1)) - 1;
14797 op &= ~((1 << reg) - 1);
14798 wr_mask |= op;
14799 unwind.opcode_count -= 2;
14800 }
14801 }
14802 }
14803 }
14804
14805 hi_reg = 15;
14806 /* We want to generate opcodes in the order the registers have been
14807 saved, ie. descending order. */
14808 for (reg = 15; reg >= -1; reg--)
14809 {
14810 /* Save registers in blocks. */
14811 if (reg < 0
14812 || !(wr_mask & (1 << reg)))
14813 {
14814 /* We found an unsaved reg. Generate opcodes to save the
14815 preceeding block. */
14816 if (reg != hi_reg)
14817 {
14818 if (reg == 9)
14819 {
14820 /* Short form. */
14821 op = 0xc0 | (hi_reg - 10);
14822 add_unwind_opcode (op, 1);
14823 }
14824 else
14825 {
14826 /* Long form. */
14827 op = 0xc600 | ((reg + 1) << 4) | ((hi_reg - reg) - 1);
14828 add_unwind_opcode (op, 2);
14829 }
14830 }
14831 hi_reg = reg - 1;
14832 }
14833 }
14834 }
14835 return;
14836 error:
14837 ignore_rest_of_line ();
14838 }
14839
14840
14841 /* Parse an unwind_save directive. */
14842
14843 static void
14844 s_arm_unwind_save (int ignored ATTRIBUTE_UNUSED)
14845 {
14846 char *saved_ptr;
14847 int reg;
14848
14849 /* Figure out what sort of save we have. */
14850 SKIP_WHITESPACE ();
14851 saved_ptr = input_line_pointer;
14852
14853 reg = arm_reg_parse (&input_line_pointer, all_reg_maps[REG_TYPE_FN].htab);
14854 if (reg != FAIL)
14855 {
14856 s_arm_unwind_save_fpa (reg);
14857 return;
14858 }
14859
14860 if (*input_line_pointer == '{')
14861 input_line_pointer++;
14862
14863 SKIP_WHITESPACE ();
14864
14865 reg = arm_reg_parse (&input_line_pointer, all_reg_maps[REG_TYPE_RN].htab);
14866 if (reg != FAIL)
14867 {
14868 input_line_pointer = saved_ptr;
14869 s_arm_unwind_save_core ();
14870 return;
14871 }
14872
14873 reg = arm_reg_parse (&input_line_pointer, all_reg_maps[REG_TYPE_DN].htab);
14874 if (reg != FAIL)
14875 {
14876 input_line_pointer = saved_ptr;
14877 s_arm_unwind_save_vfp ();
14878 return;
14879 }
14880
14881 reg = arm_reg_parse (&input_line_pointer,
14882 all_reg_maps[REG_TYPE_IWMMXT].htab);
14883 if (reg != FAIL)
14884 {
14885 input_line_pointer = saved_ptr;
14886 s_arm_unwind_save_wmmx ();
14887 return;
14888 }
14889
14890 /* TODO: Maverick registers. */
14891 as_bad (_("unrecognised register"));
14892 }
14893
14894
14895 /* Parse an unwind_movsp directive. */
14896
14897 static void
14898 s_arm_unwind_movsp (int ignored ATTRIBUTE_UNUSED)
14899 {
14900 int reg;
14901 valueT op;
14902
14903 SKIP_WHITESPACE ();
14904 reg = reg_required_here (&input_line_pointer, -1);
14905 if (reg == FAIL)
14906 {
14907 as_bad (_("ARM register expected"));
14908 ignore_rest_of_line ();
14909 return;
14910 }
14911
14912 if (reg == 13 || reg == 15)
14913 {
14914 as_bad (_("r%d not permitted in .unwind_movsp directive"), reg);
14915 ignore_rest_of_line ();
14916 return;
14917 }
14918
14919 if (unwind.fp_reg != 13)
14920 as_bad (_("unexpected .unwind_movsp directive"));
14921
14922 /* Generate opcode to restore the value. */
14923 op = 0x90 | reg;
14924 add_unwind_opcode (op, 1);
14925
14926 /* Record the information for later. */
14927 unwind.fp_reg = reg;
14928 unwind.fp_offset = unwind.frame_size;
14929 unwind.sp_restored = 1;
14930 demand_empty_rest_of_line ();
14931 }
14932
14933
14934 /* Parse #<number>. */
14935
14936 static int
14937 require_hashconst (int * val)
14938 {
14939 expressionS exp;
14940
14941 SKIP_WHITESPACE ();
14942 if (*input_line_pointer == '#')
14943 {
14944 input_line_pointer++;
14945 expression (&exp);
14946 }
14947 else
14948 exp.X_op = O_illegal;
14949
14950 if (exp.X_op != O_constant)
14951 {
14952 as_bad (_("expected #constant"));
14953 ignore_rest_of_line ();
14954 return FAIL;
14955 }
14956 *val = exp.X_add_number;
14957 return SUCCESS;
14958 }
14959
14960 /* Parse an unwind_pad directive. */
14961
14962 static void
14963 s_arm_unwind_pad (int ignored ATTRIBUTE_UNUSED)
14964 {
14965 int offset;
14966
14967 if (require_hashconst (&offset) == FAIL)
14968 return;
14969
14970 if (offset & 3)
14971 {
14972 as_bad (_("stack increment must be multiple of 4"));
14973 ignore_rest_of_line ();
14974 return;
14975 }
14976
14977 /* Don't generate any opcodes, just record the details for later. */
14978 unwind.frame_size += offset;
14979 unwind.pending_offset += offset;
14980
14981 demand_empty_rest_of_line ();
14982 }
14983
14984 /* Parse an unwind_setfp directive. */
14985
14986 static void
14987 s_arm_unwind_setfp (int ignored ATTRIBUTE_UNUSED)
14988 {
14989 int sp_reg;
14990 int fp_reg;
14991 int offset;
14992
14993 fp_reg = reg_required_here (&input_line_pointer, -1);
14994 if (skip_past_comma (&input_line_pointer) == FAIL)
14995 sp_reg = FAIL;
14996 else
14997 sp_reg = reg_required_here (&input_line_pointer, -1);
14998
14999 if (fp_reg == FAIL || sp_reg == FAIL)
15000 {
15001 as_bad (_("expected <reg>, <reg>"));
15002 ignore_rest_of_line ();
15003 return;
15004 }
15005
15006 /* Optonal constant. */
15007 if (skip_past_comma (&input_line_pointer) != FAIL)
15008 {
15009 if (require_hashconst (&offset) == FAIL)
15010 return;
15011 }
15012 else
15013 offset = 0;
15014
15015 demand_empty_rest_of_line ();
15016
15017 if (sp_reg != 13 && sp_reg != unwind.fp_reg)
15018 {
15019 as_bad (_("register must be either sp or set by a previous"
15020 "unwind_movsp directive"));
15021 return;
15022 }
15023
15024 /* Don't generate any opcodes, just record the information for later. */
15025 unwind.fp_reg = fp_reg;
15026 unwind.fp_used = 1;
15027 if (sp_reg == 13)
15028 unwind.fp_offset = unwind.frame_size - offset;
15029 else
15030 unwind.fp_offset -= offset;
15031 }
15032
15033 /* Parse an unwind_raw directive. */
15034
15035 static void
15036 s_arm_unwind_raw (int ignored ATTRIBUTE_UNUSED)
15037 {
15038 expressionS exp;
15039 /* This is an arbitary limit. */
15040 unsigned char op[16];
15041 int count;
15042
15043 SKIP_WHITESPACE ();
15044 expression (&exp);
15045 if (exp.X_op == O_constant
15046 && skip_past_comma (&input_line_pointer) != FAIL)
15047 {
15048 unwind.frame_size += exp.X_add_number;
15049 expression (&exp);
15050 }
15051 else
15052 exp.X_op = O_illegal;
15053
15054 if (exp.X_op != O_constant)
15055 {
15056 as_bad (_("expected <offset>, <opcode>"));
15057 ignore_rest_of_line ();
15058 return;
15059 }
15060
15061 count = 0;
15062
15063 /* Parse the opcode. */
15064 for (;;)
15065 {
15066 if (count >= 16)
15067 {
15068 as_bad (_("unwind opcode too long"));
15069 ignore_rest_of_line ();
15070 }
15071 if (exp.X_op != O_constant || exp.X_add_number & ~0xff)
15072 {
15073 as_bad (_("invalid unwind opcode"));
15074 ignore_rest_of_line ();
15075 return;
15076 }
15077 op[count++] = exp.X_add_number;
15078
15079 /* Parse the next byte. */
15080 if (skip_past_comma (&input_line_pointer) == FAIL)
15081 break;
15082
15083 expression (&exp);
15084 }
15085
15086 /* Add the opcode bytes in reverse order. */
15087 while (count--)
15088 add_unwind_opcode (op[count], 1);
15089
15090 demand_empty_rest_of_line ();
15091 }
15092
15093 #endif /* OBJ_ELF */
15094
15095 /* This is called from HANDLE_ALIGN in write.c. Fill in the contents
15096 of an rs_align_code fragment. */
15097
15098 void
15099 arm_handle_align (fragS * fragP)
15100 {
15101 static char const arm_noop[4] = { 0x00, 0x00, 0xa0, 0xe1 };
15102 static char const thumb_noop[2] = { 0xc0, 0x46 };
15103 static char const arm_bigend_noop[4] = { 0xe1, 0xa0, 0x00, 0x00 };
15104 static char const thumb_bigend_noop[2] = { 0x46, 0xc0 };
15105
15106 int bytes, fix, noop_size;
15107 char * p;
15108 const char * noop;
15109
15110 if (fragP->fr_type != rs_align_code)
15111 return;
15112
15113 bytes = fragP->fr_next->fr_address - fragP->fr_address - fragP->fr_fix;
15114 p = fragP->fr_literal + fragP->fr_fix;
15115 fix = 0;
15116
15117 if (bytes > MAX_MEM_FOR_RS_ALIGN_CODE)
15118 bytes &= MAX_MEM_FOR_RS_ALIGN_CODE;
15119
15120 if (fragP->tc_frag_data)
15121 {
15122 if (target_big_endian)
15123 noop = thumb_bigend_noop;
15124 else
15125 noop = thumb_noop;
15126 noop_size = sizeof (thumb_noop);
15127 }
15128 else
15129 {
15130 if (target_big_endian)
15131 noop = arm_bigend_noop;
15132 else
15133 noop = arm_noop;
15134 noop_size = sizeof (arm_noop);
15135 }
15136
15137 if (bytes & (noop_size - 1))
15138 {
15139 fix = bytes & (noop_size - 1);
15140 memset (p, 0, fix);
15141 p += fix;
15142 bytes -= fix;
15143 }
15144
15145 while (bytes >= noop_size)
15146 {
15147 memcpy (p, noop, noop_size);
15148 p += noop_size;
15149 bytes -= noop_size;
15150 fix += noop_size;
15151 }
15152
15153 fragP->fr_fix += fix;
15154 fragP->fr_var = noop_size;
15155 }
15156
15157 /* Called from md_do_align. Used to create an alignment
15158 frag in a code section. */
15159
15160 void
15161 arm_frag_align_code (int n, int max)
15162 {
15163 char * p;
15164
15165 /* We assume that there will never be a requirement
15166 to support alignments greater than 32 bytes. */
15167 if (max > MAX_MEM_FOR_RS_ALIGN_CODE)
15168 as_fatal (_("alignments greater than 32 bytes not supported in .text sections."));
15169
15170 p = frag_var (rs_align_code,
15171 MAX_MEM_FOR_RS_ALIGN_CODE,
15172 1,
15173 (relax_substateT) max,
15174 (symbolS *) NULL,
15175 (offsetT) n,
15176 (char *) NULL);
15177 *p = 0;
15178 }
15179
15180 /* Perform target specific initialisation of a frag. */
15181
15182 void
15183 arm_init_frag (fragS * fragP)
15184 {
15185 /* Record whether this frag is in an ARM or a THUMB area. */
15186 fragP->tc_frag_data = thumb_mode;
15187 }
15188
15189 #ifdef OBJ_ELF
15190
15191 /* Convert REGNAME to a DWARF-2 register number. */
15192
15193 int
15194 tc_arm_regname_to_dw2regnum (const char *regname)
15195 {
15196 unsigned int i;
15197
15198 for (i = 0; rn_table[i].name; i++)
15199 if (streq (regname, rn_table[i].name))
15200 return rn_table[i].number;
15201
15202 return -1;
15203 }
15204
15205 /* Initialize the DWARF-2 unwind information for this procedure. */
15206
15207 void
15208 tc_arm_frame_initial_instructions (void)
15209 {
15210 cfi_add_CFA_def_cfa (REG_SP, 0);
15211 }
15212 #endif
15213
15214 /* This table describes all the machine specific pseudo-ops the assembler
15215 has to support. The fields are:
15216 pseudo-op name without dot
15217 function to call to execute this pseudo-op
15218 Integer arg to pass to the function. */
15219
15220 const pseudo_typeS md_pseudo_table[] =
15221 {
15222 /* Never called because '.req' does not start a line. */
15223 { "req", s_req, 0 },
15224 { "unreq", s_unreq, 0 },
15225 { "bss", s_bss, 0 },
15226 { "align", s_align, 0 },
15227 { "arm", s_arm, 0 },
15228 { "thumb", s_thumb, 0 },
15229 { "code", s_code, 0 },
15230 { "force_thumb", s_force_thumb, 0 },
15231 { "thumb_func", s_thumb_func, 0 },
15232 { "thumb_set", s_thumb_set, 0 },
15233 { "even", s_even, 0 },
15234 { "ltorg", s_ltorg, 0 },
15235 { "pool", s_ltorg, 0 },
15236 #ifdef OBJ_ELF
15237 { "word", s_arm_elf_cons, 4 },
15238 { "long", s_arm_elf_cons, 4 },
15239 { "rel31", s_arm_rel31, 0 },
15240 { "fnstart", s_arm_unwind_fnstart, 0 },
15241 { "fnend", s_arm_unwind_fnend, 0 },
15242 { "cantunwind", s_arm_unwind_cantunwind, 0 },
15243 { "personality", s_arm_unwind_personality, 0 },
15244 { "personalityindex", s_arm_unwind_personalityindex, 0 },
15245 { "handlerdata", s_arm_unwind_handlerdata, 0 },
15246 { "save", s_arm_unwind_save, 0 },
15247 { "movsp", s_arm_unwind_movsp, 0 },
15248 { "pad", s_arm_unwind_pad, 0 },
15249 { "setfp", s_arm_unwind_setfp, 0 },
15250 { "unwind_raw", s_arm_unwind_raw, 0 },
15251 #else
15252 { "word", cons, 4},
15253 #endif
15254 { "extend", float_cons, 'x' },
15255 { "ldouble", float_cons, 'x' },
15256 { "packed", float_cons, 'p' },
15257 { 0, 0, 0 }
15258 };