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