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