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