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