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