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