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