Add VAX specific disassembler option -Mentry: to specify a function entry
[deliverable/binutils-gdb.git] / gas / config / tc-arm.c
CommitLineData
b99bd4ef 1/* tc-arm.c -- Assemble for the ARM
f17c130b
AM
2 Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
3 2004, 2005
b99bd4ef
NC
4 Free Software Foundation, Inc.
5 Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org)
6 Modified by David Taylor (dtaylor@armltd.co.uk)
22d9c8c5 7 Cirrus coprocessor mods by Aldy Hernandez (aldyh@redhat.com)
34920d91
NC
8 Cirrus coprocessor fixes by Petko Manolov (petkan@nucleusys.com)
9 Cirrus coprocessor fixes by Vladimir Ivanov (vladitx@nucleusys.com)
b99bd4ef
NC
10
11 This file is part of GAS, the GNU Assembler.
12
13 GAS is free software; you can redistribute it and/or modify
14 it under the terms of the GNU General Public License as published by
15 the Free Software Foundation; either version 2, or (at your option)
16 any later version.
17
18 GAS is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with GAS; see the file COPYING. If not, write to the Free
25 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
26 02111-1307, USA. */
27
b99bd4ef
NC
28#include <string.h>
29#define NO_RELOC 0
30#include "as.h"
3882b010 31#include "safe-ctype.h"
b99bd4ef
NC
32
33/* Need TARGET_CPU. */
34#include "config.h"
35#include "subsegs.h"
36#include "obstack.h"
37#include "symbols.h"
38#include "listing.h"
39
f263249b
RE
40#include "opcode/arm.h"
41
b99bd4ef
NC
42#ifdef OBJ_ELF
43#include "elf/arm.h"
44#include "dwarf2dbg.h"
a394c00f 45#include "dw2gencfi.h"
b99bd4ef
NC
46#endif
47
7ed4c4c5 48/* XXX Set this to 1 after the next binutils release. */
03b1477f
RE
49#define WARN_DEPRECATED 0
50
7ed4c4c5
NC
51#ifdef OBJ_ELF
52/* Must be at least the size of the largest unwind opcode (currently two). */
53#define ARM_OPCODE_CHUNK_SIZE 8
54
55/* This structure holds the unwinding state. */
56
57static struct
58{
59 symbolS * proc_start;
60 symbolS * table_entry;
61 symbolS * personality_routine;
62 int personality_index;
63 /* The segment containing the function. */
64 segT saved_seg;
65 subsegT saved_subseg;
66 /* Opcodes generated from this function. */
67 unsigned char * opcodes;
68 int opcode_count;
69 int opcode_alloc;
70 /* The number of bytes pushed to the stack. */
71 offsetT frame_size;
72 /* We don't add stack adjustment opcodes immediately so that we can merge
73 multiple adjustments. We can also omit the final adjustment
74 when using a frame pointer. */
75 offsetT pending_offset;
76 /* These two fields are set by both unwind_movsp and unwind_setfp. They
77 hold the reg+offset to use when restoring sp from a frame pointer. */
78 offsetT fp_offset;
79 int fp_reg;
80 /* Nonzero if an unwind_setfp directive has been seen. */
81 unsigned fp_used:1;
82 /* Nonzero if the last opcode restores sp from fp_reg. */
83 unsigned sp_restored:1;
84} unwind;
85
86#endif /* OBJ_ELF */
87
33a392fb
PB
88enum arm_float_abi
89{
90 ARM_FLOAT_ABI_HARD,
91 ARM_FLOAT_ABI_SOFTFP,
92 ARM_FLOAT_ABI_SOFT
93};
94
b89dddec
RE
95/* Types of processor to assemble for. */
96#define ARM_1 ARM_ARCH_V1
97#define ARM_2 ARM_ARCH_V2
98#define ARM_3 ARM_ARCH_V2S
99#define ARM_250 ARM_ARCH_V2S
100#define ARM_6 ARM_ARCH_V3
101#define ARM_7 ARM_ARCH_V3
102#define ARM_8 ARM_ARCH_V4
103#define ARM_9 ARM_ARCH_V4T
104#define ARM_STRONG ARM_ARCH_V4
105#define ARM_CPU_MASK 0x0000000f /* XXX? */
b99bd4ef
NC
106
107#ifndef CPU_DEFAULT
108#if defined __XSCALE__
b89dddec 109#define CPU_DEFAULT (ARM_ARCH_XSCALE)
b99bd4ef
NC
110#else
111#if defined __thumb__
b89dddec 112#define CPU_DEFAULT (ARM_ARCH_V5T)
b99bd4ef 113#else
03b1477f 114#define CPU_DEFAULT ARM_ANY
b99bd4ef
NC
115#endif
116#endif
117#endif
118
119#ifndef FPU_DEFAULT
c820d418
MM
120# ifdef TE_LINUX
121# define FPU_DEFAULT FPU_ARCH_FPA
122# elif defined (TE_NetBSD)
123# ifdef OBJ_ELF
124# define FPU_DEFAULT FPU_ARCH_VFP /* Soft-float, but VFP order. */
125# else
126 /* Legacy a.out format. */
127# define FPU_DEFAULT FPU_ARCH_FPA /* Soft-float, but FPA order. */
128# endif
4e7fd91e
PB
129# elif defined (TE_VXWORKS)
130# define FPU_DEFAULT FPU_ARCH_VFP /* Soft-float, VFP order. */
c820d418
MM
131# else
132 /* For backwards compatibility, default to FPA. */
133# define FPU_DEFAULT FPU_ARCH_FPA
134# endif
135#endif /* ifndef FPU_DEFAULT */
b99bd4ef
NC
136
137#define streq(a, b) (strcmp (a, b) == 0)
138#define skip_whitespace(str) while (*(str) == ' ') ++(str)
139
03b1477f 140static unsigned long cpu_variant;
b99bd4ef 141
b99bd4ef 142/* Flags stored in private area of BFD structure. */
b34976b6
AM
143static int uses_apcs_26 = FALSE;
144static int atpcs = FALSE;
145static int support_interwork = FALSE;
146static int uses_apcs_float = FALSE;
147static int pic_code = FALSE;
03b1477f
RE
148
149/* Variables that we set while parsing command-line options. Once all
150 options have been read we re-process these values to set the real
151 assembly flags. */
152static int legacy_cpu = -1;
153static int legacy_fpu = -1;
154
155static int mcpu_cpu_opt = -1;
156static int mcpu_fpu_opt = -1;
157static int march_cpu_opt = -1;
158static int march_fpu_opt = -1;
159static int mfpu_opt = -1;
33a392fb 160static int mfloat_abi_opt = -1;
7cc69913 161#ifdef OBJ_ELF
deeaaff8
DJ
162# ifdef EABI_DEFAULT
163static int meabi_flags = EABI_DEFAULT;
164# else
d507cf36 165static int meabi_flags = EF_ARM_EABI_UNKNOWN;
deeaaff8 166# endif
7cc69913 167#endif
b99bd4ef
NC
168
169/* This array holds the chars that always start a comment. If the
170 pre-processor is disabled, these aren't very useful. */
f57c81f6 171const char comment_chars[] = "@";
b99bd4ef
NC
172
173/* This array holds the chars that only start a comment at the beginning of
174 a line. If the line seems to have the form '# 123 filename'
175 .line and .file directives will appear in the pre-processed output. */
176/* Note that input_file.c hand checks for '#' at the beginning of the
177 first line of the input file. This is because the compiler outputs
178 #NO_APP at the beginning of its output. */
179/* Also note that comments like this one will always work. */
05d2d07e 180const char line_comment_chars[] = "#";
b99bd4ef 181
da89cce1 182const char line_separator_chars[] = ";";
b99bd4ef
NC
183
184/* Chars that can be used to separate mant
185 from exp in floating point numbers. */
05d2d07e 186const char EXP_CHARS[] = "eE";
b99bd4ef
NC
187
188/* Chars that mean this number is a floating point constant. */
189/* As in 0f12.456 */
190/* or 0d1.2345e12 */
191
05d2d07e 192const char FLT_CHARS[] = "rRsSfFdDxXeEpP";
b99bd4ef
NC
193
194/* Prefix characters that indicate the start of an immediate
195 value. */
196#define is_immediate_prefix(C) ((C) == '#' || (C) == '$')
197
198#ifdef OBJ_ELF
199/* Pre-defined "_GLOBAL_OFFSET_TABLE_" */
200symbolS * GOT_symbol;
201#endif
202
203/* Size of relocation record. */
05d2d07e 204const int md_reloc_size = 8;
b99bd4ef
NC
205
206/* 0: assemble for ARM,
207 1: assemble for Thumb,
208 2: assemble for Thumb even though target CPU does not support thumb
209 instructions. */
210static int thumb_mode = 0;
211
212typedef struct arm_fix
213{
214 int thumb_mode;
215} arm_fix_data;
216
217struct arm_it
218{
05d2d07e 219 const char * error;
b99bd4ef 220 unsigned long instruction;
b99bd4ef
NC
221 int size;
222 struct
223 {
224 bfd_reloc_code_real_type type;
225 expressionS exp;
226 int pc_rel;
227 } reloc;
228};
229
230struct arm_it inst;
231
232enum asm_shift_index
233{
234 SHIFT_LSL = 0,
235 SHIFT_LSR,
236 SHIFT_ASR,
237 SHIFT_ROR,
238 SHIFT_RRX
239};
240
241struct asm_shift_properties
242{
243 enum asm_shift_index index;
244 unsigned long bit_field;
245 unsigned int allows_0 : 1;
246 unsigned int allows_32 : 1;
247};
248
249static const struct asm_shift_properties shift_properties [] =
250{
251 { SHIFT_LSL, 0, 1, 0},
252 { SHIFT_LSR, 0x20, 0, 1},
253 { SHIFT_ASR, 0x40, 0, 1},
254 { SHIFT_ROR, 0x60, 0, 0},
255 { SHIFT_RRX, 0x60, 0, 0}
256};
257
258struct asm_shift_name
259{
260 const char * name;
261 const struct asm_shift_properties * properties;
262};
263
264static const struct asm_shift_name shift_names [] =
265{
266 { "asl", shift_properties + SHIFT_LSL },
267 { "lsl", shift_properties + SHIFT_LSL },
268 { "lsr", shift_properties + SHIFT_LSR },
269 { "asr", shift_properties + SHIFT_ASR },
270 { "ror", shift_properties + SHIFT_ROR },
271 { "rrx", shift_properties + SHIFT_RRX },
272 { "ASL", shift_properties + SHIFT_LSL },
273 { "LSL", shift_properties + SHIFT_LSL },
274 { "LSR", shift_properties + SHIFT_LSR },
275 { "ASR", shift_properties + SHIFT_ASR },
276 { "ROR", shift_properties + SHIFT_ROR },
277 { "RRX", shift_properties + SHIFT_RRX }
278};
279
09d92015 280/* Any kind of shift is accepted. */
b99bd4ef 281#define NO_SHIFT_RESTRICT 1
09d92015
MM
282/* The shift operand must be an immediate value, not a register. */
283#define SHIFT_IMMEDIATE 0
284/* The shift must be LSL or ASR and the operand must be an immediate. */
285#define SHIFT_LSL_OR_ASR_IMMEDIATE 2
286/* The shift must be ASR and the operand must be an immediate. */
287#define SHIFT_ASR_IMMEDIATE 3
288/* The shift must be LSL and the operand must be an immediate. */
289#define SHIFT_LSL_IMMEDIATE 4
b99bd4ef
NC
290
291#define NUM_FLOAT_VALS 8
292
05d2d07e 293const char * fp_const[] =
b99bd4ef
NC
294{
295 "0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0", 0
296};
297
298/* Number of littlenums required to hold an extended precision number. */
299#define MAX_LITTLENUMS 6
300
301LITTLENUM_TYPE fp_values[NUM_FLOAT_VALS][MAX_LITTLENUMS];
302
303#define FAIL (-1)
304#define SUCCESS (0)
305
bfae80f2
RE
306/* Whether a Co-processor load/store operation accepts write-back forms. */
307#define CP_WB_OK 1
308#define CP_NO_WB 0
309
b99bd4ef
NC
310#define SUFF_S 1
311#define SUFF_D 2
312#define SUFF_E 3
313#define SUFF_P 4
314
315#define CP_T_X 0x00008000
316#define CP_T_Y 0x00400000
317#define CP_T_Pre 0x01000000
318#define CP_T_UD 0x00800000
319#define CP_T_WB 0x00200000
320
321#define CONDS_BIT 0x00100000
322#define LOAD_BIT 0x00100000
b99bd4ef
NC
323
324#define DOUBLE_LOAD_FLAG 0x00000001
325
326struct asm_cond
327{
05d2d07e 328 const char * template;
b99bd4ef
NC
329 unsigned long value;
330};
331
b99bd4ef 332#define COND_ALWAYS 0xe0000000
90e4755a 333#define COND_MASK 0xf0000000
b99bd4ef 334
05d2d07e 335static const struct asm_cond conds[] =
b99bd4ef
NC
336{
337 {"eq", 0x00000000},
338 {"ne", 0x10000000},
339 {"cs", 0x20000000}, {"hs", 0x20000000},
340 {"cc", 0x30000000}, {"ul", 0x30000000}, {"lo", 0x30000000},
341 {"mi", 0x40000000},
342 {"pl", 0x50000000},
343 {"vs", 0x60000000},
344 {"vc", 0x70000000},
345 {"hi", 0x80000000},
346 {"ls", 0x90000000},
347 {"ge", 0xa0000000},
348 {"lt", 0xb0000000},
349 {"gt", 0xc0000000},
350 {"le", 0xd0000000},
351 {"al", 0xe0000000},
352 {"nv", 0xf0000000}
353};
354
b99bd4ef
NC
355struct asm_psr
356{
b34976b6
AM
357 const char *template;
358 bfd_boolean cpsr;
b99bd4ef
NC
359 unsigned long field;
360};
361
2d2255b5 362/* The bit that distinguishes CPSR and SPSR. */
b99bd4ef
NC
363#define SPSR_BIT (1 << 22)
364
365/* How many bits to shift the PSR_xxx bits up by. */
366#define PSR_SHIFT 16
367
368#define PSR_c (1 << 0)
369#define PSR_x (1 << 1)
370#define PSR_s (1 << 2)
371#define PSR_f (1 << 3)
372
05d2d07e 373static const struct asm_psr psrs[] =
b99bd4ef 374{
b34976b6
AM
375 {"CPSR", TRUE, PSR_c | PSR_f},
376 {"CPSR_all", TRUE, PSR_c | PSR_f},
377 {"SPSR", FALSE, PSR_c | PSR_f},
378 {"SPSR_all", FALSE, PSR_c | PSR_f},
379 {"CPSR_flg", TRUE, PSR_f},
380 {"CPSR_f", TRUE, PSR_f},
381 {"SPSR_flg", FALSE, PSR_f},
382 {"SPSR_f", FALSE, PSR_f},
383 {"CPSR_c", TRUE, PSR_c},
384 {"CPSR_ctl", TRUE, PSR_c},
385 {"SPSR_c", FALSE, PSR_c},
386 {"SPSR_ctl", FALSE, PSR_c},
387 {"CPSR_x", TRUE, PSR_x},
388 {"CPSR_s", TRUE, PSR_s},
389 {"SPSR_x", FALSE, PSR_x},
390 {"SPSR_s", FALSE, PSR_s},
b99bd4ef 391 /* Combinations of flags. */
b34976b6
AM
392 {"CPSR_fs", TRUE, PSR_f | PSR_s},
393 {"CPSR_fx", TRUE, PSR_f | PSR_x},
394 {"CPSR_fc", TRUE, PSR_f | PSR_c},
395 {"CPSR_sf", TRUE, PSR_s | PSR_f},
396 {"CPSR_sx", TRUE, PSR_s | PSR_x},
397 {"CPSR_sc", TRUE, PSR_s | PSR_c},
398 {"CPSR_xf", TRUE, PSR_x | PSR_f},
399 {"CPSR_xs", TRUE, PSR_x | PSR_s},
400 {"CPSR_xc", TRUE, PSR_x | PSR_c},
401 {"CPSR_cf", TRUE, PSR_c | PSR_f},
402 {"CPSR_cs", TRUE, PSR_c | PSR_s},
403 {"CPSR_cx", TRUE, PSR_c | PSR_x},
404 {"CPSR_fsx", TRUE, PSR_f | PSR_s | PSR_x},
405 {"CPSR_fsc", TRUE, PSR_f | PSR_s | PSR_c},
406 {"CPSR_fxs", TRUE, PSR_f | PSR_x | PSR_s},
407 {"CPSR_fxc", TRUE, PSR_f | PSR_x | PSR_c},
408 {"CPSR_fcs", TRUE, PSR_f | PSR_c | PSR_s},
409 {"CPSR_fcx", TRUE, PSR_f | PSR_c | PSR_x},
410 {"CPSR_sfx", TRUE, PSR_s | PSR_f | PSR_x},
411 {"CPSR_sfc", TRUE, PSR_s | PSR_f | PSR_c},
412 {"CPSR_sxf", TRUE, PSR_s | PSR_x | PSR_f},
413 {"CPSR_sxc", TRUE, PSR_s | PSR_x | PSR_c},
414 {"CPSR_scf", TRUE, PSR_s | PSR_c | PSR_f},
415 {"CPSR_scx", TRUE, PSR_s | PSR_c | PSR_x},
416 {"CPSR_xfs", TRUE, PSR_x | PSR_f | PSR_s},
417 {"CPSR_xfc", TRUE, PSR_x | PSR_f | PSR_c},
418 {"CPSR_xsf", TRUE, PSR_x | PSR_s | PSR_f},
419 {"CPSR_xsc", TRUE, PSR_x | PSR_s | PSR_c},
420 {"CPSR_xcf", TRUE, PSR_x | PSR_c | PSR_f},
421 {"CPSR_xcs", TRUE, PSR_x | PSR_c | PSR_s},
422 {"CPSR_cfs", TRUE, PSR_c | PSR_f | PSR_s},
423 {"CPSR_cfx", TRUE, PSR_c | PSR_f | PSR_x},
424 {"CPSR_csf", TRUE, PSR_c | PSR_s | PSR_f},
425 {"CPSR_csx", TRUE, PSR_c | PSR_s | PSR_x},
426 {"CPSR_cxf", TRUE, PSR_c | PSR_x | PSR_f},
427 {"CPSR_cxs", TRUE, PSR_c | PSR_x | PSR_s},
428 {"CPSR_fsxc", TRUE, PSR_f | PSR_s | PSR_x | PSR_c},
429 {"CPSR_fscx", TRUE, PSR_f | PSR_s | PSR_c | PSR_x},
430 {"CPSR_fxsc", TRUE, PSR_f | PSR_x | PSR_s | PSR_c},
431 {"CPSR_fxcs", TRUE, PSR_f | PSR_x | PSR_c | PSR_s},
432 {"CPSR_fcsx", TRUE, PSR_f | PSR_c | PSR_s | PSR_x},
433 {"CPSR_fcxs", TRUE, PSR_f | PSR_c | PSR_x | PSR_s},
434 {"CPSR_sfxc", TRUE, PSR_s | PSR_f | PSR_x | PSR_c},
435 {"CPSR_sfcx", TRUE, PSR_s | PSR_f | PSR_c | PSR_x},
436 {"CPSR_sxfc", TRUE, PSR_s | PSR_x | PSR_f | PSR_c},
437 {"CPSR_sxcf", TRUE, PSR_s | PSR_x | PSR_c | PSR_f},
438 {"CPSR_scfx", TRUE, PSR_s | PSR_c | PSR_f | PSR_x},
439 {"CPSR_scxf", TRUE, PSR_s | PSR_c | PSR_x | PSR_f},
440 {"CPSR_xfsc", TRUE, PSR_x | PSR_f | PSR_s | PSR_c},
441 {"CPSR_xfcs", TRUE, PSR_x | PSR_f | PSR_c | PSR_s},
442 {"CPSR_xsfc", TRUE, PSR_x | PSR_s | PSR_f | PSR_c},
443 {"CPSR_xscf", TRUE, PSR_x | PSR_s | PSR_c | PSR_f},
444 {"CPSR_xcfs", TRUE, PSR_x | PSR_c | PSR_f | PSR_s},
445 {"CPSR_xcsf", TRUE, PSR_x | PSR_c | PSR_s | PSR_f},
446 {"CPSR_cfsx", TRUE, PSR_c | PSR_f | PSR_s | PSR_x},
447 {"CPSR_cfxs", TRUE, PSR_c | PSR_f | PSR_x | PSR_s},
448 {"CPSR_csfx", TRUE, PSR_c | PSR_s | PSR_f | PSR_x},
449 {"CPSR_csxf", TRUE, PSR_c | PSR_s | PSR_x | PSR_f},
450 {"CPSR_cxfs", TRUE, PSR_c | PSR_x | PSR_f | PSR_s},
451 {"CPSR_cxsf", TRUE, PSR_c | PSR_x | PSR_s | PSR_f},
452 {"SPSR_fs", FALSE, PSR_f | PSR_s},
453 {"SPSR_fx", FALSE, PSR_f | PSR_x},
454 {"SPSR_fc", FALSE, PSR_f | PSR_c},
455 {"SPSR_sf", FALSE, PSR_s | PSR_f},
456 {"SPSR_sx", FALSE, PSR_s | PSR_x},
457 {"SPSR_sc", FALSE, PSR_s | PSR_c},
458 {"SPSR_xf", FALSE, PSR_x | PSR_f},
459 {"SPSR_xs", FALSE, PSR_x | PSR_s},
460 {"SPSR_xc", FALSE, PSR_x | PSR_c},
461 {"SPSR_cf", FALSE, PSR_c | PSR_f},
462 {"SPSR_cs", FALSE, PSR_c | PSR_s},
463 {"SPSR_cx", FALSE, PSR_c | PSR_x},
464 {"SPSR_fsx", FALSE, PSR_f | PSR_s | PSR_x},
465 {"SPSR_fsc", FALSE, PSR_f | PSR_s | PSR_c},
466 {"SPSR_fxs", FALSE, PSR_f | PSR_x | PSR_s},
467 {"SPSR_fxc", FALSE, PSR_f | PSR_x | PSR_c},
468 {"SPSR_fcs", FALSE, PSR_f | PSR_c | PSR_s},
469 {"SPSR_fcx", FALSE, PSR_f | PSR_c | PSR_x},
470 {"SPSR_sfx", FALSE, PSR_s | PSR_f | PSR_x},
471 {"SPSR_sfc", FALSE, PSR_s | PSR_f | PSR_c},
472 {"SPSR_sxf", FALSE, PSR_s | PSR_x | PSR_f},
473 {"SPSR_sxc", FALSE, PSR_s | PSR_x | PSR_c},
474 {"SPSR_scf", FALSE, PSR_s | PSR_c | PSR_f},
475 {"SPSR_scx", FALSE, PSR_s | PSR_c | PSR_x},
476 {"SPSR_xfs", FALSE, PSR_x | PSR_f | PSR_s},
477 {"SPSR_xfc", FALSE, PSR_x | PSR_f | PSR_c},
478 {"SPSR_xsf", FALSE, PSR_x | PSR_s | PSR_f},
479 {"SPSR_xsc", FALSE, PSR_x | PSR_s | PSR_c},
480 {"SPSR_xcf", FALSE, PSR_x | PSR_c | PSR_f},
481 {"SPSR_xcs", FALSE, PSR_x | PSR_c | PSR_s},
482 {"SPSR_cfs", FALSE, PSR_c | PSR_f | PSR_s},
483 {"SPSR_cfx", FALSE, PSR_c | PSR_f | PSR_x},
484 {"SPSR_csf", FALSE, PSR_c | PSR_s | PSR_f},
485 {"SPSR_csx", FALSE, PSR_c | PSR_s | PSR_x},
486 {"SPSR_cxf", FALSE, PSR_c | PSR_x | PSR_f},
487 {"SPSR_cxs", FALSE, PSR_c | PSR_x | PSR_s},
488 {"SPSR_fsxc", FALSE, PSR_f | PSR_s | PSR_x | PSR_c},
489 {"SPSR_fscx", FALSE, PSR_f | PSR_s | PSR_c | PSR_x},
490 {"SPSR_fxsc", FALSE, PSR_f | PSR_x | PSR_s | PSR_c},
491 {"SPSR_fxcs", FALSE, PSR_f | PSR_x | PSR_c | PSR_s},
492 {"SPSR_fcsx", FALSE, PSR_f | PSR_c | PSR_s | PSR_x},
493 {"SPSR_fcxs", FALSE, PSR_f | PSR_c | PSR_x | PSR_s},
494 {"SPSR_sfxc", FALSE, PSR_s | PSR_f | PSR_x | PSR_c},
495 {"SPSR_sfcx", FALSE, PSR_s | PSR_f | PSR_c | PSR_x},
496 {"SPSR_sxfc", FALSE, PSR_s | PSR_x | PSR_f | PSR_c},
497 {"SPSR_sxcf", FALSE, PSR_s | PSR_x | PSR_c | PSR_f},
498 {"SPSR_scfx", FALSE, PSR_s | PSR_c | PSR_f | PSR_x},
499 {"SPSR_scxf", FALSE, PSR_s | PSR_c | PSR_x | PSR_f},
500 {"SPSR_xfsc", FALSE, PSR_x | PSR_f | PSR_s | PSR_c},
501 {"SPSR_xfcs", FALSE, PSR_x | PSR_f | PSR_c | PSR_s},
502 {"SPSR_xsfc", FALSE, PSR_x | PSR_s | PSR_f | PSR_c},
503 {"SPSR_xscf", FALSE, PSR_x | PSR_s | PSR_c | PSR_f},
504 {"SPSR_xcfs", FALSE, PSR_x | PSR_c | PSR_f | PSR_s},
505 {"SPSR_xcsf", FALSE, PSR_x | PSR_c | PSR_s | PSR_f},
506 {"SPSR_cfsx", FALSE, PSR_c | PSR_f | PSR_s | PSR_x},
507 {"SPSR_cfxs", FALSE, PSR_c | PSR_f | PSR_x | PSR_s},
508 {"SPSR_csfx", FALSE, PSR_c | PSR_s | PSR_f | PSR_x},
509 {"SPSR_csxf", FALSE, PSR_c | PSR_s | PSR_x | PSR_f},
510 {"SPSR_cxfs", FALSE, PSR_c | PSR_x | PSR_f | PSR_s},
511 {"SPSR_cxsf", FALSE, PSR_c | PSR_x | PSR_s | PSR_f},
b99bd4ef
NC
512};
513
e16bb312
NC
514enum wreg_type
515 {
516 IWMMXT_REG_WR = 0,
517 IWMMXT_REG_WC = 1,
518 IWMMXT_REG_WR_OR_WC = 2,
519 IWMMXT_REG_WCG
520 };
521
522enum iwmmxt_insn_type
523{
524 check_rd,
525 check_wr,
526 check_wrwr,
527 check_wrwrwr,
528 check_wrwrwcg,
529 check_tbcst,
530 check_tmovmsk,
531 check_tmia,
532 check_tmcrr,
533 check_tmrrc,
534 check_tmcr,
535 check_tmrc,
536 check_tinsr,
537 check_textrc,
538 check_waligni,
539 check_textrm,
540 check_wshufh
541};
542
bfae80f2
RE
543enum vfp_dp_reg_pos
544{
545 VFP_REG_Dd, VFP_REG_Dm, VFP_REG_Dn
546};
547
548enum vfp_sp_reg_pos
549{
550 VFP_REG_Sd, VFP_REG_Sm, VFP_REG_Sn
551};
552
553enum vfp_ldstm_type
554{
555 VFP_LDSTMIA, VFP_LDSTMDB, VFP_LDSTMIAX, VFP_LDSTMDBX
556};
557
558/* VFP system registers. */
559struct vfp_reg
560{
561 const char *name;
562 unsigned long regno;
563};
564
cc8a6dd0 565static const struct vfp_reg vfp_regs[] =
bfae80f2
RE
566{
567 {"fpsid", 0x00000000},
568 {"FPSID", 0x00000000},
569 {"fpscr", 0x00010000},
570 {"FPSCR", 0x00010000},
571 {"fpexc", 0x00080000},
572 {"FPEXC", 0x00080000}
573};
574
6c43fab6
RE
575/* Structure for a hash table entry for a register. */
576struct reg_entry
577{
578 const char * name;
579 int number;
0bbf2aa4 580 bfd_boolean builtin;
6c43fab6
RE
581};
582
e28cd48c 583/* Some well known registers that we refer to directly elsewhere. */
6c43fab6
RE
584#define REG_SP 13
585#define REG_LR 14
586#define REG_PC 15
587
e16bb312
NC
588#define wr_register(reg) ((reg ^ WR_PREFIX) >= 0 && (reg ^ WR_PREFIX) <= 15)
589#define wc_register(reg) ((reg ^ WC_PREFIX) >= 0 && (reg ^ WC_PREFIX) <= 15)
590#define wcg_register(reg) ((reg ^ WC_PREFIX) >= 8 && (reg ^ WC_PREFIX) <= 11)
591
0bbf2aa4
NC
592/* These are the standard names. Users can add aliases with .req.
593 and delete them with .unreq. */
594
6c43fab6
RE
595/* Integer Register Numbers. */
596static const struct reg_entry rn_table[] =
597{
0bbf2aa4
NC
598 {"r0", 0, TRUE}, {"r1", 1, TRUE}, {"r2", 2, TRUE}, {"r3", 3, TRUE},
599 {"r4", 4, TRUE}, {"r5", 5, TRUE}, {"r6", 6, TRUE}, {"r7", 7, TRUE},
600 {"r8", 8, TRUE}, {"r9", 9, TRUE}, {"r10", 10, TRUE}, {"r11", 11, TRUE},
601 {"r12", 12, TRUE}, {"r13", REG_SP, TRUE}, {"r14", REG_LR, TRUE}, {"r15", REG_PC, TRUE},
6c43fab6 602 /* ATPCS Synonyms. */
0bbf2aa4
NC
603 {"a1", 0, TRUE}, {"a2", 1, TRUE}, {"a3", 2, TRUE}, {"a4", 3, TRUE},
604 {"v1", 4, TRUE}, {"v2", 5, TRUE}, {"v3", 6, TRUE}, {"v4", 7, TRUE},
605 {"v5", 8, TRUE}, {"v6", 9, TRUE}, {"v7", 10, TRUE}, {"v8", 11, TRUE},
6c43fab6 606 /* Well-known aliases. */
0bbf2aa4
NC
607 {"wr", 7, TRUE}, {"sb", 9, TRUE}, {"sl", 10, TRUE}, {"fp", 11, TRUE},
608 {"ip", 12, TRUE}, {"sp", REG_SP, TRUE}, {"lr", REG_LR, TRUE}, {"pc", REG_PC, TRUE},
609 {NULL, 0, TRUE}
6c43fab6
RE
610};
611
e16bb312
NC
612#define WR_PREFIX 0x200
613#define WC_PREFIX 0x400
614
615static const struct reg_entry iwmmxt_table[] =
616{
5a6c6817 617 /* Intel Wireless MMX technology register names. */
0bbf2aa4
NC
618 { "wr0", 0x0 | WR_PREFIX, TRUE}, {"wr1", 0x1 | WR_PREFIX, TRUE},
619 { "wr2", 0x2 | WR_PREFIX, TRUE}, {"wr3", 0x3 | WR_PREFIX, TRUE},
620 { "wr4", 0x4 | WR_PREFIX, TRUE}, {"wr5", 0x5 | WR_PREFIX, TRUE},
621 { "wr6", 0x6 | WR_PREFIX, TRUE}, {"wr7", 0x7 | WR_PREFIX, TRUE},
622 { "wr8", 0x8 | WR_PREFIX, TRUE}, {"wr9", 0x9 | WR_PREFIX, TRUE},
623 { "wr10", 0xa | WR_PREFIX, TRUE}, {"wr11", 0xb | WR_PREFIX, TRUE},
624 { "wr12", 0xc | WR_PREFIX, TRUE}, {"wr13", 0xd | WR_PREFIX, TRUE},
625 { "wr14", 0xe | WR_PREFIX, TRUE}, {"wr15", 0xf | WR_PREFIX, TRUE},
626 { "wcid", 0x0 | WC_PREFIX, TRUE}, {"wcon", 0x1 | WC_PREFIX, TRUE},
627 {"wcssf", 0x2 | WC_PREFIX, TRUE}, {"wcasf", 0x3 | WC_PREFIX, TRUE},
628 {"wcgr0", 0x8 | WC_PREFIX, TRUE}, {"wcgr1", 0x9 | WC_PREFIX, TRUE},
629 {"wcgr2", 0xa | WC_PREFIX, TRUE}, {"wcgr3", 0xb | WC_PREFIX, TRUE},
630
631 { "wR0", 0x0 | WR_PREFIX, TRUE}, {"wR1", 0x1 | WR_PREFIX, TRUE},
632 { "wR2", 0x2 | WR_PREFIX, TRUE}, {"wR3", 0x3 | WR_PREFIX, TRUE},
633 { "wR4", 0x4 | WR_PREFIX, TRUE}, {"wR5", 0x5 | WR_PREFIX, TRUE},
634 { "wR6", 0x6 | WR_PREFIX, TRUE}, {"wR7", 0x7 | WR_PREFIX, TRUE},
635 { "wR8", 0x8 | WR_PREFIX, TRUE}, {"wR9", 0x9 | WR_PREFIX, TRUE},
636 { "wR10", 0xa | WR_PREFIX, TRUE}, {"wR11", 0xb | WR_PREFIX, TRUE},
637 { "wR12", 0xc | WR_PREFIX, TRUE}, {"wR13", 0xd | WR_PREFIX, TRUE},
638 { "wR14", 0xe | WR_PREFIX, TRUE}, {"wR15", 0xf | WR_PREFIX, TRUE},
639 { "wCID", 0x0 | WC_PREFIX, TRUE}, {"wCon", 0x1 | WC_PREFIX, TRUE},
640 {"wCSSF", 0x2 | WC_PREFIX, TRUE}, {"wCASF", 0x3 | WC_PREFIX, TRUE},
641 {"wCGR0", 0x8 | WC_PREFIX, TRUE}, {"wCGR1", 0x9 | WC_PREFIX, TRUE},
642 {"wCGR2", 0xa | WC_PREFIX, TRUE}, {"wCGR3", 0xb | WC_PREFIX, TRUE},
643 {NULL, 0, TRUE}
e16bb312
NC
644};
645
6c43fab6
RE
646/* Co-processor Numbers. */
647static const struct reg_entry cp_table[] =
648{
0bbf2aa4
NC
649 {"p0", 0, TRUE}, {"p1", 1, TRUE}, {"p2", 2, TRUE}, {"p3", 3, TRUE},
650 {"p4", 4, TRUE}, {"p5", 5, TRUE}, {"p6", 6, TRUE}, {"p7", 7, TRUE},
651 {"p8", 8, TRUE}, {"p9", 9, TRUE}, {"p10", 10, TRUE}, {"p11", 11, TRUE},
652 {"p12", 12, TRUE}, {"p13", 13, TRUE}, {"p14", 14, TRUE}, {"p15", 15, TRUE},
653 {NULL, 0, TRUE}
6c43fab6
RE
654};
655
656/* Co-processor Register Numbers. */
657static const struct reg_entry cn_table[] =
658{
0bbf2aa4
NC
659 {"c0", 0, TRUE}, {"c1", 1, TRUE}, {"c2", 2, TRUE}, {"c3", 3, TRUE},
660 {"c4", 4, TRUE}, {"c5", 5, TRUE}, {"c6", 6, TRUE}, {"c7", 7, TRUE},
661 {"c8", 8, TRUE}, {"c9", 9, TRUE}, {"c10", 10, TRUE}, {"c11", 11, TRUE},
662 {"c12", 12, TRUE}, {"c13", 13, TRUE}, {"c14", 14, TRUE}, {"c15", 15, TRUE},
6c43fab6 663 /* Not really valid, but kept for back-wards compatibility. */
0bbf2aa4
NC
664 {"cr0", 0, TRUE}, {"cr1", 1, TRUE}, {"cr2", 2, TRUE}, {"cr3", 3, TRUE},
665 {"cr4", 4, TRUE}, {"cr5", 5, TRUE}, {"cr6", 6, TRUE}, {"cr7", 7, TRUE},
666 {"cr8", 8, TRUE}, {"cr9", 9, TRUE}, {"cr10", 10, TRUE}, {"cr11", 11, TRUE},
667 {"cr12", 12, TRUE}, {"cr13", 13, TRUE}, {"cr14", 14, TRUE}, {"cr15", 15, TRUE},
668 {NULL, 0, TRUE}
6c43fab6
RE
669};
670
671/* FPA Registers. */
672static const struct reg_entry fn_table[] =
673{
0bbf2aa4
NC
674 {"f0", 0, TRUE}, {"f1", 1, TRUE}, {"f2", 2, TRUE}, {"f3", 3, TRUE},
675 {"f4", 4, TRUE}, {"f5", 5, TRUE}, {"f6", 6, TRUE}, {"f7", 7, TRUE},
676 {NULL, 0, TRUE}
6c43fab6
RE
677};
678
bfae80f2
RE
679/* VFP SP Registers. */
680static const struct reg_entry sn_table[] =
681{
0bbf2aa4
NC
682 {"s0", 0, TRUE}, {"s1", 1, TRUE}, {"s2", 2, TRUE}, {"s3", 3, TRUE},
683 {"s4", 4, TRUE}, {"s5", 5, TRUE}, {"s6", 6, TRUE}, {"s7", 7, TRUE},
684 {"s8", 8, TRUE}, {"s9", 9, TRUE}, {"s10", 10, TRUE}, {"s11", 11, TRUE},
685 {"s12", 12, TRUE}, {"s13", 13, TRUE}, {"s14", 14, TRUE}, {"s15", 15, TRUE},
686 {"s16", 16, TRUE}, {"s17", 17, TRUE}, {"s18", 18, TRUE}, {"s19", 19, TRUE},
687 {"s20", 20, TRUE}, {"s21", 21, TRUE}, {"s22", 22, TRUE}, {"s23", 23, TRUE},
688 {"s24", 24, TRUE}, {"s25", 25, TRUE}, {"s26", 26, TRUE}, {"s27", 27, TRUE},
689 {"s28", 28, TRUE}, {"s29", 29, TRUE}, {"s30", 30, TRUE}, {"s31", 31, TRUE},
690 {NULL, 0, TRUE}
bfae80f2
RE
691};
692
693/* VFP DP Registers. */
694static const struct reg_entry dn_table[] =
695{
0bbf2aa4
NC
696 {"d0", 0, TRUE}, {"d1", 1, TRUE}, {"d2", 2, TRUE}, {"d3", 3, TRUE},
697 {"d4", 4, TRUE}, {"d5", 5, TRUE}, {"d6", 6, TRUE}, {"d7", 7, TRUE},
698 {"d8", 8, TRUE}, {"d9", 9, TRUE}, {"d10", 10, TRUE}, {"d11", 11, TRUE},
699 {"d12", 12, TRUE}, {"d13", 13, TRUE}, {"d14", 14, TRUE}, {"d15", 15, TRUE},
700 {NULL, 0, TRUE}
bfae80f2
RE
701};
702
63e63b07 703/* Maverick DSP coprocessor registers. */
6c43fab6
RE
704static const struct reg_entry mav_mvf_table[] =
705{
0bbf2aa4
NC
706 {"mvf0", 0, TRUE}, {"mvf1", 1, TRUE}, {"mvf2", 2, TRUE}, {"mvf3", 3, TRUE},
707 {"mvf4", 4, TRUE}, {"mvf5", 5, TRUE}, {"mvf6", 6, TRUE}, {"mvf7", 7, TRUE},
708 {"mvf8", 8, TRUE}, {"mvf9", 9, TRUE}, {"mvf10", 10, TRUE}, {"mvf11", 11, TRUE},
709 {"mvf12", 12, TRUE}, {"mvf13", 13, TRUE}, {"mvf14", 14, TRUE}, {"mvf15", 15, TRUE},
710 {NULL, 0, TRUE}
6c43fab6
RE
711};
712
713static const struct reg_entry mav_mvd_table[] =
714{
0bbf2aa4
NC
715 {"mvd0", 0, TRUE}, {"mvd1", 1, TRUE}, {"mvd2", 2, TRUE}, {"mvd3", 3, TRUE},
716 {"mvd4", 4, TRUE}, {"mvd5", 5, TRUE}, {"mvd6", 6, TRUE}, {"mvd7", 7, TRUE},
717 {"mvd8", 8, TRUE}, {"mvd9", 9, TRUE}, {"mvd10", 10, TRUE}, {"mvd11", 11, TRUE},
718 {"mvd12", 12, TRUE}, {"mvd13", 13, TRUE}, {"mvd14", 14, TRUE}, {"mvd15", 15, TRUE},
719 {NULL, 0, TRUE}
6c43fab6
RE
720};
721
722static const struct reg_entry mav_mvfx_table[] =
723{
0bbf2aa4
NC
724 {"mvfx0", 0, TRUE}, {"mvfx1", 1, TRUE}, {"mvfx2", 2, TRUE}, {"mvfx3", 3, TRUE},
725 {"mvfx4", 4, TRUE}, {"mvfx5", 5, TRUE}, {"mvfx6", 6, TRUE}, {"mvfx7", 7, TRUE},
726 {"mvfx8", 8, TRUE}, {"mvfx9", 9, TRUE}, {"mvfx10", 10, TRUE}, {"mvfx11", 11, TRUE},
727 {"mvfx12", 12, TRUE}, {"mvfx13", 13, TRUE}, {"mvfx14", 14, TRUE}, {"mvfx15", 15, TRUE},
728 {NULL, 0, TRUE}
6c43fab6
RE
729};
730
731static const struct reg_entry mav_mvdx_table[] =
732{
0bbf2aa4
NC
733 {"mvdx0", 0, TRUE}, {"mvdx1", 1, TRUE}, {"mvdx2", 2, TRUE}, {"mvdx3", 3, TRUE},
734 {"mvdx4", 4, TRUE}, {"mvdx5", 5, TRUE}, {"mvdx6", 6, TRUE}, {"mvdx7", 7, TRUE},
735 {"mvdx8", 8, TRUE}, {"mvdx9", 9, TRUE}, {"mvdx10", 10, TRUE}, {"mvdx11", 11, TRUE},
736 {"mvdx12", 12, TRUE}, {"mvdx13", 13, TRUE}, {"mvdx14", 14, TRUE}, {"mvdx15", 15, TRUE},
737 {NULL, 0, TRUE}
6c43fab6
RE
738};
739
740static const struct reg_entry mav_mvax_table[] =
741{
0bbf2aa4
NC
742 {"mvax0", 0, TRUE}, {"mvax1", 1, TRUE}, {"mvax2", 2, TRUE}, {"mvax3", 3, TRUE},
743 {NULL, 0, TRUE}
6c43fab6
RE
744};
745
746static const struct reg_entry mav_dspsc_table[] =
747{
0bbf2aa4
NC
748 {"dspsc", 0, TRUE},
749 {NULL, 0, TRUE}
6c43fab6
RE
750};
751
752struct reg_map
753{
a737bd4d
NC
754 const struct reg_entry * names;
755 int max_regno;
756 struct hash_control * htab;
757 const char * expected;
6c43fab6
RE
758};
759
760struct reg_map all_reg_maps[] =
761{
762 {rn_table, 15, NULL, N_("ARM register expected")},
f03698e6
RE
763 {cp_table, 15, NULL, N_("bad or missing co-processor number")},
764 {cn_table, 15, NULL, N_("co-processor register expected")},
6c43fab6 765 {fn_table, 7, NULL, N_("FPA register expected")},
bfae80f2
RE
766 {sn_table, 31, NULL, N_("VFP single precision register expected")},
767 {dn_table, 15, NULL, N_("VFP double precision register expected")},
6c43fab6
RE
768 {mav_mvf_table, 15, NULL, N_("Maverick MVF register expected")},
769 {mav_mvd_table, 15, NULL, N_("Maverick MVD register expected")},
770 {mav_mvfx_table, 15, NULL, N_("Maverick MVFX register expected")},
5a21e886 771 {mav_mvdx_table, 15, NULL, N_("Maverick MVDX register expected")},
6c43fab6
RE
772 {mav_mvax_table, 3, NULL, N_("Maverick MVAX register expected")},
773 {mav_dspsc_table, 0, NULL, N_("Maverick DSPSC register expected")},
5a6c6817 774 {iwmmxt_table, 23, NULL, N_("Intel Wireless MMX technology register expected")},
6c43fab6
RE
775};
776
777/* Enumeration matching entries in table above. */
778enum arm_reg_type
779{
780 REG_TYPE_RN = 0,
781#define REG_TYPE_FIRST REG_TYPE_RN
782 REG_TYPE_CP = 1,
783 REG_TYPE_CN = 2,
784 REG_TYPE_FN = 3,
bfae80f2
RE
785 REG_TYPE_SN = 4,
786 REG_TYPE_DN = 5,
787 REG_TYPE_MVF = 6,
788 REG_TYPE_MVD = 7,
789 REG_TYPE_MVFX = 8,
790 REG_TYPE_MVDX = 9,
791 REG_TYPE_MVAX = 10,
792 REG_TYPE_DSPSC = 11,
e16bb312 793 REG_TYPE_IWMMXT = 12,
bfae80f2 794
e16bb312 795 REG_TYPE_MAX = 13
6c43fab6 796};
404ff6b5 797
b99bd4ef
NC
798/* ARM instructions take 4bytes in the object file, Thumb instructions
799 take 2: */
800#define INSN_SIZE 4
801
404ff6b5 802/* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
63e63b07 803#define MAV_MODE1 0x100c
404ff6b5
AH
804
805/* "INSN<cond> X,Y" where X:bit16, Y:bit12. */
63e63b07 806#define MAV_MODE2 0x0c10
404ff6b5 807
34920d91
NC
808/* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
809#define MAV_MODE3 0x100c
404ff6b5
AH
810
811/* "INSN<cond> X,Y,Z" where X:16, Y:0, Z:12. */
63e63b07 812#define MAV_MODE4 0x0c0010
404ff6b5
AH
813
814/* "INSN<cond> X,Y,Z" where X:12, Y:16, Z:0. */
63e63b07 815#define MAV_MODE5 0x00100c
404ff6b5
AH
816
817/* "INSN<cond> W,X,Y,Z" where W:5, X:12, Y:16, Z:0. */
63e63b07 818#define MAV_MODE6 0x00100c05
b99bd4ef
NC
819
820struct asm_opcode
821{
822 /* Basic string to match. */
05d2d07e 823 const char * template;
b99bd4ef
NC
824
825 /* Basic instruction code. */
826 unsigned long value;
827
90e4755a
RE
828 /* Offset into the template where the condition code (if any) will be.
829 If zero, then the instruction is never conditional. */
830 unsigned cond_offset;
b99bd4ef 831
90e4755a
RE
832 /* Which architecture variant provides this instruction. */
833 unsigned long variant;
b99bd4ef
NC
834
835 /* Function to call to parse args. */
a737bd4d 836 void (* parms) (char *);
b99bd4ef
NC
837};
838
a737bd4d
NC
839/* Defines for various bits that we will want to toggle. */
840#define INST_IMMEDIATE 0x02000000
841#define OFFSET_REG 0x02000000
842#define HWOFFSET_IMM 0x00400000
843#define SHIFT_BY_REG 0x00000010
844#define PRE_INDEX 0x01000000
845#define INDEX_UP 0x00800000
846#define WRITE_BACK 0x00200000
847#define LDM_TYPE_2_OR_3 0x00400000
90e4755a 848
a737bd4d
NC
849#define LITERAL_MASK 0xf000f000
850#define OPCODE_MASK 0xfe1fffff
851#define V4_STR_BIT 0x00000020
90e4755a 852
a737bd4d 853#define DATA_OP_SHIFT 21
90e4755a 854
a737bd4d
NC
855/* Codes to distinguish the arithmetic instructions. */
856#define OPCODE_AND 0
857#define OPCODE_EOR 1
858#define OPCODE_SUB 2
859#define OPCODE_RSB 3
860#define OPCODE_ADD 4
861#define OPCODE_ADC 5
862#define OPCODE_SBC 6
863#define OPCODE_RSC 7
864#define OPCODE_TST 8
865#define OPCODE_TEQ 9
866#define OPCODE_CMP 10
867#define OPCODE_CMN 11
868#define OPCODE_ORR 12
869#define OPCODE_MOV 13
870#define OPCODE_BIC 14
871#define OPCODE_MVN 15
90e4755a 872
a737bd4d
NC
873#define T_OPCODE_MUL 0x4340
874#define T_OPCODE_TST 0x4200
875#define T_OPCODE_CMN 0x42c0
876#define T_OPCODE_NEG 0x4240
877#define T_OPCODE_MVN 0x43c0
90e4755a 878
a737bd4d
NC
879#define T_OPCODE_ADD_R3 0x1800
880#define T_OPCODE_SUB_R3 0x1a00
881#define T_OPCODE_ADD_HI 0x4400
882#define T_OPCODE_ADD_ST 0xb000
883#define T_OPCODE_SUB_ST 0xb080
884#define T_OPCODE_ADD_SP 0xa800
885#define T_OPCODE_ADD_PC 0xa000
886#define T_OPCODE_ADD_I8 0x3000
887#define T_OPCODE_SUB_I8 0x3800
888#define T_OPCODE_ADD_I3 0x1c00
889#define T_OPCODE_SUB_I3 0x1e00
b99bd4ef 890
a737bd4d
NC
891#define T_OPCODE_ASR_R 0x4100
892#define T_OPCODE_LSL_R 0x4080
893#define T_OPCODE_LSR_R 0x40c0
894#define T_OPCODE_ASR_I 0x1000
895#define T_OPCODE_LSL_I 0x0000
896#define T_OPCODE_LSR_I 0x0800
b99bd4ef 897
a737bd4d
NC
898#define T_OPCODE_MOV_I8 0x2000
899#define T_OPCODE_CMP_I8 0x2800
900#define T_OPCODE_CMP_LR 0x4280
901#define T_OPCODE_MOV_HR 0x4600
902#define T_OPCODE_CMP_HR 0x4500
b99bd4ef 903
a737bd4d
NC
904#define T_OPCODE_LDR_PC 0x4800
905#define T_OPCODE_LDR_SP 0x9800
906#define T_OPCODE_STR_SP 0x9000
907#define T_OPCODE_LDR_IW 0x6800
908#define T_OPCODE_STR_IW 0x6000
909#define T_OPCODE_LDR_IH 0x8800
910#define T_OPCODE_STR_IH 0x8000
911#define T_OPCODE_LDR_IB 0x7800
912#define T_OPCODE_STR_IB 0x7000
913#define T_OPCODE_LDR_RW 0x5800
914#define T_OPCODE_STR_RW 0x5000
915#define T_OPCODE_LDR_RH 0x5a00
916#define T_OPCODE_STR_RH 0x5200
917#define T_OPCODE_LDR_RB 0x5c00
918#define T_OPCODE_STR_RB 0x5400
c9b604bd 919
a737bd4d
NC
920#define T_OPCODE_PUSH 0xb400
921#define T_OPCODE_POP 0xbc00
b99bd4ef 922
a737bd4d 923#define T_OPCODE_BRANCH 0xe7fe
b99bd4ef 924
a737bd4d
NC
925#define THUMB_SIZE 2 /* Size of thumb instruction. */
926#define THUMB_REG_LO 0x1
927#define THUMB_REG_HI 0x2
928#define THUMB_REG_ANY 0x3
90e4755a 929
a737bd4d
NC
930#define THUMB_H1 0x0080
931#define THUMB_H2 0x0040
b99bd4ef 932
a737bd4d
NC
933#define THUMB_ASR 0
934#define THUMB_LSL 1
935#define THUMB_LSR 2
90e4755a 936
a737bd4d
NC
937#define THUMB_MOVE 0
938#define THUMB_COMPARE 1
939#define THUMB_CPY 2
90e4755a 940
a737bd4d
NC
941#define THUMB_LOAD 0
942#define THUMB_STORE 1
90e4755a 943
a737bd4d 944#define THUMB_PP_PC_LR 0x0100
90e4755a 945
a737bd4d
NC
946/* These three are used for immediate shifts, do not alter. */
947#define THUMB_WORD 2
948#define THUMB_HALFWORD 1
949#define THUMB_BYTE 0
90e4755a 950
a737bd4d
NC
951struct thumb_opcode
952{
953 /* Basic string to match. */
954 const char * template;
90e4755a 955
a737bd4d
NC
956 /* Basic instruction code. */
957 unsigned long value;
90e4755a 958
a737bd4d 959 int size;
b99bd4ef
NC
960
961 /* Which CPU variants this exists for. */
90e4755a 962 unsigned long variant;
b99bd4ef
NC
963
964 /* Function to call to parse args. */
a737bd4d 965 void (* parms) (char *);
b99bd4ef
NC
966};
967
f03698e6 968#define BAD_ARGS _("bad arguments to instruction")
b99bd4ef 969#define BAD_PC _("r15 not allowed here")
f03698e6 970#define BAD_COND _("instruction is not conditional")
b99bd4ef
NC
971#define ERR_NO_ACCUM _("acc0 expected")
972
973static struct hash_control * arm_ops_hsh = NULL;
974static struct hash_control * arm_tops_hsh = NULL;
975static struct hash_control * arm_cond_hsh = NULL;
976static struct hash_control * arm_shift_hsh = NULL;
b99bd4ef
NC
977static struct hash_control * arm_psr_hsh = NULL;
978
b99bd4ef
NC
979/* Stuff needed to resolve the label ambiguity
980 As:
981 ...
982 label: <insn>
983 may differ from:
984 ...
985 label:
986 <insn>
987*/
988
989symbolS * last_label_seen;
b34976b6 990static int label_is_thumb_function_name = FALSE;
a737bd4d 991\f
3d0c9500 992/* Literal Pool stuff. */
b99bd4ef
NC
993
994#define MAX_LITERAL_POOL_SIZE 1024
995
3d0c9500
NC
996/* Literal pool structure. Held on a per-section
997 and per-sub-section basis. */
a737bd4d 998
3d0c9500 999typedef struct literal_pool
b99bd4ef 1000{
3d0c9500
NC
1001 expressionS literals [MAX_LITERAL_POOL_SIZE];
1002 unsigned int next_free_entry;
1003 unsigned int id;
1004 symbolS * symbol;
1005 segT section;
1006 subsegT sub_section;
61b5f74b 1007 struct literal_pool * next;
3d0c9500 1008} literal_pool;
b99bd4ef 1009
3d0c9500
NC
1010/* Pointer to a linked list of literal pools. */
1011literal_pool * list_of_pools = NULL;
b99bd4ef 1012
3d0c9500 1013static literal_pool *
a737bd4d 1014find_literal_pool (void)
3d0c9500
NC
1015{
1016 literal_pool * pool;
1017
1018 for (pool = list_of_pools; pool != NULL; pool = pool->next)
1019 {
1020 if (pool->section == now_seg
1021 && pool->sub_section == now_subseg)
1022 break;
1023 }
1024
1025 return pool;
1026}
b99bd4ef 1027
3d0c9500 1028static literal_pool *
a737bd4d 1029find_or_make_literal_pool (void)
3d0c9500
NC
1030{
1031 /* Next literal pool ID number. */
1032 static unsigned int latest_pool_num = 1;
1033 literal_pool * pool;
1034
1035 pool = find_literal_pool ();
b99bd4ef 1036
3d0c9500
NC
1037 if (pool == NULL)
1038 {
1039 /* Create a new pool. */
a737bd4d 1040 pool = xmalloc (sizeof (* pool));
3d0c9500
NC
1041 if (! pool)
1042 return NULL;
1043
1044 pool->next_free_entry = 0;
1045 pool->section = now_seg;
1046 pool->sub_section = now_subseg;
1047 pool->next = list_of_pools;
1048 pool->symbol = NULL;
1049
1050 /* Add it to the list. */
1051 list_of_pools = pool;
1052 }
1053
1054 /* New pools, and emptied pools, will have a NULL symbol. */
1055 if (pool->symbol == NULL)
1056 {
1057 pool->symbol = symbol_create (FAKE_LABEL_NAME, undefined_section,
1058 (valueT) 0, &zero_address_frag);
1059 pool->id = latest_pool_num ++;
1060 }
1061
1062 /* Done. */
1063 return pool;
1064}
1065
1066/* Add the literal in the global 'inst'
1067 structure to the relevent literal pool. */
a737bd4d 1068
b99bd4ef 1069static int
a737bd4d 1070add_to_lit_pool (void)
b99bd4ef 1071{
61b5f74b 1072 literal_pool * pool;
3d0c9500 1073 unsigned int entry;
b99bd4ef 1074
3d0c9500 1075 pool = find_or_make_literal_pool ();
b99bd4ef 1076
3d0c9500
NC
1077 /* Check if this literal value is already in the pool. */
1078 for (entry = 0; entry < pool->next_free_entry; entry ++)
b99bd4ef 1079 {
3d0c9500
NC
1080 if ((pool->literals[entry].X_op == inst.reloc.exp.X_op)
1081 && (inst.reloc.exp.X_op == O_constant)
1082 && (pool->literals[entry].X_add_number
b99bd4ef 1083 == inst.reloc.exp.X_add_number)
3d0c9500
NC
1084 && (pool->literals[entry].X_unsigned
1085 == inst.reloc.exp.X_unsigned))
b99bd4ef
NC
1086 break;
1087
3d0c9500
NC
1088 if ((pool->literals[entry].X_op == inst.reloc.exp.X_op)
1089 && (inst.reloc.exp.X_op == O_symbol)
1090 && (pool->literals[entry].X_add_number
b99bd4ef 1091 == inst.reloc.exp.X_add_number)
3d0c9500 1092 && (pool->literals[entry].X_add_symbol
b99bd4ef 1093 == inst.reloc.exp.X_add_symbol)
3d0c9500 1094 && (pool->literals[entry].X_op_symbol
b99bd4ef 1095 == inst.reloc.exp.X_op_symbol))
3d0c9500 1096 break;
b99bd4ef
NC
1097 }
1098
3d0c9500
NC
1099 /* Do we need to create a new entry? */
1100 if (entry == pool->next_free_entry)
b99bd4ef 1101 {
3d0c9500 1102 if (entry >= MAX_LITERAL_POOL_SIZE)
b99bd4ef 1103 {
ed71e111 1104 inst.error = _("literal pool overflow");
b99bd4ef
NC
1105 return FAIL;
1106 }
1107
3d0c9500
NC
1108 pool->literals[entry] = inst.reloc.exp;
1109 pool->next_free_entry += 1;
b99bd4ef
NC
1110 }
1111
3d0c9500 1112 inst.reloc.exp.X_op = O_symbol;
08df2379 1113 inst.reloc.exp.X_add_number = ((int) entry) * 4 - 8;
3d0c9500 1114 inst.reloc.exp.X_add_symbol = pool->symbol;
b99bd4ef
NC
1115
1116 return SUCCESS;
1117}
1118
1119/* Can't use symbol_new here, so have to create a symbol and then at
1120 a later date assign it a value. Thats what these functions do. */
1121
1122static void
a737bd4d
NC
1123symbol_locate (symbolS * symbolP,
1124 const char * name, /* It is copied, the caller can modify. */
1125 segT segment, /* Segment identifier (SEG_<something>). */
1126 valueT valu, /* Symbol value. */
1127 fragS * frag) /* Associated fragment. */
b99bd4ef
NC
1128{
1129 unsigned int name_length;
1130 char * preserved_copy_of_name;
1131
1132 name_length = strlen (name) + 1; /* +1 for \0. */
1133 obstack_grow (&notes, name, name_length);
1134 preserved_copy_of_name = obstack_finish (&notes);
1135#ifdef STRIP_UNDERSCORE
1136 if (preserved_copy_of_name[0] == '_')
1137 preserved_copy_of_name++;
1138#endif
1139
1140#ifdef tc_canonicalize_symbol_name
1141 preserved_copy_of_name =
1142 tc_canonicalize_symbol_name (preserved_copy_of_name);
1143#endif
1144
1145 S_SET_NAME (symbolP, preserved_copy_of_name);
1146
1147 S_SET_SEGMENT (symbolP, segment);
1148 S_SET_VALUE (symbolP, valu);
c62e1cc3 1149 symbol_clear_list_pointers (symbolP);
b99bd4ef
NC
1150
1151 symbol_set_frag (symbolP, frag);
1152
1153 /* Link to end of symbol chain. */
1154 {
1155 extern int symbol_table_frozen;
a737bd4d 1156
b99bd4ef
NC
1157 if (symbol_table_frozen)
1158 abort ();
1159 }
1160
1161 symbol_append (symbolP, symbol_lastP, & symbol_rootP, & symbol_lastP);
1162
1163 obj_symbol_new_hook (symbolP);
1164
1165#ifdef tc_symbol_new_hook
1166 tc_symbol_new_hook (symbolP);
1167#endif
1168
1169#ifdef DEBUG_SYMS
1170 verify_symbol_chain (symbol_rootP, symbol_lastP);
1171#endif /* DEBUG_SYMS */
1172}
1173
1174/* Check that an immediate is valid.
1175 If so, convert it to the right format. */
1176
1177static unsigned int
a737bd4d 1178validate_immediate (unsigned int val)
b99bd4ef
NC
1179{
1180 unsigned int a;
1181 unsigned int i;
1182
1183#define rotate_left(v, n) (v << n | v >> (32 - n))
1184
1185 for (i = 0; i < 32; i += 2)
1186 if ((a = rotate_left (val, i)) <= 0xff)
1187 return a | (i << 7); /* 12-bit pack: [shift-cnt,const]. */
1188
1189 return FAIL;
1190}
1191
2d2255b5 1192/* Check to see if an immediate can be computed as two separate immediate
b99bd4ef
NC
1193 values, added together. We already know that this value cannot be
1194 computed by just one ARM instruction. */
1195
1196static unsigned int
a737bd4d
NC
1197validate_immediate_twopart (unsigned int val,
1198 unsigned int * highpart)
b99bd4ef
NC
1199{
1200 unsigned int a;
1201 unsigned int i;
1202
1203 for (i = 0; i < 32; i += 2)
1204 if (((a = rotate_left (val, i)) & 0xff) != 0)
1205 {
1206 if (a & 0xff00)
1207 {
1208 if (a & ~ 0xffff)
1209 continue;
1210 * highpart = (a >> 8) | ((i + 24) << 7);
1211 }
1212 else if (a & 0xff0000)
1213 {
1214 if (a & 0xff000000)
1215 continue;
1216 * highpart = (a >> 16) | ((i + 16) << 7);
1217 }
1218 else
1219 {
1220 assert (a & 0xff000000);
1221 * highpart = (a >> 24) | ((i + 8) << 7);
1222 }
1223
1224 return (a & 0xff) | (i << 7);
1225 }
1226
1227 return FAIL;
1228}
1229
1230static int
a737bd4d 1231validate_offset_imm (unsigned int val, int hwse)
b99bd4ef
NC
1232{
1233 if ((hwse && val > 255) || val > 4095)
1234 return FAIL;
1235 return val;
1236}
1237
6057a28f
NC
1238\f
1239#ifdef OBJ_ELF
6057a28f
NC
1240/* This code is to handle mapping symbols as defined in the ARM ELF spec.
1241 (This text is taken from version B-02 of the spec):
1242
1243 4.4.7 Mapping and tagging symbols
1244
1245 A section of an ARM ELF file can contain a mixture of ARM code,
1246 Thumb code, and data. There are inline transitions between code
1247 and data at literal pool boundaries. There can also be inline
1248 transitions between ARM code and Thumb code, for example in
1249 ARM-Thumb inter-working veneers. Linkers, machine-level
1250 debuggers, profiling tools, and disassembly tools need to map
1251 images accurately. For example, setting an ARM breakpoint on a
1252 Thumb location, or in a literal pool, can crash the program
1253 being debugged, ruining the debugging session.
1254
1255 ARM ELF entities are mapped (see section 4.4.7.1 below) and
1256 tagged (see section 4.4.7.2 below) using local symbols (with
1257 binding STB_LOCAL). To assist consumers, mapping and tagging
1258 symbols should be collated first in the symbol table, before
1259 other symbols with binding STB_LOCAL.
1260
1261 To allow properly collated mapping and tagging symbols to be
1262 skipped by consumers that have no interest in them, the first
1263 such symbol should have the name $m and its st_value field equal
1264 to the total number of mapping and tagging symbols (including
1265 the $m) in the symbol table.
1266
1267 4.4.7.1 Mapping symbols
1268
1269 $a Labels the first byte of a sequence of ARM instructions.
1270 Its type is STT_FUNC.
1271
1272 $d Labels the first byte of a sequence of data items.
1273 Its type is STT_OBJECT.
1274
1275 $t Labels the first byte of a sequence of Thumb instructions.
1276 Its type is STT_FUNC.
1277
1278 This list of mapping symbols may be extended in the future.
1279
1280 Section-relative mapping symbols
1281
1282 Mapping symbols defined in a section define a sequence of
1283 half-open address intervals that cover the address range of the
1284 section. Each interval starts at the address defined by a
1285 mapping symbol, and continues up to, but not including, the
1286 address defined by the next (in address order) mapping symbol or
1287 the end of the section. A corollary is that there must be a
1288 mapping symbol defined at the beginning of each section.
1289 Consumers can ignore the size of a section-relative mapping
1290 symbol. Producers can set it to 0.
1291
1292 Absolute mapping symbols
1293
1294 Because of the need to crystallize a Thumb address with the
1295 Thumb-bit set, absolute symbol of type STT_FUNC (symbols of type
1296 STT_FUNC defined in section SHN_ABS) need to be mapped with $a
1297 or $t.
1298
1299 The extent of a mapping symbol defined in SHN_ABS is [st_value,
1300 st_value + st_size), or [st_value, st_value + 1) if st_size = 0,
1301 where [x, y) denotes the half-open address range from x,
1302 inclusive, to y, exclusive.
1303
1304 In the absence of a mapping symbol, a consumer can interpret a
1305 function symbol with an odd value as the Thumb code address
1306 obtained by clearing the least significant bit of the
1307 value. This interpretation is deprecated, and it may not work in
1308 the future.
1309
1310 Note - the Tagging symbols ($b, $f, $p $m) have been dropped from
1311 the EABI (which is still under development), so they are not
1312 implemented here. */
1313
69b97547
NC
1314static enum mstate mapstate = MAP_UNDEFINED;
1315
6057a28f
NC
1316static void
1317mapping_state (enum mstate state)
1318{
6057a28f
NC
1319 symbolS * symbolP;
1320 const char * symname;
1321 int type;
1322
1323 if (mapstate == state)
1324 /* The mapping symbol has already been emitted.
1325 There is nothing else to do. */
1326 return;
1327
1328 mapstate = state;
1329
1330 switch (state)
1331 {
1332 case MAP_DATA:
1333 symname = "$d";
1334 type = BSF_OBJECT;
1335 break;
1336 case MAP_ARM:
1337 symname = "$a";
1338 type = BSF_FUNCTION;
1339 break;
1340 case MAP_THUMB:
1341 symname = "$t";
1342 type = BSF_FUNCTION;
1343 break;
69b97547 1344 case MAP_UNDEFINED:
a737bd4d 1345 return;
6057a28f
NC
1346 default:
1347 abort ();
1348 }
1349
69b97547
NC
1350 seg_info (now_seg)->tc_segment_info_data = state;
1351
6057a28f
NC
1352 symbolP = symbol_new (symname, now_seg, (valueT) frag_now_fix (), frag_now);
1353 symbol_table_insert (symbolP);
1354 symbol_get_bfdsym (symbolP)->flags |= type | BSF_LOCAL;
a737bd4d 1355
6057a28f
NC
1356 switch (state)
1357 {
1358 case MAP_ARM:
1359 THUMB_SET_FUNC (symbolP, 0);
1360 ARM_SET_THUMB (symbolP, 0);
1361 ARM_SET_INTERWORK (symbolP, support_interwork);
1362 break;
a737bd4d 1363
6057a28f
NC
1364 case MAP_THUMB:
1365 THUMB_SET_FUNC (symbolP, 1);
1366 ARM_SET_THUMB (symbolP, 1);
1367 ARM_SET_INTERWORK (symbolP, support_interwork);
1368 break;
a737bd4d 1369
6057a28f
NC
1370 case MAP_DATA:
1371 default:
1372 return;
1373 }
1374}
1375
a737bd4d
NC
1376/* When we change sections we need to issue a new mapping symbol. */
1377
1378void
1379arm_elf_change_section (void)
1380{
1381 flagword flags;
1382
40a18ebd
NC
1383 /* Link an unlinked unwind index table section to the .text section. */
1384 if (elf_section_type (now_seg) == SHT_ARM_EXIDX
1385 && elf_linked_to_section (now_seg) == NULL)
1386 elf_linked_to_section (now_seg) = text_section;
1387
a737bd4d
NC
1388 if (!SEG_NORMAL (now_seg))
1389 return;
1390
1391 flags = bfd_get_section_flags (stdoutput, now_seg);
1392
1393 /* We can ignore sections that only contain debug info. */
1394 if ((flags & SEC_ALLOC) == 0)
1395 return;
1396
1397 mapstate = seg_info (now_seg)->tc_segment_info_data;
1398}
40a18ebd
NC
1399
1400int
1401arm_elf_section_type (const char * str, size_t len)
1402{
1403 if (len == 5 && strncmp (str, "exidx", 5) == 0)
1404 return SHT_ARM_EXIDX;
1405
1406 return -1;
1407}
a737bd4d
NC
1408#else
1409#define mapping_state(a)
1410#endif /* OBJ_ELF */
1411\f
1412/* arm_reg_parse () := if it looks like a register, return its token and
1413 advance the pointer. */
1414
1415static int
1416arm_reg_parse (char ** ccp, struct hash_control * htab)
1417{
1418 char * start = * ccp;
1419 char c;
1420 char * p;
1421 struct reg_entry * reg;
1422
1423#ifdef REGISTER_PREFIX
1424 if (*start != REGISTER_PREFIX)
1425 return FAIL;
1426 p = start + 1;
1427#else
1428 p = start;
1429#ifdef OPTIONAL_REGISTER_PREFIX
1430 if (*p == OPTIONAL_REGISTER_PREFIX)
1431 p++, start++;
1432#endif
1433#endif
1434 if (!ISALPHA (*p) || !is_name_beginner (*p))
1435 return FAIL;
1436
1437 c = *p++;
1438 while (ISALPHA (c) || ISDIGIT (c) || c == '_')
1439 c = *p++;
1440
1441 *--p = 0;
1442 reg = (struct reg_entry *) hash_find (htab, start);
1443 *p = c;
1444
1445 if (reg)
1446 {
1447 *ccp = p;
1448 return reg->number;
1449 }
1450
1451 return FAIL;
1452}
1453
1454/* Search for the following register name in each of the possible reg name
1455 tables. Return the classification if found, or REG_TYPE_MAX if not
1456 present. */
6057a28f 1457
a737bd4d
NC
1458static enum arm_reg_type
1459arm_reg_parse_any (char *cp)
6057a28f 1460{
a737bd4d 1461 int i;
6057a28f 1462
a737bd4d
NC
1463 for (i = (int) REG_TYPE_FIRST; i < (int) REG_TYPE_MAX; i++)
1464 if (arm_reg_parse (&cp, all_reg_maps[i].htab) != FAIL)
1465 return (enum arm_reg_type) i;
6057a28f 1466
a737bd4d
NC
1467 return REG_TYPE_MAX;
1468}
6057a28f 1469
a737bd4d
NC
1470static void
1471opcode_select (int width)
1472{
1473 switch (width)
1474 {
1475 case 16:
1476 if (! thumb_mode)
1477 {
1478 if (! (cpu_variant & ARM_EXT_V4T))
1479 as_bad (_("selected processor does not support THUMB opcodes"));
6057a28f 1480
a737bd4d
NC
1481 thumb_mode = 1;
1482 /* No need to force the alignment, since we will have been
1483 coming from ARM mode, which is word-aligned. */
1484 record_alignment (now_seg, 1);
1485 }
1486 mapping_state (MAP_THUMB);
1487 break;
1488
1489 case 32:
1490 if (thumb_mode)
1491 {
1492 if ((cpu_variant & ARM_ALL) == ARM_EXT_V4T)
1493 as_bad (_("selected processor does not support ARM opcodes"));
1494
1495 thumb_mode = 0;
1496
1497 if (!need_pass_2)
1498 frag_align (2, 0, 0);
1499
1500 record_alignment (now_seg, 1);
1501 }
1502 mapping_state (MAP_ARM);
1503 break;
1504
1505 default:
1506 as_bad (_("invalid instruction size selected (%d)"), width);
1507 }
6057a28f 1508}
6057a28f 1509
b99bd4ef 1510static void
a737bd4d 1511s_req (int a ATTRIBUTE_UNUSED)
b99bd4ef 1512{
f03698e6 1513 as_bad (_("invalid syntax for .req directive"));
b99bd4ef
NC
1514}
1515
0bbf2aa4
NC
1516/* The .unreq directive deletes an alias which was previously defined
1517 by .req. For example:
1518
1519 my_alias .req r11
1520 .unreq my_alias */
1521
1522static void
1523s_unreq (int a ATTRIBUTE_UNUSED)
1524{
a737bd4d 1525 char * name;
0bbf2aa4
NC
1526 char saved_char;
1527
1528 skip_whitespace (input_line_pointer);
1529 name = input_line_pointer;
1530
1531 while (*input_line_pointer != 0
1532 && *input_line_pointer != ' '
1533 && *input_line_pointer != '\n')
1534 ++input_line_pointer;
1535
1536 saved_char = *input_line_pointer;
1537 *input_line_pointer = 0;
1538
1539 if (*name)
1540 {
1541 enum arm_reg_type req_type = arm_reg_parse_any (name);
1542
1543 if (req_type != REG_TYPE_MAX)
1544 {
1545 char *temp_name = name;
1546 int req_no = arm_reg_parse (&temp_name, all_reg_maps[req_type].htab);
1547
1548 if (req_no != FAIL)
1549 {
1550 struct reg_entry *req_entry;
1551
1552 /* Check to see if this alias is a builtin one. */
1553 req_entry = hash_delete (all_reg_maps[req_type].htab, name);
1554
1555 if (!req_entry)
1556 as_bad (_("unreq: missing hash entry for \"%s\""), name);
1557 else if (req_entry->builtin)
67c1ffbe 1558 /* FIXME: We are deleting a built in register alias which
0bbf2aa4
NC
1559 points to a const data structure, so we only need to
1560 free up the memory used by the key in the hash table.
1561 Unfortunately we have not recorded this value, so this
1562 is a memory leak. */
1563 /* FIXME: Should we issue a warning message ? */
1564 ;
1565 else
1566 {
67c1ffbe 1567 /* Deleting a user defined alias. We need to free the
0bbf2aa4
NC
1568 key and the value, but fortunately the key is the same
1569 as the value->name field. */
1570 free ((char *) req_entry->name);
1571 free (req_entry);
1572 }
1573 }
1574 else
1575 as_bad (_(".unreq: unrecognized symbol \"%s\""), name);
1576 }
1577 else
1578 as_bad (_(".unreq: unrecognized symbol \"%s\""), name);
1579 }
1580 else
1581 as_bad (_("invalid syntax for .unreq directive"));
1582
1583 *input_line_pointer = saved_char;
1584 demand_empty_rest_of_line ();
1585}
1586
b99bd4ef 1587static void
a737bd4d 1588s_bss (int ignore ATTRIBUTE_UNUSED)
b99bd4ef
NC
1589{
1590 /* We don't support putting frags in the BSS segment, we fake it by
1591 marking in_bss, then looking at s_skip for clues. */
1592 subseg_set (bss_section, 0);
1593 demand_empty_rest_of_line ();
6057a28f 1594 mapping_state (MAP_DATA);
b99bd4ef
NC
1595}
1596
1597static void
a737bd4d 1598s_even (int ignore ATTRIBUTE_UNUSED)
b99bd4ef
NC
1599{
1600 /* Never make frag if expect extra pass. */
1601 if (!need_pass_2)
1602 frag_align (1, 0, 0);
1603
1604 record_alignment (now_seg, 1);
1605
1606 demand_empty_rest_of_line ();
1607}
1608
1609static void
a737bd4d 1610s_ltorg (int ignored ATTRIBUTE_UNUSED)
b99bd4ef 1611{
3d0c9500
NC
1612 unsigned int entry;
1613 literal_pool * pool;
b99bd4ef
NC
1614 char sym_name[20];
1615
3d0c9500
NC
1616 pool = find_literal_pool ();
1617 if (pool == NULL
1618 || pool->symbol == NULL
1619 || pool->next_free_entry == 0)
b99bd4ef
NC
1620 return;
1621
69b97547
NC
1622 mapping_state (MAP_DATA);
1623
b99bd4ef
NC
1624 /* Align pool as you have word accesses.
1625 Only make a frag if we have to. */
1626 if (!need_pass_2)
1627 frag_align (2, 0, 0);
1628
1629 record_alignment (now_seg, 2);
1630
3d0c9500 1631 sprintf (sym_name, "$$lit_\002%x", pool->id);
b99bd4ef 1632
3d0c9500 1633 symbol_locate (pool->symbol, sym_name, now_seg,
b99bd4ef 1634 (valueT) frag_now_fix (), frag_now);
3d0c9500 1635 symbol_table_insert (pool->symbol);
b99bd4ef 1636
3d0c9500 1637 ARM_SET_THUMB (pool->symbol, thumb_mode);
b99bd4ef
NC
1638
1639#if defined OBJ_COFF || defined OBJ_ELF
3d0c9500 1640 ARM_SET_INTERWORK (pool->symbol, support_interwork);
b99bd4ef
NC
1641#endif
1642
3d0c9500 1643 for (entry = 0; entry < pool->next_free_entry; entry ++)
b99bd4ef 1644 /* First output the expression in the instruction to the pool. */
3d0c9500 1645 emit_expr (&(pool->literals[entry]), 4); /* .word */
b99bd4ef 1646
3d0c9500
NC
1647 /* Mark the pool as empty. */
1648 pool->next_free_entry = 0;
1649 pool->symbol = NULL;
b99bd4ef
NC
1650}
1651
1652/* Same as s_align_ptwo but align 0 => align 2. */
1653
1654static void
a737bd4d 1655s_align (int unused ATTRIBUTE_UNUSED)
b99bd4ef 1656{
a737bd4d
NC
1657 int temp;
1658 long temp_fill;
b99bd4ef
NC
1659 long max_alignment = 15;
1660
1661 temp = get_absolute_expression ();
1662 if (temp > max_alignment)
f03698e6 1663 as_bad (_("alignment too large: %d assumed"), temp = max_alignment);
b99bd4ef
NC
1664 else if (temp < 0)
1665 {
f03698e6 1666 as_bad (_("alignment negative. 0 assumed."));
b99bd4ef
NC
1667 temp = 0;
1668 }
1669
1670 if (*input_line_pointer == ',')
1671 {
1672 input_line_pointer++;
1673 temp_fill = get_absolute_expression ();
1674 }
1675 else
1676 temp_fill = 0;
1677
1678 if (!temp)
1679 temp = 2;
1680
1681 /* Only make a frag if we HAVE to. */
1682 if (temp && !need_pass_2)
1683 frag_align (temp, (int) temp_fill, 0);
1684 demand_empty_rest_of_line ();
1685
1686 record_alignment (now_seg, temp);
1687}
1688
1689static void
a737bd4d 1690s_force_thumb (int ignore ATTRIBUTE_UNUSED)
b99bd4ef
NC
1691{
1692 /* If we are not already in thumb mode go into it, EVEN if
1693 the target processor does not support thumb instructions.
1694 This is used by gcc/config/arm/lib1funcs.asm for example
1695 to compile interworking support functions even if the
1696 target processor should not support interworking. */
1697 if (! thumb_mode)
1698 {
1699 thumb_mode = 2;
1700
1701 record_alignment (now_seg, 1);
1702 }
1703
1704 demand_empty_rest_of_line ();
1705}
1706
1707static void
a737bd4d 1708s_thumb_func (int ignore ATTRIBUTE_UNUSED)
b99bd4ef
NC
1709{
1710 if (! thumb_mode)
1711 opcode_select (16);
1712
1713 /* The following label is the name/address of the start of a Thumb function.
1714 We need to know this for the interworking support. */
b34976b6 1715 label_is_thumb_function_name = TRUE;
b99bd4ef
NC
1716
1717 demand_empty_rest_of_line ();
1718}
1719
1720/* Perform a .set directive, but also mark the alias as
1721 being a thumb function. */
1722
1723static void
a737bd4d 1724s_thumb_set (int equiv)
b99bd4ef
NC
1725{
1726 /* XXX the following is a duplicate of the code for s_set() in read.c
1727 We cannot just call that code as we need to get at the symbol that
1728 is created. */
a737bd4d
NC
1729 char * name;
1730 char delim;
1731 char * end_name;
1732 symbolS * symbolP;
b99bd4ef
NC
1733
1734 /* Especial apologies for the random logic:
1735 This just grew, and could be parsed much more simply!
1736 Dean - in haste. */
1737 name = input_line_pointer;
1738 delim = get_symbol_end ();
1739 end_name = input_line_pointer;
1740 *end_name = delim;
1741
1742 SKIP_WHITESPACE ();
1743
1744 if (*input_line_pointer != ',')
1745 {
1746 *end_name = 0;
f03698e6 1747 as_bad (_("expected comma after name \"%s\""), name);
b99bd4ef
NC
1748 *end_name = delim;
1749 ignore_rest_of_line ();
1750 return;
1751 }
1752
1753 input_line_pointer++;
1754 *end_name = 0;
1755
1756 if (name[0] == '.' && name[1] == '\0')
1757 {
1758 /* XXX - this should not happen to .thumb_set. */
1759 abort ();
1760 }
1761
1762 if ((symbolP = symbol_find (name)) == NULL
1763 && (symbolP = md_undefined_symbol (name)) == NULL)
1764 {
1765#ifndef NO_LISTING
1766 /* When doing symbol listings, play games with dummy fragments living
1767 outside the normal fragment chain to record the file and line info
1768 for this symbol. */
1769 if (listing & LISTING_SYMBOLS)
1770 {
1771 extern struct list_info_struct * listing_tail;
a737bd4d 1772 fragS * dummy_frag = xmalloc (sizeof (fragS));
b99bd4ef
NC
1773
1774 memset (dummy_frag, 0, sizeof (fragS));
1775 dummy_frag->fr_type = rs_fill;
1776 dummy_frag->line = listing_tail;
1777 symbolP = symbol_new (name, undefined_section, 0, dummy_frag);
1778 dummy_frag->fr_symbol = symbolP;
1779 }
1780 else
1781#endif
1782 symbolP = symbol_new (name, undefined_section, 0, &zero_address_frag);
1783
1784#ifdef OBJ_COFF
1785 /* "set" symbols are local unless otherwise specified. */
1786 SF_SET_LOCAL (symbolP);
1787#endif /* OBJ_COFF */
1788 } /* Make a new symbol. */
1789
1790 symbol_table_insert (symbolP);
1791
1792 * end_name = delim;
1793
1794 if (equiv
1795 && S_IS_DEFINED (symbolP)
1796 && S_GET_SEGMENT (symbolP) != reg_section)
1797 as_bad (_("symbol `%s' already defined"), S_GET_NAME (symbolP));
1798
1799 pseudo_set (symbolP);
1800
1801 demand_empty_rest_of_line ();
1802
1803 /* XXX Now we come to the Thumb specific bit of code. */
1804
1805 THUMB_SET_FUNC (symbolP, 1);
1806 ARM_SET_THUMB (symbolP, 1);
1807#if defined OBJ_ELF || defined OBJ_COFF
1808 ARM_SET_INTERWORK (symbolP, support_interwork);
1809#endif
1810}
1811
b99bd4ef 1812static void
a737bd4d 1813s_arm (int ignore ATTRIBUTE_UNUSED)
b99bd4ef
NC
1814{
1815 opcode_select (32);
1816 demand_empty_rest_of_line ();
1817}
1818
1819static void
a737bd4d 1820s_thumb (int ignore ATTRIBUTE_UNUSED)
b99bd4ef
NC
1821{
1822 opcode_select (16);
1823 demand_empty_rest_of_line ();
1824}
1825
1826static void
a737bd4d 1827s_code (int unused ATTRIBUTE_UNUSED)
b99bd4ef 1828{
a737bd4d 1829 int temp;
b99bd4ef
NC
1830
1831 temp = get_absolute_expression ();
1832 switch (temp)
1833 {
1834 case 16:
1835 case 32:
1836 opcode_select (temp);
1837 break;
1838
1839 default:
1840 as_bad (_("invalid operand to .code directive (%d) (expecting 16 or 32)"), temp);
1841 }
1842}
1843
1844static void
a737bd4d 1845end_of_line (char * str)
b99bd4ef
NC
1846{
1847 skip_whitespace (str);
1848
f03698e6
RE
1849 if (*str != '\0' && !inst.error)
1850 inst.error = _("garbage following instruction");
b99bd4ef
NC
1851}
1852
1853static int
a737bd4d 1854skip_past_comma (char ** str)
b99bd4ef
NC
1855{
1856 char * p = * str, c;
1857 int comma = 0;
1858
1859 while ((c = *p) == ' ' || c == ',')
1860 {
1861 p++;
1862 if (c == ',' && comma++)
1863 return FAIL;
1864 }
1865
1866 if (c == '\0')
1867 return FAIL;
1868
1869 *str = p;
1870 return comma ? SUCCESS : FAIL;
1871}
1872
a737bd4d
NC
1873/* Return TRUE if anything in the expression is a bignum. */
1874
1875static int
1876walk_no_bignums (symbolS * sp)
1877{
1878 if (symbol_get_value_expression (sp)->X_op == O_big)
1879 return 1;
1880
1881 if (symbol_get_value_expression (sp)->X_add_symbol)
1882 {
1883 return (walk_no_bignums (symbol_get_value_expression (sp)->X_add_symbol)
1884 || (symbol_get_value_expression (sp)->X_op_symbol
1885 && walk_no_bignums (symbol_get_value_expression (sp)->X_op_symbol)));
1886 }
1887
1888 return 0;
1889}
1890
1891static int in_my_get_expression = 0;
1892
1893static int
1894my_get_expression (expressionS * ep, char ** str)
1895{
1896 char * save_in;
1897 segT seg;
1898
1899 save_in = input_line_pointer;
1900 input_line_pointer = *str;
1901 in_my_get_expression = 1;
1902 seg = expression (ep);
1903 in_my_get_expression = 0;
1904
1905 if (ep->X_op == O_illegal)
1906 {
1907 /* We found a bad expression in md_operand(). */
1908 *str = input_line_pointer;
1909 input_line_pointer = save_in;
1910 return 1;
1911 }
1912
1913#ifdef OBJ_AOUT
1914 if (seg != absolute_section
1915 && seg != text_section
1916 && seg != data_section
1917 && seg != bss_section
1918 && seg != undefined_section)
1919 {
1920 inst.error = _("bad_segment");
1921 *str = input_line_pointer;
1922 input_line_pointer = save_in;
1923 return 1;
1924 }
1925#endif
1926
1927 /* Get rid of any bignums now, so that we don't generate an error for which
1928 we can't establish a line number later on. Big numbers are never valid
1929 in instructions, which is where this routine is always called. */
1930 if (ep->X_op == O_big
1931 || (ep->X_add_symbol
1932 && (walk_no_bignums (ep->X_add_symbol)
1933 || (ep->X_op_symbol
1934 && walk_no_bignums (ep->X_op_symbol)))))
1935 {
1936 inst.error = _("invalid constant");
1937 *str = input_line_pointer;
1938 input_line_pointer = save_in;
1939 return 1;
1940 }
1941
1942 *str = input_line_pointer;
1943 input_line_pointer = save_in;
1944 return 0;
1945}
1946
b99bd4ef
NC
1947/* A standard register must be given at this point.
1948 SHIFT is the place to put it in inst.instruction.
1949 Restores input start point on error.
1950 Returns the reg#, or FAIL. */
1951
1952static int
a737bd4d 1953reg_required_here (char ** str, int shift)
b99bd4ef
NC
1954{
1955 static char buff [128]; /* XXX */
1956 int reg;
1957 char * start = * str;
1958
6c43fab6 1959 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_RN].htab)) != FAIL)
b99bd4ef
NC
1960 {
1961 if (shift >= 0)
1962 inst.instruction |= reg << shift;
1963 return reg;
1964 }
1965
1966 /* Restore the start point, we may have got a reg of the wrong class. */
1967 *str = start;
1968
1969 /* In the few cases where we might be able to accept something else
1970 this error can be overridden. */
f03698e6 1971 sprintf (buff, _("register expected, not '%.100s'"), start);
b99bd4ef
NC
1972 inst.error = buff;
1973
1974 return FAIL;
1975}
1976
5a6c6817 1977/* A Intel Wireless MMX technology register
e16bb312
NC
1978 must be given at this point.
1979 Shift is the place to put it in inst.instruction.
1980 Restores input start point on err.
1981 Returns the reg#, or FAIL. */
1982
1983static int
a737bd4d
NC
1984wreg_required_here (char ** str,
1985 int shift,
1986 enum wreg_type reg_type)
e16bb312
NC
1987{
1988 static char buff [128];
1989 int reg;
1990 char * start = *str;
1991
1992 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_IWMMXT].htab)) != FAIL)
1993 {
1994 if (wr_register (reg)
1995 && (reg_type == IWMMXT_REG_WR || reg_type == IWMMXT_REG_WR_OR_WC))
1996 {
1997 if (shift >= 0)
1998 inst.instruction |= (reg ^ WR_PREFIX) << shift;
1999 return reg;
2000 }
2001 else if (wc_register (reg)
2002 && (reg_type == IWMMXT_REG_WC || reg_type == IWMMXT_REG_WR_OR_WC))
2003 {
2004 if (shift >= 0)
2005 inst.instruction |= (reg ^ WC_PREFIX) << shift;
2006 return reg;
2007 }
2008 else if ((wcg_register (reg) && reg_type == IWMMXT_REG_WCG))
2009 {
2010 if (shift >= 0)
2011 inst.instruction |= ((reg ^ WC_PREFIX) - 8) << shift;
2012 return reg;
2013 }
2014 }
2015
2016 /* Restore the start point, we may have got a reg of the wrong class. */
2017 *str = start;
2018
2019 /* In the few cases where we might be able to accept
2020 something else this error can be overridden. */
5a6c6817 2021 sprintf (buff, _("Intel Wireless MMX technology register expected, not '%.100s'"), start);
e16bb312
NC
2022 inst.error = buff;
2023
2024 return FAIL;
2025}
2026
05d2d07e 2027static const struct asm_psr *
a737bd4d 2028arm_psr_parse (char ** ccp)
b99bd4ef
NC
2029{
2030 char * start = * ccp;
2031 char c;
2032 char * p;
05d2d07e 2033 const struct asm_psr * psr;
b99bd4ef
NC
2034
2035 p = start;
2036
2037 /* Skip to the end of the next word in the input stream. */
2038 do
2039 {
2040 c = *p++;
2041 }
3882b010 2042 while (ISALPHA (c) || c == '_');
b99bd4ef
NC
2043
2044 /* Terminate the word. */
2045 *--p = 0;
2046
2047 /* CPSR's and SPSR's can now be lowercase. This is just a convenience
2048 feature for ease of use and backwards compatibility. */
2049 if (!strncmp (start, "cpsr", 4))
2050 strncpy (start, "CPSR", 4);
2051 else if (!strncmp (start, "spsr", 4))
2052 strncpy (start, "SPSR", 4);
2053
2054 /* Now locate the word in the psr hash table. */
05d2d07e 2055 psr = (const struct asm_psr *) hash_find (arm_psr_hsh, start);
b99bd4ef
NC
2056
2057 /* Restore the input stream. */
2058 *p = c;
2059
2060 /* If we found a valid match, advance the
2061 stream pointer past the end of the word. */
2062 *ccp = p;
2063
2064 return psr;
2065}
2066
2067/* Parse the input looking for a PSR flag. */
2068
2069static int
a737bd4d 2070psr_required_here (char ** str)
b99bd4ef
NC
2071{
2072 char * start = * str;
05d2d07e 2073 const struct asm_psr * psr;
b99bd4ef
NC
2074
2075 psr = arm_psr_parse (str);
2076
2077 if (psr)
2078 {
2079 /* If this is the SPSR that is being modified, set the R bit. */
2080 if (! psr->cpsr)
2081 inst.instruction |= SPSR_BIT;
2082
2083 /* Set the psr flags in the MSR instruction. */
2084 inst.instruction |= psr->field << PSR_SHIFT;
2085
2086 return SUCCESS;
2087 }
2088
2089 /* In the few cases where we might be able to accept
2090 something else this error can be overridden. */
2091 inst.error = _("flag for {c}psr instruction expected");
2092
2093 /* Restore the start point. */
2094 *str = start;
2095 return FAIL;
2096}
2097
2098static int
a737bd4d 2099co_proc_number (char ** str)
b99bd4ef
NC
2100{
2101 int processor, pchar;
6c43fab6 2102 char *start;
b99bd4ef 2103
6c43fab6
RE
2104 skip_whitespace (*str);
2105 start = *str;
b99bd4ef
NC
2106
2107 /* The data sheet seems to imply that just a number on its own is valid
2108 here, but the RISC iX assembler seems to accept a prefix 'p'. We will
2109 accept either. */
6c43fab6
RE
2110 if ((processor = arm_reg_parse (str, all_reg_maps[REG_TYPE_CP].htab))
2111 == FAIL)
b99bd4ef 2112 {
6c43fab6
RE
2113 *str = start;
2114
2115 pchar = *(*str)++;
2116 if (pchar >= '0' && pchar <= '9')
b99bd4ef 2117 {
6c43fab6
RE
2118 processor = pchar - '0';
2119 if (**str >= '0' && **str <= '9')
b99bd4ef 2120 {
6c43fab6
RE
2121 processor = processor * 10 + *(*str)++ - '0';
2122 if (processor > 15)
2123 {
f03698e6 2124 inst.error = _("illegal co-processor number");
6c43fab6
RE
2125 return FAIL;
2126 }
b99bd4ef
NC
2127 }
2128 }
6c43fab6
RE
2129 else
2130 {
376eb240 2131 inst.error = all_reg_maps[REG_TYPE_CP].expected;
6c43fab6
RE
2132 return FAIL;
2133 }
b99bd4ef
NC
2134 }
2135
2136 inst.instruction |= processor << 8;
2137 return SUCCESS;
2138}
2139
2140static int
a737bd4d 2141cp_opc_expr (char ** str, int where, int length)
b99bd4ef
NC
2142{
2143 expressionS expr;
2144
2145 skip_whitespace (* str);
2146
2147 memset (&expr, '\0', sizeof (expr));
2148
2149 if (my_get_expression (&expr, str))
2150 return FAIL;
2151 if (expr.X_op != O_constant)
2152 {
2153 inst.error = _("bad or missing expression");
2154 return FAIL;
2155 }
2156
2157 if ((expr.X_add_number & ((1 << length) - 1)) != expr.X_add_number)
2158 {
2159 inst.error = _("immediate co-processor expression too large");
2160 return FAIL;
2161 }
2162
2163 inst.instruction |= expr.X_add_number << where;
2164 return SUCCESS;
2165}
2166
2167static int
a737bd4d 2168cp_reg_required_here (char ** str, int where)
b99bd4ef
NC
2169{
2170 int reg;
2171 char * start = *str;
2172
6c43fab6 2173 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_CN].htab)) != FAIL)
b99bd4ef 2174 {
b99bd4ef
NC
2175 inst.instruction |= reg << where;
2176 return reg;
2177 }
2178
2179 /* In the few cases where we might be able to accept something else
2180 this error can be overridden. */
376eb240 2181 inst.error = all_reg_maps[REG_TYPE_CN].expected;
b99bd4ef
NC
2182
2183 /* Restore the start point. */
2184 *str = start;
2185 return FAIL;
2186}
2187
2188static int
a737bd4d 2189fp_reg_required_here (char ** str, int where)
b99bd4ef
NC
2190{
2191 int reg;
2192 char * start = * str;
2193
6c43fab6 2194 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_FN].htab)) != FAIL)
b99bd4ef 2195 {
b99bd4ef
NC
2196 inst.instruction |= reg << where;
2197 return reg;
2198 }
2199
2200 /* In the few cases where we might be able to accept something else
2201 this error can be overridden. */
376eb240 2202 inst.error = all_reg_maps[REG_TYPE_FN].expected;
b99bd4ef
NC
2203
2204 /* Restore the start point. */
2205 *str = start;
2206 return FAIL;
2207}
2208
2209static int
a737bd4d 2210cp_address_offset (char ** str)
b99bd4ef
NC
2211{
2212 int offset;
2213
2214 skip_whitespace (* str);
2215
2216 if (! is_immediate_prefix (**str))
2217 {
2218 inst.error = _("immediate expression expected");
2219 return FAIL;
2220 }
2221
2222 (*str)++;
2223
2224 if (my_get_expression (& inst.reloc.exp, str))
2225 return FAIL;
2226
2227 if (inst.reloc.exp.X_op == O_constant)
2228 {
2229 offset = inst.reloc.exp.X_add_number;
2230
2231 if (offset & 3)
2232 {
2233 inst.error = _("co-processor address must be word aligned");
2234 return FAIL;
2235 }
2236
2237 if (offset > 1023 || offset < -1023)
2238 {
2239 inst.error = _("offset too large");
2240 return FAIL;
2241 }
2242
2243 if (offset >= 0)
2244 inst.instruction |= INDEX_UP;
2245 else
2246 offset = -offset;
2247
2248 inst.instruction |= offset >> 2;
2249 }
2250 else
2251 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
2252
2253 return SUCCESS;
2254}
2255
2256static int
a737bd4d 2257cp_address_required_here (char ** str, int wb_ok)
b99bd4ef
NC
2258{
2259 char * p = * str;
2260 int pre_inc = 0;
2261 int write_back = 0;
2262
2263 if (*p == '[')
2264 {
2265 int reg;
2266
2267 p++;
2268 skip_whitespace (p);
2269
2270 if ((reg = reg_required_here (& p, 16)) == FAIL)
2271 return FAIL;
2272
2273 skip_whitespace (p);
2274
2275 if (*p == ']')
2276 {
2277 p++;
2278
f02232aa
NC
2279 skip_whitespace (p);
2280
2281 if (*p == '\0')
b99bd4ef 2282 {
f02232aa 2283 /* As an extension to the official ARM syntax we allow:
f02232aa 2284 [Rn]
f02232aa 2285 as a short hand for:
f02232aa
NC
2286 [Rn,#0] */
2287 inst.instruction |= PRE_INDEX | INDEX_UP;
2288 *str = p;
2289 return SUCCESS;
2290 }
a737bd4d 2291
f02232aa
NC
2292 if (skip_past_comma (& p) == FAIL)
2293 {
2294 inst.error = _("comma expected after closing square bracket");
2295 return FAIL;
2296 }
b99bd4ef 2297
f02232aa
NC
2298 skip_whitespace (p);
2299
2300 if (*p == '#')
2301 {
2302 if (wb_ok)
b99bd4ef 2303 {
f02232aa
NC
2304 /* [Rn], #expr */
2305 write_back = WRITE_BACK;
2306
2307 if (reg == REG_PC)
2308 {
2309 inst.error = _("pc may not be used in post-increment");
2310 return FAIL;
2311 }
2312
2313 if (cp_address_offset (& p) == FAIL)
2314 return FAIL;
b99bd4ef 2315 }
f02232aa
NC
2316 else
2317 pre_inc = PRE_INDEX | INDEX_UP;
2318 }
2319 else if (*p == '{')
2320 {
2321 int option;
b99bd4ef 2322
f02232aa
NC
2323 /* [Rn], {<expr>} */
2324 p++;
2325
2326 skip_whitespace (p);
2327
2328 if (my_get_expression (& inst.reloc.exp, & p))
b99bd4ef 2329 return FAIL;
f02232aa
NC
2330
2331 if (inst.reloc.exp.X_op == O_constant)
2332 {
2333 option = inst.reloc.exp.X_add_number;
2334
2335 if (option > 255 || option < 0)
2336 {
2337 inst.error = _("'option' field too large");
2338 return FAIL;
2339 }
2340
2341 skip_whitespace (p);
2342
2343 if (*p != '}')
2344 {
2345 inst.error = _("'}' expected at end of 'option' field");
2346 return FAIL;
2347 }
2348 else
2349 {
2350 p++;
2351 inst.instruction |= option;
2352 inst.instruction |= INDEX_UP;
2353 }
2354 }
2355 else
2356 {
2357 inst.error = _("non-constant expressions for 'option' field not supported");
2358 return FAIL;
2359 }
b99bd4ef
NC
2360 }
2361 else
f02232aa
NC
2362 {
2363 inst.error = _("# or { expected after comma");
a737bd4d 2364 return FAIL;
f02232aa 2365 }
b99bd4ef
NC
2366 }
2367 else
2368 {
2369 /* '['Rn, #expr']'[!] */
2370
2371 if (skip_past_comma (& p) == FAIL)
2372 {
2373 inst.error = _("pre-indexed expression expected");
2374 return FAIL;
2375 }
2376
2377 pre_inc = PRE_INDEX;
2378
2379 if (cp_address_offset (& p) == FAIL)
2380 return FAIL;
2381
2382 skip_whitespace (p);
2383
2384 if (*p++ != ']')
2385 {
2386 inst.error = _("missing ]");
2387 return FAIL;
2388 }
2389
2390 skip_whitespace (p);
2391
bfae80f2 2392 if (wb_ok && *p == '!')
b99bd4ef
NC
2393 {
2394 if (reg == REG_PC)
2395 {
2396 inst.error = _("pc may not be used with write-back");
2397 return FAIL;
2398 }
2399
2400 p++;
2401 write_back = WRITE_BACK;
2402 }
2403 }
2404 }
2405 else
2406 {
2407 if (my_get_expression (&inst.reloc.exp, &p))
2408 return FAIL;
2409
2410 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
2411 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
2412 inst.reloc.pc_rel = 1;
2413 inst.instruction |= (REG_PC << 16);
2414 pre_inc = PRE_INDEX;
2415 }
2416
2417 inst.instruction |= write_back | pre_inc;
2418 *str = p;
2419 return SUCCESS;
2420}
2421
e16bb312 2422static int
a737bd4d 2423cp_byte_address_offset (char ** str)
e16bb312
NC
2424{
2425 int offset;
2426
2427 skip_whitespace (* str);
2428
2429 if (! is_immediate_prefix (**str))
2430 {
2431 inst.error = _("immediate expression expected");
2432 return FAIL;
2433 }
2434
2435 (*str)++;
a737bd4d 2436
e16bb312
NC
2437 if (my_get_expression (& inst.reloc.exp, str))
2438 return FAIL;
a737bd4d 2439
e16bb312
NC
2440 if (inst.reloc.exp.X_op == O_constant)
2441 {
2442 offset = inst.reloc.exp.X_add_number;
a737bd4d 2443
e16bb312
NC
2444 if (offset > 255 || offset < -255)
2445 {
2446 inst.error = _("offset too large");
2447 return FAIL;
2448 }
2449
2450 if (offset >= 0)
2451 inst.instruction |= INDEX_UP;
2452 else
2453 offset = -offset;
2454
2455 inst.instruction |= offset;
2456 }
2457 else
2458 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM_S2;
2459
2460 return SUCCESS;
2461}
2462
2463static int
a737bd4d 2464cp_byte_address_required_here (char ** str)
e16bb312
NC
2465{
2466 char * p = * str;
2467 int pre_inc = 0;
2468 int write_back = 0;
2469
2470 if (*p == '[')
2471 {
2472 int reg;
2473
2474 p++;
2475 skip_whitespace (p);
2476
2477 if ((reg = reg_required_here (& p, 16)) == FAIL)
2478 return FAIL;
2479
2480 skip_whitespace (p);
2481
2482 if (*p == ']')
2483 {
2484 p++;
a737bd4d 2485
e16bb312
NC
2486 if (skip_past_comma (& p) == SUCCESS)
2487 {
2488 /* [Rn], #expr */
2489 write_back = WRITE_BACK;
a737bd4d 2490
e16bb312
NC
2491 if (reg == REG_PC)
2492 {
2493 inst.error = _("pc may not be used in post-increment");
2494 return FAIL;
2495 }
2496
2497 if (cp_byte_address_offset (& p) == FAIL)
2498 return FAIL;
2499 }
2500 else
2501 pre_inc = PRE_INDEX | INDEX_UP;
2502 }
2503 else
2504 {
2505 /* '['Rn, #expr']'[!] */
2506
2507 if (skip_past_comma (& p) == FAIL)
2508 {
2509 inst.error = _("pre-indexed expression expected");
2510 return FAIL;
2511 }
2512
2513 pre_inc = PRE_INDEX;
a737bd4d 2514
e16bb312
NC
2515 if (cp_byte_address_offset (& p) == FAIL)
2516 return FAIL;
2517
2518 skip_whitespace (p);
2519
2520 if (*p++ != ']')
2521 {
2522 inst.error = _("missing ]");
2523 return FAIL;
2524 }
2525
2526 skip_whitespace (p);
2527
2528 if (*p == '!')
2529 {
2530 if (reg == REG_PC)
2531 {
2532 inst.error = _("pc may not be used with write-back");
2533 return FAIL;
2534 }
2535
2536 p++;
2537 write_back = WRITE_BACK;
2538 }
2539 }
2540 }
2541 else
2542 {
2543 if (my_get_expression (&inst.reloc.exp, &p))
2544 return FAIL;
2545
2546 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM_S2;
2547 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
2548 inst.reloc.pc_rel = 1;
2549 inst.instruction |= (REG_PC << 16);
2550 pre_inc = PRE_INDEX;
2551 }
2552
2553 inst.instruction |= write_back | pre_inc;
2554 *str = p;
2555 return SUCCESS;
2556}
2557
0dd132b6
NC
2558static void
2559do_nop (char * str)
2560{
2561 skip_whitespace (str);
2562 if (*str == '{')
2563 {
2564 str++;
2565
2566 if (my_get_expression (&inst.reloc.exp, &str))
2567 inst.reloc.exp.X_op = O_illegal;
2568 else
2569 {
2570 skip_whitespace (str);
2571 if (*str == '}')
2572 str++;
2573 else
2574 inst.reloc.exp.X_op = O_illegal;
2575 }
2576
2577 if (inst.reloc.exp.X_op != O_constant
2578 || inst.reloc.exp.X_add_number > 255
2579 || inst.reloc.exp.X_add_number < 0)
2580 {
2581 inst.error = _("Invalid NOP hint");
2582 return;
2583 }
2584
2585 /* Arcitectural NOP hints are CPSR sets with no bits selected. */
2586 inst.instruction &= 0xf0000000;
2587 inst.instruction |= 0x0320f000 + inst.reloc.exp.X_add_number;
2588 }
2589
2590 end_of_line (str);
2591}
2592
b99bd4ef 2593static void
a737bd4d 2594do_empty (char * str)
b99bd4ef
NC
2595{
2596 /* Do nothing really. */
b99bd4ef 2597 end_of_line (str);
b99bd4ef
NC
2598}
2599
2600static void
a737bd4d 2601do_mrs (char * str)
b99bd4ef
NC
2602{
2603 int skip = 0;
2604
2605 /* Only one syntax. */
2606 skip_whitespace (str);
2607
2608 if (reg_required_here (&str, 12) == FAIL)
2609 {
2610 inst.error = BAD_ARGS;
2611 return;
2612 }
2613
2614 if (skip_past_comma (&str) == FAIL)
2615 {
2616 inst.error = _("comma expected after register name");
2617 return;
2618 }
2619
2620 skip_whitespace (str);
2621
a737bd4d
NC
2622 if ( streq (str, "CPSR")
2623 || streq (str, "SPSR")
2d2255b5 2624 /* Lower case versions for backwards compatibility. */
a737bd4d
NC
2625 || streq (str, "cpsr")
2626 || streq (str, "spsr"))
b99bd4ef
NC
2627 skip = 4;
2628
2d2255b5 2629 /* This is for backwards compatibility with older toolchains. */
a737bd4d
NC
2630 else if ( streq (str, "cpsr_all")
2631 || streq (str, "spsr_all"))
b99bd4ef
NC
2632 skip = 8;
2633 else
2634 {
f03698e6 2635 inst.error = _("CPSR or SPSR expected");
b99bd4ef
NC
2636 return;
2637 }
2638
2639 if (* str == 's' || * str == 'S')
2640 inst.instruction |= SPSR_BIT;
2641 str += skip;
2642
b99bd4ef
NC
2643 end_of_line (str);
2644}
2645
2646/* Two possible forms:
2647 "{C|S}PSR_<field>, Rm",
2648 "{C|S}PSR_f, #expression". */
2649
2650static void
a737bd4d 2651do_msr (char * str)
b99bd4ef
NC
2652{
2653 skip_whitespace (str);
2654
2655 if (psr_required_here (& str) == FAIL)
2656 return;
2657
2658 if (skip_past_comma (& str) == FAIL)
2659 {
2660 inst.error = _("comma missing after psr flags");
2661 return;
2662 }
2663
2664 skip_whitespace (str);
2665
2666 if (reg_required_here (& str, 0) != FAIL)
2667 {
2668 inst.error = NULL;
b99bd4ef
NC
2669 end_of_line (str);
2670 return;
2671 }
2672
2673 if (! is_immediate_prefix (* str))
2674 {
2675 inst.error =
2676 _("only a register or immediate value can follow a psr flag");
2677 return;
2678 }
2679
2680 str ++;
2681 inst.error = NULL;
2682
2683 if (my_get_expression (& inst.reloc.exp, & str))
2684 {
2685 inst.error =
2686 _("only a register or immediate value can follow a psr flag");
2687 return;
2688 }
2689
f2b7cb0a 2690 inst.instruction |= INST_IMMEDIATE;
b99bd4ef
NC
2691
2692 if (inst.reloc.exp.X_add_symbol)
2693 {
2694 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
2695 inst.reloc.pc_rel = 0;
2696 }
2697 else
2698 {
2699 unsigned value = validate_immediate (inst.reloc.exp.X_add_number);
2700
2701 if (value == (unsigned) FAIL)
2702 {
f03698e6 2703 inst.error = _("invalid constant");
b99bd4ef
NC
2704 return;
2705 }
2706
2707 inst.instruction |= value;
2708 }
2709
2710 inst.error = NULL;
b99bd4ef
NC
2711 end_of_line (str);
2712}
2713
2714/* Long Multiply Parser
2715 UMULL RdLo, RdHi, Rm, Rs
2716 SMULL RdLo, RdHi, Rm, Rs
2717 UMLAL RdLo, RdHi, Rm, Rs
2718 SMLAL RdLo, RdHi, Rm, Rs. */
2719
2720static void
a737bd4d 2721do_mull (char * str)
b99bd4ef
NC
2722{
2723 int rdlo, rdhi, rm, rs;
2724
2725 /* Only one format "rdlo, rdhi, rm, rs". */
2726 skip_whitespace (str);
2727
2728 if ((rdlo = reg_required_here (&str, 12)) == FAIL)
2729 {
2730 inst.error = BAD_ARGS;
2731 return;
2732 }
2733
2734 if (skip_past_comma (&str) == FAIL
2735 || (rdhi = reg_required_here (&str, 16)) == FAIL)
2736 {
2737 inst.error = BAD_ARGS;
2738 return;
2739 }
2740
2741 if (skip_past_comma (&str) == FAIL
2742 || (rm = reg_required_here (&str, 0)) == FAIL)
2743 {
2744 inst.error = BAD_ARGS;
2745 return;
2746 }
2747
2748 /* rdhi, rdlo and rm must all be different. */
2749 if (rdlo == rdhi || rdlo == rm || rdhi == rm)
2750 as_tsktsk (_("rdhi, rdlo and rm must all be different"));
2751
2752 if (skip_past_comma (&str) == FAIL
2753 || (rs = reg_required_here (&str, 8)) == FAIL)
2754 {
2755 inst.error = BAD_ARGS;
2756 return;
2757 }
2758
2759 if (rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC)
2760 {
2761 inst.error = BAD_PC;
2762 return;
2763 }
2764
b99bd4ef 2765 end_of_line (str);
b99bd4ef
NC
2766}
2767
2768static void
a737bd4d 2769do_mul (char * str)
b99bd4ef
NC
2770{
2771 int rd, rm;
2772
2773 /* Only one format "rd, rm, rs". */
2774 skip_whitespace (str);
2775
2776 if ((rd = reg_required_here (&str, 16)) == FAIL)
2777 {
2778 inst.error = BAD_ARGS;
2779 return;
2780 }
2781
2782 if (rd == REG_PC)
2783 {
2784 inst.error = BAD_PC;
2785 return;
2786 }
2787
2788 if (skip_past_comma (&str) == FAIL
2789 || (rm = reg_required_here (&str, 0)) == FAIL)
2790 {
2791 inst.error = BAD_ARGS;
2792 return;
2793 }
2794
2795 if (rm == REG_PC)
2796 {
2797 inst.error = BAD_PC;
2798 return;
2799 }
2800
2801 if (rm == rd)
2802 as_tsktsk (_("rd and rm should be different in mul"));
2803
2804 if (skip_past_comma (&str) == FAIL
2805 || (rm = reg_required_here (&str, 8)) == FAIL)
2806 {
2807 inst.error = BAD_ARGS;
2808 return;
2809 }
2810
2811 if (rm == REG_PC)
2812 {
2813 inst.error = BAD_PC;
2814 return;
2815 }
2816
b99bd4ef 2817 end_of_line (str);
b99bd4ef
NC
2818}
2819
2820static void
b05fe5cf 2821do_mlas (char * str, bfd_boolean is_mls)
b99bd4ef
NC
2822{
2823 int rd, rm;
2824
2825 /* Only one format "rd, rm, rs, rn". */
2826 skip_whitespace (str);
2827
2828 if ((rd = reg_required_here (&str, 16)) == FAIL)
2829 {
2830 inst.error = BAD_ARGS;
2831 return;
2832 }
2833
2834 if (rd == REG_PC)
2835 {
2836 inst.error = BAD_PC;
2837 return;
2838 }
2839
2840 if (skip_past_comma (&str) == FAIL
2841 || (rm = reg_required_here (&str, 0)) == FAIL)
2842 {
2843 inst.error = BAD_ARGS;
2844 return;
2845 }
2846
2847 if (rm == REG_PC)
2848 {
2849 inst.error = BAD_PC;
2850 return;
2851 }
2852
b05fe5cf
ZW
2853 /* This restriction does not apply to mls (nor to mla in v6, but
2854 that's hard to detect at present). */
2855 if (rm == rd && !is_mls)
b99bd4ef
NC
2856 as_tsktsk (_("rd and rm should be different in mla"));
2857
2858 if (skip_past_comma (&str) == FAIL
2859 || (rd = reg_required_here (&str, 8)) == FAIL
2860 || skip_past_comma (&str) == FAIL
2861 || (rm = reg_required_here (&str, 12)) == FAIL)
2862 {
2863 inst.error = BAD_ARGS;
2864 return;
2865 }
2866
2867 if (rd == REG_PC || rm == REG_PC)
2868 {
2869 inst.error = BAD_PC;
2870 return;
2871 }
2872
b99bd4ef 2873 end_of_line (str);
b99bd4ef
NC
2874}
2875
b05fe5cf
ZW
2876static void
2877do_mla (char *str)
2878{
2879 do_mlas (str, FALSE);
2880}
2881
2882static void
2883do_mls (char *str)
2884{
2885 do_mlas (str, TRUE);
2886}
2887
b99bd4ef
NC
2888/* Expects *str -> the characters "acc0", possibly with leading blanks.
2889 Advances *str to the next non-alphanumeric.
2890 Returns 0, or else FAIL (in which case sets inst.error).
2891
2892 (In a future XScale, there may be accumulators other than zero.
2893 At that time this routine and its callers can be upgraded to suit.) */
2894
2895static int
a737bd4d 2896accum0_required_here (char ** str)
b99bd4ef
NC
2897{
2898 static char buff [128]; /* Note the address is taken. Hence, static. */
2899 char * p = * str;
2900 char c;
2901 int result = 0; /* The accum number. */
2902
2903 skip_whitespace (p);
2904
a737bd4d
NC
2905 *str = p; /* Advance caller's string pointer too. */
2906 c = *p++;
2907 while (ISALNUM (c))
2908 c = *p++;
2909
2910 *--p = 0; /* Aap nul into input buffer at non-alnum. */
2911
2912 if (! ( streq (*str, "acc0") || streq (*str, "ACC0")))
2913 {
2914 sprintf (buff, _("acc0 expected, not '%.100s'"), *str);
2915 inst.error = buff;
2916 result = FAIL;
2917 }
2918
2919 *p = c; /* Unzap. */
2920 *str = p; /* Caller's string pointer to after match. */
2921 return result;
2922}
2923
2924static int
2925ldst_extend_v4 (char ** str)
2926{
2927 int add = INDEX_UP;
2928
2929 switch (**str)
2930 {
2931 case '#':
2932 case '$':
2933 (*str)++;
2934 if (my_get_expression (& inst.reloc.exp, str))
2935 return FAIL;
2936
2937 if (inst.reloc.exp.X_op == O_constant)
2938 {
2939 int value = inst.reloc.exp.X_add_number;
2940
2941 if (value < -255 || value > 255)
2942 {
2943 inst.error = _("address offset too large");
2944 return FAIL;
2945 }
2946
2947 if (value < 0)
2948 {
2949 value = -value;
2950 add = 0;
2951 }
2952
2953 /* Halfword and signextension instructions have the
2954 immediate value split across bits 11..8 and bits 3..0. */
2955 inst.instruction |= (add | HWOFFSET_IMM
2956 | ((value >> 4) << 8) | (value & 0xF));
2957 }
2958 else
2959 {
2960 inst.instruction |= HWOFFSET_IMM;
2961 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
2962 inst.reloc.pc_rel = 0;
2963 }
2964 return SUCCESS;
2965
2966 case '-':
2967 add = 0;
2968 /* Fall through. */
2969
2970 case '+':
2971 (*str)++;
2972 /* Fall through. */
b99bd4ef 2973
a737bd4d
NC
2974 default:
2975 if (reg_required_here (str, 0) == FAIL)
2976 return FAIL;
b99bd4ef 2977
a737bd4d
NC
2978 inst.instruction |= add;
2979 return SUCCESS;
b99bd4ef 2980 }
b99bd4ef
NC
2981}
2982
2983/* Expects **str -> after a comma. May be leading blanks.
2984 Advances *str, recognizing a load mode, and setting inst.instruction.
2985 Returns rn, or else FAIL (in which case may set inst.error
2986 and not advance str)
2987
2988 Note: doesn't know Rd, so no err checks that require such knowledge. */
2989
2990static int
a737bd4d 2991ld_mode_required_here (char ** string)
b99bd4ef
NC
2992{
2993 char * str = * string;
2994 int rn;
2995 int pre_inc = 0;
2996
2997 skip_whitespace (str);
2998
2999 if (* str == '[')
3000 {
3001 str++;
3002
3003 skip_whitespace (str);
3004
3005 if ((rn = reg_required_here (& str, 16)) == FAIL)
3006 return FAIL;
3007
3008 skip_whitespace (str);
3009
3010 if (* str == ']')
3011 {
3012 str ++;
3013
3014 if (skip_past_comma (& str) == SUCCESS)
3015 {
3016 /* [Rn],... (post inc) */
90e4755a 3017 if (ldst_extend_v4 (&str) == FAIL)
b99bd4ef
NC
3018 return FAIL;
3019 }
3020 else /* [Rn] */
3021 {
cc8a6dd0 3022 skip_whitespace (str);
b99bd4ef 3023
cc8a6dd0
KH
3024 if (* str == '!')
3025 {
3026 str ++;
3027 inst.instruction |= WRITE_BACK;
3028 }
b99bd4ef
NC
3029
3030 inst.instruction |= INDEX_UP | HWOFFSET_IMM;
3031 pre_inc = 1;
3032 }
3033 }
3034 else /* [Rn,...] */
3035 {
3036 if (skip_past_comma (& str) == FAIL)
3037 {
3038 inst.error = _("pre-indexed expression expected");
3039 return FAIL;
3040 }
3041
3042 pre_inc = 1;
3043
90e4755a 3044 if (ldst_extend_v4 (&str) == FAIL)
b99bd4ef
NC
3045 return FAIL;
3046
3047 skip_whitespace (str);
3048
3049 if (* str ++ != ']')
3050 {
3051 inst.error = _("missing ]");
3052 return FAIL;
3053 }
3054
3055 skip_whitespace (str);
3056
3057 if (* str == '!')
3058 {
3059 str ++;
3060 inst.instruction |= WRITE_BACK;
3061 }
3062 }
3063 }
3064 else if (* str == '=') /* ldr's "r,=label" syntax */
3065 /* We should never reach here, because <text> = <expression> is
3066 caught gas/read.c read_a_source_file() as a .set operation. */
3067 return FAIL;
3068 else /* PC +- 8 bit immediate offset. */
3069 {
3070 if (my_get_expression (& inst.reloc.exp, & str))
3071 return FAIL;
3072
3073 inst.instruction |= HWOFFSET_IMM; /* The I bit. */
3074 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
3075 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
3076 inst.reloc.pc_rel = 1;
3077 inst.instruction |= (REG_PC << 16);
3078
3079 rn = REG_PC;
3080 pre_inc = 1;
3081 }
3082
3083 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
3084 * string = str;
3085
3086 return rn;
3087}
3088
3089/* ARM V5E (El Segundo) signed-multiply-accumulate (argument parse)
3090 SMLAxy{cond} Rd,Rm,Rs,Rn
3091 SMLAWy{cond} Rd,Rm,Rs,Rn
3092 Error if any register is R15. */
3093
3094static void
a737bd4d 3095do_smla (char * str)
b99bd4ef
NC
3096{
3097 int rd, rm, rs, rn;
3098
3099 skip_whitespace (str);
3100
3101 if ((rd = reg_required_here (& str, 16)) == FAIL
3102 || skip_past_comma (& str) == FAIL
3103 || (rm = reg_required_here (& str, 0)) == FAIL
3104 || skip_past_comma (& str) == FAIL
3105 || (rs = reg_required_here (& str, 8)) == FAIL
3106 || skip_past_comma (& str) == FAIL
3107 || (rn = reg_required_here (& str, 12)) == FAIL)
3108 inst.error = BAD_ARGS;
3109
3110 else if (rd == REG_PC || rm == REG_PC || rs == REG_PC || rn == REG_PC)
3111 inst.error = BAD_PC;
3112
b99bd4ef
NC
3113 else
3114 end_of_line (str);
3115}
3116
3117/* ARM V5E (El Segundo) signed-multiply-accumulate-long (argument parse)
3118 SMLALxy{cond} Rdlo,Rdhi,Rm,Rs
3119 Error if any register is R15.
3120 Warning if Rdlo == Rdhi. */
3121
3122static void
a737bd4d 3123do_smlal (char * str)
b99bd4ef
NC
3124{
3125 int rdlo, rdhi, rm, rs;
3126
3127 skip_whitespace (str);
3128
3129 if ((rdlo = reg_required_here (& str, 12)) == FAIL
3130 || skip_past_comma (& str) == FAIL
3131 || (rdhi = reg_required_here (& str, 16)) == FAIL
3132 || skip_past_comma (& str) == FAIL
3133 || (rm = reg_required_here (& str, 0)) == FAIL
3134 || skip_past_comma (& str) == FAIL
3135 || (rs = reg_required_here (& str, 8)) == FAIL)
3136 {
3137 inst.error = BAD_ARGS;
3138 return;
3139 }
3140
3141 if (rdlo == REG_PC || rdhi == REG_PC || rm == REG_PC || rs == REG_PC)
3142 {
3143 inst.error = BAD_PC;
3144 return;
3145 }
3146
3147 if (rdlo == rdhi)
3148 as_tsktsk (_("rdhi and rdlo must be different"));
3149
f2b7cb0a 3150 end_of_line (str);
b99bd4ef
NC
3151}
3152
3153/* ARM V5E (El Segundo) signed-multiply (argument parse)
3154 SMULxy{cond} Rd,Rm,Rs
3155 Error if any register is R15. */
3156
3157static void
a737bd4d 3158do_smul (char * str)
b99bd4ef
NC
3159{
3160 int rd, rm, rs;
3161
3162 skip_whitespace (str);
3163
3164 if ((rd = reg_required_here (& str, 16)) == FAIL
3165 || skip_past_comma (& str) == FAIL
3166 || (rm = reg_required_here (& str, 0)) == FAIL
3167 || skip_past_comma (& str) == FAIL
3168 || (rs = reg_required_here (& str, 8)) == FAIL)
3169 inst.error = BAD_ARGS;
3170
3171 else if (rd == REG_PC || rm == REG_PC || rs == REG_PC)
3172 inst.error = BAD_PC;
3173
b99bd4ef
NC
3174 else
3175 end_of_line (str);
3176}
3177
3178/* ARM V5E (El Segundo) saturating-add/subtract (argument parse)
3179 Q[D]{ADD,SUB}{cond} Rd,Rm,Rn
3180 Error if any register is R15. */
3181
3182static void
a737bd4d 3183do_qadd (char * str)
b99bd4ef
NC
3184{
3185 int rd, rm, rn;
3186
3187 skip_whitespace (str);
3188
3189 if ((rd = reg_required_here (& str, 12)) == FAIL
3190 || skip_past_comma (& str) == FAIL
3191 || (rm = reg_required_here (& str, 0)) == FAIL
3192 || skip_past_comma (& str) == FAIL
3193 || (rn = reg_required_here (& str, 16)) == FAIL)
3194 inst.error = BAD_ARGS;
3195
3196 else if (rd == REG_PC || rm == REG_PC || rn == REG_PC)
3197 inst.error = BAD_PC;
3198
b99bd4ef
NC
3199 else
3200 end_of_line (str);
3201}
3202
3203/* ARM V5E (el Segundo)
3204 MCRRcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
3205 MRRCcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
3206
3207 These are equivalent to the XScale instructions MAR and MRA,
3208 respectively, when coproc == 0, opcode == 0, and CRm == 0.
3209
3210 Result unpredicatable if Rd or Rn is R15. */
3211
3212static void
a737bd4d 3213do_co_reg2c (char * str)
b99bd4ef
NC
3214{
3215 int rd, rn;
3216
3217 skip_whitespace (str);
3218
3219 if (co_proc_number (& str) == FAIL)
3220 {
3221 if (!inst.error)
3222 inst.error = BAD_ARGS;
3223 return;
3224 }
3225
3226 if (skip_past_comma (& str) == FAIL
3227 || cp_opc_expr (& str, 4, 4) == FAIL)
3228 {
3229 if (!inst.error)
3230 inst.error = BAD_ARGS;
3231 return;
3232 }
3233
3234 if (skip_past_comma (& str) == FAIL
3235 || (rd = reg_required_here (& str, 12)) == FAIL)
3236 {
3237 if (!inst.error)
3238 inst.error = BAD_ARGS;
3239 return;
3240 }
3241
3242 if (skip_past_comma (& str) == FAIL
3243 || (rn = reg_required_here (& str, 16)) == FAIL)
3244 {
3245 if (!inst.error)
3246 inst.error = BAD_ARGS;
3247 return;
3248 }
3249
09d92015
MM
3250 /* Unpredictable result if rd or rn is R15. */
3251 if (rd == REG_PC || rn == REG_PC)
3252 as_tsktsk
3253 (_("Warning: instruction unpredictable when using r15"));
3254
3255 if (skip_past_comma (& str) == FAIL
3256 || cp_reg_required_here (& str, 0) == FAIL)
3257 {
3258 if (!inst.error)
3259 inst.error = BAD_ARGS;
3260 return;
3261 }
3262
3263 end_of_line (str);
3264}
3265
3266/* ARM V5 count-leading-zeroes instruction (argument parse)
3267 CLZ{<cond>} <Rd>, <Rm>
3268 Condition defaults to COND_ALWAYS.
3269 Error if Rd or Rm are R15. */
3270
3271static void
a737bd4d 3272do_clz (char * str)
09d92015
MM
3273{
3274 int rd, rm;
3275
3276 skip_whitespace (str);
3277
3278 if (((rd = reg_required_here (& str, 12)) == FAIL)
3279 || (skip_past_comma (& str) == FAIL)
3280 || ((rm = reg_required_here (& str, 0)) == FAIL))
3281 inst.error = BAD_ARGS;
3282
3283 else if (rd == REG_PC || rm == REG_PC )
3284 inst.error = BAD_PC;
3285
3286 else
3287 end_of_line (str);
3288}
3289
3290/* ARM V5 (argument parse)
3291 LDC2{L} <coproc>, <CRd>, <addressing mode>
3292 STC2{L} <coproc>, <CRd>, <addressing mode>
3293 Instruction is not conditional, and has 0xf in the condition field.
3294 Otherwise, it's the same as LDC/STC. */
3295
3296static void
a737bd4d 3297do_lstc2 (char * str)
09d92015
MM
3298{
3299 skip_whitespace (str);
3300
3301 if (co_proc_number (& str) == FAIL)
3302 {
3303 if (!inst.error)
3304 inst.error = BAD_ARGS;
3305 }
3306 else if (skip_past_comma (& str) == FAIL
3307 || cp_reg_required_here (& str, 12) == FAIL)
3308 {
3309 if (!inst.error)
3310 inst.error = BAD_ARGS;
3311 }
3312 else if (skip_past_comma (& str) == FAIL
3313 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
3314 {
3315 if (! inst.error)
3316 inst.error = BAD_ARGS;
3317 }
3318 else
3319 end_of_line (str);
3320}
3321
3322/* ARM V5 (argument parse)
3323 CDP2 <coproc>, <opcode_1>, <CRd>, <CRn>, <CRm>, <opcode_2>
3324 Instruction is not conditional, and has 0xf in the condition field.
3325 Otherwise, it's the same as CDP. */
3326
3327static void
a737bd4d 3328do_cdp2 (char * str)
09d92015
MM
3329{
3330 skip_whitespace (str);
3331
3332 if (co_proc_number (& str) == FAIL)
3333 {
3334 if (!inst.error)
3335 inst.error = BAD_ARGS;
3336 return;
3337 }
3338
3339 if (skip_past_comma (& str) == FAIL
3340 || cp_opc_expr (& str, 20,4) == FAIL)
3341 {
3342 if (!inst.error)
3343 inst.error = BAD_ARGS;
3344 return;
3345 }
3346
3347 if (skip_past_comma (& str) == FAIL
3348 || cp_reg_required_here (& str, 12) == FAIL)
3349 {
3350 if (!inst.error)
3351 inst.error = BAD_ARGS;
3352 return;
3353 }
3354
3355 if (skip_past_comma (& str) == FAIL
3356 || cp_reg_required_here (& str, 16) == FAIL)
3357 {
3358 if (!inst.error)
3359 inst.error = BAD_ARGS;
3360 return;
3361 }
3362
3363 if (skip_past_comma (& str) == FAIL
3364 || cp_reg_required_here (& str, 0) == FAIL)
3365 {
3366 if (!inst.error)
3367 inst.error = BAD_ARGS;
3368 return;
3369 }
3370
3371 if (skip_past_comma (& str) == SUCCESS)
3372 {
3373 if (cp_opc_expr (& str, 5, 3) == FAIL)
3374 {
3375 if (!inst.error)
3376 inst.error = BAD_ARGS;
3377 return;
3378 }
3379 }
3380
3381 end_of_line (str);
3382}
3383
3384/* ARM V5 (argument parse)
3385 MCR2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
3386 MRC2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
3387 Instruction is not conditional, and has 0xf in the condition field.
3388 Otherwise, it's the same as MCR/MRC. */
3389
3390static void
a737bd4d 3391do_co_reg2 (char * str)
09d92015
MM
3392{
3393 skip_whitespace (str);
3394
3395 if (co_proc_number (& str) == FAIL)
3396 {
3397 if (!inst.error)
3398 inst.error = BAD_ARGS;
3399 return;
3400 }
3401
3402 if (skip_past_comma (& str) == FAIL
3403 || cp_opc_expr (& str, 21, 3) == FAIL)
3404 {
3405 if (!inst.error)
3406 inst.error = BAD_ARGS;
3407 return;
3408 }
3409
3410 if (skip_past_comma (& str) == FAIL
3411 || reg_required_here (& str, 12) == FAIL)
3412 {
3413 if (!inst.error)
3414 inst.error = BAD_ARGS;
3415 return;
3416 }
3417
3418 if (skip_past_comma (& str) == FAIL
3419 || cp_reg_required_here (& str, 16) == FAIL)
3420 {
3421 if (!inst.error)
3422 inst.error = BAD_ARGS;
3423 return;
3424 }
3425
3426 if (skip_past_comma (& str) == FAIL
3427 || cp_reg_required_here (& str, 0) == FAIL)
3428 {
3429 if (!inst.error)
3430 inst.error = BAD_ARGS;
3431 return;
3432 }
3433
3434 if (skip_past_comma (& str) == SUCCESS)
3435 {
3436 if (cp_opc_expr (& str, 5, 3) == FAIL)
3437 {
3438 if (!inst.error)
3439 inst.error = BAD_ARGS;
3440 return;
3441 }
3442 }
3443
3444 end_of_line (str);
3445}
3446
a737bd4d
NC
3447static void
3448do_bx (char * str)
3449{
3450 int reg;
3451
3452 skip_whitespace (str);
3453
3454 if ((reg = reg_required_here (&str, 0)) == FAIL)
3455 {
3456 inst.error = BAD_ARGS;
3457 return;
3458 }
3459
3460 /* Note - it is not illegal to do a "bx pc". Useless, but not illegal. */
3461 if (reg == REG_PC)
3462 as_tsktsk (_("use of r15 in bx in ARM mode is not really useful"));
3463
3464 end_of_line (str);
3465}
3466
09d92015 3467/* ARM v5TEJ. Jump to Jazelle code. */
a737bd4d 3468
09d92015 3469static void
a737bd4d 3470do_bxj (char * str)
09d92015
MM
3471{
3472 int reg;
3473
3474 skip_whitespace (str);
3475
3476 if ((reg = reg_required_here (&str, 0)) == FAIL)
3477 {
3478 inst.error = BAD_ARGS;
3479 return;
3480 }
3481
a737bd4d
NC
3482 /* Note - it is not illegal to do a "bxj pc". Useless, but not illegal. */
3483 if (reg == REG_PC)
3484 as_tsktsk (_("use of r15 in bxj is not really useful"));
3485
3486 end_of_line (str);
3487}
3488
3489/* ARM V6 umaal (argument parse). */
3490
3491static void
3492do_umaal (char * str)
3493{
3494 int rdlo, rdhi, rm, rs;
3495
3496 skip_whitespace (str);
3497 if ((rdlo = reg_required_here (& str, 12)) == FAIL
3498 || skip_past_comma (& str) == FAIL
3499 || (rdhi = reg_required_here (& str, 16)) == FAIL
3500 || skip_past_comma (& str) == FAIL
3501 || (rm = reg_required_here (& str, 0)) == FAIL
3502 || skip_past_comma (& str) == FAIL
3503 || (rs = reg_required_here (& str, 8)) == FAIL)
3504 {
3505 inst.error = BAD_ARGS;
3506 return;
3507 }
3508
3509 if (rdlo == REG_PC || rdhi == REG_PC || rm == REG_PC || rs == REG_PC)
3510 {
3511 inst.error = BAD_PC;
3512 return;
3513 }
3514
3515 end_of_line (str);
3516}
3517
3518/* ARM V6 strex (argument parse). */
3519
3520static void
3521do_strex (char * str)
3522{
3523 int rd, rm, rn;
3524
3525 /* Parse Rd, Rm,. */
3526 skip_whitespace (str);
3527 if ((rd = reg_required_here (& str, 12)) == FAIL
3528 || skip_past_comma (& str) == FAIL
3529 || (rm = reg_required_here (& str, 0)) == FAIL
3530 || skip_past_comma (& str) == FAIL)
3531 {
3532 inst.error = BAD_ARGS;
3533 return;
3534 }
3535 if (rd == REG_PC || rm == REG_PC)
3536 {
3537 inst.error = BAD_PC;
3538 return;
3539 }
3540 if (rd == rm)
3541 {
3542 inst.error = _("Rd equal to Rm or Rn yields unpredictable results");
3543 return;
3544 }
3545
3546 /* Skip past '['. */
3547 if ((strlen (str) >= 1)
3548 && strncmp (str, "[", 1) == 0)
3549 str += 1;
3550
3551 skip_whitespace (str);
3552
3553 /* Parse Rn. */
3554 if ((rn = reg_required_here (& str, 16)) == FAIL)
3555 {
3556 inst.error = BAD_ARGS;
3557 return;
3558 }
3559 else if (rn == REG_PC)
3560 {
3561 inst.error = BAD_PC;
3562 return;
3563 }
3564 if (rd == rn)
3565 {
3566 inst.error = _("Rd equal to Rm or Rn yields unpredictable results");
3567 return;
3568 }
3569 skip_whitespace (str);
3570
3571 /* Skip past ']'. */
3572 if ((strlen (str) >= 1)
3573 && strncmp (str, "]", 1) == 0)
3574 str += 1;
3575
3576 end_of_line (str);
3577}
3578
3579/* KIND indicates what kind of shifts are accepted. */
3580
3581static int
3582decode_shift (char ** str, int kind)
3583{
3584 const struct asm_shift_name * shift;
3585 char * p;
3586 char c;
3587
3588 skip_whitespace (* str);
3589
3590 for (p = * str; ISALPHA (* p); p ++)
3591 ;
3592
3593 if (p == * str)
3594 {
3595 inst.error = _("shift expression expected");
3596 return FAIL;
3597 }
3598
3599 c = * p;
3600 * p = '\0';
3601 shift = (const struct asm_shift_name *) hash_find (arm_shift_hsh, * str);
3602 * p = c;
3603
3604 if (shift == NULL)
3605 {
3606 inst.error = _("shift expression expected");
3607 return FAIL;
3608 }
3609
3610 assert (shift->properties->index == shift_properties[shift->properties->index].index);
3611
3612 if (kind == SHIFT_LSL_OR_ASR_IMMEDIATE
3613 && shift->properties->index != SHIFT_LSL
3614 && shift->properties->index != SHIFT_ASR)
3615 {
3616 inst.error = _("'LSL' or 'ASR' required");
3617 return FAIL;
3618 }
3619 else if (kind == SHIFT_LSL_IMMEDIATE
3620 && shift->properties->index != SHIFT_LSL)
3621 {
3622 inst.error = _("'LSL' required");
3623 return FAIL;
3624 }
3625 else if (kind == SHIFT_ASR_IMMEDIATE
3626 && shift->properties->index != SHIFT_ASR)
3627 {
3628 inst.error = _("'ASR' required");
3629 return FAIL;
3630 }
3631
3632 if (shift->properties->index == SHIFT_RRX)
3633 {
3634 * str = p;
3635 inst.instruction |= shift->properties->bit_field;
3636 return SUCCESS;
3637 }
3638
3639 skip_whitespace (p);
3640
3641 if (kind == NO_SHIFT_RESTRICT && reg_required_here (& p, 8) != FAIL)
3642 {
3643 inst.instruction |= shift->properties->bit_field | SHIFT_BY_REG;
3644 * str = p;
3645 return SUCCESS;
3646 }
3647 else if (! is_immediate_prefix (* p))
3648 {
3649 inst.error = (NO_SHIFT_RESTRICT
3650 ? _("shift requires register or #expression")
3651 : _("shift requires #expression"));
3652 * str = p;
3653 return FAIL;
3654 }
3655
3656 inst.error = NULL;
3657 p ++;
3658
3659 if (my_get_expression (& inst.reloc.exp, & p))
3660 return FAIL;
3661
3662 /* Validate some simple #expressions. */
3663 if (inst.reloc.exp.X_op == O_constant)
3664 {
3665 unsigned num = inst.reloc.exp.X_add_number;
3666
3667 /* Reject operations greater than 32. */
3668 if (num > 32
3669 /* Reject a shift of 0 unless the mode allows it. */
3670 || (num == 0 && shift->properties->allows_0 == 0)
3671 /* Reject a shift of 32 unless the mode allows it. */
3672 || (num == 32 && shift->properties->allows_32 == 0)
3673 )
3674 {
3675 /* As a special case we allow a shift of zero for
3676 modes that do not support it to be recoded as an
3677 logical shift left of zero (ie nothing). We warn
3678 about this though. */
3679 if (num == 0)
3680 {
3681 as_warn (_("shift of 0 ignored."));
3682 shift = & shift_names[0];
3683 assert (shift->properties->index == SHIFT_LSL);
3684 }
3685 else
3686 {
3687 inst.error = _("invalid immediate shift");
3688 return FAIL;
3689 }
3690 }
3691
3692 /* Shifts of 32 are encoded as 0, for those shifts that
3693 support it. */
3694 if (num == 32)
3695 num = 0;
3696
3697 inst.instruction |= (num << 7) | shift->properties->bit_field;
3698 }
3699 else
3700 {
3701 inst.reloc.type = BFD_RELOC_ARM_SHIFT_IMM;
3702 inst.reloc.pc_rel = 0;
3703 inst.instruction |= shift->properties->bit_field;
3704 }
3705
3706 * str = p;
3707 return SUCCESS;
09d92015
MM
3708}
3709
09d92015 3710static void
a737bd4d 3711do_sat (char ** str, int bias)
09d92015 3712{
a737bd4d
NC
3713 int rd, rm;
3714 expressionS expr;
09d92015 3715
a737bd4d 3716 skip_whitespace (*str);
09d92015 3717
a737bd4d
NC
3718 /* Parse <Rd>, field. */
3719 if ((rd = reg_required_here (str, 12)) == FAIL
3720 || skip_past_comma (str) == FAIL)
09d92015
MM
3721 {
3722 inst.error = BAD_ARGS;
a737bd4d 3723 return;
09d92015 3724 }
a737bd4d 3725 if (rd == REG_PC)
09d92015
MM
3726 {
3727 inst.error = BAD_PC;
3728 return;
3729 }
3730
a737bd4d
NC
3731 /* Parse #<immed>, field. */
3732 if (is_immediate_prefix (**str))
3733 (*str)++;
3734 else
09d92015 3735 {
a737bd4d 3736 inst.error = _("immediate expression expected");
09d92015
MM
3737 return;
3738 }
a737bd4d 3739 if (my_get_expression (&expr, str))
09d92015 3740 {
a737bd4d 3741 inst.error = _("bad expression");
09d92015
MM
3742 return;
3743 }
a737bd4d 3744 if (expr.X_op != O_constant)
09d92015 3745 {
a737bd4d 3746 inst.error = _("constant expression expected");
09d92015
MM
3747 return;
3748 }
a737bd4d
NC
3749 if (expr.X_add_number + bias < 0
3750 || expr.X_add_number + bias > 31)
3751 {
3752 inst.error = _("immediate value out of range");
3753 return;
3754 }
3755 inst.instruction |= (expr.X_add_number + bias) << 16;
3756 if (skip_past_comma (str) == FAIL)
09d92015
MM
3757 {
3758 inst.error = BAD_ARGS;
3759 return;
3760 }
a737bd4d
NC
3761
3762 /* Parse <Rm> field. */
3763 if ((rm = reg_required_here (str, 0)) == FAIL)
09d92015 3764 {
a737bd4d 3765 inst.error = BAD_ARGS;
09d92015
MM
3766 return;
3767 }
a737bd4d 3768 if (rm == REG_PC)
09d92015 3769 {
a737bd4d 3770 inst.error = BAD_PC;
09d92015
MM
3771 return;
3772 }
09d92015 3773
a737bd4d
NC
3774 if (skip_past_comma (str) == SUCCESS)
3775 decode_shift (str, SHIFT_LSL_OR_ASR_IMMEDIATE);
09d92015
MM
3776}
3777
a737bd4d 3778/* ARM V6 ssat (argument parse). */
09d92015
MM
3779
3780static void
a737bd4d 3781do_ssat (char * str)
09d92015
MM
3782{
3783 do_sat (&str, /*bias=*/-1);
3784 end_of_line (str);
3785}
3786
a737bd4d 3787/* ARM V6 usat (argument parse). */
09d92015
MM
3788
3789static void
a737bd4d 3790do_usat (char * str)
09d92015
MM
3791{
3792 do_sat (&str, /*bias=*/0);
3793 end_of_line (str);
3794}
3795
3796static void
a737bd4d 3797do_sat16 (char ** str, int bias)
09d92015
MM
3798{
3799 int rd, rm;
3800 expressionS expr;
3801
3802 skip_whitespace (*str);
a737bd4d
NC
3803
3804 /* Parse the <Rd> field. */
09d92015
MM
3805 if ((rd = reg_required_here (str, 12)) == FAIL
3806 || skip_past_comma (str) == FAIL)
3807 {
3808 inst.error = BAD_ARGS;
3809 return;
3810 }
3811 if (rd == REG_PC)
3812 {
3813 inst.error = BAD_PC;
3814 return;
3815 }
3816
a737bd4d 3817 /* Parse #<immed>, field. */
09d92015
MM
3818 if (is_immediate_prefix (**str))
3819 (*str)++;
3820 else
3821 {
3822 inst.error = _("immediate expression expected");
3823 return;
3824 }
3825 if (my_get_expression (&expr, str))
3826 {
3827 inst.error = _("bad expression");
3828 return;
3829 }
3830 if (expr.X_op != O_constant)
3831 {
3832 inst.error = _("constant expression expected");
3833 return;
3834 }
3835 if (expr.X_add_number + bias < 0
a737bd4d 3836 || expr.X_add_number + bias > 15)
09d92015
MM
3837 {
3838 inst.error = _("immediate value out of range");
3839 return;
3840 }
3841 inst.instruction |= (expr.X_add_number + bias) << 16;
3842 if (skip_past_comma (str) == FAIL)
3843 {
3844 inst.error = BAD_ARGS;
3845 return;
3846 }
3847
a737bd4d 3848 /* Parse <Rm> field. */
09d92015
MM
3849 if ((rm = reg_required_here (str, 0)) == FAIL)
3850 {
3851 inst.error = BAD_ARGS;
3852 return;
3853 }
3854 if (rm == REG_PC)
3855 {
3856 inst.error = BAD_PC;
3857 return;
3858 }
09d92015
MM
3859}
3860
a737bd4d 3861/* ARM V6 ssat16 (argument parse). */
09d92015
MM
3862
3863static void
a737bd4d 3864do_ssat16 (char * str)
09d92015
MM
3865{
3866 do_sat16 (&str, /*bias=*/-1);
3867 end_of_line (str);
3868}
3869
3870static void
a737bd4d 3871do_usat16 (char * str)
09d92015
MM
3872{
3873 do_sat16 (&str, /*bias=*/0);
3874 end_of_line (str);
3875}
3876
3877static void
a737bd4d 3878do_cps_mode (char ** str)
09d92015 3879{
09d92015
MM
3880 expressionS expr;
3881
3882 skip_whitespace (*str);
3883
a737bd4d 3884 if (! is_immediate_prefix (**str))
09d92015
MM
3885 {
3886 inst.error = _("immediate expression expected");
3887 return;
3888 }
a737bd4d
NC
3889
3890 (*str)++; /* Strip off the immediate signifier. */
09d92015
MM
3891 if (my_get_expression (&expr, str))
3892 {
3893 inst.error = _("bad expression");
3894 return;
3895 }
a737bd4d 3896
09d92015
MM
3897 if (expr.X_op != O_constant)
3898 {
3899 inst.error = _("constant expression expected");
3900 return;
3901 }
09d92015 3902
a737bd4d
NC
3903 /* The mode is a 5 bit field. Valid values are 0-31. */
3904 if (((unsigned) expr.X_add_number) > 31
3905 || (inst.reloc.exp.X_add_number) < 0)
09d92015 3906 {
a737bd4d 3907 inst.error = _("invalid constant");
09d92015
MM
3908 return;
3909 }
a737bd4d
NC
3910
3911 inst.instruction |= expr.X_add_number;
09d92015
MM
3912}
3913
a737bd4d 3914/* ARM V6 srs (argument parse). */
09d92015
MM
3915
3916static void
a737bd4d 3917do_srs (char * str)
09d92015
MM
3918{
3919 char *exclam;
3920 skip_whitespace (str);
3921 exclam = strchr (str, '!');
3922 if (exclam)
3923 *exclam = '\0';
3924 do_cps_mode (&str);
3925 if (exclam)
3926 *exclam = '!';
a737bd4d 3927 if (*str == '!')
09d92015
MM
3928 {
3929 inst.instruction |= WRITE_BACK;
3930 str++;
3931 }
3932 end_of_line (str);
3933}
3934
a737bd4d 3935/* ARM V6 SMMUL (argument parse). */
09d92015
MM
3936
3937static void
a737bd4d 3938do_smmul (char * str)
09d92015
MM
3939{
3940 int rd, rm, rs;
a737bd4d 3941
09d92015
MM
3942 skip_whitespace (str);
3943 if ((rd = reg_required_here (&str, 16)) == FAIL
3944 || skip_past_comma (&str) == FAIL
3945 || (rm = reg_required_here (&str, 0)) == FAIL
3946 || skip_past_comma (&str) == FAIL
3947 || (rs = reg_required_here (&str, 8)) == FAIL)
3948 {
3949 inst.error = BAD_ARGS;
3950 return;
3951 }
3952
a737bd4d 3953 if ( rd == REG_PC
09d92015
MM
3954 || rm == REG_PC
3955 || rs == REG_PC)
3956 {
3957 inst.error = BAD_PC;
3958 return;
3959 }
3960
3961 end_of_line (str);
09d92015
MM
3962}
3963
a737bd4d 3964/* ARM V6 SMLALD (argument parse). */
09d92015
MM
3965
3966static void
a737bd4d 3967do_smlald (char * str)
09d92015
MM
3968{
3969 int rdlo, rdhi, rm, rs;
a737bd4d 3970
09d92015
MM
3971 skip_whitespace (str);
3972 if ((rdlo = reg_required_here (&str, 12)) == FAIL
3973 || skip_past_comma (&str) == FAIL
3974 || (rdhi = reg_required_here (&str, 16)) == FAIL
3975 || skip_past_comma (&str) == FAIL
3976 || (rm = reg_required_here (&str, 0)) == FAIL
3977 || skip_past_comma (&str) == FAIL
3978 || (rs = reg_required_here (&str, 8)) == FAIL)
3979 {
3980 inst.error = BAD_ARGS;
3981 return;
3982 }
3983
a737bd4d
NC
3984 if ( rdlo == REG_PC
3985 || rdhi == REG_PC
09d92015
MM
3986 || rm == REG_PC
3987 || rs == REG_PC)
3988 {
3989 inst.error = BAD_PC;
3990 return;
3991 }
3992
3993 end_of_line (str);
3994}
3995
a737bd4d 3996/* ARM V6 SMLAD (argument parse). Signed multiply accumulate dual.
09d92015
MM
3997 smlad{x}{<cond>} Rd, Rm, Rs, Rn */
3998
a737bd4d
NC
3999static void
4000do_smlad (char * str)
09d92015
MM
4001{
4002 int rd, rm, rs, rn;
a737bd4d 4003
09d92015
MM
4004 skip_whitespace (str);
4005 if ((rd = reg_required_here (&str, 16)) == FAIL
4006 || skip_past_comma (&str) == FAIL
4007 || (rm = reg_required_here (&str, 0)) == FAIL
4008 || skip_past_comma (&str) == FAIL
4009 || (rs = reg_required_here (&str, 8)) == FAIL
4010 || skip_past_comma (&str) == FAIL
4011 || (rn = reg_required_here (&str, 12)) == FAIL)
4012 {
4013 inst.error = BAD_ARGS;
4014 return;
4015 }
a737bd4d
NC
4016
4017 if ( rd == REG_PC
4018 || rn == REG_PC
09d92015
MM
4019 || rs == REG_PC
4020 || rm == REG_PC)
4021 {
4022 inst.error = BAD_PC;
4023 return;
4024 }
4025
4026 end_of_line (str);
09d92015
MM
4027}
4028
4029/* Returns true if the endian-specifier indicates big-endianness. */
4030
4031static int
a737bd4d 4032do_endian_specifier (char * str)
09d92015
MM
4033{
4034 int big_endian = 0;
4035
4036 skip_whitespace (str);
4037 if (strlen (str) < 2)
4038 inst.error = _("missing endian specifier");
4039 else if (strncasecmp (str, "BE", 2) == 0)
4040 {
4041 str += 2;
4042 big_endian = 1;
4043 }
4044 else if (strncasecmp (str, "LE", 2) == 0)
4045 str += 2;
4046 else
4047 inst.error = _("valid endian specifiers are be or le");
4048
4049 end_of_line (str);
4050
4051 return big_endian;
4052}
4053
a737bd4d
NC
4054/* ARM V6 SETEND (argument parse). Sets the E bit in the CPSR while
4055 preserving the other bits.
4056
4057 setend <endian_specifier>, where <endian_specifier> is either
4058 BE or LE. */
4059
4060static void
4061do_setend (char * str)
4062{
4063 if (do_endian_specifier (str))
4064 inst.instruction |= 0x200;
4065}
4066
09d92015
MM
4067/* ARM V6 SXTH.
4068
4069 SXTH {<cond>} <Rd>, <Rm>{, <rotation>}
4070 Condition defaults to COND_ALWAYS.
a737bd4d 4071 Error if any register uses R15. */
09d92015 4072
a737bd4d
NC
4073static void
4074do_sxth (char * str)
09d92015
MM
4075{
4076 int rd, rm;
4077 expressionS expr;
4078 int rotation_clear_mask = 0xfffff3ff;
4079 int rotation_eight_mask = 0x00000400;
4080 int rotation_sixteen_mask = 0x00000800;
4081 int rotation_twenty_four_mask = 0x00000c00;
a737bd4d 4082
09d92015
MM
4083 skip_whitespace (str);
4084 if ((rd = reg_required_here (&str, 12)) == FAIL
4085 || skip_past_comma (&str) == FAIL
4086 || (rm = reg_required_here (&str, 0)) == FAIL)
4087 {
4088 inst.error = BAD_ARGS;
4089 return;
4090 }
4091
4092 else if (rd == REG_PC || rm == REG_PC)
4093 {
4094 inst.error = BAD_PC;
4095 return;
4096 }
a737bd4d
NC
4097
4098 /* Zero out the rotation field. */
09d92015 4099 inst.instruction &= rotation_clear_mask;
a737bd4d
NC
4100
4101 /* Check for lack of optional rotation field. */
09d92015
MM
4102 if (skip_past_comma (&str) == FAIL)
4103 {
4104 end_of_line (str);
4105 return;
4106 }
a737bd4d
NC
4107
4108 /* Move past 'ROR'. */
09d92015
MM
4109 skip_whitespace (str);
4110 if (strncasecmp (str, "ROR", 3) == 0)
a737bd4d 4111 str += 3;
09d92015
MM
4112 else
4113 {
4114 inst.error = _("missing rotation field after comma");
4115 return;
4116 }
a737bd4d
NC
4117
4118 /* Get the immediate constant. */
09d92015
MM
4119 skip_whitespace (str);
4120 if (is_immediate_prefix (* str))
4121 str++;
4122 else
4123 {
4124 inst.error = _("immediate expression expected");
4125 return;
4126 }
a737bd4d 4127
09d92015
MM
4128 if (my_get_expression (&expr, &str))
4129 {
4130 inst.error = _("bad expression");
4131 return;
4132 }
4133
4134 if (expr.X_op != O_constant)
4135 {
4136 inst.error = _("constant expression expected");
4137 return;
4138 }
a737bd4d
NC
4139
4140 switch (expr.X_add_number)
09d92015
MM
4141 {
4142 case 0:
a737bd4d 4143 /* Rotation field has already been zeroed. */
09d92015
MM
4144 break;
4145 case 8:
4146 inst.instruction |= rotation_eight_mask;
4147 break;
4148
4149 case 16:
4150 inst.instruction |= rotation_sixteen_mask;
4151 break;
a737bd4d 4152
09d92015
MM
4153 case 24:
4154 inst.instruction |= rotation_twenty_four_mask;
4155 break;
4156
4157 default:
4158 inst.error = _("rotation can be 8, 16, 24 or 0 when field is ommited");
4159 break;
4160 }
4161
4162 end_of_line (str);
09d92015
MM
4163}
4164
4165/* ARM V6 SXTAH extracts a 16-bit value from a register, sign
4166 extends it to 32-bits, and adds the result to a value in another
4167 register. You can specify a rotation by 0, 8, 16, or 24 bits
4168 before extracting the 16-bit value.
4169 SXTAH{<cond>} <Rd>, <Rn>, <Rm>{, <rotation>}
4170 Condition defaults to COND_ALWAYS.
a737bd4d 4171 Error if any register uses R15. */
09d92015 4172
a737bd4d
NC
4173static void
4174do_sxtah (char * str)
09d92015
MM
4175{
4176 int rd, rn, rm;
4177 expressionS expr;
4178 int rotation_clear_mask = 0xfffff3ff;
4179 int rotation_eight_mask = 0x00000400;
4180 int rotation_sixteen_mask = 0x00000800;
4181 int rotation_twenty_four_mask = 0x00000c00;
a737bd4d 4182
09d92015
MM
4183 skip_whitespace (str);
4184 if ((rd = reg_required_here (&str, 12)) == FAIL
4185 || skip_past_comma (&str) == FAIL
4186 || (rn = reg_required_here (&str, 16)) == FAIL
4187 || skip_past_comma (&str) == FAIL
4188 || (rm = reg_required_here (&str, 0)) == FAIL)
4189 {
4190 inst.error = BAD_ARGS;
4191 return;
4192 }
4193
4194 else if (rd == REG_PC || rn == REG_PC || rm == REG_PC)
4195 {
4196 inst.error = BAD_PC;
4197 return;
4198 }
a737bd4d
NC
4199
4200 /* Zero out the rotation field. */
09d92015 4201 inst.instruction &= rotation_clear_mask;
a737bd4d
NC
4202
4203 /* Check for lack of optional rotation field. */
09d92015
MM
4204 if (skip_past_comma (&str) == FAIL)
4205 {
4206 end_of_line (str);
4207 return;
4208 }
a737bd4d
NC
4209
4210 /* Move past 'ROR'. */
09d92015
MM
4211 skip_whitespace (str);
4212 if (strncasecmp (str, "ROR", 3) == 0)
a737bd4d 4213 str += 3;
09d92015
MM
4214 else
4215 {
4216 inst.error = _("missing rotation field after comma");
4217 return;
4218 }
a737bd4d
NC
4219
4220 /* Get the immediate constant. */
09d92015
MM
4221 skip_whitespace (str);
4222 if (is_immediate_prefix (* str))
4223 str++;
4224 else
4225 {
4226 inst.error = _("immediate expression expected");
4227 return;
4228 }
a737bd4d 4229
09d92015
MM
4230 if (my_get_expression (&expr, &str))
4231 {
4232 inst.error = _("bad expression");
4233 return;
4234 }
4235
4236 if (expr.X_op != O_constant)
4237 {
4238 inst.error = _("constant expression expected");
4239 return;
4240 }
a737bd4d
NC
4241
4242 switch (expr.X_add_number)
09d92015
MM
4243 {
4244 case 0:
a737bd4d 4245 /* Rotation field has already been zeroed. */
09d92015
MM
4246 break;
4247
4248 case 8:
4249 inst.instruction |= rotation_eight_mask;
4250 break;
4251
4252 case 16:
4253 inst.instruction |= rotation_sixteen_mask;
4254 break;
a737bd4d 4255
09d92015
MM
4256 case 24:
4257 inst.instruction |= rotation_twenty_four_mask;
4258 break;
4259
4260 default:
4261 inst.error = _("rotation can be 8, 16, 24 or 0 when field is ommited");
4262 break;
4263 }
4264
4265 end_of_line (str);
09d92015 4266}
a737bd4d 4267
09d92015
MM
4268
4269/* ARM V6 RFE (Return from Exception) loads the PC and CPSR from the
4270 word at the specified address and the following word
a737bd4d 4271 respectively.
09d92015 4272 Unconditionally executed.
a737bd4d 4273 Error if Rn is R15. */
09d92015
MM
4274
4275static void
a737bd4d 4276do_rfe (char * str)
09d92015
MM
4277{
4278 int rn;
4279
4280 skip_whitespace (str);
a737bd4d 4281
09d92015
MM
4282 if ((rn = reg_required_here (&str, 16)) == FAIL)
4283 return;
b99bd4ef 4284
09d92015 4285 if (rn == REG_PC)
b99bd4ef 4286 {
09d92015 4287 inst.error = BAD_PC;
b99bd4ef
NC
4288 return;
4289 }
4290
09d92015 4291 skip_whitespace (str);
a737bd4d 4292
09d92015
MM
4293 if (*str == '!')
4294 {
4295 inst.instruction |= WRITE_BACK;
4296 str++;
4297 }
b99bd4ef
NC
4298 end_of_line (str);
4299}
4300
09d92015
MM
4301/* ARM V6 REV (Byte Reverse Word) reverses the byte order in a 32-bit
4302 register (argument parse).
4303 REV{<cond>} Rd, Rm.
4304 Condition defaults to COND_ALWAYS.
a737bd4d 4305 Error if Rd or Rm are R15. */
b99bd4ef
NC
4306
4307static void
a737bd4d 4308do_rev (char * str)
b99bd4ef
NC
4309{
4310 int rd, rm;
4311
b99bd4ef
NC
4312 skip_whitespace (str);
4313
09d92015
MM
4314 if ((rd = reg_required_here (&str, 12)) == FAIL
4315 || skip_past_comma (&str) == FAIL
4316 || (rm = reg_required_here (&str, 0)) == FAIL)
b99bd4ef
NC
4317 inst.error = BAD_ARGS;
4318
09d92015 4319 else if (rd == REG_PC || rm == REG_PC)
b99bd4ef
NC
4320 inst.error = BAD_PC;
4321
4322 else
4323 end_of_line (str);
4324}
4325
09d92015 4326/* ARM V6 Perform Two Sixteen Bit Integer Additions. (argument parse).
a737bd4d 4327 QADD16{<cond>} <Rd>, <Rn>, <Rm>
09d92015
MM
4328 Condition defaults to COND_ALWAYS.
4329 Error if Rd, Rn or Rm are R15. */
b99bd4ef
NC
4330
4331static void
a737bd4d 4332do_qadd16 (char * str)
b99bd4ef 4333{
09d92015
MM
4334 int rd, rm, rn;
4335
b99bd4ef
NC
4336 skip_whitespace (str);
4337
09d92015
MM
4338 if ((rd = reg_required_here (&str, 12)) == FAIL
4339 || skip_past_comma (&str) == FAIL
4340 || (rn = reg_required_here (&str, 16)) == FAIL
4341 || skip_past_comma (&str) == FAIL
4342 || (rm = reg_required_here (&str, 0)) == FAIL)
4343 inst.error = BAD_ARGS;
4344
4345 else if (rd == REG_PC || rm == REG_PC || rn == REG_PC)
4346 inst.error = BAD_PC;
4347
b99bd4ef
NC
4348 else
4349 end_of_line (str);
4350}
4351
b99bd4ef 4352static void
a737bd4d 4353do_pkh_core (char * str, int shift)
b99bd4ef 4354{
09d92015 4355 int rd, rn, rm;
b99bd4ef 4356
09d92015
MM
4357 skip_whitespace (str);
4358 if (((rd = reg_required_here (&str, 12)) == FAIL)
4359 || (skip_past_comma (&str) == FAIL)
4360 || ((rn = reg_required_here (&str, 16)) == FAIL)
4361 || (skip_past_comma (&str) == FAIL)
4362 || ((rm = reg_required_here (&str, 0)) == FAIL))
b99bd4ef 4363 {
09d92015 4364 inst.error = BAD_ARGS;
b99bd4ef
NC
4365 return;
4366 }
4367
09d92015 4368 else if (rd == REG_PC || rn == REG_PC || rm == REG_PC)
b99bd4ef 4369 {
09d92015 4370 inst.error = BAD_PC;
b99bd4ef
NC
4371 return;
4372 }
4373
a737bd4d
NC
4374 /* Check for optional shift immediate constant. */
4375 if (skip_past_comma (&str) == FAIL)
b99bd4ef 4376 {
09d92015
MM
4377 if (shift == SHIFT_ASR_IMMEDIATE)
4378 {
4379 /* If the shift specifier is ommited, turn the instruction
4380 into pkhbt rd, rm, rn. First, switch the instruction
4381 code, and clear the rn and rm fields. */
4382 inst.instruction &= 0xfff0f010;
4383 /* Now, re-encode the registers. */
4384 inst.instruction |= (rm << 16) | rn;
4385 }
b99bd4ef
NC
4386 return;
4387 }
4388
09d92015
MM
4389 decode_shift (&str, shift);
4390}
4391
a737bd4d
NC
4392/* ARM V6 Pack Halfword Bottom Top instruction (argument parse).
4393 PKHBT {<cond>} <Rd>, <Rn>, <Rm> {, LSL #<shift_imm>}
4394 Condition defaults to COND_ALWAYS.
4395 Error if Rd, Rn or Rm are R15. */
4396
4397static void
4398do_pkhbt (char * str)
4399{
4400 do_pkh_core (str, SHIFT_LSL_IMMEDIATE);
4401}
4402
4403/* ARM V6 PKHTB (Argument Parse). */
4404
4405static void
4406do_pkhtb (char * str)
4407{
4408 do_pkh_core (str, SHIFT_ASR_IMMEDIATE);
4409}
4410
09d92015 4411/* ARM V6 Load Register Exclusive instruction (argument parse).
0dd132b6 4412 LDREX{,B,D,H}{<cond>} <Rd, [<Rn>]
09d92015 4413 Condition defaults to COND_ALWAYS.
a737bd4d
NC
4414 Error if Rd or Rn are R15.
4415 See ARMARMv6 A4.1.27: LDREX. */
09d92015
MM
4416
4417static void
a737bd4d 4418do_ldrex (char * str)
09d92015
MM
4419{
4420 int rd, rn;
4421
4422 skip_whitespace (str);
4423
a737bd4d 4424 /* Parse Rd. */
09d92015
MM
4425 if (((rd = reg_required_here (&str, 12)) == FAIL)
4426 || (skip_past_comma (&str) == FAIL))
b99bd4ef 4427 {
09d92015 4428 inst.error = BAD_ARGS;
b99bd4ef
NC
4429 return;
4430 }
09d92015 4431 else if (rd == REG_PC)
b99bd4ef 4432 {
09d92015 4433 inst.error = BAD_PC;
b99bd4ef
NC
4434 return;
4435 }
a737bd4d 4436 skip_whitespace (str);
b99bd4ef 4437
a737bd4d
NC
4438 /* Skip past '['. */
4439 if ((strlen (str) >= 1)
09d92015 4440 &&strncmp (str, "[", 1) == 0)
a737bd4d
NC
4441 str += 1;
4442 skip_whitespace (str);
09d92015 4443
a737bd4d 4444 /* Parse Rn. */
09d92015 4445 if ((rn = reg_required_here (&str, 16)) == FAIL)
b99bd4ef 4446 {
09d92015
MM
4447 inst.error = BAD_ARGS;
4448 return;
b99bd4ef 4449 }
09d92015
MM
4450 else if (rn == REG_PC)
4451 {
4452 inst.error = BAD_PC;
4453 return;
4454 }
a737bd4d 4455 skip_whitespace (str);
b99bd4ef 4456
a737bd4d
NC
4457 /* Skip past ']'. */
4458 if ((strlen (str) >= 1)
09d92015 4459 && strncmp (str, "]", 1) == 0)
a737bd4d
NC
4460 str += 1;
4461
b99bd4ef
NC
4462 end_of_line (str);
4463}
4464
09d92015 4465/* ARM V6 change processor state instruction (argument parse)
a737bd4d 4466 CPS, CPSIE, CSPID . */
b99bd4ef
NC
4467
4468static void
a737bd4d 4469do_cps (char * str)
b99bd4ef 4470{
09d92015
MM
4471 do_cps_mode (&str);
4472 end_of_line (str);
4473}
b99bd4ef 4474
09d92015 4475static void
a737bd4d 4476do_cps_flags (char ** str, int thumb_p)
ea6ef066 4477{
a737bd4d
NC
4478 struct cps_flag
4479 {
09d92015
MM
4480 char character;
4481 unsigned long arm_value;
4482 unsigned long thumb_value;
4483 };
a737bd4d
NC
4484 static struct cps_flag flag_table[] =
4485 {
09d92015
MM
4486 {'a', 0x100, 0x4 },
4487 {'i', 0x080, 0x2 },
4488 {'f', 0x040, 0x1 }
4489 };
ea6ef066 4490
09d92015 4491 int saw_a_flag = 0;
ea6ef066 4492
09d92015
MM
4493 skip_whitespace (*str);
4494
a737bd4d 4495 /* Get the a, f and i flags. */
09d92015 4496 while (**str && **str != ',')
ea6ef066 4497 {
09d92015
MM
4498 struct cps_flag *p;
4499 struct cps_flag *q = flag_table + sizeof (flag_table)/sizeof (*p);
a737bd4d 4500
09d92015
MM
4501 for (p = flag_table; p < q; ++p)
4502 if (strncasecmp (*str, &p->character, 1) == 0)
4503 {
4504 inst.instruction |= (thumb_p ? p->thumb_value : p->arm_value);
4505 saw_a_flag = 1;
4506 break;
4507 }
4508 if (p == q)
4509 {
4510 inst.error = _("unrecognized flag");
4511 return;
4512 }
4513 (*str)++;
ea6ef066 4514 }
a737bd4d
NC
4515
4516 if (!saw_a_flag)
4517 inst.error = _("no 'a', 'i', or 'f' flags for 'cps'");
4518}
4519
4520static void
4521do_cpsi (char * str)
4522{
4523 do_cps_flags (&str, /*thumb_p=*/0);
4524
4525 if (skip_past_comma (&str) == SUCCESS)
4526 {
4527 skip_whitespace (str);
4528 do_cps_mode (&str);
4529 }
4530 end_of_line (str);
ea6ef066
RE
4531}
4532
b05fe5cf
ZW
4533/* ARM V6T2 bitfield manipulation instructions. */
4534
4535static int
4536five_bit_unsigned_immediate (char **str)
4537{
4538 expressionS expr;
4539
4540 skip_whitespace (*str);
4541 if (!is_immediate_prefix (**str))
4542 {
4543 inst.error = _("immediate expression expected");
4544 return -1;
4545 }
4546 (*str)++;
4547 if (my_get_expression (&expr, str))
4548 {
4549 inst.error = _("bad expression");
4550 return -1;
4551 }
4552 if (expr.X_op != O_constant)
4553 {
4554 inst.error = _("constant expression expected");
4555 return -1;
4556 }
4557 if (expr.X_add_number < 0 || expr.X_add_number > 32)
4558 {
4559 inst.error = _("immediate value out of range");
4560 return -1;
4561 }
4562
4563 return expr.X_add_number;
4564}
4565
4566static void
4567bfci_lsb_and_width (char *str)
4568{
4569 int lsb, width;
4570
4571 if ((lsb = five_bit_unsigned_immediate (&str)) == -1)
4572 return;
4573
4574 if (skip_past_comma (&str) == FAIL)
4575 {
4576 inst.error = BAD_ARGS;
4577 return;
4578 }
4579 if ((width = five_bit_unsigned_immediate (&str)) == -1)
4580 return;
4581
4582 end_of_line (str);
4583
4584 if (width == 0 || lsb == 32)
4585 {
4586 inst.error = _("immediate value out of range");
4587 return;
4588 }
4589 else if (width + lsb > 32)
4590 {
4591 inst.error = _("bit-field extends past end of register");
4592 return;
4593 }
4594
4595 /* Convert to LSB/MSB and write to register. */
4596 inst.instruction |= lsb << 7;
4597 inst.instruction |= (width + lsb - 1) << 16;
4598}
4599
4600static void
4601do_bfc (char *str)
4602{
4603 int rd;
4604
4605 /* Rd. */
4606 skip_whitespace (str);
4607 if (((rd = reg_required_here (&str, 12)) == FAIL)
4608 || (skip_past_comma (&str) == FAIL))
4609 {
4610 inst.error = BAD_ARGS;
4611 return;
4612 }
4613 else if (rd == REG_PC)
4614 {
4615 inst.error = BAD_PC;
4616 return;
4617 }
4618
4619 bfci_lsb_and_width (str);
4620}
4621
4622static void
4623do_bfi (char *str)
4624{
4625 int rd, rm;
4626
4627 /* Rd. */
4628 skip_whitespace (str);
4629 if (((rd = reg_required_here (&str, 12)) == FAIL)
4630 || (skip_past_comma (&str) == FAIL))
4631 {
4632 inst.error = BAD_ARGS;
4633 return;
4634 }
4635 else if (rd == REG_PC)
4636 {
4637 inst.error = BAD_PC;
4638 return;
4639 }
4640
4641 /* Rm. Accept #0 in this position as an alternative syntax for bfc. */
4642 skip_whitespace (str);
4643 if (is_immediate_prefix (*str))
4644 {
4645 expressionS expr;
4646 str++;
4647 if (my_get_expression (&expr, &str))
4648 {
4649 inst.error = _("bad expression");
4650 return;
4651 }
4652 if (expr.X_op != O_constant)
4653 {
4654 inst.error = _("constant expression expected");
4655 return;
4656 }
4657 if (expr.X_add_number != 0)
4658 {
4659 inst.error = _("immediate value out of range");
4660 return;
4661 }
4662 inst.instruction |= 0x0000000f; /* Rm = PC -> bfc, not bfi. */
4663 }
4664 else
4665 {
4666 if ((rm = reg_required_here (&str, 0)) == FAIL)
4667 {
4668 inst.error = BAD_ARGS;
4669 return;
4670 }
4671 else if (rm == REG_PC)
4672 {
4673 inst.error = BAD_PC;
4674 return;
4675 }
4676 }
4677 if (skip_past_comma (&str) == FAIL)
4678 {
4679 inst.error = BAD_ARGS;
4680 return;
4681 }
4682
4683 bfci_lsb_and_width (str);
4684}
4685
4686static void
4687do_bfx (char *str)
4688{
4689 int lsb, width;
4690
4691 /* Rd. */
4692 skip_whitespace (str);
4693 if (reg_required_here (&str, 12) == FAIL
4694 || skip_past_comma (&str) == FAIL)
4695 {
4696 inst.error = BAD_ARGS;
4697 return;
4698 }
4699
4700 /* Rm. */
4701 skip_whitespace (str);
4702 if (reg_required_here (&str, 0) == FAIL
4703 || skip_past_comma (&str) == FAIL)
4704 {
4705 inst.error = BAD_ARGS;
4706 return;
4707 }
4708
4709 if ((lsb = five_bit_unsigned_immediate (&str)) == -1)
4710 return;
4711
4712 if (skip_past_comma (&str) == FAIL)
4713 {
4714 inst.error = BAD_ARGS;
4715 return;
4716 }
4717 if ((width = five_bit_unsigned_immediate (&str)) == -1)
4718 return;
4719
4720 end_of_line (str);
4721
4722 if (width == 0 || lsb == 32)
4723 {
4724 inst.error = _("immediate value out of range");
4725 return;
4726 }
4727 else if (width + lsb > 32)
4728 {
4729 inst.error = _("bit-field extends past end of register");
4730 return;
4731 }
4732
4733 inst.instruction |= lsb << 7;
4734 inst.instruction |= (width - 1) << 16;
4735}
4736
4737static void
4738do_rbit (char *str)
4739{
4740 /* Rd. */
4741 skip_whitespace (str);
4742 if (reg_required_here (&str, 12) == FAIL
4743 || skip_past_comma (&str) == FAIL)
4744 {
4745 inst.error = BAD_ARGS;
4746 return;
4747 }
4748
4749 /* Rm. */
4750 skip_whitespace (str);
4751 if (reg_required_here (&str, 0) == FAIL)
4752 {
4753 inst.error = BAD_ARGS;
4754 return;
4755 }
4756
4757 end_of_line (str);
4758}
4759
4760/* ARM V6T2 16-bit immediate register load: MOV[WT]{cond} Rd, #<imm16>. */
4761static void
4762do_mov16 (char *str)
4763{
4764 int rd;
4765 expressionS expr;
4766
4767 /* Rd. */
4768 skip_whitespace (str);
4769 if (((rd = reg_required_here (&str, 12)) == FAIL)
4770 || (skip_past_comma (&str) == FAIL))
4771 {
4772 inst.error = BAD_ARGS;
4773 return;
4774 }
4775 else if (rd == REG_PC)
4776 {
4777 inst.error = BAD_PC;
4778 return;
4779 }
4780
4781 /* Imm16. */
4782 skip_whitespace (str);
4783 if (!is_immediate_prefix (*str))
4784 {
4785 inst.error = _("immediate expression expected");
4786 return;
4787 }
4788 str++;
4789 if (my_get_expression (&expr, &str))
4790 {
4791 inst.error = _("bad expression");
4792 return;
4793 }
4794 if (expr.X_op != O_constant)
4795 {
4796 inst.error = _("constant expression expected");
4797 return;
4798 }
4799 if (expr.X_add_number < 0 || expr.X_add_number > 65535)
4800 {
4801 inst.error = _("immediate value out of range");
4802 return;
4803 }
4804
4805 end_of_line (str);
4806
4807 /* The value is in two pieces: 0:11, 16:19. */
4808 inst.instruction |= (expr.X_add_number & 0x00000fff);
4809 inst.instruction |= (expr.X_add_number & 0x0000f000) << 4;
4810}
4811
4812
b99bd4ef
NC
4813/* THUMB V5 breakpoint instruction (argument parse)
4814 BKPT <immed_8>. */
4815
4816static void
a737bd4d 4817do_t_bkpt (char * str)
b99bd4ef
NC
4818{
4819 expressionS expr;
4820 unsigned long number;
4821
4822 skip_whitespace (str);
4823
4824 /* Allow optional leading '#'. */
4825 if (is_immediate_prefix (*str))
4826 str ++;
4827
4828 memset (& expr, '\0', sizeof (expr));
143c8e19
NC
4829 if (my_get_expression (& expr, & str)
4830 || (expr.X_op != O_constant
4831 /* As a convenience we allow 'bkpt' without an operand. */
4832 && expr.X_op != O_absent))
b99bd4ef 4833 {
143c8e19 4834 inst.error = _("bad expression");
b99bd4ef
NC
4835 return;
4836 }
4837
4838 number = expr.X_add_number;
4839
4840 /* Check it fits an 8 bit unsigned. */
4841 if (number != (number & 0xff))
4842 {
4843 inst.error = _("immediate value out of range");
4844 return;
4845 }
4846
4847 inst.instruction |= number;
4848
4849 end_of_line (str);
4850}
4851
f17c130b 4852#ifdef OBJ_ELF
a737bd4d
NC
4853static bfd_reloc_code_real_type
4854arm_parse_reloc (void)
4855{
4856 char id [16];
4857 char * ip;
4858 unsigned int i;
4859 static struct
4860 {
4861 char * str;
4862 int len;
4863 bfd_reloc_code_real_type reloc;
4864 }
4865 reloc_map[] =
4866 {
4867#define MAP(str,reloc) { str, sizeof (str) - 1, reloc }
4868 MAP ("(got)", BFD_RELOC_ARM_GOT32),
4869 MAP ("(gotoff)", BFD_RELOC_ARM_GOTOFF),
4870 /* ScottB: Jan 30, 1998 - Added support for parsing "var(PLT)"
4871 branch instructions generated by GCC for PLT relocs. */
4872 MAP ("(plt)", BFD_RELOC_ARM_PLT32),
4873 MAP ("(target1)", BFD_RELOC_ARM_TARGET1),
4874 MAP ("(sbrel)", BFD_RELOC_ARM_SBREL32),
4875 MAP ("(target2)", BFD_RELOC_ARM_TARGET2),
4876 { NULL, 0, BFD_RELOC_UNUSED }
4877#undef MAP
4878 };
4879
4880 for (i = 0, ip = input_line_pointer;
4881 i < sizeof (id) && (ISALNUM (*ip) || ISPUNCT (*ip));
4882 i++, ip++)
4883 id[i] = TOLOWER (*ip);
4884
4885 for (i = 0; reloc_map[i].str; i++)
4886 if (strncmp (id, reloc_map[i].str, reloc_map[i].len) == 0)
4887 break;
4888
4889 input_line_pointer += reloc_map[i].len;
4890
4891 return reloc_map[i].reloc;
4892}
f17c130b 4893#endif
a737bd4d 4894
b99bd4ef
NC
4895/* ARM V5 branch-link-exchange (argument parse) for BLX(1) only.
4896 Expects inst.instruction is set for BLX(1).
4897 Note: this is cloned from do_branch, and the reloc changed to be a
4898 new one that can cope with setting one extra bit (the H bit). */
4899
4900static void
a737bd4d 4901do_branch25 (char * str)
b99bd4ef
NC
4902{
4903 if (my_get_expression (& inst.reloc.exp, & str))
4904 return;
4905
4906#ifdef OBJ_ELF
4907 {
4908 char * save_in;
4909
4910 /* ScottB: February 5, 1998 */
4911 /* Check to see of PLT32 reloc required for the instruction. */
4912
4913 /* arm_parse_reloc() works on input_line_pointer.
4914 We actually want to parse the operands to the branch instruction
4915 passed in 'str'. Save the input pointer and restore it later. */
4916 save_in = input_line_pointer;
4917 input_line_pointer = str;
4918
4919 if (inst.reloc.exp.X_op == O_symbol
4920 && *str == '('
4921 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
4922 {
4923 inst.reloc.type = BFD_RELOC_ARM_PLT32;
4924 inst.reloc.pc_rel = 0;
4925 /* Modify str to point to after parsed operands, otherwise
4926 end_of_line() will complain about the (PLT) left in str. */
4927 str = input_line_pointer;
4928 }
4929 else
4930 {
4931 inst.reloc.type = BFD_RELOC_ARM_PCREL_BLX;
4932 inst.reloc.pc_rel = 1;
4933 }
4934
4935 input_line_pointer = save_in;
4936 }
4937#else
4938 inst.reloc.type = BFD_RELOC_ARM_PCREL_BLX;
4939 inst.reloc.pc_rel = 1;
4940#endif /* OBJ_ELF */
4941
4942 end_of_line (str);
4943}
4944
4945/* ARM V5 branch-link-exchange instruction (argument parse)
4946 BLX <target_addr> ie BLX(1)
4947 BLX{<condition>} <Rm> ie BLX(2)
4948 Unfortunately, there are two different opcodes for this mnemonic.
4949 So, the insns[].value is not used, and the code here zaps values
4950 into inst.instruction.
4951 Also, the <target_addr> can be 25 bits, hence has its own reloc. */
4952
4953static void
a737bd4d 4954do_blx (char * str)
b99bd4ef
NC
4955{
4956 char * mystr = str;
4957 int rm;
4958
b99bd4ef
NC
4959 skip_whitespace (mystr);
4960 rm = reg_required_here (& mystr, 0);
4961
4962 /* The above may set inst.error. Ignore his opinion. */
4963 inst.error = 0;
4964
4965 if (rm != FAIL)
4966 {
4967 /* Arg is a register.
4968 Use the condition code our caller put in inst.instruction.
4969 Pass ourselves off as a BX with a funny opcode. */
4970 inst.instruction |= 0x012fff30;
f2b7cb0a 4971 do_bx (str);
b99bd4ef
NC
4972 }
4973 else
4974 {
4975 /* This must be is BLX <target address>, no condition allowed. */
4976 if (inst.instruction != COND_ALWAYS)
cc8a6dd0
KH
4977 {
4978 inst.error = BAD_COND;
b99bd4ef 4979 return;
cc8a6dd0 4980 }
b99bd4ef
NC
4981
4982 inst.instruction = 0xfafffffe;
4983
4984 /* Process like a B/BL, but with a different reloc.
4985 Note that B/BL expecte fffffe, not 0, offset in the opcode table. */
f2b7cb0a 4986 do_branch25 (str);
b99bd4ef
NC
4987 }
4988}
4989
4990/* ARM V5 Thumb BLX (argument parse)
4991 BLX <target_addr> which is BLX(1)
4992 BLX <Rm> which is BLX(2)
4993 Unfortunately, there are two different opcodes for this mnemonic.
4994 So, the tinsns[].value is not used, and the code here zaps values
4995 into inst.instruction. */
4996
4997static void
a737bd4d 4998do_t_blx (char * str)
b99bd4ef
NC
4999{
5000 char * mystr = str;
5001 int rm;
5002
5003 skip_whitespace (mystr);
5004 inst.instruction = 0x4780;
5005
5006 /* Note that this call is to the ARM register recognizer. BLX(2)
5007 uses the ARM register space, not the Thumb one, so a call to
5008 thumb_reg() would be wrong. */
5009 rm = reg_required_here (& mystr, 3);
5010 inst.error = 0;
5011
5012 if (rm != FAIL)
5013 {
5014 /* It's BLX(2). The .instruction was zapped with rm & is final. */
5015 inst.size = 2;
5016 }
5017 else
5018 {
5019 /* No ARM register. This must be BLX(1). Change the .instruction. */
5020 inst.instruction = 0xf7ffeffe;
5021 inst.size = 4;
5022
5023 if (my_get_expression (& inst.reloc.exp, & mystr))
5024 return;
5025
5026 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BLX;
5027 inst.reloc.pc_rel = 1;
5028 }
5029
5030 end_of_line (mystr);
5031}
5032
5033/* ARM V5 breakpoint instruction (argument parse)
5034 BKPT <16 bit unsigned immediate>
5035 Instruction is not conditional.
5036 The bit pattern given in insns[] has the COND_ALWAYS condition,
cc8a6dd0 5037 and it is an error if the caller tried to override that. */
b99bd4ef
NC
5038
5039static void
a737bd4d 5040do_bkpt (char * str)
b99bd4ef
NC
5041{
5042 expressionS expr;
5043 unsigned long number;
5044
5045 skip_whitespace (str);
5046
5047 /* Allow optional leading '#'. */
5048 if (is_immediate_prefix (* str))
5049 str++;
5050
5051 memset (& expr, '\0', sizeof (expr));
5052
143c8e19
NC
5053 if (my_get_expression (& expr, & str)
5054 || (expr.X_op != O_constant
5055 /* As a convenience we allow 'bkpt' without an operand. */
5056 && expr.X_op != O_absent))
b99bd4ef 5057 {
143c8e19 5058 inst.error = _("bad expression");
b99bd4ef
NC
5059 return;
5060 }
5061
5062 number = expr.X_add_number;
5063
5064 /* Check it fits a 16 bit unsigned. */
5065 if (number != (number & 0xffff))
5066 {
5067 inst.error = _("immediate value out of range");
5068 return;
5069 }
5070
5071 /* Top 12 of 16 bits to bits 19:8. */
5072 inst.instruction |= (number & 0xfff0) << 4;
5073
5074 /* Bottom 4 of 16 bits to bits 3:0. */
5075 inst.instruction |= number & 0xf;
5076
5077 end_of_line (str);
b99bd4ef
NC
5078}
5079
09d92015
MM
5080/* THUMB CPS instruction (argument parse). */
5081
5082static void
a737bd4d 5083do_t_cps (char * str)
09d92015
MM
5084{
5085 do_cps_flags (&str, /*thumb_p=*/1);
5086 end_of_line (str);
5087}
5088
a737bd4d
NC
5089/* Parse and validate that a register is of the right form, this saves
5090 repeated checking of this information in many similar cases.
5091 Unlike the 32-bit case we do not insert the register into the opcode
5092 here, since the position is often unknown until the full instruction
5093 has been parsed. */
5094
5095static int
5096thumb_reg (char ** strp, int hi_lo)
5097{
5098 int reg;
5099
5100 if ((reg = reg_required_here (strp, -1)) == FAIL)
5101 return FAIL;
5102
5103 switch (hi_lo)
5104 {
5105 case THUMB_REG_LO:
5106 if (reg > 7)
5107 {
5108 inst.error = _("lo register required");
5109 return FAIL;
5110 }
5111 break;
5112
5113 case THUMB_REG_HI:
5114 if (reg < 8)
5115 {
5116 inst.error = _("hi register required");
5117 return FAIL;
5118 }
5119 break;
5120
5121 default:
5122 break;
5123 }
5124
5125 return reg;
5126}
5127
5128static void
5129thumb_mov_compare (char * str, int move)
5130{
5131 int Rd, Rs = FAIL;
5132
5133 skip_whitespace (str);
5134
5135 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
5136 || skip_past_comma (&str) == FAIL)
5137 {
5138 if (! inst.error)
5139 inst.error = BAD_ARGS;
5140 return;
5141 }
5142
5143 if (move != THUMB_CPY && is_immediate_prefix (*str))
5144 {
5145 str++;
5146 if (my_get_expression (&inst.reloc.exp, &str))
5147 return;
5148 }
5149 else if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
5150 return;
5151
5152 if (Rs != FAIL)
5153 {
5154 if (move != THUMB_CPY && Rs < 8 && Rd < 8)
5155 {
5156 if (move == THUMB_MOVE)
5157 /* A move of two lowregs is encoded as ADD Rd, Rs, #0
5158 since a MOV instruction produces unpredictable results. */
5159 inst.instruction = T_OPCODE_ADD_I3;
5160 else
5161 inst.instruction = T_OPCODE_CMP_LR;
5162 inst.instruction |= Rd | (Rs << 3);
5163 }
5164 else
5165 {
5166 if (move == THUMB_MOVE)
5167 inst.instruction = T_OPCODE_MOV_HR;
5168 else if (move != THUMB_CPY)
5169 inst.instruction = T_OPCODE_CMP_HR;
5170
5171 if (Rd > 7)
5172 inst.instruction |= THUMB_H1;
5173
5174 if (Rs > 7)
5175 inst.instruction |= THUMB_H2;
5176
5177 inst.instruction |= (Rd & 7) | ((Rs & 7) << 3);
5178 }
5179 }
5180 else
5181 {
5182 if (Rd > 7)
5183 {
5184 inst.error = _("only lo regs allowed with immediate");
5185 return;
5186 }
5187
5188 if (move == THUMB_MOVE)
5189 inst.instruction = T_OPCODE_MOV_I8;
5190 else
5191 inst.instruction = T_OPCODE_CMP_I8;
5192
5193 inst.instruction |= Rd << 8;
5194
5195 if (inst.reloc.exp.X_op != O_constant)
5196 inst.reloc.type = BFD_RELOC_ARM_THUMB_IMM;
5197 else
5198 {
5199 unsigned value = inst.reloc.exp.X_add_number;
5200
5201 if (value > 255)
5202 {
5203 inst.error = _("invalid immediate");
5204 return;
5205 }
5206
5207 inst.instruction |= value;
5208 }
5209 }
5210
5211 end_of_line (str);
5212}
5213
09d92015
MM
5214/* THUMB CPY instruction (argument parse). */
5215
5216static void
a737bd4d 5217do_t_cpy (char * str)
09d92015
MM
5218{
5219 thumb_mov_compare (str, THUMB_CPY);
5220}
5221
5222/* THUMB SETEND instruction (argument parse). */
5223
5224static void
a737bd4d 5225do_t_setend (char * str)
09d92015
MM
5226{
5227 if (do_endian_specifier (str))
5228 inst.instruction |= 0x8;
5229}
5230
e16bb312
NC
5231/* Parse INSN_TYPE insn STR having a possible IMMEDIATE_SIZE immediate. */
5232
5233static unsigned long
a737bd4d
NC
5234check_iwmmxt_insn (char * str,
5235 enum iwmmxt_insn_type insn_type,
5236 int immediate_size)
e16bb312
NC
5237{
5238 int reg = 0;
5239 const char * inst_error;
5240 expressionS expr;
5241 unsigned long number;
5242
5243 inst_error = inst.error;
5244 if (!inst.error)
5245 inst.error = BAD_ARGS;
5246 skip_whitespace (str);
5247
5248 switch (insn_type)
5249 {
5250 case check_rd:
5251 if ((reg = reg_required_here (&str, 12)) == FAIL)
5252 return FAIL;
5253 break;
a737bd4d 5254
e16bb312
NC
5255 case check_wr:
5256 if ((wreg_required_here (&str, 0, IWMMXT_REG_WR)) == FAIL)
5257 return FAIL;
5258 break;
a737bd4d 5259
e16bb312
NC
5260 case check_wrwr:
5261 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
5262 || skip_past_comma (&str) == FAIL
5263 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL))
5264 return FAIL;
5265 break;
a737bd4d 5266
e16bb312
NC
5267 case check_wrwrwr:
5268 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
5269 || skip_past_comma (&str) == FAIL
5270 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5271 || skip_past_comma (&str) == FAIL
5272 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL))
5273 return FAIL;
5274 break;
a737bd4d 5275
e16bb312
NC
5276 case check_wrwrwcg:
5277 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
5278 || skip_past_comma (&str) == FAIL
5279 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5280 || skip_past_comma (&str) == FAIL
5281 || wreg_required_here (&str, 0, IWMMXT_REG_WCG) == FAIL))
5282 return FAIL;
5283 break;
a737bd4d 5284
e16bb312
NC
5285 case check_tbcst:
5286 if ((wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5287 || skip_past_comma (&str) == FAIL
5288 || reg_required_here (&str, 12) == FAIL))
5289 return FAIL;
5290 break;
a737bd4d 5291
e16bb312
NC
5292 case check_tmovmsk:
5293 if ((reg_required_here (&str, 12) == FAIL
5294 || skip_past_comma (&str) == FAIL
5295 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL))
5296 return FAIL;
5297 break;
a737bd4d 5298
e16bb312
NC
5299 case check_tmia:
5300 if ((wreg_required_here (&str, 5, IWMMXT_REG_WR) == FAIL
5301 || skip_past_comma (&str) == FAIL
5302 || reg_required_here (&str, 0) == FAIL
5303 || skip_past_comma (&str) == FAIL
5304 || reg_required_here (&str, 12) == FAIL))
5305 return FAIL;
5306 break;
a737bd4d 5307
e16bb312
NC
5308 case check_tmcrr:
5309 if ((wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL
5310 || skip_past_comma (&str) == FAIL
5311 || reg_required_here (&str, 12) == FAIL
5312 || skip_past_comma (&str) == FAIL
5313 || reg_required_here (&str, 16) == FAIL))
5314 return FAIL;
5315 break;
a737bd4d 5316
e16bb312
NC
5317 case check_tmrrc:
5318 if ((reg_required_here (&str, 12) == FAIL
5319 || skip_past_comma (&str) == FAIL
5320 || reg_required_here (&str, 16) == FAIL
5321 || skip_past_comma (&str) == FAIL
5322 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL))
5323 return FAIL;
5324 break;
a737bd4d 5325
e16bb312
NC
5326 case check_tmcr:
5327 if ((wreg_required_here (&str, 16, IWMMXT_REG_WC) == FAIL
5328 || skip_past_comma (&str) == FAIL
5329 || reg_required_here (&str, 12) == FAIL))
5330 return FAIL;
5331 break;
a737bd4d 5332
e16bb312
NC
5333 case check_tmrc:
5334 if ((reg_required_here (&str, 12) == FAIL
5335 || skip_past_comma (&str) == FAIL
5336 || wreg_required_here (&str, 16, IWMMXT_REG_WC) == FAIL))
5337 return FAIL;
5338 break;
a737bd4d 5339
e16bb312
NC
5340 case check_tinsr:
5341 if ((wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5342 || skip_past_comma (&str) == FAIL
5343 || reg_required_here (&str, 12) == FAIL
5344 || skip_past_comma (&str) == FAIL))
5345 return FAIL;
5346 break;
a737bd4d 5347
e16bb312
NC
5348 case check_textrc:
5349 if ((reg_required_here (&str, 12) == FAIL
5350 || skip_past_comma (&str) == FAIL))
5351 return FAIL;
5352 break;
a737bd4d 5353
e16bb312
NC
5354 case check_waligni:
5355 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
5356 || skip_past_comma (&str) == FAIL
5357 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5358 || skip_past_comma (&str) == FAIL
5359 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL
5360 || skip_past_comma (&str) == FAIL))
5361 return FAIL;
5362 break;
a737bd4d 5363
e16bb312
NC
5364 case check_textrm:
5365 if ((reg_required_here (&str, 12) == FAIL
5366 || skip_past_comma (&str) == FAIL
5367 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5368 || skip_past_comma (&str) == FAIL))
5369 return FAIL;
5370 break;
a737bd4d 5371
e16bb312
NC
5372 case check_wshufh:
5373 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
5374 || skip_past_comma (&str) == FAIL
5375 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5376 || skip_past_comma (&str) == FAIL))
5377 return FAIL;
5378 break;
5379 }
a737bd4d 5380
e16bb312
NC
5381 if (immediate_size == 0)
5382 {
5383 end_of_line (str);
5384 inst.error = inst_error;
5385 return reg;
5386 }
5387 else
5388 {
a737bd4d
NC
5389 skip_whitespace (str);
5390
5391 /* Allow optional leading '#'. */
e16bb312
NC
5392 if (is_immediate_prefix (* str))
5393 str++;
5394
5395 memset (& expr, '\0', sizeof (expr));
a737bd4d 5396
e16bb312
NC
5397 if (my_get_expression (& expr, & str) || (expr.X_op != O_constant))
5398 {
5399 inst.error = _("bad or missing expression");
5400 return FAIL;
5401 }
a737bd4d 5402
e16bb312 5403 number = expr.X_add_number;
a737bd4d 5404
e16bb312
NC
5405 if (number != (number & immediate_size))
5406 {
5407 inst.error = _("immediate value out of range");
5408 return FAIL;
5409 }
5410 end_of_line (str);
5411 inst.error = inst_error;
5412 return number;
5413 }
5414}
5415
5416static void
a737bd4d 5417do_iwmmxt_byte_addr (char * str)
e16bb312
NC
5418{
5419 int op = (inst.instruction & 0x300) >> 8;
5420 int reg;
5421
5422 inst.instruction &= ~0x300;
a737bd4d 5423 inst.instruction |= (op & 1) << 22 | (op & 2) << 7;
e16bb312
NC
5424
5425 skip_whitespace (str);
5426
5427 if ((reg = wreg_required_here (&str, 12, IWMMXT_REG_WR_OR_WC)) == FAIL
5428 || skip_past_comma (& str) == FAIL
5429 || cp_byte_address_required_here (&str) == FAIL)
5430 {
5431 if (! inst.error)
5432 inst.error = BAD_ARGS;
5433 }
5434 else
5435 end_of_line (str);
5436
5437 if (wc_register (reg))
5438 {
ece01a63 5439 as_bad (_("non-word size not supported with control register"));
e16bb312
NC
5440 inst.instruction |= 0xf0000100;
5441 inst.instruction &= ~0x00400000;
5442 }
5443}
5444
5445static void
a737bd4d 5446do_iwmmxt_tandc (char * str)
e16bb312
NC
5447{
5448 int reg;
5449
5450 reg = check_iwmmxt_insn (str, check_rd, 0);
5451
5452 if (reg != REG_PC && !inst.error)
5453 inst.error = _("only r15 allowed here");
e16bb312
NC
5454}
5455
5456static void
a737bd4d 5457do_iwmmxt_tbcst (char * str)
e16bb312
NC
5458{
5459 check_iwmmxt_insn (str, check_tbcst, 0);
e16bb312
NC
5460}
5461
5462static void
a737bd4d 5463do_iwmmxt_textrc (char * str)
e16bb312
NC
5464{
5465 unsigned long number;
5466
5467 if ((number = check_iwmmxt_insn (str, check_textrc, 7)) == (unsigned long) FAIL)
5468 return;
5469
5470 inst.instruction |= number & 0x7;
e16bb312
NC
5471}
5472
5473static void
a737bd4d 5474do_iwmmxt_textrm (char * str)
e16bb312
NC
5475{
5476 unsigned long number;
5477
5478 if ((number = check_iwmmxt_insn (str, check_textrm, 7)) == (unsigned long) FAIL)
5479 return;
5480
5481 inst.instruction |= number & 0x7;
5482}
5483
5484static void
a737bd4d 5485do_iwmmxt_tinsr (char * str)
e16bb312
NC
5486{
5487 unsigned long number;
5488
5489 if ((number = check_iwmmxt_insn (str, check_tinsr, 7)) == (unsigned long) FAIL)
5490 return;
5491
5492 inst.instruction |= number & 0x7;
e16bb312
NC
5493}
5494
5495static void
a737bd4d 5496do_iwmmxt_tmcr (char * str)
e16bb312
NC
5497{
5498 check_iwmmxt_insn (str, check_tmcr, 0);
e16bb312
NC
5499}
5500
5501static void
a737bd4d 5502do_iwmmxt_tmcrr (char * str)
e16bb312
NC
5503{
5504 check_iwmmxt_insn (str, check_tmcrr, 0);
e16bb312
NC
5505}
5506
5507static void
a737bd4d 5508do_iwmmxt_tmia (char * str)
e16bb312
NC
5509{
5510 check_iwmmxt_insn (str, check_tmia, 0);
e16bb312
NC
5511}
5512
5513static void
a737bd4d 5514do_iwmmxt_tmovmsk (char * str)
e16bb312
NC
5515{
5516 check_iwmmxt_insn (str, check_tmovmsk, 0);
e16bb312
NC
5517}
5518
5519static void
a737bd4d 5520do_iwmmxt_tmrc (char * str)
e16bb312
NC
5521{
5522 check_iwmmxt_insn (str, check_tmrc, 0);
e16bb312
NC
5523}
5524
5525static void
a737bd4d 5526do_iwmmxt_tmrrc (char * str)
e16bb312
NC
5527{
5528 check_iwmmxt_insn (str, check_tmrrc, 0);
e16bb312
NC
5529}
5530
5531static void
a737bd4d 5532do_iwmmxt_torc (char * str)
e16bb312
NC
5533{
5534 check_iwmmxt_insn (str, check_rd, 0);
e16bb312
NC
5535}
5536
5537static void
a737bd4d 5538do_iwmmxt_waligni (char * str)
e16bb312
NC
5539{
5540 unsigned long number;
5541
5542 if ((number = check_iwmmxt_insn (str, check_waligni, 7)) == (unsigned long) FAIL)
5543 return;
5544
5545 inst.instruction |= ((number & 0x7) << 20);
e16bb312
NC
5546}
5547
5548static void
a737bd4d 5549do_iwmmxt_wmov (char * str)
e16bb312
NC
5550{
5551 if (check_iwmmxt_insn (str, check_wrwr, 0) == (unsigned long) FAIL)
5552 return;
a737bd4d 5553
e16bb312 5554 inst.instruction |= ((inst.instruction >> 16) & 0xf);
e16bb312
NC
5555}
5556
5557static void
a737bd4d 5558do_iwmmxt_word_addr (char * str)
e16bb312
NC
5559{
5560 int op = (inst.instruction & 0x300) >> 8;
5561 int reg;
5562
5563 inst.instruction &= ~0x300;
a737bd4d 5564 inst.instruction |= (op & 1) << 22 | (op & 2) << 7;
e16bb312
NC
5565
5566 skip_whitespace (str);
5567
5568 if ((reg = wreg_required_here (&str, 12, IWMMXT_REG_WR_OR_WC)) == FAIL
5569 || skip_past_comma (& str) == FAIL
5570 || cp_address_required_here (& str, CP_WB_OK) == FAIL)
5571 {
5572 if (! inst.error)
5573 inst.error = BAD_ARGS;
5574 }
5575 else
5576 end_of_line (str);
5577
5578 if (wc_register (reg))
5579 {
ece01a63
ILT
5580 if ((inst.instruction & COND_MASK) != COND_ALWAYS)
5581 as_bad (_("conditional execution not supported with control register"));
5582 if (op != 2)
5583 as_bad (_("non-word size not supported with control register"));
e16bb312
NC
5584 inst.instruction |= 0xf0000100;
5585 inst.instruction &= ~0x00400000;
5586 }
5587}
5588
5589static void
a737bd4d 5590do_iwmmxt_wrwr (char * str)
e16bb312
NC
5591{
5592 check_iwmmxt_insn (str, check_wrwr, 0);
e16bb312
NC
5593}
5594
5595static void
a737bd4d 5596do_iwmmxt_wrwrwcg (char * str)
e16bb312
NC
5597{
5598 check_iwmmxt_insn (str, check_wrwrwcg, 0);
e16bb312
NC
5599}
5600
5601static void
a737bd4d 5602do_iwmmxt_wrwrwr (char * str)
e16bb312
NC
5603{
5604 check_iwmmxt_insn (str, check_wrwrwr, 0);
e16bb312
NC
5605}
5606
5607static void
a737bd4d 5608do_iwmmxt_wshufh (char * str)
e16bb312
NC
5609{
5610 unsigned long number;
5611
5612 if ((number = check_iwmmxt_insn (str, check_wshufh, 0xff)) == (unsigned long) FAIL)
5613 return;
5614
5615 inst.instruction |= ((number & 0xf0) << 16) | (number & 0xf);
e16bb312
NC
5616}
5617
5618static void
a737bd4d 5619do_iwmmxt_wzero (char * str)
e16bb312
NC
5620{
5621 if (check_iwmmxt_insn (str, check_wr, 0) == (unsigned long) FAIL)
5622 return;
5623
5624 inst.instruction |= ((inst.instruction & 0xf) << 12) | ((inst.instruction & 0xf) << 16);
e16bb312
NC
5625}
5626
b99bd4ef
NC
5627/* Xscale multiply-accumulate (argument parse)
5628 MIAcc acc0,Rm,Rs
5629 MIAPHcc acc0,Rm,Rs
5630 MIAxycc acc0,Rm,Rs. */
5631
5632static void
a737bd4d 5633do_xsc_mia (char * str)
b99bd4ef
NC
5634{
5635 int rs;
5636 int rm;
5637
f2b7cb0a 5638 if (accum0_required_here (& str) == FAIL)
b99bd4ef
NC
5639 inst.error = ERR_NO_ACCUM;
5640
5641 else if (skip_past_comma (& str) == FAIL
5642 || (rm = reg_required_here (& str, 0)) == FAIL)
5643 inst.error = BAD_ARGS;
5644
5645 else if (skip_past_comma (& str) == FAIL
5646 || (rs = reg_required_here (& str, 12)) == FAIL)
5647 inst.error = BAD_ARGS;
5648
5649 /* inst.instruction has now been zapped with both rm and rs. */
5650 else if (rm == REG_PC || rs == REG_PC)
5651 inst.error = BAD_PC; /* Undefined result if rm or rs is R15. */
5652
5653 else
5654 end_of_line (str);
5655}
5656
5657/* Xscale move-accumulator-register (argument parse)
5658
5659 MARcc acc0,RdLo,RdHi. */
5660
5661static void
a737bd4d 5662do_xsc_mar (char * str)
b99bd4ef
NC
5663{
5664 int rdlo, rdhi;
5665
f2b7cb0a 5666 if (accum0_required_here (& str) == FAIL)
b99bd4ef
NC
5667 inst.error = ERR_NO_ACCUM;
5668
5669 else if (skip_past_comma (& str) == FAIL
5670 || (rdlo = reg_required_here (& str, 12)) == FAIL)
5671 inst.error = BAD_ARGS;
5672
5673 else if (skip_past_comma (& str) == FAIL
5674 || (rdhi = reg_required_here (& str, 16)) == FAIL)
5675 inst.error = BAD_ARGS;
5676
5677 /* inst.instruction has now been zapped with both rdlo and rdhi. */
5678 else if (rdlo == REG_PC || rdhi == REG_PC)
5679 inst.error = BAD_PC; /* Undefined result if rdlo or rdhi is R15. */
5680
5681 else
5682 end_of_line (str);
5683}
5684
5685/* Xscale move-register-accumulator (argument parse)
5686
5687 MRAcc RdLo,RdHi,acc0. */
5688
5689static void
a737bd4d 5690do_xsc_mra (char * str)
b99bd4ef
NC
5691{
5692 int rdlo;
5693 int rdhi;
5694
b99bd4ef
NC
5695 skip_whitespace (str);
5696
5697 if ((rdlo = reg_required_here (& str, 12)) == FAIL)
5698 inst.error = BAD_ARGS;
5699
5700 else if (skip_past_comma (& str) == FAIL
5701 || (rdhi = reg_required_here (& str, 16)) == FAIL)
5702 inst.error = BAD_ARGS;
5703
5704 else if (skip_past_comma (& str) == FAIL
5705 || accum0_required_here (& str) == FAIL)
5706 inst.error = ERR_NO_ACCUM;
5707
a737bd4d
NC
5708 /* inst.instruction has now been zapped with both rdlo and rdhi. */
5709 else if (rdlo == rdhi)
5710 inst.error = BAD_ARGS; /* Undefined result if 2 writes to same reg. */
5711
5712 else if (rdlo == REG_PC || rdhi == REG_PC)
5713 inst.error = BAD_PC; /* Undefined result if rdlo or rdhi is R15. */
5714 else
5715 end_of_line (str);
5716}
5717
5718static int
5719ldst_extend (char ** str)
5720{
5721 int add = INDEX_UP;
5722
5723 switch (**str)
5724 {
5725 case '#':
5726 case '$':
5727 (*str)++;
5728 if (my_get_expression (& inst.reloc.exp, str))
5729 return FAIL;
5730
5731 if (inst.reloc.exp.X_op == O_constant)
5732 {
5733 int value = inst.reloc.exp.X_add_number;
5734
5735 if (value < -4095 || value > 4095)
5736 {
5737 inst.error = _("address offset too large");
5738 return FAIL;
5739 }
5740
5741 if (value < 0)
5742 {
5743 value = -value;
5744 add = 0;
5745 }
5746
5747 inst.instruction |= add | value;
5748 }
5749 else
5750 {
5751 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
5752 inst.reloc.pc_rel = 0;
5753 }
5754 return SUCCESS;
5755
5756 case '-':
5757 add = 0;
5758 /* Fall through. */
5759
5760 case '+':
5761 (*str)++;
5762 /* Fall through. */
5763
5764 default:
5765 if (reg_required_here (str, 0) == FAIL)
5766 return FAIL;
5767
5768 inst.instruction |= add | OFFSET_REG;
5769 if (skip_past_comma (str) == SUCCESS)
5770 return decode_shift (str, SHIFT_IMMEDIATE);
b99bd4ef 5771
a737bd4d
NC
5772 return SUCCESS;
5773 }
b99bd4ef
NC
5774}
5775
c9b604bd 5776/* ARMv5TE: Preload-Cache
b99bd4ef
NC
5777
5778 PLD <addr_mode>
5779
5780 Syntactically, like LDR with B=1, W=0, L=1. */
5781
5782static void
a737bd4d 5783do_pld (char * str)
b99bd4ef
NC
5784{
5785 int rd;
5786
b99bd4ef
NC
5787 skip_whitespace (str);
5788
5789 if (* str != '[')
5790 {
5791 inst.error = _("'[' expected after PLD mnemonic");
5792 return;
5793 }
5794
90e4755a 5795 ++str;
b99bd4ef
NC
5796 skip_whitespace (str);
5797
5798 if ((rd = reg_required_here (& str, 16)) == FAIL)
5799 return;
5800
5801 skip_whitespace (str);
5802
90e4755a 5803 if (*str == ']')
b99bd4ef
NC
5804 {
5805 /* [Rn], ... ? */
90e4755a 5806 ++str;
b99bd4ef
NC
5807 skip_whitespace (str);
5808
90e4755a
RE
5809 /* Post-indexed addressing is not allowed with PLD. */
5810 if (skip_past_comma (&str) == SUCCESS)
b99bd4ef 5811 {
90e4755a
RE
5812 inst.error
5813 = _("post-indexed expression used in preload instruction");
5814 return;
b99bd4ef 5815 }
90e4755a 5816 else if (*str == '!') /* [Rn]! */
b99bd4ef
NC
5817 {
5818 inst.error = _("writeback used in preload instruction");
90e4755a 5819 ++str;
b99bd4ef
NC
5820 }
5821 else /* [Rn] */
5822 inst.instruction |= INDEX_UP | PRE_INDEX;
5823 }
5824 else /* [Rn, ...] */
5825 {
5826 if (skip_past_comma (& str) == FAIL)
5827 {
5828 inst.error = _("pre-indexed expression expected");
5829 return;
5830 }
5831
90e4755a 5832 if (ldst_extend (&str) == FAIL)
b99bd4ef
NC
5833 return;
5834
5835 skip_whitespace (str);
5836
5837 if (* str != ']')
5838 {
5839 inst.error = _("missing ]");
5840 return;
5841 }
5842
5843 ++ str;
5844 skip_whitespace (str);
5845
5846 if (* str == '!') /* [Rn]! */
5847 {
5848 inst.error = _("writeback used in preload instruction");
5849 ++ str;
5850 }
5851
5852 inst.instruction |= PRE_INDEX;
5853 }
5854
5855 end_of_line (str);
5856}
5857
c9b604bd 5858/* ARMv5TE load-consecutive (argument parse)
b99bd4ef
NC
5859 Mode is like LDRH.
5860
5861 LDRccD R, mode
5862 STRccD R, mode. */
5863
5864static void
a737bd4d 5865do_ldrd (char * str)
b99bd4ef
NC
5866{
5867 int rd;
5868 int rn;
5869
b99bd4ef
NC
5870 skip_whitespace (str);
5871
5872 if ((rd = reg_required_here (& str, 12)) == FAIL)
5873 {
5874 inst.error = BAD_ARGS;
5875 return;
5876 }
5877
5878 if (skip_past_comma (& str) == FAIL
5879 || (rn = ld_mode_required_here (& str)) == FAIL)
5880 {
5881 if (!inst.error)
cc8a6dd0 5882 inst.error = BAD_ARGS;
a737bd4d 5883 return;
b99bd4ef
NC
5884 }
5885
a737bd4d
NC
5886 /* inst.instruction has now been zapped with Rd and the addressing mode. */
5887 if (rd & 1) /* Unpredictable result if Rd is odd. */
5888 {
5889 inst.error = _("destination register must be even");
5890 return;
5891 }
b99bd4ef 5892
a737bd4d 5893 if (rd == REG_LR)
b99bd4ef 5894 {
a737bd4d
NC
5895 inst.error = _("r14 not allowed here");
5896 return;
b99bd4ef 5897 }
a737bd4d
NC
5898
5899 if (((rd == rn) || (rd + 1 == rn))
5900 && ((inst.instruction & WRITE_BACK)
5901 || (!(inst.instruction & PRE_INDEX))))
5902 as_warn (_("pre/post-indexing used when modified address register is destination"));
5903
5904 /* For an index-register load, the index register must not overlap the
5905 destination (even if not write-back). */
5906 if ((inst.instruction & V4_STR_BIT) == 0
5907 && (inst.instruction & HWOFFSET_IMM) == 0)
b99bd4ef 5908 {
a737bd4d
NC
5909 int rm = inst.instruction & 0x0000000f;
5910
5911 if (rm == rd || (rm == rd + 1))
5912 as_warn (_("ldrd destination registers must not overlap index register"));
b99bd4ef
NC
5913 }
5914
a737bd4d
NC
5915 end_of_line (str);
5916}
b99bd4ef 5917
a737bd4d
NC
5918/* Returns the index into fp_values of a floating point number,
5919 or -1 if not in the table. */
b99bd4ef 5920
a737bd4d
NC
5921static int
5922my_get_float_expression (char ** str)
5923{
5924 LITTLENUM_TYPE words[MAX_LITTLENUMS];
5925 char * save_in;
5926 expressionS exp;
5927 int i;
5928 int j;
b99bd4ef 5929
a737bd4d
NC
5930 memset (words, 0, MAX_LITTLENUMS * sizeof (LITTLENUM_TYPE));
5931
5932 /* Look for a raw floating point number. */
5933 if ((save_in = atof_ieee (*str, 'x', words)) != NULL
5934 && is_end_of_line[(unsigned char) *save_in])
5935 {
5936 for (i = 0; i < NUM_FLOAT_VALS; i++)
b99bd4ef 5937 {
a737bd4d 5938 for (j = 0; j < MAX_LITTLENUMS; j++)
b99bd4ef 5939 {
a737bd4d
NC
5940 if (words[j] != fp_values[i][j])
5941 break;
b99bd4ef 5942 }
a737bd4d
NC
5943
5944 if (j == MAX_LITTLENUMS)
b99bd4ef 5945 {
a737bd4d
NC
5946 *str = save_in;
5947 return i;
b99bd4ef
NC
5948 }
5949 }
a737bd4d 5950 }
b99bd4ef 5951
a737bd4d
NC
5952 /* Try and parse a more complex expression, this will probably fail
5953 unless the code uses a floating point prefix (eg "0f"). */
5954 save_in = input_line_pointer;
5955 input_line_pointer = *str;
5956 if (expression (&exp) == absolute_section
5957 && exp.X_op == O_big
5958 && exp.X_add_number < 0)
5959 {
5960 /* FIXME: 5 = X_PRECISION, should be #define'd where we can use it.
5961 Ditto for 15. */
5962 if (gen_to_words (words, 5, (long) 15) == 0)
5963 {
5964 for (i = 0; i < NUM_FLOAT_VALS; i++)
5965 {
5966 for (j = 0; j < MAX_LITTLENUMS; j++)
5967 {
5968 if (words[j] != fp_values[i][j])
5969 break;
5970 }
b99bd4ef 5971
a737bd4d
NC
5972 if (j == MAX_LITTLENUMS)
5973 {
5974 *str = input_line_pointer;
5975 input_line_pointer = save_in;
5976 return i;
5977 }
5978 }
5979 }
b99bd4ef 5980 }
a737bd4d
NC
5981
5982 *str = input_line_pointer;
5983 input_line_pointer = save_in;
5984 return -1;
5985}
5986
5987/* We handle all bad expressions here, so that we can report the faulty
5988 instruction in the error message. */
5989void
5990md_operand (expressionS * expr)
5991{
5992 if (in_my_get_expression)
b99bd4ef 5993 {
a737bd4d
NC
5994 expr->X_op = O_illegal;
5995 if (inst.error == NULL)
5996 inst.error = _("bad expression");
b99bd4ef 5997 }
b99bd4ef
NC
5998}
5999
6000/* Do those data_ops which can take a negative immediate constant
2d2255b5 6001 by altering the instruction. A bit of a hack really.
b99bd4ef
NC
6002 MOV <-> MVN
6003 AND <-> BIC
6004 ADC <-> SBC
6005 by inverting the second operand, and
6006 ADD <-> SUB
6007 CMP <-> CMN
6008 by negating the second operand. */
6009
6010static int
a737bd4d
NC
6011negate_data_op (unsigned long * instruction,
6012 unsigned long value)
b99bd4ef
NC
6013{
6014 int op, new_inst;
6015 unsigned long negated, inverted;
6016
6017 negated = validate_immediate (-value);
6018 inverted = validate_immediate (~value);
6019
6020 op = (*instruction >> DATA_OP_SHIFT) & 0xf;
6021 switch (op)
6022 {
6023 /* First negates. */
6024 case OPCODE_SUB: /* ADD <-> SUB */
6025 new_inst = OPCODE_ADD;
6026 value = negated;
6027 break;
6028
6029 case OPCODE_ADD:
6030 new_inst = OPCODE_SUB;
6031 value = negated;
6032 break;
6033
6034 case OPCODE_CMP: /* CMP <-> CMN */
6035 new_inst = OPCODE_CMN;
6036 value = negated;
6037 break;
6038
6039 case OPCODE_CMN:
6040 new_inst = OPCODE_CMP;
6041 value = negated;
6042 break;
6043
6044 /* Now Inverted ops. */
6045 case OPCODE_MOV: /* MOV <-> MVN */
6046 new_inst = OPCODE_MVN;
6047 value = inverted;
6048 break;
6049
6050 case OPCODE_MVN:
6051 new_inst = OPCODE_MOV;
6052 value = inverted;
6053 break;
6054
6055 case OPCODE_AND: /* AND <-> BIC */
6056 new_inst = OPCODE_BIC;
6057 value = inverted;
6058 break;
6059
6060 case OPCODE_BIC:
6061 new_inst = OPCODE_AND;
6062 value = inverted;
6063 break;
6064
6065 case OPCODE_ADC: /* ADC <-> SBC */
6066 new_inst = OPCODE_SBC;
6067 value = inverted;
6068 break;
6069
6070 case OPCODE_SBC:
6071 new_inst = OPCODE_ADC;
6072 value = inverted;
6073 break;
6074
6075 /* We cannot do anything. */
6076 default:
6077 return FAIL;
6078 }
6079
6080 if (value == (unsigned) FAIL)
6081 return FAIL;
6082
6083 *instruction &= OPCODE_MASK;
6084 *instruction |= new_inst << DATA_OP_SHIFT;
6085 return value;
6086}
6087
6088static int
a737bd4d 6089data_op2 (char ** str)
b99bd4ef
NC
6090{
6091 int value;
6092 expressionS expr;
6093
6094 skip_whitespace (* str);
6095
6096 if (reg_required_here (str, 0) != FAIL)
6097 {
6098 if (skip_past_comma (str) == SUCCESS)
6099 /* Shift operation on register. */
6100 return decode_shift (str, NO_SHIFT_RESTRICT);
6101
6102 return SUCCESS;
6103 }
6104 else
6105 {
6106 /* Immediate expression. */
6107 if (is_immediate_prefix (**str))
6108 {
6109 (*str)++;
6110 inst.error = NULL;
6111
6112 if (my_get_expression (&inst.reloc.exp, str))
6113 return FAIL;
6114
6115 if (inst.reloc.exp.X_add_symbol)
6116 {
6117 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
6118 inst.reloc.pc_rel = 0;
6119 }
6120 else
6121 {
6122 if (skip_past_comma (str) == SUCCESS)
6123 {
6124 /* #x, y -- ie explicit rotation by Y. */
6125 if (my_get_expression (&expr, str))
6126 return FAIL;
6127
6128 if (expr.X_op != O_constant)
6129 {
f03698e6 6130 inst.error = _("constant expression expected");
b99bd4ef
NC
6131 return FAIL;
6132 }
6133
6134 /* Rotate must be a multiple of 2. */
6135 if (((unsigned) expr.X_add_number) > 30
6136 || (expr.X_add_number & 1) != 0
6137 || ((unsigned) inst.reloc.exp.X_add_number) > 255)
6138 {
f03698e6 6139 inst.error = _("invalid constant");
b99bd4ef
NC
6140 return FAIL;
6141 }
6142 inst.instruction |= INST_IMMEDIATE;
6143 inst.instruction |= inst.reloc.exp.X_add_number;
6144 inst.instruction |= expr.X_add_number << 7;
6145 return SUCCESS;
6146 }
6147
6148 /* Implicit rotation, select a suitable one. */
6149 value = validate_immediate (inst.reloc.exp.X_add_number);
6150
6151 if (value == FAIL)
6152 {
6153 /* Can't be done. Perhaps the code reads something like
6154 "add Rd, Rn, #-n", where "sub Rd, Rn, #n" would be OK. */
6155 if ((value = negate_data_op (&inst.instruction,
6156 inst.reloc.exp.X_add_number))
6157 == FAIL)
6158 {
f03698e6 6159 inst.error = _("invalid constant");
b99bd4ef
NC
6160 return FAIL;
6161 }
6162 }
6163
6164 inst.instruction |= value;
6165 }
6166
6167 inst.instruction |= INST_IMMEDIATE;
6168 return SUCCESS;
6169 }
6170
6171 (*str)++;
f03698e6 6172 inst.error = _("register or shift expression expected");
b99bd4ef
NC
6173 return FAIL;
6174 }
6175}
6176
6177static int
a737bd4d 6178fp_op2 (char ** str)
b99bd4ef
NC
6179{
6180 skip_whitespace (* str);
6181
6182 if (fp_reg_required_here (str, 0) != FAIL)
6183 return SUCCESS;
6184 else
6185 {
6186 /* Immediate expression. */
6187 if (*((*str)++) == '#')
6188 {
6189 int i;
6190
6191 inst.error = NULL;
6192
6193 skip_whitespace (* str);
6194
6195 /* First try and match exact strings, this is to guarantee
6196 that some formats will work even for cross assembly. */
6197
6198 for (i = 0; fp_const[i]; i++)
6199 {
6200 if (strncmp (*str, fp_const[i], strlen (fp_const[i])) == 0)
6201 {
6202 char *start = *str;
6203
6204 *str += strlen (fp_const[i]);
6205 if (is_end_of_line[(unsigned char) **str])
6206 {
6207 inst.instruction |= i + 8;
6208 return SUCCESS;
6209 }
6210 *str = start;
6211 }
6212 }
6213
6214 /* Just because we didn't get a match doesn't mean that the
6215 constant isn't valid, just that it is in a format that we
6216 don't automatically recognize. Try parsing it with
6217 the standard expression routines. */
6218 if ((i = my_get_float_expression (str)) >= 0)
6219 {
6220 inst.instruction |= i + 8;
6221 return SUCCESS;
6222 }
6223
f03698e6 6224 inst.error = _("invalid floating point immediate expression");
b99bd4ef
NC
6225 return FAIL;
6226 }
6227 inst.error =
f03698e6 6228 _("floating point register or immediate expression expected");
b99bd4ef
NC
6229 return FAIL;
6230 }
6231}
6232
6233static void
a737bd4d 6234do_arit (char * str)
b99bd4ef
NC
6235{
6236 skip_whitespace (str);
6237
6238 if (reg_required_here (&str, 12) == FAIL
6239 || skip_past_comma (&str) == FAIL
6240 || reg_required_here (&str, 16) == FAIL
6241 || skip_past_comma (&str) == FAIL
6242 || data_op2 (&str) == FAIL)
6243 {
6244 if (!inst.error)
6245 inst.error = BAD_ARGS;
6246 return;
6247 }
6248
b99bd4ef 6249 end_of_line (str);
b99bd4ef
NC
6250}
6251
6252static void
a737bd4d 6253do_adr (char * str)
b99bd4ef 6254{
90e4755a
RE
6255 /* This is a pseudo-op of the form "adr rd, label" to be converted
6256 into a relative address of the form "add rd, pc, #label-.-8". */
6257 skip_whitespace (str);
6258
6259 if (reg_required_here (&str, 12) == FAIL
6260 || skip_past_comma (&str) == FAIL
6261 || my_get_expression (&inst.reloc.exp, &str))
6262 {
6263 if (!inst.error)
6264 inst.error = BAD_ARGS;
6265 return;
6266 }
6267
6268 /* Frag hacking will turn this into a sub instruction if the offset turns
6269 out to be negative. */
6270 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
250355db 6271#ifndef TE_WINCE
90e4755a 6272 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust. */
250355db 6273#endif
90e4755a
RE
6274 inst.reloc.pc_rel = 1;
6275
6276 end_of_line (str);
6277}
6278
6279static void
a737bd4d 6280do_adrl (char * str)
90e4755a
RE
6281{
6282 /* This is a pseudo-op of the form "adrl rd, label" to be converted
6283 into a relative address of the form:
6284 add rd, pc, #low(label-.-8)"
6285 add rd, rd, #high(label-.-8)" */
6286
6287 skip_whitespace (str);
6288
6289 if (reg_required_here (&str, 12) == FAIL
6290 || skip_past_comma (&str) == FAIL
6291 || my_get_expression (&inst.reloc.exp, &str))
6292 {
6293 if (!inst.error)
6294 inst.error = BAD_ARGS;
6295
6296 return;
6297 }
6298
6299 end_of_line (str);
6300 /* Frag hacking will turn this into a sub instruction if the offset turns
6301 out to be negative. */
6302 inst.reloc.type = BFD_RELOC_ARM_ADRL_IMMEDIATE;
a737bd4d 6303#ifndef TE_WINCE
90e4755a 6304 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust */
250355db 6305#endif
90e4755a
RE
6306 inst.reloc.pc_rel = 1;
6307 inst.size = INSN_SIZE * 2;
90e4755a
RE
6308}
6309
6310static void
a737bd4d 6311do_cmp (char * str)
90e4755a
RE
6312{
6313 skip_whitespace (str);
6314
6315 if (reg_required_here (&str, 16) == FAIL)
6316 {
6317 if (!inst.error)
6318 inst.error = BAD_ARGS;
6319 return;
6320 }
6321
6322 if (skip_past_comma (&str) == FAIL
6323 || data_op2 (&str) == FAIL)
6324 {
6325 if (!inst.error)
6326 inst.error = BAD_ARGS;
6327 return;
6328 }
6329
90e4755a 6330 end_of_line (str);
90e4755a
RE
6331}
6332
6333static void
a737bd4d 6334do_mov (char * str)
90e4755a
RE
6335{
6336 skip_whitespace (str);
6337
6338 if (reg_required_here (&str, 12) == FAIL)
6339 {
6340 if (!inst.error)
6341 inst.error = BAD_ARGS;
6342 return;
6343 }
6344
6345 if (skip_past_comma (&str) == FAIL
6346 || data_op2 (&str) == FAIL)
6347 {
6348 if (!inst.error)
6349 inst.error = BAD_ARGS;
6350 return;
6351 }
6352
90e4755a 6353 end_of_line (str);
90e4755a
RE
6354}
6355
90e4755a 6356static void
a737bd4d 6357do_ldst (char * str)
90e4755a
RE
6358{
6359 int pre_inc = 0;
6360 int conflict_reg;
6361 int value;
6362
b99bd4ef
NC
6363 skip_whitespace (str);
6364
90e4755a
RE
6365 if ((conflict_reg = reg_required_here (&str, 12)) == FAIL)
6366 {
6367 if (!inst.error)
6368 inst.error = BAD_ARGS;
6369 return;
6370 }
6371
6372 if (skip_past_comma (&str) == FAIL)
6373 {
f03698e6 6374 inst.error = _("address expected");
90e4755a
RE
6375 return;
6376 }
6377
90e4755a
RE
6378 if (*str == '[')
6379 {
6380 int reg;
6381
6382 str++;
6383
6384 skip_whitespace (str);
6385
6386 if ((reg = reg_required_here (&str, 16)) == FAIL)
6387 return;
6388
6389 /* Conflicts can occur on stores as well as loads. */
6390 conflict_reg = (conflict_reg == reg);
6391
6392 skip_whitespace (str);
6393
6394 if (*str == ']')
6395 {
6396 str ++;
6397
6398 if (skip_past_comma (&str) == SUCCESS)
6399 {
6400 /* [Rn],... (post inc) */
6401 if (ldst_extend (&str) == FAIL)
6402 return;
6403 if (conflict_reg)
6404 as_warn (_("%s register same as write-back base"),
6405 ((inst.instruction & LOAD_BIT)
6406 ? _("destination") : _("source")));
6407 }
6408 else
6409 {
6410 /* [Rn] */
6411 skip_whitespace (str);
6412
6413 if (*str == '!')
6414 {
6415 if (conflict_reg)
6416 as_warn (_("%s register same as write-back base"),
6417 ((inst.instruction & LOAD_BIT)
6418 ? _("destination") : _("source")));
6419 str++;
6420 inst.instruction |= WRITE_BACK;
6421 }
6422
6423 inst.instruction |= INDEX_UP;
6424 pre_inc = 1;
6425 }
6426 }
6427 else
6428 {
6429 /* [Rn,...] */
6430 if (skip_past_comma (&str) == FAIL)
6431 {
6432 inst.error = _("pre-indexed expression expected");
6433 return;
6434 }
6435
6436 pre_inc = 1;
6437 if (ldst_extend (&str) == FAIL)
6438 return;
6439
6440 skip_whitespace (str);
6441
6442 if (*str++ != ']')
6443 {
6444 inst.error = _("missing ]");
6445 return;
6446 }
6447
6448 skip_whitespace (str);
6449
6450 if (*str == '!')
6451 {
6452 if (conflict_reg)
6453 as_warn (_("%s register same as write-back base"),
6454 ((inst.instruction & LOAD_BIT)
6455 ? _("destination") : _("source")));
6456 str++;
6457 inst.instruction |= WRITE_BACK;
6458 }
6459 }
6460 }
6461 else if (*str == '=')
6462 {
f03698e6
RE
6463 if ((inst.instruction & LOAD_BIT) == 0)
6464 {
6465 inst.error = _("invalid pseudo operation");
6466 return;
6467 }
6468
90e4755a
RE
6469 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
6470 str++;
6471
6472 skip_whitespace (str);
6473
6474 if (my_get_expression (&inst.reloc.exp, &str))
6475 return;
6476
6477 if (inst.reloc.exp.X_op != O_constant
6478 && inst.reloc.exp.X_op != O_symbol)
6479 {
f03698e6 6480 inst.error = _("constant expression expected");
90e4755a
RE
6481 return;
6482 }
6483
e28cd48c 6484 if (inst.reloc.exp.X_op == O_constant)
90e4755a 6485 {
e28cd48c
RE
6486 value = validate_immediate (inst.reloc.exp.X_add_number);
6487
6488 if (value != FAIL)
90e4755a 6489 {
e28cd48c
RE
6490 /* This can be done with a mov instruction. */
6491 inst.instruction &= LITERAL_MASK;
6492 inst.instruction |= (INST_IMMEDIATE
6493 | (OPCODE_MOV << DATA_OP_SHIFT));
6494 inst.instruction |= value & 0xfff;
6495 end_of_line (str);
90e4755a
RE
6496 return;
6497 }
b99bd4ef 6498
e28cd48c
RE
6499 value = validate_immediate (~inst.reloc.exp.X_add_number);
6500
6501 if (value != FAIL)
6502 {
6503 /* This can be done with a mvn instruction. */
6504 inst.instruction &= LITERAL_MASK;
6505 inst.instruction |= (INST_IMMEDIATE
6506 | (OPCODE_MVN << DATA_OP_SHIFT));
6507 inst.instruction |= value & 0xfff;
6508 end_of_line (str);
6509 return;
6510 }
90e4755a 6511 }
e28cd48c
RE
6512
6513 /* Insert into literal pool. */
6514 if (add_to_lit_pool () == FAIL)
6515 {
6516 if (!inst.error)
6517 inst.error = _("literal pool insertion failed");
6518 return;
6519 }
6520
6521 /* Change the instruction exp to point to the pool. */
6522 inst.reloc.type = BFD_RELOC_ARM_LITERAL;
6523 inst.reloc.pc_rel = 1;
6524 inst.instruction |= (REG_PC << 16);
6525 pre_inc = 1;
1cac9012
NC
6526 }
6527 else
6528 {
90e4755a
RE
6529 if (my_get_expression (&inst.reloc.exp, &str))
6530 return;
6531
6532 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
6533#ifndef TE_WINCE
6534 /* PC rel adjust. */
6535 inst.reloc.exp.X_add_number -= 8;
6536#endif
1cac9012 6537 inst.reloc.pc_rel = 1;
90e4755a
RE
6538 inst.instruction |= (REG_PC << 16);
6539 pre_inc = 1;
b99bd4ef
NC
6540 }
6541
90e4755a 6542 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
b99bd4ef 6543 end_of_line (str);
b99bd4ef
NC
6544}
6545
6546static void
a737bd4d 6547do_ldstt (char * str)
b99bd4ef 6548{
90e4755a
RE
6549 int conflict_reg;
6550
b99bd4ef
NC
6551 skip_whitespace (str);
6552
90e4755a 6553 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
b99bd4ef
NC
6554 {
6555 if (!inst.error)
6556 inst.error = BAD_ARGS;
6557 return;
6558 }
6559
90e4755a 6560 if (skip_past_comma (& str) == FAIL)
b99bd4ef 6561 {
f03698e6 6562 inst.error = _("address expected");
b99bd4ef
NC
6563 return;
6564 }
6565
90e4755a
RE
6566 if (*str == '[')
6567 {
6568 int reg;
b99bd4ef 6569
90e4755a 6570 str++;
b99bd4ef 6571
90e4755a 6572 skip_whitespace (str);
b99bd4ef 6573
90e4755a
RE
6574 if ((reg = reg_required_here (&str, 16)) == FAIL)
6575 return;
b99bd4ef 6576
90e4755a
RE
6577 /* ldrt/strt always use post-indexed addressing, so if the base is
6578 the same as Rd, we warn. */
6579 if (conflict_reg == reg)
6580 as_warn (_("%s register same as write-back base"),
6581 ((inst.instruction & LOAD_BIT)
6582 ? _("destination") : _("source")));
6583
6584 skip_whitespace (str);
6585
6586 if (*str == ']')
6587 {
6588 str ++;
6589
6590 if (skip_past_comma (&str) == SUCCESS)
6591 {
6592 /* [Rn],... (post inc) */
6593 if (ldst_extend (&str) == FAIL)
6594 return;
6595 }
6596 else
6597 {
6598 /* [Rn] */
6599 skip_whitespace (str);
6600
6601 /* Skip a write-back '!'. */
6602 if (*str == '!')
6603 str++;
6604
6605 inst.instruction |= INDEX_UP;
6606 }
6607 }
6608 else
6609 {
6610 inst.error = _("post-indexed expression expected");
6611 return;
6612 }
6613 }
6614 else
b99bd4ef 6615 {
90e4755a 6616 inst.error = _("post-indexed expression expected");
b99bd4ef
NC
6617 return;
6618 }
6619
b99bd4ef 6620 end_of_line (str);
b99bd4ef
NC
6621}
6622
90e4755a 6623/* Halfword and signed-byte load/store operations. */
a737bd4d 6624
b99bd4ef 6625static void
a737bd4d 6626do_ldstv4 (char * str)
b99bd4ef 6627{
b99bd4ef
NC
6628 int pre_inc = 0;
6629 int conflict_reg;
6630 int value;
6631
b99bd4ef
NC
6632 skip_whitespace (str);
6633
6634 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
6635 {
6636 if (!inst.error)
6637 inst.error = BAD_ARGS;
6638 return;
6639 }
6640
6641 if (skip_past_comma (& str) == FAIL)
6642 {
f03698e6 6643 inst.error = _("address expected");
b99bd4ef
NC
6644 return;
6645 }
6646
6647 if (*str == '[')
6648 {
6649 int reg;
6650
6651 str++;
6652
6653 skip_whitespace (str);
6654
6655 if ((reg = reg_required_here (&str, 16)) == FAIL)
6656 return;
6657
6658 /* Conflicts can occur on stores as well as loads. */
6659 conflict_reg = (conflict_reg == reg);
6660
6661 skip_whitespace (str);
6662
6663 if (*str == ']')
6664 {
6665 str ++;
6666
6667 if (skip_past_comma (&str) == SUCCESS)
6668 {
6669 /* [Rn],... (post inc) */
90e4755a 6670 if (ldst_extend_v4 (&str) == FAIL)
b99bd4ef
NC
6671 return;
6672 if (conflict_reg)
90e4755a
RE
6673 as_warn (_("%s register same as write-back base"),
6674 ((inst.instruction & LOAD_BIT)
6675 ? _("destination") : _("source")));
b99bd4ef
NC
6676 }
6677 else
6678 {
6679 /* [Rn] */
90e4755a 6680 inst.instruction |= HWOFFSET_IMM;
b99bd4ef
NC
6681
6682 skip_whitespace (str);
6683
6684 if (*str == '!')
6685 {
6686 if (conflict_reg)
6687 as_warn (_("%s register same as write-back base"),
6688 ((inst.instruction & LOAD_BIT)
6689 ? _("destination") : _("source")));
6690 str++;
6691 inst.instruction |= WRITE_BACK;
6692 }
6693
90e4755a
RE
6694 inst.instruction |= INDEX_UP;
6695 pre_inc = 1;
b99bd4ef
NC
6696 }
6697 }
6698 else
6699 {
6700 /* [Rn,...] */
6701 if (skip_past_comma (&str) == FAIL)
6702 {
6703 inst.error = _("pre-indexed expression expected");
6704 return;
6705 }
6706
6707 pre_inc = 1;
90e4755a 6708 if (ldst_extend_v4 (&str) == FAIL)
b99bd4ef
NC
6709 return;
6710
6711 skip_whitespace (str);
6712
6713 if (*str++ != ']')
6714 {
6715 inst.error = _("missing ]");
6716 return;
6717 }
6718
6719 skip_whitespace (str);
6720
6721 if (*str == '!')
6722 {
6723 if (conflict_reg)
6724 as_warn (_("%s register same as write-back base"),
6725 ((inst.instruction & LOAD_BIT)
6726 ? _("destination") : _("source")));
6727 str++;
6728 inst.instruction |= WRITE_BACK;
6729 }
6730 }
6731 }
6732 else if (*str == '=')
6733 {
f03698e6
RE
6734 if ((inst.instruction & LOAD_BIT) == 0)
6735 {
6736 inst.error = _("invalid pseudo operation");
6737 return;
6738 }
6739
90e4755a 6740 /* XXX Does this work correctly for half-word/byte ops? */
b99bd4ef
NC
6741 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
6742 str++;
6743
6744 skip_whitespace (str);
6745
6746 if (my_get_expression (&inst.reloc.exp, &str))
6747 return;
6748
6749 if (inst.reloc.exp.X_op != O_constant
6750 && inst.reloc.exp.X_op != O_symbol)
6751 {
f03698e6 6752 inst.error = _("constant expression expected");
b99bd4ef
NC
6753 return;
6754 }
6755
d8273442 6756 if (inst.reloc.exp.X_op == O_constant)
b99bd4ef 6757 {
d8273442
NC
6758 value = validate_immediate (inst.reloc.exp.X_add_number);
6759
6760 if (value != FAIL)
b99bd4ef 6761 {
d8273442
NC
6762 /* This can be done with a mov instruction. */
6763 inst.instruction &= LITERAL_MASK;
6764 inst.instruction |= INST_IMMEDIATE | (OPCODE_MOV << DATA_OP_SHIFT);
90e4755a 6765 inst.instruction |= value & 0xfff;
d8273442 6766 end_of_line (str);
b99bd4ef
NC
6767 return;
6768 }
cc8a6dd0 6769
d8273442 6770 value = validate_immediate (~ inst.reloc.exp.X_add_number);
b99bd4ef 6771
d8273442 6772 if (value != FAIL)
b99bd4ef 6773 {
d8273442
NC
6774 /* This can be done with a mvn instruction. */
6775 inst.instruction &= LITERAL_MASK;
6776 inst.instruction |= INST_IMMEDIATE | (OPCODE_MVN << DATA_OP_SHIFT);
90e4755a 6777 inst.instruction |= value & 0xfff;
d8273442
NC
6778 end_of_line (str);
6779 return;
b99bd4ef 6780 }
b99bd4ef 6781 }
d8273442
NC
6782
6783 /* Insert into literal pool. */
6784 if (add_to_lit_pool () == FAIL)
6785 {
6786 if (!inst.error)
6787 inst.error = _("literal pool insertion failed");
6788 return;
6789 }
6790
6791 /* Change the instruction exp to point to the pool. */
90e4755a
RE
6792 inst.instruction |= HWOFFSET_IMM;
6793 inst.reloc.type = BFD_RELOC_ARM_HWLITERAL;
d8273442
NC
6794 inst.reloc.pc_rel = 1;
6795 inst.instruction |= (REG_PC << 16);
6796 pre_inc = 1;
b99bd4ef
NC
6797 }
6798 else
6799 {
6800 if (my_get_expression (&inst.reloc.exp, &str))
6801 return;
6802
90e4755a
RE
6803 inst.instruction |= HWOFFSET_IMM;
6804 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
b99bd4ef
NC
6805#ifndef TE_WINCE
6806 /* PC rel adjust. */
6807 inst.reloc.exp.X_add_number -= 8;
6808#endif
6809 inst.reloc.pc_rel = 1;
6810 inst.instruction |= (REG_PC << 16);
6811 pre_inc = 1;
6812 }
6813
90e4755a 6814 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
b99bd4ef 6815 end_of_line (str);
b99bd4ef
NC
6816}
6817
b05fe5cf
ZW
6818static void
6819do_ldsttv4 (char * str)
6820{
6821 int conflict_reg;
6822
6823 skip_whitespace (str);
6824
6825 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
6826 {
6827 if (!inst.error)
6828 inst.error = BAD_ARGS;
6829 return;
6830 }
6831
6832 if (skip_past_comma (& str) == FAIL)
6833 {
6834 inst.error = _("address expected");
6835 return;
6836 }
6837
6838 if (*str == '[')
6839 {
6840 int reg;
6841
6842 str++;
6843
6844 skip_whitespace (str);
6845
6846 if ((reg = reg_required_here (&str, 16)) == FAIL)
6847 return;
6848
6849 /* ldrt/strt always use post-indexed addressing, so if the base is
6850 the same as Rd, we warn. */
6851 if (conflict_reg == reg)
6852 as_warn (_("%s register same as write-back base"),
6853 ((inst.instruction & LOAD_BIT)
6854 ? _("destination") : _("source")));
6855
6856 skip_whitespace (str);
6857
6858 if (*str == ']')
6859 {
6860 str ++;
6861
6862 if (skip_past_comma (&str) == SUCCESS)
6863 {
6864 /* [Rn],... (post inc) */
6865 if (ldst_extend_v4 (&str) == FAIL)
6866 return;
6867 }
6868 else
6869 {
6870 /* [Rn] */
6871 skip_whitespace (str);
6872
6873 /* Skip a write-back '!'. */
6874 if (*str == '!')
6875 str++;
6876
6877 inst.instruction |= (INDEX_UP|HWOFFSET_IMM);
6878 }
6879 }
6880 else
6881 {
6882 inst.error = _("post-indexed expression expected");
6883 return;
6884 }
6885 }
6886 else
6887 {
6888 inst.error = _("post-indexed expression expected");
6889 return;
6890 }
6891
6892 end_of_line (str);
6893}
6894
6895
b99bd4ef 6896static long
a737bd4d 6897reg_list (char ** strp)
b99bd4ef
NC
6898{
6899 char * str = * strp;
6900 long range = 0;
6901 int another_range;
6902
6903 /* We come back here if we get ranges concatenated by '+' or '|'. */
6904 do
6905 {
6906 another_range = 0;
6907
6908 if (*str == '{')
6909 {
6910 int in_range = 0;
6911 int cur_reg = -1;
6912
6913 str++;
6914 do
6915 {
6916 int reg;
6917
6918 skip_whitespace (str);
6919
6920 if ((reg = reg_required_here (& str, -1)) == FAIL)
6921 return FAIL;
6922
6923 if (in_range)
6924 {
6925 int i;
6926
6927 if (reg <= cur_reg)
6928 {
f03698e6 6929 inst.error = _("bad range in register list");
b99bd4ef
NC
6930 return FAIL;
6931 }
6932
6933 for (i = cur_reg + 1; i < reg; i++)
6934 {
6935 if (range & (1 << i))
6936 as_tsktsk
f03698e6 6937 (_("Warning: duplicated register (r%d) in register list"),
b99bd4ef
NC
6938 i);
6939 else
6940 range |= 1 << i;
6941 }
6942 in_range = 0;
6943 }
6944
6945 if (range & (1 << reg))
f03698e6 6946 as_tsktsk (_("Warning: duplicated register (r%d) in register list"),
b99bd4ef
NC
6947 reg);
6948 else if (reg <= cur_reg)
f03698e6 6949 as_tsktsk (_("Warning: register range not in ascending order"));
b99bd4ef
NC
6950
6951 range |= 1 << reg;
6952 cur_reg = reg;
6953 }
6954 while (skip_past_comma (&str) != FAIL
6955 || (in_range = 1, *str++ == '-'));
6956 str--;
6957 skip_whitespace (str);
6958
6959 if (*str++ != '}')
6960 {
f03698e6 6961 inst.error = _("missing `}'");
b99bd4ef
NC
6962 return FAIL;
6963 }
6964 }
6965 else
6966 {
6967 expressionS expr;
6968
6969 if (my_get_expression (&expr, &str))
6970 return FAIL;
6971
6972 if (expr.X_op == O_constant)
6973 {
6974 if (expr.X_add_number
6975 != (expr.X_add_number & 0x0000ffff))
6976 {
6977 inst.error = _("invalid register mask");
6978 return FAIL;
6979 }
6980
6981 if ((range & expr.X_add_number) != 0)
6982 {
6983 int regno = range & expr.X_add_number;
6984
6985 regno &= -regno;
6986 regno = (1 << regno) - 1;
6987 as_tsktsk
f03698e6 6988 (_("Warning: duplicated register (r%d) in register list"),
b99bd4ef
NC
6989 regno);
6990 }
6991
6992 range |= expr.X_add_number;
6993 }
6994 else
6995 {
6996 if (inst.reloc.type != 0)
6997 {
6998 inst.error = _("expression too complex");
6999 return FAIL;
7000 }
7001
7002 memcpy (&inst.reloc.exp, &expr, sizeof (expressionS));
7003 inst.reloc.type = BFD_RELOC_ARM_MULTI;
7004 inst.reloc.pc_rel = 0;
7005 }
7006 }
7007
7008 skip_whitespace (str);
7009
7010 if (*str == '|' || *str == '+')
7011 {
7012 str++;
7013 another_range = 1;
7014 }
7015 }
7016 while (another_range);
7017
7018 *strp = str;
7019 return range;
7020}
7021
7022static void
a737bd4d 7023do_ldmstm (char * str)
b99bd4ef
NC
7024{
7025 int base_reg;
7026 long range;
7027
7028 skip_whitespace (str);
7029
7030 if ((base_reg = reg_required_here (&str, 16)) == FAIL)
7031 return;
7032
7033 if (base_reg == REG_PC)
7034 {
7035 inst.error = _("r15 not allowed as base register");
7036 return;
7037 }
7038
7039 skip_whitespace (str);
7040
7041 if (*str == '!')
7042 {
90e4755a 7043 inst.instruction |= WRITE_BACK;
b99bd4ef
NC
7044 str++;
7045 }
7046
7047 if (skip_past_comma (&str) == FAIL
7048 || (range = reg_list (&str)) == FAIL)
7049 {
7050 if (! inst.error)
7051 inst.error = BAD_ARGS;
7052 return;
7053 }
7054
7055 if (*str == '^')
7056 {
7057 str++;
90e4755a 7058 inst.instruction |= LDM_TYPE_2_OR_3;
b99bd4ef
NC
7059 }
7060
6189168b
NC
7061 if (inst.instruction & WRITE_BACK)
7062 {
7063 /* Check for unpredictable uses of writeback. */
7064 if (inst.instruction & LOAD_BIT)
7065 {
7066 /* Not allowed in LDM type 2. */
7067 if ((inst.instruction & LDM_TYPE_2_OR_3)
7068 && ((range & (1 << REG_PC)) == 0))
7069 as_warn (_("writeback of base register is UNPREDICTABLE"));
7070 /* Only allowed if base reg not in list for other types. */
7071 else if (range & (1 << base_reg))
7072 as_warn (_("writeback of base register when in register list is UNPREDICTABLE"));
7073 }
7074 else /* STM. */
7075 {
7076 /* Not allowed for type 2. */
7077 if (inst.instruction & LDM_TYPE_2_OR_3)
7078 as_warn (_("writeback of base register is UNPREDICTABLE"));
7079 /* Only allowed if base reg not in list, or first in list. */
7080 else if ((range & (1 << base_reg))
7081 && (range & ((1 << base_reg) - 1)))
7082 as_warn (_("if writeback register is in list, it must be the lowest reg in the list"));
7083 }
7084 }
61b5f74b 7085
f2b7cb0a 7086 inst.instruction |= range;
b99bd4ef 7087 end_of_line (str);
b99bd4ef
NC
7088}
7089
0dd132b6
NC
7090static void
7091do_smi (char * str)
7092{
7093 skip_whitespace (str);
7094
7095 /* Allow optional leading '#'. */
7096 if (is_immediate_prefix (*str))
7097 str++;
7098
7099 if (my_get_expression (& inst.reloc.exp, & str))
7100 return;
7101
7102 inst.reloc.type = BFD_RELOC_ARM_SMI;
7103 inst.reloc.pc_rel = 0;
7104 end_of_line (str);
7105}
7106
b99bd4ef 7107static void
a737bd4d 7108do_swi (char * str)
b99bd4ef
NC
7109{
7110 skip_whitespace (str);
7111
7112 /* Allow optional leading '#'. */
7113 if (is_immediate_prefix (*str))
7114 str++;
7115
7116 if (my_get_expression (& inst.reloc.exp, & str))
7117 return;
7118
7119 inst.reloc.type = BFD_RELOC_ARM_SWI;
7120 inst.reloc.pc_rel = 0;
b99bd4ef 7121 end_of_line (str);
b99bd4ef
NC
7122}
7123
7124static void
a737bd4d 7125do_swap (char * str)
b99bd4ef
NC
7126{
7127 int reg;
7128
7129 skip_whitespace (str);
7130
7131 if ((reg = reg_required_here (&str, 12)) == FAIL)
7132 return;
7133
7134 if (reg == REG_PC)
7135 {
7136 inst.error = _("r15 not allowed in swap");
7137 return;
7138 }
7139
7140 if (skip_past_comma (&str) == FAIL
7141 || (reg = reg_required_here (&str, 0)) == FAIL)
7142 {
7143 if (!inst.error)
7144 inst.error = BAD_ARGS;
7145 return;
7146 }
7147
7148 if (reg == REG_PC)
7149 {
7150 inst.error = _("r15 not allowed in swap");
7151 return;
7152 }
7153
7154 if (skip_past_comma (&str) == FAIL
7155 || *str++ != '[')
7156 {
7157 inst.error = BAD_ARGS;
7158 return;
7159 }
7160
7161 skip_whitespace (str);
7162
7163 if ((reg = reg_required_here (&str, 16)) == FAIL)
7164 return;
7165
7166 if (reg == REG_PC)
7167 {
7168 inst.error = BAD_PC;
7169 return;
7170 }
7171
7172 skip_whitespace (str);
7173
7174 if (*str++ != ']')
7175 {
7176 inst.error = _("missing ]");
7177 return;
7178 }
7179
b99bd4ef 7180 end_of_line (str);
b99bd4ef
NC
7181}
7182
7183static void
a737bd4d 7184do_branch (char * str)
b99bd4ef
NC
7185{
7186 if (my_get_expression (&inst.reloc.exp, &str))
7187 return;
7188
7189#ifdef OBJ_ELF
7190 {
7191 char * save_in;
7192
7193 /* ScottB: February 5, 1998 - Check to see of PLT32 reloc
7194 required for the instruction. */
7195
7196 /* arm_parse_reloc () works on input_line_pointer.
7197 We actually want to parse the operands to the branch instruction
7198 passed in 'str'. Save the input pointer and restore it later. */
7199 save_in = input_line_pointer;
7200 input_line_pointer = str;
7201 if (inst.reloc.exp.X_op == O_symbol
7202 && *str == '('
7203 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
7204 {
7205 inst.reloc.type = BFD_RELOC_ARM_PLT32;
7206 inst.reloc.pc_rel = 0;
7207 /* Modify str to point to after parsed operands, otherwise
7208 end_of_line() will complain about the (PLT) left in str. */
7209 str = input_line_pointer;
7210 }
7211 else
7212 {
7213 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
7214 inst.reloc.pc_rel = 1;
7215 }
7216 input_line_pointer = save_in;
7217 }
7218#else
7219 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
7220 inst.reloc.pc_rel = 1;
7221#endif /* OBJ_ELF */
7222
7223 end_of_line (str);
b99bd4ef
NC
7224}
7225
7226static void
a737bd4d 7227do_cdp (char * str)
b99bd4ef
NC
7228{
7229 /* Co-processor data operation.
7230 Format: CDP{cond} CP#,<expr>,CRd,CRn,CRm{,<expr>} */
7231 skip_whitespace (str);
7232
7233 if (co_proc_number (&str) == FAIL)
7234 {
7235 if (!inst.error)
7236 inst.error = BAD_ARGS;
7237 return;
7238 }
7239
7240 if (skip_past_comma (&str) == FAIL
7241 || cp_opc_expr (&str, 20,4) == FAIL)
7242 {
7243 if (!inst.error)
7244 inst.error = BAD_ARGS;
7245 return;
7246 }
7247
7248 if (skip_past_comma (&str) == FAIL
7249 || cp_reg_required_here (&str, 12) == FAIL)
7250 {
7251 if (!inst.error)
7252 inst.error = BAD_ARGS;
7253 return;
7254 }
7255
7256 if (skip_past_comma (&str) == FAIL
7257 || cp_reg_required_here (&str, 16) == FAIL)
7258 {
7259 if (!inst.error)
7260 inst.error = BAD_ARGS;
7261 return;
7262 }
7263
7264 if (skip_past_comma (&str) == FAIL
7265 || cp_reg_required_here (&str, 0) == FAIL)
7266 {
7267 if (!inst.error)
7268 inst.error = BAD_ARGS;
7269 return;
7270 }
7271
7272 if (skip_past_comma (&str) == SUCCESS)
7273 {
7274 if (cp_opc_expr (&str, 5, 3) == FAIL)
7275 {
7276 if (!inst.error)
7277 inst.error = BAD_ARGS;
7278 return;
7279 }
7280 }
7281
7282 end_of_line (str);
b99bd4ef
NC
7283}
7284
7285static void
a737bd4d 7286do_lstc (char * str)
b99bd4ef
NC
7287{
7288 /* Co-processor register load/store.
7289 Format: <LDC|STC{cond}[L] CP#,CRd,<address> */
7290
7291 skip_whitespace (str);
7292
7293 if (co_proc_number (&str) == FAIL)
7294 {
7295 if (!inst.error)
7296 inst.error = BAD_ARGS;
7297 return;
7298 }
7299
7300 if (skip_past_comma (&str) == FAIL
7301 || cp_reg_required_here (&str, 12) == FAIL)
7302 {
7303 if (!inst.error)
7304 inst.error = BAD_ARGS;
7305 return;
7306 }
7307
7308 if (skip_past_comma (&str) == FAIL
bfae80f2 7309 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
b99bd4ef
NC
7310 {
7311 if (! inst.error)
7312 inst.error = BAD_ARGS;
7313 return;
7314 }
7315
b99bd4ef 7316 end_of_line (str);
b99bd4ef
NC
7317}
7318
7319static void
a737bd4d 7320do_co_reg (char * str)
b99bd4ef
NC
7321{
7322 /* Co-processor register transfer.
7323 Format: <MCR|MRC>{cond} CP#,<expr1>,Rd,CRn,CRm{,<expr2>} */
7324
7325 skip_whitespace (str);
7326
7327 if (co_proc_number (&str) == FAIL)
7328 {
7329 if (!inst.error)
7330 inst.error = BAD_ARGS;
7331 return;
7332 }
7333
7334 if (skip_past_comma (&str) == FAIL
7335 || cp_opc_expr (&str, 21, 3) == FAIL)
7336 {
7337 if (!inst.error)
7338 inst.error = BAD_ARGS;
7339 return;
7340 }
7341
7342 if (skip_past_comma (&str) == FAIL
7343 || reg_required_here (&str, 12) == FAIL)
7344 {
7345 if (!inst.error)
7346 inst.error = BAD_ARGS;
7347 return;
7348 }
7349
7350 if (skip_past_comma (&str) == FAIL
7351 || cp_reg_required_here (&str, 16) == FAIL)
7352 {
7353 if (!inst.error)
7354 inst.error = BAD_ARGS;
7355 return;
7356 }
7357
7358 if (skip_past_comma (&str) == FAIL
7359 || cp_reg_required_here (&str, 0) == FAIL)
7360 {
7361 if (!inst.error)
7362 inst.error = BAD_ARGS;
7363 return;
7364 }
7365
7366 if (skip_past_comma (&str) == SUCCESS)
7367 {
7368 if (cp_opc_expr (&str, 5, 3) == FAIL)
7369 {
7370 if (!inst.error)
7371 inst.error = BAD_ARGS;
7372 return;
7373 }
7374 }
b99bd4ef
NC
7375
7376 end_of_line (str);
b99bd4ef
NC
7377}
7378
7379static void
a737bd4d 7380do_fpa_ctrl (char * str)
b99bd4ef
NC
7381{
7382 /* FP control registers.
7383 Format: <WFS|RFS|WFC|RFC>{cond} Rn */
7384
7385 skip_whitespace (str);
7386
7387 if (reg_required_here (&str, 12) == FAIL)
7388 {
7389 if (!inst.error)
7390 inst.error = BAD_ARGS;
7391 return;
7392 }
7393
7394 end_of_line (str);
b99bd4ef
NC
7395}
7396
7397static void
a737bd4d 7398do_fpa_ldst (char * str)
b99bd4ef
NC
7399{
7400 skip_whitespace (str);
7401
b99bd4ef
NC
7402 if (fp_reg_required_here (&str, 12) == FAIL)
7403 {
7404 if (!inst.error)
7405 inst.error = BAD_ARGS;
7406 return;
7407 }
7408
7409 if (skip_past_comma (&str) == FAIL
bfae80f2 7410 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
b99bd4ef
NC
7411 {
7412 if (!inst.error)
7413 inst.error = BAD_ARGS;
7414 return;
7415 }
7416
7417 end_of_line (str);
7418}
7419
7420static void
a737bd4d 7421do_fpa_ldmstm (char * str)
b99bd4ef
NC
7422{
7423 int num_regs;
7424
7425 skip_whitespace (str);
7426
7427 if (fp_reg_required_here (&str, 12) == FAIL)
7428 {
7429 if (! inst.error)
7430 inst.error = BAD_ARGS;
7431 return;
7432 }
7433
7434 /* Get Number of registers to transfer. */
7435 if (skip_past_comma (&str) == FAIL
7436 || my_get_expression (&inst.reloc.exp, &str))
7437 {
7438 if (! inst.error)
7439 inst.error = _("constant expression expected");
7440 return;
7441 }
7442
7443 if (inst.reloc.exp.X_op != O_constant)
7444 {
f03698e6 7445 inst.error = _("constant value required for number of registers");
b99bd4ef
NC
7446 return;
7447 }
7448
7449 num_regs = inst.reloc.exp.X_add_number;
7450
7451 if (num_regs < 1 || num_regs > 4)
7452 {
7453 inst.error = _("number of registers must be in the range [1:4]");
7454 return;
7455 }
7456
7457 switch (num_regs)
7458 {
7459 case 1:
7460 inst.instruction |= CP_T_X;
7461 break;
7462 case 2:
7463 inst.instruction |= CP_T_Y;
7464 break;
7465 case 3:
7466 inst.instruction |= CP_T_Y | CP_T_X;
7467 break;
7468 case 4:
7469 break;
7470 default:
7471 abort ();
7472 }
7473
e28cd48c 7474 if (inst.instruction & (CP_T_Pre | CP_T_UD)) /* ea/fd format. */
b99bd4ef
NC
7475 {
7476 int reg;
7477 int write_back;
7478 int offset;
7479
7480 /* The instruction specified "ea" or "fd", so we can only accept
7481 [Rn]{!}. The instruction does not really support stacking or
7482 unstacking, so we have to emulate these by setting appropriate
7483 bits and offsets. */
7484 if (skip_past_comma (&str) == FAIL
7485 || *str != '[')
7486 {
7487 if (! inst.error)
7488 inst.error = BAD_ARGS;
7489 return;
7490 }
7491
7492 str++;
7493 skip_whitespace (str);
7494
7495 if ((reg = reg_required_here (&str, 16)) == FAIL)
7496 return;
7497
7498 skip_whitespace (str);
7499
7500 if (*str != ']')
7501 {
7502 inst.error = BAD_ARGS;
7503 return;
7504 }
7505
7506 str++;
7507 if (*str == '!')
7508 {
7509 write_back = 1;
7510 str++;
7511 if (reg == REG_PC)
7512 {
7513 inst.error =
f03698e6 7514 _("r15 not allowed as base register with write-back");
b99bd4ef
NC
7515 return;
7516 }
7517 }
7518 else
7519 write_back = 0;
7520
90e4755a 7521 if (inst.instruction & CP_T_Pre)
b99bd4ef
NC
7522 {
7523 /* Pre-decrement. */
7524 offset = 3 * num_regs;
7525 if (write_back)
90e4755a 7526 inst.instruction |= CP_T_WB;
b99bd4ef
NC
7527 }
7528 else
7529 {
7530 /* Post-increment. */
7531 if (write_back)
7532 {
90e4755a 7533 inst.instruction |= CP_T_WB;
b99bd4ef
NC
7534 offset = 3 * num_regs;
7535 }
7536 else
7537 {
7538 /* No write-back, so convert this into a standard pre-increment
7539 instruction -- aesthetically more pleasing. */
90e4755a 7540 inst.instruction |= CP_T_Pre | CP_T_UD;
b99bd4ef
NC
7541 offset = 0;
7542 }
7543 }
7544
f2b7cb0a 7545 inst.instruction |= offset;
b99bd4ef
NC
7546 }
7547 else if (skip_past_comma (&str) == FAIL
bfae80f2 7548 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
b99bd4ef
NC
7549 {
7550 if (! inst.error)
7551 inst.error = BAD_ARGS;
7552 return;
7553 }
7554
7555 end_of_line (str);
7556}
7557
7558static void
a737bd4d 7559do_fpa_dyadic (char * str)
b99bd4ef
NC
7560{
7561 skip_whitespace (str);
7562
b99bd4ef
NC
7563 if (fp_reg_required_here (&str, 12) == FAIL)
7564 {
7565 if (! inst.error)
7566 inst.error = BAD_ARGS;
7567 return;
7568 }
7569
7570 if (skip_past_comma (&str) == FAIL
7571 || fp_reg_required_here (&str, 16) == FAIL)
7572 {
7573 if (! inst.error)
7574 inst.error = BAD_ARGS;
7575 return;
7576 }
7577
7578 if (skip_past_comma (&str) == FAIL
7579 || fp_op2 (&str) == FAIL)
7580 {
7581 if (! inst.error)
7582 inst.error = BAD_ARGS;
7583 return;
7584 }
7585
b99bd4ef 7586 end_of_line (str);
b99bd4ef
NC
7587}
7588
7589static void
a737bd4d 7590do_fpa_monadic (char * str)
b99bd4ef
NC
7591{
7592 skip_whitespace (str);
7593
b99bd4ef
NC
7594 if (fp_reg_required_here (&str, 12) == FAIL)
7595 {
7596 if (! inst.error)
7597 inst.error = BAD_ARGS;
7598 return;
7599 }
7600
7601 if (skip_past_comma (&str) == FAIL
7602 || fp_op2 (&str) == FAIL)
7603 {
7604 if (! inst.error)
7605 inst.error = BAD_ARGS;
7606 return;
7607 }
7608
b99bd4ef 7609 end_of_line (str);
b99bd4ef
NC
7610}
7611
7612static void
a737bd4d 7613do_fpa_cmp (char * str)
b99bd4ef
NC
7614{
7615 skip_whitespace (str);
7616
7617 if (fp_reg_required_here (&str, 16) == FAIL)
7618 {
7619 if (! inst.error)
7620 inst.error = BAD_ARGS;
7621 return;
7622 }
7623
7624 if (skip_past_comma (&str) == FAIL
7625 || fp_op2 (&str) == FAIL)
7626 {
7627 if (! inst.error)
7628 inst.error = BAD_ARGS;
7629 return;
7630 }
7631
b99bd4ef 7632 end_of_line (str);
b99bd4ef
NC
7633}
7634
7635static void
a737bd4d 7636do_fpa_from_reg (char * str)
b99bd4ef
NC
7637{
7638 skip_whitespace (str);
7639
b99bd4ef
NC
7640 if (fp_reg_required_here (&str, 16) == FAIL)
7641 {
7642 if (! inst.error)
7643 inst.error = BAD_ARGS;
7644 return;
7645 }
7646
7647 if (skip_past_comma (&str) == FAIL
7648 || reg_required_here (&str, 12) == FAIL)
7649 {
7650 if (! inst.error)
7651 inst.error = BAD_ARGS;
7652 return;
7653 }
7654
b99bd4ef 7655 end_of_line (str);
b99bd4ef
NC
7656}
7657
7658static void
a737bd4d 7659do_fpa_to_reg (char * str)
b99bd4ef
NC
7660{
7661 skip_whitespace (str);
7662
7663 if (reg_required_here (&str, 12) == FAIL)
7664 return;
7665
7666 if (skip_past_comma (&str) == FAIL
7667 || fp_reg_required_here (&str, 0) == FAIL)
7668 {
7669 if (! inst.error)
7670 inst.error = BAD_ARGS;
7671 return;
7672 }
7673
b99bd4ef 7674 end_of_line (str);
b99bd4ef
NC
7675}
7676
7ed4c4c5
NC
7677/* Encode a VFP SP register number. */
7678
7679static void
7680vfp_sp_encode_reg (int reg, enum vfp_sp_reg_pos pos)
7681{
7682 switch (pos)
7683 {
7684 case VFP_REG_Sd:
7685 inst.instruction |= ((reg >> 1) << 12) | ((reg & 1) << 22);
7686 break;
7687
7688 case VFP_REG_Sn:
7689 inst.instruction |= ((reg >> 1) << 16) | ((reg & 1) << 7);
7690 break;
7691
7692 case VFP_REG_Sm:
7693 inst.instruction |= ((reg >> 1) << 0) | ((reg & 1) << 5);
7694 break;
7695
7696 default:
7697 abort ();
7698 }
7699}
7700
b99bd4ef 7701static int
a737bd4d
NC
7702vfp_sp_reg_required_here (char ** str,
7703 enum vfp_sp_reg_pos pos)
b99bd4ef 7704{
bfae80f2 7705 int reg;
7ed4c4c5 7706 char * start = *str;
b99bd4ef 7707
bfae80f2 7708 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_SN].htab)) != FAIL)
b99bd4ef 7709 {
7ed4c4c5 7710 vfp_sp_encode_reg (reg, pos);
bfae80f2
RE
7711 return reg;
7712 }
b99bd4ef 7713
bfae80f2
RE
7714 /* In the few cases where we might be able to accept something else
7715 this error can be overridden. */
7716 inst.error = _(all_reg_maps[REG_TYPE_SN].expected);
7717
7718 /* Restore the start point. */
7719 *str = start;
7720 return FAIL;
7721}
7722
7723static int
a737bd4d
NC
7724vfp_dp_reg_required_here (char ** str,
7725 enum vfp_dp_reg_pos pos)
bfae80f2 7726{
a737bd4d
NC
7727 int reg;
7728 char * start = *str;
bfae80f2
RE
7729
7730 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_DN].htab)) != FAIL)
7731 {
7732 switch (pos)
b99bd4ef 7733 {
bfae80f2
RE
7734 case VFP_REG_Dd:
7735 inst.instruction |= reg << 12;
7736 break;
b99bd4ef 7737
bfae80f2
RE
7738 case VFP_REG_Dn:
7739 inst.instruction |= reg << 16;
7740 break;
7741
7742 case VFP_REG_Dm:
7743 inst.instruction |= reg << 0;
7744 break;
7745
7746 default:
7747 abort ();
7748 }
7749 return reg;
b99bd4ef
NC
7750 }
7751
bfae80f2
RE
7752 /* In the few cases where we might be able to accept something else
7753 this error can be overridden. */
7754 inst.error = _(all_reg_maps[REG_TYPE_DN].expected);
b99bd4ef 7755
bfae80f2
RE
7756 /* Restore the start point. */
7757 *str = start;
7758 return FAIL;
7759}
b99bd4ef
NC
7760
7761static void
a737bd4d 7762do_vfp_sp_monadic (char * str)
b99bd4ef 7763{
b99bd4ef
NC
7764 skip_whitespace (str);
7765
bfae80f2
RE
7766 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
7767 return;
7768
7769 if (skip_past_comma (&str) == FAIL
7770 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
b99bd4ef
NC
7771 {
7772 if (! inst.error)
7773 inst.error = BAD_ARGS;
7774 return;
7775 }
7776
bfae80f2 7777 end_of_line (str);
bfae80f2
RE
7778}
7779
7780static void
a737bd4d 7781do_vfp_dp_monadic (char * str)
bfae80f2
RE
7782{
7783 skip_whitespace (str);
7784
7785 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
7786 return;
7787
7788 if (skip_past_comma (&str) == FAIL
7789 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
b99bd4ef 7790 {
bfae80f2
RE
7791 if (! inst.error)
7792 inst.error = BAD_ARGS;
7793 return;
b99bd4ef 7794 }
b99bd4ef 7795
bfae80f2 7796 end_of_line (str);
bfae80f2 7797}
b99bd4ef 7798
bfae80f2 7799static void
a737bd4d 7800do_vfp_sp_dyadic (char * str)
bfae80f2
RE
7801{
7802 skip_whitespace (str);
b99bd4ef 7803
bfae80f2
RE
7804 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
7805 return;
b99bd4ef 7806
bfae80f2
RE
7807 if (skip_past_comma (&str) == FAIL
7808 || vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL
7809 || skip_past_comma (&str) == FAIL
7810 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
b99bd4ef 7811 {
bfae80f2
RE
7812 if (! inst.error)
7813 inst.error = BAD_ARGS;
7814 return;
7815 }
b99bd4ef 7816
bfae80f2 7817 end_of_line (str);
bfae80f2 7818}
b99bd4ef 7819
bfae80f2 7820static void
a737bd4d 7821do_vfp_dp_dyadic (char * str)
bfae80f2
RE
7822{
7823 skip_whitespace (str);
b99bd4ef 7824
bfae80f2
RE
7825 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
7826 return;
b99bd4ef 7827
bfae80f2
RE
7828 if (skip_past_comma (&str) == FAIL
7829 || vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL
7830 || skip_past_comma (&str) == FAIL
7831 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
7832 {
7833 if (! inst.error)
7834 inst.error = BAD_ARGS;
7835 return;
7836 }
b99bd4ef 7837
bfae80f2 7838 end_of_line (str);
bfae80f2 7839}
b99bd4ef 7840
bfae80f2 7841static void
a737bd4d 7842do_vfp_reg_from_sp (char * str)
bfae80f2
RE
7843{
7844 skip_whitespace (str);
7845
7846 if (reg_required_here (&str, 12) == FAIL)
7847 return;
7848
7849 if (skip_past_comma (&str) == FAIL
7850 || vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL)
7851 {
7852 if (! inst.error)
7853 inst.error = BAD_ARGS;
7854 return;
7855 }
7856
7857 end_of_line (str);
bfae80f2
RE
7858}
7859
7ed4c4c5
NC
7860/* Parse a VFP register list. If the string is invalid return FAIL.
7861 Otherwise return the number of registers, and set PBASE to the first
7862 register. Double precision registers are matched if DP is nonzero. */
a737bd4d 7863
7ed4c4c5
NC
7864static int
7865vfp_parse_reg_list (char **str, int *pbase, int dp)
a737bd4d 7866{
7ed4c4c5 7867 int base_reg;
a737bd4d 7868 int new_base;
7ed4c4c5
NC
7869 int regtype;
7870 int max_regs;
a737bd4d 7871 int count = 0;
a737bd4d 7872 int warned = 0;
7ed4c4c5
NC
7873 unsigned long mask = 0;
7874 int i;
a737bd4d
NC
7875
7876 if (**str != '{')
7877 return FAIL;
7878
7879 (*str)++;
7880 skip_whitespace (*str);
7881
7ed4c4c5 7882 if (dp)
a737bd4d 7883 {
7ed4c4c5
NC
7884 regtype = REG_TYPE_DN;
7885 max_regs = 16;
7886 }
7887 else
7888 {
7889 regtype = REG_TYPE_SN;
7890 max_regs = 32;
7891 }
a737bd4d 7892
7ed4c4c5 7893 base_reg = max_regs;
a737bd4d 7894
7ed4c4c5
NC
7895 do
7896 {
7897 new_base = arm_reg_parse (str, all_reg_maps[regtype].htab);
7898 if (new_base == FAIL)
a737bd4d 7899 {
7ed4c4c5
NC
7900 inst.error = _(all_reg_maps[regtype].expected);
7901 return FAIL;
a737bd4d
NC
7902 }
7903
7ed4c4c5
NC
7904 if (new_base < base_reg)
7905 base_reg = new_base;
7906
a737bd4d
NC
7907 if (mask & (1 << new_base))
7908 {
7909 inst.error = _("invalid register list");
7910 return FAIL;
7911 }
7912
7913 if ((mask >> new_base) != 0 && ! warned)
7914 {
7915 as_tsktsk (_("register list not in ascending order"));
7916 warned = 1;
7917 }
7918
7919 mask |= 1 << new_base;
7920 count++;
7921
7922 skip_whitespace (*str);
7923
7924 if (**str == '-') /* We have the start of a range expression */
7925 {
7926 int high_range;
7927
7928 (*str)++;
7929
7930 if ((high_range
7ed4c4c5 7931 = arm_reg_parse (str, all_reg_maps[regtype].htab))
a737bd4d
NC
7932 == FAIL)
7933 {
7ed4c4c5 7934 inst.error = _(all_reg_maps[regtype].expected);
a737bd4d
NC
7935 return FAIL;
7936 }
7937
7938 if (high_range <= new_base)
7939 {
7940 inst.error = _("register range not in ascending order");
7941 return FAIL;
7942 }
7943
7944 for (new_base++; new_base <= high_range; new_base++)
7945 {
7946 if (mask & (1 << new_base))
7947 {
7948 inst.error = _("invalid register list");
7949 return FAIL;
7950 }
7951
7952 mask |= 1 << new_base;
7953 count++;
7954 }
7955 }
7956 }
7957 while (skip_past_comma (str) != FAIL);
7958
a737bd4d
NC
7959 (*str)++;
7960
a737bd4d 7961 /* Sanity check -- should have raised a parse error above. */
7ed4c4c5 7962 if (count == 0 || count > max_regs)
a737bd4d
NC
7963 abort ();
7964
7ed4c4c5
NC
7965 *pbase = base_reg;
7966
a737bd4d 7967 /* Final test -- the registers must be consecutive. */
7ed4c4c5
NC
7968 mask >>= base_reg;
7969 for (i = 0; i < count; i++)
a737bd4d 7970 {
7ed4c4c5 7971 if ((mask & (1u << i)) == 0)
a737bd4d
NC
7972 {
7973 inst.error = _("non-contiguous register range");
7974 return FAIL;
7975 }
7976 }
7977
7ed4c4c5 7978 return count;
a737bd4d
NC
7979}
7980
bfae80f2 7981static void
a737bd4d 7982do_vfp_reg2_from_sp2 (char * str)
bfae80f2 7983{
7ed4c4c5
NC
7984 int reg;
7985
bfae80f2
RE
7986 skip_whitespace (str);
7987
e45d0630
PB
7988 if (reg_required_here (&str, 12) == FAIL
7989 || skip_past_comma (&str) == FAIL
bfae80f2
RE
7990 || reg_required_here (&str, 16) == FAIL
7991 || skip_past_comma (&str) == FAIL)
7992 {
7993 if (! inst.error)
7994 inst.error = BAD_ARGS;
7995 return;
7996 }
7997
7998 /* We require exactly two consecutive SP registers. */
7ed4c4c5 7999 if (vfp_parse_reg_list (&str, &reg, 0) != 2)
bfae80f2
RE
8000 {
8001 if (! inst.error)
8002 inst.error = _("only two consecutive VFP SP registers allowed here");
8003 }
7ed4c4c5 8004 vfp_sp_encode_reg (reg, VFP_REG_Sm);
bfae80f2
RE
8005
8006 end_of_line (str);
bfae80f2
RE
8007}
8008
8009static void
a737bd4d 8010do_vfp_sp_from_reg (char * str)
bfae80f2
RE
8011{
8012 skip_whitespace (str);
8013
8014 if (vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL)
8015 return;
8016
8017 if (skip_past_comma (&str) == FAIL
8018 || reg_required_here (&str, 12) == FAIL)
8019 {
8020 if (! inst.error)
8021 inst.error = BAD_ARGS;
8022 return;
8023 }
8024
8025 end_of_line (str);
bfae80f2
RE
8026}
8027
e45d0630 8028static void
a737bd4d 8029do_vfp_sp2_from_reg2 (char * str)
e45d0630 8030{
7ed4c4c5
NC
8031 int reg;
8032
e45d0630
PB
8033 skip_whitespace (str);
8034
8035 /* We require exactly two consecutive SP registers. */
7ed4c4c5 8036 if (vfp_parse_reg_list (&str, &reg, 0) != 2)
e45d0630
PB
8037 {
8038 if (! inst.error)
8039 inst.error = _("only two consecutive VFP SP registers allowed here");
8040 }
7ed4c4c5 8041 vfp_sp_encode_reg (reg, VFP_REG_Sm);
e45d0630
PB
8042
8043 if (skip_past_comma (&str) == FAIL
8044 || reg_required_here (&str, 12) == FAIL
8045 || skip_past_comma (&str) == FAIL
8046 || reg_required_here (&str, 16) == FAIL)
8047 {
8048 if (! inst.error)
8049 inst.error = BAD_ARGS;
8050 return;
8051 }
8052
8053 end_of_line (str);
8054}
8055
bfae80f2 8056static void
a737bd4d 8057do_vfp_reg_from_dp (char * str)
bfae80f2
RE
8058{
8059 skip_whitespace (str);
8060
8061 if (reg_required_here (&str, 12) == FAIL)
8062 return;
8063
8064 if (skip_past_comma (&str) == FAIL
8065 || vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL)
8066 {
8067 if (! inst.error)
8068 inst.error = BAD_ARGS;
8069 return;
8070 }
8071
8072 end_of_line (str);
bfae80f2
RE
8073}
8074
8075static void
a737bd4d 8076do_vfp_reg2_from_dp (char * str)
bfae80f2
RE
8077{
8078 skip_whitespace (str);
8079
8080 if (reg_required_here (&str, 12) == FAIL)
8081 return;
8082
8083 if (skip_past_comma (&str) == FAIL
8084 || reg_required_here (&str, 16) == FAIL
8085 || skip_past_comma (&str) == FAIL
8086 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
8087 {
8088 if (! inst.error)
8089 inst.error = BAD_ARGS;
8090 return;
8091 }
8092
8093 end_of_line (str);
bfae80f2
RE
8094}
8095
8096static void
a737bd4d 8097do_vfp_dp_from_reg (char * str)
bfae80f2
RE
8098{
8099 skip_whitespace (str);
8100
8101 if (vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL)
8102 return;
8103
8104 if (skip_past_comma (&str) == FAIL
8105 || reg_required_here (&str, 12) == FAIL)
8106 {
8107 if (! inst.error)
8108 inst.error = BAD_ARGS;
8109 return;
8110 }
8111
8112 end_of_line (str);
bfae80f2
RE
8113}
8114
8115static void
a737bd4d 8116do_vfp_dp_from_reg2 (char * str)
bfae80f2
RE
8117{
8118 skip_whitespace (str);
8119
8120 if (vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
8121 return;
8122
8123 if (skip_past_comma (&str) == FAIL
8124 || reg_required_here (&str, 12) == FAIL
8125 || skip_past_comma (&str) == FAIL
e45d0630 8126 || reg_required_here (&str, 16) == FAIL)
bfae80f2
RE
8127 {
8128 if (! inst.error)
8129 inst.error = BAD_ARGS;
8130 return;
8131 }
8132
8133 end_of_line (str);
bfae80f2
RE
8134}
8135
8136static const struct vfp_reg *
a737bd4d 8137vfp_psr_parse (char ** str)
bfae80f2
RE
8138{
8139 char *start = *str;
8140 char c;
8141 char *p;
8142 const struct vfp_reg *vreg;
8143
8144 p = start;
8145
8146 /* Find the end of the current token. */
8147 do
8148 {
8149 c = *p++;
8150 }
8151 while (ISALPHA (c));
8152
8153 /* Mark it. */
8154 *--p = 0;
8155
cc8a6dd0 8156 for (vreg = vfp_regs + 0;
bfae80f2
RE
8157 vreg < vfp_regs + sizeof (vfp_regs) / sizeof (struct vfp_reg);
8158 vreg++)
8159 {
a737bd4d 8160 if (streq (start, vreg->name))
bfae80f2
RE
8161 {
8162 *p = c;
8163 *str = p;
8164 return vreg;
8165 }
8166 }
8167
8168 *p = c;
8169 return NULL;
8170}
8171
8172static int
a737bd4d 8173vfp_psr_required_here (char ** str)
bfae80f2
RE
8174{
8175 char *start = *str;
8176 const struct vfp_reg *vreg;
8177
8178 vreg = vfp_psr_parse (str);
8179
8180 if (vreg)
8181 {
8182 inst.instruction |= vreg->regno;
8183 return SUCCESS;
8184 }
8185
8186 inst.error = _("VFP system register expected");
8187
8188 *str = start;
8189 return FAIL;
8190}
8191
8192static void
a737bd4d 8193do_vfp_reg_from_ctrl (char * str)
bfae80f2
RE
8194{
8195 skip_whitespace (str);
8196
8197 if (reg_required_here (&str, 12) == FAIL)
8198 return;
8199
8200 if (skip_past_comma (&str) == FAIL
8201 || vfp_psr_required_here (&str) == FAIL)
8202 {
8203 if (! inst.error)
8204 inst.error = BAD_ARGS;
8205 return;
8206 }
8207
8208 end_of_line (str);
bfae80f2
RE
8209}
8210
8211static void
a737bd4d 8212do_vfp_ctrl_from_reg (char * str)
bfae80f2
RE
8213{
8214 skip_whitespace (str);
8215
8216 if (vfp_psr_required_here (&str) == FAIL)
8217 return;
8218
8219 if (skip_past_comma (&str) == FAIL
8220 || reg_required_here (&str, 12) == FAIL)
8221 {
8222 if (! inst.error)
8223 inst.error = BAD_ARGS;
8224 return;
8225 }
8226
8227 end_of_line (str);
bfae80f2
RE
8228}
8229
8230static void
a737bd4d 8231do_vfp_sp_ldst (char * str)
bfae80f2
RE
8232{
8233 skip_whitespace (str);
8234
8235 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
8236 {
8237 if (!inst.error)
8238 inst.error = BAD_ARGS;
8239 return;
8240 }
8241
8242 if (skip_past_comma (&str) == FAIL
8243 || cp_address_required_here (&str, CP_NO_WB) == FAIL)
8244 {
8245 if (!inst.error)
8246 inst.error = BAD_ARGS;
8247 return;
8248 }
8249
8250 end_of_line (str);
bfae80f2
RE
8251}
8252
8253static void
a737bd4d 8254do_vfp_dp_ldst (char * str)
bfae80f2
RE
8255{
8256 skip_whitespace (str);
8257
8258 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
8259 {
8260 if (!inst.error)
8261 inst.error = BAD_ARGS;
8262 return;
8263 }
8264
8265 if (skip_past_comma (&str) == FAIL
8266 || cp_address_required_here (&str, CP_NO_WB) == FAIL)
8267 {
8268 if (!inst.error)
a737bd4d
NC
8269 inst.error = BAD_ARGS;
8270 return;
bfae80f2
RE
8271 }
8272
a737bd4d 8273 end_of_line (str);
bfae80f2
RE
8274}
8275
bfae80f2
RE
8276
8277static void
a737bd4d 8278vfp_sp_ldstm (char * str, enum vfp_ldstm_type ldstm_type)
bfae80f2 8279{
7ed4c4c5
NC
8280 int count;
8281 int reg;
bfae80f2
RE
8282
8283 skip_whitespace (str);
8284
8285 if (reg_required_here (&str, 16) == FAIL)
8286 return;
8287
8288 skip_whitespace (str);
8289
8290 if (*str == '!')
8291 {
8292 inst.instruction |= WRITE_BACK;
8293 str++;
8294 }
8295 else if (ldstm_type != VFP_LDSTMIA)
8296 {
8297 inst.error = _("this addressing mode requires base-register writeback");
8298 return;
8299 }
8300
8301 if (skip_past_comma (&str) == FAIL
7ed4c4c5 8302 || (count = vfp_parse_reg_list (&str, &reg, 0)) == FAIL)
bfae80f2
RE
8303 {
8304 if (!inst.error)
8305 inst.error = BAD_ARGS;
8306 return;
8307 }
7ed4c4c5 8308 vfp_sp_encode_reg (reg, VFP_REG_Sd);
bfae80f2 8309
7ed4c4c5 8310 inst.instruction |= count;
bfae80f2
RE
8311 end_of_line (str);
8312}
8313
8314static void
a737bd4d 8315vfp_dp_ldstm (char * str, enum vfp_ldstm_type ldstm_type)
bfae80f2 8316{
7ed4c4c5
NC
8317 int count;
8318 int reg;
bfae80f2
RE
8319
8320 skip_whitespace (str);
8321
8322 if (reg_required_here (&str, 16) == FAIL)
8323 return;
8324
8325 skip_whitespace (str);
8326
8327 if (*str == '!')
8328 {
8329 inst.instruction |= WRITE_BACK;
8330 str++;
8331 }
8332 else if (ldstm_type != VFP_LDSTMIA && ldstm_type != VFP_LDSTMIAX)
8333 {
8334 inst.error = _("this addressing mode requires base-register writeback");
8335 return;
8336 }
8337
8338 if (skip_past_comma (&str) == FAIL
7ed4c4c5 8339 || (count = vfp_parse_reg_list (&str, &reg, 1)) == FAIL)
bfae80f2
RE
8340 {
8341 if (!inst.error)
8342 inst.error = BAD_ARGS;
8343 return;
8344 }
8345
7ed4c4c5 8346 count <<= 1;
bfae80f2 8347 if (ldstm_type == VFP_LDSTMIAX || ldstm_type == VFP_LDSTMDBX)
7ed4c4c5 8348 count += 1;
bfae80f2 8349
7ed4c4c5 8350 inst.instruction |= (reg << 12) | count;
bfae80f2
RE
8351 end_of_line (str);
8352}
8353
8354static void
a737bd4d 8355do_vfp_sp_ldstmia (char * str)
bfae80f2
RE
8356{
8357 vfp_sp_ldstm (str, VFP_LDSTMIA);
8358}
8359
8360static void
a737bd4d 8361do_vfp_sp_ldstmdb (char * str)
bfae80f2
RE
8362{
8363 vfp_sp_ldstm (str, VFP_LDSTMDB);
8364}
8365
8366static void
a737bd4d 8367do_vfp_dp_ldstmia (char * str)
bfae80f2
RE
8368{
8369 vfp_dp_ldstm (str, VFP_LDSTMIA);
8370}
8371
8372static void
a737bd4d 8373do_vfp_dp_ldstmdb (char * str)
bfae80f2
RE
8374{
8375 vfp_dp_ldstm (str, VFP_LDSTMDB);
8376}
8377
8378static void
a737bd4d 8379do_vfp_xp_ldstmia (char *str)
bfae80f2
RE
8380{
8381 vfp_dp_ldstm (str, VFP_LDSTMIAX);
8382}
8383
8384static void
a737bd4d 8385do_vfp_xp_ldstmdb (char * str)
bfae80f2
RE
8386{
8387 vfp_dp_ldstm (str, VFP_LDSTMDBX);
8388}
8389
8390static void
a737bd4d 8391do_vfp_sp_compare_z (char * str)
bfae80f2
RE
8392{
8393 skip_whitespace (str);
8394
8395 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
8396 {
8397 if (!inst.error)
8398 inst.error = BAD_ARGS;
8399 return;
8400 }
8401
8402 end_of_line (str);
bfae80f2
RE
8403}
8404
8405static void
a737bd4d 8406do_vfp_dp_compare_z (char * str)
bfae80f2
RE
8407{
8408 skip_whitespace (str);
8409
8410 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
8411 {
8412 if (!inst.error)
8413 inst.error = BAD_ARGS;
8414 return;
8415 }
8416
8417 end_of_line (str);
bfae80f2
RE
8418}
8419
8420static void
a737bd4d 8421do_vfp_dp_sp_cvt (char * str)
bfae80f2
RE
8422{
8423 skip_whitespace (str);
8424
8425 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
8426 return;
8427
8428 if (skip_past_comma (&str) == FAIL
8429 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
8430 {
8431 if (! inst.error)
8432 inst.error = BAD_ARGS;
8433 return;
8434 }
8435
8436 end_of_line (str);
bfae80f2
RE
8437}
8438
8439static void
a737bd4d 8440do_vfp_sp_dp_cvt (char * str)
bfae80f2
RE
8441{
8442 skip_whitespace (str);
8443
8444 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
8445 return;
8446
8447 if (skip_past_comma (&str) == FAIL
8448 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
8449 {
8450 if (! inst.error)
8451 inst.error = BAD_ARGS;
8452 return;
8453 }
8454
8455 end_of_line (str);
bfae80f2
RE
8456}
8457
8458/* Thumb specific routines. */
8459
bfae80f2
RE
8460/* Parse an add or subtract instruction, SUBTRACT is non-zero if the opcode
8461 was SUB. */
8462
8463static void
a737bd4d 8464thumb_add_sub (char * str, int subtract)
bfae80f2
RE
8465{
8466 int Rd, Rs, Rn = FAIL;
8467
8468 skip_whitespace (str);
8469
8470 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
8471 || skip_past_comma (&str) == FAIL)
8472 {
8473 if (! inst.error)
8474 inst.error = BAD_ARGS;
8475 return;
8476 }
8477
8478 if (is_immediate_prefix (*str))
8479 {
8480 Rs = Rd;
8481 str++;
8482 if (my_get_expression (&inst.reloc.exp, &str))
8483 return;
8484 }
8485 else
8486 {
8487 if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
8488 return;
8489
8490 if (skip_past_comma (&str) == FAIL)
8491 {
8492 /* Two operand format, shuffle the registers
8493 and pretend there are 3. */
8494 Rn = Rs;
8495 Rs = Rd;
8496 }
8497 else if (is_immediate_prefix (*str))
8498 {
8499 str++;
8500 if (my_get_expression (&inst.reloc.exp, &str))
8501 return;
8502 }
8503 else if ((Rn = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
8504 return;
8505 }
8506
8507 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
8508 for the latter case, EXPR contains the immediate that was found. */
8509 if (Rn != FAIL)
8510 {
8511 /* All register format. */
8512 if (Rd > 7 || Rs > 7 || Rn > 7)
8513 {
8514 if (Rs != Rd)
8515 {
8516 inst.error = _("dest and source1 must be the same register");
8517 return;
8518 }
8519
8520 /* Can't do this for SUB. */
8521 if (subtract)
8522 {
8523 inst.error = _("subtract valid only on lo regs");
8524 return;
8525 }
8526
8527 inst.instruction = (T_OPCODE_ADD_HI
8528 | (Rd > 7 ? THUMB_H1 : 0)
8529 | (Rn > 7 ? THUMB_H2 : 0));
8530 inst.instruction |= (Rd & 7) | ((Rn & 7) << 3);
8531 }
8532 else
8533 {
8534 inst.instruction = subtract ? T_OPCODE_SUB_R3 : T_OPCODE_ADD_R3;
8535 inst.instruction |= Rd | (Rs << 3) | (Rn << 6);
8536 }
8537 }
8538 else
8539 {
8540 /* Immediate expression, now things start to get nasty. */
8541
8542 /* First deal with HI regs, only very restricted cases allowed:
8543 Adjusting SP, and using PC or SP to get an address. */
8544 if ((Rd > 7 && (Rd != REG_SP || Rs != REG_SP))
8545 || (Rs > 7 && Rs != REG_SP && Rs != REG_PC))
8546 {
8547 inst.error = _("invalid Hi register with immediate");
8548 return;
8549 }
8550
8551 if (inst.reloc.exp.X_op != O_constant)
8552 {
8553 /* Value isn't known yet, all we can do is store all the fragments
8554 we know about in the instruction and let the reloc hacking
8555 work it all out. */
8556 inst.instruction = (subtract ? 0x8000 : 0) | (Rd << 4) | Rs;
8557 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
8558 }
8559 else
8560 {
8561 int offset = inst.reloc.exp.X_add_number;
8562
8563 if (subtract)
358b94bd 8564 offset = - offset;
bfae80f2
RE
8565
8566 if (offset < 0)
8567 {
358b94bd 8568 offset = - offset;
bfae80f2
RE
8569 subtract = 1;
8570
8571 /* Quick check, in case offset is MIN_INT. */
8572 if (offset < 0)
8573 {
8574 inst.error = _("immediate value out of range");
8575 return;
8576 }
8577 }
358b94bd
NC
8578 /* Note - you cannot convert a subtract of 0 into an
8579 add of 0 because the carry flag is set differently. */
8580 else if (offset > 0)
bfae80f2
RE
8581 subtract = 0;
8582
8583 if (Rd == REG_SP)
8584 {
8585 if (offset & ~0x1fc)
8586 {
8587 inst.error = _("invalid immediate value for stack adjust");
8588 return;
b99bd4ef
NC
8589 }
8590 inst.instruction = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
8591 inst.instruction |= offset >> 2;
8592 }
8593 else if (Rs == REG_PC || Rs == REG_SP)
8594 {
8595 if (subtract
8596 || (offset & ~0x3fc))
8597 {
8598 inst.error = _("invalid immediate for address calculation");
8599 return;
8600 }
8601 inst.instruction = (Rs == REG_PC ? T_OPCODE_ADD_PC
8602 : T_OPCODE_ADD_SP);
8603 inst.instruction |= (Rd << 8) | (offset >> 2);
8604 }
8605 else if (Rs == Rd)
8606 {
8607 if (offset & ~0xff)
8608 {
8609 inst.error = _("immediate value out of range");
8610 return;
8611 }
8612 inst.instruction = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
8613 inst.instruction |= (Rd << 8) | offset;
8614 }
8615 else
8616 {
8617 if (offset & ~0x7)
8618 {
8619 inst.error = _("immediate value out of range");
8620 return;
8621 }
8622 inst.instruction = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
8623 inst.instruction |= Rd | (Rs << 3) | (offset << 6);
8624 }
8625 }
8626 }
8627
8628 end_of_line (str);
8629}
8630
8631static void
a737bd4d 8632thumb_shift (char * str, int shift)
b99bd4ef
NC
8633{
8634 int Rd, Rs, Rn = FAIL;
8635
8636 skip_whitespace (str);
8637
8638 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
8639 || skip_past_comma (&str) == FAIL)
8640 {
8641 if (! inst.error)
8642 inst.error = BAD_ARGS;
8643 return;
8644 }
8645
8646 if (is_immediate_prefix (*str))
8647 {
8648 /* Two operand immediate format, set Rs to Rd. */
8649 Rs = Rd;
8650 str ++;
8651 if (my_get_expression (&inst.reloc.exp, &str))
8652 return;
8653 }
8654 else
8655 {
8656 if ((Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
8657 return;
8658
8659 if (skip_past_comma (&str) == FAIL)
8660 {
8661 /* Two operand format, shuffle the registers
8662 and pretend there are 3. */
8663 Rn = Rs;
8664 Rs = Rd;
8665 }
8666 else if (is_immediate_prefix (*str))
8667 {
8668 str++;
8669 if (my_get_expression (&inst.reloc.exp, &str))
8670 return;
8671 }
8672 else if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
8673 return;
8674 }
8675
8676 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
8677 for the latter case, EXPR contains the immediate that was found. */
8678
8679 if (Rn != FAIL)
8680 {
8681 if (Rs != Rd)
8682 {
8683 inst.error = _("source1 and dest must be same register");
8684 return;
8685 }
8686
8687 switch (shift)
8688 {
8689 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_R; break;
8690 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_R; break;
8691 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_R; break;
8692 }
8693
8694 inst.instruction |= Rd | (Rn << 3);
8695 }
8696 else
8697 {
8698 switch (shift)
8699 {
8700 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_I; break;
8701 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_I; break;
8702 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_I; break;
8703 }
8704
8705 if (inst.reloc.exp.X_op != O_constant)
8706 {
8707 /* Value isn't known yet, create a dummy reloc and let reloc
8708 hacking fix it up. */
8709 inst.reloc.type = BFD_RELOC_ARM_THUMB_SHIFT;
8710 }
8711 else
8712 {
8713 unsigned shift_value = inst.reloc.exp.X_add_number;
8714
8715 if (shift_value > 32 || (shift_value == 32 && shift == THUMB_LSL))
8716 {
f03698e6 8717 inst.error = _("invalid immediate for shift");
b99bd4ef
NC
8718 return;
8719 }
8720
8721 /* Shifts of zero are handled by converting to LSL. */
8722 if (shift_value == 0)
8723 inst.instruction = T_OPCODE_LSL_I;
8724
8725 /* Shifts of 32 are encoded as a shift of zero. */
8726 if (shift_value == 32)
8727 shift_value = 0;
8728
8729 inst.instruction |= shift_value << 6;
8730 }
8731
8732 inst.instruction |= Rd | (Rs << 3);
8733 }
8734
8735 end_of_line (str);
8736}
8737
8738static void
a737bd4d 8739thumb_load_store (char * str, int load_store, int size)
b99bd4ef
NC
8740{
8741 int Rd, Rb, Ro = FAIL;
8742
8743 skip_whitespace (str);
8744
8745 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
8746 || skip_past_comma (&str) == FAIL)
8747 {
8748 if (! inst.error)
8749 inst.error = BAD_ARGS;
8750 return;
8751 }
8752
8753 if (*str == '[')
8754 {
8755 str++;
8756 if ((Rb = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
8757 return;
8758
8759 if (skip_past_comma (&str) != FAIL)
8760 {
8761 if (is_immediate_prefix (*str))
8762 {
8763 str++;
8764 if (my_get_expression (&inst.reloc.exp, &str))
8765 return;
8766 }
8767 else if ((Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
8768 return;
8769 }
8770 else
8771 {
8772 inst.reloc.exp.X_op = O_constant;
8773 inst.reloc.exp.X_add_number = 0;
8774 }
8775
8776 if (*str != ']')
8777 {
8778 inst.error = _("expected ']'");
8779 return;
8780 }
8781 str++;
8782 }
8783 else if (*str == '=')
8784 {
f03698e6
RE
8785 if (load_store != THUMB_LOAD)
8786 {
8787 inst.error = _("invalid pseudo operation");
8788 return;
8789 }
8790
b99bd4ef
NC
8791 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
8792 str++;
8793
8794 skip_whitespace (str);
8795
8796 if (my_get_expression (& inst.reloc.exp, & str))
8797 return;
8798
8799 end_of_line (str);
8800
8801 if ( inst.reloc.exp.X_op != O_constant
8802 && inst.reloc.exp.X_op != O_symbol)
8803 {
8804 inst.error = "Constant expression expected";
8805 return;
8806 }
8807
8808 if (inst.reloc.exp.X_op == O_constant
8809 && ((inst.reloc.exp.X_add_number & ~0xFF) == 0))
8810 {
8811 /* This can be done with a mov instruction. */
8812
8813 inst.instruction = T_OPCODE_MOV_I8 | (Rd << 8);
8814 inst.instruction |= inst.reloc.exp.X_add_number;
8815 return;
8816 }
8817
8818 /* Insert into literal pool. */
8819 if (add_to_lit_pool () == FAIL)
8820 {
8821 if (!inst.error)
8822 inst.error = "literal pool insertion failed";
8823 return;
8824 }
8825
8826 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
8827 inst.reloc.pc_rel = 1;
8828 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
8829 /* Adjust ARM pipeline offset to Thumb. */
8830 inst.reloc.exp.X_add_number += 4;
8831
8832 return;
8833 }
8834 else
8835 {
8836 if (my_get_expression (&inst.reloc.exp, &str))
8837 return;
8838
8839 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
8840 inst.reloc.pc_rel = 1;
8841 inst.reloc.exp.X_add_number -= 4; /* Pipeline offset. */
8842 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
8843 end_of_line (str);
8844 return;
8845 }
8846
8847 if (Rb == REG_PC || Rb == REG_SP)
8848 {
8849 if (size != THUMB_WORD)
8850 {
8851 inst.error = _("byte or halfword not valid for base register");
8852 return;
8853 }
8854 else if (Rb == REG_PC && load_store != THUMB_LOAD)
8855 {
f03698e6 8856 inst.error = _("r15 based store not allowed");
b99bd4ef
NC
8857 return;
8858 }
8859 else if (Ro != FAIL)
8860 {
f03698e6 8861 inst.error = _("invalid base register for register offset");
b99bd4ef
NC
8862 return;
8863 }
8864
8865 if (Rb == REG_PC)
8866 inst.instruction = T_OPCODE_LDR_PC;
8867 else if (load_store == THUMB_LOAD)
8868 inst.instruction = T_OPCODE_LDR_SP;
8869 else
8870 inst.instruction = T_OPCODE_STR_SP;
8871
8872 inst.instruction |= Rd << 8;
8873 if (inst.reloc.exp.X_op == O_constant)
8874 {
8875 unsigned offset = inst.reloc.exp.X_add_number;
8876
8877 if (offset & ~0x3fc)
8878 {
8879 inst.error = _("invalid offset");
8880 return;
8881 }
8882
8883 inst.instruction |= offset >> 2;
8884 }
8885 else
8886 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
8887 }
8888 else if (Rb > 7)
8889 {
8890 inst.error = _("invalid base register in load/store");
8891 return;
8892 }
8893 else if (Ro == FAIL)
8894 {
8895 /* Immediate offset. */
8896 if (size == THUMB_WORD)
8897 inst.instruction = (load_store == THUMB_LOAD
8898 ? T_OPCODE_LDR_IW : T_OPCODE_STR_IW);
8899 else if (size == THUMB_HALFWORD)
8900 inst.instruction = (load_store == THUMB_LOAD
8901 ? T_OPCODE_LDR_IH : T_OPCODE_STR_IH);
8902 else
8903 inst.instruction = (load_store == THUMB_LOAD
8904 ? T_OPCODE_LDR_IB : T_OPCODE_STR_IB);
8905
8906 inst.instruction |= Rd | (Rb << 3);
8907
8908 if (inst.reloc.exp.X_op == O_constant)
8909 {
8910 unsigned offset = inst.reloc.exp.X_add_number;
8911
8912 if (offset & ~(0x1f << size))
8913 {
f03698e6 8914 inst.error = _("invalid offset");
b99bd4ef
NC
8915 return;
8916 }
8917 inst.instruction |= (offset >> size) << 6;
8918 }
8919 else
8920 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
8921 }
8922 else
8923 {
8924 /* Register offset. */
8925 if (size == THUMB_WORD)
8926 inst.instruction = (load_store == THUMB_LOAD
8927 ? T_OPCODE_LDR_RW : T_OPCODE_STR_RW);
8928 else if (size == THUMB_HALFWORD)
8929 inst.instruction = (load_store == THUMB_LOAD
8930 ? T_OPCODE_LDR_RH : T_OPCODE_STR_RH);
8931 else
8932 inst.instruction = (load_store == THUMB_LOAD
8933 ? T_OPCODE_LDR_RB : T_OPCODE_STR_RB);
8934
8935 inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
8936 }
8937
8938 end_of_line (str);
8939}
8940
404ff6b5
AH
8941/* A register must be given at this point.
8942
404ff6b5
AH
8943 Shift is the place to put it in inst.instruction.
8944
404ff6b5
AH
8945 Restores input start point on err.
8946 Returns the reg#, or FAIL. */
8947
8948static int
a737bd4d 8949mav_reg_required_here (char ** str, int shift, enum arm_reg_type regtype)
404ff6b5 8950{
6c43fab6
RE
8951 int reg;
8952 char *start = *str;
404ff6b5 8953
6c43fab6 8954 if ((reg = arm_reg_parse (str, all_reg_maps[regtype].htab)) != FAIL)
404ff6b5 8955 {
404ff6b5
AH
8956 if (shift >= 0)
8957 inst.instruction |= reg << shift;
8958
6c43fab6 8959 return reg;
404ff6b5
AH
8960 }
8961
6c43fab6 8962 /* Restore the start point. */
404ff6b5 8963 *str = start;
cc8a6dd0 8964
3631a3c8
NC
8965 /* Try generic coprocessor name if applicable. */
8966 if (regtype == REG_TYPE_MVF ||
8967 regtype == REG_TYPE_MVD ||
8968 regtype == REG_TYPE_MVFX ||
8969 regtype == REG_TYPE_MVDX)
8970 {
8971 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_CN].htab)) != FAIL)
8972 {
8973 if (shift >= 0)
8974 inst.instruction |= reg << shift;
8975
8976 return reg;
8977 }
8978
8979 /* Restore the start point. */
8980 *str = start;
8981 }
8982
404ff6b5
AH
8983 /* In the few cases where we might be able to accept something else
8984 this error can be overridden. */
6c43fab6 8985 inst.error = _(all_reg_maps[regtype].expected);
cc8a6dd0 8986
404ff6b5
AH
8987 return FAIL;
8988}
8989
a737bd4d
NC
8990/* Cirrus Maverick Instructions. */
8991
8992/* Isnsn like "foo X,Y". */
8993
8994static void
8995do_mav_binops (char * str,
8996 int mode,
8997 enum arm_reg_type reg0,
8998 enum arm_reg_type reg1)
8999{
9000 int shift0, shift1;
9001
9002 shift0 = mode & 0xff;
9003 shift1 = (mode >> 8) & 0xff;
9004
9005 skip_whitespace (str);
9006
9007 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
9008 || skip_past_comma (&str) == FAIL
9009 || mav_reg_required_here (&str, shift1, reg1) == FAIL)
9010 {
9011 if (!inst.error)
9012 inst.error = BAD_ARGS;
9013 }
9014 else
9015 end_of_line (str);
9016}
9017
9018/* Isnsn like "foo X,Y,Z". */
9019
9020static void
9021do_mav_triple (char * str,
9022 int mode,
9023 enum arm_reg_type reg0,
9024 enum arm_reg_type reg1,
9025 enum arm_reg_type reg2)
9026{
9027 int shift0, shift1, shift2;
9028
9029 shift0 = mode & 0xff;
9030 shift1 = (mode >> 8) & 0xff;
9031 shift2 = (mode >> 16) & 0xff;
9032
9033 skip_whitespace (str);
9034
9035 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
9036 || skip_past_comma (&str) == FAIL
9037 || mav_reg_required_here (&str, shift1, reg1) == FAIL
9038 || skip_past_comma (&str) == FAIL
9039 || mav_reg_required_here (&str, shift2, reg2) == FAIL)
9040 {
9041 if (!inst.error)
9042 inst.error = BAD_ARGS;
9043 }
9044 else
9045 end_of_line (str);
9046}
9047
9048/* Wrapper functions. */
9049
9050static void
9051do_mav_binops_1a (char * str)
9052{
9053 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVF);
9054}
9055
9056static void
9057do_mav_binops_1b (char * str)
9058{
9059 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVD);
9060}
9061
9062static void
9063do_mav_binops_1c (char * str)
9064{
9065 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVDX);
9066}
9067
9068static void
9069do_mav_binops_1d (char * str)
9070{
9071 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVF);
9072}
9073
9074static void
9075do_mav_binops_1e (char * str)
9076{
9077 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVD);
9078}
9079
9080static void
9081do_mav_binops_1f (char * str)
9082{
9083 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVF);
9084}
9085
9086static void
9087do_mav_binops_1g (char * str)
9088{
9089 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVD);
9090}
9091
9092static void
9093do_mav_binops_1h (char * str)
9094{
9095 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVFX);
9096}
9097
9098static void
9099do_mav_binops_1i (char * str)
9100{
9101 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVFX);
9102}
9103
9104static void
9105do_mav_binops_1j (char * str)
9106{
9107 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVDX);
9108}
9109
9110static void
9111do_mav_binops_1k (char * str)
9112{
9113 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVDX);
9114}
9115
9116static void
9117do_mav_binops_1l (char * str)
9118{
9119 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVF);
9120}
9121
9122static void
9123do_mav_binops_1m (char * str)
9124{
9125 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVD);
9126}
9127
9128static void
9129do_mav_binops_1n (char * str)
9130{
9131 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVFX);
9132}
9133
9134static void
9135do_mav_binops_1o (char * str)
9136{
9137 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVDX, REG_TYPE_MVDX);
9138}
9139
9140static void
9141do_mav_binops_2a (char * str)
9142{
9143 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVF, REG_TYPE_RN);
9144}
9145
9146static void
9147do_mav_binops_2b (char * str)
9148{
9149 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVD, REG_TYPE_RN);
9150}
404ff6b5 9151
a737bd4d
NC
9152static void
9153do_mav_binops_2c (char * str)
9154{
9155 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVDX, REG_TYPE_RN);
9156}
404ff6b5
AH
9157
9158static void
a737bd4d 9159do_mav_binops_3a (char * str)
6c43fab6 9160{
a737bd4d 9161 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVAX, REG_TYPE_MVFX);
6c43fab6
RE
9162}
9163
9164static void
a737bd4d 9165do_mav_binops_3b (char * str)
6c43fab6 9166{
a737bd4d 9167 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVFX, REG_TYPE_MVAX);
6c43fab6
RE
9168}
9169
9170static void
a737bd4d 9171do_mav_binops_3c (char * str)
404ff6b5 9172{
a737bd4d 9173 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVAX, REG_TYPE_MVDX);
404ff6b5
AH
9174}
9175
9176static void
a737bd4d 9177do_mav_binops_3d (char * str)
404ff6b5 9178{
a737bd4d 9179 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVDX, REG_TYPE_MVAX);
404ff6b5
AH
9180}
9181
9182static void
a737bd4d 9183do_mav_triple_4a (char * str)
404ff6b5 9184{
a737bd4d 9185 do_mav_triple (str, MAV_MODE4, REG_TYPE_MVFX, REG_TYPE_MVFX, REG_TYPE_RN);
404ff6b5
AH
9186}
9187
9188static void
a737bd4d 9189do_mav_triple_4b (char * str)
404ff6b5 9190{
a737bd4d 9191 do_mav_triple (str, MAV_MODE4, REG_TYPE_MVDX, REG_TYPE_MVDX, REG_TYPE_RN);
404ff6b5
AH
9192}
9193
9194static void
a737bd4d 9195do_mav_triple_5a (char * str)
404ff6b5 9196{
a737bd4d 9197 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVF, REG_TYPE_MVF);
404ff6b5
AH
9198}
9199
9200static void
a737bd4d 9201do_mav_triple_5b (char * str)
404ff6b5 9202{
a737bd4d 9203 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVD, REG_TYPE_MVD);
404ff6b5
AH
9204}
9205
6c43fab6 9206static void
a737bd4d 9207do_mav_triple_5c (char * str)
6c43fab6 9208{
a737bd4d 9209 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVFX, REG_TYPE_MVFX);
6c43fab6
RE
9210}
9211
9212static void
a737bd4d 9213do_mav_triple_5d (char * str)
6c43fab6 9214{
a737bd4d 9215 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVDX, REG_TYPE_MVDX);
6c43fab6
RE
9216}
9217
9218static void
a737bd4d 9219do_mav_triple_5e (char * str)
6c43fab6 9220{
a737bd4d 9221 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVF, REG_TYPE_MVF, REG_TYPE_MVF);
6c43fab6
RE
9222}
9223
9224static void
a737bd4d 9225do_mav_triple_5f (char * str)
6c43fab6 9226{
a737bd4d 9227 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVD, REG_TYPE_MVD, REG_TYPE_MVD);
6c43fab6
RE
9228}
9229
9230static void
a737bd4d 9231do_mav_triple_5g (char * str)
6c43fab6 9232{
a737bd4d 9233 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVFX, REG_TYPE_MVFX, REG_TYPE_MVFX);
6c43fab6
RE
9234}
9235
9236static void
a737bd4d 9237do_mav_triple_5h (char * str)
6c43fab6 9238{
a737bd4d 9239 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVDX, REG_TYPE_MVDX, REG_TYPE_MVDX);
6c43fab6
RE
9240}
9241
a737bd4d
NC
9242/* Isnsn like "foo W,X,Y,Z".
9243 where W=MVAX[0:3] and X,Y,Z=MVFX[0:15]. */
9244
6c43fab6 9245static void
a737bd4d
NC
9246do_mav_quad (char * str,
9247 int mode,
9248 enum arm_reg_type reg0,
9249 enum arm_reg_type reg1,
9250 enum arm_reg_type reg2,
9251 enum arm_reg_type reg3)
6c43fab6 9252{
a737bd4d
NC
9253 int shift0, shift1, shift2, shift3;
9254
9255 shift0= mode & 0xff;
9256 shift1 = (mode >> 8) & 0xff;
9257 shift2 = (mode >> 16) & 0xff;
9258 shift3 = (mode >> 24) & 0xff;
9259
9260 skip_whitespace (str);
9261
9262 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
9263 || skip_past_comma (&str) == FAIL
9264 || mav_reg_required_here (&str, shift1, reg1) == FAIL
9265 || skip_past_comma (&str) == FAIL
9266 || mav_reg_required_here (&str, shift2, reg2) == FAIL
9267 || skip_past_comma (&str) == FAIL
9268 || mav_reg_required_here (&str, shift3, reg3) == FAIL)
9269 {
9270 if (!inst.error)
9271 inst.error = BAD_ARGS;
9272 }
9273 else
9274 end_of_line (str);
6c43fab6
RE
9275}
9276
9277static void
a737bd4d 9278do_mav_quad_6a (char * str)
6c43fab6 9279{
a737bd4d
NC
9280 do_mav_quad (str, MAV_MODE6, REG_TYPE_MVAX, REG_TYPE_MVFX, REG_TYPE_MVFX,
9281 REG_TYPE_MVFX);
6c43fab6
RE
9282}
9283
9284static void
a737bd4d 9285do_mav_quad_6b (char * str)
6c43fab6 9286{
a737bd4d
NC
9287 do_mav_quad (str, MAV_MODE6, REG_TYPE_MVAX, REG_TYPE_MVAX, REG_TYPE_MVFX,
9288 REG_TYPE_MVFX);
6c43fab6
RE
9289}
9290
a737bd4d 9291/* cfmvsc32<cond> DSPSC,MVDX[15:0]. */
6c43fab6 9292static void
a737bd4d 9293do_mav_dspsc_1 (char * str)
6c43fab6 9294{
a737bd4d
NC
9295 skip_whitespace (str);
9296
9297 /* cfmvsc32. */
9298 if (mav_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL
9299 || skip_past_comma (&str) == FAIL
9300 || mav_reg_required_here (&str, 12, REG_TYPE_MVDX) == FAIL)
9301 {
9302 if (!inst.error)
9303 inst.error = BAD_ARGS;
9304
9305 return;
9306 }
9307
9308 end_of_line (str);
6c43fab6
RE
9309}
9310
a737bd4d 9311/* cfmv32sc<cond> MVDX[15:0],DSPSC. */
6c43fab6 9312static void
a737bd4d 9313do_mav_dspsc_2 (char * str)
6c43fab6 9314{
a737bd4d
NC
9315 skip_whitespace (str);
9316
9317 /* cfmv32sc. */
9318 if (mav_reg_required_here (&str, 12, REG_TYPE_MVDX) == FAIL
9319 || skip_past_comma (&str) == FAIL
9320 || mav_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL)
9321 {
9322 if (!inst.error)
9323 inst.error = BAD_ARGS;
9324
9325 return;
9326 }
9327
9328 end_of_line (str);
6c43fab6
RE
9329}
9330
a737bd4d
NC
9331/* Maverick shift immediate instructions.
9332 cfsh32<cond> MVFX[15:0],MVFX[15:0],Shift[6:0].
9333 cfsh64<cond> MVDX[15:0],MVDX[15:0],Shift[6:0]. */
9334
6c43fab6 9335static void
a737bd4d
NC
9336do_mav_shift (char * str,
9337 enum arm_reg_type reg0,
9338 enum arm_reg_type reg1)
6c43fab6 9339{
a737bd4d
NC
9340 int error;
9341 int imm, neg = 0;
9342
9343 skip_whitespace (str);
9344
9345 error = 0;
9346
9347 if (mav_reg_required_here (&str, 12, reg0) == FAIL
9348 || skip_past_comma (&str) == FAIL
9349 || mav_reg_required_here (&str, 16, reg1) == FAIL
9350 || skip_past_comma (&str) == FAIL)
9351 {
9352 if (!inst.error)
9353 inst.error = BAD_ARGS;
9354 return;
9355 }
9356
9357 /* Calculate the immediate operand.
9358 The operand is a 7bit signed number. */
9359 skip_whitespace (str);
9360
9361 if (*str == '#')
9362 ++str;
9363
9364 if (!ISDIGIT (*str) && *str != '-')
9365 {
9366 inst.error = _("expecting immediate, 7bit operand");
9367 return;
9368 }
9369
9370 if (*str == '-')
9371 {
9372 neg = 1;
9373 ++str;
9374 }
9375
9376 for (imm = 0; *str && ISDIGIT (*str); ++str)
9377 imm = imm * 10 + *str - '0';
9378
9379 if (imm > 64)
9380 {
9381 inst.error = _("immediate out of range");
9382 return;
9383 }
9384
9385 /* Make negative imm's into 7bit signed numbers. */
9386 if (neg)
9387 {
9388 imm = -imm;
9389 imm &= 0x0000007f;
9390 }
9391
9392 /* Bits 0-3 of the insn should have bits 0-3 of the immediate.
9393 Bits 5-7 of the insn should have bits 4-6 of the immediate.
9394 Bit 4 should be 0. */
9395 imm = (imm & 0xf) | ((imm & 0x70) << 1);
9396
9397 inst.instruction |= imm;
9398 end_of_line (str);
6c43fab6
RE
9399}
9400
9401static void
a737bd4d 9402do_mav_shift_1 (char * str)
6c43fab6 9403{
a737bd4d 9404 do_mav_shift (str, REG_TYPE_MVFX, REG_TYPE_MVFX);
6c43fab6
RE
9405}
9406
9407static void
a737bd4d 9408do_mav_shift_2 (char * str)
6c43fab6 9409{
a737bd4d
NC
9410 do_mav_shift (str, REG_TYPE_MVDX, REG_TYPE_MVDX);
9411}
9412
9413static int
9414mav_parse_offset (char ** str, int * negative)
9415{
9416 char * p = *str;
9417 int offset;
9418
9419 *negative = 0;
9420
9421 skip_whitespace (p);
9422
9423 if (*p == '#')
9424 ++p;
9425
9426 if (*p == '-')
9427 {
9428 *negative = 1;
9429 ++p;
9430 }
9431
9432 if (!ISDIGIT (*p))
9433 {
9434 inst.error = _("offset expected");
9435 return 0;
9436 }
9437
9438 for (offset = 0; *p && ISDIGIT (*p); ++p)
9439 offset = offset * 10 + *p - '0';
9440
9441 if (offset > 0x3fc)
9442 {
9443 inst.error = _("offset out of range");
9444 return 0;
9445 }
9446 if (offset & 0x3)
9447 {
9448 inst.error = _("offset not a multiple of 4");
9449 return 0;
9450 }
9451
9452 *str = p;
9453
9454 return *negative ? -offset : offset;
6c43fab6
RE
9455}
9456
a737bd4d
NC
9457/* Maverick load/store instructions.
9458 <insn><cond> CRd,[Rn,<offset>]{!}.
9459 <insn><cond> CRd,[Rn],<offset>. */
9460
9461static void
9462do_mav_ldst (char * str, enum arm_reg_type reg0)
9463{
9464 int offset, negative;
9465
9466 skip_whitespace (str);
9467
9468 if (mav_reg_required_here (&str, 12, reg0) == FAIL
9469 || skip_past_comma (&str) == FAIL
9470 || *str++ != '['
9471 || reg_required_here (&str, 16) == FAIL)
9472 goto fail_ldst;
9473
9474 if (skip_past_comma (&str) == SUCCESS)
9475 {
9476 /* You are here: "<offset>]{!}". */
9477 inst.instruction |= PRE_INDEX;
9478
9479 offset = mav_parse_offset (&str, &negative);
9480
9481 if (inst.error)
9482 return;
9483
9484 if (*str++ != ']')
9485 {
9486 inst.error = _("missing ]");
9487 return;
9488 }
9489
9490 if (*str == '!')
9491 {
9492 inst.instruction |= WRITE_BACK;
9493 ++str;
9494 }
9495 }
9496 else
9497 {
9498 /* You are here: "], <offset>". */
9499 if (*str++ != ']')
9500 {
9501 inst.error = _("missing ]");
9502 return;
9503 }
9504
9505 if (skip_past_comma (&str) == FAIL
9506 || (offset = mav_parse_offset (&str, &negative), inst.error))
9507 goto fail_ldst;
6c43fab6 9508
a737bd4d
NC
9509 inst.instruction |= CP_T_WB; /* Post indexed, set bit W. */
9510 }
6c43fab6 9511
a737bd4d
NC
9512 if (negative)
9513 offset = -offset;
9514 else
9515 inst.instruction |= CP_T_UD; /* Positive, so set bit U. */
6c43fab6 9516
a737bd4d
NC
9517 inst.instruction |= offset >> 2;
9518 end_of_line (str);
9519 return;
6c43fab6 9520
a737bd4d
NC
9521fail_ldst:
9522 if (!inst.error)
9523 inst.error = BAD_ARGS;
6c43fab6
RE
9524}
9525
9526static void
a737bd4d 9527do_mav_ldst_1 (char * str)
6c43fab6 9528{
a737bd4d 9529 do_mav_ldst (str, REG_TYPE_MVF);
6c43fab6
RE
9530}
9531
9532static void
a737bd4d 9533do_mav_ldst_2 (char * str)
6c43fab6 9534{
a737bd4d 9535 do_mav_ldst (str, REG_TYPE_MVD);
6c43fab6
RE
9536}
9537
9538static void
a737bd4d 9539do_mav_ldst_3 (char * str)
6c43fab6 9540{
a737bd4d 9541 do_mav_ldst (str, REG_TYPE_MVFX);
6c43fab6
RE
9542}
9543
9544static void
a737bd4d 9545do_mav_ldst_4 (char * str)
6c43fab6 9546{
a737bd4d 9547 do_mav_ldst (str, REG_TYPE_MVDX);
6c43fab6
RE
9548}
9549
9550static void
a737bd4d 9551do_t_nop (char * str)
6c43fab6 9552{
a737bd4d
NC
9553 /* Do nothing. */
9554 end_of_line (str);
6c43fab6
RE
9555}
9556
a737bd4d
NC
9557/* Handle the Format 4 instructions that do not have equivalents in other
9558 formats. That is, ADC, AND, EOR, SBC, ROR, TST, NEG, CMN, ORR, MUL,
9559 BIC and MVN. */
6c43fab6
RE
9560
9561static void
a737bd4d 9562do_t_arit (char * str)
6c43fab6 9563{
a737bd4d 9564 int Rd, Rs, Rn;
6c43fab6 9565
6c43fab6
RE
9566 skip_whitespace (str);
9567
a737bd4d 9568 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
6c43fab6 9569 || skip_past_comma (&str) == FAIL
a737bd4d 9570 || (Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
6c43fab6 9571 {
a737bd4d 9572 inst.error = BAD_ARGS;
6c43fab6
RE
9573 return;
9574 }
9575
a737bd4d 9576 if (skip_past_comma (&str) != FAIL)
6c43fab6 9577 {
a737bd4d
NC
9578 /* Three operand format not allowed for TST, CMN, NEG and MVN.
9579 (It isn't allowed for CMP either, but that isn't handled by this
9580 function.) */
9581 if (inst.instruction == T_OPCODE_TST
9582 || inst.instruction == T_OPCODE_CMN
9583 || inst.instruction == T_OPCODE_NEG
9584 || inst.instruction == T_OPCODE_MVN)
9585 {
9586 inst.error = BAD_ARGS;
9587 return;
9588 }
6c43fab6 9589
a737bd4d
NC
9590 if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9591 return;
9592
9593 if (Rs != Rd)
9594 {
9595 inst.error = _("dest and source1 must be the same register");
9596 return;
9597 }
9598 Rs = Rn;
6c43fab6
RE
9599 }
9600
a737bd4d
NC
9601 if (inst.instruction == T_OPCODE_MUL
9602 && Rs == Rd)
9603 as_tsktsk (_("Rs and Rd must be different in MUL"));
9604
9605 inst.instruction |= Rd | (Rs << 3);
6c43fab6 9606 end_of_line (str);
404ff6b5
AH
9607}
9608
9609static void
a737bd4d 9610do_t_add (char * str)
404ff6b5 9611{
a737bd4d 9612 thumb_add_sub (str, 0);
404ff6b5
AH
9613}
9614
9615static void
a737bd4d 9616do_t_asr (char * str)
404ff6b5 9617{
a737bd4d 9618 thumb_shift (str, THUMB_ASR);
404ff6b5
AH
9619}
9620
9621static void
a737bd4d 9622do_t_branch9 (char * str)
404ff6b5 9623{
a737bd4d
NC
9624 if (my_get_expression (&inst.reloc.exp, &str))
9625 return;
9626 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH9;
9627 inst.reloc.pc_rel = 1;
9628 end_of_line (str);
404ff6b5
AH
9629}
9630
9631static void
a737bd4d 9632do_t_branch12 (char * str)
404ff6b5 9633{
a737bd4d
NC
9634 if (my_get_expression (&inst.reloc.exp, &str))
9635 return;
9636 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH12;
9637 inst.reloc.pc_rel = 1;
9638 end_of_line (str);
404ff6b5
AH
9639}
9640
a737bd4d 9641/* Find the real, Thumb encoded start of a Thumb function. */
404ff6b5 9642
a737bd4d
NC
9643static symbolS *
9644find_real_start (symbolS * symbolP)
404ff6b5 9645{
a737bd4d
NC
9646 char * real_start;
9647 const char * name = S_GET_NAME (symbolP);
9648 symbolS * new_target;
404ff6b5 9649
a737bd4d
NC
9650 /* This definition must agree with the one in gcc/config/arm/thumb.c. */
9651#define STUB_NAME ".real_start_of"
404ff6b5 9652
a737bd4d
NC
9653 if (name == NULL)
9654 abort ();
404ff6b5 9655
a737bd4d
NC
9656 /* Names that start with '.' are local labels, not function entry points.
9657 The compiler may generate BL instructions to these labels because it
9658 needs to perform a branch to a far away location. */
9659 if (name[0] == '.')
9660 return symbolP;
404ff6b5 9661
a737bd4d
NC
9662 real_start = malloc (strlen (name) + strlen (STUB_NAME) + 1);
9663 sprintf (real_start, "%s%s", STUB_NAME, name);
404ff6b5 9664
a737bd4d
NC
9665 new_target = symbol_find (real_start);
9666
9667 if (new_target == NULL)
404ff6b5 9668 {
a737bd4d
NC
9669 as_warn ("Failed to find real start of function: %s\n", name);
9670 new_target = symbolP;
404ff6b5 9671 }
404ff6b5 9672
a737bd4d
NC
9673 free (real_start);
9674
9675 return new_target;
9676}
404ff6b5
AH
9677
9678static void
a737bd4d 9679do_t_branch23 (char * str)
404ff6b5 9680{
a737bd4d
NC
9681 if (my_get_expression (& inst.reloc.exp, & str))
9682 return;
404ff6b5 9683
a737bd4d
NC
9684 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH23;
9685 inst.reloc.pc_rel = 1;
9686 end_of_line (str);
404ff6b5 9687
a737bd4d
NC
9688 /* If the destination of the branch is a defined symbol which does not have
9689 the THUMB_FUNC attribute, then we must be calling a function which has
9690 the (interfacearm) attribute. We look for the Thumb entry point to that
9691 function and change the branch to refer to that function instead. */
9692 if ( inst.reloc.exp.X_op == O_symbol
9693 && inst.reloc.exp.X_add_symbol != NULL
9694 && S_IS_DEFINED (inst.reloc.exp.X_add_symbol)
9695 && ! THUMB_IS_FUNC (inst.reloc.exp.X_add_symbol))
9696 inst.reloc.exp.X_add_symbol =
9697 find_real_start (inst.reloc.exp.X_add_symbol);
404ff6b5
AH
9698}
9699
404ff6b5 9700static void
a737bd4d 9701do_t_bx (char * str)
404ff6b5 9702{
a737bd4d 9703 int reg;
404ff6b5
AH
9704
9705 skip_whitespace (str);
9706
a737bd4d
NC
9707 if ((reg = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
9708 return;
9709
9710 /* This sets THUMB_H2 from the top bit of reg. */
9711 inst.instruction |= reg << 3;
9712
9713 /* ??? FIXME: Should add a hacky reloc here if reg is REG_PC. The reloc
9714 should cause the alignment to be checked once it is known. This is
9715 because BX PC only works if the instruction is word aligned. */
9716
9717 end_of_line (str);
404ff6b5
AH
9718}
9719
a737bd4d
NC
9720static void
9721do_t_compare (char * str)
9722{
9723 thumb_mov_compare (str, THUMB_COMPARE);
9724}
404ff6b5
AH
9725
9726static void
a737bd4d 9727do_t_ldmstm (char * str)
404ff6b5 9728{
a737bd4d
NC
9729 int Rb;
9730 long range;
404ff6b5
AH
9731
9732 skip_whitespace (str);
9733
a737bd4d
NC
9734 if ((Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9735 return;
404ff6b5 9736
a737bd4d
NC
9737 if (*str != '!')
9738 as_warn (_("inserted missing '!': load/store multiple always writes back base register"));
9739 else
9740 str++;
9741
9742 if (skip_past_comma (&str) == FAIL
9743 || (range = reg_list (&str)) == FAIL)
404ff6b5 9744 {
a737bd4d 9745 if (! inst.error)
404ff6b5
AH
9746 inst.error = BAD_ARGS;
9747 return;
9748 }
9749
620b81c1 9750 if (inst.reloc.type != BFD_RELOC_UNUSED)
404ff6b5 9751 {
a737bd4d 9752 /* This really doesn't seem worth it. */
620b81c1 9753 inst.reloc.type = BFD_RELOC_UNUSED;
a737bd4d 9754 inst.error = _("expression too complex");
404ff6b5
AH
9755 return;
9756 }
9757
a737bd4d 9758 if (range & ~0xff)
404ff6b5 9759 {
a737bd4d 9760 inst.error = _("only lo-regs valid in load/store multiple");
404ff6b5
AH
9761 return;
9762 }
9763
a737bd4d 9764 inst.instruction |= (Rb << 8) | range;
404ff6b5 9765 end_of_line (str);
404ff6b5
AH
9766}
9767
a737bd4d
NC
9768static void
9769do_t_ldr (char * str)
404ff6b5 9770{
a737bd4d
NC
9771 thumb_load_store (str, THUMB_LOAD, THUMB_WORD);
9772}
404ff6b5 9773
a737bd4d
NC
9774static void
9775do_t_ldrb (char * str)
9776{
9777 thumb_load_store (str, THUMB_LOAD, THUMB_BYTE);
9778}
404ff6b5 9779
a737bd4d
NC
9780static void
9781do_t_ldrh (char * str)
9782{
9783 thumb_load_store (str, THUMB_LOAD, THUMB_HALFWORD);
9784}
404ff6b5 9785
a737bd4d
NC
9786static void
9787do_t_lds (char * str)
9788{
9789 int Rd, Rb, Ro;
404ff6b5 9790
a737bd4d 9791 skip_whitespace (str);
404ff6b5 9792
a737bd4d
NC
9793 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9794 || skip_past_comma (&str) == FAIL
9795 || *str++ != '['
9796 || (Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9797 || skip_past_comma (&str) == FAIL
9798 || (Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9799 || *str++ != ']')
404ff6b5 9800 {
a737bd4d
NC
9801 if (! inst.error)
9802 inst.error = _("syntax: ldrs[b] Rd, [Rb, Ro]");
9803 return;
404ff6b5
AH
9804 }
9805
a737bd4d
NC
9806 inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
9807 end_of_line (str);
9808}
404ff6b5 9809
a737bd4d
NC
9810static void
9811do_t_lsl (char * str)
9812{
9813 thumb_shift (str, THUMB_LSL);
9814}
404ff6b5 9815
a737bd4d
NC
9816static void
9817do_t_lsr (char * str)
9818{
9819 thumb_shift (str, THUMB_LSR);
404ff6b5
AH
9820}
9821
a737bd4d
NC
9822static void
9823do_t_mov (char * str)
9824{
9825 thumb_mov_compare (str, THUMB_MOVE);
9826}
404ff6b5
AH
9827
9828static void
a737bd4d 9829do_t_push_pop (char * str)
404ff6b5 9830{
a737bd4d 9831 long range;
404ff6b5
AH
9832
9833 skip_whitespace (str);
9834
a737bd4d 9835 if ((range = reg_list (&str)) == FAIL)
404ff6b5 9836 {
a737bd4d
NC
9837 if (! inst.error)
9838 inst.error = BAD_ARGS;
9839 return;
9840 }
404ff6b5 9841
620b81c1 9842 if (inst.reloc.type != BFD_RELOC_UNUSED)
a737bd4d
NC
9843 {
9844 /* This really doesn't seem worth it. */
620b81c1 9845 inst.reloc.type = BFD_RELOC_UNUSED;
a737bd4d
NC
9846 inst.error = _("expression too complex");
9847 return;
9848 }
404ff6b5 9849
a737bd4d
NC
9850 if (range & ~0xff)
9851 {
9852 if ((inst.instruction == T_OPCODE_PUSH
9853 && (range & ~0xff) == 1 << REG_LR)
9854 || (inst.instruction == T_OPCODE_POP
9855 && (range & ~0xff) == 1 << REG_PC))
404ff6b5 9856 {
a737bd4d
NC
9857 inst.instruction |= THUMB_PP_PC_LR;
9858 range &= 0xff;
404ff6b5 9859 }
a737bd4d 9860 else
404ff6b5 9861 {
a737bd4d 9862 inst.error = _("invalid register list to push/pop instruction");
404ff6b5
AH
9863 return;
9864 }
404ff6b5
AH
9865 }
9866
a737bd4d 9867 inst.instruction |= range;
404ff6b5 9868 end_of_line (str);
a737bd4d 9869}
404ff6b5 9870
a737bd4d
NC
9871static void
9872do_t_str (char * str)
9873{
9874 thumb_load_store (str, THUMB_STORE, THUMB_WORD);
404ff6b5
AH
9875}
9876
b99bd4ef 9877static void
a737bd4d 9878do_t_strb (char * str)
b99bd4ef 9879{
a737bd4d 9880 thumb_load_store (str, THUMB_STORE, THUMB_BYTE);
b99bd4ef
NC
9881}
9882
a737bd4d
NC
9883static void
9884do_t_strh (char * str)
9885{
9886 thumb_load_store (str, THUMB_STORE, THUMB_HALFWORD);
9887}
b99bd4ef
NC
9888
9889static void
a737bd4d 9890do_t_sub (char * str)
b99bd4ef 9891{
a737bd4d
NC
9892 thumb_add_sub (str, 1);
9893}
b99bd4ef 9894
a737bd4d
NC
9895static void
9896do_t_swi (char * str)
9897{
b99bd4ef
NC
9898 skip_whitespace (str);
9899
a737bd4d
NC
9900 if (my_get_expression (&inst.reloc.exp, &str))
9901 return;
b99bd4ef 9902
a737bd4d
NC
9903 inst.reloc.type = BFD_RELOC_ARM_SWI;
9904 end_of_line (str);
9905}
b99bd4ef 9906
a737bd4d
NC
9907static void
9908do_t_adr (char * str)
9909{
9910 int reg;
b99bd4ef 9911
a737bd4d
NC
9912 /* This is a pseudo-op of the form "adr rd, label" to be converted
9913 into a relative address of the form "add rd, pc, #label-.-4". */
9914 skip_whitespace (str);
9915
9916 /* Store Rd in temporary location inside instruction. */
9917 if ((reg = reg_required_here (&str, 4)) == FAIL
9918 || (reg > 7) /* For Thumb reg must be r0..r7. */
9919 || skip_past_comma (&str) == FAIL
9920 || my_get_expression (&inst.reloc.exp, &str))
9921 {
9922 if (!inst.error)
9923 inst.error = BAD_ARGS;
9924 return;
b99bd4ef
NC
9925 }
9926
a737bd4d
NC
9927 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
9928 inst.reloc.exp.X_add_number -= 4; /* PC relative adjust. */
9929 inst.reloc.pc_rel = 1;
9930 inst.instruction |= REG_PC; /* Rd is already placed into the instruction. */
b99bd4ef 9931
b99bd4ef
NC
9932 end_of_line (str);
9933}
9934
9935static void
a737bd4d
NC
9936insert_reg (const struct reg_entry * r,
9937 struct hash_control * htab)
b99bd4ef 9938{
a737bd4d
NC
9939 int len = strlen (r->name) + 2;
9940 char * buf = xmalloc (len);
9941 char * buf2 = xmalloc (len);
9942 int i = 0;
b99bd4ef 9943
a737bd4d
NC
9944#ifdef REGISTER_PREFIX
9945 buf[i++] = REGISTER_PREFIX;
9946#endif
9947
9948 strcpy (buf + i, r->name);
9949
9950 for (i = 0; buf[i]; i++)
9951 buf2[i] = TOUPPER (buf[i]);
9952
9953 buf2[i] = '\0';
9954
9955 hash_insert (htab, buf, (PTR) r);
9956 hash_insert (htab, buf2, (PTR) r);
b99bd4ef
NC
9957}
9958
9959static void
a737bd4d 9960build_reg_hsh (struct reg_map * map)
b99bd4ef 9961{
a737bd4d
NC
9962 const struct reg_entry *r;
9963
9964 if ((map->htab = hash_new ()) == NULL)
9965 as_fatal (_("virtual memory exhausted"));
9966
9967 for (r = map->names; r->name != NULL; r++)
9968 insert_reg (r, map->htab);
b99bd4ef
NC
9969}
9970
9971static void
a737bd4d
NC
9972insert_reg_alias (char * str,
9973 int regnum,
9974 struct hash_control *htab)
b99bd4ef 9975{
a737bd4d
NC
9976 const char * error;
9977 struct reg_entry * new = xmalloc (sizeof (struct reg_entry));
9978 const char * name = xmalloc (strlen (str) + 1);
9979
9980 strcpy ((char *) name, str);
9981
9982 new->name = name;
9983 new->number = regnum;
9984 new->builtin = FALSE;
9985
9986 error = hash_insert (htab, name, (PTR) new);
9987 if (error)
9988 {
9989 as_bad (_("failed to create an alias for %s, reason: %s"),
9990 str, error);
9991 free ((char *) name);
9992 free (new);
9993 }
b99bd4ef
NC
9994}
9995
a737bd4d 9996/* Look for the .req directive. This is of the form:
b99bd4ef 9997
a737bd4d
NC
9998 new_register_name .req existing_register_name
9999
10000 If we find one, or if it looks sufficiently like one that we want to
10001 handle any error here, return non-zero. Otherwise return zero. */
10002
10003static int
10004create_register_alias (char * newname, char * p)
b99bd4ef 10005{
a737bd4d
NC
10006 char * q;
10007 char c;
b99bd4ef 10008
a737bd4d
NC
10009 q = p;
10010 skip_whitespace (q);
b99bd4ef 10011
a737bd4d
NC
10012 c = *p;
10013 *p = '\0';
b99bd4ef 10014
a737bd4d
NC
10015 if (*q && !strncmp (q, ".req ", 5))
10016 {
10017 char *copy_of_str;
10018 char *r;
b99bd4ef 10019
a737bd4d
NC
10020#ifndef IGNORE_OPCODE_CASE
10021 newname = original_case_string;
10022#endif
10023 copy_of_str = newname;
b99bd4ef 10024
a737bd4d
NC
10025 q += 4;
10026 skip_whitespace (q);
b99bd4ef 10027
a737bd4d
NC
10028 for (r = q; *r != '\0'; r++)
10029 if (*r == ' ')
10030 break;
b99bd4ef 10031
a737bd4d
NC
10032 if (r != q)
10033 {
10034 enum arm_reg_type new_type, old_type;
10035 int old_regno;
10036 char d = *r;
b99bd4ef 10037
a737bd4d
NC
10038 *r = '\0';
10039 old_type = arm_reg_parse_any (q);
10040 *r = d;
10041
10042 new_type = arm_reg_parse_any (newname);
10043
10044 if (new_type == REG_TYPE_MAX)
10045 {
10046 if (old_type != REG_TYPE_MAX)
10047 {
10048 old_regno = arm_reg_parse (&q, all_reg_maps[old_type].htab);
10049 insert_reg_alias (newname, old_regno,
10050 all_reg_maps[old_type].htab);
10051 }
10052 else
10053 as_warn (_("register '%s' does not exist\n"), q);
10054 }
10055 else if (old_type == REG_TYPE_MAX)
10056 {
10057 as_warn (_("ignoring redefinition of register alias '%s' to non-existant register '%s'"),
10058 copy_of_str, q);
10059 }
10060 else
10061 {
10062 /* Do not warn about redefinitions to the same alias. */
10063 if (new_type != old_type
10064 || (arm_reg_parse (&q, all_reg_maps[old_type].htab)
10065 != arm_reg_parse (&q, all_reg_maps[new_type].htab)))
10066 as_warn (_("ignoring redefinition of register alias '%s'"),
10067 copy_of_str);
10068
10069 }
10070 }
10071 else
10072 as_warn (_("ignoring incomplete .req pseuso op"));
10073
10074 *p = c;
10075 return 1;
10076 }
10077
10078 *p = c;
10079 return 0;
b99bd4ef
NC
10080}
10081
10082static void
a737bd4d 10083set_constant_flonums (void)
b99bd4ef 10084{
a737bd4d 10085 int i;
b99bd4ef 10086
a737bd4d
NC
10087 for (i = 0; i < NUM_FLOAT_VALS; i++)
10088 if (atof_ieee ((char *) fp_const[i], 'x', fp_values[i]) == NULL)
10089 abort ();
b99bd4ef
NC
10090}
10091
a737bd4d
NC
10092\f
10093static const struct asm_opcode insns[] =
b99bd4ef 10094{
a737bd4d
NC
10095 /* Core ARM Instructions. */
10096 {"and", 0xe0000000, 3, ARM_EXT_V1, do_arit},
10097 {"ands", 0xe0100000, 3, ARM_EXT_V1, do_arit},
10098 {"eor", 0xe0200000, 3, ARM_EXT_V1, do_arit},
10099 {"eors", 0xe0300000, 3, ARM_EXT_V1, do_arit},
10100 {"sub", 0xe0400000, 3, ARM_EXT_V1, do_arit},
10101 {"subs", 0xe0500000, 3, ARM_EXT_V1, do_arit},
10102 {"rsb", 0xe0600000, 3, ARM_EXT_V1, do_arit},
10103 {"rsbs", 0xe0700000, 3, ARM_EXT_V1, do_arit},
10104 {"add", 0xe0800000, 3, ARM_EXT_V1, do_arit},
10105 {"adds", 0xe0900000, 3, ARM_EXT_V1, do_arit},
10106 {"adc", 0xe0a00000, 3, ARM_EXT_V1, do_arit},
10107 {"adcs", 0xe0b00000, 3, ARM_EXT_V1, do_arit},
10108 {"sbc", 0xe0c00000, 3, ARM_EXT_V1, do_arit},
10109 {"sbcs", 0xe0d00000, 3, ARM_EXT_V1, do_arit},
10110 {"rsc", 0xe0e00000, 3, ARM_EXT_V1, do_arit},
10111 {"rscs", 0xe0f00000, 3, ARM_EXT_V1, do_arit},
10112 {"orr", 0xe1800000, 3, ARM_EXT_V1, do_arit},
10113 {"orrs", 0xe1900000, 3, ARM_EXT_V1, do_arit},
10114 {"bic", 0xe1c00000, 3, ARM_EXT_V1, do_arit},
10115 {"bics", 0xe1d00000, 3, ARM_EXT_V1, do_arit},
10116
10117 {"tst", 0xe1100000, 3, ARM_EXT_V1, do_cmp},
10118 {"tsts", 0xe1100000, 3, ARM_EXT_V1, do_cmp},
10119 {"tstp", 0xe110f000, 3, ARM_EXT_V1, do_cmp},
10120 {"teq", 0xe1300000, 3, ARM_EXT_V1, do_cmp},
10121 {"teqs", 0xe1300000, 3, ARM_EXT_V1, do_cmp},
10122 {"teqp", 0xe130f000, 3, ARM_EXT_V1, do_cmp},
10123 {"cmp", 0xe1500000, 3, ARM_EXT_V1, do_cmp},
10124 {"cmps", 0xe1500000, 3, ARM_EXT_V1, do_cmp},
10125 {"cmpp", 0xe150f000, 3, ARM_EXT_V1, do_cmp},
10126 {"cmn", 0xe1700000, 3, ARM_EXT_V1, do_cmp},
10127 {"cmns", 0xe1700000, 3, ARM_EXT_V1, do_cmp},
10128 {"cmnp", 0xe170f000, 3, ARM_EXT_V1, do_cmp},
10129
10130 {"mov", 0xe1a00000, 3, ARM_EXT_V1, do_mov},
10131 {"movs", 0xe1b00000, 3, ARM_EXT_V1, do_mov},
10132 {"mvn", 0xe1e00000, 3, ARM_EXT_V1, do_mov},
10133 {"mvns", 0xe1f00000, 3, ARM_EXT_V1, do_mov},
10134
10135 {"ldr", 0xe4100000, 3, ARM_EXT_V1, do_ldst},
10136 {"ldrb", 0xe4500000, 3, ARM_EXT_V1, do_ldst},
10137 {"ldrt", 0xe4300000, 3, ARM_EXT_V1, do_ldstt},
10138 {"ldrbt", 0xe4700000, 3, ARM_EXT_V1, do_ldstt},
10139 {"str", 0xe4000000, 3, ARM_EXT_V1, do_ldst},
10140 {"strb", 0xe4400000, 3, ARM_EXT_V1, do_ldst},
10141 {"strt", 0xe4200000, 3, ARM_EXT_V1, do_ldstt},
10142 {"strbt", 0xe4600000, 3, ARM_EXT_V1, do_ldstt},
10143
10144 {"stmia", 0xe8800000, 3, ARM_EXT_V1, do_ldmstm},
10145 {"stmib", 0xe9800000, 3, ARM_EXT_V1, do_ldmstm},
10146 {"stmda", 0xe8000000, 3, ARM_EXT_V1, do_ldmstm},
10147 {"stmdb", 0xe9000000, 3, ARM_EXT_V1, do_ldmstm},
10148 {"stmfd", 0xe9000000, 3, ARM_EXT_V1, do_ldmstm},
10149 {"stmfa", 0xe9800000, 3, ARM_EXT_V1, do_ldmstm},
10150 {"stmea", 0xe8800000, 3, ARM_EXT_V1, do_ldmstm},
10151 {"stmed", 0xe8000000, 3, ARM_EXT_V1, do_ldmstm},
10152
10153 {"ldmia", 0xe8900000, 3, ARM_EXT_V1, do_ldmstm},
10154 {"ldmib", 0xe9900000, 3, ARM_EXT_V1, do_ldmstm},
10155 {"ldmda", 0xe8100000, 3, ARM_EXT_V1, do_ldmstm},
10156 {"ldmdb", 0xe9100000, 3, ARM_EXT_V1, do_ldmstm},
10157 {"ldmfd", 0xe8900000, 3, ARM_EXT_V1, do_ldmstm},
10158 {"ldmfa", 0xe8100000, 3, ARM_EXT_V1, do_ldmstm},
10159 {"ldmea", 0xe9100000, 3, ARM_EXT_V1, do_ldmstm},
10160 {"ldmed", 0xe9900000, 3, ARM_EXT_V1, do_ldmstm},
b99bd4ef 10161
a737bd4d
NC
10162 {"swi", 0xef000000, 3, ARM_EXT_V1, do_swi},
10163#ifdef TE_WINCE
10164 /* XXX This is the wrong place to do this. Think multi-arch. */
10165 {"bl", 0xeb000000, 2, ARM_EXT_V1, do_branch},
10166 {"b", 0xea000000, 1, ARM_EXT_V1, do_branch},
10167#else
10168 {"bl", 0xebfffffe, 2, ARM_EXT_V1, do_branch},
10169 {"b", 0xeafffffe, 1, ARM_EXT_V1, do_branch},
10170#endif
b99bd4ef 10171
a737bd4d
NC
10172 /* Pseudo ops. */
10173 {"adr", 0xe28f0000, 3, ARM_EXT_V1, do_adr},
10174 {"adrl", 0xe28f0000, 3, ARM_EXT_V1, do_adrl},
0dd132b6 10175 {"nop", 0xe1a00000, 3, ARM_EXT_V1, do_nop},
b99bd4ef 10176
a737bd4d
NC
10177 /* ARM 2 multiplies. */
10178 {"mul", 0xe0000090, 3, ARM_EXT_V2, do_mul},
10179 {"muls", 0xe0100090, 3, ARM_EXT_V2, do_mul},
10180 {"mla", 0xe0200090, 3, ARM_EXT_V2, do_mla},
10181 {"mlas", 0xe0300090, 3, ARM_EXT_V2, do_mla},
b99bd4ef 10182
a737bd4d
NC
10183 /* Generic coprocessor instructions. */
10184 {"cdp", 0xee000000, 3, ARM_EXT_V2, do_cdp},
10185 {"ldc", 0xec100000, 3, ARM_EXT_V2, do_lstc},
10186 {"ldcl", 0xec500000, 3, ARM_EXT_V2, do_lstc},
10187 {"stc", 0xec000000, 3, ARM_EXT_V2, do_lstc},
10188 {"stcl", 0xec400000, 3, ARM_EXT_V2, do_lstc},
10189 {"mcr", 0xee000010, 3, ARM_EXT_V2, do_co_reg},
10190 {"mrc", 0xee100010, 3, ARM_EXT_V2, do_co_reg},
b99bd4ef 10191
a737bd4d
NC
10192 /* ARM 3 - swp instructions. */
10193 {"swp", 0xe1000090, 3, ARM_EXT_V2S, do_swap},
10194 {"swpb", 0xe1400090, 3, ARM_EXT_V2S, do_swap},
b99bd4ef 10195
a737bd4d
NC
10196 /* ARM 6 Status register instructions. */
10197 {"mrs", 0xe10f0000, 3, ARM_EXT_V3, do_mrs},
10198 {"msr", 0xe120f000, 3, ARM_EXT_V3, do_msr},
10199 /* ScottB: our code uses 0xe128f000 for msr.
10200 NickC: but this is wrong because the bits 16 through 19 are
10201 handled by the PSR_xxx defines above. */
b99bd4ef 10202
a737bd4d
NC
10203 /* ARM 7M long multiplies. */
10204 {"smull", 0xe0c00090, 5, ARM_EXT_V3M, do_mull},
10205 {"smulls", 0xe0d00090, 5, ARM_EXT_V3M, do_mull},
10206 {"umull", 0xe0800090, 5, ARM_EXT_V3M, do_mull},
10207 {"umulls", 0xe0900090, 5, ARM_EXT_V3M, do_mull},
10208 {"smlal", 0xe0e00090, 5, ARM_EXT_V3M, do_mull},
10209 {"smlals", 0xe0f00090, 5, ARM_EXT_V3M, do_mull},
10210 {"umlal", 0xe0a00090, 5, ARM_EXT_V3M, do_mull},
10211 {"umlals", 0xe0b00090, 5, ARM_EXT_V3M, do_mull},
b99bd4ef 10212
a737bd4d
NC
10213 /* ARM Architecture 4. */
10214 {"ldrh", 0xe01000b0, 3, ARM_EXT_V4, do_ldstv4},
10215 {"ldrsh", 0xe01000f0, 3, ARM_EXT_V4, do_ldstv4},
10216 {"ldrsb", 0xe01000d0, 3, ARM_EXT_V4, do_ldstv4},
10217 {"strh", 0xe00000b0, 3, ARM_EXT_V4, do_ldstv4},
b99bd4ef 10218
a737bd4d
NC
10219 /* ARM Architecture 4T. */
10220 /* Note: bx (and blx) are required on V5, even if the processor does
10221 not support Thumb. */
10222 {"bx", 0xe12fff10, 2, ARM_EXT_V4T | ARM_EXT_V5, do_bx},
b99bd4ef 10223
a737bd4d
NC
10224 /* ARM Architecture 5T. */
10225 /* Note: blx has 2 variants, so the .value is set dynamically.
10226 Only one of the variants has conditional execution. */
10227 {"blx", 0xe0000000, 3, ARM_EXT_V5, do_blx},
10228 {"clz", 0xe16f0f10, 3, ARM_EXT_V5, do_clz},
10229 {"bkpt", 0xe1200070, 0, ARM_EXT_V5, do_bkpt},
10230 {"ldc2", 0xfc100000, 0, ARM_EXT_V5, do_lstc2},
10231 {"ldc2l", 0xfc500000, 0, ARM_EXT_V5, do_lstc2},
10232 {"stc2", 0xfc000000, 0, ARM_EXT_V5, do_lstc2},
10233 {"stc2l", 0xfc400000, 0, ARM_EXT_V5, do_lstc2},
10234 {"cdp2", 0xfe000000, 0, ARM_EXT_V5, do_cdp2},
10235 {"mcr2", 0xfe000010, 0, ARM_EXT_V5, do_co_reg2},
10236 {"mrc2", 0xfe100010, 0, ARM_EXT_V5, do_co_reg2},
b99bd4ef 10237
a737bd4d
NC
10238 /* ARM Architecture 5TExP. */
10239 {"smlabb", 0xe1000080, 6, ARM_EXT_V5ExP, do_smla},
10240 {"smlatb", 0xe10000a0, 6, ARM_EXT_V5ExP, do_smla},
10241 {"smlabt", 0xe10000c0, 6, ARM_EXT_V5ExP, do_smla},
10242 {"smlatt", 0xe10000e0, 6, ARM_EXT_V5ExP, do_smla},
b99bd4ef 10243
a737bd4d
NC
10244 {"smlawb", 0xe1200080, 6, ARM_EXT_V5ExP, do_smla},
10245 {"smlawt", 0xe12000c0, 6, ARM_EXT_V5ExP, do_smla},
b99bd4ef 10246
a737bd4d
NC
10247 {"smlalbb", 0xe1400080, 7, ARM_EXT_V5ExP, do_smlal},
10248 {"smlaltb", 0xe14000a0, 7, ARM_EXT_V5ExP, do_smlal},
10249 {"smlalbt", 0xe14000c0, 7, ARM_EXT_V5ExP, do_smlal},
10250 {"smlaltt", 0xe14000e0, 7, ARM_EXT_V5ExP, do_smlal},
b99bd4ef 10251
a737bd4d
NC
10252 {"smulbb", 0xe1600080, 6, ARM_EXT_V5ExP, do_smul},
10253 {"smultb", 0xe16000a0, 6, ARM_EXT_V5ExP, do_smul},
10254 {"smulbt", 0xe16000c0, 6, ARM_EXT_V5ExP, do_smul},
10255 {"smultt", 0xe16000e0, 6, ARM_EXT_V5ExP, do_smul},
b99bd4ef 10256
a737bd4d
NC
10257 {"smulwb", 0xe12000a0, 6, ARM_EXT_V5ExP, do_smul},
10258 {"smulwt", 0xe12000e0, 6, ARM_EXT_V5ExP, do_smul},
b99bd4ef 10259
a737bd4d
NC
10260 {"qadd", 0xe1000050, 4, ARM_EXT_V5ExP, do_qadd},
10261 {"qdadd", 0xe1400050, 5, ARM_EXT_V5ExP, do_qadd},
10262 {"qsub", 0xe1200050, 4, ARM_EXT_V5ExP, do_qadd},
10263 {"qdsub", 0xe1600050, 5, ARM_EXT_V5ExP, do_qadd},
b99bd4ef 10264
a737bd4d
NC
10265 /* ARM Architecture 5TE. */
10266 {"pld", 0xf450f000, 0, ARM_EXT_V5E, do_pld},
10267 {"ldrd", 0xe00000d0, 3, ARM_EXT_V5E, do_ldrd},
10268 {"strd", 0xe00000f0, 3, ARM_EXT_V5E, do_ldrd},
b99bd4ef 10269
a737bd4d
NC
10270 {"mcrr", 0xec400000, 4, ARM_EXT_V5E, do_co_reg2c},
10271 {"mrrc", 0xec500000, 4, ARM_EXT_V5E, do_co_reg2c},
b99bd4ef 10272
a737bd4d
NC
10273 /* ARM Architecture 5TEJ. */
10274 {"bxj", 0xe12fff20, 3, ARM_EXT_V5J, do_bxj},
b99bd4ef 10275
a737bd4d
NC
10276 /* ARM V6. */
10277 { "cps", 0xf1020000, 0, ARM_EXT_V6, do_cps},
10278 { "cpsie", 0xf1080000, 0, ARM_EXT_V6, do_cpsi},
10279 { "cpsid", 0xf10C0000, 0, ARM_EXT_V6, do_cpsi},
10280 { "ldrex", 0xe1900f9f, 5, ARM_EXT_V6, do_ldrex},
10281 { "mcrr2", 0xfc400000, 0, ARM_EXT_V6, do_co_reg2c},
10282 { "mrrc2", 0xfc500000, 0, ARM_EXT_V6, do_co_reg2c},
10283 { "pkhbt", 0xe6800010, 5, ARM_EXT_V6, do_pkhbt},
10284 { "pkhtb", 0xe6800050, 5, ARM_EXT_V6, do_pkhtb},
10285 { "qadd16", 0xe6200f10, 6, ARM_EXT_V6, do_qadd16},
10286 { "qadd8", 0xe6200f90, 5, ARM_EXT_V6, do_qadd16},
10287 { "qaddsubx", 0xe6200f30, 8, ARM_EXT_V6, do_qadd16},
10288 { "qsub16", 0xe6200f70, 6, ARM_EXT_V6, do_qadd16},
10289 { "qsub8", 0xe6200ff0, 5, ARM_EXT_V6, do_qadd16},
10290 { "qsubaddx", 0xe6200f50, 8, ARM_EXT_V6, do_qadd16},
10291 { "sadd16", 0xe6100f10, 6, ARM_EXT_V6, do_qadd16},
10292 { "sadd8", 0xe6100f90, 5, ARM_EXT_V6, do_qadd16},
10293 { "saddsubx", 0xe6100f30, 8, ARM_EXT_V6, do_qadd16},
10294 { "shadd16", 0xe6300f10, 7, ARM_EXT_V6, do_qadd16},
10295 { "shadd8", 0xe6300f90, 6, ARM_EXT_V6, do_qadd16},
10296 { "shaddsubx", 0xe6300f30, 9, ARM_EXT_V6, do_qadd16},
10297 { "shsub16", 0xe6300f70, 7, ARM_EXT_V6, do_qadd16},
10298 { "shsub8", 0xe6300ff0, 6, ARM_EXT_V6, do_qadd16},
10299 { "shsubaddx", 0xe6300f50, 9, ARM_EXT_V6, do_qadd16},
10300 { "ssub16", 0xe6100f70, 6, ARM_EXT_V6, do_qadd16},
10301 { "ssub8", 0xe6100ff0, 5, ARM_EXT_V6, do_qadd16},
10302 { "ssubaddx", 0xe6100f50, 8, ARM_EXT_V6, do_qadd16},
10303 { "uadd16", 0xe6500f10, 6, ARM_EXT_V6, do_qadd16},
10304 { "uadd8", 0xe6500f90, 5, ARM_EXT_V6, do_qadd16},
10305 { "uaddsubx", 0xe6500f30, 8, ARM_EXT_V6, do_qadd16},
10306 { "uhadd16", 0xe6700f10, 7, ARM_EXT_V6, do_qadd16},
10307 { "uhadd8", 0xe6700f90, 6, ARM_EXT_V6, do_qadd16},
10308 { "uhaddsubx", 0xe6700f30, 9, ARM_EXT_V6, do_qadd16},
10309 { "uhsub16", 0xe6700f70, 7, ARM_EXT_V6, do_qadd16},
10310 { "uhsub8", 0xe6700ff0, 6, ARM_EXT_V6, do_qadd16},
10311 { "uhsubaddx", 0xe6700f50, 9, ARM_EXT_V6, do_qadd16},
10312 { "uqadd16", 0xe6600f10, 7, ARM_EXT_V6, do_qadd16},
10313 { "uqadd8", 0xe6600f90, 6, ARM_EXT_V6, do_qadd16},
10314 { "uqaddsubx", 0xe6600f30, 9, ARM_EXT_V6, do_qadd16},
10315 { "uqsub16", 0xe6600f70, 7, ARM_EXT_V6, do_qadd16},
10316 { "uqsub8", 0xe6600ff0, 6, ARM_EXT_V6, do_qadd16},
10317 { "uqsubaddx", 0xe6600f50, 9, ARM_EXT_V6, do_qadd16},
10318 { "usub16", 0xe6500f70, 6, ARM_EXT_V6, do_qadd16},
10319 { "usub8", 0xe6500ff0, 5, ARM_EXT_V6, do_qadd16},
10320 { "usubaddx", 0xe6500f50, 8, ARM_EXT_V6, do_qadd16},
10321 { "rev", 0xe6bf0f30, 3, ARM_EXT_V6, do_rev},
10322 { "rev16", 0xe6bf0fb0, 5, ARM_EXT_V6, do_rev},
10323 { "revsh", 0xe6ff0fb0, 5, ARM_EXT_V6, do_rev},
10324 { "rfeia", 0xf8900a00, 0, ARM_EXT_V6, do_rfe},
10325 { "rfeib", 0xf9900a00, 0, ARM_EXT_V6, do_rfe},
10326 { "rfeda", 0xf8100a00, 0, ARM_EXT_V6, do_rfe},
10327 { "rfedb", 0xf9100a00, 0, ARM_EXT_V6, do_rfe},
10328 { "rfefd", 0xf8900a00, 0, ARM_EXT_V6, do_rfe},
10329 { "rfefa", 0xf9900a00, 0, ARM_EXT_V6, do_rfe},
10330 { "rfeea", 0xf8100a00, 0, ARM_EXT_V6, do_rfe},
10331 { "rfeed", 0xf9100a00, 0, ARM_EXT_V6, do_rfe},
10332 { "sxtah", 0xe6b00070, 5, ARM_EXT_V6, do_sxtah},
10333 { "sxtab16", 0xe6800070, 7, ARM_EXT_V6, do_sxtah},
10334 { "sxtab", 0xe6a00070, 5, ARM_EXT_V6, do_sxtah},
10335 { "sxth", 0xe6bf0070, 4, ARM_EXT_V6, do_sxth},
10336 { "sxtb16", 0xe68f0070, 6, ARM_EXT_V6, do_sxth},
10337 { "sxtb", 0xe6af0070, 4, ARM_EXT_V6, do_sxth},
10338 { "uxtah", 0xe6f00070, 5, ARM_EXT_V6, do_sxtah},
10339 { "uxtab16", 0xe6c00070, 7, ARM_EXT_V6, do_sxtah},
10340 { "uxtab", 0xe6e00070, 5, ARM_EXT_V6, do_sxtah},
10341 { "uxth", 0xe6ff0070, 4, ARM_EXT_V6, do_sxth},
10342 { "uxtb16", 0xe6cf0070, 6, ARM_EXT_V6, do_sxth},
10343 { "uxtb", 0xe6ef0070, 4, ARM_EXT_V6, do_sxth},
10344 { "sel", 0xe68000b0, 3, ARM_EXT_V6, do_qadd16},
10345 { "setend", 0xf1010000, 0, ARM_EXT_V6, do_setend},
10346 { "smlad", 0xe7000010, 5, ARM_EXT_V6, do_smlad},
10347 { "smladx", 0xe7000030, 6, ARM_EXT_V6, do_smlad},
10348 { "smlald", 0xe7400010, 6, ARM_EXT_V6, do_smlald},
10349 { "smlaldx", 0xe7400030, 7, ARM_EXT_V6, do_smlald},
10350 { "smlsd", 0xe7000050, 5, ARM_EXT_V6, do_smlad},
10351 { "smlsdx", 0xe7000070, 6, ARM_EXT_V6, do_smlad},
10352 { "smlsld", 0xe7400050, 6, ARM_EXT_V6, do_smlald},
10353 { "smlsldx", 0xe7400070, 7, ARM_EXT_V6, do_smlald},
10354 { "smmla", 0xe7500010, 5, ARM_EXT_V6, do_smlad},
10355 { "smmlar", 0xe7500030, 6, ARM_EXT_V6, do_smlad},
10356 { "smmls", 0xe75000d0, 5, ARM_EXT_V6, do_smlad},
10357 { "smmlsr", 0xe75000f0, 6, ARM_EXT_V6, do_smlad},
10358 { "smmul", 0xe750f010, 5, ARM_EXT_V6, do_smmul},
10359 { "smmulr", 0xe750f030, 6, ARM_EXT_V6, do_smmul},
10360 { "smuad", 0xe700f010, 5, ARM_EXT_V6, do_smmul},
10361 { "smuadx", 0xe700f030, 6, ARM_EXT_V6, do_smmul},
10362 { "smusd", 0xe700f050, 5, ARM_EXT_V6, do_smmul},
10363 { "smusdx", 0xe700f070, 6, ARM_EXT_V6, do_smmul},
10364 { "srsia", 0xf8cd0500, 0, ARM_EXT_V6, do_srs},
10365 { "srsib", 0xf9cd0500, 0, ARM_EXT_V6, do_srs},
10366 { "srsda", 0xf84d0500, 0, ARM_EXT_V6, do_srs},
10367 { "srsdb", 0xf94d0500, 0, ARM_EXT_V6, do_srs},
10368 { "ssat", 0xe6a00010, 4, ARM_EXT_V6, do_ssat},
10369 { "ssat16", 0xe6a00f30, 6, ARM_EXT_V6, do_ssat16},
10370 { "strex", 0xe1800f90, 5, ARM_EXT_V6, do_strex},
10371 { "umaal", 0xe0400090, 5, ARM_EXT_V6, do_umaal},
10372 { "usad8", 0xe780f010, 5, ARM_EXT_V6, do_smmul},
10373 { "usada8", 0xe7800010, 6, ARM_EXT_V6, do_smlad},
10374 { "usat", 0xe6e00010, 4, ARM_EXT_V6, do_usat},
10375 { "usat16", 0xe6e00f30, 6, ARM_EXT_V6, do_usat16},
b99bd4ef 10376
0dd132b6
NC
10377 /* ARM V6K. */
10378 { "clrex", 0xf57ff01f, 0, ARM_EXT_V6K, do_empty},
10379 { "ldrexb", 0xe1d00f9f, 6, ARM_EXT_V6K, do_ldrex},
10380 { "ldrexd", 0xe1b00f9f, 6, ARM_EXT_V6K, do_ldrex},
10381 { "ldrexh", 0xe1f00f9f, 6, ARM_EXT_V6K, do_ldrex},
10382 { "sev", 0xe320f004, 3, ARM_EXT_V6K, do_empty},
10383 { "strexb", 0xe1c00f90, 6, ARM_EXT_V6K, do_strex},
10384 { "strexd", 0xe1a00f90, 6, ARM_EXT_V6K, do_strex},
10385 { "strexh", 0xe1e00f90, 6, ARM_EXT_V6K, do_strex},
10386 { "wfe", 0xe320f002, 3, ARM_EXT_V6K, do_empty},
10387 { "wfi", 0xe320f003, 3, ARM_EXT_V6K, do_empty},
10388 { "yield", 0xe320f001, 5, ARM_EXT_V6K, do_empty},
7ed4c4c5 10389
0dd132b6
NC
10390 /* ARM V6Z. */
10391 { "smi", 0xe1600070, 3, ARM_EXT_V6Z, do_smi},
10392
b05fe5cf
ZW
10393 /* ARM V6T2. */
10394 { "bfc", 0xe7c0001f, 3, ARM_EXT_V6T2, do_bfc},
10395 { "bfi", 0xe7c00010, 3, ARM_EXT_V6T2, do_bfi},
10396 { "mls", 0xe0600090, 3, ARM_EXT_V6T2, do_mls},
10397 { "movw", 0xe3000000, 4, ARM_EXT_V6T2, do_mov16},
10398 { "movt", 0xe3400000, 4, ARM_EXT_V6T2, do_mov16},
10399 { "rbit", 0xe3ff0f30, 4, ARM_EXT_V6T2, do_rbit},
10400 { "sbfx", 0xe7a00050, 4, ARM_EXT_V6T2, do_bfx},
10401 { "ubfx", 0xe7e00050, 4, ARM_EXT_V6T2, do_bfx},
10402
10403 { "ldrht", 0xe03000b0, 3, ARM_EXT_V6T2, do_ldsttv4},
10404 { "ldrsht", 0xe03000f0, 3, ARM_EXT_V6T2, do_ldsttv4},
10405 { "ldrsbt", 0xe03000d0, 3, ARM_EXT_V6T2, do_ldsttv4},
10406 { "strht", 0xe02000b0, 3, ARM_EXT_V6T2, do_ldsttv4},
10407
a737bd4d
NC
10408 /* Core FPA instruction set (V1). */
10409 {"wfs", 0xee200110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
10410 {"rfs", 0xee300110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
10411 {"wfc", 0xee400110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
10412 {"rfc", 0xee500110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
b99bd4ef 10413
a737bd4d
NC
10414 {"ldfs", 0xec100100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10415 {"ldfd", 0xec108100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10416 {"ldfe", 0xec500100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10417 {"ldfp", 0xec508100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
b99bd4ef 10418
a737bd4d
NC
10419 {"stfs", 0xec000100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10420 {"stfd", 0xec008100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10421 {"stfe", 0xec400100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10422 {"stfp", 0xec408100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
b99bd4ef 10423
a737bd4d
NC
10424 {"mvfs", 0xee008100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10425 {"mvfsp", 0xee008120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10426 {"mvfsm", 0xee008140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10427 {"mvfsz", 0xee008160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10428 {"mvfd", 0xee008180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10429 {"mvfdp", 0xee0081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10430 {"mvfdm", 0xee0081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10431 {"mvfdz", 0xee0081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10432 {"mvfe", 0xee088100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10433 {"mvfep", 0xee088120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10434 {"mvfem", 0xee088140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10435 {"mvfez", 0xee088160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10436
a737bd4d
NC
10437 {"mnfs", 0xee108100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10438 {"mnfsp", 0xee108120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10439 {"mnfsm", 0xee108140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10440 {"mnfsz", 0xee108160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10441 {"mnfd", 0xee108180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10442 {"mnfdp", 0xee1081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10443 {"mnfdm", 0xee1081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10444 {"mnfdz", 0xee1081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10445 {"mnfe", 0xee188100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10446 {"mnfep", 0xee188120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10447 {"mnfem", 0xee188140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10448 {"mnfez", 0xee188160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10449
a737bd4d
NC
10450 {"abss", 0xee208100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10451 {"abssp", 0xee208120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10452 {"abssm", 0xee208140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10453 {"abssz", 0xee208160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10454 {"absd", 0xee208180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10455 {"absdp", 0xee2081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10456 {"absdm", 0xee2081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10457 {"absdz", 0xee2081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10458 {"abse", 0xee288100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10459 {"absep", 0xee288120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10460 {"absem", 0xee288140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10461 {"absez", 0xee288160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10462
a737bd4d
NC
10463 {"rnds", 0xee308100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10464 {"rndsp", 0xee308120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10465 {"rndsm", 0xee308140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10466 {"rndsz", 0xee308160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10467 {"rndd", 0xee308180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10468 {"rnddp", 0xee3081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10469 {"rnddm", 0xee3081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10470 {"rnddz", 0xee3081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10471 {"rnde", 0xee388100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10472 {"rndep", 0xee388120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10473 {"rndem", 0xee388140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10474 {"rndez", 0xee388160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10475
a737bd4d
NC
10476 {"sqts", 0xee408100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10477 {"sqtsp", 0xee408120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10478 {"sqtsm", 0xee408140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10479 {"sqtsz", 0xee408160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10480 {"sqtd", 0xee408180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10481 {"sqtdp", 0xee4081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10482 {"sqtdm", 0xee4081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10483 {"sqtdz", 0xee4081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10484 {"sqte", 0xee488100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10485 {"sqtep", 0xee488120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10486 {"sqtem", 0xee488140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10487 {"sqtez", 0xee488160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10488
a737bd4d
NC
10489 {"logs", 0xee508100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10490 {"logsp", 0xee508120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10491 {"logsm", 0xee508140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10492 {"logsz", 0xee508160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10493 {"logd", 0xee508180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10494 {"logdp", 0xee5081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10495 {"logdm", 0xee5081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10496 {"logdz", 0xee5081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10497 {"loge", 0xee588100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10498 {"logep", 0xee588120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10499 {"logem", 0xee588140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10500 {"logez", 0xee588160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10501
a737bd4d
NC
10502 {"lgns", 0xee608100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10503 {"lgnsp", 0xee608120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10504 {"lgnsm", 0xee608140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10505 {"lgnsz", 0xee608160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10506 {"lgnd", 0xee608180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10507 {"lgndp", 0xee6081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10508 {"lgndm", 0xee6081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10509 {"lgndz", 0xee6081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10510 {"lgne", 0xee688100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10511 {"lgnep", 0xee688120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10512 {"lgnem", 0xee688140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10513 {"lgnez", 0xee688160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10514
a737bd4d
NC
10515 {"exps", 0xee708100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10516 {"expsp", 0xee708120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10517 {"expsm", 0xee708140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10518 {"expsz", 0xee708160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10519 {"expd", 0xee708180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10520 {"expdp", 0xee7081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10521 {"expdm", 0xee7081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10522 {"expdz", 0xee7081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10523 {"expe", 0xee788100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10524 {"expep", 0xee788120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10525 {"expem", 0xee788140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10526 {"expdz", 0xee788160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10527
a737bd4d
NC
10528 {"sins", 0xee808100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10529 {"sinsp", 0xee808120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10530 {"sinsm", 0xee808140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10531 {"sinsz", 0xee808160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10532 {"sind", 0xee808180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10533 {"sindp", 0xee8081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10534 {"sindm", 0xee8081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10535 {"sindz", 0xee8081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10536 {"sine", 0xee888100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10537 {"sinep", 0xee888120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10538 {"sinem", 0xee888140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10539 {"sinez", 0xee888160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10540
a737bd4d
NC
10541 {"coss", 0xee908100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10542 {"cossp", 0xee908120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10543 {"cossm", 0xee908140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10544 {"cossz", 0xee908160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10545 {"cosd", 0xee908180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10546 {"cosdp", 0xee9081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10547 {"cosdm", 0xee9081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10548 {"cosdz", 0xee9081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10549 {"cose", 0xee988100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10550 {"cosep", 0xee988120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10551 {"cosem", 0xee988140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10552 {"cosez", 0xee988160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10553
a737bd4d
NC
10554 {"tans", 0xeea08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10555 {"tansp", 0xeea08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10556 {"tansm", 0xeea08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10557 {"tansz", 0xeea08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10558 {"tand", 0xeea08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10559 {"tandp", 0xeea081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10560 {"tandm", 0xeea081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10561 {"tandz", 0xeea081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10562 {"tane", 0xeea88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10563 {"tanep", 0xeea88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10564 {"tanem", 0xeea88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10565 {"tanez", 0xeea88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10566
a737bd4d
NC
10567 {"asns", 0xeeb08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10568 {"asnsp", 0xeeb08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10569 {"asnsm", 0xeeb08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10570 {"asnsz", 0xeeb08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10571 {"asnd", 0xeeb08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10572 {"asndp", 0xeeb081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10573 {"asndm", 0xeeb081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10574 {"asndz", 0xeeb081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10575 {"asne", 0xeeb88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10576 {"asnep", 0xeeb88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10577 {"asnem", 0xeeb88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10578 {"asnez", 0xeeb88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10579
a737bd4d
NC
10580 {"acss", 0xeec08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10581 {"acssp", 0xeec08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10582 {"acssm", 0xeec08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10583 {"acssz", 0xeec08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10584 {"acsd", 0xeec08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10585 {"acsdp", 0xeec081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10586 {"acsdm", 0xeec081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10587 {"acsdz", 0xeec081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10588 {"acse", 0xeec88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10589 {"acsep", 0xeec88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10590 {"acsem", 0xeec88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10591 {"acsez", 0xeec88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10592
a737bd4d
NC
10593 {"atns", 0xeed08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10594 {"atnsp", 0xeed08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10595 {"atnsm", 0xeed08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10596 {"atnsz", 0xeed08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10597 {"atnd", 0xeed08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10598 {"atndp", 0xeed081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10599 {"atndm", 0xeed081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10600 {"atndz", 0xeed081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10601 {"atne", 0xeed88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10602 {"atnep", 0xeed88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10603 {"atnem", 0xeed88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10604 {"atnez", 0xeed88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10605
a737bd4d
NC
10606 {"urds", 0xeee08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10607 {"urdsp", 0xeee08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10608 {"urdsm", 0xeee08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10609 {"urdsz", 0xeee08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10610 {"urdd", 0xeee08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10611 {"urddp", 0xeee081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10612 {"urddm", 0xeee081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10613 {"urddz", 0xeee081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10614 {"urde", 0xeee88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10615 {"urdep", 0xeee88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10616 {"urdem", 0xeee88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10617 {"urdez", 0xeee88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10618
a737bd4d
NC
10619 {"nrms", 0xeef08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10620 {"nrmsp", 0xeef08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10621 {"nrmsm", 0xeef08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10622 {"nrmsz", 0xeef08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10623 {"nrmd", 0xeef08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10624 {"nrmdp", 0xeef081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10625 {"nrmdm", 0xeef081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10626 {"nrmdz", 0xeef081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10627 {"nrme", 0xeef88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10628 {"nrmep", 0xeef88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10629 {"nrmem", 0xeef88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10630 {"nrmez", 0xeef88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10631
a737bd4d
NC
10632 {"adfs", 0xee000100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10633 {"adfsp", 0xee000120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10634 {"adfsm", 0xee000140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10635 {"adfsz", 0xee000160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10636 {"adfd", 0xee000180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10637 {"adfdp", 0xee0001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10638 {"adfdm", 0xee0001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10639 {"adfdz", 0xee0001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10640 {"adfe", 0xee080100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10641 {"adfep", 0xee080120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10642 {"adfem", 0xee080140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10643 {"adfez", 0xee080160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
b99bd4ef 10644
a737bd4d
NC
10645 {"sufs", 0xee200100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10646 {"sufsp", 0xee200120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10647 {"sufsm", 0xee200140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10648 {"sufsz", 0xee200160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10649 {"sufd", 0xee200180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10650 {"sufdp", 0xee2001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10651 {"sufdm", 0xee2001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10652 {"sufdz", 0xee2001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10653 {"sufe", 0xee280100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10654 {"sufep", 0xee280120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10655 {"sufem", 0xee280140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10656 {"sufez", 0xee280160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
b99bd4ef 10657
a737bd4d
NC
10658 {"rsfs", 0xee300100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10659 {"rsfsp", 0xee300120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10660 {"rsfsm", 0xee300140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10661 {"rsfsz", 0xee300160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10662 {"rsfd", 0xee300180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10663 {"rsfdp", 0xee3001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10664 {"rsfdm", 0xee3001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10665 {"rsfdz", 0xee3001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10666 {"rsfe", 0xee380100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10667 {"rsfep", 0xee380120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10668 {"rsfem", 0xee380140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10669 {"rsfez", 0xee380160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
b99bd4ef 10670
a737bd4d
NC
10671 {"mufs", 0xee100100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10672 {"mufsp", 0xee100120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10673 {"mufsm", 0xee100140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10674 {"mufsz", 0xee100160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10675 {"mufd", 0xee100180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10676 {"mufdp", 0xee1001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10677 {"mufdm", 0xee1001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10678 {"mufdz", 0xee1001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10679 {"mufe", 0xee180100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10680 {"mufep", 0xee180120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10681 {"mufem", 0xee180140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10682 {"mufez", 0xee180160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
b99bd4ef 10683
a737bd4d
NC
10684 {"dvfs", 0xee400100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10685 {"dvfsp", 0xee400120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10686 {"dvfsm", 0xee400140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10687 {"dvfsz", 0xee400160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10688 {"dvfd", 0xee400180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10689 {"dvfdp", 0xee4001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10690 {"dvfdm", 0xee4001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10691 {"dvfdz", 0xee4001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10692 {"dvfe", 0xee480100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10693 {"dvfep", 0xee480120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10694 {"dvfem", 0xee480140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10695 {"dvfez", 0xee480160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
b99bd4ef 10696
a737bd4d
NC
10697 {"rdfs", 0xee500100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10698 {"rdfsp", 0xee500120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10699 {"rdfsm", 0xee500140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10700 {"rdfsz", 0xee500160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10701 {"rdfd", 0xee500180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10702 {"rdfdp", 0xee5001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10703 {"rdfdm", 0xee5001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10704 {"rdfdz", 0xee5001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10705 {"rdfe", 0xee580100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10706 {"rdfep", 0xee580120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10707 {"rdfem", 0xee580140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10708 {"rdfez", 0xee580160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
b99bd4ef 10709
a737bd4d
NC
10710 {"pows", 0xee600100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10711 {"powsp", 0xee600120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10712 {"powsm", 0xee600140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10713 {"powsz", 0xee600160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10714 {"powd", 0xee600180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10715 {"powdp", 0xee6001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10716 {"powdm", 0xee6001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10717 {"powdz", 0xee6001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10718 {"powe", 0xee680100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10719 {"powep", 0xee680120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10720 {"powem", 0xee680140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10721 {"powez", 0xee680160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
b99bd4ef 10722
a737bd4d
NC
10723 {"rpws", 0xee700100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10724 {"rpwsp", 0xee700120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10725 {"rpwsm", 0xee700140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10726 {"rpwsz", 0xee700160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10727 {"rpwd", 0xee700180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10728 {"rpwdp", 0xee7001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10729 {"rpwdm", 0xee7001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10730 {"rpwdz", 0xee7001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10731 {"rpwe", 0xee780100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10732 {"rpwep", 0xee780120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10733 {"rpwem", 0xee780140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10734 {"rpwez", 0xee780160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
b99bd4ef 10735
a737bd4d
NC
10736 {"rmfs", 0xee800100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10737 {"rmfsp", 0xee800120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10738 {"rmfsm", 0xee800140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10739 {"rmfsz", 0xee800160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10740 {"rmfd", 0xee800180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10741 {"rmfdp", 0xee8001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10742 {"rmfdm", 0xee8001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10743 {"rmfdz", 0xee8001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10744 {"rmfe", 0xee880100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10745 {"rmfep", 0xee880120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10746 {"rmfem", 0xee880140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10747 {"rmfez", 0xee880160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
b99bd4ef 10748
a737bd4d
NC
10749 {"fmls", 0xee900100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10750 {"fmlsp", 0xee900120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10751 {"fmlsm", 0xee900140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10752 {"fmlsz", 0xee900160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10753 {"fmld", 0xee900180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10754 {"fmldp", 0xee9001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10755 {"fmldm", 0xee9001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10756 {"fmldz", 0xee9001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10757 {"fmle", 0xee980100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10758 {"fmlep", 0xee980120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10759 {"fmlem", 0xee980140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10760 {"fmlez", 0xee980160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
6c43fab6 10761
a737bd4d
NC
10762 {"fdvs", 0xeea00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10763 {"fdvsp", 0xeea00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10764 {"fdvsm", 0xeea00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10765 {"fdvsz", 0xeea00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10766 {"fdvd", 0xeea00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10767 {"fdvdp", 0xeea001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10768 {"fdvdm", 0xeea001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10769 {"fdvdz", 0xeea001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10770 {"fdve", 0xeea80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10771 {"fdvep", 0xeea80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10772 {"fdvem", 0xeea80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10773 {"fdvez", 0xeea80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
6c43fab6 10774
a737bd4d
NC
10775 {"frds", 0xeeb00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10776 {"frdsp", 0xeeb00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10777 {"frdsm", 0xeeb00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10778 {"frdsz", 0xeeb00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10779 {"frdd", 0xeeb00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10780 {"frddp", 0xeeb001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10781 {"frddm", 0xeeb001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10782 {"frddz", 0xeeb001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10783 {"frde", 0xeeb80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10784 {"frdep", 0xeeb80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10785 {"frdem", 0xeeb80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10786 {"frdez", 0xeeb80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
6c43fab6 10787
a737bd4d
NC
10788 {"pols", 0xeec00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10789 {"polsp", 0xeec00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10790 {"polsm", 0xeec00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10791 {"polsz", 0xeec00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10792 {"pold", 0xeec00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10793 {"poldp", 0xeec001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10794 {"poldm", 0xeec001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10795 {"poldz", 0xeec001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10796 {"pole", 0xeec80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10797 {"polep", 0xeec80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10798 {"polem", 0xeec80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10799 {"polez", 0xeec80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
b99bd4ef 10800
a737bd4d
NC
10801 {"cmf", 0xee90f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
10802 {"cmfe", 0xeed0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
10803 {"cnf", 0xeeb0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
10804 {"cnfe", 0xeef0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
10805 /* The FPA10 data sheet suggests that the 'E' of cmfe/cnfe should
10806 not be an optional suffix, but part of the instruction. To be
10807 compatible, we accept either. */
10808 {"cmfe", 0xeed0f110, 4, FPU_FPA_EXT_V1, do_fpa_cmp},
10809 {"cnfe", 0xeef0f110, 4, FPU_FPA_EXT_V1, do_fpa_cmp},
b99bd4ef 10810
a737bd4d
NC
10811 {"flts", 0xee000110, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10812 {"fltsp", 0xee000130, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10813 {"fltsm", 0xee000150, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10814 {"fltsz", 0xee000170, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10815 {"fltd", 0xee000190, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10816 {"fltdp", 0xee0001b0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10817 {"fltdm", 0xee0001d0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10818 {"fltdz", 0xee0001f0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10819 {"flte", 0xee080110, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10820 {"fltep", 0xee080130, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10821 {"fltem", 0xee080150, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10822 {"fltez", 0xee080170, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
6c43fab6 10823
a737bd4d
NC
10824 /* The implementation of the FIX instruction is broken on some
10825 assemblers, in that it accepts a precision specifier as well as a
10826 rounding specifier, despite the fact that this is meaningless.
10827 To be more compatible, we accept it as well, though of course it
10828 does not set any bits. */
10829 {"fix", 0xee100110, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10830 {"fixp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10831 {"fixm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10832 {"fixz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10833 {"fixsp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10834 {"fixsm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10835 {"fixsz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10836 {"fixdp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10837 {"fixdm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10838 {"fixdz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10839 {"fixep", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10840 {"fixem", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10841 {"fixez", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
6c43fab6 10842
a737bd4d
NC
10843 /* Instructions that were new with the real FPA, call them V2. */
10844 {"lfm", 0xec100200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10845 {"lfmfd", 0xec900200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10846 {"lfmea", 0xed100200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10847 {"sfm", 0xec000200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10848 {"sfmfd", 0xed000200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10849 {"sfmea", 0xec800200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
6c43fab6 10850
a737bd4d
NC
10851 /* VFP V1xD (single precision). */
10852 /* Moves and type conversions. */
10853 {"fcpys", 0xeeb00a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10854 {"fmrs", 0xee100a10, 4, FPU_VFP_EXT_V1xD, do_vfp_reg_from_sp},
10855 {"fmsr", 0xee000a10, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_from_reg},
10856 {"fmstat", 0xeef1fa10, 6, FPU_VFP_EXT_V1xD, do_empty},
10857 {"fsitos", 0xeeb80ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10858 {"fuitos", 0xeeb80a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10859 {"ftosis", 0xeebd0a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10860 {"ftosizs", 0xeebd0ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10861 {"ftouis", 0xeebc0a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10862 {"ftouizs", 0xeebc0ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10863 {"fmrx", 0xeef00a10, 4, FPU_VFP_EXT_V1xD, do_vfp_reg_from_ctrl},
10864 {"fmxr", 0xeee00a10, 4, FPU_VFP_EXT_V1xD, do_vfp_ctrl_from_reg},
6c43fab6 10865
a737bd4d
NC
10866 /* Memory operations. */
10867 {"flds", 0xed100a00, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_ldst},
10868 {"fsts", 0xed000a00, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_ldst},
10869 {"fldmias", 0xec900a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
10870 {"fldmfds", 0xec900a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
10871 {"fldmdbs", 0xed300a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
10872 {"fldmeas", 0xed300a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
10873 {"fldmiax", 0xec900b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
10874 {"fldmfdx", 0xec900b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
10875 {"fldmdbx", 0xed300b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
10876 {"fldmeax", 0xed300b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
10877 {"fstmias", 0xec800a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
10878 {"fstmeas", 0xec800a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
10879 {"fstmdbs", 0xed200a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
10880 {"fstmfds", 0xed200a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
10881 {"fstmiax", 0xec800b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
10882 {"fstmeax", 0xec800b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
10883 {"fstmdbx", 0xed200b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
10884 {"fstmfdx", 0xed200b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
6c43fab6 10885
a737bd4d
NC
10886 /* Monadic operations. */
10887 {"fabss", 0xeeb00ac0, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10888 {"fnegs", 0xeeb10a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10889 {"fsqrts", 0xeeb10ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
6c43fab6 10890
a737bd4d
NC
10891 /* Dyadic operations. */
10892 {"fadds", 0xee300a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10893 {"fsubs", 0xee300a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10894 {"fmuls", 0xee200a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10895 {"fdivs", 0xee800a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10896 {"fmacs", 0xee000a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10897 {"fmscs", 0xee100a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10898 {"fnmuls", 0xee200a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10899 {"fnmacs", 0xee000a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10900 {"fnmscs", 0xee100a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
6c43fab6 10901
a737bd4d
NC
10902 /* Comparisons. */
10903 {"fcmps", 0xeeb40a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10904 {"fcmpzs", 0xeeb50a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_compare_z},
10905 {"fcmpes", 0xeeb40ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10906 {"fcmpezs", 0xeeb50ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_compare_z},
6c43fab6 10907
a737bd4d
NC
10908 /* VFP V1 (Double precision). */
10909 /* Moves and type conversions. */
10910 {"fcpyd", 0xeeb00b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10911 {"fcvtds", 0xeeb70ac0, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
10912 {"fcvtsd", 0xeeb70bc0, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
10913 {"fmdhr", 0xee200b10, 5, FPU_VFP_EXT_V1, do_vfp_dp_from_reg},
10914 {"fmdlr", 0xee000b10, 5, FPU_VFP_EXT_V1, do_vfp_dp_from_reg},
10915 {"fmrdh", 0xee300b10, 5, FPU_VFP_EXT_V1, do_vfp_reg_from_dp},
10916 {"fmrdl", 0xee100b10, 5, FPU_VFP_EXT_V1, do_vfp_reg_from_dp},
10917 {"fsitod", 0xeeb80bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
10918 {"fuitod", 0xeeb80b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
10919 {"ftosid", 0xeebd0b40, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
10920 {"ftosizd", 0xeebd0bc0, 7, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
10921 {"ftouid", 0xeebc0b40, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
10922 {"ftouizd", 0xeebc0bc0, 7, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
6c43fab6 10923
a737bd4d
NC
10924 /* Memory operations. */
10925 {"fldd", 0xed100b00, 4, FPU_VFP_EXT_V1, do_vfp_dp_ldst},
10926 {"fstd", 0xed000b00, 4, FPU_VFP_EXT_V1, do_vfp_dp_ldst},
10927 {"fldmiad", 0xec900b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
10928 {"fldmfdd", 0xec900b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
10929 {"fldmdbd", 0xed300b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
10930 {"fldmead", 0xed300b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
10931 {"fstmiad", 0xec800b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
10932 {"fstmead", 0xec800b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
10933 {"fstmdbd", 0xed200b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
10934 {"fstmfdd", 0xed200b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
6c43fab6 10935
a737bd4d
NC
10936 /* Monadic operations. */
10937 {"fabsd", 0xeeb00bc0, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10938 {"fnegd", 0xeeb10b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10939 {"fsqrtd", 0xeeb10bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
6c43fab6 10940
a737bd4d
NC
10941 /* Dyadic operations. */
10942 {"faddd", 0xee300b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10943 {"fsubd", 0xee300b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10944 {"fmuld", 0xee200b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10945 {"fdivd", 0xee800b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10946 {"fmacd", 0xee000b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10947 {"fmscd", 0xee100b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10948 {"fnmuld", 0xee200b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10949 {"fnmacd", 0xee000b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10950 {"fnmscd", 0xee100b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
6c43fab6 10951
a737bd4d
NC
10952 /* Comparisons. */
10953 {"fcmpd", 0xeeb40b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10954 {"fcmpzd", 0xeeb50b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_compare_z},
10955 {"fcmped", 0xeeb40bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10956 {"fcmpezd", 0xeeb50bc0, 7, FPU_VFP_EXT_V1, do_vfp_dp_compare_z},
6c43fab6 10957
a737bd4d
NC
10958 /* VFP V2. */
10959 {"fmsrr", 0xec400a10, 5, FPU_VFP_EXT_V2, do_vfp_sp2_from_reg2},
10960 {"fmrrs", 0xec500a10, 5, FPU_VFP_EXT_V2, do_vfp_reg2_from_sp2},
10961 {"fmdrr", 0xec400b10, 5, FPU_VFP_EXT_V2, do_vfp_dp_from_reg2},
10962 {"fmrrd", 0xec500b10, 5, FPU_VFP_EXT_V2, do_vfp_reg2_from_dp},
6c43fab6 10963
a737bd4d
NC
10964 /* Intel XScale extensions to ARM V5 ISA. (All use CP0). */
10965 {"mia", 0xee200010, 3, ARM_CEXT_XSCALE, do_xsc_mia},
10966 {"miaph", 0xee280010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
10967 {"miabb", 0xee2c0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
10968 {"miabt", 0xee2d0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
10969 {"miatb", 0xee2e0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
10970 {"miatt", 0xee2f0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
10971 {"mar", 0xec400000, 3, ARM_CEXT_XSCALE, do_xsc_mar},
10972 {"mra", 0xec500000, 3, ARM_CEXT_XSCALE, do_xsc_mra},
cc8a6dd0 10973
a737bd4d
NC
10974 /* Intel Wireless MMX technology instructions. */
10975 {"tandcb", 0xee130130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
10976 {"tandch", 0xee530130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
10977 {"tandcw", 0xee930130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
10978 {"tbcstb", 0xee400010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
10979 {"tbcsth", 0xee400050, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
10980 {"tbcstw", 0xee400090, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
10981 {"textrcb", 0xee130170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
10982 {"textrch", 0xee530170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
10983 {"textrcw", 0xee930170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
10984 {"textrmub", 0xee100070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10985 {"textrmuh", 0xee500070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10986 {"textrmuw", 0xee900070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10987 {"textrmsb", 0xee100078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10988 {"textrmsh", 0xee500078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10989 {"textrmsw", 0xee900078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10990 {"tinsrb", 0xee600010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
10991 {"tinsrh", 0xee600050, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
10992 {"tinsrw", 0xee600090, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
10993 {"tmcr", 0xee000110, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmcr},
10994 {"tmcrr", 0xec400000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_tmcrr},
10995 {"tmia", 0xee200010, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10996 {"tmiaph", 0xee280010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10997 {"tmiabb", 0xee2c0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10998 {"tmiabt", 0xee2d0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10999 {"tmiatb", 0xee2e0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
11000 {"tmiatt", 0xee2f0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
11001 {"tmovmskb", 0xee100030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
11002 {"tmovmskh", 0xee500030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
11003 {"tmovmskw", 0xee900030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
11004 {"tmrc", 0xee100110, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmrc},
11005 {"tmrrc", 0xec500000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_tmrrc},
11006 {"torcb", 0xee130150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
11007 {"torch", 0xee530150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
11008 {"torcw", 0xee930150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
11009 {"waccb", 0xee0001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11010 {"wacch", 0xee4001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11011 {"waccw", 0xee8001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11012 {"waddbss", 0xee300180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11013 {"waddb", 0xee000180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11014 {"waddbus", 0xee100180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11015 {"waddhss", 0xee700180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11016 {"waddh", 0xee400180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11017 {"waddhus", 0xee500180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11018 {"waddwss", 0xeeb00180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11019 {"waddw", 0xee800180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11020 {"waddwus", 0xee900180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11021 {"waligni", 0xee000020, 7, ARM_CEXT_IWMMXT, do_iwmmxt_waligni},
11022 {"walignr0", 0xee800020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11023 {"walignr1", 0xee900020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11024 {"walignr2", 0xeea00020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11025 {"walignr3", 0xeeb00020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11026 {"wand", 0xee200000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11027 {"wandn", 0xee300000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11028 {"wavg2b", 0xee800000, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11029 {"wavg2br", 0xee900000, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11030 {"wavg2h", 0xeec00000, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11031 {"wavg2hr", 0xeed00000, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11032 {"wcmpeqb", 0xee000060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11033 {"wcmpeqh", 0xee400060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11034 {"wcmpeqw", 0xee800060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11035 {"wcmpgtub", 0xee100060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11036 {"wcmpgtuh", 0xee500060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11037 {"wcmpgtuw", 0xee900060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11038 {"wcmpgtsb", 0xee300060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11039 {"wcmpgtsh", 0xee700060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11040 {"wcmpgtsw", 0xeeb00060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11041 {"wldrb", 0xec100000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
11042 {"wldrh", 0xec100100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
11043 {"wldrw", 0xec100200, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
11044 {"wldrd", 0xec100300, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
11045 {"wmacs", 0xee600100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11046 {"wmacsz", 0xee700100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11047 {"wmacu", 0xee400100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11048 {"wmacuz", 0xee500100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11049 {"wmadds", 0xeea00100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11050 {"wmaddu", 0xee800100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11051 {"wmaxsb", 0xee200160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11052 {"wmaxsh", 0xee600160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11053 {"wmaxsw", 0xeea00160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11054 {"wmaxub", 0xee000160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11055 {"wmaxuh", 0xee400160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11056 {"wmaxuw", 0xee800160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11057 {"wminsb", 0xee300160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11058 {"wminsh", 0xee700160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11059 {"wminsw", 0xeeb00160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11060 {"wminub", 0xee100160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11061 {"wminuh", 0xee500160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11062 {"wminuw", 0xee900160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11063 {"wmov", 0xee000000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wmov},
11064 {"wmulsm", 0xee300100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11065 {"wmulsl", 0xee200100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11066 {"wmulum", 0xee100100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11067 {"wmulul", 0xee000100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11068 {"wor", 0xee000000, 3, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11069 {"wpackhss", 0xee700080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11070 {"wpackhus", 0xee500080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11071 {"wpackwss", 0xeeb00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11072 {"wpackwus", 0xee900080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11073 {"wpackdss", 0xeef00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11074 {"wpackdus", 0xeed00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11075 {"wrorh", 0xee700040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11076 {"wrorhg", 0xee700148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11077 {"wrorw", 0xeeb00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11078 {"wrorwg", 0xeeb00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11079 {"wrord", 0xeef00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11080 {"wrordg", 0xeef00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11081 {"wsadb", 0xee000120, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11082 {"wsadbz", 0xee100120, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11083 {"wsadh", 0xee400120, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11084 {"wsadhz", 0xee500120, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11085 {"wshufh", 0xee0001e0, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wshufh},
11086 {"wsllh", 0xee500040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11087 {"wsllhg", 0xee500148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11088 {"wsllw", 0xee900040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11089 {"wsllwg", 0xee900148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11090 {"wslld", 0xeed00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11091 {"wslldg", 0xeed00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11092 {"wsrah", 0xee400040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11093 {"wsrahg", 0xee400148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11094 {"wsraw", 0xee800040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11095 {"wsrawg", 0xee800148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11096 {"wsrad", 0xeec00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11097 {"wsradg", 0xeec00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11098 {"wsrlh", 0xee600040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11099 {"wsrlhg", 0xee600148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11100 {"wsrlw", 0xeea00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11101 {"wsrlwg", 0xeea00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11102 {"wsrld", 0xeee00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11103 {"wsrldg", 0xeee00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11104 {"wstrb", 0xec000000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
11105 {"wstrh", 0xec000100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
11106 {"wstrw", 0xec000200, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
11107 {"wstrd", 0xec000300, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
11108 {"wsubbss", 0xee3001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11109 {"wsubb", 0xee0001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11110 {"wsubbus", 0xee1001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11111 {"wsubhss", 0xee7001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11112 {"wsubh", 0xee4001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11113 {"wsubhus", 0xee5001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11114 {"wsubwss", 0xeeb001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11115 {"wsubw", 0xee8001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11116 {"wsubwus", 0xee9001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11117 {"wunpckehub", 0xee0000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11118 {"wunpckehuh", 0xee4000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11119 {"wunpckehuw", 0xee8000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11120 {"wunpckehsb", 0xee2000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11121 {"wunpckehsh", 0xee6000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11122 {"wunpckehsw", 0xeea000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11123 {"wunpckihb", 0xee1000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11124 {"wunpckihh", 0xee5000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11125 {"wunpckihw", 0xee9000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11126 {"wunpckelub", 0xee0000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11127 {"wunpckeluh", 0xee4000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11128 {"wunpckeluw", 0xee8000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11129 {"wunpckelsb", 0xee2000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11130 {"wunpckelsh", 0xee6000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11131 {"wunpckelsw", 0xeea000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11132 {"wunpckilb", 0xee1000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11133 {"wunpckilh", 0xee5000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11134 {"wunpckilw", 0xee9000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11135 {"wxor", 0xee100000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11136 {"wzero", 0xee300000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wzero},
b99bd4ef 11137
a737bd4d
NC
11138 /* Cirrus Maverick instructions. */
11139 {"cfldrs", 0xec100400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_1},
11140 {"cfldrd", 0xec500400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_2},
11141 {"cfldr32", 0xec100500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_3},
11142 {"cfldr64", 0xec500500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_4},
11143 {"cfstrs", 0xec000400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_1},
11144 {"cfstrd", 0xec400400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_2},
11145 {"cfstr32", 0xec000500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_3},
11146 {"cfstr64", 0xec400500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_4},
11147 {"cfmvsr", 0xee000450, 6, ARM_CEXT_MAVERICK, do_mav_binops_2a},
11148 {"cfmvrs", 0xee100450, 6, ARM_CEXT_MAVERICK, do_mav_binops_1a},
11149 {"cfmvdlr", 0xee000410, 7, ARM_CEXT_MAVERICK, do_mav_binops_2b},
11150 {"cfmvrdl", 0xee100410, 7, ARM_CEXT_MAVERICK, do_mav_binops_1b},
11151 {"cfmvdhr", 0xee000430, 7, ARM_CEXT_MAVERICK, do_mav_binops_2b},
11152 {"cfmvrdh", 0xee100430, 7, ARM_CEXT_MAVERICK, do_mav_binops_1b},
11153 {"cfmv64lr", 0xee000510, 8, ARM_CEXT_MAVERICK, do_mav_binops_2c},
11154 {"cfmvr64l", 0xee100510, 8, ARM_CEXT_MAVERICK, do_mav_binops_1c},
11155 {"cfmv64hr", 0xee000530, 8, ARM_CEXT_MAVERICK, do_mav_binops_2c},
11156 {"cfmvr64h", 0xee100530, 8, ARM_CEXT_MAVERICK, do_mav_binops_1c},
11157 {"cfmval32", 0xee200440, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
11158 {"cfmv32al", 0xee100440, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
11159 {"cfmvam32", 0xee200460, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
11160 {"cfmv32am", 0xee100460, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
11161 {"cfmvah32", 0xee200480, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
11162 {"cfmv32ah", 0xee100480, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
11163 {"cfmva32", 0xee2004a0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3a},
11164 {"cfmv32a", 0xee1004a0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3b},
11165 {"cfmva64", 0xee2004c0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3c},
11166 {"cfmv64a", 0xee1004c0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3d},
11167 {"cfmvsc32", 0xee2004e0, 8, ARM_CEXT_MAVERICK, do_mav_dspsc_1},
11168 {"cfmv32sc", 0xee1004e0, 8, ARM_CEXT_MAVERICK, do_mav_dspsc_2},
11169 {"cfcpys", 0xee000400, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
11170 {"cfcpyd", 0xee000420, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
11171 {"cfcvtsd", 0xee000460, 7, ARM_CEXT_MAVERICK, do_mav_binops_1f},
11172 {"cfcvtds", 0xee000440, 7, ARM_CEXT_MAVERICK, do_mav_binops_1g},
11173 {"cfcvt32s", 0xee000480, 8, ARM_CEXT_MAVERICK, do_mav_binops_1h},
11174 {"cfcvt32d", 0xee0004a0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1i},
11175 {"cfcvt64s", 0xee0004c0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1j},
11176 {"cfcvt64d", 0xee0004e0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1k},
11177 {"cfcvts32", 0xee100580, 8, ARM_CEXT_MAVERICK, do_mav_binops_1l},
11178 {"cfcvtd32", 0xee1005a0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1m},
11179 {"cftruncs32", 0xee1005c0, 10, ARM_CEXT_MAVERICK, do_mav_binops_1l},
11180 {"cftruncd32", 0xee1005e0, 10, ARM_CEXT_MAVERICK, do_mav_binops_1m},
11181 {"cfrshl32", 0xee000550, 8, ARM_CEXT_MAVERICK, do_mav_triple_4a},
11182 {"cfrshl64", 0xee000570, 8, ARM_CEXT_MAVERICK, do_mav_triple_4b},
11183 {"cfsh32", 0xee000500, 6, ARM_CEXT_MAVERICK, do_mav_shift_1},
11184 {"cfsh64", 0xee200500, 6, ARM_CEXT_MAVERICK, do_mav_shift_2},
11185 {"cfcmps", 0xee100490, 6, ARM_CEXT_MAVERICK, do_mav_triple_5a},
11186 {"cfcmpd", 0xee1004b0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5b},
11187 {"cfcmp32", 0xee100590, 7, ARM_CEXT_MAVERICK, do_mav_triple_5c},
11188 {"cfcmp64", 0xee1005b0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5d},
11189 {"cfabss", 0xee300400, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
11190 {"cfabsd", 0xee300420, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
11191 {"cfnegs", 0xee300440, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
11192 {"cfnegd", 0xee300460, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
11193 {"cfadds", 0xee300480, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
11194 {"cfaddd", 0xee3004a0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
11195 {"cfsubs", 0xee3004c0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
11196 {"cfsubd", 0xee3004e0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
11197 {"cfmuls", 0xee100400, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
11198 {"cfmuld", 0xee100420, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
11199 {"cfabs32", 0xee300500, 7, ARM_CEXT_MAVERICK, do_mav_binops_1n},
11200 {"cfabs64", 0xee300520, 7, ARM_CEXT_MAVERICK, do_mav_binops_1o},
11201 {"cfneg32", 0xee300540, 7, ARM_CEXT_MAVERICK, do_mav_binops_1n},
11202 {"cfneg64", 0xee300560, 7, ARM_CEXT_MAVERICK, do_mav_binops_1o},
11203 {"cfadd32", 0xee300580, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
11204 {"cfadd64", 0xee3005a0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
11205 {"cfsub32", 0xee3005c0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
11206 {"cfsub64", 0xee3005e0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
11207 {"cfmul32", 0xee100500, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
11208 {"cfmul64", 0xee100520, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
11209 {"cfmac32", 0xee100540, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
11210 {"cfmsc32", 0xee100560, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
11211 {"cfmadd32", 0xee000600, 8, ARM_CEXT_MAVERICK, do_mav_quad_6a},
11212 {"cfmsub32", 0xee100600, 8, ARM_CEXT_MAVERICK, do_mav_quad_6a},
11213 {"cfmadda32", 0xee200600, 9, ARM_CEXT_MAVERICK, do_mav_quad_6b},
11214 {"cfmsuba32", 0xee300600, 9, ARM_CEXT_MAVERICK, do_mav_quad_6b},
11215};
b99bd4ef 11216
90e4755a 11217/* Iterate over the base tables to create the instruction patterns. */
a737bd4d 11218
90e4755a 11219static void
a737bd4d 11220build_arm_ops_hsh (void)
90e4755a
RE
11221{
11222 unsigned int i;
11223 unsigned int j;
11224 static struct obstack insn_obstack;
11225
11226 obstack_begin (&insn_obstack, 4000);
11227
11228 for (i = 0; i < sizeof (insns) / sizeof (struct asm_opcode); i++)
11229 {
6c43fab6 11230 const struct asm_opcode *insn = insns + i;
90e4755a
RE
11231
11232 if (insn->cond_offset != 0)
11233 {
11234 /* Insn supports conditional execution. Build the varaints
11235 and insert them in the hash table. */
11236 for (j = 0; j < sizeof (conds) / sizeof (struct asm_cond); j++)
11237 {
11238 unsigned len = strlen (insn->template);
11239 struct asm_opcode *new;
11240 char *template;
11241
11242 new = obstack_alloc (&insn_obstack, sizeof (struct asm_opcode));
11243 /* All condition codes are two characters. */
11244 template = obstack_alloc (&insn_obstack, len + 3);
11245
11246 strncpy (template, insn->template, insn->cond_offset);
11247 strcpy (template + insn->cond_offset, conds[j].template);
11248 if (len > insn->cond_offset)
11249 strcpy (template + insn->cond_offset + 2,
11250 insn->template + insn->cond_offset);
11251 new->template = template;
11252 new->cond_offset = 0;
11253 new->variant = insn->variant;
11254 new->parms = insn->parms;
11255 new->value = (insn->value & ~COND_MASK) | conds[j].value;
11256
11257 hash_insert (arm_ops_hsh, new->template, (PTR) new);
11258 }
11259 }
11260 /* Finally, insert the unconditional insn in the table directly;
11261 no need to build a copy. */
11262 hash_insert (arm_ops_hsh, insn->template, (PTR) insn);
11263 }
11264}
11265
a737bd4d
NC
11266\f
11267static const struct thumb_opcode tinsns[] =
11268{
11269 /* Thumb v1 (ARMv4T). */
11270 {"adc", 0x4140, 2, ARM_EXT_V4T, do_t_arit},
11271 {"add", 0x0000, 2, ARM_EXT_V4T, do_t_add},
11272 {"and", 0x4000, 2, ARM_EXT_V4T, do_t_arit},
11273 {"asr", 0x0000, 2, ARM_EXT_V4T, do_t_asr},
11274 {"b", T_OPCODE_BRANCH, 2, ARM_EXT_V4T, do_t_branch12},
11275 {"beq", 0xd0fe, 2, ARM_EXT_V4T, do_t_branch9},
11276 {"bne", 0xd1fe, 2, ARM_EXT_V4T, do_t_branch9},
11277 {"bcs", 0xd2fe, 2, ARM_EXT_V4T, do_t_branch9},
11278 {"bhs", 0xd2fe, 2, ARM_EXT_V4T, do_t_branch9},
11279 {"bcc", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
11280 {"bul", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
11281 {"blo", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
11282 {"bmi", 0xd4fe, 2, ARM_EXT_V4T, do_t_branch9},
11283 {"bpl", 0xd5fe, 2, ARM_EXT_V4T, do_t_branch9},
11284 {"bvs", 0xd6fe, 2, ARM_EXT_V4T, do_t_branch9},
11285 {"bvc", 0xd7fe, 2, ARM_EXT_V4T, do_t_branch9},
11286 {"bhi", 0xd8fe, 2, ARM_EXT_V4T, do_t_branch9},
11287 {"bls", 0xd9fe, 2, ARM_EXT_V4T, do_t_branch9},
11288 {"bge", 0xdafe, 2, ARM_EXT_V4T, do_t_branch9},
11289 {"blt", 0xdbfe, 2, ARM_EXT_V4T, do_t_branch9},
11290 {"bgt", 0xdcfe, 2, ARM_EXT_V4T, do_t_branch9},
11291 {"ble", 0xddfe, 2, ARM_EXT_V4T, do_t_branch9},
11292 {"bal", 0xdefe, 2, ARM_EXT_V4T, do_t_branch9},
11293 {"bic", 0x4380, 2, ARM_EXT_V4T, do_t_arit},
11294 {"bl", 0xf7fffffe, 4, ARM_EXT_V4T, do_t_branch23},
11295 {"bx", 0x4700, 2, ARM_EXT_V4T, do_t_bx},
11296 {"cmn", T_OPCODE_CMN, 2, ARM_EXT_V4T, do_t_arit},
11297 {"cmp", 0x0000, 2, ARM_EXT_V4T, do_t_compare},
11298 {"eor", 0x4040, 2, ARM_EXT_V4T, do_t_arit},
11299 {"ldmia", 0xc800, 2, ARM_EXT_V4T, do_t_ldmstm},
11300 {"ldr", 0x0000, 2, ARM_EXT_V4T, do_t_ldr},
11301 {"ldrb", 0x0000, 2, ARM_EXT_V4T, do_t_ldrb},
11302 {"ldrh", 0x0000, 2, ARM_EXT_V4T, do_t_ldrh},
11303 {"ldrsb", 0x5600, 2, ARM_EXT_V4T, do_t_lds},
11304 {"ldrsh", 0x5e00, 2, ARM_EXT_V4T, do_t_lds},
11305 {"ldsb", 0x5600, 2, ARM_EXT_V4T, do_t_lds},
11306 {"ldsh", 0x5e00, 2, ARM_EXT_V4T, do_t_lds},
11307 {"lsl", 0x0000, 2, ARM_EXT_V4T, do_t_lsl},
11308 {"lsr", 0x0000, 2, ARM_EXT_V4T, do_t_lsr},
11309 {"mov", 0x0000, 2, ARM_EXT_V4T, do_t_mov},
11310 {"mul", T_OPCODE_MUL, 2, ARM_EXT_V4T, do_t_arit},
11311 {"mvn", T_OPCODE_MVN, 2, ARM_EXT_V4T, do_t_arit},
11312 {"neg", T_OPCODE_NEG, 2, ARM_EXT_V4T, do_t_arit},
11313 {"orr", 0x4300, 2, ARM_EXT_V4T, do_t_arit},
11314 {"pop", 0xbc00, 2, ARM_EXT_V4T, do_t_push_pop},
11315 {"push", 0xb400, 2, ARM_EXT_V4T, do_t_push_pop},
11316 {"ror", 0x41c0, 2, ARM_EXT_V4T, do_t_arit},
11317 {"sbc", 0x4180, 2, ARM_EXT_V4T, do_t_arit},
11318 {"stmia", 0xc000, 2, ARM_EXT_V4T, do_t_ldmstm},
11319 {"str", 0x0000, 2, ARM_EXT_V4T, do_t_str},
11320 {"strb", 0x0000, 2, ARM_EXT_V4T, do_t_strb},
11321 {"strh", 0x0000, 2, ARM_EXT_V4T, do_t_strh},
11322 {"swi", 0xdf00, 2, ARM_EXT_V4T, do_t_swi},
11323 {"sub", 0x0000, 2, ARM_EXT_V4T, do_t_sub},
11324 {"tst", T_OPCODE_TST, 2, ARM_EXT_V4T, do_t_arit},
11325 /* Pseudo ops: */
11326 {"adr", 0x0000, 2, ARM_EXT_V4T, do_t_adr},
11327 {"nop", 0x46C0, 2, ARM_EXT_V4T, do_t_nop}, /* mov r8,r8 */
11328 /* Thumb v2 (ARMv5T). */
11329 {"blx", 0, 0, ARM_EXT_V5T, do_t_blx},
11330 {"bkpt", 0xbe00, 2, ARM_EXT_V5T, do_t_bkpt},
11331
11332 /* ARM V6. */
11333 {"cpsie", 0xb660, 2, ARM_EXT_V6, do_t_cps},
11334 {"cpsid", 0xb670, 2, ARM_EXT_V6, do_t_cps},
11335 {"cpy", 0x4600, 2, ARM_EXT_V6, do_t_cpy},
11336 {"rev", 0xba00, 2, ARM_EXT_V6, do_t_arit},
11337 {"rev16", 0xba40, 2, ARM_EXT_V6, do_t_arit},
11338 {"revsh", 0xbac0, 2, ARM_EXT_V6, do_t_arit},
11339 {"setend", 0xb650, 2, ARM_EXT_V6, do_t_setend},
11340 {"sxth", 0xb200, 2, ARM_EXT_V6, do_t_arit},
11341 {"sxtb", 0xb240, 2, ARM_EXT_V6, do_t_arit},
11342 {"uxth", 0xb280, 2, ARM_EXT_V6, do_t_arit},
11343 {"uxtb", 0xb2c0, 2, ARM_EXT_V6, do_t_arit},
885fc257
ZW
11344
11345 /* ARM V6K. */
11346 {"sev", 0xbf40, 2, ARM_EXT_V6K, do_empty},
11347 {"wfe", 0xbf20, 2, ARM_EXT_V6K, do_empty},
11348 {"wfi", 0xbf30, 2, ARM_EXT_V6K, do_empty},
11349 {"yield", 0xbf10, 2, ARM_EXT_V6K, do_empty},
a737bd4d 11350};
5a6c6817 11351
b99bd4ef 11352void
a737bd4d 11353md_begin (void)
b99bd4ef
NC
11354{
11355 unsigned mach;
11356 unsigned int i;
11357
11358 if ( (arm_ops_hsh = hash_new ()) == NULL
11359 || (arm_tops_hsh = hash_new ()) == NULL
11360 || (arm_cond_hsh = hash_new ()) == NULL
11361 || (arm_shift_hsh = hash_new ()) == NULL
b99bd4ef 11362 || (arm_psr_hsh = hash_new ()) == NULL)
f03698e6 11363 as_fatal (_("virtual memory exhausted"));
b99bd4ef 11364
90e4755a 11365 build_arm_ops_hsh ();
b99bd4ef
NC
11366 for (i = 0; i < sizeof (tinsns) / sizeof (struct thumb_opcode); i++)
11367 hash_insert (arm_tops_hsh, tinsns[i].template, (PTR) (tinsns + i));
11368 for (i = 0; i < sizeof (conds) / sizeof (struct asm_cond); i++)
11369 hash_insert (arm_cond_hsh, conds[i].template, (PTR) (conds + i));
11370 for (i = 0; i < sizeof (shift_names) / sizeof (struct asm_shift_name); i++)
11371 hash_insert (arm_shift_hsh, shift_names[i].name, (PTR) (shift_names + i));
11372 for (i = 0; i < sizeof (psrs) / sizeof (struct asm_psr); i++)
11373 hash_insert (arm_psr_hsh, psrs[i].template, (PTR) (psrs + i));
11374
6c43fab6
RE
11375 for (i = (int) REG_TYPE_FIRST; i < (int) REG_TYPE_MAX; i++)
11376 build_reg_hsh (all_reg_maps + i);
b99bd4ef
NC
11377
11378 set_constant_flonums ();
11379
03b1477f
RE
11380 /* Set the cpu variant based on the command-line options. We prefer
11381 -mcpu= over -march= if both are set (as for GCC); and we prefer
11382 -mfpu= over any other way of setting the floating point unit.
11383 Use of legacy options with new options are faulted. */
11384 if (legacy_cpu != -1)
11385 {
11386 if (mcpu_cpu_opt != -1 || march_cpu_opt != -1)
11387 as_bad (_("use of old and new-style options to set CPU type"));
11388
11389 mcpu_cpu_opt = legacy_cpu;
11390 }
11391 else if (mcpu_cpu_opt == -1)
11392 mcpu_cpu_opt = march_cpu_opt;
11393
11394 if (legacy_fpu != -1)
11395 {
11396 if (mfpu_opt != -1)
11397 as_bad (_("use of old and new-style options to set FPU type"));
11398
11399 mfpu_opt = legacy_fpu;
11400 }
11401 else if (mfpu_opt == -1)
11402 {
4e7fd91e 11403#if !(defined (TE_LINUX) || defined (TE_NetBSD) || defined (TE_VXWORKS))
39c2da32
RE
11404 /* Some environments specify a default FPU. If they don't, infer it
11405 from the processor. */
03b1477f
RE
11406 if (mcpu_fpu_opt != -1)
11407 mfpu_opt = mcpu_fpu_opt;
11408 else
11409 mfpu_opt = march_fpu_opt;
39c2da32
RE
11410#else
11411 mfpu_opt = FPU_DEFAULT;
11412#endif
03b1477f
RE
11413 }
11414
11415 if (mfpu_opt == -1)
11416 {
11417 if (mcpu_cpu_opt == -1)
11418 mfpu_opt = FPU_DEFAULT;
11419 else if (mcpu_cpu_opt & ARM_EXT_V5)
11420 mfpu_opt = FPU_ARCH_VFP_V2;
11421 else
11422 mfpu_opt = FPU_ARCH_FPA;
11423 }
11424
11425 if (mcpu_cpu_opt == -1)
11426 mcpu_cpu_opt = CPU_DEFAULT;
11427
11428 cpu_variant = mcpu_cpu_opt | mfpu_opt;
11429
f17c130b 11430#if defined OBJ_COFF || defined OBJ_ELF
b99bd4ef 11431 {
7cc69913
NC
11432 unsigned int flags = 0;
11433
11434#if defined OBJ_ELF
11435 flags = meabi_flags;
d507cf36
PB
11436
11437 switch (meabi_flags)
33a392fb 11438 {
d507cf36 11439 case EF_ARM_EABI_UNKNOWN:
7cc69913 11440#endif
d507cf36
PB
11441 /* Set the flags in the private structure. */
11442 if (uses_apcs_26) flags |= F_APCS26;
11443 if (support_interwork) flags |= F_INTERWORK;
11444 if (uses_apcs_float) flags |= F_APCS_FLOAT;
11445 if (pic_code) flags |= F_PIC;
11446 if ((cpu_variant & FPU_ANY) == FPU_NONE
11447 || (cpu_variant & FPU_ANY) == FPU_ARCH_VFP) /* VFP layout only. */
7cc69913
NC
11448 flags |= F_SOFT_FLOAT;
11449
d507cf36
PB
11450 switch (mfloat_abi_opt)
11451 {
11452 case ARM_FLOAT_ABI_SOFT:
11453 case ARM_FLOAT_ABI_SOFTFP:
11454 flags |= F_SOFT_FLOAT;
11455 break;
33a392fb 11456
d507cf36
PB
11457 case ARM_FLOAT_ABI_HARD:
11458 if (flags & F_SOFT_FLOAT)
11459 as_bad (_("hard-float conflicts with specified fpu"));
11460 break;
11461 }
03b1477f 11462
7cc69913
NC
11463 /* Using VFP conventions (even if soft-float). */
11464 if (cpu_variant & FPU_VFP_EXT_NONE)
11465 flags |= F_VFP_FLOAT;
f17c130b 11466
fde78edd 11467#if defined OBJ_ELF
d507cf36
PB
11468 if (cpu_variant & FPU_ARCH_MAVERICK)
11469 flags |= EF_ARM_MAVERICK_FLOAT;
d507cf36
PB
11470 break;
11471
8cb51566 11472 case EF_ARM_EABI_VER4:
d507cf36
PB
11473 /* No additional flags to set. */
11474 break;
11475
11476 default:
11477 abort ();
11478 }
7cc69913 11479#endif
b99bd4ef
NC
11480 bfd_set_private_flags (stdoutput, flags);
11481
11482 /* We have run out flags in the COFF header to encode the
11483 status of ATPCS support, so instead we create a dummy,
11484 empty, debug section called .arm.atpcs. */
11485 if (atpcs)
11486 {
11487 asection * sec;
11488
11489 sec = bfd_make_section (stdoutput, ".arm.atpcs");
11490
11491 if (sec != NULL)
11492 {
11493 bfd_set_section_flags
11494 (stdoutput, sec, SEC_READONLY | SEC_DEBUGGING /* | SEC_HAS_CONTENTS */);
11495 bfd_set_section_size (stdoutput, sec, 0);
11496 bfd_set_section_contents (stdoutput, sec, NULL, 0, 0);
11497 }
11498 }
7cc69913 11499 }
f17c130b 11500#endif
b99bd4ef
NC
11501
11502 /* Record the CPU type as well. */
11503 switch (cpu_variant & ARM_CPU_MASK)
11504 {
11505 case ARM_2:
11506 mach = bfd_mach_arm_2;
11507 break;
11508
11509 case ARM_3: /* Also ARM_250. */
11510 mach = bfd_mach_arm_2a;
11511 break;
11512
b89dddec
RE
11513 case ARM_6: /* Also ARM_7. */
11514 mach = bfd_mach_arm_3;
11515 break;
11516
b99bd4ef 11517 default:
5a6c6817 11518 mach = bfd_mach_arm_unknown;
b99bd4ef 11519 break;
b99bd4ef
NC
11520 }
11521
11522 /* Catch special cases. */
e16bb312
NC
11523 if (cpu_variant & ARM_CEXT_IWMMXT)
11524 mach = bfd_mach_arm_iWMMXt;
11525 else if (cpu_variant & ARM_CEXT_XSCALE)
b99bd4ef 11526 mach = bfd_mach_arm_XScale;
fde78edd
NC
11527 else if (cpu_variant & ARM_CEXT_MAVERICK)
11528 mach = bfd_mach_arm_ep9312;
b99bd4ef
NC
11529 else if (cpu_variant & ARM_EXT_V5E)
11530 mach = bfd_mach_arm_5TE;
11531 else if (cpu_variant & ARM_EXT_V5)
11532 {
b89dddec 11533 if (cpu_variant & ARM_EXT_V4T)
b99bd4ef
NC
11534 mach = bfd_mach_arm_5T;
11535 else
11536 mach = bfd_mach_arm_5;
11537 }
b89dddec 11538 else if (cpu_variant & ARM_EXT_V4)
b99bd4ef 11539 {
b89dddec 11540 if (cpu_variant & ARM_EXT_V4T)
b99bd4ef
NC
11541 mach = bfd_mach_arm_4T;
11542 else
11543 mach = bfd_mach_arm_4;
11544 }
b89dddec 11545 else if (cpu_variant & ARM_EXT_V3M)
b99bd4ef
NC
11546 mach = bfd_mach_arm_3M;
11547
11548 bfd_set_arch_mach (stdoutput, TARGET_ARCH, mach);
11549}
11550
11551/* Turn an integer of n bytes (in val) into a stream of bytes appropriate
11552 for use in the a.out file, and stores them in the array pointed to by buf.
11553 This knows about the endian-ness of the target machine and does
11554 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
11555 2 (short) and 4 (long) Floating numbers are put out as a series of
11556 LITTLENUMS (shorts, here at least). */
11557
11558void
a737bd4d 11559md_number_to_chars (char * buf, valueT val, int n)
b99bd4ef
NC
11560{
11561 if (target_big_endian)
11562 number_to_chars_bigendian (buf, val, n);
11563 else
11564 number_to_chars_littleendian (buf, val, n);
11565}
11566
11567static valueT
a737bd4d 11568md_chars_to_number (char * buf, int n)
b99bd4ef
NC
11569{
11570 valueT result = 0;
11571 unsigned char * where = (unsigned char *) buf;
11572
11573 if (target_big_endian)
11574 {
11575 while (n--)
11576 {
11577 result <<= 8;
11578 result |= (*where++ & 255);
11579 }
11580 }
11581 else
11582 {
11583 while (n--)
11584 {
11585 result <<= 8;
11586 result |= (where[n] & 255);
11587 }
11588 }
11589
11590 return result;
11591}
11592
11593/* Turn a string in input_line_pointer into a floating point constant
11594 of type TYPE, and store the appropriate bytes in *LITP. The number
11595 of LITTLENUMS emitted is stored in *SIZEP. An error message is
11596 returned, or NULL on OK.
11597
11598 Note that fp constants aren't represent in the normal way on the ARM.
11599 In big endian mode, things are as expected. However, in little endian
11600 mode fp constants are big-endian word-wise, and little-endian byte-wise
11601 within the words. For example, (double) 1.1 in big endian mode is
11602 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
11603 the byte sequence 99 99 f1 3f 9a 99 99 99.
11604
11605 ??? The format of 12 byte floats is uncertain according to gcc's arm.h. */
11606
11607char *
a737bd4d 11608md_atof (int type, char * litP, int * sizeP)
b99bd4ef
NC
11609{
11610 int prec;
11611 LITTLENUM_TYPE words[MAX_LITTLENUMS];
11612 char *t;
11613 int i;
11614
11615 switch (type)
11616 {
11617 case 'f':
11618 case 'F':
11619 case 's':
11620 case 'S':
11621 prec = 2;
11622 break;
11623
11624 case 'd':
11625 case 'D':
11626 case 'r':
11627 case 'R':
11628 prec = 4;
11629 break;
11630
11631 case 'x':
11632 case 'X':
11633 prec = 6;
11634 break;
11635
11636 case 'p':
11637 case 'P':
11638 prec = 6;
11639 break;
11640
11641 default:
11642 *sizeP = 0;
f03698e6 11643 return _("bad call to MD_ATOF()");
b99bd4ef
NC
11644 }
11645
11646 t = atof_ieee (input_line_pointer, type, words);
11647 if (t)
11648 input_line_pointer = t;
11649 *sizeP = prec * 2;
11650
11651 if (target_big_endian)
11652 {
11653 for (i = 0; i < prec; i++)
11654 {
11655 md_number_to_chars (litP, (valueT) words[i], 2);
11656 litP += 2;
11657 }
11658 }
11659 else
11660 {
bfae80f2
RE
11661 if (cpu_variant & FPU_ARCH_VFP)
11662 for (i = prec - 1; i >= 0; i--)
11663 {
11664 md_number_to_chars (litP, (valueT) words[i], 2);
11665 litP += 2;
11666 }
11667 else
11668 /* For a 4 byte float the order of elements in `words' is 1 0.
11669 For an 8 byte float the order is 1 0 3 2. */
11670 for (i = 0; i < prec; i += 2)
11671 {
11672 md_number_to_chars (litP, (valueT) words[i + 1], 2);
11673 md_number_to_chars (litP + 2, (valueT) words[i], 2);
11674 litP += 4;
11675 }
b99bd4ef
NC
11676 }
11677
11678 return 0;
11679}
11680
11681/* The knowledge of the PC's pipeline offset is built into the insns
11682 themselves. */
11683
11684long
a737bd4d 11685md_pcrel_from (fixS * fixP)
b99bd4ef
NC
11686{
11687 if (fixP->fx_addsy
11688 && S_GET_SEGMENT (fixP->fx_addsy) == undefined_section
11689 && fixP->fx_subsy == NULL)
11690 return 0;
11691
11692 if (fixP->fx_pcrel && (fixP->fx_r_type == BFD_RELOC_ARM_THUMB_ADD))
11693 {
11694 /* PC relative addressing on the Thumb is slightly odd
11695 as the bottom two bits of the PC are forced to zero
11696 for the calculation. */
11697 return (fixP->fx_where + fixP->fx_frag->fr_address) & ~3;
11698 }
11699
11700#ifdef TE_WINCE
2d2255b5
KH
11701 /* The pattern was adjusted to accommodate CE's off-by-one fixups,
11702 so we un-adjust here to compensate for the accommodation. */
b99bd4ef
NC
11703 return fixP->fx_where + fixP->fx_frag->fr_address + 8;
11704#else
11705 return fixP->fx_where + fixP->fx_frag->fr_address;
11706#endif
11707}
11708
11709/* Round up a section size to the appropriate boundary. */
11710
11711valueT
a737bd4d
NC
11712md_section_align (segT segment ATTRIBUTE_UNUSED,
11713 valueT size)
b99bd4ef
NC
11714{
11715#ifdef OBJ_ELF
11716 return size;
11717#else
11718 /* Round all sects to multiple of 4. */
11719 return (size + 3) & ~3;
11720#endif
11721}
11722
11723/* Under ELF we need to default _GLOBAL_OFFSET_TABLE.
11724 Otherwise we have no need to default values of symbols. */
11725
11726symbolS *
a737bd4d 11727md_undefined_symbol (char * name ATTRIBUTE_UNUSED)
b99bd4ef
NC
11728{
11729#ifdef OBJ_ELF
11730 if (name[0] == '_' && name[1] == 'G'
11731 && streq (name, GLOBAL_OFFSET_TABLE_NAME))
11732 {
11733 if (!GOT_symbol)
11734 {
11735 if (symbol_find (name))
11736 as_bad ("GOT already in the symbol table");
11737
11738 GOT_symbol = symbol_new (name, undefined_section,
11739 (valueT) 0, & zero_address_frag);
11740 }
11741
11742 return GOT_symbol;
11743 }
11744#endif
11745
11746 return 0;
11747}
11748
94f592af 11749void
a737bd4d
NC
11750md_apply_fix3 (fixS * fixP,
11751 valueT * valP,
11752 segT seg)
b99bd4ef 11753{
94f592af 11754 offsetT value = * valP;
b99bd4ef
NC
11755 offsetT newval;
11756 unsigned int newimm;
11757 unsigned long temp;
11758 int sign;
11759 char * buf = fixP->fx_where + fixP->fx_frag->fr_literal;
11760 arm_fix_data * arm_data = (arm_fix_data *) fixP->tc_fix_data;
11761
620b81c1 11762 assert (fixP->fx_r_type <= BFD_RELOC_UNUSED);
b99bd4ef
NC
11763
11764 /* Note whether this will delete the relocation. */
b99bd4ef 11765 if (fixP->fx_addsy == 0 && !fixP->fx_pcrel)
b99bd4ef
NC
11766 fixP->fx_done = 1;
11767
11768 /* If this symbol is in a different section then we need to leave it for
11769 the linker to deal with. Unfortunately, md_pcrel_from can't tell,
11770 so we have to undo it's effects here. */
11771 if (fixP->fx_pcrel)
11772 {
11773 if (fixP->fx_addsy != NULL
11774 && S_IS_DEFINED (fixP->fx_addsy)
11775 && S_GET_SEGMENT (fixP->fx_addsy) != seg)
7f266840 11776 value += md_pcrel_from (fixP);
b99bd4ef
NC
11777 }
11778
11779 /* Remember value for emit_reloc. */
11780 fixP->fx_addnumber = value;
11781
11782 switch (fixP->fx_r_type)
11783 {
620b81c1
JB
11784 case BFD_RELOC_NONE:
11785 /* This will need to go in the object file. */
11786 fixP->fx_done = 0;
11787 break;
11788
b99bd4ef 11789 case BFD_RELOC_ARM_IMMEDIATE:
310ea308
NC
11790 /* We claim that this fixup has been processed here,
11791 even if in fact we generate an error because we do
11792 not have a reloc for it, so tc_gen_reloc will reject it. */
11793 fixP->fx_done = 1;
11794
11795 if (fixP->fx_addsy
11796 && ! S_IS_DEFINED (fixP->fx_addsy))
11797 {
11798 as_bad_where (fixP->fx_file, fixP->fx_line,
11799 _("undefined symbol %s used as an immediate value"),
11800 S_GET_NAME (fixP->fx_addsy));
11801 break;
11802 }
11803
b99bd4ef
NC
11804 newimm = validate_immediate (value);
11805 temp = md_chars_to_number (buf, INSN_SIZE);
11806
11807 /* If the instruction will fail, see if we can fix things up by
11808 changing the opcode. */
11809 if (newimm == (unsigned int) FAIL
11810 && (newimm = negate_data_op (&temp, value)) == (unsigned int) FAIL)
11811 {
11812 as_bad_where (fixP->fx_file, fixP->fx_line,
11813 _("invalid constant (%lx) after fixup"),
11814 (unsigned long) value);
11815 break;
11816 }
11817
11818 newimm |= (temp & 0xfffff000);
11819 md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
11820 break;
11821
11822 case BFD_RELOC_ARM_ADRL_IMMEDIATE:
11823 {
11824 unsigned int highpart = 0;
11825 unsigned int newinsn = 0xe1a00000; /* nop. */
6189168b 11826
b99bd4ef
NC
11827 newimm = validate_immediate (value);
11828 temp = md_chars_to_number (buf, INSN_SIZE);
11829
11830 /* If the instruction will fail, see if we can fix things up by
11831 changing the opcode. */
11832 if (newimm == (unsigned int) FAIL
11833 && (newimm = negate_data_op (& temp, value)) == (unsigned int) FAIL)
11834 {
11835 /* No ? OK - try using two ADD instructions to generate
11836 the value. */
11837 newimm = validate_immediate_twopart (value, & highpart);
11838
11839 /* Yes - then make sure that the second instruction is
11840 also an add. */
11841 if (newimm != (unsigned int) FAIL)
11842 newinsn = temp;
11843 /* Still No ? Try using a negated value. */
11844 else if ((newimm = validate_immediate_twopart (- value, & highpart)) != (unsigned int) FAIL)
11845 temp = newinsn = (temp & OPCODE_MASK) | OPCODE_SUB << DATA_OP_SHIFT;
11846 /* Otherwise - give up. */
11847 else
11848 {
11849 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 11850 _("unable to compute ADRL instructions for PC offset of 0x%lx"),
08df2379 11851 (long) value);
b99bd4ef
NC
11852 break;
11853 }
11854
11855 /* Replace the first operand in the 2nd instruction (which
11856 is the PC) with the destination register. We have
11857 already added in the PC in the first instruction and we
11858 do not want to do it again. */
11859 newinsn &= ~ 0xf0000;
11860 newinsn |= ((newinsn & 0x0f000) << 4);
11861 }
11862
11863 newimm |= (temp & 0xfffff000);
11864 md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
11865
11866 highpart |= (newinsn & 0xfffff000);
11867 md_number_to_chars (buf + INSN_SIZE, (valueT) highpart, INSN_SIZE);
11868 }
11869 break;
11870
11871 case BFD_RELOC_ARM_OFFSET_IMM:
11872 sign = value >= 0;
11873
11874 if (value < 0)
11875 value = - value;
11876
11877 if (validate_offset_imm (value, 0) == FAIL)
11878 {
11879 as_bad_where (fixP->fx_file, fixP->fx_line,
11880 _("bad immediate value for offset (%ld)"),
11881 (long) value);
11882 break;
11883 }
11884
11885 newval = md_chars_to_number (buf, INSN_SIZE);
11886 newval &= 0xff7ff000;
11887 newval |= value | (sign ? INDEX_UP : 0);
11888 md_number_to_chars (buf, newval, INSN_SIZE);
11889 break;
11890
11891 case BFD_RELOC_ARM_OFFSET_IMM8:
11892 case BFD_RELOC_ARM_HWLITERAL:
11893 sign = value >= 0;
11894
11895 if (value < 0)
11896 value = - value;
11897
11898 if (validate_offset_imm (value, 1) == FAIL)
11899 {
11900 if (fixP->fx_r_type == BFD_RELOC_ARM_HWLITERAL)
11901 as_bad_where (fixP->fx_file, fixP->fx_line,
11902 _("invalid literal constant: pool needs to be closer"));
11903 else
11904 as_bad (_("bad immediate value for half-word offset (%ld)"),
11905 (long) value);
11906 break;
11907 }
11908
11909 newval = md_chars_to_number (buf, INSN_SIZE);
11910 newval &= 0xff7ff0f0;
11911 newval |= ((value >> 4) << 8) | (value & 0xf) | (sign ? INDEX_UP : 0);
11912 md_number_to_chars (buf, newval, INSN_SIZE);
11913 break;
11914
11915 case BFD_RELOC_ARM_LITERAL:
11916 sign = value >= 0;
11917
11918 if (value < 0)
11919 value = - value;
11920
11921 if (validate_offset_imm (value, 0) == FAIL)
11922 {
11923 as_bad_where (fixP->fx_file, fixP->fx_line,
11924 _("invalid literal constant: pool needs to be closer"));
11925 break;
11926 }
11927
11928 newval = md_chars_to_number (buf, INSN_SIZE);
11929 newval &= 0xff7ff000;
11930 newval |= value | (sign ? INDEX_UP : 0);
11931 md_number_to_chars (buf, newval, INSN_SIZE);
11932 break;
11933
11934 case BFD_RELOC_ARM_SHIFT_IMM:
11935 newval = md_chars_to_number (buf, INSN_SIZE);
11936 if (((unsigned long) value) > 32
11937 || (value == 32
11938 && (((newval & 0x60) == 0) || (newval & 0x60) == 0x60)))
11939 {
11940 as_bad_where (fixP->fx_file, fixP->fx_line,
11941 _("shift expression is too large"));
11942 break;
11943 }
11944
11945 if (value == 0)
11946 /* Shifts of zero must be done as lsl. */
11947 newval &= ~0x60;
11948 else if (value == 32)
11949 value = 0;
11950 newval &= 0xfffff07f;
11951 newval |= (value & 0x1f) << 7;
11952 md_number_to_chars (buf, newval, INSN_SIZE);
11953 break;
11954
0dd132b6
NC
11955 case BFD_RELOC_ARM_SMI:
11956 if (((unsigned long) value) > 0xffff)
11957 as_bad_where (fixP->fx_file, fixP->fx_line,
11958 _("invalid smi expression"));
11959 newval = md_chars_to_number (buf, INSN_SIZE) & 0xfff000f0;
11960 newval |= (value & 0xf) | ((value & 0xfff0) << 4);
11961 md_number_to_chars (buf, newval, INSN_SIZE);
11962 break;
11963
b99bd4ef
NC
11964 case BFD_RELOC_ARM_SWI:
11965 if (arm_data->thumb_mode)
11966 {
11967 if (((unsigned long) value) > 0xff)
11968 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 11969 _("invalid swi expression"));
b99bd4ef
NC
11970 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xff00;
11971 newval |= value;
11972 md_number_to_chars (buf, newval, THUMB_SIZE);
11973 }
11974 else
11975 {
11976 if (((unsigned long) value) > 0x00ffffff)
11977 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 11978 _("invalid swi expression"));
b99bd4ef
NC
11979 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff000000;
11980 newval |= value;
11981 md_number_to_chars (buf, newval, INSN_SIZE);
11982 }
11983 break;
11984
11985 case BFD_RELOC_ARM_MULTI:
11986 if (((unsigned long) value) > 0xffff)
11987 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 11988 _("invalid expression in load/store multiple"));
b99bd4ef
NC
11989 newval = value | md_chars_to_number (buf, INSN_SIZE);
11990 md_number_to_chars (buf, newval, INSN_SIZE);
11991 break;
11992
11993 case BFD_RELOC_ARM_PCREL_BRANCH:
11994 newval = md_chars_to_number (buf, INSN_SIZE);
11995
11996 /* Sign-extend a 24-bit number. */
11997#define SEXT24(x) ((((x) & 0xffffff) ^ (~ 0x7fffff)) + 0x800000)
11998
11999#ifdef OBJ_ELF
7f266840 12000 value = fixP->fx_offset;
b99bd4ef
NC
12001#endif
12002
12003 /* We are going to store value (shifted right by two) in the
12004 instruction, in a 24 bit, signed field. Thus we need to check
12005 that none of the top 8 bits of the shifted value (top 7 bits of
12006 the unshifted, unsigned value) are set, or that they are all set. */
12007 if ((value & ~ ((offsetT) 0x1ffffff)) != 0
12008 && ((value & ~ ((offsetT) 0x1ffffff)) != ~ ((offsetT) 0x1ffffff)))
12009 {
12010#ifdef OBJ_ELF
12011 /* Normally we would be stuck at this point, since we cannot store
12012 the absolute address that is the destination of the branch in the
12013 24 bits of the branch instruction. If however, we happen to know
12014 that the destination of the branch is in the same section as the
2d2255b5 12015 branch instruction itself, then we can compute the relocation for
b99bd4ef
NC
12016 ourselves and not have to bother the linker with it.
12017
7f266840
DJ
12018 FIXME: The test for OBJ_ELF is only here because I have not
12019 worked out how to do this for OBJ_COFF. */
12020 if (fixP->fx_addsy != NULL
b99bd4ef
NC
12021 && S_IS_DEFINED (fixP->fx_addsy)
12022 && S_GET_SEGMENT (fixP->fx_addsy) == seg)
12023 {
12024 /* Get pc relative value to go into the branch. */
94f592af 12025 value = * valP;
b99bd4ef
NC
12026
12027 /* Permit a backward branch provided that enough bits
12028 are set. Allow a forwards branch, provided that
12029 enough bits are clear. */
12030 if ( (value & ~ ((offsetT) 0x1ffffff)) == ~ ((offsetT) 0x1ffffff)
12031 || (value & ~ ((offsetT) 0x1ffffff)) == 0)
12032 fixP->fx_done = 1;
12033 }
12034
12035 if (! fixP->fx_done)
12036#endif
12037 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12038 _("GAS can't handle same-section branch dest >= 0x04000000"));
b99bd4ef
NC
12039 }
12040
12041 value >>= 2;
12042 value += SEXT24 (newval);
12043
12044 if ( (value & ~ ((offsetT) 0xffffff)) != 0
12045 && ((value & ~ ((offsetT) 0xffffff)) != ~ ((offsetT) 0xffffff)))
12046 as_bad_where (fixP->fx_file, fixP->fx_line,
12047 _("out of range branch"));
12048
4e7fd91e
PB
12049 if (seg->use_rela_p && !fixP->fx_done)
12050 {
12051 /* Must unshift the value before storing it in the addend. */
12052 value <<= 2;
12053#ifdef OBJ_ELF
12054 fixP->fx_offset = value;
12055#endif
12056 fixP->fx_addnumber = value;
12057 newval = newval & 0xff000000;
12058 }
12059 else
12060 newval = (value & 0x00ffffff) | (newval & 0xff000000);
b99bd4ef
NC
12061 md_number_to_chars (buf, newval, INSN_SIZE);
12062 break;
12063
12064 case BFD_RELOC_ARM_PCREL_BLX:
12065 {
12066 offsetT hbit;
12067 newval = md_chars_to_number (buf, INSN_SIZE);
12068
12069#ifdef OBJ_ELF
7f266840 12070 value = fixP->fx_offset;
b99bd4ef
NC
12071#endif
12072 hbit = (value >> 1) & 1;
12073 value = (value >> 2) & 0x00ffffff;
12074 value = (value + (newval & 0x00ffffff)) & 0x00ffffff;
4e7fd91e
PB
12075
12076 if (seg->use_rela_p && !fixP->fx_done)
12077 {
12078 /* Must sign-extend and unshift the value before storing
12079 it in the addend. */
12080 value = SEXT24 (value);
12081 value = (value << 2) | hbit;
12082#ifdef OBJ_ELF
12083 fixP->fx_offset = value;
12084#endif
12085 fixP->fx_addnumber = value;
12086 newval = newval & 0xfe000000;
12087 }
12088 else
12089 newval = value | (newval & 0xfe000000) | (hbit << 24);
b99bd4ef
NC
12090 md_number_to_chars (buf, newval, INSN_SIZE);
12091 }
12092 break;
12093
12094 case BFD_RELOC_THUMB_PCREL_BRANCH9: /* Conditional branch. */
12095 newval = md_chars_to_number (buf, THUMB_SIZE);
12096 {
12097 addressT diff = (newval & 0xff) << 1;
12098 if (diff & 0x100)
12099 diff |= ~0xff;
12100
12101 value += diff;
12102 if ((value & ~0xff) && ((value & ~0xff) != ~0xff))
12103 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12104 _("branch out of range"));
4e7fd91e
PB
12105 if (seg->use_rela_p && !fixP->fx_done)
12106 {
12107#ifdef OBJ_ELF
12108 fixP->fx_offset = value;
12109#endif
12110 fixP->fx_addnumber = value;
12111 newval = newval & 0xff00;
12112 }
12113 else
12114 newval = (newval & 0xff00) | ((value & 0x1ff) >> 1);
b99bd4ef
NC
12115 }
12116 md_number_to_chars (buf, newval, THUMB_SIZE);
12117 break;
12118
12119 case BFD_RELOC_THUMB_PCREL_BRANCH12: /* Unconditional branch. */
12120 newval = md_chars_to_number (buf, THUMB_SIZE);
12121 {
12122 addressT diff = (newval & 0x7ff) << 1;
12123 if (diff & 0x800)
12124 diff |= ~0x7ff;
12125
12126 value += diff;
12127 if ((value & ~0x7ff) && ((value & ~0x7ff) != ~0x7ff))
12128 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12129 _("branch out of range"));
4e7fd91e
PB
12130 if (seg->use_rela_p && !fixP->fx_done)
12131 {
12132#ifdef OBJ_ELF
12133 fixP->fx_offset = value;
12134#endif
12135 fixP->fx_addnumber = value;
12136 newval = newval & 0xf800;
12137 }
12138 else
12139 newval = (newval & 0xf800) | ((value & 0xfff) >> 1);
b99bd4ef
NC
12140 }
12141 md_number_to_chars (buf, newval, THUMB_SIZE);
12142 break;
12143
12144 case BFD_RELOC_THUMB_PCREL_BLX:
12145 case BFD_RELOC_THUMB_PCREL_BRANCH23:
12146 {
12147 offsetT newval2;
12148 addressT diff;
12149
12150 newval = md_chars_to_number (buf, THUMB_SIZE);
12151 newval2 = md_chars_to_number (buf + THUMB_SIZE, THUMB_SIZE);
12152 diff = ((newval & 0x7ff) << 12) | ((newval2 & 0x7ff) << 1);
12153 if (diff & 0x400000)
12154 diff |= ~0x3fffff;
12155#ifdef OBJ_ELF
12156 value = fixP->fx_offset;
12157#endif
12158 value += diff;
c62e1cc3 12159
b99bd4ef
NC
12160 if ((value & ~0x3fffff) && ((value & ~0x3fffff) != ~0x3fffff))
12161 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12162 _("branch with link out of range"));
b99bd4ef 12163
b99bd4ef 12164 if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX)
c62e1cc3
NC
12165 /* For a BLX instruction, make sure that the relocation is rounded up
12166 to a word boundary. This follows the semantics of the instruction
12167 which specifies that bit 1 of the target address will come from bit
12168 1 of the base address. */
4e7fd91e
PB
12169 value = (value + 1) & ~ 1;
12170
12171 if (seg->use_rela_p && !fixP->fx_done)
12172 {
12173#ifdef OBJ_ELF
12174 fixP->fx_offset = value;
12175#endif
12176 fixP->fx_addnumber = value;
12177 newval = newval & 0xf800;
12178 newval2 = newval2 & 0xf800;
12179 }
12180 else
12181 {
12182 newval = (newval & 0xf800) | ((value & 0x7fffff) >> 12);
12183 newval2 = (newval2 & 0xf800) | ((value & 0xfff) >> 1);
12184 }
b99bd4ef
NC
12185 md_number_to_chars (buf, newval, THUMB_SIZE);
12186 md_number_to_chars (buf + THUMB_SIZE, newval2, THUMB_SIZE);
12187 }
12188 break;
12189
12190 case BFD_RELOC_8:
4e7fd91e
PB
12191 if (seg->use_rela_p && !fixP->fx_done)
12192 break;
b99bd4ef
NC
12193 if (fixP->fx_done || fixP->fx_pcrel)
12194 md_number_to_chars (buf, value, 1);
12195#ifdef OBJ_ELF
7f266840 12196 else
b99bd4ef
NC
12197 {
12198 value = fixP->fx_offset;
12199 md_number_to_chars (buf, value, 1);
12200 }
12201#endif
12202 break;
12203
12204 case BFD_RELOC_16:
4e7fd91e
PB
12205 if (seg->use_rela_p && !fixP->fx_done)
12206 break;
b99bd4ef
NC
12207 if (fixP->fx_done || fixP->fx_pcrel)
12208 md_number_to_chars (buf, value, 2);
12209#ifdef OBJ_ELF
7f266840 12210 else
b99bd4ef
NC
12211 {
12212 value = fixP->fx_offset;
12213 md_number_to_chars (buf, value, 2);
12214 }
12215#endif
12216 break;
12217
12218#ifdef OBJ_ELF
12219 case BFD_RELOC_ARM_GOT32:
12220 case BFD_RELOC_ARM_GOTOFF:
eb043451 12221 case BFD_RELOC_ARM_TARGET2:
4e7fd91e
PB
12222 if (seg->use_rela_p && !fixP->fx_done)
12223 break;
b99bd4ef
NC
12224 md_number_to_chars (buf, 0, 4);
12225 break;
12226#endif
12227
12228 case BFD_RELOC_RVA:
12229 case BFD_RELOC_32:
9c504268 12230 case BFD_RELOC_ARM_TARGET1:
db6579d4
PB
12231 case BFD_RELOC_ARM_ROSEGREL32:
12232 case BFD_RELOC_ARM_SBREL32:
eb043451 12233 case BFD_RELOC_32_PCREL:
4e7fd91e
PB
12234 if (seg->use_rela_p && !fixP->fx_done)
12235 break;
b99bd4ef
NC
12236 if (fixP->fx_done || fixP->fx_pcrel)
12237 md_number_to_chars (buf, value, 4);
12238#ifdef OBJ_ELF
7f266840 12239 else
b99bd4ef
NC
12240 {
12241 value = fixP->fx_offset;
12242 md_number_to_chars (buf, value, 4);
12243 }
12244#endif
12245 break;
12246
12247#ifdef OBJ_ELF
eb043451
PB
12248 case BFD_RELOC_ARM_PREL31:
12249 if (fixP->fx_done || fixP->fx_pcrel)
12250 {
12251 newval = md_chars_to_number (buf, 4) & 0x80000000;
12252 if ((value ^ (value >> 1)) & 0x40000000)
12253 {
12254 as_bad_where (fixP->fx_file, fixP->fx_line,
12255 _("rel31 relocation overflow"));
12256 }
12257 newval |= value & 0x7fffffff;
12258 md_number_to_chars (buf, newval, 4);
12259 }
12260 break;
12261
b99bd4ef
NC
12262 case BFD_RELOC_ARM_PLT32:
12263 /* It appears the instruction is fully prepared at this point. */
12264 break;
12265#endif
12266
b99bd4ef
NC
12267 case BFD_RELOC_ARM_CP_OFF_IMM:
12268 sign = value >= 0;
12269 if (value < -1023 || value > 1023 || (value & 3))
12270 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12271 _("illegal value for co-processor offset"));
b99bd4ef
NC
12272 if (value < 0)
12273 value = -value;
12274 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
12275 newval |= (value >> 2) | (sign ? INDEX_UP : 0);
12276 md_number_to_chars (buf, newval, INSN_SIZE);
12277 break;
12278
e16bb312
NC
12279 case BFD_RELOC_ARM_CP_OFF_IMM_S2:
12280 sign = value >= 0;
12281 if (value < -255 || value > 255)
12282 as_bad_where (fixP->fx_file, fixP->fx_line,
12283 _("Illegal value for co-processor offset"));
12284 if (value < 0)
12285 value = -value;
12286 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
12287 newval |= value | (sign ? INDEX_UP : 0);
12288 md_number_to_chars (buf, newval , INSN_SIZE);
12289 break;
12290
b99bd4ef
NC
12291 case BFD_RELOC_ARM_THUMB_OFFSET:
12292 newval = md_chars_to_number (buf, THUMB_SIZE);
12293 /* Exactly what ranges, and where the offset is inserted depends
12294 on the type of instruction, we can establish this from the
12295 top 4 bits. */
12296 switch (newval >> 12)
12297 {
12298 case 4: /* PC load. */
12299 /* Thumb PC loads are somewhat odd, bit 1 of the PC is
12300 forced to zero for these loads, so we will need to round
12301 up the offset if the instruction address is not word
12302 aligned (since the final address produced must be, and
12303 we can only describe word-aligned immediate offsets). */
12304
12305 if ((fixP->fx_frag->fr_address + fixP->fx_where + value) & 3)
12306 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12307 _("invalid offset, target not word aligned (0x%08X)"),
b99bd4ef
NC
12308 (unsigned int) (fixP->fx_frag->fr_address
12309 + fixP->fx_where + value));
12310
12311 if ((value + 2) & ~0x3fe)
12312 as_bad_where (fixP->fx_file, fixP->fx_line,
08df2379
NC
12313 _("invalid offset, value too big (0x%08lX)"),
12314 (long) value);
b99bd4ef
NC
12315
12316 /* Round up, since pc will be rounded down. */
12317 newval |= (value + 2) >> 2;
12318 break;
12319
12320 case 9: /* SP load/store. */
12321 if (value & ~0x3fc)
12322 as_bad_where (fixP->fx_file, fixP->fx_line,
08df2379
NC
12323 _("invalid offset, value too big (0x%08lX)"),
12324 (long) value);
b99bd4ef
NC
12325 newval |= value >> 2;
12326 break;
12327
12328 case 6: /* Word load/store. */
12329 if (value & ~0x7c)
12330 as_bad_where (fixP->fx_file, fixP->fx_line,
08df2379
NC
12331 _("invalid offset, value too big (0x%08lX)"),
12332 (long) value);
b99bd4ef
NC
12333 newval |= value << 4; /* 6 - 2. */
12334 break;
12335
12336 case 7: /* Byte load/store. */
12337 if (value & ~0x1f)
12338 as_bad_where (fixP->fx_file, fixP->fx_line,
08df2379
NC
12339 _("invalid offset, value too big (0x%08lX)"),
12340 (long) value);
b99bd4ef
NC
12341 newval |= value << 6;
12342 break;
12343
12344 case 8: /* Halfword load/store. */
12345 if (value & ~0x3e)
12346 as_bad_where (fixP->fx_file, fixP->fx_line,
08df2379
NC
12347 _("invalid offset, value too big (0x%08lX)"),
12348 (long) value);
b99bd4ef
NC
12349 newval |= value << 5; /* 6 - 1. */
12350 break;
12351
12352 default:
12353 as_bad_where (fixP->fx_file, fixP->fx_line,
12354 "Unable to process relocation for thumb opcode: %lx",
12355 (unsigned long) newval);
12356 break;
12357 }
12358 md_number_to_chars (buf, newval, THUMB_SIZE);
12359 break;
12360
12361 case BFD_RELOC_ARM_THUMB_ADD:
12362 /* This is a complicated relocation, since we use it for all of
12363 the following immediate relocations:
12364
12365 3bit ADD/SUB
12366 8bit ADD/SUB
12367 9bit ADD/SUB SP word-aligned
12368 10bit ADD PC/SP word-aligned
12369
12370 The type of instruction being processed is encoded in the
12371 instruction field:
12372
12373 0x8000 SUB
12374 0x00F0 Rd
12375 0x000F Rs
12376 */
12377 newval = md_chars_to_number (buf, THUMB_SIZE);
12378 {
12379 int rd = (newval >> 4) & 0xf;
12380 int rs = newval & 0xf;
12381 int subtract = newval & 0x8000;
12382
12383 if (rd == REG_SP)
12384 {
12385 if (value & ~0x1fc)
12386 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12387 _("invalid immediate for stack address calculation"));
b99bd4ef
NC
12388 newval = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
12389 newval |= value >> 2;
12390 }
12391 else if (rs == REG_PC || rs == REG_SP)
12392 {
12393 if (subtract ||
12394 value & ~0x3fc)
12395 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12396 _("invalid immediate for address calculation (value = 0x%08lX)"),
b99bd4ef
NC
12397 (unsigned long) value);
12398 newval = (rs == REG_PC ? T_OPCODE_ADD_PC : T_OPCODE_ADD_SP);
12399 newval |= rd << 8;
12400 newval |= value >> 2;
12401 }
12402 else if (rs == rd)
12403 {
12404 if (value & ~0xff)
12405 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12406 _("invalid 8bit immediate"));
b99bd4ef
NC
12407 newval = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
12408 newval |= (rd << 8) | value;
12409 }
12410 else
12411 {
12412 if (value & ~0x7)
12413 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12414 _("invalid 3bit immediate"));
b99bd4ef
NC
12415 newval = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
12416 newval |= rd | (rs << 3) | (value << 6);
12417 }
12418 }
12419 md_number_to_chars (buf, newval, THUMB_SIZE);
12420 break;
12421
12422 case BFD_RELOC_ARM_THUMB_IMM:
12423 newval = md_chars_to_number (buf, THUMB_SIZE);
12424 switch (newval >> 11)
12425 {
12426 case 0x04: /* 8bit immediate MOV. */
12427 case 0x05: /* 8bit immediate CMP. */
12428 if (value < 0 || value > 255)
12429 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12430 _("invalid immediate: %ld is too large"),
b99bd4ef
NC
12431 (long) value);
12432 newval |= value;
12433 break;
12434
12435 default:
12436 abort ();
12437 }
12438 md_number_to_chars (buf, newval, THUMB_SIZE);
12439 break;
12440
12441 case BFD_RELOC_ARM_THUMB_SHIFT:
12442 /* 5bit shift value (0..31). */
12443 if (value < 0 || value > 31)
12444 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12445 _("illegal Thumb shift value: %ld"), (long) value);
b99bd4ef
NC
12446 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xf03f;
12447 newval |= value << 6;
12448 md_number_to_chars (buf, newval, THUMB_SIZE);
12449 break;
12450
12451 case BFD_RELOC_VTABLE_INHERIT:
12452 case BFD_RELOC_VTABLE_ENTRY:
12453 fixP->fx_done = 0;
94f592af 12454 return;
b99bd4ef 12455
620b81c1 12456 case BFD_RELOC_UNUSED:
b99bd4ef
NC
12457 default:
12458 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12459 _("bad relocation fixup type (%d)"), fixP->fx_r_type);
b99bd4ef 12460 }
b99bd4ef
NC
12461}
12462
12463/* Translate internal representation of relocation info to BFD target
12464 format. */
12465
12466arelent *
a737bd4d
NC
12467tc_gen_reloc (asection * section ATTRIBUTE_UNUSED,
12468 fixS * fixp)
b99bd4ef
NC
12469{
12470 arelent * reloc;
12471 bfd_reloc_code_real_type code;
12472
a737bd4d 12473 reloc = xmalloc (sizeof (arelent));
b99bd4ef 12474
a737bd4d 12475 reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
b99bd4ef
NC
12476 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
12477 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
12478
12479 /* @@ Why fx_addnumber sometimes and fx_offset other times? */
12480#ifndef OBJ_ELF
12481 if (fixp->fx_pcrel == 0)
12482 reloc->addend = fixp->fx_offset;
12483 else
12484 reloc->addend = fixp->fx_offset = reloc->address;
12485#else /* OBJ_ELF */
12486 reloc->addend = fixp->fx_offset;
12487#endif
12488
12489 switch (fixp->fx_r_type)
12490 {
12491 case BFD_RELOC_8:
12492 if (fixp->fx_pcrel)
12493 {
12494 code = BFD_RELOC_8_PCREL;
12495 break;
12496 }
12497
12498 case BFD_RELOC_16:
12499 if (fixp->fx_pcrel)
12500 {
12501 code = BFD_RELOC_16_PCREL;
12502 break;
12503 }
12504
12505 case BFD_RELOC_32:
12506 if (fixp->fx_pcrel)
12507 {
12508 code = BFD_RELOC_32_PCREL;
12509 break;
12510 }
12511
620b81c1 12512 case BFD_RELOC_NONE:
b99bd4ef
NC
12513 case BFD_RELOC_ARM_PCREL_BRANCH:
12514 case BFD_RELOC_ARM_PCREL_BLX:
12515 case BFD_RELOC_RVA:
12516 case BFD_RELOC_THUMB_PCREL_BRANCH9:
12517 case BFD_RELOC_THUMB_PCREL_BRANCH12:
12518 case BFD_RELOC_THUMB_PCREL_BRANCH23:
12519 case BFD_RELOC_THUMB_PCREL_BLX:
12520 case BFD_RELOC_VTABLE_ENTRY:
12521 case BFD_RELOC_VTABLE_INHERIT:
12522 code = fixp->fx_r_type;
12523 break;
12524
12525 case BFD_RELOC_ARM_LITERAL:
12526 case BFD_RELOC_ARM_HWLITERAL:
3d0c9500
NC
12527 /* If this is called then the a literal has
12528 been referenced across a section boundary. */
b99bd4ef 12529 as_bad_where (fixp->fx_file, fixp->fx_line,
61b5f74b 12530 _("literal referenced across section boundary"));
b99bd4ef
NC
12531 return NULL;
12532
12533#ifdef OBJ_ELF
12534 case BFD_RELOC_ARM_GOT32:
12535 case BFD_RELOC_ARM_GOTOFF:
12536 case BFD_RELOC_ARM_PLT32:
9c504268 12537 case BFD_RELOC_ARM_TARGET1:
db6579d4
PB
12538 case BFD_RELOC_ARM_ROSEGREL32:
12539 case BFD_RELOC_ARM_SBREL32:
eb043451
PB
12540 case BFD_RELOC_ARM_PREL31:
12541 case BFD_RELOC_ARM_TARGET2:
b99bd4ef
NC
12542 code = fixp->fx_r_type;
12543 break;
12544#endif
12545
12546 case BFD_RELOC_ARM_IMMEDIATE:
12547 as_bad_where (fixp->fx_file, fixp->fx_line,
6189168b 12548 _("internal relocation (type: IMMEDIATE) not fixed up"));
b99bd4ef
NC
12549 return NULL;
12550
12551 case BFD_RELOC_ARM_ADRL_IMMEDIATE:
12552 as_bad_where (fixp->fx_file, fixp->fx_line,
12553 _("ADRL used for a symbol not defined in the same file"));
12554 return NULL;
12555
12556 case BFD_RELOC_ARM_OFFSET_IMM:
c3ba240c
DJ
12557 if (fixp->fx_addsy != NULL
12558 && !S_IS_DEFINED (fixp->fx_addsy)
12559 && S_IS_LOCAL (fixp->fx_addsy))
12560 {
12561 as_bad_where (fixp->fx_file, fixp->fx_line,
12562 _("undefined local label `%s'"),
12563 S_GET_NAME (fixp->fx_addsy));
12564 return NULL;
12565 }
12566
b99bd4ef 12567 as_bad_where (fixp->fx_file, fixp->fx_line,
6189168b 12568 _("internal_relocation (type: OFFSET_IMM) not fixed up"));
b99bd4ef
NC
12569 return NULL;
12570
12571 default:
12572 {
12573 char * type;
12574
12575 switch (fixp->fx_r_type)
12576 {
620b81c1 12577 case BFD_RELOC_NONE: type = "NONE"; break;
b99bd4ef
NC
12578 case BFD_RELOC_ARM_OFFSET_IMM8: type = "OFFSET_IMM8"; break;
12579 case BFD_RELOC_ARM_SHIFT_IMM: type = "SHIFT_IMM"; break;
0dd132b6 12580 case BFD_RELOC_ARM_SMI: type = "SMI"; break;
b99bd4ef
NC
12581 case BFD_RELOC_ARM_SWI: type = "SWI"; break;
12582 case BFD_RELOC_ARM_MULTI: type = "MULTI"; break;
12583 case BFD_RELOC_ARM_CP_OFF_IMM: type = "CP_OFF_IMM"; break;
12584 case BFD_RELOC_ARM_THUMB_ADD: type = "THUMB_ADD"; break;
12585 case BFD_RELOC_ARM_THUMB_SHIFT: type = "THUMB_SHIFT"; break;
12586 case BFD_RELOC_ARM_THUMB_IMM: type = "THUMB_IMM"; break;
12587 case BFD_RELOC_ARM_THUMB_OFFSET: type = "THUMB_OFFSET"; break;
12588 default: type = _("<unknown>"); break;
12589 }
12590 as_bad_where (fixp->fx_file, fixp->fx_line,
f03698e6 12591 _("cannot represent %s relocation in this object file format"),
b99bd4ef
NC
12592 type);
12593 return NULL;
12594 }
12595 }
12596
12597#ifdef OBJ_ELF
8df7094c 12598 if ((code == BFD_RELOC_32_PCREL || code == BFD_RELOC_32)
b99bd4ef
NC
12599 && GOT_symbol
12600 && fixp->fx_addsy == GOT_symbol)
12601 {
12602 code = BFD_RELOC_ARM_GOTPC;
12603 reloc->addend = fixp->fx_offset = reloc->address;
12604 }
12605#endif
12606
12607 reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
12608
12609 if (reloc->howto == NULL)
12610 {
12611 as_bad_where (fixp->fx_file, fixp->fx_line,
f03698e6 12612 _("cannot represent %s relocation in this object file format"),
b99bd4ef
NC
12613 bfd_get_reloc_code_name (code));
12614 return NULL;
12615 }
12616
12617 /* HACK: Since arm ELF uses Rel instead of Rela, encode the
12618 vtable entry to be used in the relocation's section offset. */
12619 if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
12620 reloc->address = fixp->fx_offset;
12621
12622 return reloc;
12623}
12624
12625int
a737bd4d
NC
12626md_estimate_size_before_relax (fragS * fragP ATTRIBUTE_UNUSED,
12627 segT segtype ATTRIBUTE_UNUSED)
b99bd4ef
NC
12628{
12629 as_fatal (_("md_estimate_size_before_relax\n"));
12630 return 1;
12631}
12632
a737bd4d
NC
12633/* We need to be able to fix up arbitrary expressions in some statements.
12634 This is so that we can handle symbols that are an arbitrary distance from
12635 the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
12636 which returns part of an address in a form which will be valid for
12637 a data instruction. We do this by pushing the expression into a symbol
12638 in the expr_section, and creating a fix for that. */
12639
12640static void
12641fix_new_arm (fragS * frag,
12642 int where,
12643 short int size,
12644 expressionS * exp,
12645 int pc_rel,
12646 int reloc)
12647{
12648 fixS * new_fix;
12649 arm_fix_data * arm_data;
12650
12651 switch (exp->X_op)
12652 {
12653 case O_constant:
12654 case O_symbol:
12655 case O_add:
12656 case O_subtract:
12657 new_fix = fix_new_exp (frag, where, size, exp, pc_rel, reloc);
12658 break;
12659
12660 default:
12661 new_fix = fix_new (frag, where, size, make_expr_symbol (exp), 0,
12662 pc_rel, reloc);
12663 break;
12664 }
12665
12666 /* Mark whether the fix is to a THUMB instruction, or an ARM
12667 instruction. */
12668 arm_data = obstack_alloc (& notes, sizeof (arm_fix_data));
12669 new_fix->tc_fix_data = (PTR) arm_data;
12670 arm_data->thumb_mode = thumb_mode;
12671}
12672
b99bd4ef 12673static void
a737bd4d 12674output_inst (const char * str)
b99bd4ef
NC
12675{
12676 char * to = NULL;
12677
12678 if (inst.error)
12679 {
f03698e6 12680 as_bad ("%s -- `%s'", inst.error, str);
b99bd4ef
NC
12681 return;
12682 }
12683
12684 to = frag_more (inst.size);
12685
12686 if (thumb_mode && (inst.size > THUMB_SIZE))
12687 {
12688 assert (inst.size == (2 * THUMB_SIZE));
12689 md_number_to_chars (to, inst.instruction >> 16, THUMB_SIZE);
12690 md_number_to_chars (to + THUMB_SIZE, inst.instruction, THUMB_SIZE);
12691 }
12692 else if (inst.size > INSN_SIZE)
12693 {
12694 assert (inst.size == (2 * INSN_SIZE));
12695 md_number_to_chars (to, inst.instruction, INSN_SIZE);
12696 md_number_to_chars (to + INSN_SIZE, inst.instruction, INSN_SIZE);
12697 }
12698 else
12699 md_number_to_chars (to, inst.instruction, inst.size);
12700
620b81c1 12701 if (inst.reloc.type != BFD_RELOC_UNUSED)
b99bd4ef
NC
12702 fix_new_arm (frag_now, to - frag_now->fr_literal,
12703 inst.size, & inst.reloc.exp, inst.reloc.pc_rel,
12704 inst.reloc.type);
12705
12706#ifdef OBJ_ELF
12707 dwarf2_emit_insn (inst.size);
12708#endif
12709}
12710
12711void
a737bd4d 12712md_assemble (char * str)
b99bd4ef 12713{
6c43fab6
RE
12714 char c;
12715 char *p;
12716 char *start;
b99bd4ef 12717
b99bd4ef
NC
12718 /* Align the previous label if needed. */
12719 if (last_label_seen != NULL)
12720 {
12721 symbol_set_frag (last_label_seen, frag_now);
12722 S_SET_VALUE (last_label_seen, (valueT) frag_now_fix ());
12723 S_SET_SEGMENT (last_label_seen, now_seg);
12724 }
12725
12726 memset (&inst, '\0', sizeof (inst));
620b81c1 12727 inst.reloc.type = BFD_RELOC_UNUSED;
b99bd4ef
NC
12728
12729 skip_whitespace (str);
12730
12731 /* Scan up to the end of the op-code, which must end in white space or
12732 end of string. */
12733 for (start = p = str; *p != '\0'; p++)
12734 if (*p == ' ')
12735 break;
12736
12737 if (p == str)
12738 {
f03698e6 12739 as_bad (_("no operator -- statement `%s'\n"), str);
b99bd4ef
NC
12740 return;
12741 }
12742
12743 if (thumb_mode)
12744 {
05d2d07e 12745 const struct thumb_opcode * opcode;
b99bd4ef
NC
12746
12747 c = *p;
12748 *p = '\0';
05d2d07e 12749 opcode = (const struct thumb_opcode *) hash_find (arm_tops_hsh, str);
b99bd4ef
NC
12750 *p = c;
12751
12752 if (opcode)
12753 {
12754 /* Check that this instruction is supported for this CPU. */
90e4755a 12755 if (thumb_mode == 1 && (opcode->variant & cpu_variant) == 0)
b99bd4ef 12756 {
f03698e6 12757 as_bad (_("selected processor does not support `%s'"), str);
b99bd4ef
NC
12758 return;
12759 }
12760
6057a28f 12761 mapping_state (MAP_THUMB);
b99bd4ef
NC
12762 inst.instruction = opcode->value;
12763 inst.size = opcode->size;
a737bd4d 12764 opcode->parms (p);
f03698e6 12765 output_inst (str);
b99bd4ef
NC
12766 return;
12767 }
12768 }
12769 else
12770 {
05d2d07e 12771 const struct asm_opcode * opcode;
b99bd4ef 12772
90e4755a
RE
12773 c = *p;
12774 *p = '\0';
6c43fab6 12775 opcode = (const struct asm_opcode *) hash_find (arm_ops_hsh, str);
90e4755a 12776 *p = c;
b99bd4ef 12777
90e4755a 12778 if (opcode)
b99bd4ef 12779 {
90e4755a
RE
12780 /* Check that this instruction is supported for this CPU. */
12781 if ((opcode->variant & cpu_variant) == 0)
b99bd4ef 12782 {
f03698e6 12783 as_bad (_("selected processor does not support `%s'"), str);
b99bd4ef
NC
12784 return;
12785 }
12786
6057a28f 12787 mapping_state (MAP_ARM);
90e4755a
RE
12788 inst.instruction = opcode->value;
12789 inst.size = INSN_SIZE;
a737bd4d 12790 opcode->parms (p);
f03698e6 12791 output_inst (str);
90e4755a 12792 return;
b99bd4ef
NC
12793 }
12794 }
12795
12796 /* It wasn't an instruction, but it might be a register alias of the form
12797 alias .req reg. */
6c43fab6
RE
12798 if (create_register_alias (str, p))
12799 return;
b99bd4ef 12800
b99bd4ef
NC
12801 as_bad (_("bad instruction `%s'"), start);
12802}
12803
12804/* md_parse_option
12805 Invocation line includes a switch not recognized by the base assembler.
cc8a6dd0 12806 See if it's a processor-specific option.
03b1477f
RE
12807
12808 This routine is somewhat complicated by the need for backwards
12809 compatibility (since older releases of gcc can't be changed).
12810 The new options try to make the interface as compatible as
12811 possible with GCC.
12812
12813 New options (supported) are:
12814
12815 -mcpu=<cpu name> Assemble for selected processor
12816 -march=<architecture name> Assemble for selected architecture
12817 -mfpu=<fpu architecture> Assemble for selected FPU.
12818 -EB/-mbig-endian Big-endian
12819 -EL/-mlittle-endian Little-endian
12820 -k Generate PIC code
12821 -mthumb Start in Thumb mode
12822 -mthumb-interwork Code supports ARM/Thumb interworking
12823
3d0c9500 12824 For now we will also provide support for:
03b1477f
RE
12825
12826 -mapcs-32 32-bit Program counter
12827 -mapcs-26 26-bit Program counter
12828 -macps-float Floats passed in FP registers
12829 -mapcs-reentrant Reentrant code
12830 -matpcs
12831 (sometime these will probably be replaced with -mapcs=<list of options>
12832 and -matpcs=<list of options>)
12833
12834 The remaining options are only supported for back-wards compatibility.
b99bd4ef
NC
12835 Cpu variants, the arm part is optional:
12836 -m[arm]1 Currently not supported.
12837 -m[arm]2, -m[arm]250 Arm 2 and Arm 250 processor
12838 -m[arm]3 Arm 3 processor
12839 -m[arm]6[xx], Arm 6 processors
12840 -m[arm]7[xx][t][[d]m] Arm 7 processors
12841 -m[arm]8[10] Arm 8 processors
12842 -m[arm]9[20][tdmi] Arm 9 processors
12843 -mstrongarm[110[0]] StrongARM processors
12844 -mxscale XScale processors
12845 -m[arm]v[2345[t[e]]] Arm architectures
12846 -mall All (except the ARM1)
12847 FP variants:
12848 -mfpa10, -mfpa11 FPA10 and 11 co-processor instructions
12849 -mfpe-old (No float load/store multiples)
bfae80f2
RE
12850 -mvfpxd VFP Single precision
12851 -mvfp All VFP
b99bd4ef 12852 -mno-fpu Disable all floating point instructions
b99bd4ef 12853
03b1477f
RE
12854 The following CPU names are recognized:
12855 arm1, arm2, arm250, arm3, arm6, arm600, arm610, arm620,
12856 arm7, arm7m, arm7d, arm7dm, arm7di, arm7dmi, arm70, arm700,
12857 arm700i, arm710 arm710t, arm720, arm720t, arm740t, arm710c,
12858 arm7100, arm7500, arm7500fe, arm7tdmi, arm8, arm810, arm9,
12859 arm920, arm920t, arm940t, arm946, arm966, arm9tdmi, arm9e,
12860 arm10t arm10e, arm1020t, arm1020e, arm10200e,
12861 strongarm, strongarm110, strongarm1100, strongarm1110, xscale.
12862
12863 */
12864
5a38dc70 12865const char * md_shortopts = "m:k";
03b1477f 12866
b99bd4ef
NC
12867#ifdef ARM_BI_ENDIAN
12868#define OPTION_EB (OPTION_MD_BASE + 0)
b99bd4ef 12869#define OPTION_EL (OPTION_MD_BASE + 1)
21f0f23a 12870#else
21f0f23a
RE
12871#if TARGET_BYTES_BIG_ENDIAN
12872#define OPTION_EB (OPTION_MD_BASE + 0)
21f0f23a
RE
12873#else
12874#define OPTION_EL (OPTION_MD_BASE + 1)
21f0f23a 12875#endif
ce058b6c 12876#endif
03b1477f
RE
12877
12878struct option md_longopts[] =
12879{
12880#ifdef OPTION_EB
12881 {"EB", no_argument, NULL, OPTION_EB},
12882#endif
12883#ifdef OPTION_EL
12884 {"EL", no_argument, NULL, OPTION_EL},
b99bd4ef
NC
12885#endif
12886 {NULL, no_argument, NULL, 0}
12887};
12888
12889size_t md_longopts_size = sizeof (md_longopts);
12890
03b1477f 12891struct arm_option_table
b99bd4ef 12892{
03b1477f
RE
12893 char *option; /* Option name to match. */
12894 char *help; /* Help information. */
12895 int *var; /* Variable to change. */
12896 int value; /* What to change it to. */
12897 char *deprecated; /* If non-null, print this message. */
12898};
b99bd4ef 12899
cc8a6dd0 12900struct arm_option_table arm_opts[] =
03b1477f
RE
12901{
12902 {"k", N_("generate PIC code"), &pic_code, 1, NULL},
12903 {"mthumb", N_("assemble Thumb code"), &thumb_mode, 1, NULL},
12904 {"mthumb-interwork", N_("support ARM/Thumb interworking"),
12905 &support_interwork, 1, NULL},
03b1477f
RE
12906 {"mapcs-32", N_("code uses 32-bit program counter"), &uses_apcs_26, 0, NULL},
12907 {"mapcs-26", N_("code uses 26-bit program counter"), &uses_apcs_26, 1, NULL},
12908 {"mapcs-float", N_("floating point args are in fp regs"), &uses_apcs_float,
12909 1, NULL},
12910 {"mapcs-reentrant", N_("re-entrant code"), &pic_code, 1, NULL},
12911 {"matpcs", N_("code is ATPCS conformant"), &atpcs, 1, NULL},
12912 {"mbig-endian", N_("assemble for big-endian"), &target_big_endian, 1, NULL},
12913 {"mlittle-endian", N_("assemble for little-endian"), &target_big_endian, 1,
12914 NULL},
12915
12916 /* These are recognized by the assembler, but have no affect on code. */
12917 {"mapcs-frame", N_("use frame pointer"), NULL, 0, NULL},
12918 {"mapcs-stack-check", N_("use stack size checking"), NULL, 0, NULL},
12919
12920 /* DON'T add any new processors to this list -- we want the whole list
12921 to go away... Add them to the processors table instead. */
12922 {"marm1", NULL, &legacy_cpu, ARM_ARCH_V1, N_("use -mcpu=arm1")},
12923 {"m1", NULL, &legacy_cpu, ARM_ARCH_V1, N_("use -mcpu=arm1")},
12924 {"marm2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -mcpu=arm2")},
12925 {"m2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -mcpu=arm2")},
12926 {"marm250", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm250")},
12927 {"m250", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm250")},
12928 {"marm3", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm3")},
12929 {"m3", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm3")},
12930 {"marm6", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm6")},
12931 {"m6", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm6")},
12932 {"marm600", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm600")},
12933 {"m600", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm600")},
12934 {"marm610", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm610")},
12935 {"m610", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm610")},
12936 {"marm620", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm620")},
12937 {"m620", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm620")},
12938 {"marm7", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7")},
12939 {"m7", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7")},
12940 {"marm70", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm70")},
12941 {"m70", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm70")},
12942 {"marm700", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700")},
12943 {"m700", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700")},
12944 {"marm700i", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700i")},
12945 {"m700i", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700i")},
12946 {"marm710", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710")},
12947 {"m710", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710")},
12948 {"marm710c", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710c")},
12949 {"m710c", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710c")},
12950 {"marm720", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm720")},
12951 {"m720", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm720")},
12952 {"marm7d", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7d")},
12953 {"m7d", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7d")},
12954 {"marm7di", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7di")},
12955 {"m7di", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7di")},
12956 {"marm7m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7m")},
12957 {"m7m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7m")},
12958 {"marm7dm", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dm")},
12959 {"m7dm", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dm")},
12960 {"marm7dmi", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dmi")},
12961 {"m7dmi", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dmi")},
12962 {"marm7100", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7100")},
12963 {"m7100", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7100")},
12964 {"marm7500", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500")},
12965 {"m7500", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500")},
12966 {"marm7500fe", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500fe")},
12967 {"m7500fe", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500fe")},
12968 {"marm7t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
12969 {"m7t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
12970 {"marm7tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
12971 {"m7tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
12972 {"marm710t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm710t")},
12973 {"m710t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm710t")},
12974 {"marm720t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm720t")},
12975 {"m720t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm720t")},
12976 {"marm740t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm740t")},
12977 {"m740t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm740t")},
12978 {"marm8", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm8")},
12979 {"m8", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm8")},
12980 {"marm810", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm810")},
12981 {"m810", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm810")},
12982 {"marm9", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9")},
12983 {"m9", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9")},
12984 {"marm9tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9tdmi")},
12985 {"m9tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9tdmi")},
12986 {"marm920", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm920")},
12987 {"m920", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm920")},
12988 {"marm940", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm940")},
12989 {"m940", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm940")},
12990 {"mstrongarm", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=strongarm")},
12991 {"mstrongarm110", NULL, &legacy_cpu, ARM_ARCH_V4,
12992 N_("use -mcpu=strongarm110")},
12993 {"mstrongarm1100", NULL, &legacy_cpu, ARM_ARCH_V4,
12994 N_("use -mcpu=strongarm1100")},
12995 {"mstrongarm1110", NULL, &legacy_cpu, ARM_ARCH_V4,
12996 N_("use -mcpu=strongarm1110")},
12997 {"mxscale", NULL, &legacy_cpu, ARM_ARCH_XSCALE, N_("use -mcpu=xscale")},
e16bb312 12998 {"miwmmxt", NULL, &legacy_cpu, ARM_ARCH_IWMMXT, N_("use -mcpu=iwmmxt")},
03b1477f
RE
12999 {"mall", NULL, &legacy_cpu, ARM_ANY, N_("use -mcpu=all")},
13000
13001 /* Architecture variants -- don't add any more to this list either. */
13002 {"mv2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -march=armv2")},
13003 {"marmv2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -march=armv2")},
13004 {"mv2a", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -march=armv2a")},
13005 {"marmv2a", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -march=armv2a")},
13006 {"mv3", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -march=armv3")},
13007 {"marmv3", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -march=armv3")},
13008 {"mv3m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -march=armv3m")},
13009 {"marmv3m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -march=armv3m")},
13010 {"mv4", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -march=armv4")},
13011 {"marmv4", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -march=armv4")},
13012 {"mv4t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -march=armv4t")},
13013 {"marmv4t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -march=armv4t")},
13014 {"mv5", NULL, &legacy_cpu, ARM_ARCH_V5, N_("use -march=armv5")},
13015 {"marmv5", NULL, &legacy_cpu, ARM_ARCH_V5, N_("use -march=armv5")},
13016 {"mv5t", NULL, &legacy_cpu, ARM_ARCH_V5T, N_("use -march=armv5t")},
13017 {"marmv5t", NULL, &legacy_cpu, ARM_ARCH_V5T, N_("use -march=armv5t")},
13018 {"mv5e", NULL, &legacy_cpu, ARM_ARCH_V5TE, N_("use -march=armv5te")},
13019 {"marmv5e", NULL, &legacy_cpu, ARM_ARCH_V5TE, N_("use -march=armv5te")},
13020
13021 /* Floating point variants -- don't add any more to this list either. */
13022 {"mfpe-old", NULL, &legacy_fpu, FPU_ARCH_FPE, N_("use -mfpu=fpe")},
13023 {"mfpa10", NULL, &legacy_fpu, FPU_ARCH_FPA, N_("use -mfpu=fpa10")},
13024 {"mfpa11", NULL, &legacy_fpu, FPU_ARCH_FPA, N_("use -mfpu=fpa11")},
13025 {"mno-fpu", NULL, &legacy_fpu, 0,
13026 N_("use either -mfpu=softfpa or -mfpu=softvfp")},
13027
13028 {NULL, NULL, NULL, 0, NULL}
13029};
21f0f23a 13030
03b1477f
RE
13031struct arm_cpu_option_table
13032{
13033 char *name;
13034 int value;
13035 /* For some CPUs we assume an FPU unless the user explicitly sets
13036 -mfpu=... */
13037 int default_fpu;
13038};
13039
13040/* This list should, at a minimum, contain all the cpu names
13041 recognized by GCC. */
13042static struct arm_cpu_option_table arm_cpus[] =
13043{
13044 {"all", ARM_ANY, FPU_ARCH_FPA},
13045 {"arm1", ARM_ARCH_V1, FPU_ARCH_FPA},
13046 {"arm2", ARM_ARCH_V2, FPU_ARCH_FPA},
13047 {"arm250", ARM_ARCH_V2S, FPU_ARCH_FPA},
13048 {"arm3", ARM_ARCH_V2S, FPU_ARCH_FPA},
13049 {"arm6", ARM_ARCH_V3, FPU_ARCH_FPA},
13050 {"arm60", ARM_ARCH_V3, FPU_ARCH_FPA},
13051 {"arm600", ARM_ARCH_V3, FPU_ARCH_FPA},
13052 {"arm610", ARM_ARCH_V3, FPU_ARCH_FPA},
13053 {"arm620", ARM_ARCH_V3, FPU_ARCH_FPA},
13054 {"arm7", ARM_ARCH_V3, FPU_ARCH_FPA},
13055 {"arm7m", ARM_ARCH_V3M, FPU_ARCH_FPA},
13056 {"arm7d", ARM_ARCH_V3, FPU_ARCH_FPA},
13057 {"arm7dm", ARM_ARCH_V3M, FPU_ARCH_FPA},
13058 {"arm7di", ARM_ARCH_V3, FPU_ARCH_FPA},
13059 {"arm7dmi", ARM_ARCH_V3M, FPU_ARCH_FPA},
13060 {"arm70", ARM_ARCH_V3, FPU_ARCH_FPA},
13061 {"arm700", ARM_ARCH_V3, FPU_ARCH_FPA},
13062 {"arm700i", ARM_ARCH_V3, FPU_ARCH_FPA},
13063 {"arm710", ARM_ARCH_V3, FPU_ARCH_FPA},
13064 {"arm710t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13065 {"arm720", ARM_ARCH_V3, FPU_ARCH_FPA},
13066 {"arm720t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13067 {"arm740t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13068 {"arm710c", ARM_ARCH_V3, FPU_ARCH_FPA},
13069 {"arm7100", ARM_ARCH_V3, FPU_ARCH_FPA},
13070 {"arm7500", ARM_ARCH_V3, FPU_ARCH_FPA},
13071 {"arm7500fe", ARM_ARCH_V3, FPU_ARCH_FPA},
13072 {"arm7t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13073 {"arm7tdmi", ARM_ARCH_V4T, FPU_ARCH_FPA},
8783612f 13074 {"arm7tdmi-s", ARM_ARCH_V4T, FPU_ARCH_FPA},
03b1477f
RE
13075 {"arm8", ARM_ARCH_V4, FPU_ARCH_FPA},
13076 {"arm810", ARM_ARCH_V4, FPU_ARCH_FPA},
13077 {"strongarm", ARM_ARCH_V4, FPU_ARCH_FPA},
13078 {"strongarm1", ARM_ARCH_V4, FPU_ARCH_FPA},
13079 {"strongarm110", ARM_ARCH_V4, FPU_ARCH_FPA},
13080 {"strongarm1100", ARM_ARCH_V4, FPU_ARCH_FPA},
13081 {"strongarm1110", ARM_ARCH_V4, FPU_ARCH_FPA},
13082 {"arm9", ARM_ARCH_V4T, FPU_ARCH_FPA},
13083 {"arm920", ARM_ARCH_V4T, FPU_ARCH_FPA},
13084 {"arm920t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13085 {"arm922t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13086 {"arm940t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13087 {"arm9tdmi", ARM_ARCH_V4T, FPU_ARCH_FPA},
13088 /* For V5 or later processors we default to using VFP; but the user
13089 should really set the FPU type explicitly. */
13090 {"arm9e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
13091 {"arm9e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
ea6ef066 13092 {"arm926ej", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
7de9afa2 13093 {"arm926ejs", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
8783612f 13094 {"arm926ej-s", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
03b1477f
RE
13095 {"arm946e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
13096 {"arm946e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13097 {"arm966e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
13098 {"arm966e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13099 {"arm10t", ARM_ARCH_V5T, FPU_ARCH_VFP_V1},
13100 {"arm10e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13101 {"arm1020", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13102 {"arm1020t", ARM_ARCH_V5T, FPU_ARCH_VFP_V1},
13103 {"arm1020e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
5dc1606f
PB
13104 {"arm1026ejs", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
13105 {"arm1026ej-s", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
09d92015 13106 {"arm1136js", ARM_ARCH_V6, FPU_NONE},
9166bcd7 13107 {"arm1136j-s", ARM_ARCH_V6, FPU_NONE},
09d92015 13108 {"arm1136jfs", ARM_ARCH_V6, FPU_ARCH_VFP_V2},
8783612f 13109 {"arm1136jf-s", ARM_ARCH_V6, FPU_ARCH_VFP_V2},
0dd132b6
NC
13110 {"mpcore", ARM_ARCH_V6K, FPU_ARCH_VFP_V2},
13111 {"mpcorenovfp", ARM_ARCH_V6K, FPU_NONE},
13112 {"arm1176jz-s", ARM_ARCH_V6ZK, FPU_NONE},
13113 {"arm1176jzf-s", ARM_ARCH_V6ZK, FPU_ARCH_VFP_V2},
03b1477f
RE
13114 /* ??? XSCALE is really an architecture. */
13115 {"xscale", ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2},
5a6c6817 13116 /* ??? iwmmxt is not a processor. */
e16bb312 13117 {"iwmmxt", ARM_ARCH_IWMMXT, FPU_ARCH_VFP_V2},
03b1477f
RE
13118 {"i80200", ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2},
13119 /* Maverick */
33a392fb 13120 {"ep9312", ARM_ARCH_V4T | ARM_CEXT_MAVERICK, FPU_ARCH_MAVERICK},
03b1477f
RE
13121 {NULL, 0, 0}
13122};
cc8a6dd0 13123
03b1477f
RE
13124struct arm_arch_option_table
13125{
13126 char *name;
13127 int value;
13128 int default_fpu;
13129};
13130
13131/* This list should, at a minimum, contain all the architecture names
13132 recognized by GCC. */
13133static struct arm_arch_option_table arm_archs[] =
13134{
13135 {"all", ARM_ANY, FPU_ARCH_FPA},
13136 {"armv1", ARM_ARCH_V1, FPU_ARCH_FPA},
13137 {"armv2", ARM_ARCH_V2, FPU_ARCH_FPA},
13138 {"armv2a", ARM_ARCH_V2S, FPU_ARCH_FPA},
13139 {"armv2s", ARM_ARCH_V2S, FPU_ARCH_FPA},
13140 {"armv3", ARM_ARCH_V3, FPU_ARCH_FPA},
13141 {"armv3m", ARM_ARCH_V3M, FPU_ARCH_FPA},
13142 {"armv4", ARM_ARCH_V4, FPU_ARCH_FPA},
13143 {"armv4xm", ARM_ARCH_V4xM, FPU_ARCH_FPA},
13144 {"armv4t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13145 {"armv4txm", ARM_ARCH_V4TxM, FPU_ARCH_FPA},
13146 {"armv5", ARM_ARCH_V5, FPU_ARCH_VFP},
13147 {"armv5t", ARM_ARCH_V5T, FPU_ARCH_VFP},
13148 {"armv5txm", ARM_ARCH_V5TxM, FPU_ARCH_VFP},
13149 {"armv5te", ARM_ARCH_V5TE, FPU_ARCH_VFP},
13150 {"armv5texp", ARM_ARCH_V5TExP, FPU_ARCH_VFP},
ea6ef066 13151 {"armv5tej", ARM_ARCH_V5TEJ, FPU_ARCH_VFP},
84255574 13152 {"armv6", ARM_ARCH_V6, FPU_ARCH_VFP},
1ddd7f43 13153 {"armv6j", ARM_ARCH_V6, FPU_ARCH_VFP},
0dd132b6
NC
13154 {"armv6k", ARM_ARCH_V6K, FPU_ARCH_VFP},
13155 {"armv6z", ARM_ARCH_V6Z, FPU_ARCH_VFP},
13156 {"armv6zk", ARM_ARCH_V6ZK, FPU_ARCH_VFP},
b05fe5cf
ZW
13157 {"armv6t2", ARM_ARCH_V6T2, FPU_ARCH_VFP},
13158 {"armv6kt2", ARM_ARCH_V6KT2, FPU_ARCH_VFP},
13159 {"armv6zt2", ARM_ARCH_V6ZT2, FPU_ARCH_VFP},
13160 {"armv6zkt2", ARM_ARCH_V6ZKT2, FPU_ARCH_VFP},
03b1477f 13161 {"xscale", ARM_ARCH_XSCALE, FPU_ARCH_VFP},
8266886e 13162 {"iwmmxt", ARM_ARCH_IWMMXT, FPU_ARCH_VFP},
03b1477f
RE
13163 {NULL, 0, 0}
13164};
13165
13166/* ISA extensions in the co-processor space. */
13167struct arm_arch_extension_table
13168{
13169 char *name;
13170 int value;
13171};
13172
13173static struct arm_arch_extension_table arm_extensions[] =
13174{
13175 {"maverick", ARM_CEXT_MAVERICK},
13176 {"xscale", ARM_CEXT_XSCALE},
e16bb312 13177 {"iwmmxt", ARM_CEXT_IWMMXT},
03b1477f
RE
13178 {NULL, 0}
13179};
b99bd4ef 13180
03b1477f
RE
13181struct arm_fpu_option_table
13182{
13183 char *name;
13184 int value;
13185};
13186
13187/* This list should, at a minimum, contain all the fpu names
13188 recognized by GCC. */
13189static struct arm_fpu_option_table arm_fpus[] =
13190{
13191 {"softfpa", FPU_NONE},
13192 {"fpe", FPU_ARCH_FPE},
d193a22a
RE
13193 {"fpe2", FPU_ARCH_FPE},
13194 {"fpe3", FPU_ARCH_FPA}, /* Third release supports LFM/SFM. */
03b1477f
RE
13195 {"fpa", FPU_ARCH_FPA},
13196 {"fpa10", FPU_ARCH_FPA},
13197 {"fpa11", FPU_ARCH_FPA},
13198 {"arm7500fe", FPU_ARCH_FPA},
13199 {"softvfp", FPU_ARCH_VFP},
13200 {"softvfp+vfp", FPU_ARCH_VFP_V2},
13201 {"vfp", FPU_ARCH_VFP_V2},
13202 {"vfp9", FPU_ARCH_VFP_V2},
13203 {"vfp10", FPU_ARCH_VFP_V2},
13204 {"vfp10-r0", FPU_ARCH_VFP_V1},
13205 {"vfpxd", FPU_ARCH_VFP_V1xD},
13206 {"arm1020t", FPU_ARCH_VFP_V1},
13207 {"arm1020e", FPU_ARCH_VFP_V2},
09d92015 13208 {"arm1136jfs", FPU_ARCH_VFP_V2},
8783612f 13209 {"arm1136jf-s", FPU_ARCH_VFP_V2},
33a392fb
PB
13210 {"maverick", FPU_ARCH_MAVERICK},
13211 {NULL, 0}
13212};
13213
13214struct arm_float_abi_option_table
13215{
13216 char *name;
13217 int value;
13218};
13219
13220static struct arm_float_abi_option_table arm_float_abis[] =
13221{
13222 {"hard", ARM_FLOAT_ABI_HARD},
13223 {"softfp", ARM_FLOAT_ABI_SOFTFP},
13224 {"soft", ARM_FLOAT_ABI_SOFT},
03b1477f
RE
13225 {NULL, 0}
13226};
13227
d507cf36
PB
13228struct arm_eabi_option_table
13229{
13230 char *name;
13231 unsigned int value;
13232};
13233
7cc69913 13234#ifdef OBJ_ELF
8cb51566 13235/* We only know how to output GNU and ver 4 (AAELF) formats. */
d507cf36
PB
13236static struct arm_eabi_option_table arm_eabis[] =
13237{
13238 {"gnu", EF_ARM_EABI_UNKNOWN},
8cb51566 13239 {"4", EF_ARM_EABI_VER4},
d507cf36
PB
13240 {NULL, 0}
13241};
7cc69913 13242#endif
d507cf36 13243
03b1477f
RE
13244struct arm_long_option_table
13245{
a737bd4d
NC
13246 char * option; /* Substring to match. */
13247 char * help; /* Help information. */
13248 int (* func) (char * subopt); /* Function to decode sub-option. */
13249 char * deprecated; /* If non-null, print this message. */
03b1477f
RE
13250};
13251
13252static int
a737bd4d 13253arm_parse_extension (char * str, int * opt_p)
03b1477f
RE
13254{
13255 while (str != NULL && *str != 0)
13256 {
a737bd4d
NC
13257 struct arm_arch_extension_table * opt;
13258 char * ext;
03b1477f
RE
13259 int optlen;
13260
13261 if (*str != '+')
b99bd4ef 13262 {
03b1477f
RE
13263 as_bad (_("invalid architectural extension"));
13264 return 0;
13265 }
b99bd4ef 13266
03b1477f
RE
13267 str++;
13268 ext = strchr (str, '+');
b99bd4ef 13269
03b1477f
RE
13270 if (ext != NULL)
13271 optlen = ext - str;
13272 else
13273 optlen = strlen (str);
b99bd4ef 13274
03b1477f
RE
13275 if (optlen == 0)
13276 {
13277 as_bad (_("missing architectural extension"));
13278 return 0;
13279 }
b99bd4ef 13280
03b1477f
RE
13281 for (opt = arm_extensions; opt->name != NULL; opt++)
13282 if (strncmp (opt->name, str, optlen) == 0)
13283 {
13284 *opt_p |= opt->value;
13285 break;
13286 }
bfae80f2 13287
03b1477f
RE
13288 if (opt->name == NULL)
13289 {
13290 as_bad (_("unknown architectural extnsion `%s'"), str);
13291 return 0;
13292 }
b99bd4ef 13293
03b1477f
RE
13294 str = ext;
13295 };
b99bd4ef 13296
03b1477f
RE
13297 return 1;
13298}
b99bd4ef 13299
03b1477f 13300static int
a737bd4d 13301arm_parse_cpu (char * str)
03b1477f 13302{
a737bd4d
NC
13303 struct arm_cpu_option_table * opt;
13304 char * ext = strchr (str, '+');
03b1477f 13305 int optlen;
b99bd4ef 13306
03b1477f
RE
13307 if (ext != NULL)
13308 optlen = ext - str;
13309 else
13310 optlen = strlen (str);
b99bd4ef 13311
03b1477f
RE
13312 if (optlen == 0)
13313 {
13314 as_bad (_("missing cpu name `%s'"), str);
13315 return 0;
13316 }
b99bd4ef 13317
03b1477f
RE
13318 for (opt = arm_cpus; opt->name != NULL; opt++)
13319 if (strncmp (opt->name, str, optlen) == 0)
13320 {
13321 mcpu_cpu_opt = opt->value;
13322 mcpu_fpu_opt = opt->default_fpu;
b99bd4ef 13323
03b1477f
RE
13324 if (ext != NULL)
13325 return arm_parse_extension (ext, &mcpu_cpu_opt);
b99bd4ef 13326
03b1477f
RE
13327 return 1;
13328 }
b99bd4ef 13329
03b1477f
RE
13330 as_bad (_("unknown cpu `%s'"), str);
13331 return 0;
13332}
b99bd4ef 13333
03b1477f 13334static int
a737bd4d 13335arm_parse_arch (char * str)
03b1477f
RE
13336{
13337 struct arm_arch_option_table *opt;
13338 char *ext = strchr (str, '+');
13339 int optlen;
b99bd4ef 13340
03b1477f
RE
13341 if (ext != NULL)
13342 optlen = ext - str;
13343 else
13344 optlen = strlen (str);
b99bd4ef 13345
03b1477f
RE
13346 if (optlen == 0)
13347 {
13348 as_bad (_("missing architecture name `%s'"), str);
13349 return 0;
13350 }
b99bd4ef 13351
b99bd4ef 13352
03b1477f 13353 for (opt = arm_archs; opt->name != NULL; opt++)
a737bd4d 13354 if (streq (opt->name, str))
03b1477f
RE
13355 {
13356 march_cpu_opt = opt->value;
13357 march_fpu_opt = opt->default_fpu;
b99bd4ef 13358
03b1477f
RE
13359 if (ext != NULL)
13360 return arm_parse_extension (ext, &march_cpu_opt);
b99bd4ef 13361
03b1477f
RE
13362 return 1;
13363 }
b99bd4ef 13364
03b1477f
RE
13365 as_bad (_("unknown architecture `%s'\n"), str);
13366 return 0;
13367}
13368
13369static int
a737bd4d 13370arm_parse_fpu (char * str)
03b1477f 13371{
a737bd4d 13372 struct arm_fpu_option_table * opt;
b99bd4ef 13373
03b1477f 13374 for (opt = arm_fpus; opt->name != NULL; opt++)
a737bd4d 13375 if (streq (opt->name, str))
03b1477f
RE
13376 {
13377 mfpu_opt = opt->value;
13378 return 1;
13379 }
b99bd4ef 13380
03b1477f
RE
13381 as_bad (_("unknown floating point format `%s'\n"), str);
13382 return 0;
13383}
b99bd4ef 13384
33a392fb 13385static int
a737bd4d 13386arm_parse_float_abi (char * str)
33a392fb 13387{
a737bd4d 13388 struct arm_float_abi_option_table * opt;
33a392fb
PB
13389
13390 for (opt = arm_float_abis; opt->name != NULL; opt++)
a737bd4d 13391 if (streq (opt->name, str))
33a392fb
PB
13392 {
13393 mfloat_abi_opt = opt->value;
13394 return 1;
13395 }
13396
13397 as_bad (_("unknown floating point abi `%s'\n"), str);
13398 return 0;
13399}
13400
7cc69913 13401#ifdef OBJ_ELF
d507cf36 13402static int
a737bd4d 13403arm_parse_eabi (char * str)
d507cf36
PB
13404{
13405 struct arm_eabi_option_table *opt;
13406
13407 for (opt = arm_eabis; opt->name != NULL; opt++)
a737bd4d 13408 if (streq (opt->name, str))
d507cf36
PB
13409 {
13410 meabi_flags = opt->value;
13411 return 1;
13412 }
13413 as_bad (_("unknown EABI `%s'\n"), str);
13414 return 0;
13415}
7cc69913 13416#endif
d507cf36 13417
03b1477f
RE
13418struct arm_long_option_table arm_long_opts[] =
13419{
13420 {"mcpu=", N_("<cpu name>\t assemble for CPU <cpu name>"),
13421 arm_parse_cpu, NULL},
13422 {"march=", N_("<arch name>\t assemble for architecture <arch name>"),
13423 arm_parse_arch, NULL},
13424 {"mfpu=", N_("<fpu name>\t assemble for FPU architecture <fpu name>"),
13425 arm_parse_fpu, NULL},
33a392fb
PB
13426 {"mfloat-abi=", N_("<abi>\t assemble for floating point ABI <abi>"),
13427 arm_parse_float_abi, NULL},
7cc69913 13428#ifdef OBJ_ELF
d507cf36
PB
13429 {"meabi=", N_("<ver>\t assemble for eabi version <ver>"),
13430 arm_parse_eabi, NULL},
7cc69913 13431#endif
03b1477f
RE
13432 {NULL, NULL, 0, NULL}
13433};
b99bd4ef 13434
03b1477f 13435int
a737bd4d 13436md_parse_option (int c, char * arg)
03b1477f
RE
13437{
13438 struct arm_option_table *opt;
13439 struct arm_long_option_table *lopt;
b99bd4ef 13440
03b1477f
RE
13441 switch (c)
13442 {
13443#ifdef OPTION_EB
13444 case OPTION_EB:
13445 target_big_endian = 1;
b99bd4ef 13446 break;
03b1477f 13447#endif
b99bd4ef 13448
03b1477f
RE
13449#ifdef OPTION_EL
13450 case OPTION_EL:
13451 target_big_endian = 0;
b99bd4ef
NC
13452 break;
13453#endif
13454
03b1477f 13455 case 'a':
cc8a6dd0 13456 /* Listing option. Just ignore these, we don't support additional
03b1477f
RE
13457 ones. */
13458 return 0;
13459
b99bd4ef 13460 default:
03b1477f
RE
13461 for (opt = arm_opts; opt->option != NULL; opt++)
13462 {
13463 if (c == opt->option[0]
13464 && ((arg == NULL && opt->option[1] == 0)
a737bd4d 13465 || streq (arg, opt->option + 1)))
03b1477f
RE
13466 {
13467#if WARN_DEPRECATED
13468 /* If the option is deprecated, tell the user. */
13469 if (opt->deprecated != NULL)
13470 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c,
13471 arg ? arg : "", _(opt->deprecated));
13472#endif
13473
13474 if (opt->var != NULL)
13475 *opt->var = opt->value;
13476
13477 return 1;
13478 }
13479 }
13480
13481 for (lopt = arm_long_opts; lopt->option != NULL; lopt++)
13482 {
cc8a6dd0 13483 /* These options are expected to have an argument. */
03b1477f
RE
13484 if (c == lopt->option[0]
13485 && arg != NULL
cc8a6dd0 13486 && strncmp (arg, lopt->option + 1,
03b1477f
RE
13487 strlen (lopt->option + 1)) == 0)
13488 {
13489#if WARN_DEPRECATED
13490 /* If the option is deprecated, tell the user. */
13491 if (lopt->deprecated != NULL)
13492 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c, arg,
13493 _(lopt->deprecated));
13494#endif
13495
13496 /* Call the sup-option parser. */
a737bd4d 13497 return lopt->func (arg + strlen (lopt->option) - 1);
03b1477f
RE
13498 }
13499 }
13500
b99bd4ef
NC
13501 return 0;
13502 }
13503
13504 return 1;
13505}
13506
13507void
a737bd4d 13508md_show_usage (FILE * fp)
b99bd4ef 13509{
03b1477f
RE
13510 struct arm_option_table *opt;
13511 struct arm_long_option_table *lopt;
13512
13513 fprintf (fp, _(" ARM-specific assembler options:\n"));
13514
13515 for (opt = arm_opts; opt->option != NULL; opt++)
13516 if (opt->help != NULL)
13517 fprintf (fp, " -%-23s%s\n", opt->option, _(opt->help));
13518
13519 for (lopt = arm_long_opts; lopt->option != NULL; lopt++)
13520 if (lopt->help != NULL)
13521 fprintf (fp, " -%s%s\n", lopt->option, _(lopt->help));
13522
13523#ifdef OPTION_EB
b99bd4ef 13524 fprintf (fp, _("\
03b1477f 13525 -EB assemble code for a big-endian cpu\n"));
b99bd4ef 13526#endif
03b1477f
RE
13527
13528#ifdef OPTION_EL
b99bd4ef 13529 fprintf (fp, _("\
03b1477f 13530 -EL assemble code for a little-endian cpu\n"));
b99bd4ef
NC
13531#endif
13532}
13533
b99bd4ef
NC
13534/* This fix_new is called by cons via TC_CONS_FIX_NEW. */
13535
13536void
a737bd4d
NC
13537cons_fix_new_arm (fragS * frag,
13538 int where,
13539 int size,
13540 expressionS * exp)
b99bd4ef
NC
13541{
13542 bfd_reloc_code_real_type type;
13543 int pcrel = 0;
13544
13545 /* Pick a reloc.
13546 FIXME: @@ Should look at CPU word size. */
13547 switch (size)
13548 {
13549 case 1:
13550 type = BFD_RELOC_8;
13551 break;
13552 case 2:
13553 type = BFD_RELOC_16;
13554 break;
13555 case 4:
13556 default:
13557 type = BFD_RELOC_32;
13558 break;
13559 case 8:
13560 type = BFD_RELOC_64;
13561 break;
13562 }
13563
13564 fix_new_exp (frag, where, (int) size, exp, pcrel, type);
13565}
13566
13567/* A good place to do this, although this was probably not intended
13568 for this kind of use. We need to dump the literal pool before
13569 references are made to a null symbol pointer. */
13570
13571void
a737bd4d 13572arm_cleanup (void)
b99bd4ef 13573{
3d0c9500 13574 literal_pool * pool;
b99bd4ef 13575
3d0c9500
NC
13576 for (pool = list_of_pools; pool; pool = pool->next)
13577 {
13578 /* Put it at the end of the relevent section. */
13579 subseg_set (pool->section, pool->sub_section);
69b97547
NC
13580#ifdef OBJ_ELF
13581 arm_elf_change_section ();
13582#endif
3d0c9500
NC
13583 s_ltorg (0);
13584 }
b99bd4ef
NC
13585}
13586
13587void
a737bd4d 13588arm_start_line_hook (void)
b99bd4ef
NC
13589{
13590 last_label_seen = NULL;
13591}
13592
13593void
a737bd4d 13594arm_frob_label (symbolS * sym)
b99bd4ef
NC
13595{
13596 last_label_seen = sym;
13597
13598 ARM_SET_THUMB (sym, thumb_mode);
13599
13600#if defined OBJ_COFF || defined OBJ_ELF
13601 ARM_SET_INTERWORK (sym, support_interwork);
13602#endif
13603
13604 /* Note - do not allow local symbols (.Lxxx) to be labeled
13605 as Thumb functions. This is because these labels, whilst
13606 they exist inside Thumb code, are not the entry points for
13607 possible ARM->Thumb calls. Also, these labels can be used
13608 as part of a computed goto or switch statement. eg gcc
13609 can generate code that looks like this:
13610
13611 ldr r2, [pc, .Laaa]
13612 lsl r3, r3, #2
13613 ldr r2, [r3, r2]
13614 mov pc, r2
cc8a6dd0 13615
b99bd4ef
NC
13616 .Lbbb: .word .Lxxx
13617 .Lccc: .word .Lyyy
13618 ..etc...
13619 .Laaa: .word Lbbb
13620
13621 The first instruction loads the address of the jump table.
13622 The second instruction converts a table index into a byte offset.
13623 The third instruction gets the jump address out of the table.
13624 The fourth instruction performs the jump.
cc8a6dd0 13625
b99bd4ef
NC
13626 If the address stored at .Laaa is that of a symbol which has the
13627 Thumb_Func bit set, then the linker will arrange for this address
13628 to have the bottom bit set, which in turn would mean that the
13629 address computation performed by the third instruction would end
13630 up with the bottom bit set. Since the ARM is capable of unaligned
13631 word loads, the instruction would then load the incorrect address
13632 out of the jump table, and chaos would ensue. */
13633 if (label_is_thumb_function_name
13634 && (S_GET_NAME (sym)[0] != '.' || S_GET_NAME (sym)[1] != 'L')
13635 && (bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
13636 {
13637 /* When the address of a Thumb function is taken the bottom
13638 bit of that address should be set. This will allow
13639 interworking between Arm and Thumb functions to work
13640 correctly. */
13641
13642 THUMB_SET_FUNC (sym, 1);
13643
b34976b6 13644 label_is_thumb_function_name = FALSE;
b99bd4ef
NC
13645 }
13646}
13647
13648/* Adjust the symbol table. This marks Thumb symbols as distinct from
13649 ARM ones. */
13650
13651void
a737bd4d 13652arm_adjust_symtab (void)
b99bd4ef
NC
13653{
13654#ifdef OBJ_COFF
13655 symbolS * sym;
13656
13657 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
13658 {
13659 if (ARM_IS_THUMB (sym))
13660 {
13661 if (THUMB_IS_FUNC (sym))
13662 {
13663 /* Mark the symbol as a Thumb function. */
13664 if ( S_GET_STORAGE_CLASS (sym) == C_STAT
13665 || S_GET_STORAGE_CLASS (sym) == C_LABEL) /* This can happen! */
13666 S_SET_STORAGE_CLASS (sym, C_THUMBSTATFUNC);
13667
13668 else if (S_GET_STORAGE_CLASS (sym) == C_EXT)
13669 S_SET_STORAGE_CLASS (sym, C_THUMBEXTFUNC);
13670 else
13671 as_bad (_("%s: unexpected function type: %d"),
13672 S_GET_NAME (sym), S_GET_STORAGE_CLASS (sym));
13673 }
cc8a6dd0 13674 else switch (S_GET_STORAGE_CLASS (sym))
b99bd4ef
NC
13675 {
13676 case C_EXT:
13677 S_SET_STORAGE_CLASS (sym, C_THUMBEXT);
13678 break;
13679 case C_STAT:
13680 S_SET_STORAGE_CLASS (sym, C_THUMBSTAT);
13681 break;
13682 case C_LABEL:
13683 S_SET_STORAGE_CLASS (sym, C_THUMBLABEL);
13684 break;
13685 default:
13686 /* Do nothing. */
13687 break;
13688 }
13689 }
13690
13691 if (ARM_IS_INTERWORK (sym))
13692 coffsymbol (symbol_get_bfdsym (sym))->native->u.syment.n_flags = 0xFF;
13693 }
13694#endif
13695#ifdef OBJ_ELF
13696 symbolS * sym;
13697 char bind;
13698
13699 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
13700 {
13701 if (ARM_IS_THUMB (sym))
13702 {
13703 elf_symbol_type * elf_sym;
13704
13705 elf_sym = elf_symbol (symbol_get_bfdsym (sym));
d110d6a2 13706 bind = ELF_ST_BIND (elf_sym->internal_elf_sym.st_info);
b99bd4ef
NC
13707
13708 /* If it's a .thumb_func, declare it as so,
13709 otherwise tag label as .code 16. */
13710 if (THUMB_IS_FUNC (sym))
13711 elf_sym->internal_elf_sym.st_info =
13712 ELF_ST_INFO (bind, STT_ARM_TFUNC);
13713 else
13714 elf_sym->internal_elf_sym.st_info =
13715 ELF_ST_INFO (bind, STT_ARM_16BIT);
13716 }
13717 }
13718#endif
13719}
13720
13721int
a737bd4d 13722arm_data_in_code (void)
b99bd4ef
NC
13723{
13724 if (thumb_mode && ! strncmp (input_line_pointer + 1, "data:", 5))
13725 {
13726 *input_line_pointer = '/';
13727 input_line_pointer += 5;
13728 *input_line_pointer = 0;
13729 return 1;
13730 }
13731
13732 return 0;
13733}
13734
13735char *
a737bd4d 13736arm_canonicalize_symbol_name (char * name)
b99bd4ef
NC
13737{
13738 int len;
13739
13740 if (thumb_mode && (len = strlen (name)) > 5
13741 && streq (name + len - 5, "/data"))
13742 *(name + len - 5) = 0;
13743
13744 return name;
13745}
13746
bfc866a6 13747#if defined OBJ_COFF || defined OBJ_ELF
a161fe53 13748void
a737bd4d 13749arm_validate_fix (fixS * fixP)
b99bd4ef
NC
13750{
13751 /* If the destination of the branch is a defined symbol which does not have
13752 the THUMB_FUNC attribute, then we must be calling a function which has
13753 the (interfacearm) attribute. We look for the Thumb entry point to that
13754 function and change the branch to refer to that function instead. */
13755 if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23
13756 && fixP->fx_addsy != NULL
13757 && S_IS_DEFINED (fixP->fx_addsy)
13758 && ! THUMB_IS_FUNC (fixP->fx_addsy))
13759 {
13760 fixP->fx_addsy = find_real_start (fixP->fx_addsy);
b99bd4ef 13761 }
b99bd4ef 13762}
bfc866a6 13763#endif
b99bd4ef 13764
114424c6 13765int
a737bd4d 13766arm_force_relocation (struct fix * fixp)
114424c6
AM
13767{
13768#if defined (OBJ_COFF) && defined (TE_PE)
13769 if (fixp->fx_r_type == BFD_RELOC_RVA)
13770 return 1;
13771#endif
13772#ifdef OBJ_ELF
ae6063d4 13773 if (fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH
114424c6
AM
13774 || fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BLX
13775 || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX
13776 || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23)
13777 return 1;
13778#endif
13779
13780 /* Resolve these relocations even if the symbol is extern or weak. */
13781 if (fixp->fx_r_type == BFD_RELOC_ARM_IMMEDIATE
47281638 13782 || fixp->fx_r_type == BFD_RELOC_ARM_OFFSET_IMM
114424c6
AM
13783 || fixp->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE)
13784 return 0;
13785
ae6063d4 13786 return generic_force_reloc (fixp);
114424c6
AM
13787}
13788
b99bd4ef
NC
13789#ifdef OBJ_COFF
13790/* This is a little hack to help the gas/arm/adrl.s test. It prevents
13791 local labels from being added to the output symbol table when they
13792 are used with the ADRL pseudo op. The ADRL relocation should always
13793 be resolved before the binbary is emitted, so it is safe to say that
13794 it is adjustable. */
13795
b34976b6 13796bfd_boolean
a737bd4d 13797arm_fix_adjustable (fixS * fixP)
b99bd4ef
NC
13798{
13799 if (fixP->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE)
13800 return 1;
13801 return 0;
13802}
13803#endif
114424c6 13804
b99bd4ef
NC
13805#ifdef OBJ_ELF
13806/* Relocations against Thumb function names must be left unadjusted,
13807 so that the linker can use this information to correctly set the
13808 bottom bit of their addresses. The MIPS version of this function
13809 also prevents relocations that are mips-16 specific, but I do not
13810 know why it does this.
13811
13812 FIXME:
13813 There is one other problem that ought to be addressed here, but
13814 which currently is not: Taking the address of a label (rather
13815 than a function) and then later jumping to that address. Such
13816 addresses also ought to have their bottom bit set (assuming that
13817 they reside in Thumb code), but at the moment they will not. */
13818
b34976b6 13819bfd_boolean
a737bd4d 13820arm_fix_adjustable (fixS * fixP)
b99bd4ef
NC
13821{
13822 if (fixP->fx_addsy == NULL)
13823 return 1;
13824
b99bd4ef
NC
13825 if (THUMB_IS_FUNC (fixP->fx_addsy)
13826 && fixP->fx_subsy == NULL)
13827 return 0;
13828
13829 /* We need the symbol name for the VTABLE entries. */
13830 if ( fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
13831 || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
13832 return 0;
13833
a161fe53
AM
13834 /* Don't allow symbols to be discarded on GOT related relocs. */
13835 if (fixP->fx_r_type == BFD_RELOC_ARM_PLT32
13836 || fixP->fx_r_type == BFD_RELOC_ARM_GOT32
eb043451
PB
13837 || fixP->fx_r_type == BFD_RELOC_ARM_GOTOFF
13838 || fixP->fx_r_type == BFD_RELOC_ARM_TARGET2)
a161fe53
AM
13839 return 0;
13840
b99bd4ef
NC
13841 return 1;
13842}
13843
13844const char *
a737bd4d 13845elf32_arm_target_format (void)
b99bd4ef 13846{
e5a52504
MM
13847#ifdef TE_SYMBIAN
13848 return (target_big_endian
13849 ? "elf32-bigarm-symbian"
13850 : "elf32-littlearm-symbian");
4e7fd91e
PB
13851#elif defined (TE_VXWORKS)
13852 return (target_big_endian
13853 ? "elf32-bigarm-vxworks"
13854 : "elf32-littlearm-vxworks");
a737bd4d 13855#else
b99bd4ef 13856 if (target_big_endian)
7f266840 13857 return "elf32-bigarm";
b99bd4ef 13858 else
7f266840 13859 return "elf32-littlearm";
e5a52504 13860#endif
b99bd4ef
NC
13861}
13862
13863void
a737bd4d
NC
13864armelf_frob_symbol (symbolS * symp,
13865 int * puntp)
b99bd4ef
NC
13866{
13867 elf_frob_symbol (symp, puntp);
13868}
13869
b99bd4ef 13870static void
a737bd4d 13871s_arm_elf_cons (int nbytes)
b99bd4ef
NC
13872{
13873 expressionS exp;
13874
13875#ifdef md_flush_pending_output
13876 md_flush_pending_output ();
13877#endif
13878
13879 if (is_it_end_of_statement ())
13880 {
13881 demand_empty_rest_of_line ();
13882 return;
13883 }
13884
13885#ifdef md_cons_align
13886 md_cons_align (nbytes);
13887#endif
13888
6057a28f 13889 mapping_state (MAP_DATA);
b99bd4ef
NC
13890 do
13891 {
13892 bfd_reloc_code_real_type reloc;
13893
13894 expression (& exp);
13895
13896 if (exp.X_op == O_symbol
13897 && * input_line_pointer == '('
13898 && (reloc = arm_parse_reloc ()) != BFD_RELOC_UNUSED)
13899 {
13900 reloc_howto_type *howto = bfd_reloc_type_lookup (stdoutput, reloc);
13901 int size = bfd_get_reloc_size (howto);
13902
13903 if (size > nbytes)
13904 as_bad ("%s relocations do not fit in %d bytes",
13905 howto->name, nbytes);
13906 else
13907 {
a737bd4d 13908 char *p = frag_more ((int) nbytes);
b99bd4ef
NC
13909 int offset = nbytes - size;
13910
13911 fix_new_exp (frag_now, p - frag_now->fr_literal + offset, size,
13912 &exp, 0, reloc);
13913 }
13914 }
13915 else
13916 emit_expr (&exp, (unsigned int) nbytes);
13917 }
13918 while (*input_line_pointer++ == ',');
13919
13920 /* Put terminator back into stream. */
13921 input_line_pointer --;
13922 demand_empty_rest_of_line ();
13923}
13924
eb043451
PB
13925
13926/* Parse a .rel31 directive. */
13927
13928static void
13929s_arm_rel31 (int ignored ATTRIBUTE_UNUSED)
13930{
13931 expressionS exp;
13932 char *p;
13933 valueT highbit;
a737bd4d 13934
eb043451
PB
13935 SKIP_WHITESPACE ();
13936
13937 highbit = 0;
13938 if (*input_line_pointer == '1')
13939 highbit = 0x80000000;
13940 else if (*input_line_pointer != '0')
13941 as_bad (_("expected 0 or 1"));
13942
13943 input_line_pointer++;
13944 SKIP_WHITESPACE ();
13945 if (*input_line_pointer != ',')
13946 as_bad (_("missing comma"));
13947 input_line_pointer++;
13948
13949#ifdef md_flush_pending_output
13950 md_flush_pending_output ();
13951#endif
13952
13953#ifdef md_cons_align
13954 md_cons_align (4);
13955#endif
13956
13957 mapping_state (MAP_DATA);
13958
13959 expression (&exp);
13960
13961 p = frag_more (4);
13962 md_number_to_chars (p, highbit, 4);
13963 fix_new_arm (frag_now, p - frag_now->fr_literal, 4, &exp, 1,
13964 BFD_RELOC_ARM_PREL31);
13965
13966 demand_empty_rest_of_line ();
13967}
7ed4c4c5
NC
13968\f
13969/* Code to deal with unwinding tables. */
13970
13971static void add_unwind_adjustsp (offsetT);
13972
13973/* Switch to section NAME and create section if necessary. It's
13974 rather ugly that we have to manipulate input_line_pointer but I
13975 don't see any other way to accomplish the same thing without
13976 changing obj-elf.c (which may be the Right Thing, in the end).
13977 Copied from tc-ia64.c. */
13978
13979static void
13980set_section (char *name)
13981{
13982 char *saved_input_line_pointer;
13983
13984 saved_input_line_pointer = input_line_pointer;
13985 input_line_pointer = name;
13986 obj_elf_section (0);
13987 input_line_pointer = saved_input_line_pointer;
13988}
13989
13990/* Cenerate and deferred unwind frame offset. */
13991
13992static void
13993flush_pending_unwind (void)
13994{
13995 offsetT offset;
13996
13997 offset = unwind.pending_offset;
13998 unwind.pending_offset = 0;
13999 if (offset != 0)
14000 add_unwind_adjustsp (offset);
14001}
14002
14003/* Add an opcode to this list for this function. Two-byte opcodes should
14004 be passed as op[0] << 8 | op[1]. The list of opcodes is built in reverse
14005 order. */
14006
14007static void
14008add_unwind_opcode (valueT op, int length)
14009{
14010 /* Add any deferred stack adjustment. */
14011 if (unwind.pending_offset)
14012 flush_pending_unwind ();
14013
14014 unwind.sp_restored = 0;
14015
14016 if (unwind.opcode_count + length > unwind.opcode_alloc)
14017 {
14018 unwind.opcode_alloc += ARM_OPCODE_CHUNK_SIZE;
14019 if (unwind.opcodes)
14020 unwind.opcodes = xrealloc (unwind.opcodes,
14021 unwind.opcode_alloc);
14022 else
14023 unwind.opcodes = xmalloc (unwind.opcode_alloc);
14024 }
14025 while (length > 0)
14026 {
14027 length--;
14028 unwind.opcodes[unwind.opcode_count] = op & 0xff;
14029 op >>= 8;
14030 unwind.opcode_count++;
14031 }
14032}
14033
14034/* Add unwind opcodes to adjust the stack pointer. */
14035
14036static void
14037add_unwind_adjustsp (offsetT offset)
14038{
14039 valueT op;
14040
14041 if (offset > 0x200)
14042 {
14043 /* We need at most 5 bytes to hold a 32-bit value in a uleb128. */
14044 char bytes[5];
14045 int n;
14046 valueT o;
14047
14048 /* Long form: 0xb2, uleb128. */
14049 /* This might not fit in a word so add the individual bytes,
14050 remembering the list is built in reverse order. */
14051 o = (valueT) ((offset - 0x204) >> 2);
14052 if (o == 0)
14053 add_unwind_opcode (0, 1);
14054
14055 /* Calculate the uleb128 encoding of the offset. */
14056 n = 0;
14057 while (o)
14058 {
14059 bytes[n] = o & 0x7f;
14060 o >>= 7;
14061 if (o)
14062 bytes[n] |= 0x80;
14063 n++;
14064 }
14065 /* Add the insn. */
14066 for (; n; n--)
14067 add_unwind_opcode (bytes[n - 1], 1);
14068 add_unwind_opcode (0xb2, 1);
14069 }
14070 else if (offset > 0x100)
14071 {
14072 /* Two short opcodes. */
14073 add_unwind_opcode (0x3f, 1);
14074 op = (offset - 0x104) >> 2;
14075 add_unwind_opcode (op, 1);
14076 }
14077 else if (offset > 0)
14078 {
14079 /* Short opcode. */
14080 op = (offset - 4) >> 2;
14081 add_unwind_opcode (op, 1);
14082 }
14083 else if (offset < 0)
14084 {
14085 offset = -offset;
14086 while (offset > 0x100)
14087 {
14088 add_unwind_opcode (0x7f, 1);
14089 offset -= 0x100;
14090 }
14091 op = ((offset - 4) >> 2) | 0x40;
14092 add_unwind_opcode (op, 1);
14093 }
14094}
14095
14096/* Finish the list of unwind opcodes for this function. */
14097static void
14098finish_unwind_opcodes (void)
14099{
14100 valueT op;
14101
14102 if (unwind.fp_used)
14103 {
14104 /* Adjust sp as neccessary. */
14105 unwind.pending_offset += unwind.fp_offset - unwind.frame_size;
14106 flush_pending_unwind ();
14107
14108 /* After restoring sp from the frame pointer. */
14109 op = 0x90 | unwind.fp_reg;
14110 add_unwind_opcode (op, 1);
14111 }
14112 else
14113 flush_pending_unwind ();
14114}
14115
14116
14117/* Start an exception table entry. If idx is nonzero this is an index table
14118 entry. */
14119
14120static void
14121start_unwind_section (const segT text_seg, int idx)
14122{
14123 const char * text_name;
14124 const char * prefix;
14125 const char * prefix_once;
14126 size_t prefix_len;
14127 size_t text_len;
14128 char * sec_name;
14129 size_t sec_name_len;
14130
14131 if (idx)
14132 {
14133 prefix = ELF_STRING_ARM_unwind;
14134 prefix_once = ELF_STRING_ARM_unwind_once;
14135 }
14136 else
14137 {
14138 prefix = ELF_STRING_ARM_unwind_info;
14139 prefix_once = ELF_STRING_ARM_unwind_info_once;
14140 }
14141
14142 text_name = segment_name (text_seg);
14143 if (streq (text_name, ".text"))
14144 text_name = "";
14145
14146 if (strncmp (text_name, ".gnu.linkonce.t.",
14147 strlen (".gnu.linkonce.t.")) == 0)
14148 {
14149 prefix = prefix_once;
14150 text_name += strlen (".gnu.linkonce.t.");
14151 }
14152
14153 prefix_len = strlen (prefix);
14154 text_len = strlen (text_name);
14155 sec_name_len = prefix_len + text_len;
14156 sec_name = alloca (sec_name_len + 1);
14157 memcpy (sec_name, prefix, prefix_len);
14158 memcpy (sec_name + prefix_len, text_name, text_len);
14159 sec_name[prefix_len + text_len] = '\0';
14160
14161 /* Handle COMDAT group. */
14162 if (prefix != prefix_once && (text_seg->flags & SEC_LINK_ONCE) != 0)
14163 {
14164 char *section;
14165 size_t len, group_name_len;
14166 const char *group_name = elf_group_name (text_seg);
14167
14168 if (group_name == NULL)
14169 {
14170 as_bad ("Group section `%s' has no group signature",
14171 segment_name (text_seg));
14172 ignore_rest_of_line ();
14173 return;
14174 }
14175 /* We have to construct a fake section directive. */
14176 group_name_len = strlen (group_name);
14177 if (idx)
14178 prefix_len = 13;
14179 else
14180 prefix_len = 16;
14181
14182 len = (sec_name_len
14183 + prefix_len /* ,"aG",%sectiontype, */
14184 + group_name_len /* ,group_name */
14185 + 7); /* ,comdat */
14186
14187 section = alloca (len + 1);
14188 memcpy (section, sec_name, sec_name_len);
14189 if (idx)
14190 memcpy (section + sec_name_len, ",\"aG\",%exidx,", 13);
14191 else
14192 memcpy (section + sec_name_len, ",\"aG\",%progbits,", 16);
14193 memcpy (section + sec_name_len + prefix_len, group_name, group_name_len);
14194 memcpy (section + len - 7, ",comdat", 7);
14195 section [len] = '\0';
14196 set_section (section);
14197 }
14198 else
14199 {
14200 set_section (sec_name);
14201 bfd_set_section_flags (stdoutput, now_seg,
14202 SEC_LOAD | SEC_ALLOC | SEC_READONLY);
14203 }
14204
14205 /* Set the setion link for index tables. */
14206 if (idx)
14207 elf_linked_to_section (now_seg) = text_seg;
14208}
14209
14210
14211/* Start an unwind table entry. HAVE_DATA is nonzero if we have additional
14212 personality routine data. Returns zero, or the index table value for
14213 and inline entry. */
14214
14215static valueT
14216create_unwind_entry (int have_data)
14217{
14218 int size;
14219 addressT where;
2132e3a3 14220 char *ptr;
7ed4c4c5
NC
14221 /* The current word of data. */
14222 valueT data;
14223 /* The number of bytes left in this word. */
14224 int n;
14225
14226 finish_unwind_opcodes ();
14227
14228 /* Remember the current text section. */
14229 unwind.saved_seg = now_seg;
14230 unwind.saved_subseg = now_subseg;
14231
14232 start_unwind_section (now_seg, 0);
14233
14234 if (unwind.personality_routine == NULL)
14235 {
14236 if (unwind.personality_index == -2)
14237 {
14238 if (have_data)
14239 as_bad (_("handerdata in cantunwind frame"));
14240 return 1; /* EXIDX_CANTUNWIND. */
14241 }
14242
14243 /* Use a default personality routine if none is specified. */
14244 if (unwind.personality_index == -1)
14245 {
14246 if (unwind.opcode_count > 3)
14247 unwind.personality_index = 1;
14248 else
14249 unwind.personality_index = 0;
14250 }
14251
14252 /* Space for the personality routine entry. */
14253 if (unwind.personality_index == 0)
14254 {
14255 if (unwind.opcode_count > 3)
14256 as_bad (_("too many unwind opcodes for personality routine 0"));
14257
14258 if (!have_data)
14259 {
14260 /* All the data is inline in the index table. */
14261 data = 0x80;
14262 n = 3;
14263 while (unwind.opcode_count > 0)
14264 {
14265 unwind.opcode_count--;
14266 data = (data << 8) | unwind.opcodes[unwind.opcode_count];
14267 n--;
14268 }
14269
14270 /* Pad with "finish" opcodes. */
14271 while (n--)
14272 data = (data << 8) | 0xb0;
14273
14274 return data;
14275 }
14276 size = 0;
14277 }
14278 else
14279 /* We get two opcodes "free" in the first word. */
14280 size = unwind.opcode_count - 2;
14281 }
14282 else
14283 /* An extra byte is required for the opcode count. */
14284 size = unwind.opcode_count + 1;
14285
14286 size = (size + 3) >> 2;
14287 if (size > 0xff)
14288 as_bad (_("too many unwind opcodes"));
14289
14290 frag_align (2, 0, 0);
14291 record_alignment (now_seg, 2);
14292 unwind.table_entry = expr_build_dot ();
14293
14294 /* Allocate the table entry. */
14295 ptr = frag_more ((size << 2) + 4);
14296 where = frag_now_fix () - ((size << 2) + 4);
14297
14298 switch (unwind.personality_index)
14299 {
14300 case -1:
14301 /* ??? Should this be a PLT generating relocation? */
14302 /* Custom personality routine. */
14303 fix_new (frag_now, where, 4, unwind.personality_routine, 0, 1,
14304 BFD_RELOC_ARM_PREL31);
620b81c1
JB
14305
14306 /* Indicate dependency to linker. */
14307 {
14308 char *name = "__aeabi_unwind_cpp_pr0";
14309 symbolS *pr = symbol_find_or_make (name);
14310 fix_new (frag_now, where, 4, pr, 0, 1, BFD_RELOC_NONE);
14311 }
14312
7ed4c4c5
NC
14313 where += 4;
14314 ptr += 4;
14315
14316 /* Set the first byte to the number of additional words. */
14317 data = size - 1;
14318 n = 3;
14319 break;
14320
14321 /* ABI defined personality routines. */
7ed4c4c5
NC
14322 case 0:
14323 /* Three opcodes bytes are packed into the first word. */
14324 data = 0x80;
14325 n = 3;
620b81c1 14326 goto emit_reloc;
7ed4c4c5
NC
14327
14328 case 1:
14329 case 2:
14330 /* The size and first two opcode bytes go in the first word. */
14331 data = ((0x80 + unwind.personality_index) << 8) | size;
14332 n = 2;
620b81c1
JB
14333 goto emit_reloc;
14334
14335 emit_reloc:
14336 {
14337 /* Indicate dependency to linker. */
14338 char *name[] = { "__aeabi_unwind_cpp_pr0",
14339 "__aeabi_unwind_cpp_pr1",
14340 "__aeabi_unwind_cpp_pr2" };
14341 symbolS *pr = symbol_find_or_make (name[unwind.personality_index]);
14342 fix_new (frag_now, where, 4, pr, 0, 1, BFD_RELOC_NONE);
14343 }
7ed4c4c5
NC
14344 break;
14345
14346 default:
14347 /* Should never happen. */
14348 abort ();
14349 }
14350
14351 /* Pack the opcodes into words (MSB first), reversing the list at the same
14352 time. */
14353 while (unwind.opcode_count > 0)
14354 {
14355 if (n == 0)
14356 {
14357 md_number_to_chars (ptr, data, 4);
14358 ptr += 4;
14359 n = 4;
14360 data = 0;
14361 }
14362 unwind.opcode_count--;
14363 n--;
14364 data = (data << 8) | unwind.opcodes[unwind.opcode_count];
14365 }
14366
14367 /* Finish off the last word. */
14368 if (n < 4)
14369 {
14370 /* Pad with "finish" opcodes. */
14371 while (n--)
14372 data = (data << 8) | 0xb0;
14373
14374 md_number_to_chars (ptr, data, 4);
14375 }
14376
14377 if (!have_data)
14378 {
14379 /* Add an empty descriptor if there is no user-specified data. */
14380 ptr = frag_more (4);
14381 md_number_to_chars (ptr, 0, 4);
14382 }
14383
14384 return 0;
14385}
14386
14387
14388/* Parse an unwind_fnstart directive. Simply records the current location. */
14389
14390static void
14391s_arm_unwind_fnstart (int ignored ATTRIBUTE_UNUSED)
14392{
14393 demand_empty_rest_of_line ();
14394 /* Mark the start of the function. */
14395 unwind.proc_start = expr_build_dot ();
14396
14397 /* Reset the rest of the unwind info. */
14398 unwind.opcode_count = 0;
14399 unwind.table_entry = NULL;
14400 unwind.personality_routine = NULL;
14401 unwind.personality_index = -1;
14402 unwind.frame_size = 0;
14403 unwind.fp_offset = 0;
14404 unwind.fp_reg = 13;
14405 unwind.fp_used = 0;
14406 unwind.sp_restored = 0;
14407}
14408
14409
14410/* Parse a handlerdata directive. Creates the exception handling table entry
14411 for the function. */
14412
14413static void
14414s_arm_unwind_handlerdata (int ignored ATTRIBUTE_UNUSED)
14415{
14416 demand_empty_rest_of_line ();
14417 if (unwind.table_entry)
14418 as_bad (_("dupicate .handlerdata directive"));
14419
14420 create_unwind_entry (1);
14421}
14422
14423/* Parse an unwind_fnend directive. Generates the index table entry. */
14424
14425static void
14426s_arm_unwind_fnend (int ignored ATTRIBUTE_UNUSED)
14427{
14428 long where;
2132e3a3 14429 char *ptr;
7ed4c4c5
NC
14430 valueT val;
14431
14432 demand_empty_rest_of_line ();
14433
14434 /* Add eh table entry. */
14435 if (unwind.table_entry == NULL)
14436 val = create_unwind_entry (0);
14437 else
14438 val = 0;
14439
14440 /* Add index table entry. This is two words. */
14441 start_unwind_section (unwind.saved_seg, 1);
14442 frag_align (2, 0, 0);
14443 record_alignment (now_seg, 2);
14444
14445 ptr = frag_more (8);
14446 where = frag_now_fix () - 8;
14447
14448 /* Self relative offset of the function start. */
14449 fix_new (frag_now, where, 4, unwind.proc_start, 0, 1,
be1b2b4b 14450 BFD_RELOC_ARM_PREL31);
7ed4c4c5
NC
14451
14452 if (val)
14453 /* Inline exception table entry. */
14454 md_number_to_chars (ptr + 4, val, 4);
14455 else
14456 /* Self relative offset of the table entry. */
14457 fix_new (frag_now, where + 4, 4, unwind.table_entry, 0, 1,
14458 BFD_RELOC_ARM_PREL31);
14459
14460 /* Restore the original section. */
14461 subseg_set (unwind.saved_seg, unwind.saved_subseg);
14462}
14463
14464
14465/* Parse an unwind_cantunwind directive. */
14466
14467static void
14468s_arm_unwind_cantunwind (int ignored ATTRIBUTE_UNUSED)
14469{
14470 demand_empty_rest_of_line ();
14471 if (unwind.personality_routine || unwind.personality_index != -1)
14472 as_bad (_("personality routine specified for cantunwind frame"));
14473
14474 unwind.personality_index = -2;
14475}
14476
14477
14478/* Parse a personalityindex directive. */
14479
14480static void
14481s_arm_unwind_personalityindex (int ignored ATTRIBUTE_UNUSED)
14482{
14483 expressionS exp;
14484
14485 if (unwind.personality_routine || unwind.personality_index != -1)
14486 as_bad (_("duplicate .personalityindex directive"));
14487
14488 SKIP_WHITESPACE ();
14489
14490 expression (&exp);
14491
14492 if (exp.X_op != O_constant
14493 || exp.X_add_number < 0 || exp.X_add_number > 15)
14494 {
14495 as_bad (_("bad personality routine number"));
14496 ignore_rest_of_line ();
14497 return;
14498 }
14499
14500 unwind.personality_index = exp.X_add_number;
14501
14502 demand_empty_rest_of_line ();
14503}
14504
14505
14506/* Parse a personality directive. */
14507
14508static void
14509s_arm_unwind_personality (int ignored ATTRIBUTE_UNUSED)
14510{
14511 char *name, *p, c;
14512
14513 if (unwind.personality_routine || unwind.personality_index != -1)
14514 as_bad (_("duplicate .personality directive"));
14515
14516 SKIP_WHITESPACE ();
14517 name = input_line_pointer;
14518 c = get_symbol_end ();
14519 p = input_line_pointer;
14520 unwind.personality_routine = symbol_find_or_make (name);
14521 *p = c;
14522 SKIP_WHITESPACE ();
14523 demand_empty_rest_of_line ();
14524}
14525
14526
14527/* Parse a directive saving core registers. */
14528
14529static void
14530s_arm_unwind_save_core (void)
14531{
14532 valueT op;
14533 long range;
14534 int n;
14535
14536 SKIP_WHITESPACE ();
14537 range = reg_list (&input_line_pointer);
14538 if (range == FAIL)
14539 {
14540 as_bad (_("expected register list"));
14541 ignore_rest_of_line ();
14542 return;
14543 }
14544
14545 demand_empty_rest_of_line ();
14546
14547 /* Turn .unwind_movsp ip followed by .unwind_save {..., ip, ...}
14548 into .unwind_save {..., sp...}. We aren't bothered about the value of
14549 ip because it is clobbered by calls. */
14550 if (unwind.sp_restored && unwind.fp_reg == 12
14551 && (range & 0x3000) == 0x1000)
14552 {
14553 unwind.opcode_count--;
14554 unwind.sp_restored = 0;
14555 range = (range | 0x2000) & ~0x1000;
14556 unwind.pending_offset = 0;
14557 }
14558
14559 /* See if we can use the short opcodes. These pop a block of upto 8
14560 registers starting with r4, plus maybe r14. */
14561 for (n = 0; n < 8; n++)
14562 {
14563 /* Break at the first non-saved register. */
14564 if ((range & (1 << (n + 4))) == 0)
14565 break;
14566 }
14567 /* See if there are any other bits set. */
14568 if (n == 0 || (range & (0xfff0 << n) & 0xbff0) != 0)
14569 {
14570 /* Use the long form. */
14571 op = 0x8000 | ((range >> 4) & 0xfff);
14572 add_unwind_opcode (op, 2);
14573 }
14574 else
14575 {
14576 /* Use the short form. */
14577 if (range & 0x4000)
14578 op = 0xa8; /* Pop r14. */
14579 else
14580 op = 0xa0; /* Do not pop r14. */
14581 op |= (n - 1);
14582 add_unwind_opcode (op, 1);
14583 }
14584
14585 /* Pop r0-r3. */
14586 if (range & 0xf)
14587 {
14588 op = 0xb100 | (range & 0xf);
14589 add_unwind_opcode (op, 2);
14590 }
14591
14592 /* Record the number of bytes pushed. */
14593 for (n = 0; n < 16; n++)
14594 {
14595 if (range & (1 << n))
14596 unwind.frame_size += 4;
14597 }
14598}
14599
14600
14601/* Parse a directive saving FPA registers. */
14602
14603static void
14604s_arm_unwind_save_fpa (int reg)
14605{
14606 expressionS exp;
14607 int num_regs;
14608 valueT op;
14609
14610 /* Get Number of registers to transfer. */
14611 if (skip_past_comma (&input_line_pointer) != FAIL)
14612 expression (&exp);
14613 else
14614 exp.X_op = O_illegal;
14615
14616 if (exp.X_op != O_constant)
14617 {
14618 as_bad (_("expected , <constant>"));
14619 ignore_rest_of_line ();
14620 return;
14621 }
14622
14623 num_regs = exp.X_add_number;
14624
14625 if (num_regs < 1 || num_regs > 4)
14626 {
14627 as_bad (_("number of registers must be in the range [1:4]"));
14628 ignore_rest_of_line ();
14629 return;
14630 }
14631
14632 demand_empty_rest_of_line ();
14633
14634 if (reg == 4)
14635 {
14636 /* Short form. */
14637 op = 0xb4 | (num_regs - 1);
14638 add_unwind_opcode (op, 1);
14639 }
14640 else
14641 {
14642 /* Long form. */
14643 op = 0xc800 | (reg << 4) | (num_regs - 1);
14644 add_unwind_opcode (op, 2);
14645 }
14646 unwind.frame_size += num_regs * 12;
14647}
14648
14649
14650/* Parse a directive saving VFP registers. */
14651
14652static void
14653s_arm_unwind_save_vfp (void)
14654{
14655 int count;
14656 int reg;
14657 valueT op;
14658
14659 count = vfp_parse_reg_list (&input_line_pointer, &reg, 1);
14660 if (count == FAIL)
14661 {
14662 as_bad (_("expected register list"));
14663 ignore_rest_of_line ();
14664 return;
14665 }
14666
14667 demand_empty_rest_of_line ();
14668
14669 if (reg == 8)
14670 {
14671 /* Short form. */
14672 op = 0xb8 | (count - 1);
14673 add_unwind_opcode (op, 1);
14674 }
14675 else
14676 {
14677 /* Long form. */
14678 op = 0xb300 | (reg << 4) | (count - 1);
14679 add_unwind_opcode (op, 2);
14680 }
14681 unwind.frame_size += count * 8 + 4;
14682}
14683
14684
14685/* Parse a directive saving iWMMXt registers. */
14686
14687static void
14688s_arm_unwind_save_wmmx (void)
14689{
14690 int reg;
14691 int hi_reg;
14692 int i;
14693 unsigned wcg_mask;
14694 unsigned wr_mask;
14695 valueT op;
14696
14697 if (*input_line_pointer == '{')
14698 input_line_pointer++;
14699
14700 wcg_mask = 0;
14701 wr_mask = 0;
14702 do
14703 {
14704 reg = arm_reg_parse (&input_line_pointer,
14705 all_reg_maps[REG_TYPE_IWMMXT].htab);
14706
14707 if (wr_register (reg))
14708 {
14709 i = reg & ~WR_PREFIX;
14710 if (wr_mask >> i)
14711 as_tsktsk (_("register list not in ascending order"));
14712 wr_mask |= 1 << i;
14713 }
14714 else if (wcg_register (reg))
14715 {
14716 i = (reg & ~WC_PREFIX) - 8;
14717 if (wcg_mask >> i)
14718 as_tsktsk (_("register list not in ascending order"));
14719 wcg_mask |= 1 << i;
14720 }
14721 else
14722 {
14723 as_bad (_("expected wr or wcgr"));
14724 goto error;
14725 }
14726
14727 SKIP_WHITESPACE ();
14728 if (*input_line_pointer == '-')
14729 {
14730 hi_reg = arm_reg_parse (&input_line_pointer,
14731 all_reg_maps[REG_TYPE_IWMMXT].htab);
14732 if (wr_register (reg) && wr_register (hi_reg))
14733 {
14734 for (; reg < hi_reg; reg++)
14735 wr_mask |= 1 << (reg & ~WR_PREFIX);
14736 }
14737 else if (wcg_register (reg) && wcg_register (hi_reg))
14738 {
14739 for (; reg < hi_reg; reg++)
14740 wcg_mask |= 1 << ((reg & ~WC_PREFIX) - 8);
14741 }
14742 else
14743 {
14744 as_bad (_("bad register range"));
14745 goto error;
14746 }
14747 }
14748 }
14749 while (skip_past_comma (&input_line_pointer) != FAIL);
14750
14751 SKIP_WHITESPACE ();
14752 if (*input_line_pointer == '}')
14753 input_line_pointer++;
14754
14755 demand_empty_rest_of_line ();
14756
14757 if (wr_mask && wcg_mask)
14758 {
14759 as_bad (_("inconsistent register types"));
14760 goto error;
14761 }
14762
14763 /* Generate any deferred opcodes becuuse we're going to be looking at
14764 the list. */
14765 flush_pending_unwind ();
14766
14767 if (wcg_mask)
14768 {
14769 for (i = 0; i < 16; i++)
14770 {
14771 if (wcg_mask & (1 << i))
14772 unwind.frame_size += 4;
14773 }
14774 op = 0xc700 | wcg_mask;
14775 add_unwind_opcode (op, 2);
14776 }
14777 else
14778 {
14779 for (i = 0; i < 16; i++)
14780 {
14781 if (wr_mask & (1 << i))
14782 unwind.frame_size += 8;
14783 }
14784 /* Attempt to combine with a previous opcode. We do this because gcc
14785 likes to output separate unwind directives for a single block of
14786 registers. */
14787 if (unwind.opcode_count > 0)
14788 {
14789 i = unwind.opcodes[unwind.opcode_count - 1];
14790 if ((i & 0xf8) == 0xc0)
14791 {
14792 i &= 7;
14793 /* Only merge if the blocks are contiguous. */
14794 if (i < 6)
14795 {
14796 if ((wr_mask & 0xfe00) == (1 << 9))
14797 {
14798 wr_mask |= ((1 << (i + 11)) - 1) & 0xfc00;
14799 unwind.opcode_count--;
14800 }
14801 }
14802 else if (i == 6 && unwind.opcode_count >= 2)
14803 {
14804 i = unwind.opcodes[unwind.opcode_count - 2];
14805 reg = i >> 4;
14806 i &= 0xf;
14807
14808 op = 0xffff << (reg - 1);
14809 if (reg > 0
14810 || ((wr_mask & op) == (1u << (reg - 1))))
14811 {
14812 op = (1 << (reg + i + 1)) - 1;
14813 op &= ~((1 << reg) - 1);
14814 wr_mask |= op;
14815 unwind.opcode_count -= 2;
14816 }
14817 }
14818 }
14819 }
14820
14821 hi_reg = 15;
14822 /* We want to generate opcodes in the order the registers have been
14823 saved, ie. descending order. */
14824 for (reg = 15; reg >= -1; reg--)
14825 {
14826 /* Save registers in blocks. */
14827 if (reg < 0
14828 || !(wr_mask & (1 << reg)))
14829 {
14830 /* We found an unsaved reg. Generate opcodes to save the
14831 preceeding block. */
14832 if (reg != hi_reg)
14833 {
14834 if (reg == 9)
14835 {
14836 /* Short form. */
14837 op = 0xc0 | (hi_reg - 10);
14838 add_unwind_opcode (op, 1);
14839 }
14840 else
14841 {
14842 /* Long form. */
14843 op = 0xc600 | ((reg + 1) << 4) | ((hi_reg - reg) - 1);
14844 add_unwind_opcode (op, 2);
14845 }
14846 }
14847 hi_reg = reg - 1;
14848 }
14849 }
14850 }
14851 return;
14852error:
14853 ignore_rest_of_line ();
14854}
14855
14856
14857/* Parse an unwind_save directive. */
14858
14859static void
14860s_arm_unwind_save (int ignored ATTRIBUTE_UNUSED)
14861{
14862 char *saved_ptr;
14863 int reg;
14864
14865 /* Figure out what sort of save we have. */
14866 SKIP_WHITESPACE ();
14867 saved_ptr = input_line_pointer;
14868
14869 reg = arm_reg_parse (&input_line_pointer, all_reg_maps[REG_TYPE_FN].htab);
14870 if (reg != FAIL)
14871 {
14872 s_arm_unwind_save_fpa (reg);
14873 return;
14874 }
14875
14876 if (*input_line_pointer == '{')
14877 input_line_pointer++;
14878
14879 SKIP_WHITESPACE ();
14880
14881 reg = arm_reg_parse (&input_line_pointer, all_reg_maps[REG_TYPE_RN].htab);
14882 if (reg != FAIL)
14883 {
14884 input_line_pointer = saved_ptr;
14885 s_arm_unwind_save_core ();
14886 return;
14887 }
14888
14889 reg = arm_reg_parse (&input_line_pointer, all_reg_maps[REG_TYPE_DN].htab);
14890 if (reg != FAIL)
14891 {
14892 input_line_pointer = saved_ptr;
14893 s_arm_unwind_save_vfp ();
14894 return;
14895 }
14896
14897 reg = arm_reg_parse (&input_line_pointer,
14898 all_reg_maps[REG_TYPE_IWMMXT].htab);
14899 if (reg != FAIL)
14900 {
14901 input_line_pointer = saved_ptr;
14902 s_arm_unwind_save_wmmx ();
14903 return;
14904 }
14905
14906 /* TODO: Maverick registers. */
14907 as_bad (_("unrecognised register"));
14908}
14909
14910
14911/* Parse an unwind_movsp directive. */
14912
14913static void
14914s_arm_unwind_movsp (int ignored ATTRIBUTE_UNUSED)
14915{
14916 int reg;
14917 valueT op;
14918
14919 SKIP_WHITESPACE ();
14920 reg = reg_required_here (&input_line_pointer, -1);
14921 if (reg == FAIL)
14922 {
14923 as_bad (_("ARM register expected"));
14924 ignore_rest_of_line ();
14925 return;
14926 }
14927
14928 if (reg == 13 || reg == 15)
14929 {
14930 as_bad (_("r%d not permitted in .unwind_movsp directive"), reg);
14931 ignore_rest_of_line ();
14932 return;
14933 }
14934
14935 if (unwind.fp_reg != 13)
14936 as_bad (_("unexpected .unwind_movsp directive"));
14937
14938 /* Generate opcode to restore the value. */
14939 op = 0x90 | reg;
14940 add_unwind_opcode (op, 1);
14941
14942 /* Record the information for later. */
14943 unwind.fp_reg = reg;
14944 unwind.fp_offset = unwind.frame_size;
14945 unwind.sp_restored = 1;
14946 demand_empty_rest_of_line ();
14947}
14948
14949
14950/* Parse #<number>. */
14951
14952static int
14953require_hashconst (int * val)
14954{
14955 expressionS exp;
14956
14957 SKIP_WHITESPACE ();
14958 if (*input_line_pointer == '#')
14959 {
14960 input_line_pointer++;
14961 expression (&exp);
14962 }
14963 else
14964 exp.X_op = O_illegal;
14965
14966 if (exp.X_op != O_constant)
14967 {
14968 as_bad (_("expected #constant"));
14969 ignore_rest_of_line ();
14970 return FAIL;
14971 }
14972 *val = exp.X_add_number;
14973 return SUCCESS;
14974}
14975
14976/* Parse an unwind_pad directive. */
14977
14978static void
14979s_arm_unwind_pad (int ignored ATTRIBUTE_UNUSED)
14980{
14981 int offset;
14982
14983 if (require_hashconst (&offset) == FAIL)
14984 return;
14985
14986 if (offset & 3)
14987 {
14988 as_bad (_("stack increment must be multiple of 4"));
14989 ignore_rest_of_line ();
14990 return;
14991 }
14992
14993 /* Don't generate any opcodes, just record the details for later. */
14994 unwind.frame_size += offset;
14995 unwind.pending_offset += offset;
14996
14997 demand_empty_rest_of_line ();
14998}
14999
15000/* Parse an unwind_setfp directive. */
15001
15002static void
15003s_arm_unwind_setfp (int ignored ATTRIBUTE_UNUSED)
15004{
15005 int sp_reg;
15006 int fp_reg;
15007 int offset;
15008
15009 fp_reg = reg_required_here (&input_line_pointer, -1);
15010 if (skip_past_comma (&input_line_pointer) == FAIL)
15011 sp_reg = FAIL;
15012 else
15013 sp_reg = reg_required_here (&input_line_pointer, -1);
15014
15015 if (fp_reg == FAIL || sp_reg == FAIL)
15016 {
15017 as_bad (_("expected <reg>, <reg>"));
15018 ignore_rest_of_line ();
15019 return;
15020 }
15021
15022 /* Optonal constant. */
15023 if (skip_past_comma (&input_line_pointer) != FAIL)
15024 {
15025 if (require_hashconst (&offset) == FAIL)
15026 return;
15027 }
15028 else
15029 offset = 0;
15030
15031 demand_empty_rest_of_line ();
15032
15033 if (sp_reg != 13 && sp_reg != unwind.fp_reg)
15034 {
15035 as_bad (_("register must be either sp or set by a previous"
15036 "unwind_movsp directive"));
15037 return;
15038 }
15039
15040 /* Don't generate any opcodes, just record the information for later. */
15041 unwind.fp_reg = fp_reg;
15042 unwind.fp_used = 1;
15043 if (sp_reg == 13)
15044 unwind.fp_offset = unwind.frame_size - offset;
15045 else
15046 unwind.fp_offset -= offset;
15047}
15048
15049/* Parse an unwind_raw directive. */
15050
15051static void
15052s_arm_unwind_raw (int ignored ATTRIBUTE_UNUSED)
15053{
15054 expressionS exp;
15055 /* This is an arbitary limit. */
15056 unsigned char op[16];
15057 int count;
15058
15059 SKIP_WHITESPACE ();
15060 expression (&exp);
15061 if (exp.X_op == O_constant
15062 && skip_past_comma (&input_line_pointer) != FAIL)
15063 {
15064 unwind.frame_size += exp.X_add_number;
15065 expression (&exp);
15066 }
15067 else
15068 exp.X_op = O_illegal;
15069
15070 if (exp.X_op != O_constant)
15071 {
15072 as_bad (_("expected <offset>, <opcode>"));
15073 ignore_rest_of_line ();
15074 return;
15075 }
15076
15077 count = 0;
15078
15079 /* Parse the opcode. */
15080 for (;;)
15081 {
15082 if (count >= 16)
15083 {
15084 as_bad (_("unwind opcode too long"));
15085 ignore_rest_of_line ();
15086 }
15087 if (exp.X_op != O_constant || exp.X_add_number & ~0xff)
15088 {
15089 as_bad (_("invalid unwind opcode"));
15090 ignore_rest_of_line ();
15091 return;
15092 }
15093 op[count++] = exp.X_add_number;
15094
15095 /* Parse the next byte. */
15096 if (skip_past_comma (&input_line_pointer) == FAIL)
15097 break;
15098
15099 expression (&exp);
15100 }
15101
15102 /* Add the opcode bytes in reverse order. */
15103 while (count--)
15104 add_unwind_opcode (op[count], 1);
15105
15106 demand_empty_rest_of_line ();
15107}
eb043451 15108
b99bd4ef
NC
15109#endif /* OBJ_ELF */
15110
15111/* This is called from HANDLE_ALIGN in write.c. Fill in the contents
15112 of an rs_align_code fragment. */
15113
15114void
a737bd4d 15115arm_handle_align (fragS * fragP)
b99bd4ef
NC
15116{
15117 static char const arm_noop[4] = { 0x00, 0x00, 0xa0, 0xe1 };
15118 static char const thumb_noop[2] = { 0xc0, 0x46 };
15119 static char const arm_bigend_noop[4] = { 0xe1, 0xa0, 0x00, 0x00 };
15120 static char const thumb_bigend_noop[2] = { 0x46, 0xc0 };
15121
15122 int bytes, fix, noop_size;
15123 char * p;
15124 const char * noop;
cc8a6dd0 15125
b99bd4ef
NC
15126 if (fragP->fr_type != rs_align_code)
15127 return;
15128
15129 bytes = fragP->fr_next->fr_address - fragP->fr_address - fragP->fr_fix;
15130 p = fragP->fr_literal + fragP->fr_fix;
15131 fix = 0;
cc8a6dd0 15132
b99bd4ef
NC
15133 if (bytes > MAX_MEM_FOR_RS_ALIGN_CODE)
15134 bytes &= MAX_MEM_FOR_RS_ALIGN_CODE;
cc8a6dd0 15135
b99bd4ef
NC
15136 if (fragP->tc_frag_data)
15137 {
15138 if (target_big_endian)
15139 noop = thumb_bigend_noop;
15140 else
15141 noop = thumb_noop;
15142 noop_size = sizeof (thumb_noop);
15143 }
15144 else
15145 {
15146 if (target_big_endian)
15147 noop = arm_bigend_noop;
15148 else
15149 noop = arm_noop;
15150 noop_size = sizeof (arm_noop);
15151 }
cc8a6dd0 15152
b99bd4ef
NC
15153 if (bytes & (noop_size - 1))
15154 {
15155 fix = bytes & (noop_size - 1);
15156 memset (p, 0, fix);
15157 p += fix;
15158 bytes -= fix;
15159 }
15160
15161 while (bytes >= noop_size)
15162 {
15163 memcpy (p, noop, noop_size);
15164 p += noop_size;
15165 bytes -= noop_size;
15166 fix += noop_size;
15167 }
cc8a6dd0 15168
b99bd4ef
NC
15169 fragP->fr_fix += fix;
15170 fragP->fr_var = noop_size;
15171}
15172
15173/* Called from md_do_align. Used to create an alignment
15174 frag in a code section. */
15175
15176void
a737bd4d 15177arm_frag_align_code (int n, int max)
b99bd4ef
NC
15178{
15179 char * p;
15180
2d2255b5 15181 /* We assume that there will never be a requirement
b99bd4ef
NC
15182 to support alignments greater than 32 bytes. */
15183 if (max > MAX_MEM_FOR_RS_ALIGN_CODE)
15184 as_fatal (_("alignments greater than 32 bytes not supported in .text sections."));
cc8a6dd0 15185
b99bd4ef
NC
15186 p = frag_var (rs_align_code,
15187 MAX_MEM_FOR_RS_ALIGN_CODE,
15188 1,
15189 (relax_substateT) max,
15190 (symbolS *) NULL,
15191 (offsetT) n,
15192 (char *) NULL);
15193 *p = 0;
b99bd4ef
NC
15194}
15195
15196/* Perform target specific initialisation of a frag. */
15197
15198void
a737bd4d 15199arm_init_frag (fragS * fragP)
b99bd4ef
NC
15200{
15201 /* Record whether this frag is in an ARM or a THUMB area. */
15202 fragP->tc_frag_data = thumb_mode;
15203}
a737bd4d 15204
a394c00f
NC
15205#ifdef OBJ_ELF
15206
15207/* Convert REGNAME to a DWARF-2 register number. */
15208
15209int
15210tc_arm_regname_to_dw2regnum (const char *regname)
15211{
15212 unsigned int i;
15213
15214 for (i = 0; rn_table[i].name; i++)
15215 if (streq (regname, rn_table[i].name))
15216 return rn_table[i].number;
15217
15218 return -1;
15219}
15220
15221/* Initialize the DWARF-2 unwind information for this procedure. */
15222
15223void
15224tc_arm_frame_initial_instructions (void)
15225{
15226 cfi_add_CFA_def_cfa (REG_SP, 0);
15227}
15228#endif
15229
a737bd4d
NC
15230/* This table describes all the machine specific pseudo-ops the assembler
15231 has to support. The fields are:
15232 pseudo-op name without dot
15233 function to call to execute this pseudo-op
15234 Integer arg to pass to the function. */
15235
15236const pseudo_typeS md_pseudo_table[] =
15237{
15238 /* Never called because '.req' does not start a line. */
15239 { "req", s_req, 0 },
15240 { "unreq", s_unreq, 0 },
15241 { "bss", s_bss, 0 },
15242 { "align", s_align, 0 },
15243 { "arm", s_arm, 0 },
15244 { "thumb", s_thumb, 0 },
15245 { "code", s_code, 0 },
15246 { "force_thumb", s_force_thumb, 0 },
15247 { "thumb_func", s_thumb_func, 0 },
15248 { "thumb_set", s_thumb_set, 0 },
15249 { "even", s_even, 0 },
15250 { "ltorg", s_ltorg, 0 },
15251 { "pool", s_ltorg, 0 },
15252#ifdef OBJ_ELF
15253 { "word", s_arm_elf_cons, 4 },
15254 { "long", s_arm_elf_cons, 4 },
15255 { "rel31", s_arm_rel31, 0 },
7ed4c4c5
NC
15256 { "fnstart", s_arm_unwind_fnstart, 0 },
15257 { "fnend", s_arm_unwind_fnend, 0 },
15258 { "cantunwind", s_arm_unwind_cantunwind, 0 },
15259 { "personality", s_arm_unwind_personality, 0 },
15260 { "personalityindex", s_arm_unwind_personalityindex, 0 },
15261 { "handlerdata", s_arm_unwind_handlerdata, 0 },
15262 { "save", s_arm_unwind_save, 0 },
15263 { "movsp", s_arm_unwind_movsp, 0 },
15264 { "pad", s_arm_unwind_pad, 0 },
15265 { "setfp", s_arm_unwind_setfp, 0 },
15266 { "unwind_raw", s_arm_unwind_raw, 0 },
a737bd4d
NC
15267#else
15268 { "word", cons, 4},
15269#endif
15270 { "extend", float_cons, 'x' },
15271 { "ldouble", float_cons, 'x' },
15272 { "packed", float_cons, 'p' },
15273 { 0, 0, 0 }
15274};
This page took 1.073817 seconds and 4 git commands to generate.