752cd3c04a62f0bdd0c4d13348085c0172466493
[deliverable/binutils-gdb.git] / gas / config / tc-arm.c
1 /* tc-arm.c -- Assemble for the ARM
2 Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
3 Free Software Foundation, Inc.
4 Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org)
5 Modified by David Taylor (dtaylor@armltd.co.uk)
6 Cirrus coprocessor mods by Aldy Hernandez (aldyh@redhat.com)
7 Cirrus coprocessor fixes by Petko Manolov (petkan@nucleusys.com)
8 Cirrus coprocessor fixes by Vladimir Ivanov (vladitx@nucleusys.com)
9
10 This file is part of GAS, the GNU Assembler.
11
12 GAS is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2, or (at your option)
15 any later version.
16
17 GAS is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
21
22 You should have received a copy of the GNU General Public License
23 along with GAS; see the file COPYING. If not, write to the Free
24 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
25 02111-1307, USA. */
26
27 #include <string.h>
28 #define NO_RELOC 0
29 #include "as.h"
30 #include "safe-ctype.h"
31
32 /* Need TARGET_CPU. */
33 #include "config.h"
34 #include "subsegs.h"
35 #include "obstack.h"
36 #include "symbols.h"
37 #include "listing.h"
38
39 #include "opcode/arm.h"
40
41 #ifdef OBJ_ELF
42 #include "elf/arm.h"
43 #include "dwarf2dbg.h"
44 #endif
45
46 /* XXX Set this to 1 after the next binutils release */
47 #define WARN_DEPRECATED 0
48
49 enum arm_float_abi
50 {
51 ARM_FLOAT_ABI_HARD,
52 ARM_FLOAT_ABI_SOFTFP,
53 ARM_FLOAT_ABI_SOFT
54 };
55
56 /* Types of processor to assemble for. */
57 #define ARM_1 ARM_ARCH_V1
58 #define ARM_2 ARM_ARCH_V2
59 #define ARM_3 ARM_ARCH_V2S
60 #define ARM_250 ARM_ARCH_V2S
61 #define ARM_6 ARM_ARCH_V3
62 #define ARM_7 ARM_ARCH_V3
63 #define ARM_8 ARM_ARCH_V4
64 #define ARM_9 ARM_ARCH_V4T
65 #define ARM_STRONG ARM_ARCH_V4
66 #define ARM_CPU_MASK 0x0000000f /* XXX? */
67
68 #ifndef CPU_DEFAULT
69 #if defined __XSCALE__
70 #define CPU_DEFAULT (ARM_ARCH_XSCALE)
71 #else
72 #if defined __thumb__
73 #define CPU_DEFAULT (ARM_ARCH_V5T)
74 #else
75 #define CPU_DEFAULT ARM_ANY
76 #endif
77 #endif
78 #endif
79
80 #ifdef TE_LINUX
81 #define FPU_DEFAULT FPU_ARCH_FPA
82 #endif
83
84 #ifdef TE_NetBSD
85 #ifdef OBJ_ELF
86 #define FPU_DEFAULT FPU_ARCH_VFP /* Soft-float, but VFP order. */
87 #else
88 /* Legacy a.out format. */
89 #define FPU_DEFAULT FPU_ARCH_FPA /* Soft-float, but FPA order. */
90 #endif
91 #endif
92
93 /* For backwards compatibility we default to the FPA. */
94 #ifndef FPU_DEFAULT
95 #define FPU_DEFAULT FPU_ARCH_FPA
96 #endif
97
98 #define streq(a, b) (strcmp (a, b) == 0)
99 #define skip_whitespace(str) while (*(str) == ' ') ++(str)
100
101 static unsigned long cpu_variant;
102 static int target_oabi = 0;
103
104 /* Flags stored in private area of BFD structure. */
105 static int uses_apcs_26 = FALSE;
106 static int atpcs = FALSE;
107 static int support_interwork = FALSE;
108 static int uses_apcs_float = FALSE;
109 static int pic_code = FALSE;
110
111 /* Variables that we set while parsing command-line options. Once all
112 options have been read we re-process these values to set the real
113 assembly flags. */
114 static int legacy_cpu = -1;
115 static int legacy_fpu = -1;
116
117 static int mcpu_cpu_opt = -1;
118 static int mcpu_fpu_opt = -1;
119 static int march_cpu_opt = -1;
120 static int march_fpu_opt = -1;
121 static int mfpu_opt = -1;
122 static int mfloat_abi_opt = -1;
123 #ifdef OBJ_ELF
124 static int meabi_flags = EF_ARM_EABI_UNKNOWN;
125 #endif
126
127 /* This array holds the chars that always start a comment. If the
128 pre-processor is disabled, these aren't very useful. */
129 const char comment_chars[] = "@";
130
131 /* This array holds the chars that only start a comment at the beginning of
132 a line. If the line seems to have the form '# 123 filename'
133 .line and .file directives will appear in the pre-processed output. */
134 /* Note that input_file.c hand checks for '#' at the beginning of the
135 first line of the input file. This is because the compiler outputs
136 #NO_APP at the beginning of its output. */
137 /* Also note that comments like this one will always work. */
138 const char line_comment_chars[] = "#";
139
140 const char line_separator_chars[] = ";";
141
142 /* Chars that can be used to separate mant
143 from exp in floating point numbers. */
144 const char EXP_CHARS[] = "eE";
145
146 /* Chars that mean this number is a floating point constant. */
147 /* As in 0f12.456 */
148 /* or 0d1.2345e12 */
149
150 const char FLT_CHARS[] = "rRsSfFdDxXeEpP";
151
152 /* Prefix characters that indicate the start of an immediate
153 value. */
154 #define is_immediate_prefix(C) ((C) == '#' || (C) == '$')
155
156 #ifdef OBJ_ELF
157 /* Pre-defined "_GLOBAL_OFFSET_TABLE_" */
158 symbolS * GOT_symbol;
159 #endif
160
161 /* Size of relocation record. */
162 const int md_reloc_size = 8;
163
164 /* 0: assemble for ARM,
165 1: assemble for Thumb,
166 2: assemble for Thumb even though target CPU does not support thumb
167 instructions. */
168 static int thumb_mode = 0;
169
170 typedef struct arm_fix
171 {
172 int thumb_mode;
173 } arm_fix_data;
174
175 struct arm_it
176 {
177 const char * error;
178 unsigned long instruction;
179 int size;
180 struct
181 {
182 bfd_reloc_code_real_type type;
183 expressionS exp;
184 int pc_rel;
185 } reloc;
186 };
187
188 struct arm_it inst;
189
190 enum asm_shift_index
191 {
192 SHIFT_LSL = 0,
193 SHIFT_LSR,
194 SHIFT_ASR,
195 SHIFT_ROR,
196 SHIFT_RRX
197 };
198
199 struct asm_shift_properties
200 {
201 enum asm_shift_index index;
202 unsigned long bit_field;
203 unsigned int allows_0 : 1;
204 unsigned int allows_32 : 1;
205 };
206
207 static const struct asm_shift_properties shift_properties [] =
208 {
209 { SHIFT_LSL, 0, 1, 0},
210 { SHIFT_LSR, 0x20, 0, 1},
211 { SHIFT_ASR, 0x40, 0, 1},
212 { SHIFT_ROR, 0x60, 0, 0},
213 { SHIFT_RRX, 0x60, 0, 0}
214 };
215
216 struct asm_shift_name
217 {
218 const char * name;
219 const struct asm_shift_properties * properties;
220 };
221
222 static const struct asm_shift_name shift_names [] =
223 {
224 { "asl", shift_properties + SHIFT_LSL },
225 { "lsl", shift_properties + SHIFT_LSL },
226 { "lsr", shift_properties + SHIFT_LSR },
227 { "asr", shift_properties + SHIFT_ASR },
228 { "ror", shift_properties + SHIFT_ROR },
229 { "rrx", shift_properties + SHIFT_RRX },
230 { "ASL", shift_properties + SHIFT_LSL },
231 { "LSL", shift_properties + SHIFT_LSL },
232 { "LSR", shift_properties + SHIFT_LSR },
233 { "ASR", shift_properties + SHIFT_ASR },
234 { "ROR", shift_properties + SHIFT_ROR },
235 { "RRX", shift_properties + SHIFT_RRX }
236 };
237
238 /* Any kind of shift is accepted. */
239 #define NO_SHIFT_RESTRICT 1
240 /* The shift operand must be an immediate value, not a register. */
241 #define SHIFT_IMMEDIATE 0
242 /* The shift must be LSL or ASR and the operand must be an immediate. */
243 #define SHIFT_LSL_OR_ASR_IMMEDIATE 2
244 /* The shift must be ASR and the operand must be an immediate. */
245 #define SHIFT_ASR_IMMEDIATE 3
246 /* The shift must be LSL and the operand must be an immediate. */
247 #define SHIFT_LSL_IMMEDIATE 4
248
249 #define NUM_FLOAT_VALS 8
250
251 const char * fp_const[] =
252 {
253 "0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0", 0
254 };
255
256 /* Number of littlenums required to hold an extended precision number. */
257 #define MAX_LITTLENUMS 6
258
259 LITTLENUM_TYPE fp_values[NUM_FLOAT_VALS][MAX_LITTLENUMS];
260
261 #define FAIL (-1)
262 #define SUCCESS (0)
263
264 /* Whether a Co-processor load/store operation accepts write-back forms. */
265 #define CP_WB_OK 1
266 #define CP_NO_WB 0
267
268 #define SUFF_S 1
269 #define SUFF_D 2
270 #define SUFF_E 3
271 #define SUFF_P 4
272
273 #define CP_T_X 0x00008000
274 #define CP_T_Y 0x00400000
275 #define CP_T_Pre 0x01000000
276 #define CP_T_UD 0x00800000
277 #define CP_T_WB 0x00200000
278
279 #define CONDS_BIT 0x00100000
280 #define LOAD_BIT 0x00100000
281
282 #define DOUBLE_LOAD_FLAG 0x00000001
283
284 struct asm_cond
285 {
286 const char * template;
287 unsigned long value;
288 };
289
290 #define COND_ALWAYS 0xe0000000
291 #define COND_MASK 0xf0000000
292
293 static const struct asm_cond conds[] =
294 {
295 {"eq", 0x00000000},
296 {"ne", 0x10000000},
297 {"cs", 0x20000000}, {"hs", 0x20000000},
298 {"cc", 0x30000000}, {"ul", 0x30000000}, {"lo", 0x30000000},
299 {"mi", 0x40000000},
300 {"pl", 0x50000000},
301 {"vs", 0x60000000},
302 {"vc", 0x70000000},
303 {"hi", 0x80000000},
304 {"ls", 0x90000000},
305 {"ge", 0xa0000000},
306 {"lt", 0xb0000000},
307 {"gt", 0xc0000000},
308 {"le", 0xd0000000},
309 {"al", 0xe0000000},
310 {"nv", 0xf0000000}
311 };
312
313 struct asm_psr
314 {
315 const char *template;
316 bfd_boolean cpsr;
317 unsigned long field;
318 };
319
320 /* The bit that distinguishes CPSR and SPSR. */
321 #define SPSR_BIT (1 << 22)
322
323 /* How many bits to shift the PSR_xxx bits up by. */
324 #define PSR_SHIFT 16
325
326 #define PSR_c (1 << 0)
327 #define PSR_x (1 << 1)
328 #define PSR_s (1 << 2)
329 #define PSR_f (1 << 3)
330
331 static const struct asm_psr psrs[] =
332 {
333 {"CPSR", TRUE, PSR_c | PSR_f},
334 {"CPSR_all", TRUE, PSR_c | PSR_f},
335 {"SPSR", FALSE, PSR_c | PSR_f},
336 {"SPSR_all", FALSE, PSR_c | PSR_f},
337 {"CPSR_flg", TRUE, PSR_f},
338 {"CPSR_f", TRUE, PSR_f},
339 {"SPSR_flg", FALSE, PSR_f},
340 {"SPSR_f", FALSE, PSR_f},
341 {"CPSR_c", TRUE, PSR_c},
342 {"CPSR_ctl", TRUE, PSR_c},
343 {"SPSR_c", FALSE, PSR_c},
344 {"SPSR_ctl", FALSE, PSR_c},
345 {"CPSR_x", TRUE, PSR_x},
346 {"CPSR_s", TRUE, PSR_s},
347 {"SPSR_x", FALSE, PSR_x},
348 {"SPSR_s", FALSE, PSR_s},
349 /* Combinations of flags. */
350 {"CPSR_fs", TRUE, PSR_f | PSR_s},
351 {"CPSR_fx", TRUE, PSR_f | PSR_x},
352 {"CPSR_fc", TRUE, PSR_f | PSR_c},
353 {"CPSR_sf", TRUE, PSR_s | PSR_f},
354 {"CPSR_sx", TRUE, PSR_s | PSR_x},
355 {"CPSR_sc", TRUE, PSR_s | PSR_c},
356 {"CPSR_xf", TRUE, PSR_x | PSR_f},
357 {"CPSR_xs", TRUE, PSR_x | PSR_s},
358 {"CPSR_xc", TRUE, PSR_x | PSR_c},
359 {"CPSR_cf", TRUE, PSR_c | PSR_f},
360 {"CPSR_cs", TRUE, PSR_c | PSR_s},
361 {"CPSR_cx", TRUE, PSR_c | PSR_x},
362 {"CPSR_fsx", TRUE, PSR_f | PSR_s | PSR_x},
363 {"CPSR_fsc", TRUE, PSR_f | PSR_s | PSR_c},
364 {"CPSR_fxs", TRUE, PSR_f | PSR_x | PSR_s},
365 {"CPSR_fxc", TRUE, PSR_f | PSR_x | PSR_c},
366 {"CPSR_fcs", TRUE, PSR_f | PSR_c | PSR_s},
367 {"CPSR_fcx", TRUE, PSR_f | PSR_c | PSR_x},
368 {"CPSR_sfx", TRUE, PSR_s | PSR_f | PSR_x},
369 {"CPSR_sfc", TRUE, PSR_s | PSR_f | PSR_c},
370 {"CPSR_sxf", TRUE, PSR_s | PSR_x | PSR_f},
371 {"CPSR_sxc", TRUE, PSR_s | PSR_x | PSR_c},
372 {"CPSR_scf", TRUE, PSR_s | PSR_c | PSR_f},
373 {"CPSR_scx", TRUE, PSR_s | PSR_c | PSR_x},
374 {"CPSR_xfs", TRUE, PSR_x | PSR_f | PSR_s},
375 {"CPSR_xfc", TRUE, PSR_x | PSR_f | PSR_c},
376 {"CPSR_xsf", TRUE, PSR_x | PSR_s | PSR_f},
377 {"CPSR_xsc", TRUE, PSR_x | PSR_s | PSR_c},
378 {"CPSR_xcf", TRUE, PSR_x | PSR_c | PSR_f},
379 {"CPSR_xcs", TRUE, PSR_x | PSR_c | PSR_s},
380 {"CPSR_cfs", TRUE, PSR_c | PSR_f | PSR_s},
381 {"CPSR_cfx", TRUE, PSR_c | PSR_f | PSR_x},
382 {"CPSR_csf", TRUE, PSR_c | PSR_s | PSR_f},
383 {"CPSR_csx", TRUE, PSR_c | PSR_s | PSR_x},
384 {"CPSR_cxf", TRUE, PSR_c | PSR_x | PSR_f},
385 {"CPSR_cxs", TRUE, PSR_c | PSR_x | PSR_s},
386 {"CPSR_fsxc", TRUE, PSR_f | PSR_s | PSR_x | PSR_c},
387 {"CPSR_fscx", TRUE, PSR_f | PSR_s | PSR_c | PSR_x},
388 {"CPSR_fxsc", TRUE, PSR_f | PSR_x | PSR_s | PSR_c},
389 {"CPSR_fxcs", TRUE, PSR_f | PSR_x | PSR_c | PSR_s},
390 {"CPSR_fcsx", TRUE, PSR_f | PSR_c | PSR_s | PSR_x},
391 {"CPSR_fcxs", TRUE, PSR_f | PSR_c | PSR_x | PSR_s},
392 {"CPSR_sfxc", TRUE, PSR_s | PSR_f | PSR_x | PSR_c},
393 {"CPSR_sfcx", TRUE, PSR_s | PSR_f | PSR_c | PSR_x},
394 {"CPSR_sxfc", TRUE, PSR_s | PSR_x | PSR_f | PSR_c},
395 {"CPSR_sxcf", TRUE, PSR_s | PSR_x | PSR_c | PSR_f},
396 {"CPSR_scfx", TRUE, PSR_s | PSR_c | PSR_f | PSR_x},
397 {"CPSR_scxf", TRUE, PSR_s | PSR_c | PSR_x | PSR_f},
398 {"CPSR_xfsc", TRUE, PSR_x | PSR_f | PSR_s | PSR_c},
399 {"CPSR_xfcs", TRUE, PSR_x | PSR_f | PSR_c | PSR_s},
400 {"CPSR_xsfc", TRUE, PSR_x | PSR_s | PSR_f | PSR_c},
401 {"CPSR_xscf", TRUE, PSR_x | PSR_s | PSR_c | PSR_f},
402 {"CPSR_xcfs", TRUE, PSR_x | PSR_c | PSR_f | PSR_s},
403 {"CPSR_xcsf", TRUE, PSR_x | PSR_c | PSR_s | PSR_f},
404 {"CPSR_cfsx", TRUE, PSR_c | PSR_f | PSR_s | PSR_x},
405 {"CPSR_cfxs", TRUE, PSR_c | PSR_f | PSR_x | PSR_s},
406 {"CPSR_csfx", TRUE, PSR_c | PSR_s | PSR_f | PSR_x},
407 {"CPSR_csxf", TRUE, PSR_c | PSR_s | PSR_x | PSR_f},
408 {"CPSR_cxfs", TRUE, PSR_c | PSR_x | PSR_f | PSR_s},
409 {"CPSR_cxsf", TRUE, PSR_c | PSR_x | PSR_s | PSR_f},
410 {"SPSR_fs", FALSE, PSR_f | PSR_s},
411 {"SPSR_fx", FALSE, PSR_f | PSR_x},
412 {"SPSR_fc", FALSE, PSR_f | PSR_c},
413 {"SPSR_sf", FALSE, PSR_s | PSR_f},
414 {"SPSR_sx", FALSE, PSR_s | PSR_x},
415 {"SPSR_sc", FALSE, PSR_s | PSR_c},
416 {"SPSR_xf", FALSE, PSR_x | PSR_f},
417 {"SPSR_xs", FALSE, PSR_x | PSR_s},
418 {"SPSR_xc", FALSE, PSR_x | PSR_c},
419 {"SPSR_cf", FALSE, PSR_c | PSR_f},
420 {"SPSR_cs", FALSE, PSR_c | PSR_s},
421 {"SPSR_cx", FALSE, PSR_c | PSR_x},
422 {"SPSR_fsx", FALSE, PSR_f | PSR_s | PSR_x},
423 {"SPSR_fsc", FALSE, PSR_f | PSR_s | PSR_c},
424 {"SPSR_fxs", FALSE, PSR_f | PSR_x | PSR_s},
425 {"SPSR_fxc", FALSE, PSR_f | PSR_x | PSR_c},
426 {"SPSR_fcs", FALSE, PSR_f | PSR_c | PSR_s},
427 {"SPSR_fcx", FALSE, PSR_f | PSR_c | PSR_x},
428 {"SPSR_sfx", FALSE, PSR_s | PSR_f | PSR_x},
429 {"SPSR_sfc", FALSE, PSR_s | PSR_f | PSR_c},
430 {"SPSR_sxf", FALSE, PSR_s | PSR_x | PSR_f},
431 {"SPSR_sxc", FALSE, PSR_s | PSR_x | PSR_c},
432 {"SPSR_scf", FALSE, PSR_s | PSR_c | PSR_f},
433 {"SPSR_scx", FALSE, PSR_s | PSR_c | PSR_x},
434 {"SPSR_xfs", FALSE, PSR_x | PSR_f | PSR_s},
435 {"SPSR_xfc", FALSE, PSR_x | PSR_f | PSR_c},
436 {"SPSR_xsf", FALSE, PSR_x | PSR_s | PSR_f},
437 {"SPSR_xsc", FALSE, PSR_x | PSR_s | PSR_c},
438 {"SPSR_xcf", FALSE, PSR_x | PSR_c | PSR_f},
439 {"SPSR_xcs", FALSE, PSR_x | PSR_c | PSR_s},
440 {"SPSR_cfs", FALSE, PSR_c | PSR_f | PSR_s},
441 {"SPSR_cfx", FALSE, PSR_c | PSR_f | PSR_x},
442 {"SPSR_csf", FALSE, PSR_c | PSR_s | PSR_f},
443 {"SPSR_csx", FALSE, PSR_c | PSR_s | PSR_x},
444 {"SPSR_cxf", FALSE, PSR_c | PSR_x | PSR_f},
445 {"SPSR_cxs", FALSE, PSR_c | PSR_x | PSR_s},
446 {"SPSR_fsxc", FALSE, PSR_f | PSR_s | PSR_x | PSR_c},
447 {"SPSR_fscx", FALSE, PSR_f | PSR_s | PSR_c | PSR_x},
448 {"SPSR_fxsc", FALSE, PSR_f | PSR_x | PSR_s | PSR_c},
449 {"SPSR_fxcs", FALSE, PSR_f | PSR_x | PSR_c | PSR_s},
450 {"SPSR_fcsx", FALSE, PSR_f | PSR_c | PSR_s | PSR_x},
451 {"SPSR_fcxs", FALSE, PSR_f | PSR_c | PSR_x | PSR_s},
452 {"SPSR_sfxc", FALSE, PSR_s | PSR_f | PSR_x | PSR_c},
453 {"SPSR_sfcx", FALSE, PSR_s | PSR_f | PSR_c | PSR_x},
454 {"SPSR_sxfc", FALSE, PSR_s | PSR_x | PSR_f | PSR_c},
455 {"SPSR_sxcf", FALSE, PSR_s | PSR_x | PSR_c | PSR_f},
456 {"SPSR_scfx", FALSE, PSR_s | PSR_c | PSR_f | PSR_x},
457 {"SPSR_scxf", FALSE, PSR_s | PSR_c | PSR_x | PSR_f},
458 {"SPSR_xfsc", FALSE, PSR_x | PSR_f | PSR_s | PSR_c},
459 {"SPSR_xfcs", FALSE, PSR_x | PSR_f | PSR_c | PSR_s},
460 {"SPSR_xsfc", FALSE, PSR_x | PSR_s | PSR_f | PSR_c},
461 {"SPSR_xscf", FALSE, PSR_x | PSR_s | PSR_c | PSR_f},
462 {"SPSR_xcfs", FALSE, PSR_x | PSR_c | PSR_f | PSR_s},
463 {"SPSR_xcsf", FALSE, PSR_x | PSR_c | PSR_s | PSR_f},
464 {"SPSR_cfsx", FALSE, PSR_c | PSR_f | PSR_s | PSR_x},
465 {"SPSR_cfxs", FALSE, PSR_c | PSR_f | PSR_x | PSR_s},
466 {"SPSR_csfx", FALSE, PSR_c | PSR_s | PSR_f | PSR_x},
467 {"SPSR_csxf", FALSE, PSR_c | PSR_s | PSR_x | PSR_f},
468 {"SPSR_cxfs", FALSE, PSR_c | PSR_x | PSR_f | PSR_s},
469 {"SPSR_cxsf", FALSE, PSR_c | PSR_x | PSR_s | PSR_f},
470 };
471
472 enum wreg_type
473 {
474 IWMMXT_REG_WR = 0,
475 IWMMXT_REG_WC = 1,
476 IWMMXT_REG_WR_OR_WC = 2,
477 IWMMXT_REG_WCG
478 };
479
480 enum iwmmxt_insn_type
481 {
482 check_rd,
483 check_wr,
484 check_wrwr,
485 check_wrwrwr,
486 check_wrwrwcg,
487 check_tbcst,
488 check_tmovmsk,
489 check_tmia,
490 check_tmcrr,
491 check_tmrrc,
492 check_tmcr,
493 check_tmrc,
494 check_tinsr,
495 check_textrc,
496 check_waligni,
497 check_textrm,
498 check_wshufh
499 };
500
501 enum vfp_dp_reg_pos
502 {
503 VFP_REG_Dd, VFP_REG_Dm, VFP_REG_Dn
504 };
505
506 enum vfp_sp_reg_pos
507 {
508 VFP_REG_Sd, VFP_REG_Sm, VFP_REG_Sn
509 };
510
511 enum vfp_ldstm_type
512 {
513 VFP_LDSTMIA, VFP_LDSTMDB, VFP_LDSTMIAX, VFP_LDSTMDBX
514 };
515
516 /* VFP system registers. */
517 struct vfp_reg
518 {
519 const char *name;
520 unsigned long regno;
521 };
522
523 static const struct vfp_reg vfp_regs[] =
524 {
525 {"fpsid", 0x00000000},
526 {"FPSID", 0x00000000},
527 {"fpscr", 0x00010000},
528 {"FPSCR", 0x00010000},
529 {"fpexc", 0x00080000},
530 {"FPEXC", 0x00080000}
531 };
532
533 /* Structure for a hash table entry for a register. */
534 struct reg_entry
535 {
536 const char * name;
537 int number;
538 bfd_boolean builtin;
539 };
540
541 /* Some well known registers that we refer to directly elsewhere. */
542 #define REG_SP 13
543 #define REG_LR 14
544 #define REG_PC 15
545
546 #define wr_register(reg) ((reg ^ WR_PREFIX) >= 0 && (reg ^ WR_PREFIX) <= 15)
547 #define wc_register(reg) ((reg ^ WC_PREFIX) >= 0 && (reg ^ WC_PREFIX) <= 15)
548 #define wcg_register(reg) ((reg ^ WC_PREFIX) >= 8 && (reg ^ WC_PREFIX) <= 11)
549
550 /* These are the standard names. Users can add aliases with .req.
551 and delete them with .unreq. */
552
553 /* Integer Register Numbers. */
554 static const struct reg_entry rn_table[] =
555 {
556 {"r0", 0, TRUE}, {"r1", 1, TRUE}, {"r2", 2, TRUE}, {"r3", 3, TRUE},
557 {"r4", 4, TRUE}, {"r5", 5, TRUE}, {"r6", 6, TRUE}, {"r7", 7, TRUE},
558 {"r8", 8, TRUE}, {"r9", 9, TRUE}, {"r10", 10, TRUE}, {"r11", 11, TRUE},
559 {"r12", 12, TRUE}, {"r13", REG_SP, TRUE}, {"r14", REG_LR, TRUE}, {"r15", REG_PC, TRUE},
560 /* ATPCS Synonyms. */
561 {"a1", 0, TRUE}, {"a2", 1, TRUE}, {"a3", 2, TRUE}, {"a4", 3, TRUE},
562 {"v1", 4, TRUE}, {"v2", 5, TRUE}, {"v3", 6, TRUE}, {"v4", 7, TRUE},
563 {"v5", 8, TRUE}, {"v6", 9, TRUE}, {"v7", 10, TRUE}, {"v8", 11, TRUE},
564 /* Well-known aliases. */
565 {"wr", 7, TRUE}, {"sb", 9, TRUE}, {"sl", 10, TRUE}, {"fp", 11, TRUE},
566 {"ip", 12, TRUE}, {"sp", REG_SP, TRUE}, {"lr", REG_LR, TRUE}, {"pc", REG_PC, TRUE},
567 {NULL, 0, TRUE}
568 };
569
570 #define WR_PREFIX 0x200
571 #define WC_PREFIX 0x400
572
573 static const struct reg_entry iwmmxt_table[] =
574 {
575 /* Intel Wireless MMX technology register names. */
576 { "wr0", 0x0 | WR_PREFIX, TRUE}, {"wr1", 0x1 | WR_PREFIX, TRUE},
577 { "wr2", 0x2 | WR_PREFIX, TRUE}, {"wr3", 0x3 | WR_PREFIX, TRUE},
578 { "wr4", 0x4 | WR_PREFIX, TRUE}, {"wr5", 0x5 | WR_PREFIX, TRUE},
579 { "wr6", 0x6 | WR_PREFIX, TRUE}, {"wr7", 0x7 | WR_PREFIX, TRUE},
580 { "wr8", 0x8 | WR_PREFIX, TRUE}, {"wr9", 0x9 | WR_PREFIX, TRUE},
581 { "wr10", 0xa | WR_PREFIX, TRUE}, {"wr11", 0xb | WR_PREFIX, TRUE},
582 { "wr12", 0xc | WR_PREFIX, TRUE}, {"wr13", 0xd | WR_PREFIX, TRUE},
583 { "wr14", 0xe | WR_PREFIX, TRUE}, {"wr15", 0xf | WR_PREFIX, TRUE},
584 { "wcid", 0x0 | WC_PREFIX, TRUE}, {"wcon", 0x1 | WC_PREFIX, TRUE},
585 {"wcssf", 0x2 | WC_PREFIX, TRUE}, {"wcasf", 0x3 | WC_PREFIX, TRUE},
586 {"wcgr0", 0x8 | WC_PREFIX, TRUE}, {"wcgr1", 0x9 | WC_PREFIX, TRUE},
587 {"wcgr2", 0xa | WC_PREFIX, TRUE}, {"wcgr3", 0xb | WC_PREFIX, TRUE},
588
589 { "wR0", 0x0 | WR_PREFIX, TRUE}, {"wR1", 0x1 | WR_PREFIX, TRUE},
590 { "wR2", 0x2 | WR_PREFIX, TRUE}, {"wR3", 0x3 | WR_PREFIX, TRUE},
591 { "wR4", 0x4 | WR_PREFIX, TRUE}, {"wR5", 0x5 | WR_PREFIX, TRUE},
592 { "wR6", 0x6 | WR_PREFIX, TRUE}, {"wR7", 0x7 | WR_PREFIX, TRUE},
593 { "wR8", 0x8 | WR_PREFIX, TRUE}, {"wR9", 0x9 | WR_PREFIX, TRUE},
594 { "wR10", 0xa | WR_PREFIX, TRUE}, {"wR11", 0xb | WR_PREFIX, TRUE},
595 { "wR12", 0xc | WR_PREFIX, TRUE}, {"wR13", 0xd | WR_PREFIX, TRUE},
596 { "wR14", 0xe | WR_PREFIX, TRUE}, {"wR15", 0xf | WR_PREFIX, TRUE},
597 { "wCID", 0x0 | WC_PREFIX, TRUE}, {"wCon", 0x1 | WC_PREFIX, TRUE},
598 {"wCSSF", 0x2 | WC_PREFIX, TRUE}, {"wCASF", 0x3 | WC_PREFIX, TRUE},
599 {"wCGR0", 0x8 | WC_PREFIX, TRUE}, {"wCGR1", 0x9 | WC_PREFIX, TRUE},
600 {"wCGR2", 0xa | WC_PREFIX, TRUE}, {"wCGR3", 0xb | WC_PREFIX, TRUE},
601 {NULL, 0, TRUE}
602 };
603
604 /* Co-processor Numbers. */
605 static const struct reg_entry cp_table[] =
606 {
607 {"p0", 0, TRUE}, {"p1", 1, TRUE}, {"p2", 2, TRUE}, {"p3", 3, TRUE},
608 {"p4", 4, TRUE}, {"p5", 5, TRUE}, {"p6", 6, TRUE}, {"p7", 7, TRUE},
609 {"p8", 8, TRUE}, {"p9", 9, TRUE}, {"p10", 10, TRUE}, {"p11", 11, TRUE},
610 {"p12", 12, TRUE}, {"p13", 13, TRUE}, {"p14", 14, TRUE}, {"p15", 15, TRUE},
611 {NULL, 0, TRUE}
612 };
613
614 /* Co-processor Register Numbers. */
615 static const struct reg_entry cn_table[] =
616 {
617 {"c0", 0, TRUE}, {"c1", 1, TRUE}, {"c2", 2, TRUE}, {"c3", 3, TRUE},
618 {"c4", 4, TRUE}, {"c5", 5, TRUE}, {"c6", 6, TRUE}, {"c7", 7, TRUE},
619 {"c8", 8, TRUE}, {"c9", 9, TRUE}, {"c10", 10, TRUE}, {"c11", 11, TRUE},
620 {"c12", 12, TRUE}, {"c13", 13, TRUE}, {"c14", 14, TRUE}, {"c15", 15, TRUE},
621 /* Not really valid, but kept for back-wards compatibility. */
622 {"cr0", 0, TRUE}, {"cr1", 1, TRUE}, {"cr2", 2, TRUE}, {"cr3", 3, TRUE},
623 {"cr4", 4, TRUE}, {"cr5", 5, TRUE}, {"cr6", 6, TRUE}, {"cr7", 7, TRUE},
624 {"cr8", 8, TRUE}, {"cr9", 9, TRUE}, {"cr10", 10, TRUE}, {"cr11", 11, TRUE},
625 {"cr12", 12, TRUE}, {"cr13", 13, TRUE}, {"cr14", 14, TRUE}, {"cr15", 15, TRUE},
626 {NULL, 0, TRUE}
627 };
628
629 /* FPA Registers. */
630 static const struct reg_entry fn_table[] =
631 {
632 {"f0", 0, TRUE}, {"f1", 1, TRUE}, {"f2", 2, TRUE}, {"f3", 3, TRUE},
633 {"f4", 4, TRUE}, {"f5", 5, TRUE}, {"f6", 6, TRUE}, {"f7", 7, TRUE},
634 {NULL, 0, TRUE}
635 };
636
637 /* VFP SP Registers. */
638 static const struct reg_entry sn_table[] =
639 {
640 {"s0", 0, TRUE}, {"s1", 1, TRUE}, {"s2", 2, TRUE}, {"s3", 3, TRUE},
641 {"s4", 4, TRUE}, {"s5", 5, TRUE}, {"s6", 6, TRUE}, {"s7", 7, TRUE},
642 {"s8", 8, TRUE}, {"s9", 9, TRUE}, {"s10", 10, TRUE}, {"s11", 11, TRUE},
643 {"s12", 12, TRUE}, {"s13", 13, TRUE}, {"s14", 14, TRUE}, {"s15", 15, TRUE},
644 {"s16", 16, TRUE}, {"s17", 17, TRUE}, {"s18", 18, TRUE}, {"s19", 19, TRUE},
645 {"s20", 20, TRUE}, {"s21", 21, TRUE}, {"s22", 22, TRUE}, {"s23", 23, TRUE},
646 {"s24", 24, TRUE}, {"s25", 25, TRUE}, {"s26", 26, TRUE}, {"s27", 27, TRUE},
647 {"s28", 28, TRUE}, {"s29", 29, TRUE}, {"s30", 30, TRUE}, {"s31", 31, TRUE},
648 {NULL, 0, TRUE}
649 };
650
651 /* VFP DP Registers. */
652 static const struct reg_entry dn_table[] =
653 {
654 {"d0", 0, TRUE}, {"d1", 1, TRUE}, {"d2", 2, TRUE}, {"d3", 3, TRUE},
655 {"d4", 4, TRUE}, {"d5", 5, TRUE}, {"d6", 6, TRUE}, {"d7", 7, TRUE},
656 {"d8", 8, TRUE}, {"d9", 9, TRUE}, {"d10", 10, TRUE}, {"d11", 11, TRUE},
657 {"d12", 12, TRUE}, {"d13", 13, TRUE}, {"d14", 14, TRUE}, {"d15", 15, TRUE},
658 {NULL, 0, TRUE}
659 };
660
661 /* Maverick DSP coprocessor registers. */
662 static const struct reg_entry mav_mvf_table[] =
663 {
664 {"mvf0", 0, TRUE}, {"mvf1", 1, TRUE}, {"mvf2", 2, TRUE}, {"mvf3", 3, TRUE},
665 {"mvf4", 4, TRUE}, {"mvf5", 5, TRUE}, {"mvf6", 6, TRUE}, {"mvf7", 7, TRUE},
666 {"mvf8", 8, TRUE}, {"mvf9", 9, TRUE}, {"mvf10", 10, TRUE}, {"mvf11", 11, TRUE},
667 {"mvf12", 12, TRUE}, {"mvf13", 13, TRUE}, {"mvf14", 14, TRUE}, {"mvf15", 15, TRUE},
668 {NULL, 0, TRUE}
669 };
670
671 static const struct reg_entry mav_mvd_table[] =
672 {
673 {"mvd0", 0, TRUE}, {"mvd1", 1, TRUE}, {"mvd2", 2, TRUE}, {"mvd3", 3, TRUE},
674 {"mvd4", 4, TRUE}, {"mvd5", 5, TRUE}, {"mvd6", 6, TRUE}, {"mvd7", 7, TRUE},
675 {"mvd8", 8, TRUE}, {"mvd9", 9, TRUE}, {"mvd10", 10, TRUE}, {"mvd11", 11, TRUE},
676 {"mvd12", 12, TRUE}, {"mvd13", 13, TRUE}, {"mvd14", 14, TRUE}, {"mvd15", 15, TRUE},
677 {NULL, 0, TRUE}
678 };
679
680 static const struct reg_entry mav_mvfx_table[] =
681 {
682 {"mvfx0", 0, TRUE}, {"mvfx1", 1, TRUE}, {"mvfx2", 2, TRUE}, {"mvfx3", 3, TRUE},
683 {"mvfx4", 4, TRUE}, {"mvfx5", 5, TRUE}, {"mvfx6", 6, TRUE}, {"mvfx7", 7, TRUE},
684 {"mvfx8", 8, TRUE}, {"mvfx9", 9, TRUE}, {"mvfx10", 10, TRUE}, {"mvfx11", 11, TRUE},
685 {"mvfx12", 12, TRUE}, {"mvfx13", 13, TRUE}, {"mvfx14", 14, TRUE}, {"mvfx15", 15, TRUE},
686 {NULL, 0, TRUE}
687 };
688
689 static const struct reg_entry mav_mvdx_table[] =
690 {
691 {"mvdx0", 0, TRUE}, {"mvdx1", 1, TRUE}, {"mvdx2", 2, TRUE}, {"mvdx3", 3, TRUE},
692 {"mvdx4", 4, TRUE}, {"mvdx5", 5, TRUE}, {"mvdx6", 6, TRUE}, {"mvdx7", 7, TRUE},
693 {"mvdx8", 8, TRUE}, {"mvdx9", 9, TRUE}, {"mvdx10", 10, TRUE}, {"mvdx11", 11, TRUE},
694 {"mvdx12", 12, TRUE}, {"mvdx13", 13, TRUE}, {"mvdx14", 14, TRUE}, {"mvdx15", 15, TRUE},
695 {NULL, 0, TRUE}
696 };
697
698 static const struct reg_entry mav_mvax_table[] =
699 {
700 {"mvax0", 0, TRUE}, {"mvax1", 1, TRUE}, {"mvax2", 2, TRUE}, {"mvax3", 3, TRUE},
701 {NULL, 0, TRUE}
702 };
703
704 static const struct reg_entry mav_dspsc_table[] =
705 {
706 {"dspsc", 0, TRUE},
707 {NULL, 0, TRUE}
708 };
709
710 struct reg_map
711 {
712 const struct reg_entry * names;
713 int max_regno;
714 struct hash_control * htab;
715 const char * expected;
716 };
717
718 struct reg_map all_reg_maps[] =
719 {
720 {rn_table, 15, NULL, N_("ARM register expected")},
721 {cp_table, 15, NULL, N_("bad or missing co-processor number")},
722 {cn_table, 15, NULL, N_("co-processor register expected")},
723 {fn_table, 7, NULL, N_("FPA register expected")},
724 {sn_table, 31, NULL, N_("VFP single precision register expected")},
725 {dn_table, 15, NULL, N_("VFP double precision register expected")},
726 {mav_mvf_table, 15, NULL, N_("Maverick MVF register expected")},
727 {mav_mvd_table, 15, NULL, N_("Maverick MVD register expected")},
728 {mav_mvfx_table, 15, NULL, N_("Maverick MVFX register expected")},
729 {mav_mvdx_table, 15, NULL, N_("Maverick MVDX register expected")},
730 {mav_mvax_table, 3, NULL, N_("Maverick MVAX register expected")},
731 {mav_dspsc_table, 0, NULL, N_("Maverick DSPSC register expected")},
732 {iwmmxt_table, 23, NULL, N_("Intel Wireless MMX technology register expected")},
733 };
734
735 /* Enumeration matching entries in table above. */
736 enum arm_reg_type
737 {
738 REG_TYPE_RN = 0,
739 #define REG_TYPE_FIRST REG_TYPE_RN
740 REG_TYPE_CP = 1,
741 REG_TYPE_CN = 2,
742 REG_TYPE_FN = 3,
743 REG_TYPE_SN = 4,
744 REG_TYPE_DN = 5,
745 REG_TYPE_MVF = 6,
746 REG_TYPE_MVD = 7,
747 REG_TYPE_MVFX = 8,
748 REG_TYPE_MVDX = 9,
749 REG_TYPE_MVAX = 10,
750 REG_TYPE_DSPSC = 11,
751 REG_TYPE_IWMMXT = 12,
752
753 REG_TYPE_MAX = 13
754 };
755
756 /* ARM instructions take 4bytes in the object file, Thumb instructions
757 take 2: */
758 #define INSN_SIZE 4
759
760 /* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
761 #define MAV_MODE1 0x100c
762
763 /* "INSN<cond> X,Y" where X:bit16, Y:bit12. */
764 #define MAV_MODE2 0x0c10
765
766 /* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
767 #define MAV_MODE3 0x100c
768
769 /* "INSN<cond> X,Y,Z" where X:16, Y:0, Z:12. */
770 #define MAV_MODE4 0x0c0010
771
772 /* "INSN<cond> X,Y,Z" where X:12, Y:16, Z:0. */
773 #define MAV_MODE5 0x00100c
774
775 /* "INSN<cond> W,X,Y,Z" where W:5, X:12, Y:16, Z:0. */
776 #define MAV_MODE6 0x00100c05
777
778 struct asm_opcode
779 {
780 /* Basic string to match. */
781 const char * template;
782
783 /* Basic instruction code. */
784 unsigned long value;
785
786 /* Offset into the template where the condition code (if any) will be.
787 If zero, then the instruction is never conditional. */
788 unsigned cond_offset;
789
790 /* Which architecture variant provides this instruction. */
791 unsigned long variant;
792
793 /* Function to call to parse args. */
794 void (* parms) (char *);
795 };
796
797 /* Defines for various bits that we will want to toggle. */
798 #define INST_IMMEDIATE 0x02000000
799 #define OFFSET_REG 0x02000000
800 #define HWOFFSET_IMM 0x00400000
801 #define SHIFT_BY_REG 0x00000010
802 #define PRE_INDEX 0x01000000
803 #define INDEX_UP 0x00800000
804 #define WRITE_BACK 0x00200000
805 #define LDM_TYPE_2_OR_3 0x00400000
806
807 #define LITERAL_MASK 0xf000f000
808 #define OPCODE_MASK 0xfe1fffff
809 #define V4_STR_BIT 0x00000020
810
811 #define DATA_OP_SHIFT 21
812
813 /* Codes to distinguish the arithmetic instructions. */
814 #define OPCODE_AND 0
815 #define OPCODE_EOR 1
816 #define OPCODE_SUB 2
817 #define OPCODE_RSB 3
818 #define OPCODE_ADD 4
819 #define OPCODE_ADC 5
820 #define OPCODE_SBC 6
821 #define OPCODE_RSC 7
822 #define OPCODE_TST 8
823 #define OPCODE_TEQ 9
824 #define OPCODE_CMP 10
825 #define OPCODE_CMN 11
826 #define OPCODE_ORR 12
827 #define OPCODE_MOV 13
828 #define OPCODE_BIC 14
829 #define OPCODE_MVN 15
830
831 #define T_OPCODE_MUL 0x4340
832 #define T_OPCODE_TST 0x4200
833 #define T_OPCODE_CMN 0x42c0
834 #define T_OPCODE_NEG 0x4240
835 #define T_OPCODE_MVN 0x43c0
836
837 #define T_OPCODE_ADD_R3 0x1800
838 #define T_OPCODE_SUB_R3 0x1a00
839 #define T_OPCODE_ADD_HI 0x4400
840 #define T_OPCODE_ADD_ST 0xb000
841 #define T_OPCODE_SUB_ST 0xb080
842 #define T_OPCODE_ADD_SP 0xa800
843 #define T_OPCODE_ADD_PC 0xa000
844 #define T_OPCODE_ADD_I8 0x3000
845 #define T_OPCODE_SUB_I8 0x3800
846 #define T_OPCODE_ADD_I3 0x1c00
847 #define T_OPCODE_SUB_I3 0x1e00
848
849 #define T_OPCODE_ASR_R 0x4100
850 #define T_OPCODE_LSL_R 0x4080
851 #define T_OPCODE_LSR_R 0x40c0
852 #define T_OPCODE_ASR_I 0x1000
853 #define T_OPCODE_LSL_I 0x0000
854 #define T_OPCODE_LSR_I 0x0800
855
856 #define T_OPCODE_MOV_I8 0x2000
857 #define T_OPCODE_CMP_I8 0x2800
858 #define T_OPCODE_CMP_LR 0x4280
859 #define T_OPCODE_MOV_HR 0x4600
860 #define T_OPCODE_CMP_HR 0x4500
861
862 #define T_OPCODE_LDR_PC 0x4800
863 #define T_OPCODE_LDR_SP 0x9800
864 #define T_OPCODE_STR_SP 0x9000
865 #define T_OPCODE_LDR_IW 0x6800
866 #define T_OPCODE_STR_IW 0x6000
867 #define T_OPCODE_LDR_IH 0x8800
868 #define T_OPCODE_STR_IH 0x8000
869 #define T_OPCODE_LDR_IB 0x7800
870 #define T_OPCODE_STR_IB 0x7000
871 #define T_OPCODE_LDR_RW 0x5800
872 #define T_OPCODE_STR_RW 0x5000
873 #define T_OPCODE_LDR_RH 0x5a00
874 #define T_OPCODE_STR_RH 0x5200
875 #define T_OPCODE_LDR_RB 0x5c00
876 #define T_OPCODE_STR_RB 0x5400
877
878 #define T_OPCODE_PUSH 0xb400
879 #define T_OPCODE_POP 0xbc00
880
881 #define T_OPCODE_BRANCH 0xe7fe
882
883 #define THUMB_SIZE 2 /* Size of thumb instruction. */
884 #define THUMB_REG_LO 0x1
885 #define THUMB_REG_HI 0x2
886 #define THUMB_REG_ANY 0x3
887
888 #define THUMB_H1 0x0080
889 #define THUMB_H2 0x0040
890
891 #define THUMB_ASR 0
892 #define THUMB_LSL 1
893 #define THUMB_LSR 2
894
895 #define THUMB_MOVE 0
896 #define THUMB_COMPARE 1
897 #define THUMB_CPY 2
898
899 #define THUMB_LOAD 0
900 #define THUMB_STORE 1
901
902 #define THUMB_PP_PC_LR 0x0100
903
904 /* These three are used for immediate shifts, do not alter. */
905 #define THUMB_WORD 2
906 #define THUMB_HALFWORD 1
907 #define THUMB_BYTE 0
908
909 struct thumb_opcode
910 {
911 /* Basic string to match. */
912 const char * template;
913
914 /* Basic instruction code. */
915 unsigned long value;
916
917 int size;
918
919 /* Which CPU variants this exists for. */
920 unsigned long variant;
921
922 /* Function to call to parse args. */
923 void (* parms) (char *);
924 };
925
926 #define BAD_ARGS _("bad arguments to instruction")
927 #define BAD_PC _("r15 not allowed here")
928 #define BAD_COND _("instruction is not conditional")
929 #define ERR_NO_ACCUM _("acc0 expected")
930
931 static struct hash_control * arm_ops_hsh = NULL;
932 static struct hash_control * arm_tops_hsh = NULL;
933 static struct hash_control * arm_cond_hsh = NULL;
934 static struct hash_control * arm_shift_hsh = NULL;
935 static struct hash_control * arm_psr_hsh = NULL;
936
937 /* Stuff needed to resolve the label ambiguity
938 As:
939 ...
940 label: <insn>
941 may differ from:
942 ...
943 label:
944 <insn>
945 */
946
947 symbolS * last_label_seen;
948 static int label_is_thumb_function_name = FALSE;
949 \f
950 /* Literal Pool stuff. */
951
952 #define MAX_LITERAL_POOL_SIZE 1024
953
954 /* Literal pool structure. Held on a per-section
955 and per-sub-section basis. */
956
957 typedef struct literal_pool
958 {
959 expressionS literals [MAX_LITERAL_POOL_SIZE];
960 unsigned int next_free_entry;
961 unsigned int id;
962 symbolS * symbol;
963 segT section;
964 subsegT sub_section;
965 struct literal_pool * next;
966 } literal_pool;
967
968 /* Pointer to a linked list of literal pools. */
969 literal_pool * list_of_pools = NULL;
970
971 static literal_pool *
972 find_literal_pool (void)
973 {
974 literal_pool * pool;
975
976 for (pool = list_of_pools; pool != NULL; pool = pool->next)
977 {
978 if (pool->section == now_seg
979 && pool->sub_section == now_subseg)
980 break;
981 }
982
983 return pool;
984 }
985
986 static literal_pool *
987 find_or_make_literal_pool (void)
988 {
989 /* Next literal pool ID number. */
990 static unsigned int latest_pool_num = 1;
991 literal_pool * pool;
992
993 pool = find_literal_pool ();
994
995 if (pool == NULL)
996 {
997 /* Create a new pool. */
998 pool = xmalloc (sizeof (* pool));
999 if (! pool)
1000 return NULL;
1001
1002 pool->next_free_entry = 0;
1003 pool->section = now_seg;
1004 pool->sub_section = now_subseg;
1005 pool->next = list_of_pools;
1006 pool->symbol = NULL;
1007
1008 /* Add it to the list. */
1009 list_of_pools = pool;
1010 }
1011
1012 /* New pools, and emptied pools, will have a NULL symbol. */
1013 if (pool->symbol == NULL)
1014 {
1015 pool->symbol = symbol_create (FAKE_LABEL_NAME, undefined_section,
1016 (valueT) 0, &zero_address_frag);
1017 pool->id = latest_pool_num ++;
1018 }
1019
1020 /* Done. */
1021 return pool;
1022 }
1023
1024 /* Add the literal in the global 'inst'
1025 structure to the relevent literal pool. */
1026
1027 static int
1028 add_to_lit_pool (void)
1029 {
1030 literal_pool * pool;
1031 unsigned int entry;
1032
1033 pool = find_or_make_literal_pool ();
1034
1035 /* Check if this literal value is already in the pool. */
1036 for (entry = 0; entry < pool->next_free_entry; entry ++)
1037 {
1038 if ((pool->literals[entry].X_op == inst.reloc.exp.X_op)
1039 && (inst.reloc.exp.X_op == O_constant)
1040 && (pool->literals[entry].X_add_number
1041 == inst.reloc.exp.X_add_number)
1042 && (pool->literals[entry].X_unsigned
1043 == inst.reloc.exp.X_unsigned))
1044 break;
1045
1046 if ((pool->literals[entry].X_op == inst.reloc.exp.X_op)
1047 && (inst.reloc.exp.X_op == O_symbol)
1048 && (pool->literals[entry].X_add_number
1049 == inst.reloc.exp.X_add_number)
1050 && (pool->literals[entry].X_add_symbol
1051 == inst.reloc.exp.X_add_symbol)
1052 && (pool->literals[entry].X_op_symbol
1053 == inst.reloc.exp.X_op_symbol))
1054 break;
1055 }
1056
1057 /* Do we need to create a new entry? */
1058 if (entry == pool->next_free_entry)
1059 {
1060 if (entry >= MAX_LITERAL_POOL_SIZE)
1061 {
1062 inst.error = _("literal pool overflow");
1063 return FAIL;
1064 }
1065
1066 pool->literals[entry] = inst.reloc.exp;
1067 pool->next_free_entry += 1;
1068 }
1069
1070 inst.reloc.exp.X_op = O_symbol;
1071 inst.reloc.exp.X_add_number = ((int) entry) * 4 - 8;
1072 inst.reloc.exp.X_add_symbol = pool->symbol;
1073
1074 return SUCCESS;
1075 }
1076
1077 /* Can't use symbol_new here, so have to create a symbol and then at
1078 a later date assign it a value. Thats what these functions do. */
1079
1080 static void
1081 symbol_locate (symbolS * symbolP,
1082 const char * name, /* It is copied, the caller can modify. */
1083 segT segment, /* Segment identifier (SEG_<something>). */
1084 valueT valu, /* Symbol value. */
1085 fragS * frag) /* Associated fragment. */
1086 {
1087 unsigned int name_length;
1088 char * preserved_copy_of_name;
1089
1090 name_length = strlen (name) + 1; /* +1 for \0. */
1091 obstack_grow (&notes, name, name_length);
1092 preserved_copy_of_name = obstack_finish (&notes);
1093 #ifdef STRIP_UNDERSCORE
1094 if (preserved_copy_of_name[0] == '_')
1095 preserved_copy_of_name++;
1096 #endif
1097
1098 #ifdef tc_canonicalize_symbol_name
1099 preserved_copy_of_name =
1100 tc_canonicalize_symbol_name (preserved_copy_of_name);
1101 #endif
1102
1103 S_SET_NAME (symbolP, preserved_copy_of_name);
1104
1105 S_SET_SEGMENT (symbolP, segment);
1106 S_SET_VALUE (symbolP, valu);
1107 symbol_clear_list_pointers (symbolP);
1108
1109 symbol_set_frag (symbolP, frag);
1110
1111 /* Link to end of symbol chain. */
1112 {
1113 extern int symbol_table_frozen;
1114
1115 if (symbol_table_frozen)
1116 abort ();
1117 }
1118
1119 symbol_append (symbolP, symbol_lastP, & symbol_rootP, & symbol_lastP);
1120
1121 obj_symbol_new_hook (symbolP);
1122
1123 #ifdef tc_symbol_new_hook
1124 tc_symbol_new_hook (symbolP);
1125 #endif
1126
1127 #ifdef DEBUG_SYMS
1128 verify_symbol_chain (symbol_rootP, symbol_lastP);
1129 #endif /* DEBUG_SYMS */
1130 }
1131
1132 /* Check that an immediate is valid.
1133 If so, convert it to the right format. */
1134
1135 static unsigned int
1136 validate_immediate (unsigned int val)
1137 {
1138 unsigned int a;
1139 unsigned int i;
1140
1141 #define rotate_left(v, n) (v << n | v >> (32 - n))
1142
1143 for (i = 0; i < 32; i += 2)
1144 if ((a = rotate_left (val, i)) <= 0xff)
1145 return a | (i << 7); /* 12-bit pack: [shift-cnt,const]. */
1146
1147 return FAIL;
1148 }
1149
1150 /* Check to see if an immediate can be computed as two separate immediate
1151 values, added together. We already know that this value cannot be
1152 computed by just one ARM instruction. */
1153
1154 static unsigned int
1155 validate_immediate_twopart (unsigned int val,
1156 unsigned int * highpart)
1157 {
1158 unsigned int a;
1159 unsigned int i;
1160
1161 for (i = 0; i < 32; i += 2)
1162 if (((a = rotate_left (val, i)) & 0xff) != 0)
1163 {
1164 if (a & 0xff00)
1165 {
1166 if (a & ~ 0xffff)
1167 continue;
1168 * highpart = (a >> 8) | ((i + 24) << 7);
1169 }
1170 else if (a & 0xff0000)
1171 {
1172 if (a & 0xff000000)
1173 continue;
1174 * highpart = (a >> 16) | ((i + 16) << 7);
1175 }
1176 else
1177 {
1178 assert (a & 0xff000000);
1179 * highpart = (a >> 24) | ((i + 8) << 7);
1180 }
1181
1182 return (a & 0xff) | (i << 7);
1183 }
1184
1185 return FAIL;
1186 }
1187
1188 static int
1189 validate_offset_imm (unsigned int val, int hwse)
1190 {
1191 if ((hwse && val > 255) || val > 4095)
1192 return FAIL;
1193 return val;
1194 }
1195
1196 \f
1197 #ifdef OBJ_ELF
1198 /* This code is to handle mapping symbols as defined in the ARM ELF spec.
1199 (This text is taken from version B-02 of the spec):
1200
1201 4.4.7 Mapping and tagging symbols
1202
1203 A section of an ARM ELF file can contain a mixture of ARM code,
1204 Thumb code, and data. There are inline transitions between code
1205 and data at literal pool boundaries. There can also be inline
1206 transitions between ARM code and Thumb code, for example in
1207 ARM-Thumb inter-working veneers. Linkers, machine-level
1208 debuggers, profiling tools, and disassembly tools need to map
1209 images accurately. For example, setting an ARM breakpoint on a
1210 Thumb location, or in a literal pool, can crash the program
1211 being debugged, ruining the debugging session.
1212
1213 ARM ELF entities are mapped (see section 4.4.7.1 below) and
1214 tagged (see section 4.4.7.2 below) using local symbols (with
1215 binding STB_LOCAL). To assist consumers, mapping and tagging
1216 symbols should be collated first in the symbol table, before
1217 other symbols with binding STB_LOCAL.
1218
1219 To allow properly collated mapping and tagging symbols to be
1220 skipped by consumers that have no interest in them, the first
1221 such symbol should have the name $m and its st_value field equal
1222 to the total number of mapping and tagging symbols (including
1223 the $m) in the symbol table.
1224
1225 4.4.7.1 Mapping symbols
1226
1227 $a Labels the first byte of a sequence of ARM instructions.
1228 Its type is STT_FUNC.
1229
1230 $d Labels the first byte of a sequence of data items.
1231 Its type is STT_OBJECT.
1232
1233 $t Labels the first byte of a sequence of Thumb instructions.
1234 Its type is STT_FUNC.
1235
1236 This list of mapping symbols may be extended in the future.
1237
1238 Section-relative mapping symbols
1239
1240 Mapping symbols defined in a section define a sequence of
1241 half-open address intervals that cover the address range of the
1242 section. Each interval starts at the address defined by a
1243 mapping symbol, and continues up to, but not including, the
1244 address defined by the next (in address order) mapping symbol or
1245 the end of the section. A corollary is that there must be a
1246 mapping symbol defined at the beginning of each section.
1247 Consumers can ignore the size of a section-relative mapping
1248 symbol. Producers can set it to 0.
1249
1250 Absolute mapping symbols
1251
1252 Because of the need to crystallize a Thumb address with the
1253 Thumb-bit set, absolute symbol of type STT_FUNC (symbols of type
1254 STT_FUNC defined in section SHN_ABS) need to be mapped with $a
1255 or $t.
1256
1257 The extent of a mapping symbol defined in SHN_ABS is [st_value,
1258 st_value + st_size), or [st_value, st_value + 1) if st_size = 0,
1259 where [x, y) denotes the half-open address range from x,
1260 inclusive, to y, exclusive.
1261
1262 In the absence of a mapping symbol, a consumer can interpret a
1263 function symbol with an odd value as the Thumb code address
1264 obtained by clearing the least significant bit of the
1265 value. This interpretation is deprecated, and it may not work in
1266 the future.
1267
1268 Note - the Tagging symbols ($b, $f, $p $m) have been dropped from
1269 the EABI (which is still under development), so they are not
1270 implemented here. */
1271
1272 static enum mstate mapstate = MAP_UNDEFINED;
1273
1274 static void
1275 mapping_state (enum mstate state)
1276 {
1277 symbolS * symbolP;
1278 const char * symname;
1279 int type;
1280
1281 if (mapstate == state)
1282 /* The mapping symbol has already been emitted.
1283 There is nothing else to do. */
1284 return;
1285
1286 mapstate = state;
1287
1288 switch (state)
1289 {
1290 case MAP_DATA:
1291 symname = "$d";
1292 type = BSF_OBJECT;
1293 break;
1294 case MAP_ARM:
1295 symname = "$a";
1296 type = BSF_FUNCTION;
1297 break;
1298 case MAP_THUMB:
1299 symname = "$t";
1300 type = BSF_FUNCTION;
1301 break;
1302 case MAP_UNDEFINED:
1303 return;
1304 default:
1305 abort ();
1306 }
1307
1308 seg_info (now_seg)->tc_segment_info_data = state;
1309
1310 symbolP = symbol_new (symname, now_seg, (valueT) frag_now_fix (), frag_now);
1311 symbol_table_insert (symbolP);
1312 symbol_get_bfdsym (symbolP)->flags |= type | BSF_LOCAL;
1313
1314 switch (state)
1315 {
1316 case MAP_ARM:
1317 THUMB_SET_FUNC (symbolP, 0);
1318 ARM_SET_THUMB (symbolP, 0);
1319 ARM_SET_INTERWORK (symbolP, support_interwork);
1320 break;
1321
1322 case MAP_THUMB:
1323 THUMB_SET_FUNC (symbolP, 1);
1324 ARM_SET_THUMB (symbolP, 1);
1325 ARM_SET_INTERWORK (symbolP, support_interwork);
1326 break;
1327
1328 case MAP_DATA:
1329 default:
1330 return;
1331 }
1332 }
1333
1334 /* When we change sections we need to issue a new mapping symbol. */
1335
1336 void
1337 arm_elf_change_section (void)
1338 {
1339 flagword flags;
1340
1341 if (!SEG_NORMAL (now_seg))
1342 return;
1343
1344 flags = bfd_get_section_flags (stdoutput, now_seg);
1345
1346 /* We can ignore sections that only contain debug info. */
1347 if ((flags & SEC_ALLOC) == 0)
1348 return;
1349
1350 mapstate = seg_info (now_seg)->tc_segment_info_data;
1351 }
1352 #else
1353 #define mapping_state(a)
1354 #endif /* OBJ_ELF */
1355 \f
1356 /* arm_reg_parse () := if it looks like a register, return its token and
1357 advance the pointer. */
1358
1359 static int
1360 arm_reg_parse (char ** ccp, struct hash_control * htab)
1361 {
1362 char * start = * ccp;
1363 char c;
1364 char * p;
1365 struct reg_entry * reg;
1366
1367 #ifdef REGISTER_PREFIX
1368 if (*start != REGISTER_PREFIX)
1369 return FAIL;
1370 p = start + 1;
1371 #else
1372 p = start;
1373 #ifdef OPTIONAL_REGISTER_PREFIX
1374 if (*p == OPTIONAL_REGISTER_PREFIX)
1375 p++, start++;
1376 #endif
1377 #endif
1378 if (!ISALPHA (*p) || !is_name_beginner (*p))
1379 return FAIL;
1380
1381 c = *p++;
1382 while (ISALPHA (c) || ISDIGIT (c) || c == '_')
1383 c = *p++;
1384
1385 *--p = 0;
1386 reg = (struct reg_entry *) hash_find (htab, start);
1387 *p = c;
1388
1389 if (reg)
1390 {
1391 *ccp = p;
1392 return reg->number;
1393 }
1394
1395 return FAIL;
1396 }
1397
1398 /* Search for the following register name in each of the possible reg name
1399 tables. Return the classification if found, or REG_TYPE_MAX if not
1400 present. */
1401
1402 static enum arm_reg_type
1403 arm_reg_parse_any (char *cp)
1404 {
1405 int i;
1406
1407 for (i = (int) REG_TYPE_FIRST; i < (int) REG_TYPE_MAX; i++)
1408 if (arm_reg_parse (&cp, all_reg_maps[i].htab) != FAIL)
1409 return (enum arm_reg_type) i;
1410
1411 return REG_TYPE_MAX;
1412 }
1413
1414 static void
1415 opcode_select (int width)
1416 {
1417 switch (width)
1418 {
1419 case 16:
1420 if (! thumb_mode)
1421 {
1422 if (! (cpu_variant & ARM_EXT_V4T))
1423 as_bad (_("selected processor does not support THUMB opcodes"));
1424
1425 thumb_mode = 1;
1426 /* No need to force the alignment, since we will have been
1427 coming from ARM mode, which is word-aligned. */
1428 record_alignment (now_seg, 1);
1429 }
1430 mapping_state (MAP_THUMB);
1431 break;
1432
1433 case 32:
1434 if (thumb_mode)
1435 {
1436 if ((cpu_variant & ARM_ALL) == ARM_EXT_V4T)
1437 as_bad (_("selected processor does not support ARM opcodes"));
1438
1439 thumb_mode = 0;
1440
1441 if (!need_pass_2)
1442 frag_align (2, 0, 0);
1443
1444 record_alignment (now_seg, 1);
1445 }
1446 mapping_state (MAP_ARM);
1447 break;
1448
1449 default:
1450 as_bad (_("invalid instruction size selected (%d)"), width);
1451 }
1452 }
1453
1454 static void
1455 s_req (int a ATTRIBUTE_UNUSED)
1456 {
1457 as_bad (_("invalid syntax for .req directive"));
1458 }
1459
1460 /* The .unreq directive deletes an alias which was previously defined
1461 by .req. For example:
1462
1463 my_alias .req r11
1464 .unreq my_alias */
1465
1466 static void
1467 s_unreq (int a ATTRIBUTE_UNUSED)
1468 {
1469 char * name;
1470 char saved_char;
1471
1472 skip_whitespace (input_line_pointer);
1473 name = input_line_pointer;
1474
1475 while (*input_line_pointer != 0
1476 && *input_line_pointer != ' '
1477 && *input_line_pointer != '\n')
1478 ++input_line_pointer;
1479
1480 saved_char = *input_line_pointer;
1481 *input_line_pointer = 0;
1482
1483 if (*name)
1484 {
1485 enum arm_reg_type req_type = arm_reg_parse_any (name);
1486
1487 if (req_type != REG_TYPE_MAX)
1488 {
1489 char *temp_name = name;
1490 int req_no = arm_reg_parse (&temp_name, all_reg_maps[req_type].htab);
1491
1492 if (req_no != FAIL)
1493 {
1494 struct reg_entry *req_entry;
1495
1496 /* Check to see if this alias is a builtin one. */
1497 req_entry = hash_delete (all_reg_maps[req_type].htab, name);
1498
1499 if (!req_entry)
1500 as_bad (_("unreq: missing hash entry for \"%s\""), name);
1501 else if (req_entry->builtin)
1502 /* FIXME: We are deleting a built in register alias which
1503 points to a const data structure, so we only need to
1504 free up the memory used by the key in the hash table.
1505 Unfortunately we have not recorded this value, so this
1506 is a memory leak. */
1507 /* FIXME: Should we issue a warning message ? */
1508 ;
1509 else
1510 {
1511 /* Deleting a user defined alias. We need to free the
1512 key and the value, but fortunately the key is the same
1513 as the value->name field. */
1514 free ((char *) req_entry->name);
1515 free (req_entry);
1516 }
1517 }
1518 else
1519 as_bad (_(".unreq: unrecognized symbol \"%s\""), name);
1520 }
1521 else
1522 as_bad (_(".unreq: unrecognized symbol \"%s\""), name);
1523 }
1524 else
1525 as_bad (_("invalid syntax for .unreq directive"));
1526
1527 *input_line_pointer = saved_char;
1528 demand_empty_rest_of_line ();
1529 }
1530
1531 static void
1532 s_bss (int ignore ATTRIBUTE_UNUSED)
1533 {
1534 /* We don't support putting frags in the BSS segment, we fake it by
1535 marking in_bss, then looking at s_skip for clues. */
1536 subseg_set (bss_section, 0);
1537 demand_empty_rest_of_line ();
1538 mapping_state (MAP_DATA);
1539 }
1540
1541 static void
1542 s_even (int ignore ATTRIBUTE_UNUSED)
1543 {
1544 /* Never make frag if expect extra pass. */
1545 if (!need_pass_2)
1546 frag_align (1, 0, 0);
1547
1548 record_alignment (now_seg, 1);
1549
1550 demand_empty_rest_of_line ();
1551 }
1552
1553 static void
1554 s_ltorg (int ignored ATTRIBUTE_UNUSED)
1555 {
1556 unsigned int entry;
1557 literal_pool * pool;
1558 char sym_name[20];
1559
1560 pool = find_literal_pool ();
1561 if (pool == NULL
1562 || pool->symbol == NULL
1563 || pool->next_free_entry == 0)
1564 return;
1565
1566 mapping_state (MAP_DATA);
1567
1568 /* Align pool as you have word accesses.
1569 Only make a frag if we have to. */
1570 if (!need_pass_2)
1571 frag_align (2, 0, 0);
1572
1573 record_alignment (now_seg, 2);
1574
1575 sprintf (sym_name, "$$lit_\002%x", pool->id);
1576
1577 symbol_locate (pool->symbol, sym_name, now_seg,
1578 (valueT) frag_now_fix (), frag_now);
1579 symbol_table_insert (pool->symbol);
1580
1581 ARM_SET_THUMB (pool->symbol, thumb_mode);
1582
1583 #if defined OBJ_COFF || defined OBJ_ELF
1584 ARM_SET_INTERWORK (pool->symbol, support_interwork);
1585 #endif
1586
1587 for (entry = 0; entry < pool->next_free_entry; entry ++)
1588 /* First output the expression in the instruction to the pool. */
1589 emit_expr (&(pool->literals[entry]), 4); /* .word */
1590
1591 /* Mark the pool as empty. */
1592 pool->next_free_entry = 0;
1593 pool->symbol = NULL;
1594 }
1595
1596 /* Same as s_align_ptwo but align 0 => align 2. */
1597
1598 static void
1599 s_align (int unused ATTRIBUTE_UNUSED)
1600 {
1601 int temp;
1602 long temp_fill;
1603 long max_alignment = 15;
1604
1605 temp = get_absolute_expression ();
1606 if (temp > max_alignment)
1607 as_bad (_("alignment too large: %d assumed"), temp = max_alignment);
1608 else if (temp < 0)
1609 {
1610 as_bad (_("alignment negative. 0 assumed."));
1611 temp = 0;
1612 }
1613
1614 if (*input_line_pointer == ',')
1615 {
1616 input_line_pointer++;
1617 temp_fill = get_absolute_expression ();
1618 }
1619 else
1620 temp_fill = 0;
1621
1622 if (!temp)
1623 temp = 2;
1624
1625 /* Only make a frag if we HAVE to. */
1626 if (temp && !need_pass_2)
1627 frag_align (temp, (int) temp_fill, 0);
1628 demand_empty_rest_of_line ();
1629
1630 record_alignment (now_seg, temp);
1631 }
1632
1633 static void
1634 s_force_thumb (int ignore ATTRIBUTE_UNUSED)
1635 {
1636 /* If we are not already in thumb mode go into it, EVEN if
1637 the target processor does not support thumb instructions.
1638 This is used by gcc/config/arm/lib1funcs.asm for example
1639 to compile interworking support functions even if the
1640 target processor should not support interworking. */
1641 if (! thumb_mode)
1642 {
1643 thumb_mode = 2;
1644
1645 record_alignment (now_seg, 1);
1646 }
1647
1648 demand_empty_rest_of_line ();
1649 }
1650
1651 static void
1652 s_thumb_func (int ignore ATTRIBUTE_UNUSED)
1653 {
1654 if (! thumb_mode)
1655 opcode_select (16);
1656
1657 /* The following label is the name/address of the start of a Thumb function.
1658 We need to know this for the interworking support. */
1659 label_is_thumb_function_name = TRUE;
1660
1661 demand_empty_rest_of_line ();
1662 }
1663
1664 /* Perform a .set directive, but also mark the alias as
1665 being a thumb function. */
1666
1667 static void
1668 s_thumb_set (int equiv)
1669 {
1670 /* XXX the following is a duplicate of the code for s_set() in read.c
1671 We cannot just call that code as we need to get at the symbol that
1672 is created. */
1673 char * name;
1674 char delim;
1675 char * end_name;
1676 symbolS * symbolP;
1677
1678 /* Especial apologies for the random logic:
1679 This just grew, and could be parsed much more simply!
1680 Dean - in haste. */
1681 name = input_line_pointer;
1682 delim = get_symbol_end ();
1683 end_name = input_line_pointer;
1684 *end_name = delim;
1685
1686 SKIP_WHITESPACE ();
1687
1688 if (*input_line_pointer != ',')
1689 {
1690 *end_name = 0;
1691 as_bad (_("expected comma after name \"%s\""), name);
1692 *end_name = delim;
1693 ignore_rest_of_line ();
1694 return;
1695 }
1696
1697 input_line_pointer++;
1698 *end_name = 0;
1699
1700 if (name[0] == '.' && name[1] == '\0')
1701 {
1702 /* XXX - this should not happen to .thumb_set. */
1703 abort ();
1704 }
1705
1706 if ((symbolP = symbol_find (name)) == NULL
1707 && (symbolP = md_undefined_symbol (name)) == NULL)
1708 {
1709 #ifndef NO_LISTING
1710 /* When doing symbol listings, play games with dummy fragments living
1711 outside the normal fragment chain to record the file and line info
1712 for this symbol. */
1713 if (listing & LISTING_SYMBOLS)
1714 {
1715 extern struct list_info_struct * listing_tail;
1716 fragS * dummy_frag = xmalloc (sizeof (fragS));
1717
1718 memset (dummy_frag, 0, sizeof (fragS));
1719 dummy_frag->fr_type = rs_fill;
1720 dummy_frag->line = listing_tail;
1721 symbolP = symbol_new (name, undefined_section, 0, dummy_frag);
1722 dummy_frag->fr_symbol = symbolP;
1723 }
1724 else
1725 #endif
1726 symbolP = symbol_new (name, undefined_section, 0, &zero_address_frag);
1727
1728 #ifdef OBJ_COFF
1729 /* "set" symbols are local unless otherwise specified. */
1730 SF_SET_LOCAL (symbolP);
1731 #endif /* OBJ_COFF */
1732 } /* Make a new symbol. */
1733
1734 symbol_table_insert (symbolP);
1735
1736 * end_name = delim;
1737
1738 if (equiv
1739 && S_IS_DEFINED (symbolP)
1740 && S_GET_SEGMENT (symbolP) != reg_section)
1741 as_bad (_("symbol `%s' already defined"), S_GET_NAME (symbolP));
1742
1743 pseudo_set (symbolP);
1744
1745 demand_empty_rest_of_line ();
1746
1747 /* XXX Now we come to the Thumb specific bit of code. */
1748
1749 THUMB_SET_FUNC (symbolP, 1);
1750 ARM_SET_THUMB (symbolP, 1);
1751 #if defined OBJ_ELF || defined OBJ_COFF
1752 ARM_SET_INTERWORK (symbolP, support_interwork);
1753 #endif
1754 }
1755
1756 static void
1757 s_arm (int ignore ATTRIBUTE_UNUSED)
1758 {
1759 opcode_select (32);
1760 demand_empty_rest_of_line ();
1761 }
1762
1763 static void
1764 s_thumb (int ignore ATTRIBUTE_UNUSED)
1765 {
1766 opcode_select (16);
1767 demand_empty_rest_of_line ();
1768 }
1769
1770 static void
1771 s_code (int unused ATTRIBUTE_UNUSED)
1772 {
1773 int temp;
1774
1775 temp = get_absolute_expression ();
1776 switch (temp)
1777 {
1778 case 16:
1779 case 32:
1780 opcode_select (temp);
1781 break;
1782
1783 default:
1784 as_bad (_("invalid operand to .code directive (%d) (expecting 16 or 32)"), temp);
1785 }
1786 }
1787
1788 static void
1789 end_of_line (char * str)
1790 {
1791 skip_whitespace (str);
1792
1793 if (*str != '\0' && !inst.error)
1794 inst.error = _("garbage following instruction");
1795 }
1796
1797 static int
1798 skip_past_comma (char ** str)
1799 {
1800 char * p = * str, c;
1801 int comma = 0;
1802
1803 while ((c = *p) == ' ' || c == ',')
1804 {
1805 p++;
1806 if (c == ',' && comma++)
1807 return FAIL;
1808 }
1809
1810 if (c == '\0')
1811 return FAIL;
1812
1813 *str = p;
1814 return comma ? SUCCESS : FAIL;
1815 }
1816
1817 /* Return TRUE if anything in the expression is a bignum. */
1818
1819 static int
1820 walk_no_bignums (symbolS * sp)
1821 {
1822 if (symbol_get_value_expression (sp)->X_op == O_big)
1823 return 1;
1824
1825 if (symbol_get_value_expression (sp)->X_add_symbol)
1826 {
1827 return (walk_no_bignums (symbol_get_value_expression (sp)->X_add_symbol)
1828 || (symbol_get_value_expression (sp)->X_op_symbol
1829 && walk_no_bignums (symbol_get_value_expression (sp)->X_op_symbol)));
1830 }
1831
1832 return 0;
1833 }
1834
1835 static int in_my_get_expression = 0;
1836
1837 static int
1838 my_get_expression (expressionS * ep, char ** str)
1839 {
1840 char * save_in;
1841 segT seg;
1842
1843 save_in = input_line_pointer;
1844 input_line_pointer = *str;
1845 in_my_get_expression = 1;
1846 seg = expression (ep);
1847 in_my_get_expression = 0;
1848
1849 if (ep->X_op == O_illegal)
1850 {
1851 /* We found a bad expression in md_operand(). */
1852 *str = input_line_pointer;
1853 input_line_pointer = save_in;
1854 return 1;
1855 }
1856
1857 #ifdef OBJ_AOUT
1858 if (seg != absolute_section
1859 && seg != text_section
1860 && seg != data_section
1861 && seg != bss_section
1862 && seg != undefined_section)
1863 {
1864 inst.error = _("bad_segment");
1865 *str = input_line_pointer;
1866 input_line_pointer = save_in;
1867 return 1;
1868 }
1869 #endif
1870
1871 /* Get rid of any bignums now, so that we don't generate an error for which
1872 we can't establish a line number later on. Big numbers are never valid
1873 in instructions, which is where this routine is always called. */
1874 if (ep->X_op == O_big
1875 || (ep->X_add_symbol
1876 && (walk_no_bignums (ep->X_add_symbol)
1877 || (ep->X_op_symbol
1878 && walk_no_bignums (ep->X_op_symbol)))))
1879 {
1880 inst.error = _("invalid constant");
1881 *str = input_line_pointer;
1882 input_line_pointer = save_in;
1883 return 1;
1884 }
1885
1886 *str = input_line_pointer;
1887 input_line_pointer = save_in;
1888 return 0;
1889 }
1890
1891 /* A standard register must be given at this point.
1892 SHIFT is the place to put it in inst.instruction.
1893 Restores input start point on error.
1894 Returns the reg#, or FAIL. */
1895
1896 static int
1897 reg_required_here (char ** str, int shift)
1898 {
1899 static char buff [128]; /* XXX */
1900 int reg;
1901 char * start = * str;
1902
1903 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_RN].htab)) != FAIL)
1904 {
1905 if (shift >= 0)
1906 inst.instruction |= reg << shift;
1907 return reg;
1908 }
1909
1910 /* Restore the start point, we may have got a reg of the wrong class. */
1911 *str = start;
1912
1913 /* In the few cases where we might be able to accept something else
1914 this error can be overridden. */
1915 sprintf (buff, _("register expected, not '%.100s'"), start);
1916 inst.error = buff;
1917
1918 return FAIL;
1919 }
1920
1921 /* A Intel Wireless MMX technology register
1922 must be given at this point.
1923 Shift is the place to put it in inst.instruction.
1924 Restores input start point on err.
1925 Returns the reg#, or FAIL. */
1926
1927 static int
1928 wreg_required_here (char ** str,
1929 int shift,
1930 enum wreg_type reg_type)
1931 {
1932 static char buff [128];
1933 int reg;
1934 char * start = *str;
1935
1936 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_IWMMXT].htab)) != FAIL)
1937 {
1938 if (wr_register (reg)
1939 && (reg_type == IWMMXT_REG_WR || reg_type == IWMMXT_REG_WR_OR_WC))
1940 {
1941 if (shift >= 0)
1942 inst.instruction |= (reg ^ WR_PREFIX) << shift;
1943 return reg;
1944 }
1945 else if (wc_register (reg)
1946 && (reg_type == IWMMXT_REG_WC || reg_type == IWMMXT_REG_WR_OR_WC))
1947 {
1948 if (shift >= 0)
1949 inst.instruction |= (reg ^ WC_PREFIX) << shift;
1950 return reg;
1951 }
1952 else if ((wcg_register (reg) && reg_type == IWMMXT_REG_WCG))
1953 {
1954 if (shift >= 0)
1955 inst.instruction |= ((reg ^ WC_PREFIX) - 8) << shift;
1956 return reg;
1957 }
1958 }
1959
1960 /* Restore the start point, we may have got a reg of the wrong class. */
1961 *str = start;
1962
1963 /* In the few cases where we might be able to accept
1964 something else this error can be overridden. */
1965 sprintf (buff, _("Intel Wireless MMX technology register expected, not '%.100s'"), start);
1966 inst.error = buff;
1967
1968 return FAIL;
1969 }
1970
1971 static const struct asm_psr *
1972 arm_psr_parse (char ** ccp)
1973 {
1974 char * start = * ccp;
1975 char c;
1976 char * p;
1977 const struct asm_psr * psr;
1978
1979 p = start;
1980
1981 /* Skip to the end of the next word in the input stream. */
1982 do
1983 {
1984 c = *p++;
1985 }
1986 while (ISALPHA (c) || c == '_');
1987
1988 /* Terminate the word. */
1989 *--p = 0;
1990
1991 /* CPSR's and SPSR's can now be lowercase. This is just a convenience
1992 feature for ease of use and backwards compatibility. */
1993 if (!strncmp (start, "cpsr", 4))
1994 strncpy (start, "CPSR", 4);
1995 else if (!strncmp (start, "spsr", 4))
1996 strncpy (start, "SPSR", 4);
1997
1998 /* Now locate the word in the psr hash table. */
1999 psr = (const struct asm_psr *) hash_find (arm_psr_hsh, start);
2000
2001 /* Restore the input stream. */
2002 *p = c;
2003
2004 /* If we found a valid match, advance the
2005 stream pointer past the end of the word. */
2006 *ccp = p;
2007
2008 return psr;
2009 }
2010
2011 /* Parse the input looking for a PSR flag. */
2012
2013 static int
2014 psr_required_here (char ** str)
2015 {
2016 char * start = * str;
2017 const struct asm_psr * psr;
2018
2019 psr = arm_psr_parse (str);
2020
2021 if (psr)
2022 {
2023 /* If this is the SPSR that is being modified, set the R bit. */
2024 if (! psr->cpsr)
2025 inst.instruction |= SPSR_BIT;
2026
2027 /* Set the psr flags in the MSR instruction. */
2028 inst.instruction |= psr->field << PSR_SHIFT;
2029
2030 return SUCCESS;
2031 }
2032
2033 /* In the few cases where we might be able to accept
2034 something else this error can be overridden. */
2035 inst.error = _("flag for {c}psr instruction expected");
2036
2037 /* Restore the start point. */
2038 *str = start;
2039 return FAIL;
2040 }
2041
2042 static int
2043 co_proc_number (char ** str)
2044 {
2045 int processor, pchar;
2046 char *start;
2047
2048 skip_whitespace (*str);
2049 start = *str;
2050
2051 /* The data sheet seems to imply that just a number on its own is valid
2052 here, but the RISC iX assembler seems to accept a prefix 'p'. We will
2053 accept either. */
2054 if ((processor = arm_reg_parse (str, all_reg_maps[REG_TYPE_CP].htab))
2055 == FAIL)
2056 {
2057 *str = start;
2058
2059 pchar = *(*str)++;
2060 if (pchar >= '0' && pchar <= '9')
2061 {
2062 processor = pchar - '0';
2063 if (**str >= '0' && **str <= '9')
2064 {
2065 processor = processor * 10 + *(*str)++ - '0';
2066 if (processor > 15)
2067 {
2068 inst.error = _("illegal co-processor number");
2069 return FAIL;
2070 }
2071 }
2072 }
2073 else
2074 {
2075 inst.error = all_reg_maps[REG_TYPE_CP].expected;
2076 return FAIL;
2077 }
2078 }
2079
2080 inst.instruction |= processor << 8;
2081 return SUCCESS;
2082 }
2083
2084 static int
2085 cp_opc_expr (char ** str, int where, int length)
2086 {
2087 expressionS expr;
2088
2089 skip_whitespace (* str);
2090
2091 memset (&expr, '\0', sizeof (expr));
2092
2093 if (my_get_expression (&expr, str))
2094 return FAIL;
2095 if (expr.X_op != O_constant)
2096 {
2097 inst.error = _("bad or missing expression");
2098 return FAIL;
2099 }
2100
2101 if ((expr.X_add_number & ((1 << length) - 1)) != expr.X_add_number)
2102 {
2103 inst.error = _("immediate co-processor expression too large");
2104 return FAIL;
2105 }
2106
2107 inst.instruction |= expr.X_add_number << where;
2108 return SUCCESS;
2109 }
2110
2111 static int
2112 cp_reg_required_here (char ** str, int where)
2113 {
2114 int reg;
2115 char * start = *str;
2116
2117 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_CN].htab)) != FAIL)
2118 {
2119 inst.instruction |= reg << where;
2120 return reg;
2121 }
2122
2123 /* In the few cases where we might be able to accept something else
2124 this error can be overridden. */
2125 inst.error = all_reg_maps[REG_TYPE_CN].expected;
2126
2127 /* Restore the start point. */
2128 *str = start;
2129 return FAIL;
2130 }
2131
2132 static int
2133 fp_reg_required_here (char ** str, int where)
2134 {
2135 int reg;
2136 char * start = * str;
2137
2138 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_FN].htab)) != FAIL)
2139 {
2140 inst.instruction |= reg << where;
2141 return reg;
2142 }
2143
2144 /* In the few cases where we might be able to accept something else
2145 this error can be overridden. */
2146 inst.error = all_reg_maps[REG_TYPE_FN].expected;
2147
2148 /* Restore the start point. */
2149 *str = start;
2150 return FAIL;
2151 }
2152
2153 static int
2154 cp_address_offset (char ** str)
2155 {
2156 int offset;
2157
2158 skip_whitespace (* str);
2159
2160 if (! is_immediate_prefix (**str))
2161 {
2162 inst.error = _("immediate expression expected");
2163 return FAIL;
2164 }
2165
2166 (*str)++;
2167
2168 if (my_get_expression (& inst.reloc.exp, str))
2169 return FAIL;
2170
2171 if (inst.reloc.exp.X_op == O_constant)
2172 {
2173 offset = inst.reloc.exp.X_add_number;
2174
2175 if (offset & 3)
2176 {
2177 inst.error = _("co-processor address must be word aligned");
2178 return FAIL;
2179 }
2180
2181 if (offset > 1023 || offset < -1023)
2182 {
2183 inst.error = _("offset too large");
2184 return FAIL;
2185 }
2186
2187 if (offset >= 0)
2188 inst.instruction |= INDEX_UP;
2189 else
2190 offset = -offset;
2191
2192 inst.instruction |= offset >> 2;
2193 }
2194 else
2195 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
2196
2197 return SUCCESS;
2198 }
2199
2200 static int
2201 cp_address_required_here (char ** str, int wb_ok)
2202 {
2203 char * p = * str;
2204 int pre_inc = 0;
2205 int write_back = 0;
2206
2207 if (*p == '[')
2208 {
2209 int reg;
2210
2211 p++;
2212 skip_whitespace (p);
2213
2214 if ((reg = reg_required_here (& p, 16)) == FAIL)
2215 return FAIL;
2216
2217 skip_whitespace (p);
2218
2219 if (*p == ']')
2220 {
2221 p++;
2222
2223 skip_whitespace (p);
2224
2225 if (*p == '\0')
2226 {
2227 /* As an extension to the official ARM syntax we allow:
2228 [Rn]
2229 as a short hand for:
2230 [Rn,#0] */
2231 inst.instruction |= PRE_INDEX | INDEX_UP;
2232 *str = p;
2233 return SUCCESS;
2234 }
2235
2236 if (skip_past_comma (& p) == FAIL)
2237 {
2238 inst.error = _("comma expected after closing square bracket");
2239 return FAIL;
2240 }
2241
2242 skip_whitespace (p);
2243
2244 if (*p == '#')
2245 {
2246 if (wb_ok)
2247 {
2248 /* [Rn], #expr */
2249 write_back = WRITE_BACK;
2250
2251 if (reg == REG_PC)
2252 {
2253 inst.error = _("pc may not be used in post-increment");
2254 return FAIL;
2255 }
2256
2257 if (cp_address_offset (& p) == FAIL)
2258 return FAIL;
2259 }
2260 else
2261 pre_inc = PRE_INDEX | INDEX_UP;
2262 }
2263 else if (*p == '{')
2264 {
2265 int option;
2266
2267 /* [Rn], {<expr>} */
2268 p++;
2269
2270 skip_whitespace (p);
2271
2272 if (my_get_expression (& inst.reloc.exp, & p))
2273 return FAIL;
2274
2275 if (inst.reloc.exp.X_op == O_constant)
2276 {
2277 option = inst.reloc.exp.X_add_number;
2278
2279 if (option > 255 || option < 0)
2280 {
2281 inst.error = _("'option' field too large");
2282 return FAIL;
2283 }
2284
2285 skip_whitespace (p);
2286
2287 if (*p != '}')
2288 {
2289 inst.error = _("'}' expected at end of 'option' field");
2290 return FAIL;
2291 }
2292 else
2293 {
2294 p++;
2295 inst.instruction |= option;
2296 inst.instruction |= INDEX_UP;
2297 }
2298 }
2299 else
2300 {
2301 inst.error = _("non-constant expressions for 'option' field not supported");
2302 return FAIL;
2303 }
2304 }
2305 else
2306 {
2307 inst.error = _("# or { expected after comma");
2308 return FAIL;
2309 }
2310 }
2311 else
2312 {
2313 /* '['Rn, #expr']'[!] */
2314
2315 if (skip_past_comma (& p) == FAIL)
2316 {
2317 inst.error = _("pre-indexed expression expected");
2318 return FAIL;
2319 }
2320
2321 pre_inc = PRE_INDEX;
2322
2323 if (cp_address_offset (& p) == FAIL)
2324 return FAIL;
2325
2326 skip_whitespace (p);
2327
2328 if (*p++ != ']')
2329 {
2330 inst.error = _("missing ]");
2331 return FAIL;
2332 }
2333
2334 skip_whitespace (p);
2335
2336 if (wb_ok && *p == '!')
2337 {
2338 if (reg == REG_PC)
2339 {
2340 inst.error = _("pc may not be used with write-back");
2341 return FAIL;
2342 }
2343
2344 p++;
2345 write_back = WRITE_BACK;
2346 }
2347 }
2348 }
2349 else
2350 {
2351 if (my_get_expression (&inst.reloc.exp, &p))
2352 return FAIL;
2353
2354 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
2355 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
2356 inst.reloc.pc_rel = 1;
2357 inst.instruction |= (REG_PC << 16);
2358 pre_inc = PRE_INDEX;
2359 }
2360
2361 inst.instruction |= write_back | pre_inc;
2362 *str = p;
2363 return SUCCESS;
2364 }
2365
2366 static int
2367 cp_byte_address_offset (char ** str)
2368 {
2369 int offset;
2370
2371 skip_whitespace (* str);
2372
2373 if (! is_immediate_prefix (**str))
2374 {
2375 inst.error = _("immediate expression expected");
2376 return FAIL;
2377 }
2378
2379 (*str)++;
2380
2381 if (my_get_expression (& inst.reloc.exp, str))
2382 return FAIL;
2383
2384 if (inst.reloc.exp.X_op == O_constant)
2385 {
2386 offset = inst.reloc.exp.X_add_number;
2387
2388 if (offset > 255 || offset < -255)
2389 {
2390 inst.error = _("offset too large");
2391 return FAIL;
2392 }
2393
2394 if (offset >= 0)
2395 inst.instruction |= INDEX_UP;
2396 else
2397 offset = -offset;
2398
2399 inst.instruction |= offset;
2400 }
2401 else
2402 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM_S2;
2403
2404 return SUCCESS;
2405 }
2406
2407 static int
2408 cp_byte_address_required_here (char ** str)
2409 {
2410 char * p = * str;
2411 int pre_inc = 0;
2412 int write_back = 0;
2413
2414 if (*p == '[')
2415 {
2416 int reg;
2417
2418 p++;
2419 skip_whitespace (p);
2420
2421 if ((reg = reg_required_here (& p, 16)) == FAIL)
2422 return FAIL;
2423
2424 skip_whitespace (p);
2425
2426 if (*p == ']')
2427 {
2428 p++;
2429
2430 if (skip_past_comma (& p) == SUCCESS)
2431 {
2432 /* [Rn], #expr */
2433 write_back = WRITE_BACK;
2434
2435 if (reg == REG_PC)
2436 {
2437 inst.error = _("pc may not be used in post-increment");
2438 return FAIL;
2439 }
2440
2441 if (cp_byte_address_offset (& p) == FAIL)
2442 return FAIL;
2443 }
2444 else
2445 pre_inc = PRE_INDEX | INDEX_UP;
2446 }
2447 else
2448 {
2449 /* '['Rn, #expr']'[!] */
2450
2451 if (skip_past_comma (& p) == FAIL)
2452 {
2453 inst.error = _("pre-indexed expression expected");
2454 return FAIL;
2455 }
2456
2457 pre_inc = PRE_INDEX;
2458
2459 if (cp_byte_address_offset (& p) == FAIL)
2460 return FAIL;
2461
2462 skip_whitespace (p);
2463
2464 if (*p++ != ']')
2465 {
2466 inst.error = _("missing ]");
2467 return FAIL;
2468 }
2469
2470 skip_whitespace (p);
2471
2472 if (*p == '!')
2473 {
2474 if (reg == REG_PC)
2475 {
2476 inst.error = _("pc may not be used with write-back");
2477 return FAIL;
2478 }
2479
2480 p++;
2481 write_back = WRITE_BACK;
2482 }
2483 }
2484 }
2485 else
2486 {
2487 if (my_get_expression (&inst.reloc.exp, &p))
2488 return FAIL;
2489
2490 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM_S2;
2491 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
2492 inst.reloc.pc_rel = 1;
2493 inst.instruction |= (REG_PC << 16);
2494 pre_inc = PRE_INDEX;
2495 }
2496
2497 inst.instruction |= write_back | pre_inc;
2498 *str = p;
2499 return SUCCESS;
2500 }
2501
2502 static void
2503 do_nop (char * str)
2504 {
2505 skip_whitespace (str);
2506 if (*str == '{')
2507 {
2508 str++;
2509
2510 if (my_get_expression (&inst.reloc.exp, &str))
2511 inst.reloc.exp.X_op = O_illegal;
2512 else
2513 {
2514 skip_whitespace (str);
2515 if (*str == '}')
2516 str++;
2517 else
2518 inst.reloc.exp.X_op = O_illegal;
2519 }
2520
2521 if (inst.reloc.exp.X_op != O_constant
2522 || inst.reloc.exp.X_add_number > 255
2523 || inst.reloc.exp.X_add_number < 0)
2524 {
2525 inst.error = _("Invalid NOP hint");
2526 return;
2527 }
2528
2529 /* Arcitectural NOP hints are CPSR sets with no bits selected. */
2530 inst.instruction &= 0xf0000000;
2531 inst.instruction |= 0x0320f000 + inst.reloc.exp.X_add_number;
2532 }
2533
2534 end_of_line (str);
2535 }
2536
2537 static void
2538 do_empty (char * str)
2539 {
2540 /* Do nothing really. */
2541 end_of_line (str);
2542 }
2543
2544 static void
2545 do_mrs (char * str)
2546 {
2547 int skip = 0;
2548
2549 /* Only one syntax. */
2550 skip_whitespace (str);
2551
2552 if (reg_required_here (&str, 12) == FAIL)
2553 {
2554 inst.error = BAD_ARGS;
2555 return;
2556 }
2557
2558 if (skip_past_comma (&str) == FAIL)
2559 {
2560 inst.error = _("comma expected after register name");
2561 return;
2562 }
2563
2564 skip_whitespace (str);
2565
2566 if ( streq (str, "CPSR")
2567 || streq (str, "SPSR")
2568 /* Lower case versions for backwards compatibility. */
2569 || streq (str, "cpsr")
2570 || streq (str, "spsr"))
2571 skip = 4;
2572
2573 /* This is for backwards compatibility with older toolchains. */
2574 else if ( streq (str, "cpsr_all")
2575 || streq (str, "spsr_all"))
2576 skip = 8;
2577 else
2578 {
2579 inst.error = _("CPSR or SPSR expected");
2580 return;
2581 }
2582
2583 if (* str == 's' || * str == 'S')
2584 inst.instruction |= SPSR_BIT;
2585 str += skip;
2586
2587 end_of_line (str);
2588 }
2589
2590 /* Two possible forms:
2591 "{C|S}PSR_<field>, Rm",
2592 "{C|S}PSR_f, #expression". */
2593
2594 static void
2595 do_msr (char * str)
2596 {
2597 skip_whitespace (str);
2598
2599 if (psr_required_here (& str) == FAIL)
2600 return;
2601
2602 if (skip_past_comma (& str) == FAIL)
2603 {
2604 inst.error = _("comma missing after psr flags");
2605 return;
2606 }
2607
2608 skip_whitespace (str);
2609
2610 if (reg_required_here (& str, 0) != FAIL)
2611 {
2612 inst.error = NULL;
2613 end_of_line (str);
2614 return;
2615 }
2616
2617 if (! is_immediate_prefix (* str))
2618 {
2619 inst.error =
2620 _("only a register or immediate value can follow a psr flag");
2621 return;
2622 }
2623
2624 str ++;
2625 inst.error = NULL;
2626
2627 if (my_get_expression (& inst.reloc.exp, & str))
2628 {
2629 inst.error =
2630 _("only a register or immediate value can follow a psr flag");
2631 return;
2632 }
2633
2634 #if 0 /* The first edition of the ARM architecture manual stated that
2635 writing anything other than the flags with an immediate operation
2636 had UNPREDICTABLE effects. This constraint was removed in the
2637 second edition of the specification. */
2638 if ((cpu_variant & ARM_EXT_V5) != ARM_EXT_V5
2639 && inst.instruction & ((PSR_c | PSR_x | PSR_s) << PSR_SHIFT))
2640 {
2641 inst.error = _("immediate value cannot be used to set this field");
2642 return;
2643 }
2644 #endif
2645
2646 inst.instruction |= INST_IMMEDIATE;
2647
2648 if (inst.reloc.exp.X_add_symbol)
2649 {
2650 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
2651 inst.reloc.pc_rel = 0;
2652 }
2653 else
2654 {
2655 unsigned value = validate_immediate (inst.reloc.exp.X_add_number);
2656
2657 if (value == (unsigned) FAIL)
2658 {
2659 inst.error = _("invalid constant");
2660 return;
2661 }
2662
2663 inst.instruction |= value;
2664 }
2665
2666 inst.error = NULL;
2667 end_of_line (str);
2668 }
2669
2670 /* Long Multiply Parser
2671 UMULL RdLo, RdHi, Rm, Rs
2672 SMULL RdLo, RdHi, Rm, Rs
2673 UMLAL RdLo, RdHi, Rm, Rs
2674 SMLAL RdLo, RdHi, Rm, Rs. */
2675
2676 static void
2677 do_mull (char * str)
2678 {
2679 int rdlo, rdhi, rm, rs;
2680
2681 /* Only one format "rdlo, rdhi, rm, rs". */
2682 skip_whitespace (str);
2683
2684 if ((rdlo = reg_required_here (&str, 12)) == FAIL)
2685 {
2686 inst.error = BAD_ARGS;
2687 return;
2688 }
2689
2690 if (skip_past_comma (&str) == FAIL
2691 || (rdhi = reg_required_here (&str, 16)) == FAIL)
2692 {
2693 inst.error = BAD_ARGS;
2694 return;
2695 }
2696
2697 if (skip_past_comma (&str) == FAIL
2698 || (rm = reg_required_here (&str, 0)) == FAIL)
2699 {
2700 inst.error = BAD_ARGS;
2701 return;
2702 }
2703
2704 /* rdhi, rdlo and rm must all be different. */
2705 if (rdlo == rdhi || rdlo == rm || rdhi == rm)
2706 as_tsktsk (_("rdhi, rdlo and rm must all be different"));
2707
2708 if (skip_past_comma (&str) == FAIL
2709 || (rs = reg_required_here (&str, 8)) == FAIL)
2710 {
2711 inst.error = BAD_ARGS;
2712 return;
2713 }
2714
2715 if (rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC)
2716 {
2717 inst.error = BAD_PC;
2718 return;
2719 }
2720
2721 end_of_line (str);
2722 }
2723
2724 static void
2725 do_mul (char * str)
2726 {
2727 int rd, rm;
2728
2729 /* Only one format "rd, rm, rs". */
2730 skip_whitespace (str);
2731
2732 if ((rd = reg_required_here (&str, 16)) == FAIL)
2733 {
2734 inst.error = BAD_ARGS;
2735 return;
2736 }
2737
2738 if (rd == REG_PC)
2739 {
2740 inst.error = BAD_PC;
2741 return;
2742 }
2743
2744 if (skip_past_comma (&str) == FAIL
2745 || (rm = reg_required_here (&str, 0)) == FAIL)
2746 {
2747 inst.error = BAD_ARGS;
2748 return;
2749 }
2750
2751 if (rm == REG_PC)
2752 {
2753 inst.error = BAD_PC;
2754 return;
2755 }
2756
2757 if (rm == rd)
2758 as_tsktsk (_("rd and rm should be different in mul"));
2759
2760 if (skip_past_comma (&str) == FAIL
2761 || (rm = reg_required_here (&str, 8)) == FAIL)
2762 {
2763 inst.error = BAD_ARGS;
2764 return;
2765 }
2766
2767 if (rm == REG_PC)
2768 {
2769 inst.error = BAD_PC;
2770 return;
2771 }
2772
2773 end_of_line (str);
2774 }
2775
2776 static void
2777 do_mla (char * str)
2778 {
2779 int rd, rm;
2780
2781 /* Only one format "rd, rm, rs, rn". */
2782 skip_whitespace (str);
2783
2784 if ((rd = reg_required_here (&str, 16)) == FAIL)
2785 {
2786 inst.error = BAD_ARGS;
2787 return;
2788 }
2789
2790 if (rd == REG_PC)
2791 {
2792 inst.error = BAD_PC;
2793 return;
2794 }
2795
2796 if (skip_past_comma (&str) == FAIL
2797 || (rm = reg_required_here (&str, 0)) == FAIL)
2798 {
2799 inst.error = BAD_ARGS;
2800 return;
2801 }
2802
2803 if (rm == REG_PC)
2804 {
2805 inst.error = BAD_PC;
2806 return;
2807 }
2808
2809 if (rm == rd)
2810 as_tsktsk (_("rd and rm should be different in mla"));
2811
2812 if (skip_past_comma (&str) == FAIL
2813 || (rd = reg_required_here (&str, 8)) == FAIL
2814 || skip_past_comma (&str) == FAIL
2815 || (rm = reg_required_here (&str, 12)) == FAIL)
2816 {
2817 inst.error = BAD_ARGS;
2818 return;
2819 }
2820
2821 if (rd == REG_PC || rm == REG_PC)
2822 {
2823 inst.error = BAD_PC;
2824 return;
2825 }
2826
2827 end_of_line (str);
2828 }
2829
2830 /* Expects *str -> the characters "acc0", possibly with leading blanks.
2831 Advances *str to the next non-alphanumeric.
2832 Returns 0, or else FAIL (in which case sets inst.error).
2833
2834 (In a future XScale, there may be accumulators other than zero.
2835 At that time this routine and its callers can be upgraded to suit.) */
2836
2837 static int
2838 accum0_required_here (char ** str)
2839 {
2840 static char buff [128]; /* Note the address is taken. Hence, static. */
2841 char * p = * str;
2842 char c;
2843 int result = 0; /* The accum number. */
2844
2845 skip_whitespace (p);
2846
2847 *str = p; /* Advance caller's string pointer too. */
2848 c = *p++;
2849 while (ISALNUM (c))
2850 c = *p++;
2851
2852 *--p = 0; /* Aap nul into input buffer at non-alnum. */
2853
2854 if (! ( streq (*str, "acc0") || streq (*str, "ACC0")))
2855 {
2856 sprintf (buff, _("acc0 expected, not '%.100s'"), *str);
2857 inst.error = buff;
2858 result = FAIL;
2859 }
2860
2861 *p = c; /* Unzap. */
2862 *str = p; /* Caller's string pointer to after match. */
2863 return result;
2864 }
2865
2866 static int
2867 ldst_extend_v4 (char ** str)
2868 {
2869 int add = INDEX_UP;
2870
2871 switch (**str)
2872 {
2873 case '#':
2874 case '$':
2875 (*str)++;
2876 if (my_get_expression (& inst.reloc.exp, str))
2877 return FAIL;
2878
2879 if (inst.reloc.exp.X_op == O_constant)
2880 {
2881 int value = inst.reloc.exp.X_add_number;
2882
2883 if (value < -255 || value > 255)
2884 {
2885 inst.error = _("address offset too large");
2886 return FAIL;
2887 }
2888
2889 if (value < 0)
2890 {
2891 value = -value;
2892 add = 0;
2893 }
2894
2895 /* Halfword and signextension instructions have the
2896 immediate value split across bits 11..8 and bits 3..0. */
2897 inst.instruction |= (add | HWOFFSET_IMM
2898 | ((value >> 4) << 8) | (value & 0xF));
2899 }
2900 else
2901 {
2902 inst.instruction |= HWOFFSET_IMM;
2903 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
2904 inst.reloc.pc_rel = 0;
2905 }
2906 return SUCCESS;
2907
2908 case '-':
2909 add = 0;
2910 /* Fall through. */
2911
2912 case '+':
2913 (*str)++;
2914 /* Fall through. */
2915
2916 default:
2917 if (reg_required_here (str, 0) == FAIL)
2918 return FAIL;
2919
2920 inst.instruction |= add;
2921 return SUCCESS;
2922 }
2923 }
2924
2925 /* Expects **str -> after a comma. May be leading blanks.
2926 Advances *str, recognizing a load mode, and setting inst.instruction.
2927 Returns rn, or else FAIL (in which case may set inst.error
2928 and not advance str)
2929
2930 Note: doesn't know Rd, so no err checks that require such knowledge. */
2931
2932 static int
2933 ld_mode_required_here (char ** string)
2934 {
2935 char * str = * string;
2936 int rn;
2937 int pre_inc = 0;
2938
2939 skip_whitespace (str);
2940
2941 if (* str == '[')
2942 {
2943 str++;
2944
2945 skip_whitespace (str);
2946
2947 if ((rn = reg_required_here (& str, 16)) == FAIL)
2948 return FAIL;
2949
2950 skip_whitespace (str);
2951
2952 if (* str == ']')
2953 {
2954 str ++;
2955
2956 if (skip_past_comma (& str) == SUCCESS)
2957 {
2958 /* [Rn],... (post inc) */
2959 if (ldst_extend_v4 (&str) == FAIL)
2960 return FAIL;
2961 }
2962 else /* [Rn] */
2963 {
2964 skip_whitespace (str);
2965
2966 if (* str == '!')
2967 {
2968 str ++;
2969 inst.instruction |= WRITE_BACK;
2970 }
2971
2972 inst.instruction |= INDEX_UP | HWOFFSET_IMM;
2973 pre_inc = 1;
2974 }
2975 }
2976 else /* [Rn,...] */
2977 {
2978 if (skip_past_comma (& str) == FAIL)
2979 {
2980 inst.error = _("pre-indexed expression expected");
2981 return FAIL;
2982 }
2983
2984 pre_inc = 1;
2985
2986 if (ldst_extend_v4 (&str) == FAIL)
2987 return FAIL;
2988
2989 skip_whitespace (str);
2990
2991 if (* str ++ != ']')
2992 {
2993 inst.error = _("missing ]");
2994 return FAIL;
2995 }
2996
2997 skip_whitespace (str);
2998
2999 if (* str == '!')
3000 {
3001 str ++;
3002 inst.instruction |= WRITE_BACK;
3003 }
3004 }
3005 }
3006 else if (* str == '=') /* ldr's "r,=label" syntax */
3007 /* We should never reach here, because <text> = <expression> is
3008 caught gas/read.c read_a_source_file() as a .set operation. */
3009 return FAIL;
3010 else /* PC +- 8 bit immediate offset. */
3011 {
3012 if (my_get_expression (& inst.reloc.exp, & str))
3013 return FAIL;
3014
3015 inst.instruction |= HWOFFSET_IMM; /* The I bit. */
3016 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
3017 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
3018 inst.reloc.pc_rel = 1;
3019 inst.instruction |= (REG_PC << 16);
3020
3021 rn = REG_PC;
3022 pre_inc = 1;
3023 }
3024
3025 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
3026 * string = str;
3027
3028 return rn;
3029 }
3030
3031 /* ARM V5E (El Segundo) signed-multiply-accumulate (argument parse)
3032 SMLAxy{cond} Rd,Rm,Rs,Rn
3033 SMLAWy{cond} Rd,Rm,Rs,Rn
3034 Error if any register is R15. */
3035
3036 static void
3037 do_smla (char * str)
3038 {
3039 int rd, rm, rs, rn;
3040
3041 skip_whitespace (str);
3042
3043 if ((rd = reg_required_here (& str, 16)) == FAIL
3044 || skip_past_comma (& str) == FAIL
3045 || (rm = reg_required_here (& str, 0)) == FAIL
3046 || skip_past_comma (& str) == FAIL
3047 || (rs = reg_required_here (& str, 8)) == FAIL
3048 || skip_past_comma (& str) == FAIL
3049 || (rn = reg_required_here (& str, 12)) == FAIL)
3050 inst.error = BAD_ARGS;
3051
3052 else if (rd == REG_PC || rm == REG_PC || rs == REG_PC || rn == REG_PC)
3053 inst.error = BAD_PC;
3054
3055 else
3056 end_of_line (str);
3057 }
3058
3059 /* ARM V5E (El Segundo) signed-multiply-accumulate-long (argument parse)
3060 SMLALxy{cond} Rdlo,Rdhi,Rm,Rs
3061 Error if any register is R15.
3062 Warning if Rdlo == Rdhi. */
3063
3064 static void
3065 do_smlal (char * str)
3066 {
3067 int rdlo, rdhi, rm, rs;
3068
3069 skip_whitespace (str);
3070
3071 if ((rdlo = reg_required_here (& str, 12)) == FAIL
3072 || skip_past_comma (& str) == FAIL
3073 || (rdhi = reg_required_here (& str, 16)) == FAIL
3074 || skip_past_comma (& str) == FAIL
3075 || (rm = reg_required_here (& str, 0)) == FAIL
3076 || skip_past_comma (& str) == FAIL
3077 || (rs = reg_required_here (& str, 8)) == FAIL)
3078 {
3079 inst.error = BAD_ARGS;
3080 return;
3081 }
3082
3083 if (rdlo == REG_PC || rdhi == REG_PC || rm == REG_PC || rs == REG_PC)
3084 {
3085 inst.error = BAD_PC;
3086 return;
3087 }
3088
3089 if (rdlo == rdhi)
3090 as_tsktsk (_("rdhi and rdlo must be different"));
3091
3092 end_of_line (str);
3093 }
3094
3095 /* ARM V5E (El Segundo) signed-multiply (argument parse)
3096 SMULxy{cond} Rd,Rm,Rs
3097 Error if any register is R15. */
3098
3099 static void
3100 do_smul (char * str)
3101 {
3102 int rd, rm, rs;
3103
3104 skip_whitespace (str);
3105
3106 if ((rd = reg_required_here (& str, 16)) == FAIL
3107 || skip_past_comma (& str) == FAIL
3108 || (rm = reg_required_here (& str, 0)) == FAIL
3109 || skip_past_comma (& str) == FAIL
3110 || (rs = reg_required_here (& str, 8)) == FAIL)
3111 inst.error = BAD_ARGS;
3112
3113 else if (rd == REG_PC || rm == REG_PC || rs == REG_PC)
3114 inst.error = BAD_PC;
3115
3116 else
3117 end_of_line (str);
3118 }
3119
3120 /* ARM V5E (El Segundo) saturating-add/subtract (argument parse)
3121 Q[D]{ADD,SUB}{cond} Rd,Rm,Rn
3122 Error if any register is R15. */
3123
3124 static void
3125 do_qadd (char * str)
3126 {
3127 int rd, rm, rn;
3128
3129 skip_whitespace (str);
3130
3131 if ((rd = reg_required_here (& str, 12)) == FAIL
3132 || skip_past_comma (& str) == FAIL
3133 || (rm = reg_required_here (& str, 0)) == FAIL
3134 || skip_past_comma (& str) == FAIL
3135 || (rn = reg_required_here (& str, 16)) == FAIL)
3136 inst.error = BAD_ARGS;
3137
3138 else if (rd == REG_PC || rm == REG_PC || rn == REG_PC)
3139 inst.error = BAD_PC;
3140
3141 else
3142 end_of_line (str);
3143 }
3144
3145 /* ARM V5E (el Segundo)
3146 MCRRcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
3147 MRRCcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
3148
3149 These are equivalent to the XScale instructions MAR and MRA,
3150 respectively, when coproc == 0, opcode == 0, and CRm == 0.
3151
3152 Result unpredicatable if Rd or Rn is R15. */
3153
3154 static void
3155 do_co_reg2c (char * str)
3156 {
3157 int rd, rn;
3158
3159 skip_whitespace (str);
3160
3161 if (co_proc_number (& str) == FAIL)
3162 {
3163 if (!inst.error)
3164 inst.error = BAD_ARGS;
3165 return;
3166 }
3167
3168 if (skip_past_comma (& str) == FAIL
3169 || cp_opc_expr (& str, 4, 4) == FAIL)
3170 {
3171 if (!inst.error)
3172 inst.error = BAD_ARGS;
3173 return;
3174 }
3175
3176 if (skip_past_comma (& str) == FAIL
3177 || (rd = reg_required_here (& str, 12)) == FAIL)
3178 {
3179 if (!inst.error)
3180 inst.error = BAD_ARGS;
3181 return;
3182 }
3183
3184 if (skip_past_comma (& str) == FAIL
3185 || (rn = reg_required_here (& str, 16)) == FAIL)
3186 {
3187 if (!inst.error)
3188 inst.error = BAD_ARGS;
3189 return;
3190 }
3191
3192 /* Unpredictable result if rd or rn is R15. */
3193 if (rd == REG_PC || rn == REG_PC)
3194 as_tsktsk
3195 (_("Warning: instruction unpredictable when using r15"));
3196
3197 if (skip_past_comma (& str) == FAIL
3198 || cp_reg_required_here (& str, 0) == FAIL)
3199 {
3200 if (!inst.error)
3201 inst.error = BAD_ARGS;
3202 return;
3203 }
3204
3205 end_of_line (str);
3206 }
3207
3208 /* ARM V5 count-leading-zeroes instruction (argument parse)
3209 CLZ{<cond>} <Rd>, <Rm>
3210 Condition defaults to COND_ALWAYS.
3211 Error if Rd or Rm are R15. */
3212
3213 static void
3214 do_clz (char * str)
3215 {
3216 int rd, rm;
3217
3218 skip_whitespace (str);
3219
3220 if (((rd = reg_required_here (& str, 12)) == FAIL)
3221 || (skip_past_comma (& str) == FAIL)
3222 || ((rm = reg_required_here (& str, 0)) == FAIL))
3223 inst.error = BAD_ARGS;
3224
3225 else if (rd == REG_PC || rm == REG_PC )
3226 inst.error = BAD_PC;
3227
3228 else
3229 end_of_line (str);
3230 }
3231
3232 /* ARM V5 (argument parse)
3233 LDC2{L} <coproc>, <CRd>, <addressing mode>
3234 STC2{L} <coproc>, <CRd>, <addressing mode>
3235 Instruction is not conditional, and has 0xf in the condition field.
3236 Otherwise, it's the same as LDC/STC. */
3237
3238 static void
3239 do_lstc2 (char * str)
3240 {
3241 skip_whitespace (str);
3242
3243 if (co_proc_number (& str) == FAIL)
3244 {
3245 if (!inst.error)
3246 inst.error = BAD_ARGS;
3247 }
3248 else if (skip_past_comma (& str) == FAIL
3249 || cp_reg_required_here (& str, 12) == FAIL)
3250 {
3251 if (!inst.error)
3252 inst.error = BAD_ARGS;
3253 }
3254 else if (skip_past_comma (& str) == FAIL
3255 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
3256 {
3257 if (! inst.error)
3258 inst.error = BAD_ARGS;
3259 }
3260 else
3261 end_of_line (str);
3262 }
3263
3264 /* ARM V5 (argument parse)
3265 CDP2 <coproc>, <opcode_1>, <CRd>, <CRn>, <CRm>, <opcode_2>
3266 Instruction is not conditional, and has 0xf in the condition field.
3267 Otherwise, it's the same as CDP. */
3268
3269 static void
3270 do_cdp2 (char * str)
3271 {
3272 skip_whitespace (str);
3273
3274 if (co_proc_number (& str) == FAIL)
3275 {
3276 if (!inst.error)
3277 inst.error = BAD_ARGS;
3278 return;
3279 }
3280
3281 if (skip_past_comma (& str) == FAIL
3282 || cp_opc_expr (& str, 20,4) == FAIL)
3283 {
3284 if (!inst.error)
3285 inst.error = BAD_ARGS;
3286 return;
3287 }
3288
3289 if (skip_past_comma (& str) == FAIL
3290 || cp_reg_required_here (& str, 12) == FAIL)
3291 {
3292 if (!inst.error)
3293 inst.error = BAD_ARGS;
3294 return;
3295 }
3296
3297 if (skip_past_comma (& str) == FAIL
3298 || cp_reg_required_here (& str, 16) == FAIL)
3299 {
3300 if (!inst.error)
3301 inst.error = BAD_ARGS;
3302 return;
3303 }
3304
3305 if (skip_past_comma (& str) == FAIL
3306 || cp_reg_required_here (& str, 0) == FAIL)
3307 {
3308 if (!inst.error)
3309 inst.error = BAD_ARGS;
3310 return;
3311 }
3312
3313 if (skip_past_comma (& str) == SUCCESS)
3314 {
3315 if (cp_opc_expr (& str, 5, 3) == FAIL)
3316 {
3317 if (!inst.error)
3318 inst.error = BAD_ARGS;
3319 return;
3320 }
3321 }
3322
3323 end_of_line (str);
3324 }
3325
3326 /* ARM V5 (argument parse)
3327 MCR2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
3328 MRC2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
3329 Instruction is not conditional, and has 0xf in the condition field.
3330 Otherwise, it's the same as MCR/MRC. */
3331
3332 static void
3333 do_co_reg2 (char * str)
3334 {
3335 skip_whitespace (str);
3336
3337 if (co_proc_number (& str) == FAIL)
3338 {
3339 if (!inst.error)
3340 inst.error = BAD_ARGS;
3341 return;
3342 }
3343
3344 if (skip_past_comma (& str) == FAIL
3345 || cp_opc_expr (& str, 21, 3) == FAIL)
3346 {
3347 if (!inst.error)
3348 inst.error = BAD_ARGS;
3349 return;
3350 }
3351
3352 if (skip_past_comma (& str) == FAIL
3353 || reg_required_here (& str, 12) == FAIL)
3354 {
3355 if (!inst.error)
3356 inst.error = BAD_ARGS;
3357 return;
3358 }
3359
3360 if (skip_past_comma (& str) == FAIL
3361 || cp_reg_required_here (& str, 16) == FAIL)
3362 {
3363 if (!inst.error)
3364 inst.error = BAD_ARGS;
3365 return;
3366 }
3367
3368 if (skip_past_comma (& str) == FAIL
3369 || cp_reg_required_here (& str, 0) == FAIL)
3370 {
3371 if (!inst.error)
3372 inst.error = BAD_ARGS;
3373 return;
3374 }
3375
3376 if (skip_past_comma (& str) == SUCCESS)
3377 {
3378 if (cp_opc_expr (& str, 5, 3) == FAIL)
3379 {
3380 if (!inst.error)
3381 inst.error = BAD_ARGS;
3382 return;
3383 }
3384 }
3385
3386 end_of_line (str);
3387 }
3388
3389 static void
3390 do_bx (char * str)
3391 {
3392 int reg;
3393
3394 skip_whitespace (str);
3395
3396 if ((reg = reg_required_here (&str, 0)) == FAIL)
3397 {
3398 inst.error = BAD_ARGS;
3399 return;
3400 }
3401
3402 /* Note - it is not illegal to do a "bx pc". Useless, but not illegal. */
3403 if (reg == REG_PC)
3404 as_tsktsk (_("use of r15 in bx in ARM mode is not really useful"));
3405
3406 end_of_line (str);
3407 }
3408
3409 /* ARM v5TEJ. Jump to Jazelle code. */
3410
3411 static void
3412 do_bxj (char * str)
3413 {
3414 int reg;
3415
3416 skip_whitespace (str);
3417
3418 if ((reg = reg_required_here (&str, 0)) == FAIL)
3419 {
3420 inst.error = BAD_ARGS;
3421 return;
3422 }
3423
3424 /* Note - it is not illegal to do a "bxj pc". Useless, but not illegal. */
3425 if (reg == REG_PC)
3426 as_tsktsk (_("use of r15 in bxj is not really useful"));
3427
3428 end_of_line (str);
3429 }
3430
3431 /* ARM V6 umaal (argument parse). */
3432
3433 static void
3434 do_umaal (char * str)
3435 {
3436 int rdlo, rdhi, rm, rs;
3437
3438 skip_whitespace (str);
3439 if ((rdlo = reg_required_here (& str, 12)) == FAIL
3440 || skip_past_comma (& str) == FAIL
3441 || (rdhi = reg_required_here (& str, 16)) == FAIL
3442 || skip_past_comma (& str) == FAIL
3443 || (rm = reg_required_here (& str, 0)) == FAIL
3444 || skip_past_comma (& str) == FAIL
3445 || (rs = reg_required_here (& str, 8)) == FAIL)
3446 {
3447 inst.error = BAD_ARGS;
3448 return;
3449 }
3450
3451 if (rdlo == REG_PC || rdhi == REG_PC || rm == REG_PC || rs == REG_PC)
3452 {
3453 inst.error = BAD_PC;
3454 return;
3455 }
3456
3457 end_of_line (str);
3458 }
3459
3460 /* ARM V6 strex (argument parse). */
3461
3462 static void
3463 do_strex (char * str)
3464 {
3465 int rd, rm, rn;
3466
3467 /* Parse Rd, Rm,. */
3468 skip_whitespace (str);
3469 if ((rd = reg_required_here (& str, 12)) == FAIL
3470 || skip_past_comma (& str) == FAIL
3471 || (rm = reg_required_here (& str, 0)) == FAIL
3472 || skip_past_comma (& str) == FAIL)
3473 {
3474 inst.error = BAD_ARGS;
3475 return;
3476 }
3477 if (rd == REG_PC || rm == REG_PC)
3478 {
3479 inst.error = BAD_PC;
3480 return;
3481 }
3482 if (rd == rm)
3483 {
3484 inst.error = _("Rd equal to Rm or Rn yields unpredictable results");
3485 return;
3486 }
3487
3488 /* Skip past '['. */
3489 if ((strlen (str) >= 1)
3490 && strncmp (str, "[", 1) == 0)
3491 str += 1;
3492
3493 skip_whitespace (str);
3494
3495 /* Parse Rn. */
3496 if ((rn = reg_required_here (& str, 16)) == FAIL)
3497 {
3498 inst.error = BAD_ARGS;
3499 return;
3500 }
3501 else if (rn == REG_PC)
3502 {
3503 inst.error = BAD_PC;
3504 return;
3505 }
3506 if (rd == rn)
3507 {
3508 inst.error = _("Rd equal to Rm or Rn yields unpredictable results");
3509 return;
3510 }
3511 skip_whitespace (str);
3512
3513 /* Skip past ']'. */
3514 if ((strlen (str) >= 1)
3515 && strncmp (str, "]", 1) == 0)
3516 str += 1;
3517
3518 end_of_line (str);
3519 }
3520
3521 /* KIND indicates what kind of shifts are accepted. */
3522
3523 static int
3524 decode_shift (char ** str, int kind)
3525 {
3526 const struct asm_shift_name * shift;
3527 char * p;
3528 char c;
3529
3530 skip_whitespace (* str);
3531
3532 for (p = * str; ISALPHA (* p); p ++)
3533 ;
3534
3535 if (p == * str)
3536 {
3537 inst.error = _("shift expression expected");
3538 return FAIL;
3539 }
3540
3541 c = * p;
3542 * p = '\0';
3543 shift = (const struct asm_shift_name *) hash_find (arm_shift_hsh, * str);
3544 * p = c;
3545
3546 if (shift == NULL)
3547 {
3548 inst.error = _("shift expression expected");
3549 return FAIL;
3550 }
3551
3552 assert (shift->properties->index == shift_properties[shift->properties->index].index);
3553
3554 if (kind == SHIFT_LSL_OR_ASR_IMMEDIATE
3555 && shift->properties->index != SHIFT_LSL
3556 && shift->properties->index != SHIFT_ASR)
3557 {
3558 inst.error = _("'LSL' or 'ASR' required");
3559 return FAIL;
3560 }
3561 else if (kind == SHIFT_LSL_IMMEDIATE
3562 && shift->properties->index != SHIFT_LSL)
3563 {
3564 inst.error = _("'LSL' required");
3565 return FAIL;
3566 }
3567 else if (kind == SHIFT_ASR_IMMEDIATE
3568 && shift->properties->index != SHIFT_ASR)
3569 {
3570 inst.error = _("'ASR' required");
3571 return FAIL;
3572 }
3573
3574 if (shift->properties->index == SHIFT_RRX)
3575 {
3576 * str = p;
3577 inst.instruction |= shift->properties->bit_field;
3578 return SUCCESS;
3579 }
3580
3581 skip_whitespace (p);
3582
3583 if (kind == NO_SHIFT_RESTRICT && reg_required_here (& p, 8) != FAIL)
3584 {
3585 inst.instruction |= shift->properties->bit_field | SHIFT_BY_REG;
3586 * str = p;
3587 return SUCCESS;
3588 }
3589 else if (! is_immediate_prefix (* p))
3590 {
3591 inst.error = (NO_SHIFT_RESTRICT
3592 ? _("shift requires register or #expression")
3593 : _("shift requires #expression"));
3594 * str = p;
3595 return FAIL;
3596 }
3597
3598 inst.error = NULL;
3599 p ++;
3600
3601 if (my_get_expression (& inst.reloc.exp, & p))
3602 return FAIL;
3603
3604 /* Validate some simple #expressions. */
3605 if (inst.reloc.exp.X_op == O_constant)
3606 {
3607 unsigned num = inst.reloc.exp.X_add_number;
3608
3609 /* Reject operations greater than 32. */
3610 if (num > 32
3611 /* Reject a shift of 0 unless the mode allows it. */
3612 || (num == 0 && shift->properties->allows_0 == 0)
3613 /* Reject a shift of 32 unless the mode allows it. */
3614 || (num == 32 && shift->properties->allows_32 == 0)
3615 )
3616 {
3617 /* As a special case we allow a shift of zero for
3618 modes that do not support it to be recoded as an
3619 logical shift left of zero (ie nothing). We warn
3620 about this though. */
3621 if (num == 0)
3622 {
3623 as_warn (_("shift of 0 ignored."));
3624 shift = & shift_names[0];
3625 assert (shift->properties->index == SHIFT_LSL);
3626 }
3627 else
3628 {
3629 inst.error = _("invalid immediate shift");
3630 return FAIL;
3631 }
3632 }
3633
3634 /* Shifts of 32 are encoded as 0, for those shifts that
3635 support it. */
3636 if (num == 32)
3637 num = 0;
3638
3639 inst.instruction |= (num << 7) | shift->properties->bit_field;
3640 }
3641 else
3642 {
3643 inst.reloc.type = BFD_RELOC_ARM_SHIFT_IMM;
3644 inst.reloc.pc_rel = 0;
3645 inst.instruction |= shift->properties->bit_field;
3646 }
3647
3648 * str = p;
3649 return SUCCESS;
3650 }
3651
3652 static void
3653 do_sat (char ** str, int bias)
3654 {
3655 int rd, rm;
3656 expressionS expr;
3657
3658 skip_whitespace (*str);
3659
3660 /* Parse <Rd>, field. */
3661 if ((rd = reg_required_here (str, 12)) == FAIL
3662 || skip_past_comma (str) == FAIL)
3663 {
3664 inst.error = BAD_ARGS;
3665 return;
3666 }
3667 if (rd == REG_PC)
3668 {
3669 inst.error = BAD_PC;
3670 return;
3671 }
3672
3673 /* Parse #<immed>, field. */
3674 if (is_immediate_prefix (**str))
3675 (*str)++;
3676 else
3677 {
3678 inst.error = _("immediate expression expected");
3679 return;
3680 }
3681 if (my_get_expression (&expr, str))
3682 {
3683 inst.error = _("bad expression");
3684 return;
3685 }
3686 if (expr.X_op != O_constant)
3687 {
3688 inst.error = _("constant expression expected");
3689 return;
3690 }
3691 if (expr.X_add_number + bias < 0
3692 || expr.X_add_number + bias > 31)
3693 {
3694 inst.error = _("immediate value out of range");
3695 return;
3696 }
3697 inst.instruction |= (expr.X_add_number + bias) << 16;
3698 if (skip_past_comma (str) == FAIL)
3699 {
3700 inst.error = BAD_ARGS;
3701 return;
3702 }
3703
3704 /* Parse <Rm> field. */
3705 if ((rm = reg_required_here (str, 0)) == FAIL)
3706 {
3707 inst.error = BAD_ARGS;
3708 return;
3709 }
3710 if (rm == REG_PC)
3711 {
3712 inst.error = BAD_PC;
3713 return;
3714 }
3715
3716 if (skip_past_comma (str) == SUCCESS)
3717 decode_shift (str, SHIFT_LSL_OR_ASR_IMMEDIATE);
3718 }
3719
3720 /* ARM V6 ssat (argument parse). */
3721
3722 static void
3723 do_ssat (char * str)
3724 {
3725 do_sat (&str, /*bias=*/-1);
3726 end_of_line (str);
3727 }
3728
3729 /* ARM V6 usat (argument parse). */
3730
3731 static void
3732 do_usat (char * str)
3733 {
3734 do_sat (&str, /*bias=*/0);
3735 end_of_line (str);
3736 }
3737
3738 static void
3739 do_sat16 (char ** str, int bias)
3740 {
3741 int rd, rm;
3742 expressionS expr;
3743
3744 skip_whitespace (*str);
3745
3746 /* Parse the <Rd> field. */
3747 if ((rd = reg_required_here (str, 12)) == FAIL
3748 || skip_past_comma (str) == FAIL)
3749 {
3750 inst.error = BAD_ARGS;
3751 return;
3752 }
3753 if (rd == REG_PC)
3754 {
3755 inst.error = BAD_PC;
3756 return;
3757 }
3758
3759 /* Parse #<immed>, field. */
3760 if (is_immediate_prefix (**str))
3761 (*str)++;
3762 else
3763 {
3764 inst.error = _("immediate expression expected");
3765 return;
3766 }
3767 if (my_get_expression (&expr, str))
3768 {
3769 inst.error = _("bad expression");
3770 return;
3771 }
3772 if (expr.X_op != O_constant)
3773 {
3774 inst.error = _("constant expression expected");
3775 return;
3776 }
3777 if (expr.X_add_number + bias < 0
3778 || expr.X_add_number + bias > 15)
3779 {
3780 inst.error = _("immediate value out of range");
3781 return;
3782 }
3783 inst.instruction |= (expr.X_add_number + bias) << 16;
3784 if (skip_past_comma (str) == FAIL)
3785 {
3786 inst.error = BAD_ARGS;
3787 return;
3788 }
3789
3790 /* Parse <Rm> field. */
3791 if ((rm = reg_required_here (str, 0)) == FAIL)
3792 {
3793 inst.error = BAD_ARGS;
3794 return;
3795 }
3796 if (rm == REG_PC)
3797 {
3798 inst.error = BAD_PC;
3799 return;
3800 }
3801 }
3802
3803 /* ARM V6 ssat16 (argument parse). */
3804
3805 static void
3806 do_ssat16 (char * str)
3807 {
3808 do_sat16 (&str, /*bias=*/-1);
3809 end_of_line (str);
3810 }
3811
3812 static void
3813 do_usat16 (char * str)
3814 {
3815 do_sat16 (&str, /*bias=*/0);
3816 end_of_line (str);
3817 }
3818
3819 static void
3820 do_cps_mode (char ** str)
3821 {
3822 expressionS expr;
3823
3824 skip_whitespace (*str);
3825
3826 if (! is_immediate_prefix (**str))
3827 {
3828 inst.error = _("immediate expression expected");
3829 return;
3830 }
3831
3832 (*str)++; /* Strip off the immediate signifier. */
3833 if (my_get_expression (&expr, str))
3834 {
3835 inst.error = _("bad expression");
3836 return;
3837 }
3838
3839 if (expr.X_op != O_constant)
3840 {
3841 inst.error = _("constant expression expected");
3842 return;
3843 }
3844
3845 /* The mode is a 5 bit field. Valid values are 0-31. */
3846 if (((unsigned) expr.X_add_number) > 31
3847 || (inst.reloc.exp.X_add_number) < 0)
3848 {
3849 inst.error = _("invalid constant");
3850 return;
3851 }
3852
3853 inst.instruction |= expr.X_add_number;
3854 }
3855
3856 /* ARM V6 srs (argument parse). */
3857
3858 static void
3859 do_srs (char * str)
3860 {
3861 char *exclam;
3862 skip_whitespace (str);
3863 exclam = strchr (str, '!');
3864 if (exclam)
3865 *exclam = '\0';
3866 do_cps_mode (&str);
3867 if (exclam)
3868 *exclam = '!';
3869 if (*str == '!')
3870 {
3871 inst.instruction |= WRITE_BACK;
3872 str++;
3873 }
3874 end_of_line (str);
3875 }
3876
3877 /* ARM V6 SMMUL (argument parse). */
3878
3879 static void
3880 do_smmul (char * str)
3881 {
3882 int rd, rm, rs;
3883
3884 skip_whitespace (str);
3885 if ((rd = reg_required_here (&str, 16)) == FAIL
3886 || skip_past_comma (&str) == FAIL
3887 || (rm = reg_required_here (&str, 0)) == FAIL
3888 || skip_past_comma (&str) == FAIL
3889 || (rs = reg_required_here (&str, 8)) == FAIL)
3890 {
3891 inst.error = BAD_ARGS;
3892 return;
3893 }
3894
3895 if ( rd == REG_PC
3896 || rm == REG_PC
3897 || rs == REG_PC)
3898 {
3899 inst.error = BAD_PC;
3900 return;
3901 }
3902
3903 end_of_line (str);
3904 }
3905
3906 /* ARM V6 SMLALD (argument parse). */
3907
3908 static void
3909 do_smlald (char * str)
3910 {
3911 int rdlo, rdhi, rm, rs;
3912
3913 skip_whitespace (str);
3914 if ((rdlo = reg_required_here (&str, 12)) == FAIL
3915 || skip_past_comma (&str) == FAIL
3916 || (rdhi = reg_required_here (&str, 16)) == FAIL
3917 || skip_past_comma (&str) == FAIL
3918 || (rm = reg_required_here (&str, 0)) == FAIL
3919 || skip_past_comma (&str) == FAIL
3920 || (rs = reg_required_here (&str, 8)) == FAIL)
3921 {
3922 inst.error = BAD_ARGS;
3923 return;
3924 }
3925
3926 if ( rdlo == REG_PC
3927 || rdhi == REG_PC
3928 || rm == REG_PC
3929 || rs == REG_PC)
3930 {
3931 inst.error = BAD_PC;
3932 return;
3933 }
3934
3935 end_of_line (str);
3936 }
3937
3938 /* ARM V6 SMLAD (argument parse). Signed multiply accumulate dual.
3939 smlad{x}{<cond>} Rd, Rm, Rs, Rn */
3940
3941 static void
3942 do_smlad (char * str)
3943 {
3944 int rd, rm, rs, rn;
3945
3946 skip_whitespace (str);
3947 if ((rd = reg_required_here (&str, 16)) == FAIL
3948 || skip_past_comma (&str) == FAIL
3949 || (rm = reg_required_here (&str, 0)) == FAIL
3950 || skip_past_comma (&str) == FAIL
3951 || (rs = reg_required_here (&str, 8)) == FAIL
3952 || skip_past_comma (&str) == FAIL
3953 || (rn = reg_required_here (&str, 12)) == FAIL)
3954 {
3955 inst.error = BAD_ARGS;
3956 return;
3957 }
3958
3959 if ( rd == REG_PC
3960 || rn == REG_PC
3961 || rs == REG_PC
3962 || rm == REG_PC)
3963 {
3964 inst.error = BAD_PC;
3965 return;
3966 }
3967
3968 end_of_line (str);
3969 }
3970
3971 /* Returns true if the endian-specifier indicates big-endianness. */
3972
3973 static int
3974 do_endian_specifier (char * str)
3975 {
3976 int big_endian = 0;
3977
3978 skip_whitespace (str);
3979 if (strlen (str) < 2)
3980 inst.error = _("missing endian specifier");
3981 else if (strncasecmp (str, "BE", 2) == 0)
3982 {
3983 str += 2;
3984 big_endian = 1;
3985 }
3986 else if (strncasecmp (str, "LE", 2) == 0)
3987 str += 2;
3988 else
3989 inst.error = _("valid endian specifiers are be or le");
3990
3991 end_of_line (str);
3992
3993 return big_endian;
3994 }
3995
3996 /* ARM V6 SETEND (argument parse). Sets the E bit in the CPSR while
3997 preserving the other bits.
3998
3999 setend <endian_specifier>, where <endian_specifier> is either
4000 BE or LE. */
4001
4002 static void
4003 do_setend (char * str)
4004 {
4005 if (do_endian_specifier (str))
4006 inst.instruction |= 0x200;
4007 }
4008
4009 /* ARM V6 SXTH.
4010
4011 SXTH {<cond>} <Rd>, <Rm>{, <rotation>}
4012 Condition defaults to COND_ALWAYS.
4013 Error if any register uses R15. */
4014
4015 static void
4016 do_sxth (char * str)
4017 {
4018 int rd, rm;
4019 expressionS expr;
4020 int rotation_clear_mask = 0xfffff3ff;
4021 int rotation_eight_mask = 0x00000400;
4022 int rotation_sixteen_mask = 0x00000800;
4023 int rotation_twenty_four_mask = 0x00000c00;
4024
4025 skip_whitespace (str);
4026 if ((rd = reg_required_here (&str, 12)) == FAIL
4027 || skip_past_comma (&str) == FAIL
4028 || (rm = reg_required_here (&str, 0)) == FAIL)
4029 {
4030 inst.error = BAD_ARGS;
4031 return;
4032 }
4033
4034 else if (rd == REG_PC || rm == REG_PC)
4035 {
4036 inst.error = BAD_PC;
4037 return;
4038 }
4039
4040 /* Zero out the rotation field. */
4041 inst.instruction &= rotation_clear_mask;
4042
4043 /* Check for lack of optional rotation field. */
4044 if (skip_past_comma (&str) == FAIL)
4045 {
4046 end_of_line (str);
4047 return;
4048 }
4049
4050 /* Move past 'ROR'. */
4051 skip_whitespace (str);
4052 if (strncasecmp (str, "ROR", 3) == 0)
4053 str += 3;
4054 else
4055 {
4056 inst.error = _("missing rotation field after comma");
4057 return;
4058 }
4059
4060 /* Get the immediate constant. */
4061 skip_whitespace (str);
4062 if (is_immediate_prefix (* str))
4063 str++;
4064 else
4065 {
4066 inst.error = _("immediate expression expected");
4067 return;
4068 }
4069
4070 if (my_get_expression (&expr, &str))
4071 {
4072 inst.error = _("bad expression");
4073 return;
4074 }
4075
4076 if (expr.X_op != O_constant)
4077 {
4078 inst.error = _("constant expression expected");
4079 return;
4080 }
4081
4082 switch (expr.X_add_number)
4083 {
4084 case 0:
4085 /* Rotation field has already been zeroed. */
4086 break;
4087 case 8:
4088 inst.instruction |= rotation_eight_mask;
4089 break;
4090
4091 case 16:
4092 inst.instruction |= rotation_sixteen_mask;
4093 break;
4094
4095 case 24:
4096 inst.instruction |= rotation_twenty_four_mask;
4097 break;
4098
4099 default:
4100 inst.error = _("rotation can be 8, 16, 24 or 0 when field is ommited");
4101 break;
4102 }
4103
4104 end_of_line (str);
4105 }
4106
4107 /* ARM V6 SXTAH extracts a 16-bit value from a register, sign
4108 extends it to 32-bits, and adds the result to a value in another
4109 register. You can specify a rotation by 0, 8, 16, or 24 bits
4110 before extracting the 16-bit value.
4111 SXTAH{<cond>} <Rd>, <Rn>, <Rm>{, <rotation>}
4112 Condition defaults to COND_ALWAYS.
4113 Error if any register uses R15. */
4114
4115 static void
4116 do_sxtah (char * str)
4117 {
4118 int rd, rn, rm;
4119 expressionS expr;
4120 int rotation_clear_mask = 0xfffff3ff;
4121 int rotation_eight_mask = 0x00000400;
4122 int rotation_sixteen_mask = 0x00000800;
4123 int rotation_twenty_four_mask = 0x00000c00;
4124
4125 skip_whitespace (str);
4126 if ((rd = reg_required_here (&str, 12)) == FAIL
4127 || skip_past_comma (&str) == FAIL
4128 || (rn = reg_required_here (&str, 16)) == FAIL
4129 || skip_past_comma (&str) == FAIL
4130 || (rm = reg_required_here (&str, 0)) == FAIL)
4131 {
4132 inst.error = BAD_ARGS;
4133 return;
4134 }
4135
4136 else if (rd == REG_PC || rn == REG_PC || rm == REG_PC)
4137 {
4138 inst.error = BAD_PC;
4139 return;
4140 }
4141
4142 /* Zero out the rotation field. */
4143 inst.instruction &= rotation_clear_mask;
4144
4145 /* Check for lack of optional rotation field. */
4146 if (skip_past_comma (&str) == FAIL)
4147 {
4148 end_of_line (str);
4149 return;
4150 }
4151
4152 /* Move past 'ROR'. */
4153 skip_whitespace (str);
4154 if (strncasecmp (str, "ROR", 3) == 0)
4155 str += 3;
4156 else
4157 {
4158 inst.error = _("missing rotation field after comma");
4159 return;
4160 }
4161
4162 /* Get the immediate constant. */
4163 skip_whitespace (str);
4164 if (is_immediate_prefix (* str))
4165 str++;
4166 else
4167 {
4168 inst.error = _("immediate expression expected");
4169 return;
4170 }
4171
4172 if (my_get_expression (&expr, &str))
4173 {
4174 inst.error = _("bad expression");
4175 return;
4176 }
4177
4178 if (expr.X_op != O_constant)
4179 {
4180 inst.error = _("constant expression expected");
4181 return;
4182 }
4183
4184 switch (expr.X_add_number)
4185 {
4186 case 0:
4187 /* Rotation field has already been zeroed. */
4188 break;
4189
4190 case 8:
4191 inst.instruction |= rotation_eight_mask;
4192 break;
4193
4194 case 16:
4195 inst.instruction |= rotation_sixteen_mask;
4196 break;
4197
4198 case 24:
4199 inst.instruction |= rotation_twenty_four_mask;
4200 break;
4201
4202 default:
4203 inst.error = _("rotation can be 8, 16, 24 or 0 when field is ommited");
4204 break;
4205 }
4206
4207 end_of_line (str);
4208 }
4209
4210
4211 /* ARM V6 RFE (Return from Exception) loads the PC and CPSR from the
4212 word at the specified address and the following word
4213 respectively.
4214 Unconditionally executed.
4215 Error if Rn is R15. */
4216
4217 static void
4218 do_rfe (char * str)
4219 {
4220 int rn;
4221
4222 skip_whitespace (str);
4223
4224 if ((rn = reg_required_here (&str, 16)) == FAIL)
4225 return;
4226
4227 if (rn == REG_PC)
4228 {
4229 inst.error = BAD_PC;
4230 return;
4231 }
4232
4233 skip_whitespace (str);
4234
4235 if (*str == '!')
4236 {
4237 inst.instruction |= WRITE_BACK;
4238 str++;
4239 }
4240 end_of_line (str);
4241 }
4242
4243 /* ARM V6 REV (Byte Reverse Word) reverses the byte order in a 32-bit
4244 register (argument parse).
4245 REV{<cond>} Rd, Rm.
4246 Condition defaults to COND_ALWAYS.
4247 Error if Rd or Rm are R15. */
4248
4249 static void
4250 do_rev (char * str)
4251 {
4252 int rd, rm;
4253
4254 skip_whitespace (str);
4255
4256 if ((rd = reg_required_here (&str, 12)) == FAIL
4257 || skip_past_comma (&str) == FAIL
4258 || (rm = reg_required_here (&str, 0)) == FAIL)
4259 inst.error = BAD_ARGS;
4260
4261 else if (rd == REG_PC || rm == REG_PC)
4262 inst.error = BAD_PC;
4263
4264 else
4265 end_of_line (str);
4266 }
4267
4268 /* ARM V6 Perform Two Sixteen Bit Integer Additions. (argument parse).
4269 QADD16{<cond>} <Rd>, <Rn>, <Rm>
4270 Condition defaults to COND_ALWAYS.
4271 Error if Rd, Rn or Rm are R15. */
4272
4273 static void
4274 do_qadd16 (char * str)
4275 {
4276 int rd, rm, rn;
4277
4278 skip_whitespace (str);
4279
4280 if ((rd = reg_required_here (&str, 12)) == FAIL
4281 || skip_past_comma (&str) == FAIL
4282 || (rn = reg_required_here (&str, 16)) == FAIL
4283 || skip_past_comma (&str) == FAIL
4284 || (rm = reg_required_here (&str, 0)) == FAIL)
4285 inst.error = BAD_ARGS;
4286
4287 else if (rd == REG_PC || rm == REG_PC || rn == REG_PC)
4288 inst.error = BAD_PC;
4289
4290 else
4291 end_of_line (str);
4292 }
4293
4294 static void
4295 do_pkh_core (char * str, int shift)
4296 {
4297 int rd, rn, rm;
4298
4299 skip_whitespace (str);
4300 if (((rd = reg_required_here (&str, 12)) == FAIL)
4301 || (skip_past_comma (&str) == FAIL)
4302 || ((rn = reg_required_here (&str, 16)) == FAIL)
4303 || (skip_past_comma (&str) == FAIL)
4304 || ((rm = reg_required_here (&str, 0)) == FAIL))
4305 {
4306 inst.error = BAD_ARGS;
4307 return;
4308 }
4309
4310 else if (rd == REG_PC || rn == REG_PC || rm == REG_PC)
4311 {
4312 inst.error = BAD_PC;
4313 return;
4314 }
4315
4316 /* Check for optional shift immediate constant. */
4317 if (skip_past_comma (&str) == FAIL)
4318 {
4319 if (shift == SHIFT_ASR_IMMEDIATE)
4320 {
4321 /* If the shift specifier is ommited, turn the instruction
4322 into pkhbt rd, rm, rn. First, switch the instruction
4323 code, and clear the rn and rm fields. */
4324 inst.instruction &= 0xfff0f010;
4325 /* Now, re-encode the registers. */
4326 inst.instruction |= (rm << 16) | rn;
4327 }
4328 return;
4329 }
4330
4331 decode_shift (&str, shift);
4332 }
4333
4334 /* ARM V6 Pack Halfword Bottom Top instruction (argument parse).
4335 PKHBT {<cond>} <Rd>, <Rn>, <Rm> {, LSL #<shift_imm>}
4336 Condition defaults to COND_ALWAYS.
4337 Error if Rd, Rn or Rm are R15. */
4338
4339 static void
4340 do_pkhbt (char * str)
4341 {
4342 do_pkh_core (str, SHIFT_LSL_IMMEDIATE);
4343 }
4344
4345 /* ARM V6 PKHTB (Argument Parse). */
4346
4347 static void
4348 do_pkhtb (char * str)
4349 {
4350 do_pkh_core (str, SHIFT_ASR_IMMEDIATE);
4351 }
4352
4353 /* ARM V6 Load Register Exclusive instruction (argument parse).
4354 LDREX{,B,D,H}{<cond>} <Rd, [<Rn>]
4355 Condition defaults to COND_ALWAYS.
4356 Error if Rd or Rn are R15.
4357 See ARMARMv6 A4.1.27: LDREX. */
4358
4359 static void
4360 do_ldrex (char * str)
4361 {
4362 int rd, rn;
4363
4364 skip_whitespace (str);
4365
4366 /* Parse Rd. */
4367 if (((rd = reg_required_here (&str, 12)) == FAIL)
4368 || (skip_past_comma (&str) == FAIL))
4369 {
4370 inst.error = BAD_ARGS;
4371 return;
4372 }
4373 else if (rd == REG_PC)
4374 {
4375 inst.error = BAD_PC;
4376 return;
4377 }
4378 skip_whitespace (str);
4379
4380 /* Skip past '['. */
4381 if ((strlen (str) >= 1)
4382 &&strncmp (str, "[", 1) == 0)
4383 str += 1;
4384 skip_whitespace (str);
4385
4386 /* Parse Rn. */
4387 if ((rn = reg_required_here (&str, 16)) == FAIL)
4388 {
4389 inst.error = BAD_ARGS;
4390 return;
4391 }
4392 else if (rn == REG_PC)
4393 {
4394 inst.error = BAD_PC;
4395 return;
4396 }
4397 skip_whitespace (str);
4398
4399 /* Skip past ']'. */
4400 if ((strlen (str) >= 1)
4401 && strncmp (str, "]", 1) == 0)
4402 str += 1;
4403
4404 end_of_line (str);
4405 }
4406
4407 /* ARM V6 change processor state instruction (argument parse)
4408 CPS, CPSIE, CSPID . */
4409
4410 static void
4411 do_cps (char * str)
4412 {
4413 do_cps_mode (&str);
4414 end_of_line (str);
4415 }
4416
4417 static void
4418 do_cps_flags (char ** str, int thumb_p)
4419 {
4420 struct cps_flag
4421 {
4422 char character;
4423 unsigned long arm_value;
4424 unsigned long thumb_value;
4425 };
4426 static struct cps_flag flag_table[] =
4427 {
4428 {'a', 0x100, 0x4 },
4429 {'i', 0x080, 0x2 },
4430 {'f', 0x040, 0x1 }
4431 };
4432
4433 int saw_a_flag = 0;
4434
4435 skip_whitespace (*str);
4436
4437 /* Get the a, f and i flags. */
4438 while (**str && **str != ',')
4439 {
4440 struct cps_flag *p;
4441 struct cps_flag *q = flag_table + sizeof (flag_table)/sizeof (*p);
4442
4443 for (p = flag_table; p < q; ++p)
4444 if (strncasecmp (*str, &p->character, 1) == 0)
4445 {
4446 inst.instruction |= (thumb_p ? p->thumb_value : p->arm_value);
4447 saw_a_flag = 1;
4448 break;
4449 }
4450 if (p == q)
4451 {
4452 inst.error = _("unrecognized flag");
4453 return;
4454 }
4455 (*str)++;
4456 }
4457
4458 if (!saw_a_flag)
4459 inst.error = _("no 'a', 'i', or 'f' flags for 'cps'");
4460 }
4461
4462 static void
4463 do_cpsi (char * str)
4464 {
4465 do_cps_flags (&str, /*thumb_p=*/0);
4466
4467 if (skip_past_comma (&str) == SUCCESS)
4468 {
4469 skip_whitespace (str);
4470 do_cps_mode (&str);
4471 }
4472 end_of_line (str);
4473 }
4474
4475 /* THUMB V5 breakpoint instruction (argument parse)
4476 BKPT <immed_8>. */
4477
4478 static void
4479 do_t_bkpt (char * str)
4480 {
4481 expressionS expr;
4482 unsigned long number;
4483
4484 skip_whitespace (str);
4485
4486 /* Allow optional leading '#'. */
4487 if (is_immediate_prefix (*str))
4488 str ++;
4489
4490 memset (& expr, '\0', sizeof (expr));
4491 if (my_get_expression (& expr, & str)
4492 || (expr.X_op != O_constant
4493 /* As a convenience we allow 'bkpt' without an operand. */
4494 && expr.X_op != O_absent))
4495 {
4496 inst.error = _("bad expression");
4497 return;
4498 }
4499
4500 number = expr.X_add_number;
4501
4502 /* Check it fits an 8 bit unsigned. */
4503 if (number != (number & 0xff))
4504 {
4505 inst.error = _("immediate value out of range");
4506 return;
4507 }
4508
4509 inst.instruction |= number;
4510
4511 end_of_line (str);
4512 }
4513
4514 static bfd_reloc_code_real_type
4515 arm_parse_reloc (void)
4516 {
4517 char id [16];
4518 char * ip;
4519 unsigned int i;
4520 static struct
4521 {
4522 char * str;
4523 int len;
4524 bfd_reloc_code_real_type reloc;
4525 }
4526 reloc_map[] =
4527 {
4528 #define MAP(str,reloc) { str, sizeof (str) - 1, reloc }
4529 MAP ("(got)", BFD_RELOC_ARM_GOT32),
4530 MAP ("(gotoff)", BFD_RELOC_ARM_GOTOFF),
4531 /* ScottB: Jan 30, 1998 - Added support for parsing "var(PLT)"
4532 branch instructions generated by GCC for PLT relocs. */
4533 MAP ("(plt)", BFD_RELOC_ARM_PLT32),
4534 MAP ("(target1)", BFD_RELOC_ARM_TARGET1),
4535 MAP ("(sbrel)", BFD_RELOC_ARM_SBREL32),
4536 MAP ("(target2)", BFD_RELOC_ARM_TARGET2),
4537 { NULL, 0, BFD_RELOC_UNUSED }
4538 #undef MAP
4539 };
4540
4541 for (i = 0, ip = input_line_pointer;
4542 i < sizeof (id) && (ISALNUM (*ip) || ISPUNCT (*ip));
4543 i++, ip++)
4544 id[i] = TOLOWER (*ip);
4545
4546 for (i = 0; reloc_map[i].str; i++)
4547 if (strncmp (id, reloc_map[i].str, reloc_map[i].len) == 0)
4548 break;
4549
4550 input_line_pointer += reloc_map[i].len;
4551
4552 return reloc_map[i].reloc;
4553 }
4554
4555 /* ARM V5 branch-link-exchange (argument parse) for BLX(1) only.
4556 Expects inst.instruction is set for BLX(1).
4557 Note: this is cloned from do_branch, and the reloc changed to be a
4558 new one that can cope with setting one extra bit (the H bit). */
4559
4560 static void
4561 do_branch25 (char * str)
4562 {
4563 if (my_get_expression (& inst.reloc.exp, & str))
4564 return;
4565
4566 #ifdef OBJ_ELF
4567 {
4568 char * save_in;
4569
4570 /* ScottB: February 5, 1998 */
4571 /* Check to see of PLT32 reloc required for the instruction. */
4572
4573 /* arm_parse_reloc() works on input_line_pointer.
4574 We actually want to parse the operands to the branch instruction
4575 passed in 'str'. Save the input pointer and restore it later. */
4576 save_in = input_line_pointer;
4577 input_line_pointer = str;
4578
4579 if (inst.reloc.exp.X_op == O_symbol
4580 && *str == '('
4581 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
4582 {
4583 inst.reloc.type = BFD_RELOC_ARM_PLT32;
4584 inst.reloc.pc_rel = 0;
4585 /* Modify str to point to after parsed operands, otherwise
4586 end_of_line() will complain about the (PLT) left in str. */
4587 str = input_line_pointer;
4588 }
4589 else
4590 {
4591 inst.reloc.type = BFD_RELOC_ARM_PCREL_BLX;
4592 inst.reloc.pc_rel = 1;
4593 }
4594
4595 input_line_pointer = save_in;
4596 }
4597 #else
4598 inst.reloc.type = BFD_RELOC_ARM_PCREL_BLX;
4599 inst.reloc.pc_rel = 1;
4600 #endif /* OBJ_ELF */
4601
4602 end_of_line (str);
4603 }
4604
4605 /* ARM V5 branch-link-exchange instruction (argument parse)
4606 BLX <target_addr> ie BLX(1)
4607 BLX{<condition>} <Rm> ie BLX(2)
4608 Unfortunately, there are two different opcodes for this mnemonic.
4609 So, the insns[].value is not used, and the code here zaps values
4610 into inst.instruction.
4611 Also, the <target_addr> can be 25 bits, hence has its own reloc. */
4612
4613 static void
4614 do_blx (char * str)
4615 {
4616 char * mystr = str;
4617 int rm;
4618
4619 skip_whitespace (mystr);
4620 rm = reg_required_here (& mystr, 0);
4621
4622 /* The above may set inst.error. Ignore his opinion. */
4623 inst.error = 0;
4624
4625 if (rm != FAIL)
4626 {
4627 /* Arg is a register.
4628 Use the condition code our caller put in inst.instruction.
4629 Pass ourselves off as a BX with a funny opcode. */
4630 inst.instruction |= 0x012fff30;
4631 do_bx (str);
4632 }
4633 else
4634 {
4635 /* This must be is BLX <target address>, no condition allowed. */
4636 if (inst.instruction != COND_ALWAYS)
4637 {
4638 inst.error = BAD_COND;
4639 return;
4640 }
4641
4642 inst.instruction = 0xfafffffe;
4643
4644 /* Process like a B/BL, but with a different reloc.
4645 Note that B/BL expecte fffffe, not 0, offset in the opcode table. */
4646 do_branch25 (str);
4647 }
4648 }
4649
4650 /* ARM V5 Thumb BLX (argument parse)
4651 BLX <target_addr> which is BLX(1)
4652 BLX <Rm> which is BLX(2)
4653 Unfortunately, there are two different opcodes for this mnemonic.
4654 So, the tinsns[].value is not used, and the code here zaps values
4655 into inst.instruction. */
4656
4657 static void
4658 do_t_blx (char * str)
4659 {
4660 char * mystr = str;
4661 int rm;
4662
4663 skip_whitespace (mystr);
4664 inst.instruction = 0x4780;
4665
4666 /* Note that this call is to the ARM register recognizer. BLX(2)
4667 uses the ARM register space, not the Thumb one, so a call to
4668 thumb_reg() would be wrong. */
4669 rm = reg_required_here (& mystr, 3);
4670 inst.error = 0;
4671
4672 if (rm != FAIL)
4673 {
4674 /* It's BLX(2). The .instruction was zapped with rm & is final. */
4675 inst.size = 2;
4676 }
4677 else
4678 {
4679 /* No ARM register. This must be BLX(1). Change the .instruction. */
4680 inst.instruction = 0xf7ffeffe;
4681 inst.size = 4;
4682
4683 if (my_get_expression (& inst.reloc.exp, & mystr))
4684 return;
4685
4686 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BLX;
4687 inst.reloc.pc_rel = 1;
4688 }
4689
4690 end_of_line (mystr);
4691 }
4692
4693 /* ARM V5 breakpoint instruction (argument parse)
4694 BKPT <16 bit unsigned immediate>
4695 Instruction is not conditional.
4696 The bit pattern given in insns[] has the COND_ALWAYS condition,
4697 and it is an error if the caller tried to override that. */
4698
4699 static void
4700 do_bkpt (char * str)
4701 {
4702 expressionS expr;
4703 unsigned long number;
4704
4705 skip_whitespace (str);
4706
4707 /* Allow optional leading '#'. */
4708 if (is_immediate_prefix (* str))
4709 str++;
4710
4711 memset (& expr, '\0', sizeof (expr));
4712
4713 if (my_get_expression (& expr, & str)
4714 || (expr.X_op != O_constant
4715 /* As a convenience we allow 'bkpt' without an operand. */
4716 && expr.X_op != O_absent))
4717 {
4718 inst.error = _("bad expression");
4719 return;
4720 }
4721
4722 number = expr.X_add_number;
4723
4724 /* Check it fits a 16 bit unsigned. */
4725 if (number != (number & 0xffff))
4726 {
4727 inst.error = _("immediate value out of range");
4728 return;
4729 }
4730
4731 /* Top 12 of 16 bits to bits 19:8. */
4732 inst.instruction |= (number & 0xfff0) << 4;
4733
4734 /* Bottom 4 of 16 bits to bits 3:0. */
4735 inst.instruction |= number & 0xf;
4736
4737 end_of_line (str);
4738 }
4739
4740 /* THUMB CPS instruction (argument parse). */
4741
4742 static void
4743 do_t_cps (char * str)
4744 {
4745 do_cps_flags (&str, /*thumb_p=*/1);
4746 end_of_line (str);
4747 }
4748
4749 /* Parse and validate that a register is of the right form, this saves
4750 repeated checking of this information in many similar cases.
4751 Unlike the 32-bit case we do not insert the register into the opcode
4752 here, since the position is often unknown until the full instruction
4753 has been parsed. */
4754
4755 static int
4756 thumb_reg (char ** strp, int hi_lo)
4757 {
4758 int reg;
4759
4760 if ((reg = reg_required_here (strp, -1)) == FAIL)
4761 return FAIL;
4762
4763 switch (hi_lo)
4764 {
4765 case THUMB_REG_LO:
4766 if (reg > 7)
4767 {
4768 inst.error = _("lo register required");
4769 return FAIL;
4770 }
4771 break;
4772
4773 case THUMB_REG_HI:
4774 if (reg < 8)
4775 {
4776 inst.error = _("hi register required");
4777 return FAIL;
4778 }
4779 break;
4780
4781 default:
4782 break;
4783 }
4784
4785 return reg;
4786 }
4787
4788 static void
4789 thumb_mov_compare (char * str, int move)
4790 {
4791 int Rd, Rs = FAIL;
4792
4793 skip_whitespace (str);
4794
4795 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
4796 || skip_past_comma (&str) == FAIL)
4797 {
4798 if (! inst.error)
4799 inst.error = BAD_ARGS;
4800 return;
4801 }
4802
4803 if (move != THUMB_CPY && is_immediate_prefix (*str))
4804 {
4805 str++;
4806 if (my_get_expression (&inst.reloc.exp, &str))
4807 return;
4808 }
4809 else if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
4810 return;
4811
4812 if (Rs != FAIL)
4813 {
4814 if (move != THUMB_CPY && Rs < 8 && Rd < 8)
4815 {
4816 if (move == THUMB_MOVE)
4817 /* A move of two lowregs is encoded as ADD Rd, Rs, #0
4818 since a MOV instruction produces unpredictable results. */
4819 inst.instruction = T_OPCODE_ADD_I3;
4820 else
4821 inst.instruction = T_OPCODE_CMP_LR;
4822 inst.instruction |= Rd | (Rs << 3);
4823 }
4824 else
4825 {
4826 if (move == THUMB_MOVE)
4827 inst.instruction = T_OPCODE_MOV_HR;
4828 else if (move != THUMB_CPY)
4829 inst.instruction = T_OPCODE_CMP_HR;
4830
4831 if (Rd > 7)
4832 inst.instruction |= THUMB_H1;
4833
4834 if (Rs > 7)
4835 inst.instruction |= THUMB_H2;
4836
4837 inst.instruction |= (Rd & 7) | ((Rs & 7) << 3);
4838 }
4839 }
4840 else
4841 {
4842 if (Rd > 7)
4843 {
4844 inst.error = _("only lo regs allowed with immediate");
4845 return;
4846 }
4847
4848 if (move == THUMB_MOVE)
4849 inst.instruction = T_OPCODE_MOV_I8;
4850 else
4851 inst.instruction = T_OPCODE_CMP_I8;
4852
4853 inst.instruction |= Rd << 8;
4854
4855 if (inst.reloc.exp.X_op != O_constant)
4856 inst.reloc.type = BFD_RELOC_ARM_THUMB_IMM;
4857 else
4858 {
4859 unsigned value = inst.reloc.exp.X_add_number;
4860
4861 if (value > 255)
4862 {
4863 inst.error = _("invalid immediate");
4864 return;
4865 }
4866
4867 inst.instruction |= value;
4868 }
4869 }
4870
4871 end_of_line (str);
4872 }
4873
4874 /* THUMB CPY instruction (argument parse). */
4875
4876 static void
4877 do_t_cpy (char * str)
4878 {
4879 thumb_mov_compare (str, THUMB_CPY);
4880 }
4881
4882 /* THUMB SETEND instruction (argument parse). */
4883
4884 static void
4885 do_t_setend (char * str)
4886 {
4887 if (do_endian_specifier (str))
4888 inst.instruction |= 0x8;
4889 }
4890
4891 /* Parse INSN_TYPE insn STR having a possible IMMEDIATE_SIZE immediate. */
4892
4893 static unsigned long
4894 check_iwmmxt_insn (char * str,
4895 enum iwmmxt_insn_type insn_type,
4896 int immediate_size)
4897 {
4898 int reg = 0;
4899 const char * inst_error;
4900 expressionS expr;
4901 unsigned long number;
4902
4903 inst_error = inst.error;
4904 if (!inst.error)
4905 inst.error = BAD_ARGS;
4906 skip_whitespace (str);
4907
4908 switch (insn_type)
4909 {
4910 case check_rd:
4911 if ((reg = reg_required_here (&str, 12)) == FAIL)
4912 return FAIL;
4913 break;
4914
4915 case check_wr:
4916 if ((wreg_required_here (&str, 0, IWMMXT_REG_WR)) == FAIL)
4917 return FAIL;
4918 break;
4919
4920 case check_wrwr:
4921 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
4922 || skip_past_comma (&str) == FAIL
4923 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL))
4924 return FAIL;
4925 break;
4926
4927 case check_wrwrwr:
4928 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
4929 || skip_past_comma (&str) == FAIL
4930 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
4931 || skip_past_comma (&str) == FAIL
4932 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL))
4933 return FAIL;
4934 break;
4935
4936 case check_wrwrwcg:
4937 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
4938 || skip_past_comma (&str) == FAIL
4939 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
4940 || skip_past_comma (&str) == FAIL
4941 || wreg_required_here (&str, 0, IWMMXT_REG_WCG) == FAIL))
4942 return FAIL;
4943 break;
4944
4945 case check_tbcst:
4946 if ((wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
4947 || skip_past_comma (&str) == FAIL
4948 || reg_required_here (&str, 12) == FAIL))
4949 return FAIL;
4950 break;
4951
4952 case check_tmovmsk:
4953 if ((reg_required_here (&str, 12) == FAIL
4954 || skip_past_comma (&str) == FAIL
4955 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL))
4956 return FAIL;
4957 break;
4958
4959 case check_tmia:
4960 if ((wreg_required_here (&str, 5, IWMMXT_REG_WR) == FAIL
4961 || skip_past_comma (&str) == FAIL
4962 || reg_required_here (&str, 0) == FAIL
4963 || skip_past_comma (&str) == FAIL
4964 || reg_required_here (&str, 12) == FAIL))
4965 return FAIL;
4966 break;
4967
4968 case check_tmcrr:
4969 if ((wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL
4970 || skip_past_comma (&str) == FAIL
4971 || reg_required_here (&str, 12) == FAIL
4972 || skip_past_comma (&str) == FAIL
4973 || reg_required_here (&str, 16) == FAIL))
4974 return FAIL;
4975 break;
4976
4977 case check_tmrrc:
4978 if ((reg_required_here (&str, 12) == FAIL
4979 || skip_past_comma (&str) == FAIL
4980 || reg_required_here (&str, 16) == FAIL
4981 || skip_past_comma (&str) == FAIL
4982 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL))
4983 return FAIL;
4984 break;
4985
4986 case check_tmcr:
4987 if ((wreg_required_here (&str, 16, IWMMXT_REG_WC) == FAIL
4988 || skip_past_comma (&str) == FAIL
4989 || reg_required_here (&str, 12) == FAIL))
4990 return FAIL;
4991 break;
4992
4993 case check_tmrc:
4994 if ((reg_required_here (&str, 12) == FAIL
4995 || skip_past_comma (&str) == FAIL
4996 || wreg_required_here (&str, 16, IWMMXT_REG_WC) == FAIL))
4997 return FAIL;
4998 break;
4999
5000 case check_tinsr:
5001 if ((wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5002 || skip_past_comma (&str) == FAIL
5003 || reg_required_here (&str, 12) == FAIL
5004 || skip_past_comma (&str) == FAIL))
5005 return FAIL;
5006 break;
5007
5008 case check_textrc:
5009 if ((reg_required_here (&str, 12) == FAIL
5010 || skip_past_comma (&str) == FAIL))
5011 return FAIL;
5012 break;
5013
5014 case check_waligni:
5015 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
5016 || skip_past_comma (&str) == FAIL
5017 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5018 || skip_past_comma (&str) == FAIL
5019 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL
5020 || skip_past_comma (&str) == FAIL))
5021 return FAIL;
5022 break;
5023
5024 case check_textrm:
5025 if ((reg_required_here (&str, 12) == FAIL
5026 || skip_past_comma (&str) == FAIL
5027 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5028 || skip_past_comma (&str) == FAIL))
5029 return FAIL;
5030 break;
5031
5032 case check_wshufh:
5033 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
5034 || skip_past_comma (&str) == FAIL
5035 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5036 || skip_past_comma (&str) == FAIL))
5037 return FAIL;
5038 break;
5039 }
5040
5041 if (immediate_size == 0)
5042 {
5043 end_of_line (str);
5044 inst.error = inst_error;
5045 return reg;
5046 }
5047 else
5048 {
5049 skip_whitespace (str);
5050
5051 /* Allow optional leading '#'. */
5052 if (is_immediate_prefix (* str))
5053 str++;
5054
5055 memset (& expr, '\0', sizeof (expr));
5056
5057 if (my_get_expression (& expr, & str) || (expr.X_op != O_constant))
5058 {
5059 inst.error = _("bad or missing expression");
5060 return FAIL;
5061 }
5062
5063 number = expr.X_add_number;
5064
5065 if (number != (number & immediate_size))
5066 {
5067 inst.error = _("immediate value out of range");
5068 return FAIL;
5069 }
5070 end_of_line (str);
5071 inst.error = inst_error;
5072 return number;
5073 }
5074 }
5075
5076 static void
5077 do_iwmmxt_byte_addr (char * str)
5078 {
5079 int op = (inst.instruction & 0x300) >> 8;
5080 int reg;
5081
5082 inst.instruction &= ~0x300;
5083 inst.instruction |= (op & 1) << 22 | (op & 2) << 7;
5084
5085 skip_whitespace (str);
5086
5087 if ((reg = wreg_required_here (&str, 12, IWMMXT_REG_WR_OR_WC)) == FAIL
5088 || skip_past_comma (& str) == FAIL
5089 || cp_byte_address_required_here (&str) == FAIL)
5090 {
5091 if (! inst.error)
5092 inst.error = BAD_ARGS;
5093 }
5094 else
5095 end_of_line (str);
5096
5097 if (wc_register (reg))
5098 {
5099 as_bad (_("non-word size not supported with control register"));
5100 inst.instruction |= 0xf0000100;
5101 inst.instruction &= ~0x00400000;
5102 }
5103 }
5104
5105 static void
5106 do_iwmmxt_tandc (char * str)
5107 {
5108 int reg;
5109
5110 reg = check_iwmmxt_insn (str, check_rd, 0);
5111
5112 if (reg != REG_PC && !inst.error)
5113 inst.error = _("only r15 allowed here");
5114 }
5115
5116 static void
5117 do_iwmmxt_tbcst (char * str)
5118 {
5119 check_iwmmxt_insn (str, check_tbcst, 0);
5120 }
5121
5122 static void
5123 do_iwmmxt_textrc (char * str)
5124 {
5125 unsigned long number;
5126
5127 if ((number = check_iwmmxt_insn (str, check_textrc, 7)) == (unsigned long) FAIL)
5128 return;
5129
5130 inst.instruction |= number & 0x7;
5131 }
5132
5133 static void
5134 do_iwmmxt_textrm (char * str)
5135 {
5136 unsigned long number;
5137
5138 if ((number = check_iwmmxt_insn (str, check_textrm, 7)) == (unsigned long) FAIL)
5139 return;
5140
5141 inst.instruction |= number & 0x7;
5142 }
5143
5144 static void
5145 do_iwmmxt_tinsr (char * str)
5146 {
5147 unsigned long number;
5148
5149 if ((number = check_iwmmxt_insn (str, check_tinsr, 7)) == (unsigned long) FAIL)
5150 return;
5151
5152 inst.instruction |= number & 0x7;
5153 }
5154
5155 static void
5156 do_iwmmxt_tmcr (char * str)
5157 {
5158 check_iwmmxt_insn (str, check_tmcr, 0);
5159 }
5160
5161 static void
5162 do_iwmmxt_tmcrr (char * str)
5163 {
5164 check_iwmmxt_insn (str, check_tmcrr, 0);
5165 }
5166
5167 static void
5168 do_iwmmxt_tmia (char * str)
5169 {
5170 check_iwmmxt_insn (str, check_tmia, 0);
5171 }
5172
5173 static void
5174 do_iwmmxt_tmovmsk (char * str)
5175 {
5176 check_iwmmxt_insn (str, check_tmovmsk, 0);
5177 }
5178
5179 static void
5180 do_iwmmxt_tmrc (char * str)
5181 {
5182 check_iwmmxt_insn (str, check_tmrc, 0);
5183 }
5184
5185 static void
5186 do_iwmmxt_tmrrc (char * str)
5187 {
5188 check_iwmmxt_insn (str, check_tmrrc, 0);
5189 }
5190
5191 static void
5192 do_iwmmxt_torc (char * str)
5193 {
5194 check_iwmmxt_insn (str, check_rd, 0);
5195 }
5196
5197 static void
5198 do_iwmmxt_waligni (char * str)
5199 {
5200 unsigned long number;
5201
5202 if ((number = check_iwmmxt_insn (str, check_waligni, 7)) == (unsigned long) FAIL)
5203 return;
5204
5205 inst.instruction |= ((number & 0x7) << 20);
5206 }
5207
5208 static void
5209 do_iwmmxt_wmov (char * str)
5210 {
5211 if (check_iwmmxt_insn (str, check_wrwr, 0) == (unsigned long) FAIL)
5212 return;
5213
5214 inst.instruction |= ((inst.instruction >> 16) & 0xf);
5215 }
5216
5217 static void
5218 do_iwmmxt_word_addr (char * str)
5219 {
5220 int op = (inst.instruction & 0x300) >> 8;
5221 int reg;
5222
5223 inst.instruction &= ~0x300;
5224 inst.instruction |= (op & 1) << 22 | (op & 2) << 7;
5225
5226 skip_whitespace (str);
5227
5228 if ((reg = wreg_required_here (&str, 12, IWMMXT_REG_WR_OR_WC)) == FAIL
5229 || skip_past_comma (& str) == FAIL
5230 || cp_address_required_here (& str, CP_WB_OK) == FAIL)
5231 {
5232 if (! inst.error)
5233 inst.error = BAD_ARGS;
5234 }
5235 else
5236 end_of_line (str);
5237
5238 if (wc_register (reg))
5239 {
5240 if ((inst.instruction & COND_MASK) != COND_ALWAYS)
5241 as_bad (_("conditional execution not supported with control register"));
5242 if (op != 2)
5243 as_bad (_("non-word size not supported with control register"));
5244 inst.instruction |= 0xf0000100;
5245 inst.instruction &= ~0x00400000;
5246 }
5247 }
5248
5249 static void
5250 do_iwmmxt_wrwr (char * str)
5251 {
5252 check_iwmmxt_insn (str, check_wrwr, 0);
5253 }
5254
5255 static void
5256 do_iwmmxt_wrwrwcg (char * str)
5257 {
5258 check_iwmmxt_insn (str, check_wrwrwcg, 0);
5259 }
5260
5261 static void
5262 do_iwmmxt_wrwrwr (char * str)
5263 {
5264 check_iwmmxt_insn (str, check_wrwrwr, 0);
5265 }
5266
5267 static void
5268 do_iwmmxt_wshufh (char * str)
5269 {
5270 unsigned long number;
5271
5272 if ((number = check_iwmmxt_insn (str, check_wshufh, 0xff)) == (unsigned long) FAIL)
5273 return;
5274
5275 inst.instruction |= ((number & 0xf0) << 16) | (number & 0xf);
5276 }
5277
5278 static void
5279 do_iwmmxt_wzero (char * str)
5280 {
5281 if (check_iwmmxt_insn (str, check_wr, 0) == (unsigned long) FAIL)
5282 return;
5283
5284 inst.instruction |= ((inst.instruction & 0xf) << 12) | ((inst.instruction & 0xf) << 16);
5285 }
5286
5287 /* Xscale multiply-accumulate (argument parse)
5288 MIAcc acc0,Rm,Rs
5289 MIAPHcc acc0,Rm,Rs
5290 MIAxycc acc0,Rm,Rs. */
5291
5292 static void
5293 do_xsc_mia (char * str)
5294 {
5295 int rs;
5296 int rm;
5297
5298 if (accum0_required_here (& str) == FAIL)
5299 inst.error = ERR_NO_ACCUM;
5300
5301 else if (skip_past_comma (& str) == FAIL
5302 || (rm = reg_required_here (& str, 0)) == FAIL)
5303 inst.error = BAD_ARGS;
5304
5305 else if (skip_past_comma (& str) == FAIL
5306 || (rs = reg_required_here (& str, 12)) == FAIL)
5307 inst.error = BAD_ARGS;
5308
5309 /* inst.instruction has now been zapped with both rm and rs. */
5310 else if (rm == REG_PC || rs == REG_PC)
5311 inst.error = BAD_PC; /* Undefined result if rm or rs is R15. */
5312
5313 else
5314 end_of_line (str);
5315 }
5316
5317 /* Xscale move-accumulator-register (argument parse)
5318
5319 MARcc acc0,RdLo,RdHi. */
5320
5321 static void
5322 do_xsc_mar (char * str)
5323 {
5324 int rdlo, rdhi;
5325
5326 if (accum0_required_here (& str) == FAIL)
5327 inst.error = ERR_NO_ACCUM;
5328
5329 else if (skip_past_comma (& str) == FAIL
5330 || (rdlo = reg_required_here (& str, 12)) == FAIL)
5331 inst.error = BAD_ARGS;
5332
5333 else if (skip_past_comma (& str) == FAIL
5334 || (rdhi = reg_required_here (& str, 16)) == FAIL)
5335 inst.error = BAD_ARGS;
5336
5337 /* inst.instruction has now been zapped with both rdlo and rdhi. */
5338 else if (rdlo == REG_PC || rdhi == REG_PC)
5339 inst.error = BAD_PC; /* Undefined result if rdlo or rdhi is R15. */
5340
5341 else
5342 end_of_line (str);
5343 }
5344
5345 /* Xscale move-register-accumulator (argument parse)
5346
5347 MRAcc RdLo,RdHi,acc0. */
5348
5349 static void
5350 do_xsc_mra (char * str)
5351 {
5352 int rdlo;
5353 int rdhi;
5354
5355 skip_whitespace (str);
5356
5357 if ((rdlo = reg_required_here (& str, 12)) == FAIL)
5358 inst.error = BAD_ARGS;
5359
5360 else if (skip_past_comma (& str) == FAIL
5361 || (rdhi = reg_required_here (& str, 16)) == FAIL)
5362 inst.error = BAD_ARGS;
5363
5364 else if (skip_past_comma (& str) == FAIL
5365 || accum0_required_here (& str) == FAIL)
5366 inst.error = ERR_NO_ACCUM;
5367
5368 /* inst.instruction has now been zapped with both rdlo and rdhi. */
5369 else if (rdlo == rdhi)
5370 inst.error = BAD_ARGS; /* Undefined result if 2 writes to same reg. */
5371
5372 else if (rdlo == REG_PC || rdhi == REG_PC)
5373 inst.error = BAD_PC; /* Undefined result if rdlo or rdhi is R15. */
5374 else
5375 end_of_line (str);
5376 }
5377
5378 static int
5379 ldst_extend (char ** str)
5380 {
5381 int add = INDEX_UP;
5382
5383 switch (**str)
5384 {
5385 case '#':
5386 case '$':
5387 (*str)++;
5388 if (my_get_expression (& inst.reloc.exp, str))
5389 return FAIL;
5390
5391 if (inst.reloc.exp.X_op == O_constant)
5392 {
5393 int value = inst.reloc.exp.X_add_number;
5394
5395 if (value < -4095 || value > 4095)
5396 {
5397 inst.error = _("address offset too large");
5398 return FAIL;
5399 }
5400
5401 if (value < 0)
5402 {
5403 value = -value;
5404 add = 0;
5405 }
5406
5407 inst.instruction |= add | value;
5408 }
5409 else
5410 {
5411 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
5412 inst.reloc.pc_rel = 0;
5413 }
5414 return SUCCESS;
5415
5416 case '-':
5417 add = 0;
5418 /* Fall through. */
5419
5420 case '+':
5421 (*str)++;
5422 /* Fall through. */
5423
5424 default:
5425 if (reg_required_here (str, 0) == FAIL)
5426 return FAIL;
5427
5428 inst.instruction |= add | OFFSET_REG;
5429 if (skip_past_comma (str) == SUCCESS)
5430 return decode_shift (str, SHIFT_IMMEDIATE);
5431
5432 return SUCCESS;
5433 }
5434 }
5435
5436 /* ARMv5TE: Preload-Cache
5437
5438 PLD <addr_mode>
5439
5440 Syntactically, like LDR with B=1, W=0, L=1. */
5441
5442 static void
5443 do_pld (char * str)
5444 {
5445 int rd;
5446
5447 skip_whitespace (str);
5448
5449 if (* str != '[')
5450 {
5451 inst.error = _("'[' expected after PLD mnemonic");
5452 return;
5453 }
5454
5455 ++str;
5456 skip_whitespace (str);
5457
5458 if ((rd = reg_required_here (& str, 16)) == FAIL)
5459 return;
5460
5461 skip_whitespace (str);
5462
5463 if (*str == ']')
5464 {
5465 /* [Rn], ... ? */
5466 ++str;
5467 skip_whitespace (str);
5468
5469 /* Post-indexed addressing is not allowed with PLD. */
5470 if (skip_past_comma (&str) == SUCCESS)
5471 {
5472 inst.error
5473 = _("post-indexed expression used in preload instruction");
5474 return;
5475 }
5476 else if (*str == '!') /* [Rn]! */
5477 {
5478 inst.error = _("writeback used in preload instruction");
5479 ++str;
5480 }
5481 else /* [Rn] */
5482 inst.instruction |= INDEX_UP | PRE_INDEX;
5483 }
5484 else /* [Rn, ...] */
5485 {
5486 if (skip_past_comma (& str) == FAIL)
5487 {
5488 inst.error = _("pre-indexed expression expected");
5489 return;
5490 }
5491
5492 if (ldst_extend (&str) == FAIL)
5493 return;
5494
5495 skip_whitespace (str);
5496
5497 if (* str != ']')
5498 {
5499 inst.error = _("missing ]");
5500 return;
5501 }
5502
5503 ++ str;
5504 skip_whitespace (str);
5505
5506 if (* str == '!') /* [Rn]! */
5507 {
5508 inst.error = _("writeback used in preload instruction");
5509 ++ str;
5510 }
5511
5512 inst.instruction |= PRE_INDEX;
5513 }
5514
5515 end_of_line (str);
5516 }
5517
5518 /* ARMv5TE load-consecutive (argument parse)
5519 Mode is like LDRH.
5520
5521 LDRccD R, mode
5522 STRccD R, mode. */
5523
5524 static void
5525 do_ldrd (char * str)
5526 {
5527 int rd;
5528 int rn;
5529
5530 skip_whitespace (str);
5531
5532 if ((rd = reg_required_here (& str, 12)) == FAIL)
5533 {
5534 inst.error = BAD_ARGS;
5535 return;
5536 }
5537
5538 if (skip_past_comma (& str) == FAIL
5539 || (rn = ld_mode_required_here (& str)) == FAIL)
5540 {
5541 if (!inst.error)
5542 inst.error = BAD_ARGS;
5543 return;
5544 }
5545
5546 /* inst.instruction has now been zapped with Rd and the addressing mode. */
5547 if (rd & 1) /* Unpredictable result if Rd is odd. */
5548 {
5549 inst.error = _("destination register must be even");
5550 return;
5551 }
5552
5553 if (rd == REG_LR)
5554 {
5555 inst.error = _("r14 not allowed here");
5556 return;
5557 }
5558
5559 if (((rd == rn) || (rd + 1 == rn))
5560 && ((inst.instruction & WRITE_BACK)
5561 || (!(inst.instruction & PRE_INDEX))))
5562 as_warn (_("pre/post-indexing used when modified address register is destination"));
5563
5564 /* For an index-register load, the index register must not overlap the
5565 destination (even if not write-back). */
5566 if ((inst.instruction & V4_STR_BIT) == 0
5567 && (inst.instruction & HWOFFSET_IMM) == 0)
5568 {
5569 int rm = inst.instruction & 0x0000000f;
5570
5571 if (rm == rd || (rm == rd + 1))
5572 as_warn (_("ldrd destination registers must not overlap index register"));
5573 }
5574
5575 end_of_line (str);
5576 }
5577
5578 /* Returns the index into fp_values of a floating point number,
5579 or -1 if not in the table. */
5580
5581 static int
5582 my_get_float_expression (char ** str)
5583 {
5584 LITTLENUM_TYPE words[MAX_LITTLENUMS];
5585 char * save_in;
5586 expressionS exp;
5587 int i;
5588 int j;
5589
5590 memset (words, 0, MAX_LITTLENUMS * sizeof (LITTLENUM_TYPE));
5591
5592 /* Look for a raw floating point number. */
5593 if ((save_in = atof_ieee (*str, 'x', words)) != NULL
5594 && is_end_of_line[(unsigned char) *save_in])
5595 {
5596 for (i = 0; i < NUM_FLOAT_VALS; i++)
5597 {
5598 for (j = 0; j < MAX_LITTLENUMS; j++)
5599 {
5600 if (words[j] != fp_values[i][j])
5601 break;
5602 }
5603
5604 if (j == MAX_LITTLENUMS)
5605 {
5606 *str = save_in;
5607 return i;
5608 }
5609 }
5610 }
5611
5612 /* Try and parse a more complex expression, this will probably fail
5613 unless the code uses a floating point prefix (eg "0f"). */
5614 save_in = input_line_pointer;
5615 input_line_pointer = *str;
5616 if (expression (&exp) == absolute_section
5617 && exp.X_op == O_big
5618 && exp.X_add_number < 0)
5619 {
5620 /* FIXME: 5 = X_PRECISION, should be #define'd where we can use it.
5621 Ditto for 15. */
5622 if (gen_to_words (words, 5, (long) 15) == 0)
5623 {
5624 for (i = 0; i < NUM_FLOAT_VALS; i++)
5625 {
5626 for (j = 0; j < MAX_LITTLENUMS; j++)
5627 {
5628 if (words[j] != fp_values[i][j])
5629 break;
5630 }
5631
5632 if (j == MAX_LITTLENUMS)
5633 {
5634 *str = input_line_pointer;
5635 input_line_pointer = save_in;
5636 return i;
5637 }
5638 }
5639 }
5640 }
5641
5642 *str = input_line_pointer;
5643 input_line_pointer = save_in;
5644 return -1;
5645 }
5646
5647 /* We handle all bad expressions here, so that we can report the faulty
5648 instruction in the error message. */
5649 void
5650 md_operand (expressionS * expr)
5651 {
5652 if (in_my_get_expression)
5653 {
5654 expr->X_op = O_illegal;
5655 if (inst.error == NULL)
5656 inst.error = _("bad expression");
5657 }
5658 }
5659
5660 /* Do those data_ops which can take a negative immediate constant
5661 by altering the instruction. A bit of a hack really.
5662 MOV <-> MVN
5663 AND <-> BIC
5664 ADC <-> SBC
5665 by inverting the second operand, and
5666 ADD <-> SUB
5667 CMP <-> CMN
5668 by negating the second operand. */
5669
5670 static int
5671 negate_data_op (unsigned long * instruction,
5672 unsigned long value)
5673 {
5674 int op, new_inst;
5675 unsigned long negated, inverted;
5676
5677 negated = validate_immediate (-value);
5678 inverted = validate_immediate (~value);
5679
5680 op = (*instruction >> DATA_OP_SHIFT) & 0xf;
5681 switch (op)
5682 {
5683 /* First negates. */
5684 case OPCODE_SUB: /* ADD <-> SUB */
5685 new_inst = OPCODE_ADD;
5686 value = negated;
5687 break;
5688
5689 case OPCODE_ADD:
5690 new_inst = OPCODE_SUB;
5691 value = negated;
5692 break;
5693
5694 case OPCODE_CMP: /* CMP <-> CMN */
5695 new_inst = OPCODE_CMN;
5696 value = negated;
5697 break;
5698
5699 case OPCODE_CMN:
5700 new_inst = OPCODE_CMP;
5701 value = negated;
5702 break;
5703
5704 /* Now Inverted ops. */
5705 case OPCODE_MOV: /* MOV <-> MVN */
5706 new_inst = OPCODE_MVN;
5707 value = inverted;
5708 break;
5709
5710 case OPCODE_MVN:
5711 new_inst = OPCODE_MOV;
5712 value = inverted;
5713 break;
5714
5715 case OPCODE_AND: /* AND <-> BIC */
5716 new_inst = OPCODE_BIC;
5717 value = inverted;
5718 break;
5719
5720 case OPCODE_BIC:
5721 new_inst = OPCODE_AND;
5722 value = inverted;
5723 break;
5724
5725 case OPCODE_ADC: /* ADC <-> SBC */
5726 new_inst = OPCODE_SBC;
5727 value = inverted;
5728 break;
5729
5730 case OPCODE_SBC:
5731 new_inst = OPCODE_ADC;
5732 value = inverted;
5733 break;
5734
5735 /* We cannot do anything. */
5736 default:
5737 return FAIL;
5738 }
5739
5740 if (value == (unsigned) FAIL)
5741 return FAIL;
5742
5743 *instruction &= OPCODE_MASK;
5744 *instruction |= new_inst << DATA_OP_SHIFT;
5745 return value;
5746 }
5747
5748 static int
5749 data_op2 (char ** str)
5750 {
5751 int value;
5752 expressionS expr;
5753
5754 skip_whitespace (* str);
5755
5756 if (reg_required_here (str, 0) != FAIL)
5757 {
5758 if (skip_past_comma (str) == SUCCESS)
5759 /* Shift operation on register. */
5760 return decode_shift (str, NO_SHIFT_RESTRICT);
5761
5762 return SUCCESS;
5763 }
5764 else
5765 {
5766 /* Immediate expression. */
5767 if (is_immediate_prefix (**str))
5768 {
5769 (*str)++;
5770 inst.error = NULL;
5771
5772 if (my_get_expression (&inst.reloc.exp, str))
5773 return FAIL;
5774
5775 if (inst.reloc.exp.X_add_symbol)
5776 {
5777 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
5778 inst.reloc.pc_rel = 0;
5779 }
5780 else
5781 {
5782 if (skip_past_comma (str) == SUCCESS)
5783 {
5784 /* #x, y -- ie explicit rotation by Y. */
5785 if (my_get_expression (&expr, str))
5786 return FAIL;
5787
5788 if (expr.X_op != O_constant)
5789 {
5790 inst.error = _("constant expression expected");
5791 return FAIL;
5792 }
5793
5794 /* Rotate must be a multiple of 2. */
5795 if (((unsigned) expr.X_add_number) > 30
5796 || (expr.X_add_number & 1) != 0
5797 || ((unsigned) inst.reloc.exp.X_add_number) > 255)
5798 {
5799 inst.error = _("invalid constant");
5800 return FAIL;
5801 }
5802 inst.instruction |= INST_IMMEDIATE;
5803 inst.instruction |= inst.reloc.exp.X_add_number;
5804 inst.instruction |= expr.X_add_number << 7;
5805 return SUCCESS;
5806 }
5807
5808 /* Implicit rotation, select a suitable one. */
5809 value = validate_immediate (inst.reloc.exp.X_add_number);
5810
5811 if (value == FAIL)
5812 {
5813 /* Can't be done. Perhaps the code reads something like
5814 "add Rd, Rn, #-n", where "sub Rd, Rn, #n" would be OK. */
5815 if ((value = negate_data_op (&inst.instruction,
5816 inst.reloc.exp.X_add_number))
5817 == FAIL)
5818 {
5819 inst.error = _("invalid constant");
5820 return FAIL;
5821 }
5822 }
5823
5824 inst.instruction |= value;
5825 }
5826
5827 inst.instruction |= INST_IMMEDIATE;
5828 return SUCCESS;
5829 }
5830
5831 (*str)++;
5832 inst.error = _("register or shift expression expected");
5833 return FAIL;
5834 }
5835 }
5836
5837 static int
5838 fp_op2 (char ** str)
5839 {
5840 skip_whitespace (* str);
5841
5842 if (fp_reg_required_here (str, 0) != FAIL)
5843 return SUCCESS;
5844 else
5845 {
5846 /* Immediate expression. */
5847 if (*((*str)++) == '#')
5848 {
5849 int i;
5850
5851 inst.error = NULL;
5852
5853 skip_whitespace (* str);
5854
5855 /* First try and match exact strings, this is to guarantee
5856 that some formats will work even for cross assembly. */
5857
5858 for (i = 0; fp_const[i]; i++)
5859 {
5860 if (strncmp (*str, fp_const[i], strlen (fp_const[i])) == 0)
5861 {
5862 char *start = *str;
5863
5864 *str += strlen (fp_const[i]);
5865 if (is_end_of_line[(unsigned char) **str])
5866 {
5867 inst.instruction |= i + 8;
5868 return SUCCESS;
5869 }
5870 *str = start;
5871 }
5872 }
5873
5874 /* Just because we didn't get a match doesn't mean that the
5875 constant isn't valid, just that it is in a format that we
5876 don't automatically recognize. Try parsing it with
5877 the standard expression routines. */
5878 if ((i = my_get_float_expression (str)) >= 0)
5879 {
5880 inst.instruction |= i + 8;
5881 return SUCCESS;
5882 }
5883
5884 inst.error = _("invalid floating point immediate expression");
5885 return FAIL;
5886 }
5887 inst.error =
5888 _("floating point register or immediate expression expected");
5889 return FAIL;
5890 }
5891 }
5892
5893 static void
5894 do_arit (char * str)
5895 {
5896 skip_whitespace (str);
5897
5898 if (reg_required_here (&str, 12) == FAIL
5899 || skip_past_comma (&str) == FAIL
5900 || reg_required_here (&str, 16) == FAIL
5901 || skip_past_comma (&str) == FAIL
5902 || data_op2 (&str) == FAIL)
5903 {
5904 if (!inst.error)
5905 inst.error = BAD_ARGS;
5906 return;
5907 }
5908
5909 end_of_line (str);
5910 }
5911
5912 static void
5913 do_adr (char * str)
5914 {
5915 /* This is a pseudo-op of the form "adr rd, label" to be converted
5916 into a relative address of the form "add rd, pc, #label-.-8". */
5917 skip_whitespace (str);
5918
5919 if (reg_required_here (&str, 12) == FAIL
5920 || skip_past_comma (&str) == FAIL
5921 || my_get_expression (&inst.reloc.exp, &str))
5922 {
5923 if (!inst.error)
5924 inst.error = BAD_ARGS;
5925 return;
5926 }
5927
5928 /* Frag hacking will turn this into a sub instruction if the offset turns
5929 out to be negative. */
5930 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
5931 #ifndef TE_WINCE
5932 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust. */
5933 #endif
5934 inst.reloc.pc_rel = 1;
5935
5936 end_of_line (str);
5937 }
5938
5939 static void
5940 do_adrl (char * str)
5941 {
5942 /* This is a pseudo-op of the form "adrl rd, label" to be converted
5943 into a relative address of the form:
5944 add rd, pc, #low(label-.-8)"
5945 add rd, rd, #high(label-.-8)" */
5946
5947 skip_whitespace (str);
5948
5949 if (reg_required_here (&str, 12) == FAIL
5950 || skip_past_comma (&str) == FAIL
5951 || my_get_expression (&inst.reloc.exp, &str))
5952 {
5953 if (!inst.error)
5954 inst.error = BAD_ARGS;
5955
5956 return;
5957 }
5958
5959 end_of_line (str);
5960 /* Frag hacking will turn this into a sub instruction if the offset turns
5961 out to be negative. */
5962 inst.reloc.type = BFD_RELOC_ARM_ADRL_IMMEDIATE;
5963 #ifndef TE_WINCE
5964 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust */
5965 #endif
5966 inst.reloc.pc_rel = 1;
5967 inst.size = INSN_SIZE * 2;
5968 }
5969
5970 static void
5971 do_cmp (char * str)
5972 {
5973 skip_whitespace (str);
5974
5975 if (reg_required_here (&str, 16) == FAIL)
5976 {
5977 if (!inst.error)
5978 inst.error = BAD_ARGS;
5979 return;
5980 }
5981
5982 if (skip_past_comma (&str) == FAIL
5983 || data_op2 (&str) == FAIL)
5984 {
5985 if (!inst.error)
5986 inst.error = BAD_ARGS;
5987 return;
5988 }
5989
5990 end_of_line (str);
5991 }
5992
5993 static void
5994 do_mov (char * str)
5995 {
5996 skip_whitespace (str);
5997
5998 if (reg_required_here (&str, 12) == FAIL)
5999 {
6000 if (!inst.error)
6001 inst.error = BAD_ARGS;
6002 return;
6003 }
6004
6005 if (skip_past_comma (&str) == FAIL
6006 || data_op2 (&str) == FAIL)
6007 {
6008 if (!inst.error)
6009 inst.error = BAD_ARGS;
6010 return;
6011 }
6012
6013 end_of_line (str);
6014 }
6015
6016 static void
6017 do_ldst (char * str)
6018 {
6019 int pre_inc = 0;
6020 int conflict_reg;
6021 int value;
6022
6023 skip_whitespace (str);
6024
6025 if ((conflict_reg = reg_required_here (&str, 12)) == FAIL)
6026 {
6027 if (!inst.error)
6028 inst.error = BAD_ARGS;
6029 return;
6030 }
6031
6032 if (skip_past_comma (&str) == FAIL)
6033 {
6034 inst.error = _("address expected");
6035 return;
6036 }
6037
6038 if (*str == '[')
6039 {
6040 int reg;
6041
6042 str++;
6043
6044 skip_whitespace (str);
6045
6046 if ((reg = reg_required_here (&str, 16)) == FAIL)
6047 return;
6048
6049 /* Conflicts can occur on stores as well as loads. */
6050 conflict_reg = (conflict_reg == reg);
6051
6052 skip_whitespace (str);
6053
6054 if (*str == ']')
6055 {
6056 str ++;
6057
6058 if (skip_past_comma (&str) == SUCCESS)
6059 {
6060 /* [Rn],... (post inc) */
6061 if (ldst_extend (&str) == FAIL)
6062 return;
6063 if (conflict_reg)
6064 as_warn (_("%s register same as write-back base"),
6065 ((inst.instruction & LOAD_BIT)
6066 ? _("destination") : _("source")));
6067 }
6068 else
6069 {
6070 /* [Rn] */
6071 skip_whitespace (str);
6072
6073 if (*str == '!')
6074 {
6075 if (conflict_reg)
6076 as_warn (_("%s register same as write-back base"),
6077 ((inst.instruction & LOAD_BIT)
6078 ? _("destination") : _("source")));
6079 str++;
6080 inst.instruction |= WRITE_BACK;
6081 }
6082
6083 inst.instruction |= INDEX_UP;
6084 pre_inc = 1;
6085 }
6086 }
6087 else
6088 {
6089 /* [Rn,...] */
6090 if (skip_past_comma (&str) == FAIL)
6091 {
6092 inst.error = _("pre-indexed expression expected");
6093 return;
6094 }
6095
6096 pre_inc = 1;
6097 if (ldst_extend (&str) == FAIL)
6098 return;
6099
6100 skip_whitespace (str);
6101
6102 if (*str++ != ']')
6103 {
6104 inst.error = _("missing ]");
6105 return;
6106 }
6107
6108 skip_whitespace (str);
6109
6110 if (*str == '!')
6111 {
6112 if (conflict_reg)
6113 as_warn (_("%s register same as write-back base"),
6114 ((inst.instruction & LOAD_BIT)
6115 ? _("destination") : _("source")));
6116 str++;
6117 inst.instruction |= WRITE_BACK;
6118 }
6119 }
6120 }
6121 else if (*str == '=')
6122 {
6123 if ((inst.instruction & LOAD_BIT) == 0)
6124 {
6125 inst.error = _("invalid pseudo operation");
6126 return;
6127 }
6128
6129 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
6130 str++;
6131
6132 skip_whitespace (str);
6133
6134 if (my_get_expression (&inst.reloc.exp, &str))
6135 return;
6136
6137 if (inst.reloc.exp.X_op != O_constant
6138 && inst.reloc.exp.X_op != O_symbol)
6139 {
6140 inst.error = _("constant expression expected");
6141 return;
6142 }
6143
6144 if (inst.reloc.exp.X_op == O_constant)
6145 {
6146 value = validate_immediate (inst.reloc.exp.X_add_number);
6147
6148 if (value != FAIL)
6149 {
6150 /* This can be done with a mov instruction. */
6151 inst.instruction &= LITERAL_MASK;
6152 inst.instruction |= (INST_IMMEDIATE
6153 | (OPCODE_MOV << DATA_OP_SHIFT));
6154 inst.instruction |= value & 0xfff;
6155 end_of_line (str);
6156 return;
6157 }
6158
6159 value = validate_immediate (~inst.reloc.exp.X_add_number);
6160
6161 if (value != FAIL)
6162 {
6163 /* This can be done with a mvn instruction. */
6164 inst.instruction &= LITERAL_MASK;
6165 inst.instruction |= (INST_IMMEDIATE
6166 | (OPCODE_MVN << DATA_OP_SHIFT));
6167 inst.instruction |= value & 0xfff;
6168 end_of_line (str);
6169 return;
6170 }
6171 }
6172
6173 /* Insert into literal pool. */
6174 if (add_to_lit_pool () == FAIL)
6175 {
6176 if (!inst.error)
6177 inst.error = _("literal pool insertion failed");
6178 return;
6179 }
6180
6181 /* Change the instruction exp to point to the pool. */
6182 inst.reloc.type = BFD_RELOC_ARM_LITERAL;
6183 inst.reloc.pc_rel = 1;
6184 inst.instruction |= (REG_PC << 16);
6185 pre_inc = 1;
6186 }
6187 else
6188 {
6189 if (my_get_expression (&inst.reloc.exp, &str))
6190 return;
6191
6192 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
6193 #ifndef TE_WINCE
6194 /* PC rel adjust. */
6195 inst.reloc.exp.X_add_number -= 8;
6196 #endif
6197 inst.reloc.pc_rel = 1;
6198 inst.instruction |= (REG_PC << 16);
6199 pre_inc = 1;
6200 }
6201
6202 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
6203 end_of_line (str);
6204 }
6205
6206 static void
6207 do_ldstt (char * str)
6208 {
6209 int conflict_reg;
6210
6211 skip_whitespace (str);
6212
6213 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
6214 {
6215 if (!inst.error)
6216 inst.error = BAD_ARGS;
6217 return;
6218 }
6219
6220 if (skip_past_comma (& str) == FAIL)
6221 {
6222 inst.error = _("address expected");
6223 return;
6224 }
6225
6226 if (*str == '[')
6227 {
6228 int reg;
6229
6230 str++;
6231
6232 skip_whitespace (str);
6233
6234 if ((reg = reg_required_here (&str, 16)) == FAIL)
6235 return;
6236
6237 /* ldrt/strt always use post-indexed addressing, so if the base is
6238 the same as Rd, we warn. */
6239 if (conflict_reg == reg)
6240 as_warn (_("%s register same as write-back base"),
6241 ((inst.instruction & LOAD_BIT)
6242 ? _("destination") : _("source")));
6243
6244 skip_whitespace (str);
6245
6246 if (*str == ']')
6247 {
6248 str ++;
6249
6250 if (skip_past_comma (&str) == SUCCESS)
6251 {
6252 /* [Rn],... (post inc) */
6253 if (ldst_extend (&str) == FAIL)
6254 return;
6255 }
6256 else
6257 {
6258 /* [Rn] */
6259 skip_whitespace (str);
6260
6261 /* Skip a write-back '!'. */
6262 if (*str == '!')
6263 str++;
6264
6265 inst.instruction |= INDEX_UP;
6266 }
6267 }
6268 else
6269 {
6270 inst.error = _("post-indexed expression expected");
6271 return;
6272 }
6273 }
6274 else
6275 {
6276 inst.error = _("post-indexed expression expected");
6277 return;
6278 }
6279
6280 end_of_line (str);
6281 }
6282
6283 /* Halfword and signed-byte load/store operations. */
6284
6285 static void
6286 do_ldstv4 (char * str)
6287 {
6288 int pre_inc = 0;
6289 int conflict_reg;
6290 int value;
6291
6292 skip_whitespace (str);
6293
6294 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
6295 {
6296 if (!inst.error)
6297 inst.error = BAD_ARGS;
6298 return;
6299 }
6300
6301 if (skip_past_comma (& str) == FAIL)
6302 {
6303 inst.error = _("address expected");
6304 return;
6305 }
6306
6307 if (*str == '[')
6308 {
6309 int reg;
6310
6311 str++;
6312
6313 skip_whitespace (str);
6314
6315 if ((reg = reg_required_here (&str, 16)) == FAIL)
6316 return;
6317
6318 /* Conflicts can occur on stores as well as loads. */
6319 conflict_reg = (conflict_reg == reg);
6320
6321 skip_whitespace (str);
6322
6323 if (*str == ']')
6324 {
6325 str ++;
6326
6327 if (skip_past_comma (&str) == SUCCESS)
6328 {
6329 /* [Rn],... (post inc) */
6330 if (ldst_extend_v4 (&str) == FAIL)
6331 return;
6332 if (conflict_reg)
6333 as_warn (_("%s register same as write-back base"),
6334 ((inst.instruction & LOAD_BIT)
6335 ? _("destination") : _("source")));
6336 }
6337 else
6338 {
6339 /* [Rn] */
6340 inst.instruction |= HWOFFSET_IMM;
6341
6342 skip_whitespace (str);
6343
6344 if (*str == '!')
6345 {
6346 if (conflict_reg)
6347 as_warn (_("%s register same as write-back base"),
6348 ((inst.instruction & LOAD_BIT)
6349 ? _("destination") : _("source")));
6350 str++;
6351 inst.instruction |= WRITE_BACK;
6352 }
6353
6354 inst.instruction |= INDEX_UP;
6355 pre_inc = 1;
6356 }
6357 }
6358 else
6359 {
6360 /* [Rn,...] */
6361 if (skip_past_comma (&str) == FAIL)
6362 {
6363 inst.error = _("pre-indexed expression expected");
6364 return;
6365 }
6366
6367 pre_inc = 1;
6368 if (ldst_extend_v4 (&str) == FAIL)
6369 return;
6370
6371 skip_whitespace (str);
6372
6373 if (*str++ != ']')
6374 {
6375 inst.error = _("missing ]");
6376 return;
6377 }
6378
6379 skip_whitespace (str);
6380
6381 if (*str == '!')
6382 {
6383 if (conflict_reg)
6384 as_warn (_("%s register same as write-back base"),
6385 ((inst.instruction & LOAD_BIT)
6386 ? _("destination") : _("source")));
6387 str++;
6388 inst.instruction |= WRITE_BACK;
6389 }
6390 }
6391 }
6392 else if (*str == '=')
6393 {
6394 if ((inst.instruction & LOAD_BIT) == 0)
6395 {
6396 inst.error = _("invalid pseudo operation");
6397 return;
6398 }
6399
6400 /* XXX Does this work correctly for half-word/byte ops? */
6401 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
6402 str++;
6403
6404 skip_whitespace (str);
6405
6406 if (my_get_expression (&inst.reloc.exp, &str))
6407 return;
6408
6409 if (inst.reloc.exp.X_op != O_constant
6410 && inst.reloc.exp.X_op != O_symbol)
6411 {
6412 inst.error = _("constant expression expected");
6413 return;
6414 }
6415
6416 if (inst.reloc.exp.X_op == O_constant)
6417 {
6418 value = validate_immediate (inst.reloc.exp.X_add_number);
6419
6420 if (value != FAIL)
6421 {
6422 /* This can be done with a mov instruction. */
6423 inst.instruction &= LITERAL_MASK;
6424 inst.instruction |= INST_IMMEDIATE | (OPCODE_MOV << DATA_OP_SHIFT);
6425 inst.instruction |= value & 0xfff;
6426 end_of_line (str);
6427 return;
6428 }
6429
6430 value = validate_immediate (~ inst.reloc.exp.X_add_number);
6431
6432 if (value != FAIL)
6433 {
6434 /* This can be done with a mvn instruction. */
6435 inst.instruction &= LITERAL_MASK;
6436 inst.instruction |= INST_IMMEDIATE | (OPCODE_MVN << DATA_OP_SHIFT);
6437 inst.instruction |= value & 0xfff;
6438 end_of_line (str);
6439 return;
6440 }
6441 }
6442
6443 /* Insert into literal pool. */
6444 if (add_to_lit_pool () == FAIL)
6445 {
6446 if (!inst.error)
6447 inst.error = _("literal pool insertion failed");
6448 return;
6449 }
6450
6451 /* Change the instruction exp to point to the pool. */
6452 inst.instruction |= HWOFFSET_IMM;
6453 inst.reloc.type = BFD_RELOC_ARM_HWLITERAL;
6454 inst.reloc.pc_rel = 1;
6455 inst.instruction |= (REG_PC << 16);
6456 pre_inc = 1;
6457 }
6458 else
6459 {
6460 if (my_get_expression (&inst.reloc.exp, &str))
6461 return;
6462
6463 inst.instruction |= HWOFFSET_IMM;
6464 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
6465 #ifndef TE_WINCE
6466 /* PC rel adjust. */
6467 inst.reloc.exp.X_add_number -= 8;
6468 #endif
6469 inst.reloc.pc_rel = 1;
6470 inst.instruction |= (REG_PC << 16);
6471 pre_inc = 1;
6472 }
6473
6474 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
6475 end_of_line (str);
6476 }
6477
6478 static long
6479 reg_list (char ** strp)
6480 {
6481 char * str = * strp;
6482 long range = 0;
6483 int another_range;
6484
6485 /* We come back here if we get ranges concatenated by '+' or '|'. */
6486 do
6487 {
6488 another_range = 0;
6489
6490 if (*str == '{')
6491 {
6492 int in_range = 0;
6493 int cur_reg = -1;
6494
6495 str++;
6496 do
6497 {
6498 int reg;
6499
6500 skip_whitespace (str);
6501
6502 if ((reg = reg_required_here (& str, -1)) == FAIL)
6503 return FAIL;
6504
6505 if (in_range)
6506 {
6507 int i;
6508
6509 if (reg <= cur_reg)
6510 {
6511 inst.error = _("bad range in register list");
6512 return FAIL;
6513 }
6514
6515 for (i = cur_reg + 1; i < reg; i++)
6516 {
6517 if (range & (1 << i))
6518 as_tsktsk
6519 (_("Warning: duplicated register (r%d) in register list"),
6520 i);
6521 else
6522 range |= 1 << i;
6523 }
6524 in_range = 0;
6525 }
6526
6527 if (range & (1 << reg))
6528 as_tsktsk (_("Warning: duplicated register (r%d) in register list"),
6529 reg);
6530 else if (reg <= cur_reg)
6531 as_tsktsk (_("Warning: register range not in ascending order"));
6532
6533 range |= 1 << reg;
6534 cur_reg = reg;
6535 }
6536 while (skip_past_comma (&str) != FAIL
6537 || (in_range = 1, *str++ == '-'));
6538 str--;
6539 skip_whitespace (str);
6540
6541 if (*str++ != '}')
6542 {
6543 inst.error = _("missing `}'");
6544 return FAIL;
6545 }
6546 }
6547 else
6548 {
6549 expressionS expr;
6550
6551 if (my_get_expression (&expr, &str))
6552 return FAIL;
6553
6554 if (expr.X_op == O_constant)
6555 {
6556 if (expr.X_add_number
6557 != (expr.X_add_number & 0x0000ffff))
6558 {
6559 inst.error = _("invalid register mask");
6560 return FAIL;
6561 }
6562
6563 if ((range & expr.X_add_number) != 0)
6564 {
6565 int regno = range & expr.X_add_number;
6566
6567 regno &= -regno;
6568 regno = (1 << regno) - 1;
6569 as_tsktsk
6570 (_("Warning: duplicated register (r%d) in register list"),
6571 regno);
6572 }
6573
6574 range |= expr.X_add_number;
6575 }
6576 else
6577 {
6578 if (inst.reloc.type != 0)
6579 {
6580 inst.error = _("expression too complex");
6581 return FAIL;
6582 }
6583
6584 memcpy (&inst.reloc.exp, &expr, sizeof (expressionS));
6585 inst.reloc.type = BFD_RELOC_ARM_MULTI;
6586 inst.reloc.pc_rel = 0;
6587 }
6588 }
6589
6590 skip_whitespace (str);
6591
6592 if (*str == '|' || *str == '+')
6593 {
6594 str++;
6595 another_range = 1;
6596 }
6597 }
6598 while (another_range);
6599
6600 *strp = str;
6601 return range;
6602 }
6603
6604 static void
6605 do_ldmstm (char * str)
6606 {
6607 int base_reg;
6608 long range;
6609
6610 skip_whitespace (str);
6611
6612 if ((base_reg = reg_required_here (&str, 16)) == FAIL)
6613 return;
6614
6615 if (base_reg == REG_PC)
6616 {
6617 inst.error = _("r15 not allowed as base register");
6618 return;
6619 }
6620
6621 skip_whitespace (str);
6622
6623 if (*str == '!')
6624 {
6625 inst.instruction |= WRITE_BACK;
6626 str++;
6627 }
6628
6629 if (skip_past_comma (&str) == FAIL
6630 || (range = reg_list (&str)) == FAIL)
6631 {
6632 if (! inst.error)
6633 inst.error = BAD_ARGS;
6634 return;
6635 }
6636
6637 if (*str == '^')
6638 {
6639 str++;
6640 inst.instruction |= LDM_TYPE_2_OR_3;
6641 }
6642
6643 if (inst.instruction & WRITE_BACK)
6644 {
6645 /* Check for unpredictable uses of writeback. */
6646 if (inst.instruction & LOAD_BIT)
6647 {
6648 /* Not allowed in LDM type 2. */
6649 if ((inst.instruction & LDM_TYPE_2_OR_3)
6650 && ((range & (1 << REG_PC)) == 0))
6651 as_warn (_("writeback of base register is UNPREDICTABLE"));
6652 /* Only allowed if base reg not in list for other types. */
6653 else if (range & (1 << base_reg))
6654 as_warn (_("writeback of base register when in register list is UNPREDICTABLE"));
6655 }
6656 else /* STM. */
6657 {
6658 /* Not allowed for type 2. */
6659 if (inst.instruction & LDM_TYPE_2_OR_3)
6660 as_warn (_("writeback of base register is UNPREDICTABLE"));
6661 /* Only allowed if base reg not in list, or first in list. */
6662 else if ((range & (1 << base_reg))
6663 && (range & ((1 << base_reg) - 1)))
6664 as_warn (_("if writeback register is in list, it must be the lowest reg in the list"));
6665 }
6666 }
6667
6668 inst.instruction |= range;
6669 end_of_line (str);
6670 }
6671
6672 static void
6673 do_smi (char * str)
6674 {
6675 skip_whitespace (str);
6676
6677 /* Allow optional leading '#'. */
6678 if (is_immediate_prefix (*str))
6679 str++;
6680
6681 if (my_get_expression (& inst.reloc.exp, & str))
6682 return;
6683
6684 inst.reloc.type = BFD_RELOC_ARM_SMI;
6685 inst.reloc.pc_rel = 0;
6686 end_of_line (str);
6687 }
6688
6689 static void
6690 do_swi (char * str)
6691 {
6692 skip_whitespace (str);
6693
6694 /* Allow optional leading '#'. */
6695 if (is_immediate_prefix (*str))
6696 str++;
6697
6698 if (my_get_expression (& inst.reloc.exp, & str))
6699 return;
6700
6701 inst.reloc.type = BFD_RELOC_ARM_SWI;
6702 inst.reloc.pc_rel = 0;
6703 end_of_line (str);
6704 }
6705
6706 static void
6707 do_swap (char * str)
6708 {
6709 int reg;
6710
6711 skip_whitespace (str);
6712
6713 if ((reg = reg_required_here (&str, 12)) == FAIL)
6714 return;
6715
6716 if (reg == REG_PC)
6717 {
6718 inst.error = _("r15 not allowed in swap");
6719 return;
6720 }
6721
6722 if (skip_past_comma (&str) == FAIL
6723 || (reg = reg_required_here (&str, 0)) == FAIL)
6724 {
6725 if (!inst.error)
6726 inst.error = BAD_ARGS;
6727 return;
6728 }
6729
6730 if (reg == REG_PC)
6731 {
6732 inst.error = _("r15 not allowed in swap");
6733 return;
6734 }
6735
6736 if (skip_past_comma (&str) == FAIL
6737 || *str++ != '[')
6738 {
6739 inst.error = BAD_ARGS;
6740 return;
6741 }
6742
6743 skip_whitespace (str);
6744
6745 if ((reg = reg_required_here (&str, 16)) == FAIL)
6746 return;
6747
6748 if (reg == REG_PC)
6749 {
6750 inst.error = BAD_PC;
6751 return;
6752 }
6753
6754 skip_whitespace (str);
6755
6756 if (*str++ != ']')
6757 {
6758 inst.error = _("missing ]");
6759 return;
6760 }
6761
6762 end_of_line (str);
6763 }
6764
6765 static void
6766 do_branch (char * str)
6767 {
6768 if (my_get_expression (&inst.reloc.exp, &str))
6769 return;
6770
6771 #ifdef OBJ_ELF
6772 {
6773 char * save_in;
6774
6775 /* ScottB: February 5, 1998 - Check to see of PLT32 reloc
6776 required for the instruction. */
6777
6778 /* arm_parse_reloc () works on input_line_pointer.
6779 We actually want to parse the operands to the branch instruction
6780 passed in 'str'. Save the input pointer and restore it later. */
6781 save_in = input_line_pointer;
6782 input_line_pointer = str;
6783 if (inst.reloc.exp.X_op == O_symbol
6784 && *str == '('
6785 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
6786 {
6787 inst.reloc.type = BFD_RELOC_ARM_PLT32;
6788 inst.reloc.pc_rel = 0;
6789 /* Modify str to point to after parsed operands, otherwise
6790 end_of_line() will complain about the (PLT) left in str. */
6791 str = input_line_pointer;
6792 }
6793 else
6794 {
6795 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
6796 inst.reloc.pc_rel = 1;
6797 }
6798 input_line_pointer = save_in;
6799 }
6800 #else
6801 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
6802 inst.reloc.pc_rel = 1;
6803 #endif /* OBJ_ELF */
6804
6805 end_of_line (str);
6806 }
6807
6808 static void
6809 do_cdp (char * str)
6810 {
6811 /* Co-processor data operation.
6812 Format: CDP{cond} CP#,<expr>,CRd,CRn,CRm{,<expr>} */
6813 skip_whitespace (str);
6814
6815 if (co_proc_number (&str) == FAIL)
6816 {
6817 if (!inst.error)
6818 inst.error = BAD_ARGS;
6819 return;
6820 }
6821
6822 if (skip_past_comma (&str) == FAIL
6823 || cp_opc_expr (&str, 20,4) == FAIL)
6824 {
6825 if (!inst.error)
6826 inst.error = BAD_ARGS;
6827 return;
6828 }
6829
6830 if (skip_past_comma (&str) == FAIL
6831 || cp_reg_required_here (&str, 12) == FAIL)
6832 {
6833 if (!inst.error)
6834 inst.error = BAD_ARGS;
6835 return;
6836 }
6837
6838 if (skip_past_comma (&str) == FAIL
6839 || cp_reg_required_here (&str, 16) == FAIL)
6840 {
6841 if (!inst.error)
6842 inst.error = BAD_ARGS;
6843 return;
6844 }
6845
6846 if (skip_past_comma (&str) == FAIL
6847 || cp_reg_required_here (&str, 0) == FAIL)
6848 {
6849 if (!inst.error)
6850 inst.error = BAD_ARGS;
6851 return;
6852 }
6853
6854 if (skip_past_comma (&str) == SUCCESS)
6855 {
6856 if (cp_opc_expr (&str, 5, 3) == FAIL)
6857 {
6858 if (!inst.error)
6859 inst.error = BAD_ARGS;
6860 return;
6861 }
6862 }
6863
6864 end_of_line (str);
6865 }
6866
6867 static void
6868 do_lstc (char * str)
6869 {
6870 /* Co-processor register load/store.
6871 Format: <LDC|STC{cond}[L] CP#,CRd,<address> */
6872
6873 skip_whitespace (str);
6874
6875 if (co_proc_number (&str) == FAIL)
6876 {
6877 if (!inst.error)
6878 inst.error = BAD_ARGS;
6879 return;
6880 }
6881
6882 if (skip_past_comma (&str) == FAIL
6883 || cp_reg_required_here (&str, 12) == FAIL)
6884 {
6885 if (!inst.error)
6886 inst.error = BAD_ARGS;
6887 return;
6888 }
6889
6890 if (skip_past_comma (&str) == FAIL
6891 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
6892 {
6893 if (! inst.error)
6894 inst.error = BAD_ARGS;
6895 return;
6896 }
6897
6898 end_of_line (str);
6899 }
6900
6901 static void
6902 do_co_reg (char * str)
6903 {
6904 /* Co-processor register transfer.
6905 Format: <MCR|MRC>{cond} CP#,<expr1>,Rd,CRn,CRm{,<expr2>} */
6906
6907 skip_whitespace (str);
6908
6909 if (co_proc_number (&str) == FAIL)
6910 {
6911 if (!inst.error)
6912 inst.error = BAD_ARGS;
6913 return;
6914 }
6915
6916 if (skip_past_comma (&str) == FAIL
6917 || cp_opc_expr (&str, 21, 3) == FAIL)
6918 {
6919 if (!inst.error)
6920 inst.error = BAD_ARGS;
6921 return;
6922 }
6923
6924 if (skip_past_comma (&str) == FAIL
6925 || reg_required_here (&str, 12) == FAIL)
6926 {
6927 if (!inst.error)
6928 inst.error = BAD_ARGS;
6929 return;
6930 }
6931
6932 if (skip_past_comma (&str) == FAIL
6933 || cp_reg_required_here (&str, 16) == FAIL)
6934 {
6935 if (!inst.error)
6936 inst.error = BAD_ARGS;
6937 return;
6938 }
6939
6940 if (skip_past_comma (&str) == FAIL
6941 || cp_reg_required_here (&str, 0) == FAIL)
6942 {
6943 if (!inst.error)
6944 inst.error = BAD_ARGS;
6945 return;
6946 }
6947
6948 if (skip_past_comma (&str) == SUCCESS)
6949 {
6950 if (cp_opc_expr (&str, 5, 3) == FAIL)
6951 {
6952 if (!inst.error)
6953 inst.error = BAD_ARGS;
6954 return;
6955 }
6956 }
6957
6958 end_of_line (str);
6959 }
6960
6961 static void
6962 do_fpa_ctrl (char * str)
6963 {
6964 /* FP control registers.
6965 Format: <WFS|RFS|WFC|RFC>{cond} Rn */
6966
6967 skip_whitespace (str);
6968
6969 if (reg_required_here (&str, 12) == FAIL)
6970 {
6971 if (!inst.error)
6972 inst.error = BAD_ARGS;
6973 return;
6974 }
6975
6976 end_of_line (str);
6977 }
6978
6979 static void
6980 do_fpa_ldst (char * str)
6981 {
6982 skip_whitespace (str);
6983
6984 if (fp_reg_required_here (&str, 12) == FAIL)
6985 {
6986 if (!inst.error)
6987 inst.error = BAD_ARGS;
6988 return;
6989 }
6990
6991 if (skip_past_comma (&str) == FAIL
6992 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
6993 {
6994 if (!inst.error)
6995 inst.error = BAD_ARGS;
6996 return;
6997 }
6998
6999 end_of_line (str);
7000 }
7001
7002 static void
7003 do_fpa_ldmstm (char * str)
7004 {
7005 int num_regs;
7006
7007 skip_whitespace (str);
7008
7009 if (fp_reg_required_here (&str, 12) == FAIL)
7010 {
7011 if (! inst.error)
7012 inst.error = BAD_ARGS;
7013 return;
7014 }
7015
7016 /* Get Number of registers to transfer. */
7017 if (skip_past_comma (&str) == FAIL
7018 || my_get_expression (&inst.reloc.exp, &str))
7019 {
7020 if (! inst.error)
7021 inst.error = _("constant expression expected");
7022 return;
7023 }
7024
7025 if (inst.reloc.exp.X_op != O_constant)
7026 {
7027 inst.error = _("constant value required for number of registers");
7028 return;
7029 }
7030
7031 num_regs = inst.reloc.exp.X_add_number;
7032
7033 if (num_regs < 1 || num_regs > 4)
7034 {
7035 inst.error = _("number of registers must be in the range [1:4]");
7036 return;
7037 }
7038
7039 switch (num_regs)
7040 {
7041 case 1:
7042 inst.instruction |= CP_T_X;
7043 break;
7044 case 2:
7045 inst.instruction |= CP_T_Y;
7046 break;
7047 case 3:
7048 inst.instruction |= CP_T_Y | CP_T_X;
7049 break;
7050 case 4:
7051 break;
7052 default:
7053 abort ();
7054 }
7055
7056 if (inst.instruction & (CP_T_Pre | CP_T_UD)) /* ea/fd format. */
7057 {
7058 int reg;
7059 int write_back;
7060 int offset;
7061
7062 /* The instruction specified "ea" or "fd", so we can only accept
7063 [Rn]{!}. The instruction does not really support stacking or
7064 unstacking, so we have to emulate these by setting appropriate
7065 bits and offsets. */
7066 if (skip_past_comma (&str) == FAIL
7067 || *str != '[')
7068 {
7069 if (! inst.error)
7070 inst.error = BAD_ARGS;
7071 return;
7072 }
7073
7074 str++;
7075 skip_whitespace (str);
7076
7077 if ((reg = reg_required_here (&str, 16)) == FAIL)
7078 return;
7079
7080 skip_whitespace (str);
7081
7082 if (*str != ']')
7083 {
7084 inst.error = BAD_ARGS;
7085 return;
7086 }
7087
7088 str++;
7089 if (*str == '!')
7090 {
7091 write_back = 1;
7092 str++;
7093 if (reg == REG_PC)
7094 {
7095 inst.error =
7096 _("r15 not allowed as base register with write-back");
7097 return;
7098 }
7099 }
7100 else
7101 write_back = 0;
7102
7103 if (inst.instruction & CP_T_Pre)
7104 {
7105 /* Pre-decrement. */
7106 offset = 3 * num_regs;
7107 if (write_back)
7108 inst.instruction |= CP_T_WB;
7109 }
7110 else
7111 {
7112 /* Post-increment. */
7113 if (write_back)
7114 {
7115 inst.instruction |= CP_T_WB;
7116 offset = 3 * num_regs;
7117 }
7118 else
7119 {
7120 /* No write-back, so convert this into a standard pre-increment
7121 instruction -- aesthetically more pleasing. */
7122 inst.instruction |= CP_T_Pre | CP_T_UD;
7123 offset = 0;
7124 }
7125 }
7126
7127 inst.instruction |= offset;
7128 }
7129 else if (skip_past_comma (&str) == FAIL
7130 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
7131 {
7132 if (! inst.error)
7133 inst.error = BAD_ARGS;
7134 return;
7135 }
7136
7137 end_of_line (str);
7138 }
7139
7140 static void
7141 do_fpa_dyadic (char * str)
7142 {
7143 skip_whitespace (str);
7144
7145 if (fp_reg_required_here (&str, 12) == FAIL)
7146 {
7147 if (! inst.error)
7148 inst.error = BAD_ARGS;
7149 return;
7150 }
7151
7152 if (skip_past_comma (&str) == FAIL
7153 || fp_reg_required_here (&str, 16) == FAIL)
7154 {
7155 if (! inst.error)
7156 inst.error = BAD_ARGS;
7157 return;
7158 }
7159
7160 if (skip_past_comma (&str) == FAIL
7161 || fp_op2 (&str) == FAIL)
7162 {
7163 if (! inst.error)
7164 inst.error = BAD_ARGS;
7165 return;
7166 }
7167
7168 end_of_line (str);
7169 }
7170
7171 static void
7172 do_fpa_monadic (char * str)
7173 {
7174 skip_whitespace (str);
7175
7176 if (fp_reg_required_here (&str, 12) == FAIL)
7177 {
7178 if (! inst.error)
7179 inst.error = BAD_ARGS;
7180 return;
7181 }
7182
7183 if (skip_past_comma (&str) == FAIL
7184 || fp_op2 (&str) == FAIL)
7185 {
7186 if (! inst.error)
7187 inst.error = BAD_ARGS;
7188 return;
7189 }
7190
7191 end_of_line (str);
7192 }
7193
7194 static void
7195 do_fpa_cmp (char * str)
7196 {
7197 skip_whitespace (str);
7198
7199 if (fp_reg_required_here (&str, 16) == FAIL)
7200 {
7201 if (! inst.error)
7202 inst.error = BAD_ARGS;
7203 return;
7204 }
7205
7206 if (skip_past_comma (&str) == FAIL
7207 || fp_op2 (&str) == FAIL)
7208 {
7209 if (! inst.error)
7210 inst.error = BAD_ARGS;
7211 return;
7212 }
7213
7214 end_of_line (str);
7215 }
7216
7217 static void
7218 do_fpa_from_reg (char * str)
7219 {
7220 skip_whitespace (str);
7221
7222 if (fp_reg_required_here (&str, 16) == FAIL)
7223 {
7224 if (! inst.error)
7225 inst.error = BAD_ARGS;
7226 return;
7227 }
7228
7229 if (skip_past_comma (&str) == FAIL
7230 || reg_required_here (&str, 12) == FAIL)
7231 {
7232 if (! inst.error)
7233 inst.error = BAD_ARGS;
7234 return;
7235 }
7236
7237 end_of_line (str);
7238 }
7239
7240 static void
7241 do_fpa_to_reg (char * str)
7242 {
7243 skip_whitespace (str);
7244
7245 if (reg_required_here (&str, 12) == FAIL)
7246 return;
7247
7248 if (skip_past_comma (&str) == FAIL
7249 || fp_reg_required_here (&str, 0) == FAIL)
7250 {
7251 if (! inst.error)
7252 inst.error = BAD_ARGS;
7253 return;
7254 }
7255
7256 end_of_line (str);
7257 }
7258
7259 static int
7260 vfp_sp_reg_required_here (char ** str,
7261 enum vfp_sp_reg_pos pos)
7262 {
7263 int reg;
7264 char *start = *str;
7265
7266 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_SN].htab)) != FAIL)
7267 {
7268 switch (pos)
7269 {
7270 case VFP_REG_Sd:
7271 inst.instruction |= ((reg >> 1) << 12) | ((reg & 1) << 22);
7272 break;
7273
7274 case VFP_REG_Sn:
7275 inst.instruction |= ((reg >> 1) << 16) | ((reg & 1) << 7);
7276 break;
7277
7278 case VFP_REG_Sm:
7279 inst.instruction |= ((reg >> 1) << 0) | ((reg & 1) << 5);
7280 break;
7281
7282 default:
7283 abort ();
7284 }
7285 return reg;
7286 }
7287
7288 /* In the few cases where we might be able to accept something else
7289 this error can be overridden. */
7290 inst.error = _(all_reg_maps[REG_TYPE_SN].expected);
7291
7292 /* Restore the start point. */
7293 *str = start;
7294 return FAIL;
7295 }
7296
7297 static int
7298 vfp_dp_reg_required_here (char ** str,
7299 enum vfp_dp_reg_pos pos)
7300 {
7301 int reg;
7302 char * start = *str;
7303
7304 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_DN].htab)) != FAIL)
7305 {
7306 switch (pos)
7307 {
7308 case VFP_REG_Dd:
7309 inst.instruction |= reg << 12;
7310 break;
7311
7312 case VFP_REG_Dn:
7313 inst.instruction |= reg << 16;
7314 break;
7315
7316 case VFP_REG_Dm:
7317 inst.instruction |= reg << 0;
7318 break;
7319
7320 default:
7321 abort ();
7322 }
7323 return reg;
7324 }
7325
7326 /* In the few cases where we might be able to accept something else
7327 this error can be overridden. */
7328 inst.error = _(all_reg_maps[REG_TYPE_DN].expected);
7329
7330 /* Restore the start point. */
7331 *str = start;
7332 return FAIL;
7333 }
7334
7335 static void
7336 do_vfp_sp_monadic (char * str)
7337 {
7338 skip_whitespace (str);
7339
7340 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
7341 return;
7342
7343 if (skip_past_comma (&str) == FAIL
7344 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
7345 {
7346 if (! inst.error)
7347 inst.error = BAD_ARGS;
7348 return;
7349 }
7350
7351 end_of_line (str);
7352 }
7353
7354 static void
7355 do_vfp_dp_monadic (char * str)
7356 {
7357 skip_whitespace (str);
7358
7359 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
7360 return;
7361
7362 if (skip_past_comma (&str) == FAIL
7363 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
7364 {
7365 if (! inst.error)
7366 inst.error = BAD_ARGS;
7367 return;
7368 }
7369
7370 end_of_line (str);
7371 }
7372
7373 static void
7374 do_vfp_sp_dyadic (char * str)
7375 {
7376 skip_whitespace (str);
7377
7378 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
7379 return;
7380
7381 if (skip_past_comma (&str) == FAIL
7382 || vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL
7383 || skip_past_comma (&str) == FAIL
7384 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
7385 {
7386 if (! inst.error)
7387 inst.error = BAD_ARGS;
7388 return;
7389 }
7390
7391 end_of_line (str);
7392 }
7393
7394 static void
7395 do_vfp_dp_dyadic (char * str)
7396 {
7397 skip_whitespace (str);
7398
7399 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
7400 return;
7401
7402 if (skip_past_comma (&str) == FAIL
7403 || vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL
7404 || skip_past_comma (&str) == FAIL
7405 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
7406 {
7407 if (! inst.error)
7408 inst.error = BAD_ARGS;
7409 return;
7410 }
7411
7412 end_of_line (str);
7413 }
7414
7415 static void
7416 do_vfp_reg_from_sp (char * str)
7417 {
7418 skip_whitespace (str);
7419
7420 if (reg_required_here (&str, 12) == FAIL)
7421 return;
7422
7423 if (skip_past_comma (&str) == FAIL
7424 || vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL)
7425 {
7426 if (! inst.error)
7427 inst.error = BAD_ARGS;
7428 return;
7429 }
7430
7431 end_of_line (str);
7432 }
7433
7434 /* Parse and encode a VFP SP register list, storing the initial
7435 register in position POS and returning the range as the result. If
7436 the string is invalid return FAIL (an invalid range). */
7437
7438 static long
7439 vfp_sp_reg_list (char ** str, enum vfp_sp_reg_pos pos)
7440 {
7441 long range = 0;
7442 int base_reg = 0;
7443 int new_base;
7444 long base_bits = 0;
7445 int count = 0;
7446 long tempinst;
7447 unsigned long mask = 0;
7448 int warned = 0;
7449
7450 if (**str != '{')
7451 return FAIL;
7452
7453 (*str)++;
7454 skip_whitespace (*str);
7455
7456 tempinst = inst.instruction;
7457
7458 do
7459 {
7460 inst.instruction = 0;
7461
7462 if ((new_base = vfp_sp_reg_required_here (str, pos)) == FAIL)
7463 return FAIL;
7464
7465 if (count == 0 || base_reg > new_base)
7466 {
7467 base_reg = new_base;
7468 base_bits = inst.instruction;
7469 }
7470
7471 if (mask & (1 << new_base))
7472 {
7473 inst.error = _("invalid register list");
7474 return FAIL;
7475 }
7476
7477 if ((mask >> new_base) != 0 && ! warned)
7478 {
7479 as_tsktsk (_("register list not in ascending order"));
7480 warned = 1;
7481 }
7482
7483 mask |= 1 << new_base;
7484 count++;
7485
7486 skip_whitespace (*str);
7487
7488 if (**str == '-') /* We have the start of a range expression */
7489 {
7490 int high_range;
7491
7492 (*str)++;
7493
7494 if ((high_range
7495 = arm_reg_parse (str, all_reg_maps[REG_TYPE_SN].htab))
7496 == FAIL)
7497 {
7498 inst.error = _(all_reg_maps[REG_TYPE_SN].expected);
7499 return FAIL;
7500 }
7501
7502 if (high_range <= new_base)
7503 {
7504 inst.error = _("register range not in ascending order");
7505 return FAIL;
7506 }
7507
7508 for (new_base++; new_base <= high_range; new_base++)
7509 {
7510 if (mask & (1 << new_base))
7511 {
7512 inst.error = _("invalid register list");
7513 return FAIL;
7514 }
7515
7516 mask |= 1 << new_base;
7517 count++;
7518 }
7519 }
7520 }
7521 while (skip_past_comma (str) != FAIL);
7522
7523 if (**str != '}')
7524 {
7525 inst.error = _("invalid register list");
7526 return FAIL;
7527 }
7528
7529 (*str)++;
7530
7531 range = count;
7532
7533 /* Sanity check -- should have raised a parse error above. */
7534 if (count == 0 || count > 32)
7535 abort ();
7536
7537 /* Final test -- the registers must be consecutive. */
7538 while (count--)
7539 {
7540 if ((mask & (1 << base_reg++)) == 0)
7541 {
7542 inst.error = _("non-contiguous register range");
7543 return FAIL;
7544 }
7545 }
7546
7547 inst.instruction = tempinst | base_bits;
7548 return range;
7549 }
7550
7551 static void
7552 do_vfp_reg2_from_sp2 (char * str)
7553 {
7554 skip_whitespace (str);
7555
7556 if (reg_required_here (&str, 12) == FAIL
7557 || skip_past_comma (&str) == FAIL
7558 || reg_required_here (&str, 16) == FAIL
7559 || skip_past_comma (&str) == FAIL)
7560 {
7561 if (! inst.error)
7562 inst.error = BAD_ARGS;
7563 return;
7564 }
7565
7566 /* We require exactly two consecutive SP registers. */
7567 if (vfp_sp_reg_list (&str, VFP_REG_Sm) != 2)
7568 {
7569 if (! inst.error)
7570 inst.error = _("only two consecutive VFP SP registers allowed here");
7571 }
7572
7573 end_of_line (str);
7574 }
7575
7576 static void
7577 do_vfp_sp_from_reg (char * str)
7578 {
7579 skip_whitespace (str);
7580
7581 if (vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL)
7582 return;
7583
7584 if (skip_past_comma (&str) == FAIL
7585 || reg_required_here (&str, 12) == FAIL)
7586 {
7587 if (! inst.error)
7588 inst.error = BAD_ARGS;
7589 return;
7590 }
7591
7592 end_of_line (str);
7593 }
7594
7595 static void
7596 do_vfp_sp2_from_reg2 (char * str)
7597 {
7598 skip_whitespace (str);
7599
7600 /* We require exactly two consecutive SP registers. */
7601 if (vfp_sp_reg_list (&str, VFP_REG_Sm) != 2)
7602 {
7603 if (! inst.error)
7604 inst.error = _("only two consecutive VFP SP registers allowed here");
7605 }
7606
7607 if (skip_past_comma (&str) == FAIL
7608 || reg_required_here (&str, 12) == FAIL
7609 || skip_past_comma (&str) == FAIL
7610 || reg_required_here (&str, 16) == FAIL)
7611 {
7612 if (! inst.error)
7613 inst.error = BAD_ARGS;
7614 return;
7615 }
7616
7617 end_of_line (str);
7618 }
7619
7620 static void
7621 do_vfp_reg_from_dp (char * str)
7622 {
7623 skip_whitespace (str);
7624
7625 if (reg_required_here (&str, 12) == FAIL)
7626 return;
7627
7628 if (skip_past_comma (&str) == FAIL
7629 || vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL)
7630 {
7631 if (! inst.error)
7632 inst.error = BAD_ARGS;
7633 return;
7634 }
7635
7636 end_of_line (str);
7637 }
7638
7639 static void
7640 do_vfp_reg2_from_dp (char * str)
7641 {
7642 skip_whitespace (str);
7643
7644 if (reg_required_here (&str, 12) == FAIL)
7645 return;
7646
7647 if (skip_past_comma (&str) == FAIL
7648 || reg_required_here (&str, 16) == FAIL
7649 || skip_past_comma (&str) == FAIL
7650 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
7651 {
7652 if (! inst.error)
7653 inst.error = BAD_ARGS;
7654 return;
7655 }
7656
7657 end_of_line (str);
7658 }
7659
7660 static void
7661 do_vfp_dp_from_reg (char * str)
7662 {
7663 skip_whitespace (str);
7664
7665 if (vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL)
7666 return;
7667
7668 if (skip_past_comma (&str) == FAIL
7669 || reg_required_here (&str, 12) == FAIL)
7670 {
7671 if (! inst.error)
7672 inst.error = BAD_ARGS;
7673 return;
7674 }
7675
7676 end_of_line (str);
7677 }
7678
7679 static void
7680 do_vfp_dp_from_reg2 (char * str)
7681 {
7682 skip_whitespace (str);
7683
7684 if (vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
7685 return;
7686
7687 if (skip_past_comma (&str) == FAIL
7688 || reg_required_here (&str, 12) == FAIL
7689 || skip_past_comma (&str) == FAIL
7690 || reg_required_here (&str, 16) == FAIL)
7691 {
7692 if (! inst.error)
7693 inst.error = BAD_ARGS;
7694 return;
7695 }
7696
7697 end_of_line (str);
7698 }
7699
7700 static const struct vfp_reg *
7701 vfp_psr_parse (char ** str)
7702 {
7703 char *start = *str;
7704 char c;
7705 char *p;
7706 const struct vfp_reg *vreg;
7707
7708 p = start;
7709
7710 /* Find the end of the current token. */
7711 do
7712 {
7713 c = *p++;
7714 }
7715 while (ISALPHA (c));
7716
7717 /* Mark it. */
7718 *--p = 0;
7719
7720 for (vreg = vfp_regs + 0;
7721 vreg < vfp_regs + sizeof (vfp_regs) / sizeof (struct vfp_reg);
7722 vreg++)
7723 {
7724 if (streq (start, vreg->name))
7725 {
7726 *p = c;
7727 *str = p;
7728 return vreg;
7729 }
7730 }
7731
7732 *p = c;
7733 return NULL;
7734 }
7735
7736 static int
7737 vfp_psr_required_here (char ** str)
7738 {
7739 char *start = *str;
7740 const struct vfp_reg *vreg;
7741
7742 vreg = vfp_psr_parse (str);
7743
7744 if (vreg)
7745 {
7746 inst.instruction |= vreg->regno;
7747 return SUCCESS;
7748 }
7749
7750 inst.error = _("VFP system register expected");
7751
7752 *str = start;
7753 return FAIL;
7754 }
7755
7756 static void
7757 do_vfp_reg_from_ctrl (char * str)
7758 {
7759 skip_whitespace (str);
7760
7761 if (reg_required_here (&str, 12) == FAIL)
7762 return;
7763
7764 if (skip_past_comma (&str) == FAIL
7765 || vfp_psr_required_here (&str) == FAIL)
7766 {
7767 if (! inst.error)
7768 inst.error = BAD_ARGS;
7769 return;
7770 }
7771
7772 end_of_line (str);
7773 }
7774
7775 static void
7776 do_vfp_ctrl_from_reg (char * str)
7777 {
7778 skip_whitespace (str);
7779
7780 if (vfp_psr_required_here (&str) == FAIL)
7781 return;
7782
7783 if (skip_past_comma (&str) == FAIL
7784 || reg_required_here (&str, 12) == FAIL)
7785 {
7786 if (! inst.error)
7787 inst.error = BAD_ARGS;
7788 return;
7789 }
7790
7791 end_of_line (str);
7792 }
7793
7794 static void
7795 do_vfp_sp_ldst (char * str)
7796 {
7797 skip_whitespace (str);
7798
7799 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
7800 {
7801 if (!inst.error)
7802 inst.error = BAD_ARGS;
7803 return;
7804 }
7805
7806 if (skip_past_comma (&str) == FAIL
7807 || cp_address_required_here (&str, CP_NO_WB) == FAIL)
7808 {
7809 if (!inst.error)
7810 inst.error = BAD_ARGS;
7811 return;
7812 }
7813
7814 end_of_line (str);
7815 }
7816
7817 static void
7818 do_vfp_dp_ldst (char * str)
7819 {
7820 skip_whitespace (str);
7821
7822 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
7823 {
7824 if (!inst.error)
7825 inst.error = BAD_ARGS;
7826 return;
7827 }
7828
7829 if (skip_past_comma (&str) == FAIL
7830 || cp_address_required_here (&str, CP_NO_WB) == FAIL)
7831 {
7832 if (!inst.error)
7833 inst.error = BAD_ARGS;
7834 return;
7835 }
7836
7837 end_of_line (str);
7838 }
7839
7840 static long
7841 vfp_dp_reg_list (char ** str)
7842 {
7843 long range = 0;
7844 int base_reg = 0;
7845 int new_base;
7846 int count = 0;
7847 long tempinst;
7848 unsigned long mask = 0;
7849 int warned = 0;
7850
7851 if (**str != '{')
7852 return FAIL;
7853
7854 (*str)++;
7855 skip_whitespace (*str);
7856
7857 tempinst = inst.instruction;
7858
7859 do
7860 {
7861 inst.instruction = 0;
7862
7863 if ((new_base = vfp_dp_reg_required_here (str, VFP_REG_Dd)) == FAIL)
7864 return FAIL;
7865
7866 if (count == 0 || base_reg > new_base)
7867 {
7868 base_reg = new_base;
7869 range = inst.instruction;
7870 }
7871
7872 if (mask & (1 << new_base))
7873 {
7874 inst.error = _("invalid register list");
7875 return FAIL;
7876 }
7877
7878 if ((mask >> new_base) != 0 && ! warned)
7879 {
7880 as_tsktsk (_("register list not in ascending order"));
7881 warned = 1;
7882 }
7883
7884 mask |= 1 << new_base;
7885 count++;
7886
7887 skip_whitespace (*str);
7888
7889 if (**str == '-') /* We have the start of a range expression */
7890 {
7891 int high_range;
7892
7893 (*str)++;
7894
7895 if ((high_range
7896 = arm_reg_parse (str, all_reg_maps[REG_TYPE_DN].htab))
7897 == FAIL)
7898 {
7899 inst.error = _(all_reg_maps[REG_TYPE_DN].expected);
7900 return FAIL;
7901 }
7902
7903 if (high_range <= new_base)
7904 {
7905 inst.error = _("register range not in ascending order");
7906 return FAIL;
7907 }
7908
7909 for (new_base++; new_base <= high_range; new_base++)
7910 {
7911 if (mask & (1 << new_base))
7912 {
7913 inst.error = _("invalid register list");
7914 return FAIL;
7915 }
7916
7917 mask |= 1 << new_base;
7918 count++;
7919 }
7920 }
7921 }
7922 while (skip_past_comma (str) != FAIL);
7923
7924 if (**str != '}')
7925 {
7926 inst.error = _("invalid register list");
7927 return FAIL;
7928 }
7929
7930 (*str)++;
7931
7932 range |= 2 * count;
7933
7934 /* Sanity check -- should have raised a parse error above. */
7935 if (count == 0 || count > 16)
7936 abort ();
7937
7938 /* Final test -- the registers must be consecutive. */
7939 while (count--)
7940 {
7941 if ((mask & (1 << base_reg++)) == 0)
7942 {
7943 inst.error = _("non-contiguous register range");
7944 return FAIL;
7945 }
7946 }
7947
7948 inst.instruction = tempinst;
7949 return range;
7950 }
7951
7952 static void
7953 vfp_sp_ldstm (char * str, enum vfp_ldstm_type ldstm_type)
7954 {
7955 long range;
7956
7957 skip_whitespace (str);
7958
7959 if (reg_required_here (&str, 16) == FAIL)
7960 return;
7961
7962 skip_whitespace (str);
7963
7964 if (*str == '!')
7965 {
7966 inst.instruction |= WRITE_BACK;
7967 str++;
7968 }
7969 else if (ldstm_type != VFP_LDSTMIA)
7970 {
7971 inst.error = _("this addressing mode requires base-register writeback");
7972 return;
7973 }
7974
7975 if (skip_past_comma (&str) == FAIL
7976 || (range = vfp_sp_reg_list (&str, VFP_REG_Sd)) == FAIL)
7977 {
7978 if (!inst.error)
7979 inst.error = BAD_ARGS;
7980 return;
7981 }
7982
7983 inst.instruction |= range;
7984 end_of_line (str);
7985 }
7986
7987 static void
7988 vfp_dp_ldstm (char * str, enum vfp_ldstm_type ldstm_type)
7989 {
7990 long range;
7991
7992 skip_whitespace (str);
7993
7994 if (reg_required_here (&str, 16) == FAIL)
7995 return;
7996
7997 skip_whitespace (str);
7998
7999 if (*str == '!')
8000 {
8001 inst.instruction |= WRITE_BACK;
8002 str++;
8003 }
8004 else if (ldstm_type != VFP_LDSTMIA && ldstm_type != VFP_LDSTMIAX)
8005 {
8006 inst.error = _("this addressing mode requires base-register writeback");
8007 return;
8008 }
8009
8010 if (skip_past_comma (&str) == FAIL
8011 || (range = vfp_dp_reg_list (&str)) == FAIL)
8012 {
8013 if (!inst.error)
8014 inst.error = BAD_ARGS;
8015 return;
8016 }
8017
8018 if (ldstm_type == VFP_LDSTMIAX || ldstm_type == VFP_LDSTMDBX)
8019 range += 1;
8020
8021 inst.instruction |= range;
8022 end_of_line (str);
8023 }
8024
8025 static void
8026 do_vfp_sp_ldstmia (char * str)
8027 {
8028 vfp_sp_ldstm (str, VFP_LDSTMIA);
8029 }
8030
8031 static void
8032 do_vfp_sp_ldstmdb (char * str)
8033 {
8034 vfp_sp_ldstm (str, VFP_LDSTMDB);
8035 }
8036
8037 static void
8038 do_vfp_dp_ldstmia (char * str)
8039 {
8040 vfp_dp_ldstm (str, VFP_LDSTMIA);
8041 }
8042
8043 static void
8044 do_vfp_dp_ldstmdb (char * str)
8045 {
8046 vfp_dp_ldstm (str, VFP_LDSTMDB);
8047 }
8048
8049 static void
8050 do_vfp_xp_ldstmia (char *str)
8051 {
8052 vfp_dp_ldstm (str, VFP_LDSTMIAX);
8053 }
8054
8055 static void
8056 do_vfp_xp_ldstmdb (char * str)
8057 {
8058 vfp_dp_ldstm (str, VFP_LDSTMDBX);
8059 }
8060
8061 static void
8062 do_vfp_sp_compare_z (char * str)
8063 {
8064 skip_whitespace (str);
8065
8066 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
8067 {
8068 if (!inst.error)
8069 inst.error = BAD_ARGS;
8070 return;
8071 }
8072
8073 end_of_line (str);
8074 }
8075
8076 static void
8077 do_vfp_dp_compare_z (char * str)
8078 {
8079 skip_whitespace (str);
8080
8081 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
8082 {
8083 if (!inst.error)
8084 inst.error = BAD_ARGS;
8085 return;
8086 }
8087
8088 end_of_line (str);
8089 }
8090
8091 static void
8092 do_vfp_dp_sp_cvt (char * str)
8093 {
8094 skip_whitespace (str);
8095
8096 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
8097 return;
8098
8099 if (skip_past_comma (&str) == FAIL
8100 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
8101 {
8102 if (! inst.error)
8103 inst.error = BAD_ARGS;
8104 return;
8105 }
8106
8107 end_of_line (str);
8108 }
8109
8110 static void
8111 do_vfp_sp_dp_cvt (char * str)
8112 {
8113 skip_whitespace (str);
8114
8115 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
8116 return;
8117
8118 if (skip_past_comma (&str) == FAIL
8119 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
8120 {
8121 if (! inst.error)
8122 inst.error = BAD_ARGS;
8123 return;
8124 }
8125
8126 end_of_line (str);
8127 }
8128
8129 /* Thumb specific routines. */
8130
8131 /* Parse an add or subtract instruction, SUBTRACT is non-zero if the opcode
8132 was SUB. */
8133
8134 static void
8135 thumb_add_sub (char * str, int subtract)
8136 {
8137 int Rd, Rs, Rn = FAIL;
8138
8139 skip_whitespace (str);
8140
8141 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
8142 || skip_past_comma (&str) == FAIL)
8143 {
8144 if (! inst.error)
8145 inst.error = BAD_ARGS;
8146 return;
8147 }
8148
8149 if (is_immediate_prefix (*str))
8150 {
8151 Rs = Rd;
8152 str++;
8153 if (my_get_expression (&inst.reloc.exp, &str))
8154 return;
8155 }
8156 else
8157 {
8158 if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
8159 return;
8160
8161 if (skip_past_comma (&str) == FAIL)
8162 {
8163 /* Two operand format, shuffle the registers
8164 and pretend there are 3. */
8165 Rn = Rs;
8166 Rs = Rd;
8167 }
8168 else if (is_immediate_prefix (*str))
8169 {
8170 str++;
8171 if (my_get_expression (&inst.reloc.exp, &str))
8172 return;
8173 }
8174 else if ((Rn = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
8175 return;
8176 }
8177
8178 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
8179 for the latter case, EXPR contains the immediate that was found. */
8180 if (Rn != FAIL)
8181 {
8182 /* All register format. */
8183 if (Rd > 7 || Rs > 7 || Rn > 7)
8184 {
8185 if (Rs != Rd)
8186 {
8187 inst.error = _("dest and source1 must be the same register");
8188 return;
8189 }
8190
8191 /* Can't do this for SUB. */
8192 if (subtract)
8193 {
8194 inst.error = _("subtract valid only on lo regs");
8195 return;
8196 }
8197
8198 inst.instruction = (T_OPCODE_ADD_HI
8199 | (Rd > 7 ? THUMB_H1 : 0)
8200 | (Rn > 7 ? THUMB_H2 : 0));
8201 inst.instruction |= (Rd & 7) | ((Rn & 7) << 3);
8202 }
8203 else
8204 {
8205 inst.instruction = subtract ? T_OPCODE_SUB_R3 : T_OPCODE_ADD_R3;
8206 inst.instruction |= Rd | (Rs << 3) | (Rn << 6);
8207 }
8208 }
8209 else
8210 {
8211 /* Immediate expression, now things start to get nasty. */
8212
8213 /* First deal with HI regs, only very restricted cases allowed:
8214 Adjusting SP, and using PC or SP to get an address. */
8215 if ((Rd > 7 && (Rd != REG_SP || Rs != REG_SP))
8216 || (Rs > 7 && Rs != REG_SP && Rs != REG_PC))
8217 {
8218 inst.error = _("invalid Hi register with immediate");
8219 return;
8220 }
8221
8222 if (inst.reloc.exp.X_op != O_constant)
8223 {
8224 /* Value isn't known yet, all we can do is store all the fragments
8225 we know about in the instruction and let the reloc hacking
8226 work it all out. */
8227 inst.instruction = (subtract ? 0x8000 : 0) | (Rd << 4) | Rs;
8228 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
8229 }
8230 else
8231 {
8232 int offset = inst.reloc.exp.X_add_number;
8233
8234 if (subtract)
8235 offset = - offset;
8236
8237 if (offset < 0)
8238 {
8239 offset = - offset;
8240 subtract = 1;
8241
8242 /* Quick check, in case offset is MIN_INT. */
8243 if (offset < 0)
8244 {
8245 inst.error = _("immediate value out of range");
8246 return;
8247 }
8248 }
8249 /* Note - you cannot convert a subtract of 0 into an
8250 add of 0 because the carry flag is set differently. */
8251 else if (offset > 0)
8252 subtract = 0;
8253
8254 if (Rd == REG_SP)
8255 {
8256 if (offset & ~0x1fc)
8257 {
8258 inst.error = _("invalid immediate value for stack adjust");
8259 return;
8260 }
8261 inst.instruction = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
8262 inst.instruction |= offset >> 2;
8263 }
8264 else if (Rs == REG_PC || Rs == REG_SP)
8265 {
8266 if (subtract
8267 || (offset & ~0x3fc))
8268 {
8269 inst.error = _("invalid immediate for address calculation");
8270 return;
8271 }
8272 inst.instruction = (Rs == REG_PC ? T_OPCODE_ADD_PC
8273 : T_OPCODE_ADD_SP);
8274 inst.instruction |= (Rd << 8) | (offset >> 2);
8275 }
8276 else if (Rs == Rd)
8277 {
8278 if (offset & ~0xff)
8279 {
8280 inst.error = _("immediate value out of range");
8281 return;
8282 }
8283 inst.instruction = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
8284 inst.instruction |= (Rd << 8) | offset;
8285 }
8286 else
8287 {
8288 if (offset & ~0x7)
8289 {
8290 inst.error = _("immediate value out of range");
8291 return;
8292 }
8293 inst.instruction = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
8294 inst.instruction |= Rd | (Rs << 3) | (offset << 6);
8295 }
8296 }
8297 }
8298
8299 end_of_line (str);
8300 }
8301
8302 static void
8303 thumb_shift (char * str, int shift)
8304 {
8305 int Rd, Rs, Rn = FAIL;
8306
8307 skip_whitespace (str);
8308
8309 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
8310 || skip_past_comma (&str) == FAIL)
8311 {
8312 if (! inst.error)
8313 inst.error = BAD_ARGS;
8314 return;
8315 }
8316
8317 if (is_immediate_prefix (*str))
8318 {
8319 /* Two operand immediate format, set Rs to Rd. */
8320 Rs = Rd;
8321 str ++;
8322 if (my_get_expression (&inst.reloc.exp, &str))
8323 return;
8324 }
8325 else
8326 {
8327 if ((Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
8328 return;
8329
8330 if (skip_past_comma (&str) == FAIL)
8331 {
8332 /* Two operand format, shuffle the registers
8333 and pretend there are 3. */
8334 Rn = Rs;
8335 Rs = Rd;
8336 }
8337 else if (is_immediate_prefix (*str))
8338 {
8339 str++;
8340 if (my_get_expression (&inst.reloc.exp, &str))
8341 return;
8342 }
8343 else if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
8344 return;
8345 }
8346
8347 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
8348 for the latter case, EXPR contains the immediate that was found. */
8349
8350 if (Rn != FAIL)
8351 {
8352 if (Rs != Rd)
8353 {
8354 inst.error = _("source1 and dest must be same register");
8355 return;
8356 }
8357
8358 switch (shift)
8359 {
8360 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_R; break;
8361 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_R; break;
8362 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_R; break;
8363 }
8364
8365 inst.instruction |= Rd | (Rn << 3);
8366 }
8367 else
8368 {
8369 switch (shift)
8370 {
8371 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_I; break;
8372 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_I; break;
8373 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_I; break;
8374 }
8375
8376 if (inst.reloc.exp.X_op != O_constant)
8377 {
8378 /* Value isn't known yet, create a dummy reloc and let reloc
8379 hacking fix it up. */
8380 inst.reloc.type = BFD_RELOC_ARM_THUMB_SHIFT;
8381 }
8382 else
8383 {
8384 unsigned shift_value = inst.reloc.exp.X_add_number;
8385
8386 if (shift_value > 32 || (shift_value == 32 && shift == THUMB_LSL))
8387 {
8388 inst.error = _("invalid immediate for shift");
8389 return;
8390 }
8391
8392 /* Shifts of zero are handled by converting to LSL. */
8393 if (shift_value == 0)
8394 inst.instruction = T_OPCODE_LSL_I;
8395
8396 /* Shifts of 32 are encoded as a shift of zero. */
8397 if (shift_value == 32)
8398 shift_value = 0;
8399
8400 inst.instruction |= shift_value << 6;
8401 }
8402
8403 inst.instruction |= Rd | (Rs << 3);
8404 }
8405
8406 end_of_line (str);
8407 }
8408
8409 static void
8410 thumb_load_store (char * str, int load_store, int size)
8411 {
8412 int Rd, Rb, Ro = FAIL;
8413
8414 skip_whitespace (str);
8415
8416 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
8417 || skip_past_comma (&str) == FAIL)
8418 {
8419 if (! inst.error)
8420 inst.error = BAD_ARGS;
8421 return;
8422 }
8423
8424 if (*str == '[')
8425 {
8426 str++;
8427 if ((Rb = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
8428 return;
8429
8430 if (skip_past_comma (&str) != FAIL)
8431 {
8432 if (is_immediate_prefix (*str))
8433 {
8434 str++;
8435 if (my_get_expression (&inst.reloc.exp, &str))
8436 return;
8437 }
8438 else if ((Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
8439 return;
8440 }
8441 else
8442 {
8443 inst.reloc.exp.X_op = O_constant;
8444 inst.reloc.exp.X_add_number = 0;
8445 }
8446
8447 if (*str != ']')
8448 {
8449 inst.error = _("expected ']'");
8450 return;
8451 }
8452 str++;
8453 }
8454 else if (*str == '=')
8455 {
8456 if (load_store != THUMB_LOAD)
8457 {
8458 inst.error = _("invalid pseudo operation");
8459 return;
8460 }
8461
8462 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
8463 str++;
8464
8465 skip_whitespace (str);
8466
8467 if (my_get_expression (& inst.reloc.exp, & str))
8468 return;
8469
8470 end_of_line (str);
8471
8472 if ( inst.reloc.exp.X_op != O_constant
8473 && inst.reloc.exp.X_op != O_symbol)
8474 {
8475 inst.error = "Constant expression expected";
8476 return;
8477 }
8478
8479 if (inst.reloc.exp.X_op == O_constant
8480 && ((inst.reloc.exp.X_add_number & ~0xFF) == 0))
8481 {
8482 /* This can be done with a mov instruction. */
8483
8484 inst.instruction = T_OPCODE_MOV_I8 | (Rd << 8);
8485 inst.instruction |= inst.reloc.exp.X_add_number;
8486 return;
8487 }
8488
8489 /* Insert into literal pool. */
8490 if (add_to_lit_pool () == FAIL)
8491 {
8492 if (!inst.error)
8493 inst.error = "literal pool insertion failed";
8494 return;
8495 }
8496
8497 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
8498 inst.reloc.pc_rel = 1;
8499 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
8500 /* Adjust ARM pipeline offset to Thumb. */
8501 inst.reloc.exp.X_add_number += 4;
8502
8503 return;
8504 }
8505 else
8506 {
8507 if (my_get_expression (&inst.reloc.exp, &str))
8508 return;
8509
8510 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
8511 inst.reloc.pc_rel = 1;
8512 inst.reloc.exp.X_add_number -= 4; /* Pipeline offset. */
8513 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
8514 end_of_line (str);
8515 return;
8516 }
8517
8518 if (Rb == REG_PC || Rb == REG_SP)
8519 {
8520 if (size != THUMB_WORD)
8521 {
8522 inst.error = _("byte or halfword not valid for base register");
8523 return;
8524 }
8525 else if (Rb == REG_PC && load_store != THUMB_LOAD)
8526 {
8527 inst.error = _("r15 based store not allowed");
8528 return;
8529 }
8530 else if (Ro != FAIL)
8531 {
8532 inst.error = _("invalid base register for register offset");
8533 return;
8534 }
8535
8536 if (Rb == REG_PC)
8537 inst.instruction = T_OPCODE_LDR_PC;
8538 else if (load_store == THUMB_LOAD)
8539 inst.instruction = T_OPCODE_LDR_SP;
8540 else
8541 inst.instruction = T_OPCODE_STR_SP;
8542
8543 inst.instruction |= Rd << 8;
8544 if (inst.reloc.exp.X_op == O_constant)
8545 {
8546 unsigned offset = inst.reloc.exp.X_add_number;
8547
8548 if (offset & ~0x3fc)
8549 {
8550 inst.error = _("invalid offset");
8551 return;
8552 }
8553
8554 inst.instruction |= offset >> 2;
8555 }
8556 else
8557 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
8558 }
8559 else if (Rb > 7)
8560 {
8561 inst.error = _("invalid base register in load/store");
8562 return;
8563 }
8564 else if (Ro == FAIL)
8565 {
8566 /* Immediate offset. */
8567 if (size == THUMB_WORD)
8568 inst.instruction = (load_store == THUMB_LOAD
8569 ? T_OPCODE_LDR_IW : T_OPCODE_STR_IW);
8570 else if (size == THUMB_HALFWORD)
8571 inst.instruction = (load_store == THUMB_LOAD
8572 ? T_OPCODE_LDR_IH : T_OPCODE_STR_IH);
8573 else
8574 inst.instruction = (load_store == THUMB_LOAD
8575 ? T_OPCODE_LDR_IB : T_OPCODE_STR_IB);
8576
8577 inst.instruction |= Rd | (Rb << 3);
8578
8579 if (inst.reloc.exp.X_op == O_constant)
8580 {
8581 unsigned offset = inst.reloc.exp.X_add_number;
8582
8583 if (offset & ~(0x1f << size))
8584 {
8585 inst.error = _("invalid offset");
8586 return;
8587 }
8588 inst.instruction |= (offset >> size) << 6;
8589 }
8590 else
8591 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
8592 }
8593 else
8594 {
8595 /* Register offset. */
8596 if (size == THUMB_WORD)
8597 inst.instruction = (load_store == THUMB_LOAD
8598 ? T_OPCODE_LDR_RW : T_OPCODE_STR_RW);
8599 else if (size == THUMB_HALFWORD)
8600 inst.instruction = (load_store == THUMB_LOAD
8601 ? T_OPCODE_LDR_RH : T_OPCODE_STR_RH);
8602 else
8603 inst.instruction = (load_store == THUMB_LOAD
8604 ? T_OPCODE_LDR_RB : T_OPCODE_STR_RB);
8605
8606 inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
8607 }
8608
8609 end_of_line (str);
8610 }
8611
8612 /* A register must be given at this point.
8613
8614 Shift is the place to put it in inst.instruction.
8615
8616 Restores input start point on err.
8617 Returns the reg#, or FAIL. */
8618
8619 static int
8620 mav_reg_required_here (char ** str, int shift, enum arm_reg_type regtype)
8621 {
8622 int reg;
8623 char *start = *str;
8624
8625 if ((reg = arm_reg_parse (str, all_reg_maps[regtype].htab)) != FAIL)
8626 {
8627 if (shift >= 0)
8628 inst.instruction |= reg << shift;
8629
8630 return reg;
8631 }
8632
8633 /* Restore the start point. */
8634 *str = start;
8635
8636 /* Try generic coprocessor name if applicable. */
8637 if (regtype == REG_TYPE_MVF ||
8638 regtype == REG_TYPE_MVD ||
8639 regtype == REG_TYPE_MVFX ||
8640 regtype == REG_TYPE_MVDX)
8641 {
8642 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_CN].htab)) != FAIL)
8643 {
8644 if (shift >= 0)
8645 inst.instruction |= reg << shift;
8646
8647 return reg;
8648 }
8649
8650 /* Restore the start point. */
8651 *str = start;
8652 }
8653
8654 /* In the few cases where we might be able to accept something else
8655 this error can be overridden. */
8656 inst.error = _(all_reg_maps[regtype].expected);
8657
8658 return FAIL;
8659 }
8660
8661 /* Cirrus Maverick Instructions. */
8662
8663 /* Isnsn like "foo X,Y". */
8664
8665 static void
8666 do_mav_binops (char * str,
8667 int mode,
8668 enum arm_reg_type reg0,
8669 enum arm_reg_type reg1)
8670 {
8671 int shift0, shift1;
8672
8673 shift0 = mode & 0xff;
8674 shift1 = (mode >> 8) & 0xff;
8675
8676 skip_whitespace (str);
8677
8678 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
8679 || skip_past_comma (&str) == FAIL
8680 || mav_reg_required_here (&str, shift1, reg1) == FAIL)
8681 {
8682 if (!inst.error)
8683 inst.error = BAD_ARGS;
8684 }
8685 else
8686 end_of_line (str);
8687 }
8688
8689 /* Isnsn like "foo X,Y,Z". */
8690
8691 static void
8692 do_mav_triple (char * str,
8693 int mode,
8694 enum arm_reg_type reg0,
8695 enum arm_reg_type reg1,
8696 enum arm_reg_type reg2)
8697 {
8698 int shift0, shift1, shift2;
8699
8700 shift0 = mode & 0xff;
8701 shift1 = (mode >> 8) & 0xff;
8702 shift2 = (mode >> 16) & 0xff;
8703
8704 skip_whitespace (str);
8705
8706 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
8707 || skip_past_comma (&str) == FAIL
8708 || mav_reg_required_here (&str, shift1, reg1) == FAIL
8709 || skip_past_comma (&str) == FAIL
8710 || mav_reg_required_here (&str, shift2, reg2) == FAIL)
8711 {
8712 if (!inst.error)
8713 inst.error = BAD_ARGS;
8714 }
8715 else
8716 end_of_line (str);
8717 }
8718
8719 /* Wrapper functions. */
8720
8721 static void
8722 do_mav_binops_1a (char * str)
8723 {
8724 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVF);
8725 }
8726
8727 static void
8728 do_mav_binops_1b (char * str)
8729 {
8730 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVD);
8731 }
8732
8733 static void
8734 do_mav_binops_1c (char * str)
8735 {
8736 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVDX);
8737 }
8738
8739 static void
8740 do_mav_binops_1d (char * str)
8741 {
8742 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVF);
8743 }
8744
8745 static void
8746 do_mav_binops_1e (char * str)
8747 {
8748 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVD);
8749 }
8750
8751 static void
8752 do_mav_binops_1f (char * str)
8753 {
8754 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVF);
8755 }
8756
8757 static void
8758 do_mav_binops_1g (char * str)
8759 {
8760 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVD);
8761 }
8762
8763 static void
8764 do_mav_binops_1h (char * str)
8765 {
8766 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVFX);
8767 }
8768
8769 static void
8770 do_mav_binops_1i (char * str)
8771 {
8772 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVFX);
8773 }
8774
8775 static void
8776 do_mav_binops_1j (char * str)
8777 {
8778 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVDX);
8779 }
8780
8781 static void
8782 do_mav_binops_1k (char * str)
8783 {
8784 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVDX);
8785 }
8786
8787 static void
8788 do_mav_binops_1l (char * str)
8789 {
8790 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVF);
8791 }
8792
8793 static void
8794 do_mav_binops_1m (char * str)
8795 {
8796 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVD);
8797 }
8798
8799 static void
8800 do_mav_binops_1n (char * str)
8801 {
8802 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVFX);
8803 }
8804
8805 static void
8806 do_mav_binops_1o (char * str)
8807 {
8808 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVDX, REG_TYPE_MVDX);
8809 }
8810
8811 static void
8812 do_mav_binops_2a (char * str)
8813 {
8814 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVF, REG_TYPE_RN);
8815 }
8816
8817 static void
8818 do_mav_binops_2b (char * str)
8819 {
8820 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVD, REG_TYPE_RN);
8821 }
8822
8823 static void
8824 do_mav_binops_2c (char * str)
8825 {
8826 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVDX, REG_TYPE_RN);
8827 }
8828
8829 static void
8830 do_mav_binops_3a (char * str)
8831 {
8832 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVAX, REG_TYPE_MVFX);
8833 }
8834
8835 static void
8836 do_mav_binops_3b (char * str)
8837 {
8838 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVFX, REG_TYPE_MVAX);
8839 }
8840
8841 static void
8842 do_mav_binops_3c (char * str)
8843 {
8844 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVAX, REG_TYPE_MVDX);
8845 }
8846
8847 static void
8848 do_mav_binops_3d (char * str)
8849 {
8850 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVDX, REG_TYPE_MVAX);
8851 }
8852
8853 static void
8854 do_mav_triple_4a (char * str)
8855 {
8856 do_mav_triple (str, MAV_MODE4, REG_TYPE_MVFX, REG_TYPE_MVFX, REG_TYPE_RN);
8857 }
8858
8859 static void
8860 do_mav_triple_4b (char * str)
8861 {
8862 do_mav_triple (str, MAV_MODE4, REG_TYPE_MVDX, REG_TYPE_MVDX, REG_TYPE_RN);
8863 }
8864
8865 static void
8866 do_mav_triple_5a (char * str)
8867 {
8868 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVF, REG_TYPE_MVF);
8869 }
8870
8871 static void
8872 do_mav_triple_5b (char * str)
8873 {
8874 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVD, REG_TYPE_MVD);
8875 }
8876
8877 static void
8878 do_mav_triple_5c (char * str)
8879 {
8880 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVFX, REG_TYPE_MVFX);
8881 }
8882
8883 static void
8884 do_mav_triple_5d (char * str)
8885 {
8886 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVDX, REG_TYPE_MVDX);
8887 }
8888
8889 static void
8890 do_mav_triple_5e (char * str)
8891 {
8892 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVF, REG_TYPE_MVF, REG_TYPE_MVF);
8893 }
8894
8895 static void
8896 do_mav_triple_5f (char * str)
8897 {
8898 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVD, REG_TYPE_MVD, REG_TYPE_MVD);
8899 }
8900
8901 static void
8902 do_mav_triple_5g (char * str)
8903 {
8904 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVFX, REG_TYPE_MVFX, REG_TYPE_MVFX);
8905 }
8906
8907 static void
8908 do_mav_triple_5h (char * str)
8909 {
8910 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVDX, REG_TYPE_MVDX, REG_TYPE_MVDX);
8911 }
8912
8913 /* Isnsn like "foo W,X,Y,Z".
8914 where W=MVAX[0:3] and X,Y,Z=MVFX[0:15]. */
8915
8916 static void
8917 do_mav_quad (char * str,
8918 int mode,
8919 enum arm_reg_type reg0,
8920 enum arm_reg_type reg1,
8921 enum arm_reg_type reg2,
8922 enum arm_reg_type reg3)
8923 {
8924 int shift0, shift1, shift2, shift3;
8925
8926 shift0= mode & 0xff;
8927 shift1 = (mode >> 8) & 0xff;
8928 shift2 = (mode >> 16) & 0xff;
8929 shift3 = (mode >> 24) & 0xff;
8930
8931 skip_whitespace (str);
8932
8933 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
8934 || skip_past_comma (&str) == FAIL
8935 || mav_reg_required_here (&str, shift1, reg1) == FAIL
8936 || skip_past_comma (&str) == FAIL
8937 || mav_reg_required_here (&str, shift2, reg2) == FAIL
8938 || skip_past_comma (&str) == FAIL
8939 || mav_reg_required_here (&str, shift3, reg3) == FAIL)
8940 {
8941 if (!inst.error)
8942 inst.error = BAD_ARGS;
8943 }
8944 else
8945 end_of_line (str);
8946 }
8947
8948 static void
8949 do_mav_quad_6a (char * str)
8950 {
8951 do_mav_quad (str, MAV_MODE6, REG_TYPE_MVAX, REG_TYPE_MVFX, REG_TYPE_MVFX,
8952 REG_TYPE_MVFX);
8953 }
8954
8955 static void
8956 do_mav_quad_6b (char * str)
8957 {
8958 do_mav_quad (str, MAV_MODE6, REG_TYPE_MVAX, REG_TYPE_MVAX, REG_TYPE_MVFX,
8959 REG_TYPE_MVFX);
8960 }
8961
8962 /* cfmvsc32<cond> DSPSC,MVDX[15:0]. */
8963 static void
8964 do_mav_dspsc_1 (char * str)
8965 {
8966 skip_whitespace (str);
8967
8968 /* cfmvsc32. */
8969 if (mav_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL
8970 || skip_past_comma (&str) == FAIL
8971 || mav_reg_required_here (&str, 12, REG_TYPE_MVDX) == FAIL)
8972 {
8973 if (!inst.error)
8974 inst.error = BAD_ARGS;
8975
8976 return;
8977 }
8978
8979 end_of_line (str);
8980 }
8981
8982 /* cfmv32sc<cond> MVDX[15:0],DSPSC. */
8983 static void
8984 do_mav_dspsc_2 (char * str)
8985 {
8986 skip_whitespace (str);
8987
8988 /* cfmv32sc. */
8989 if (mav_reg_required_here (&str, 12, REG_TYPE_MVDX) == FAIL
8990 || skip_past_comma (&str) == FAIL
8991 || mav_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL)
8992 {
8993 if (!inst.error)
8994 inst.error = BAD_ARGS;
8995
8996 return;
8997 }
8998
8999 end_of_line (str);
9000 }
9001
9002 /* Maverick shift immediate instructions.
9003 cfsh32<cond> MVFX[15:0],MVFX[15:0],Shift[6:0].
9004 cfsh64<cond> MVDX[15:0],MVDX[15:0],Shift[6:0]. */
9005
9006 static void
9007 do_mav_shift (char * str,
9008 enum arm_reg_type reg0,
9009 enum arm_reg_type reg1)
9010 {
9011 int error;
9012 int imm, neg = 0;
9013
9014 skip_whitespace (str);
9015
9016 error = 0;
9017
9018 if (mav_reg_required_here (&str, 12, reg0) == FAIL
9019 || skip_past_comma (&str) == FAIL
9020 || mav_reg_required_here (&str, 16, reg1) == FAIL
9021 || skip_past_comma (&str) == FAIL)
9022 {
9023 if (!inst.error)
9024 inst.error = BAD_ARGS;
9025 return;
9026 }
9027
9028 /* Calculate the immediate operand.
9029 The operand is a 7bit signed number. */
9030 skip_whitespace (str);
9031
9032 if (*str == '#')
9033 ++str;
9034
9035 if (!ISDIGIT (*str) && *str != '-')
9036 {
9037 inst.error = _("expecting immediate, 7bit operand");
9038 return;
9039 }
9040
9041 if (*str == '-')
9042 {
9043 neg = 1;
9044 ++str;
9045 }
9046
9047 for (imm = 0; *str && ISDIGIT (*str); ++str)
9048 imm = imm * 10 + *str - '0';
9049
9050 if (imm > 64)
9051 {
9052 inst.error = _("immediate out of range");
9053 return;
9054 }
9055
9056 /* Make negative imm's into 7bit signed numbers. */
9057 if (neg)
9058 {
9059 imm = -imm;
9060 imm &= 0x0000007f;
9061 }
9062
9063 /* Bits 0-3 of the insn should have bits 0-3 of the immediate.
9064 Bits 5-7 of the insn should have bits 4-6 of the immediate.
9065 Bit 4 should be 0. */
9066 imm = (imm & 0xf) | ((imm & 0x70) << 1);
9067
9068 inst.instruction |= imm;
9069 end_of_line (str);
9070 }
9071
9072 static void
9073 do_mav_shift_1 (char * str)
9074 {
9075 do_mav_shift (str, REG_TYPE_MVFX, REG_TYPE_MVFX);
9076 }
9077
9078 static void
9079 do_mav_shift_2 (char * str)
9080 {
9081 do_mav_shift (str, REG_TYPE_MVDX, REG_TYPE_MVDX);
9082 }
9083
9084 static int
9085 mav_parse_offset (char ** str, int * negative)
9086 {
9087 char * p = *str;
9088 int offset;
9089
9090 *negative = 0;
9091
9092 skip_whitespace (p);
9093
9094 if (*p == '#')
9095 ++p;
9096
9097 if (*p == '-')
9098 {
9099 *negative = 1;
9100 ++p;
9101 }
9102
9103 if (!ISDIGIT (*p))
9104 {
9105 inst.error = _("offset expected");
9106 return 0;
9107 }
9108
9109 for (offset = 0; *p && ISDIGIT (*p); ++p)
9110 offset = offset * 10 + *p - '0';
9111
9112 if (offset > 0x3fc)
9113 {
9114 inst.error = _("offset out of range");
9115 return 0;
9116 }
9117 if (offset & 0x3)
9118 {
9119 inst.error = _("offset not a multiple of 4");
9120 return 0;
9121 }
9122
9123 *str = p;
9124
9125 return *negative ? -offset : offset;
9126 }
9127
9128 /* Maverick load/store instructions.
9129 <insn><cond> CRd,[Rn,<offset>]{!}.
9130 <insn><cond> CRd,[Rn],<offset>. */
9131
9132 static void
9133 do_mav_ldst (char * str, enum arm_reg_type reg0)
9134 {
9135 int offset, negative;
9136
9137 skip_whitespace (str);
9138
9139 if (mav_reg_required_here (&str, 12, reg0) == FAIL
9140 || skip_past_comma (&str) == FAIL
9141 || *str++ != '['
9142 || reg_required_here (&str, 16) == FAIL)
9143 goto fail_ldst;
9144
9145 if (skip_past_comma (&str) == SUCCESS)
9146 {
9147 /* You are here: "<offset>]{!}". */
9148 inst.instruction |= PRE_INDEX;
9149
9150 offset = mav_parse_offset (&str, &negative);
9151
9152 if (inst.error)
9153 return;
9154
9155 if (*str++ != ']')
9156 {
9157 inst.error = _("missing ]");
9158 return;
9159 }
9160
9161 if (*str == '!')
9162 {
9163 inst.instruction |= WRITE_BACK;
9164 ++str;
9165 }
9166 }
9167 else
9168 {
9169 /* You are here: "], <offset>". */
9170 if (*str++ != ']')
9171 {
9172 inst.error = _("missing ]");
9173 return;
9174 }
9175
9176 if (skip_past_comma (&str) == FAIL
9177 || (offset = mav_parse_offset (&str, &negative), inst.error))
9178 goto fail_ldst;
9179
9180 inst.instruction |= CP_T_WB; /* Post indexed, set bit W. */
9181 }
9182
9183 if (negative)
9184 offset = -offset;
9185 else
9186 inst.instruction |= CP_T_UD; /* Positive, so set bit U. */
9187
9188 inst.instruction |= offset >> 2;
9189 end_of_line (str);
9190 return;
9191
9192 fail_ldst:
9193 if (!inst.error)
9194 inst.error = BAD_ARGS;
9195 }
9196
9197 static void
9198 do_mav_ldst_1 (char * str)
9199 {
9200 do_mav_ldst (str, REG_TYPE_MVF);
9201 }
9202
9203 static void
9204 do_mav_ldst_2 (char * str)
9205 {
9206 do_mav_ldst (str, REG_TYPE_MVD);
9207 }
9208
9209 static void
9210 do_mav_ldst_3 (char * str)
9211 {
9212 do_mav_ldst (str, REG_TYPE_MVFX);
9213 }
9214
9215 static void
9216 do_mav_ldst_4 (char * str)
9217 {
9218 do_mav_ldst (str, REG_TYPE_MVDX);
9219 }
9220
9221 static void
9222 do_t_nop (char * str)
9223 {
9224 /* Do nothing. */
9225 end_of_line (str);
9226 }
9227
9228 /* Handle the Format 4 instructions that do not have equivalents in other
9229 formats. That is, ADC, AND, EOR, SBC, ROR, TST, NEG, CMN, ORR, MUL,
9230 BIC and MVN. */
9231
9232 static void
9233 do_t_arit (char * str)
9234 {
9235 int Rd, Rs, Rn;
9236
9237 skip_whitespace (str);
9238
9239 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9240 || skip_past_comma (&str) == FAIL
9241 || (Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9242 {
9243 inst.error = BAD_ARGS;
9244 return;
9245 }
9246
9247 if (skip_past_comma (&str) != FAIL)
9248 {
9249 /* Three operand format not allowed for TST, CMN, NEG and MVN.
9250 (It isn't allowed for CMP either, but that isn't handled by this
9251 function.) */
9252 if (inst.instruction == T_OPCODE_TST
9253 || inst.instruction == T_OPCODE_CMN
9254 || inst.instruction == T_OPCODE_NEG
9255 || inst.instruction == T_OPCODE_MVN)
9256 {
9257 inst.error = BAD_ARGS;
9258 return;
9259 }
9260
9261 if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9262 return;
9263
9264 if (Rs != Rd)
9265 {
9266 inst.error = _("dest and source1 must be the same register");
9267 return;
9268 }
9269 Rs = Rn;
9270 }
9271
9272 if (inst.instruction == T_OPCODE_MUL
9273 && Rs == Rd)
9274 as_tsktsk (_("Rs and Rd must be different in MUL"));
9275
9276 inst.instruction |= Rd | (Rs << 3);
9277 end_of_line (str);
9278 }
9279
9280 static void
9281 do_t_add (char * str)
9282 {
9283 thumb_add_sub (str, 0);
9284 }
9285
9286 static void
9287 do_t_asr (char * str)
9288 {
9289 thumb_shift (str, THUMB_ASR);
9290 }
9291
9292 static void
9293 do_t_branch9 (char * str)
9294 {
9295 if (my_get_expression (&inst.reloc.exp, &str))
9296 return;
9297 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH9;
9298 inst.reloc.pc_rel = 1;
9299 end_of_line (str);
9300 }
9301
9302 static void
9303 do_t_branch12 (char * str)
9304 {
9305 if (my_get_expression (&inst.reloc.exp, &str))
9306 return;
9307 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH12;
9308 inst.reloc.pc_rel = 1;
9309 end_of_line (str);
9310 }
9311
9312 /* Find the real, Thumb encoded start of a Thumb function. */
9313
9314 static symbolS *
9315 find_real_start (symbolS * symbolP)
9316 {
9317 char * real_start;
9318 const char * name = S_GET_NAME (symbolP);
9319 symbolS * new_target;
9320
9321 /* This definition must agree with the one in gcc/config/arm/thumb.c. */
9322 #define STUB_NAME ".real_start_of"
9323
9324 if (name == NULL)
9325 abort ();
9326
9327 /* Names that start with '.' are local labels, not function entry points.
9328 The compiler may generate BL instructions to these labels because it
9329 needs to perform a branch to a far away location. */
9330 if (name[0] == '.')
9331 return symbolP;
9332
9333 real_start = malloc (strlen (name) + strlen (STUB_NAME) + 1);
9334 sprintf (real_start, "%s%s", STUB_NAME, name);
9335
9336 new_target = symbol_find (real_start);
9337
9338 if (new_target == NULL)
9339 {
9340 as_warn ("Failed to find real start of function: %s\n", name);
9341 new_target = symbolP;
9342 }
9343
9344 free (real_start);
9345
9346 return new_target;
9347 }
9348
9349 static void
9350 do_t_branch23 (char * str)
9351 {
9352 if (my_get_expression (& inst.reloc.exp, & str))
9353 return;
9354
9355 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH23;
9356 inst.reloc.pc_rel = 1;
9357 end_of_line (str);
9358
9359 /* If the destination of the branch is a defined symbol which does not have
9360 the THUMB_FUNC attribute, then we must be calling a function which has
9361 the (interfacearm) attribute. We look for the Thumb entry point to that
9362 function and change the branch to refer to that function instead. */
9363 if ( inst.reloc.exp.X_op == O_symbol
9364 && inst.reloc.exp.X_add_symbol != NULL
9365 && S_IS_DEFINED (inst.reloc.exp.X_add_symbol)
9366 && ! THUMB_IS_FUNC (inst.reloc.exp.X_add_symbol))
9367 inst.reloc.exp.X_add_symbol =
9368 find_real_start (inst.reloc.exp.X_add_symbol);
9369 }
9370
9371 static void
9372 do_t_bx (char * str)
9373 {
9374 int reg;
9375
9376 skip_whitespace (str);
9377
9378 if ((reg = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
9379 return;
9380
9381 /* This sets THUMB_H2 from the top bit of reg. */
9382 inst.instruction |= reg << 3;
9383
9384 /* ??? FIXME: Should add a hacky reloc here if reg is REG_PC. The reloc
9385 should cause the alignment to be checked once it is known. This is
9386 because BX PC only works if the instruction is word aligned. */
9387
9388 end_of_line (str);
9389 }
9390
9391 static void
9392 do_t_compare (char * str)
9393 {
9394 thumb_mov_compare (str, THUMB_COMPARE);
9395 }
9396
9397 static void
9398 do_t_ldmstm (char * str)
9399 {
9400 int Rb;
9401 long range;
9402
9403 skip_whitespace (str);
9404
9405 if ((Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9406 return;
9407
9408 if (*str != '!')
9409 as_warn (_("inserted missing '!': load/store multiple always writes back base register"));
9410 else
9411 str++;
9412
9413 if (skip_past_comma (&str) == FAIL
9414 || (range = reg_list (&str)) == FAIL)
9415 {
9416 if (! inst.error)
9417 inst.error = BAD_ARGS;
9418 return;
9419 }
9420
9421 if (inst.reloc.type != BFD_RELOC_NONE)
9422 {
9423 /* This really doesn't seem worth it. */
9424 inst.reloc.type = BFD_RELOC_NONE;
9425 inst.error = _("expression too complex");
9426 return;
9427 }
9428
9429 if (range & ~0xff)
9430 {
9431 inst.error = _("only lo-regs valid in load/store multiple");
9432 return;
9433 }
9434
9435 inst.instruction |= (Rb << 8) | range;
9436 end_of_line (str);
9437 }
9438
9439 static void
9440 do_t_ldr (char * str)
9441 {
9442 thumb_load_store (str, THUMB_LOAD, THUMB_WORD);
9443 }
9444
9445 static void
9446 do_t_ldrb (char * str)
9447 {
9448 thumb_load_store (str, THUMB_LOAD, THUMB_BYTE);
9449 }
9450
9451 static void
9452 do_t_ldrh (char * str)
9453 {
9454 thumb_load_store (str, THUMB_LOAD, THUMB_HALFWORD);
9455 }
9456
9457 static void
9458 do_t_lds (char * str)
9459 {
9460 int Rd, Rb, Ro;
9461
9462 skip_whitespace (str);
9463
9464 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9465 || skip_past_comma (&str) == FAIL
9466 || *str++ != '['
9467 || (Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9468 || skip_past_comma (&str) == FAIL
9469 || (Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9470 || *str++ != ']')
9471 {
9472 if (! inst.error)
9473 inst.error = _("syntax: ldrs[b] Rd, [Rb, Ro]");
9474 return;
9475 }
9476
9477 inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
9478 end_of_line (str);
9479 }
9480
9481 static void
9482 do_t_lsl (char * str)
9483 {
9484 thumb_shift (str, THUMB_LSL);
9485 }
9486
9487 static void
9488 do_t_lsr (char * str)
9489 {
9490 thumb_shift (str, THUMB_LSR);
9491 }
9492
9493 static void
9494 do_t_mov (char * str)
9495 {
9496 thumb_mov_compare (str, THUMB_MOVE);
9497 }
9498
9499 static void
9500 do_t_push_pop (char * str)
9501 {
9502 long range;
9503
9504 skip_whitespace (str);
9505
9506 if ((range = reg_list (&str)) == FAIL)
9507 {
9508 if (! inst.error)
9509 inst.error = BAD_ARGS;
9510 return;
9511 }
9512
9513 if (inst.reloc.type != BFD_RELOC_NONE)
9514 {
9515 /* This really doesn't seem worth it. */
9516 inst.reloc.type = BFD_RELOC_NONE;
9517 inst.error = _("expression too complex");
9518 return;
9519 }
9520
9521 if (range & ~0xff)
9522 {
9523 if ((inst.instruction == T_OPCODE_PUSH
9524 && (range & ~0xff) == 1 << REG_LR)
9525 || (inst.instruction == T_OPCODE_POP
9526 && (range & ~0xff) == 1 << REG_PC))
9527 {
9528 inst.instruction |= THUMB_PP_PC_LR;
9529 range &= 0xff;
9530 }
9531 else
9532 {
9533 inst.error = _("invalid register list to push/pop instruction");
9534 return;
9535 }
9536 }
9537
9538 inst.instruction |= range;
9539 end_of_line (str);
9540 }
9541
9542 static void
9543 do_t_str (char * str)
9544 {
9545 thumb_load_store (str, THUMB_STORE, THUMB_WORD);
9546 }
9547
9548 static void
9549 do_t_strb (char * str)
9550 {
9551 thumb_load_store (str, THUMB_STORE, THUMB_BYTE);
9552 }
9553
9554 static void
9555 do_t_strh (char * str)
9556 {
9557 thumb_load_store (str, THUMB_STORE, THUMB_HALFWORD);
9558 }
9559
9560 static void
9561 do_t_sub (char * str)
9562 {
9563 thumb_add_sub (str, 1);
9564 }
9565
9566 static void
9567 do_t_swi (char * str)
9568 {
9569 skip_whitespace (str);
9570
9571 if (my_get_expression (&inst.reloc.exp, &str))
9572 return;
9573
9574 inst.reloc.type = BFD_RELOC_ARM_SWI;
9575 end_of_line (str);
9576 }
9577
9578 static void
9579 do_t_adr (char * str)
9580 {
9581 int reg;
9582
9583 /* This is a pseudo-op of the form "adr rd, label" to be converted
9584 into a relative address of the form "add rd, pc, #label-.-4". */
9585 skip_whitespace (str);
9586
9587 /* Store Rd in temporary location inside instruction. */
9588 if ((reg = reg_required_here (&str, 4)) == FAIL
9589 || (reg > 7) /* For Thumb reg must be r0..r7. */
9590 || skip_past_comma (&str) == FAIL
9591 || my_get_expression (&inst.reloc.exp, &str))
9592 {
9593 if (!inst.error)
9594 inst.error = BAD_ARGS;
9595 return;
9596 }
9597
9598 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
9599 inst.reloc.exp.X_add_number -= 4; /* PC relative adjust. */
9600 inst.reloc.pc_rel = 1;
9601 inst.instruction |= REG_PC; /* Rd is already placed into the instruction. */
9602
9603 end_of_line (str);
9604 }
9605
9606 static void
9607 insert_reg (const struct reg_entry * r,
9608 struct hash_control * htab)
9609 {
9610 int len = strlen (r->name) + 2;
9611 char * buf = xmalloc (len);
9612 char * buf2 = xmalloc (len);
9613 int i = 0;
9614
9615 #ifdef REGISTER_PREFIX
9616 buf[i++] = REGISTER_PREFIX;
9617 #endif
9618
9619 strcpy (buf + i, r->name);
9620
9621 for (i = 0; buf[i]; i++)
9622 buf2[i] = TOUPPER (buf[i]);
9623
9624 buf2[i] = '\0';
9625
9626 hash_insert (htab, buf, (PTR) r);
9627 hash_insert (htab, buf2, (PTR) r);
9628 }
9629
9630 static void
9631 build_reg_hsh (struct reg_map * map)
9632 {
9633 const struct reg_entry *r;
9634
9635 if ((map->htab = hash_new ()) == NULL)
9636 as_fatal (_("virtual memory exhausted"));
9637
9638 for (r = map->names; r->name != NULL; r++)
9639 insert_reg (r, map->htab);
9640 }
9641
9642 static void
9643 insert_reg_alias (char * str,
9644 int regnum,
9645 struct hash_control *htab)
9646 {
9647 const char * error;
9648 struct reg_entry * new = xmalloc (sizeof (struct reg_entry));
9649 const char * name = xmalloc (strlen (str) + 1);
9650
9651 strcpy ((char *) name, str);
9652
9653 new->name = name;
9654 new->number = regnum;
9655 new->builtin = FALSE;
9656
9657 error = hash_insert (htab, name, (PTR) new);
9658 if (error)
9659 {
9660 as_bad (_("failed to create an alias for %s, reason: %s"),
9661 str, error);
9662 free ((char *) name);
9663 free (new);
9664 }
9665 }
9666
9667 /* Look for the .req directive. This is of the form:
9668
9669 new_register_name .req existing_register_name
9670
9671 If we find one, or if it looks sufficiently like one that we want to
9672 handle any error here, return non-zero. Otherwise return zero. */
9673
9674 static int
9675 create_register_alias (char * newname, char * p)
9676 {
9677 char * q;
9678 char c;
9679
9680 q = p;
9681 skip_whitespace (q);
9682
9683 c = *p;
9684 *p = '\0';
9685
9686 if (*q && !strncmp (q, ".req ", 5))
9687 {
9688 char *copy_of_str;
9689 char *r;
9690
9691 #ifndef IGNORE_OPCODE_CASE
9692 newname = original_case_string;
9693 #endif
9694 copy_of_str = newname;
9695
9696 q += 4;
9697 skip_whitespace (q);
9698
9699 for (r = q; *r != '\0'; r++)
9700 if (*r == ' ')
9701 break;
9702
9703 if (r != q)
9704 {
9705 enum arm_reg_type new_type, old_type;
9706 int old_regno;
9707 char d = *r;
9708
9709 *r = '\0';
9710 old_type = arm_reg_parse_any (q);
9711 *r = d;
9712
9713 new_type = arm_reg_parse_any (newname);
9714
9715 if (new_type == REG_TYPE_MAX)
9716 {
9717 if (old_type != REG_TYPE_MAX)
9718 {
9719 old_regno = arm_reg_parse (&q, all_reg_maps[old_type].htab);
9720 insert_reg_alias (newname, old_regno,
9721 all_reg_maps[old_type].htab);
9722 }
9723 else
9724 as_warn (_("register '%s' does not exist\n"), q);
9725 }
9726 else if (old_type == REG_TYPE_MAX)
9727 {
9728 as_warn (_("ignoring redefinition of register alias '%s' to non-existant register '%s'"),
9729 copy_of_str, q);
9730 }
9731 else
9732 {
9733 /* Do not warn about redefinitions to the same alias. */
9734 if (new_type != old_type
9735 || (arm_reg_parse (&q, all_reg_maps[old_type].htab)
9736 != arm_reg_parse (&q, all_reg_maps[new_type].htab)))
9737 as_warn (_("ignoring redefinition of register alias '%s'"),
9738 copy_of_str);
9739
9740 }
9741 }
9742 else
9743 as_warn (_("ignoring incomplete .req pseuso op"));
9744
9745 *p = c;
9746 return 1;
9747 }
9748
9749 *p = c;
9750 return 0;
9751 }
9752
9753 static void
9754 set_constant_flonums (void)
9755 {
9756 int i;
9757
9758 for (i = 0; i < NUM_FLOAT_VALS; i++)
9759 if (atof_ieee ((char *) fp_const[i], 'x', fp_values[i]) == NULL)
9760 abort ();
9761 }
9762
9763 \f
9764 static const struct asm_opcode insns[] =
9765 {
9766 /* Core ARM Instructions. */
9767 {"and", 0xe0000000, 3, ARM_EXT_V1, do_arit},
9768 {"ands", 0xe0100000, 3, ARM_EXT_V1, do_arit},
9769 {"eor", 0xe0200000, 3, ARM_EXT_V1, do_arit},
9770 {"eors", 0xe0300000, 3, ARM_EXT_V1, do_arit},
9771 {"sub", 0xe0400000, 3, ARM_EXT_V1, do_arit},
9772 {"subs", 0xe0500000, 3, ARM_EXT_V1, do_arit},
9773 {"rsb", 0xe0600000, 3, ARM_EXT_V1, do_arit},
9774 {"rsbs", 0xe0700000, 3, ARM_EXT_V1, do_arit},
9775 {"add", 0xe0800000, 3, ARM_EXT_V1, do_arit},
9776 {"adds", 0xe0900000, 3, ARM_EXT_V1, do_arit},
9777 {"adc", 0xe0a00000, 3, ARM_EXT_V1, do_arit},
9778 {"adcs", 0xe0b00000, 3, ARM_EXT_V1, do_arit},
9779 {"sbc", 0xe0c00000, 3, ARM_EXT_V1, do_arit},
9780 {"sbcs", 0xe0d00000, 3, ARM_EXT_V1, do_arit},
9781 {"rsc", 0xe0e00000, 3, ARM_EXT_V1, do_arit},
9782 {"rscs", 0xe0f00000, 3, ARM_EXT_V1, do_arit},
9783 {"orr", 0xe1800000, 3, ARM_EXT_V1, do_arit},
9784 {"orrs", 0xe1900000, 3, ARM_EXT_V1, do_arit},
9785 {"bic", 0xe1c00000, 3, ARM_EXT_V1, do_arit},
9786 {"bics", 0xe1d00000, 3, ARM_EXT_V1, do_arit},
9787
9788 {"tst", 0xe1100000, 3, ARM_EXT_V1, do_cmp},
9789 {"tsts", 0xe1100000, 3, ARM_EXT_V1, do_cmp},
9790 {"tstp", 0xe110f000, 3, ARM_EXT_V1, do_cmp},
9791 {"teq", 0xe1300000, 3, ARM_EXT_V1, do_cmp},
9792 {"teqs", 0xe1300000, 3, ARM_EXT_V1, do_cmp},
9793 {"teqp", 0xe130f000, 3, ARM_EXT_V1, do_cmp},
9794 {"cmp", 0xe1500000, 3, ARM_EXT_V1, do_cmp},
9795 {"cmps", 0xe1500000, 3, ARM_EXT_V1, do_cmp},
9796 {"cmpp", 0xe150f000, 3, ARM_EXT_V1, do_cmp},
9797 {"cmn", 0xe1700000, 3, ARM_EXT_V1, do_cmp},
9798 {"cmns", 0xe1700000, 3, ARM_EXT_V1, do_cmp},
9799 {"cmnp", 0xe170f000, 3, ARM_EXT_V1, do_cmp},
9800
9801 {"mov", 0xe1a00000, 3, ARM_EXT_V1, do_mov},
9802 {"movs", 0xe1b00000, 3, ARM_EXT_V1, do_mov},
9803 {"mvn", 0xe1e00000, 3, ARM_EXT_V1, do_mov},
9804 {"mvns", 0xe1f00000, 3, ARM_EXT_V1, do_mov},
9805
9806 {"ldr", 0xe4100000, 3, ARM_EXT_V1, do_ldst},
9807 {"ldrb", 0xe4500000, 3, ARM_EXT_V1, do_ldst},
9808 {"ldrt", 0xe4300000, 3, ARM_EXT_V1, do_ldstt},
9809 {"ldrbt", 0xe4700000, 3, ARM_EXT_V1, do_ldstt},
9810 {"str", 0xe4000000, 3, ARM_EXT_V1, do_ldst},
9811 {"strb", 0xe4400000, 3, ARM_EXT_V1, do_ldst},
9812 {"strt", 0xe4200000, 3, ARM_EXT_V1, do_ldstt},
9813 {"strbt", 0xe4600000, 3, ARM_EXT_V1, do_ldstt},
9814
9815 {"stmia", 0xe8800000, 3, ARM_EXT_V1, do_ldmstm},
9816 {"stmib", 0xe9800000, 3, ARM_EXT_V1, do_ldmstm},
9817 {"stmda", 0xe8000000, 3, ARM_EXT_V1, do_ldmstm},
9818 {"stmdb", 0xe9000000, 3, ARM_EXT_V1, do_ldmstm},
9819 {"stmfd", 0xe9000000, 3, ARM_EXT_V1, do_ldmstm},
9820 {"stmfa", 0xe9800000, 3, ARM_EXT_V1, do_ldmstm},
9821 {"stmea", 0xe8800000, 3, ARM_EXT_V1, do_ldmstm},
9822 {"stmed", 0xe8000000, 3, ARM_EXT_V1, do_ldmstm},
9823
9824 {"ldmia", 0xe8900000, 3, ARM_EXT_V1, do_ldmstm},
9825 {"ldmib", 0xe9900000, 3, ARM_EXT_V1, do_ldmstm},
9826 {"ldmda", 0xe8100000, 3, ARM_EXT_V1, do_ldmstm},
9827 {"ldmdb", 0xe9100000, 3, ARM_EXT_V1, do_ldmstm},
9828 {"ldmfd", 0xe8900000, 3, ARM_EXT_V1, do_ldmstm},
9829 {"ldmfa", 0xe8100000, 3, ARM_EXT_V1, do_ldmstm},
9830 {"ldmea", 0xe9100000, 3, ARM_EXT_V1, do_ldmstm},
9831 {"ldmed", 0xe9900000, 3, ARM_EXT_V1, do_ldmstm},
9832
9833 {"swi", 0xef000000, 3, ARM_EXT_V1, do_swi},
9834 #ifdef TE_WINCE
9835 /* XXX This is the wrong place to do this. Think multi-arch. */
9836 {"bl", 0xeb000000, 2, ARM_EXT_V1, do_branch},
9837 {"b", 0xea000000, 1, ARM_EXT_V1, do_branch},
9838 #else
9839 {"bl", 0xebfffffe, 2, ARM_EXT_V1, do_branch},
9840 {"b", 0xeafffffe, 1, ARM_EXT_V1, do_branch},
9841 #endif
9842
9843 /* Pseudo ops. */
9844 {"adr", 0xe28f0000, 3, ARM_EXT_V1, do_adr},
9845 {"adrl", 0xe28f0000, 3, ARM_EXT_V1, do_adrl},
9846 {"nop", 0xe1a00000, 3, ARM_EXT_V1, do_nop},
9847
9848 /* ARM 2 multiplies. */
9849 {"mul", 0xe0000090, 3, ARM_EXT_V2, do_mul},
9850 {"muls", 0xe0100090, 3, ARM_EXT_V2, do_mul},
9851 {"mla", 0xe0200090, 3, ARM_EXT_V2, do_mla},
9852 {"mlas", 0xe0300090, 3, ARM_EXT_V2, do_mla},
9853
9854 /* Generic coprocessor instructions. */
9855 {"cdp", 0xee000000, 3, ARM_EXT_V2, do_cdp},
9856 {"ldc", 0xec100000, 3, ARM_EXT_V2, do_lstc},
9857 {"ldcl", 0xec500000, 3, ARM_EXT_V2, do_lstc},
9858 {"stc", 0xec000000, 3, ARM_EXT_V2, do_lstc},
9859 {"stcl", 0xec400000, 3, ARM_EXT_V2, do_lstc},
9860 {"mcr", 0xee000010, 3, ARM_EXT_V2, do_co_reg},
9861 {"mrc", 0xee100010, 3, ARM_EXT_V2, do_co_reg},
9862
9863 /* ARM 3 - swp instructions. */
9864 {"swp", 0xe1000090, 3, ARM_EXT_V2S, do_swap},
9865 {"swpb", 0xe1400090, 3, ARM_EXT_V2S, do_swap},
9866
9867 /* ARM 6 Status register instructions. */
9868 {"mrs", 0xe10f0000, 3, ARM_EXT_V3, do_mrs},
9869 {"msr", 0xe120f000, 3, ARM_EXT_V3, do_msr},
9870 /* ScottB: our code uses 0xe128f000 for msr.
9871 NickC: but this is wrong because the bits 16 through 19 are
9872 handled by the PSR_xxx defines above. */
9873
9874 /* ARM 7M long multiplies. */
9875 {"smull", 0xe0c00090, 5, ARM_EXT_V3M, do_mull},
9876 {"smulls", 0xe0d00090, 5, ARM_EXT_V3M, do_mull},
9877 {"umull", 0xe0800090, 5, ARM_EXT_V3M, do_mull},
9878 {"umulls", 0xe0900090, 5, ARM_EXT_V3M, do_mull},
9879 {"smlal", 0xe0e00090, 5, ARM_EXT_V3M, do_mull},
9880 {"smlals", 0xe0f00090, 5, ARM_EXT_V3M, do_mull},
9881 {"umlal", 0xe0a00090, 5, ARM_EXT_V3M, do_mull},
9882 {"umlals", 0xe0b00090, 5, ARM_EXT_V3M, do_mull},
9883
9884 /* ARM Architecture 4. */
9885 {"ldrh", 0xe01000b0, 3, ARM_EXT_V4, do_ldstv4},
9886 {"ldrsh", 0xe01000f0, 3, ARM_EXT_V4, do_ldstv4},
9887 {"ldrsb", 0xe01000d0, 3, ARM_EXT_V4, do_ldstv4},
9888 {"strh", 0xe00000b0, 3, ARM_EXT_V4, do_ldstv4},
9889
9890 /* ARM Architecture 4T. */
9891 /* Note: bx (and blx) are required on V5, even if the processor does
9892 not support Thumb. */
9893 {"bx", 0xe12fff10, 2, ARM_EXT_V4T | ARM_EXT_V5, do_bx},
9894
9895 /* ARM Architecture 5T. */
9896 /* Note: blx has 2 variants, so the .value is set dynamically.
9897 Only one of the variants has conditional execution. */
9898 {"blx", 0xe0000000, 3, ARM_EXT_V5, do_blx},
9899 {"clz", 0xe16f0f10, 3, ARM_EXT_V5, do_clz},
9900 {"bkpt", 0xe1200070, 0, ARM_EXT_V5, do_bkpt},
9901 {"ldc2", 0xfc100000, 0, ARM_EXT_V5, do_lstc2},
9902 {"ldc2l", 0xfc500000, 0, ARM_EXT_V5, do_lstc2},
9903 {"stc2", 0xfc000000, 0, ARM_EXT_V5, do_lstc2},
9904 {"stc2l", 0xfc400000, 0, ARM_EXT_V5, do_lstc2},
9905 {"cdp2", 0xfe000000, 0, ARM_EXT_V5, do_cdp2},
9906 {"mcr2", 0xfe000010, 0, ARM_EXT_V5, do_co_reg2},
9907 {"mrc2", 0xfe100010, 0, ARM_EXT_V5, do_co_reg2},
9908
9909 /* ARM Architecture 5TExP. */
9910 {"smlabb", 0xe1000080, 6, ARM_EXT_V5ExP, do_smla},
9911 {"smlatb", 0xe10000a0, 6, ARM_EXT_V5ExP, do_smla},
9912 {"smlabt", 0xe10000c0, 6, ARM_EXT_V5ExP, do_smla},
9913 {"smlatt", 0xe10000e0, 6, ARM_EXT_V5ExP, do_smla},
9914
9915 {"smlawb", 0xe1200080, 6, ARM_EXT_V5ExP, do_smla},
9916 {"smlawt", 0xe12000c0, 6, ARM_EXT_V5ExP, do_smla},
9917
9918 {"smlalbb", 0xe1400080, 7, ARM_EXT_V5ExP, do_smlal},
9919 {"smlaltb", 0xe14000a0, 7, ARM_EXT_V5ExP, do_smlal},
9920 {"smlalbt", 0xe14000c0, 7, ARM_EXT_V5ExP, do_smlal},
9921 {"smlaltt", 0xe14000e0, 7, ARM_EXT_V5ExP, do_smlal},
9922
9923 {"smulbb", 0xe1600080, 6, ARM_EXT_V5ExP, do_smul},
9924 {"smultb", 0xe16000a0, 6, ARM_EXT_V5ExP, do_smul},
9925 {"smulbt", 0xe16000c0, 6, ARM_EXT_V5ExP, do_smul},
9926 {"smultt", 0xe16000e0, 6, ARM_EXT_V5ExP, do_smul},
9927
9928 {"smulwb", 0xe12000a0, 6, ARM_EXT_V5ExP, do_smul},
9929 {"smulwt", 0xe12000e0, 6, ARM_EXT_V5ExP, do_smul},
9930
9931 {"qadd", 0xe1000050, 4, ARM_EXT_V5ExP, do_qadd},
9932 {"qdadd", 0xe1400050, 5, ARM_EXT_V5ExP, do_qadd},
9933 {"qsub", 0xe1200050, 4, ARM_EXT_V5ExP, do_qadd},
9934 {"qdsub", 0xe1600050, 5, ARM_EXT_V5ExP, do_qadd},
9935
9936 /* ARM Architecture 5TE. */
9937 {"pld", 0xf450f000, 0, ARM_EXT_V5E, do_pld},
9938 {"ldrd", 0xe00000d0, 3, ARM_EXT_V5E, do_ldrd},
9939 {"strd", 0xe00000f0, 3, ARM_EXT_V5E, do_ldrd},
9940
9941 {"mcrr", 0xec400000, 4, ARM_EXT_V5E, do_co_reg2c},
9942 {"mrrc", 0xec500000, 4, ARM_EXT_V5E, do_co_reg2c},
9943
9944 /* ARM Architecture 5TEJ. */
9945 {"bxj", 0xe12fff20, 3, ARM_EXT_V5J, do_bxj},
9946
9947 /* ARM V6. */
9948 { "cps", 0xf1020000, 0, ARM_EXT_V6, do_cps},
9949 { "cpsie", 0xf1080000, 0, ARM_EXT_V6, do_cpsi},
9950 { "cpsid", 0xf10C0000, 0, ARM_EXT_V6, do_cpsi},
9951 { "ldrex", 0xe1900f9f, 5, ARM_EXT_V6, do_ldrex},
9952 { "mcrr2", 0xfc400000, 0, ARM_EXT_V6, do_co_reg2c},
9953 { "mrrc2", 0xfc500000, 0, ARM_EXT_V6, do_co_reg2c},
9954 { "pkhbt", 0xe6800010, 5, ARM_EXT_V6, do_pkhbt},
9955 { "pkhtb", 0xe6800050, 5, ARM_EXT_V6, do_pkhtb},
9956 { "qadd16", 0xe6200f10, 6, ARM_EXT_V6, do_qadd16},
9957 { "qadd8", 0xe6200f90, 5, ARM_EXT_V6, do_qadd16},
9958 { "qaddsubx", 0xe6200f30, 8, ARM_EXT_V6, do_qadd16},
9959 { "qsub16", 0xe6200f70, 6, ARM_EXT_V6, do_qadd16},
9960 { "qsub8", 0xe6200ff0, 5, ARM_EXT_V6, do_qadd16},
9961 { "qsubaddx", 0xe6200f50, 8, ARM_EXT_V6, do_qadd16},
9962 { "sadd16", 0xe6100f10, 6, ARM_EXT_V6, do_qadd16},
9963 { "sadd8", 0xe6100f90, 5, ARM_EXT_V6, do_qadd16},
9964 { "saddsubx", 0xe6100f30, 8, ARM_EXT_V6, do_qadd16},
9965 { "shadd16", 0xe6300f10, 7, ARM_EXT_V6, do_qadd16},
9966 { "shadd8", 0xe6300f90, 6, ARM_EXT_V6, do_qadd16},
9967 { "shaddsubx", 0xe6300f30, 9, ARM_EXT_V6, do_qadd16},
9968 { "shsub16", 0xe6300f70, 7, ARM_EXT_V6, do_qadd16},
9969 { "shsub8", 0xe6300ff0, 6, ARM_EXT_V6, do_qadd16},
9970 { "shsubaddx", 0xe6300f50, 9, ARM_EXT_V6, do_qadd16},
9971 { "ssub16", 0xe6100f70, 6, ARM_EXT_V6, do_qadd16},
9972 { "ssub8", 0xe6100ff0, 5, ARM_EXT_V6, do_qadd16},
9973 { "ssubaddx", 0xe6100f50, 8, ARM_EXT_V6, do_qadd16},
9974 { "uadd16", 0xe6500f10, 6, ARM_EXT_V6, do_qadd16},
9975 { "uadd8", 0xe6500f90, 5, ARM_EXT_V6, do_qadd16},
9976 { "uaddsubx", 0xe6500f30, 8, ARM_EXT_V6, do_qadd16},
9977 { "uhadd16", 0xe6700f10, 7, ARM_EXT_V6, do_qadd16},
9978 { "uhadd8", 0xe6700f90, 6, ARM_EXT_V6, do_qadd16},
9979 { "uhaddsubx", 0xe6700f30, 9, ARM_EXT_V6, do_qadd16},
9980 { "uhsub16", 0xe6700f70, 7, ARM_EXT_V6, do_qadd16},
9981 { "uhsub8", 0xe6700ff0, 6, ARM_EXT_V6, do_qadd16},
9982 { "uhsubaddx", 0xe6700f50, 9, ARM_EXT_V6, do_qadd16},
9983 { "uqadd16", 0xe6600f10, 7, ARM_EXT_V6, do_qadd16},
9984 { "uqadd8", 0xe6600f90, 6, ARM_EXT_V6, do_qadd16},
9985 { "uqaddsubx", 0xe6600f30, 9, ARM_EXT_V6, do_qadd16},
9986 { "uqsub16", 0xe6600f70, 7, ARM_EXT_V6, do_qadd16},
9987 { "uqsub8", 0xe6600ff0, 6, ARM_EXT_V6, do_qadd16},
9988 { "uqsubaddx", 0xe6600f50, 9, ARM_EXT_V6, do_qadd16},
9989 { "usub16", 0xe6500f70, 6, ARM_EXT_V6, do_qadd16},
9990 { "usub8", 0xe6500ff0, 5, ARM_EXT_V6, do_qadd16},
9991 { "usubaddx", 0xe6500f50, 8, ARM_EXT_V6, do_qadd16},
9992 { "rev", 0xe6bf0f30, 3, ARM_EXT_V6, do_rev},
9993 { "rev16", 0xe6bf0fb0, 5, ARM_EXT_V6, do_rev},
9994 { "revsh", 0xe6ff0fb0, 5, ARM_EXT_V6, do_rev},
9995 { "rfeia", 0xf8900a00, 0, ARM_EXT_V6, do_rfe},
9996 { "rfeib", 0xf9900a00, 0, ARM_EXT_V6, do_rfe},
9997 { "rfeda", 0xf8100a00, 0, ARM_EXT_V6, do_rfe},
9998 { "rfedb", 0xf9100a00, 0, ARM_EXT_V6, do_rfe},
9999 { "rfefd", 0xf8900a00, 0, ARM_EXT_V6, do_rfe},
10000 { "rfefa", 0xf9900a00, 0, ARM_EXT_V6, do_rfe},
10001 { "rfeea", 0xf8100a00, 0, ARM_EXT_V6, do_rfe},
10002 { "rfeed", 0xf9100a00, 0, ARM_EXT_V6, do_rfe},
10003 { "sxtah", 0xe6b00070, 5, ARM_EXT_V6, do_sxtah},
10004 { "sxtab16", 0xe6800070, 7, ARM_EXT_V6, do_sxtah},
10005 { "sxtab", 0xe6a00070, 5, ARM_EXT_V6, do_sxtah},
10006 { "sxth", 0xe6bf0070, 4, ARM_EXT_V6, do_sxth},
10007 { "sxtb16", 0xe68f0070, 6, ARM_EXT_V6, do_sxth},
10008 { "sxtb", 0xe6af0070, 4, ARM_EXT_V6, do_sxth},
10009 { "uxtah", 0xe6f00070, 5, ARM_EXT_V6, do_sxtah},
10010 { "uxtab16", 0xe6c00070, 7, ARM_EXT_V6, do_sxtah},
10011 { "uxtab", 0xe6e00070, 5, ARM_EXT_V6, do_sxtah},
10012 { "uxth", 0xe6ff0070, 4, ARM_EXT_V6, do_sxth},
10013 { "uxtb16", 0xe6cf0070, 6, ARM_EXT_V6, do_sxth},
10014 { "uxtb", 0xe6ef0070, 4, ARM_EXT_V6, do_sxth},
10015 { "sel", 0xe68000b0, 3, ARM_EXT_V6, do_qadd16},
10016 { "setend", 0xf1010000, 0, ARM_EXT_V6, do_setend},
10017 { "smlad", 0xe7000010, 5, ARM_EXT_V6, do_smlad},
10018 { "smladx", 0xe7000030, 6, ARM_EXT_V6, do_smlad},
10019 { "smlald", 0xe7400010, 6, ARM_EXT_V6, do_smlald},
10020 { "smlaldx", 0xe7400030, 7, ARM_EXT_V6, do_smlald},
10021 { "smlsd", 0xe7000050, 5, ARM_EXT_V6, do_smlad},
10022 { "smlsdx", 0xe7000070, 6, ARM_EXT_V6, do_smlad},
10023 { "smlsld", 0xe7400050, 6, ARM_EXT_V6, do_smlald},
10024 { "smlsldx", 0xe7400070, 7, ARM_EXT_V6, do_smlald},
10025 { "smmla", 0xe7500010, 5, ARM_EXT_V6, do_smlad},
10026 { "smmlar", 0xe7500030, 6, ARM_EXT_V6, do_smlad},
10027 { "smmls", 0xe75000d0, 5, ARM_EXT_V6, do_smlad},
10028 { "smmlsr", 0xe75000f0, 6, ARM_EXT_V6, do_smlad},
10029 { "smmul", 0xe750f010, 5, ARM_EXT_V6, do_smmul},
10030 { "smmulr", 0xe750f030, 6, ARM_EXT_V6, do_smmul},
10031 { "smuad", 0xe700f010, 5, ARM_EXT_V6, do_smmul},
10032 { "smuadx", 0xe700f030, 6, ARM_EXT_V6, do_smmul},
10033 { "smusd", 0xe700f050, 5, ARM_EXT_V6, do_smmul},
10034 { "smusdx", 0xe700f070, 6, ARM_EXT_V6, do_smmul},
10035 { "srsia", 0xf8cd0500, 0, ARM_EXT_V6, do_srs},
10036 { "srsib", 0xf9cd0500, 0, ARM_EXT_V6, do_srs},
10037 { "srsda", 0xf84d0500, 0, ARM_EXT_V6, do_srs},
10038 { "srsdb", 0xf94d0500, 0, ARM_EXT_V6, do_srs},
10039 { "ssat", 0xe6a00010, 4, ARM_EXT_V6, do_ssat},
10040 { "ssat16", 0xe6a00f30, 6, ARM_EXT_V6, do_ssat16},
10041 { "strex", 0xe1800f90, 5, ARM_EXT_V6, do_strex},
10042 { "umaal", 0xe0400090, 5, ARM_EXT_V6, do_umaal},
10043 { "usad8", 0xe780f010, 5, ARM_EXT_V6, do_smmul},
10044 { "usada8", 0xe7800010, 6, ARM_EXT_V6, do_smlad},
10045 { "usat", 0xe6e00010, 4, ARM_EXT_V6, do_usat},
10046 { "usat16", 0xe6e00f30, 6, ARM_EXT_V6, do_usat16},
10047
10048 /* ARM V6K. */
10049 { "clrex", 0xf57ff01f, 0, ARM_EXT_V6K, do_empty},
10050 { "ldrexb", 0xe1d00f9f, 6, ARM_EXT_V6K, do_ldrex},
10051 { "ldrexd", 0xe1b00f9f, 6, ARM_EXT_V6K, do_ldrex},
10052 { "ldrexh", 0xe1f00f9f, 6, ARM_EXT_V6K, do_ldrex},
10053 { "sev", 0xe320f004, 3, ARM_EXT_V6K, do_empty},
10054 { "strexb", 0xe1c00f90, 6, ARM_EXT_V6K, do_strex},
10055 { "strexd", 0xe1a00f90, 6, ARM_EXT_V6K, do_strex},
10056 { "strexh", 0xe1e00f90, 6, ARM_EXT_V6K, do_strex},
10057 { "wfe", 0xe320f002, 3, ARM_EXT_V6K, do_empty},
10058 { "wfi", 0xe320f003, 3, ARM_EXT_V6K, do_empty},
10059 { "yield", 0xe320f001, 5, ARM_EXT_V6K, do_empty},
10060
10061 /* ARM V6Z. */
10062 { "smi", 0xe1600070, 3, ARM_EXT_V6Z, do_smi},
10063
10064 /* Core FPA instruction set (V1). */
10065 {"wfs", 0xee200110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
10066 {"rfs", 0xee300110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
10067 {"wfc", 0xee400110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
10068 {"rfc", 0xee500110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
10069
10070 {"ldfs", 0xec100100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10071 {"ldfd", 0xec108100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10072 {"ldfe", 0xec500100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10073 {"ldfp", 0xec508100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10074
10075 {"stfs", 0xec000100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10076 {"stfd", 0xec008100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10077 {"stfe", 0xec400100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10078 {"stfp", 0xec408100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10079
10080 {"mvfs", 0xee008100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10081 {"mvfsp", 0xee008120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10082 {"mvfsm", 0xee008140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10083 {"mvfsz", 0xee008160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10084 {"mvfd", 0xee008180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10085 {"mvfdp", 0xee0081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10086 {"mvfdm", 0xee0081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10087 {"mvfdz", 0xee0081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10088 {"mvfe", 0xee088100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10089 {"mvfep", 0xee088120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10090 {"mvfem", 0xee088140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10091 {"mvfez", 0xee088160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10092
10093 {"mnfs", 0xee108100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10094 {"mnfsp", 0xee108120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10095 {"mnfsm", 0xee108140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10096 {"mnfsz", 0xee108160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10097 {"mnfd", 0xee108180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10098 {"mnfdp", 0xee1081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10099 {"mnfdm", 0xee1081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10100 {"mnfdz", 0xee1081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10101 {"mnfe", 0xee188100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10102 {"mnfep", 0xee188120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10103 {"mnfem", 0xee188140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10104 {"mnfez", 0xee188160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10105
10106 {"abss", 0xee208100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10107 {"abssp", 0xee208120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10108 {"abssm", 0xee208140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10109 {"abssz", 0xee208160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10110 {"absd", 0xee208180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10111 {"absdp", 0xee2081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10112 {"absdm", 0xee2081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10113 {"absdz", 0xee2081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10114 {"abse", 0xee288100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10115 {"absep", 0xee288120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10116 {"absem", 0xee288140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10117 {"absez", 0xee288160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10118
10119 {"rnds", 0xee308100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10120 {"rndsp", 0xee308120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10121 {"rndsm", 0xee308140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10122 {"rndsz", 0xee308160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10123 {"rndd", 0xee308180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10124 {"rnddp", 0xee3081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10125 {"rnddm", 0xee3081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10126 {"rnddz", 0xee3081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10127 {"rnde", 0xee388100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10128 {"rndep", 0xee388120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10129 {"rndem", 0xee388140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10130 {"rndez", 0xee388160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10131
10132 {"sqts", 0xee408100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10133 {"sqtsp", 0xee408120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10134 {"sqtsm", 0xee408140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10135 {"sqtsz", 0xee408160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10136 {"sqtd", 0xee408180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10137 {"sqtdp", 0xee4081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10138 {"sqtdm", 0xee4081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10139 {"sqtdz", 0xee4081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10140 {"sqte", 0xee488100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10141 {"sqtep", 0xee488120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10142 {"sqtem", 0xee488140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10143 {"sqtez", 0xee488160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10144
10145 {"logs", 0xee508100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10146 {"logsp", 0xee508120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10147 {"logsm", 0xee508140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10148 {"logsz", 0xee508160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10149 {"logd", 0xee508180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10150 {"logdp", 0xee5081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10151 {"logdm", 0xee5081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10152 {"logdz", 0xee5081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10153 {"loge", 0xee588100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10154 {"logep", 0xee588120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10155 {"logem", 0xee588140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10156 {"logez", 0xee588160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10157
10158 {"lgns", 0xee608100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10159 {"lgnsp", 0xee608120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10160 {"lgnsm", 0xee608140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10161 {"lgnsz", 0xee608160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10162 {"lgnd", 0xee608180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10163 {"lgndp", 0xee6081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10164 {"lgndm", 0xee6081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10165 {"lgndz", 0xee6081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10166 {"lgne", 0xee688100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10167 {"lgnep", 0xee688120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10168 {"lgnem", 0xee688140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10169 {"lgnez", 0xee688160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10170
10171 {"exps", 0xee708100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10172 {"expsp", 0xee708120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10173 {"expsm", 0xee708140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10174 {"expsz", 0xee708160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10175 {"expd", 0xee708180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10176 {"expdp", 0xee7081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10177 {"expdm", 0xee7081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10178 {"expdz", 0xee7081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10179 {"expe", 0xee788100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10180 {"expep", 0xee788120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10181 {"expem", 0xee788140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10182 {"expdz", 0xee788160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10183
10184 {"sins", 0xee808100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10185 {"sinsp", 0xee808120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10186 {"sinsm", 0xee808140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10187 {"sinsz", 0xee808160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10188 {"sind", 0xee808180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10189 {"sindp", 0xee8081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10190 {"sindm", 0xee8081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10191 {"sindz", 0xee8081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10192 {"sine", 0xee888100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10193 {"sinep", 0xee888120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10194 {"sinem", 0xee888140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10195 {"sinez", 0xee888160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10196
10197 {"coss", 0xee908100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10198 {"cossp", 0xee908120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10199 {"cossm", 0xee908140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10200 {"cossz", 0xee908160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10201 {"cosd", 0xee908180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10202 {"cosdp", 0xee9081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10203 {"cosdm", 0xee9081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10204 {"cosdz", 0xee9081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10205 {"cose", 0xee988100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10206 {"cosep", 0xee988120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10207 {"cosem", 0xee988140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10208 {"cosez", 0xee988160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10209
10210 {"tans", 0xeea08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10211 {"tansp", 0xeea08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10212 {"tansm", 0xeea08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10213 {"tansz", 0xeea08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10214 {"tand", 0xeea08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10215 {"tandp", 0xeea081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10216 {"tandm", 0xeea081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10217 {"tandz", 0xeea081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10218 {"tane", 0xeea88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10219 {"tanep", 0xeea88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10220 {"tanem", 0xeea88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10221 {"tanez", 0xeea88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10222
10223 {"asns", 0xeeb08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10224 {"asnsp", 0xeeb08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10225 {"asnsm", 0xeeb08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10226 {"asnsz", 0xeeb08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10227 {"asnd", 0xeeb08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10228 {"asndp", 0xeeb081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10229 {"asndm", 0xeeb081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10230 {"asndz", 0xeeb081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10231 {"asne", 0xeeb88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10232 {"asnep", 0xeeb88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10233 {"asnem", 0xeeb88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10234 {"asnez", 0xeeb88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10235
10236 {"acss", 0xeec08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10237 {"acssp", 0xeec08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10238 {"acssm", 0xeec08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10239 {"acssz", 0xeec08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10240 {"acsd", 0xeec08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10241 {"acsdp", 0xeec081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10242 {"acsdm", 0xeec081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10243 {"acsdz", 0xeec081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10244 {"acse", 0xeec88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10245 {"acsep", 0xeec88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10246 {"acsem", 0xeec88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10247 {"acsez", 0xeec88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10248
10249 {"atns", 0xeed08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10250 {"atnsp", 0xeed08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10251 {"atnsm", 0xeed08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10252 {"atnsz", 0xeed08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10253 {"atnd", 0xeed08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10254 {"atndp", 0xeed081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10255 {"atndm", 0xeed081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10256 {"atndz", 0xeed081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10257 {"atne", 0xeed88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10258 {"atnep", 0xeed88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10259 {"atnem", 0xeed88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10260 {"atnez", 0xeed88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10261
10262 {"urds", 0xeee08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10263 {"urdsp", 0xeee08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10264 {"urdsm", 0xeee08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10265 {"urdsz", 0xeee08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10266 {"urdd", 0xeee08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10267 {"urddp", 0xeee081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10268 {"urddm", 0xeee081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10269 {"urddz", 0xeee081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10270 {"urde", 0xeee88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10271 {"urdep", 0xeee88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10272 {"urdem", 0xeee88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10273 {"urdez", 0xeee88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10274
10275 {"nrms", 0xeef08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10276 {"nrmsp", 0xeef08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10277 {"nrmsm", 0xeef08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10278 {"nrmsz", 0xeef08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10279 {"nrmd", 0xeef08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10280 {"nrmdp", 0xeef081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10281 {"nrmdm", 0xeef081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10282 {"nrmdz", 0xeef081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10283 {"nrme", 0xeef88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10284 {"nrmep", 0xeef88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10285 {"nrmem", 0xeef88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10286 {"nrmez", 0xeef88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10287
10288 {"adfs", 0xee000100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10289 {"adfsp", 0xee000120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10290 {"adfsm", 0xee000140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10291 {"adfsz", 0xee000160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10292 {"adfd", 0xee000180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10293 {"adfdp", 0xee0001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10294 {"adfdm", 0xee0001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10295 {"adfdz", 0xee0001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10296 {"adfe", 0xee080100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10297 {"adfep", 0xee080120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10298 {"adfem", 0xee080140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10299 {"adfez", 0xee080160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10300
10301 {"sufs", 0xee200100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10302 {"sufsp", 0xee200120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10303 {"sufsm", 0xee200140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10304 {"sufsz", 0xee200160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10305 {"sufd", 0xee200180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10306 {"sufdp", 0xee2001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10307 {"sufdm", 0xee2001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10308 {"sufdz", 0xee2001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10309 {"sufe", 0xee280100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10310 {"sufep", 0xee280120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10311 {"sufem", 0xee280140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10312 {"sufez", 0xee280160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10313
10314 {"rsfs", 0xee300100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10315 {"rsfsp", 0xee300120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10316 {"rsfsm", 0xee300140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10317 {"rsfsz", 0xee300160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10318 {"rsfd", 0xee300180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10319 {"rsfdp", 0xee3001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10320 {"rsfdm", 0xee3001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10321 {"rsfdz", 0xee3001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10322 {"rsfe", 0xee380100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10323 {"rsfep", 0xee380120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10324 {"rsfem", 0xee380140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10325 {"rsfez", 0xee380160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10326
10327 {"mufs", 0xee100100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10328 {"mufsp", 0xee100120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10329 {"mufsm", 0xee100140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10330 {"mufsz", 0xee100160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10331 {"mufd", 0xee100180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10332 {"mufdp", 0xee1001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10333 {"mufdm", 0xee1001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10334 {"mufdz", 0xee1001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10335 {"mufe", 0xee180100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10336 {"mufep", 0xee180120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10337 {"mufem", 0xee180140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10338 {"mufez", 0xee180160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10339
10340 {"dvfs", 0xee400100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10341 {"dvfsp", 0xee400120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10342 {"dvfsm", 0xee400140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10343 {"dvfsz", 0xee400160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10344 {"dvfd", 0xee400180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10345 {"dvfdp", 0xee4001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10346 {"dvfdm", 0xee4001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10347 {"dvfdz", 0xee4001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10348 {"dvfe", 0xee480100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10349 {"dvfep", 0xee480120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10350 {"dvfem", 0xee480140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10351 {"dvfez", 0xee480160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10352
10353 {"rdfs", 0xee500100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10354 {"rdfsp", 0xee500120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10355 {"rdfsm", 0xee500140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10356 {"rdfsz", 0xee500160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10357 {"rdfd", 0xee500180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10358 {"rdfdp", 0xee5001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10359 {"rdfdm", 0xee5001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10360 {"rdfdz", 0xee5001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10361 {"rdfe", 0xee580100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10362 {"rdfep", 0xee580120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10363 {"rdfem", 0xee580140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10364 {"rdfez", 0xee580160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10365
10366 {"pows", 0xee600100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10367 {"powsp", 0xee600120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10368 {"powsm", 0xee600140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10369 {"powsz", 0xee600160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10370 {"powd", 0xee600180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10371 {"powdp", 0xee6001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10372 {"powdm", 0xee6001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10373 {"powdz", 0xee6001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10374 {"powe", 0xee680100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10375 {"powep", 0xee680120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10376 {"powem", 0xee680140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10377 {"powez", 0xee680160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10378
10379 {"rpws", 0xee700100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10380 {"rpwsp", 0xee700120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10381 {"rpwsm", 0xee700140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10382 {"rpwsz", 0xee700160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10383 {"rpwd", 0xee700180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10384 {"rpwdp", 0xee7001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10385 {"rpwdm", 0xee7001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10386 {"rpwdz", 0xee7001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10387 {"rpwe", 0xee780100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10388 {"rpwep", 0xee780120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10389 {"rpwem", 0xee780140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10390 {"rpwez", 0xee780160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10391
10392 {"rmfs", 0xee800100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10393 {"rmfsp", 0xee800120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10394 {"rmfsm", 0xee800140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10395 {"rmfsz", 0xee800160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10396 {"rmfd", 0xee800180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10397 {"rmfdp", 0xee8001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10398 {"rmfdm", 0xee8001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10399 {"rmfdz", 0xee8001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10400 {"rmfe", 0xee880100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10401 {"rmfep", 0xee880120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10402 {"rmfem", 0xee880140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10403 {"rmfez", 0xee880160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10404
10405 {"fmls", 0xee900100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10406 {"fmlsp", 0xee900120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10407 {"fmlsm", 0xee900140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10408 {"fmlsz", 0xee900160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10409 {"fmld", 0xee900180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10410 {"fmldp", 0xee9001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10411 {"fmldm", 0xee9001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10412 {"fmldz", 0xee9001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10413 {"fmle", 0xee980100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10414 {"fmlep", 0xee980120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10415 {"fmlem", 0xee980140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10416 {"fmlez", 0xee980160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10417
10418 {"fdvs", 0xeea00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10419 {"fdvsp", 0xeea00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10420 {"fdvsm", 0xeea00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10421 {"fdvsz", 0xeea00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10422 {"fdvd", 0xeea00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10423 {"fdvdp", 0xeea001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10424 {"fdvdm", 0xeea001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10425 {"fdvdz", 0xeea001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10426 {"fdve", 0xeea80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10427 {"fdvep", 0xeea80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10428 {"fdvem", 0xeea80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10429 {"fdvez", 0xeea80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10430
10431 {"frds", 0xeeb00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10432 {"frdsp", 0xeeb00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10433 {"frdsm", 0xeeb00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10434 {"frdsz", 0xeeb00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10435 {"frdd", 0xeeb00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10436 {"frddp", 0xeeb001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10437 {"frddm", 0xeeb001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10438 {"frddz", 0xeeb001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10439 {"frde", 0xeeb80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10440 {"frdep", 0xeeb80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10441 {"frdem", 0xeeb80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10442 {"frdez", 0xeeb80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10443
10444 {"pols", 0xeec00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10445 {"polsp", 0xeec00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10446 {"polsm", 0xeec00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10447 {"polsz", 0xeec00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10448 {"pold", 0xeec00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10449 {"poldp", 0xeec001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10450 {"poldm", 0xeec001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10451 {"poldz", 0xeec001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10452 {"pole", 0xeec80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10453 {"polep", 0xeec80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10454 {"polem", 0xeec80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10455 {"polez", 0xeec80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10456
10457 {"cmf", 0xee90f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
10458 {"cmfe", 0xeed0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
10459 {"cnf", 0xeeb0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
10460 {"cnfe", 0xeef0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
10461 /* The FPA10 data sheet suggests that the 'E' of cmfe/cnfe should
10462 not be an optional suffix, but part of the instruction. To be
10463 compatible, we accept either. */
10464 {"cmfe", 0xeed0f110, 4, FPU_FPA_EXT_V1, do_fpa_cmp},
10465 {"cnfe", 0xeef0f110, 4, FPU_FPA_EXT_V1, do_fpa_cmp},
10466
10467 {"flts", 0xee000110, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10468 {"fltsp", 0xee000130, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10469 {"fltsm", 0xee000150, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10470 {"fltsz", 0xee000170, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10471 {"fltd", 0xee000190, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10472 {"fltdp", 0xee0001b0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10473 {"fltdm", 0xee0001d0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10474 {"fltdz", 0xee0001f0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10475 {"flte", 0xee080110, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10476 {"fltep", 0xee080130, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10477 {"fltem", 0xee080150, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10478 {"fltez", 0xee080170, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10479
10480 /* The implementation of the FIX instruction is broken on some
10481 assemblers, in that it accepts a precision specifier as well as a
10482 rounding specifier, despite the fact that this is meaningless.
10483 To be more compatible, we accept it as well, though of course it
10484 does not set any bits. */
10485 {"fix", 0xee100110, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10486 {"fixp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10487 {"fixm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10488 {"fixz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10489 {"fixsp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10490 {"fixsm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10491 {"fixsz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10492 {"fixdp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10493 {"fixdm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10494 {"fixdz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10495 {"fixep", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10496 {"fixem", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10497 {"fixez", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10498
10499 /* Instructions that were new with the real FPA, call them V2. */
10500 {"lfm", 0xec100200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10501 {"lfmfd", 0xec900200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10502 {"lfmea", 0xed100200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10503 {"sfm", 0xec000200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10504 {"sfmfd", 0xed000200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10505 {"sfmea", 0xec800200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10506
10507 /* VFP V1xD (single precision). */
10508 /* Moves and type conversions. */
10509 {"fcpys", 0xeeb00a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10510 {"fmrs", 0xee100a10, 4, FPU_VFP_EXT_V1xD, do_vfp_reg_from_sp},
10511 {"fmsr", 0xee000a10, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_from_reg},
10512 {"fmstat", 0xeef1fa10, 6, FPU_VFP_EXT_V1xD, do_empty},
10513 {"fsitos", 0xeeb80ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10514 {"fuitos", 0xeeb80a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10515 {"ftosis", 0xeebd0a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10516 {"ftosizs", 0xeebd0ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10517 {"ftouis", 0xeebc0a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10518 {"ftouizs", 0xeebc0ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10519 {"fmrx", 0xeef00a10, 4, FPU_VFP_EXT_V1xD, do_vfp_reg_from_ctrl},
10520 {"fmxr", 0xeee00a10, 4, FPU_VFP_EXT_V1xD, do_vfp_ctrl_from_reg},
10521
10522 /* Memory operations. */
10523 {"flds", 0xed100a00, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_ldst},
10524 {"fsts", 0xed000a00, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_ldst},
10525 {"fldmias", 0xec900a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
10526 {"fldmfds", 0xec900a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
10527 {"fldmdbs", 0xed300a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
10528 {"fldmeas", 0xed300a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
10529 {"fldmiax", 0xec900b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
10530 {"fldmfdx", 0xec900b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
10531 {"fldmdbx", 0xed300b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
10532 {"fldmeax", 0xed300b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
10533 {"fstmias", 0xec800a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
10534 {"fstmeas", 0xec800a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
10535 {"fstmdbs", 0xed200a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
10536 {"fstmfds", 0xed200a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
10537 {"fstmiax", 0xec800b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
10538 {"fstmeax", 0xec800b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
10539 {"fstmdbx", 0xed200b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
10540 {"fstmfdx", 0xed200b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
10541
10542 /* Monadic operations. */
10543 {"fabss", 0xeeb00ac0, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10544 {"fnegs", 0xeeb10a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10545 {"fsqrts", 0xeeb10ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10546
10547 /* Dyadic operations. */
10548 {"fadds", 0xee300a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10549 {"fsubs", 0xee300a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10550 {"fmuls", 0xee200a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10551 {"fdivs", 0xee800a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10552 {"fmacs", 0xee000a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10553 {"fmscs", 0xee100a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10554 {"fnmuls", 0xee200a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10555 {"fnmacs", 0xee000a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10556 {"fnmscs", 0xee100a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10557
10558 /* Comparisons. */
10559 {"fcmps", 0xeeb40a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10560 {"fcmpzs", 0xeeb50a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_compare_z},
10561 {"fcmpes", 0xeeb40ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10562 {"fcmpezs", 0xeeb50ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_compare_z},
10563
10564 /* VFP V1 (Double precision). */
10565 /* Moves and type conversions. */
10566 {"fcpyd", 0xeeb00b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10567 {"fcvtds", 0xeeb70ac0, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
10568 {"fcvtsd", 0xeeb70bc0, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
10569 {"fmdhr", 0xee200b10, 5, FPU_VFP_EXT_V1, do_vfp_dp_from_reg},
10570 {"fmdlr", 0xee000b10, 5, FPU_VFP_EXT_V1, do_vfp_dp_from_reg},
10571 {"fmrdh", 0xee300b10, 5, FPU_VFP_EXT_V1, do_vfp_reg_from_dp},
10572 {"fmrdl", 0xee100b10, 5, FPU_VFP_EXT_V1, do_vfp_reg_from_dp},
10573 {"fsitod", 0xeeb80bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
10574 {"fuitod", 0xeeb80b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
10575 {"ftosid", 0xeebd0b40, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
10576 {"ftosizd", 0xeebd0bc0, 7, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
10577 {"ftouid", 0xeebc0b40, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
10578 {"ftouizd", 0xeebc0bc0, 7, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
10579
10580 /* Memory operations. */
10581 {"fldd", 0xed100b00, 4, FPU_VFP_EXT_V1, do_vfp_dp_ldst},
10582 {"fstd", 0xed000b00, 4, FPU_VFP_EXT_V1, do_vfp_dp_ldst},
10583 {"fldmiad", 0xec900b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
10584 {"fldmfdd", 0xec900b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
10585 {"fldmdbd", 0xed300b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
10586 {"fldmead", 0xed300b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
10587 {"fstmiad", 0xec800b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
10588 {"fstmead", 0xec800b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
10589 {"fstmdbd", 0xed200b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
10590 {"fstmfdd", 0xed200b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
10591
10592 /* Monadic operations. */
10593 {"fabsd", 0xeeb00bc0, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10594 {"fnegd", 0xeeb10b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10595 {"fsqrtd", 0xeeb10bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10596
10597 /* Dyadic operations. */
10598 {"faddd", 0xee300b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10599 {"fsubd", 0xee300b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10600 {"fmuld", 0xee200b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10601 {"fdivd", 0xee800b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10602 {"fmacd", 0xee000b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10603 {"fmscd", 0xee100b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10604 {"fnmuld", 0xee200b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10605 {"fnmacd", 0xee000b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10606 {"fnmscd", 0xee100b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10607
10608 /* Comparisons. */
10609 {"fcmpd", 0xeeb40b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10610 {"fcmpzd", 0xeeb50b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_compare_z},
10611 {"fcmped", 0xeeb40bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10612 {"fcmpezd", 0xeeb50bc0, 7, FPU_VFP_EXT_V1, do_vfp_dp_compare_z},
10613
10614 /* VFP V2. */
10615 {"fmsrr", 0xec400a10, 5, FPU_VFP_EXT_V2, do_vfp_sp2_from_reg2},
10616 {"fmrrs", 0xec500a10, 5, FPU_VFP_EXT_V2, do_vfp_reg2_from_sp2},
10617 {"fmdrr", 0xec400b10, 5, FPU_VFP_EXT_V2, do_vfp_dp_from_reg2},
10618 {"fmrrd", 0xec500b10, 5, FPU_VFP_EXT_V2, do_vfp_reg2_from_dp},
10619
10620 /* Intel XScale extensions to ARM V5 ISA. (All use CP0). */
10621 {"mia", 0xee200010, 3, ARM_CEXT_XSCALE, do_xsc_mia},
10622 {"miaph", 0xee280010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
10623 {"miabb", 0xee2c0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
10624 {"miabt", 0xee2d0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
10625 {"miatb", 0xee2e0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
10626 {"miatt", 0xee2f0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
10627 {"mar", 0xec400000, 3, ARM_CEXT_XSCALE, do_xsc_mar},
10628 {"mra", 0xec500000, 3, ARM_CEXT_XSCALE, do_xsc_mra},
10629
10630 /* Intel Wireless MMX technology instructions. */
10631 {"tandcb", 0xee130130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
10632 {"tandch", 0xee530130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
10633 {"tandcw", 0xee930130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
10634 {"tbcstb", 0xee400010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
10635 {"tbcsth", 0xee400050, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
10636 {"tbcstw", 0xee400090, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
10637 {"textrcb", 0xee130170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
10638 {"textrch", 0xee530170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
10639 {"textrcw", 0xee930170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
10640 {"textrmub", 0xee100070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10641 {"textrmuh", 0xee500070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10642 {"textrmuw", 0xee900070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10643 {"textrmsb", 0xee100078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10644 {"textrmsh", 0xee500078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10645 {"textrmsw", 0xee900078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10646 {"tinsrb", 0xee600010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
10647 {"tinsrh", 0xee600050, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
10648 {"tinsrw", 0xee600090, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
10649 {"tmcr", 0xee000110, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmcr},
10650 {"tmcrr", 0xec400000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_tmcrr},
10651 {"tmia", 0xee200010, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10652 {"tmiaph", 0xee280010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10653 {"tmiabb", 0xee2c0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10654 {"tmiabt", 0xee2d0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10655 {"tmiatb", 0xee2e0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10656 {"tmiatt", 0xee2f0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10657 {"tmovmskb", 0xee100030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
10658 {"tmovmskh", 0xee500030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
10659 {"tmovmskw", 0xee900030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
10660 {"tmrc", 0xee100110, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmrc},
10661 {"tmrrc", 0xec500000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_tmrrc},
10662 {"torcb", 0xee130150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
10663 {"torch", 0xee530150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
10664 {"torcw", 0xee930150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
10665 {"waccb", 0xee0001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10666 {"wacch", 0xee4001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10667 {"waccw", 0xee8001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10668 {"waddbss", 0xee300180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10669 {"waddb", 0xee000180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10670 {"waddbus", 0xee100180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10671 {"waddhss", 0xee700180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10672 {"waddh", 0xee400180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10673 {"waddhus", 0xee500180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10674 {"waddwss", 0xeeb00180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10675 {"waddw", 0xee800180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10676 {"waddwus", 0xee900180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10677 {"waligni", 0xee000020, 7, ARM_CEXT_IWMMXT, do_iwmmxt_waligni},
10678 {"walignr0", 0xee800020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10679 {"walignr1", 0xee900020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10680 {"walignr2", 0xeea00020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10681 {"walignr3", 0xeeb00020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10682 {"wand", 0xee200000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10683 {"wandn", 0xee300000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10684 {"wavg2b", 0xee800000, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10685 {"wavg2br", 0xee900000, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10686 {"wavg2h", 0xeec00000, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10687 {"wavg2hr", 0xeed00000, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10688 {"wcmpeqb", 0xee000060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10689 {"wcmpeqh", 0xee400060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10690 {"wcmpeqw", 0xee800060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10691 {"wcmpgtub", 0xee100060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10692 {"wcmpgtuh", 0xee500060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10693 {"wcmpgtuw", 0xee900060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10694 {"wcmpgtsb", 0xee300060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10695 {"wcmpgtsh", 0xee700060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10696 {"wcmpgtsw", 0xeeb00060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10697 {"wldrb", 0xec100000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
10698 {"wldrh", 0xec100100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
10699 {"wldrw", 0xec100200, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
10700 {"wldrd", 0xec100300, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
10701 {"wmacs", 0xee600100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10702 {"wmacsz", 0xee700100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10703 {"wmacu", 0xee400100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10704 {"wmacuz", 0xee500100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10705 {"wmadds", 0xeea00100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10706 {"wmaddu", 0xee800100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10707 {"wmaxsb", 0xee200160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10708 {"wmaxsh", 0xee600160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10709 {"wmaxsw", 0xeea00160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10710 {"wmaxub", 0xee000160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10711 {"wmaxuh", 0xee400160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10712 {"wmaxuw", 0xee800160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10713 {"wminsb", 0xee300160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10714 {"wminsh", 0xee700160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10715 {"wminsw", 0xeeb00160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10716 {"wminub", 0xee100160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10717 {"wminuh", 0xee500160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10718 {"wminuw", 0xee900160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10719 {"wmov", 0xee000000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wmov},
10720 {"wmulsm", 0xee300100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10721 {"wmulsl", 0xee200100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10722 {"wmulum", 0xee100100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10723 {"wmulul", 0xee000100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10724 {"wor", 0xee000000, 3, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10725 {"wpackhss", 0xee700080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10726 {"wpackhus", 0xee500080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10727 {"wpackwss", 0xeeb00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10728 {"wpackwus", 0xee900080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10729 {"wpackdss", 0xeef00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10730 {"wpackdus", 0xeed00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10731 {"wrorh", 0xee700040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10732 {"wrorhg", 0xee700148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
10733 {"wrorw", 0xeeb00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10734 {"wrorwg", 0xeeb00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
10735 {"wrord", 0xeef00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10736 {"wrordg", 0xeef00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
10737 {"wsadb", 0xee000120, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10738 {"wsadbz", 0xee100120, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10739 {"wsadh", 0xee400120, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10740 {"wsadhz", 0xee500120, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10741 {"wshufh", 0xee0001e0, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wshufh},
10742 {"wsllh", 0xee500040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10743 {"wsllhg", 0xee500148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
10744 {"wsllw", 0xee900040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10745 {"wsllwg", 0xee900148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
10746 {"wslld", 0xeed00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10747 {"wslldg", 0xeed00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
10748 {"wsrah", 0xee400040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10749 {"wsrahg", 0xee400148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
10750 {"wsraw", 0xee800040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10751 {"wsrawg", 0xee800148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
10752 {"wsrad", 0xeec00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10753 {"wsradg", 0xeec00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
10754 {"wsrlh", 0xee600040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10755 {"wsrlhg", 0xee600148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
10756 {"wsrlw", 0xeea00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10757 {"wsrlwg", 0xeea00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
10758 {"wsrld", 0xeee00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10759 {"wsrldg", 0xeee00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
10760 {"wstrb", 0xec000000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
10761 {"wstrh", 0xec000100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
10762 {"wstrw", 0xec000200, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
10763 {"wstrd", 0xec000300, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
10764 {"wsubbss", 0xee3001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10765 {"wsubb", 0xee0001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10766 {"wsubbus", 0xee1001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10767 {"wsubhss", 0xee7001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10768 {"wsubh", 0xee4001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10769 {"wsubhus", 0xee5001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10770 {"wsubwss", 0xeeb001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10771 {"wsubw", 0xee8001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10772 {"wsubwus", 0xee9001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10773 {"wunpckehub", 0xee0000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10774 {"wunpckehuh", 0xee4000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10775 {"wunpckehuw", 0xee8000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10776 {"wunpckehsb", 0xee2000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10777 {"wunpckehsh", 0xee6000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10778 {"wunpckehsw", 0xeea000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10779 {"wunpckihb", 0xee1000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10780 {"wunpckihh", 0xee5000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10781 {"wunpckihw", 0xee9000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10782 {"wunpckelub", 0xee0000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10783 {"wunpckeluh", 0xee4000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10784 {"wunpckeluw", 0xee8000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10785 {"wunpckelsb", 0xee2000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10786 {"wunpckelsh", 0xee6000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10787 {"wunpckelsw", 0xeea000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10788 {"wunpckilb", 0xee1000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10789 {"wunpckilh", 0xee5000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10790 {"wunpckilw", 0xee9000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10791 {"wxor", 0xee100000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10792 {"wzero", 0xee300000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wzero},
10793
10794 /* Cirrus Maverick instructions. */
10795 {"cfldrs", 0xec100400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_1},
10796 {"cfldrd", 0xec500400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_2},
10797 {"cfldr32", 0xec100500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_3},
10798 {"cfldr64", 0xec500500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_4},
10799 {"cfstrs", 0xec000400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_1},
10800 {"cfstrd", 0xec400400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_2},
10801 {"cfstr32", 0xec000500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_3},
10802 {"cfstr64", 0xec400500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_4},
10803 {"cfmvsr", 0xee000450, 6, ARM_CEXT_MAVERICK, do_mav_binops_2a},
10804 {"cfmvrs", 0xee100450, 6, ARM_CEXT_MAVERICK, do_mav_binops_1a},
10805 {"cfmvdlr", 0xee000410, 7, ARM_CEXT_MAVERICK, do_mav_binops_2b},
10806 {"cfmvrdl", 0xee100410, 7, ARM_CEXT_MAVERICK, do_mav_binops_1b},
10807 {"cfmvdhr", 0xee000430, 7, ARM_CEXT_MAVERICK, do_mav_binops_2b},
10808 {"cfmvrdh", 0xee100430, 7, ARM_CEXT_MAVERICK, do_mav_binops_1b},
10809 {"cfmv64lr", 0xee000510, 8, ARM_CEXT_MAVERICK, do_mav_binops_2c},
10810 {"cfmvr64l", 0xee100510, 8, ARM_CEXT_MAVERICK, do_mav_binops_1c},
10811 {"cfmv64hr", 0xee000530, 8, ARM_CEXT_MAVERICK, do_mav_binops_2c},
10812 {"cfmvr64h", 0xee100530, 8, ARM_CEXT_MAVERICK, do_mav_binops_1c},
10813 {"cfmval32", 0xee200440, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
10814 {"cfmv32al", 0xee100440, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
10815 {"cfmvam32", 0xee200460, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
10816 {"cfmv32am", 0xee100460, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
10817 {"cfmvah32", 0xee200480, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
10818 {"cfmv32ah", 0xee100480, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
10819 {"cfmva32", 0xee2004a0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3a},
10820 {"cfmv32a", 0xee1004a0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3b},
10821 {"cfmva64", 0xee2004c0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3c},
10822 {"cfmv64a", 0xee1004c0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3d},
10823 {"cfmvsc32", 0xee2004e0, 8, ARM_CEXT_MAVERICK, do_mav_dspsc_1},
10824 {"cfmv32sc", 0xee1004e0, 8, ARM_CEXT_MAVERICK, do_mav_dspsc_2},
10825 {"cfcpys", 0xee000400, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
10826 {"cfcpyd", 0xee000420, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
10827 {"cfcvtsd", 0xee000460, 7, ARM_CEXT_MAVERICK, do_mav_binops_1f},
10828 {"cfcvtds", 0xee000440, 7, ARM_CEXT_MAVERICK, do_mav_binops_1g},
10829 {"cfcvt32s", 0xee000480, 8, ARM_CEXT_MAVERICK, do_mav_binops_1h},
10830 {"cfcvt32d", 0xee0004a0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1i},
10831 {"cfcvt64s", 0xee0004c0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1j},
10832 {"cfcvt64d", 0xee0004e0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1k},
10833 {"cfcvts32", 0xee100580, 8, ARM_CEXT_MAVERICK, do_mav_binops_1l},
10834 {"cfcvtd32", 0xee1005a0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1m},
10835 {"cftruncs32", 0xee1005c0, 10, ARM_CEXT_MAVERICK, do_mav_binops_1l},
10836 {"cftruncd32", 0xee1005e0, 10, ARM_CEXT_MAVERICK, do_mav_binops_1m},
10837 {"cfrshl32", 0xee000550, 8, ARM_CEXT_MAVERICK, do_mav_triple_4a},
10838 {"cfrshl64", 0xee000570, 8, ARM_CEXT_MAVERICK, do_mav_triple_4b},
10839 {"cfsh32", 0xee000500, 6, ARM_CEXT_MAVERICK, do_mav_shift_1},
10840 {"cfsh64", 0xee200500, 6, ARM_CEXT_MAVERICK, do_mav_shift_2},
10841 {"cfcmps", 0xee100490, 6, ARM_CEXT_MAVERICK, do_mav_triple_5a},
10842 {"cfcmpd", 0xee1004b0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5b},
10843 {"cfcmp32", 0xee100590, 7, ARM_CEXT_MAVERICK, do_mav_triple_5c},
10844 {"cfcmp64", 0xee1005b0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5d},
10845 {"cfabss", 0xee300400, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
10846 {"cfabsd", 0xee300420, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
10847 {"cfnegs", 0xee300440, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
10848 {"cfnegd", 0xee300460, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
10849 {"cfadds", 0xee300480, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
10850 {"cfaddd", 0xee3004a0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
10851 {"cfsubs", 0xee3004c0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
10852 {"cfsubd", 0xee3004e0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
10853 {"cfmuls", 0xee100400, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
10854 {"cfmuld", 0xee100420, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
10855 {"cfabs32", 0xee300500, 7, ARM_CEXT_MAVERICK, do_mav_binops_1n},
10856 {"cfabs64", 0xee300520, 7, ARM_CEXT_MAVERICK, do_mav_binops_1o},
10857 {"cfneg32", 0xee300540, 7, ARM_CEXT_MAVERICK, do_mav_binops_1n},
10858 {"cfneg64", 0xee300560, 7, ARM_CEXT_MAVERICK, do_mav_binops_1o},
10859 {"cfadd32", 0xee300580, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
10860 {"cfadd64", 0xee3005a0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
10861 {"cfsub32", 0xee3005c0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
10862 {"cfsub64", 0xee3005e0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
10863 {"cfmul32", 0xee100500, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
10864 {"cfmul64", 0xee100520, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
10865 {"cfmac32", 0xee100540, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
10866 {"cfmsc32", 0xee100560, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
10867 {"cfmadd32", 0xee000600, 8, ARM_CEXT_MAVERICK, do_mav_quad_6a},
10868 {"cfmsub32", 0xee100600, 8, ARM_CEXT_MAVERICK, do_mav_quad_6a},
10869 {"cfmadda32", 0xee200600, 9, ARM_CEXT_MAVERICK, do_mav_quad_6b},
10870 {"cfmsuba32", 0xee300600, 9, ARM_CEXT_MAVERICK, do_mav_quad_6b},
10871 };
10872
10873 /* Iterate over the base tables to create the instruction patterns. */
10874
10875 static void
10876 build_arm_ops_hsh (void)
10877 {
10878 unsigned int i;
10879 unsigned int j;
10880 static struct obstack insn_obstack;
10881
10882 obstack_begin (&insn_obstack, 4000);
10883
10884 for (i = 0; i < sizeof (insns) / sizeof (struct asm_opcode); i++)
10885 {
10886 const struct asm_opcode *insn = insns + i;
10887
10888 if (insn->cond_offset != 0)
10889 {
10890 /* Insn supports conditional execution. Build the varaints
10891 and insert them in the hash table. */
10892 for (j = 0; j < sizeof (conds) / sizeof (struct asm_cond); j++)
10893 {
10894 unsigned len = strlen (insn->template);
10895 struct asm_opcode *new;
10896 char *template;
10897
10898 new = obstack_alloc (&insn_obstack, sizeof (struct asm_opcode));
10899 /* All condition codes are two characters. */
10900 template = obstack_alloc (&insn_obstack, len + 3);
10901
10902 strncpy (template, insn->template, insn->cond_offset);
10903 strcpy (template + insn->cond_offset, conds[j].template);
10904 if (len > insn->cond_offset)
10905 strcpy (template + insn->cond_offset + 2,
10906 insn->template + insn->cond_offset);
10907 new->template = template;
10908 new->cond_offset = 0;
10909 new->variant = insn->variant;
10910 new->parms = insn->parms;
10911 new->value = (insn->value & ~COND_MASK) | conds[j].value;
10912
10913 hash_insert (arm_ops_hsh, new->template, (PTR) new);
10914 }
10915 }
10916 /* Finally, insert the unconditional insn in the table directly;
10917 no need to build a copy. */
10918 hash_insert (arm_ops_hsh, insn->template, (PTR) insn);
10919 }
10920 }
10921
10922 #if 0 /* Suppressed - for now. */
10923 #if defined OBJ_ELF || defined OBJ_COFF
10924
10925 #ifdef OBJ_ELF
10926 #define arm_Note Elf_External_Note
10927 #else
10928 typedef struct
10929 {
10930 unsigned char namesz[4]; /* Size of entry's owner string. */
10931 unsigned char descsz[4]; /* Size of the note descriptor. */
10932 unsigned char type[4]; /* Interpretation of the descriptor. */
10933 char name[1]; /* Start of the name+desc data. */
10934 } arm_Note;
10935 #endif
10936
10937 /* The description is kept to a fix sized in order to make updating
10938 it and merging it easier. */
10939 #define ARM_NOTE_DESCRIPTION_LENGTH 8
10940
10941 static void
10942 arm_add_note (const char * name,
10943 const char * description,
10944 unsigned int type)
10945 {
10946 arm_Note note ATTRIBUTE_UNUSED;
10947 char * p;
10948 unsigned int name_len;
10949
10950 name_len = (strlen (name) + 1 + 3) & ~3;
10951
10952 p = frag_more (sizeof (note.namesz));
10953 md_number_to_chars (p, (valueT) name_len, sizeof (note.namesz));
10954
10955 p = frag_more (sizeof (note.descsz));
10956 md_number_to_chars (p, (valueT) ARM_NOTE_DESCRIPTION_LENGTH, sizeof (note.descsz));
10957
10958 p = frag_more (sizeof (note.type));
10959 md_number_to_chars (p, (valueT) type, sizeof (note.type));
10960
10961 p = frag_more (name_len);
10962 strcpy (p, name);
10963
10964 p = frag_more (ARM_NOTE_DESCRIPTION_LENGTH);
10965 strncpy (p, description, ARM_NOTE_DESCRIPTION_LENGTH);
10966 frag_align (2, 0, 0);
10967 }
10968 #endif
10969 #endif
10970
10971 \f
10972 static const struct thumb_opcode tinsns[] =
10973 {
10974 /* Thumb v1 (ARMv4T). */
10975 {"adc", 0x4140, 2, ARM_EXT_V4T, do_t_arit},
10976 {"add", 0x0000, 2, ARM_EXT_V4T, do_t_add},
10977 {"and", 0x4000, 2, ARM_EXT_V4T, do_t_arit},
10978 {"asr", 0x0000, 2, ARM_EXT_V4T, do_t_asr},
10979 {"b", T_OPCODE_BRANCH, 2, ARM_EXT_V4T, do_t_branch12},
10980 {"beq", 0xd0fe, 2, ARM_EXT_V4T, do_t_branch9},
10981 {"bne", 0xd1fe, 2, ARM_EXT_V4T, do_t_branch9},
10982 {"bcs", 0xd2fe, 2, ARM_EXT_V4T, do_t_branch9},
10983 {"bhs", 0xd2fe, 2, ARM_EXT_V4T, do_t_branch9},
10984 {"bcc", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
10985 {"bul", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
10986 {"blo", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
10987 {"bmi", 0xd4fe, 2, ARM_EXT_V4T, do_t_branch9},
10988 {"bpl", 0xd5fe, 2, ARM_EXT_V4T, do_t_branch9},
10989 {"bvs", 0xd6fe, 2, ARM_EXT_V4T, do_t_branch9},
10990 {"bvc", 0xd7fe, 2, ARM_EXT_V4T, do_t_branch9},
10991 {"bhi", 0xd8fe, 2, ARM_EXT_V4T, do_t_branch9},
10992 {"bls", 0xd9fe, 2, ARM_EXT_V4T, do_t_branch9},
10993 {"bge", 0xdafe, 2, ARM_EXT_V4T, do_t_branch9},
10994 {"blt", 0xdbfe, 2, ARM_EXT_V4T, do_t_branch9},
10995 {"bgt", 0xdcfe, 2, ARM_EXT_V4T, do_t_branch9},
10996 {"ble", 0xddfe, 2, ARM_EXT_V4T, do_t_branch9},
10997 {"bal", 0xdefe, 2, ARM_EXT_V4T, do_t_branch9},
10998 {"bic", 0x4380, 2, ARM_EXT_V4T, do_t_arit},
10999 {"bl", 0xf7fffffe, 4, ARM_EXT_V4T, do_t_branch23},
11000 {"bx", 0x4700, 2, ARM_EXT_V4T, do_t_bx},
11001 {"cmn", T_OPCODE_CMN, 2, ARM_EXT_V4T, do_t_arit},
11002 {"cmp", 0x0000, 2, ARM_EXT_V4T, do_t_compare},
11003 {"eor", 0x4040, 2, ARM_EXT_V4T, do_t_arit},
11004 {"ldmia", 0xc800, 2, ARM_EXT_V4T, do_t_ldmstm},
11005 {"ldr", 0x0000, 2, ARM_EXT_V4T, do_t_ldr},
11006 {"ldrb", 0x0000, 2, ARM_EXT_V4T, do_t_ldrb},
11007 {"ldrh", 0x0000, 2, ARM_EXT_V4T, do_t_ldrh},
11008 {"ldrsb", 0x5600, 2, ARM_EXT_V4T, do_t_lds},
11009 {"ldrsh", 0x5e00, 2, ARM_EXT_V4T, do_t_lds},
11010 {"ldsb", 0x5600, 2, ARM_EXT_V4T, do_t_lds},
11011 {"ldsh", 0x5e00, 2, ARM_EXT_V4T, do_t_lds},
11012 {"lsl", 0x0000, 2, ARM_EXT_V4T, do_t_lsl},
11013 {"lsr", 0x0000, 2, ARM_EXT_V4T, do_t_lsr},
11014 {"mov", 0x0000, 2, ARM_EXT_V4T, do_t_mov},
11015 {"mul", T_OPCODE_MUL, 2, ARM_EXT_V4T, do_t_arit},
11016 {"mvn", T_OPCODE_MVN, 2, ARM_EXT_V4T, do_t_arit},
11017 {"neg", T_OPCODE_NEG, 2, ARM_EXT_V4T, do_t_arit},
11018 {"orr", 0x4300, 2, ARM_EXT_V4T, do_t_arit},
11019 {"pop", 0xbc00, 2, ARM_EXT_V4T, do_t_push_pop},
11020 {"push", 0xb400, 2, ARM_EXT_V4T, do_t_push_pop},
11021 {"ror", 0x41c0, 2, ARM_EXT_V4T, do_t_arit},
11022 {"sbc", 0x4180, 2, ARM_EXT_V4T, do_t_arit},
11023 {"stmia", 0xc000, 2, ARM_EXT_V4T, do_t_ldmstm},
11024 {"str", 0x0000, 2, ARM_EXT_V4T, do_t_str},
11025 {"strb", 0x0000, 2, ARM_EXT_V4T, do_t_strb},
11026 {"strh", 0x0000, 2, ARM_EXT_V4T, do_t_strh},
11027 {"swi", 0xdf00, 2, ARM_EXT_V4T, do_t_swi},
11028 {"sub", 0x0000, 2, ARM_EXT_V4T, do_t_sub},
11029 {"tst", T_OPCODE_TST, 2, ARM_EXT_V4T, do_t_arit},
11030 /* Pseudo ops: */
11031 {"adr", 0x0000, 2, ARM_EXT_V4T, do_t_adr},
11032 {"nop", 0x46C0, 2, ARM_EXT_V4T, do_t_nop}, /* mov r8,r8 */
11033 /* Thumb v2 (ARMv5T). */
11034 {"blx", 0, 0, ARM_EXT_V5T, do_t_blx},
11035 {"bkpt", 0xbe00, 2, ARM_EXT_V5T, do_t_bkpt},
11036
11037 /* ARM V6. */
11038 {"cpsie", 0xb660, 2, ARM_EXT_V6, do_t_cps},
11039 {"cpsid", 0xb670, 2, ARM_EXT_V6, do_t_cps},
11040 {"cpy", 0x4600, 2, ARM_EXT_V6, do_t_cpy},
11041 {"rev", 0xba00, 2, ARM_EXT_V6, do_t_arit},
11042 {"rev16", 0xba40, 2, ARM_EXT_V6, do_t_arit},
11043 {"revsh", 0xbac0, 2, ARM_EXT_V6, do_t_arit},
11044 {"setend", 0xb650, 2, ARM_EXT_V6, do_t_setend},
11045 {"sxth", 0xb200, 2, ARM_EXT_V6, do_t_arit},
11046 {"sxtb", 0xb240, 2, ARM_EXT_V6, do_t_arit},
11047 {"uxth", 0xb280, 2, ARM_EXT_V6, do_t_arit},
11048 {"uxtb", 0xb2c0, 2, ARM_EXT_V6, do_t_arit},
11049 };
11050
11051 void
11052 md_begin (void)
11053 {
11054 unsigned mach;
11055 unsigned int i;
11056
11057 if ( (arm_ops_hsh = hash_new ()) == NULL
11058 || (arm_tops_hsh = hash_new ()) == NULL
11059 || (arm_cond_hsh = hash_new ()) == NULL
11060 || (arm_shift_hsh = hash_new ()) == NULL
11061 || (arm_psr_hsh = hash_new ()) == NULL)
11062 as_fatal (_("virtual memory exhausted"));
11063
11064 build_arm_ops_hsh ();
11065 for (i = 0; i < sizeof (tinsns) / sizeof (struct thumb_opcode); i++)
11066 hash_insert (arm_tops_hsh, tinsns[i].template, (PTR) (tinsns + i));
11067 for (i = 0; i < sizeof (conds) / sizeof (struct asm_cond); i++)
11068 hash_insert (arm_cond_hsh, conds[i].template, (PTR) (conds + i));
11069 for (i = 0; i < sizeof (shift_names) / sizeof (struct asm_shift_name); i++)
11070 hash_insert (arm_shift_hsh, shift_names[i].name, (PTR) (shift_names + i));
11071 for (i = 0; i < sizeof (psrs) / sizeof (struct asm_psr); i++)
11072 hash_insert (arm_psr_hsh, psrs[i].template, (PTR) (psrs + i));
11073
11074 for (i = (int) REG_TYPE_FIRST; i < (int) REG_TYPE_MAX; i++)
11075 build_reg_hsh (all_reg_maps + i);
11076
11077 set_constant_flonums ();
11078
11079 /* Set the cpu variant based on the command-line options. We prefer
11080 -mcpu= over -march= if both are set (as for GCC); and we prefer
11081 -mfpu= over any other way of setting the floating point unit.
11082 Use of legacy options with new options are faulted. */
11083 if (legacy_cpu != -1)
11084 {
11085 if (mcpu_cpu_opt != -1 || march_cpu_opt != -1)
11086 as_bad (_("use of old and new-style options to set CPU type"));
11087
11088 mcpu_cpu_opt = legacy_cpu;
11089 }
11090 else if (mcpu_cpu_opt == -1)
11091 mcpu_cpu_opt = march_cpu_opt;
11092
11093 if (legacy_fpu != -1)
11094 {
11095 if (mfpu_opt != -1)
11096 as_bad (_("use of old and new-style options to set FPU type"));
11097
11098 mfpu_opt = legacy_fpu;
11099 }
11100 else if (mfpu_opt == -1)
11101 {
11102 #if !(defined (TE_LINUX) || defined (TE_NetBSD))
11103 /* Some environments specify a default FPU. If they don't, infer it
11104 from the processor. */
11105 if (mcpu_fpu_opt != -1)
11106 mfpu_opt = mcpu_fpu_opt;
11107 else
11108 mfpu_opt = march_fpu_opt;
11109 #else
11110 mfpu_opt = FPU_DEFAULT;
11111 #endif
11112 }
11113
11114 if (mfpu_opt == -1)
11115 {
11116 if (mcpu_cpu_opt == -1)
11117 mfpu_opt = FPU_DEFAULT;
11118 else if (mcpu_cpu_opt & ARM_EXT_V5)
11119 mfpu_opt = FPU_ARCH_VFP_V2;
11120 else
11121 mfpu_opt = FPU_ARCH_FPA;
11122 }
11123
11124 if (mcpu_cpu_opt == -1)
11125 mcpu_cpu_opt = CPU_DEFAULT;
11126
11127 cpu_variant = mcpu_cpu_opt | mfpu_opt;
11128
11129 {
11130 unsigned int flags = 0;
11131
11132 #if defined OBJ_ELF
11133 flags = meabi_flags;
11134
11135 switch (meabi_flags)
11136 {
11137 case EF_ARM_EABI_UNKNOWN:
11138 #endif
11139 #if defined OBJ_COFF || defined OBJ_ELF
11140 /* Set the flags in the private structure. */
11141 if (uses_apcs_26) flags |= F_APCS26;
11142 if (support_interwork) flags |= F_INTERWORK;
11143 if (uses_apcs_float) flags |= F_APCS_FLOAT;
11144 if (pic_code) flags |= F_PIC;
11145 if ((cpu_variant & FPU_ANY) == FPU_NONE
11146 || (cpu_variant & FPU_ANY) == FPU_ARCH_VFP) /* VFP layout only. */
11147 flags |= F_SOFT_FLOAT;
11148
11149 switch (mfloat_abi_opt)
11150 {
11151 case ARM_FLOAT_ABI_SOFT:
11152 case ARM_FLOAT_ABI_SOFTFP:
11153 flags |= F_SOFT_FLOAT;
11154 break;
11155
11156 case ARM_FLOAT_ABI_HARD:
11157 if (flags & F_SOFT_FLOAT)
11158 as_bad (_("hard-float conflicts with specified fpu"));
11159 break;
11160 }
11161
11162 /* Using VFP conventions (even if soft-float). */
11163 if (cpu_variant & FPU_VFP_EXT_NONE)
11164 flags |= F_VFP_FLOAT;
11165 #endif
11166 #if defined OBJ_ELF
11167 if (cpu_variant & FPU_ARCH_MAVERICK)
11168 flags |= EF_ARM_MAVERICK_FLOAT;
11169 break;
11170
11171 case EF_ARM_EABI_VER3:
11172 /* No additional flags to set. */
11173 break;
11174
11175 default:
11176 abort ();
11177 }
11178 #endif
11179 #if defined OBJ_COFF || defined OBJ_ELF
11180 bfd_set_private_flags (stdoutput, flags);
11181
11182 /* We have run out flags in the COFF header to encode the
11183 status of ATPCS support, so instead we create a dummy,
11184 empty, debug section called .arm.atpcs. */
11185 if (atpcs)
11186 {
11187 asection * sec;
11188
11189 sec = bfd_make_section (stdoutput, ".arm.atpcs");
11190
11191 if (sec != NULL)
11192 {
11193 bfd_set_section_flags
11194 (stdoutput, sec, SEC_READONLY | SEC_DEBUGGING /* | SEC_HAS_CONTENTS */);
11195 bfd_set_section_size (stdoutput, sec, 0);
11196 bfd_set_section_contents (stdoutput, sec, NULL, 0, 0);
11197 }
11198 }
11199 #endif
11200 }
11201
11202 /* Record the CPU type as well. */
11203 switch (cpu_variant & ARM_CPU_MASK)
11204 {
11205 case ARM_2:
11206 mach = bfd_mach_arm_2;
11207 break;
11208
11209 case ARM_3: /* Also ARM_250. */
11210 mach = bfd_mach_arm_2a;
11211 break;
11212
11213 case ARM_6: /* Also ARM_7. */
11214 mach = bfd_mach_arm_3;
11215 break;
11216
11217 default:
11218 mach = bfd_mach_arm_unknown;
11219 break;
11220 }
11221
11222 /* Catch special cases. */
11223 if (cpu_variant & ARM_CEXT_IWMMXT)
11224 mach = bfd_mach_arm_iWMMXt;
11225 else if (cpu_variant & ARM_CEXT_XSCALE)
11226 mach = bfd_mach_arm_XScale;
11227 else if (cpu_variant & ARM_CEXT_MAVERICK)
11228 mach = bfd_mach_arm_ep9312;
11229 else if (cpu_variant & ARM_EXT_V5E)
11230 mach = bfd_mach_arm_5TE;
11231 else if (cpu_variant & ARM_EXT_V5)
11232 {
11233 if (cpu_variant & ARM_EXT_V4T)
11234 mach = bfd_mach_arm_5T;
11235 else
11236 mach = bfd_mach_arm_5;
11237 }
11238 else if (cpu_variant & ARM_EXT_V4)
11239 {
11240 if (cpu_variant & ARM_EXT_V4T)
11241 mach = bfd_mach_arm_4T;
11242 else
11243 mach = bfd_mach_arm_4;
11244 }
11245 else if (cpu_variant & ARM_EXT_V3M)
11246 mach = bfd_mach_arm_3M;
11247
11248 #if 0 /* Suppressed - for now. */
11249 #if defined (OBJ_ELF) || defined (OBJ_COFF)
11250
11251 /* Create a .note section to fully identify this arm binary. */
11252
11253 #define NOTE_ARCH_STRING "arch: "
11254
11255 #if defined OBJ_COFF && ! defined NT_VERSION
11256 #define NT_VERSION 1
11257 #define NT_ARCH 2
11258 #endif
11259
11260 {
11261 segT current_seg = now_seg;
11262 subsegT current_subseg = now_subseg;
11263 asection * arm_arch;
11264 const char * arch_string;
11265
11266 arm_arch = bfd_make_section_old_way (stdoutput, ARM_NOTE_SECTION);
11267
11268 #ifdef OBJ_COFF
11269 bfd_set_section_flags (stdoutput, arm_arch,
11270 SEC_DATA | SEC_ALLOC | SEC_LOAD | SEC_LINK_ONCE \
11271 | SEC_HAS_CONTENTS);
11272 #else
11273 bfd_set_section_flags (stdoutput, arm_arch,
11274 SEC_READONLY | SEC_HAS_CONTENTS);
11275 #endif
11276 arm_arch->output_section = arm_arch;
11277 subseg_set (arm_arch, 0);
11278
11279 switch (mach)
11280 {
11281 default:
11282 case bfd_mach_arm_unknown: arch_string = "unknown"; break;
11283 case bfd_mach_arm_2: arch_string = "armv2"; break;
11284 case bfd_mach_arm_2a: arch_string = "armv2a"; break;
11285 case bfd_mach_arm_3: arch_string = "armv3"; break;
11286 case bfd_mach_arm_3M: arch_string = "armv3M"; break;
11287 case bfd_mach_arm_4: arch_string = "armv4"; break;
11288 case bfd_mach_arm_4T: arch_string = "armv4t"; break;
11289 case bfd_mach_arm_5: arch_string = "armv5"; break;
11290 case bfd_mach_arm_5T: arch_string = "armv5t"; break;
11291 case bfd_mach_arm_5TE: arch_string = "armv5te"; break;
11292 case bfd_mach_arm_XScale: arch_string = "XScale"; break;
11293 case bfd_mach_arm_ep9312: arch_string = "ep9312"; break;
11294 case bfd_mach_arm_iWMMXt: arch_string = "iWMMXt"; break;
11295 }
11296
11297 arm_add_note (NOTE_ARCH_STRING, arch_string, NT_ARCH);
11298
11299 subseg_set (current_seg, current_subseg);
11300 }
11301 #endif
11302 #endif /* Suppressed code. */
11303
11304 bfd_set_arch_mach (stdoutput, TARGET_ARCH, mach);
11305 }
11306
11307 /* Turn an integer of n bytes (in val) into a stream of bytes appropriate
11308 for use in the a.out file, and stores them in the array pointed to by buf.
11309 This knows about the endian-ness of the target machine and does
11310 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
11311 2 (short) and 4 (long) Floating numbers are put out as a series of
11312 LITTLENUMS (shorts, here at least). */
11313
11314 void
11315 md_number_to_chars (char * buf, valueT val, int n)
11316 {
11317 if (target_big_endian)
11318 number_to_chars_bigendian (buf, val, n);
11319 else
11320 number_to_chars_littleendian (buf, val, n);
11321 }
11322
11323 static valueT
11324 md_chars_to_number (char * buf, int n)
11325 {
11326 valueT result = 0;
11327 unsigned char * where = (unsigned char *) buf;
11328
11329 if (target_big_endian)
11330 {
11331 while (n--)
11332 {
11333 result <<= 8;
11334 result |= (*where++ & 255);
11335 }
11336 }
11337 else
11338 {
11339 while (n--)
11340 {
11341 result <<= 8;
11342 result |= (where[n] & 255);
11343 }
11344 }
11345
11346 return result;
11347 }
11348
11349 /* Turn a string in input_line_pointer into a floating point constant
11350 of type TYPE, and store the appropriate bytes in *LITP. The number
11351 of LITTLENUMS emitted is stored in *SIZEP. An error message is
11352 returned, or NULL on OK.
11353
11354 Note that fp constants aren't represent in the normal way on the ARM.
11355 In big endian mode, things are as expected. However, in little endian
11356 mode fp constants are big-endian word-wise, and little-endian byte-wise
11357 within the words. For example, (double) 1.1 in big endian mode is
11358 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
11359 the byte sequence 99 99 f1 3f 9a 99 99 99.
11360
11361 ??? The format of 12 byte floats is uncertain according to gcc's arm.h. */
11362
11363 char *
11364 md_atof (int type, char * litP, int * sizeP)
11365 {
11366 int prec;
11367 LITTLENUM_TYPE words[MAX_LITTLENUMS];
11368 char *t;
11369 int i;
11370
11371 switch (type)
11372 {
11373 case 'f':
11374 case 'F':
11375 case 's':
11376 case 'S':
11377 prec = 2;
11378 break;
11379
11380 case 'd':
11381 case 'D':
11382 case 'r':
11383 case 'R':
11384 prec = 4;
11385 break;
11386
11387 case 'x':
11388 case 'X':
11389 prec = 6;
11390 break;
11391
11392 case 'p':
11393 case 'P':
11394 prec = 6;
11395 break;
11396
11397 default:
11398 *sizeP = 0;
11399 return _("bad call to MD_ATOF()");
11400 }
11401
11402 t = atof_ieee (input_line_pointer, type, words);
11403 if (t)
11404 input_line_pointer = t;
11405 *sizeP = prec * 2;
11406
11407 if (target_big_endian)
11408 {
11409 for (i = 0; i < prec; i++)
11410 {
11411 md_number_to_chars (litP, (valueT) words[i], 2);
11412 litP += 2;
11413 }
11414 }
11415 else
11416 {
11417 if (cpu_variant & FPU_ARCH_VFP)
11418 for (i = prec - 1; i >= 0; i--)
11419 {
11420 md_number_to_chars (litP, (valueT) words[i], 2);
11421 litP += 2;
11422 }
11423 else
11424 /* For a 4 byte float the order of elements in `words' is 1 0.
11425 For an 8 byte float the order is 1 0 3 2. */
11426 for (i = 0; i < prec; i += 2)
11427 {
11428 md_number_to_chars (litP, (valueT) words[i + 1], 2);
11429 md_number_to_chars (litP + 2, (valueT) words[i], 2);
11430 litP += 4;
11431 }
11432 }
11433
11434 return 0;
11435 }
11436
11437 /* The knowledge of the PC's pipeline offset is built into the insns
11438 themselves. */
11439
11440 long
11441 md_pcrel_from (fixS * fixP)
11442 {
11443 if (fixP->fx_addsy
11444 && S_GET_SEGMENT (fixP->fx_addsy) == undefined_section
11445 && fixP->fx_subsy == NULL)
11446 return 0;
11447
11448 if (fixP->fx_pcrel && (fixP->fx_r_type == BFD_RELOC_ARM_THUMB_ADD))
11449 {
11450 /* PC relative addressing on the Thumb is slightly odd
11451 as the bottom two bits of the PC are forced to zero
11452 for the calculation. */
11453 return (fixP->fx_where + fixP->fx_frag->fr_address) & ~3;
11454 }
11455
11456 #ifdef TE_WINCE
11457 /* The pattern was adjusted to accommodate CE's off-by-one fixups,
11458 so we un-adjust here to compensate for the accommodation. */
11459 return fixP->fx_where + fixP->fx_frag->fr_address + 8;
11460 #else
11461 return fixP->fx_where + fixP->fx_frag->fr_address;
11462 #endif
11463 }
11464
11465 /* Round up a section size to the appropriate boundary. */
11466
11467 valueT
11468 md_section_align (segT segment ATTRIBUTE_UNUSED,
11469 valueT size)
11470 {
11471 #ifdef OBJ_ELF
11472 return size;
11473 #else
11474 /* Round all sects to multiple of 4. */
11475 return (size + 3) & ~3;
11476 #endif
11477 }
11478
11479 /* Under ELF we need to default _GLOBAL_OFFSET_TABLE.
11480 Otherwise we have no need to default values of symbols. */
11481
11482 symbolS *
11483 md_undefined_symbol (char * name ATTRIBUTE_UNUSED)
11484 {
11485 #ifdef OBJ_ELF
11486 if (name[0] == '_' && name[1] == 'G'
11487 && streq (name, GLOBAL_OFFSET_TABLE_NAME))
11488 {
11489 if (!GOT_symbol)
11490 {
11491 if (symbol_find (name))
11492 as_bad ("GOT already in the symbol table");
11493
11494 GOT_symbol = symbol_new (name, undefined_section,
11495 (valueT) 0, & zero_address_frag);
11496 }
11497
11498 return GOT_symbol;
11499 }
11500 #endif
11501
11502 return 0;
11503 }
11504
11505 void
11506 md_apply_fix3 (fixS * fixP,
11507 valueT * valP,
11508 segT seg)
11509 {
11510 offsetT value = * valP;
11511 offsetT newval;
11512 unsigned int newimm;
11513 unsigned long temp;
11514 int sign;
11515 char * buf = fixP->fx_where + fixP->fx_frag->fr_literal;
11516 arm_fix_data * arm_data = (arm_fix_data *) fixP->tc_fix_data;
11517
11518 assert (fixP->fx_r_type < BFD_RELOC_UNUSED);
11519
11520 /* Note whether this will delete the relocation. */
11521 #if 0
11522 /* Patch from REarnshaw to JDavis (disabled for the moment, since it
11523 doesn't work fully.) */
11524 if ((fixP->fx_addsy == 0 || symbol_constant_p (fixP->fx_addsy))
11525 && !fixP->fx_pcrel)
11526 #else
11527 if (fixP->fx_addsy == 0 && !fixP->fx_pcrel)
11528 #endif
11529 fixP->fx_done = 1;
11530
11531 /* If this symbol is in a different section then we need to leave it for
11532 the linker to deal with. Unfortunately, md_pcrel_from can't tell,
11533 so we have to undo it's effects here. */
11534 if (fixP->fx_pcrel)
11535 {
11536 if (fixP->fx_addsy != NULL
11537 && S_IS_DEFINED (fixP->fx_addsy)
11538 && S_GET_SEGMENT (fixP->fx_addsy) != seg)
11539 {
11540 if (target_oabi
11541 && (fixP->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH
11542 || fixP->fx_r_type == BFD_RELOC_ARM_PCREL_BLX
11543 ))
11544 value = 0;
11545 else
11546 value += md_pcrel_from (fixP);
11547 }
11548 }
11549
11550 /* Remember value for emit_reloc. */
11551 fixP->fx_addnumber = value;
11552
11553 switch (fixP->fx_r_type)
11554 {
11555 case BFD_RELOC_ARM_IMMEDIATE:
11556 /* We claim that this fixup has been processed here,
11557 even if in fact we generate an error because we do
11558 not have a reloc for it, so tc_gen_reloc will reject it. */
11559 fixP->fx_done = 1;
11560
11561 if (fixP->fx_addsy
11562 && ! S_IS_DEFINED (fixP->fx_addsy))
11563 {
11564 as_bad_where (fixP->fx_file, fixP->fx_line,
11565 _("undefined symbol %s used as an immediate value"),
11566 S_GET_NAME (fixP->fx_addsy));
11567 break;
11568 }
11569
11570 newimm = validate_immediate (value);
11571 temp = md_chars_to_number (buf, INSN_SIZE);
11572
11573 /* If the instruction will fail, see if we can fix things up by
11574 changing the opcode. */
11575 if (newimm == (unsigned int) FAIL
11576 && (newimm = negate_data_op (&temp, value)) == (unsigned int) FAIL)
11577 {
11578 as_bad_where (fixP->fx_file, fixP->fx_line,
11579 _("invalid constant (%lx) after fixup"),
11580 (unsigned long) value);
11581 break;
11582 }
11583
11584 newimm |= (temp & 0xfffff000);
11585 md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
11586 break;
11587
11588 case BFD_RELOC_ARM_ADRL_IMMEDIATE:
11589 {
11590 unsigned int highpart = 0;
11591 unsigned int newinsn = 0xe1a00000; /* nop. */
11592
11593 newimm = validate_immediate (value);
11594 temp = md_chars_to_number (buf, INSN_SIZE);
11595
11596 /* If the instruction will fail, see if we can fix things up by
11597 changing the opcode. */
11598 if (newimm == (unsigned int) FAIL
11599 && (newimm = negate_data_op (& temp, value)) == (unsigned int) FAIL)
11600 {
11601 /* No ? OK - try using two ADD instructions to generate
11602 the value. */
11603 newimm = validate_immediate_twopart (value, & highpart);
11604
11605 /* Yes - then make sure that the second instruction is
11606 also an add. */
11607 if (newimm != (unsigned int) FAIL)
11608 newinsn = temp;
11609 /* Still No ? Try using a negated value. */
11610 else if ((newimm = validate_immediate_twopart (- value, & highpart)) != (unsigned int) FAIL)
11611 temp = newinsn = (temp & OPCODE_MASK) | OPCODE_SUB << DATA_OP_SHIFT;
11612 /* Otherwise - give up. */
11613 else
11614 {
11615 as_bad_where (fixP->fx_file, fixP->fx_line,
11616 _("unable to compute ADRL instructions for PC offset of 0x%lx"),
11617 (long) value);
11618 break;
11619 }
11620
11621 /* Replace the first operand in the 2nd instruction (which
11622 is the PC) with the destination register. We have
11623 already added in the PC in the first instruction and we
11624 do not want to do it again. */
11625 newinsn &= ~ 0xf0000;
11626 newinsn |= ((newinsn & 0x0f000) << 4);
11627 }
11628
11629 newimm |= (temp & 0xfffff000);
11630 md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
11631
11632 highpart |= (newinsn & 0xfffff000);
11633 md_number_to_chars (buf + INSN_SIZE, (valueT) highpart, INSN_SIZE);
11634 }
11635 break;
11636
11637 case BFD_RELOC_ARM_OFFSET_IMM:
11638 sign = value >= 0;
11639
11640 if (value < 0)
11641 value = - value;
11642
11643 if (validate_offset_imm (value, 0) == FAIL)
11644 {
11645 as_bad_where (fixP->fx_file, fixP->fx_line,
11646 _("bad immediate value for offset (%ld)"),
11647 (long) value);
11648 break;
11649 }
11650
11651 newval = md_chars_to_number (buf, INSN_SIZE);
11652 newval &= 0xff7ff000;
11653 newval |= value | (sign ? INDEX_UP : 0);
11654 md_number_to_chars (buf, newval, INSN_SIZE);
11655 break;
11656
11657 case BFD_RELOC_ARM_OFFSET_IMM8:
11658 case BFD_RELOC_ARM_HWLITERAL:
11659 sign = value >= 0;
11660
11661 if (value < 0)
11662 value = - value;
11663
11664 if (validate_offset_imm (value, 1) == FAIL)
11665 {
11666 if (fixP->fx_r_type == BFD_RELOC_ARM_HWLITERAL)
11667 as_bad_where (fixP->fx_file, fixP->fx_line,
11668 _("invalid literal constant: pool needs to be closer"));
11669 else
11670 as_bad (_("bad immediate value for half-word offset (%ld)"),
11671 (long) value);
11672 break;
11673 }
11674
11675 newval = md_chars_to_number (buf, INSN_SIZE);
11676 newval &= 0xff7ff0f0;
11677 newval |= ((value >> 4) << 8) | (value & 0xf) | (sign ? INDEX_UP : 0);
11678 md_number_to_chars (buf, newval, INSN_SIZE);
11679 break;
11680
11681 case BFD_RELOC_ARM_LITERAL:
11682 sign = value >= 0;
11683
11684 if (value < 0)
11685 value = - value;
11686
11687 if (validate_offset_imm (value, 0) == FAIL)
11688 {
11689 as_bad_where (fixP->fx_file, fixP->fx_line,
11690 _("invalid literal constant: pool needs to be closer"));
11691 break;
11692 }
11693
11694 newval = md_chars_to_number (buf, INSN_SIZE);
11695 newval &= 0xff7ff000;
11696 newval |= value | (sign ? INDEX_UP : 0);
11697 md_number_to_chars (buf, newval, INSN_SIZE);
11698 break;
11699
11700 case BFD_RELOC_ARM_SHIFT_IMM:
11701 newval = md_chars_to_number (buf, INSN_SIZE);
11702 if (((unsigned long) value) > 32
11703 || (value == 32
11704 && (((newval & 0x60) == 0) || (newval & 0x60) == 0x60)))
11705 {
11706 as_bad_where (fixP->fx_file, fixP->fx_line,
11707 _("shift expression is too large"));
11708 break;
11709 }
11710
11711 if (value == 0)
11712 /* Shifts of zero must be done as lsl. */
11713 newval &= ~0x60;
11714 else if (value == 32)
11715 value = 0;
11716 newval &= 0xfffff07f;
11717 newval |= (value & 0x1f) << 7;
11718 md_number_to_chars (buf, newval, INSN_SIZE);
11719 break;
11720
11721 case BFD_RELOC_ARM_SMI:
11722 if (((unsigned long) value) > 0xffff)
11723 as_bad_where (fixP->fx_file, fixP->fx_line,
11724 _("invalid smi expression"));
11725 newval = md_chars_to_number (buf, INSN_SIZE) & 0xfff000f0;
11726 newval |= (value & 0xf) | ((value & 0xfff0) << 4);
11727 md_number_to_chars (buf, newval, INSN_SIZE);
11728 break;
11729
11730 case BFD_RELOC_ARM_SWI:
11731 if (arm_data->thumb_mode)
11732 {
11733 if (((unsigned long) value) > 0xff)
11734 as_bad_where (fixP->fx_file, fixP->fx_line,
11735 _("invalid swi expression"));
11736 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xff00;
11737 newval |= value;
11738 md_number_to_chars (buf, newval, THUMB_SIZE);
11739 }
11740 else
11741 {
11742 if (((unsigned long) value) > 0x00ffffff)
11743 as_bad_where (fixP->fx_file, fixP->fx_line,
11744 _("invalid swi expression"));
11745 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff000000;
11746 newval |= value;
11747 md_number_to_chars (buf, newval, INSN_SIZE);
11748 }
11749 break;
11750
11751 case BFD_RELOC_ARM_MULTI:
11752 if (((unsigned long) value) > 0xffff)
11753 as_bad_where (fixP->fx_file, fixP->fx_line,
11754 _("invalid expression in load/store multiple"));
11755 newval = value | md_chars_to_number (buf, INSN_SIZE);
11756 md_number_to_chars (buf, newval, INSN_SIZE);
11757 break;
11758
11759 case BFD_RELOC_ARM_PCREL_BRANCH:
11760 newval = md_chars_to_number (buf, INSN_SIZE);
11761
11762 /* Sign-extend a 24-bit number. */
11763 #define SEXT24(x) ((((x) & 0xffffff) ^ (~ 0x7fffff)) + 0x800000)
11764
11765 #ifdef OBJ_ELF
11766 if (! target_oabi)
11767 value = fixP->fx_offset;
11768 #endif
11769
11770 /* We are going to store value (shifted right by two) in the
11771 instruction, in a 24 bit, signed field. Thus we need to check
11772 that none of the top 8 bits of the shifted value (top 7 bits of
11773 the unshifted, unsigned value) are set, or that they are all set. */
11774 if ((value & ~ ((offsetT) 0x1ffffff)) != 0
11775 && ((value & ~ ((offsetT) 0x1ffffff)) != ~ ((offsetT) 0x1ffffff)))
11776 {
11777 #ifdef OBJ_ELF
11778 /* Normally we would be stuck at this point, since we cannot store
11779 the absolute address that is the destination of the branch in the
11780 24 bits of the branch instruction. If however, we happen to know
11781 that the destination of the branch is in the same section as the
11782 branch instruction itself, then we can compute the relocation for
11783 ourselves and not have to bother the linker with it.
11784
11785 FIXME: The tests for OBJ_ELF and ! target_oabi are only here
11786 because I have not worked out how to do this for OBJ_COFF or
11787 target_oabi. */
11788 if (! target_oabi
11789 && fixP->fx_addsy != NULL
11790 && S_IS_DEFINED (fixP->fx_addsy)
11791 && S_GET_SEGMENT (fixP->fx_addsy) == seg)
11792 {
11793 /* Get pc relative value to go into the branch. */
11794 value = * valP;
11795
11796 /* Permit a backward branch provided that enough bits
11797 are set. Allow a forwards branch, provided that
11798 enough bits are clear. */
11799 if ( (value & ~ ((offsetT) 0x1ffffff)) == ~ ((offsetT) 0x1ffffff)
11800 || (value & ~ ((offsetT) 0x1ffffff)) == 0)
11801 fixP->fx_done = 1;
11802 }
11803
11804 if (! fixP->fx_done)
11805 #endif
11806 as_bad_where (fixP->fx_file, fixP->fx_line,
11807 _("GAS can't handle same-section branch dest >= 0x04000000"));
11808 }
11809
11810 value >>= 2;
11811 value += SEXT24 (newval);
11812
11813 if ( (value & ~ ((offsetT) 0xffffff)) != 0
11814 && ((value & ~ ((offsetT) 0xffffff)) != ~ ((offsetT) 0xffffff)))
11815 as_bad_where (fixP->fx_file, fixP->fx_line,
11816 _("out of range branch"));
11817
11818 newval = (value & 0x00ffffff) | (newval & 0xff000000);
11819 md_number_to_chars (buf, newval, INSN_SIZE);
11820 break;
11821
11822 case BFD_RELOC_ARM_PCREL_BLX:
11823 {
11824 offsetT hbit;
11825 newval = md_chars_to_number (buf, INSN_SIZE);
11826
11827 #ifdef OBJ_ELF
11828 if (! target_oabi)
11829 value = fixP->fx_offset;
11830 #endif
11831 hbit = (value >> 1) & 1;
11832 value = (value >> 2) & 0x00ffffff;
11833 value = (value + (newval & 0x00ffffff)) & 0x00ffffff;
11834 newval = value | (newval & 0xfe000000) | (hbit << 24);
11835 md_number_to_chars (buf, newval, INSN_SIZE);
11836 }
11837 break;
11838
11839 case BFD_RELOC_THUMB_PCREL_BRANCH9: /* Conditional branch. */
11840 newval = md_chars_to_number (buf, THUMB_SIZE);
11841 {
11842 addressT diff = (newval & 0xff) << 1;
11843 if (diff & 0x100)
11844 diff |= ~0xff;
11845
11846 value += diff;
11847 if ((value & ~0xff) && ((value & ~0xff) != ~0xff))
11848 as_bad_where (fixP->fx_file, fixP->fx_line,
11849 _("branch out of range"));
11850 newval = (newval & 0xff00) | ((value & 0x1ff) >> 1);
11851 }
11852 md_number_to_chars (buf, newval, THUMB_SIZE);
11853 break;
11854
11855 case BFD_RELOC_THUMB_PCREL_BRANCH12: /* Unconditional branch. */
11856 newval = md_chars_to_number (buf, THUMB_SIZE);
11857 {
11858 addressT diff = (newval & 0x7ff) << 1;
11859 if (diff & 0x800)
11860 diff |= ~0x7ff;
11861
11862 value += diff;
11863 if ((value & ~0x7ff) && ((value & ~0x7ff) != ~0x7ff))
11864 as_bad_where (fixP->fx_file, fixP->fx_line,
11865 _("branch out of range"));
11866 newval = (newval & 0xf800) | ((value & 0xfff) >> 1);
11867 }
11868 md_number_to_chars (buf, newval, THUMB_SIZE);
11869 break;
11870
11871 case BFD_RELOC_THUMB_PCREL_BLX:
11872 case BFD_RELOC_THUMB_PCREL_BRANCH23:
11873 {
11874 offsetT newval2;
11875 addressT diff;
11876
11877 newval = md_chars_to_number (buf, THUMB_SIZE);
11878 newval2 = md_chars_to_number (buf + THUMB_SIZE, THUMB_SIZE);
11879 diff = ((newval & 0x7ff) << 12) | ((newval2 & 0x7ff) << 1);
11880 if (diff & 0x400000)
11881 diff |= ~0x3fffff;
11882 #ifdef OBJ_ELF
11883 value = fixP->fx_offset;
11884 #endif
11885 value += diff;
11886
11887 if ((value & ~0x3fffff) && ((value & ~0x3fffff) != ~0x3fffff))
11888 as_bad_where (fixP->fx_file, fixP->fx_line,
11889 _("branch with link out of range"));
11890
11891 newval = (newval & 0xf800) | ((value & 0x7fffff) >> 12);
11892 newval2 = (newval2 & 0xf800) | ((value & 0xfff) >> 1);
11893 if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX)
11894 /* For a BLX instruction, make sure that the relocation is rounded up
11895 to a word boundary. This follows the semantics of the instruction
11896 which specifies that bit 1 of the target address will come from bit
11897 1 of the base address. */
11898 newval2 = (newval2 + 1) & ~ 1;
11899 md_number_to_chars (buf, newval, THUMB_SIZE);
11900 md_number_to_chars (buf + THUMB_SIZE, newval2, THUMB_SIZE);
11901 }
11902 break;
11903
11904 case BFD_RELOC_8:
11905 if (fixP->fx_done || fixP->fx_pcrel)
11906 md_number_to_chars (buf, value, 1);
11907 #ifdef OBJ_ELF
11908 else if (!target_oabi)
11909 {
11910 value = fixP->fx_offset;
11911 md_number_to_chars (buf, value, 1);
11912 }
11913 #endif
11914 break;
11915
11916 case BFD_RELOC_16:
11917 if (fixP->fx_done || fixP->fx_pcrel)
11918 md_number_to_chars (buf, value, 2);
11919 #ifdef OBJ_ELF
11920 else if (!target_oabi)
11921 {
11922 value = fixP->fx_offset;
11923 md_number_to_chars (buf, value, 2);
11924 }
11925 #endif
11926 break;
11927
11928 #ifdef OBJ_ELF
11929 case BFD_RELOC_ARM_GOT32:
11930 case BFD_RELOC_ARM_GOTOFF:
11931 case BFD_RELOC_ARM_TARGET2:
11932 md_number_to_chars (buf, 0, 4);
11933 break;
11934 #endif
11935
11936 case BFD_RELOC_RVA:
11937 case BFD_RELOC_32:
11938 case BFD_RELOC_ARM_TARGET1:
11939 case BFD_RELOC_ARM_ROSEGREL32:
11940 case BFD_RELOC_ARM_SBREL32:
11941 case BFD_RELOC_32_PCREL:
11942 if (fixP->fx_done || fixP->fx_pcrel)
11943 md_number_to_chars (buf, value, 4);
11944 #ifdef OBJ_ELF
11945 else if (!target_oabi)
11946 {
11947 value = fixP->fx_offset;
11948 md_number_to_chars (buf, value, 4);
11949 }
11950 #endif
11951 break;
11952
11953 #ifdef OBJ_ELF
11954 case BFD_RELOC_ARM_PREL31:
11955 if (fixP->fx_done || fixP->fx_pcrel)
11956 {
11957 newval = md_chars_to_number (buf, 4) & 0x80000000;
11958 if ((value ^ (value >> 1)) & 0x40000000)
11959 {
11960 as_bad_where (fixP->fx_file, fixP->fx_line,
11961 _("rel31 relocation overflow"));
11962 }
11963 newval |= value & 0x7fffffff;
11964 md_number_to_chars (buf, newval, 4);
11965 }
11966 break;
11967
11968 case BFD_RELOC_ARM_PLT32:
11969 /* It appears the instruction is fully prepared at this point. */
11970 break;
11971 #endif
11972
11973 case BFD_RELOC_ARM_CP_OFF_IMM:
11974 sign = value >= 0;
11975 if (value < -1023 || value > 1023 || (value & 3))
11976 as_bad_where (fixP->fx_file, fixP->fx_line,
11977 _("illegal value for co-processor offset"));
11978 if (value < 0)
11979 value = -value;
11980 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
11981 newval |= (value >> 2) | (sign ? INDEX_UP : 0);
11982 md_number_to_chars (buf, newval, INSN_SIZE);
11983 break;
11984
11985 case BFD_RELOC_ARM_CP_OFF_IMM_S2:
11986 sign = value >= 0;
11987 if (value < -255 || value > 255)
11988 as_bad_where (fixP->fx_file, fixP->fx_line,
11989 _("Illegal value for co-processor offset"));
11990 if (value < 0)
11991 value = -value;
11992 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
11993 newval |= value | (sign ? INDEX_UP : 0);
11994 md_number_to_chars (buf, newval , INSN_SIZE);
11995 break;
11996
11997 case BFD_RELOC_ARM_THUMB_OFFSET:
11998 newval = md_chars_to_number (buf, THUMB_SIZE);
11999 /* Exactly what ranges, and where the offset is inserted depends
12000 on the type of instruction, we can establish this from the
12001 top 4 bits. */
12002 switch (newval >> 12)
12003 {
12004 case 4: /* PC load. */
12005 /* Thumb PC loads are somewhat odd, bit 1 of the PC is
12006 forced to zero for these loads, so we will need to round
12007 up the offset if the instruction address is not word
12008 aligned (since the final address produced must be, and
12009 we can only describe word-aligned immediate offsets). */
12010
12011 if ((fixP->fx_frag->fr_address + fixP->fx_where + value) & 3)
12012 as_bad_where (fixP->fx_file, fixP->fx_line,
12013 _("invalid offset, target not word aligned (0x%08X)"),
12014 (unsigned int) (fixP->fx_frag->fr_address
12015 + fixP->fx_where + value));
12016
12017 if ((value + 2) & ~0x3fe)
12018 as_bad_where (fixP->fx_file, fixP->fx_line,
12019 _("invalid offset, value too big (0x%08lX)"),
12020 (long) value);
12021
12022 /* Round up, since pc will be rounded down. */
12023 newval |= (value + 2) >> 2;
12024 break;
12025
12026 case 9: /* SP load/store. */
12027 if (value & ~0x3fc)
12028 as_bad_where (fixP->fx_file, fixP->fx_line,
12029 _("invalid offset, value too big (0x%08lX)"),
12030 (long) value);
12031 newval |= value >> 2;
12032 break;
12033
12034 case 6: /* Word load/store. */
12035 if (value & ~0x7c)
12036 as_bad_where (fixP->fx_file, fixP->fx_line,
12037 _("invalid offset, value too big (0x%08lX)"),
12038 (long) value);
12039 newval |= value << 4; /* 6 - 2. */
12040 break;
12041
12042 case 7: /* Byte load/store. */
12043 if (value & ~0x1f)
12044 as_bad_where (fixP->fx_file, fixP->fx_line,
12045 _("invalid offset, value too big (0x%08lX)"),
12046 (long) value);
12047 newval |= value << 6;
12048 break;
12049
12050 case 8: /* Halfword load/store. */
12051 if (value & ~0x3e)
12052 as_bad_where (fixP->fx_file, fixP->fx_line,
12053 _("invalid offset, value too big (0x%08lX)"),
12054 (long) value);
12055 newval |= value << 5; /* 6 - 1. */
12056 break;
12057
12058 default:
12059 as_bad_where (fixP->fx_file, fixP->fx_line,
12060 "Unable to process relocation for thumb opcode: %lx",
12061 (unsigned long) newval);
12062 break;
12063 }
12064 md_number_to_chars (buf, newval, THUMB_SIZE);
12065 break;
12066
12067 case BFD_RELOC_ARM_THUMB_ADD:
12068 /* This is a complicated relocation, since we use it for all of
12069 the following immediate relocations:
12070
12071 3bit ADD/SUB
12072 8bit ADD/SUB
12073 9bit ADD/SUB SP word-aligned
12074 10bit ADD PC/SP word-aligned
12075
12076 The type of instruction being processed is encoded in the
12077 instruction field:
12078
12079 0x8000 SUB
12080 0x00F0 Rd
12081 0x000F Rs
12082 */
12083 newval = md_chars_to_number (buf, THUMB_SIZE);
12084 {
12085 int rd = (newval >> 4) & 0xf;
12086 int rs = newval & 0xf;
12087 int subtract = newval & 0x8000;
12088
12089 if (rd == REG_SP)
12090 {
12091 if (value & ~0x1fc)
12092 as_bad_where (fixP->fx_file, fixP->fx_line,
12093 _("invalid immediate for stack address calculation"));
12094 newval = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
12095 newval |= value >> 2;
12096 }
12097 else if (rs == REG_PC || rs == REG_SP)
12098 {
12099 if (subtract ||
12100 value & ~0x3fc)
12101 as_bad_where (fixP->fx_file, fixP->fx_line,
12102 _("invalid immediate for address calculation (value = 0x%08lX)"),
12103 (unsigned long) value);
12104 newval = (rs == REG_PC ? T_OPCODE_ADD_PC : T_OPCODE_ADD_SP);
12105 newval |= rd << 8;
12106 newval |= value >> 2;
12107 }
12108 else if (rs == rd)
12109 {
12110 if (value & ~0xff)
12111 as_bad_where (fixP->fx_file, fixP->fx_line,
12112 _("invalid 8bit immediate"));
12113 newval = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
12114 newval |= (rd << 8) | value;
12115 }
12116 else
12117 {
12118 if (value & ~0x7)
12119 as_bad_where (fixP->fx_file, fixP->fx_line,
12120 _("invalid 3bit immediate"));
12121 newval = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
12122 newval |= rd | (rs << 3) | (value << 6);
12123 }
12124 }
12125 md_number_to_chars (buf, newval, THUMB_SIZE);
12126 break;
12127
12128 case BFD_RELOC_ARM_THUMB_IMM:
12129 newval = md_chars_to_number (buf, THUMB_SIZE);
12130 switch (newval >> 11)
12131 {
12132 case 0x04: /* 8bit immediate MOV. */
12133 case 0x05: /* 8bit immediate CMP. */
12134 if (value < 0 || value > 255)
12135 as_bad_where (fixP->fx_file, fixP->fx_line,
12136 _("invalid immediate: %ld is too large"),
12137 (long) value);
12138 newval |= value;
12139 break;
12140
12141 default:
12142 abort ();
12143 }
12144 md_number_to_chars (buf, newval, THUMB_SIZE);
12145 break;
12146
12147 case BFD_RELOC_ARM_THUMB_SHIFT:
12148 /* 5bit shift value (0..31). */
12149 if (value < 0 || value > 31)
12150 as_bad_where (fixP->fx_file, fixP->fx_line,
12151 _("illegal Thumb shift value: %ld"), (long) value);
12152 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xf03f;
12153 newval |= value << 6;
12154 md_number_to_chars (buf, newval, THUMB_SIZE);
12155 break;
12156
12157 case BFD_RELOC_VTABLE_INHERIT:
12158 case BFD_RELOC_VTABLE_ENTRY:
12159 fixP->fx_done = 0;
12160 return;
12161
12162 case BFD_RELOC_NONE:
12163 default:
12164 as_bad_where (fixP->fx_file, fixP->fx_line,
12165 _("bad relocation fixup type (%d)"), fixP->fx_r_type);
12166 }
12167 }
12168
12169 /* Translate internal representation of relocation info to BFD target
12170 format. */
12171
12172 arelent *
12173 tc_gen_reloc (asection * section ATTRIBUTE_UNUSED,
12174 fixS * fixp)
12175 {
12176 arelent * reloc;
12177 bfd_reloc_code_real_type code;
12178
12179 reloc = xmalloc (sizeof (arelent));
12180
12181 reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
12182 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
12183 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
12184
12185 /* @@ Why fx_addnumber sometimes and fx_offset other times? */
12186 #ifndef OBJ_ELF
12187 if (fixp->fx_pcrel == 0)
12188 reloc->addend = fixp->fx_offset;
12189 else
12190 reloc->addend = fixp->fx_offset = reloc->address;
12191 #else /* OBJ_ELF */
12192 reloc->addend = fixp->fx_offset;
12193 #endif
12194
12195 switch (fixp->fx_r_type)
12196 {
12197 case BFD_RELOC_8:
12198 if (fixp->fx_pcrel)
12199 {
12200 code = BFD_RELOC_8_PCREL;
12201 break;
12202 }
12203
12204 case BFD_RELOC_16:
12205 if (fixp->fx_pcrel)
12206 {
12207 code = BFD_RELOC_16_PCREL;
12208 break;
12209 }
12210
12211 case BFD_RELOC_32:
12212 if (fixp->fx_pcrel)
12213 {
12214 code = BFD_RELOC_32_PCREL;
12215 break;
12216 }
12217
12218 case BFD_RELOC_ARM_PCREL_BRANCH:
12219 case BFD_RELOC_ARM_PCREL_BLX:
12220 case BFD_RELOC_RVA:
12221 case BFD_RELOC_THUMB_PCREL_BRANCH9:
12222 case BFD_RELOC_THUMB_PCREL_BRANCH12:
12223 case BFD_RELOC_THUMB_PCREL_BRANCH23:
12224 case BFD_RELOC_THUMB_PCREL_BLX:
12225 case BFD_RELOC_VTABLE_ENTRY:
12226 case BFD_RELOC_VTABLE_INHERIT:
12227 code = fixp->fx_r_type;
12228 break;
12229
12230 case BFD_RELOC_ARM_LITERAL:
12231 case BFD_RELOC_ARM_HWLITERAL:
12232 /* If this is called then the a literal has
12233 been referenced across a section boundary. */
12234 as_bad_where (fixp->fx_file, fixp->fx_line,
12235 _("literal referenced across section boundary"));
12236 return NULL;
12237
12238 #ifdef OBJ_ELF
12239 case BFD_RELOC_ARM_GOT32:
12240 case BFD_RELOC_ARM_GOTOFF:
12241 case BFD_RELOC_ARM_PLT32:
12242 case BFD_RELOC_ARM_TARGET1:
12243 case BFD_RELOC_ARM_ROSEGREL32:
12244 case BFD_RELOC_ARM_SBREL32:
12245 case BFD_RELOC_ARM_PREL31:
12246 case BFD_RELOC_ARM_TARGET2:
12247 code = fixp->fx_r_type;
12248 break;
12249 #endif
12250
12251 case BFD_RELOC_ARM_IMMEDIATE:
12252 as_bad_where (fixp->fx_file, fixp->fx_line,
12253 _("internal relocation (type: IMMEDIATE) not fixed up"));
12254 return NULL;
12255
12256 case BFD_RELOC_ARM_ADRL_IMMEDIATE:
12257 as_bad_where (fixp->fx_file, fixp->fx_line,
12258 _("ADRL used for a symbol not defined in the same file"));
12259 return NULL;
12260
12261 case BFD_RELOC_ARM_OFFSET_IMM:
12262 if (fixp->fx_addsy != NULL
12263 && !S_IS_DEFINED (fixp->fx_addsy)
12264 && S_IS_LOCAL (fixp->fx_addsy))
12265 {
12266 as_bad_where (fixp->fx_file, fixp->fx_line,
12267 _("undefined local label `%s'"),
12268 S_GET_NAME (fixp->fx_addsy));
12269 return NULL;
12270 }
12271
12272 as_bad_where (fixp->fx_file, fixp->fx_line,
12273 _("internal_relocation (type: OFFSET_IMM) not fixed up"));
12274 return NULL;
12275
12276 default:
12277 {
12278 char * type;
12279
12280 switch (fixp->fx_r_type)
12281 {
12282 case BFD_RELOC_ARM_OFFSET_IMM8: type = "OFFSET_IMM8"; break;
12283 case BFD_RELOC_ARM_SHIFT_IMM: type = "SHIFT_IMM"; break;
12284 case BFD_RELOC_ARM_SMI: type = "SMI"; break;
12285 case BFD_RELOC_ARM_SWI: type = "SWI"; break;
12286 case BFD_RELOC_ARM_MULTI: type = "MULTI"; break;
12287 case BFD_RELOC_ARM_CP_OFF_IMM: type = "CP_OFF_IMM"; break;
12288 case BFD_RELOC_ARM_THUMB_ADD: type = "THUMB_ADD"; break;
12289 case BFD_RELOC_ARM_THUMB_SHIFT: type = "THUMB_SHIFT"; break;
12290 case BFD_RELOC_ARM_THUMB_IMM: type = "THUMB_IMM"; break;
12291 case BFD_RELOC_ARM_THUMB_OFFSET: type = "THUMB_OFFSET"; break;
12292 default: type = _("<unknown>"); break;
12293 }
12294 as_bad_where (fixp->fx_file, fixp->fx_line,
12295 _("cannot represent %s relocation in this object file format"),
12296 type);
12297 return NULL;
12298 }
12299 }
12300
12301 #ifdef OBJ_ELF
12302 if ((code == BFD_RELOC_32_PCREL || code == BFD_RELOC_32)
12303 && GOT_symbol
12304 && fixp->fx_addsy == GOT_symbol)
12305 {
12306 code = BFD_RELOC_ARM_GOTPC;
12307 reloc->addend = fixp->fx_offset = reloc->address;
12308 }
12309 #endif
12310
12311 reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
12312
12313 if (reloc->howto == NULL)
12314 {
12315 as_bad_where (fixp->fx_file, fixp->fx_line,
12316 _("cannot represent %s relocation in this object file format"),
12317 bfd_get_reloc_code_name (code));
12318 return NULL;
12319 }
12320
12321 /* HACK: Since arm ELF uses Rel instead of Rela, encode the
12322 vtable entry to be used in the relocation's section offset. */
12323 if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
12324 reloc->address = fixp->fx_offset;
12325
12326 return reloc;
12327 }
12328
12329 int
12330 md_estimate_size_before_relax (fragS * fragP ATTRIBUTE_UNUSED,
12331 segT segtype ATTRIBUTE_UNUSED)
12332 {
12333 as_fatal (_("md_estimate_size_before_relax\n"));
12334 return 1;
12335 }
12336
12337 /* We need to be able to fix up arbitrary expressions in some statements.
12338 This is so that we can handle symbols that are an arbitrary distance from
12339 the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
12340 which returns part of an address in a form which will be valid for
12341 a data instruction. We do this by pushing the expression into a symbol
12342 in the expr_section, and creating a fix for that. */
12343
12344 static void
12345 fix_new_arm (fragS * frag,
12346 int where,
12347 short int size,
12348 expressionS * exp,
12349 int pc_rel,
12350 int reloc)
12351 {
12352 fixS * new_fix;
12353 arm_fix_data * arm_data;
12354
12355 switch (exp->X_op)
12356 {
12357 case O_constant:
12358 case O_symbol:
12359 case O_add:
12360 case O_subtract:
12361 new_fix = fix_new_exp (frag, where, size, exp, pc_rel, reloc);
12362 break;
12363
12364 default:
12365 new_fix = fix_new (frag, where, size, make_expr_symbol (exp), 0,
12366 pc_rel, reloc);
12367 break;
12368 }
12369
12370 /* Mark whether the fix is to a THUMB instruction, or an ARM
12371 instruction. */
12372 arm_data = obstack_alloc (& notes, sizeof (arm_fix_data));
12373 new_fix->tc_fix_data = (PTR) arm_data;
12374 arm_data->thumb_mode = thumb_mode;
12375 }
12376
12377 static void
12378 output_inst (const char * str)
12379 {
12380 char * to = NULL;
12381
12382 if (inst.error)
12383 {
12384 as_bad ("%s -- `%s'", inst.error, str);
12385 return;
12386 }
12387
12388 to = frag_more (inst.size);
12389
12390 if (thumb_mode && (inst.size > THUMB_SIZE))
12391 {
12392 assert (inst.size == (2 * THUMB_SIZE));
12393 md_number_to_chars (to, inst.instruction >> 16, THUMB_SIZE);
12394 md_number_to_chars (to + THUMB_SIZE, inst.instruction, THUMB_SIZE);
12395 }
12396 else if (inst.size > INSN_SIZE)
12397 {
12398 assert (inst.size == (2 * INSN_SIZE));
12399 md_number_to_chars (to, inst.instruction, INSN_SIZE);
12400 md_number_to_chars (to + INSN_SIZE, inst.instruction, INSN_SIZE);
12401 }
12402 else
12403 md_number_to_chars (to, inst.instruction, inst.size);
12404
12405 if (inst.reloc.type != BFD_RELOC_NONE)
12406 fix_new_arm (frag_now, to - frag_now->fr_literal,
12407 inst.size, & inst.reloc.exp, inst.reloc.pc_rel,
12408 inst.reloc.type);
12409
12410 #ifdef OBJ_ELF
12411 dwarf2_emit_insn (inst.size);
12412 #endif
12413 }
12414
12415 void
12416 md_assemble (char * str)
12417 {
12418 char c;
12419 char *p;
12420 char *start;
12421
12422 /* Align the instruction.
12423 This may not be the right thing to do but ... */
12424 #if 0
12425 arm_align (2, 0);
12426 #endif
12427
12428 /* Align the previous label if needed. */
12429 if (last_label_seen != NULL)
12430 {
12431 symbol_set_frag (last_label_seen, frag_now);
12432 S_SET_VALUE (last_label_seen, (valueT) frag_now_fix ());
12433 S_SET_SEGMENT (last_label_seen, now_seg);
12434 }
12435
12436 memset (&inst, '\0', sizeof (inst));
12437 inst.reloc.type = BFD_RELOC_NONE;
12438
12439 skip_whitespace (str);
12440
12441 /* Scan up to the end of the op-code, which must end in white space or
12442 end of string. */
12443 for (start = p = str; *p != '\0'; p++)
12444 if (*p == ' ')
12445 break;
12446
12447 if (p == str)
12448 {
12449 as_bad (_("no operator -- statement `%s'\n"), str);
12450 return;
12451 }
12452
12453 if (thumb_mode)
12454 {
12455 const struct thumb_opcode * opcode;
12456
12457 c = *p;
12458 *p = '\0';
12459 opcode = (const struct thumb_opcode *) hash_find (arm_tops_hsh, str);
12460 *p = c;
12461
12462 if (opcode)
12463 {
12464 /* Check that this instruction is supported for this CPU. */
12465 if (thumb_mode == 1 && (opcode->variant & cpu_variant) == 0)
12466 {
12467 as_bad (_("selected processor does not support `%s'"), str);
12468 return;
12469 }
12470
12471 mapping_state (MAP_THUMB);
12472 inst.instruction = opcode->value;
12473 inst.size = opcode->size;
12474 opcode->parms (p);
12475 output_inst (str);
12476 return;
12477 }
12478 }
12479 else
12480 {
12481 const struct asm_opcode * opcode;
12482
12483 c = *p;
12484 *p = '\0';
12485 opcode = (const struct asm_opcode *) hash_find (arm_ops_hsh, str);
12486 *p = c;
12487
12488 if (opcode)
12489 {
12490 /* Check that this instruction is supported for this CPU. */
12491 if ((opcode->variant & cpu_variant) == 0)
12492 {
12493 as_bad (_("selected processor does not support `%s'"), str);
12494 return;
12495 }
12496
12497 mapping_state (MAP_ARM);
12498 inst.instruction = opcode->value;
12499 inst.size = INSN_SIZE;
12500 opcode->parms (p);
12501 output_inst (str);
12502 return;
12503 }
12504 }
12505
12506 /* It wasn't an instruction, but it might be a register alias of the form
12507 alias .req reg. */
12508 if (create_register_alias (str, p))
12509 return;
12510
12511 as_bad (_("bad instruction `%s'"), start);
12512 }
12513
12514 /* md_parse_option
12515 Invocation line includes a switch not recognized by the base assembler.
12516 See if it's a processor-specific option.
12517
12518 This routine is somewhat complicated by the need for backwards
12519 compatibility (since older releases of gcc can't be changed).
12520 The new options try to make the interface as compatible as
12521 possible with GCC.
12522
12523 New options (supported) are:
12524
12525 -mcpu=<cpu name> Assemble for selected processor
12526 -march=<architecture name> Assemble for selected architecture
12527 -mfpu=<fpu architecture> Assemble for selected FPU.
12528 -EB/-mbig-endian Big-endian
12529 -EL/-mlittle-endian Little-endian
12530 -k Generate PIC code
12531 -mthumb Start in Thumb mode
12532 -mthumb-interwork Code supports ARM/Thumb interworking
12533
12534 For now we will also provide support for:
12535
12536 -mapcs-32 32-bit Program counter
12537 -mapcs-26 26-bit Program counter
12538 -macps-float Floats passed in FP registers
12539 -mapcs-reentrant Reentrant code
12540 -matpcs
12541 (sometime these will probably be replaced with -mapcs=<list of options>
12542 and -matpcs=<list of options>)
12543
12544 The remaining options are only supported for back-wards compatibility.
12545 Cpu variants, the arm part is optional:
12546 -m[arm]1 Currently not supported.
12547 -m[arm]2, -m[arm]250 Arm 2 and Arm 250 processor
12548 -m[arm]3 Arm 3 processor
12549 -m[arm]6[xx], Arm 6 processors
12550 -m[arm]7[xx][t][[d]m] Arm 7 processors
12551 -m[arm]8[10] Arm 8 processors
12552 -m[arm]9[20][tdmi] Arm 9 processors
12553 -mstrongarm[110[0]] StrongARM processors
12554 -mxscale XScale processors
12555 -m[arm]v[2345[t[e]]] Arm architectures
12556 -mall All (except the ARM1)
12557 FP variants:
12558 -mfpa10, -mfpa11 FPA10 and 11 co-processor instructions
12559 -mfpe-old (No float load/store multiples)
12560 -mvfpxd VFP Single precision
12561 -mvfp All VFP
12562 -mno-fpu Disable all floating point instructions
12563
12564 The following CPU names are recognized:
12565 arm1, arm2, arm250, arm3, arm6, arm600, arm610, arm620,
12566 arm7, arm7m, arm7d, arm7dm, arm7di, arm7dmi, arm70, arm700,
12567 arm700i, arm710 arm710t, arm720, arm720t, arm740t, arm710c,
12568 arm7100, arm7500, arm7500fe, arm7tdmi, arm8, arm810, arm9,
12569 arm920, arm920t, arm940t, arm946, arm966, arm9tdmi, arm9e,
12570 arm10t arm10e, arm1020t, arm1020e, arm10200e,
12571 strongarm, strongarm110, strongarm1100, strongarm1110, xscale.
12572
12573 */
12574
12575 const char * md_shortopts = "m:k";
12576
12577 #ifdef ARM_BI_ENDIAN
12578 #define OPTION_EB (OPTION_MD_BASE + 0)
12579 #define OPTION_EL (OPTION_MD_BASE + 1)
12580 #else
12581 #if TARGET_BYTES_BIG_ENDIAN
12582 #define OPTION_EB (OPTION_MD_BASE + 0)
12583 #else
12584 #define OPTION_EL (OPTION_MD_BASE + 1)
12585 #endif
12586 #endif
12587
12588 struct option md_longopts[] =
12589 {
12590 #ifdef OPTION_EB
12591 {"EB", no_argument, NULL, OPTION_EB},
12592 #endif
12593 #ifdef OPTION_EL
12594 {"EL", no_argument, NULL, OPTION_EL},
12595 #endif
12596 {NULL, no_argument, NULL, 0}
12597 };
12598
12599 size_t md_longopts_size = sizeof (md_longopts);
12600
12601 struct arm_option_table
12602 {
12603 char *option; /* Option name to match. */
12604 char *help; /* Help information. */
12605 int *var; /* Variable to change. */
12606 int value; /* What to change it to. */
12607 char *deprecated; /* If non-null, print this message. */
12608 };
12609
12610 struct arm_option_table arm_opts[] =
12611 {
12612 {"k", N_("generate PIC code"), &pic_code, 1, NULL},
12613 {"mthumb", N_("assemble Thumb code"), &thumb_mode, 1, NULL},
12614 {"mthumb-interwork", N_("support ARM/Thumb interworking"),
12615 &support_interwork, 1, NULL},
12616 {"moabi", N_("use old ABI (ELF only)"), &target_oabi, 1, NULL},
12617 {"mapcs-32", N_("code uses 32-bit program counter"), &uses_apcs_26, 0, NULL},
12618 {"mapcs-26", N_("code uses 26-bit program counter"), &uses_apcs_26, 1, NULL},
12619 {"mapcs-float", N_("floating point args are in fp regs"), &uses_apcs_float,
12620 1, NULL},
12621 {"mapcs-reentrant", N_("re-entrant code"), &pic_code, 1, NULL},
12622 {"matpcs", N_("code is ATPCS conformant"), &atpcs, 1, NULL},
12623 {"mbig-endian", N_("assemble for big-endian"), &target_big_endian, 1, NULL},
12624 {"mlittle-endian", N_("assemble for little-endian"), &target_big_endian, 1,
12625 NULL},
12626
12627 /* These are recognized by the assembler, but have no affect on code. */
12628 {"mapcs-frame", N_("use frame pointer"), NULL, 0, NULL},
12629 {"mapcs-stack-check", N_("use stack size checking"), NULL, 0, NULL},
12630
12631 /* DON'T add any new processors to this list -- we want the whole list
12632 to go away... Add them to the processors table instead. */
12633 {"marm1", NULL, &legacy_cpu, ARM_ARCH_V1, N_("use -mcpu=arm1")},
12634 {"m1", NULL, &legacy_cpu, ARM_ARCH_V1, N_("use -mcpu=arm1")},
12635 {"marm2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -mcpu=arm2")},
12636 {"m2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -mcpu=arm2")},
12637 {"marm250", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm250")},
12638 {"m250", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm250")},
12639 {"marm3", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm3")},
12640 {"m3", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm3")},
12641 {"marm6", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm6")},
12642 {"m6", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm6")},
12643 {"marm600", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm600")},
12644 {"m600", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm600")},
12645 {"marm610", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm610")},
12646 {"m610", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm610")},
12647 {"marm620", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm620")},
12648 {"m620", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm620")},
12649 {"marm7", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7")},
12650 {"m7", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7")},
12651 {"marm70", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm70")},
12652 {"m70", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm70")},
12653 {"marm700", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700")},
12654 {"m700", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700")},
12655 {"marm700i", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700i")},
12656 {"m700i", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700i")},
12657 {"marm710", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710")},
12658 {"m710", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710")},
12659 {"marm710c", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710c")},
12660 {"m710c", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710c")},
12661 {"marm720", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm720")},
12662 {"m720", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm720")},
12663 {"marm7d", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7d")},
12664 {"m7d", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7d")},
12665 {"marm7di", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7di")},
12666 {"m7di", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7di")},
12667 {"marm7m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7m")},
12668 {"m7m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7m")},
12669 {"marm7dm", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dm")},
12670 {"m7dm", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dm")},
12671 {"marm7dmi", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dmi")},
12672 {"m7dmi", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dmi")},
12673 {"marm7100", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7100")},
12674 {"m7100", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7100")},
12675 {"marm7500", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500")},
12676 {"m7500", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500")},
12677 {"marm7500fe", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500fe")},
12678 {"m7500fe", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500fe")},
12679 {"marm7t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
12680 {"m7t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
12681 {"marm7tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
12682 {"m7tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
12683 {"marm710t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm710t")},
12684 {"m710t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm710t")},
12685 {"marm720t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm720t")},
12686 {"m720t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm720t")},
12687 {"marm740t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm740t")},
12688 {"m740t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm740t")},
12689 {"marm8", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm8")},
12690 {"m8", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm8")},
12691 {"marm810", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm810")},
12692 {"m810", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm810")},
12693 {"marm9", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9")},
12694 {"m9", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9")},
12695 {"marm9tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9tdmi")},
12696 {"m9tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9tdmi")},
12697 {"marm920", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm920")},
12698 {"m920", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm920")},
12699 {"marm940", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm940")},
12700 {"m940", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm940")},
12701 {"mstrongarm", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=strongarm")},
12702 {"mstrongarm110", NULL, &legacy_cpu, ARM_ARCH_V4,
12703 N_("use -mcpu=strongarm110")},
12704 {"mstrongarm1100", NULL, &legacy_cpu, ARM_ARCH_V4,
12705 N_("use -mcpu=strongarm1100")},
12706 {"mstrongarm1110", NULL, &legacy_cpu, ARM_ARCH_V4,
12707 N_("use -mcpu=strongarm1110")},
12708 {"mxscale", NULL, &legacy_cpu, ARM_ARCH_XSCALE, N_("use -mcpu=xscale")},
12709 {"miwmmxt", NULL, &legacy_cpu, ARM_ARCH_IWMMXT, N_("use -mcpu=iwmmxt")},
12710 {"mall", NULL, &legacy_cpu, ARM_ANY, N_("use -mcpu=all")},
12711
12712 /* Architecture variants -- don't add any more to this list either. */
12713 {"mv2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -march=armv2")},
12714 {"marmv2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -march=armv2")},
12715 {"mv2a", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -march=armv2a")},
12716 {"marmv2a", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -march=armv2a")},
12717 {"mv3", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -march=armv3")},
12718 {"marmv3", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -march=armv3")},
12719 {"mv3m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -march=armv3m")},
12720 {"marmv3m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -march=armv3m")},
12721 {"mv4", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -march=armv4")},
12722 {"marmv4", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -march=armv4")},
12723 {"mv4t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -march=armv4t")},
12724 {"marmv4t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -march=armv4t")},
12725 {"mv5", NULL, &legacy_cpu, ARM_ARCH_V5, N_("use -march=armv5")},
12726 {"marmv5", NULL, &legacy_cpu, ARM_ARCH_V5, N_("use -march=armv5")},
12727 {"mv5t", NULL, &legacy_cpu, ARM_ARCH_V5T, N_("use -march=armv5t")},
12728 {"marmv5t", NULL, &legacy_cpu, ARM_ARCH_V5T, N_("use -march=armv5t")},
12729 {"mv5e", NULL, &legacy_cpu, ARM_ARCH_V5TE, N_("use -march=armv5te")},
12730 {"marmv5e", NULL, &legacy_cpu, ARM_ARCH_V5TE, N_("use -march=armv5te")},
12731
12732 /* Floating point variants -- don't add any more to this list either. */
12733 {"mfpe-old", NULL, &legacy_fpu, FPU_ARCH_FPE, N_("use -mfpu=fpe")},
12734 {"mfpa10", NULL, &legacy_fpu, FPU_ARCH_FPA, N_("use -mfpu=fpa10")},
12735 {"mfpa11", NULL, &legacy_fpu, FPU_ARCH_FPA, N_("use -mfpu=fpa11")},
12736 {"mno-fpu", NULL, &legacy_fpu, 0,
12737 N_("use either -mfpu=softfpa or -mfpu=softvfp")},
12738
12739 {NULL, NULL, NULL, 0, NULL}
12740 };
12741
12742 struct arm_cpu_option_table
12743 {
12744 char *name;
12745 int value;
12746 /* For some CPUs we assume an FPU unless the user explicitly sets
12747 -mfpu=... */
12748 int default_fpu;
12749 };
12750
12751 /* This list should, at a minimum, contain all the cpu names
12752 recognized by GCC. */
12753 static struct arm_cpu_option_table arm_cpus[] =
12754 {
12755 {"all", ARM_ANY, FPU_ARCH_FPA},
12756 {"arm1", ARM_ARCH_V1, FPU_ARCH_FPA},
12757 {"arm2", ARM_ARCH_V2, FPU_ARCH_FPA},
12758 {"arm250", ARM_ARCH_V2S, FPU_ARCH_FPA},
12759 {"arm3", ARM_ARCH_V2S, FPU_ARCH_FPA},
12760 {"arm6", ARM_ARCH_V3, FPU_ARCH_FPA},
12761 {"arm60", ARM_ARCH_V3, FPU_ARCH_FPA},
12762 {"arm600", ARM_ARCH_V3, FPU_ARCH_FPA},
12763 {"arm610", ARM_ARCH_V3, FPU_ARCH_FPA},
12764 {"arm620", ARM_ARCH_V3, FPU_ARCH_FPA},
12765 {"arm7", ARM_ARCH_V3, FPU_ARCH_FPA},
12766 {"arm7m", ARM_ARCH_V3M, FPU_ARCH_FPA},
12767 {"arm7d", ARM_ARCH_V3, FPU_ARCH_FPA},
12768 {"arm7dm", ARM_ARCH_V3M, FPU_ARCH_FPA},
12769 {"arm7di", ARM_ARCH_V3, FPU_ARCH_FPA},
12770 {"arm7dmi", ARM_ARCH_V3M, FPU_ARCH_FPA},
12771 {"arm70", ARM_ARCH_V3, FPU_ARCH_FPA},
12772 {"arm700", ARM_ARCH_V3, FPU_ARCH_FPA},
12773 {"arm700i", ARM_ARCH_V3, FPU_ARCH_FPA},
12774 {"arm710", ARM_ARCH_V3, FPU_ARCH_FPA},
12775 {"arm710t", ARM_ARCH_V4T, FPU_ARCH_FPA},
12776 {"arm720", ARM_ARCH_V3, FPU_ARCH_FPA},
12777 {"arm720t", ARM_ARCH_V4T, FPU_ARCH_FPA},
12778 {"arm740t", ARM_ARCH_V4T, FPU_ARCH_FPA},
12779 {"arm710c", ARM_ARCH_V3, FPU_ARCH_FPA},
12780 {"arm7100", ARM_ARCH_V3, FPU_ARCH_FPA},
12781 {"arm7500", ARM_ARCH_V3, FPU_ARCH_FPA},
12782 {"arm7500fe", ARM_ARCH_V3, FPU_ARCH_FPA},
12783 {"arm7t", ARM_ARCH_V4T, FPU_ARCH_FPA},
12784 {"arm7tdmi", ARM_ARCH_V4T, FPU_ARCH_FPA},
12785 {"arm7tdmi-s", ARM_ARCH_V4T, FPU_ARCH_FPA},
12786 {"arm8", ARM_ARCH_V4, FPU_ARCH_FPA},
12787 {"arm810", ARM_ARCH_V4, FPU_ARCH_FPA},
12788 {"strongarm", ARM_ARCH_V4, FPU_ARCH_FPA},
12789 {"strongarm1", ARM_ARCH_V4, FPU_ARCH_FPA},
12790 {"strongarm110", ARM_ARCH_V4, FPU_ARCH_FPA},
12791 {"strongarm1100", ARM_ARCH_V4, FPU_ARCH_FPA},
12792 {"strongarm1110", ARM_ARCH_V4, FPU_ARCH_FPA},
12793 {"arm9", ARM_ARCH_V4T, FPU_ARCH_FPA},
12794 {"arm920", ARM_ARCH_V4T, FPU_ARCH_FPA},
12795 {"arm920t", ARM_ARCH_V4T, FPU_ARCH_FPA},
12796 {"arm922t", ARM_ARCH_V4T, FPU_ARCH_FPA},
12797 {"arm940t", ARM_ARCH_V4T, FPU_ARCH_FPA},
12798 {"arm9tdmi", ARM_ARCH_V4T, FPU_ARCH_FPA},
12799 /* For V5 or later processors we default to using VFP; but the user
12800 should really set the FPU type explicitly. */
12801 {"arm9e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
12802 {"arm9e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
12803 {"arm926ej", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
12804 {"arm926ejs", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
12805 {"arm926ej-s", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
12806 {"arm946e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
12807 {"arm946e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
12808 {"arm966e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
12809 {"arm966e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
12810 {"arm10t", ARM_ARCH_V5T, FPU_ARCH_VFP_V1},
12811 {"arm10e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
12812 {"arm1020", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
12813 {"arm1020t", ARM_ARCH_V5T, FPU_ARCH_VFP_V1},
12814 {"arm1020e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
12815 {"arm1026ejs", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
12816 {"arm1026ej-s", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
12817 {"arm1136js", ARM_ARCH_V6, FPU_NONE},
12818 {"arm1136j-s", ARM_ARCH_V6, FPU_NONE},
12819 {"arm1136jfs", ARM_ARCH_V6, FPU_ARCH_VFP_V2},
12820 {"arm1136jf-s", ARM_ARCH_V6, FPU_ARCH_VFP_V2},
12821 {"mpcore", ARM_ARCH_V6K, FPU_ARCH_VFP_V2},
12822 {"mpcorenovfp", ARM_ARCH_V6K, FPU_NONE},
12823 {"arm1176jz-s", ARM_ARCH_V6ZK, FPU_NONE},
12824 {"arm1176jzf-s", ARM_ARCH_V6ZK, FPU_ARCH_VFP_V2},
12825 /* ??? XSCALE is really an architecture. */
12826 {"xscale", ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2},
12827 /* ??? iwmmxt is not a processor. */
12828 {"iwmmxt", ARM_ARCH_IWMMXT, FPU_ARCH_VFP_V2},
12829 {"i80200", ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2},
12830 /* Maverick */
12831 {"ep9312", ARM_ARCH_V4T | ARM_CEXT_MAVERICK, FPU_ARCH_MAVERICK},
12832 {NULL, 0, 0}
12833 };
12834
12835 struct arm_arch_option_table
12836 {
12837 char *name;
12838 int value;
12839 int default_fpu;
12840 };
12841
12842 /* This list should, at a minimum, contain all the architecture names
12843 recognized by GCC. */
12844 static struct arm_arch_option_table arm_archs[] =
12845 {
12846 {"all", ARM_ANY, FPU_ARCH_FPA},
12847 {"armv1", ARM_ARCH_V1, FPU_ARCH_FPA},
12848 {"armv2", ARM_ARCH_V2, FPU_ARCH_FPA},
12849 {"armv2a", ARM_ARCH_V2S, FPU_ARCH_FPA},
12850 {"armv2s", ARM_ARCH_V2S, FPU_ARCH_FPA},
12851 {"armv3", ARM_ARCH_V3, FPU_ARCH_FPA},
12852 {"armv3m", ARM_ARCH_V3M, FPU_ARCH_FPA},
12853 {"armv4", ARM_ARCH_V4, FPU_ARCH_FPA},
12854 {"armv4xm", ARM_ARCH_V4xM, FPU_ARCH_FPA},
12855 {"armv4t", ARM_ARCH_V4T, FPU_ARCH_FPA},
12856 {"armv4txm", ARM_ARCH_V4TxM, FPU_ARCH_FPA},
12857 {"armv5", ARM_ARCH_V5, FPU_ARCH_VFP},
12858 {"armv5t", ARM_ARCH_V5T, FPU_ARCH_VFP},
12859 {"armv5txm", ARM_ARCH_V5TxM, FPU_ARCH_VFP},
12860 {"armv5te", ARM_ARCH_V5TE, FPU_ARCH_VFP},
12861 {"armv5texp", ARM_ARCH_V5TExP, FPU_ARCH_VFP},
12862 {"armv5tej", ARM_ARCH_V5TEJ, FPU_ARCH_VFP},
12863 {"armv6", ARM_ARCH_V6, FPU_ARCH_VFP},
12864 {"armv6j", ARM_ARCH_V6, FPU_ARCH_VFP},
12865 {"armv6k", ARM_ARCH_V6K, FPU_ARCH_VFP},
12866 {"armv6z", ARM_ARCH_V6Z, FPU_ARCH_VFP},
12867 {"armv6zk", ARM_ARCH_V6ZK, FPU_ARCH_VFP},
12868 {"xscale", ARM_ARCH_XSCALE, FPU_ARCH_VFP},
12869 {"iwmmxt", ARM_ARCH_IWMMXT, FPU_ARCH_VFP},
12870 {NULL, 0, 0}
12871 };
12872
12873 /* ISA extensions in the co-processor space. */
12874 struct arm_arch_extension_table
12875 {
12876 char *name;
12877 int value;
12878 };
12879
12880 static struct arm_arch_extension_table arm_extensions[] =
12881 {
12882 {"maverick", ARM_CEXT_MAVERICK},
12883 {"xscale", ARM_CEXT_XSCALE},
12884 {"iwmmxt", ARM_CEXT_IWMMXT},
12885 {NULL, 0}
12886 };
12887
12888 struct arm_fpu_option_table
12889 {
12890 char *name;
12891 int value;
12892 };
12893
12894 /* This list should, at a minimum, contain all the fpu names
12895 recognized by GCC. */
12896 static struct arm_fpu_option_table arm_fpus[] =
12897 {
12898 {"softfpa", FPU_NONE},
12899 {"fpe", FPU_ARCH_FPE},
12900 {"fpe2", FPU_ARCH_FPE},
12901 {"fpe3", FPU_ARCH_FPA}, /* Third release supports LFM/SFM. */
12902 {"fpa", FPU_ARCH_FPA},
12903 {"fpa10", FPU_ARCH_FPA},
12904 {"fpa11", FPU_ARCH_FPA},
12905 {"arm7500fe", FPU_ARCH_FPA},
12906 {"softvfp", FPU_ARCH_VFP},
12907 {"softvfp+vfp", FPU_ARCH_VFP_V2},
12908 {"vfp", FPU_ARCH_VFP_V2},
12909 {"vfp9", FPU_ARCH_VFP_V2},
12910 {"vfp10", FPU_ARCH_VFP_V2},
12911 {"vfp10-r0", FPU_ARCH_VFP_V1},
12912 {"vfpxd", FPU_ARCH_VFP_V1xD},
12913 {"arm1020t", FPU_ARCH_VFP_V1},
12914 {"arm1020e", FPU_ARCH_VFP_V2},
12915 {"arm1136jfs", FPU_ARCH_VFP_V2},
12916 {"arm1136jf-s", FPU_ARCH_VFP_V2},
12917 {"maverick", FPU_ARCH_MAVERICK},
12918 {NULL, 0}
12919 };
12920
12921 struct arm_float_abi_option_table
12922 {
12923 char *name;
12924 int value;
12925 };
12926
12927 static struct arm_float_abi_option_table arm_float_abis[] =
12928 {
12929 {"hard", ARM_FLOAT_ABI_HARD},
12930 {"softfp", ARM_FLOAT_ABI_SOFTFP},
12931 {"soft", ARM_FLOAT_ABI_SOFT},
12932 {NULL, 0}
12933 };
12934
12935 struct arm_eabi_option_table
12936 {
12937 char *name;
12938 unsigned int value;
12939 };
12940
12941 #ifdef OBJ_ELF
12942 /* We only know hot to output GNU and ver 3 (AAELF) formats. */
12943 static struct arm_eabi_option_table arm_eabis[] =
12944 {
12945 {"gnu", EF_ARM_EABI_UNKNOWN},
12946 {"3", EF_ARM_EABI_VER3},
12947 {NULL, 0}
12948 };
12949 #endif
12950
12951 struct arm_long_option_table
12952 {
12953 char * option; /* Substring to match. */
12954 char * help; /* Help information. */
12955 int (* func) (char * subopt); /* Function to decode sub-option. */
12956 char * deprecated; /* If non-null, print this message. */
12957 };
12958
12959 static int
12960 arm_parse_extension (char * str, int * opt_p)
12961 {
12962 while (str != NULL && *str != 0)
12963 {
12964 struct arm_arch_extension_table * opt;
12965 char * ext;
12966 int optlen;
12967
12968 if (*str != '+')
12969 {
12970 as_bad (_("invalid architectural extension"));
12971 return 0;
12972 }
12973
12974 str++;
12975 ext = strchr (str, '+');
12976
12977 if (ext != NULL)
12978 optlen = ext - str;
12979 else
12980 optlen = strlen (str);
12981
12982 if (optlen == 0)
12983 {
12984 as_bad (_("missing architectural extension"));
12985 return 0;
12986 }
12987
12988 for (opt = arm_extensions; opt->name != NULL; opt++)
12989 if (strncmp (opt->name, str, optlen) == 0)
12990 {
12991 *opt_p |= opt->value;
12992 break;
12993 }
12994
12995 if (opt->name == NULL)
12996 {
12997 as_bad (_("unknown architectural extnsion `%s'"), str);
12998 return 0;
12999 }
13000
13001 str = ext;
13002 };
13003
13004 return 1;
13005 }
13006
13007 static int
13008 arm_parse_cpu (char * str)
13009 {
13010 struct arm_cpu_option_table * opt;
13011 char * ext = strchr (str, '+');
13012 int optlen;
13013
13014 if (ext != NULL)
13015 optlen = ext - str;
13016 else
13017 optlen = strlen (str);
13018
13019 if (optlen == 0)
13020 {
13021 as_bad (_("missing cpu name `%s'"), str);
13022 return 0;
13023 }
13024
13025 for (opt = arm_cpus; opt->name != NULL; opt++)
13026 if (strncmp (opt->name, str, optlen) == 0)
13027 {
13028 mcpu_cpu_opt = opt->value;
13029 mcpu_fpu_opt = opt->default_fpu;
13030
13031 if (ext != NULL)
13032 return arm_parse_extension (ext, &mcpu_cpu_opt);
13033
13034 return 1;
13035 }
13036
13037 as_bad (_("unknown cpu `%s'"), str);
13038 return 0;
13039 }
13040
13041 static int
13042 arm_parse_arch (char * str)
13043 {
13044 struct arm_arch_option_table *opt;
13045 char *ext = strchr (str, '+');
13046 int optlen;
13047
13048 if (ext != NULL)
13049 optlen = ext - str;
13050 else
13051 optlen = strlen (str);
13052
13053 if (optlen == 0)
13054 {
13055 as_bad (_("missing architecture name `%s'"), str);
13056 return 0;
13057 }
13058
13059
13060 for (opt = arm_archs; opt->name != NULL; opt++)
13061 if (streq (opt->name, str))
13062 {
13063 march_cpu_opt = opt->value;
13064 march_fpu_opt = opt->default_fpu;
13065
13066 if (ext != NULL)
13067 return arm_parse_extension (ext, &march_cpu_opt);
13068
13069 return 1;
13070 }
13071
13072 as_bad (_("unknown architecture `%s'\n"), str);
13073 return 0;
13074 }
13075
13076 static int
13077 arm_parse_fpu (char * str)
13078 {
13079 struct arm_fpu_option_table * opt;
13080
13081 for (opt = arm_fpus; opt->name != NULL; opt++)
13082 if (streq (opt->name, str))
13083 {
13084 mfpu_opt = opt->value;
13085 return 1;
13086 }
13087
13088 as_bad (_("unknown floating point format `%s'\n"), str);
13089 return 0;
13090 }
13091
13092 static int
13093 arm_parse_float_abi (char * str)
13094 {
13095 struct arm_float_abi_option_table * opt;
13096
13097 for (opt = arm_float_abis; opt->name != NULL; opt++)
13098 if (streq (opt->name, str))
13099 {
13100 mfloat_abi_opt = opt->value;
13101 return 1;
13102 }
13103
13104 as_bad (_("unknown floating point abi `%s'\n"), str);
13105 return 0;
13106 }
13107
13108 #ifdef OBJ_ELF
13109 static int
13110 arm_parse_eabi (char * str)
13111 {
13112 struct arm_eabi_option_table *opt;
13113
13114 for (opt = arm_eabis; opt->name != NULL; opt++)
13115 if (streq (opt->name, str))
13116 {
13117 meabi_flags = opt->value;
13118 return 1;
13119 }
13120 as_bad (_("unknown EABI `%s'\n"), str);
13121 return 0;
13122 }
13123 #endif
13124
13125 struct arm_long_option_table arm_long_opts[] =
13126 {
13127 {"mcpu=", N_("<cpu name>\t assemble for CPU <cpu name>"),
13128 arm_parse_cpu, NULL},
13129 {"march=", N_("<arch name>\t assemble for architecture <arch name>"),
13130 arm_parse_arch, NULL},
13131 {"mfpu=", N_("<fpu name>\t assemble for FPU architecture <fpu name>"),
13132 arm_parse_fpu, NULL},
13133 {"mfloat-abi=", N_("<abi>\t assemble for floating point ABI <abi>"),
13134 arm_parse_float_abi, NULL},
13135 #ifdef OBJ_ELF
13136 {"meabi=", N_("<ver>\t assemble for eabi version <ver>"),
13137 arm_parse_eabi, NULL},
13138 #endif
13139 {NULL, NULL, 0, NULL}
13140 };
13141
13142 int
13143 md_parse_option (int c, char * arg)
13144 {
13145 struct arm_option_table *opt;
13146 struct arm_long_option_table *lopt;
13147
13148 switch (c)
13149 {
13150 #ifdef OPTION_EB
13151 case OPTION_EB:
13152 target_big_endian = 1;
13153 break;
13154 #endif
13155
13156 #ifdef OPTION_EL
13157 case OPTION_EL:
13158 target_big_endian = 0;
13159 break;
13160 #endif
13161
13162 case 'a':
13163 /* Listing option. Just ignore these, we don't support additional
13164 ones. */
13165 return 0;
13166
13167 default:
13168 for (opt = arm_opts; opt->option != NULL; opt++)
13169 {
13170 if (c == opt->option[0]
13171 && ((arg == NULL && opt->option[1] == 0)
13172 || streq (arg, opt->option + 1)))
13173 {
13174 #if WARN_DEPRECATED
13175 /* If the option is deprecated, tell the user. */
13176 if (opt->deprecated != NULL)
13177 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c,
13178 arg ? arg : "", _(opt->deprecated));
13179 #endif
13180
13181 if (opt->var != NULL)
13182 *opt->var = opt->value;
13183
13184 return 1;
13185 }
13186 }
13187
13188 for (lopt = arm_long_opts; lopt->option != NULL; lopt++)
13189 {
13190 /* These options are expected to have an argument. */
13191 if (c == lopt->option[0]
13192 && arg != NULL
13193 && strncmp (arg, lopt->option + 1,
13194 strlen (lopt->option + 1)) == 0)
13195 {
13196 #if WARN_DEPRECATED
13197 /* If the option is deprecated, tell the user. */
13198 if (lopt->deprecated != NULL)
13199 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c, arg,
13200 _(lopt->deprecated));
13201 #endif
13202
13203 /* Call the sup-option parser. */
13204 return lopt->func (arg + strlen (lopt->option) - 1);
13205 }
13206 }
13207
13208 return 0;
13209 }
13210
13211 return 1;
13212 }
13213
13214 void
13215 md_show_usage (FILE * fp)
13216 {
13217 struct arm_option_table *opt;
13218 struct arm_long_option_table *lopt;
13219
13220 fprintf (fp, _(" ARM-specific assembler options:\n"));
13221
13222 for (opt = arm_opts; opt->option != NULL; opt++)
13223 if (opt->help != NULL)
13224 fprintf (fp, " -%-23s%s\n", opt->option, _(opt->help));
13225
13226 for (lopt = arm_long_opts; lopt->option != NULL; lopt++)
13227 if (lopt->help != NULL)
13228 fprintf (fp, " -%s%s\n", lopt->option, _(lopt->help));
13229
13230 #ifdef OPTION_EB
13231 fprintf (fp, _("\
13232 -EB assemble code for a big-endian cpu\n"));
13233 #endif
13234
13235 #ifdef OPTION_EL
13236 fprintf (fp, _("\
13237 -EL assemble code for a little-endian cpu\n"));
13238 #endif
13239 }
13240
13241 /* This fix_new is called by cons via TC_CONS_FIX_NEW. */
13242
13243 void
13244 cons_fix_new_arm (fragS * frag,
13245 int where,
13246 int size,
13247 expressionS * exp)
13248 {
13249 bfd_reloc_code_real_type type;
13250 int pcrel = 0;
13251
13252 /* Pick a reloc.
13253 FIXME: @@ Should look at CPU word size. */
13254 switch (size)
13255 {
13256 case 1:
13257 type = BFD_RELOC_8;
13258 break;
13259 case 2:
13260 type = BFD_RELOC_16;
13261 break;
13262 case 4:
13263 default:
13264 type = BFD_RELOC_32;
13265 break;
13266 case 8:
13267 type = BFD_RELOC_64;
13268 break;
13269 }
13270
13271 fix_new_exp (frag, where, (int) size, exp, pcrel, type);
13272 }
13273
13274 /* A good place to do this, although this was probably not intended
13275 for this kind of use. We need to dump the literal pool before
13276 references are made to a null symbol pointer. */
13277
13278 void
13279 arm_cleanup (void)
13280 {
13281 literal_pool * pool;
13282
13283 for (pool = list_of_pools; pool; pool = pool->next)
13284 {
13285 /* Put it at the end of the relevent section. */
13286 subseg_set (pool->section, pool->sub_section);
13287 #ifdef OBJ_ELF
13288 arm_elf_change_section ();
13289 #endif
13290 s_ltorg (0);
13291 }
13292 }
13293
13294 void
13295 arm_start_line_hook (void)
13296 {
13297 last_label_seen = NULL;
13298 }
13299
13300 void
13301 arm_frob_label (symbolS * sym)
13302 {
13303 last_label_seen = sym;
13304
13305 ARM_SET_THUMB (sym, thumb_mode);
13306
13307 #if defined OBJ_COFF || defined OBJ_ELF
13308 ARM_SET_INTERWORK (sym, support_interwork);
13309 #endif
13310
13311 /* Note - do not allow local symbols (.Lxxx) to be labeled
13312 as Thumb functions. This is because these labels, whilst
13313 they exist inside Thumb code, are not the entry points for
13314 possible ARM->Thumb calls. Also, these labels can be used
13315 as part of a computed goto or switch statement. eg gcc
13316 can generate code that looks like this:
13317
13318 ldr r2, [pc, .Laaa]
13319 lsl r3, r3, #2
13320 ldr r2, [r3, r2]
13321 mov pc, r2
13322
13323 .Lbbb: .word .Lxxx
13324 .Lccc: .word .Lyyy
13325 ..etc...
13326 .Laaa: .word Lbbb
13327
13328 The first instruction loads the address of the jump table.
13329 The second instruction converts a table index into a byte offset.
13330 The third instruction gets the jump address out of the table.
13331 The fourth instruction performs the jump.
13332
13333 If the address stored at .Laaa is that of a symbol which has the
13334 Thumb_Func bit set, then the linker will arrange for this address
13335 to have the bottom bit set, which in turn would mean that the
13336 address computation performed by the third instruction would end
13337 up with the bottom bit set. Since the ARM is capable of unaligned
13338 word loads, the instruction would then load the incorrect address
13339 out of the jump table, and chaos would ensue. */
13340 if (label_is_thumb_function_name
13341 && (S_GET_NAME (sym)[0] != '.' || S_GET_NAME (sym)[1] != 'L')
13342 && (bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
13343 {
13344 /* When the address of a Thumb function is taken the bottom
13345 bit of that address should be set. This will allow
13346 interworking between Arm and Thumb functions to work
13347 correctly. */
13348
13349 THUMB_SET_FUNC (sym, 1);
13350
13351 label_is_thumb_function_name = FALSE;
13352 }
13353 }
13354
13355 /* Adjust the symbol table. This marks Thumb symbols as distinct from
13356 ARM ones. */
13357
13358 void
13359 arm_adjust_symtab (void)
13360 {
13361 #ifdef OBJ_COFF
13362 symbolS * sym;
13363
13364 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
13365 {
13366 if (ARM_IS_THUMB (sym))
13367 {
13368 if (THUMB_IS_FUNC (sym))
13369 {
13370 /* Mark the symbol as a Thumb function. */
13371 if ( S_GET_STORAGE_CLASS (sym) == C_STAT
13372 || S_GET_STORAGE_CLASS (sym) == C_LABEL) /* This can happen! */
13373 S_SET_STORAGE_CLASS (sym, C_THUMBSTATFUNC);
13374
13375 else if (S_GET_STORAGE_CLASS (sym) == C_EXT)
13376 S_SET_STORAGE_CLASS (sym, C_THUMBEXTFUNC);
13377 else
13378 as_bad (_("%s: unexpected function type: %d"),
13379 S_GET_NAME (sym), S_GET_STORAGE_CLASS (sym));
13380 }
13381 else switch (S_GET_STORAGE_CLASS (sym))
13382 {
13383 case C_EXT:
13384 S_SET_STORAGE_CLASS (sym, C_THUMBEXT);
13385 break;
13386 case C_STAT:
13387 S_SET_STORAGE_CLASS (sym, C_THUMBSTAT);
13388 break;
13389 case C_LABEL:
13390 S_SET_STORAGE_CLASS (sym, C_THUMBLABEL);
13391 break;
13392 default:
13393 /* Do nothing. */
13394 break;
13395 }
13396 }
13397
13398 if (ARM_IS_INTERWORK (sym))
13399 coffsymbol (symbol_get_bfdsym (sym))->native->u.syment.n_flags = 0xFF;
13400 }
13401 #endif
13402 #ifdef OBJ_ELF
13403 symbolS * sym;
13404 char bind;
13405
13406 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
13407 {
13408 if (ARM_IS_THUMB (sym))
13409 {
13410 elf_symbol_type * elf_sym;
13411
13412 elf_sym = elf_symbol (symbol_get_bfdsym (sym));
13413 bind = ELF_ST_BIND (elf_sym);
13414
13415 /* If it's a .thumb_func, declare it as so,
13416 otherwise tag label as .code 16. */
13417 if (THUMB_IS_FUNC (sym))
13418 elf_sym->internal_elf_sym.st_info =
13419 ELF_ST_INFO (bind, STT_ARM_TFUNC);
13420 else
13421 elf_sym->internal_elf_sym.st_info =
13422 ELF_ST_INFO (bind, STT_ARM_16BIT);
13423 }
13424 }
13425 #endif
13426 }
13427
13428 int
13429 arm_data_in_code (void)
13430 {
13431 if (thumb_mode && ! strncmp (input_line_pointer + 1, "data:", 5))
13432 {
13433 *input_line_pointer = '/';
13434 input_line_pointer += 5;
13435 *input_line_pointer = 0;
13436 return 1;
13437 }
13438
13439 return 0;
13440 }
13441
13442 char *
13443 arm_canonicalize_symbol_name (char * name)
13444 {
13445 int len;
13446
13447 if (thumb_mode && (len = strlen (name)) > 5
13448 && streq (name + len - 5, "/data"))
13449 *(name + len - 5) = 0;
13450
13451 return name;
13452 }
13453
13454 #if defined OBJ_COFF || defined OBJ_ELF
13455 void
13456 arm_validate_fix (fixS * fixP)
13457 {
13458 /* If the destination of the branch is a defined symbol which does not have
13459 the THUMB_FUNC attribute, then we must be calling a function which has
13460 the (interfacearm) attribute. We look for the Thumb entry point to that
13461 function and change the branch to refer to that function instead. */
13462 if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23
13463 && fixP->fx_addsy != NULL
13464 && S_IS_DEFINED (fixP->fx_addsy)
13465 && ! THUMB_IS_FUNC (fixP->fx_addsy))
13466 {
13467 fixP->fx_addsy = find_real_start (fixP->fx_addsy);
13468 }
13469 }
13470 #endif
13471
13472 int
13473 arm_force_relocation (struct fix * fixp)
13474 {
13475 #if defined (OBJ_COFF) && defined (TE_PE)
13476 if (fixp->fx_r_type == BFD_RELOC_RVA)
13477 return 1;
13478 #endif
13479 #ifdef OBJ_ELF
13480 if (fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH
13481 || fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BLX
13482 || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX
13483 || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23)
13484 return 1;
13485 #endif
13486
13487 /* Resolve these relocations even if the symbol is extern or weak. */
13488 if (fixp->fx_r_type == BFD_RELOC_ARM_IMMEDIATE
13489 || fixp->fx_r_type == BFD_RELOC_ARM_OFFSET_IMM
13490 || fixp->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE)
13491 return 0;
13492
13493 return generic_force_reloc (fixp);
13494 }
13495
13496 #ifdef OBJ_COFF
13497 /* This is a little hack to help the gas/arm/adrl.s test. It prevents
13498 local labels from being added to the output symbol table when they
13499 are used with the ADRL pseudo op. The ADRL relocation should always
13500 be resolved before the binbary is emitted, so it is safe to say that
13501 it is adjustable. */
13502
13503 bfd_boolean
13504 arm_fix_adjustable (fixS * fixP)
13505 {
13506 if (fixP->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE)
13507 return 1;
13508 return 0;
13509 }
13510 #endif
13511
13512 #ifdef OBJ_ELF
13513 /* Relocations against Thumb function names must be left unadjusted,
13514 so that the linker can use this information to correctly set the
13515 bottom bit of their addresses. The MIPS version of this function
13516 also prevents relocations that are mips-16 specific, but I do not
13517 know why it does this.
13518
13519 FIXME:
13520 There is one other problem that ought to be addressed here, but
13521 which currently is not: Taking the address of a label (rather
13522 than a function) and then later jumping to that address. Such
13523 addresses also ought to have their bottom bit set (assuming that
13524 they reside in Thumb code), but at the moment they will not. */
13525
13526 bfd_boolean
13527 arm_fix_adjustable (fixS * fixP)
13528 {
13529 if (fixP->fx_addsy == NULL)
13530 return 1;
13531
13532 if (THUMB_IS_FUNC (fixP->fx_addsy)
13533 && fixP->fx_subsy == NULL)
13534 return 0;
13535
13536 /* We need the symbol name for the VTABLE entries. */
13537 if ( fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
13538 || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
13539 return 0;
13540
13541 /* Don't allow symbols to be discarded on GOT related relocs. */
13542 if (fixP->fx_r_type == BFD_RELOC_ARM_PLT32
13543 || fixP->fx_r_type == BFD_RELOC_ARM_GOT32
13544 || fixP->fx_r_type == BFD_RELOC_ARM_GOTOFF
13545 || fixP->fx_r_type == BFD_RELOC_ARM_TARGET2)
13546 return 0;
13547
13548 return 1;
13549 }
13550
13551 const char *
13552 elf32_arm_target_format (void)
13553 {
13554 #ifdef TE_SYMBIAN
13555 return (target_big_endian
13556 ? "elf32-bigarm-symbian"
13557 : "elf32-littlearm-symbian");
13558 #else
13559 if (target_big_endian)
13560 {
13561 if (target_oabi)
13562 return "elf32-bigarm-oabi";
13563 else
13564 return "elf32-bigarm";
13565 }
13566 else
13567 {
13568 if (target_oabi)
13569 return "elf32-littlearm-oabi";
13570 else
13571 return "elf32-littlearm";
13572 }
13573 #endif
13574 }
13575
13576 void
13577 armelf_frob_symbol (symbolS * symp,
13578 int * puntp)
13579 {
13580 elf_frob_symbol (symp, puntp);
13581 }
13582
13583 static void
13584 s_arm_elf_cons (int nbytes)
13585 {
13586 expressionS exp;
13587
13588 #ifdef md_flush_pending_output
13589 md_flush_pending_output ();
13590 #endif
13591
13592 if (is_it_end_of_statement ())
13593 {
13594 demand_empty_rest_of_line ();
13595 return;
13596 }
13597
13598 #ifdef md_cons_align
13599 md_cons_align (nbytes);
13600 #endif
13601
13602 mapping_state (MAP_DATA);
13603 do
13604 {
13605 bfd_reloc_code_real_type reloc;
13606
13607 expression (& exp);
13608
13609 if (exp.X_op == O_symbol
13610 && * input_line_pointer == '('
13611 && (reloc = arm_parse_reloc ()) != BFD_RELOC_UNUSED)
13612 {
13613 reloc_howto_type *howto = bfd_reloc_type_lookup (stdoutput, reloc);
13614 int size = bfd_get_reloc_size (howto);
13615
13616 if (size > nbytes)
13617 as_bad ("%s relocations do not fit in %d bytes",
13618 howto->name, nbytes);
13619 else
13620 {
13621 char *p = frag_more ((int) nbytes);
13622 int offset = nbytes - size;
13623
13624 fix_new_exp (frag_now, p - frag_now->fr_literal + offset, size,
13625 &exp, 0, reloc);
13626 }
13627 }
13628 else
13629 emit_expr (&exp, (unsigned int) nbytes);
13630 }
13631 while (*input_line_pointer++ == ',');
13632
13633 /* Put terminator back into stream. */
13634 input_line_pointer --;
13635 demand_empty_rest_of_line ();
13636 }
13637
13638
13639 /* Parse a .rel31 directive. */
13640
13641 static void
13642 s_arm_rel31 (int ignored ATTRIBUTE_UNUSED)
13643 {
13644 expressionS exp;
13645 char *p;
13646 valueT highbit;
13647
13648 SKIP_WHITESPACE ();
13649
13650 highbit = 0;
13651 if (*input_line_pointer == '1')
13652 highbit = 0x80000000;
13653 else if (*input_line_pointer != '0')
13654 as_bad (_("expected 0 or 1"));
13655
13656 input_line_pointer++;
13657 SKIP_WHITESPACE ();
13658 if (*input_line_pointer != ',')
13659 as_bad (_("missing comma"));
13660 input_line_pointer++;
13661
13662 #ifdef md_flush_pending_output
13663 md_flush_pending_output ();
13664 #endif
13665
13666 #ifdef md_cons_align
13667 md_cons_align (4);
13668 #endif
13669
13670 mapping_state (MAP_DATA);
13671
13672 expression (&exp);
13673
13674 p = frag_more (4);
13675 md_number_to_chars (p, highbit, 4);
13676 fix_new_arm (frag_now, p - frag_now->fr_literal, 4, &exp, 1,
13677 BFD_RELOC_ARM_PREL31);
13678
13679 demand_empty_rest_of_line ();
13680 }
13681
13682 #endif /* OBJ_ELF */
13683
13684 /* This is called from HANDLE_ALIGN in write.c. Fill in the contents
13685 of an rs_align_code fragment. */
13686
13687 void
13688 arm_handle_align (fragS * fragP)
13689 {
13690 static char const arm_noop[4] = { 0x00, 0x00, 0xa0, 0xe1 };
13691 static char const thumb_noop[2] = { 0xc0, 0x46 };
13692 static char const arm_bigend_noop[4] = { 0xe1, 0xa0, 0x00, 0x00 };
13693 static char const thumb_bigend_noop[2] = { 0x46, 0xc0 };
13694
13695 int bytes, fix, noop_size;
13696 char * p;
13697 const char * noop;
13698
13699 if (fragP->fr_type != rs_align_code)
13700 return;
13701
13702 bytes = fragP->fr_next->fr_address - fragP->fr_address - fragP->fr_fix;
13703 p = fragP->fr_literal + fragP->fr_fix;
13704 fix = 0;
13705
13706 if (bytes > MAX_MEM_FOR_RS_ALIGN_CODE)
13707 bytes &= MAX_MEM_FOR_RS_ALIGN_CODE;
13708
13709 if (fragP->tc_frag_data)
13710 {
13711 if (target_big_endian)
13712 noop = thumb_bigend_noop;
13713 else
13714 noop = thumb_noop;
13715 noop_size = sizeof (thumb_noop);
13716 }
13717 else
13718 {
13719 if (target_big_endian)
13720 noop = arm_bigend_noop;
13721 else
13722 noop = arm_noop;
13723 noop_size = sizeof (arm_noop);
13724 }
13725
13726 if (bytes & (noop_size - 1))
13727 {
13728 fix = bytes & (noop_size - 1);
13729 memset (p, 0, fix);
13730 p += fix;
13731 bytes -= fix;
13732 }
13733
13734 while (bytes >= noop_size)
13735 {
13736 memcpy (p, noop, noop_size);
13737 p += noop_size;
13738 bytes -= noop_size;
13739 fix += noop_size;
13740 }
13741
13742 fragP->fr_fix += fix;
13743 fragP->fr_var = noop_size;
13744 }
13745
13746 /* Called from md_do_align. Used to create an alignment
13747 frag in a code section. */
13748
13749 void
13750 arm_frag_align_code (int n, int max)
13751 {
13752 char * p;
13753
13754 /* We assume that there will never be a requirement
13755 to support alignments greater than 32 bytes. */
13756 if (max > MAX_MEM_FOR_RS_ALIGN_CODE)
13757 as_fatal (_("alignments greater than 32 bytes not supported in .text sections."));
13758
13759 p = frag_var (rs_align_code,
13760 MAX_MEM_FOR_RS_ALIGN_CODE,
13761 1,
13762 (relax_substateT) max,
13763 (symbolS *) NULL,
13764 (offsetT) n,
13765 (char *) NULL);
13766 *p = 0;
13767 }
13768
13769 /* Perform target specific initialisation of a frag. */
13770
13771 void
13772 arm_init_frag (fragS * fragP)
13773 {
13774 /* Record whether this frag is in an ARM or a THUMB area. */
13775 fragP->tc_frag_data = thumb_mode;
13776 }
13777
13778 /* This table describes all the machine specific pseudo-ops the assembler
13779 has to support. The fields are:
13780 pseudo-op name without dot
13781 function to call to execute this pseudo-op
13782 Integer arg to pass to the function. */
13783
13784 const pseudo_typeS md_pseudo_table[] =
13785 {
13786 /* Never called because '.req' does not start a line. */
13787 { "req", s_req, 0 },
13788 { "unreq", s_unreq, 0 },
13789 { "bss", s_bss, 0 },
13790 { "align", s_align, 0 },
13791 { "arm", s_arm, 0 },
13792 { "thumb", s_thumb, 0 },
13793 { "code", s_code, 0 },
13794 { "force_thumb", s_force_thumb, 0 },
13795 { "thumb_func", s_thumb_func, 0 },
13796 { "thumb_set", s_thumb_set, 0 },
13797 { "even", s_even, 0 },
13798 { "ltorg", s_ltorg, 0 },
13799 { "pool", s_ltorg, 0 },
13800 #ifdef OBJ_ELF
13801 { "word", s_arm_elf_cons, 4 },
13802 { "long", s_arm_elf_cons, 4 },
13803 { "rel31", s_arm_rel31, 0 },
13804 #else
13805 { "word", cons, 4},
13806 #endif
13807 { "extend", float_cons, 'x' },
13808 { "ldouble", float_cons, 'x' },
13809 { "packed", float_cons, 'p' },
13810 { 0, 0, 0 }
13811 };
This page took 0.311516 seconds and 3 git commands to generate.