]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gas/config/tc-arm.c
* config.bfd (arm*-*-symbianelf*): Use OS-specific target vectors.
[thirdparty/binutils-gdb.git] / gas / config / tc-arm.c
CommitLineData
b99bd4ef 1/* tc-arm.c -- Assemble for the ARM
69b97547 2 Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
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)
34920d91
NC
7 Cirrus coprocessor fixes by Petko Manolov (petkan@nucleusys.com)
8 Cirrus coprocessor fixes by Vladimir Ivanov (vladitx@nucleusys.com)
b99bd4ef
NC
9
10 This file is part of GAS, the GNU Assembler.
11
12 GAS is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2, or (at your option)
15 any later version.
16
17 GAS is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
21
22 You should have received a copy of the GNU General Public License
23 along with GAS; see the file COPYING. If not, write to the Free
24 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
25 02111-1307, USA. */
26
b99bd4ef
NC
27#include <string.h>
28#define NO_RELOC 0
29#include "as.h"
3882b010 30#include "safe-ctype.h"
b99bd4ef
NC
31
32/* Need TARGET_CPU. */
33#include "config.h"
34#include "subsegs.h"
35#include "obstack.h"
36#include "symbols.h"
37#include "listing.h"
38
f263249b
RE
39#include "opcode/arm.h"
40
b99bd4ef
NC
41#ifdef OBJ_ELF
42#include "elf/arm.h"
43#include "dwarf2dbg.h"
44#endif
45
03b1477f
RE
46/* XXX Set this to 1 after the next binutils release */
47#define WARN_DEPRECATED 0
48
33a392fb
PB
49enum arm_float_abi
50{
51 ARM_FLOAT_ABI_HARD,
52 ARM_FLOAT_ABI_SOFTFP,
53 ARM_FLOAT_ABI_SOFT
54};
55
b89dddec
RE
56/* Types of processor to assemble for. */
57#define ARM_1 ARM_ARCH_V1
58#define ARM_2 ARM_ARCH_V2
59#define ARM_3 ARM_ARCH_V2S
60#define ARM_250 ARM_ARCH_V2S
61#define ARM_6 ARM_ARCH_V3
62#define ARM_7 ARM_ARCH_V3
63#define ARM_8 ARM_ARCH_V4
64#define ARM_9 ARM_ARCH_V4T
65#define ARM_STRONG ARM_ARCH_V4
66#define ARM_CPU_MASK 0x0000000f /* XXX? */
b99bd4ef
NC
67
68#ifndef CPU_DEFAULT
69#if defined __XSCALE__
b89dddec 70#define CPU_DEFAULT (ARM_ARCH_XSCALE)
b99bd4ef
NC
71#else
72#if defined __thumb__
b89dddec 73#define CPU_DEFAULT (ARM_ARCH_V5T)
b99bd4ef 74#else
03b1477f 75#define CPU_DEFAULT ARM_ANY
b99bd4ef
NC
76#endif
77#endif
78#endif
79
39c2da32
RE
80#ifdef TE_LINUX
81#define FPU_DEFAULT FPU_ARCH_FPA
82#endif
83
84#ifdef TE_NetBSD
85#ifdef OBJ_ELF
86#define FPU_DEFAULT FPU_ARCH_VFP /* Soft-float, but VFP order. */
87#else
88/* Legacy a.out format. */
89#define FPU_DEFAULT FPU_ARCH_FPA /* Soft-float, but FPA order. */
90#endif
91#endif
92
bfae80f2 93/* For backwards compatibility we default to the FPA. */
b99bd4ef 94#ifndef FPU_DEFAULT
b89dddec 95#define FPU_DEFAULT FPU_ARCH_FPA
b99bd4ef
NC
96#endif
97
98#define streq(a, b) (strcmp (a, b) == 0)
99#define skip_whitespace(str) while (*(str) == ' ') ++(str)
100
03b1477f 101static unsigned long cpu_variant;
b99bd4ef
NC
102static int target_oabi = 0;
103
b99bd4ef 104/* Flags stored in private area of BFD structure. */
b34976b6
AM
105static int uses_apcs_26 = FALSE;
106static int atpcs = FALSE;
107static int support_interwork = FALSE;
108static int uses_apcs_float = FALSE;
109static int pic_code = FALSE;
03b1477f
RE
110
111/* Variables that we set while parsing command-line options. Once all
112 options have been read we re-process these values to set the real
113 assembly flags. */
114static int legacy_cpu = -1;
115static int legacy_fpu = -1;
116
117static int mcpu_cpu_opt = -1;
118static int mcpu_fpu_opt = -1;
119static int march_cpu_opt = -1;
120static int march_fpu_opt = -1;
121static int mfpu_opt = -1;
33a392fb 122static int mfloat_abi_opt = -1;
7cc69913 123#ifdef OBJ_ELF
d507cf36 124static int meabi_flags = EF_ARM_EABI_UNKNOWN;
7cc69913 125#endif
b99bd4ef
NC
126
127/* This array holds the chars that always start a comment. If the
128 pre-processor is disabled, these aren't very useful. */
f57c81f6 129const char comment_chars[] = "@";
b99bd4ef
NC
130
131/* This array holds the chars that only start a comment at the beginning of
132 a line. If the line seems to have the form '# 123 filename'
133 .line and .file directives will appear in the pre-processed output. */
134/* Note that input_file.c hand checks for '#' at the beginning of the
135 first line of the input file. This is because the compiler outputs
136 #NO_APP at the beginning of its output. */
137/* Also note that comments like this one will always work. */
05d2d07e 138const char line_comment_chars[] = "#";
b99bd4ef 139
da89cce1 140const char line_separator_chars[] = ";";
b99bd4ef
NC
141
142/* Chars that can be used to separate mant
143 from exp in floating point numbers. */
05d2d07e 144const char EXP_CHARS[] = "eE";
b99bd4ef
NC
145
146/* Chars that mean this number is a floating point constant. */
147/* As in 0f12.456 */
148/* or 0d1.2345e12 */
149
05d2d07e 150const char FLT_CHARS[] = "rRsSfFdDxXeEpP";
b99bd4ef
NC
151
152/* Prefix characters that indicate the start of an immediate
153 value. */
154#define is_immediate_prefix(C) ((C) == '#' || (C) == '$')
155
156#ifdef OBJ_ELF
157/* Pre-defined "_GLOBAL_OFFSET_TABLE_" */
158symbolS * GOT_symbol;
159#endif
160
161/* Size of relocation record. */
05d2d07e 162const int md_reloc_size = 8;
b99bd4ef
NC
163
164/* 0: assemble for ARM,
165 1: assemble for Thumb,
166 2: assemble for Thumb even though target CPU does not support thumb
167 instructions. */
168static int thumb_mode = 0;
169
170typedef struct arm_fix
171{
172 int thumb_mode;
173} arm_fix_data;
174
175struct arm_it
176{
05d2d07e 177 const char * error;
b99bd4ef 178 unsigned long instruction;
b99bd4ef
NC
179 int size;
180 struct
181 {
182 bfd_reloc_code_real_type type;
183 expressionS exp;
184 int pc_rel;
185 } reloc;
186};
187
188struct arm_it inst;
189
190enum asm_shift_index
191{
192 SHIFT_LSL = 0,
193 SHIFT_LSR,
194 SHIFT_ASR,
195 SHIFT_ROR,
196 SHIFT_RRX
197};
198
199struct asm_shift_properties
200{
201 enum asm_shift_index index;
202 unsigned long bit_field;
203 unsigned int allows_0 : 1;
204 unsigned int allows_32 : 1;
205};
206
207static const struct asm_shift_properties shift_properties [] =
208{
209 { SHIFT_LSL, 0, 1, 0},
210 { SHIFT_LSR, 0x20, 0, 1},
211 { SHIFT_ASR, 0x40, 0, 1},
212 { SHIFT_ROR, 0x60, 0, 0},
213 { SHIFT_RRX, 0x60, 0, 0}
214};
215
216struct asm_shift_name
217{
218 const char * name;
219 const struct asm_shift_properties * properties;
220};
221
222static const struct asm_shift_name shift_names [] =
223{
224 { "asl", shift_properties + SHIFT_LSL },
225 { "lsl", shift_properties + SHIFT_LSL },
226 { "lsr", shift_properties + SHIFT_LSR },
227 { "asr", shift_properties + SHIFT_ASR },
228 { "ror", shift_properties + SHIFT_ROR },
229 { "rrx", shift_properties + SHIFT_RRX },
230 { "ASL", shift_properties + SHIFT_LSL },
231 { "LSL", shift_properties + SHIFT_LSL },
232 { "LSR", shift_properties + SHIFT_LSR },
233 { "ASR", shift_properties + SHIFT_ASR },
234 { "ROR", shift_properties + SHIFT_ROR },
235 { "RRX", shift_properties + SHIFT_RRX }
236};
237
09d92015 238/* Any kind of shift is accepted. */
b99bd4ef 239#define NO_SHIFT_RESTRICT 1
09d92015
MM
240/* The shift operand must be an immediate value, not a register. */
241#define SHIFT_IMMEDIATE 0
242/* The shift must be LSL or ASR and the operand must be an immediate. */
243#define SHIFT_LSL_OR_ASR_IMMEDIATE 2
244/* The shift must be ASR and the operand must be an immediate. */
245#define SHIFT_ASR_IMMEDIATE 3
246/* The shift must be LSL and the operand must be an immediate. */
247#define SHIFT_LSL_IMMEDIATE 4
b99bd4ef
NC
248
249#define NUM_FLOAT_VALS 8
250
05d2d07e 251const char * fp_const[] =
b99bd4ef
NC
252{
253 "0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0", 0
254};
255
256/* Number of littlenums required to hold an extended precision number. */
257#define MAX_LITTLENUMS 6
258
259LITTLENUM_TYPE fp_values[NUM_FLOAT_VALS][MAX_LITTLENUMS];
260
261#define FAIL (-1)
262#define SUCCESS (0)
263
bfae80f2
RE
264/* Whether a Co-processor load/store operation accepts write-back forms. */
265#define CP_WB_OK 1
266#define CP_NO_WB 0
267
b99bd4ef
NC
268#define SUFF_S 1
269#define SUFF_D 2
270#define SUFF_E 3
271#define SUFF_P 4
272
273#define CP_T_X 0x00008000
274#define CP_T_Y 0x00400000
275#define CP_T_Pre 0x01000000
276#define CP_T_UD 0x00800000
277#define CP_T_WB 0x00200000
278
279#define CONDS_BIT 0x00100000
280#define LOAD_BIT 0x00100000
b99bd4ef
NC
281
282#define DOUBLE_LOAD_FLAG 0x00000001
283
284struct asm_cond
285{
05d2d07e 286 const char * template;
b99bd4ef
NC
287 unsigned long value;
288};
289
b99bd4ef 290#define COND_ALWAYS 0xe0000000
90e4755a 291#define COND_MASK 0xf0000000
b99bd4ef 292
05d2d07e 293static const struct asm_cond conds[] =
b99bd4ef
NC
294{
295 {"eq", 0x00000000},
296 {"ne", 0x10000000},
297 {"cs", 0x20000000}, {"hs", 0x20000000},
298 {"cc", 0x30000000}, {"ul", 0x30000000}, {"lo", 0x30000000},
299 {"mi", 0x40000000},
300 {"pl", 0x50000000},
301 {"vs", 0x60000000},
302 {"vc", 0x70000000},
303 {"hi", 0x80000000},
304 {"ls", 0x90000000},
305 {"ge", 0xa0000000},
306 {"lt", 0xb0000000},
307 {"gt", 0xc0000000},
308 {"le", 0xd0000000},
309 {"al", 0xe0000000},
310 {"nv", 0xf0000000}
311};
312
b99bd4ef
NC
313struct asm_psr
314{
b34976b6
AM
315 const char *template;
316 bfd_boolean cpsr;
b99bd4ef
NC
317 unsigned long field;
318};
319
2d2255b5 320/* The bit that distinguishes CPSR and SPSR. */
b99bd4ef
NC
321#define SPSR_BIT (1 << 22)
322
323/* How many bits to shift the PSR_xxx bits up by. */
324#define PSR_SHIFT 16
325
326#define PSR_c (1 << 0)
327#define PSR_x (1 << 1)
328#define PSR_s (1 << 2)
329#define PSR_f (1 << 3)
330
05d2d07e 331static const struct asm_psr psrs[] =
b99bd4ef 332{
b34976b6
AM
333 {"CPSR", TRUE, PSR_c | PSR_f},
334 {"CPSR_all", TRUE, PSR_c | PSR_f},
335 {"SPSR", FALSE, PSR_c | PSR_f},
336 {"SPSR_all", FALSE, PSR_c | PSR_f},
337 {"CPSR_flg", TRUE, PSR_f},
338 {"CPSR_f", TRUE, PSR_f},
339 {"SPSR_flg", FALSE, PSR_f},
340 {"SPSR_f", FALSE, PSR_f},
341 {"CPSR_c", TRUE, PSR_c},
342 {"CPSR_ctl", TRUE, PSR_c},
343 {"SPSR_c", FALSE, PSR_c},
344 {"SPSR_ctl", FALSE, PSR_c},
345 {"CPSR_x", TRUE, PSR_x},
346 {"CPSR_s", TRUE, PSR_s},
347 {"SPSR_x", FALSE, PSR_x},
348 {"SPSR_s", FALSE, PSR_s},
b99bd4ef 349 /* Combinations of flags. */
b34976b6
AM
350 {"CPSR_fs", TRUE, PSR_f | PSR_s},
351 {"CPSR_fx", TRUE, PSR_f | PSR_x},
352 {"CPSR_fc", TRUE, PSR_f | PSR_c},
353 {"CPSR_sf", TRUE, PSR_s | PSR_f},
354 {"CPSR_sx", TRUE, PSR_s | PSR_x},
355 {"CPSR_sc", TRUE, PSR_s | PSR_c},
356 {"CPSR_xf", TRUE, PSR_x | PSR_f},
357 {"CPSR_xs", TRUE, PSR_x | PSR_s},
358 {"CPSR_xc", TRUE, PSR_x | PSR_c},
359 {"CPSR_cf", TRUE, PSR_c | PSR_f},
360 {"CPSR_cs", TRUE, PSR_c | PSR_s},
361 {"CPSR_cx", TRUE, PSR_c | PSR_x},
362 {"CPSR_fsx", TRUE, PSR_f | PSR_s | PSR_x},
363 {"CPSR_fsc", TRUE, PSR_f | PSR_s | PSR_c},
364 {"CPSR_fxs", TRUE, PSR_f | PSR_x | PSR_s},
365 {"CPSR_fxc", TRUE, PSR_f | PSR_x | PSR_c},
366 {"CPSR_fcs", TRUE, PSR_f | PSR_c | PSR_s},
367 {"CPSR_fcx", TRUE, PSR_f | PSR_c | PSR_x},
368 {"CPSR_sfx", TRUE, PSR_s | PSR_f | PSR_x},
369 {"CPSR_sfc", TRUE, PSR_s | PSR_f | PSR_c},
370 {"CPSR_sxf", TRUE, PSR_s | PSR_x | PSR_f},
371 {"CPSR_sxc", TRUE, PSR_s | PSR_x | PSR_c},
372 {"CPSR_scf", TRUE, PSR_s | PSR_c | PSR_f},
373 {"CPSR_scx", TRUE, PSR_s | PSR_c | PSR_x},
374 {"CPSR_xfs", TRUE, PSR_x | PSR_f | PSR_s},
375 {"CPSR_xfc", TRUE, PSR_x | PSR_f | PSR_c},
376 {"CPSR_xsf", TRUE, PSR_x | PSR_s | PSR_f},
377 {"CPSR_xsc", TRUE, PSR_x | PSR_s | PSR_c},
378 {"CPSR_xcf", TRUE, PSR_x | PSR_c | PSR_f},
379 {"CPSR_xcs", TRUE, PSR_x | PSR_c | PSR_s},
380 {"CPSR_cfs", TRUE, PSR_c | PSR_f | PSR_s},
381 {"CPSR_cfx", TRUE, PSR_c | PSR_f | PSR_x},
382 {"CPSR_csf", TRUE, PSR_c | PSR_s | PSR_f},
383 {"CPSR_csx", TRUE, PSR_c | PSR_s | PSR_x},
384 {"CPSR_cxf", TRUE, PSR_c | PSR_x | PSR_f},
385 {"CPSR_cxs", TRUE, PSR_c | PSR_x | PSR_s},
386 {"CPSR_fsxc", TRUE, PSR_f | PSR_s | PSR_x | PSR_c},
387 {"CPSR_fscx", TRUE, PSR_f | PSR_s | PSR_c | PSR_x},
388 {"CPSR_fxsc", TRUE, PSR_f | PSR_x | PSR_s | PSR_c},
389 {"CPSR_fxcs", TRUE, PSR_f | PSR_x | PSR_c | PSR_s},
390 {"CPSR_fcsx", TRUE, PSR_f | PSR_c | PSR_s | PSR_x},
391 {"CPSR_fcxs", TRUE, PSR_f | PSR_c | PSR_x | PSR_s},
392 {"CPSR_sfxc", TRUE, PSR_s | PSR_f | PSR_x | PSR_c},
393 {"CPSR_sfcx", TRUE, PSR_s | PSR_f | PSR_c | PSR_x},
394 {"CPSR_sxfc", TRUE, PSR_s | PSR_x | PSR_f | PSR_c},
395 {"CPSR_sxcf", TRUE, PSR_s | PSR_x | PSR_c | PSR_f},
396 {"CPSR_scfx", TRUE, PSR_s | PSR_c | PSR_f | PSR_x},
397 {"CPSR_scxf", TRUE, PSR_s | PSR_c | PSR_x | PSR_f},
398 {"CPSR_xfsc", TRUE, PSR_x | PSR_f | PSR_s | PSR_c},
399 {"CPSR_xfcs", TRUE, PSR_x | PSR_f | PSR_c | PSR_s},
400 {"CPSR_xsfc", TRUE, PSR_x | PSR_s | PSR_f | PSR_c},
401 {"CPSR_xscf", TRUE, PSR_x | PSR_s | PSR_c | PSR_f},
402 {"CPSR_xcfs", TRUE, PSR_x | PSR_c | PSR_f | PSR_s},
403 {"CPSR_xcsf", TRUE, PSR_x | PSR_c | PSR_s | PSR_f},
404 {"CPSR_cfsx", TRUE, PSR_c | PSR_f | PSR_s | PSR_x},
405 {"CPSR_cfxs", TRUE, PSR_c | PSR_f | PSR_x | PSR_s},
406 {"CPSR_csfx", TRUE, PSR_c | PSR_s | PSR_f | PSR_x},
407 {"CPSR_csxf", TRUE, PSR_c | PSR_s | PSR_x | PSR_f},
408 {"CPSR_cxfs", TRUE, PSR_c | PSR_x | PSR_f | PSR_s},
409 {"CPSR_cxsf", TRUE, PSR_c | PSR_x | PSR_s | PSR_f},
410 {"SPSR_fs", FALSE, PSR_f | PSR_s},
411 {"SPSR_fx", FALSE, PSR_f | PSR_x},
412 {"SPSR_fc", FALSE, PSR_f | PSR_c},
413 {"SPSR_sf", FALSE, PSR_s | PSR_f},
414 {"SPSR_sx", FALSE, PSR_s | PSR_x},
415 {"SPSR_sc", FALSE, PSR_s | PSR_c},
416 {"SPSR_xf", FALSE, PSR_x | PSR_f},
417 {"SPSR_xs", FALSE, PSR_x | PSR_s},
418 {"SPSR_xc", FALSE, PSR_x | PSR_c},
419 {"SPSR_cf", FALSE, PSR_c | PSR_f},
420 {"SPSR_cs", FALSE, PSR_c | PSR_s},
421 {"SPSR_cx", FALSE, PSR_c | PSR_x},
422 {"SPSR_fsx", FALSE, PSR_f | PSR_s | PSR_x},
423 {"SPSR_fsc", FALSE, PSR_f | PSR_s | PSR_c},
424 {"SPSR_fxs", FALSE, PSR_f | PSR_x | PSR_s},
425 {"SPSR_fxc", FALSE, PSR_f | PSR_x | PSR_c},
426 {"SPSR_fcs", FALSE, PSR_f | PSR_c | PSR_s},
427 {"SPSR_fcx", FALSE, PSR_f | PSR_c | PSR_x},
428 {"SPSR_sfx", FALSE, PSR_s | PSR_f | PSR_x},
429 {"SPSR_sfc", FALSE, PSR_s | PSR_f | PSR_c},
430 {"SPSR_sxf", FALSE, PSR_s | PSR_x | PSR_f},
431 {"SPSR_sxc", FALSE, PSR_s | PSR_x | PSR_c},
432 {"SPSR_scf", FALSE, PSR_s | PSR_c | PSR_f},
433 {"SPSR_scx", FALSE, PSR_s | PSR_c | PSR_x},
434 {"SPSR_xfs", FALSE, PSR_x | PSR_f | PSR_s},
435 {"SPSR_xfc", FALSE, PSR_x | PSR_f | PSR_c},
436 {"SPSR_xsf", FALSE, PSR_x | PSR_s | PSR_f},
437 {"SPSR_xsc", FALSE, PSR_x | PSR_s | PSR_c},
438 {"SPSR_xcf", FALSE, PSR_x | PSR_c | PSR_f},
439 {"SPSR_xcs", FALSE, PSR_x | PSR_c | PSR_s},
440 {"SPSR_cfs", FALSE, PSR_c | PSR_f | PSR_s},
441 {"SPSR_cfx", FALSE, PSR_c | PSR_f | PSR_x},
442 {"SPSR_csf", FALSE, PSR_c | PSR_s | PSR_f},
443 {"SPSR_csx", FALSE, PSR_c | PSR_s | PSR_x},
444 {"SPSR_cxf", FALSE, PSR_c | PSR_x | PSR_f},
445 {"SPSR_cxs", FALSE, PSR_c | PSR_x | PSR_s},
446 {"SPSR_fsxc", FALSE, PSR_f | PSR_s | PSR_x | PSR_c},
447 {"SPSR_fscx", FALSE, PSR_f | PSR_s | PSR_c | PSR_x},
448 {"SPSR_fxsc", FALSE, PSR_f | PSR_x | PSR_s | PSR_c},
449 {"SPSR_fxcs", FALSE, PSR_f | PSR_x | PSR_c | PSR_s},
450 {"SPSR_fcsx", FALSE, PSR_f | PSR_c | PSR_s | PSR_x},
451 {"SPSR_fcxs", FALSE, PSR_f | PSR_c | PSR_x | PSR_s},
452 {"SPSR_sfxc", FALSE, PSR_s | PSR_f | PSR_x | PSR_c},
453 {"SPSR_sfcx", FALSE, PSR_s | PSR_f | PSR_c | PSR_x},
454 {"SPSR_sxfc", FALSE, PSR_s | PSR_x | PSR_f | PSR_c},
455 {"SPSR_sxcf", FALSE, PSR_s | PSR_x | PSR_c | PSR_f},
456 {"SPSR_scfx", FALSE, PSR_s | PSR_c | PSR_f | PSR_x},
457 {"SPSR_scxf", FALSE, PSR_s | PSR_c | PSR_x | PSR_f},
458 {"SPSR_xfsc", FALSE, PSR_x | PSR_f | PSR_s | PSR_c},
459 {"SPSR_xfcs", FALSE, PSR_x | PSR_f | PSR_c | PSR_s},
460 {"SPSR_xsfc", FALSE, PSR_x | PSR_s | PSR_f | PSR_c},
461 {"SPSR_xscf", FALSE, PSR_x | PSR_s | PSR_c | PSR_f},
462 {"SPSR_xcfs", FALSE, PSR_x | PSR_c | PSR_f | PSR_s},
463 {"SPSR_xcsf", FALSE, PSR_x | PSR_c | PSR_s | PSR_f},
464 {"SPSR_cfsx", FALSE, PSR_c | PSR_f | PSR_s | PSR_x},
465 {"SPSR_cfxs", FALSE, PSR_c | PSR_f | PSR_x | PSR_s},
466 {"SPSR_csfx", FALSE, PSR_c | PSR_s | PSR_f | PSR_x},
467 {"SPSR_csxf", FALSE, PSR_c | PSR_s | PSR_x | PSR_f},
468 {"SPSR_cxfs", FALSE, PSR_c | PSR_x | PSR_f | PSR_s},
469 {"SPSR_cxsf", FALSE, PSR_c | PSR_x | PSR_s | PSR_f},
b99bd4ef
NC
470};
471
e16bb312
NC
472enum wreg_type
473 {
474 IWMMXT_REG_WR = 0,
475 IWMMXT_REG_WC = 1,
476 IWMMXT_REG_WR_OR_WC = 2,
477 IWMMXT_REG_WCG
478 };
479
480enum iwmmxt_insn_type
481{
482 check_rd,
483 check_wr,
484 check_wrwr,
485 check_wrwrwr,
486 check_wrwrwcg,
487 check_tbcst,
488 check_tmovmsk,
489 check_tmia,
490 check_tmcrr,
491 check_tmrrc,
492 check_tmcr,
493 check_tmrc,
494 check_tinsr,
495 check_textrc,
496 check_waligni,
497 check_textrm,
498 check_wshufh
499};
500
bfae80f2
RE
501enum vfp_dp_reg_pos
502{
503 VFP_REG_Dd, VFP_REG_Dm, VFP_REG_Dn
504};
505
506enum vfp_sp_reg_pos
507{
508 VFP_REG_Sd, VFP_REG_Sm, VFP_REG_Sn
509};
510
511enum vfp_ldstm_type
512{
513 VFP_LDSTMIA, VFP_LDSTMDB, VFP_LDSTMIAX, VFP_LDSTMDBX
514};
515
516/* VFP system registers. */
517struct vfp_reg
518{
519 const char *name;
520 unsigned long regno;
521};
522
cc8a6dd0 523static const struct vfp_reg vfp_regs[] =
bfae80f2
RE
524{
525 {"fpsid", 0x00000000},
526 {"FPSID", 0x00000000},
527 {"fpscr", 0x00010000},
528 {"FPSCR", 0x00010000},
529 {"fpexc", 0x00080000},
530 {"FPEXC", 0x00080000}
531};
532
6c43fab6
RE
533/* Structure for a hash table entry for a register. */
534struct reg_entry
535{
536 const char * name;
537 int number;
0bbf2aa4 538 bfd_boolean builtin;
6c43fab6
RE
539};
540
e28cd48c 541/* Some well known registers that we refer to directly elsewhere. */
6c43fab6
RE
542#define REG_SP 13
543#define REG_LR 14
544#define REG_PC 15
545
e16bb312
NC
546#define wr_register(reg) ((reg ^ WR_PREFIX) >= 0 && (reg ^ WR_PREFIX) <= 15)
547#define wc_register(reg) ((reg ^ WC_PREFIX) >= 0 && (reg ^ WC_PREFIX) <= 15)
548#define wcg_register(reg) ((reg ^ WC_PREFIX) >= 8 && (reg ^ WC_PREFIX) <= 11)
549
0bbf2aa4
NC
550/* These are the standard names. Users can add aliases with .req.
551 and delete them with .unreq. */
552
6c43fab6
RE
553/* Integer Register Numbers. */
554static const struct reg_entry rn_table[] =
555{
0bbf2aa4
NC
556 {"r0", 0, TRUE}, {"r1", 1, TRUE}, {"r2", 2, TRUE}, {"r3", 3, TRUE},
557 {"r4", 4, TRUE}, {"r5", 5, TRUE}, {"r6", 6, TRUE}, {"r7", 7, TRUE},
558 {"r8", 8, TRUE}, {"r9", 9, TRUE}, {"r10", 10, TRUE}, {"r11", 11, TRUE},
559 {"r12", 12, TRUE}, {"r13", REG_SP, TRUE}, {"r14", REG_LR, TRUE}, {"r15", REG_PC, TRUE},
6c43fab6 560 /* ATPCS Synonyms. */
0bbf2aa4
NC
561 {"a1", 0, TRUE}, {"a2", 1, TRUE}, {"a3", 2, TRUE}, {"a4", 3, TRUE},
562 {"v1", 4, TRUE}, {"v2", 5, TRUE}, {"v3", 6, TRUE}, {"v4", 7, TRUE},
563 {"v5", 8, TRUE}, {"v6", 9, TRUE}, {"v7", 10, TRUE}, {"v8", 11, TRUE},
6c43fab6 564 /* Well-known aliases. */
0bbf2aa4
NC
565 {"wr", 7, TRUE}, {"sb", 9, TRUE}, {"sl", 10, TRUE}, {"fp", 11, TRUE},
566 {"ip", 12, TRUE}, {"sp", REG_SP, TRUE}, {"lr", REG_LR, TRUE}, {"pc", REG_PC, TRUE},
567 {NULL, 0, TRUE}
6c43fab6
RE
568};
569
e16bb312
NC
570#define WR_PREFIX 0x200
571#define WC_PREFIX 0x400
572
573static const struct reg_entry iwmmxt_table[] =
574{
5a6c6817 575 /* Intel Wireless MMX technology register names. */
0bbf2aa4
NC
576 { "wr0", 0x0 | WR_PREFIX, TRUE}, {"wr1", 0x1 | WR_PREFIX, TRUE},
577 { "wr2", 0x2 | WR_PREFIX, TRUE}, {"wr3", 0x3 | WR_PREFIX, TRUE},
578 { "wr4", 0x4 | WR_PREFIX, TRUE}, {"wr5", 0x5 | WR_PREFIX, TRUE},
579 { "wr6", 0x6 | WR_PREFIX, TRUE}, {"wr7", 0x7 | WR_PREFIX, TRUE},
580 { "wr8", 0x8 | WR_PREFIX, TRUE}, {"wr9", 0x9 | WR_PREFIX, TRUE},
581 { "wr10", 0xa | WR_PREFIX, TRUE}, {"wr11", 0xb | WR_PREFIX, TRUE},
582 { "wr12", 0xc | WR_PREFIX, TRUE}, {"wr13", 0xd | WR_PREFIX, TRUE},
583 { "wr14", 0xe | WR_PREFIX, TRUE}, {"wr15", 0xf | WR_PREFIX, TRUE},
584 { "wcid", 0x0 | WC_PREFIX, TRUE}, {"wcon", 0x1 | WC_PREFIX, TRUE},
585 {"wcssf", 0x2 | WC_PREFIX, TRUE}, {"wcasf", 0x3 | WC_PREFIX, TRUE},
586 {"wcgr0", 0x8 | WC_PREFIX, TRUE}, {"wcgr1", 0x9 | WC_PREFIX, TRUE},
587 {"wcgr2", 0xa | WC_PREFIX, TRUE}, {"wcgr3", 0xb | WC_PREFIX, TRUE},
588
589 { "wR0", 0x0 | WR_PREFIX, TRUE}, {"wR1", 0x1 | WR_PREFIX, TRUE},
590 { "wR2", 0x2 | WR_PREFIX, TRUE}, {"wR3", 0x3 | WR_PREFIX, TRUE},
591 { "wR4", 0x4 | WR_PREFIX, TRUE}, {"wR5", 0x5 | WR_PREFIX, TRUE},
592 { "wR6", 0x6 | WR_PREFIX, TRUE}, {"wR7", 0x7 | WR_PREFIX, TRUE},
593 { "wR8", 0x8 | WR_PREFIX, TRUE}, {"wR9", 0x9 | WR_PREFIX, TRUE},
594 { "wR10", 0xa | WR_PREFIX, TRUE}, {"wR11", 0xb | WR_PREFIX, TRUE},
595 { "wR12", 0xc | WR_PREFIX, TRUE}, {"wR13", 0xd | WR_PREFIX, TRUE},
596 { "wR14", 0xe | WR_PREFIX, TRUE}, {"wR15", 0xf | WR_PREFIX, TRUE},
597 { "wCID", 0x0 | WC_PREFIX, TRUE}, {"wCon", 0x1 | WC_PREFIX, TRUE},
598 {"wCSSF", 0x2 | WC_PREFIX, TRUE}, {"wCASF", 0x3 | WC_PREFIX, TRUE},
599 {"wCGR0", 0x8 | WC_PREFIX, TRUE}, {"wCGR1", 0x9 | WC_PREFIX, TRUE},
600 {"wCGR2", 0xa | WC_PREFIX, TRUE}, {"wCGR3", 0xb | WC_PREFIX, TRUE},
601 {NULL, 0, TRUE}
e16bb312
NC
602};
603
6c43fab6
RE
604/* Co-processor Numbers. */
605static const struct reg_entry cp_table[] =
606{
0bbf2aa4
NC
607 {"p0", 0, TRUE}, {"p1", 1, TRUE}, {"p2", 2, TRUE}, {"p3", 3, TRUE},
608 {"p4", 4, TRUE}, {"p5", 5, TRUE}, {"p6", 6, TRUE}, {"p7", 7, TRUE},
609 {"p8", 8, TRUE}, {"p9", 9, TRUE}, {"p10", 10, TRUE}, {"p11", 11, TRUE},
610 {"p12", 12, TRUE}, {"p13", 13, TRUE}, {"p14", 14, TRUE}, {"p15", 15, TRUE},
611 {NULL, 0, TRUE}
6c43fab6
RE
612};
613
614/* Co-processor Register Numbers. */
615static const struct reg_entry cn_table[] =
616{
0bbf2aa4
NC
617 {"c0", 0, TRUE}, {"c1", 1, TRUE}, {"c2", 2, TRUE}, {"c3", 3, TRUE},
618 {"c4", 4, TRUE}, {"c5", 5, TRUE}, {"c6", 6, TRUE}, {"c7", 7, TRUE},
619 {"c8", 8, TRUE}, {"c9", 9, TRUE}, {"c10", 10, TRUE}, {"c11", 11, TRUE},
620 {"c12", 12, TRUE}, {"c13", 13, TRUE}, {"c14", 14, TRUE}, {"c15", 15, TRUE},
6c43fab6 621 /* Not really valid, but kept for back-wards compatibility. */
0bbf2aa4
NC
622 {"cr0", 0, TRUE}, {"cr1", 1, TRUE}, {"cr2", 2, TRUE}, {"cr3", 3, TRUE},
623 {"cr4", 4, TRUE}, {"cr5", 5, TRUE}, {"cr6", 6, TRUE}, {"cr7", 7, TRUE},
624 {"cr8", 8, TRUE}, {"cr9", 9, TRUE}, {"cr10", 10, TRUE}, {"cr11", 11, TRUE},
625 {"cr12", 12, TRUE}, {"cr13", 13, TRUE}, {"cr14", 14, TRUE}, {"cr15", 15, TRUE},
626 {NULL, 0, TRUE}
6c43fab6
RE
627};
628
629/* FPA Registers. */
630static const struct reg_entry fn_table[] =
631{
0bbf2aa4
NC
632 {"f0", 0, TRUE}, {"f1", 1, TRUE}, {"f2", 2, TRUE}, {"f3", 3, TRUE},
633 {"f4", 4, TRUE}, {"f5", 5, TRUE}, {"f6", 6, TRUE}, {"f7", 7, TRUE},
634 {NULL, 0, TRUE}
6c43fab6
RE
635};
636
bfae80f2
RE
637/* VFP SP Registers. */
638static const struct reg_entry sn_table[] =
639{
0bbf2aa4
NC
640 {"s0", 0, TRUE}, {"s1", 1, TRUE}, {"s2", 2, TRUE}, {"s3", 3, TRUE},
641 {"s4", 4, TRUE}, {"s5", 5, TRUE}, {"s6", 6, TRUE}, {"s7", 7, TRUE},
642 {"s8", 8, TRUE}, {"s9", 9, TRUE}, {"s10", 10, TRUE}, {"s11", 11, TRUE},
643 {"s12", 12, TRUE}, {"s13", 13, TRUE}, {"s14", 14, TRUE}, {"s15", 15, TRUE},
644 {"s16", 16, TRUE}, {"s17", 17, TRUE}, {"s18", 18, TRUE}, {"s19", 19, TRUE},
645 {"s20", 20, TRUE}, {"s21", 21, TRUE}, {"s22", 22, TRUE}, {"s23", 23, TRUE},
646 {"s24", 24, TRUE}, {"s25", 25, TRUE}, {"s26", 26, TRUE}, {"s27", 27, TRUE},
647 {"s28", 28, TRUE}, {"s29", 29, TRUE}, {"s30", 30, TRUE}, {"s31", 31, TRUE},
648 {NULL, 0, TRUE}
bfae80f2
RE
649};
650
651/* VFP DP Registers. */
652static const struct reg_entry dn_table[] =
653{
0bbf2aa4
NC
654 {"d0", 0, TRUE}, {"d1", 1, TRUE}, {"d2", 2, TRUE}, {"d3", 3, TRUE},
655 {"d4", 4, TRUE}, {"d5", 5, TRUE}, {"d6", 6, TRUE}, {"d7", 7, TRUE},
656 {"d8", 8, TRUE}, {"d9", 9, TRUE}, {"d10", 10, TRUE}, {"d11", 11, TRUE},
657 {"d12", 12, TRUE}, {"d13", 13, TRUE}, {"d14", 14, TRUE}, {"d15", 15, TRUE},
658 {NULL, 0, TRUE}
bfae80f2
RE
659};
660
63e63b07 661/* Maverick DSP coprocessor registers. */
6c43fab6
RE
662static const struct reg_entry mav_mvf_table[] =
663{
0bbf2aa4
NC
664 {"mvf0", 0, TRUE}, {"mvf1", 1, TRUE}, {"mvf2", 2, TRUE}, {"mvf3", 3, TRUE},
665 {"mvf4", 4, TRUE}, {"mvf5", 5, TRUE}, {"mvf6", 6, TRUE}, {"mvf7", 7, TRUE},
666 {"mvf8", 8, TRUE}, {"mvf9", 9, TRUE}, {"mvf10", 10, TRUE}, {"mvf11", 11, TRUE},
667 {"mvf12", 12, TRUE}, {"mvf13", 13, TRUE}, {"mvf14", 14, TRUE}, {"mvf15", 15, TRUE},
668 {NULL, 0, TRUE}
6c43fab6
RE
669};
670
671static const struct reg_entry mav_mvd_table[] =
672{
0bbf2aa4
NC
673 {"mvd0", 0, TRUE}, {"mvd1", 1, TRUE}, {"mvd2", 2, TRUE}, {"mvd3", 3, TRUE},
674 {"mvd4", 4, TRUE}, {"mvd5", 5, TRUE}, {"mvd6", 6, TRUE}, {"mvd7", 7, TRUE},
675 {"mvd8", 8, TRUE}, {"mvd9", 9, TRUE}, {"mvd10", 10, TRUE}, {"mvd11", 11, TRUE},
676 {"mvd12", 12, TRUE}, {"mvd13", 13, TRUE}, {"mvd14", 14, TRUE}, {"mvd15", 15, TRUE},
677 {NULL, 0, TRUE}
6c43fab6
RE
678};
679
680static const struct reg_entry mav_mvfx_table[] =
681{
0bbf2aa4
NC
682 {"mvfx0", 0, TRUE}, {"mvfx1", 1, TRUE}, {"mvfx2", 2, TRUE}, {"mvfx3", 3, TRUE},
683 {"mvfx4", 4, TRUE}, {"mvfx5", 5, TRUE}, {"mvfx6", 6, TRUE}, {"mvfx7", 7, TRUE},
684 {"mvfx8", 8, TRUE}, {"mvfx9", 9, TRUE}, {"mvfx10", 10, TRUE}, {"mvfx11", 11, TRUE},
685 {"mvfx12", 12, TRUE}, {"mvfx13", 13, TRUE}, {"mvfx14", 14, TRUE}, {"mvfx15", 15, TRUE},
686 {NULL, 0, TRUE}
6c43fab6
RE
687};
688
689static const struct reg_entry mav_mvdx_table[] =
690{
0bbf2aa4
NC
691 {"mvdx0", 0, TRUE}, {"mvdx1", 1, TRUE}, {"mvdx2", 2, TRUE}, {"mvdx3", 3, TRUE},
692 {"mvdx4", 4, TRUE}, {"mvdx5", 5, TRUE}, {"mvdx6", 6, TRUE}, {"mvdx7", 7, TRUE},
693 {"mvdx8", 8, TRUE}, {"mvdx9", 9, TRUE}, {"mvdx10", 10, TRUE}, {"mvdx11", 11, TRUE},
694 {"mvdx12", 12, TRUE}, {"mvdx13", 13, TRUE}, {"mvdx14", 14, TRUE}, {"mvdx15", 15, TRUE},
695 {NULL, 0, TRUE}
6c43fab6
RE
696};
697
698static const struct reg_entry mav_mvax_table[] =
699{
0bbf2aa4
NC
700 {"mvax0", 0, TRUE}, {"mvax1", 1, TRUE}, {"mvax2", 2, TRUE}, {"mvax3", 3, TRUE},
701 {NULL, 0, TRUE}
6c43fab6
RE
702};
703
704static const struct reg_entry mav_dspsc_table[] =
705{
0bbf2aa4
NC
706 {"dspsc", 0, TRUE},
707 {NULL, 0, TRUE}
6c43fab6
RE
708};
709
710struct reg_map
711{
712 const struct reg_entry *names;
713 int max_regno;
714 struct hash_control *htab;
715 const char *expected;
716};
717
718struct reg_map all_reg_maps[] =
719{
720 {rn_table, 15, NULL, N_("ARM register expected")},
f03698e6
RE
721 {cp_table, 15, NULL, N_("bad or missing co-processor number")},
722 {cn_table, 15, NULL, N_("co-processor register expected")},
6c43fab6 723 {fn_table, 7, NULL, N_("FPA register expected")},
bfae80f2
RE
724 {sn_table, 31, NULL, N_("VFP single precision register expected")},
725 {dn_table, 15, NULL, N_("VFP double precision register expected")},
6c43fab6
RE
726 {mav_mvf_table, 15, NULL, N_("Maverick MVF register expected")},
727 {mav_mvd_table, 15, NULL, N_("Maverick MVD register expected")},
728 {mav_mvfx_table, 15, NULL, N_("Maverick MVFX register expected")},
5a21e886 729 {mav_mvdx_table, 15, NULL, N_("Maverick MVDX register expected")},
6c43fab6
RE
730 {mav_mvax_table, 3, NULL, N_("Maverick MVAX register expected")},
731 {mav_dspsc_table, 0, NULL, N_("Maverick DSPSC register expected")},
5a6c6817 732 {iwmmxt_table, 23, NULL, N_("Intel Wireless MMX technology register expected")},
6c43fab6
RE
733};
734
735/* Enumeration matching entries in table above. */
736enum arm_reg_type
737{
738 REG_TYPE_RN = 0,
739#define REG_TYPE_FIRST REG_TYPE_RN
740 REG_TYPE_CP = 1,
741 REG_TYPE_CN = 2,
742 REG_TYPE_FN = 3,
bfae80f2
RE
743 REG_TYPE_SN = 4,
744 REG_TYPE_DN = 5,
745 REG_TYPE_MVF = 6,
746 REG_TYPE_MVD = 7,
747 REG_TYPE_MVFX = 8,
748 REG_TYPE_MVDX = 9,
749 REG_TYPE_MVAX = 10,
750 REG_TYPE_DSPSC = 11,
e16bb312 751 REG_TYPE_IWMMXT = 12,
bfae80f2 752
e16bb312 753 REG_TYPE_MAX = 13
6c43fab6 754};
404ff6b5 755
b99bd4ef
NC
756/* Functions called by parser. */
757/* ARM instructions. */
f2b7cb0a
RE
758static void do_arit PARAMS ((char *));
759static void do_cmp PARAMS ((char *));
760static void do_mov PARAMS ((char *));
761static void do_ldst PARAMS ((char *));
762static void do_ldstt PARAMS ((char *));
763static void do_ldmstm PARAMS ((char *));
764static void do_branch PARAMS ((char *));
765static void do_swi PARAMS ((char *));
c9b604bd 766
b99bd4ef 767/* Pseudo Op codes. */
f2b7cb0a
RE
768static void do_adr PARAMS ((char *));
769static void do_adrl PARAMS ((char *));
770static void do_empty PARAMS ((char *));
c9b604bd
RE
771
772/* ARM v2. */
f2b7cb0a
RE
773static void do_mul PARAMS ((char *));
774static void do_mla PARAMS ((char *));
c9b604bd
RE
775
776/* ARM v2S. */
f2b7cb0a 777static void do_swap PARAMS ((char *));
c9b604bd
RE
778
779/* ARM v3. */
f2b7cb0a
RE
780static void do_msr PARAMS ((char *));
781static void do_mrs PARAMS ((char *));
c9b604bd
RE
782
783/* ARM v3M. */
f2b7cb0a 784static void do_mull PARAMS ((char *));
b99bd4ef 785
90e4755a 786/* ARM v4. */
f2b7cb0a 787static void do_ldstv4 PARAMS ((char *));
90e4755a 788
c9b604bd 789/* ARM v4T. */
f2b7cb0a 790static void do_bx PARAMS ((char *));
b99bd4ef 791
ea6ef066 792/* ARM v5T. */
f2b7cb0a
RE
793static void do_blx PARAMS ((char *));
794static void do_bkpt PARAMS ((char *));
795static void do_clz PARAMS ((char *));
796static void do_lstc2 PARAMS ((char *));
797static void do_cdp2 PARAMS ((char *));
798static void do_co_reg2 PARAMS ((char *));
b99bd4ef 799
ea6ef066 800/* ARM v5TExP. */
f2b7cb0a
RE
801static void do_smla PARAMS ((char *));
802static void do_smlal PARAMS ((char *));
803static void do_smul PARAMS ((char *));
804static void do_qadd PARAMS ((char *));
c9b604bd 805
ea6ef066 806/* ARM v5TE. */
f2b7cb0a
RE
807static void do_pld PARAMS ((char *));
808static void do_ldrd PARAMS ((char *));
809static void do_co_reg2c PARAMS ((char *));
b99bd4ef 810
ea6ef066
RE
811/* ARM v5TEJ. */
812static void do_bxj PARAMS ((char *));
813
09d92015
MM
814/* ARM V6. */
815static void do_cps PARAMS ((char *));
816static void do_cpsi PARAMS ((char *));
817static void do_ldrex PARAMS ((char *));
818static void do_pkhbt PARAMS ((char *));
819static void do_pkhtb PARAMS ((char *));
820static void do_qadd16 PARAMS ((char *));
821static void do_rev PARAMS ((char *));
822static void do_rfe PARAMS ((char *));
823static void do_sxtah PARAMS ((char *));
824static void do_sxth PARAMS ((char *));
825static void do_setend PARAMS ((char *));
826static void do_smlad PARAMS ((char *));
827static void do_smlald PARAMS ((char *));
828static void do_smmul PARAMS ((char *));
829static void do_ssat PARAMS ((char *));
830static void do_usat PARAMS ((char *));
831static void do_srs PARAMS ((char *));
832static void do_ssat16 PARAMS ((char *));
833static void do_usat16 PARAMS ((char *));
834static void do_strex PARAMS ((char *));
835static void do_umaal PARAMS ((char *));
836
837static void do_cps_mode PARAMS ((char **));
838static void do_cps_flags PARAMS ((char **, int));
839static int do_endian_specifier PARAMS ((char *));
840static void do_pkh_core PARAMS ((char *, int));
841static void do_sat PARAMS ((char **, int));
842static void do_sat16 PARAMS ((char **, int));
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 *));
e45d0630
PB
866static void do_vfp_reg2_from_sp2 PARAMS ((char *));
867static void do_vfp_sp2_from_reg2 PARAMS ((char *));
bfae80f2
RE
868static void do_vfp_reg_from_dp PARAMS ((char *));
869static void do_vfp_reg2_from_dp PARAMS ((char *));
870static void do_vfp_dp_from_reg PARAMS ((char *));
871static void do_vfp_dp_from_reg2 PARAMS ((char *));
872static void do_vfp_reg_from_ctrl PARAMS ((char *));
873static void do_vfp_ctrl_from_reg PARAMS ((char *));
874static void do_vfp_sp_ldst PARAMS ((char *));
875static void do_vfp_dp_ldst PARAMS ((char *));
876static void do_vfp_sp_ldstmia PARAMS ((char *));
877static void do_vfp_sp_ldstmdb PARAMS ((char *));
878static void do_vfp_dp_ldstmia PARAMS ((char *));
879static void do_vfp_dp_ldstmdb PARAMS ((char *));
880static void do_vfp_xp_ldstmia PARAMS ((char *));
881static void do_vfp_xp_ldstmdb PARAMS ((char *));
882static void do_vfp_sp_compare_z PARAMS ((char *));
883static void do_vfp_dp_compare_z PARAMS ((char *));
884static void do_vfp_dp_sp_cvt PARAMS ((char *));
885static void do_vfp_sp_dp_cvt PARAMS ((char *));
886
c9b604bd 887/* XScale. */
63e63b07
RE
888static void do_xsc_mia PARAMS ((char *));
889static void do_xsc_mar PARAMS ((char *));
890static void do_xsc_mra PARAMS ((char *));
f2b7cb0a
RE
891
892/* Maverick. */
63e63b07 893static void do_mav_binops PARAMS ((char *, int, enum arm_reg_type,
6c43fab6 894 enum arm_reg_type));
63e63b07
RE
895static void do_mav_binops_1a PARAMS ((char *));
896static void do_mav_binops_1b PARAMS ((char *));
897static void do_mav_binops_1c PARAMS ((char *));
898static void do_mav_binops_1d PARAMS ((char *));
899static void do_mav_binops_1e PARAMS ((char *));
900static void do_mav_binops_1f PARAMS ((char *));
901static void do_mav_binops_1g PARAMS ((char *));
902static void do_mav_binops_1h PARAMS ((char *));
903static void do_mav_binops_1i PARAMS ((char *));
904static void do_mav_binops_1j PARAMS ((char *));
905static void do_mav_binops_1k PARAMS ((char *));
906static void do_mav_binops_1l PARAMS ((char *));
907static void do_mav_binops_1m PARAMS ((char *));
908static void do_mav_binops_1n PARAMS ((char *));
909static void do_mav_binops_1o PARAMS ((char *));
910static void do_mav_binops_2a PARAMS ((char *));
911static void do_mav_binops_2b PARAMS ((char *));
912static void do_mav_binops_2c PARAMS ((char *));
913static void do_mav_binops_3a PARAMS ((char *));
914static void do_mav_binops_3b PARAMS ((char *));
915static void do_mav_binops_3c PARAMS ((char *));
916static void do_mav_binops_3d PARAMS ((char *));
cc8a6dd0 917static void do_mav_triple PARAMS ((char *, int, enum arm_reg_type,
6c43fab6
RE
918 enum arm_reg_type,
919 enum arm_reg_type));
63e63b07
RE
920static void do_mav_triple_4a PARAMS ((char *));
921static void do_mav_triple_4b PARAMS ((char *));
922static void do_mav_triple_5a PARAMS ((char *));
923static void do_mav_triple_5b PARAMS ((char *));
924static void do_mav_triple_5c PARAMS ((char *));
925static void do_mav_triple_5d PARAMS ((char *));
926static void do_mav_triple_5e PARAMS ((char *));
927static void do_mav_triple_5f PARAMS ((char *));
928static void do_mav_triple_5g PARAMS ((char *));
929static void do_mav_triple_5h PARAMS ((char *));
cc8a6dd0 930static void do_mav_quad PARAMS ((char *, int, enum arm_reg_type,
6c43fab6
RE
931 enum arm_reg_type,
932 enum arm_reg_type,
933 enum arm_reg_type));
63e63b07
RE
934static void do_mav_quad_6a PARAMS ((char *));
935static void do_mav_quad_6b PARAMS ((char *));
936static void do_mav_dspsc_1 PARAMS ((char *));
937static void do_mav_dspsc_2 PARAMS ((char *));
938static void do_mav_shift PARAMS ((char *, enum arm_reg_type,
6c43fab6 939 enum arm_reg_type));
63e63b07
RE
940static void do_mav_shift_1 PARAMS ((char *));
941static void do_mav_shift_2 PARAMS ((char *));
942static void do_mav_ldst PARAMS ((char *, enum arm_reg_type));
943static void do_mav_ldst_1 PARAMS ((char *));
944static void do_mav_ldst_2 PARAMS ((char *));
945static void do_mav_ldst_3 PARAMS ((char *));
946static void do_mav_ldst_4 PARAMS ((char *));
947
948static int mav_reg_required_here PARAMS ((char **, int,
6c43fab6 949 enum arm_reg_type));
63e63b07 950static int mav_parse_offset PARAMS ((char **, int *));
404ff6b5 951
90e4755a
RE
952static void fix_new_arm PARAMS ((fragS *, int, short, expressionS *,
953 int, int));
6c43fab6
RE
954static int arm_reg_parse PARAMS ((char **, struct hash_control *));
955static enum arm_reg_type arm_reg_parse_any PARAMS ((char *));
05d2d07e 956static const struct asm_psr * arm_psr_parse PARAMS ((char **));
90e4755a
RE
957static void symbol_locate PARAMS ((symbolS *, const char *, segT, valueT,
958 fragS *));
b99bd4ef
NC
959static int add_to_lit_pool PARAMS ((void));
960static unsigned validate_immediate PARAMS ((unsigned));
90e4755a
RE
961static unsigned validate_immediate_twopart PARAMS ((unsigned int,
962 unsigned int *));
b99bd4ef
NC
963static int validate_offset_imm PARAMS ((unsigned int, int));
964static void opcode_select PARAMS ((int));
965static void end_of_line PARAMS ((char *));
966static int reg_required_here PARAMS ((char **, int));
967static int psr_required_here PARAMS ((char **));
968static int co_proc_number PARAMS ((char **));
969static int cp_opc_expr PARAMS ((char **, int, int));
970static int cp_reg_required_here PARAMS ((char **, int));
971static int fp_reg_required_here PARAMS ((char **, int));
bfae80f2
RE
972static int vfp_sp_reg_required_here PARAMS ((char **, enum vfp_sp_reg_pos));
973static int vfp_dp_reg_required_here PARAMS ((char **, enum vfp_dp_reg_pos));
974static void vfp_sp_ldstm PARAMS ((char *, enum vfp_ldstm_type));
975static void vfp_dp_ldstm PARAMS ((char *, enum vfp_ldstm_type));
976static long vfp_sp_reg_list PARAMS ((char **, enum vfp_sp_reg_pos));
977static long vfp_dp_reg_list PARAMS ((char **));
978static int vfp_psr_required_here PARAMS ((char **str));
979static const struct vfp_reg *vfp_psr_parse PARAMS ((char **str));
b99bd4ef 980static int cp_address_offset PARAMS ((char **));
bfae80f2 981static int cp_address_required_here PARAMS ((char **, int));
b99bd4ef
NC
982static int my_get_float_expression PARAMS ((char **));
983static int skip_past_comma PARAMS ((char **));
984static int walk_no_bignums PARAMS ((symbolS *));
985static int negate_data_op PARAMS ((unsigned long *, unsigned long));
986static int data_op2 PARAMS ((char **));
987static int fp_op2 PARAMS ((char **));
988static long reg_list PARAMS ((char **));
989static void thumb_load_store PARAMS ((char *, int, int));
990static int decode_shift PARAMS ((char **, int));
90e4755a
RE
991static int ldst_extend PARAMS ((char **));
992static int ldst_extend_v4 PARAMS ((char **));
b99bd4ef 993static void thumb_add_sub PARAMS ((char *, int));
6c43fab6
RE
994static void insert_reg PARAMS ((const struct reg_entry *,
995 struct hash_control *));
b99bd4ef
NC
996static void thumb_shift PARAMS ((char *, int));
997static void thumb_mov_compare PARAMS ((char *, int));
f2b7cb0a 998static void build_arm_ops_hsh PARAMS ((void));
b99bd4ef
NC
999static void set_constant_flonums PARAMS ((void));
1000static valueT md_chars_to_number PARAMS ((char *, int));
6c43fab6
RE
1001static void build_reg_hsh PARAMS ((struct reg_map *));
1002static void insert_reg_alias PARAMS ((char *, int, struct hash_control *));
1003static int create_register_alias PARAMS ((char *, char *));
f03698e6 1004static void output_inst PARAMS ((const char *));
2c20dfb2
NC
1005static int accum0_required_here PARAMS ((char **));
1006static int ld_mode_required_here PARAMS ((char **));
f2b7cb0a 1007static void do_branch25 PARAMS ((char *));
2c20dfb2 1008static symbolS * find_real_start PARAMS ((symbolS *));
b99bd4ef
NC
1009#ifdef OBJ_ELF
1010static bfd_reloc_code_real_type arm_parse_reloc PARAMS ((void));
1011#endif
1012
e16bb312
NC
1013static int wreg_required_here PARAMS ((char **, int, enum wreg_type));
1014static void do_iwmmxt_byte_addr PARAMS ((char *));
1015static void do_iwmmxt_tandc PARAMS ((char *));
1016static void do_iwmmxt_tbcst PARAMS ((char *));
1017static void do_iwmmxt_textrc PARAMS ((char *));
1018static void do_iwmmxt_textrm PARAMS ((char *));
1019static void do_iwmmxt_tinsr PARAMS ((char *));
1020static void do_iwmmxt_tmcr PARAMS ((char *));
1021static void do_iwmmxt_tmcrr PARAMS ((char *));
1022static void do_iwmmxt_tmia PARAMS ((char *));
1023static void do_iwmmxt_tmovmsk PARAMS ((char *));
1024static void do_iwmmxt_tmrc PARAMS ((char *));
1025static void do_iwmmxt_tmrrc PARAMS ((char *));
1026static void do_iwmmxt_torc PARAMS ((char *));
1027static void do_iwmmxt_waligni PARAMS ((char *));
1028static void do_iwmmxt_wmov PARAMS ((char *));
1029static void do_iwmmxt_word_addr PARAMS ((char *));
1030static void do_iwmmxt_wrwr PARAMS ((char *));
1031static void do_iwmmxt_wrwrwcg PARAMS ((char *));
1032static void do_iwmmxt_wrwrwr PARAMS ((char *));
1033static void do_iwmmxt_wshufh PARAMS ((char *));
1034static void do_iwmmxt_wzero PARAMS ((char *));
1035static int cp_byte_address_offset PARAMS ((char **));
1036static int cp_byte_address_required_here PARAMS ((char **));
1037
b99bd4ef
NC
1038/* ARM instructions take 4bytes in the object file, Thumb instructions
1039 take 2: */
1040#define INSN_SIZE 4
1041
404ff6b5 1042/* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
63e63b07 1043#define MAV_MODE1 0x100c
404ff6b5
AH
1044
1045/* "INSN<cond> X,Y" where X:bit16, Y:bit12. */
63e63b07 1046#define MAV_MODE2 0x0c10
404ff6b5 1047
34920d91
NC
1048/* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
1049#define MAV_MODE3 0x100c
404ff6b5
AH
1050
1051/* "INSN<cond> X,Y,Z" where X:16, Y:0, Z:12. */
63e63b07 1052#define MAV_MODE4 0x0c0010
404ff6b5
AH
1053
1054/* "INSN<cond> X,Y,Z" where X:12, Y:16, Z:0. */
63e63b07 1055#define MAV_MODE5 0x00100c
404ff6b5
AH
1056
1057/* "INSN<cond> W,X,Y,Z" where W:5, X:12, Y:16, Z:0. */
63e63b07 1058#define MAV_MODE6 0x00100c05
b99bd4ef
NC
1059
1060struct asm_opcode
1061{
1062 /* Basic string to match. */
05d2d07e 1063 const char * template;
b99bd4ef
NC
1064
1065 /* Basic instruction code. */
1066 unsigned long value;
1067
90e4755a
RE
1068 /* Offset into the template where the condition code (if any) will be.
1069 If zero, then the instruction is never conditional. */
1070 unsigned cond_offset;
b99bd4ef 1071
90e4755a
RE
1072 /* Which architecture variant provides this instruction. */
1073 unsigned long variant;
b99bd4ef
NC
1074
1075 /* Function to call to parse args. */
f2b7cb0a 1076 void (* parms) PARAMS ((char *));
b99bd4ef
NC
1077};
1078
05d2d07e 1079static const struct asm_opcode insns[] =
b99bd4ef 1080{
c9b604bd 1081 /* Core ARM Instructions. */
90e4755a
RE
1082 {"and", 0xe0000000, 3, ARM_EXT_V1, do_arit},
1083 {"ands", 0xe0100000, 3, ARM_EXT_V1, do_arit},
1084 {"eor", 0xe0200000, 3, ARM_EXT_V1, do_arit},
1085 {"eors", 0xe0300000, 3, ARM_EXT_V1, do_arit},
1086 {"sub", 0xe0400000, 3, ARM_EXT_V1, do_arit},
1087 {"subs", 0xe0500000, 3, ARM_EXT_V1, do_arit},
1088 {"rsb", 0xe0600000, 3, ARM_EXT_V1, do_arit},
1089 {"rsbs", 0xe0700000, 3, ARM_EXT_V1, do_arit},
1090 {"add", 0xe0800000, 3, ARM_EXT_V1, do_arit},
1091 {"adds", 0xe0900000, 3, ARM_EXT_V1, do_arit},
1092 {"adc", 0xe0a00000, 3, ARM_EXT_V1, do_arit},
1093 {"adcs", 0xe0b00000, 3, ARM_EXT_V1, do_arit},
1094 {"sbc", 0xe0c00000, 3, ARM_EXT_V1, do_arit},
1095 {"sbcs", 0xe0d00000, 3, ARM_EXT_V1, do_arit},
1096 {"rsc", 0xe0e00000, 3, ARM_EXT_V1, do_arit},
1097 {"rscs", 0xe0f00000, 3, ARM_EXT_V1, do_arit},
1098 {"orr", 0xe1800000, 3, ARM_EXT_V1, do_arit},
1099 {"orrs", 0xe1900000, 3, ARM_EXT_V1, do_arit},
1100 {"bic", 0xe1c00000, 3, ARM_EXT_V1, do_arit},
1101 {"bics", 0xe1d00000, 3, ARM_EXT_V1, do_arit},
1102
1103 {"tst", 0xe1100000, 3, ARM_EXT_V1, do_cmp},
1104 {"tsts", 0xe1100000, 3, ARM_EXT_V1, do_cmp},
1105 {"tstp", 0xe110f000, 3, ARM_EXT_V1, do_cmp},
1106 {"teq", 0xe1300000, 3, ARM_EXT_V1, do_cmp},
1107 {"teqs", 0xe1300000, 3, ARM_EXT_V1, do_cmp},
1108 {"teqp", 0xe130f000, 3, ARM_EXT_V1, do_cmp},
1109 {"cmp", 0xe1500000, 3, ARM_EXT_V1, do_cmp},
1110 {"cmps", 0xe1500000, 3, ARM_EXT_V1, do_cmp},
1111 {"cmpp", 0xe150f000, 3, ARM_EXT_V1, do_cmp},
1112 {"cmn", 0xe1700000, 3, ARM_EXT_V1, do_cmp},
1113 {"cmns", 0xe1700000, 3, ARM_EXT_V1, do_cmp},
1114 {"cmnp", 0xe170f000, 3, ARM_EXT_V1, do_cmp},
1115
1116 {"mov", 0xe1a00000, 3, ARM_EXT_V1, do_mov},
1117 {"movs", 0xe1b00000, 3, ARM_EXT_V1, do_mov},
1118 {"mvn", 0xe1e00000, 3, ARM_EXT_V1, do_mov},
1119 {"mvns", 0xe1f00000, 3, ARM_EXT_V1, do_mov},
1120
1121 {"ldr", 0xe4100000, 3, ARM_EXT_V1, do_ldst},
1122 {"ldrb", 0xe4500000, 3, ARM_EXT_V1, do_ldst},
1123 {"ldrt", 0xe4300000, 3, ARM_EXT_V1, do_ldstt},
1124 {"ldrbt", 0xe4700000, 3, ARM_EXT_V1, do_ldstt},
1125 {"str", 0xe4000000, 3, ARM_EXT_V1, do_ldst},
1126 {"strb", 0xe4400000, 3, ARM_EXT_V1, do_ldst},
1127 {"strt", 0xe4200000, 3, ARM_EXT_V1, do_ldstt},
1128 {"strbt", 0xe4600000, 3, ARM_EXT_V1, do_ldstt},
1129
1130 {"stmia", 0xe8800000, 3, ARM_EXT_V1, do_ldmstm},
1131 {"stmib", 0xe9800000, 3, ARM_EXT_V1, do_ldmstm},
1132 {"stmda", 0xe8000000, 3, ARM_EXT_V1, do_ldmstm},
1133 {"stmdb", 0xe9000000, 3, ARM_EXT_V1, do_ldmstm},
1134 {"stmfd", 0xe9000000, 3, ARM_EXT_V1, do_ldmstm},
1135 {"stmfa", 0xe9800000, 3, ARM_EXT_V1, do_ldmstm},
1136 {"stmea", 0xe8800000, 3, ARM_EXT_V1, do_ldmstm},
1137 {"stmed", 0xe8000000, 3, ARM_EXT_V1, do_ldmstm},
1138
1139 {"ldmia", 0xe8900000, 3, ARM_EXT_V1, do_ldmstm},
1140 {"ldmib", 0xe9900000, 3, ARM_EXT_V1, do_ldmstm},
1141 {"ldmda", 0xe8100000, 3, ARM_EXT_V1, do_ldmstm},
1142 {"ldmdb", 0xe9100000, 3, ARM_EXT_V1, do_ldmstm},
1143 {"ldmfd", 0xe8900000, 3, ARM_EXT_V1, do_ldmstm},
1144 {"ldmfa", 0xe8100000, 3, ARM_EXT_V1, do_ldmstm},
1145 {"ldmea", 0xe9100000, 3, ARM_EXT_V1, do_ldmstm},
1146 {"ldmed", 0xe9900000, 3, ARM_EXT_V1, do_ldmstm},
1147
1148 {"swi", 0xef000000, 3, ARM_EXT_V1, do_swi},
b99bd4ef 1149#ifdef TE_WINCE
c9b604bd 1150 /* XXX This is the wrong place to do this. Think multi-arch. */
90e4755a
RE
1151 {"bl", 0xeb000000, 2, ARM_EXT_V1, do_branch},
1152 {"b", 0xea000000, 1, ARM_EXT_V1, do_branch},
b99bd4ef 1153#else
90e4755a
RE
1154 {"bl", 0xebfffffe, 2, ARM_EXT_V1, do_branch},
1155 {"b", 0xeafffffe, 1, ARM_EXT_V1, do_branch},
b99bd4ef
NC
1156#endif
1157
c9b604bd 1158 /* Pseudo ops. */
90e4755a
RE
1159 {"adr", 0xe28f0000, 3, ARM_EXT_V1, do_adr},
1160 {"adrl", 0xe28f0000, 3, ARM_EXT_V1, do_adrl},
1161 {"nop", 0xe1a00000, 3, ARM_EXT_V1, do_empty},
b99bd4ef 1162
c9b604bd 1163 /* ARM 2 multiplies. */
90e4755a
RE
1164 {"mul", 0xe0000090, 3, ARM_EXT_V2, do_mul},
1165 {"muls", 0xe0100090, 3, ARM_EXT_V2, do_mul},
1166 {"mla", 0xe0200090, 3, ARM_EXT_V2, do_mla},
1167 {"mlas", 0xe0300090, 3, ARM_EXT_V2, do_mla},
b99bd4ef 1168
67c1ffbe 1169 /* Generic coprocessor instructions. */
90e4755a
RE
1170 {"cdp", 0xee000000, 3, ARM_EXT_V2, do_cdp},
1171 {"ldc", 0xec100000, 3, ARM_EXT_V2, do_lstc},
1172 {"ldcl", 0xec500000, 3, ARM_EXT_V2, do_lstc},
1173 {"stc", 0xec000000, 3, ARM_EXT_V2, do_lstc},
1174 {"stcl", 0xec400000, 3, ARM_EXT_V2, do_lstc},
1175 {"mcr", 0xee000010, 3, ARM_EXT_V2, do_co_reg},
1176 {"mrc", 0xee100010, 3, ARM_EXT_V2, do_co_reg},
c9b604bd
RE
1177
1178 /* ARM 3 - swp instructions. */
90e4755a
RE
1179 {"swp", 0xe1000090, 3, ARM_EXT_V2S, do_swap},
1180 {"swpb", 0xe1400090, 3, ARM_EXT_V2S, do_swap},
b99bd4ef 1181
c9b604bd 1182 /* ARM 6 Status register instructions. */
90e4755a
RE
1183 {"mrs", 0xe10f0000, 3, ARM_EXT_V3, do_mrs},
1184 {"msr", 0xe120f000, 3, ARM_EXT_V3, do_msr},
1185 /* ScottB: our code uses 0xe128f000 for msr.
c9b604bd 1186 NickC: but this is wrong because the bits 16 through 19 are
90e4755a 1187 handled by the PSR_xxx defines above. */
b99bd4ef 1188
f2b7cb0a 1189 /* ARM 7M long multiplies. */
90e4755a
RE
1190 {"smull", 0xe0c00090, 5, ARM_EXT_V3M, do_mull},
1191 {"smulls", 0xe0d00090, 5, ARM_EXT_V3M, do_mull},
1192 {"umull", 0xe0800090, 5, ARM_EXT_V3M, do_mull},
1193 {"umulls", 0xe0900090, 5, ARM_EXT_V3M, do_mull},
1194 {"smlal", 0xe0e00090, 5, ARM_EXT_V3M, do_mull},
1195 {"smlals", 0xe0f00090, 5, ARM_EXT_V3M, do_mull},
1196 {"umlal", 0xe0a00090, 5, ARM_EXT_V3M, do_mull},
1197 {"umlals", 0xe0b00090, 5, ARM_EXT_V3M, do_mull},
1198
1199 /* ARM Architecture 4. */
1200 {"ldrh", 0xe01000b0, 3, ARM_EXT_V4, do_ldstv4},
1201 {"ldrsh", 0xe01000f0, 3, ARM_EXT_V4, do_ldstv4},
1202 {"ldrsb", 0xe01000d0, 3, ARM_EXT_V4, do_ldstv4},
1203 {"strh", 0xe00000b0, 3, ARM_EXT_V4, do_ldstv4},
b99bd4ef 1204
c9b604bd 1205 /* ARM Architecture 4T. */
cc8a6dd0 1206 /* Note: bx (and blx) are required on V5, even if the processor does
90e4755a
RE
1207 not support Thumb. */
1208 {"bx", 0xe12fff10, 2, ARM_EXT_V4T | ARM_EXT_V5, do_bx},
1209
ea6ef066 1210 /* ARM Architecture 5T. */
90e4755a
RE
1211 /* Note: blx has 2 variants, so the .value is set dynamically.
1212 Only one of the variants has conditional execution. */
1213 {"blx", 0xe0000000, 3, ARM_EXT_V5, do_blx},
1214 {"clz", 0xe16f0f10, 3, ARM_EXT_V5, do_clz},
1215 {"bkpt", 0xe1200070, 0, ARM_EXT_V5, do_bkpt},
1216 {"ldc2", 0xfc100000, 0, ARM_EXT_V5, do_lstc2},
1217 {"ldc2l", 0xfc500000, 0, ARM_EXT_V5, do_lstc2},
1218 {"stc2", 0xfc000000, 0, ARM_EXT_V5, do_lstc2},
1219 {"stc2l", 0xfc400000, 0, ARM_EXT_V5, do_lstc2},
1220 {"cdp2", 0xfe000000, 0, ARM_EXT_V5, do_cdp2},
1221 {"mcr2", 0xfe000010, 0, ARM_EXT_V5, do_co_reg2},
1222 {"mrc2", 0xfe100010, 0, ARM_EXT_V5, do_co_reg2},
1223
ea6ef066 1224 /* ARM Architecture 5TExP. */
90e4755a
RE
1225 {"smlabb", 0xe1000080, 6, ARM_EXT_V5ExP, do_smla},
1226 {"smlatb", 0xe10000a0, 6, ARM_EXT_V5ExP, do_smla},
1227 {"smlabt", 0xe10000c0, 6, ARM_EXT_V5ExP, do_smla},
1228 {"smlatt", 0xe10000e0, 6, ARM_EXT_V5ExP, do_smla},
1229
1230 {"smlawb", 0xe1200080, 6, ARM_EXT_V5ExP, do_smla},
1231 {"smlawt", 0xe12000c0, 6, ARM_EXT_V5ExP, do_smla},
1232
1233 {"smlalbb", 0xe1400080, 7, ARM_EXT_V5ExP, do_smlal},
1234 {"smlaltb", 0xe14000a0, 7, ARM_EXT_V5ExP, do_smlal},
1235 {"smlalbt", 0xe14000c0, 7, ARM_EXT_V5ExP, do_smlal},
1236 {"smlaltt", 0xe14000e0, 7, ARM_EXT_V5ExP, do_smlal},
1237
1238 {"smulbb", 0xe1600080, 6, ARM_EXT_V5ExP, do_smul},
1239 {"smultb", 0xe16000a0, 6, ARM_EXT_V5ExP, do_smul},
1240 {"smulbt", 0xe16000c0, 6, ARM_EXT_V5ExP, do_smul},
1241 {"smultt", 0xe16000e0, 6, ARM_EXT_V5ExP, do_smul},
1242
1243 {"smulwb", 0xe12000a0, 6, ARM_EXT_V5ExP, do_smul},
1244 {"smulwt", 0xe12000e0, 6, ARM_EXT_V5ExP, do_smul},
1245
1246 {"qadd", 0xe1000050, 4, ARM_EXT_V5ExP, do_qadd},
1247 {"qdadd", 0xe1400050, 5, ARM_EXT_V5ExP, do_qadd},
1248 {"qsub", 0xe1200050, 4, ARM_EXT_V5ExP, do_qadd},
1249 {"qdsub", 0xe1600050, 5, ARM_EXT_V5ExP, do_qadd},
c9b604bd 1250
ea6ef066 1251 /* ARM Architecture 5TE. */
90e4755a
RE
1252 {"pld", 0xf450f000, 0, ARM_EXT_V5E, do_pld},
1253 {"ldrd", 0xe00000d0, 3, ARM_EXT_V5E, do_ldrd},
1254 {"strd", 0xe00000f0, 3, ARM_EXT_V5E, do_ldrd},
1255
1256 {"mcrr", 0xec400000, 4, ARM_EXT_V5E, do_co_reg2c},
1257 {"mrrc", 0xec500000, 4, ARM_EXT_V5E, do_co_reg2c},
404ff6b5 1258
ea6ef066
RE
1259 /* ARM Architecture 5TEJ. */
1260 {"bxj", 0xe12fff20, 3, ARM_EXT_V5J, do_bxj},
1261
09d92015
MM
1262 /* ARM V6. */
1263 { "cps", 0xf1020000, 0, ARM_EXT_V6, do_cps},
1264 { "cpsie", 0xf1080000, 0, ARM_EXT_V6, do_cpsi},
1265 { "cpsid", 0xf10C0000, 0, ARM_EXT_V6, do_cpsi},
1266 { "ldrex", 0xe1900f9f, 5, ARM_EXT_V6, do_ldrex},
1267 { "mcrr2", 0xfc400000, 0, ARM_EXT_V6, do_co_reg2c},
1268 { "mrrc2", 0xfc500000, 0, ARM_EXT_V6, do_co_reg2c},
1269 { "pkhbt", 0xe6800010, 5, ARM_EXT_V6, do_pkhbt},
1270 { "pkhtb", 0xe6800050, 5, ARM_EXT_V6, do_pkhtb},
1271 { "qadd16", 0xe6200f10, 6, ARM_EXT_V6, do_qadd16},
1272 { "qadd8", 0xe6200f90, 5, ARM_EXT_V6, do_qadd16},
1273 { "qaddsubx", 0xe6200f30, 8, ARM_EXT_V6, do_qadd16},
1274 { "qsub16", 0xe6200f70, 6, ARM_EXT_V6, do_qadd16},
1275 { "qsub8", 0xe6200ff0, 5, ARM_EXT_V6, do_qadd16},
1276 { "qsubaddx", 0xe6200f50, 8, ARM_EXT_V6, do_qadd16},
1277 { "sadd16", 0xe6100f10, 6, ARM_EXT_V6, do_qadd16},
1278 { "sadd8", 0xe6100f90, 5, ARM_EXT_V6, do_qadd16},
1279 { "saddsubx", 0xe6100f30, 8, ARM_EXT_V6, do_qadd16},
1280 { "shadd16", 0xe6300f10, 7, ARM_EXT_V6, do_qadd16},
1281 { "shadd8", 0xe6300f90, 6, ARM_EXT_V6, do_qadd16},
1282 { "shaddsubx", 0xe6300f30, 9, ARM_EXT_V6, do_qadd16},
1283 { "shsub16", 0xe6300f70, 7, ARM_EXT_V6, do_qadd16},
1284 { "shsub8", 0xe6300ff0, 6, ARM_EXT_V6, do_qadd16},
1285 { "shsubaddx", 0xe6300f50, 9, ARM_EXT_V6, do_qadd16},
1286 { "ssub16", 0xe6100f70, 6, ARM_EXT_V6, do_qadd16},
1287 { "ssub8", 0xe6100ff0, 5, ARM_EXT_V6, do_qadd16},
1288 { "ssubaddx", 0xe6100f50, 8, ARM_EXT_V6, do_qadd16},
1289 { "uadd16", 0xe6500f10, 6, ARM_EXT_V6, do_qadd16},
1290 { "uadd8", 0xe6500f90, 5, ARM_EXT_V6, do_qadd16},
1291 { "uaddsubx", 0xe6500f30, 8, ARM_EXT_V6, do_qadd16},
1292 { "uhadd16", 0xe6700f10, 7, ARM_EXT_V6, do_qadd16},
1293 { "uhadd8", 0xe6700f90, 6, ARM_EXT_V6, do_qadd16},
1294 { "uhaddsubx", 0xe6700f30, 9, ARM_EXT_V6, do_qadd16},
1295 { "uhsub16", 0xe6700f70, 7, ARM_EXT_V6, do_qadd16},
1296 { "uhsub8", 0xe6700ff0, 6, ARM_EXT_V6, do_qadd16},
1297 { "uhsubaddx", 0xe6700f50, 9, ARM_EXT_V6, do_qadd16},
1298 { "uqadd16", 0xe6600f10, 7, ARM_EXT_V6, do_qadd16},
1299 { "uqadd8", 0xe6600f90, 6, ARM_EXT_V6, do_qadd16},
1300 { "uqaddsubx", 0xe6600f30, 9, ARM_EXT_V6, do_qadd16},
1301 { "uqsub16", 0xe6600f70, 7, ARM_EXT_V6, do_qadd16},
1302 { "uqsub8", 0xe6600ff0, 6, ARM_EXT_V6, do_qadd16},
1303 { "uqsubaddx", 0xe6600f50, 9, ARM_EXT_V6, do_qadd16},
1304 { "usub16", 0xe6500f70, 6, ARM_EXT_V6, do_qadd16},
1305 { "usub8", 0xe6500ff0, 5, ARM_EXT_V6, do_qadd16},
1306 { "usubaddx", 0xe6500f50, 8, ARM_EXT_V6, do_qadd16},
1307 { "rev", 0xe6bf0f30, 3, ARM_EXT_V6, do_rev},
1308 { "rev16", 0xe6bf0fb0, 5, ARM_EXT_V6, do_rev},
1309 { "revsh", 0xe6ff0fb0, 5, ARM_EXT_V6, do_rev},
1310 { "rfeia", 0xf8900a00, 0, ARM_EXT_V6, do_rfe},
1311 { "rfeib", 0xf9900a00, 0, ARM_EXT_V6, do_rfe},
1312 { "rfeda", 0xf8100a00, 0, ARM_EXT_V6, do_rfe},
1313 { "rfedb", 0xf9100a00, 0, ARM_EXT_V6, do_rfe},
1314 { "rfefd", 0xf8900a00, 0, ARM_EXT_V6, do_rfe},
1315 { "rfefa", 0xf9900a00, 0, ARM_EXT_V6, do_rfe},
1316 { "rfeea", 0xf8100a00, 0, ARM_EXT_V6, do_rfe},
1317 { "rfeed", 0xf9100a00, 0, ARM_EXT_V6, do_rfe},
1318 { "sxtah", 0xe6b00070, 5, ARM_EXT_V6, do_sxtah},
1319 { "sxtab16", 0xe6800070, 7, ARM_EXT_V6, do_sxtah},
1320 { "sxtab", 0xe6a00070, 5, ARM_EXT_V6, do_sxtah},
1321 { "sxth", 0xe6bf0070, 4, ARM_EXT_V6, do_sxth},
1322 { "sxtb16", 0xe68f0070, 6, ARM_EXT_V6, do_sxth},
1323 { "sxtb", 0xe6af0070, 4, ARM_EXT_V6, do_sxth},
1324 { "uxtah", 0xe6f00070, 5, ARM_EXT_V6, do_sxtah},
1325 { "uxtab16", 0xe6c00070, 7, ARM_EXT_V6, do_sxtah},
1326 { "uxtab", 0xe6e00070, 5, ARM_EXT_V6, do_sxtah},
1327 { "uxth", 0xe6ff0070, 4, ARM_EXT_V6, do_sxth},
1328 { "uxtb16", 0xe6cf0070, 6, ARM_EXT_V6, do_sxth},
1329 { "uxtb", 0xe6ef0070, 4, ARM_EXT_V6, do_sxth},
1330 { "sel", 0xe68000b0, 3, ARM_EXT_V6, do_qadd16},
1331 { "setend", 0xf1010000, 0, ARM_EXT_V6, do_setend},
1332 { "smlad", 0xe7000010, 5, ARM_EXT_V6, do_smlad},
1333 { "smladx", 0xe7000030, 6, ARM_EXT_V6, do_smlad},
1334 { "smlald", 0xe7400010, 6, ARM_EXT_V6, do_smlald},
1335 { "smlaldx", 0xe7400030, 7, ARM_EXT_V6, do_smlald},
1336 { "smlsd", 0xe7000050, 5, ARM_EXT_V6, do_smlad},
1337 { "smlsdx", 0xe7000070, 6, ARM_EXT_V6, do_smlad},
1338 { "smlsld", 0xe7400050, 6, ARM_EXT_V6, do_smlald},
1339 { "smlsldx", 0xe7400070, 7, ARM_EXT_V6, do_smlald},
1340 { "smmla", 0xe7500010, 5, ARM_EXT_V6, do_smlad},
1341 { "smmlar", 0xe7500030, 6, ARM_EXT_V6, do_smlad},
1342 { "smmls", 0xe75000d0, 5, ARM_EXT_V6, do_smlad},
1343 { "smmlsr", 0xe75000f0, 6, ARM_EXT_V6, do_smlad},
1344 { "smmul", 0xe750f010, 5, ARM_EXT_V6, do_smmul},
1345 { "smmulr", 0xe750f030, 6, ARM_EXT_V6, do_smmul},
1346 { "smuad", 0xe700f010, 5, ARM_EXT_V6, do_smmul},
1347 { "smuadx", 0xe700f030, 6, ARM_EXT_V6, do_smmul},
1348 { "smusd", 0xe700f050, 5, ARM_EXT_V6, do_smmul},
1349 { "smusdx", 0xe700f070, 6, ARM_EXT_V6, do_smmul},
1350 { "srsia", 0xf8cd0500, 0, ARM_EXT_V6, do_srs},
1351 { "srsib", 0xf9cd0500, 0, ARM_EXT_V6, do_srs},
1352 { "srsda", 0xf84d0500, 0, ARM_EXT_V6, do_srs},
1353 { "srsdb", 0xf94d0500, 0, ARM_EXT_V6, do_srs},
1354 { "ssat", 0xe6a00010, 4, ARM_EXT_V6, do_ssat},
1355 { "ssat16", 0xe6a00f30, 6, ARM_EXT_V6, do_ssat16},
1356 { "strex", 0xe1800f90, 5, ARM_EXT_V6, do_strex},
1357 { "umaal", 0xe0400090, 5, ARM_EXT_V6, do_umaal},
1358 { "usad8", 0xe780f010, 5, ARM_EXT_V6, do_smmul},
1359 { "usada8", 0xe7800010, 6, ARM_EXT_V6, do_smlad},
1360 { "usat", 0xe6e00010, 4, ARM_EXT_V6, do_usat},
1361 { "usat16", 0xe6e00f30, 6, ARM_EXT_V6, do_usat16},
1362
c9b604bd 1363 /* Core FPA instruction set (V1). */
90e4755a
RE
1364 {"wfs", 0xee200110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
1365 {"rfs", 0xee300110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
1366 {"wfc", 0xee400110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
1367 {"rfc", 0xee500110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
1368
1369 {"ldfs", 0xec100100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1370 {"ldfd", 0xec108100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1371 {"ldfe", 0xec500100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1372 {"ldfp", 0xec508100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1373
1374 {"stfs", 0xec000100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1375 {"stfd", 0xec008100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1376 {"stfe", 0xec400100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1377 {"stfp", 0xec408100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1378
1379 {"mvfs", 0xee008100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1380 {"mvfsp", 0xee008120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1381 {"mvfsm", 0xee008140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1382 {"mvfsz", 0xee008160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1383 {"mvfd", 0xee008180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1384 {"mvfdp", 0xee0081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1385 {"mvfdm", 0xee0081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1386 {"mvfdz", 0xee0081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1387 {"mvfe", 0xee088100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1388 {"mvfep", 0xee088120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1389 {"mvfem", 0xee088140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1390 {"mvfez", 0xee088160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1391
1392 {"mnfs", 0xee108100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1393 {"mnfsp", 0xee108120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1394 {"mnfsm", 0xee108140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1395 {"mnfsz", 0xee108160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1396 {"mnfd", 0xee108180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1397 {"mnfdp", 0xee1081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1398 {"mnfdm", 0xee1081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1399 {"mnfdz", 0xee1081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1400 {"mnfe", 0xee188100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1401 {"mnfep", 0xee188120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1402 {"mnfem", 0xee188140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1403 {"mnfez", 0xee188160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1404
1405 {"abss", 0xee208100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1406 {"abssp", 0xee208120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1407 {"abssm", 0xee208140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1408 {"abssz", 0xee208160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1409 {"absd", 0xee208180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1410 {"absdp", 0xee2081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1411 {"absdm", 0xee2081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1412 {"absdz", 0xee2081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1413 {"abse", 0xee288100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1414 {"absep", 0xee288120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1415 {"absem", 0xee288140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1416 {"absez", 0xee288160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1417
1418 {"rnds", 0xee308100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1419 {"rndsp", 0xee308120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1420 {"rndsm", 0xee308140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1421 {"rndsz", 0xee308160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1422 {"rndd", 0xee308180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1423 {"rnddp", 0xee3081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1424 {"rnddm", 0xee3081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1425 {"rnddz", 0xee3081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1426 {"rnde", 0xee388100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1427 {"rndep", 0xee388120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1428 {"rndem", 0xee388140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1429 {"rndez", 0xee388160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1430
1431 {"sqts", 0xee408100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1432 {"sqtsp", 0xee408120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1433 {"sqtsm", 0xee408140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1434 {"sqtsz", 0xee408160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1435 {"sqtd", 0xee408180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1436 {"sqtdp", 0xee4081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1437 {"sqtdm", 0xee4081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1438 {"sqtdz", 0xee4081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1439 {"sqte", 0xee488100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1440 {"sqtep", 0xee488120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1441 {"sqtem", 0xee488140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1442 {"sqtez", 0xee488160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1443
1444 {"logs", 0xee508100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1445 {"logsp", 0xee508120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1446 {"logsm", 0xee508140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1447 {"logsz", 0xee508160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1448 {"logd", 0xee508180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1449 {"logdp", 0xee5081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1450 {"logdm", 0xee5081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1451 {"logdz", 0xee5081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1452 {"loge", 0xee588100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1453 {"logep", 0xee588120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1454 {"logem", 0xee588140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1455 {"logez", 0xee588160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1456
1457 {"lgns", 0xee608100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1458 {"lgnsp", 0xee608120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1459 {"lgnsm", 0xee608140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1460 {"lgnsz", 0xee608160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1461 {"lgnd", 0xee608180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1462 {"lgndp", 0xee6081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1463 {"lgndm", 0xee6081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1464 {"lgndz", 0xee6081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1465 {"lgne", 0xee688100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1466 {"lgnep", 0xee688120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1467 {"lgnem", 0xee688140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1468 {"lgnez", 0xee688160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1469
1470 {"exps", 0xee708100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1471 {"expsp", 0xee708120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1472 {"expsm", 0xee708140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1473 {"expsz", 0xee708160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1474 {"expd", 0xee708180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1475 {"expdp", 0xee7081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1476 {"expdm", 0xee7081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1477 {"expdz", 0xee7081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1478 {"expe", 0xee788100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1479 {"expep", 0xee788120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1480 {"expem", 0xee788140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1481 {"expdz", 0xee788160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1482
1483 {"sins", 0xee808100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1484 {"sinsp", 0xee808120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1485 {"sinsm", 0xee808140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1486 {"sinsz", 0xee808160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1487 {"sind", 0xee808180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1488 {"sindp", 0xee8081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1489 {"sindm", 0xee8081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1490 {"sindz", 0xee8081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1491 {"sine", 0xee888100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1492 {"sinep", 0xee888120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1493 {"sinem", 0xee888140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1494 {"sinez", 0xee888160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1495
1496 {"coss", 0xee908100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1497 {"cossp", 0xee908120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1498 {"cossm", 0xee908140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1499 {"cossz", 0xee908160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1500 {"cosd", 0xee908180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1501 {"cosdp", 0xee9081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1502 {"cosdm", 0xee9081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1503 {"cosdz", 0xee9081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1504 {"cose", 0xee988100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1505 {"cosep", 0xee988120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1506 {"cosem", 0xee988140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1507 {"cosez", 0xee988160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1508
1509 {"tans", 0xeea08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1510 {"tansp", 0xeea08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1511 {"tansm", 0xeea08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1512 {"tansz", 0xeea08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1513 {"tand", 0xeea08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1514 {"tandp", 0xeea081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1515 {"tandm", 0xeea081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1516 {"tandz", 0xeea081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1517 {"tane", 0xeea88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1518 {"tanep", 0xeea88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1519 {"tanem", 0xeea88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1520 {"tanez", 0xeea88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1521
1522 {"asns", 0xeeb08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1523 {"asnsp", 0xeeb08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1524 {"asnsm", 0xeeb08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1525 {"asnsz", 0xeeb08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1526 {"asnd", 0xeeb08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1527 {"asndp", 0xeeb081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1528 {"asndm", 0xeeb081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1529 {"asndz", 0xeeb081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1530 {"asne", 0xeeb88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1531 {"asnep", 0xeeb88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1532 {"asnem", 0xeeb88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1533 {"asnez", 0xeeb88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1534
1535 {"acss", 0xeec08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1536 {"acssp", 0xeec08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1537 {"acssm", 0xeec08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1538 {"acssz", 0xeec08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1539 {"acsd", 0xeec08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1540 {"acsdp", 0xeec081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1541 {"acsdm", 0xeec081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1542 {"acsdz", 0xeec081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1543 {"acse", 0xeec88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1544 {"acsep", 0xeec88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1545 {"acsem", 0xeec88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1546 {"acsez", 0xeec88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1547
1548 {"atns", 0xeed08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1549 {"atnsp", 0xeed08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1550 {"atnsm", 0xeed08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1551 {"atnsz", 0xeed08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1552 {"atnd", 0xeed08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1553 {"atndp", 0xeed081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1554 {"atndm", 0xeed081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1555 {"atndz", 0xeed081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1556 {"atne", 0xeed88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1557 {"atnep", 0xeed88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1558 {"atnem", 0xeed88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1559 {"atnez", 0xeed88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1560
1561 {"urds", 0xeee08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1562 {"urdsp", 0xeee08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1563 {"urdsm", 0xeee08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1564 {"urdsz", 0xeee08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1565 {"urdd", 0xeee08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1566 {"urddp", 0xeee081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1567 {"urddm", 0xeee081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1568 {"urddz", 0xeee081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1569 {"urde", 0xeee88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1570 {"urdep", 0xeee88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1571 {"urdem", 0xeee88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1572 {"urdez", 0xeee88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1573
1574 {"nrms", 0xeef08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1575 {"nrmsp", 0xeef08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1576 {"nrmsm", 0xeef08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1577 {"nrmsz", 0xeef08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1578 {"nrmd", 0xeef08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1579 {"nrmdp", 0xeef081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1580 {"nrmdm", 0xeef081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1581 {"nrmdz", 0xeef081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1582 {"nrme", 0xeef88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1583 {"nrmep", 0xeef88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1584 {"nrmem", 0xeef88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1585 {"nrmez", 0xeef88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1586
1587 {"adfs", 0xee000100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1588 {"adfsp", 0xee000120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1589 {"adfsm", 0xee000140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1590 {"adfsz", 0xee000160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1591 {"adfd", 0xee000180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1592 {"adfdp", 0xee0001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1593 {"adfdm", 0xee0001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1594 {"adfdz", 0xee0001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1595 {"adfe", 0xee080100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1596 {"adfep", 0xee080120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1597 {"adfem", 0xee080140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1598 {"adfez", 0xee080160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1599
1600 {"sufs", 0xee200100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1601 {"sufsp", 0xee200120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1602 {"sufsm", 0xee200140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1603 {"sufsz", 0xee200160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1604 {"sufd", 0xee200180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1605 {"sufdp", 0xee2001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1606 {"sufdm", 0xee2001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1607 {"sufdz", 0xee2001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1608 {"sufe", 0xee280100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1609 {"sufep", 0xee280120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1610 {"sufem", 0xee280140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1611 {"sufez", 0xee280160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1612
1613 {"rsfs", 0xee300100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1614 {"rsfsp", 0xee300120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1615 {"rsfsm", 0xee300140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1616 {"rsfsz", 0xee300160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1617 {"rsfd", 0xee300180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1618 {"rsfdp", 0xee3001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1619 {"rsfdm", 0xee3001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1620 {"rsfdz", 0xee3001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1621 {"rsfe", 0xee380100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1622 {"rsfep", 0xee380120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1623 {"rsfem", 0xee380140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1624 {"rsfez", 0xee380160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1625
1626 {"mufs", 0xee100100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1627 {"mufsp", 0xee100120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1628 {"mufsm", 0xee100140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1629 {"mufsz", 0xee100160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1630 {"mufd", 0xee100180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1631 {"mufdp", 0xee1001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1632 {"mufdm", 0xee1001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1633 {"mufdz", 0xee1001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1634 {"mufe", 0xee180100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1635 {"mufep", 0xee180120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1636 {"mufem", 0xee180140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1637 {"mufez", 0xee180160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1638
1639 {"dvfs", 0xee400100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1640 {"dvfsp", 0xee400120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1641 {"dvfsm", 0xee400140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1642 {"dvfsz", 0xee400160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1643 {"dvfd", 0xee400180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1644 {"dvfdp", 0xee4001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1645 {"dvfdm", 0xee4001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1646 {"dvfdz", 0xee4001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1647 {"dvfe", 0xee480100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1648 {"dvfep", 0xee480120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1649 {"dvfem", 0xee480140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1650 {"dvfez", 0xee480160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1651
1652 {"rdfs", 0xee500100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1653 {"rdfsp", 0xee500120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1654 {"rdfsm", 0xee500140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1655 {"rdfsz", 0xee500160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1656 {"rdfd", 0xee500180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1657 {"rdfdp", 0xee5001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1658 {"rdfdm", 0xee5001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1659 {"rdfdz", 0xee5001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1660 {"rdfe", 0xee580100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1661 {"rdfep", 0xee580120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1662 {"rdfem", 0xee580140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1663 {"rdfez", 0xee580160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1664
1665 {"pows", 0xee600100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1666 {"powsp", 0xee600120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1667 {"powsm", 0xee600140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1668 {"powsz", 0xee600160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1669 {"powd", 0xee600180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1670 {"powdp", 0xee6001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1671 {"powdm", 0xee6001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1672 {"powdz", 0xee6001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1673 {"powe", 0xee680100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1674 {"powep", 0xee680120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1675 {"powem", 0xee680140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1676 {"powez", 0xee680160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1677
1678 {"rpws", 0xee700100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1679 {"rpwsp", 0xee700120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1680 {"rpwsm", 0xee700140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1681 {"rpwsz", 0xee700160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1682 {"rpwd", 0xee700180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1683 {"rpwdp", 0xee7001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1684 {"rpwdm", 0xee7001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1685 {"rpwdz", 0xee7001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1686 {"rpwe", 0xee780100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1687 {"rpwep", 0xee780120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1688 {"rpwem", 0xee780140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1689 {"rpwez", 0xee780160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1690
1691 {"rmfs", 0xee800100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1692 {"rmfsp", 0xee800120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1693 {"rmfsm", 0xee800140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1694 {"rmfsz", 0xee800160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1695 {"rmfd", 0xee800180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1696 {"rmfdp", 0xee8001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1697 {"rmfdm", 0xee8001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1698 {"rmfdz", 0xee8001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1699 {"rmfe", 0xee880100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1700 {"rmfep", 0xee880120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1701 {"rmfem", 0xee880140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1702 {"rmfez", 0xee880160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1703
1704 {"fmls", 0xee900100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1705 {"fmlsp", 0xee900120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1706 {"fmlsm", 0xee900140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1707 {"fmlsz", 0xee900160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1708 {"fmld", 0xee900180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1709 {"fmldp", 0xee9001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1710 {"fmldm", 0xee9001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1711 {"fmldz", 0xee9001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1712 {"fmle", 0xee980100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1713 {"fmlep", 0xee980120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1714 {"fmlem", 0xee980140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1715 {"fmlez", 0xee980160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1716
1717 {"fdvs", 0xeea00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1718 {"fdvsp", 0xeea00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1719 {"fdvsm", 0xeea00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1720 {"fdvsz", 0xeea00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1721 {"fdvd", 0xeea00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1722 {"fdvdp", 0xeea001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1723 {"fdvdm", 0xeea001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1724 {"fdvdz", 0xeea001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1725 {"fdve", 0xeea80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1726 {"fdvep", 0xeea80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1727 {"fdvem", 0xeea80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1728 {"fdvez", 0xeea80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1729
1730 {"frds", 0xeeb00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1731 {"frdsp", 0xeeb00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1732 {"frdsm", 0xeeb00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1733 {"frdsz", 0xeeb00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1734 {"frdd", 0xeeb00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1735 {"frddp", 0xeeb001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1736 {"frddm", 0xeeb001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1737 {"frddz", 0xeeb001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1738 {"frde", 0xeeb80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1739 {"frdep", 0xeeb80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1740 {"frdem", 0xeeb80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1741 {"frdez", 0xeeb80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1742
1743 {"pols", 0xeec00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1744 {"polsp", 0xeec00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1745 {"polsm", 0xeec00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1746 {"polsz", 0xeec00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1747 {"pold", 0xeec00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1748 {"poldp", 0xeec001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1749 {"poldm", 0xeec001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1750 {"poldz", 0xeec001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1751 {"pole", 0xeec80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1752 {"polep", 0xeec80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1753 {"polem", 0xeec80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1754 {"polez", 0xeec80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1755
1756 {"cmf", 0xee90f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
1757 {"cmfe", 0xeed0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
1758 {"cnf", 0xeeb0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
1759 {"cnfe", 0xeef0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
1760 /* The FPA10 data sheet suggests that the 'E' of cmfe/cnfe should
1761 not be an optional suffix, but part of the instruction. To be
1762 compatible, we accept either. */
1763 {"cmfe", 0xeed0f110, 4, FPU_FPA_EXT_V1, do_fpa_cmp},
1764 {"cnfe", 0xeef0f110, 4, FPU_FPA_EXT_V1, do_fpa_cmp},
1765
1766 {"flts", 0xee000110, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1767 {"fltsp", 0xee000130, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1768 {"fltsm", 0xee000150, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1769 {"fltsz", 0xee000170, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1770 {"fltd", 0xee000190, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1771 {"fltdp", 0xee0001b0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1772 {"fltdm", 0xee0001d0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1773 {"fltdz", 0xee0001f0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1774 {"flte", 0xee080110, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1775 {"fltep", 0xee080130, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1776 {"fltem", 0xee080150, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1777 {"fltez", 0xee080170, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1778
1779 /* The implementation of the FIX instruction is broken on some
1780 assemblers, in that it accepts a precision specifier as well as a
1781 rounding specifier, despite the fact that this is meaningless.
1782 To be more compatible, we accept it as well, though of course it
1783 does not set any bits. */
1784 {"fix", 0xee100110, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1785 {"fixp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1786 {"fixm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1787 {"fixz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1788 {"fixsp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1789 {"fixsm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1790 {"fixsz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1791 {"fixdp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1792 {"fixdm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1793 {"fixdz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1794 {"fixep", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1795 {"fixem", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1796 {"fixez", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
c9b604bd
RE
1797
1798 /* Instructions that were new with the real FPA, call them V2. */
90e4755a
RE
1799 {"lfm", 0xec100200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1800 {"lfmfd", 0xec900200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1801 {"lfmea", 0xed100200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1802 {"sfm", 0xec000200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1803 {"sfmfd", 0xed000200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1804 {"sfmea", 0xec800200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
c9b604bd 1805
bfae80f2
RE
1806 /* VFP V1xD (single precision). */
1807 /* Moves and type conversions. */
1808 {"fcpys", 0xeeb00a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1809 {"fmrs", 0xee100a10, 4, FPU_VFP_EXT_V1xD, do_vfp_reg_from_sp},
1810 {"fmsr", 0xee000a10, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_from_reg},
1811 {"fmstat", 0xeef1fa10, 6, FPU_VFP_EXT_V1xD, do_empty},
1812 {"fsitos", 0xeeb80ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1813 {"fuitos", 0xeeb80a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1814 {"ftosis", 0xeebd0a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1815 {"ftosizs", 0xeebd0ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1816 {"ftouis", 0xeebc0a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1817 {"ftouizs", 0xeebc0ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1818 {"fmrx", 0xeef00a10, 4, FPU_VFP_EXT_V1xD, do_vfp_reg_from_ctrl},
1819 {"fmxr", 0xeee00a10, 4, FPU_VFP_EXT_V1xD, do_vfp_ctrl_from_reg},
1820
1821 /* Memory operations. */
1822 {"flds", 0xed100a00, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_ldst},
1823 {"fsts", 0xed000a00, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_ldst},
1824 {"fldmias", 0xec900a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
1825 {"fldmfds", 0xec900a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
1826 {"fldmdbs", 0xed300a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
1827 {"fldmeas", 0xed300a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
1828 {"fldmiax", 0xec900b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
1829 {"fldmfdx", 0xec900b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
1830 {"fldmdbx", 0xed300b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
1831 {"fldmeax", 0xed300b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
1832 {"fstmias", 0xec800a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
1833 {"fstmeas", 0xec800a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
1834 {"fstmdbs", 0xed200a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
1835 {"fstmfds", 0xed200a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
1836 {"fstmiax", 0xec800b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
1837 {"fstmeax", 0xec800b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
1838 {"fstmdbx", 0xed200b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
1839 {"fstmfdx", 0xed200b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
1840
1841 /* Monadic operations. */
1842 {"fabss", 0xeeb00ac0, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1843 {"fnegs", 0xeeb10a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1844 {"fsqrts", 0xeeb10ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1845
1846 /* Dyadic operations. */
1847 {"fadds", 0xee300a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1848 {"fsubs", 0xee300a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1849 {"fmuls", 0xee200a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1850 {"fdivs", 0xee800a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1851 {"fmacs", 0xee000a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1852 {"fmscs", 0xee100a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1853 {"fnmuls", 0xee200a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1854 {"fnmacs", 0xee000a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1855 {"fnmscs", 0xee100a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1856
1857 /* Comparisons. */
1858 {"fcmps", 0xeeb40a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1859 {"fcmpzs", 0xeeb50a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_compare_z},
1860 {"fcmpes", 0xeeb40ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1861 {"fcmpezs", 0xeeb50ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_compare_z},
1862
1863 /* VFP V1 (Double precision). */
1864 /* Moves and type conversions. */
1865 {"fcpyd", 0xeeb00b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1866 {"fcvtds", 0xeeb70ac0, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
1867 {"fcvtsd", 0xeeb70bc0, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
1868 {"fmdhr", 0xee200b10, 5, FPU_VFP_EXT_V1, do_vfp_dp_from_reg},
1869 {"fmdlr", 0xee000b10, 5, FPU_VFP_EXT_V1, do_vfp_dp_from_reg},
1870 {"fmrdh", 0xee300b10, 5, FPU_VFP_EXT_V1, do_vfp_reg_from_dp},
1871 {"fmrdl", 0xee100b10, 5, FPU_VFP_EXT_V1, do_vfp_reg_from_dp},
1872 {"fsitod", 0xeeb80bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
1873 {"fuitod", 0xeeb80b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
1874 {"ftosid", 0xeebd0b40, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
1875 {"ftosizd", 0xeebd0bc0, 7, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
1876 {"ftouid", 0xeebc0b40, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
1877 {"ftouizd", 0xeebc0bc0, 7, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
1878
1879 /* Memory operations. */
1880 {"fldd", 0xed100b00, 4, FPU_VFP_EXT_V1, do_vfp_dp_ldst},
1881 {"fstd", 0xed000b00, 4, FPU_VFP_EXT_V1, do_vfp_dp_ldst},
1882 {"fldmiad", 0xec900b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
1883 {"fldmfdd", 0xec900b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
1884 {"fldmdbd", 0xed300b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
1885 {"fldmead", 0xed300b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
1886 {"fstmiad", 0xec800b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
1887 {"fstmead", 0xec800b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
1888 {"fstmdbd", 0xed200b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
1889 {"fstmfdd", 0xed200b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
1890
1891 /* Monadic operations. */
1892 {"fabsd", 0xeeb00bc0, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1893 {"fnegd", 0xeeb10b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1894 {"fsqrtd", 0xeeb10bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1895
1896 /* Dyadic operations. */
1897 {"faddd", 0xee300b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1898 {"fsubd", 0xee300b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1899 {"fmuld", 0xee200b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1900 {"fdivd", 0xee800b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1901 {"fmacd", 0xee000b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1902 {"fmscd", 0xee100b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1903 {"fnmuld", 0xee200b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1904 {"fnmacd", 0xee000b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1905 {"fnmscd", 0xee100b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1906
1907 /* Comparisons. */
1908 {"fcmpd", 0xeeb40b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1909 {"fcmpzd", 0xeeb50b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_compare_z},
1910 {"fcmped", 0xeeb40bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1911 {"fcmpezd", 0xeeb50bc0, 7, FPU_VFP_EXT_V1, do_vfp_dp_compare_z},
1912
1913 /* VFP V2. */
e45d0630
PB
1914 {"fmsrr", 0xec400a10, 5, FPU_VFP_EXT_V2, do_vfp_sp2_from_reg2},
1915 {"fmrrs", 0xec500a10, 5, FPU_VFP_EXT_V2, do_vfp_reg2_from_sp2},
bfae80f2
RE
1916 {"fmdrr", 0xec400b10, 5, FPU_VFP_EXT_V2, do_vfp_dp_from_reg2},
1917 {"fmrrd", 0xec500b10, 5, FPU_VFP_EXT_V2, do_vfp_reg2_from_dp},
1918
c9b604bd 1919 /* Intel XScale extensions to ARM V5 ISA. (All use CP0). */
63e63b07
RE
1920 {"mia", 0xee200010, 3, ARM_CEXT_XSCALE, do_xsc_mia},
1921 {"miaph", 0xee280010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
1922 {"miabb", 0xee2c0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
1923 {"miabt", 0xee2d0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
1924 {"miatb", 0xee2e0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
1925 {"miatt", 0xee2f0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
1926 {"mar", 0xec400000, 3, ARM_CEXT_XSCALE, do_xsc_mar},
1927 {"mra", 0xec500000, 3, ARM_CEXT_XSCALE, do_xsc_mra},
1928
5a6c6817
NC
1929 /* Intel Wireless MMX technology instructions. */
1930 {"tandcb", 0xee130130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
1931 {"tandch", 0xee530130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
1932 {"tandcw", 0xee930130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
1933 {"tbcstb", 0xee400010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
1934 {"tbcsth", 0xee400050, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
1935 {"tbcstw", 0xee400090, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
1936 {"textrcb", 0xee130170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
1937 {"textrch", 0xee530170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
1938 {"textrcw", 0xee930170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
1939 {"textrmub", 0xee100070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
1940 {"textrmuh", 0xee500070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
1941 {"textrmuw", 0xee900070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
1942 {"textrmsb", 0xee100078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
1943 {"textrmsh", 0xee500078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
1944 {"textrmsw", 0xee900078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
1945 {"tinsrb", 0xee600010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
1946 {"tinsrh", 0xee600050, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
1947 {"tinsrw", 0xee600090, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
1948 {"tmcr", 0xee000110, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmcr},
1949 {"tmcrr", 0xec400000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_tmcrr},
1950 {"tmia", 0xee200010, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
1951 {"tmiaph", 0xee280010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
1952 {"tmiabb", 0xee2c0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
1953 {"tmiabt", 0xee2d0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
1954 {"tmiatb", 0xee2e0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
1955 {"tmiatt", 0xee2f0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
1956 {"tmovmskb", 0xee100030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
1957 {"tmovmskh", 0xee500030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
1958 {"tmovmskw", 0xee900030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
1959 {"tmrc", 0xee100110, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmrc},
1960 {"tmrrc", 0xec500000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_tmrrc},
1961 {"torcb", 0xee130150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
1962 {"torch", 0xee530150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
1963 {"torcw", 0xee930150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
1964 {"waccb", 0xee0001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
1965 {"wacch", 0xee4001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
1966 {"waccw", 0xee8001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
1967 {"waddbss", 0xee300180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1968 {"waddb", 0xee000180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1969 {"waddbus", 0xee100180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1970 {"waddhss", 0xee700180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1971 {"waddh", 0xee400180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1972 {"waddhus", 0xee500180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1973 {"waddwss", 0xeeb00180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1974 {"waddw", 0xee800180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1975 {"waddwus", 0xee900180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1976 {"waligni", 0xee000020, 7, ARM_CEXT_IWMMXT, do_iwmmxt_waligni},
1977 {"walignr0", 0xee800020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1978 {"walignr1", 0xee900020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1979 {"walignr2", 0xeea00020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1980 {"walignr3", 0xeeb00020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1981 {"wand", 0xee200000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1982 {"wandn", 0xee300000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1983 {"wavg2b", 0xee800000, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1984 {"wavg2br", 0xee900000, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1985 {"wavg2h", 0xeec00000, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1986 {"wavg2hr", 0xeed00000, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1987 {"wcmpeqb", 0xee000060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1988 {"wcmpeqh", 0xee400060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1989 {"wcmpeqw", 0xee800060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1990 {"wcmpgtub", 0xee100060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1991 {"wcmpgtuh", 0xee500060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1992 {"wcmpgtuw", 0xee900060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1993 {"wcmpgtsb", 0xee300060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1994 {"wcmpgtsh", 0xee700060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1995 {"wcmpgtsw", 0xeeb00060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1996 {"wldrb", 0xec100000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
1997 {"wldrh", 0xec100100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
1998 {"wldrw", 0xec100200, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
1999 {"wldrd", 0xec100300, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
2000 {"wmacs", 0xee600100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2001 {"wmacsz", 0xee700100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2002 {"wmacu", 0xee400100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2003 {"wmacuz", 0xee500100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2004 {"wmadds", 0xeea00100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2005 {"wmaddu", 0xee800100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2006 {"wmaxsb", 0xee200160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2007 {"wmaxsh", 0xee600160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2008 {"wmaxsw", 0xeea00160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2009 {"wmaxub", 0xee000160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2010 {"wmaxuh", 0xee400160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2011 {"wmaxuw", 0xee800160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2012 {"wminsb", 0xee300160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2013 {"wminsh", 0xee700160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2014 {"wminsw", 0xeeb00160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2015 {"wminub", 0xee100160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2016 {"wminuh", 0xee500160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2017 {"wminuw", 0xee900160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2018 {"wmov", 0xee000000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wmov},
2019 {"wmulsm", 0xee300100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2020 {"wmulsl", 0xee200100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2021 {"wmulum", 0xee100100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2022 {"wmulul", 0xee000100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2023 {"wor", 0xee000000, 3, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2024 {"wpackhss", 0xee700080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2025 {"wpackhus", 0xee500080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2026 {"wpackwss", 0xeeb00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2027 {"wpackwus", 0xee900080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2028 {"wpackdss", 0xeef00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2029 {"wpackdus", 0xeed00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2030 {"wrorh", 0xee700040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2031 {"wrorhg", 0xee700148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2032 {"wrorw", 0xeeb00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2033 {"wrorwg", 0xeeb00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2034 {"wrord", 0xeef00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2035 {"wrordg", 0xeef00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2036 {"wsadb", 0xee000120, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2037 {"wsadbz", 0xee100120, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2038 {"wsadh", 0xee400120, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2039 {"wsadhz", 0xee500120, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2040 {"wshufh", 0xee0001e0, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wshufh},
2041 {"wsllh", 0xee500040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2042 {"wsllhg", 0xee500148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2043 {"wsllw", 0xee900040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2044 {"wsllwg", 0xee900148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2045 {"wslld", 0xeed00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2046 {"wslldg", 0xeed00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2047 {"wsrah", 0xee400040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2048 {"wsrahg", 0xee400148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2049 {"wsraw", 0xee800040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2050 {"wsrawg", 0xee800148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2051 {"wsrad", 0xeec00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2052 {"wsradg", 0xeec00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2053 {"wsrlh", 0xee600040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2054 {"wsrlhg", 0xee600148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2055 {"wsrlw", 0xeea00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2056 {"wsrlwg", 0xeea00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2057 {"wsrld", 0xeee00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2058 {"wsrldg", 0xeee00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2059 {"wstrb", 0xec000000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
2060 {"wstrh", 0xec000100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
2061 {"wstrw", 0xec000200, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
2062 {"wstrd", 0xec000300, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
2063 {"wsubbss", 0xee3001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2064 {"wsubb", 0xee0001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2065 {"wsubbus", 0xee1001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2066 {"wsubhss", 0xee7001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2067 {"wsubh", 0xee4001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2068 {"wsubhus", 0xee5001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2069 {"wsubwss", 0xeeb001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2070 {"wsubw", 0xee8001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2071 {"wsubwus", 0xee9001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2072 {"wunpckehub", 0xee0000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2073 {"wunpckehuh", 0xee4000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2074 {"wunpckehuw", 0xee8000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2075 {"wunpckehsb", 0xee2000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2076 {"wunpckehsh", 0xee6000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2077 {"wunpckehsw", 0xeea000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2078 {"wunpckihb", 0xee1000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2079 {"wunpckihh", 0xee5000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2080 {"wunpckihw", 0xee9000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2081 {"wunpckelub", 0xee0000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2082 {"wunpckeluh", 0xee4000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2083 {"wunpckeluw", 0xee8000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2084 {"wunpckelsb", 0xee2000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2085 {"wunpckelsh", 0xee6000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2086 {"wunpckelsw", 0xeea000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2087 {"wunpckilb", 0xee1000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2088 {"wunpckilh", 0xee5000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2089 {"wunpckilw", 0xee9000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2090 {"wxor", 0xee100000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2091 {"wzero", 0xee300000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wzero},
2092
63e63b07
RE
2093 /* Cirrus Maverick instructions. */
2094 {"cfldrs", 0xec100400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_1},
2095 {"cfldrd", 0xec500400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_2},
2096 {"cfldr32", 0xec100500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_3},
2097 {"cfldr64", 0xec500500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_4},
2098 {"cfstrs", 0xec000400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_1},
2099 {"cfstrd", 0xec400400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_2},
2100 {"cfstr32", 0xec000500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_3},
2101 {"cfstr64", 0xec400500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_4},
2102 {"cfmvsr", 0xee000450, 6, ARM_CEXT_MAVERICK, do_mav_binops_2a},
2103 {"cfmvrs", 0xee100450, 6, ARM_CEXT_MAVERICK, do_mav_binops_1a},
2104 {"cfmvdlr", 0xee000410, 7, ARM_CEXT_MAVERICK, do_mav_binops_2b},
2105 {"cfmvrdl", 0xee100410, 7, ARM_CEXT_MAVERICK, do_mav_binops_1b},
2106 {"cfmvdhr", 0xee000430, 7, ARM_CEXT_MAVERICK, do_mav_binops_2b},
2107 {"cfmvrdh", 0xee100430, 7, ARM_CEXT_MAVERICK, do_mav_binops_1b},
2108 {"cfmv64lr", 0xee000510, 8, ARM_CEXT_MAVERICK, do_mav_binops_2c},
2109 {"cfmvr64l", 0xee100510, 8, ARM_CEXT_MAVERICK, do_mav_binops_1c},
2110 {"cfmv64hr", 0xee000530, 8, ARM_CEXT_MAVERICK, do_mav_binops_2c},
2111 {"cfmvr64h", 0xee100530, 8, ARM_CEXT_MAVERICK, do_mav_binops_1c},
34920d91
NC
2112 {"cfmval32", 0xee200440, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
2113 {"cfmv32al", 0xee100440, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
2114 {"cfmvam32", 0xee200460, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
2115 {"cfmv32am", 0xee100460, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
2116 {"cfmvah32", 0xee200480, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
2117 {"cfmv32ah", 0xee100480, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
2118 {"cfmva32", 0xee2004a0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3a},
2119 {"cfmv32a", 0xee1004a0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3b},
2120 {"cfmva64", 0xee2004c0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3c},
2121 {"cfmv64a", 0xee1004c0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3d},
2122 {"cfmvsc32", 0xee2004e0, 8, ARM_CEXT_MAVERICK, do_mav_dspsc_1},
2123 {"cfmv32sc", 0xee1004e0, 8, ARM_CEXT_MAVERICK, do_mav_dspsc_2},
63e63b07
RE
2124 {"cfcpys", 0xee000400, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
2125 {"cfcpyd", 0xee000420, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
2126 {"cfcvtsd", 0xee000460, 7, ARM_CEXT_MAVERICK, do_mav_binops_1f},
2127 {"cfcvtds", 0xee000440, 7, ARM_CEXT_MAVERICK, do_mav_binops_1g},
2128 {"cfcvt32s", 0xee000480, 8, ARM_CEXT_MAVERICK, do_mav_binops_1h},
2129 {"cfcvt32d", 0xee0004a0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1i},
2130 {"cfcvt64s", 0xee0004c0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1j},
2131 {"cfcvt64d", 0xee0004e0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1k},
2132 {"cfcvts32", 0xee100580, 8, ARM_CEXT_MAVERICK, do_mav_binops_1l},
2133 {"cfcvtd32", 0xee1005a0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1m},
2134 {"cftruncs32", 0xee1005c0, 10, ARM_CEXT_MAVERICK, do_mav_binops_1l},
2135 {"cftruncd32", 0xee1005e0, 10, ARM_CEXT_MAVERICK, do_mav_binops_1m},
2136 {"cfrshl32", 0xee000550, 8, ARM_CEXT_MAVERICK, do_mav_triple_4a},
2137 {"cfrshl64", 0xee000570, 8, ARM_CEXT_MAVERICK, do_mav_triple_4b},
2138 {"cfsh32", 0xee000500, 6, ARM_CEXT_MAVERICK, do_mav_shift_1},
2139 {"cfsh64", 0xee200500, 6, ARM_CEXT_MAVERICK, do_mav_shift_2},
2140 {"cfcmps", 0xee100490, 6, ARM_CEXT_MAVERICK, do_mav_triple_5a},
2141 {"cfcmpd", 0xee1004b0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5b},
2142 {"cfcmp32", 0xee100590, 7, ARM_CEXT_MAVERICK, do_mav_triple_5c},
2143 {"cfcmp64", 0xee1005b0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5d},
2144 {"cfabss", 0xee300400, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
2145 {"cfabsd", 0xee300420, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
2146 {"cfnegs", 0xee300440, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
2147 {"cfnegd", 0xee300460, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
2148 {"cfadds", 0xee300480, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
2149 {"cfaddd", 0xee3004a0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
2150 {"cfsubs", 0xee3004c0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
2151 {"cfsubd", 0xee3004e0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
2152 {"cfmuls", 0xee100400, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
2153 {"cfmuld", 0xee100420, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
2154 {"cfabs32", 0xee300500, 7, ARM_CEXT_MAVERICK, do_mav_binops_1n},
2155 {"cfabs64", 0xee300520, 7, ARM_CEXT_MAVERICK, do_mav_binops_1o},
2156 {"cfneg32", 0xee300540, 7, ARM_CEXT_MAVERICK, do_mav_binops_1n},
2157 {"cfneg64", 0xee300560, 7, ARM_CEXT_MAVERICK, do_mav_binops_1o},
2158 {"cfadd32", 0xee300580, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
2159 {"cfadd64", 0xee3005a0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
2160 {"cfsub32", 0xee3005c0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
2161 {"cfsub64", 0xee3005e0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
2162 {"cfmul32", 0xee100500, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
2163 {"cfmul64", 0xee100520, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
2164 {"cfmac32", 0xee100540, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
2165 {"cfmsc32", 0xee100560, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
2166 {"cfmadd32", 0xee000600, 8, ARM_CEXT_MAVERICK, do_mav_quad_6a},
2167 {"cfmsub32", 0xee100600, 8, ARM_CEXT_MAVERICK, do_mav_quad_6a},
2168 {"cfmadda32", 0xee200600, 9, ARM_CEXT_MAVERICK, do_mav_quad_6b},
2169 {"cfmsuba32", 0xee300600, 9, ARM_CEXT_MAVERICK, do_mav_quad_6b},
b99bd4ef
NC
2170};
2171
2172/* Defines for various bits that we will want to toggle. */
2173#define INST_IMMEDIATE 0x02000000
2174#define OFFSET_REG 0x02000000
2175#define HWOFFSET_IMM 0x00400000
2176#define SHIFT_BY_REG 0x00000010
2177#define PRE_INDEX 0x01000000
2178#define INDEX_UP 0x00800000
2179#define WRITE_BACK 0x00200000
2180#define LDM_TYPE_2_OR_3 0x00400000
2181
2182#define LITERAL_MASK 0xf000f000
b99bd4ef 2183#define OPCODE_MASK 0xfe1fffff
90e4755a
RE
2184#define V4_STR_BIT 0x00000020
2185
b99bd4ef
NC
2186#define DATA_OP_SHIFT 21
2187
2188/* Codes to distinguish the arithmetic instructions. */
2189#define OPCODE_AND 0
2190#define OPCODE_EOR 1
2191#define OPCODE_SUB 2
2192#define OPCODE_RSB 3
2193#define OPCODE_ADD 4
2194#define OPCODE_ADC 5
2195#define OPCODE_SBC 6
2196#define OPCODE_RSC 7
2197#define OPCODE_TST 8
2198#define OPCODE_TEQ 9
2199#define OPCODE_CMP 10
2200#define OPCODE_CMN 11
2201#define OPCODE_ORR 12
2202#define OPCODE_MOV 13
2203#define OPCODE_BIC 14
2204#define OPCODE_MVN 15
2205
c9b604bd 2206/* Thumb v1 (ARMv4T). */
b99bd4ef
NC
2207static void do_t_nop PARAMS ((char *));
2208static void do_t_arit PARAMS ((char *));
2209static void do_t_add PARAMS ((char *));
2210static void do_t_asr PARAMS ((char *));
2211static void do_t_branch9 PARAMS ((char *));
2212static void do_t_branch12 PARAMS ((char *));
2213static void do_t_branch23 PARAMS ((char *));
2214static void do_t_bx PARAMS ((char *));
2215static void do_t_compare PARAMS ((char *));
2216static void do_t_ldmstm PARAMS ((char *));
2217static void do_t_ldr PARAMS ((char *));
2218static void do_t_ldrb PARAMS ((char *));
2219static void do_t_ldrh PARAMS ((char *));
2220static void do_t_lds PARAMS ((char *));
2221static void do_t_lsl PARAMS ((char *));
2222static void do_t_lsr PARAMS ((char *));
2223static void do_t_mov PARAMS ((char *));
2224static void do_t_push_pop PARAMS ((char *));
2225static void do_t_str PARAMS ((char *));
2226static void do_t_strb PARAMS ((char *));
2227static void do_t_strh PARAMS ((char *));
2228static void do_t_sub PARAMS ((char *));
2229static void do_t_swi PARAMS ((char *));
2230static void do_t_adr PARAMS ((char *));
2231
c9b604bd
RE
2232/* Thumb v2 (ARMv5T). */
2233static void do_t_blx PARAMS ((char *));
2234static void do_t_bkpt PARAMS ((char *));
2235
09d92015
MM
2236/* ARM V6. */
2237static void do_t_cps PARAMS ((char *));
2238static void do_t_cpy PARAMS ((char *));
2239static void do_t_setend PARAMS ((char *));;
2240
b99bd4ef
NC
2241#define T_OPCODE_MUL 0x4340
2242#define T_OPCODE_TST 0x4200
2243#define T_OPCODE_CMN 0x42c0
2244#define T_OPCODE_NEG 0x4240
2245#define T_OPCODE_MVN 0x43c0
2246
2247#define T_OPCODE_ADD_R3 0x1800
2248#define T_OPCODE_SUB_R3 0x1a00
2249#define T_OPCODE_ADD_HI 0x4400
2250#define T_OPCODE_ADD_ST 0xb000
2251#define T_OPCODE_SUB_ST 0xb080
2252#define T_OPCODE_ADD_SP 0xa800
2253#define T_OPCODE_ADD_PC 0xa000
2254#define T_OPCODE_ADD_I8 0x3000
2255#define T_OPCODE_SUB_I8 0x3800
2256#define T_OPCODE_ADD_I3 0x1c00
2257#define T_OPCODE_SUB_I3 0x1e00
2258
2259#define T_OPCODE_ASR_R 0x4100
2260#define T_OPCODE_LSL_R 0x4080
2261#define T_OPCODE_LSR_R 0x40c0
2262#define T_OPCODE_ASR_I 0x1000
2263#define T_OPCODE_LSL_I 0x0000
2264#define T_OPCODE_LSR_I 0x0800
2265
2266#define T_OPCODE_MOV_I8 0x2000
2267#define T_OPCODE_CMP_I8 0x2800
2268#define T_OPCODE_CMP_LR 0x4280
2269#define T_OPCODE_MOV_HR 0x4600
2270#define T_OPCODE_CMP_HR 0x4500
2271
2272#define T_OPCODE_LDR_PC 0x4800
2273#define T_OPCODE_LDR_SP 0x9800
2274#define T_OPCODE_STR_SP 0x9000
2275#define T_OPCODE_LDR_IW 0x6800
2276#define T_OPCODE_STR_IW 0x6000
2277#define T_OPCODE_LDR_IH 0x8800
2278#define T_OPCODE_STR_IH 0x8000
2279#define T_OPCODE_LDR_IB 0x7800
2280#define T_OPCODE_STR_IB 0x7000
2281#define T_OPCODE_LDR_RW 0x5800
2282#define T_OPCODE_STR_RW 0x5000
2283#define T_OPCODE_LDR_RH 0x5a00
2284#define T_OPCODE_STR_RH 0x5200
2285#define T_OPCODE_LDR_RB 0x5c00
2286#define T_OPCODE_STR_RB 0x5400
2287
2288#define T_OPCODE_PUSH 0xb400
2289#define T_OPCODE_POP 0xbc00
2290
2291#define T_OPCODE_BRANCH 0xe7fe
2292
2293static int thumb_reg PARAMS ((char ** str, int hi_lo));
2294
2295#define THUMB_SIZE 2 /* Size of thumb instruction. */
2296#define THUMB_REG_LO 0x1
2297#define THUMB_REG_HI 0x2
2298#define THUMB_REG_ANY 0x3
2299
2300#define THUMB_H1 0x0080
2301#define THUMB_H2 0x0040
2302
2303#define THUMB_ASR 0
2304#define THUMB_LSL 1
2305#define THUMB_LSR 2
2306
2307#define THUMB_MOVE 0
2308#define THUMB_COMPARE 1
09d92015 2309#define THUMB_CPY 2
b99bd4ef
NC
2310
2311#define THUMB_LOAD 0
2312#define THUMB_STORE 1
2313
2314#define THUMB_PP_PC_LR 0x0100
2315
2316/* These three are used for immediate shifts, do not alter. */
2317#define THUMB_WORD 2
2318#define THUMB_HALFWORD 1
2319#define THUMB_BYTE 0
2320
2321struct thumb_opcode
2322{
2323 /* Basic string to match. */
05d2d07e 2324 const char * template;
b99bd4ef
NC
2325
2326 /* Basic instruction code. */
2327 unsigned long value;
2328
2329 int size;
2330
2331 /* Which CPU variants this exists for. */
90e4755a 2332 unsigned long variant;
b99bd4ef
NC
2333
2334 /* Function to call to parse args. */
2335 void (* parms) PARAMS ((char *));
2336};
2337
05d2d07e 2338static const struct thumb_opcode tinsns[] =
b99bd4ef 2339{
c9b604bd 2340 /* Thumb v1 (ARMv4T). */
b89dddec
RE
2341 {"adc", 0x4140, 2, ARM_EXT_V4T, do_t_arit},
2342 {"add", 0x0000, 2, ARM_EXT_V4T, do_t_add},
2343 {"and", 0x4000, 2, ARM_EXT_V4T, do_t_arit},
2344 {"asr", 0x0000, 2, ARM_EXT_V4T, do_t_asr},
2345 {"b", T_OPCODE_BRANCH, 2, ARM_EXT_V4T, do_t_branch12},
2346 {"beq", 0xd0fe, 2, ARM_EXT_V4T, do_t_branch9},
2347 {"bne", 0xd1fe, 2, ARM_EXT_V4T, do_t_branch9},
2348 {"bcs", 0xd2fe, 2, ARM_EXT_V4T, do_t_branch9},
2349 {"bhs", 0xd2fe, 2, ARM_EXT_V4T, do_t_branch9},
2350 {"bcc", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
2351 {"bul", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
2352 {"blo", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
2353 {"bmi", 0xd4fe, 2, ARM_EXT_V4T, do_t_branch9},
2354 {"bpl", 0xd5fe, 2, ARM_EXT_V4T, do_t_branch9},
2355 {"bvs", 0xd6fe, 2, ARM_EXT_V4T, do_t_branch9},
2356 {"bvc", 0xd7fe, 2, ARM_EXT_V4T, do_t_branch9},
2357 {"bhi", 0xd8fe, 2, ARM_EXT_V4T, do_t_branch9},
2358 {"bls", 0xd9fe, 2, ARM_EXT_V4T, do_t_branch9},
2359 {"bge", 0xdafe, 2, ARM_EXT_V4T, do_t_branch9},
2360 {"blt", 0xdbfe, 2, ARM_EXT_V4T, do_t_branch9},
2361 {"bgt", 0xdcfe, 2, ARM_EXT_V4T, do_t_branch9},
2362 {"ble", 0xddfe, 2, ARM_EXT_V4T, do_t_branch9},
2363 {"bal", 0xdefe, 2, ARM_EXT_V4T, do_t_branch9},
2364 {"bic", 0x4380, 2, ARM_EXT_V4T, do_t_arit},
2365 {"bl", 0xf7fffffe, 4, ARM_EXT_V4T, do_t_branch23},
b89dddec
RE
2366 {"bx", 0x4700, 2, ARM_EXT_V4T, do_t_bx},
2367 {"cmn", T_OPCODE_CMN, 2, ARM_EXT_V4T, do_t_arit},
2368 {"cmp", 0x0000, 2, ARM_EXT_V4T, do_t_compare},
2369 {"eor", 0x4040, 2, ARM_EXT_V4T, do_t_arit},
2370 {"ldmia", 0xc800, 2, ARM_EXT_V4T, do_t_ldmstm},
2371 {"ldr", 0x0000, 2, ARM_EXT_V4T, do_t_ldr},
2372 {"ldrb", 0x0000, 2, ARM_EXT_V4T, do_t_ldrb},
2373 {"ldrh", 0x0000, 2, ARM_EXT_V4T, do_t_ldrh},
2374 {"ldrsb", 0x5600, 2, ARM_EXT_V4T, do_t_lds},
2375 {"ldrsh", 0x5e00, 2, ARM_EXT_V4T, do_t_lds},
2376 {"ldsb", 0x5600, 2, ARM_EXT_V4T, do_t_lds},
2377 {"ldsh", 0x5e00, 2, ARM_EXT_V4T, do_t_lds},
2378 {"lsl", 0x0000, 2, ARM_EXT_V4T, do_t_lsl},
2379 {"lsr", 0x0000, 2, ARM_EXT_V4T, do_t_lsr},
2380 {"mov", 0x0000, 2, ARM_EXT_V4T, do_t_mov},
2381 {"mul", T_OPCODE_MUL, 2, ARM_EXT_V4T, do_t_arit},
2382 {"mvn", T_OPCODE_MVN, 2, ARM_EXT_V4T, do_t_arit},
2383 {"neg", T_OPCODE_NEG, 2, ARM_EXT_V4T, do_t_arit},
2384 {"orr", 0x4300, 2, ARM_EXT_V4T, do_t_arit},
2385 {"pop", 0xbc00, 2, ARM_EXT_V4T, do_t_push_pop},
2386 {"push", 0xb400, 2, ARM_EXT_V4T, do_t_push_pop},
2387 {"ror", 0x41c0, 2, ARM_EXT_V4T, do_t_arit},
2388 {"sbc", 0x4180, 2, ARM_EXT_V4T, do_t_arit},
2389 {"stmia", 0xc000, 2, ARM_EXT_V4T, do_t_ldmstm},
2390 {"str", 0x0000, 2, ARM_EXT_V4T, do_t_str},
2391 {"strb", 0x0000, 2, ARM_EXT_V4T, do_t_strb},
2392 {"strh", 0x0000, 2, ARM_EXT_V4T, do_t_strh},
2393 {"swi", 0xdf00, 2, ARM_EXT_V4T, do_t_swi},
2394 {"sub", 0x0000, 2, ARM_EXT_V4T, do_t_sub},
2395 {"tst", T_OPCODE_TST, 2, ARM_EXT_V4T, do_t_arit},
b99bd4ef 2396 /* Pseudo ops: */
b89dddec
RE
2397 {"adr", 0x0000, 2, ARM_EXT_V4T, do_t_adr},
2398 {"nop", 0x46C0, 2, ARM_EXT_V4T, do_t_nop}, /* mov r8,r8 */
c9b604bd
RE
2399 /* Thumb v2 (ARMv5T). */
2400 {"blx", 0, 0, ARM_EXT_V5T, do_t_blx},
2401 {"bkpt", 0xbe00, 2, ARM_EXT_V5T, do_t_bkpt},
09d92015
MM
2402
2403 /* ARM V6. */
2404 {"cpsie", 0xb660, 2, ARM_EXT_V6, do_t_cps},
2405 {"cpsid", 0xb670, 2, ARM_EXT_V6, do_t_cps},
2406 {"cpy", 0x4600, 2, ARM_EXT_V6, do_t_cpy},
2407 {"rev", 0xba00, 2, ARM_EXT_V6, do_t_arit},
2408 {"rev16", 0xba40, 2, ARM_EXT_V6, do_t_arit},
2409 {"revsh", 0xbac0, 2, ARM_EXT_V6, do_t_arit},
2410 {"setend", 0xb650, 2, ARM_EXT_V6, do_t_setend},
2411 {"sxth", 0xb200, 2, ARM_EXT_V6, do_t_arit},
2412 {"sxtb", 0xb240, 2, ARM_EXT_V6, do_t_arit},
2413 {"uxth", 0xb280, 2, ARM_EXT_V6, do_t_arit},
2414 {"uxtb", 0xb2c0, 2, ARM_EXT_V6, do_t_arit},
b99bd4ef
NC
2415};
2416
f03698e6 2417#define BAD_ARGS _("bad arguments to instruction")
b99bd4ef 2418#define BAD_PC _("r15 not allowed here")
f03698e6 2419#define BAD_COND _("instruction is not conditional")
b99bd4ef
NC
2420#define ERR_NO_ACCUM _("acc0 expected")
2421
2422static struct hash_control * arm_ops_hsh = NULL;
2423static struct hash_control * arm_tops_hsh = NULL;
2424static struct hash_control * arm_cond_hsh = NULL;
2425static struct hash_control * arm_shift_hsh = NULL;
b99bd4ef
NC
2426static struct hash_control * arm_psr_hsh = NULL;
2427
2428/* This table describes all the machine specific pseudo-ops the assembler
2429 has to support. The fields are:
2430 pseudo-op name without dot
2431 function to call to execute this pseudo-op
2432 Integer arg to pass to the function. */
2433
2434static void s_req PARAMS ((int));
0bbf2aa4 2435static void s_unreq PARAMS ((int));
b99bd4ef
NC
2436static void s_align PARAMS ((int));
2437static void s_bss PARAMS ((int));
2438static void s_even PARAMS ((int));
2439static void s_ltorg PARAMS ((int));
2440static void s_arm PARAMS ((int));
2441static void s_thumb PARAMS ((int));
2442static void s_code PARAMS ((int));
2443static void s_force_thumb PARAMS ((int));
2444static void s_thumb_func PARAMS ((int));
2445static void s_thumb_set PARAMS ((int));
76feaaf3 2446#ifdef OBJ_ELF
b99bd4ef
NC
2447static void s_arm_elf_cons PARAMS ((int));
2448#endif
2449
2450static int my_get_expression PARAMS ((expressionS *, char **));
2451
05d2d07e 2452const pseudo_typeS md_pseudo_table[] =
b99bd4ef 2453{
0bbf2aa4 2454 /* Never called because '.req' does not start a line. */
b99bd4ef 2455 { "req", s_req, 0 },
0bbf2aa4 2456 { "unreq", s_unreq, 0 },
b99bd4ef
NC
2457 { "bss", s_bss, 0 },
2458 { "align", s_align, 0 },
2459 { "arm", s_arm, 0 },
2460 { "thumb", s_thumb, 0 },
2461 { "code", s_code, 0 },
2462 { "force_thumb", s_force_thumb, 0 },
2463 { "thumb_func", s_thumb_func, 0 },
2464 { "thumb_set", s_thumb_set, 0 },
2465 { "even", s_even, 0 },
2466 { "ltorg", s_ltorg, 0 },
2467 { "pool", s_ltorg, 0 },
76feaaf3 2468#ifdef OBJ_ELF
b99bd4ef
NC
2469 { "word", s_arm_elf_cons, 4 },
2470 { "long", s_arm_elf_cons, 4 },
b99bd4ef
NC
2471#else
2472 { "word", cons, 4},
2473#endif
2474 { "extend", float_cons, 'x' },
2475 { "ldouble", float_cons, 'x' },
2476 { "packed", float_cons, 'p' },
2477 { 0, 0, 0 }
2478};
2479
03b1477f
RE
2480/* Other internal functions. */
2481static int arm_parse_extension PARAMS ((char *, int *));
2482static int arm_parse_cpu PARAMS ((char *));
2483static int arm_parse_arch PARAMS ((char *));
2484static int arm_parse_fpu PARAMS ((char *));
33a392fb 2485static int arm_parse_float_abi PARAMS ((char *));
7cc69913 2486#ifdef OBJ_ELF
d507cf36 2487static int arm_parse_eabi PARAMS ((char *));
7cc69913 2488#endif
0bbf2aa4 2489#if 0 /* Suppressed - for now. */
5a6c6817
NC
2490#if defined OBJ_COFF || defined OBJ_ELF
2491static void arm_add_note PARAMS ((const char *, const char *, unsigned int));
2492#endif
0bbf2aa4 2493#endif
03b1477f 2494
b99bd4ef
NC
2495/* Stuff needed to resolve the label ambiguity
2496 As:
2497 ...
2498 label: <insn>
2499 may differ from:
2500 ...
2501 label:
2502 <insn>
2503*/
2504
2505symbolS * last_label_seen;
b34976b6 2506static int label_is_thumb_function_name = FALSE;
b99bd4ef 2507
3d0c9500 2508/* Literal Pool stuff. */
b99bd4ef
NC
2509
2510#define MAX_LITERAL_POOL_SIZE 1024
2511
3d0c9500
NC
2512/* Literal pool structure. Held on a per-section
2513 and per-sub-section basis. */
2514typedef struct literal_pool
b99bd4ef 2515{
3d0c9500
NC
2516 expressionS literals [MAX_LITERAL_POOL_SIZE];
2517 unsigned int next_free_entry;
2518 unsigned int id;
2519 symbolS * symbol;
2520 segT section;
2521 subsegT sub_section;
61b5f74b 2522 struct literal_pool * next;
3d0c9500 2523} literal_pool;
b99bd4ef 2524
3d0c9500
NC
2525/* Pointer to a linked list of literal pools. */
2526literal_pool * list_of_pools = NULL;
b99bd4ef 2527
3d0c9500
NC
2528static literal_pool * find_literal_pool PARAMS ((void));
2529static literal_pool * find_or_make_literal_pool PARAMS ((void));
b99bd4ef 2530
3d0c9500
NC
2531static literal_pool *
2532find_literal_pool ()
2533{
2534 literal_pool * pool;
2535
2536 for (pool = list_of_pools; pool != NULL; pool = pool->next)
2537 {
2538 if (pool->section == now_seg
2539 && pool->sub_section == now_subseg)
2540 break;
2541 }
2542
2543 return pool;
2544}
b99bd4ef 2545
3d0c9500
NC
2546static literal_pool *
2547find_or_make_literal_pool ()
2548{
2549 /* Next literal pool ID number. */
2550 static unsigned int latest_pool_num = 1;
2551 literal_pool * pool;
2552
2553 pool = find_literal_pool ();
b99bd4ef 2554
3d0c9500
NC
2555 if (pool == NULL)
2556 {
2557 /* Create a new pool. */
2558 pool = (literal_pool *) xmalloc (sizeof (* pool));
2559 if (! pool)
2560 return NULL;
2561
2562 pool->next_free_entry = 0;
2563 pool->section = now_seg;
2564 pool->sub_section = now_subseg;
2565 pool->next = list_of_pools;
2566 pool->symbol = NULL;
2567
2568 /* Add it to the list. */
2569 list_of_pools = pool;
2570 }
2571
2572 /* New pools, and emptied pools, will have a NULL symbol. */
2573 if (pool->symbol == NULL)
2574 {
2575 pool->symbol = symbol_create (FAKE_LABEL_NAME, undefined_section,
2576 (valueT) 0, &zero_address_frag);
2577 pool->id = latest_pool_num ++;
2578 }
2579
2580 /* Done. */
2581 return pool;
2582}
2583
2584/* Add the literal in the global 'inst'
2585 structure to the relevent literal pool. */
b99bd4ef
NC
2586static int
2587add_to_lit_pool ()
2588{
61b5f74b 2589 literal_pool * pool;
3d0c9500 2590 unsigned int entry;
b99bd4ef 2591
3d0c9500 2592 pool = find_or_make_literal_pool ();
b99bd4ef 2593
3d0c9500
NC
2594 /* Check if this literal value is already in the pool. */
2595 for (entry = 0; entry < pool->next_free_entry; entry ++)
b99bd4ef 2596 {
3d0c9500
NC
2597 if ((pool->literals[entry].X_op == inst.reloc.exp.X_op)
2598 && (inst.reloc.exp.X_op == O_constant)
2599 && (pool->literals[entry].X_add_number
b99bd4ef 2600 == inst.reloc.exp.X_add_number)
3d0c9500
NC
2601 && (pool->literals[entry].X_unsigned
2602 == inst.reloc.exp.X_unsigned))
b99bd4ef
NC
2603 break;
2604
3d0c9500
NC
2605 if ((pool->literals[entry].X_op == inst.reloc.exp.X_op)
2606 && (inst.reloc.exp.X_op == O_symbol)
2607 && (pool->literals[entry].X_add_number
b99bd4ef 2608 == inst.reloc.exp.X_add_number)
3d0c9500 2609 && (pool->literals[entry].X_add_symbol
b99bd4ef 2610 == inst.reloc.exp.X_add_symbol)
3d0c9500 2611 && (pool->literals[entry].X_op_symbol
b99bd4ef 2612 == inst.reloc.exp.X_op_symbol))
3d0c9500 2613 break;
b99bd4ef
NC
2614 }
2615
3d0c9500
NC
2616 /* Do we need to create a new entry? */
2617 if (entry == pool->next_free_entry)
b99bd4ef 2618 {
3d0c9500 2619 if (entry >= MAX_LITERAL_POOL_SIZE)
b99bd4ef 2620 {
ed71e111 2621 inst.error = _("literal pool overflow");
b99bd4ef
NC
2622 return FAIL;
2623 }
2624
3d0c9500
NC
2625 pool->literals[entry] = inst.reloc.exp;
2626 pool->next_free_entry += 1;
b99bd4ef
NC
2627 }
2628
3d0c9500 2629 inst.reloc.exp.X_op = O_symbol;
08df2379 2630 inst.reloc.exp.X_add_number = ((int) entry) * 4 - 8;
3d0c9500 2631 inst.reloc.exp.X_add_symbol = pool->symbol;
b99bd4ef
NC
2632
2633 return SUCCESS;
2634}
2635
2636/* Can't use symbol_new here, so have to create a symbol and then at
2637 a later date assign it a value. Thats what these functions do. */
2638
2639static void
2640symbol_locate (symbolP, name, segment, valu, frag)
2641 symbolS * symbolP;
05d2d07e 2642 const char * name; /* It is copied, the caller can modify. */
b99bd4ef
NC
2643 segT segment; /* Segment identifier (SEG_<something>). */
2644 valueT valu; /* Symbol value. */
2645 fragS * frag; /* Associated fragment. */
2646{
2647 unsigned int name_length;
2648 char * preserved_copy_of_name;
2649
2650 name_length = strlen (name) + 1; /* +1 for \0. */
2651 obstack_grow (&notes, name, name_length);
2652 preserved_copy_of_name = obstack_finish (&notes);
2653#ifdef STRIP_UNDERSCORE
2654 if (preserved_copy_of_name[0] == '_')
2655 preserved_copy_of_name++;
2656#endif
2657
2658#ifdef tc_canonicalize_symbol_name
2659 preserved_copy_of_name =
2660 tc_canonicalize_symbol_name (preserved_copy_of_name);
2661#endif
2662
2663 S_SET_NAME (symbolP, preserved_copy_of_name);
2664
2665 S_SET_SEGMENT (symbolP, segment);
2666 S_SET_VALUE (symbolP, valu);
c62e1cc3 2667 symbol_clear_list_pointers (symbolP);
b99bd4ef
NC
2668
2669 symbol_set_frag (symbolP, frag);
2670
2671 /* Link to end of symbol chain. */
2672 {
2673 extern int symbol_table_frozen;
2674 if (symbol_table_frozen)
2675 abort ();
2676 }
2677
2678 symbol_append (symbolP, symbol_lastP, & symbol_rootP, & symbol_lastP);
2679
2680 obj_symbol_new_hook (symbolP);
2681
2682#ifdef tc_symbol_new_hook
2683 tc_symbol_new_hook (symbolP);
2684#endif
2685
2686#ifdef DEBUG_SYMS
2687 verify_symbol_chain (symbol_rootP, symbol_lastP);
2688#endif /* DEBUG_SYMS */
2689}
2690
2691/* Check that an immediate is valid.
2692 If so, convert it to the right format. */
2693
2694static unsigned int
2695validate_immediate (val)
2696 unsigned int val;
2697{
2698 unsigned int a;
2699 unsigned int i;
2700
2701#define rotate_left(v, n) (v << n | v >> (32 - n))
2702
2703 for (i = 0; i < 32; i += 2)
2704 if ((a = rotate_left (val, i)) <= 0xff)
2705 return a | (i << 7); /* 12-bit pack: [shift-cnt,const]. */
2706
2707 return FAIL;
2708}
2709
2d2255b5 2710/* Check to see if an immediate can be computed as two separate immediate
b99bd4ef
NC
2711 values, added together. We already know that this value cannot be
2712 computed by just one ARM instruction. */
2713
2714static unsigned int
2715validate_immediate_twopart (val, highpart)
2716 unsigned int val;
2717 unsigned int * highpart;
2718{
2719 unsigned int a;
2720 unsigned int i;
2721
2722 for (i = 0; i < 32; i += 2)
2723 if (((a = rotate_left (val, i)) & 0xff) != 0)
2724 {
2725 if (a & 0xff00)
2726 {
2727 if (a & ~ 0xffff)
2728 continue;
2729 * highpart = (a >> 8) | ((i + 24) << 7);
2730 }
2731 else if (a & 0xff0000)
2732 {
2733 if (a & 0xff000000)
2734 continue;
2735 * highpart = (a >> 16) | ((i + 16) << 7);
2736 }
2737 else
2738 {
2739 assert (a & 0xff000000);
2740 * highpart = (a >> 24) | ((i + 8) << 7);
2741 }
2742
2743 return (a & 0xff) | (i << 7);
2744 }
2745
2746 return FAIL;
2747}
2748
2749static int
2750validate_offset_imm (val, hwse)
2751 unsigned int val;
2752 int hwse;
2753{
2754 if ((hwse && val > 255) || val > 4095)
2755 return FAIL;
2756 return val;
2757}
2758
6057a28f
NC
2759\f
2760#ifdef OBJ_ELF
6057a28f
NC
2761/* This code is to handle mapping symbols as defined in the ARM ELF spec.
2762 (This text is taken from version B-02 of the spec):
2763
2764 4.4.7 Mapping and tagging symbols
2765
2766 A section of an ARM ELF file can contain a mixture of ARM code,
2767 Thumb code, and data. There are inline transitions between code
2768 and data at literal pool boundaries. There can also be inline
2769 transitions between ARM code and Thumb code, for example in
2770 ARM-Thumb inter-working veneers. Linkers, machine-level
2771 debuggers, profiling tools, and disassembly tools need to map
2772 images accurately. For example, setting an ARM breakpoint on a
2773 Thumb location, or in a literal pool, can crash the program
2774 being debugged, ruining the debugging session.
2775
2776 ARM ELF entities are mapped (see section 4.4.7.1 below) and
2777 tagged (see section 4.4.7.2 below) using local symbols (with
2778 binding STB_LOCAL). To assist consumers, mapping and tagging
2779 symbols should be collated first in the symbol table, before
2780 other symbols with binding STB_LOCAL.
2781
2782 To allow properly collated mapping and tagging symbols to be
2783 skipped by consumers that have no interest in them, the first
2784 such symbol should have the name $m and its st_value field equal
2785 to the total number of mapping and tagging symbols (including
2786 the $m) in the symbol table.
2787
2788 4.4.7.1 Mapping symbols
2789
2790 $a Labels the first byte of a sequence of ARM instructions.
2791 Its type is STT_FUNC.
2792
2793 $d Labels the first byte of a sequence of data items.
2794 Its type is STT_OBJECT.
2795
2796 $t Labels the first byte of a sequence of Thumb instructions.
2797 Its type is STT_FUNC.
2798
2799 This list of mapping symbols may be extended in the future.
2800
2801 Section-relative mapping symbols
2802
2803 Mapping symbols defined in a section define a sequence of
2804 half-open address intervals that cover the address range of the
2805 section. Each interval starts at the address defined by a
2806 mapping symbol, and continues up to, but not including, the
2807 address defined by the next (in address order) mapping symbol or
2808 the end of the section. A corollary is that there must be a
2809 mapping symbol defined at the beginning of each section.
2810 Consumers can ignore the size of a section-relative mapping
2811 symbol. Producers can set it to 0.
2812
2813 Absolute mapping symbols
2814
2815 Because of the need to crystallize a Thumb address with the
2816 Thumb-bit set, absolute symbol of type STT_FUNC (symbols of type
2817 STT_FUNC defined in section SHN_ABS) need to be mapped with $a
2818 or $t.
2819
2820 The extent of a mapping symbol defined in SHN_ABS is [st_value,
2821 st_value + st_size), or [st_value, st_value + 1) if st_size = 0,
2822 where [x, y) denotes the half-open address range from x,
2823 inclusive, to y, exclusive.
2824
2825 In the absence of a mapping symbol, a consumer can interpret a
2826 function symbol with an odd value as the Thumb code address
2827 obtained by clearing the least significant bit of the
2828 value. This interpretation is deprecated, and it may not work in
2829 the future.
2830
2831 Note - the Tagging symbols ($b, $f, $p $m) have been dropped from
2832 the EABI (which is still under development), so they are not
2833 implemented here. */
2834
69b97547
NC
2835static enum mstate mapstate = MAP_UNDEFINED;
2836
6057a28f
NC
2837static void
2838mapping_state (enum mstate state)
2839{
6057a28f
NC
2840 symbolS * symbolP;
2841 const char * symname;
2842 int type;
2843
2844 if (mapstate == state)
2845 /* The mapping symbol has already been emitted.
2846 There is nothing else to do. */
2847 return;
2848
2849 mapstate = state;
2850
2851 switch (state)
2852 {
2853 case MAP_DATA:
2854 symname = "$d";
2855 type = BSF_OBJECT;
2856 break;
2857 case MAP_ARM:
2858 symname = "$a";
2859 type = BSF_FUNCTION;
2860 break;
2861 case MAP_THUMB:
2862 symname = "$t";
2863 type = BSF_FUNCTION;
2864 break;
69b97547
NC
2865 case MAP_UNDEFINED:
2866 return;
6057a28f
NC
2867 default:
2868 abort ();
2869 }
2870
69b97547
NC
2871 seg_info (now_seg)->tc_segment_info_data = state;
2872
6057a28f
NC
2873 symbolP = symbol_new (symname, now_seg, (valueT) frag_now_fix (), frag_now);
2874 symbol_table_insert (symbolP);
2875 symbol_get_bfdsym (symbolP)->flags |= type | BSF_LOCAL;
2876
2877 switch (state)
2878 {
2879 case MAP_ARM:
2880 THUMB_SET_FUNC (symbolP, 0);
2881 ARM_SET_THUMB (symbolP, 0);
2882 ARM_SET_INTERWORK (symbolP, support_interwork);
2883 break;
2884
2885 case MAP_THUMB:
2886 THUMB_SET_FUNC (symbolP, 1);
2887 ARM_SET_THUMB (symbolP, 1);
2888 ARM_SET_INTERWORK (symbolP, support_interwork);
2889 break;
2890
2891 case MAP_DATA:
2892 default:
2893 return;
2894 }
2895}
2896
2897/* When we change sections we need to issue a new mapping symbol. */
2898
9ce887a1 2899void
6057a28f
NC
2900arm_elf_change_section (void)
2901{
2902 flagword flags;
2903
2904 if (!SEG_NORMAL (now_seg))
2905 return;
2906
2907 flags = bfd_get_section_flags (stdoutput, now_seg);
2908
2909 /* We can ignore sections that only contain debug info. */
2910 if ((flags & SEC_ALLOC) == 0)
2911 return;
2912
69b97547 2913 mapstate = seg_info (now_seg)->tc_segment_info_data;
6057a28f
NC
2914}
2915#else
2916#define mapping_state(a)
2917#endif /* OBJ_ELF */
2918\f
2919
b99bd4ef
NC
2920static void
2921s_req (a)
2922 int a ATTRIBUTE_UNUSED;
2923{
f03698e6 2924 as_bad (_("invalid syntax for .req directive"));
b99bd4ef
NC
2925}
2926
0bbf2aa4
NC
2927/* The .unreq directive deletes an alias which was previously defined
2928 by .req. For example:
2929
2930 my_alias .req r11
2931 .unreq my_alias */
2932
2933static void
2934s_unreq (int a ATTRIBUTE_UNUSED)
2935{
2936 char *name;
2937 char saved_char;
2938
2939 skip_whitespace (input_line_pointer);
2940 name = input_line_pointer;
2941
2942 while (*input_line_pointer != 0
2943 && *input_line_pointer != ' '
2944 && *input_line_pointer != '\n')
2945 ++input_line_pointer;
2946
2947 saved_char = *input_line_pointer;
2948 *input_line_pointer = 0;
2949
2950 if (*name)
2951 {
2952 enum arm_reg_type req_type = arm_reg_parse_any (name);
2953
2954 if (req_type != REG_TYPE_MAX)
2955 {
2956 char *temp_name = name;
2957 int req_no = arm_reg_parse (&temp_name, all_reg_maps[req_type].htab);
2958
2959 if (req_no != FAIL)
2960 {
2961 struct reg_entry *req_entry;
2962
2963 /* Check to see if this alias is a builtin one. */
2964 req_entry = hash_delete (all_reg_maps[req_type].htab, name);
2965
2966 if (!req_entry)
2967 as_bad (_("unreq: missing hash entry for \"%s\""), name);
2968 else if (req_entry->builtin)
67c1ffbe 2969 /* FIXME: We are deleting a built in register alias which
0bbf2aa4
NC
2970 points to a const data structure, so we only need to
2971 free up the memory used by the key in the hash table.
2972 Unfortunately we have not recorded this value, so this
2973 is a memory leak. */
2974 /* FIXME: Should we issue a warning message ? */
2975 ;
2976 else
2977 {
67c1ffbe 2978 /* Deleting a user defined alias. We need to free the
0bbf2aa4
NC
2979 key and the value, but fortunately the key is the same
2980 as the value->name field. */
2981 free ((char *) req_entry->name);
2982 free (req_entry);
2983 }
2984 }
2985 else
2986 as_bad (_(".unreq: unrecognized symbol \"%s\""), name);
2987 }
2988 else
2989 as_bad (_(".unreq: unrecognized symbol \"%s\""), name);
2990 }
2991 else
2992 as_bad (_("invalid syntax for .unreq directive"));
2993
2994 *input_line_pointer = saved_char;
2995 demand_empty_rest_of_line ();
2996}
2997
b99bd4ef
NC
2998static void
2999s_bss (ignore)
3000 int ignore ATTRIBUTE_UNUSED;
3001{
3002 /* We don't support putting frags in the BSS segment, we fake it by
3003 marking in_bss, then looking at s_skip for clues. */
3004 subseg_set (bss_section, 0);
3005 demand_empty_rest_of_line ();
6057a28f 3006 mapping_state (MAP_DATA);
b99bd4ef
NC
3007}
3008
3009static void
3010s_even (ignore)
3011 int ignore ATTRIBUTE_UNUSED;
3012{
3013 /* Never make frag if expect extra pass. */
3014 if (!need_pass_2)
3015 frag_align (1, 0, 0);
3016
3017 record_alignment (now_seg, 1);
3018
3019 demand_empty_rest_of_line ();
3020}
3021
3022static void
3023s_ltorg (ignored)
3024 int ignored ATTRIBUTE_UNUSED;
3025{
3d0c9500
NC
3026 unsigned int entry;
3027 literal_pool * pool;
b99bd4ef
NC
3028 char sym_name[20];
3029
3d0c9500
NC
3030 pool = find_literal_pool ();
3031 if (pool == NULL
3032 || pool->symbol == NULL
3033 || pool->next_free_entry == 0)
b99bd4ef
NC
3034 return;
3035
69b97547
NC
3036 mapping_state (MAP_DATA);
3037
b99bd4ef
NC
3038 /* Align pool as you have word accesses.
3039 Only make a frag if we have to. */
3040 if (!need_pass_2)
3041 frag_align (2, 0, 0);
3042
3043 record_alignment (now_seg, 2);
3044
3d0c9500 3045 sprintf (sym_name, "$$lit_\002%x", pool->id);
b99bd4ef 3046
3d0c9500 3047 symbol_locate (pool->symbol, sym_name, now_seg,
b99bd4ef 3048 (valueT) frag_now_fix (), frag_now);
3d0c9500 3049 symbol_table_insert (pool->symbol);
b99bd4ef 3050
3d0c9500 3051 ARM_SET_THUMB (pool->symbol, thumb_mode);
b99bd4ef
NC
3052
3053#if defined OBJ_COFF || defined OBJ_ELF
3d0c9500 3054 ARM_SET_INTERWORK (pool->symbol, support_interwork);
b99bd4ef
NC
3055#endif
3056
3d0c9500 3057 for (entry = 0; entry < pool->next_free_entry; entry ++)
b99bd4ef 3058 /* First output the expression in the instruction to the pool. */
3d0c9500 3059 emit_expr (&(pool->literals[entry]), 4); /* .word */
b99bd4ef 3060
3d0c9500
NC
3061 /* Mark the pool as empty. */
3062 pool->next_free_entry = 0;
3063 pool->symbol = NULL;
b99bd4ef
NC
3064}
3065
3066/* Same as s_align_ptwo but align 0 => align 2. */
3067
3068static void
3069s_align (unused)
3070 int unused ATTRIBUTE_UNUSED;
3071{
3072 register int temp;
3073 register long temp_fill;
3074 long max_alignment = 15;
3075
3076 temp = get_absolute_expression ();
3077 if (temp > max_alignment)
f03698e6 3078 as_bad (_("alignment too large: %d assumed"), temp = max_alignment);
b99bd4ef
NC
3079 else if (temp < 0)
3080 {
f03698e6 3081 as_bad (_("alignment negative. 0 assumed."));
b99bd4ef
NC
3082 temp = 0;
3083 }
3084
3085 if (*input_line_pointer == ',')
3086 {
3087 input_line_pointer++;
3088 temp_fill = get_absolute_expression ();
3089 }
3090 else
3091 temp_fill = 0;
3092
3093 if (!temp)
3094 temp = 2;
3095
3096 /* Only make a frag if we HAVE to. */
3097 if (temp && !need_pass_2)
3098 frag_align (temp, (int) temp_fill, 0);
3099 demand_empty_rest_of_line ();
3100
3101 record_alignment (now_seg, temp);
3102}
3103
3104static void
3105s_force_thumb (ignore)
3106 int ignore ATTRIBUTE_UNUSED;
3107{
3108 /* If we are not already in thumb mode go into it, EVEN if
3109 the target processor does not support thumb instructions.
3110 This is used by gcc/config/arm/lib1funcs.asm for example
3111 to compile interworking support functions even if the
3112 target processor should not support interworking. */
3113 if (! thumb_mode)
3114 {
3115 thumb_mode = 2;
3116
3117 record_alignment (now_seg, 1);
3118 }
3119
3120 demand_empty_rest_of_line ();
3121}
3122
3123static void
3124s_thumb_func (ignore)
3125 int ignore ATTRIBUTE_UNUSED;
3126{
3127 if (! thumb_mode)
3128 opcode_select (16);
3129
3130 /* The following label is the name/address of the start of a Thumb function.
3131 We need to know this for the interworking support. */
b34976b6 3132 label_is_thumb_function_name = TRUE;
b99bd4ef
NC
3133
3134 demand_empty_rest_of_line ();
3135}
3136
3137/* Perform a .set directive, but also mark the alias as
3138 being a thumb function. */
3139
3140static void
3141s_thumb_set (equiv)
3142 int equiv;
3143{
3144 /* XXX the following is a duplicate of the code for s_set() in read.c
3145 We cannot just call that code as we need to get at the symbol that
3146 is created. */
3147 register char * name;
3148 register char delim;
3149 register char * end_name;
3150 register symbolS * symbolP;
3151
3152 /* Especial apologies for the random logic:
3153 This just grew, and could be parsed much more simply!
3154 Dean - in haste. */
3155 name = input_line_pointer;
3156 delim = get_symbol_end ();
3157 end_name = input_line_pointer;
3158 *end_name = delim;
3159
3160 SKIP_WHITESPACE ();
3161
3162 if (*input_line_pointer != ',')
3163 {
3164 *end_name = 0;
f03698e6 3165 as_bad (_("expected comma after name \"%s\""), name);
b99bd4ef
NC
3166 *end_name = delim;
3167 ignore_rest_of_line ();
3168 return;
3169 }
3170
3171 input_line_pointer++;
3172 *end_name = 0;
3173
3174 if (name[0] == '.' && name[1] == '\0')
3175 {
3176 /* XXX - this should not happen to .thumb_set. */
3177 abort ();
3178 }
3179
3180 if ((symbolP = symbol_find (name)) == NULL
3181 && (symbolP = md_undefined_symbol (name)) == NULL)
3182 {
3183#ifndef NO_LISTING
3184 /* When doing symbol listings, play games with dummy fragments living
3185 outside the normal fragment chain to record the file and line info
3186 for this symbol. */
3187 if (listing & LISTING_SYMBOLS)
3188 {
3189 extern struct list_info_struct * listing_tail;
3190 fragS * dummy_frag = (fragS *) xmalloc (sizeof (fragS));
3191
3192 memset (dummy_frag, 0, sizeof (fragS));
3193 dummy_frag->fr_type = rs_fill;
3194 dummy_frag->line = listing_tail;
3195 symbolP = symbol_new (name, undefined_section, 0, dummy_frag);
3196 dummy_frag->fr_symbol = symbolP;
3197 }
3198 else
3199#endif
3200 symbolP = symbol_new (name, undefined_section, 0, &zero_address_frag);
3201
3202#ifdef OBJ_COFF
3203 /* "set" symbols are local unless otherwise specified. */
3204 SF_SET_LOCAL (symbolP);
3205#endif /* OBJ_COFF */
3206 } /* Make a new symbol. */
3207
3208 symbol_table_insert (symbolP);
3209
3210 * end_name = delim;
3211
3212 if (equiv
3213 && S_IS_DEFINED (symbolP)
3214 && S_GET_SEGMENT (symbolP) != reg_section)
3215 as_bad (_("symbol `%s' already defined"), S_GET_NAME (symbolP));
3216
3217 pseudo_set (symbolP);
3218
3219 demand_empty_rest_of_line ();
3220
3221 /* XXX Now we come to the Thumb specific bit of code. */
3222
3223 THUMB_SET_FUNC (symbolP, 1);
3224 ARM_SET_THUMB (symbolP, 1);
3225#if defined OBJ_ELF || defined OBJ_COFF
3226 ARM_SET_INTERWORK (symbolP, support_interwork);
3227#endif
3228}
3229
b99bd4ef
NC
3230static void
3231opcode_select (width)
3232 int width;
3233{
3234 switch (width)
3235 {
3236 case 16:
3237 if (! thumb_mode)
3238 {
b89dddec 3239 if (! (cpu_variant & ARM_EXT_V4T))
b99bd4ef
NC
3240 as_bad (_("selected processor does not support THUMB opcodes"));
3241
3242 thumb_mode = 1;
3243 /* No need to force the alignment, since we will have been
3244 coming from ARM mode, which is word-aligned. */
3245 record_alignment (now_seg, 1);
3246 }
6057a28f 3247 mapping_state (MAP_THUMB);
b99bd4ef
NC
3248 break;
3249
3250 case 32:
3251 if (thumb_mode)
3252 {
03b1477f 3253 if ((cpu_variant & ARM_ALL) == ARM_EXT_V4T)
b99bd4ef
NC
3254 as_bad (_("selected processor does not support ARM opcodes"));
3255
3256 thumb_mode = 0;
3257
3258 if (!need_pass_2)
cc8a6dd0 3259 frag_align (2, 0, 0);
b99bd4ef 3260
cc8a6dd0 3261 record_alignment (now_seg, 1);
b99bd4ef 3262 }
6057a28f 3263 mapping_state (MAP_ARM);
b99bd4ef
NC
3264 break;
3265
3266 default:
3267 as_bad (_("invalid instruction size selected (%d)"), width);
3268 }
3269}
3270
3271static void
3272s_arm (ignore)
3273 int ignore ATTRIBUTE_UNUSED;
3274{
3275 opcode_select (32);
3276 demand_empty_rest_of_line ();
3277}
3278
3279static void
3280s_thumb (ignore)
3281 int ignore ATTRIBUTE_UNUSED;
3282{
3283 opcode_select (16);
3284 demand_empty_rest_of_line ();
3285}
3286
3287static void
3288s_code (unused)
3289 int unused ATTRIBUTE_UNUSED;
3290{
3291 register int temp;
3292
3293 temp = get_absolute_expression ();
3294 switch (temp)
3295 {
3296 case 16:
3297 case 32:
3298 opcode_select (temp);
3299 break;
3300
3301 default:
3302 as_bad (_("invalid operand to .code directive (%d) (expecting 16 or 32)"), temp);
3303 }
3304}
3305
3306static void
3307end_of_line (str)
f03698e6 3308 char *str;
b99bd4ef
NC
3309{
3310 skip_whitespace (str);
3311
f03698e6
RE
3312 if (*str != '\0' && !inst.error)
3313 inst.error = _("garbage following instruction");
b99bd4ef
NC
3314}
3315
3316static int
3317skip_past_comma (str)
3318 char ** str;
3319{
3320 char * p = * str, c;
3321 int comma = 0;
3322
3323 while ((c = *p) == ' ' || c == ',')
3324 {
3325 p++;
3326 if (c == ',' && comma++)
3327 return FAIL;
3328 }
3329
3330 if (c == '\0')
3331 return FAIL;
3332
3333 *str = p;
3334 return comma ? SUCCESS : FAIL;
3335}
3336
3337/* A standard register must be given at this point.
3338 SHIFT is the place to put it in inst.instruction.
3339 Restores input start point on error.
3340 Returns the reg#, or FAIL. */
3341
3342static int
3343reg_required_here (str, shift)
3344 char ** str;
3345 int shift;
3346{
3347 static char buff [128]; /* XXX */
3348 int reg;
3349 char * start = * str;
3350
6c43fab6 3351 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_RN].htab)) != FAIL)
b99bd4ef
NC
3352 {
3353 if (shift >= 0)
3354 inst.instruction |= reg << shift;
3355 return reg;
3356 }
3357
3358 /* Restore the start point, we may have got a reg of the wrong class. */
3359 *str = start;
3360
3361 /* In the few cases where we might be able to accept something else
3362 this error can be overridden. */
f03698e6 3363 sprintf (buff, _("register expected, not '%.100s'"), start);
b99bd4ef
NC
3364 inst.error = buff;
3365
3366 return FAIL;
3367}
3368
5a6c6817 3369/* A Intel Wireless MMX technology register
e16bb312
NC
3370 must be given at this point.
3371 Shift is the place to put it in inst.instruction.
3372 Restores input start point on err.
3373 Returns the reg#, or FAIL. */
3374
3375static int
3376wreg_required_here (str, shift, reg_type)
3377 char ** str;
3378 int shift;
3379 enum wreg_type reg_type;
3380{
3381 static char buff [128];
3382 int reg;
3383 char * start = *str;
3384
3385 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_IWMMXT].htab)) != FAIL)
3386 {
3387 if (wr_register (reg)
3388 && (reg_type == IWMMXT_REG_WR || reg_type == IWMMXT_REG_WR_OR_WC))
3389 {
3390 if (shift >= 0)
3391 inst.instruction |= (reg ^ WR_PREFIX) << shift;
3392 return reg;
3393 }
3394 else if (wc_register (reg)
3395 && (reg_type == IWMMXT_REG_WC || reg_type == IWMMXT_REG_WR_OR_WC))
3396 {
3397 if (shift >= 0)
3398 inst.instruction |= (reg ^ WC_PREFIX) << shift;
3399 return reg;
3400 }
3401 else if ((wcg_register (reg) && reg_type == IWMMXT_REG_WCG))
3402 {
3403 if (shift >= 0)
3404 inst.instruction |= ((reg ^ WC_PREFIX) - 8) << shift;
3405 return reg;
3406 }
3407 }
3408
3409 /* Restore the start point, we may have got a reg of the wrong class. */
3410 *str = start;
3411
3412 /* In the few cases where we might be able to accept
3413 something else this error can be overridden. */
5a6c6817 3414 sprintf (buff, _("Intel Wireless MMX technology register expected, not '%.100s'"), start);
e16bb312
NC
3415 inst.error = buff;
3416
3417 return FAIL;
3418}
3419
05d2d07e 3420static const struct asm_psr *
b99bd4ef
NC
3421arm_psr_parse (ccp)
3422 register char ** ccp;
3423{
3424 char * start = * ccp;
3425 char c;
3426 char * p;
05d2d07e 3427 const struct asm_psr * psr;
b99bd4ef
NC
3428
3429 p = start;
3430
3431 /* Skip to the end of the next word in the input stream. */
3432 do
3433 {
3434 c = *p++;
3435 }
3882b010 3436 while (ISALPHA (c) || c == '_');
b99bd4ef
NC
3437
3438 /* Terminate the word. */
3439 *--p = 0;
3440
3441 /* CPSR's and SPSR's can now be lowercase. This is just a convenience
3442 feature for ease of use and backwards compatibility. */
3443 if (!strncmp (start, "cpsr", 4))
3444 strncpy (start, "CPSR", 4);
3445 else if (!strncmp (start, "spsr", 4))
3446 strncpy (start, "SPSR", 4);
3447
3448 /* Now locate the word in the psr hash table. */
05d2d07e 3449 psr = (const struct asm_psr *) hash_find (arm_psr_hsh, start);
b99bd4ef
NC
3450
3451 /* Restore the input stream. */
3452 *p = c;
3453
3454 /* If we found a valid match, advance the
3455 stream pointer past the end of the word. */
3456 *ccp = p;
3457
3458 return psr;
3459}
3460
3461/* Parse the input looking for a PSR flag. */
3462
3463static int
3464psr_required_here (str)
3465 char ** str;
3466{
3467 char * start = * str;
05d2d07e 3468 const struct asm_psr * psr;
b99bd4ef
NC
3469
3470 psr = arm_psr_parse (str);
3471
3472 if (psr)
3473 {
3474 /* If this is the SPSR that is being modified, set the R bit. */
3475 if (! psr->cpsr)
3476 inst.instruction |= SPSR_BIT;
3477
3478 /* Set the psr flags in the MSR instruction. */
3479 inst.instruction |= psr->field << PSR_SHIFT;
3480
3481 return SUCCESS;
3482 }
3483
3484 /* In the few cases where we might be able to accept
3485 something else this error can be overridden. */
3486 inst.error = _("flag for {c}psr instruction expected");
3487
3488 /* Restore the start point. */
3489 *str = start;
3490 return FAIL;
3491}
3492
3493static int
3494co_proc_number (str)
6c43fab6 3495 char **str;
b99bd4ef
NC
3496{
3497 int processor, pchar;
6c43fab6 3498 char *start;
b99bd4ef 3499
6c43fab6
RE
3500 skip_whitespace (*str);
3501 start = *str;
b99bd4ef
NC
3502
3503 /* The data sheet seems to imply that just a number on its own is valid
3504 here, but the RISC iX assembler seems to accept a prefix 'p'. We will
3505 accept either. */
6c43fab6
RE
3506 if ((processor = arm_reg_parse (str, all_reg_maps[REG_TYPE_CP].htab))
3507 == FAIL)
b99bd4ef 3508 {
6c43fab6
RE
3509 *str = start;
3510
3511 pchar = *(*str)++;
3512 if (pchar >= '0' && pchar <= '9')
b99bd4ef 3513 {
6c43fab6
RE
3514 processor = pchar - '0';
3515 if (**str >= '0' && **str <= '9')
b99bd4ef 3516 {
6c43fab6
RE
3517 processor = processor * 10 + *(*str)++ - '0';
3518 if (processor > 15)
3519 {
f03698e6 3520 inst.error = _("illegal co-processor number");
6c43fab6
RE
3521 return FAIL;
3522 }
b99bd4ef
NC
3523 }
3524 }
6c43fab6
RE
3525 else
3526 {
376eb240 3527 inst.error = all_reg_maps[REG_TYPE_CP].expected;
6c43fab6
RE
3528 return FAIL;
3529 }
b99bd4ef
NC
3530 }
3531
3532 inst.instruction |= processor << 8;
3533 return SUCCESS;
3534}
3535
3536static int
3537cp_opc_expr (str, where, length)
3538 char ** str;
3539 int where;
3540 int length;
3541{
3542 expressionS expr;
3543
3544 skip_whitespace (* str);
3545
3546 memset (&expr, '\0', sizeof (expr));
3547
3548 if (my_get_expression (&expr, str))
3549 return FAIL;
3550 if (expr.X_op != O_constant)
3551 {
3552 inst.error = _("bad or missing expression");
3553 return FAIL;
3554 }
3555
3556 if ((expr.X_add_number & ((1 << length) - 1)) != expr.X_add_number)
3557 {
3558 inst.error = _("immediate co-processor expression too large");
3559 return FAIL;
3560 }
3561
3562 inst.instruction |= expr.X_add_number << where;
3563 return SUCCESS;
3564}
3565
3566static int
3567cp_reg_required_here (str, where)
3568 char ** str;
3569 int where;
3570{
3571 int reg;
3572 char * start = *str;
3573
6c43fab6 3574 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_CN].htab)) != FAIL)
b99bd4ef 3575 {
b99bd4ef
NC
3576 inst.instruction |= reg << where;
3577 return reg;
3578 }
3579
3580 /* In the few cases where we might be able to accept something else
3581 this error can be overridden. */
376eb240 3582 inst.error = all_reg_maps[REG_TYPE_CN].expected;
b99bd4ef
NC
3583
3584 /* Restore the start point. */
3585 *str = start;
3586 return FAIL;
3587}
3588
3589static int
3590fp_reg_required_here (str, where)
3591 char ** str;
3592 int where;
3593{
3594 int reg;
3595 char * start = * str;
3596
6c43fab6 3597 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_FN].htab)) != FAIL)
b99bd4ef 3598 {
b99bd4ef
NC
3599 inst.instruction |= reg << where;
3600 return reg;
3601 }
3602
3603 /* In the few cases where we might be able to accept something else
3604 this error can be overridden. */
376eb240 3605 inst.error = all_reg_maps[REG_TYPE_FN].expected;
b99bd4ef
NC
3606
3607 /* Restore the start point. */
3608 *str = start;
3609 return FAIL;
3610}
3611
3612static int
3613cp_address_offset (str)
3614 char ** str;
3615{
3616 int offset;
3617
3618 skip_whitespace (* str);
3619
3620 if (! is_immediate_prefix (**str))
3621 {
3622 inst.error = _("immediate expression expected");
3623 return FAIL;
3624 }
3625
3626 (*str)++;
3627
3628 if (my_get_expression (& inst.reloc.exp, str))
3629 return FAIL;
3630
3631 if (inst.reloc.exp.X_op == O_constant)
3632 {
3633 offset = inst.reloc.exp.X_add_number;
3634
3635 if (offset & 3)
3636 {
3637 inst.error = _("co-processor address must be word aligned");
3638 return FAIL;
3639 }
3640
3641 if (offset > 1023 || offset < -1023)
3642 {
3643 inst.error = _("offset too large");
3644 return FAIL;
3645 }
3646
3647 if (offset >= 0)
3648 inst.instruction |= INDEX_UP;
3649 else
3650 offset = -offset;
3651
3652 inst.instruction |= offset >> 2;
3653 }
3654 else
3655 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
3656
3657 return SUCCESS;
3658}
3659
3660static int
bfae80f2 3661cp_address_required_here (str, wb_ok)
b99bd4ef 3662 char ** str;
bfae80f2 3663 int wb_ok;
b99bd4ef
NC
3664{
3665 char * p = * str;
3666 int pre_inc = 0;
3667 int write_back = 0;
3668
3669 if (*p == '[')
3670 {
3671 int reg;
3672
3673 p++;
3674 skip_whitespace (p);
3675
3676 if ((reg = reg_required_here (& p, 16)) == FAIL)
3677 return FAIL;
3678
3679 skip_whitespace (p);
3680
3681 if (*p == ']')
3682 {
3683 p++;
3684
f02232aa
NC
3685 skip_whitespace (p);
3686
3687 if (*p == '\0')
b99bd4ef 3688 {
f02232aa
NC
3689 /* As an extension to the official ARM syntax we allow:
3690
3691 [Rn]
3692
3693 as a short hand for:
3694
3695 [Rn,#0] */
3696 inst.instruction |= PRE_INDEX | INDEX_UP;
3697 *str = p;
3698 return SUCCESS;
3699 }
3700
3701 if (skip_past_comma (& p) == FAIL)
3702 {
3703 inst.error = _("comma expected after closing square bracket");
3704 return FAIL;
3705 }
b99bd4ef 3706
f02232aa
NC
3707 skip_whitespace (p);
3708
3709 if (*p == '#')
3710 {
3711 if (wb_ok)
b99bd4ef 3712 {
f02232aa
NC
3713 /* [Rn], #expr */
3714 write_back = WRITE_BACK;
3715
3716 if (reg == REG_PC)
3717 {
3718 inst.error = _("pc may not be used in post-increment");
3719 return FAIL;
3720 }
3721
3722 if (cp_address_offset (& p) == FAIL)
3723 return FAIL;
b99bd4ef 3724 }
f02232aa
NC
3725 else
3726 pre_inc = PRE_INDEX | INDEX_UP;
3727 }
3728 else if (*p == '{')
3729 {
3730 int option;
b99bd4ef 3731
f02232aa
NC
3732 /* [Rn], {<expr>} */
3733 p++;
3734
3735 skip_whitespace (p);
3736
3737 if (my_get_expression (& inst.reloc.exp, & p))
b99bd4ef 3738 return FAIL;
f02232aa
NC
3739
3740 if (inst.reloc.exp.X_op == O_constant)
3741 {
3742 option = inst.reloc.exp.X_add_number;
3743
3744 if (option > 255 || option < 0)
3745 {
3746 inst.error = _("'option' field too large");
3747 return FAIL;
3748 }
3749
3750 skip_whitespace (p);
3751
3752 if (*p != '}')
3753 {
3754 inst.error = _("'}' expected at end of 'option' field");
3755 return FAIL;
3756 }
3757 else
3758 {
3759 p++;
3760 inst.instruction |= option;
3761 inst.instruction |= INDEX_UP;
3762 }
3763 }
3764 else
3765 {
3766 inst.error = _("non-constant expressions for 'option' field not supported");
3767 return FAIL;
3768 }
b99bd4ef
NC
3769 }
3770 else
f02232aa
NC
3771 {
3772 inst.error = _("# or { expected after comma");
3773 return FAIL;
3774 }
b99bd4ef
NC
3775 }
3776 else
3777 {
3778 /* '['Rn, #expr']'[!] */
3779
3780 if (skip_past_comma (& p) == FAIL)
3781 {
3782 inst.error = _("pre-indexed expression expected");
3783 return FAIL;
3784 }
3785
3786 pre_inc = PRE_INDEX;
3787
3788 if (cp_address_offset (& p) == FAIL)
3789 return FAIL;
3790
3791 skip_whitespace (p);
3792
3793 if (*p++ != ']')
3794 {
3795 inst.error = _("missing ]");
3796 return FAIL;
3797 }
3798
3799 skip_whitespace (p);
3800
bfae80f2 3801 if (wb_ok && *p == '!')
b99bd4ef
NC
3802 {
3803 if (reg == REG_PC)
3804 {
3805 inst.error = _("pc may not be used with write-back");
3806 return FAIL;
3807 }
3808
3809 p++;
3810 write_back = WRITE_BACK;
3811 }
3812 }
3813 }
3814 else
3815 {
3816 if (my_get_expression (&inst.reloc.exp, &p))
3817 return FAIL;
3818
3819 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
3820 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
3821 inst.reloc.pc_rel = 1;
3822 inst.instruction |= (REG_PC << 16);
3823 pre_inc = PRE_INDEX;
3824 }
3825
3826 inst.instruction |= write_back | pre_inc;
3827 *str = p;
3828 return SUCCESS;
3829}
3830
e16bb312
NC
3831static int
3832cp_byte_address_offset (str)
3833 char ** str;
3834{
3835 int offset;
3836
3837 skip_whitespace (* str);
3838
3839 if (! is_immediate_prefix (**str))
3840 {
3841 inst.error = _("immediate expression expected");
3842 return FAIL;
3843 }
3844
3845 (*str)++;
3846
3847 if (my_get_expression (& inst.reloc.exp, str))
3848 return FAIL;
3849
3850 if (inst.reloc.exp.X_op == O_constant)
3851 {
3852 offset = inst.reloc.exp.X_add_number;
3853
3854 if (offset > 255 || offset < -255)
3855 {
3856 inst.error = _("offset too large");
3857 return FAIL;
3858 }
3859
3860 if (offset >= 0)
3861 inst.instruction |= INDEX_UP;
3862 else
3863 offset = -offset;
3864
3865 inst.instruction |= offset;
3866 }
3867 else
3868 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM_S2;
3869
3870 return SUCCESS;
3871}
3872
3873static int
3874cp_byte_address_required_here (str)
3875 char ** str;
3876{
3877 char * p = * str;
3878 int pre_inc = 0;
3879 int write_back = 0;
3880
3881 if (*p == '[')
3882 {
3883 int reg;
3884
3885 p++;
3886 skip_whitespace (p);
3887
3888 if ((reg = reg_required_here (& p, 16)) == FAIL)
3889 return FAIL;
3890
3891 skip_whitespace (p);
3892
3893 if (*p == ']')
3894 {
3895 p++;
3896
3897 if (skip_past_comma (& p) == SUCCESS)
3898 {
3899 /* [Rn], #expr */
3900 write_back = WRITE_BACK;
3901
3902 if (reg == REG_PC)
3903 {
3904 inst.error = _("pc may not be used in post-increment");
3905 return FAIL;
3906 }
3907
3908 if (cp_byte_address_offset (& p) == FAIL)
3909 return FAIL;
3910 }
3911 else
3912 pre_inc = PRE_INDEX | INDEX_UP;
3913 }
3914 else
3915 {
3916 /* '['Rn, #expr']'[!] */
3917
3918 if (skip_past_comma (& p) == FAIL)
3919 {
3920 inst.error = _("pre-indexed expression expected");
3921 return FAIL;
3922 }
3923
3924 pre_inc = PRE_INDEX;
3925
3926 if (cp_byte_address_offset (& p) == FAIL)
3927 return FAIL;
3928
3929 skip_whitespace (p);
3930
3931 if (*p++ != ']')
3932 {
3933 inst.error = _("missing ]");
3934 return FAIL;
3935 }
3936
3937 skip_whitespace (p);
3938
3939 if (*p == '!')
3940 {
3941 if (reg == REG_PC)
3942 {
3943 inst.error = _("pc may not be used with write-back");
3944 return FAIL;
3945 }
3946
3947 p++;
3948 write_back = WRITE_BACK;
3949 }
3950 }
3951 }
3952 else
3953 {
3954 if (my_get_expression (&inst.reloc.exp, &p))
3955 return FAIL;
3956
3957 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM_S2;
3958 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
3959 inst.reloc.pc_rel = 1;
3960 inst.instruction |= (REG_PC << 16);
3961 pre_inc = PRE_INDEX;
3962 }
3963
3964 inst.instruction |= write_back | pre_inc;
3965 *str = p;
3966 return SUCCESS;
3967}
3968
b99bd4ef 3969static void
f2b7cb0a 3970do_empty (str)
b99bd4ef 3971 char * str;
b99bd4ef
NC
3972{
3973 /* Do nothing really. */
b99bd4ef 3974 end_of_line (str);
b99bd4ef
NC
3975}
3976
3977static void
f2b7cb0a 3978do_mrs (str)
b99bd4ef 3979 char *str;
b99bd4ef
NC
3980{
3981 int skip = 0;
3982
3983 /* Only one syntax. */
3984 skip_whitespace (str);
3985
3986 if (reg_required_here (&str, 12) == FAIL)
3987 {
3988 inst.error = BAD_ARGS;
3989 return;
3990 }
3991
3992 if (skip_past_comma (&str) == FAIL)
3993 {
3994 inst.error = _("comma expected after register name");
3995 return;
3996 }
3997
3998 skip_whitespace (str);
3999
4000 if ( strcmp (str, "CPSR") == 0
4001 || strcmp (str, "SPSR") == 0
2d2255b5 4002 /* Lower case versions for backwards compatibility. */
b99bd4ef
NC
4003 || strcmp (str, "cpsr") == 0
4004 || strcmp (str, "spsr") == 0)
4005 skip = 4;
4006
2d2255b5 4007 /* This is for backwards compatibility with older toolchains. */
b99bd4ef
NC
4008 else if ( strcmp (str, "cpsr_all") == 0
4009 || strcmp (str, "spsr_all") == 0)
4010 skip = 8;
4011 else
4012 {
f03698e6 4013 inst.error = _("CPSR or SPSR expected");
b99bd4ef
NC
4014 return;
4015 }
4016
4017 if (* str == 's' || * str == 'S')
4018 inst.instruction |= SPSR_BIT;
4019 str += skip;
4020
b99bd4ef
NC
4021 end_of_line (str);
4022}
4023
4024/* Two possible forms:
4025 "{C|S}PSR_<field>, Rm",
4026 "{C|S}PSR_f, #expression". */
4027
4028static void
f2b7cb0a 4029do_msr (str)
b99bd4ef 4030 char * str;
b99bd4ef
NC
4031{
4032 skip_whitespace (str);
4033
4034 if (psr_required_here (& str) == FAIL)
4035 return;
4036
4037 if (skip_past_comma (& str) == FAIL)
4038 {
4039 inst.error = _("comma missing after psr flags");
4040 return;
4041 }
4042
4043 skip_whitespace (str);
4044
4045 if (reg_required_here (& str, 0) != FAIL)
4046 {
4047 inst.error = NULL;
b99bd4ef
NC
4048 end_of_line (str);
4049 return;
4050 }
4051
4052 if (! is_immediate_prefix (* str))
4053 {
4054 inst.error =
4055 _("only a register or immediate value can follow a psr flag");
4056 return;
4057 }
4058
4059 str ++;
4060 inst.error = NULL;
4061
4062 if (my_get_expression (& inst.reloc.exp, & str))
4063 {
4064 inst.error =
4065 _("only a register or immediate value can follow a psr flag");
4066 return;
4067 }
4068
4069#if 0 /* The first edition of the ARM architecture manual stated that
4070 writing anything other than the flags with an immediate operation
4071 had UNPREDICTABLE effects. This constraint was removed in the
4072 second edition of the specification. */
4073 if ((cpu_variant & ARM_EXT_V5) != ARM_EXT_V5
4074 && inst.instruction & ((PSR_c | PSR_x | PSR_s) << PSR_SHIFT))
4075 {
4076 inst.error = _("immediate value cannot be used to set this field");
4077 return;
4078 }
4079#endif
4080
f2b7cb0a 4081 inst.instruction |= INST_IMMEDIATE;
b99bd4ef
NC
4082
4083 if (inst.reloc.exp.X_add_symbol)
4084 {
4085 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
4086 inst.reloc.pc_rel = 0;
4087 }
4088 else
4089 {
4090 unsigned value = validate_immediate (inst.reloc.exp.X_add_number);
4091
4092 if (value == (unsigned) FAIL)
4093 {
f03698e6 4094 inst.error = _("invalid constant");
b99bd4ef
NC
4095 return;
4096 }
4097
4098 inst.instruction |= value;
4099 }
4100
4101 inst.error = NULL;
b99bd4ef
NC
4102 end_of_line (str);
4103}
4104
4105/* Long Multiply Parser
4106 UMULL RdLo, RdHi, Rm, Rs
4107 SMULL RdLo, RdHi, Rm, Rs
4108 UMLAL RdLo, RdHi, Rm, Rs
4109 SMLAL RdLo, RdHi, Rm, Rs. */
4110
4111static void
f2b7cb0a 4112do_mull (str)
b99bd4ef 4113 char * str;
b99bd4ef
NC
4114{
4115 int rdlo, rdhi, rm, rs;
4116
4117 /* Only one format "rdlo, rdhi, rm, rs". */
4118 skip_whitespace (str);
4119
4120 if ((rdlo = reg_required_here (&str, 12)) == FAIL)
4121 {
4122 inst.error = BAD_ARGS;
4123 return;
4124 }
4125
4126 if (skip_past_comma (&str) == FAIL
4127 || (rdhi = reg_required_here (&str, 16)) == FAIL)
4128 {
4129 inst.error = BAD_ARGS;
4130 return;
4131 }
4132
4133 if (skip_past_comma (&str) == FAIL
4134 || (rm = reg_required_here (&str, 0)) == FAIL)
4135 {
4136 inst.error = BAD_ARGS;
4137 return;
4138 }
4139
4140 /* rdhi, rdlo and rm must all be different. */
4141 if (rdlo == rdhi || rdlo == rm || rdhi == rm)
4142 as_tsktsk (_("rdhi, rdlo and rm must all be different"));
4143
4144 if (skip_past_comma (&str) == FAIL
4145 || (rs = reg_required_here (&str, 8)) == FAIL)
4146 {
4147 inst.error = BAD_ARGS;
4148 return;
4149 }
4150
4151 if (rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC)
4152 {
4153 inst.error = BAD_PC;
4154 return;
4155 }
4156
b99bd4ef 4157 end_of_line (str);
b99bd4ef
NC
4158}
4159
4160static void
f2b7cb0a 4161do_mul (str)
b99bd4ef 4162 char * str;
b99bd4ef
NC
4163{
4164 int rd, rm;
4165
4166 /* Only one format "rd, rm, rs". */
4167 skip_whitespace (str);
4168
4169 if ((rd = reg_required_here (&str, 16)) == FAIL)
4170 {
4171 inst.error = BAD_ARGS;
4172 return;
4173 }
4174
4175 if (rd == REG_PC)
4176 {
4177 inst.error = BAD_PC;
4178 return;
4179 }
4180
4181 if (skip_past_comma (&str) == FAIL
4182 || (rm = reg_required_here (&str, 0)) == FAIL)
4183 {
4184 inst.error = BAD_ARGS;
4185 return;
4186 }
4187
4188 if (rm == REG_PC)
4189 {
4190 inst.error = BAD_PC;
4191 return;
4192 }
4193
4194 if (rm == rd)
4195 as_tsktsk (_("rd and rm should be different in mul"));
4196
4197 if (skip_past_comma (&str) == FAIL
4198 || (rm = reg_required_here (&str, 8)) == FAIL)
4199 {
4200 inst.error = BAD_ARGS;
4201 return;
4202 }
4203
4204 if (rm == REG_PC)
4205 {
4206 inst.error = BAD_PC;
4207 return;
4208 }
4209
b99bd4ef 4210 end_of_line (str);
b99bd4ef
NC
4211}
4212
4213static void
f2b7cb0a 4214do_mla (str)
b99bd4ef 4215 char * str;
b99bd4ef
NC
4216{
4217 int rd, rm;
4218
4219 /* Only one format "rd, rm, rs, rn". */
4220 skip_whitespace (str);
4221
4222 if ((rd = reg_required_here (&str, 16)) == FAIL)
4223 {
4224 inst.error = BAD_ARGS;
4225 return;
4226 }
4227
4228 if (rd == REG_PC)
4229 {
4230 inst.error = BAD_PC;
4231 return;
4232 }
4233
4234 if (skip_past_comma (&str) == FAIL
4235 || (rm = reg_required_here (&str, 0)) == FAIL)
4236 {
4237 inst.error = BAD_ARGS;
4238 return;
4239 }
4240
4241 if (rm == REG_PC)
4242 {
4243 inst.error = BAD_PC;
4244 return;
4245 }
4246
4247 if (rm == rd)
4248 as_tsktsk (_("rd and rm should be different in mla"));
4249
4250 if (skip_past_comma (&str) == FAIL
4251 || (rd = reg_required_here (&str, 8)) == FAIL
4252 || skip_past_comma (&str) == FAIL
4253 || (rm = reg_required_here (&str, 12)) == FAIL)
4254 {
4255 inst.error = BAD_ARGS;
4256 return;
4257 }
4258
4259 if (rd == REG_PC || rm == REG_PC)
4260 {
4261 inst.error = BAD_PC;
4262 return;
4263 }
4264
b99bd4ef 4265 end_of_line (str);
b99bd4ef
NC
4266}
4267
4268/* Expects *str -> the characters "acc0", possibly with leading blanks.
4269 Advances *str to the next non-alphanumeric.
4270 Returns 0, or else FAIL (in which case sets inst.error).
4271
4272 (In a future XScale, there may be accumulators other than zero.
4273 At that time this routine and its callers can be upgraded to suit.) */
4274
4275static int
4276accum0_required_here (str)
4277 char ** str;
4278{
4279 static char buff [128]; /* Note the address is taken. Hence, static. */
4280 char * p = * str;
4281 char c;
4282 int result = 0; /* The accum number. */
4283
4284 skip_whitespace (p);
4285
4286 *str = p; /* Advance caller's string pointer too. */
4287 c = *p++;
3882b010 4288 while (ISALNUM (c))
b99bd4ef
NC
4289 c = *p++;
4290
4291 *--p = 0; /* Aap nul into input buffer at non-alnum. */
4292
4293 if (! ( streq (*str, "acc0") || streq (*str, "ACC0")))
4294 {
4295 sprintf (buff, _("acc0 expected, not '%.100s'"), *str);
4296 inst.error = buff;
4297 result = FAIL;
4298 }
4299
4300 *p = c; /* Unzap. */
4301 *str = p; /* Caller's string pointer to after match. */
4302 return result;
4303}
4304
4305/* Expects **str -> after a comma. May be leading blanks.
4306 Advances *str, recognizing a load mode, and setting inst.instruction.
4307 Returns rn, or else FAIL (in which case may set inst.error
4308 and not advance str)
4309
4310 Note: doesn't know Rd, so no err checks that require such knowledge. */
4311
4312static int
4313ld_mode_required_here (string)
4314 char ** string;
4315{
4316 char * str = * string;
4317 int rn;
4318 int pre_inc = 0;
4319
4320 skip_whitespace (str);
4321
4322 if (* str == '[')
4323 {
4324 str++;
4325
4326 skip_whitespace (str);
4327
4328 if ((rn = reg_required_here (& str, 16)) == FAIL)
4329 return FAIL;
4330
4331 skip_whitespace (str);
4332
4333 if (* str == ']')
4334 {
4335 str ++;
4336
4337 if (skip_past_comma (& str) == SUCCESS)
4338 {
4339 /* [Rn],... (post inc) */
90e4755a 4340 if (ldst_extend_v4 (&str) == FAIL)
b99bd4ef
NC
4341 return FAIL;
4342 }
4343 else /* [Rn] */
4344 {
cc8a6dd0 4345 skip_whitespace (str);
b99bd4ef 4346
cc8a6dd0
KH
4347 if (* str == '!')
4348 {
4349 str ++;
4350 inst.instruction |= WRITE_BACK;
4351 }
b99bd4ef
NC
4352
4353 inst.instruction |= INDEX_UP | HWOFFSET_IMM;
4354 pre_inc = 1;
4355 }
4356 }
4357 else /* [Rn,...] */
4358 {
4359 if (skip_past_comma (& str) == FAIL)
4360 {
4361 inst.error = _("pre-indexed expression expected");
4362 return FAIL;
4363 }
4364
4365 pre_inc = 1;
4366
90e4755a 4367 if (ldst_extend_v4 (&str) == FAIL)
b99bd4ef
NC
4368 return FAIL;
4369
4370 skip_whitespace (str);
4371
4372 if (* str ++ != ']')
4373 {
4374 inst.error = _("missing ]");
4375 return FAIL;
4376 }
4377
4378 skip_whitespace (str);
4379
4380 if (* str == '!')
4381 {
4382 str ++;
4383 inst.instruction |= WRITE_BACK;
4384 }
4385 }
4386 }
4387 else if (* str == '=') /* ldr's "r,=label" syntax */
4388 /* We should never reach here, because <text> = <expression> is
4389 caught gas/read.c read_a_source_file() as a .set operation. */
4390 return FAIL;
4391 else /* PC +- 8 bit immediate offset. */
4392 {
4393 if (my_get_expression (& inst.reloc.exp, & str))
4394 return FAIL;
4395
4396 inst.instruction |= HWOFFSET_IMM; /* The I bit. */
4397 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
4398 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
4399 inst.reloc.pc_rel = 1;
4400 inst.instruction |= (REG_PC << 16);
4401
4402 rn = REG_PC;
4403 pre_inc = 1;
4404 }
4405
4406 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
4407 * string = str;
4408
4409 return rn;
4410}
4411
4412/* ARM V5E (El Segundo) signed-multiply-accumulate (argument parse)
4413 SMLAxy{cond} Rd,Rm,Rs,Rn
4414 SMLAWy{cond} Rd,Rm,Rs,Rn
4415 Error if any register is R15. */
4416
4417static void
f2b7cb0a 4418do_smla (str)
b99bd4ef 4419 char * str;
b99bd4ef
NC
4420{
4421 int rd, rm, rs, rn;
4422
4423 skip_whitespace (str);
4424
4425 if ((rd = reg_required_here (& str, 16)) == FAIL
4426 || skip_past_comma (& str) == FAIL
4427 || (rm = reg_required_here (& str, 0)) == FAIL
4428 || skip_past_comma (& str) == FAIL
4429 || (rs = reg_required_here (& str, 8)) == FAIL
4430 || skip_past_comma (& str) == FAIL
4431 || (rn = reg_required_here (& str, 12)) == FAIL)
4432 inst.error = BAD_ARGS;
4433
4434 else if (rd == REG_PC || rm == REG_PC || rs == REG_PC || rn == REG_PC)
4435 inst.error = BAD_PC;
4436
b99bd4ef
NC
4437 else
4438 end_of_line (str);
4439}
4440
4441/* ARM V5E (El Segundo) signed-multiply-accumulate-long (argument parse)
4442 SMLALxy{cond} Rdlo,Rdhi,Rm,Rs
4443 Error if any register is R15.
4444 Warning if Rdlo == Rdhi. */
4445
4446static void
f2b7cb0a 4447do_smlal (str)
b99bd4ef 4448 char * str;
b99bd4ef
NC
4449{
4450 int rdlo, rdhi, rm, rs;
4451
4452 skip_whitespace (str);
4453
4454 if ((rdlo = reg_required_here (& str, 12)) == FAIL
4455 || skip_past_comma (& str) == FAIL
4456 || (rdhi = reg_required_here (& str, 16)) == FAIL
4457 || skip_past_comma (& str) == FAIL
4458 || (rm = reg_required_here (& str, 0)) == FAIL
4459 || skip_past_comma (& str) == FAIL
4460 || (rs = reg_required_here (& str, 8)) == FAIL)
4461 {
4462 inst.error = BAD_ARGS;
4463 return;
4464 }
4465
4466 if (rdlo == REG_PC || rdhi == REG_PC || rm == REG_PC || rs == REG_PC)
4467 {
4468 inst.error = BAD_PC;
4469 return;
4470 }
4471
4472 if (rdlo == rdhi)
4473 as_tsktsk (_("rdhi and rdlo must be different"));
4474
f2b7cb0a 4475 end_of_line (str);
b99bd4ef
NC
4476}
4477
4478/* ARM V5E (El Segundo) signed-multiply (argument parse)
4479 SMULxy{cond} Rd,Rm,Rs
4480 Error if any register is R15. */
4481
4482static void
f2b7cb0a 4483do_smul (str)
b99bd4ef 4484 char * str;
b99bd4ef
NC
4485{
4486 int rd, rm, rs;
4487
4488 skip_whitespace (str);
4489
4490 if ((rd = reg_required_here (& str, 16)) == FAIL
4491 || skip_past_comma (& str) == FAIL
4492 || (rm = reg_required_here (& str, 0)) == FAIL
4493 || skip_past_comma (& str) == FAIL
4494 || (rs = reg_required_here (& str, 8)) == FAIL)
4495 inst.error = BAD_ARGS;
4496
4497 else if (rd == REG_PC || rm == REG_PC || rs == REG_PC)
4498 inst.error = BAD_PC;
4499
b99bd4ef
NC
4500 else
4501 end_of_line (str);
4502}
4503
4504/* ARM V5E (El Segundo) saturating-add/subtract (argument parse)
4505 Q[D]{ADD,SUB}{cond} Rd,Rm,Rn
4506 Error if any register is R15. */
4507
4508static void
f2b7cb0a 4509do_qadd (str)
b99bd4ef 4510 char * str;
b99bd4ef
NC
4511{
4512 int rd, rm, rn;
4513
4514 skip_whitespace (str);
4515
4516 if ((rd = reg_required_here (& str, 12)) == FAIL
4517 || skip_past_comma (& str) == FAIL
4518 || (rm = reg_required_here (& str, 0)) == FAIL
4519 || skip_past_comma (& str) == FAIL
4520 || (rn = reg_required_here (& str, 16)) == FAIL)
4521 inst.error = BAD_ARGS;
4522
4523 else if (rd == REG_PC || rm == REG_PC || rn == REG_PC)
4524 inst.error = BAD_PC;
4525
b99bd4ef
NC
4526 else
4527 end_of_line (str);
4528}
4529
4530/* ARM V5E (el Segundo)
4531 MCRRcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
4532 MRRCcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
4533
4534 These are equivalent to the XScale instructions MAR and MRA,
4535 respectively, when coproc == 0, opcode == 0, and CRm == 0.
4536
4537 Result unpredicatable if Rd or Rn is R15. */
4538
4539static void
f2b7cb0a 4540do_co_reg2c (str)
b99bd4ef 4541 char * str;
b99bd4ef
NC
4542{
4543 int rd, rn;
4544
4545 skip_whitespace (str);
4546
4547 if (co_proc_number (& str) == FAIL)
4548 {
4549 if (!inst.error)
4550 inst.error = BAD_ARGS;
4551 return;
4552 }
4553
4554 if (skip_past_comma (& str) == FAIL
4555 || cp_opc_expr (& str, 4, 4) == FAIL)
4556 {
4557 if (!inst.error)
4558 inst.error = BAD_ARGS;
4559 return;
4560 }
4561
4562 if (skip_past_comma (& str) == FAIL
4563 || (rd = reg_required_here (& str, 12)) == FAIL)
4564 {
4565 if (!inst.error)
4566 inst.error = BAD_ARGS;
4567 return;
4568 }
4569
4570 if (skip_past_comma (& str) == FAIL
4571 || (rn = reg_required_here (& str, 16)) == FAIL)
4572 {
4573 if (!inst.error)
4574 inst.error = BAD_ARGS;
4575 return;
4576 }
4577
09d92015
MM
4578 /* Unpredictable result if rd or rn is R15. */
4579 if (rd == REG_PC || rn == REG_PC)
4580 as_tsktsk
4581 (_("Warning: instruction unpredictable when using r15"));
4582
4583 if (skip_past_comma (& str) == FAIL
4584 || cp_reg_required_here (& str, 0) == FAIL)
4585 {
4586 if (!inst.error)
4587 inst.error = BAD_ARGS;
4588 return;
4589 }
4590
4591 end_of_line (str);
4592}
4593
4594/* ARM V5 count-leading-zeroes instruction (argument parse)
4595 CLZ{<cond>} <Rd>, <Rm>
4596 Condition defaults to COND_ALWAYS.
4597 Error if Rd or Rm are R15. */
4598
4599static void
4600do_clz (str)
4601 char * str;
4602{
4603 int rd, rm;
4604
4605 skip_whitespace (str);
4606
4607 if (((rd = reg_required_here (& str, 12)) == FAIL)
4608 || (skip_past_comma (& str) == FAIL)
4609 || ((rm = reg_required_here (& str, 0)) == FAIL))
4610 inst.error = BAD_ARGS;
4611
4612 else if (rd == REG_PC || rm == REG_PC )
4613 inst.error = BAD_PC;
4614
4615 else
4616 end_of_line (str);
4617}
4618
4619/* ARM V5 (argument parse)
4620 LDC2{L} <coproc>, <CRd>, <addressing mode>
4621 STC2{L} <coproc>, <CRd>, <addressing mode>
4622 Instruction is not conditional, and has 0xf in the condition field.
4623 Otherwise, it's the same as LDC/STC. */
4624
4625static void
4626do_lstc2 (str)
4627 char * str;
4628{
4629 skip_whitespace (str);
4630
4631 if (co_proc_number (& str) == FAIL)
4632 {
4633 if (!inst.error)
4634 inst.error = BAD_ARGS;
4635 }
4636 else if (skip_past_comma (& str) == FAIL
4637 || cp_reg_required_here (& str, 12) == FAIL)
4638 {
4639 if (!inst.error)
4640 inst.error = BAD_ARGS;
4641 }
4642 else if (skip_past_comma (& str) == FAIL
4643 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
4644 {
4645 if (! inst.error)
4646 inst.error = BAD_ARGS;
4647 }
4648 else
4649 end_of_line (str);
4650}
4651
4652/* ARM V5 (argument parse)
4653 CDP2 <coproc>, <opcode_1>, <CRd>, <CRn>, <CRm>, <opcode_2>
4654 Instruction is not conditional, and has 0xf in the condition field.
4655 Otherwise, it's the same as CDP. */
4656
4657static void
4658do_cdp2 (str)
4659 char * str;
4660{
4661 skip_whitespace (str);
4662
4663 if (co_proc_number (& str) == FAIL)
4664 {
4665 if (!inst.error)
4666 inst.error = BAD_ARGS;
4667 return;
4668 }
4669
4670 if (skip_past_comma (& str) == FAIL
4671 || cp_opc_expr (& str, 20,4) == FAIL)
4672 {
4673 if (!inst.error)
4674 inst.error = BAD_ARGS;
4675 return;
4676 }
4677
4678 if (skip_past_comma (& str) == FAIL
4679 || cp_reg_required_here (& str, 12) == FAIL)
4680 {
4681 if (!inst.error)
4682 inst.error = BAD_ARGS;
4683 return;
4684 }
4685
4686 if (skip_past_comma (& str) == FAIL
4687 || cp_reg_required_here (& str, 16) == FAIL)
4688 {
4689 if (!inst.error)
4690 inst.error = BAD_ARGS;
4691 return;
4692 }
4693
4694 if (skip_past_comma (& str) == FAIL
4695 || cp_reg_required_here (& str, 0) == FAIL)
4696 {
4697 if (!inst.error)
4698 inst.error = BAD_ARGS;
4699 return;
4700 }
4701
4702 if (skip_past_comma (& str) == SUCCESS)
4703 {
4704 if (cp_opc_expr (& str, 5, 3) == FAIL)
4705 {
4706 if (!inst.error)
4707 inst.error = BAD_ARGS;
4708 return;
4709 }
4710 }
4711
4712 end_of_line (str);
4713}
4714
4715/* ARM V5 (argument parse)
4716 MCR2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
4717 MRC2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
4718 Instruction is not conditional, and has 0xf in the condition field.
4719 Otherwise, it's the same as MCR/MRC. */
4720
4721static void
4722do_co_reg2 (str)
4723 char * str;
4724{
4725 skip_whitespace (str);
4726
4727 if (co_proc_number (& str) == FAIL)
4728 {
4729 if (!inst.error)
4730 inst.error = BAD_ARGS;
4731 return;
4732 }
4733
4734 if (skip_past_comma (& str) == FAIL
4735 || cp_opc_expr (& str, 21, 3) == FAIL)
4736 {
4737 if (!inst.error)
4738 inst.error = BAD_ARGS;
4739 return;
4740 }
4741
4742 if (skip_past_comma (& str) == FAIL
4743 || reg_required_here (& str, 12) == FAIL)
4744 {
4745 if (!inst.error)
4746 inst.error = BAD_ARGS;
4747 return;
4748 }
4749
4750 if (skip_past_comma (& str) == FAIL
4751 || cp_reg_required_here (& str, 16) == FAIL)
4752 {
4753 if (!inst.error)
4754 inst.error = BAD_ARGS;
4755 return;
4756 }
4757
4758 if (skip_past_comma (& str) == FAIL
4759 || cp_reg_required_here (& str, 0) == FAIL)
4760 {
4761 if (!inst.error)
4762 inst.error = BAD_ARGS;
4763 return;
4764 }
4765
4766 if (skip_past_comma (& str) == SUCCESS)
4767 {
4768 if (cp_opc_expr (& str, 5, 3) == FAIL)
4769 {
4770 if (!inst.error)
4771 inst.error = BAD_ARGS;
4772 return;
4773 }
4774 }
4775
4776 end_of_line (str);
4777}
4778
4779/* ARM v5TEJ. Jump to Jazelle code. */
4780static void
4781do_bxj (str)
4782 char * str;
4783{
4784 int reg;
4785
4786 skip_whitespace (str);
4787
4788 if ((reg = reg_required_here (&str, 0)) == FAIL)
4789 {
4790 inst.error = BAD_ARGS;
4791 return;
4792 }
4793
4794 /* Note - it is not illegal to do a "bxj pc". Useless, but not illegal. */
4795 if (reg == REG_PC)
4796 as_tsktsk (_("use of r15 in bxj is not really useful"));
4797
4798 end_of_line (str);
4799}
4800
4801/* ARM V6 umaal (argument parse). */
4802
4803static void
4804do_umaal (str)
4805 char *str;
4806{
4807
4808 int rdlo, rdhi, rm, rs;
4809
4810 skip_whitespace (str);
4811 if ((rdlo = reg_required_here (& str, 12)) == FAIL
4812 || skip_past_comma (& str) == FAIL
4813 || (rdhi = reg_required_here (& str, 16)) == FAIL
4814 || skip_past_comma (& str) == FAIL
4815 || (rm = reg_required_here (& str, 0)) == FAIL
4816 || skip_past_comma (& str) == FAIL
5533419b 4817 || (rs = reg_required_here (& str, 8)) == FAIL)
09d92015
MM
4818 {
4819 inst.error = BAD_ARGS;
4820 return;
4821 }
4822
4823 if (rdlo == REG_PC || rdhi == REG_PC || rm == REG_PC || rs == REG_PC)
4824 {
4825 inst.error = BAD_PC;
4826 return;
4827 }
4828
4829 end_of_line (str);
4830}
4831
4832/* ARM V6 strex (argument parse). */
4833
4834static void
4835do_strex (str)
4836 char *str;
4837{
4838 int rd, rm, rn;
4839
4840 /* Parse Rd, Rm,. */
4841 skip_whitespace (str);
4842 if ((rd = reg_required_here (& str, 12)) == FAIL
4843 || skip_past_comma (& str) == FAIL
4844 || (rm = reg_required_here (& str, 0)) == FAIL
4845 || skip_past_comma (& str) == FAIL)
4846 {
4847 inst.error = BAD_ARGS;
4848 return;
4849 }
4850 if (rd == REG_PC || rm == REG_PC)
4851 {
4852 inst.error = BAD_PC;
4853 return;
4854 }
4855 if (rd == rm)
4856 {
4857 inst.error = _("Rd equal to Rm or Rn yields unpredictable results");
4858 return;
4859 }
4860
4861 /* Skip past '['. */
4862 if ((strlen (str) >= 1)
4863 && strncmp (str, "[", 1) == 0)
4864 str+=1;
4865 skip_whitespace (str);
4866
4867 /* Parse Rn. */
4868 if ((rn = reg_required_here (& str, 16)) == FAIL)
4869 {
4870 inst.error = BAD_ARGS;
4871 return;
4872 }
4873 else if (rn == REG_PC)
4874 {
4875 inst.error = BAD_PC;
4876 return;
4877 }
4878 if (rd == rn)
4879 {
4880 inst.error = _("Rd equal to Rm or Rn yields unpredictable results");
4881 return;
4882 }
4883 skip_whitespace (str);
4884
4885 /* Skip past ']'. */
4886 if ((strlen (str) >= 1)
4887 && strncmp (str, "]", 1) == 0)
4888 str+=1;
4889
4890 end_of_line (str);
4891}
4892
4893/* ARM V6 ssat (argument parse). */
4894
4895static void
4896do_ssat (str)
4897 char* str;
4898{
4899 do_sat (&str, /*bias=*/-1);
4900 end_of_line (str);
4901}
4902
4903/* ARM V6 usat (argument parse). */
4904
4905static void
4906do_usat (str)
4907 char* str;
4908{
4909 do_sat (&str, /*bias=*/0);
4910 end_of_line (str);
4911}
4912
4913static void
4914do_sat (str, bias)
4915 char **str;
4916 int bias;
4917{
4918 int rd, rm;
4919 expressionS expr;
4920
4921 skip_whitespace (*str);
4922
4923 /* Parse <Rd>, field. */
4924 if ((rd = reg_required_here (str, 12)) == FAIL
4925 || skip_past_comma (str) == FAIL)
4926 {
4927 inst.error = BAD_ARGS;
4928 return;
4929 }
4930 if (rd == REG_PC)
4931 {
4932 inst.error = BAD_PC;
4933 return;
4934 }
4935
4936 /* Parse #<immed>, field. */
4937 if (is_immediate_prefix (**str))
4938 (*str)++;
4939 else
4940 {
4941 inst.error = _("immediate expression expected");
4942 return;
4943 }
4944 if (my_get_expression (&expr, str))
4945 {
4946 inst.error = _("bad expression");
4947 return;
4948 }
4949 if (expr.X_op != O_constant)
4950 {
4951 inst.error = _("constant expression expected");
4952 return;
4953 }
4954 if (expr.X_add_number + bias < 0
4955 || expr.X_add_number + bias > 31)
4956 {
4957 inst.error = _("immediate value out of range");
4958 return;
4959 }
4960 inst.instruction |= (expr.X_add_number + bias) << 16;
4961 if (skip_past_comma (str) == FAIL)
4962 {
4963 inst.error = BAD_ARGS;
4964 return;
4965 }
4966
4967 /* Parse <Rm> field. */
4968 if ((rm = reg_required_here (str, 0)) == FAIL)
4969 {
4970 inst.error = BAD_ARGS;
4971 return;
4972 }
4973 if (rm == REG_PC)
4974 {
4975 inst.error = BAD_PC;
4976 return;
4977 }
4978
4979 if (skip_past_comma (str) == SUCCESS)
4980 decode_shift (str, SHIFT_LSL_OR_ASR_IMMEDIATE);
4981}
4982
4983/* ARM V6 ssat16 (argument parse). */
4984
4985static void
4986do_ssat16 (str)
4987 char *str;
4988{
4989 do_sat16 (&str, /*bias=*/-1);
4990 end_of_line (str);
4991}
4992
4993static void
4994do_usat16 (str)
4995 char *str;
4996{
4997 do_sat16 (&str, /*bias=*/0);
4998 end_of_line (str);
4999}
5000
5001static void
5002do_sat16 (str, bias)
5003 char **str;
5004 int bias;
5005{
5006 int rd, rm;
5007 expressionS expr;
5008
5009 skip_whitespace (*str);
5010
5011 /* Parse the <Rd> field. */
5012 if ((rd = reg_required_here (str, 12)) == FAIL
5013 || skip_past_comma (str) == FAIL)
5014 {
5015 inst.error = BAD_ARGS;
5016 return;
5017 }
5018 if (rd == REG_PC)
5019 {
5020 inst.error = BAD_PC;
5021 return;
5022 }
5023
5024 /* Parse #<immed>, field. */
5025 if (is_immediate_prefix (**str))
5026 (*str)++;
5027 else
5028 {
5029 inst.error = _("immediate expression expected");
5030 return;
5031 }
5032 if (my_get_expression (&expr, str))
5033 {
5034 inst.error = _("bad expression");
5035 return;
5036 }
5037 if (expr.X_op != O_constant)
5038 {
5039 inst.error = _("constant expression expected");
5040 return;
5041 }
5042 if (expr.X_add_number + bias < 0
5043 || expr.X_add_number + bias > 15)
5044 {
5045 inst.error = _("immediate value out of range");
5046 return;
5047 }
5048 inst.instruction |= (expr.X_add_number + bias) << 16;
5049 if (skip_past_comma (str) == FAIL)
5050 {
5051 inst.error = BAD_ARGS;
5052 return;
5053 }
5054
5055 /* Parse <Rm> field. */
5056 if ((rm = reg_required_here (str, 0)) == FAIL)
5057 {
5058 inst.error = BAD_ARGS;
5059 return;
5060 }
5061 if (rm == REG_PC)
5062 {
5063 inst.error = BAD_PC;
5064 return;
5065 }
5066}
5067
5068/* ARM V6 srs (argument parse). */
5069
5070static void
5071do_srs (str)
5072 char* str;
5073{
5074 char *exclam;
5075 skip_whitespace (str);
5076 exclam = strchr (str, '!');
5077 if (exclam)
5078 *exclam = '\0';
5079 do_cps_mode (&str);
5080 if (exclam)
5081 *exclam = '!';
5082 if (*str == '!')
5083 {
5084 inst.instruction |= WRITE_BACK;
5085 str++;
5086 }
5087 end_of_line (str);
5088}
5089
5090/* ARM V6 SMMUL (argument parse). */
5091
5092static void
5093do_smmul (str)
5094 char* str;
5095{
5096 int rd, rm, rs;
5097
5098 skip_whitespace (str);
5099 if ((rd = reg_required_here (&str, 16)) == FAIL
5100 || skip_past_comma (&str) == FAIL
5101 || (rm = reg_required_here (&str, 0)) == FAIL
5102 || skip_past_comma (&str) == FAIL
5103 || (rs = reg_required_here (&str, 8)) == FAIL)
5104 {
5105 inst.error = BAD_ARGS;
5106 return;
5107 }
5108
5109 if (rd == REG_PC
5110 || rm == REG_PC
5111 || rs == REG_PC)
5112 {
5113 inst.error = BAD_PC;
5114 return;
5115 }
5116
5117 end_of_line (str);
5118
5119}
5120
5121/* ARM V6 SMLALD (argument parse). */
5122
5123static void
5124do_smlald (str)
5125 char* str;
5126{
5127 int rdlo, rdhi, rm, rs;
5128 skip_whitespace (str);
5129 if ((rdlo = reg_required_here (&str, 12)) == FAIL
5130 || skip_past_comma (&str) == FAIL
5131 || (rdhi = reg_required_here (&str, 16)) == FAIL
5132 || skip_past_comma (&str) == FAIL
5133 || (rm = reg_required_here (&str, 0)) == FAIL
5134 || skip_past_comma (&str) == FAIL
5135 || (rs = reg_required_here (&str, 8)) == FAIL)
5136 {
5137 inst.error = BAD_ARGS;
5138 return;
5139 }
5140
5141 if (rdlo == REG_PC
5142 || rdhi == REG_PC
5143 || rm == REG_PC
5144 || rs == REG_PC)
5145 {
5146 inst.error = BAD_PC;
5147 return;
5148 }
5149
5150 end_of_line (str);
5151}
5152
5153/* ARM V6 SMLAD (argument parse). Signed multiply accumulate dual.
5154 smlad{x}{<cond>} Rd, Rm, Rs, Rn */
5155
5156static void
5157do_smlad (str)
5158 char *str;
5159{
5160 int rd, rm, rs, rn;
5161
5162 skip_whitespace (str);
5163 if ((rd = reg_required_here (&str, 16)) == FAIL
5164 || skip_past_comma (&str) == FAIL
5165 || (rm = reg_required_here (&str, 0)) == FAIL
5166 || skip_past_comma (&str) == FAIL
5167 || (rs = reg_required_here (&str, 8)) == FAIL
5168 || skip_past_comma (&str) == FAIL
5169 || (rn = reg_required_here (&str, 12)) == FAIL)
5170 {
5171 inst.error = BAD_ARGS;
5172 return;
5173 }
5174
5175 if (rd == REG_PC
5176 || rn == REG_PC
5177 || rs == REG_PC
5178 || rm == REG_PC)
5179 {
5180 inst.error = BAD_PC;
5181 return;
5182 }
5183
5184 end_of_line (str);
5185}
5186
5187/* ARM V6 SETEND (argument parse). Sets the E bit in the CPSR while
5188 preserving the other bits.
5189
5190 setend <endian_specifier>, where <endian_specifier> is either
5191 BE or LE. */
5192
5193static void
5194do_setend (str)
5195 char *str;
5196{
5197 if (do_endian_specifier (str))
5198 inst.instruction |= 0x200;
5199}
5200
5201/* Returns true if the endian-specifier indicates big-endianness. */
5202
5203static int
5204do_endian_specifier (str)
5205 char *str;
5206{
5207 int big_endian = 0;
5208
5209 skip_whitespace (str);
5210 if (strlen (str) < 2)
5211 inst.error = _("missing endian specifier");
5212 else if (strncasecmp (str, "BE", 2) == 0)
5213 {
5214 str += 2;
5215 big_endian = 1;
5216 }
5217 else if (strncasecmp (str, "LE", 2) == 0)
5218 str += 2;
5219 else
5220 inst.error = _("valid endian specifiers are be or le");
5221
5222 end_of_line (str);
5223
5224 return big_endian;
5225}
5226
5227/* ARM V6 SXTH.
5228
5229 SXTH {<cond>} <Rd>, <Rm>{, <rotation>}
5230 Condition defaults to COND_ALWAYS.
5231 Error if any register uses R15. */
5232
5233static void
5234do_sxth (str)
5235 char *str;
5236{
5237 int rd, rm;
5238 expressionS expr;
5239 int rotation_clear_mask = 0xfffff3ff;
5240 int rotation_eight_mask = 0x00000400;
5241 int rotation_sixteen_mask = 0x00000800;
5242 int rotation_twenty_four_mask = 0x00000c00;
5243
5244 skip_whitespace (str);
5245 if ((rd = reg_required_here (&str, 12)) == FAIL
5246 || skip_past_comma (&str) == FAIL
5247 || (rm = reg_required_here (&str, 0)) == FAIL)
5248 {
5249 inst.error = BAD_ARGS;
5250 return;
5251 }
5252
5253 else if (rd == REG_PC || rm == REG_PC)
5254 {
5255 inst.error = BAD_PC;
5256 return;
5257 }
5258
5259 /* Zero out the rotation field. */
5260 inst.instruction &= rotation_clear_mask;
5261
5262 /* Check for lack of optional rotation field. */
5263 if (skip_past_comma (&str) == FAIL)
5264 {
5265 end_of_line (str);
5266 return;
5267 }
5268
5269 /* Move past 'ROR'. */
5270 skip_whitespace (str);
5271 if (strncasecmp (str, "ROR", 3) == 0)
5272 str+=3;
5273 else
5274 {
5275 inst.error = _("missing rotation field after comma");
5276 return;
5277 }
5278
5279 /* Get the immediate constant. */
5280 skip_whitespace (str);
5281 if (is_immediate_prefix (* str))
5282 str++;
5283 else
5284 {
5285 inst.error = _("immediate expression expected");
5286 return;
5287 }
5288
5289 if (my_get_expression (&expr, &str))
5290 {
5291 inst.error = _("bad expression");
5292 return;
5293 }
5294
5295 if (expr.X_op != O_constant)
5296 {
5297 inst.error = _("constant expression expected");
5298 return;
5299 }
5300
5301 switch (expr.X_add_number)
5302 {
5303 case 0:
5304 /* Rotation field has already been zeroed. */
5305 break;
5306 case 8:
5307 inst.instruction |= rotation_eight_mask;
5308 break;
5309
5310 case 16:
5311 inst.instruction |= rotation_sixteen_mask;
5312 break;
5313
5314 case 24:
5315 inst.instruction |= rotation_twenty_four_mask;
5316 break;
5317
5318 default:
5319 inst.error = _("rotation can be 8, 16, 24 or 0 when field is ommited");
5320 break;
5321 }
5322
5323 end_of_line (str);
5324
5325}
5326
5327/* ARM V6 SXTAH extracts a 16-bit value from a register, sign
5328 extends it to 32-bits, and adds the result to a value in another
5329 register. You can specify a rotation by 0, 8, 16, or 24 bits
5330 before extracting the 16-bit value.
5331 SXTAH{<cond>} <Rd>, <Rn>, <Rm>{, <rotation>}
5332 Condition defaults to COND_ALWAYS.
5333 Error if any register uses R15. */
5334
5335static void
5336do_sxtah (str)
5337 char *str;
5338{
5339 int rd, rn, rm;
5340 expressionS expr;
5341 int rotation_clear_mask = 0xfffff3ff;
5342 int rotation_eight_mask = 0x00000400;
5343 int rotation_sixteen_mask = 0x00000800;
5344 int rotation_twenty_four_mask = 0x00000c00;
5345
5346 skip_whitespace (str);
5347 if ((rd = reg_required_here (&str, 12)) == FAIL
5348 || skip_past_comma (&str) == FAIL
5349 || (rn = reg_required_here (&str, 16)) == FAIL
5350 || skip_past_comma (&str) == FAIL
5351 || (rm = reg_required_here (&str, 0)) == FAIL)
5352 {
5353 inst.error = BAD_ARGS;
5354 return;
5355 }
5356
5357 else if (rd == REG_PC || rn == REG_PC || rm == REG_PC)
5358 {
5359 inst.error = BAD_PC;
5360 return;
5361 }
5362
5363 /* Zero out the rotation field. */
5364 inst.instruction &= rotation_clear_mask;
5365
5366 /* Check for lack of optional rotation field. */
5367 if (skip_past_comma (&str) == FAIL)
5368 {
5369 end_of_line (str);
5370 return;
5371 }
5372
5373 /* Move past 'ROR'. */
5374 skip_whitespace (str);
5375 if (strncasecmp (str, "ROR", 3) == 0)
5376 str+=3;
5377 else
5378 {
5379 inst.error = _("missing rotation field after comma");
5380 return;
5381 }
5382
5383 /* Get the immediate constant. */
5384 skip_whitespace (str);
5385 if (is_immediate_prefix (* str))
5386 str++;
5387 else
5388 {
5389 inst.error = _("immediate expression expected");
5390 return;
5391 }
5392
5393 if (my_get_expression (&expr, &str))
5394 {
5395 inst.error = _("bad expression");
5396 return;
5397 }
5398
5399 if (expr.X_op != O_constant)
5400 {
5401 inst.error = _("constant expression expected");
5402 return;
5403 }
5404
5405 switch (expr.X_add_number)
5406 {
5407 case 0:
5408 /* Rotation field has already been zeroed. */
5409 break;
5410
5411 case 8:
5412 inst.instruction |= rotation_eight_mask;
5413 break;
5414
5415 case 16:
5416 inst.instruction |= rotation_sixteen_mask;
5417 break;
5418
5419 case 24:
5420 inst.instruction |= rotation_twenty_four_mask;
5421 break;
5422
5423 default:
5424 inst.error = _("rotation can be 8, 16, 24 or 0 when field is ommited");
5425 break;
5426 }
5427
5428 end_of_line (str);
5429
5430}
5431
5432
5433/* ARM V6 RFE (Return from Exception) loads the PC and CPSR from the
5434 word at the specified address and the following word
5435 respectively.
5436 Unconditionally executed.
5437 Error if Rn is R15.
5438*/
5439
5440static void
5441do_rfe (str)
5442 char *str;
5443{
5444 int rn;
5445
5446 skip_whitespace (str);
5447
5448 if ((rn = reg_required_here (&str, 16)) == FAIL)
5449 return;
b99bd4ef 5450
09d92015 5451 if (rn == REG_PC)
b99bd4ef 5452 {
09d92015 5453 inst.error = BAD_PC;
b99bd4ef
NC
5454 return;
5455 }
5456
09d92015
MM
5457 skip_whitespace (str);
5458
5459 if (*str == '!')
5460 {
5461 inst.instruction |= WRITE_BACK;
5462 str++;
5463 }
b99bd4ef
NC
5464 end_of_line (str);
5465}
5466
09d92015
MM
5467/* ARM V6 REV (Byte Reverse Word) reverses the byte order in a 32-bit
5468 register (argument parse).
5469 REV{<cond>} Rd, Rm.
5470 Condition defaults to COND_ALWAYS.
5471 Error if Rd or Rm are R15. */
b99bd4ef
NC
5472
5473static void
09d92015
MM
5474do_rev (str)
5475 char* str;
b99bd4ef
NC
5476{
5477 int rd, rm;
5478
b99bd4ef
NC
5479 skip_whitespace (str);
5480
09d92015
MM
5481 if ((rd = reg_required_here (&str, 12)) == FAIL
5482 || skip_past_comma (&str) == FAIL
5483 || (rm = reg_required_here (&str, 0)) == FAIL)
b99bd4ef
NC
5484 inst.error = BAD_ARGS;
5485
09d92015 5486 else if (rd == REG_PC || rm == REG_PC)
b99bd4ef
NC
5487 inst.error = BAD_PC;
5488
5489 else
5490 end_of_line (str);
5491}
5492
09d92015
MM
5493/* ARM V6 Perform Two Sixteen Bit Integer Additions. (argument parse).
5494 QADD16{<cond>} <Rd>, <Rn>, <Rm>
5495 Condition defaults to COND_ALWAYS.
5496 Error if Rd, Rn or Rm are R15. */
b99bd4ef
NC
5497
5498static void
09d92015
MM
5499do_qadd16 (str)
5500 char* str;
b99bd4ef 5501{
09d92015
MM
5502 int rd, rm, rn;
5503
b99bd4ef
NC
5504 skip_whitespace (str);
5505
09d92015
MM
5506 if ((rd = reg_required_here (&str, 12)) == FAIL
5507 || skip_past_comma (&str) == FAIL
5508 || (rn = reg_required_here (&str, 16)) == FAIL
5509 || skip_past_comma (&str) == FAIL
5510 || (rm = reg_required_here (&str, 0)) == FAIL)
5511 inst.error = BAD_ARGS;
5512
5513 else if (rd == REG_PC || rm == REG_PC || rn == REG_PC)
5514 inst.error = BAD_PC;
5515
b99bd4ef
NC
5516 else
5517 end_of_line (str);
5518}
5519
09d92015
MM
5520/* ARM V6 Pack Halfword Bottom Top instruction (argument parse).
5521 PKHBT {<cond>} <Rd>, <Rn>, <Rm> {, LSL #<shift_imm>}
5522 Condition defaults to COND_ALWAYS.
5523 Error if Rd, Rn or Rm are R15. */
5524
5525static void
5526do_pkhbt (str)
5527 char* str;
5528{
5529 do_pkh_core (str, SHIFT_LSL_IMMEDIATE);
5530}
5531
5532/* ARM V6 PKHTB (Argument Parse). */
5533
5534static void
5535do_pkhtb (str)
5536 char* str;
5537{
5538 do_pkh_core (str, SHIFT_ASR_IMMEDIATE);
5539}
b99bd4ef
NC
5540
5541static void
09d92015
MM
5542do_pkh_core (str, shift)
5543 char* str;
5544 int shift;
b99bd4ef 5545{
09d92015 5546 int rd, rn, rm;
b99bd4ef 5547
09d92015
MM
5548 skip_whitespace (str);
5549 if (((rd = reg_required_here (&str, 12)) == FAIL)
5550 || (skip_past_comma (&str) == FAIL)
5551 || ((rn = reg_required_here (&str, 16)) == FAIL)
5552 || (skip_past_comma (&str) == FAIL)
5553 || ((rm = reg_required_here (&str, 0)) == FAIL))
b99bd4ef 5554 {
09d92015 5555 inst.error = BAD_ARGS;
b99bd4ef
NC
5556 return;
5557 }
5558
09d92015 5559 else if (rd == REG_PC || rn == REG_PC || rm == REG_PC)
b99bd4ef 5560 {
09d92015 5561 inst.error = BAD_PC;
b99bd4ef
NC
5562 return;
5563 }
5564
09d92015
MM
5565 /* Check for optional shift immediate constant. */
5566 if (skip_past_comma (&str) == FAIL)
b99bd4ef 5567 {
09d92015
MM
5568 if (shift == SHIFT_ASR_IMMEDIATE)
5569 {
5570 /* If the shift specifier is ommited, turn the instruction
5571 into pkhbt rd, rm, rn. First, switch the instruction
5572 code, and clear the rn and rm fields. */
5573 inst.instruction &= 0xfff0f010;
5574 /* Now, re-encode the registers. */
5575 inst.instruction |= (rm << 16) | rn;
5576 }
b99bd4ef
NC
5577 return;
5578 }
5579
09d92015
MM
5580 decode_shift (&str, shift);
5581}
5582
5583/* ARM V6 Load Register Exclusive instruction (argument parse).
5584 LDREX{<cond>} <Rd, [<Rn>]
5585 Condition defaults to COND_ALWAYS.
5586 Error if Rd or Rn are R15.
5587 See ARMARMv6 A4.1.27: LDREX. */
5588
5589
5590static void
5591do_ldrex (str)
5592 char * str;
5593{
5594 int rd, rn;
5595
5596 skip_whitespace (str);
5597
5598 /* Parse Rd. */
5599 if (((rd = reg_required_here (&str, 12)) == FAIL)
5600 || (skip_past_comma (&str) == FAIL))
b99bd4ef 5601 {
09d92015 5602 inst.error = BAD_ARGS;
b99bd4ef
NC
5603 return;
5604 }
09d92015 5605 else if (rd == REG_PC)
b99bd4ef 5606 {
09d92015 5607 inst.error = BAD_PC;
b99bd4ef
NC
5608 return;
5609 }
09d92015 5610 skip_whitespace (str);
b99bd4ef 5611
09d92015
MM
5612 /* Skip past '['. */
5613 if ((strlen (str) >= 1)
5614 &&strncmp (str, "[", 1) == 0)
5615 str+=1;
5616 skip_whitespace (str);
5617
5618 /* Parse Rn. */
5619 if ((rn = reg_required_here (&str, 16)) == FAIL)
b99bd4ef 5620 {
09d92015
MM
5621 inst.error = BAD_ARGS;
5622 return;
b99bd4ef 5623 }
09d92015
MM
5624 else if (rn == REG_PC)
5625 {
5626 inst.error = BAD_PC;
5627 return;
5628 }
5629 skip_whitespace (str);
b99bd4ef 5630
09d92015
MM
5631 /* Skip past ']'. */
5632 if ((strlen (str) >= 1)
5633 && strncmp (str, "]", 1) == 0)
5634 str+=1;
5635
b99bd4ef
NC
5636 end_of_line (str);
5637}
5638
09d92015
MM
5639/* ARM V6 change processor state instruction (argument parse)
5640 CPS, CPSIE, CSPID . */
b99bd4ef
NC
5641
5642static void
09d92015
MM
5643do_cps (str)
5644 char * str;
b99bd4ef 5645{
09d92015
MM
5646 do_cps_mode (&str);
5647 end_of_line (str);
5648}
b99bd4ef 5649
09d92015
MM
5650static void
5651do_cpsi (str)
5652 char * str;
5653{
5654 do_cps_flags (&str, /*thumb_p=*/0);
b99bd4ef 5655
09d92015 5656 if (skip_past_comma (&str) == SUCCESS)
b99bd4ef 5657 {
09d92015
MM
5658 skip_whitespace (str);
5659 do_cps_mode (&str);
b99bd4ef 5660 }
09d92015
MM
5661 end_of_line (str);
5662}
b99bd4ef 5663
09d92015
MM
5664static void
5665do_cps_mode (str)
5666 char **str;
5667{
5668 expressionS expr;
5669
5670 skip_whitespace (*str);
5671
5672 if (! is_immediate_prefix (**str))
b99bd4ef 5673 {
09d92015 5674 inst.error = _("immediate expression expected");
b99bd4ef
NC
5675 return;
5676 }
5677
09d92015
MM
5678 (*str)++; /* Strip off the immediate signifier. */
5679 if (my_get_expression (&expr, str))
b99bd4ef 5680 {
09d92015 5681 inst.error = _("bad expression");
b99bd4ef
NC
5682 return;
5683 }
5684
09d92015 5685 if (expr.X_op != O_constant)
b99bd4ef 5686 {
09d92015 5687 inst.error = _("constant expression expected");
b99bd4ef
NC
5688 return;
5689 }
09d92015
MM
5690
5691 /* The mode is a 5 bit field. Valid values are 0-31. */
5692 if (((unsigned) expr.X_add_number) > 31
5693 || (inst.reloc.exp.X_add_number) < 0)
b99bd4ef 5694 {
09d92015
MM
5695 inst.error = _("invalid constant");
5696 return;
b99bd4ef 5697 }
09d92015
MM
5698
5699 inst.instruction |= expr.X_add_number;
b99bd4ef
NC
5700}
5701
ea6ef066 5702static void
09d92015
MM
5703do_cps_flags (str, thumb_p)
5704 char **str;
5705 int thumb_p;
ea6ef066 5706{
09d92015
MM
5707 struct cps_flag {
5708 char character;
5709 unsigned long arm_value;
5710 unsigned long thumb_value;
5711 };
5712 static struct cps_flag flag_table[] = {
5713 {'a', 0x100, 0x4 },
5714 {'i', 0x080, 0x2 },
5715 {'f', 0x040, 0x1 }
5716 };
ea6ef066 5717
09d92015 5718 int saw_a_flag = 0;
ea6ef066 5719
09d92015
MM
5720 skip_whitespace (*str);
5721
5722 /* Get the a, f and i flags. */
5723 while (**str && **str != ',')
ea6ef066 5724 {
09d92015
MM
5725 struct cps_flag *p;
5726 struct cps_flag *q = flag_table + sizeof (flag_table)/sizeof (*p);
5727 for (p = flag_table; p < q; ++p)
5728 if (strncasecmp (*str, &p->character, 1) == 0)
5729 {
5730 inst.instruction |= (thumb_p ? p->thumb_value : p->arm_value);
5731 saw_a_flag = 1;
5732 break;
5733 }
5734 if (p == q)
5735 {
5736 inst.error = _("unrecognized flag");
5737 return;
5738 }
5739 (*str)++;
ea6ef066 5740 }
09d92015
MM
5741 if (!saw_a_flag)
5742 inst.error = _("no 'a', 'i', or 'f' flags for 'cps'");
ea6ef066
RE
5743}
5744
b99bd4ef
NC
5745/* THUMB V5 breakpoint instruction (argument parse)
5746 BKPT <immed_8>. */
5747
5748static void
5749do_t_bkpt (str)
5750 char * str;
5751{
5752 expressionS expr;
5753 unsigned long number;
5754
5755 skip_whitespace (str);
5756
5757 /* Allow optional leading '#'. */
5758 if (is_immediate_prefix (*str))
5759 str ++;
5760
5761 memset (& expr, '\0', sizeof (expr));
143c8e19
NC
5762 if (my_get_expression (& expr, & str)
5763 || (expr.X_op != O_constant
5764 /* As a convenience we allow 'bkpt' without an operand. */
5765 && expr.X_op != O_absent))
b99bd4ef 5766 {
143c8e19 5767 inst.error = _("bad expression");
b99bd4ef
NC
5768 return;
5769 }
5770
5771 number = expr.X_add_number;
5772
5773 /* Check it fits an 8 bit unsigned. */
5774 if (number != (number & 0xff))
5775 {
5776 inst.error = _("immediate value out of range");
5777 return;
5778 }
5779
5780 inst.instruction |= number;
5781
5782 end_of_line (str);
5783}
5784
5785/* ARM V5 branch-link-exchange (argument parse) for BLX(1) only.
5786 Expects inst.instruction is set for BLX(1).
5787 Note: this is cloned from do_branch, and the reloc changed to be a
5788 new one that can cope with setting one extra bit (the H bit). */
5789
5790static void
f2b7cb0a 5791do_branch25 (str)
b99bd4ef 5792 char * str;
b99bd4ef
NC
5793{
5794 if (my_get_expression (& inst.reloc.exp, & str))
5795 return;
5796
5797#ifdef OBJ_ELF
5798 {
5799 char * save_in;
5800
5801 /* ScottB: February 5, 1998 */
5802 /* Check to see of PLT32 reloc required for the instruction. */
5803
5804 /* arm_parse_reloc() works on input_line_pointer.
5805 We actually want to parse the operands to the branch instruction
5806 passed in 'str'. Save the input pointer and restore it later. */
5807 save_in = input_line_pointer;
5808 input_line_pointer = str;
5809
5810 if (inst.reloc.exp.X_op == O_symbol
5811 && *str == '('
5812 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
5813 {
5814 inst.reloc.type = BFD_RELOC_ARM_PLT32;
5815 inst.reloc.pc_rel = 0;
5816 /* Modify str to point to after parsed operands, otherwise
5817 end_of_line() will complain about the (PLT) left in str. */
5818 str = input_line_pointer;
5819 }
5820 else
5821 {
5822 inst.reloc.type = BFD_RELOC_ARM_PCREL_BLX;
5823 inst.reloc.pc_rel = 1;
5824 }
5825
5826 input_line_pointer = save_in;
5827 }
5828#else
5829 inst.reloc.type = BFD_RELOC_ARM_PCREL_BLX;
5830 inst.reloc.pc_rel = 1;
5831#endif /* OBJ_ELF */
5832
5833 end_of_line (str);
5834}
5835
5836/* ARM V5 branch-link-exchange instruction (argument parse)
5837 BLX <target_addr> ie BLX(1)
5838 BLX{<condition>} <Rm> ie BLX(2)
5839 Unfortunately, there are two different opcodes for this mnemonic.
5840 So, the insns[].value is not used, and the code here zaps values
5841 into inst.instruction.
5842 Also, the <target_addr> can be 25 bits, hence has its own reloc. */
5843
5844static void
f2b7cb0a 5845do_blx (str)
b99bd4ef 5846 char * str;
b99bd4ef
NC
5847{
5848 char * mystr = str;
5849 int rm;
5850
b99bd4ef
NC
5851 skip_whitespace (mystr);
5852 rm = reg_required_here (& mystr, 0);
5853
5854 /* The above may set inst.error. Ignore his opinion. */
5855 inst.error = 0;
5856
5857 if (rm != FAIL)
5858 {
5859 /* Arg is a register.
5860 Use the condition code our caller put in inst.instruction.
5861 Pass ourselves off as a BX with a funny opcode. */
5862 inst.instruction |= 0x012fff30;
f2b7cb0a 5863 do_bx (str);
b99bd4ef
NC
5864 }
5865 else
5866 {
5867 /* This must be is BLX <target address>, no condition allowed. */
5868 if (inst.instruction != COND_ALWAYS)
cc8a6dd0
KH
5869 {
5870 inst.error = BAD_COND;
b99bd4ef 5871 return;
cc8a6dd0 5872 }
b99bd4ef
NC
5873
5874 inst.instruction = 0xfafffffe;
5875
5876 /* Process like a B/BL, but with a different reloc.
5877 Note that B/BL expecte fffffe, not 0, offset in the opcode table. */
f2b7cb0a 5878 do_branch25 (str);
b99bd4ef
NC
5879 }
5880}
5881
5882/* ARM V5 Thumb BLX (argument parse)
5883 BLX <target_addr> which is BLX(1)
5884 BLX <Rm> which is BLX(2)
5885 Unfortunately, there are two different opcodes for this mnemonic.
5886 So, the tinsns[].value is not used, and the code here zaps values
5887 into inst.instruction. */
5888
5889static void
5890do_t_blx (str)
5891 char * str;
5892{
5893 char * mystr = str;
5894 int rm;
5895
5896 skip_whitespace (mystr);
5897 inst.instruction = 0x4780;
5898
5899 /* Note that this call is to the ARM register recognizer. BLX(2)
5900 uses the ARM register space, not the Thumb one, so a call to
5901 thumb_reg() would be wrong. */
5902 rm = reg_required_here (& mystr, 3);
5903 inst.error = 0;
5904
5905 if (rm != FAIL)
5906 {
5907 /* It's BLX(2). The .instruction was zapped with rm & is final. */
5908 inst.size = 2;
5909 }
5910 else
5911 {
5912 /* No ARM register. This must be BLX(1). Change the .instruction. */
5913 inst.instruction = 0xf7ffeffe;
5914 inst.size = 4;
5915
5916 if (my_get_expression (& inst.reloc.exp, & mystr))
5917 return;
5918
5919 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BLX;
5920 inst.reloc.pc_rel = 1;
5921 }
5922
5923 end_of_line (mystr);
5924}
5925
5926/* ARM V5 breakpoint instruction (argument parse)
5927 BKPT <16 bit unsigned immediate>
5928 Instruction is not conditional.
5929 The bit pattern given in insns[] has the COND_ALWAYS condition,
cc8a6dd0 5930 and it is an error if the caller tried to override that. */
b99bd4ef
NC
5931
5932static void
f2b7cb0a 5933do_bkpt (str)
b99bd4ef 5934 char * str;
b99bd4ef
NC
5935{
5936 expressionS expr;
5937 unsigned long number;
5938
5939 skip_whitespace (str);
5940
5941 /* Allow optional leading '#'. */
5942 if (is_immediate_prefix (* str))
5943 str++;
5944
5945 memset (& expr, '\0', sizeof (expr));
5946
143c8e19
NC
5947 if (my_get_expression (& expr, & str)
5948 || (expr.X_op != O_constant
5949 /* As a convenience we allow 'bkpt' without an operand. */
5950 && expr.X_op != O_absent))
b99bd4ef 5951 {
143c8e19 5952 inst.error = _("bad expression");
b99bd4ef
NC
5953 return;
5954 }
5955
5956 number = expr.X_add_number;
5957
5958 /* Check it fits a 16 bit unsigned. */
5959 if (number != (number & 0xffff))
5960 {
5961 inst.error = _("immediate value out of range");
5962 return;
5963 }
5964
5965 /* Top 12 of 16 bits to bits 19:8. */
5966 inst.instruction |= (number & 0xfff0) << 4;
5967
5968 /* Bottom 4 of 16 bits to bits 3:0. */
5969 inst.instruction |= number & 0xf;
5970
5971 end_of_line (str);
b99bd4ef
NC
5972}
5973
09d92015
MM
5974/* THUMB CPS instruction (argument parse). */
5975
5976static void
5977do_t_cps (str)
5978 char *str;
5979{
5980 do_cps_flags (&str, /*thumb_p=*/1);
5981 end_of_line (str);
5982}
5983
5984/* THUMB CPY instruction (argument parse). */
5985
5986static void
5987do_t_cpy (str)
5988 char *str;
5989{
5990 thumb_mov_compare (str, THUMB_CPY);
5991}
5992
5993/* THUMB SETEND instruction (argument parse). */
5994
5995static void
5996do_t_setend (str)
5997 char *str;
5998{
5999 if (do_endian_specifier (str))
6000 inst.instruction |= 0x8;
6001}
6002
e16bb312
NC
6003static unsigned long check_iwmmxt_insn PARAMS ((char *, enum iwmmxt_insn_type, int));
6004
6005/* Parse INSN_TYPE insn STR having a possible IMMEDIATE_SIZE immediate. */
6006
6007static unsigned long
6008check_iwmmxt_insn (str, insn_type, immediate_size)
6009 char * str;
6010 enum iwmmxt_insn_type insn_type;
6011 int immediate_size;
6012{
6013 int reg = 0;
6014 const char * inst_error;
6015 expressionS expr;
6016 unsigned long number;
6017
6018 inst_error = inst.error;
6019 if (!inst.error)
6020 inst.error = BAD_ARGS;
6021 skip_whitespace (str);
6022
6023 switch (insn_type)
6024 {
6025 case check_rd:
6026 if ((reg = reg_required_here (&str, 12)) == FAIL)
6027 return FAIL;
6028 break;
6029
6030 case check_wr:
6031 if ((wreg_required_here (&str, 0, IWMMXT_REG_WR)) == FAIL)
6032 return FAIL;
6033 break;
6034
6035 case check_wrwr:
6036 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
6037 || skip_past_comma (&str) == FAIL
6038 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL))
6039 return FAIL;
6040 break;
6041
6042 case check_wrwrwr:
6043 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
6044 || skip_past_comma (&str) == FAIL
6045 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6046 || skip_past_comma (&str) == FAIL
6047 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL))
6048 return FAIL;
6049 break;
6050
6051 case check_wrwrwcg:
6052 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
6053 || skip_past_comma (&str) == FAIL
6054 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6055 || skip_past_comma (&str) == FAIL
6056 || wreg_required_here (&str, 0, IWMMXT_REG_WCG) == FAIL))
6057 return FAIL;
6058 break;
6059
6060 case check_tbcst:
6061 if ((wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6062 || skip_past_comma (&str) == FAIL
6063 || reg_required_here (&str, 12) == FAIL))
6064 return FAIL;
6065 break;
6066
6067 case check_tmovmsk:
6068 if ((reg_required_here (&str, 12) == FAIL
6069 || skip_past_comma (&str) == FAIL
6070 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL))
6071 return FAIL;
6072 break;
6073
6074 case check_tmia:
6075 if ((wreg_required_here (&str, 5, IWMMXT_REG_WR) == FAIL
6076 || skip_past_comma (&str) == FAIL
6077 || reg_required_here (&str, 0) == FAIL
6078 || skip_past_comma (&str) == FAIL
6079 || reg_required_here (&str, 12) == FAIL))
6080 return FAIL;
6081 break;
6082
6083 case check_tmcrr:
6084 if ((wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL
6085 || skip_past_comma (&str) == FAIL
6086 || reg_required_here (&str, 12) == FAIL
6087 || skip_past_comma (&str) == FAIL
6088 || reg_required_here (&str, 16) == FAIL))
6089 return FAIL;
6090 break;
6091
6092 case check_tmrrc:
6093 if ((reg_required_here (&str, 12) == FAIL
6094 || skip_past_comma (&str) == FAIL
6095 || reg_required_here (&str, 16) == FAIL
6096 || skip_past_comma (&str) == FAIL
6097 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL))
6098 return FAIL;
6099 break;
6100
6101 case check_tmcr:
6102 if ((wreg_required_here (&str, 16, IWMMXT_REG_WC) == FAIL
6103 || skip_past_comma (&str) == FAIL
6104 || reg_required_here (&str, 12) == FAIL))
6105 return FAIL;
6106 break;
6107
6108 case check_tmrc:
6109 if ((reg_required_here (&str, 12) == FAIL
6110 || skip_past_comma (&str) == FAIL
6111 || wreg_required_here (&str, 16, IWMMXT_REG_WC) == FAIL))
6112 return FAIL;
6113 break;
6114
6115 case check_tinsr:
6116 if ((wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6117 || skip_past_comma (&str) == FAIL
6118 || reg_required_here (&str, 12) == FAIL
6119 || skip_past_comma (&str) == FAIL))
6120 return FAIL;
6121 break;
6122
6123 case check_textrc:
6124 if ((reg_required_here (&str, 12) == FAIL
6125 || skip_past_comma (&str) == FAIL))
6126 return FAIL;
6127 break;
6128
6129 case check_waligni:
6130 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
6131 || skip_past_comma (&str) == FAIL
6132 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6133 || skip_past_comma (&str) == FAIL
6134 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL
6135 || skip_past_comma (&str) == FAIL))
6136 return FAIL;
6137 break;
6138
6139 case check_textrm:
6140 if ((reg_required_here (&str, 12) == FAIL
6141 || skip_past_comma (&str) == FAIL
6142 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6143 || skip_past_comma (&str) == FAIL))
6144 return FAIL;
6145 break;
6146
6147 case check_wshufh:
6148 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
6149 || skip_past_comma (&str) == FAIL
6150 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6151 || skip_past_comma (&str) == FAIL))
6152 return FAIL;
6153 break;
6154 }
6155
6156 if (immediate_size == 0)
6157 {
6158 end_of_line (str);
6159 inst.error = inst_error;
6160 return reg;
6161 }
6162 else
6163 {
6164 skip_whitespace (str);
6165
6166 /* Allow optional leading '#'. */
6167 if (is_immediate_prefix (* str))
6168 str++;
6169
6170 memset (& expr, '\0', sizeof (expr));
6171
6172 if (my_get_expression (& expr, & str) || (expr.X_op != O_constant))
6173 {
6174 inst.error = _("bad or missing expression");
6175 return FAIL;
6176 }
6177
6178 number = expr.X_add_number;
6179
6180 if (number != (number & immediate_size))
6181 {
6182 inst.error = _("immediate value out of range");
6183 return FAIL;
6184 }
6185 end_of_line (str);
6186 inst.error = inst_error;
6187 return number;
6188 }
6189}
6190
6191static void
6192do_iwmmxt_byte_addr (str)
6193 char * str;
6194{
6195 int op = (inst.instruction & 0x300) >> 8;
6196 int reg;
6197
6198 inst.instruction &= ~0x300;
6199 inst.instruction |= (op & 1) << 22 | (op & 2) << 7;
6200
6201 skip_whitespace (str);
6202
6203 if ((reg = wreg_required_here (&str, 12, IWMMXT_REG_WR_OR_WC)) == FAIL
6204 || skip_past_comma (& str) == FAIL
6205 || cp_byte_address_required_here (&str) == FAIL)
6206 {
6207 if (! inst.error)
6208 inst.error = BAD_ARGS;
6209 }
6210 else
6211 end_of_line (str);
6212
6213 if (wc_register (reg))
6214 {
ece01a63 6215 as_bad (_("non-word size not supported with control register"));
e16bb312
NC
6216 inst.instruction |= 0xf0000100;
6217 inst.instruction &= ~0x00400000;
6218 }
6219}
6220
6221static void
6222do_iwmmxt_tandc (str)
6223 char * str;
6224{
6225 int reg;
6226
6227 reg = check_iwmmxt_insn (str, check_rd, 0);
6228
6229 if (reg != REG_PC && !inst.error)
6230 inst.error = _("only r15 allowed here");
e16bb312
NC
6231}
6232
6233static void
6234do_iwmmxt_tbcst (str)
6235 char * str;
6236{
6237 check_iwmmxt_insn (str, check_tbcst, 0);
e16bb312
NC
6238}
6239
6240static void
6241do_iwmmxt_textrc (str)
6242 char * str;
6243{
6244 unsigned long number;
6245
6246 if ((number = check_iwmmxt_insn (str, check_textrc, 7)) == (unsigned long) FAIL)
6247 return;
6248
6249 inst.instruction |= number & 0x7;
e16bb312
NC
6250}
6251
6252static void
6253do_iwmmxt_textrm (str)
6254 char * str;
6255{
6256 unsigned long number;
6257
6258 if ((number = check_iwmmxt_insn (str, check_textrm, 7)) == (unsigned long) FAIL)
6259 return;
6260
6261 inst.instruction |= number & 0x7;
6262}
6263
6264static void
6265do_iwmmxt_tinsr (str)
6266 char * str;
6267{
6268 unsigned long number;
6269
6270 if ((number = check_iwmmxt_insn (str, check_tinsr, 7)) == (unsigned long) FAIL)
6271 return;
6272
6273 inst.instruction |= number & 0x7;
e16bb312
NC
6274}
6275
6276static void
6277do_iwmmxt_tmcr (str)
6278 char * str;
6279{
6280 check_iwmmxt_insn (str, check_tmcr, 0);
e16bb312
NC
6281}
6282
6283static void
6284do_iwmmxt_tmcrr (str)
6285 char * str;
6286{
6287 check_iwmmxt_insn (str, check_tmcrr, 0);
e16bb312
NC
6288}
6289
6290static void
6291do_iwmmxt_tmia (str)
6292 char * str;
6293{
6294 check_iwmmxt_insn (str, check_tmia, 0);
e16bb312
NC
6295}
6296
6297static void
6298do_iwmmxt_tmovmsk (str)
6299 char * str;
6300{
6301 check_iwmmxt_insn (str, check_tmovmsk, 0);
e16bb312
NC
6302}
6303
6304static void
6305do_iwmmxt_tmrc (str)
6306 char * str;
6307{
6308 check_iwmmxt_insn (str, check_tmrc, 0);
e16bb312
NC
6309}
6310
6311static void
6312do_iwmmxt_tmrrc (str)
6313 char * str;
6314{
6315 check_iwmmxt_insn (str, check_tmrrc, 0);
e16bb312
NC
6316}
6317
6318static void
6319do_iwmmxt_torc (str)
6320 char * str;
6321{
6322 check_iwmmxt_insn (str, check_rd, 0);
e16bb312
NC
6323}
6324
6325static void
6326do_iwmmxt_waligni (str)
6327 char * str;
6328{
6329 unsigned long number;
6330
6331 if ((number = check_iwmmxt_insn (str, check_waligni, 7)) == (unsigned long) FAIL)
6332 return;
6333
6334 inst.instruction |= ((number & 0x7) << 20);
e16bb312
NC
6335}
6336
6337static void
6338do_iwmmxt_wmov (str)
6339 char * str;
6340{
6341 if (check_iwmmxt_insn (str, check_wrwr, 0) == (unsigned long) FAIL)
6342 return;
6343
6344 inst.instruction |= ((inst.instruction >> 16) & 0xf);
e16bb312
NC
6345}
6346
6347static void
6348do_iwmmxt_word_addr (str)
6349 char * str;
6350{
6351 int op = (inst.instruction & 0x300) >> 8;
6352 int reg;
6353
6354 inst.instruction &= ~0x300;
6355 inst.instruction |= (op & 1) << 22 | (op & 2) << 7;
6356
6357 skip_whitespace (str);
6358
6359 if ((reg = wreg_required_here (&str, 12, IWMMXT_REG_WR_OR_WC)) == FAIL
6360 || skip_past_comma (& str) == FAIL
6361 || cp_address_required_here (& str, CP_WB_OK) == FAIL)
6362 {
6363 if (! inst.error)
6364 inst.error = BAD_ARGS;
6365 }
6366 else
6367 end_of_line (str);
6368
6369 if (wc_register (reg))
6370 {
ece01a63
ILT
6371 if ((inst.instruction & COND_MASK) != COND_ALWAYS)
6372 as_bad (_("conditional execution not supported with control register"));
6373 if (op != 2)
6374 as_bad (_("non-word size not supported with control register"));
e16bb312
NC
6375 inst.instruction |= 0xf0000100;
6376 inst.instruction &= ~0x00400000;
6377 }
6378}
6379
6380static void
6381do_iwmmxt_wrwr (str)
6382 char * str;
6383{
6384 check_iwmmxt_insn (str, check_wrwr, 0);
e16bb312
NC
6385}
6386
6387static void
6388do_iwmmxt_wrwrwcg (str)
6389 char * str;
6390{
6391 check_iwmmxt_insn (str, check_wrwrwcg, 0);
e16bb312
NC
6392}
6393
6394static void
6395do_iwmmxt_wrwrwr (str)
6396 char * str;
6397{
6398 check_iwmmxt_insn (str, check_wrwrwr, 0);
e16bb312
NC
6399}
6400
6401static void
6402do_iwmmxt_wshufh (str)
6403 char * str;
6404{
6405 unsigned long number;
6406
6407 if ((number = check_iwmmxt_insn (str, check_wshufh, 0xff)) == (unsigned long) FAIL)
6408 return;
6409
6410 inst.instruction |= ((number & 0xf0) << 16) | (number & 0xf);
e16bb312
NC
6411}
6412
6413static void
6414do_iwmmxt_wzero (str)
6415 char * str;
6416{
6417 if (check_iwmmxt_insn (str, check_wr, 0) == (unsigned long) FAIL)
6418 return;
6419
6420 inst.instruction |= ((inst.instruction & 0xf) << 12) | ((inst.instruction & 0xf) << 16);
e16bb312
NC
6421}
6422
b99bd4ef
NC
6423/* Xscale multiply-accumulate (argument parse)
6424 MIAcc acc0,Rm,Rs
6425 MIAPHcc acc0,Rm,Rs
6426 MIAxycc acc0,Rm,Rs. */
6427
6428static void
63e63b07 6429do_xsc_mia (str)
b99bd4ef 6430 char * str;
b99bd4ef
NC
6431{
6432 int rs;
6433 int rm;
6434
f2b7cb0a 6435 if (accum0_required_here (& str) == FAIL)
b99bd4ef
NC
6436 inst.error = ERR_NO_ACCUM;
6437
6438 else if (skip_past_comma (& str) == FAIL
6439 || (rm = reg_required_here (& str, 0)) == FAIL)
6440 inst.error = BAD_ARGS;
6441
6442 else if (skip_past_comma (& str) == FAIL
6443 || (rs = reg_required_here (& str, 12)) == FAIL)
6444 inst.error = BAD_ARGS;
6445
6446 /* inst.instruction has now been zapped with both rm and rs. */
6447 else if (rm == REG_PC || rs == REG_PC)
6448 inst.error = BAD_PC; /* Undefined result if rm or rs is R15. */
6449
6450 else
6451 end_of_line (str);
6452}
6453
6454/* Xscale move-accumulator-register (argument parse)
6455
6456 MARcc acc0,RdLo,RdHi. */
6457
6458static void
63e63b07 6459do_xsc_mar (str)
b99bd4ef 6460 char * str;
b99bd4ef
NC
6461{
6462 int rdlo, rdhi;
6463
f2b7cb0a 6464 if (accum0_required_here (& str) == FAIL)
b99bd4ef
NC
6465 inst.error = ERR_NO_ACCUM;
6466
6467 else if (skip_past_comma (& str) == FAIL
6468 || (rdlo = reg_required_here (& str, 12)) == FAIL)
6469 inst.error = BAD_ARGS;
6470
6471 else if (skip_past_comma (& str) == FAIL
6472 || (rdhi = reg_required_here (& str, 16)) == FAIL)
6473 inst.error = BAD_ARGS;
6474
6475 /* inst.instruction has now been zapped with both rdlo and rdhi. */
6476 else if (rdlo == REG_PC || rdhi == REG_PC)
6477 inst.error = BAD_PC; /* Undefined result if rdlo or rdhi is R15. */
6478
6479 else
6480 end_of_line (str);
6481}
6482
6483/* Xscale move-register-accumulator (argument parse)
6484
6485 MRAcc RdLo,RdHi,acc0. */
6486
6487static void
63e63b07 6488do_xsc_mra (str)
b99bd4ef 6489 char * str;
b99bd4ef
NC
6490{
6491 int rdlo;
6492 int rdhi;
6493
b99bd4ef
NC
6494 skip_whitespace (str);
6495
6496 if ((rdlo = reg_required_here (& str, 12)) == FAIL)
6497 inst.error = BAD_ARGS;
6498
6499 else if (skip_past_comma (& str) == FAIL
6500 || (rdhi = reg_required_here (& str, 16)) == FAIL)
6501 inst.error = BAD_ARGS;
6502
6503 else if (skip_past_comma (& str) == FAIL
6504 || accum0_required_here (& str) == FAIL)
6505 inst.error = ERR_NO_ACCUM;
6506
6507 /* inst.instruction has now been zapped with both rdlo and rdhi. */
6508 else if (rdlo == rdhi)
6509 inst.error = BAD_ARGS; /* Undefined result if 2 writes to same reg. */
6510
6511 else if (rdlo == REG_PC || rdhi == REG_PC)
6512 inst.error = BAD_PC; /* Undefined result if rdlo or rdhi is R15. */
6513 else
6514 end_of_line (str);
6515}
6516
c9b604bd 6517/* ARMv5TE: Preload-Cache
b99bd4ef
NC
6518
6519 PLD <addr_mode>
6520
6521 Syntactically, like LDR with B=1, W=0, L=1. */
6522
6523static void
f2b7cb0a 6524do_pld (str)
b99bd4ef 6525 char * str;
b99bd4ef
NC
6526{
6527 int rd;
6528
b99bd4ef
NC
6529 skip_whitespace (str);
6530
6531 if (* str != '[')
6532 {
6533 inst.error = _("'[' expected after PLD mnemonic");
6534 return;
6535 }
6536
90e4755a 6537 ++str;
b99bd4ef
NC
6538 skip_whitespace (str);
6539
6540 if ((rd = reg_required_here (& str, 16)) == FAIL)
6541 return;
6542
6543 skip_whitespace (str);
6544
90e4755a 6545 if (*str == ']')
b99bd4ef
NC
6546 {
6547 /* [Rn], ... ? */
90e4755a 6548 ++str;
b99bd4ef
NC
6549 skip_whitespace (str);
6550
90e4755a
RE
6551 /* Post-indexed addressing is not allowed with PLD. */
6552 if (skip_past_comma (&str) == SUCCESS)
b99bd4ef 6553 {
90e4755a
RE
6554 inst.error
6555 = _("post-indexed expression used in preload instruction");
6556 return;
b99bd4ef 6557 }
90e4755a 6558 else if (*str == '!') /* [Rn]! */
b99bd4ef
NC
6559 {
6560 inst.error = _("writeback used in preload instruction");
90e4755a 6561 ++str;
b99bd4ef
NC
6562 }
6563 else /* [Rn] */
6564 inst.instruction |= INDEX_UP | PRE_INDEX;
6565 }
6566 else /* [Rn, ...] */
6567 {
6568 if (skip_past_comma (& str) == FAIL)
6569 {
6570 inst.error = _("pre-indexed expression expected");
6571 return;
6572 }
6573
90e4755a 6574 if (ldst_extend (&str) == FAIL)
b99bd4ef
NC
6575 return;
6576
6577 skip_whitespace (str);
6578
6579 if (* str != ']')
6580 {
6581 inst.error = _("missing ]");
6582 return;
6583 }
6584
6585 ++ str;
6586 skip_whitespace (str);
6587
6588 if (* str == '!') /* [Rn]! */
6589 {
6590 inst.error = _("writeback used in preload instruction");
6591 ++ str;
6592 }
6593
6594 inst.instruction |= PRE_INDEX;
6595 }
6596
6597 end_of_line (str);
6598}
6599
c9b604bd 6600/* ARMv5TE load-consecutive (argument parse)
b99bd4ef
NC
6601 Mode is like LDRH.
6602
6603 LDRccD R, mode
6604 STRccD R, mode. */
6605
6606static void
f2b7cb0a 6607do_ldrd (str)
b99bd4ef 6608 char * str;
b99bd4ef
NC
6609{
6610 int rd;
6611 int rn;
6612
b99bd4ef
NC
6613 skip_whitespace (str);
6614
6615 if ((rd = reg_required_here (& str, 12)) == FAIL)
6616 {
6617 inst.error = BAD_ARGS;
6618 return;
6619 }
6620
6621 if (skip_past_comma (& str) == FAIL
6622 || (rn = ld_mode_required_here (& str)) == FAIL)
6623 {
6624 if (!inst.error)
cc8a6dd0 6625 inst.error = BAD_ARGS;
b99bd4ef
NC
6626 return;
6627 }
6628
6629 /* inst.instruction has now been zapped with Rd and the addressing mode. */
6630 if (rd & 1) /* Unpredictable result if Rd is odd. */
6631 {
f03698e6 6632 inst.error = _("destination register must be even");
b99bd4ef
NC
6633 return;
6634 }
6635
90e4755a 6636 if (rd == REG_LR)
b99bd4ef 6637 {
f2b7cb0a 6638 inst.error = _("r14 not allowed here");
b99bd4ef
NC
6639 return;
6640 }
6641
6642 if (((rd == rn) || (rd + 1 == rn))
90e4755a
RE
6643 && ((inst.instruction & WRITE_BACK)
6644 || (!(inst.instruction & PRE_INDEX))))
b99bd4ef
NC
6645 as_warn (_("pre/post-indexing used when modified address register is destination"));
6646
90e4755a
RE
6647 /* For an index-register load, the index register must not overlap the
6648 destination (even if not write-back). */
6649 if ((inst.instruction & V4_STR_BIT) == 0
6650 && (inst.instruction & HWOFFSET_IMM) == 0)
6651 {
6652 int rm = inst.instruction & 0x0000000f;
6653
6654 if (rm == rd || (rm == rd + 1))
6655 as_warn (_("ldrd destination registers must not overlap index register"));
6656 }
6657
b99bd4ef
NC
6658 end_of_line (str);
6659}
6660
6661/* Returns the index into fp_values of a floating point number,
6662 or -1 if not in the table. */
6663
6664static int
6665my_get_float_expression (str)
6666 char ** str;
6667{
6668 LITTLENUM_TYPE words[MAX_LITTLENUMS];
6669 char * save_in;
6670 expressionS exp;
6671 int i;
6672 int j;
6673
6674 memset (words, 0, MAX_LITTLENUMS * sizeof (LITTLENUM_TYPE));
6675
6676 /* Look for a raw floating point number. */
6677 if ((save_in = atof_ieee (*str, 'x', words)) != NULL
6678 && is_end_of_line[(unsigned char) *save_in])
6679 {
6680 for (i = 0; i < NUM_FLOAT_VALS; i++)
6681 {
6682 for (j = 0; j < MAX_LITTLENUMS; j++)
6683 {
6684 if (words[j] != fp_values[i][j])
6685 break;
6686 }
6687
6688 if (j == MAX_LITTLENUMS)
6689 {
6690 *str = save_in;
6691 return i;
6692 }
6693 }
6694 }
6695
6696 /* Try and parse a more complex expression, this will probably fail
6697 unless the code uses a floating point prefix (eg "0f"). */
6698 save_in = input_line_pointer;
6699 input_line_pointer = *str;
6700 if (expression (&exp) == absolute_section
6701 && exp.X_op == O_big
6702 && exp.X_add_number < 0)
6703 {
6704 /* FIXME: 5 = X_PRECISION, should be #define'd where we can use it.
6705 Ditto for 15. */
6706 if (gen_to_words (words, 5, (long) 15) == 0)
6707 {
6708 for (i = 0; i < NUM_FLOAT_VALS; i++)
6709 {
6710 for (j = 0; j < MAX_LITTLENUMS; j++)
6711 {
6712 if (words[j] != fp_values[i][j])
6713 break;
6714 }
6715
6716 if (j == MAX_LITTLENUMS)
6717 {
6718 *str = input_line_pointer;
6719 input_line_pointer = save_in;
6720 return i;
6721 }
6722 }
6723 }
6724 }
6725
6726 *str = input_line_pointer;
6727 input_line_pointer = save_in;
6728 return -1;
6729}
6730
b34976b6 6731/* Return TRUE if anything in the expression is a bignum. */
b99bd4ef
NC
6732
6733static int
6734walk_no_bignums (sp)
6735 symbolS * sp;
6736{
6737 if (symbol_get_value_expression (sp)->X_op == O_big)
6738 return 1;
6739
6740 if (symbol_get_value_expression (sp)->X_add_symbol)
6741 {
6742 return (walk_no_bignums (symbol_get_value_expression (sp)->X_add_symbol)
6743 || (symbol_get_value_expression (sp)->X_op_symbol
6744 && walk_no_bignums (symbol_get_value_expression (sp)->X_op_symbol)));
6745 }
6746
6747 return 0;
6748}
6749
f03698e6
RE
6750static int in_my_get_expression = 0;
6751
b99bd4ef
NC
6752static int
6753my_get_expression (ep, str)
6754 expressionS * ep;
6755 char ** str;
6756{
6757 char * save_in;
6758 segT seg;
6759
6760 save_in = input_line_pointer;
6761 input_line_pointer = *str;
f03698e6 6762 in_my_get_expression = 1;
b99bd4ef 6763 seg = expression (ep);
f03698e6
RE
6764 in_my_get_expression = 0;
6765
6766 if (ep->X_op == O_illegal)
6767 {
6768 /* We found a bad expression in md_operand(). */
6769 *str = input_line_pointer;
6770 input_line_pointer = save_in;
6771 return 1;
6772 }
b99bd4ef
NC
6773
6774#ifdef OBJ_AOUT
6775 if (seg != absolute_section
6776 && seg != text_section
6777 && seg != data_section
6778 && seg != bss_section
6779 && seg != undefined_section)
6780 {
6781 inst.error = _("bad_segment");
6782 *str = input_line_pointer;
6783 input_line_pointer = save_in;
6784 return 1;
6785 }
6786#endif
6787
6788 /* Get rid of any bignums now, so that we don't generate an error for which
6789 we can't establish a line number later on. Big numbers are never valid
6790 in instructions, which is where this routine is always called. */
6791 if (ep->X_op == O_big
6792 || (ep->X_add_symbol
6793 && (walk_no_bignums (ep->X_add_symbol)
6794 || (ep->X_op_symbol
6795 && walk_no_bignums (ep->X_op_symbol)))))
6796 {
f03698e6 6797 inst.error = _("invalid constant");
b99bd4ef
NC
6798 *str = input_line_pointer;
6799 input_line_pointer = save_in;
6800 return 1;
6801 }
6802
6803 *str = input_line_pointer;
6804 input_line_pointer = save_in;
6805 return 0;
6806}
6807
cc8a6dd0 6808/* We handle all bad expressions here, so that we can report the faulty
f03698e6
RE
6809 instruction in the error message. */
6810void
ce058b6c 6811md_operand (expr)
f03698e6
RE
6812 expressionS *expr;
6813{
6814 if (in_my_get_expression)
6815 {
6816 expr->X_op = O_illegal;
6817 if (inst.error == NULL)
6818 inst.error = _("bad expression");
6819 }
6820}
6821
09d92015 6822/* KIND indicates what kind of shifts are accepted. */
b99bd4ef
NC
6823
6824static int
09d92015 6825decode_shift (str, kind)
b99bd4ef 6826 char ** str;
09d92015 6827 int kind;
b99bd4ef
NC
6828{
6829 const struct asm_shift_name * shift;
6830 char * p;
6831 char c;
6832
6833 skip_whitespace (* str);
6834
3882b010 6835 for (p = * str; ISALPHA (* p); p ++)
b99bd4ef
NC
6836 ;
6837
6838 if (p == * str)
6839 {
f03698e6 6840 inst.error = _("shift expression expected");
b99bd4ef
NC
6841 return FAIL;
6842 }
6843
6844 c = * p;
6845 * p = '\0';
6846 shift = (const struct asm_shift_name *) hash_find (arm_shift_hsh, * str);
6847 * p = c;
6848
6849 if (shift == NULL)
6850 {
f03698e6 6851 inst.error = _("shift expression expected");
b99bd4ef
NC
6852 return FAIL;
6853 }
6854
6855 assert (shift->properties->index == shift_properties[shift->properties->index].index);
6856
09d92015
MM
6857 if (kind == SHIFT_LSL_OR_ASR_IMMEDIATE
6858 && shift->properties->index != SHIFT_LSL
6859 && shift->properties->index != SHIFT_ASR)
6860 {
6861 inst.error = _("'LSL' or 'ASR' required");
6862 return FAIL;
6863 }
6864 else if (kind == SHIFT_LSL_IMMEDIATE
6865 && shift->properties->index != SHIFT_LSL)
6866 {
6867 inst.error = _("'LSL' required");
6868 return FAIL;
6869 }
6870 else if (kind == SHIFT_ASR_IMMEDIATE
6871 && shift->properties->index != SHIFT_ASR)
6872 {
6873 inst.error = _("'ASR' required");
6874 return FAIL;
6875 }
6876
b99bd4ef
NC
6877 if (shift->properties->index == SHIFT_RRX)
6878 {
6879 * str = p;
6880 inst.instruction |= shift->properties->bit_field;
6881 return SUCCESS;
6882 }
6883
6884 skip_whitespace (p);
6885
09d92015 6886 if (kind == NO_SHIFT_RESTRICT && reg_required_here (& p, 8) != FAIL)
b99bd4ef
NC
6887 {
6888 inst.instruction |= shift->properties->bit_field | SHIFT_BY_REG;
6889 * str = p;
6890 return SUCCESS;
6891 }
6892 else if (! is_immediate_prefix (* p))
6893 {
09d92015 6894 inst.error = (NO_SHIFT_RESTRICT
b99bd4ef
NC
6895 ? _("shift requires register or #expression")
6896 : _("shift requires #expression"));
6897 * str = p;
6898 return FAIL;
6899 }
6900
6901 inst.error = NULL;
6902 p ++;
6903
6904 if (my_get_expression (& inst.reloc.exp, & p))
6905 return FAIL;
6906
6907 /* Validate some simple #expressions. */
6908 if (inst.reloc.exp.X_op == O_constant)
6909 {
6910 unsigned num = inst.reloc.exp.X_add_number;
6911
6912 /* Reject operations greater than 32. */
6913 if (num > 32
6914 /* Reject a shift of 0 unless the mode allows it. */
6915 || (num == 0 && shift->properties->allows_0 == 0)
6916 /* Reject a shift of 32 unless the mode allows it. */
6917 || (num == 32 && shift->properties->allows_32 == 0)
6918 )
6919 {
6920 /* As a special case we allow a shift of zero for
6921 modes that do not support it to be recoded as an
6922 logical shift left of zero (ie nothing). We warn
6923 about this though. */
6924 if (num == 0)
6925 {
f03698e6 6926 as_warn (_("shift of 0 ignored."));
b99bd4ef
NC
6927 shift = & shift_names[0];
6928 assert (shift->properties->index == SHIFT_LSL);
6929 }
6930 else
6931 {
f03698e6 6932 inst.error = _("invalid immediate shift");
b99bd4ef
NC
6933 return FAIL;
6934 }
6935 }
6936
6937 /* Shifts of 32 are encoded as 0, for those shifts that
6938 support it. */
6939 if (num == 32)
6940 num = 0;
6941
6942 inst.instruction |= (num << 7) | shift->properties->bit_field;
6943 }
6944 else
6945 {
6946 inst.reloc.type = BFD_RELOC_ARM_SHIFT_IMM;
6947 inst.reloc.pc_rel = 0;
6948 inst.instruction |= shift->properties->bit_field;
6949 }
6950
6951 * str = p;
6952 return SUCCESS;
6953}
6954
6955/* Do those data_ops which can take a negative immediate constant
2d2255b5 6956 by altering the instruction. A bit of a hack really.
b99bd4ef
NC
6957 MOV <-> MVN
6958 AND <-> BIC
6959 ADC <-> SBC
6960 by inverting the second operand, and
6961 ADD <-> SUB
6962 CMP <-> CMN
6963 by negating the second operand. */
6964
6965static int
6966negate_data_op (instruction, value)
6967 unsigned long * instruction;
6968 unsigned long value;
6969{
6970 int op, new_inst;
6971 unsigned long negated, inverted;
6972
6973 negated = validate_immediate (-value);
6974 inverted = validate_immediate (~value);
6975
6976 op = (*instruction >> DATA_OP_SHIFT) & 0xf;
6977 switch (op)
6978 {
6979 /* First negates. */
6980 case OPCODE_SUB: /* ADD <-> SUB */
6981 new_inst = OPCODE_ADD;
6982 value = negated;
6983 break;
6984
6985 case OPCODE_ADD:
6986 new_inst = OPCODE_SUB;
6987 value = negated;
6988 break;
6989
6990 case OPCODE_CMP: /* CMP <-> CMN */
6991 new_inst = OPCODE_CMN;
6992 value = negated;
6993 break;
6994
6995 case OPCODE_CMN:
6996 new_inst = OPCODE_CMP;
6997 value = negated;
6998 break;
6999
7000 /* Now Inverted ops. */
7001 case OPCODE_MOV: /* MOV <-> MVN */
7002 new_inst = OPCODE_MVN;
7003 value = inverted;
7004 break;
7005
7006 case OPCODE_MVN:
7007 new_inst = OPCODE_MOV;
7008 value = inverted;
7009 break;
7010
7011 case OPCODE_AND: /* AND <-> BIC */
7012 new_inst = OPCODE_BIC;
7013 value = inverted;
7014 break;
7015
7016 case OPCODE_BIC:
7017 new_inst = OPCODE_AND;
7018 value = inverted;
7019 break;
7020
7021 case OPCODE_ADC: /* ADC <-> SBC */
7022 new_inst = OPCODE_SBC;
7023 value = inverted;
7024 break;
7025
7026 case OPCODE_SBC:
7027 new_inst = OPCODE_ADC;
7028 value = inverted;
7029 break;
7030
7031 /* We cannot do anything. */
7032 default:
7033 return FAIL;
7034 }
7035
7036 if (value == (unsigned) FAIL)
7037 return FAIL;
7038
7039 *instruction &= OPCODE_MASK;
7040 *instruction |= new_inst << DATA_OP_SHIFT;
7041 return value;
7042}
7043
7044static int
7045data_op2 (str)
7046 char ** str;
7047{
7048 int value;
7049 expressionS expr;
7050
7051 skip_whitespace (* str);
7052
7053 if (reg_required_here (str, 0) != FAIL)
7054 {
7055 if (skip_past_comma (str) == SUCCESS)
7056 /* Shift operation on register. */
7057 return decode_shift (str, NO_SHIFT_RESTRICT);
7058
7059 return SUCCESS;
7060 }
7061 else
7062 {
7063 /* Immediate expression. */
7064 if (is_immediate_prefix (**str))
7065 {
7066 (*str)++;
7067 inst.error = NULL;
7068
7069 if (my_get_expression (&inst.reloc.exp, str))
7070 return FAIL;
7071
7072 if (inst.reloc.exp.X_add_symbol)
7073 {
7074 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
7075 inst.reloc.pc_rel = 0;
7076 }
7077 else
7078 {
7079 if (skip_past_comma (str) == SUCCESS)
7080 {
7081 /* #x, y -- ie explicit rotation by Y. */
7082 if (my_get_expression (&expr, str))
7083 return FAIL;
7084
7085 if (expr.X_op != O_constant)
7086 {
f03698e6 7087 inst.error = _("constant expression expected");
b99bd4ef
NC
7088 return FAIL;
7089 }
7090
7091 /* Rotate must be a multiple of 2. */
7092 if (((unsigned) expr.X_add_number) > 30
7093 || (expr.X_add_number & 1) != 0
7094 || ((unsigned) inst.reloc.exp.X_add_number) > 255)
7095 {
f03698e6 7096 inst.error = _("invalid constant");
b99bd4ef
NC
7097 return FAIL;
7098 }
7099 inst.instruction |= INST_IMMEDIATE;
7100 inst.instruction |= inst.reloc.exp.X_add_number;
7101 inst.instruction |= expr.X_add_number << 7;
7102 return SUCCESS;
7103 }
7104
7105 /* Implicit rotation, select a suitable one. */
7106 value = validate_immediate (inst.reloc.exp.X_add_number);
7107
7108 if (value == FAIL)
7109 {
7110 /* Can't be done. Perhaps the code reads something like
7111 "add Rd, Rn, #-n", where "sub Rd, Rn, #n" would be OK. */
7112 if ((value = negate_data_op (&inst.instruction,
7113 inst.reloc.exp.X_add_number))
7114 == FAIL)
7115 {
f03698e6 7116 inst.error = _("invalid constant");
b99bd4ef
NC
7117 return FAIL;
7118 }
7119 }
7120
7121 inst.instruction |= value;
7122 }
7123
7124 inst.instruction |= INST_IMMEDIATE;
7125 return SUCCESS;
7126 }
7127
7128 (*str)++;
f03698e6 7129 inst.error = _("register or shift expression expected");
b99bd4ef
NC
7130 return FAIL;
7131 }
7132}
7133
7134static int
7135fp_op2 (str)
7136 char ** str;
7137{
7138 skip_whitespace (* str);
7139
7140 if (fp_reg_required_here (str, 0) != FAIL)
7141 return SUCCESS;
7142 else
7143 {
7144 /* Immediate expression. */
7145 if (*((*str)++) == '#')
7146 {
7147 int i;
7148
7149 inst.error = NULL;
7150
7151 skip_whitespace (* str);
7152
7153 /* First try and match exact strings, this is to guarantee
7154 that some formats will work even for cross assembly. */
7155
7156 for (i = 0; fp_const[i]; i++)
7157 {
7158 if (strncmp (*str, fp_const[i], strlen (fp_const[i])) == 0)
7159 {
7160 char *start = *str;
7161
7162 *str += strlen (fp_const[i]);
7163 if (is_end_of_line[(unsigned char) **str])
7164 {
7165 inst.instruction |= i + 8;
7166 return SUCCESS;
7167 }
7168 *str = start;
7169 }
7170 }
7171
7172 /* Just because we didn't get a match doesn't mean that the
7173 constant isn't valid, just that it is in a format that we
7174 don't automatically recognize. Try parsing it with
7175 the standard expression routines. */
7176 if ((i = my_get_float_expression (str)) >= 0)
7177 {
7178 inst.instruction |= i + 8;
7179 return SUCCESS;
7180 }
7181
f03698e6 7182 inst.error = _("invalid floating point immediate expression");
b99bd4ef
NC
7183 return FAIL;
7184 }
7185 inst.error =
f03698e6 7186 _("floating point register or immediate expression expected");
b99bd4ef
NC
7187 return FAIL;
7188 }
7189}
7190
7191static void
f2b7cb0a 7192do_arit (str)
b99bd4ef 7193 char * str;
b99bd4ef
NC
7194{
7195 skip_whitespace (str);
7196
7197 if (reg_required_here (&str, 12) == FAIL
7198 || skip_past_comma (&str) == FAIL
7199 || reg_required_here (&str, 16) == FAIL
7200 || skip_past_comma (&str) == FAIL
7201 || data_op2 (&str) == FAIL)
7202 {
7203 if (!inst.error)
7204 inst.error = BAD_ARGS;
7205 return;
7206 }
7207
b99bd4ef 7208 end_of_line (str);
b99bd4ef
NC
7209}
7210
7211static void
f2b7cb0a 7212do_adr (str)
b99bd4ef 7213 char * str;
b99bd4ef 7214{
90e4755a
RE
7215 /* This is a pseudo-op of the form "adr rd, label" to be converted
7216 into a relative address of the form "add rd, pc, #label-.-8". */
7217 skip_whitespace (str);
7218
7219 if (reg_required_here (&str, 12) == FAIL
7220 || skip_past_comma (&str) == FAIL
7221 || my_get_expression (&inst.reloc.exp, &str))
7222 {
7223 if (!inst.error)
7224 inst.error = BAD_ARGS;
7225 return;
7226 }
7227
7228 /* Frag hacking will turn this into a sub instruction if the offset turns
7229 out to be negative. */
7230 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
250355db 7231#ifndef TE_WINCE
90e4755a 7232 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust. */
250355db 7233#endif
90e4755a
RE
7234 inst.reloc.pc_rel = 1;
7235
7236 end_of_line (str);
7237}
7238
7239static void
f2b7cb0a 7240do_adrl (str)
90e4755a 7241 char * str;
90e4755a
RE
7242{
7243 /* This is a pseudo-op of the form "adrl rd, label" to be converted
7244 into a relative address of the form:
7245 add rd, pc, #low(label-.-8)"
7246 add rd, rd, #high(label-.-8)" */
7247
7248 skip_whitespace (str);
7249
7250 if (reg_required_here (&str, 12) == FAIL
7251 || skip_past_comma (&str) == FAIL
7252 || my_get_expression (&inst.reloc.exp, &str))
7253 {
7254 if (!inst.error)
7255 inst.error = BAD_ARGS;
7256
7257 return;
7258 }
7259
7260 end_of_line (str);
7261 /* Frag hacking will turn this into a sub instruction if the offset turns
7262 out to be negative. */
7263 inst.reloc.type = BFD_RELOC_ARM_ADRL_IMMEDIATE;
250355db 7264#ifndef TE_WINCE
90e4755a 7265 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust */
250355db 7266#endif
90e4755a
RE
7267 inst.reloc.pc_rel = 1;
7268 inst.size = INSN_SIZE * 2;
90e4755a
RE
7269}
7270
7271static void
f2b7cb0a 7272do_cmp (str)
90e4755a 7273 char * str;
90e4755a
RE
7274{
7275 skip_whitespace (str);
7276
7277 if (reg_required_here (&str, 16) == FAIL)
7278 {
7279 if (!inst.error)
7280 inst.error = BAD_ARGS;
7281 return;
7282 }
7283
7284 if (skip_past_comma (&str) == FAIL
7285 || data_op2 (&str) == FAIL)
7286 {
7287 if (!inst.error)
7288 inst.error = BAD_ARGS;
7289 return;
7290 }
7291
90e4755a 7292 end_of_line (str);
90e4755a
RE
7293}
7294
7295static void
f2b7cb0a 7296do_mov (str)
90e4755a 7297 char * str;
90e4755a
RE
7298{
7299 skip_whitespace (str);
7300
7301 if (reg_required_here (&str, 12) == FAIL)
7302 {
7303 if (!inst.error)
7304 inst.error = BAD_ARGS;
7305 return;
7306 }
7307
7308 if (skip_past_comma (&str) == FAIL
7309 || data_op2 (&str) == FAIL)
7310 {
7311 if (!inst.error)
7312 inst.error = BAD_ARGS;
7313 return;
7314 }
7315
90e4755a 7316 end_of_line (str);
90e4755a
RE
7317}
7318
7319static int
7320ldst_extend (str)
7321 char ** str;
7322{
7323 int add = INDEX_UP;
7324
7325 switch (**str)
7326 {
7327 case '#':
7328 case '$':
7329 (*str)++;
7330 if (my_get_expression (& inst.reloc.exp, str))
7331 return FAIL;
7332
7333 if (inst.reloc.exp.X_op == O_constant)
7334 {
7335 int value = inst.reloc.exp.X_add_number;
7336
7337 if (value < -4095 || value > 4095)
7338 {
7339 inst.error = _("address offset too large");
7340 return FAIL;
7341 }
7342
7343 if (value < 0)
7344 {
7345 value = -value;
7346 add = 0;
7347 }
7348
7349 inst.instruction |= add | value;
7350 }
7351 else
7352 {
7353 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
7354 inst.reloc.pc_rel = 0;
7355 }
7356 return SUCCESS;
7357
7358 case '-':
7359 add = 0;
7360 /* Fall through. */
7361
7362 case '+':
7363 (*str)++;
7364 /* Fall through. */
7365
7366 default:
7367 if (reg_required_here (str, 0) == FAIL)
7368 return FAIL;
7369
7370 inst.instruction |= add | OFFSET_REG;
7371 if (skip_past_comma (str) == SUCCESS)
09d92015 7372 return decode_shift (str, SHIFT_IMMEDIATE);
90e4755a
RE
7373
7374 return SUCCESS;
7375 }
7376}
7377
7378static void
f2b7cb0a 7379do_ldst (str)
90e4755a 7380 char * str;
90e4755a
RE
7381{
7382 int pre_inc = 0;
7383 int conflict_reg;
7384 int value;
7385
b99bd4ef
NC
7386 skip_whitespace (str);
7387
90e4755a
RE
7388 if ((conflict_reg = reg_required_here (&str, 12)) == FAIL)
7389 {
7390 if (!inst.error)
7391 inst.error = BAD_ARGS;
7392 return;
7393 }
7394
7395 if (skip_past_comma (&str) == FAIL)
7396 {
f03698e6 7397 inst.error = _("address expected");
90e4755a
RE
7398 return;
7399 }
7400
90e4755a
RE
7401 if (*str == '[')
7402 {
7403 int reg;
7404
7405 str++;
7406
7407 skip_whitespace (str);
7408
7409 if ((reg = reg_required_here (&str, 16)) == FAIL)
7410 return;
7411
7412 /* Conflicts can occur on stores as well as loads. */
7413 conflict_reg = (conflict_reg == reg);
7414
7415 skip_whitespace (str);
7416
7417 if (*str == ']')
7418 {
7419 str ++;
7420
7421 if (skip_past_comma (&str) == SUCCESS)
7422 {
7423 /* [Rn],... (post inc) */
7424 if (ldst_extend (&str) == FAIL)
7425 return;
7426 if (conflict_reg)
7427 as_warn (_("%s register same as write-back base"),
7428 ((inst.instruction & LOAD_BIT)
7429 ? _("destination") : _("source")));
7430 }
7431 else
7432 {
7433 /* [Rn] */
7434 skip_whitespace (str);
7435
7436 if (*str == '!')
7437 {
7438 if (conflict_reg)
7439 as_warn (_("%s register same as write-back base"),
7440 ((inst.instruction & LOAD_BIT)
7441 ? _("destination") : _("source")));
7442 str++;
7443 inst.instruction |= WRITE_BACK;
7444 }
7445
7446 inst.instruction |= INDEX_UP;
7447 pre_inc = 1;
7448 }
7449 }
7450 else
7451 {
7452 /* [Rn,...] */
7453 if (skip_past_comma (&str) == FAIL)
7454 {
7455 inst.error = _("pre-indexed expression expected");
7456 return;
7457 }
7458
7459 pre_inc = 1;
7460 if (ldst_extend (&str) == FAIL)
7461 return;
7462
7463 skip_whitespace (str);
7464
7465 if (*str++ != ']')
7466 {
7467 inst.error = _("missing ]");
7468 return;
7469 }
7470
7471 skip_whitespace (str);
7472
7473 if (*str == '!')
7474 {
7475 if (conflict_reg)
7476 as_warn (_("%s register same as write-back base"),
7477 ((inst.instruction & LOAD_BIT)
7478 ? _("destination") : _("source")));
7479 str++;
7480 inst.instruction |= WRITE_BACK;
7481 }
7482 }
7483 }
7484 else if (*str == '=')
7485 {
f03698e6
RE
7486 if ((inst.instruction & LOAD_BIT) == 0)
7487 {
7488 inst.error = _("invalid pseudo operation");
7489 return;
7490 }
7491
90e4755a
RE
7492 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
7493 str++;
7494
7495 skip_whitespace (str);
7496
7497 if (my_get_expression (&inst.reloc.exp, &str))
7498 return;
7499
7500 if (inst.reloc.exp.X_op != O_constant
7501 && inst.reloc.exp.X_op != O_symbol)
7502 {
f03698e6 7503 inst.error = _("constant expression expected");
90e4755a
RE
7504 return;
7505 }
7506
e28cd48c 7507 if (inst.reloc.exp.X_op == O_constant)
90e4755a 7508 {
e28cd48c
RE
7509 value = validate_immediate (inst.reloc.exp.X_add_number);
7510
7511 if (value != FAIL)
90e4755a 7512 {
e28cd48c
RE
7513 /* This can be done with a mov instruction. */
7514 inst.instruction &= LITERAL_MASK;
7515 inst.instruction |= (INST_IMMEDIATE
7516 | (OPCODE_MOV << DATA_OP_SHIFT));
7517 inst.instruction |= value & 0xfff;
7518 end_of_line (str);
90e4755a
RE
7519 return;
7520 }
b99bd4ef 7521
e28cd48c
RE
7522 value = validate_immediate (~inst.reloc.exp.X_add_number);
7523
7524 if (value != FAIL)
7525 {
7526 /* This can be done with a mvn instruction. */
7527 inst.instruction &= LITERAL_MASK;
7528 inst.instruction |= (INST_IMMEDIATE
7529 | (OPCODE_MVN << DATA_OP_SHIFT));
7530 inst.instruction |= value & 0xfff;
7531 end_of_line (str);
7532 return;
7533 }
90e4755a 7534 }
e28cd48c
RE
7535
7536 /* Insert into literal pool. */
7537 if (add_to_lit_pool () == FAIL)
7538 {
7539 if (!inst.error)
7540 inst.error = _("literal pool insertion failed");
7541 return;
7542 }
7543
7544 /* Change the instruction exp to point to the pool. */
7545 inst.reloc.type = BFD_RELOC_ARM_LITERAL;
7546 inst.reloc.pc_rel = 1;
7547 inst.instruction |= (REG_PC << 16);
7548 pre_inc = 1;
1cac9012
NC
7549 }
7550 else
7551 {
90e4755a
RE
7552 if (my_get_expression (&inst.reloc.exp, &str))
7553 return;
7554
7555 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
7556#ifndef TE_WINCE
7557 /* PC rel adjust. */
7558 inst.reloc.exp.X_add_number -= 8;
7559#endif
1cac9012 7560 inst.reloc.pc_rel = 1;
90e4755a
RE
7561 inst.instruction |= (REG_PC << 16);
7562 pre_inc = 1;
b99bd4ef
NC
7563 }
7564
90e4755a 7565 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
b99bd4ef 7566 end_of_line (str);
b99bd4ef
NC
7567}
7568
7569static void
f2b7cb0a 7570do_ldstt (str)
90e4755a 7571 char * str;
b99bd4ef 7572{
90e4755a
RE
7573 int conflict_reg;
7574
b99bd4ef
NC
7575 skip_whitespace (str);
7576
90e4755a 7577 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
b99bd4ef
NC
7578 {
7579 if (!inst.error)
7580 inst.error = BAD_ARGS;
7581 return;
7582 }
7583
90e4755a 7584 if (skip_past_comma (& str) == FAIL)
b99bd4ef 7585 {
f03698e6 7586 inst.error = _("address expected");
b99bd4ef
NC
7587 return;
7588 }
7589
90e4755a
RE
7590 if (*str == '[')
7591 {
7592 int reg;
b99bd4ef 7593
90e4755a 7594 str++;
b99bd4ef 7595
90e4755a 7596 skip_whitespace (str);
b99bd4ef 7597
90e4755a
RE
7598 if ((reg = reg_required_here (&str, 16)) == FAIL)
7599 return;
b99bd4ef 7600
90e4755a
RE
7601 /* ldrt/strt always use post-indexed addressing, so if the base is
7602 the same as Rd, we warn. */
7603 if (conflict_reg == reg)
7604 as_warn (_("%s register same as write-back base"),
7605 ((inst.instruction & LOAD_BIT)
7606 ? _("destination") : _("source")));
7607
7608 skip_whitespace (str);
7609
7610 if (*str == ']')
7611 {
7612 str ++;
7613
7614 if (skip_past_comma (&str) == SUCCESS)
7615 {
7616 /* [Rn],... (post inc) */
7617 if (ldst_extend (&str) == FAIL)
7618 return;
7619 }
7620 else
7621 {
7622 /* [Rn] */
7623 skip_whitespace (str);
7624
7625 /* Skip a write-back '!'. */
7626 if (*str == '!')
7627 str++;
7628
7629 inst.instruction |= INDEX_UP;
7630 }
7631 }
7632 else
7633 {
7634 inst.error = _("post-indexed expression expected");
7635 return;
7636 }
7637 }
7638 else
b99bd4ef 7639 {
90e4755a 7640 inst.error = _("post-indexed expression expected");
b99bd4ef
NC
7641 return;
7642 }
7643
b99bd4ef 7644 end_of_line (str);
b99bd4ef
NC
7645}
7646
7647static int
90e4755a 7648ldst_extend_v4 (str)
b99bd4ef 7649 char ** str;
b99bd4ef
NC
7650{
7651 int add = INDEX_UP;
7652
7653 switch (**str)
7654 {
7655 case '#':
7656 case '$':
7657 (*str)++;
7658 if (my_get_expression (& inst.reloc.exp, str))
7659 return FAIL;
7660
7661 if (inst.reloc.exp.X_op == O_constant)
7662 {
7663 int value = inst.reloc.exp.X_add_number;
7664
90e4755a 7665 if (value < -255 || value > 255)
b99bd4ef
NC
7666 {
7667 inst.error = _("address offset too large");
7668 return FAIL;
7669 }
7670
7671 if (value < 0)
7672 {
7673 value = -value;
7674 add = 0;
7675 }
7676
7677 /* Halfword and signextension instructions have the
7678 immediate value split across bits 11..8 and bits 3..0. */
90e4755a
RE
7679 inst.instruction |= (add | HWOFFSET_IMM
7680 | ((value >> 4) << 8) | (value & 0xF));
b99bd4ef
NC
7681 }
7682 else
7683 {
90e4755a
RE
7684 inst.instruction |= HWOFFSET_IMM;
7685 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
b99bd4ef
NC
7686 inst.reloc.pc_rel = 0;
7687 }
7688 return SUCCESS;
7689
7690 case '-':
7691 add = 0;
7692 /* Fall through. */
7693
7694 case '+':
7695 (*str)++;
7696 /* Fall through. */
7697
7698 default:
7699 if (reg_required_here (str, 0) == FAIL)
7700 return FAIL;
7701
90e4755a 7702 inst.instruction |= add;
b99bd4ef
NC
7703 return SUCCESS;
7704 }
7705}
7706
90e4755a 7707/* Halfword and signed-byte load/store operations. */
b99bd4ef 7708static void
f2b7cb0a 7709do_ldstv4 (str)
b99bd4ef 7710 char * str;
b99bd4ef 7711{
b99bd4ef
NC
7712 int pre_inc = 0;
7713 int conflict_reg;
7714 int value;
7715
b99bd4ef
NC
7716 skip_whitespace (str);
7717
7718 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
7719 {
7720 if (!inst.error)
7721 inst.error = BAD_ARGS;
7722 return;
7723 }
7724
7725 if (skip_past_comma (& str) == FAIL)
7726 {
f03698e6 7727 inst.error = _("address expected");
b99bd4ef
NC
7728 return;
7729 }
7730
7731 if (*str == '[')
7732 {
7733 int reg;
7734
7735 str++;
7736
7737 skip_whitespace (str);
7738
7739 if ((reg = reg_required_here (&str, 16)) == FAIL)
7740 return;
7741
7742 /* Conflicts can occur on stores as well as loads. */
7743 conflict_reg = (conflict_reg == reg);
7744
7745 skip_whitespace (str);
7746
7747 if (*str == ']')
7748 {
7749 str ++;
7750
7751 if (skip_past_comma (&str) == SUCCESS)
7752 {
7753 /* [Rn],... (post inc) */
90e4755a 7754 if (ldst_extend_v4 (&str) == FAIL)
b99bd4ef
NC
7755 return;
7756 if (conflict_reg)
90e4755a
RE
7757 as_warn (_("%s register same as write-back base"),
7758 ((inst.instruction & LOAD_BIT)
7759 ? _("destination") : _("source")));
b99bd4ef
NC
7760 }
7761 else
7762 {
7763 /* [Rn] */
90e4755a 7764 inst.instruction |= HWOFFSET_IMM;
b99bd4ef
NC
7765
7766 skip_whitespace (str);
7767
7768 if (*str == '!')
7769 {
7770 if (conflict_reg)
7771 as_warn (_("%s register same as write-back base"),
7772 ((inst.instruction & LOAD_BIT)
7773 ? _("destination") : _("source")));
7774 str++;
7775 inst.instruction |= WRITE_BACK;
7776 }
7777
90e4755a
RE
7778 inst.instruction |= INDEX_UP;
7779 pre_inc = 1;
b99bd4ef
NC
7780 }
7781 }
7782 else
7783 {
7784 /* [Rn,...] */
7785 if (skip_past_comma (&str) == FAIL)
7786 {
7787 inst.error = _("pre-indexed expression expected");
7788 return;
7789 }
7790
7791 pre_inc = 1;
90e4755a 7792 if (ldst_extend_v4 (&str) == FAIL)
b99bd4ef
NC
7793 return;
7794
7795 skip_whitespace (str);
7796
7797 if (*str++ != ']')
7798 {
7799 inst.error = _("missing ]");
7800 return;
7801 }
7802
7803 skip_whitespace (str);
7804
7805 if (*str == '!')
7806 {
7807 if (conflict_reg)
7808 as_warn (_("%s register same as write-back base"),
7809 ((inst.instruction & LOAD_BIT)
7810 ? _("destination") : _("source")));
7811 str++;
7812 inst.instruction |= WRITE_BACK;
7813 }
7814 }
7815 }
7816 else if (*str == '=')
7817 {
f03698e6
RE
7818 if ((inst.instruction & LOAD_BIT) == 0)
7819 {
7820 inst.error = _("invalid pseudo operation");
7821 return;
7822 }
7823
90e4755a 7824 /* XXX Does this work correctly for half-word/byte ops? */
b99bd4ef
NC
7825 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
7826 str++;
7827
7828 skip_whitespace (str);
7829
7830 if (my_get_expression (&inst.reloc.exp, &str))
7831 return;
7832
7833 if (inst.reloc.exp.X_op != O_constant
7834 && inst.reloc.exp.X_op != O_symbol)
7835 {
f03698e6 7836 inst.error = _("constant expression expected");
b99bd4ef
NC
7837 return;
7838 }
7839
d8273442 7840 if (inst.reloc.exp.X_op == O_constant)
b99bd4ef 7841 {
d8273442
NC
7842 value = validate_immediate (inst.reloc.exp.X_add_number);
7843
7844 if (value != FAIL)
b99bd4ef 7845 {
d8273442
NC
7846 /* This can be done with a mov instruction. */
7847 inst.instruction &= LITERAL_MASK;
7848 inst.instruction |= INST_IMMEDIATE | (OPCODE_MOV << DATA_OP_SHIFT);
90e4755a 7849 inst.instruction |= value & 0xfff;
d8273442 7850 end_of_line (str);
b99bd4ef
NC
7851 return;
7852 }
cc8a6dd0 7853
d8273442 7854 value = validate_immediate (~ inst.reloc.exp.X_add_number);
b99bd4ef 7855
d8273442 7856 if (value != FAIL)
b99bd4ef 7857 {
d8273442
NC
7858 /* This can be done with a mvn instruction. */
7859 inst.instruction &= LITERAL_MASK;
7860 inst.instruction |= INST_IMMEDIATE | (OPCODE_MVN << DATA_OP_SHIFT);
90e4755a 7861 inst.instruction |= value & 0xfff;
d8273442
NC
7862 end_of_line (str);
7863 return;
b99bd4ef 7864 }
b99bd4ef 7865 }
d8273442
NC
7866
7867 /* Insert into literal pool. */
7868 if (add_to_lit_pool () == FAIL)
7869 {
7870 if (!inst.error)
7871 inst.error = _("literal pool insertion failed");
7872 return;
7873 }
7874
7875 /* Change the instruction exp to point to the pool. */
90e4755a
RE
7876 inst.instruction |= HWOFFSET_IMM;
7877 inst.reloc.type = BFD_RELOC_ARM_HWLITERAL;
d8273442
NC
7878 inst.reloc.pc_rel = 1;
7879 inst.instruction |= (REG_PC << 16);
7880 pre_inc = 1;
b99bd4ef
NC
7881 }
7882 else
7883 {
7884 if (my_get_expression (&inst.reloc.exp, &str))
7885 return;
7886
90e4755a
RE
7887 inst.instruction |= HWOFFSET_IMM;
7888 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
b99bd4ef
NC
7889#ifndef TE_WINCE
7890 /* PC rel adjust. */
7891 inst.reloc.exp.X_add_number -= 8;
7892#endif
7893 inst.reloc.pc_rel = 1;
7894 inst.instruction |= (REG_PC << 16);
7895 pre_inc = 1;
7896 }
7897
90e4755a 7898 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
b99bd4ef 7899 end_of_line (str);
b99bd4ef
NC
7900}
7901
7902static long
7903reg_list (strp)
7904 char ** strp;
7905{
7906 char * str = * strp;
7907 long range = 0;
7908 int another_range;
7909
7910 /* We come back here if we get ranges concatenated by '+' or '|'. */
7911 do
7912 {
7913 another_range = 0;
7914
7915 if (*str == '{')
7916 {
7917 int in_range = 0;
7918 int cur_reg = -1;
7919
7920 str++;
7921 do
7922 {
7923 int reg;
7924
7925 skip_whitespace (str);
7926
7927 if ((reg = reg_required_here (& str, -1)) == FAIL)
7928 return FAIL;
7929
7930 if (in_range)
7931 {
7932 int i;
7933
7934 if (reg <= cur_reg)
7935 {
f03698e6 7936 inst.error = _("bad range in register list");
b99bd4ef
NC
7937 return FAIL;
7938 }
7939
7940 for (i = cur_reg + 1; i < reg; i++)
7941 {
7942 if (range & (1 << i))
7943 as_tsktsk
f03698e6 7944 (_("Warning: duplicated register (r%d) in register list"),
b99bd4ef
NC
7945 i);
7946 else
7947 range |= 1 << i;
7948 }
7949 in_range = 0;
7950 }
7951
7952 if (range & (1 << reg))
f03698e6 7953 as_tsktsk (_("Warning: duplicated register (r%d) in register list"),
b99bd4ef
NC
7954 reg);
7955 else if (reg <= cur_reg)
f03698e6 7956 as_tsktsk (_("Warning: register range not in ascending order"));
b99bd4ef
NC
7957
7958 range |= 1 << reg;
7959 cur_reg = reg;
7960 }
7961 while (skip_past_comma (&str) != FAIL
7962 || (in_range = 1, *str++ == '-'));
7963 str--;
7964 skip_whitespace (str);
7965
7966 if (*str++ != '}')
7967 {
f03698e6 7968 inst.error = _("missing `}'");
b99bd4ef
NC
7969 return FAIL;
7970 }
7971 }
7972 else
7973 {
7974 expressionS expr;
7975
7976 if (my_get_expression (&expr, &str))
7977 return FAIL;
7978
7979 if (expr.X_op == O_constant)
7980 {
7981 if (expr.X_add_number
7982 != (expr.X_add_number & 0x0000ffff))
7983 {
7984 inst.error = _("invalid register mask");
7985 return FAIL;
7986 }
7987
7988 if ((range & expr.X_add_number) != 0)
7989 {
7990 int regno = range & expr.X_add_number;
7991
7992 regno &= -regno;
7993 regno = (1 << regno) - 1;
7994 as_tsktsk
f03698e6 7995 (_("Warning: duplicated register (r%d) in register list"),
b99bd4ef
NC
7996 regno);
7997 }
7998
7999 range |= expr.X_add_number;
8000 }
8001 else
8002 {
8003 if (inst.reloc.type != 0)
8004 {
8005 inst.error = _("expression too complex");
8006 return FAIL;
8007 }
8008
8009 memcpy (&inst.reloc.exp, &expr, sizeof (expressionS));
8010 inst.reloc.type = BFD_RELOC_ARM_MULTI;
8011 inst.reloc.pc_rel = 0;
8012 }
8013 }
8014
8015 skip_whitespace (str);
8016
8017 if (*str == '|' || *str == '+')
8018 {
8019 str++;
8020 another_range = 1;
8021 }
8022 }
8023 while (another_range);
8024
8025 *strp = str;
8026 return range;
8027}
8028
8029static void
f2b7cb0a 8030do_ldmstm (str)
b99bd4ef 8031 char * str;
b99bd4ef
NC
8032{
8033 int base_reg;
8034 long range;
8035
8036 skip_whitespace (str);
8037
8038 if ((base_reg = reg_required_here (&str, 16)) == FAIL)
8039 return;
8040
8041 if (base_reg == REG_PC)
8042 {
8043 inst.error = _("r15 not allowed as base register");
8044 return;
8045 }
8046
8047 skip_whitespace (str);
8048
8049 if (*str == '!')
8050 {
90e4755a 8051 inst.instruction |= WRITE_BACK;
b99bd4ef
NC
8052 str++;
8053 }
8054
8055 if (skip_past_comma (&str) == FAIL
8056 || (range = reg_list (&str)) == FAIL)
8057 {
8058 if (! inst.error)
8059 inst.error = BAD_ARGS;
8060 return;
8061 }
8062
8063 if (*str == '^')
8064 {
8065 str++;
90e4755a 8066 inst.instruction |= LDM_TYPE_2_OR_3;
b99bd4ef
NC
8067 }
8068
6189168b
NC
8069 if (inst.instruction & WRITE_BACK)
8070 {
8071 /* Check for unpredictable uses of writeback. */
8072 if (inst.instruction & LOAD_BIT)
8073 {
8074 /* Not allowed in LDM type 2. */
8075 if ((inst.instruction & LDM_TYPE_2_OR_3)
8076 && ((range & (1 << REG_PC)) == 0))
8077 as_warn (_("writeback of base register is UNPREDICTABLE"));
8078 /* Only allowed if base reg not in list for other types. */
8079 else if (range & (1 << base_reg))
8080 as_warn (_("writeback of base register when in register list is UNPREDICTABLE"));
8081 }
8082 else /* STM. */
8083 {
8084 /* Not allowed for type 2. */
8085 if (inst.instruction & LDM_TYPE_2_OR_3)
8086 as_warn (_("writeback of base register is UNPREDICTABLE"));
8087 /* Only allowed if base reg not in list, or first in list. */
8088 else if ((range & (1 << base_reg))
8089 && (range & ((1 << base_reg) - 1)))
8090 as_warn (_("if writeback register is in list, it must be the lowest reg in the list"));
8091 }
8092 }
61b5f74b 8093
f2b7cb0a 8094 inst.instruction |= range;
b99bd4ef 8095 end_of_line (str);
b99bd4ef
NC
8096}
8097
8098static void
f2b7cb0a 8099do_swi (str)
b99bd4ef 8100 char * str;
b99bd4ef
NC
8101{
8102 skip_whitespace (str);
8103
8104 /* Allow optional leading '#'. */
8105 if (is_immediate_prefix (*str))
8106 str++;
8107
8108 if (my_get_expression (& inst.reloc.exp, & str))
8109 return;
8110
8111 inst.reloc.type = BFD_RELOC_ARM_SWI;
8112 inst.reloc.pc_rel = 0;
b99bd4ef 8113 end_of_line (str);
b99bd4ef
NC
8114}
8115
8116static void
f2b7cb0a 8117do_swap (str)
b99bd4ef 8118 char * str;
b99bd4ef
NC
8119{
8120 int reg;
8121
8122 skip_whitespace (str);
8123
8124 if ((reg = reg_required_here (&str, 12)) == FAIL)
8125 return;
8126
8127 if (reg == REG_PC)
8128 {
8129 inst.error = _("r15 not allowed in swap");
8130 return;
8131 }
8132
8133 if (skip_past_comma (&str) == FAIL
8134 || (reg = reg_required_here (&str, 0)) == FAIL)
8135 {
8136 if (!inst.error)
8137 inst.error = BAD_ARGS;
8138 return;
8139 }
8140
8141 if (reg == REG_PC)
8142 {
8143 inst.error = _("r15 not allowed in swap");
8144 return;
8145 }
8146
8147 if (skip_past_comma (&str) == FAIL
8148 || *str++ != '[')
8149 {
8150 inst.error = BAD_ARGS;
8151 return;
8152 }
8153
8154 skip_whitespace (str);
8155
8156 if ((reg = reg_required_here (&str, 16)) == FAIL)
8157 return;
8158
8159 if (reg == REG_PC)
8160 {
8161 inst.error = BAD_PC;
8162 return;
8163 }
8164
8165 skip_whitespace (str);
8166
8167 if (*str++ != ']')
8168 {
8169 inst.error = _("missing ]");
8170 return;
8171 }
8172
b99bd4ef 8173 end_of_line (str);
b99bd4ef
NC
8174}
8175
8176static void
f2b7cb0a 8177do_branch (str)
b99bd4ef 8178 char * str;
b99bd4ef
NC
8179{
8180 if (my_get_expression (&inst.reloc.exp, &str))
8181 return;
8182
8183#ifdef OBJ_ELF
8184 {
8185 char * save_in;
8186
8187 /* ScottB: February 5, 1998 - Check to see of PLT32 reloc
8188 required for the instruction. */
8189
8190 /* arm_parse_reloc () works on input_line_pointer.
8191 We actually want to parse the operands to the branch instruction
8192 passed in 'str'. Save the input pointer and restore it later. */
8193 save_in = input_line_pointer;
8194 input_line_pointer = str;
8195 if (inst.reloc.exp.X_op == O_symbol
8196 && *str == '('
8197 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
8198 {
8199 inst.reloc.type = BFD_RELOC_ARM_PLT32;
8200 inst.reloc.pc_rel = 0;
8201 /* Modify str to point to after parsed operands, otherwise
8202 end_of_line() will complain about the (PLT) left in str. */
8203 str = input_line_pointer;
8204 }
8205 else
8206 {
8207 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
8208 inst.reloc.pc_rel = 1;
8209 }
8210 input_line_pointer = save_in;
8211 }
8212#else
8213 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
8214 inst.reloc.pc_rel = 1;
8215#endif /* OBJ_ELF */
8216
8217 end_of_line (str);
b99bd4ef
NC
8218}
8219
8220static void
f2b7cb0a 8221do_bx (str)
b99bd4ef 8222 char * str;
b99bd4ef
NC
8223{
8224 int reg;
8225
8226 skip_whitespace (str);
8227
8228 if ((reg = reg_required_here (&str, 0)) == FAIL)
8229 {
8230 inst.error = BAD_ARGS;
8231 return;
8232 }
8233
8234 /* Note - it is not illegal to do a "bx pc". Useless, but not illegal. */
8235 if (reg == REG_PC)
f03698e6 8236 as_tsktsk (_("use of r15 in bx in ARM mode is not really useful"));
b99bd4ef
NC
8237
8238 end_of_line (str);
8239}
8240
8241static void
f2b7cb0a 8242do_cdp (str)
b99bd4ef 8243 char * str;
b99bd4ef
NC
8244{
8245 /* Co-processor data operation.
8246 Format: CDP{cond} CP#,<expr>,CRd,CRn,CRm{,<expr>} */
8247 skip_whitespace (str);
8248
8249 if (co_proc_number (&str) == FAIL)
8250 {
8251 if (!inst.error)
8252 inst.error = BAD_ARGS;
8253 return;
8254 }
8255
8256 if (skip_past_comma (&str) == FAIL
8257 || cp_opc_expr (&str, 20,4) == FAIL)
8258 {
8259 if (!inst.error)
8260 inst.error = BAD_ARGS;
8261 return;
8262 }
8263
8264 if (skip_past_comma (&str) == FAIL
8265 || cp_reg_required_here (&str, 12) == FAIL)
8266 {
8267 if (!inst.error)
8268 inst.error = BAD_ARGS;
8269 return;
8270 }
8271
8272 if (skip_past_comma (&str) == FAIL
8273 || cp_reg_required_here (&str, 16) == FAIL)
8274 {
8275 if (!inst.error)
8276 inst.error = BAD_ARGS;
8277 return;
8278 }
8279
8280 if (skip_past_comma (&str) == FAIL
8281 || cp_reg_required_here (&str, 0) == FAIL)
8282 {
8283 if (!inst.error)
8284 inst.error = BAD_ARGS;
8285 return;
8286 }
8287
8288 if (skip_past_comma (&str) == SUCCESS)
8289 {
8290 if (cp_opc_expr (&str, 5, 3) == FAIL)
8291 {
8292 if (!inst.error)
8293 inst.error = BAD_ARGS;
8294 return;
8295 }
8296 }
8297
8298 end_of_line (str);
b99bd4ef
NC
8299}
8300
8301static void
f2b7cb0a 8302do_lstc (str)
b99bd4ef 8303 char * str;
b99bd4ef
NC
8304{
8305 /* Co-processor register load/store.
8306 Format: <LDC|STC{cond}[L] CP#,CRd,<address> */
8307
8308 skip_whitespace (str);
8309
8310 if (co_proc_number (&str) == FAIL)
8311 {
8312 if (!inst.error)
8313 inst.error = BAD_ARGS;
8314 return;
8315 }
8316
8317 if (skip_past_comma (&str) == FAIL
8318 || cp_reg_required_here (&str, 12) == FAIL)
8319 {
8320 if (!inst.error)
8321 inst.error = BAD_ARGS;
8322 return;
8323 }
8324
8325 if (skip_past_comma (&str) == FAIL
bfae80f2 8326 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
b99bd4ef
NC
8327 {
8328 if (! inst.error)
8329 inst.error = BAD_ARGS;
8330 return;
8331 }
8332
b99bd4ef 8333 end_of_line (str);
b99bd4ef
NC
8334}
8335
8336static void
f2b7cb0a 8337do_co_reg (str)
b99bd4ef 8338 char * str;
b99bd4ef
NC
8339{
8340 /* Co-processor register transfer.
8341 Format: <MCR|MRC>{cond} CP#,<expr1>,Rd,CRn,CRm{,<expr2>} */
8342
8343 skip_whitespace (str);
8344
8345 if (co_proc_number (&str) == FAIL)
8346 {
8347 if (!inst.error)
8348 inst.error = BAD_ARGS;
8349 return;
8350 }
8351
8352 if (skip_past_comma (&str) == FAIL
8353 || cp_opc_expr (&str, 21, 3) == FAIL)
8354 {
8355 if (!inst.error)
8356 inst.error = BAD_ARGS;
8357 return;
8358 }
8359
8360 if (skip_past_comma (&str) == FAIL
8361 || reg_required_here (&str, 12) == FAIL)
8362 {
8363 if (!inst.error)
8364 inst.error = BAD_ARGS;
8365 return;
8366 }
8367
8368 if (skip_past_comma (&str) == FAIL
8369 || cp_reg_required_here (&str, 16) == FAIL)
8370 {
8371 if (!inst.error)
8372 inst.error = BAD_ARGS;
8373 return;
8374 }
8375
8376 if (skip_past_comma (&str) == FAIL
8377 || cp_reg_required_here (&str, 0) == FAIL)
8378 {
8379 if (!inst.error)
8380 inst.error = BAD_ARGS;
8381 return;
8382 }
8383
8384 if (skip_past_comma (&str) == SUCCESS)
8385 {
8386 if (cp_opc_expr (&str, 5, 3) == FAIL)
8387 {
8388 if (!inst.error)
8389 inst.error = BAD_ARGS;
8390 return;
8391 }
8392 }
b99bd4ef
NC
8393
8394 end_of_line (str);
b99bd4ef
NC
8395}
8396
8397static void
f2b7cb0a 8398do_fpa_ctrl (str)
b99bd4ef 8399 char * str;
b99bd4ef
NC
8400{
8401 /* FP control registers.
8402 Format: <WFS|RFS|WFC|RFC>{cond} Rn */
8403
8404 skip_whitespace (str);
8405
8406 if (reg_required_here (&str, 12) == FAIL)
8407 {
8408 if (!inst.error)
8409 inst.error = BAD_ARGS;
8410 return;
8411 }
8412
8413 end_of_line (str);
b99bd4ef
NC
8414}
8415
8416static void
f2b7cb0a 8417do_fpa_ldst (str)
b99bd4ef 8418 char * str;
b99bd4ef
NC
8419{
8420 skip_whitespace (str);
8421
b99bd4ef
NC
8422 if (fp_reg_required_here (&str, 12) == FAIL)
8423 {
8424 if (!inst.error)
8425 inst.error = BAD_ARGS;
8426 return;
8427 }
8428
8429 if (skip_past_comma (&str) == FAIL
bfae80f2 8430 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
b99bd4ef
NC
8431 {
8432 if (!inst.error)
8433 inst.error = BAD_ARGS;
8434 return;
8435 }
8436
8437 end_of_line (str);
8438}
8439
8440static void
f2b7cb0a 8441do_fpa_ldmstm (str)
b99bd4ef 8442 char * str;
b99bd4ef
NC
8443{
8444 int num_regs;
8445
8446 skip_whitespace (str);
8447
8448 if (fp_reg_required_here (&str, 12) == FAIL)
8449 {
8450 if (! inst.error)
8451 inst.error = BAD_ARGS;
8452 return;
8453 }
8454
8455 /* Get Number of registers to transfer. */
8456 if (skip_past_comma (&str) == FAIL
8457 || my_get_expression (&inst.reloc.exp, &str))
8458 {
8459 if (! inst.error)
8460 inst.error = _("constant expression expected");
8461 return;
8462 }
8463
8464 if (inst.reloc.exp.X_op != O_constant)
8465 {
f03698e6 8466 inst.error = _("constant value required for number of registers");
b99bd4ef
NC
8467 return;
8468 }
8469
8470 num_regs = inst.reloc.exp.X_add_number;
8471
8472 if (num_regs < 1 || num_regs > 4)
8473 {
8474 inst.error = _("number of registers must be in the range [1:4]");
8475 return;
8476 }
8477
8478 switch (num_regs)
8479 {
8480 case 1:
8481 inst.instruction |= CP_T_X;
8482 break;
8483 case 2:
8484 inst.instruction |= CP_T_Y;
8485 break;
8486 case 3:
8487 inst.instruction |= CP_T_Y | CP_T_X;
8488 break;
8489 case 4:
8490 break;
8491 default:
8492 abort ();
8493 }
8494
e28cd48c 8495 if (inst.instruction & (CP_T_Pre | CP_T_UD)) /* ea/fd format. */
b99bd4ef
NC
8496 {
8497 int reg;
8498 int write_back;
8499 int offset;
8500
8501 /* The instruction specified "ea" or "fd", so we can only accept
8502 [Rn]{!}. The instruction does not really support stacking or
8503 unstacking, so we have to emulate these by setting appropriate
8504 bits and offsets. */
8505 if (skip_past_comma (&str) == FAIL
8506 || *str != '[')
8507 {
8508 if (! inst.error)
8509 inst.error = BAD_ARGS;
8510 return;
8511 }
8512
8513 str++;
8514 skip_whitespace (str);
8515
8516 if ((reg = reg_required_here (&str, 16)) == FAIL)
8517 return;
8518
8519 skip_whitespace (str);
8520
8521 if (*str != ']')
8522 {
8523 inst.error = BAD_ARGS;
8524 return;
8525 }
8526
8527 str++;
8528 if (*str == '!')
8529 {
8530 write_back = 1;
8531 str++;
8532 if (reg == REG_PC)
8533 {
8534 inst.error =
f03698e6 8535 _("r15 not allowed as base register with write-back");
b99bd4ef
NC
8536 return;
8537 }
8538 }
8539 else
8540 write_back = 0;
8541
90e4755a 8542 if (inst.instruction & CP_T_Pre)
b99bd4ef
NC
8543 {
8544 /* Pre-decrement. */
8545 offset = 3 * num_regs;
8546 if (write_back)
90e4755a 8547 inst.instruction |= CP_T_WB;
b99bd4ef
NC
8548 }
8549 else
8550 {
8551 /* Post-increment. */
8552 if (write_back)
8553 {
90e4755a 8554 inst.instruction |= CP_T_WB;
b99bd4ef
NC
8555 offset = 3 * num_regs;
8556 }
8557 else
8558 {
8559 /* No write-back, so convert this into a standard pre-increment
8560 instruction -- aesthetically more pleasing. */
90e4755a 8561 inst.instruction |= CP_T_Pre | CP_T_UD;
b99bd4ef
NC
8562 offset = 0;
8563 }
8564 }
8565
f2b7cb0a 8566 inst.instruction |= offset;
b99bd4ef
NC
8567 }
8568 else if (skip_past_comma (&str) == FAIL
bfae80f2 8569 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
b99bd4ef
NC
8570 {
8571 if (! inst.error)
8572 inst.error = BAD_ARGS;
8573 return;
8574 }
8575
8576 end_of_line (str);
8577}
8578
8579static void
f2b7cb0a 8580do_fpa_dyadic (str)
b99bd4ef 8581 char * str;
b99bd4ef
NC
8582{
8583 skip_whitespace (str);
8584
b99bd4ef
NC
8585 if (fp_reg_required_here (&str, 12) == FAIL)
8586 {
8587 if (! inst.error)
8588 inst.error = BAD_ARGS;
8589 return;
8590 }
8591
8592 if (skip_past_comma (&str) == FAIL
8593 || fp_reg_required_here (&str, 16) == FAIL)
8594 {
8595 if (! inst.error)
8596 inst.error = BAD_ARGS;
8597 return;
8598 }
8599
8600 if (skip_past_comma (&str) == FAIL
8601 || fp_op2 (&str) == FAIL)
8602 {
8603 if (! inst.error)
8604 inst.error = BAD_ARGS;
8605 return;
8606 }
8607
b99bd4ef 8608 end_of_line (str);
b99bd4ef
NC
8609}
8610
8611static void
f2b7cb0a 8612do_fpa_monadic (str)
b99bd4ef 8613 char * str;
b99bd4ef
NC
8614{
8615 skip_whitespace (str);
8616
b99bd4ef
NC
8617 if (fp_reg_required_here (&str, 12) == FAIL)
8618 {
8619 if (! inst.error)
8620 inst.error = BAD_ARGS;
8621 return;
8622 }
8623
8624 if (skip_past_comma (&str) == FAIL
8625 || fp_op2 (&str) == FAIL)
8626 {
8627 if (! inst.error)
8628 inst.error = BAD_ARGS;
8629 return;
8630 }
8631
b99bd4ef 8632 end_of_line (str);
b99bd4ef
NC
8633}
8634
8635static void
f2b7cb0a 8636do_fpa_cmp (str)
b99bd4ef 8637 char * str;
b99bd4ef
NC
8638{
8639 skip_whitespace (str);
8640
8641 if (fp_reg_required_here (&str, 16) == FAIL)
8642 {
8643 if (! inst.error)
8644 inst.error = BAD_ARGS;
8645 return;
8646 }
8647
8648 if (skip_past_comma (&str) == FAIL
8649 || fp_op2 (&str) == FAIL)
8650 {
8651 if (! inst.error)
8652 inst.error = BAD_ARGS;
8653 return;
8654 }
8655
b99bd4ef 8656 end_of_line (str);
b99bd4ef
NC
8657}
8658
8659static void
f2b7cb0a 8660do_fpa_from_reg (str)
b99bd4ef 8661 char * str;
b99bd4ef
NC
8662{
8663 skip_whitespace (str);
8664
b99bd4ef
NC
8665 if (fp_reg_required_here (&str, 16) == FAIL)
8666 {
8667 if (! inst.error)
8668 inst.error = BAD_ARGS;
8669 return;
8670 }
8671
8672 if (skip_past_comma (&str) == FAIL
8673 || reg_required_here (&str, 12) == FAIL)
8674 {
8675 if (! inst.error)
8676 inst.error = BAD_ARGS;
8677 return;
8678 }
8679
b99bd4ef 8680 end_of_line (str);
b99bd4ef
NC
8681}
8682
8683static void
f2b7cb0a 8684do_fpa_to_reg (str)
b99bd4ef 8685 char * str;
b99bd4ef
NC
8686{
8687 skip_whitespace (str);
8688
8689 if (reg_required_here (&str, 12) == FAIL)
8690 return;
8691
8692 if (skip_past_comma (&str) == FAIL
8693 || fp_reg_required_here (&str, 0) == FAIL)
8694 {
8695 if (! inst.error)
8696 inst.error = BAD_ARGS;
8697 return;
8698 }
8699
b99bd4ef 8700 end_of_line (str);
b99bd4ef
NC
8701}
8702
b99bd4ef 8703static int
bfae80f2
RE
8704vfp_sp_reg_required_here (str, pos)
8705 char **str;
8706 enum vfp_sp_reg_pos pos;
b99bd4ef 8707{
bfae80f2
RE
8708 int reg;
8709 char *start = *str;
b99bd4ef 8710
bfae80f2 8711 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_SN].htab)) != FAIL)
b99bd4ef 8712 {
bfae80f2 8713 switch (pos)
b99bd4ef 8714 {
bfae80f2
RE
8715 case VFP_REG_Sd:
8716 inst.instruction |= ((reg >> 1) << 12) | ((reg & 1) << 22);
8717 break;
8718
8719 case VFP_REG_Sn:
8720 inst.instruction |= ((reg >> 1) << 16) | ((reg & 1) << 7);
8721 break;
8722
8723 case VFP_REG_Sm:
8724 inst.instruction |= ((reg >> 1) << 0) | ((reg & 1) << 5);
8725 break;
8726
8727 default:
8728 abort ();
b99bd4ef 8729 }
bfae80f2
RE
8730 return reg;
8731 }
b99bd4ef 8732
bfae80f2
RE
8733 /* In the few cases where we might be able to accept something else
8734 this error can be overridden. */
8735 inst.error = _(all_reg_maps[REG_TYPE_SN].expected);
8736
8737 /* Restore the start point. */
8738 *str = start;
8739 return FAIL;
8740}
8741
8742static int
8743vfp_dp_reg_required_here (str, pos)
8744 char **str;
f201ccb3 8745 enum vfp_dp_reg_pos pos;
bfae80f2
RE
8746{
8747 int reg;
8748 char *start = *str;
8749
8750 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_DN].htab)) != FAIL)
8751 {
8752 switch (pos)
b99bd4ef 8753 {
bfae80f2
RE
8754 case VFP_REG_Dd:
8755 inst.instruction |= reg << 12;
8756 break;
b99bd4ef 8757
bfae80f2
RE
8758 case VFP_REG_Dn:
8759 inst.instruction |= reg << 16;
8760 break;
8761
8762 case VFP_REG_Dm:
8763 inst.instruction |= reg << 0;
8764 break;
8765
8766 default:
8767 abort ();
8768 }
8769 return reg;
b99bd4ef
NC
8770 }
8771
bfae80f2
RE
8772 /* In the few cases where we might be able to accept something else
8773 this error can be overridden. */
8774 inst.error = _(all_reg_maps[REG_TYPE_DN].expected);
b99bd4ef 8775
bfae80f2
RE
8776 /* Restore the start point. */
8777 *str = start;
8778 return FAIL;
8779}
b99bd4ef
NC
8780
8781static void
bfae80f2
RE
8782do_vfp_sp_monadic (str)
8783 char *str;
b99bd4ef 8784{
b99bd4ef
NC
8785 skip_whitespace (str);
8786
bfae80f2
RE
8787 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
8788 return;
8789
8790 if (skip_past_comma (&str) == FAIL
8791 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
b99bd4ef
NC
8792 {
8793 if (! inst.error)
8794 inst.error = BAD_ARGS;
8795 return;
8796 }
8797
bfae80f2 8798 end_of_line (str);
bfae80f2
RE
8799}
8800
8801static void
8802do_vfp_dp_monadic (str)
8803 char *str;
8804{
8805 skip_whitespace (str);
8806
8807 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
8808 return;
8809
8810 if (skip_past_comma (&str) == FAIL
8811 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
b99bd4ef 8812 {
bfae80f2
RE
8813 if (! inst.error)
8814 inst.error = BAD_ARGS;
8815 return;
b99bd4ef 8816 }
b99bd4ef 8817
bfae80f2 8818 end_of_line (str);
bfae80f2 8819}
b99bd4ef 8820
bfae80f2
RE
8821static void
8822do_vfp_sp_dyadic (str)
8823 char *str;
8824{
8825 skip_whitespace (str);
b99bd4ef 8826
bfae80f2
RE
8827 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
8828 return;
b99bd4ef 8829
bfae80f2
RE
8830 if (skip_past_comma (&str) == FAIL
8831 || vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL
8832 || skip_past_comma (&str) == FAIL
8833 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
b99bd4ef 8834 {
bfae80f2
RE
8835 if (! inst.error)
8836 inst.error = BAD_ARGS;
8837 return;
8838 }
b99bd4ef 8839
bfae80f2 8840 end_of_line (str);
bfae80f2 8841}
b99bd4ef 8842
bfae80f2
RE
8843static void
8844do_vfp_dp_dyadic (str)
8845 char *str;
8846{
8847 skip_whitespace (str);
b99bd4ef 8848
bfae80f2
RE
8849 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
8850 return;
b99bd4ef 8851
bfae80f2
RE
8852 if (skip_past_comma (&str) == FAIL
8853 || vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL
8854 || skip_past_comma (&str) == FAIL
8855 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
8856 {
8857 if (! inst.error)
8858 inst.error = BAD_ARGS;
8859 return;
8860 }
b99bd4ef 8861
bfae80f2 8862 end_of_line (str);
bfae80f2 8863}
b99bd4ef 8864
bfae80f2
RE
8865static void
8866do_vfp_reg_from_sp (str)
8867 char *str;
8868{
8869 skip_whitespace (str);
8870
8871 if (reg_required_here (&str, 12) == FAIL)
8872 return;
8873
8874 if (skip_past_comma (&str) == FAIL
8875 || vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL)
8876 {
8877 if (! inst.error)
8878 inst.error = BAD_ARGS;
8879 return;
8880 }
8881
8882 end_of_line (str);
bfae80f2
RE
8883}
8884
8885static void
e45d0630 8886do_vfp_reg2_from_sp2 (str)
bfae80f2
RE
8887 char *str;
8888{
8889 skip_whitespace (str);
8890
e45d0630
PB
8891 if (reg_required_here (&str, 12) == FAIL
8892 || skip_past_comma (&str) == FAIL
bfae80f2
RE
8893 || reg_required_here (&str, 16) == FAIL
8894 || skip_past_comma (&str) == FAIL)
8895 {
8896 if (! inst.error)
8897 inst.error = BAD_ARGS;
8898 return;
8899 }
8900
8901 /* We require exactly two consecutive SP registers. */
8902 if (vfp_sp_reg_list (&str, VFP_REG_Sm) != 2)
8903 {
8904 if (! inst.error)
8905 inst.error = _("only two consecutive VFP SP registers allowed here");
8906 }
8907
8908 end_of_line (str);
bfae80f2
RE
8909}
8910
8911static void
8912do_vfp_sp_from_reg (str)
8913 char *str;
8914{
8915 skip_whitespace (str);
8916
8917 if (vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL)
8918 return;
8919
8920 if (skip_past_comma (&str) == FAIL
8921 || reg_required_here (&str, 12) == FAIL)
8922 {
8923 if (! inst.error)
8924 inst.error = BAD_ARGS;
8925 return;
8926 }
8927
8928 end_of_line (str);
bfae80f2
RE
8929}
8930
e45d0630
PB
8931static void
8932do_vfp_sp2_from_reg2 (str)
8933 char *str;
8934{
8935 skip_whitespace (str);
8936
8937 /* We require exactly two consecutive SP registers. */
8938 if (vfp_sp_reg_list (&str, VFP_REG_Sm) != 2)
8939 {
8940 if (! inst.error)
8941 inst.error = _("only two consecutive VFP SP registers allowed here");
8942 }
8943
8944 if (skip_past_comma (&str) == FAIL
8945 || reg_required_here (&str, 12) == FAIL
8946 || skip_past_comma (&str) == FAIL
8947 || reg_required_here (&str, 16) == FAIL)
8948 {
8949 if (! inst.error)
8950 inst.error = BAD_ARGS;
8951 return;
8952 }
8953
8954 end_of_line (str);
8955}
8956
bfae80f2
RE
8957static void
8958do_vfp_reg_from_dp (str)
8959 char *str;
8960{
8961 skip_whitespace (str);
8962
8963 if (reg_required_here (&str, 12) == FAIL)
8964 return;
8965
8966 if (skip_past_comma (&str) == FAIL
8967 || vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL)
8968 {
8969 if (! inst.error)
8970 inst.error = BAD_ARGS;
8971 return;
8972 }
8973
8974 end_of_line (str);
bfae80f2
RE
8975}
8976
8977static void
8978do_vfp_reg2_from_dp (str)
8979 char *str;
8980{
8981 skip_whitespace (str);
8982
8983 if (reg_required_here (&str, 12) == FAIL)
8984 return;
8985
8986 if (skip_past_comma (&str) == FAIL
8987 || reg_required_here (&str, 16) == FAIL
8988 || skip_past_comma (&str) == FAIL
8989 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
8990 {
8991 if (! inst.error)
8992 inst.error = BAD_ARGS;
8993 return;
8994 }
8995
8996 end_of_line (str);
bfae80f2
RE
8997}
8998
8999static void
9000do_vfp_dp_from_reg (str)
9001 char *str;
9002{
9003 skip_whitespace (str);
9004
9005 if (vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL)
9006 return;
9007
9008 if (skip_past_comma (&str) == FAIL
9009 || reg_required_here (&str, 12) == FAIL)
9010 {
9011 if (! inst.error)
9012 inst.error = BAD_ARGS;
9013 return;
9014 }
9015
9016 end_of_line (str);
bfae80f2
RE
9017}
9018
9019static void
9020do_vfp_dp_from_reg2 (str)
9021 char *str;
9022{
9023 skip_whitespace (str);
9024
9025 if (vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
9026 return;
9027
9028 if (skip_past_comma (&str) == FAIL
9029 || reg_required_here (&str, 12) == FAIL
9030 || skip_past_comma (&str) == FAIL
e45d0630 9031 || reg_required_here (&str, 16) == FAIL)
bfae80f2
RE
9032 {
9033 if (! inst.error)
9034 inst.error = BAD_ARGS;
9035 return;
9036 }
9037
9038 end_of_line (str);
bfae80f2
RE
9039}
9040
9041static const struct vfp_reg *
9042vfp_psr_parse (str)
9043 char **str;
9044{
9045 char *start = *str;
9046 char c;
9047 char *p;
9048 const struct vfp_reg *vreg;
9049
9050 p = start;
9051
9052 /* Find the end of the current token. */
9053 do
9054 {
9055 c = *p++;
9056 }
9057 while (ISALPHA (c));
9058
9059 /* Mark it. */
9060 *--p = 0;
9061
cc8a6dd0 9062 for (vreg = vfp_regs + 0;
bfae80f2
RE
9063 vreg < vfp_regs + sizeof (vfp_regs) / sizeof (struct vfp_reg);
9064 vreg++)
9065 {
9066 if (strcmp (start, vreg->name) == 0)
9067 {
9068 *p = c;
9069 *str = p;
9070 return vreg;
9071 }
9072 }
9073
9074 *p = c;
9075 return NULL;
9076}
9077
9078static int
9079vfp_psr_required_here (str)
9080 char **str;
9081{
9082 char *start = *str;
9083 const struct vfp_reg *vreg;
9084
9085 vreg = vfp_psr_parse (str);
9086
9087 if (vreg)
9088 {
9089 inst.instruction |= vreg->regno;
9090 return SUCCESS;
9091 }
9092
9093 inst.error = _("VFP system register expected");
9094
9095 *str = start;
9096 return FAIL;
9097}
9098
9099static void
9100do_vfp_reg_from_ctrl (str)
9101 char *str;
9102{
9103 skip_whitespace (str);
9104
9105 if (reg_required_here (&str, 12) == FAIL)
9106 return;
9107
9108 if (skip_past_comma (&str) == FAIL
9109 || vfp_psr_required_here (&str) == FAIL)
9110 {
9111 if (! inst.error)
9112 inst.error = BAD_ARGS;
9113 return;
9114 }
9115
9116 end_of_line (str);
bfae80f2
RE
9117}
9118
9119static void
9120do_vfp_ctrl_from_reg (str)
9121 char *str;
9122{
9123 skip_whitespace (str);
9124
9125 if (vfp_psr_required_here (&str) == FAIL)
9126 return;
9127
9128 if (skip_past_comma (&str) == FAIL
9129 || reg_required_here (&str, 12) == FAIL)
9130 {
9131 if (! inst.error)
9132 inst.error = BAD_ARGS;
9133 return;
9134 }
9135
9136 end_of_line (str);
bfae80f2
RE
9137}
9138
9139static void
9140do_vfp_sp_ldst (str)
9141 char *str;
9142{
9143 skip_whitespace (str);
9144
9145 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
9146 {
9147 if (!inst.error)
9148 inst.error = BAD_ARGS;
9149 return;
9150 }
9151
9152 if (skip_past_comma (&str) == FAIL
9153 || cp_address_required_here (&str, CP_NO_WB) == FAIL)
9154 {
9155 if (!inst.error)
9156 inst.error = BAD_ARGS;
9157 return;
9158 }
9159
9160 end_of_line (str);
bfae80f2
RE
9161}
9162
9163static void
9164do_vfp_dp_ldst (str)
9165 char *str;
9166{
9167 skip_whitespace (str);
9168
9169 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
9170 {
9171 if (!inst.error)
9172 inst.error = BAD_ARGS;
9173 return;
9174 }
9175
9176 if (skip_past_comma (&str) == FAIL
9177 || cp_address_required_here (&str, CP_NO_WB) == FAIL)
9178 {
9179 if (!inst.error)
9180 inst.error = BAD_ARGS;
9181 return;
9182 }
9183
9184 end_of_line (str);
bfae80f2
RE
9185}
9186
9187/* Parse and encode a VFP SP register list, storing the initial
9188 register in position POS and returning the range as the result. If
9189 the string is invalid return FAIL (an invalid range). */
9190static long
9191vfp_sp_reg_list (str, pos)
9192 char **str;
9193 enum vfp_sp_reg_pos pos;
9194{
9195 long range = 0;
9196 int base_reg = 0;
9197 int new_base;
9198 long base_bits = 0;
9199 int count = 0;
9200 long tempinst;
9201 unsigned long mask = 0;
9202 int warned = 0;
9203
9204 if (**str != '{')
9205 return FAIL;
9206
9207 (*str)++;
9208 skip_whitespace (*str);
9209
9210 tempinst = inst.instruction;
9211
9212 do
9213 {
9214 inst.instruction = 0;
9215
9216 if ((new_base = vfp_sp_reg_required_here (str, pos)) == FAIL)
9217 return FAIL;
9218
9219 if (count == 0 || base_reg > new_base)
9220 {
9221 base_reg = new_base;
9222 base_bits = inst.instruction;
9223 }
9224
9225 if (mask & (1 << new_base))
9226 {
9227 inst.error = _("invalid register list");
9228 return FAIL;
9229 }
9230
9231 if ((mask >> new_base) != 0 && ! warned)
9232 {
9233 as_tsktsk (_("register list not in ascending order"));
9234 warned = 1;
9235 }
9236
9237 mask |= 1 << new_base;
9238 count++;
9239
9240 skip_whitespace (*str);
9241
9242 if (**str == '-') /* We have the start of a range expression */
9243 {
9244 int high_range;
9245
9246 (*str)++;
9247
9248 if ((high_range
9249 = arm_reg_parse (str, all_reg_maps[REG_TYPE_SN].htab))
9250 == FAIL)
9251 {
9252 inst.error = _(all_reg_maps[REG_TYPE_SN].expected);
9253 return FAIL;
9254 }
9255
9256 if (high_range <= new_base)
9257 {
9258 inst.error = _("register range not in ascending order");
9259 return FAIL;
9260 }
9261
9262 for (new_base++; new_base <= high_range; new_base++)
9263 {
9264 if (mask & (1 << new_base))
9265 {
9266 inst.error = _("invalid register list");
9267 return FAIL;
9268 }
9269
9270 mask |= 1 << new_base;
9271 count++;
9272 }
9273 }
9274 }
9275 while (skip_past_comma (str) != FAIL);
9276
9277 if (**str != '}')
9278 {
9279 inst.error = _("invalid register list");
9280 return FAIL;
9281 }
9282
9283 (*str)++;
9284
9285 range = count;
9286
9287 /* Sanity check -- should have raised a parse error above. */
9288 if (count == 0 || count > 32)
c62e1cc3 9289 abort ();
bfae80f2
RE
9290
9291 /* Final test -- the registers must be consecutive. */
9292 while (count--)
9293 {
9294 if ((mask & (1 << base_reg++)) == 0)
9295 {
9296 inst.error = _("non-contiguous register range");
9297 return FAIL;
9298 }
9299 }
9300
9301 inst.instruction = tempinst | base_bits;
9302 return range;
9303}
9304
9305static long
9306vfp_dp_reg_list (str)
9307 char **str;
9308{
9309 long range = 0;
9310 int base_reg = 0;
9311 int new_base;
9312 int count = 0;
9313 long tempinst;
9314 unsigned long mask = 0;
9315 int warned = 0;
9316
9317 if (**str != '{')
9318 return FAIL;
9319
9320 (*str)++;
9321 skip_whitespace (*str);
9322
9323 tempinst = inst.instruction;
9324
9325 do
9326 {
9327 inst.instruction = 0;
9328
9329 if ((new_base = vfp_dp_reg_required_here (str, VFP_REG_Dd)) == FAIL)
9330 return FAIL;
9331
9332 if (count == 0 || base_reg > new_base)
9333 {
9334 base_reg = new_base;
9335 range = inst.instruction;
9336 }
9337
9338 if (mask & (1 << new_base))
9339 {
9340 inst.error = _("invalid register list");
9341 return FAIL;
9342 }
9343
9344 if ((mask >> new_base) != 0 && ! warned)
9345 {
9346 as_tsktsk (_("register list not in ascending order"));
9347 warned = 1;
9348 }
9349
9350 mask |= 1 << new_base;
9351 count++;
9352
9353 skip_whitespace (*str);
9354
9355 if (**str == '-') /* We have the start of a range expression */
9356 {
9357 int high_range;
9358
9359 (*str)++;
9360
9361 if ((high_range
9362 = arm_reg_parse (str, all_reg_maps[REG_TYPE_DN].htab))
9363 == FAIL)
9364 {
9365 inst.error = _(all_reg_maps[REG_TYPE_DN].expected);
9366 return FAIL;
9367 }
9368
9369 if (high_range <= new_base)
9370 {
9371 inst.error = _("register range not in ascending order");
9372 return FAIL;
9373 }
9374
9375 for (new_base++; new_base <= high_range; new_base++)
9376 {
9377 if (mask & (1 << new_base))
9378 {
9379 inst.error = _("invalid register list");
9380 return FAIL;
9381 }
9382
9383 mask |= 1 << new_base;
9384 count++;
9385 }
9386 }
9387 }
9388 while (skip_past_comma (str) != FAIL);
9389
9390 if (**str != '}')
9391 {
9392 inst.error = _("invalid register list");
9393 return FAIL;
9394 }
9395
9396 (*str)++;
9397
9398 range |= 2 * count;
9399
9400 /* Sanity check -- should have raised a parse error above. */
9401 if (count == 0 || count > 16)
c62e1cc3 9402 abort ();
bfae80f2
RE
9403
9404 /* Final test -- the registers must be consecutive. */
9405 while (count--)
9406 {
9407 if ((mask & (1 << base_reg++)) == 0)
9408 {
9409 inst.error = _("non-contiguous register range");
9410 return FAIL;
9411 }
9412 }
9413
9414 inst.instruction = tempinst;
9415 return range;
9416}
9417
9418static void
c62e1cc3 9419vfp_sp_ldstm (str, ldstm_type)
bfae80f2
RE
9420 char *str;
9421 enum vfp_ldstm_type ldstm_type;
9422{
9423 long range;
9424
9425 skip_whitespace (str);
9426
9427 if (reg_required_here (&str, 16) == FAIL)
9428 return;
9429
9430 skip_whitespace (str);
9431
9432 if (*str == '!')
9433 {
9434 inst.instruction |= WRITE_BACK;
9435 str++;
9436 }
9437 else if (ldstm_type != VFP_LDSTMIA)
9438 {
9439 inst.error = _("this addressing mode requires base-register writeback");
9440 return;
9441 }
9442
9443 if (skip_past_comma (&str) == FAIL
9444 || (range = vfp_sp_reg_list (&str, VFP_REG_Sd)) == FAIL)
9445 {
9446 if (!inst.error)
9447 inst.error = BAD_ARGS;
9448 return;
9449 }
9450
9451 inst.instruction |= range;
9452 end_of_line (str);
9453}
9454
9455static void
c62e1cc3 9456vfp_dp_ldstm (str, ldstm_type)
bfae80f2
RE
9457 char *str;
9458 enum vfp_ldstm_type ldstm_type;
9459{
9460 long range;
9461
9462 skip_whitespace (str);
9463
9464 if (reg_required_here (&str, 16) == FAIL)
9465 return;
9466
9467 skip_whitespace (str);
9468
9469 if (*str == '!')
9470 {
9471 inst.instruction |= WRITE_BACK;
9472 str++;
9473 }
9474 else if (ldstm_type != VFP_LDSTMIA && ldstm_type != VFP_LDSTMIAX)
9475 {
9476 inst.error = _("this addressing mode requires base-register writeback");
9477 return;
9478 }
9479
9480 if (skip_past_comma (&str) == FAIL
9481 || (range = vfp_dp_reg_list (&str)) == FAIL)
9482 {
9483 if (!inst.error)
9484 inst.error = BAD_ARGS;
9485 return;
9486 }
9487
9488 if (ldstm_type == VFP_LDSTMIAX || ldstm_type == VFP_LDSTMDBX)
9489 range += 1;
9490
9491 inst.instruction |= range;
9492 end_of_line (str);
9493}
9494
9495static void
9496do_vfp_sp_ldstmia (str)
9497 char *str;
9498{
9499 vfp_sp_ldstm (str, VFP_LDSTMIA);
9500}
9501
9502static void
9503do_vfp_sp_ldstmdb (str)
9504 char *str;
9505{
9506 vfp_sp_ldstm (str, VFP_LDSTMDB);
9507}
9508
9509static void
9510do_vfp_dp_ldstmia (str)
9511 char *str;
9512{
9513 vfp_dp_ldstm (str, VFP_LDSTMIA);
9514}
9515
9516static void
9517do_vfp_dp_ldstmdb (str)
9518 char *str;
9519{
9520 vfp_dp_ldstm (str, VFP_LDSTMDB);
9521}
9522
9523static void
9524do_vfp_xp_ldstmia (str)
9525 char *str;
9526{
9527 vfp_dp_ldstm (str, VFP_LDSTMIAX);
9528}
9529
9530static void
9531do_vfp_xp_ldstmdb (str)
9532 char *str;
9533{
9534 vfp_dp_ldstm (str, VFP_LDSTMDBX);
9535}
9536
9537static void
9538do_vfp_sp_compare_z (str)
9539 char *str;
9540{
9541 skip_whitespace (str);
9542
9543 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
9544 {
9545 if (!inst.error)
9546 inst.error = BAD_ARGS;
9547 return;
9548 }
9549
9550 end_of_line (str);
bfae80f2
RE
9551}
9552
9553static void
9554do_vfp_dp_compare_z (str)
9555 char *str;
9556{
9557 skip_whitespace (str);
9558
9559 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
9560 {
9561 if (!inst.error)
9562 inst.error = BAD_ARGS;
9563 return;
9564 }
9565
9566 end_of_line (str);
bfae80f2
RE
9567}
9568
9569static void
9570do_vfp_dp_sp_cvt (str)
9571 char *str;
9572{
9573 skip_whitespace (str);
9574
9575 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
9576 return;
9577
9578 if (skip_past_comma (&str) == FAIL
9579 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
9580 {
9581 if (! inst.error)
9582 inst.error = BAD_ARGS;
9583 return;
9584 }
9585
9586 end_of_line (str);
bfae80f2
RE
9587}
9588
9589static void
9590do_vfp_sp_dp_cvt (str)
9591 char *str;
9592{
9593 skip_whitespace (str);
9594
9595 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
9596 return;
9597
9598 if (skip_past_comma (&str) == FAIL
9599 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
9600 {
9601 if (! inst.error)
9602 inst.error = BAD_ARGS;
9603 return;
9604 }
9605
9606 end_of_line (str);
bfae80f2
RE
9607}
9608
9609/* Thumb specific routines. */
9610
9611/* Parse and validate that a register is of the right form, this saves
9612 repeated checking of this information in many similar cases.
9613 Unlike the 32-bit case we do not insert the register into the opcode
9614 here, since the position is often unknown until the full instruction
9615 has been parsed. */
9616
9617static int
9618thumb_reg (strp, hi_lo)
9619 char ** strp;
9620 int hi_lo;
9621{
9622 int reg;
9623
9624 if ((reg = reg_required_here (strp, -1)) == FAIL)
9625 return FAIL;
9626
9627 switch (hi_lo)
9628 {
9629 case THUMB_REG_LO:
9630 if (reg > 7)
9631 {
9632 inst.error = _("lo register required");
9633 return FAIL;
9634 }
9635 break;
9636
9637 case THUMB_REG_HI:
9638 if (reg < 8)
9639 {
9640 inst.error = _("hi register required");
9641 return FAIL;
9642 }
9643 break;
9644
9645 default:
9646 break;
9647 }
9648
9649 return reg;
9650}
9651
9652/* Parse an add or subtract instruction, SUBTRACT is non-zero if the opcode
9653 was SUB. */
9654
9655static void
9656thumb_add_sub (str, subtract)
9657 char * str;
9658 int subtract;
9659{
9660 int Rd, Rs, Rn = FAIL;
9661
9662 skip_whitespace (str);
9663
9664 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
9665 || skip_past_comma (&str) == FAIL)
9666 {
9667 if (! inst.error)
9668 inst.error = BAD_ARGS;
9669 return;
9670 }
9671
9672 if (is_immediate_prefix (*str))
9673 {
9674 Rs = Rd;
9675 str++;
9676 if (my_get_expression (&inst.reloc.exp, &str))
9677 return;
9678 }
9679 else
9680 {
9681 if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
9682 return;
9683
9684 if (skip_past_comma (&str) == FAIL)
9685 {
9686 /* Two operand format, shuffle the registers
9687 and pretend there are 3. */
9688 Rn = Rs;
9689 Rs = Rd;
9690 }
9691 else if (is_immediate_prefix (*str))
9692 {
9693 str++;
9694 if (my_get_expression (&inst.reloc.exp, &str))
9695 return;
9696 }
9697 else if ((Rn = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
9698 return;
9699 }
9700
9701 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
9702 for the latter case, EXPR contains the immediate that was found. */
9703 if (Rn != FAIL)
9704 {
9705 /* All register format. */
9706 if (Rd > 7 || Rs > 7 || Rn > 7)
9707 {
9708 if (Rs != Rd)
9709 {
9710 inst.error = _("dest and source1 must be the same register");
9711 return;
9712 }
9713
9714 /* Can't do this for SUB. */
9715 if (subtract)
9716 {
9717 inst.error = _("subtract valid only on lo regs");
9718 return;
9719 }
9720
9721 inst.instruction = (T_OPCODE_ADD_HI
9722 | (Rd > 7 ? THUMB_H1 : 0)
9723 | (Rn > 7 ? THUMB_H2 : 0));
9724 inst.instruction |= (Rd & 7) | ((Rn & 7) << 3);
9725 }
9726 else
9727 {
9728 inst.instruction = subtract ? T_OPCODE_SUB_R3 : T_OPCODE_ADD_R3;
9729 inst.instruction |= Rd | (Rs << 3) | (Rn << 6);
9730 }
9731 }
9732 else
9733 {
9734 /* Immediate expression, now things start to get nasty. */
9735
9736 /* First deal with HI regs, only very restricted cases allowed:
9737 Adjusting SP, and using PC or SP to get an address. */
9738 if ((Rd > 7 && (Rd != REG_SP || Rs != REG_SP))
9739 || (Rs > 7 && Rs != REG_SP && Rs != REG_PC))
9740 {
9741 inst.error = _("invalid Hi register with immediate");
9742 return;
9743 }
9744
9745 if (inst.reloc.exp.X_op != O_constant)
9746 {
9747 /* Value isn't known yet, all we can do is store all the fragments
9748 we know about in the instruction and let the reloc hacking
9749 work it all out. */
9750 inst.instruction = (subtract ? 0x8000 : 0) | (Rd << 4) | Rs;
9751 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
9752 }
9753 else
9754 {
9755 int offset = inst.reloc.exp.X_add_number;
9756
9757 if (subtract)
358b94bd 9758 offset = - offset;
bfae80f2
RE
9759
9760 if (offset < 0)
9761 {
358b94bd 9762 offset = - offset;
bfae80f2
RE
9763 subtract = 1;
9764
9765 /* Quick check, in case offset is MIN_INT. */
9766 if (offset < 0)
9767 {
9768 inst.error = _("immediate value out of range");
9769 return;
9770 }
9771 }
358b94bd
NC
9772 /* Note - you cannot convert a subtract of 0 into an
9773 add of 0 because the carry flag is set differently. */
9774 else if (offset > 0)
bfae80f2
RE
9775 subtract = 0;
9776
9777 if (Rd == REG_SP)
9778 {
9779 if (offset & ~0x1fc)
9780 {
9781 inst.error = _("invalid immediate value for stack adjust");
9782 return;
b99bd4ef
NC
9783 }
9784 inst.instruction = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
9785 inst.instruction |= offset >> 2;
9786 }
9787 else if (Rs == REG_PC || Rs == REG_SP)
9788 {
9789 if (subtract
9790 || (offset & ~0x3fc))
9791 {
9792 inst.error = _("invalid immediate for address calculation");
9793 return;
9794 }
9795 inst.instruction = (Rs == REG_PC ? T_OPCODE_ADD_PC
9796 : T_OPCODE_ADD_SP);
9797 inst.instruction |= (Rd << 8) | (offset >> 2);
9798 }
9799 else if (Rs == Rd)
9800 {
9801 if (offset & ~0xff)
9802 {
9803 inst.error = _("immediate value out of range");
9804 return;
9805 }
9806 inst.instruction = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
9807 inst.instruction |= (Rd << 8) | offset;
9808 }
9809 else
9810 {
9811 if (offset & ~0x7)
9812 {
9813 inst.error = _("immediate value out of range");
9814 return;
9815 }
9816 inst.instruction = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
9817 inst.instruction |= Rd | (Rs << 3) | (offset << 6);
9818 }
9819 }
9820 }
9821
9822 end_of_line (str);
9823}
9824
9825static void
9826thumb_shift (str, shift)
9827 char * str;
9828 int shift;
9829{
9830 int Rd, Rs, Rn = FAIL;
9831
9832 skip_whitespace (str);
9833
9834 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9835 || skip_past_comma (&str) == FAIL)
9836 {
9837 if (! inst.error)
9838 inst.error = BAD_ARGS;
9839 return;
9840 }
9841
9842 if (is_immediate_prefix (*str))
9843 {
9844 /* Two operand immediate format, set Rs to Rd. */
9845 Rs = Rd;
9846 str ++;
9847 if (my_get_expression (&inst.reloc.exp, &str))
9848 return;
9849 }
9850 else
9851 {
9852 if ((Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9853 return;
9854
9855 if (skip_past_comma (&str) == FAIL)
9856 {
9857 /* Two operand format, shuffle the registers
9858 and pretend there are 3. */
9859 Rn = Rs;
9860 Rs = Rd;
9861 }
9862 else if (is_immediate_prefix (*str))
9863 {
9864 str++;
9865 if (my_get_expression (&inst.reloc.exp, &str))
9866 return;
9867 }
9868 else if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9869 return;
9870 }
9871
9872 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
9873 for the latter case, EXPR contains the immediate that was found. */
9874
9875 if (Rn != FAIL)
9876 {
9877 if (Rs != Rd)
9878 {
9879 inst.error = _("source1 and dest must be same register");
9880 return;
9881 }
9882
9883 switch (shift)
9884 {
9885 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_R; break;
9886 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_R; break;
9887 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_R; break;
9888 }
9889
9890 inst.instruction |= Rd | (Rn << 3);
9891 }
9892 else
9893 {
9894 switch (shift)
9895 {
9896 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_I; break;
9897 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_I; break;
9898 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_I; break;
9899 }
9900
9901 if (inst.reloc.exp.X_op != O_constant)
9902 {
9903 /* Value isn't known yet, create a dummy reloc and let reloc
9904 hacking fix it up. */
9905 inst.reloc.type = BFD_RELOC_ARM_THUMB_SHIFT;
9906 }
9907 else
9908 {
9909 unsigned shift_value = inst.reloc.exp.X_add_number;
9910
9911 if (shift_value > 32 || (shift_value == 32 && shift == THUMB_LSL))
9912 {
f03698e6 9913 inst.error = _("invalid immediate for shift");
b99bd4ef
NC
9914 return;
9915 }
9916
9917 /* Shifts of zero are handled by converting to LSL. */
9918 if (shift_value == 0)
9919 inst.instruction = T_OPCODE_LSL_I;
9920
9921 /* Shifts of 32 are encoded as a shift of zero. */
9922 if (shift_value == 32)
9923 shift_value = 0;
9924
9925 inst.instruction |= shift_value << 6;
9926 }
9927
9928 inst.instruction |= Rd | (Rs << 3);
9929 }
9930
9931 end_of_line (str);
9932}
9933
9934static void
9935thumb_mov_compare (str, move)
9936 char * str;
9937 int move;
9938{
9939 int Rd, Rs = FAIL;
9940
9941 skip_whitespace (str);
9942
9943 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
9944 || skip_past_comma (&str) == FAIL)
9945 {
9946 if (! inst.error)
9947 inst.error = BAD_ARGS;
9948 return;
9949 }
9950
09d92015 9951 if (move != THUMB_CPY && is_immediate_prefix (*str))
b99bd4ef
NC
9952 {
9953 str++;
9954 if (my_get_expression (&inst.reloc.exp, &str))
9955 return;
9956 }
9957 else if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
9958 return;
9959
9960 if (Rs != FAIL)
9961 {
09d92015 9962 if (move != THUMB_CPY && Rs < 8 && Rd < 8)
b99bd4ef
NC
9963 {
9964 if (move == THUMB_MOVE)
9965 /* A move of two lowregs is encoded as ADD Rd, Rs, #0
9966 since a MOV instruction produces unpredictable results. */
9967 inst.instruction = T_OPCODE_ADD_I3;
9968 else
9969 inst.instruction = T_OPCODE_CMP_LR;
9970 inst.instruction |= Rd | (Rs << 3);
9971 }
9972 else
9973 {
9974 if (move == THUMB_MOVE)
9975 inst.instruction = T_OPCODE_MOV_HR;
09d92015 9976 else if (move != THUMB_CPY)
b99bd4ef
NC
9977 inst.instruction = T_OPCODE_CMP_HR;
9978
9979 if (Rd > 7)
9980 inst.instruction |= THUMB_H1;
9981
9982 if (Rs > 7)
9983 inst.instruction |= THUMB_H2;
9984
9985 inst.instruction |= (Rd & 7) | ((Rs & 7) << 3);
9986 }
9987 }
9988 else
9989 {
9990 if (Rd > 7)
9991 {
9992 inst.error = _("only lo regs allowed with immediate");
9993 return;
9994 }
9995
9996 if (move == THUMB_MOVE)
9997 inst.instruction = T_OPCODE_MOV_I8;
9998 else
9999 inst.instruction = T_OPCODE_CMP_I8;
10000
10001 inst.instruction |= Rd << 8;
10002
10003 if (inst.reloc.exp.X_op != O_constant)
10004 inst.reloc.type = BFD_RELOC_ARM_THUMB_IMM;
10005 else
10006 {
10007 unsigned value = inst.reloc.exp.X_add_number;
10008
10009 if (value > 255)
10010 {
10011 inst.error = _("invalid immediate");
10012 return;
10013 }
10014
10015 inst.instruction |= value;
10016 }
10017 }
10018
10019 end_of_line (str);
10020}
10021
10022static void
10023thumb_load_store (str, load_store, size)
10024 char * str;
10025 int load_store;
10026 int size;
10027{
10028 int Rd, Rb, Ro = FAIL;
10029
10030 skip_whitespace (str);
10031
10032 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
10033 || skip_past_comma (&str) == FAIL)
10034 {
10035 if (! inst.error)
10036 inst.error = BAD_ARGS;
10037 return;
10038 }
10039
10040 if (*str == '[')
10041 {
10042 str++;
10043 if ((Rb = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
10044 return;
10045
10046 if (skip_past_comma (&str) != FAIL)
10047 {
10048 if (is_immediate_prefix (*str))
10049 {
10050 str++;
10051 if (my_get_expression (&inst.reloc.exp, &str))
10052 return;
10053 }
10054 else if ((Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
10055 return;
10056 }
10057 else
10058 {
10059 inst.reloc.exp.X_op = O_constant;
10060 inst.reloc.exp.X_add_number = 0;
10061 }
10062
10063 if (*str != ']')
10064 {
10065 inst.error = _("expected ']'");
10066 return;
10067 }
10068 str++;
10069 }
10070 else if (*str == '=')
10071 {
f03698e6
RE
10072 if (load_store != THUMB_LOAD)
10073 {
10074 inst.error = _("invalid pseudo operation");
10075 return;
10076 }
10077
b99bd4ef
NC
10078 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
10079 str++;
10080
10081 skip_whitespace (str);
10082
10083 if (my_get_expression (& inst.reloc.exp, & str))
10084 return;
10085
10086 end_of_line (str);
10087
10088 if ( inst.reloc.exp.X_op != O_constant
10089 && inst.reloc.exp.X_op != O_symbol)
10090 {
10091 inst.error = "Constant expression expected";
10092 return;
10093 }
10094
10095 if (inst.reloc.exp.X_op == O_constant
10096 && ((inst.reloc.exp.X_add_number & ~0xFF) == 0))
10097 {
10098 /* This can be done with a mov instruction. */
10099
10100 inst.instruction = T_OPCODE_MOV_I8 | (Rd << 8);
10101 inst.instruction |= inst.reloc.exp.X_add_number;
10102 return;
10103 }
10104
10105 /* Insert into literal pool. */
10106 if (add_to_lit_pool () == FAIL)
10107 {
10108 if (!inst.error)
10109 inst.error = "literal pool insertion failed";
10110 return;
10111 }
10112
10113 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
10114 inst.reloc.pc_rel = 1;
10115 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
10116 /* Adjust ARM pipeline offset to Thumb. */
10117 inst.reloc.exp.X_add_number += 4;
10118
10119 return;
10120 }
10121 else
10122 {
10123 if (my_get_expression (&inst.reloc.exp, &str))
10124 return;
10125
10126 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
10127 inst.reloc.pc_rel = 1;
10128 inst.reloc.exp.X_add_number -= 4; /* Pipeline offset. */
10129 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
10130 end_of_line (str);
10131 return;
10132 }
10133
10134 if (Rb == REG_PC || Rb == REG_SP)
10135 {
10136 if (size != THUMB_WORD)
10137 {
10138 inst.error = _("byte or halfword not valid for base register");
10139 return;
10140 }
10141 else if (Rb == REG_PC && load_store != THUMB_LOAD)
10142 {
f03698e6 10143 inst.error = _("r15 based store not allowed");
b99bd4ef
NC
10144 return;
10145 }
10146 else if (Ro != FAIL)
10147 {
f03698e6 10148 inst.error = _("invalid base register for register offset");
b99bd4ef
NC
10149 return;
10150 }
10151
10152 if (Rb == REG_PC)
10153 inst.instruction = T_OPCODE_LDR_PC;
10154 else if (load_store == THUMB_LOAD)
10155 inst.instruction = T_OPCODE_LDR_SP;
10156 else
10157 inst.instruction = T_OPCODE_STR_SP;
10158
10159 inst.instruction |= Rd << 8;
10160 if (inst.reloc.exp.X_op == O_constant)
10161 {
10162 unsigned offset = inst.reloc.exp.X_add_number;
10163
10164 if (offset & ~0x3fc)
10165 {
10166 inst.error = _("invalid offset");
10167 return;
10168 }
10169
10170 inst.instruction |= offset >> 2;
10171 }
10172 else
10173 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
10174 }
10175 else if (Rb > 7)
10176 {
10177 inst.error = _("invalid base register in load/store");
10178 return;
10179 }
10180 else if (Ro == FAIL)
10181 {
10182 /* Immediate offset. */
10183 if (size == THUMB_WORD)
10184 inst.instruction = (load_store == THUMB_LOAD
10185 ? T_OPCODE_LDR_IW : T_OPCODE_STR_IW);
10186 else if (size == THUMB_HALFWORD)
10187 inst.instruction = (load_store == THUMB_LOAD
10188 ? T_OPCODE_LDR_IH : T_OPCODE_STR_IH);
10189 else
10190 inst.instruction = (load_store == THUMB_LOAD
10191 ? T_OPCODE_LDR_IB : T_OPCODE_STR_IB);
10192
10193 inst.instruction |= Rd | (Rb << 3);
10194
10195 if (inst.reloc.exp.X_op == O_constant)
10196 {
10197 unsigned offset = inst.reloc.exp.X_add_number;
10198
10199 if (offset & ~(0x1f << size))
10200 {
f03698e6 10201 inst.error = _("invalid offset");
b99bd4ef
NC
10202 return;
10203 }
10204 inst.instruction |= (offset >> size) << 6;
10205 }
10206 else
10207 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
10208 }
10209 else
10210 {
10211 /* Register offset. */
10212 if (size == THUMB_WORD)
10213 inst.instruction = (load_store == THUMB_LOAD
10214 ? T_OPCODE_LDR_RW : T_OPCODE_STR_RW);
10215 else if (size == THUMB_HALFWORD)
10216 inst.instruction = (load_store == THUMB_LOAD
10217 ? T_OPCODE_LDR_RH : T_OPCODE_STR_RH);
10218 else
10219 inst.instruction = (load_store == THUMB_LOAD
10220 ? T_OPCODE_LDR_RB : T_OPCODE_STR_RB);
10221
10222 inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
10223 }
10224
10225 end_of_line (str);
10226}
10227
404ff6b5
AH
10228/* A register must be given at this point.
10229
404ff6b5
AH
10230 Shift is the place to put it in inst.instruction.
10231
404ff6b5
AH
10232 Restores input start point on err.
10233 Returns the reg#, or FAIL. */
10234
10235static int
63e63b07 10236mav_reg_required_here (str, shift, regtype)
404ff6b5
AH
10237 char ** str;
10238 int shift;
6c43fab6 10239 enum arm_reg_type regtype;
404ff6b5 10240{
6c43fab6
RE
10241 int reg;
10242 char *start = *str;
404ff6b5 10243
6c43fab6 10244 if ((reg = arm_reg_parse (str, all_reg_maps[regtype].htab)) != FAIL)
404ff6b5 10245 {
404ff6b5
AH
10246 if (shift >= 0)
10247 inst.instruction |= reg << shift;
10248
6c43fab6 10249 return reg;
404ff6b5
AH
10250 }
10251
6c43fab6 10252 /* Restore the start point. */
404ff6b5 10253 *str = start;
cc8a6dd0 10254
404ff6b5
AH
10255 /* In the few cases where we might be able to accept something else
10256 this error can be overridden. */
6c43fab6 10257 inst.error = _(all_reg_maps[regtype].expected);
cc8a6dd0 10258
404ff6b5
AH
10259 return FAIL;
10260}
10261
63e63b07 10262/* Cirrus Maverick Instructions. */
404ff6b5
AH
10263
10264/* Wrapper functions. */
10265
10266static void
63e63b07 10267do_mav_binops_1a (str)
6c43fab6
RE
10268 char * str;
10269{
63e63b07 10270 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVF);
6c43fab6
RE
10271}
10272
10273static void
63e63b07 10274do_mav_binops_1b (str)
6c43fab6
RE
10275 char * str;
10276{
63e63b07 10277 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVD);
6c43fab6
RE
10278}
10279
10280static void
63e63b07 10281do_mav_binops_1c (str)
404ff6b5 10282 char * str;
404ff6b5 10283{
63e63b07 10284 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVDX);
404ff6b5
AH
10285}
10286
10287static void
63e63b07 10288do_mav_binops_1d (str)
404ff6b5 10289 char * str;
404ff6b5 10290{
63e63b07 10291 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVF);
404ff6b5
AH
10292}
10293
10294static void
63e63b07 10295do_mav_binops_1e (str)
404ff6b5 10296 char * str;
404ff6b5 10297{
63e63b07 10298 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVD);
404ff6b5
AH
10299}
10300
10301static void
63e63b07 10302do_mav_binops_1f (str)
404ff6b5 10303 char * str;
404ff6b5 10304{
63e63b07 10305 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVF);
404ff6b5
AH
10306}
10307
10308static void
63e63b07 10309do_mav_binops_1g (str)
404ff6b5 10310 char * str;
404ff6b5 10311{
63e63b07 10312 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVD);
404ff6b5
AH
10313}
10314
10315static void
63e63b07 10316do_mav_binops_1h (str)
404ff6b5 10317 char * str;
404ff6b5 10318{
63e63b07 10319 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVFX);
404ff6b5
AH
10320}
10321
6c43fab6 10322static void
63e63b07 10323do_mav_binops_1i (str)
6c43fab6
RE
10324 char * str;
10325{
63e63b07 10326 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVFX);
6c43fab6
RE
10327}
10328
10329static void
63e63b07 10330do_mav_binops_1j (str)
6c43fab6
RE
10331 char * str;
10332{
63e63b07 10333 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVDX);
6c43fab6
RE
10334}
10335
10336static void
63e63b07 10337do_mav_binops_1k (str)
6c43fab6
RE
10338 char * str;
10339{
63e63b07 10340 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVDX);
6c43fab6
RE
10341}
10342
10343static void
63e63b07 10344do_mav_binops_1l (str)
6c43fab6
RE
10345 char * str;
10346{
63e63b07 10347 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVF);
6c43fab6
RE
10348}
10349
10350static void
63e63b07 10351do_mav_binops_1m (str)
6c43fab6
RE
10352 char * str;
10353{
63e63b07 10354 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVD);
6c43fab6
RE
10355}
10356
10357static void
63e63b07 10358do_mav_binops_1n (str)
6c43fab6
RE
10359 char * str;
10360{
63e63b07 10361 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVFX);
6c43fab6
RE
10362}
10363
10364static void
63e63b07 10365do_mav_binops_1o (str)
6c43fab6
RE
10366 char * str;
10367{
63e63b07 10368 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVDX, REG_TYPE_MVDX);
6c43fab6
RE
10369}
10370
10371static void
63e63b07 10372do_mav_binops_2a (str)
6c43fab6
RE
10373 char * str;
10374{
63e63b07 10375 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVF, REG_TYPE_RN);
6c43fab6
RE
10376}
10377
10378static void
63e63b07 10379do_mav_binops_2b (str)
6c43fab6
RE
10380 char * str;
10381{
63e63b07 10382 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVD, REG_TYPE_RN);
6c43fab6
RE
10383}
10384
10385static void
63e63b07 10386do_mav_binops_2c (str)
6c43fab6
RE
10387 char * str;
10388{
63e63b07 10389 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVDX, REG_TYPE_RN);
6c43fab6
RE
10390}
10391
10392static void
63e63b07 10393do_mav_binops_3a (str)
6c43fab6
RE
10394 char * str;
10395{
63e63b07 10396 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVAX, REG_TYPE_MVFX);
6c43fab6
RE
10397}
10398
10399static void
63e63b07 10400do_mav_binops_3b (str)
6c43fab6
RE
10401 char * str;
10402{
63e63b07 10403 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVFX, REG_TYPE_MVAX);
6c43fab6
RE
10404}
10405
10406static void
63e63b07 10407do_mav_binops_3c (str)
6c43fab6
RE
10408 char * str;
10409{
63e63b07 10410 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVAX, REG_TYPE_MVDX);
6c43fab6
RE
10411}
10412
10413static void
63e63b07 10414do_mav_binops_3d (str)
6c43fab6
RE
10415 char * str;
10416{
63e63b07 10417 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVDX, REG_TYPE_MVAX);
6c43fab6
RE
10418}
10419
10420static void
63e63b07 10421do_mav_triple_4a (str)
6c43fab6
RE
10422 char * str;
10423{
63e63b07 10424 do_mav_triple (str, MAV_MODE4, REG_TYPE_MVFX, REG_TYPE_MVFX, REG_TYPE_RN);
6c43fab6
RE
10425}
10426
10427static void
63e63b07 10428do_mav_triple_4b (str)
6c43fab6
RE
10429 char * str;
10430{
63e63b07 10431 do_mav_triple (str, MAV_MODE4, REG_TYPE_MVDX, REG_TYPE_MVDX, REG_TYPE_RN);
6c43fab6
RE
10432}
10433
10434static void
63e63b07 10435do_mav_triple_5a (str)
6c43fab6
RE
10436 char * str;
10437{
63e63b07 10438 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVF, REG_TYPE_MVF);
6c43fab6
RE
10439}
10440
10441static void
63e63b07 10442do_mav_triple_5b (str)
6c43fab6
RE
10443 char * str;
10444{
63e63b07 10445 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVD, REG_TYPE_MVD);
6c43fab6
RE
10446}
10447
10448static void
63e63b07 10449do_mav_triple_5c (str)
6c43fab6
RE
10450 char * str;
10451{
63e63b07 10452 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVFX, REG_TYPE_MVFX);
6c43fab6
RE
10453}
10454
10455static void
63e63b07 10456do_mav_triple_5d (str)
6c43fab6
RE
10457 char * str;
10458{
63e63b07 10459 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVDX, REG_TYPE_MVDX);
6c43fab6
RE
10460}
10461
10462static void
63e63b07 10463do_mav_triple_5e (str)
6c43fab6
RE
10464 char * str;
10465{
63e63b07 10466 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVF, REG_TYPE_MVF, REG_TYPE_MVF);
6c43fab6
RE
10467}
10468
10469static void
63e63b07 10470do_mav_triple_5f (str)
6c43fab6
RE
10471 char * str;
10472{
63e63b07 10473 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVD, REG_TYPE_MVD, REG_TYPE_MVD);
6c43fab6
RE
10474}
10475
10476static void
63e63b07 10477do_mav_triple_5g (str)
6c43fab6
RE
10478 char * str;
10479{
63e63b07 10480 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVFX, REG_TYPE_MVFX, REG_TYPE_MVFX);
6c43fab6
RE
10481}
10482
10483static void
63e63b07 10484do_mav_triple_5h (str)
6c43fab6
RE
10485 char * str;
10486{
63e63b07 10487 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVDX, REG_TYPE_MVDX, REG_TYPE_MVDX);
6c43fab6
RE
10488}
10489
10490static void
63e63b07 10491do_mav_quad_6a (str)
6c43fab6
RE
10492 char * str;
10493{
63e63b07 10494 do_mav_quad (str, MAV_MODE6, REG_TYPE_MVAX, REG_TYPE_MVFX, REG_TYPE_MVFX,
6c43fab6
RE
10495 REG_TYPE_MVFX);
10496}
10497
10498static void
63e63b07 10499do_mav_quad_6b (str)
6c43fab6
RE
10500 char * str;
10501{
63e63b07 10502 do_mav_quad (str, MAV_MODE6, REG_TYPE_MVAX, REG_TYPE_MVAX, REG_TYPE_MVFX,
6c43fab6
RE
10503 REG_TYPE_MVFX);
10504}
10505
34920d91 10506/* cfmvsc32<cond> DSPSC,MVDX[15:0]. */
404ff6b5 10507static void
63e63b07 10508do_mav_dspsc_1 (str)
404ff6b5 10509 char * str;
404ff6b5 10510{
6c43fab6
RE
10511 skip_whitespace (str);
10512
10513 /* cfmvsc32. */
63e63b07 10514 if (mav_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL
6c43fab6 10515 || skip_past_comma (&str) == FAIL
34920d91 10516 || mav_reg_required_here (&str, 12, REG_TYPE_MVDX) == FAIL)
6c43fab6
RE
10517 {
10518 if (!inst.error)
10519 inst.error = BAD_ARGS;
10520
10521 return;
10522 }
10523
10524 end_of_line (str);
404ff6b5
AH
10525}
10526
34920d91 10527/* cfmv32sc<cond> MVDX[15:0],DSPSC. */
404ff6b5 10528static void
63e63b07 10529do_mav_dspsc_2 (str)
404ff6b5 10530 char * str;
404ff6b5 10531{
6c43fab6
RE
10532 skip_whitespace (str);
10533
10534 /* cfmv32sc. */
34920d91 10535 if (mav_reg_required_here (&str, 12, REG_TYPE_MVDX) == FAIL
6c43fab6 10536 || skip_past_comma (&str) == FAIL
63e63b07 10537 || mav_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL)
6c43fab6
RE
10538 {
10539 if (!inst.error)
10540 inst.error = BAD_ARGS;
10541
10542 return;
10543 }
10544
10545 end_of_line (str);
404ff6b5
AH
10546}
10547
10548static void
63e63b07 10549do_mav_shift_1 (str)
404ff6b5 10550 char * str;
404ff6b5 10551{
63e63b07 10552 do_mav_shift (str, REG_TYPE_MVFX, REG_TYPE_MVFX);
404ff6b5
AH
10553}
10554
10555static void
63e63b07 10556do_mav_shift_2 (str)
404ff6b5 10557 char * str;
404ff6b5 10558{
63e63b07 10559 do_mav_shift (str, REG_TYPE_MVDX, REG_TYPE_MVDX);
404ff6b5
AH
10560}
10561
10562static void
63e63b07 10563do_mav_ldst_1 (str)
404ff6b5 10564 char * str;
404ff6b5 10565{
63e63b07 10566 do_mav_ldst (str, REG_TYPE_MVF);
404ff6b5
AH
10567}
10568
10569static void
63e63b07 10570do_mav_ldst_2 (str)
404ff6b5 10571 char * str;
404ff6b5 10572{
63e63b07 10573 do_mav_ldst (str, REG_TYPE_MVD);
404ff6b5
AH
10574}
10575
10576static void
63e63b07 10577do_mav_ldst_3 (str)
404ff6b5 10578 char * str;
404ff6b5 10579{
63e63b07 10580 do_mav_ldst (str, REG_TYPE_MVFX);
404ff6b5
AH
10581}
10582
10583static void
63e63b07 10584do_mav_ldst_4 (str)
404ff6b5 10585 char * str;
404ff6b5 10586{
63e63b07 10587 do_mav_ldst (str, REG_TYPE_MVDX);
404ff6b5
AH
10588}
10589
10590/* Isnsn like "foo X,Y". */
10591
10592static void
63e63b07 10593do_mav_binops (str, mode, reg0, reg1)
404ff6b5 10594 char * str;
404ff6b5 10595 int mode;
6c43fab6
RE
10596 enum arm_reg_type reg0;
10597 enum arm_reg_type reg1;
404ff6b5 10598{
6c43fab6 10599 int shift0, shift1;
404ff6b5 10600
6c43fab6
RE
10601 shift0 = mode & 0xff;
10602 shift1 = (mode >> 8) & 0xff;
404ff6b5
AH
10603
10604 skip_whitespace (str);
10605
63e63b07 10606 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
404ff6b5 10607 || skip_past_comma (&str) == FAIL
63e63b07 10608 || mav_reg_required_here (&str, shift1, reg1) == FAIL)
404ff6b5
AH
10609 {
10610 if (!inst.error)
10611 inst.error = BAD_ARGS;
10612 }
10613 else
10614 end_of_line (str);
404ff6b5
AH
10615}
10616
10617/* Isnsn like "foo X,Y,Z". */
10618
10619static void
63e63b07 10620do_mav_triple (str, mode, reg0, reg1, reg2)
404ff6b5 10621 char * str;
404ff6b5 10622 int mode;
6c43fab6
RE
10623 enum arm_reg_type reg0;
10624 enum arm_reg_type reg1;
10625 enum arm_reg_type reg2;
404ff6b5 10626{
6c43fab6 10627 int shift0, shift1, shift2;
404ff6b5 10628
6c43fab6
RE
10629 shift0 = mode & 0xff;
10630 shift1 = (mode >> 8) & 0xff;
10631 shift2 = (mode >> 16) & 0xff;
404ff6b5
AH
10632
10633 skip_whitespace (str);
10634
63e63b07 10635 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
404ff6b5 10636 || skip_past_comma (&str) == FAIL
63e63b07 10637 || mav_reg_required_here (&str, shift1, reg1) == FAIL
404ff6b5 10638 || skip_past_comma (&str) == FAIL
63e63b07 10639 || mav_reg_required_here (&str, shift2, reg2) == FAIL)
404ff6b5
AH
10640 {
10641 if (!inst.error)
10642 inst.error = BAD_ARGS;
10643 }
10644 else
10645 end_of_line (str);
404ff6b5
AH
10646}
10647
10648/* Isnsn like "foo W,X,Y,Z".
10649 where W=MVAX[0:3] and X,Y,Z=MVFX[0:15]. */
10650
10651static void
63e63b07 10652do_mav_quad (str, mode, reg0, reg1, reg2, reg3)
404ff6b5 10653 char * str;
404ff6b5 10654 int mode;
6c43fab6
RE
10655 enum arm_reg_type reg0;
10656 enum arm_reg_type reg1;
10657 enum arm_reg_type reg2;
10658 enum arm_reg_type reg3;
404ff6b5 10659{
6c43fab6 10660 int shift0, shift1, shift2, shift3;
404ff6b5 10661
6c43fab6
RE
10662 shift0= mode & 0xff;
10663 shift1 = (mode >> 8) & 0xff;
10664 shift2 = (mode >> 16) & 0xff;
10665 shift3 = (mode >> 24) & 0xff;
404ff6b5
AH
10666
10667 skip_whitespace (str);
10668
63e63b07 10669 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
404ff6b5 10670 || skip_past_comma (&str) == FAIL
63e63b07 10671 || mav_reg_required_here (&str, shift1, reg1) == FAIL
404ff6b5 10672 || skip_past_comma (&str) == FAIL
63e63b07 10673 || mav_reg_required_here (&str, shift2, reg2) == FAIL
404ff6b5 10674 || skip_past_comma (&str) == FAIL
63e63b07 10675 || mav_reg_required_here (&str, shift3, reg3) == FAIL)
404ff6b5
AH
10676 {
10677 if (!inst.error)
10678 inst.error = BAD_ARGS;
10679 }
10680 else
10681 end_of_line (str);
404ff6b5
AH
10682}
10683
63e63b07 10684/* Maverick shift immediate instructions.
404ff6b5
AH
10685 cfsh32<cond> MVFX[15:0],MVFX[15:0],Shift[6:0].
10686 cfsh64<cond> MVDX[15:0],MVDX[15:0],Shift[6:0]. */
10687
10688static void
63e63b07 10689do_mav_shift (str, reg0, reg1)
404ff6b5 10690 char * str;
6c43fab6
RE
10691 enum arm_reg_type reg0;
10692 enum arm_reg_type reg1;
404ff6b5
AH
10693{
10694 int error;
10695 int imm, neg = 0;
10696
10697 skip_whitespace (str);
10698
10699 error = 0;
10700
63e63b07 10701 if (mav_reg_required_here (&str, 12, reg0) == FAIL
404ff6b5 10702 || skip_past_comma (&str) == FAIL
63e63b07 10703 || mav_reg_required_here (&str, 16, reg1) == FAIL
404ff6b5
AH
10704 || skip_past_comma (&str) == FAIL)
10705 {
10706 if (!inst.error)
10707 inst.error = BAD_ARGS;
10708 return;
10709 }
10710
10711 /* Calculate the immediate operand.
10712 The operand is a 7bit signed number. */
10713 skip_whitespace (str);
10714
10715 if (*str == '#')
10716 ++str;
10717
8420dfca 10718 if (!ISDIGIT (*str) && *str != '-')
404ff6b5
AH
10719 {
10720 inst.error = _("expecting immediate, 7bit operand");
10721 return;
10722 }
10723
10724 if (*str == '-')
10725 {
10726 neg = 1;
10727 ++str;
10728 }
10729
8420dfca 10730 for (imm = 0; *str && ISDIGIT (*str); ++str)
404ff6b5
AH
10731 imm = imm * 10 + *str - '0';
10732
10733 if (imm > 64)
10734 {
10735 inst.error = _("immediate out of range");
10736 return;
10737 }
10738
10739 /* Make negative imm's into 7bit signed numbers. */
10740 if (neg)
10741 {
10742 imm = -imm;
10743 imm &= 0x0000007f;
10744 }
10745
10746 /* Bits 0-3 of the insn should have bits 0-3 of the immediate.
10747 Bits 5-7 of the insn should have bits 4-6 of the immediate.
10748 Bit 4 should be 0. */
10749 imm = (imm & 0xf) | ((imm & 0x70) << 1);
10750
10751 inst.instruction |= imm;
404ff6b5 10752 end_of_line (str);
404ff6b5
AH
10753}
10754
10755static int
63e63b07 10756mav_parse_offset (str, negative)
404ff6b5
AH
10757 char ** str;
10758 int *negative;
10759{
10760 char * p = *str;
10761 int offset;
10762
10763 *negative = 0;
10764
10765 skip_whitespace (p);
10766
10767 if (*p == '#')
10768 ++p;
10769
10770 if (*p == '-')
10771 {
10772 *negative = 1;
10773 ++p;
10774 }
10775
8420dfca 10776 if (!ISDIGIT (*p))
404ff6b5
AH
10777 {
10778 inst.error = _("offset expected");
10779 return 0;
10780 }
10781
8420dfca 10782 for (offset = 0; *p && ISDIGIT (*p); ++p)
404ff6b5
AH
10783 offset = offset * 10 + *p - '0';
10784
06516a5e 10785 if (offset > 0x3fc)
404ff6b5
AH
10786 {
10787 inst.error = _("offset out of range");
10788 return 0;
10789 }
06516a5e
PB
10790 if (offset & 0x3)
10791 {
10792 inst.error = _("offset not a multiple of 4");
10793 return 0;
10794 }
404ff6b5
AH
10795
10796 *str = p;
10797
10798 return *negative ? -offset : offset;
10799}
10800
63e63b07 10801/* Maverick load/store instructions.
404ff6b5
AH
10802 <insn><cond> CRd,[Rn,<offset>]{!}.
10803 <insn><cond> CRd,[Rn],<offset>. */
10804
10805static void
63e63b07 10806do_mav_ldst (str, reg0)
404ff6b5 10807 char * str;
6c43fab6 10808 enum arm_reg_type reg0;
404ff6b5
AH
10809{
10810 int offset, negative;
404ff6b5
AH
10811
10812 skip_whitespace (str);
10813
63e63b07 10814 if (mav_reg_required_here (&str, 12, reg0) == FAIL
6c43fab6 10815 || skip_past_comma (&str) == FAIL
404ff6b5 10816 || *str++ != '['
6c43fab6 10817 || reg_required_here (&str, 16) == FAIL)
404ff6b5
AH
10818 goto fail_ldst;
10819
6c43fab6 10820 if (skip_past_comma (&str) == SUCCESS)
404ff6b5
AH
10821 {
10822 /* You are here: "<offset>]{!}". */
10823 inst.instruction |= PRE_INDEX;
10824
63e63b07 10825 offset = mav_parse_offset (&str, &negative);
404ff6b5
AH
10826
10827 if (inst.error)
10828 return;
10829
10830 if (*str++ != ']')
10831 {
10832 inst.error = _("missing ]");
10833 return;
10834 }
10835
10836 if (*str == '!')
10837 {
10838 inst.instruction |= WRITE_BACK;
10839 ++str;
10840 }
10841 }
10842 else
10843 {
10844 /* You are here: "], <offset>". */
10845 if (*str++ != ']')
10846 {
10847 inst.error = _("missing ]");
10848 return;
10849 }
10850
10851 if (skip_past_comma (&str) == FAIL
63e63b07 10852 || (offset = mav_parse_offset (&str, &negative), inst.error))
404ff6b5
AH
10853 goto fail_ldst;
10854
10855 inst.instruction |= CP_T_WB; /* Post indexed, set bit W. */
10856 }
10857
10858 if (negative)
10859 offset = -offset;
10860 else
2d2255b5 10861 inst.instruction |= CP_T_UD; /* Positive, so set bit U. */
404ff6b5
AH
10862
10863 inst.instruction |= offset >> 2;
404ff6b5
AH
10864 end_of_line (str);
10865 return;
10866
10867fail_ldst:
10868 if (!inst.error)
10869 inst.error = BAD_ARGS;
404ff6b5
AH
10870}
10871
b99bd4ef
NC
10872static void
10873do_t_nop (str)
10874 char * str;
10875{
10876 /* Do nothing. */
10877 end_of_line (str);
b99bd4ef
NC
10878}
10879
10880/* Handle the Format 4 instructions that do not have equivalents in other
10881 formats. That is, ADC, AND, EOR, SBC, ROR, TST, NEG, CMN, ORR, MUL,
10882 BIC and MVN. */
10883
10884static void
10885do_t_arit (str)
10886 char * str;
10887{
10888 int Rd, Rs, Rn;
10889
10890 skip_whitespace (str);
10891
10892 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
10893 || skip_past_comma (&str) == FAIL
10894 || (Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
10895 {
10896 inst.error = BAD_ARGS;
10897 return;
10898 }
10899
10900 if (skip_past_comma (&str) != FAIL)
10901 {
10902 /* Three operand format not allowed for TST, CMN, NEG and MVN.
10903 (It isn't allowed for CMP either, but that isn't handled by this
10904 function.) */
10905 if (inst.instruction == T_OPCODE_TST
10906 || inst.instruction == T_OPCODE_CMN
10907 || inst.instruction == T_OPCODE_NEG
10908 || inst.instruction == T_OPCODE_MVN)
10909 {
10910 inst.error = BAD_ARGS;
10911 return;
10912 }
10913
10914 if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
10915 return;
10916
10917 if (Rs != Rd)
10918 {
10919 inst.error = _("dest and source1 must be the same register");
10920 return;
10921 }
10922 Rs = Rn;
10923 }
10924
10925 if (inst.instruction == T_OPCODE_MUL
10926 && Rs == Rd)
10927 as_tsktsk (_("Rs and Rd must be different in MUL"));
10928
10929 inst.instruction |= Rd | (Rs << 3);
10930 end_of_line (str);
10931}
10932
10933static void
10934do_t_add (str)
10935 char * str;
10936{
10937 thumb_add_sub (str, 0);
10938}
10939
10940static void
10941do_t_asr (str)
10942 char * str;
10943{
10944 thumb_shift (str, THUMB_ASR);
10945}
10946
10947static void
10948do_t_branch9 (str)
10949 char * str;
10950{
10951 if (my_get_expression (&inst.reloc.exp, &str))
10952 return;
10953 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH9;
10954 inst.reloc.pc_rel = 1;
10955 end_of_line (str);
10956}
10957
10958static void
10959do_t_branch12 (str)
10960 char * str;
10961{
10962 if (my_get_expression (&inst.reloc.exp, &str))
10963 return;
10964 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH12;
10965 inst.reloc.pc_rel = 1;
10966 end_of_line (str);
10967}
10968
10969/* Find the real, Thumb encoded start of a Thumb function. */
10970
10971static symbolS *
10972find_real_start (symbolP)
10973 symbolS * symbolP;
10974{
10975 char * real_start;
10976 const char * name = S_GET_NAME (symbolP);
10977 symbolS * new_target;
10978
2d2255b5 10979 /* This definition must agree with the one in gcc/config/arm/thumb.c. */
b99bd4ef
NC
10980#define STUB_NAME ".real_start_of"
10981
10982 if (name == NULL)
10983 abort ();
10984
10985 /* Names that start with '.' are local labels, not function entry points.
10986 The compiler may generate BL instructions to these labels because it
10987 needs to perform a branch to a far away location. */
10988 if (name[0] == '.')
10989 return symbolP;
10990
10991 real_start = malloc (strlen (name) + strlen (STUB_NAME) + 1);
10992 sprintf (real_start, "%s%s", STUB_NAME, name);
10993
10994 new_target = symbol_find (real_start);
10995
10996 if (new_target == NULL)
10997 {
10998 as_warn ("Failed to find real start of function: %s\n", name);
10999 new_target = symbolP;
11000 }
11001
11002 free (real_start);
11003
11004 return new_target;
11005}
11006
11007static void
11008do_t_branch23 (str)
11009 char * str;
11010{
11011 if (my_get_expression (& inst.reloc.exp, & str))
11012 return;
11013
11014 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH23;
11015 inst.reloc.pc_rel = 1;
11016 end_of_line (str);
11017
11018 /* If the destination of the branch is a defined symbol which does not have
11019 the THUMB_FUNC attribute, then we must be calling a function which has
11020 the (interfacearm) attribute. We look for the Thumb entry point to that
11021 function and change the branch to refer to that function instead. */
11022 if ( inst.reloc.exp.X_op == O_symbol
11023 && inst.reloc.exp.X_add_symbol != NULL
11024 && S_IS_DEFINED (inst.reloc.exp.X_add_symbol)
11025 && ! THUMB_IS_FUNC (inst.reloc.exp.X_add_symbol))
11026 inst.reloc.exp.X_add_symbol =
11027 find_real_start (inst.reloc.exp.X_add_symbol);
11028}
11029
11030static void
11031do_t_bx (str)
11032 char * str;
11033{
11034 int reg;
11035
11036 skip_whitespace (str);
11037
11038 if ((reg = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
11039 return;
11040
11041 /* This sets THUMB_H2 from the top bit of reg. */
11042 inst.instruction |= reg << 3;
11043
11044 /* ??? FIXME: Should add a hacky reloc here if reg is REG_PC. The reloc
11045 should cause the alignment to be checked once it is known. This is
11046 because BX PC only works if the instruction is word aligned. */
11047
11048 end_of_line (str);
11049}
11050
11051static void
11052do_t_compare (str)
11053 char * str;
11054{
11055 thumb_mov_compare (str, THUMB_COMPARE);
11056}
11057
11058static void
11059do_t_ldmstm (str)
11060 char * str;
11061{
11062 int Rb;
11063 long range;
11064
11065 skip_whitespace (str);
11066
11067 if ((Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
11068 return;
11069
11070 if (*str != '!')
f03698e6 11071 as_warn (_("inserted missing '!': load/store multiple always writes back base register"));
b99bd4ef
NC
11072 else
11073 str++;
11074
11075 if (skip_past_comma (&str) == FAIL
11076 || (range = reg_list (&str)) == FAIL)
11077 {
11078 if (! inst.error)
11079 inst.error = BAD_ARGS;
11080 return;
11081 }
11082
11083 if (inst.reloc.type != BFD_RELOC_NONE)
11084 {
11085 /* This really doesn't seem worth it. */
11086 inst.reloc.type = BFD_RELOC_NONE;
f03698e6 11087 inst.error = _("expression too complex");
b99bd4ef
NC
11088 return;
11089 }
11090
11091 if (range & ~0xff)
11092 {
11093 inst.error = _("only lo-regs valid in load/store multiple");
11094 return;
11095 }
11096
11097 inst.instruction |= (Rb << 8) | range;
11098 end_of_line (str);
11099}
11100
11101static void
11102do_t_ldr (str)
11103 char * str;
11104{
11105 thumb_load_store (str, THUMB_LOAD, THUMB_WORD);
11106}
11107
11108static void
11109do_t_ldrb (str)
11110 char * str;
11111{
11112 thumb_load_store (str, THUMB_LOAD, THUMB_BYTE);
11113}
11114
11115static void
11116do_t_ldrh (str)
11117 char * str;
11118{
11119 thumb_load_store (str, THUMB_LOAD, THUMB_HALFWORD);
11120}
11121
11122static void
11123do_t_lds (str)
11124 char * str;
11125{
11126 int Rd, Rb, Ro;
11127
11128 skip_whitespace (str);
11129
11130 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
11131 || skip_past_comma (&str) == FAIL
11132 || *str++ != '['
11133 || (Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL
11134 || skip_past_comma (&str) == FAIL
11135 || (Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL
11136 || *str++ != ']')
11137 {
11138 if (! inst.error)
f03698e6 11139 inst.error = _("syntax: ldrs[b] Rd, [Rb, Ro]");
b99bd4ef
NC
11140 return;
11141 }
11142
11143 inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
11144 end_of_line (str);
11145}
11146
11147static void
11148do_t_lsl (str)
11149 char * str;
11150{
11151 thumb_shift (str, THUMB_LSL);
11152}
11153
11154static void
11155do_t_lsr (str)
11156 char * str;
11157{
11158 thumb_shift (str, THUMB_LSR);
11159}
11160
11161static void
11162do_t_mov (str)
11163 char * str;
11164{
11165 thumb_mov_compare (str, THUMB_MOVE);
11166}
11167
11168static void
11169do_t_push_pop (str)
11170 char * str;
11171{
11172 long range;
11173
11174 skip_whitespace (str);
11175
11176 if ((range = reg_list (&str)) == FAIL)
11177 {
11178 if (! inst.error)
11179 inst.error = BAD_ARGS;
11180 return;
11181 }
11182
11183 if (inst.reloc.type != BFD_RELOC_NONE)
11184 {
11185 /* This really doesn't seem worth it. */
11186 inst.reloc.type = BFD_RELOC_NONE;
f03698e6 11187 inst.error = _("expression too complex");
b99bd4ef
NC
11188 return;
11189 }
11190
11191 if (range & ~0xff)
11192 {
11193 if ((inst.instruction == T_OPCODE_PUSH
11194 && (range & ~0xff) == 1 << REG_LR)
11195 || (inst.instruction == T_OPCODE_POP
11196 && (range & ~0xff) == 1 << REG_PC))
11197 {
11198 inst.instruction |= THUMB_PP_PC_LR;
11199 range &= 0xff;
11200 }
11201 else
11202 {
11203 inst.error = _("invalid register list to push/pop instruction");
11204 return;
11205 }
11206 }
11207
11208 inst.instruction |= range;
11209 end_of_line (str);
11210}
11211
11212static void
11213do_t_str (str)
11214 char * str;
11215{
11216 thumb_load_store (str, THUMB_STORE, THUMB_WORD);
11217}
11218
11219static void
11220do_t_strb (str)
11221 char * str;
11222{
11223 thumb_load_store (str, THUMB_STORE, THUMB_BYTE);
11224}
11225
11226static void
11227do_t_strh (str)
11228 char * str;
11229{
11230 thumb_load_store (str, THUMB_STORE, THUMB_HALFWORD);
11231}
11232
11233static void
11234do_t_sub (str)
11235 char * str;
11236{
11237 thumb_add_sub (str, 1);
11238}
11239
11240static void
11241do_t_swi (str)
11242 char * str;
11243{
11244 skip_whitespace (str);
11245
11246 if (my_get_expression (&inst.reloc.exp, &str))
11247 return;
11248
11249 inst.reloc.type = BFD_RELOC_ARM_SWI;
11250 end_of_line (str);
b99bd4ef
NC
11251}
11252
11253static void
11254do_t_adr (str)
11255 char * str;
11256{
11257 int reg;
11258
11259 /* This is a pseudo-op of the form "adr rd, label" to be converted
11260 into a relative address of the form "add rd, pc, #label-.-4". */
11261 skip_whitespace (str);
11262
11263 /* Store Rd in temporary location inside instruction. */
11264 if ((reg = reg_required_here (&str, 4)) == FAIL
11265 || (reg > 7) /* For Thumb reg must be r0..r7. */
11266 || skip_past_comma (&str) == FAIL
11267 || my_get_expression (&inst.reloc.exp, &str))
11268 {
11269 if (!inst.error)
11270 inst.error = BAD_ARGS;
11271 return;
11272 }
11273
11274 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
11275 inst.reloc.exp.X_add_number -= 4; /* PC relative adjust. */
11276 inst.reloc.pc_rel = 1;
11277 inst.instruction |= REG_PC; /* Rd is already placed into the instruction. */
11278
11279 end_of_line (str);
11280}
11281
11282static void
6c43fab6
RE
11283insert_reg (r, htab)
11284 const struct reg_entry *r;
11285 struct hash_control *htab;
b99bd4ef 11286{
6c43fab6 11287 int len = strlen (r->name) + 2;
b99bd4ef
NC
11288 char * buf = (char *) xmalloc (len);
11289 char * buf2 = (char *) xmalloc (len);
11290 int i = 0;
11291
11292#ifdef REGISTER_PREFIX
11293 buf[i++] = REGISTER_PREFIX;
11294#endif
11295
6c43fab6 11296 strcpy (buf + i, r->name);
b99bd4ef
NC
11297
11298 for (i = 0; buf[i]; i++)
3882b010 11299 buf2[i] = TOUPPER (buf[i]);
b99bd4ef
NC
11300
11301 buf2[i] = '\0';
11302
6c43fab6
RE
11303 hash_insert (htab, buf, (PTR) r);
11304 hash_insert (htab, buf2, (PTR) r);
b99bd4ef
NC
11305}
11306
11307static void
6c43fab6
RE
11308build_reg_hsh (map)
11309 struct reg_map *map;
11310{
11311 const struct reg_entry *r;
11312
11313 if ((map->htab = hash_new ()) == NULL)
f03698e6 11314 as_fatal (_("virtual memory exhausted"));
6c43fab6
RE
11315
11316 for (r = map->names; r->name != NULL; r++)
11317 insert_reg (r, map->htab);
11318}
11319
11320static void
11321insert_reg_alias (str, regnum, htab)
b99bd4ef
NC
11322 char *str;
11323 int regnum;
6c43fab6 11324 struct hash_control *htab;
b99bd4ef 11325{
0bbf2aa4
NC
11326 const char *error;
11327 struct reg_entry *new = xmalloc (sizeof (struct reg_entry));
11328 const char *name = xmalloc (strlen (str) + 1);
11329
11330 strcpy ((char *) name, str);
11331
b99bd4ef
NC
11332 new->name = name;
11333 new->number = regnum;
0bbf2aa4 11334 new->builtin = FALSE;
b99bd4ef 11335
0bbf2aa4
NC
11336 error = hash_insert (htab, name, (PTR) new);
11337 if (error)
11338 {
11339 as_bad (_("failed to create an alias for %s, reason: %s"),
11340 str, error);
11341 free ((char *) name);
11342 free (new);
11343 }
b99bd4ef
NC
11344}
11345
6c43fab6
RE
11346/* Look for the .req directive. This is of the form:
11347
0bbf2aa4 11348 new_register_name .req existing_register_name
6c43fab6
RE
11349
11350 If we find one, or if it looks sufficiently like one that we want to
11351 handle any error here, return non-zero. Otherwise return zero. */
11352static int
11353create_register_alias (newname, p)
11354 char *newname;
11355 char *p;
11356{
11357 char *q;
11358 char c;
11359
11360 q = p;
11361 skip_whitespace (q);
11362
11363 c = *p;
11364 *p = '\0';
11365
11366 if (*q && !strncmp (q, ".req ", 5))
11367 {
11368 char *copy_of_str;
11369 char *r;
11370
376eb240 11371#ifndef IGNORE_OPCODE_CASE
6c43fab6
RE
11372 newname = original_case_string;
11373#endif
11374 copy_of_str = newname;
11375
11376 q += 4;
11377 skip_whitespace (q);
11378
11379 for (r = q; *r != '\0'; r++)
11380 if (*r == ' ')
11381 break;
11382
11383 if (r != q)
11384 {
11385 enum arm_reg_type new_type, old_type;
11386 int old_regno;
11387 char d = *r;
11388
11389 *r = '\0';
11390 old_type = arm_reg_parse_any (q);
11391 *r = d;
11392
11393 new_type = arm_reg_parse_any (newname);
11394
11395 if (new_type == REG_TYPE_MAX)
11396 {
11397 if (old_type != REG_TYPE_MAX)
11398 {
11399 old_regno = arm_reg_parse (&q, all_reg_maps[old_type].htab);
11400 insert_reg_alias (newname, old_regno,
11401 all_reg_maps[old_type].htab);
11402 }
11403 else
11404 as_warn (_("register '%s' does not exist\n"), q);
11405 }
11406 else if (old_type == REG_TYPE_MAX)
11407 {
11408 as_warn (_("ignoring redefinition of register alias '%s' to non-existant register '%s'"),
11409 copy_of_str, q);
11410 }
11411 else
11412 {
11413 /* Do not warn about redefinitions to the same alias. */
11414 if (new_type != old_type
11415 || (arm_reg_parse (&q, all_reg_maps[old_type].htab)
11416 != arm_reg_parse (&q, all_reg_maps[new_type].htab)))
11417 as_warn (_("ignoring redefinition of register alias '%s'"),
11418 copy_of_str);
11419
11420 }
11421 }
11422 else
11423 as_warn (_("ignoring incomplete .req pseuso op"));
11424
11425 *p = c;
11426 return 1;
11427 }
0bbf2aa4 11428
6c43fab6
RE
11429 *p = c;
11430 return 0;
11431}
cc8a6dd0 11432
b99bd4ef
NC
11433static void
11434set_constant_flonums ()
11435{
11436 int i;
11437
11438 for (i = 0; i < NUM_FLOAT_VALS; i++)
11439 if (atof_ieee ((char *) fp_const[i], 'x', fp_values[i]) == NULL)
11440 abort ();
11441}
11442
90e4755a
RE
11443/* Iterate over the base tables to create the instruction patterns. */
11444static void
11445build_arm_ops_hsh ()
11446{
11447 unsigned int i;
11448 unsigned int j;
11449 static struct obstack insn_obstack;
11450
11451 obstack_begin (&insn_obstack, 4000);
11452
11453 for (i = 0; i < sizeof (insns) / sizeof (struct asm_opcode); i++)
11454 {
6c43fab6 11455 const struct asm_opcode *insn = insns + i;
90e4755a
RE
11456
11457 if (insn->cond_offset != 0)
11458 {
11459 /* Insn supports conditional execution. Build the varaints
11460 and insert them in the hash table. */
11461 for (j = 0; j < sizeof (conds) / sizeof (struct asm_cond); j++)
11462 {
11463 unsigned len = strlen (insn->template);
11464 struct asm_opcode *new;
11465 char *template;
11466
11467 new = obstack_alloc (&insn_obstack, sizeof (struct asm_opcode));
11468 /* All condition codes are two characters. */
11469 template = obstack_alloc (&insn_obstack, len + 3);
11470
11471 strncpy (template, insn->template, insn->cond_offset);
11472 strcpy (template + insn->cond_offset, conds[j].template);
11473 if (len > insn->cond_offset)
11474 strcpy (template + insn->cond_offset + 2,
11475 insn->template + insn->cond_offset);
11476 new->template = template;
11477 new->cond_offset = 0;
11478 new->variant = insn->variant;
11479 new->parms = insn->parms;
11480 new->value = (insn->value & ~COND_MASK) | conds[j].value;
11481
11482 hash_insert (arm_ops_hsh, new->template, (PTR) new);
11483 }
11484 }
11485 /* Finally, insert the unconditional insn in the table directly;
11486 no need to build a copy. */
11487 hash_insert (arm_ops_hsh, insn->template, (PTR) insn);
11488 }
11489}
11490
0bbf2aa4 11491#if 0 /* Suppressed - for now. */
5a6c6817
NC
11492#if defined OBJ_ELF || defined OBJ_COFF
11493
11494#ifdef OBJ_ELF
11495#define arm_Note Elf_External_Note
11496#else
11497typedef struct
11498{
11499 unsigned char namesz[4]; /* Size of entry's owner string. */
11500 unsigned char descsz[4]; /* Size of the note descriptor. */
11501 unsigned char type[4]; /* Interpretation of the descriptor. */
11502 char name[1]; /* Start of the name+desc data. */
11503} arm_Note;
11504#endif
11505
11506/* The description is kept to a fix sized in order to make updating
11507 it and merging it easier. */
11508#define ARM_NOTE_DESCRIPTION_LENGTH 8
11509
11510static void
11511arm_add_note (name, description, type)
11512 const char * name;
11513 const char * description;
11514 unsigned int type;
11515{
11516 arm_Note note ATTRIBUTE_UNUSED;
11517 char * p;
11518 unsigned int name_len;
11519
11520 name_len = (strlen (name) + 1 + 3) & ~3;
11521
11522 p = frag_more (sizeof (note.namesz));
11523 md_number_to_chars (p, (valueT) name_len, sizeof (note.namesz));
11524
11525 p = frag_more (sizeof (note.descsz));
11526 md_number_to_chars (p, (valueT) ARM_NOTE_DESCRIPTION_LENGTH, sizeof (note.descsz));
11527
11528 p = frag_more (sizeof (note.type));
11529 md_number_to_chars (p, (valueT) type, sizeof (note.type));
11530
11531 p = frag_more (name_len);
11532 strcpy (p, name);
11533
11534 p = frag_more (ARM_NOTE_DESCRIPTION_LENGTH);
11535 strncpy (p, description, ARM_NOTE_DESCRIPTION_LENGTH);
11536 frag_align (2, 0, 0);
11537}
11538#endif
0bbf2aa4 11539#endif
5a6c6817 11540
b99bd4ef
NC
11541void
11542md_begin ()
11543{
11544 unsigned mach;
11545 unsigned int i;
11546
11547 if ( (arm_ops_hsh = hash_new ()) == NULL
11548 || (arm_tops_hsh = hash_new ()) == NULL
11549 || (arm_cond_hsh = hash_new ()) == NULL
11550 || (arm_shift_hsh = hash_new ()) == NULL
b99bd4ef 11551 || (arm_psr_hsh = hash_new ()) == NULL)
f03698e6 11552 as_fatal (_("virtual memory exhausted"));
b99bd4ef 11553
90e4755a 11554 build_arm_ops_hsh ();
b99bd4ef
NC
11555 for (i = 0; i < sizeof (tinsns) / sizeof (struct thumb_opcode); i++)
11556 hash_insert (arm_tops_hsh, tinsns[i].template, (PTR) (tinsns + i));
11557 for (i = 0; i < sizeof (conds) / sizeof (struct asm_cond); i++)
11558 hash_insert (arm_cond_hsh, conds[i].template, (PTR) (conds + i));
11559 for (i = 0; i < sizeof (shift_names) / sizeof (struct asm_shift_name); i++)
11560 hash_insert (arm_shift_hsh, shift_names[i].name, (PTR) (shift_names + i));
11561 for (i = 0; i < sizeof (psrs) / sizeof (struct asm_psr); i++)
11562 hash_insert (arm_psr_hsh, psrs[i].template, (PTR) (psrs + i));
11563
6c43fab6
RE
11564 for (i = (int) REG_TYPE_FIRST; i < (int) REG_TYPE_MAX; i++)
11565 build_reg_hsh (all_reg_maps + i);
b99bd4ef
NC
11566
11567 set_constant_flonums ();
11568
03b1477f
RE
11569 /* Set the cpu variant based on the command-line options. We prefer
11570 -mcpu= over -march= if both are set (as for GCC); and we prefer
11571 -mfpu= over any other way of setting the floating point unit.
11572 Use of legacy options with new options are faulted. */
11573 if (legacy_cpu != -1)
11574 {
11575 if (mcpu_cpu_opt != -1 || march_cpu_opt != -1)
11576 as_bad (_("use of old and new-style options to set CPU type"));
11577
11578 mcpu_cpu_opt = legacy_cpu;
11579 }
11580 else if (mcpu_cpu_opt == -1)
11581 mcpu_cpu_opt = march_cpu_opt;
11582
11583 if (legacy_fpu != -1)
11584 {
11585 if (mfpu_opt != -1)
11586 as_bad (_("use of old and new-style options to set FPU type"));
11587
11588 mfpu_opt = legacy_fpu;
11589 }
11590 else if (mfpu_opt == -1)
11591 {
39c2da32
RE
11592#if !(defined (TE_LINUX) || defined (TE_NetBSD))
11593 /* Some environments specify a default FPU. If they don't, infer it
11594 from the processor. */
03b1477f
RE
11595 if (mcpu_fpu_opt != -1)
11596 mfpu_opt = mcpu_fpu_opt;
11597 else
11598 mfpu_opt = march_fpu_opt;
39c2da32
RE
11599#else
11600 mfpu_opt = FPU_DEFAULT;
11601#endif
03b1477f
RE
11602 }
11603
11604 if (mfpu_opt == -1)
11605 {
11606 if (mcpu_cpu_opt == -1)
11607 mfpu_opt = FPU_DEFAULT;
11608 else if (mcpu_cpu_opt & ARM_EXT_V5)
11609 mfpu_opt = FPU_ARCH_VFP_V2;
11610 else
11611 mfpu_opt = FPU_ARCH_FPA;
11612 }
11613
11614 if (mcpu_cpu_opt == -1)
11615 mcpu_cpu_opt = CPU_DEFAULT;
11616
11617 cpu_variant = mcpu_cpu_opt | mfpu_opt;
11618
b99bd4ef 11619 {
7cc69913
NC
11620 unsigned int flags = 0;
11621
11622#if defined OBJ_ELF
11623 flags = meabi_flags;
d507cf36
PB
11624
11625 switch (meabi_flags)
33a392fb 11626 {
d507cf36 11627 case EF_ARM_EABI_UNKNOWN:
7cc69913
NC
11628#endif
11629#if defined OBJ_COFF || defined OBJ_ELF
d507cf36
PB
11630 /* Set the flags in the private structure. */
11631 if (uses_apcs_26) flags |= F_APCS26;
11632 if (support_interwork) flags |= F_INTERWORK;
11633 if (uses_apcs_float) flags |= F_APCS_FLOAT;
11634 if (pic_code) flags |= F_PIC;
11635 if ((cpu_variant & FPU_ANY) == FPU_NONE
11636 || (cpu_variant & FPU_ANY) == FPU_ARCH_VFP) /* VFP layout only. */
7cc69913
NC
11637 flags |= F_SOFT_FLOAT;
11638
d507cf36
PB
11639 switch (mfloat_abi_opt)
11640 {
11641 case ARM_FLOAT_ABI_SOFT:
11642 case ARM_FLOAT_ABI_SOFTFP:
11643 flags |= F_SOFT_FLOAT;
11644 break;
33a392fb 11645
d507cf36
PB
11646 case ARM_FLOAT_ABI_HARD:
11647 if (flags & F_SOFT_FLOAT)
11648 as_bad (_("hard-float conflicts with specified fpu"));
11649 break;
11650 }
03b1477f 11651
7cc69913
NC
11652 /* Using VFP conventions (even if soft-float). */
11653 if (cpu_variant & FPU_VFP_EXT_NONE)
11654 flags |= F_VFP_FLOAT;
11655#endif
fde78edd 11656#if defined OBJ_ELF
d507cf36
PB
11657 if (cpu_variant & FPU_ARCH_MAVERICK)
11658 flags |= EF_ARM_MAVERICK_FLOAT;
d507cf36
PB
11659 break;
11660
11661 case EF_ARM_EABI_VER3:
11662 /* No additional flags to set. */
11663 break;
11664
11665 default:
11666 abort ();
11667 }
7cc69913
NC
11668#endif
11669#if defined OBJ_COFF || defined OBJ_ELF
b99bd4ef
NC
11670 bfd_set_private_flags (stdoutput, flags);
11671
11672 /* We have run out flags in the COFF header to encode the
11673 status of ATPCS support, so instead we create a dummy,
11674 empty, debug section called .arm.atpcs. */
11675 if (atpcs)
11676 {
11677 asection * sec;
11678
11679 sec = bfd_make_section (stdoutput, ".arm.atpcs");
11680
11681 if (sec != NULL)
11682 {
11683 bfd_set_section_flags
11684 (stdoutput, sec, SEC_READONLY | SEC_DEBUGGING /* | SEC_HAS_CONTENTS */);
11685 bfd_set_section_size (stdoutput, sec, 0);
11686 bfd_set_section_contents (stdoutput, sec, NULL, 0, 0);
11687 }
11688 }
b99bd4ef 11689#endif
7cc69913 11690 }
b99bd4ef
NC
11691
11692 /* Record the CPU type as well. */
11693 switch (cpu_variant & ARM_CPU_MASK)
11694 {
11695 case ARM_2:
11696 mach = bfd_mach_arm_2;
11697 break;
11698
11699 case ARM_3: /* Also ARM_250. */
11700 mach = bfd_mach_arm_2a;
11701 break;
11702
b89dddec
RE
11703 case ARM_6: /* Also ARM_7. */
11704 mach = bfd_mach_arm_3;
11705 break;
11706
b99bd4ef 11707 default:
5a6c6817 11708 mach = bfd_mach_arm_unknown;
b99bd4ef 11709 break;
b99bd4ef
NC
11710 }
11711
11712 /* Catch special cases. */
e16bb312
NC
11713 if (cpu_variant & ARM_CEXT_IWMMXT)
11714 mach = bfd_mach_arm_iWMMXt;
11715 else if (cpu_variant & ARM_CEXT_XSCALE)
b99bd4ef 11716 mach = bfd_mach_arm_XScale;
fde78edd
NC
11717 else if (cpu_variant & ARM_CEXT_MAVERICK)
11718 mach = bfd_mach_arm_ep9312;
b99bd4ef
NC
11719 else if (cpu_variant & ARM_EXT_V5E)
11720 mach = bfd_mach_arm_5TE;
11721 else if (cpu_variant & ARM_EXT_V5)
11722 {
b89dddec 11723 if (cpu_variant & ARM_EXT_V4T)
b99bd4ef
NC
11724 mach = bfd_mach_arm_5T;
11725 else
11726 mach = bfd_mach_arm_5;
11727 }
b89dddec 11728 else if (cpu_variant & ARM_EXT_V4)
b99bd4ef 11729 {
b89dddec 11730 if (cpu_variant & ARM_EXT_V4T)
b99bd4ef
NC
11731 mach = bfd_mach_arm_4T;
11732 else
11733 mach = bfd_mach_arm_4;
11734 }
b89dddec 11735 else if (cpu_variant & ARM_EXT_V3M)
b99bd4ef
NC
11736 mach = bfd_mach_arm_3M;
11737
5a6c6817 11738#if 0 /* Suppressed - for now. */
e16bb312 11739#if defined (OBJ_ELF) || defined (OBJ_COFF)
5a6c6817
NC
11740
11741 /* Create a .note section to fully identify this arm binary. */
11742
11743#define NOTE_ARCH_STRING "arch: "
11744
11745#if defined OBJ_COFF && ! defined NT_VERSION
11746#define NT_VERSION 1
11747#define NT_ARCH 2
11748#endif
11749
e16bb312 11750 {
e16bb312
NC
11751 segT current_seg = now_seg;
11752 subsegT current_subseg = now_subseg;
11753 asection * arm_arch;
5a6c6817
NC
11754 const char * arch_string;
11755
e16bb312
NC
11756 arm_arch = bfd_make_section_old_way (stdoutput, ARM_NOTE_SECTION);
11757
11758#ifdef OBJ_COFF
11759 bfd_set_section_flags (stdoutput, arm_arch,
11760 SEC_DATA | SEC_ALLOC | SEC_LOAD | SEC_LINK_ONCE \
11761 | SEC_HAS_CONTENTS);
e41f12f3
DJ
11762#else
11763 bfd_set_section_flags (stdoutput, arm_arch,
11764 SEC_READONLY | SEC_HAS_CONTENTS);
e16bb312
NC
11765#endif
11766 arm_arch->output_section = arm_arch;
11767 subseg_set (arm_arch, 0);
e16bb312 11768
5a6c6817
NC
11769 switch (mach)
11770 {
11771 default:
11772 case bfd_mach_arm_unknown: arch_string = "unknown"; break;
11773 case bfd_mach_arm_2: arch_string = "armv2"; break;
11774 case bfd_mach_arm_2a: arch_string = "armv2a"; break;
11775 case bfd_mach_arm_3: arch_string = "armv3"; break;
11776 case bfd_mach_arm_3M: arch_string = "armv3M"; break;
11777 case bfd_mach_arm_4: arch_string = "armv4"; break;
11778 case bfd_mach_arm_4T: arch_string = "armv4t"; break;
11779 case bfd_mach_arm_5: arch_string = "armv5"; break;
11780 case bfd_mach_arm_5T: arch_string = "armv5t"; break;
11781 case bfd_mach_arm_5TE: arch_string = "armv5te"; break;
11782 case bfd_mach_arm_XScale: arch_string = "XScale"; break;
11783 case bfd_mach_arm_ep9312: arch_string = "ep9312"; break;
11784 case bfd_mach_arm_iWMMXt: arch_string = "iWMMXt"; break;
11785 }
11786
11787 arm_add_note (NOTE_ARCH_STRING, arch_string, NT_ARCH);
e16bb312
NC
11788
11789 subseg_set (current_seg, current_subseg);
11790 }
11791#endif
5a6c6817
NC
11792#endif /* Suppressed code. */
11793
b99bd4ef
NC
11794 bfd_set_arch_mach (stdoutput, TARGET_ARCH, mach);
11795}
11796
11797/* Turn an integer of n bytes (in val) into a stream of bytes appropriate
11798 for use in the a.out file, and stores them in the array pointed to by buf.
11799 This knows about the endian-ness of the target machine and does
11800 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
11801 2 (short) and 4 (long) Floating numbers are put out as a series of
11802 LITTLENUMS (shorts, here at least). */
11803
11804void
11805md_number_to_chars (buf, val, n)
11806 char * buf;
11807 valueT val;
11808 int n;
11809{
11810 if (target_big_endian)
11811 number_to_chars_bigendian (buf, val, n);
11812 else
11813 number_to_chars_littleendian (buf, val, n);
11814}
11815
11816static valueT
11817md_chars_to_number (buf, n)
11818 char * buf;
11819 int n;
11820{
11821 valueT result = 0;
11822 unsigned char * where = (unsigned char *) buf;
11823
11824 if (target_big_endian)
11825 {
11826 while (n--)
11827 {
11828 result <<= 8;
11829 result |= (*where++ & 255);
11830 }
11831 }
11832 else
11833 {
11834 while (n--)
11835 {
11836 result <<= 8;
11837 result |= (where[n] & 255);
11838 }
11839 }
11840
11841 return result;
11842}
11843
11844/* Turn a string in input_line_pointer into a floating point constant
11845 of type TYPE, and store the appropriate bytes in *LITP. The number
11846 of LITTLENUMS emitted is stored in *SIZEP. An error message is
11847 returned, or NULL on OK.
11848
11849 Note that fp constants aren't represent in the normal way on the ARM.
11850 In big endian mode, things are as expected. However, in little endian
11851 mode fp constants are big-endian word-wise, and little-endian byte-wise
11852 within the words. For example, (double) 1.1 in big endian mode is
11853 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
11854 the byte sequence 99 99 f1 3f 9a 99 99 99.
11855
11856 ??? The format of 12 byte floats is uncertain according to gcc's arm.h. */
11857
11858char *
11859md_atof (type, litP, sizeP)
11860 char type;
11861 char * litP;
11862 int * sizeP;
11863{
11864 int prec;
11865 LITTLENUM_TYPE words[MAX_LITTLENUMS];
11866 char *t;
11867 int i;
11868
11869 switch (type)
11870 {
11871 case 'f':
11872 case 'F':
11873 case 's':
11874 case 'S':
11875 prec = 2;
11876 break;
11877
11878 case 'd':
11879 case 'D':
11880 case 'r':
11881 case 'R':
11882 prec = 4;
11883 break;
11884
11885 case 'x':
11886 case 'X':
11887 prec = 6;
11888 break;
11889
11890 case 'p':
11891 case 'P':
11892 prec = 6;
11893 break;
11894
11895 default:
11896 *sizeP = 0;
f03698e6 11897 return _("bad call to MD_ATOF()");
b99bd4ef
NC
11898 }
11899
11900 t = atof_ieee (input_line_pointer, type, words);
11901 if (t)
11902 input_line_pointer = t;
11903 *sizeP = prec * 2;
11904
11905 if (target_big_endian)
11906 {
11907 for (i = 0; i < prec; i++)
11908 {
11909 md_number_to_chars (litP, (valueT) words[i], 2);
11910 litP += 2;
11911 }
11912 }
11913 else
11914 {
bfae80f2
RE
11915 if (cpu_variant & FPU_ARCH_VFP)
11916 for (i = prec - 1; i >= 0; i--)
11917 {
11918 md_number_to_chars (litP, (valueT) words[i], 2);
11919 litP += 2;
11920 }
11921 else
11922 /* For a 4 byte float the order of elements in `words' is 1 0.
11923 For an 8 byte float the order is 1 0 3 2. */
11924 for (i = 0; i < prec; i += 2)
11925 {
11926 md_number_to_chars (litP, (valueT) words[i + 1], 2);
11927 md_number_to_chars (litP + 2, (valueT) words[i], 2);
11928 litP += 4;
11929 }
b99bd4ef
NC
11930 }
11931
11932 return 0;
11933}
11934
11935/* The knowledge of the PC's pipeline offset is built into the insns
11936 themselves. */
11937
11938long
11939md_pcrel_from (fixP)
11940 fixS * fixP;
11941{
11942 if (fixP->fx_addsy
11943 && S_GET_SEGMENT (fixP->fx_addsy) == undefined_section
11944 && fixP->fx_subsy == NULL)
11945 return 0;
11946
11947 if (fixP->fx_pcrel && (fixP->fx_r_type == BFD_RELOC_ARM_THUMB_ADD))
11948 {
11949 /* PC relative addressing on the Thumb is slightly odd
11950 as the bottom two bits of the PC are forced to zero
11951 for the calculation. */
11952 return (fixP->fx_where + fixP->fx_frag->fr_address) & ~3;
11953 }
11954
11955#ifdef TE_WINCE
2d2255b5
KH
11956 /* The pattern was adjusted to accommodate CE's off-by-one fixups,
11957 so we un-adjust here to compensate for the accommodation. */
b99bd4ef
NC
11958 return fixP->fx_where + fixP->fx_frag->fr_address + 8;
11959#else
11960 return fixP->fx_where + fixP->fx_frag->fr_address;
11961#endif
11962}
11963
11964/* Round up a section size to the appropriate boundary. */
11965
11966valueT
11967md_section_align (segment, size)
11968 segT segment ATTRIBUTE_UNUSED;
11969 valueT size;
11970{
11971#ifdef OBJ_ELF
11972 return size;
11973#else
11974 /* Round all sects to multiple of 4. */
11975 return (size + 3) & ~3;
11976#endif
11977}
11978
11979/* Under ELF we need to default _GLOBAL_OFFSET_TABLE.
11980 Otherwise we have no need to default values of symbols. */
11981
11982symbolS *
11983md_undefined_symbol (name)
11984 char * name ATTRIBUTE_UNUSED;
11985{
11986#ifdef OBJ_ELF
11987 if (name[0] == '_' && name[1] == 'G'
11988 && streq (name, GLOBAL_OFFSET_TABLE_NAME))
11989 {
11990 if (!GOT_symbol)
11991 {
11992 if (symbol_find (name))
11993 as_bad ("GOT already in the symbol table");
11994
11995 GOT_symbol = symbol_new (name, undefined_section,
11996 (valueT) 0, & zero_address_frag);
11997 }
11998
11999 return GOT_symbol;
12000 }
12001#endif
12002
12003 return 0;
12004}
12005
12006/* arm_reg_parse () := if it looks like a register, return its token and
12007 advance the pointer. */
12008
12009static int
6c43fab6 12010arm_reg_parse (ccp, htab)
b99bd4ef 12011 register char ** ccp;
6c43fab6 12012 struct hash_control *htab;
b99bd4ef
NC
12013{
12014 char * start = * ccp;
12015 char c;
12016 char * p;
12017 struct reg_entry * reg;
12018
12019#ifdef REGISTER_PREFIX
12020 if (*start != REGISTER_PREFIX)
12021 return FAIL;
12022 p = start + 1;
12023#else
12024 p = start;
12025#ifdef OPTIONAL_REGISTER_PREFIX
12026 if (*p == OPTIONAL_REGISTER_PREFIX)
12027 p++, start++;
12028#endif
12029#endif
3882b010 12030 if (!ISALPHA (*p) || !is_name_beginner (*p))
b99bd4ef
NC
12031 return FAIL;
12032
12033 c = *p++;
3882b010 12034 while (ISALPHA (c) || ISDIGIT (c) || c == '_')
b99bd4ef
NC
12035 c = *p++;
12036
12037 *--p = 0;
6c43fab6 12038 reg = (struct reg_entry *) hash_find (htab, start);
b99bd4ef
NC
12039 *p = c;
12040
12041 if (reg)
12042 {
12043 *ccp = p;
12044 return reg->number;
12045 }
12046
12047 return FAIL;
12048}
12049
6c43fab6
RE
12050/* Search for the following register name in each of the possible reg name
12051 tables. Return the classification if found, or REG_TYPE_MAX if not
12052 present. */
12053static enum arm_reg_type
12054arm_reg_parse_any (cp)
12055 char *cp;
12056{
12057 int i;
12058
12059 for (i = (int) REG_TYPE_FIRST; i < (int) REG_TYPE_MAX; i++)
12060 if (arm_reg_parse (&cp, all_reg_maps[i].htab) != FAIL)
12061 return (enum arm_reg_type) i;
12062
12063 return REG_TYPE_MAX;
12064}
12065
94f592af
NC
12066void
12067md_apply_fix3 (fixP, valP, seg)
b99bd4ef 12068 fixS * fixP;
94f592af 12069 valueT * valP;
b99bd4ef
NC
12070 segT seg;
12071{
94f592af 12072 offsetT value = * valP;
b99bd4ef
NC
12073 offsetT newval;
12074 unsigned int newimm;
12075 unsigned long temp;
12076 int sign;
12077 char * buf = fixP->fx_where + fixP->fx_frag->fr_literal;
12078 arm_fix_data * arm_data = (arm_fix_data *) fixP->tc_fix_data;
12079
12080 assert (fixP->fx_r_type < BFD_RELOC_UNUSED);
12081
12082 /* Note whether this will delete the relocation. */
12083#if 0
12084 /* Patch from REarnshaw to JDavis (disabled for the moment, since it
12085 doesn't work fully.) */
12086 if ((fixP->fx_addsy == 0 || symbol_constant_p (fixP->fx_addsy))
12087 && !fixP->fx_pcrel)
12088#else
12089 if (fixP->fx_addsy == 0 && !fixP->fx_pcrel)
12090#endif
12091 fixP->fx_done = 1;
12092
12093 /* If this symbol is in a different section then we need to leave it for
12094 the linker to deal with. Unfortunately, md_pcrel_from can't tell,
12095 so we have to undo it's effects here. */
12096 if (fixP->fx_pcrel)
12097 {
12098 if (fixP->fx_addsy != NULL
12099 && S_IS_DEFINED (fixP->fx_addsy)
12100 && S_GET_SEGMENT (fixP->fx_addsy) != seg)
12101 {
12102 if (target_oabi
12103 && (fixP->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH
12104 || fixP->fx_r_type == BFD_RELOC_ARM_PCREL_BLX
12105 ))
12106 value = 0;
12107 else
12108 value += md_pcrel_from (fixP);
12109 }
12110 }
12111
12112 /* Remember value for emit_reloc. */
12113 fixP->fx_addnumber = value;
12114
12115 switch (fixP->fx_r_type)
12116 {
12117 case BFD_RELOC_ARM_IMMEDIATE:
310ea308
NC
12118 /* We claim that this fixup has been processed here,
12119 even if in fact we generate an error because we do
12120 not have a reloc for it, so tc_gen_reloc will reject it. */
12121 fixP->fx_done = 1;
12122
12123 if (fixP->fx_addsy
12124 && ! S_IS_DEFINED (fixP->fx_addsy))
12125 {
12126 as_bad_where (fixP->fx_file, fixP->fx_line,
12127 _("undefined symbol %s used as an immediate value"),
12128 S_GET_NAME (fixP->fx_addsy));
12129 break;
12130 }
12131
b99bd4ef
NC
12132 newimm = validate_immediate (value);
12133 temp = md_chars_to_number (buf, INSN_SIZE);
12134
12135 /* If the instruction will fail, see if we can fix things up by
12136 changing the opcode. */
12137 if (newimm == (unsigned int) FAIL
12138 && (newimm = negate_data_op (&temp, value)) == (unsigned int) FAIL)
12139 {
12140 as_bad_where (fixP->fx_file, fixP->fx_line,
12141 _("invalid constant (%lx) after fixup"),
12142 (unsigned long) value);
12143 break;
12144 }
12145
12146 newimm |= (temp & 0xfffff000);
12147 md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
12148 break;
12149
12150 case BFD_RELOC_ARM_ADRL_IMMEDIATE:
12151 {
12152 unsigned int highpart = 0;
12153 unsigned int newinsn = 0xe1a00000; /* nop. */
6189168b 12154
b99bd4ef
NC
12155 newimm = validate_immediate (value);
12156 temp = md_chars_to_number (buf, INSN_SIZE);
12157
12158 /* If the instruction will fail, see if we can fix things up by
12159 changing the opcode. */
12160 if (newimm == (unsigned int) FAIL
12161 && (newimm = negate_data_op (& temp, value)) == (unsigned int) FAIL)
12162 {
12163 /* No ? OK - try using two ADD instructions to generate
12164 the value. */
12165 newimm = validate_immediate_twopart (value, & highpart);
12166
12167 /* Yes - then make sure that the second instruction is
12168 also an add. */
12169 if (newimm != (unsigned int) FAIL)
12170 newinsn = temp;
12171 /* Still No ? Try using a negated value. */
12172 else if ((newimm = validate_immediate_twopart (- value, & highpart)) != (unsigned int) FAIL)
12173 temp = newinsn = (temp & OPCODE_MASK) | OPCODE_SUB << DATA_OP_SHIFT;
12174 /* Otherwise - give up. */
12175 else
12176 {
12177 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12178 _("unable to compute ADRL instructions for PC offset of 0x%lx"),
08df2379 12179 (long) value);
b99bd4ef
NC
12180 break;
12181 }
12182
12183 /* Replace the first operand in the 2nd instruction (which
12184 is the PC) with the destination register. We have
12185 already added in the PC in the first instruction and we
12186 do not want to do it again. */
12187 newinsn &= ~ 0xf0000;
12188 newinsn |= ((newinsn & 0x0f000) << 4);
12189 }
12190
12191 newimm |= (temp & 0xfffff000);
12192 md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
12193
12194 highpart |= (newinsn & 0xfffff000);
12195 md_number_to_chars (buf + INSN_SIZE, (valueT) highpart, INSN_SIZE);
12196 }
12197 break;
12198
12199 case BFD_RELOC_ARM_OFFSET_IMM:
12200 sign = value >= 0;
12201
12202 if (value < 0)
12203 value = - value;
12204
12205 if (validate_offset_imm (value, 0) == FAIL)
12206 {
12207 as_bad_where (fixP->fx_file, fixP->fx_line,
12208 _("bad immediate value for offset (%ld)"),
12209 (long) value);
12210 break;
12211 }
12212
12213 newval = md_chars_to_number (buf, INSN_SIZE);
12214 newval &= 0xff7ff000;
12215 newval |= value | (sign ? INDEX_UP : 0);
12216 md_number_to_chars (buf, newval, INSN_SIZE);
12217 break;
12218
12219 case BFD_RELOC_ARM_OFFSET_IMM8:
12220 case BFD_RELOC_ARM_HWLITERAL:
12221 sign = value >= 0;
12222
12223 if (value < 0)
12224 value = - value;
12225
12226 if (validate_offset_imm (value, 1) == FAIL)
12227 {
12228 if (fixP->fx_r_type == BFD_RELOC_ARM_HWLITERAL)
12229 as_bad_where (fixP->fx_file, fixP->fx_line,
12230 _("invalid literal constant: pool needs to be closer"));
12231 else
12232 as_bad (_("bad immediate value for half-word offset (%ld)"),
12233 (long) value);
12234 break;
12235 }
12236
12237 newval = md_chars_to_number (buf, INSN_SIZE);
12238 newval &= 0xff7ff0f0;
12239 newval |= ((value >> 4) << 8) | (value & 0xf) | (sign ? INDEX_UP : 0);
12240 md_number_to_chars (buf, newval, INSN_SIZE);
12241 break;
12242
12243 case BFD_RELOC_ARM_LITERAL:
12244 sign = value >= 0;
12245
12246 if (value < 0)
12247 value = - value;
12248
12249 if (validate_offset_imm (value, 0) == FAIL)
12250 {
12251 as_bad_where (fixP->fx_file, fixP->fx_line,
12252 _("invalid literal constant: pool needs to be closer"));
12253 break;
12254 }
12255
12256 newval = md_chars_to_number (buf, INSN_SIZE);
12257 newval &= 0xff7ff000;
12258 newval |= value | (sign ? INDEX_UP : 0);
12259 md_number_to_chars (buf, newval, INSN_SIZE);
12260 break;
12261
12262 case BFD_RELOC_ARM_SHIFT_IMM:
12263 newval = md_chars_to_number (buf, INSN_SIZE);
12264 if (((unsigned long) value) > 32
12265 || (value == 32
12266 && (((newval & 0x60) == 0) || (newval & 0x60) == 0x60)))
12267 {
12268 as_bad_where (fixP->fx_file, fixP->fx_line,
12269 _("shift expression is too large"));
12270 break;
12271 }
12272
12273 if (value == 0)
12274 /* Shifts of zero must be done as lsl. */
12275 newval &= ~0x60;
12276 else if (value == 32)
12277 value = 0;
12278 newval &= 0xfffff07f;
12279 newval |= (value & 0x1f) << 7;
12280 md_number_to_chars (buf, newval, INSN_SIZE);
12281 break;
12282
12283 case BFD_RELOC_ARM_SWI:
12284 if (arm_data->thumb_mode)
12285 {
12286 if (((unsigned long) value) > 0xff)
12287 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12288 _("invalid swi expression"));
b99bd4ef
NC
12289 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xff00;
12290 newval |= value;
12291 md_number_to_chars (buf, newval, THUMB_SIZE);
12292 }
12293 else
12294 {
12295 if (((unsigned long) value) > 0x00ffffff)
12296 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12297 _("invalid swi expression"));
b99bd4ef
NC
12298 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff000000;
12299 newval |= value;
12300 md_number_to_chars (buf, newval, INSN_SIZE);
12301 }
12302 break;
12303
12304 case BFD_RELOC_ARM_MULTI:
12305 if (((unsigned long) value) > 0xffff)
12306 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12307 _("invalid expression in load/store multiple"));
b99bd4ef
NC
12308 newval = value | md_chars_to_number (buf, INSN_SIZE);
12309 md_number_to_chars (buf, newval, INSN_SIZE);
12310 break;
12311
12312 case BFD_RELOC_ARM_PCREL_BRANCH:
12313 newval = md_chars_to_number (buf, INSN_SIZE);
12314
12315 /* Sign-extend a 24-bit number. */
12316#define SEXT24(x) ((((x) & 0xffffff) ^ (~ 0x7fffff)) + 0x800000)
12317
12318#ifdef OBJ_ELF
12319 if (! target_oabi)
12320 value = fixP->fx_offset;
12321#endif
12322
12323 /* We are going to store value (shifted right by two) in the
12324 instruction, in a 24 bit, signed field. Thus we need to check
12325 that none of the top 8 bits of the shifted value (top 7 bits of
12326 the unshifted, unsigned value) are set, or that they are all set. */
12327 if ((value & ~ ((offsetT) 0x1ffffff)) != 0
12328 && ((value & ~ ((offsetT) 0x1ffffff)) != ~ ((offsetT) 0x1ffffff)))
12329 {
12330#ifdef OBJ_ELF
12331 /* Normally we would be stuck at this point, since we cannot store
12332 the absolute address that is the destination of the branch in the
12333 24 bits of the branch instruction. If however, we happen to know
12334 that the destination of the branch is in the same section as the
2d2255b5 12335 branch instruction itself, then we can compute the relocation for
b99bd4ef
NC
12336 ourselves and not have to bother the linker with it.
12337
12338 FIXME: The tests for OBJ_ELF and ! target_oabi are only here
12339 because I have not worked out how to do this for OBJ_COFF or
12340 target_oabi. */
12341 if (! target_oabi
12342 && fixP->fx_addsy != NULL
12343 && S_IS_DEFINED (fixP->fx_addsy)
12344 && S_GET_SEGMENT (fixP->fx_addsy) == seg)
12345 {
12346 /* Get pc relative value to go into the branch. */
94f592af 12347 value = * valP;
b99bd4ef
NC
12348
12349 /* Permit a backward branch provided that enough bits
12350 are set. Allow a forwards branch, provided that
12351 enough bits are clear. */
12352 if ( (value & ~ ((offsetT) 0x1ffffff)) == ~ ((offsetT) 0x1ffffff)
12353 || (value & ~ ((offsetT) 0x1ffffff)) == 0)
12354 fixP->fx_done = 1;
12355 }
12356
12357 if (! fixP->fx_done)
12358#endif
12359 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12360 _("GAS can't handle same-section branch dest >= 0x04000000"));
b99bd4ef
NC
12361 }
12362
12363 value >>= 2;
12364 value += SEXT24 (newval);
12365
12366 if ( (value & ~ ((offsetT) 0xffffff)) != 0
12367 && ((value & ~ ((offsetT) 0xffffff)) != ~ ((offsetT) 0xffffff)))
12368 as_bad_where (fixP->fx_file, fixP->fx_line,
12369 _("out of range branch"));
12370
12371 newval = (value & 0x00ffffff) | (newval & 0xff000000);
12372 md_number_to_chars (buf, newval, INSN_SIZE);
12373 break;
12374
12375 case BFD_RELOC_ARM_PCREL_BLX:
12376 {
12377 offsetT hbit;
12378 newval = md_chars_to_number (buf, INSN_SIZE);
12379
12380#ifdef OBJ_ELF
12381 if (! target_oabi)
12382 value = fixP->fx_offset;
12383#endif
12384 hbit = (value >> 1) & 1;
12385 value = (value >> 2) & 0x00ffffff;
12386 value = (value + (newval & 0x00ffffff)) & 0x00ffffff;
12387 newval = value | (newval & 0xfe000000) | (hbit << 24);
12388 md_number_to_chars (buf, newval, INSN_SIZE);
12389 }
12390 break;
12391
12392 case BFD_RELOC_THUMB_PCREL_BRANCH9: /* Conditional branch. */
12393 newval = md_chars_to_number (buf, THUMB_SIZE);
12394 {
12395 addressT diff = (newval & 0xff) << 1;
12396 if (diff & 0x100)
12397 diff |= ~0xff;
12398
12399 value += diff;
12400 if ((value & ~0xff) && ((value & ~0xff) != ~0xff))
12401 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12402 _("branch out of range"));
b99bd4ef
NC
12403 newval = (newval & 0xff00) | ((value & 0x1ff) >> 1);
12404 }
12405 md_number_to_chars (buf, newval, THUMB_SIZE);
12406 break;
12407
12408 case BFD_RELOC_THUMB_PCREL_BRANCH12: /* Unconditional branch. */
12409 newval = md_chars_to_number (buf, THUMB_SIZE);
12410 {
12411 addressT diff = (newval & 0x7ff) << 1;
12412 if (diff & 0x800)
12413 diff |= ~0x7ff;
12414
12415 value += diff;
12416 if ((value & ~0x7ff) && ((value & ~0x7ff) != ~0x7ff))
12417 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12418 _("branch out of range"));
b99bd4ef
NC
12419 newval = (newval & 0xf800) | ((value & 0xfff) >> 1);
12420 }
12421 md_number_to_chars (buf, newval, THUMB_SIZE);
12422 break;
12423
12424 case BFD_RELOC_THUMB_PCREL_BLX:
12425 case BFD_RELOC_THUMB_PCREL_BRANCH23:
12426 {
12427 offsetT newval2;
12428 addressT diff;
12429
12430 newval = md_chars_to_number (buf, THUMB_SIZE);
12431 newval2 = md_chars_to_number (buf + THUMB_SIZE, THUMB_SIZE);
12432 diff = ((newval & 0x7ff) << 12) | ((newval2 & 0x7ff) << 1);
12433 if (diff & 0x400000)
12434 diff |= ~0x3fffff;
12435#ifdef OBJ_ELF
12436 value = fixP->fx_offset;
12437#endif
12438 value += diff;
c62e1cc3 12439
b99bd4ef
NC
12440 if ((value & ~0x3fffff) && ((value & ~0x3fffff) != ~0x3fffff))
12441 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12442 _("branch with link out of range"));
b99bd4ef
NC
12443
12444 newval = (newval & 0xf800) | ((value & 0x7fffff) >> 12);
12445 newval2 = (newval2 & 0xf800) | ((value & 0xfff) >> 1);
12446 if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX)
c62e1cc3
NC
12447 /* For a BLX instruction, make sure that the relocation is rounded up
12448 to a word boundary. This follows the semantics of the instruction
12449 which specifies that bit 1 of the target address will come from bit
12450 1 of the base address. */
12451 newval2 = (newval2 + 1) & ~ 1;
b99bd4ef
NC
12452 md_number_to_chars (buf, newval, THUMB_SIZE);
12453 md_number_to_chars (buf + THUMB_SIZE, newval2, THUMB_SIZE);
12454 }
12455 break;
12456
12457 case BFD_RELOC_8:
12458 if (fixP->fx_done || fixP->fx_pcrel)
12459 md_number_to_chars (buf, value, 1);
12460#ifdef OBJ_ELF
12461 else if (!target_oabi)
12462 {
12463 value = fixP->fx_offset;
12464 md_number_to_chars (buf, value, 1);
12465 }
12466#endif
12467 break;
12468
12469 case BFD_RELOC_16:
12470 if (fixP->fx_done || fixP->fx_pcrel)
12471 md_number_to_chars (buf, value, 2);
12472#ifdef OBJ_ELF
12473 else if (!target_oabi)
12474 {
12475 value = fixP->fx_offset;
12476 md_number_to_chars (buf, value, 2);
12477 }
12478#endif
12479 break;
12480
12481#ifdef OBJ_ELF
12482 case BFD_RELOC_ARM_GOT32:
12483 case BFD_RELOC_ARM_GOTOFF:
12484 md_number_to_chars (buf, 0, 4);
12485 break;
12486#endif
12487
12488 case BFD_RELOC_RVA:
12489 case BFD_RELOC_32:
db6579d4
PB
12490 case BFD_RELOC_ARM_RELABS32:
12491 case BFD_RELOC_ARM_ROSEGREL32:
12492 case BFD_RELOC_ARM_SBREL32:
b99bd4ef
NC
12493 if (fixP->fx_done || fixP->fx_pcrel)
12494 md_number_to_chars (buf, value, 4);
12495#ifdef OBJ_ELF
12496 else if (!target_oabi)
12497 {
12498 value = fixP->fx_offset;
12499 md_number_to_chars (buf, value, 4);
12500 }
12501#endif
12502 break;
12503
12504#ifdef OBJ_ELF
12505 case BFD_RELOC_ARM_PLT32:
12506 /* It appears the instruction is fully prepared at this point. */
12507 break;
12508#endif
12509
b99bd4ef
NC
12510 case BFD_RELOC_ARM_CP_OFF_IMM:
12511 sign = value >= 0;
12512 if (value < -1023 || value > 1023 || (value & 3))
12513 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12514 _("illegal value for co-processor offset"));
b99bd4ef
NC
12515 if (value < 0)
12516 value = -value;
12517 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
12518 newval |= (value >> 2) | (sign ? INDEX_UP : 0);
12519 md_number_to_chars (buf, newval, INSN_SIZE);
12520 break;
12521
e16bb312
NC
12522 case BFD_RELOC_ARM_CP_OFF_IMM_S2:
12523 sign = value >= 0;
12524 if (value < -255 || value > 255)
12525 as_bad_where (fixP->fx_file, fixP->fx_line,
12526 _("Illegal value for co-processor offset"));
12527 if (value < 0)
12528 value = -value;
12529 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
12530 newval |= value | (sign ? INDEX_UP : 0);
12531 md_number_to_chars (buf, newval , INSN_SIZE);
12532 break;
12533
b99bd4ef
NC
12534 case BFD_RELOC_ARM_THUMB_OFFSET:
12535 newval = md_chars_to_number (buf, THUMB_SIZE);
12536 /* Exactly what ranges, and where the offset is inserted depends
12537 on the type of instruction, we can establish this from the
12538 top 4 bits. */
12539 switch (newval >> 12)
12540 {
12541 case 4: /* PC load. */
12542 /* Thumb PC loads are somewhat odd, bit 1 of the PC is
12543 forced to zero for these loads, so we will need to round
12544 up the offset if the instruction address is not word
12545 aligned (since the final address produced must be, and
12546 we can only describe word-aligned immediate offsets). */
12547
12548 if ((fixP->fx_frag->fr_address + fixP->fx_where + value) & 3)
12549 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12550 _("invalid offset, target not word aligned (0x%08X)"),
b99bd4ef
NC
12551 (unsigned int) (fixP->fx_frag->fr_address
12552 + fixP->fx_where + value));
12553
12554 if ((value + 2) & ~0x3fe)
12555 as_bad_where (fixP->fx_file, fixP->fx_line,
08df2379
NC
12556 _("invalid offset, value too big (0x%08lX)"),
12557 (long) value);
b99bd4ef
NC
12558
12559 /* Round up, since pc will be rounded down. */
12560 newval |= (value + 2) >> 2;
12561 break;
12562
12563 case 9: /* SP load/store. */
12564 if (value & ~0x3fc)
12565 as_bad_where (fixP->fx_file, fixP->fx_line,
08df2379
NC
12566 _("invalid offset, value too big (0x%08lX)"),
12567 (long) value);
b99bd4ef
NC
12568 newval |= value >> 2;
12569 break;
12570
12571 case 6: /* Word load/store. */
12572 if (value & ~0x7c)
12573 as_bad_where (fixP->fx_file, fixP->fx_line,
08df2379
NC
12574 _("invalid offset, value too big (0x%08lX)"),
12575 (long) value);
b99bd4ef
NC
12576 newval |= value << 4; /* 6 - 2. */
12577 break;
12578
12579 case 7: /* Byte load/store. */
12580 if (value & ~0x1f)
12581 as_bad_where (fixP->fx_file, fixP->fx_line,
08df2379
NC
12582 _("invalid offset, value too big (0x%08lX)"),
12583 (long) value);
b99bd4ef
NC
12584 newval |= value << 6;
12585 break;
12586
12587 case 8: /* Halfword load/store. */
12588 if (value & ~0x3e)
12589 as_bad_where (fixP->fx_file, fixP->fx_line,
08df2379
NC
12590 _("invalid offset, value too big (0x%08lX)"),
12591 (long) value);
b99bd4ef
NC
12592 newval |= value << 5; /* 6 - 1. */
12593 break;
12594
12595 default:
12596 as_bad_where (fixP->fx_file, fixP->fx_line,
12597 "Unable to process relocation for thumb opcode: %lx",
12598 (unsigned long) newval);
12599 break;
12600 }
12601 md_number_to_chars (buf, newval, THUMB_SIZE);
12602 break;
12603
12604 case BFD_RELOC_ARM_THUMB_ADD:
12605 /* This is a complicated relocation, since we use it for all of
12606 the following immediate relocations:
12607
12608 3bit ADD/SUB
12609 8bit ADD/SUB
12610 9bit ADD/SUB SP word-aligned
12611 10bit ADD PC/SP word-aligned
12612
12613 The type of instruction being processed is encoded in the
12614 instruction field:
12615
12616 0x8000 SUB
12617 0x00F0 Rd
12618 0x000F Rs
12619 */
12620 newval = md_chars_to_number (buf, THUMB_SIZE);
12621 {
12622 int rd = (newval >> 4) & 0xf;
12623 int rs = newval & 0xf;
12624 int subtract = newval & 0x8000;
12625
12626 if (rd == REG_SP)
12627 {
12628 if (value & ~0x1fc)
12629 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12630 _("invalid immediate for stack address calculation"));
b99bd4ef
NC
12631 newval = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
12632 newval |= value >> 2;
12633 }
12634 else if (rs == REG_PC || rs == REG_SP)
12635 {
12636 if (subtract ||
12637 value & ~0x3fc)
12638 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12639 _("invalid immediate for address calculation (value = 0x%08lX)"),
b99bd4ef
NC
12640 (unsigned long) value);
12641 newval = (rs == REG_PC ? T_OPCODE_ADD_PC : T_OPCODE_ADD_SP);
12642 newval |= rd << 8;
12643 newval |= value >> 2;
12644 }
12645 else if (rs == rd)
12646 {
12647 if (value & ~0xff)
12648 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12649 _("invalid 8bit immediate"));
b99bd4ef
NC
12650 newval = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
12651 newval |= (rd << 8) | value;
12652 }
12653 else
12654 {
12655 if (value & ~0x7)
12656 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12657 _("invalid 3bit immediate"));
b99bd4ef
NC
12658 newval = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
12659 newval |= rd | (rs << 3) | (value << 6);
12660 }
12661 }
12662 md_number_to_chars (buf, newval, THUMB_SIZE);
12663 break;
12664
12665 case BFD_RELOC_ARM_THUMB_IMM:
12666 newval = md_chars_to_number (buf, THUMB_SIZE);
12667 switch (newval >> 11)
12668 {
12669 case 0x04: /* 8bit immediate MOV. */
12670 case 0x05: /* 8bit immediate CMP. */
12671 if (value < 0 || value > 255)
12672 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12673 _("invalid immediate: %ld is too large"),
b99bd4ef
NC
12674 (long) value);
12675 newval |= value;
12676 break;
12677
12678 default:
12679 abort ();
12680 }
12681 md_number_to_chars (buf, newval, THUMB_SIZE);
12682 break;
12683
12684 case BFD_RELOC_ARM_THUMB_SHIFT:
12685 /* 5bit shift value (0..31). */
12686 if (value < 0 || value > 31)
12687 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12688 _("illegal Thumb shift value: %ld"), (long) value);
b99bd4ef
NC
12689 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xf03f;
12690 newval |= value << 6;
12691 md_number_to_chars (buf, newval, THUMB_SIZE);
12692 break;
12693
12694 case BFD_RELOC_VTABLE_INHERIT:
12695 case BFD_RELOC_VTABLE_ENTRY:
12696 fixP->fx_done = 0;
94f592af 12697 return;
b99bd4ef
NC
12698
12699 case BFD_RELOC_NONE:
12700 default:
12701 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12702 _("bad relocation fixup type (%d)"), fixP->fx_r_type);
b99bd4ef 12703 }
b99bd4ef
NC
12704}
12705
12706/* Translate internal representation of relocation info to BFD target
12707 format. */
12708
12709arelent *
12710tc_gen_reloc (section, fixp)
12711 asection * section ATTRIBUTE_UNUSED;
12712 fixS * fixp;
12713{
12714 arelent * reloc;
12715 bfd_reloc_code_real_type code;
12716
12717 reloc = (arelent *) xmalloc (sizeof (arelent));
12718
12719 reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
12720 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
12721 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
12722
12723 /* @@ Why fx_addnumber sometimes and fx_offset other times? */
12724#ifndef OBJ_ELF
12725 if (fixp->fx_pcrel == 0)
12726 reloc->addend = fixp->fx_offset;
12727 else
12728 reloc->addend = fixp->fx_offset = reloc->address;
12729#else /* OBJ_ELF */
12730 reloc->addend = fixp->fx_offset;
12731#endif
12732
12733 switch (fixp->fx_r_type)
12734 {
12735 case BFD_RELOC_8:
12736 if (fixp->fx_pcrel)
12737 {
12738 code = BFD_RELOC_8_PCREL;
12739 break;
12740 }
12741
12742 case BFD_RELOC_16:
12743 if (fixp->fx_pcrel)
12744 {
12745 code = BFD_RELOC_16_PCREL;
12746 break;
12747 }
12748
12749 case BFD_RELOC_32:
12750 if (fixp->fx_pcrel)
12751 {
12752 code = BFD_RELOC_32_PCREL;
12753 break;
12754 }
12755
12756 case BFD_RELOC_ARM_PCREL_BRANCH:
12757 case BFD_RELOC_ARM_PCREL_BLX:
12758 case BFD_RELOC_RVA:
12759 case BFD_RELOC_THUMB_PCREL_BRANCH9:
12760 case BFD_RELOC_THUMB_PCREL_BRANCH12:
12761 case BFD_RELOC_THUMB_PCREL_BRANCH23:
12762 case BFD_RELOC_THUMB_PCREL_BLX:
12763 case BFD_RELOC_VTABLE_ENTRY:
12764 case BFD_RELOC_VTABLE_INHERIT:
12765 code = fixp->fx_r_type;
12766 break;
12767
12768 case BFD_RELOC_ARM_LITERAL:
12769 case BFD_RELOC_ARM_HWLITERAL:
3d0c9500
NC
12770 /* If this is called then the a literal has
12771 been referenced across a section boundary. */
b99bd4ef 12772 as_bad_where (fixp->fx_file, fixp->fx_line,
61b5f74b 12773 _("literal referenced across section boundary"));
b99bd4ef
NC
12774 return NULL;
12775
12776#ifdef OBJ_ELF
12777 case BFD_RELOC_ARM_GOT32:
12778 case BFD_RELOC_ARM_GOTOFF:
12779 case BFD_RELOC_ARM_PLT32:
db6579d4
PB
12780 case BFD_RELOC_ARM_RELABS32:
12781 case BFD_RELOC_ARM_ROSEGREL32:
12782 case BFD_RELOC_ARM_SBREL32:
b99bd4ef
NC
12783 code = fixp->fx_r_type;
12784 break;
12785#endif
12786
12787 case BFD_RELOC_ARM_IMMEDIATE:
12788 as_bad_where (fixp->fx_file, fixp->fx_line,
6189168b 12789 _("internal relocation (type: IMMEDIATE) not fixed up"));
b99bd4ef
NC
12790 return NULL;
12791
12792 case BFD_RELOC_ARM_ADRL_IMMEDIATE:
12793 as_bad_where (fixp->fx_file, fixp->fx_line,
12794 _("ADRL used for a symbol not defined in the same file"));
12795 return NULL;
12796
12797 case BFD_RELOC_ARM_OFFSET_IMM:
c3ba240c
DJ
12798 if (fixp->fx_addsy != NULL
12799 && !S_IS_DEFINED (fixp->fx_addsy)
12800 && S_IS_LOCAL (fixp->fx_addsy))
12801 {
12802 as_bad_where (fixp->fx_file, fixp->fx_line,
12803 _("undefined local label `%s'"),
12804 S_GET_NAME (fixp->fx_addsy));
12805 return NULL;
12806 }
12807
b99bd4ef 12808 as_bad_where (fixp->fx_file, fixp->fx_line,
6189168b 12809 _("internal_relocation (type: OFFSET_IMM) not fixed up"));
b99bd4ef
NC
12810 return NULL;
12811
12812 default:
12813 {
12814 char * type;
12815
12816 switch (fixp->fx_r_type)
12817 {
b99bd4ef
NC
12818 case BFD_RELOC_ARM_OFFSET_IMM8: type = "OFFSET_IMM8"; break;
12819 case BFD_RELOC_ARM_SHIFT_IMM: type = "SHIFT_IMM"; break;
12820 case BFD_RELOC_ARM_SWI: type = "SWI"; break;
12821 case BFD_RELOC_ARM_MULTI: type = "MULTI"; break;
12822 case BFD_RELOC_ARM_CP_OFF_IMM: type = "CP_OFF_IMM"; break;
12823 case BFD_RELOC_ARM_THUMB_ADD: type = "THUMB_ADD"; break;
12824 case BFD_RELOC_ARM_THUMB_SHIFT: type = "THUMB_SHIFT"; break;
12825 case BFD_RELOC_ARM_THUMB_IMM: type = "THUMB_IMM"; break;
12826 case BFD_RELOC_ARM_THUMB_OFFSET: type = "THUMB_OFFSET"; break;
12827 default: type = _("<unknown>"); break;
12828 }
12829 as_bad_where (fixp->fx_file, fixp->fx_line,
f03698e6 12830 _("cannot represent %s relocation in this object file format"),
b99bd4ef
NC
12831 type);
12832 return NULL;
12833 }
12834 }
12835
12836#ifdef OBJ_ELF
8df7094c 12837 if ((code == BFD_RELOC_32_PCREL || code == BFD_RELOC_32)
b99bd4ef
NC
12838 && GOT_symbol
12839 && fixp->fx_addsy == GOT_symbol)
12840 {
12841 code = BFD_RELOC_ARM_GOTPC;
12842 reloc->addend = fixp->fx_offset = reloc->address;
12843 }
12844#endif
12845
12846 reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
12847
12848 if (reloc->howto == NULL)
12849 {
12850 as_bad_where (fixp->fx_file, fixp->fx_line,
f03698e6 12851 _("cannot represent %s relocation in this object file format"),
b99bd4ef
NC
12852 bfd_get_reloc_code_name (code));
12853 return NULL;
12854 }
12855
12856 /* HACK: Since arm ELF uses Rel instead of Rela, encode the
12857 vtable entry to be used in the relocation's section offset. */
12858 if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
12859 reloc->address = fixp->fx_offset;
12860
12861 return reloc;
12862}
12863
12864int
12865md_estimate_size_before_relax (fragP, segtype)
12866 fragS * fragP ATTRIBUTE_UNUSED;
12867 segT segtype ATTRIBUTE_UNUSED;
12868{
12869 as_fatal (_("md_estimate_size_before_relax\n"));
12870 return 1;
12871}
12872
12873static void
f03698e6
RE
12874output_inst (str)
12875 const char *str;
b99bd4ef
NC
12876{
12877 char * to = NULL;
12878
12879 if (inst.error)
12880 {
f03698e6 12881 as_bad ("%s -- `%s'", inst.error, str);
b99bd4ef
NC
12882 return;
12883 }
12884
12885 to = frag_more (inst.size);
12886
12887 if (thumb_mode && (inst.size > THUMB_SIZE))
12888 {
12889 assert (inst.size == (2 * THUMB_SIZE));
12890 md_number_to_chars (to, inst.instruction >> 16, THUMB_SIZE);
12891 md_number_to_chars (to + THUMB_SIZE, inst.instruction, THUMB_SIZE);
12892 }
12893 else if (inst.size > INSN_SIZE)
12894 {
12895 assert (inst.size == (2 * INSN_SIZE));
12896 md_number_to_chars (to, inst.instruction, INSN_SIZE);
12897 md_number_to_chars (to + INSN_SIZE, inst.instruction, INSN_SIZE);
12898 }
12899 else
12900 md_number_to_chars (to, inst.instruction, inst.size);
12901
12902 if (inst.reloc.type != BFD_RELOC_NONE)
12903 fix_new_arm (frag_now, to - frag_now->fr_literal,
12904 inst.size, & inst.reloc.exp, inst.reloc.pc_rel,
12905 inst.reloc.type);
12906
12907#ifdef OBJ_ELF
12908 dwarf2_emit_insn (inst.size);
12909#endif
12910}
12911
12912void
12913md_assemble (str)
12914 char * str;
12915{
6c43fab6
RE
12916 char c;
12917 char *p;
12918 char *start;
b99bd4ef
NC
12919
12920 /* Align the instruction.
12921 This may not be the right thing to do but ... */
12922#if 0
12923 arm_align (2, 0);
12924#endif
b99bd4ef
NC
12925
12926 /* Align the previous label if needed. */
12927 if (last_label_seen != NULL)
12928 {
12929 symbol_set_frag (last_label_seen, frag_now);
12930 S_SET_VALUE (last_label_seen, (valueT) frag_now_fix ());
12931 S_SET_SEGMENT (last_label_seen, now_seg);
12932 }
12933
12934 memset (&inst, '\0', sizeof (inst));
12935 inst.reloc.type = BFD_RELOC_NONE;
12936
12937 skip_whitespace (str);
12938
12939 /* Scan up to the end of the op-code, which must end in white space or
12940 end of string. */
12941 for (start = p = str; *p != '\0'; p++)
12942 if (*p == ' ')
12943 break;
12944
12945 if (p == str)
12946 {
f03698e6 12947 as_bad (_("no operator -- statement `%s'\n"), str);
b99bd4ef
NC
12948 return;
12949 }
12950
12951 if (thumb_mode)
12952 {
05d2d07e 12953 const struct thumb_opcode * opcode;
b99bd4ef
NC
12954
12955 c = *p;
12956 *p = '\0';
05d2d07e 12957 opcode = (const struct thumb_opcode *) hash_find (arm_tops_hsh, str);
b99bd4ef
NC
12958 *p = c;
12959
12960 if (opcode)
12961 {
12962 /* Check that this instruction is supported for this CPU. */
90e4755a 12963 if (thumb_mode == 1 && (opcode->variant & cpu_variant) == 0)
b99bd4ef 12964 {
f03698e6 12965 as_bad (_("selected processor does not support `%s'"), str);
b99bd4ef
NC
12966 return;
12967 }
12968
6057a28f 12969 mapping_state (MAP_THUMB);
b99bd4ef
NC
12970 inst.instruction = opcode->value;
12971 inst.size = opcode->size;
12972 (*opcode->parms) (p);
f03698e6 12973 output_inst (str);
b99bd4ef
NC
12974 return;
12975 }
12976 }
12977 else
12978 {
05d2d07e 12979 const struct asm_opcode * opcode;
b99bd4ef 12980
90e4755a
RE
12981 c = *p;
12982 *p = '\0';
6c43fab6 12983 opcode = (const struct asm_opcode *) hash_find (arm_ops_hsh, str);
90e4755a 12984 *p = c;
b99bd4ef 12985
90e4755a 12986 if (opcode)
b99bd4ef 12987 {
90e4755a
RE
12988 /* Check that this instruction is supported for this CPU. */
12989 if ((opcode->variant & cpu_variant) == 0)
b99bd4ef 12990 {
f03698e6 12991 as_bad (_("selected processor does not support `%s'"), str);
b99bd4ef
NC
12992 return;
12993 }
12994
6057a28f 12995 mapping_state (MAP_ARM);
90e4755a
RE
12996 inst.instruction = opcode->value;
12997 inst.size = INSN_SIZE;
f2b7cb0a 12998 (*opcode->parms) (p);
f03698e6 12999 output_inst (str);
90e4755a 13000 return;
b99bd4ef
NC
13001 }
13002 }
13003
13004 /* It wasn't an instruction, but it might be a register alias of the form
13005 alias .req reg. */
6c43fab6
RE
13006 if (create_register_alias (str, p))
13007 return;
b99bd4ef 13008
b99bd4ef
NC
13009 as_bad (_("bad instruction `%s'"), start);
13010}
13011
13012/* md_parse_option
13013 Invocation line includes a switch not recognized by the base assembler.
cc8a6dd0 13014 See if it's a processor-specific option.
03b1477f
RE
13015
13016 This routine is somewhat complicated by the need for backwards
13017 compatibility (since older releases of gcc can't be changed).
13018 The new options try to make the interface as compatible as
13019 possible with GCC.
13020
13021 New options (supported) are:
13022
13023 -mcpu=<cpu name> Assemble for selected processor
13024 -march=<architecture name> Assemble for selected architecture
13025 -mfpu=<fpu architecture> Assemble for selected FPU.
13026 -EB/-mbig-endian Big-endian
13027 -EL/-mlittle-endian Little-endian
13028 -k Generate PIC code
13029 -mthumb Start in Thumb mode
13030 -mthumb-interwork Code supports ARM/Thumb interworking
13031
3d0c9500 13032 For now we will also provide support for:
03b1477f
RE
13033
13034 -mapcs-32 32-bit Program counter
13035 -mapcs-26 26-bit Program counter
13036 -macps-float Floats passed in FP registers
13037 -mapcs-reentrant Reentrant code
13038 -matpcs
13039 (sometime these will probably be replaced with -mapcs=<list of options>
13040 and -matpcs=<list of options>)
13041
13042 The remaining options are only supported for back-wards compatibility.
b99bd4ef
NC
13043 Cpu variants, the arm part is optional:
13044 -m[arm]1 Currently not supported.
13045 -m[arm]2, -m[arm]250 Arm 2 and Arm 250 processor
13046 -m[arm]3 Arm 3 processor
13047 -m[arm]6[xx], Arm 6 processors
13048 -m[arm]7[xx][t][[d]m] Arm 7 processors
13049 -m[arm]8[10] Arm 8 processors
13050 -m[arm]9[20][tdmi] Arm 9 processors
13051 -mstrongarm[110[0]] StrongARM processors
13052 -mxscale XScale processors
13053 -m[arm]v[2345[t[e]]] Arm architectures
13054 -mall All (except the ARM1)
13055 FP variants:
13056 -mfpa10, -mfpa11 FPA10 and 11 co-processor instructions
13057 -mfpe-old (No float load/store multiples)
bfae80f2
RE
13058 -mvfpxd VFP Single precision
13059 -mvfp All VFP
b99bd4ef 13060 -mno-fpu Disable all floating point instructions
b99bd4ef 13061
03b1477f
RE
13062 The following CPU names are recognized:
13063 arm1, arm2, arm250, arm3, arm6, arm600, arm610, arm620,
13064 arm7, arm7m, arm7d, arm7dm, arm7di, arm7dmi, arm70, arm700,
13065 arm700i, arm710 arm710t, arm720, arm720t, arm740t, arm710c,
13066 arm7100, arm7500, arm7500fe, arm7tdmi, arm8, arm810, arm9,
13067 arm920, arm920t, arm940t, arm946, arm966, arm9tdmi, arm9e,
13068 arm10t arm10e, arm1020t, arm1020e, arm10200e,
13069 strongarm, strongarm110, strongarm1100, strongarm1110, xscale.
13070
13071 */
13072
5a38dc70 13073const char * md_shortopts = "m:k";
03b1477f 13074
b99bd4ef
NC
13075#ifdef ARM_BI_ENDIAN
13076#define OPTION_EB (OPTION_MD_BASE + 0)
b99bd4ef 13077#define OPTION_EL (OPTION_MD_BASE + 1)
21f0f23a 13078#else
21f0f23a
RE
13079#if TARGET_BYTES_BIG_ENDIAN
13080#define OPTION_EB (OPTION_MD_BASE + 0)
21f0f23a
RE
13081#else
13082#define OPTION_EL (OPTION_MD_BASE + 1)
21f0f23a 13083#endif
ce058b6c 13084#endif
03b1477f
RE
13085
13086struct option md_longopts[] =
13087{
13088#ifdef OPTION_EB
13089 {"EB", no_argument, NULL, OPTION_EB},
13090#endif
13091#ifdef OPTION_EL
13092 {"EL", no_argument, NULL, OPTION_EL},
b99bd4ef
NC
13093#endif
13094 {NULL, no_argument, NULL, 0}
13095};
13096
13097size_t md_longopts_size = sizeof (md_longopts);
13098
03b1477f 13099struct arm_option_table
b99bd4ef 13100{
03b1477f
RE
13101 char *option; /* Option name to match. */
13102 char *help; /* Help information. */
13103 int *var; /* Variable to change. */
13104 int value; /* What to change it to. */
13105 char *deprecated; /* If non-null, print this message. */
13106};
b99bd4ef 13107
cc8a6dd0 13108struct arm_option_table arm_opts[] =
03b1477f
RE
13109{
13110 {"k", N_("generate PIC code"), &pic_code, 1, NULL},
13111 {"mthumb", N_("assemble Thumb code"), &thumb_mode, 1, NULL},
13112 {"mthumb-interwork", N_("support ARM/Thumb interworking"),
13113 &support_interwork, 1, NULL},
13114 {"moabi", N_("use old ABI (ELF only)"), &target_oabi, 1, NULL},
13115 {"mapcs-32", N_("code uses 32-bit program counter"), &uses_apcs_26, 0, NULL},
13116 {"mapcs-26", N_("code uses 26-bit program counter"), &uses_apcs_26, 1, NULL},
13117 {"mapcs-float", N_("floating point args are in fp regs"), &uses_apcs_float,
13118 1, NULL},
13119 {"mapcs-reentrant", N_("re-entrant code"), &pic_code, 1, NULL},
13120 {"matpcs", N_("code is ATPCS conformant"), &atpcs, 1, NULL},
13121 {"mbig-endian", N_("assemble for big-endian"), &target_big_endian, 1, NULL},
13122 {"mlittle-endian", N_("assemble for little-endian"), &target_big_endian, 1,
13123 NULL},
13124
13125 /* These are recognized by the assembler, but have no affect on code. */
13126 {"mapcs-frame", N_("use frame pointer"), NULL, 0, NULL},
13127 {"mapcs-stack-check", N_("use stack size checking"), NULL, 0, NULL},
13128
13129 /* DON'T add any new processors to this list -- we want the whole list
13130 to go away... Add them to the processors table instead. */
13131 {"marm1", NULL, &legacy_cpu, ARM_ARCH_V1, N_("use -mcpu=arm1")},
13132 {"m1", NULL, &legacy_cpu, ARM_ARCH_V1, N_("use -mcpu=arm1")},
13133 {"marm2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -mcpu=arm2")},
13134 {"m2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -mcpu=arm2")},
13135 {"marm250", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm250")},
13136 {"m250", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm250")},
13137 {"marm3", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm3")},
13138 {"m3", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm3")},
13139 {"marm6", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm6")},
13140 {"m6", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm6")},
13141 {"marm600", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm600")},
13142 {"m600", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm600")},
13143 {"marm610", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm610")},
13144 {"m610", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm610")},
13145 {"marm620", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm620")},
13146 {"m620", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm620")},
13147 {"marm7", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7")},
13148 {"m7", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7")},
13149 {"marm70", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm70")},
13150 {"m70", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm70")},
13151 {"marm700", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700")},
13152 {"m700", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700")},
13153 {"marm700i", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700i")},
13154 {"m700i", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700i")},
13155 {"marm710", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710")},
13156 {"m710", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710")},
13157 {"marm710c", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710c")},
13158 {"m710c", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710c")},
13159 {"marm720", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm720")},
13160 {"m720", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm720")},
13161 {"marm7d", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7d")},
13162 {"m7d", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7d")},
13163 {"marm7di", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7di")},
13164 {"m7di", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7di")},
13165 {"marm7m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7m")},
13166 {"m7m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7m")},
13167 {"marm7dm", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dm")},
13168 {"m7dm", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dm")},
13169 {"marm7dmi", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dmi")},
13170 {"m7dmi", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dmi")},
13171 {"marm7100", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7100")},
13172 {"m7100", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7100")},
13173 {"marm7500", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500")},
13174 {"m7500", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500")},
13175 {"marm7500fe", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500fe")},
13176 {"m7500fe", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500fe")},
13177 {"marm7t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
13178 {"m7t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
13179 {"marm7tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
13180 {"m7tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
13181 {"marm710t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm710t")},
13182 {"m710t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm710t")},
13183 {"marm720t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm720t")},
13184 {"m720t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm720t")},
13185 {"marm740t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm740t")},
13186 {"m740t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm740t")},
13187 {"marm8", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm8")},
13188 {"m8", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm8")},
13189 {"marm810", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm810")},
13190 {"m810", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm810")},
13191 {"marm9", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9")},
13192 {"m9", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9")},
13193 {"marm9tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9tdmi")},
13194 {"m9tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9tdmi")},
13195 {"marm920", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm920")},
13196 {"m920", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm920")},
13197 {"marm940", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm940")},
13198 {"m940", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm940")},
13199 {"mstrongarm", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=strongarm")},
13200 {"mstrongarm110", NULL, &legacy_cpu, ARM_ARCH_V4,
13201 N_("use -mcpu=strongarm110")},
13202 {"mstrongarm1100", NULL, &legacy_cpu, ARM_ARCH_V4,
13203 N_("use -mcpu=strongarm1100")},
13204 {"mstrongarm1110", NULL, &legacy_cpu, ARM_ARCH_V4,
13205 N_("use -mcpu=strongarm1110")},
13206 {"mxscale", NULL, &legacy_cpu, ARM_ARCH_XSCALE, N_("use -mcpu=xscale")},
e16bb312 13207 {"miwmmxt", NULL, &legacy_cpu, ARM_ARCH_IWMMXT, N_("use -mcpu=iwmmxt")},
03b1477f
RE
13208 {"mall", NULL, &legacy_cpu, ARM_ANY, N_("use -mcpu=all")},
13209
13210 /* Architecture variants -- don't add any more to this list either. */
13211 {"mv2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -march=armv2")},
13212 {"marmv2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -march=armv2")},
13213 {"mv2a", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -march=armv2a")},
13214 {"marmv2a", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -march=armv2a")},
13215 {"mv3", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -march=armv3")},
13216 {"marmv3", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -march=armv3")},
13217 {"mv3m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -march=armv3m")},
13218 {"marmv3m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -march=armv3m")},
13219 {"mv4", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -march=armv4")},
13220 {"marmv4", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -march=armv4")},
13221 {"mv4t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -march=armv4t")},
13222 {"marmv4t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -march=armv4t")},
13223 {"mv5", NULL, &legacy_cpu, ARM_ARCH_V5, N_("use -march=armv5")},
13224 {"marmv5", NULL, &legacy_cpu, ARM_ARCH_V5, N_("use -march=armv5")},
13225 {"mv5t", NULL, &legacy_cpu, ARM_ARCH_V5T, N_("use -march=armv5t")},
13226 {"marmv5t", NULL, &legacy_cpu, ARM_ARCH_V5T, N_("use -march=armv5t")},
13227 {"mv5e", NULL, &legacy_cpu, ARM_ARCH_V5TE, N_("use -march=armv5te")},
13228 {"marmv5e", NULL, &legacy_cpu, ARM_ARCH_V5TE, N_("use -march=armv5te")},
13229
13230 /* Floating point variants -- don't add any more to this list either. */
13231 {"mfpe-old", NULL, &legacy_fpu, FPU_ARCH_FPE, N_("use -mfpu=fpe")},
13232 {"mfpa10", NULL, &legacy_fpu, FPU_ARCH_FPA, N_("use -mfpu=fpa10")},
13233 {"mfpa11", NULL, &legacy_fpu, FPU_ARCH_FPA, N_("use -mfpu=fpa11")},
13234 {"mno-fpu", NULL, &legacy_fpu, 0,
13235 N_("use either -mfpu=softfpa or -mfpu=softvfp")},
13236
13237 {NULL, NULL, NULL, 0, NULL}
13238};
21f0f23a 13239
03b1477f
RE
13240struct arm_cpu_option_table
13241{
13242 char *name;
13243 int value;
13244 /* For some CPUs we assume an FPU unless the user explicitly sets
13245 -mfpu=... */
13246 int default_fpu;
13247};
13248
13249/* This list should, at a minimum, contain all the cpu names
13250 recognized by GCC. */
13251static struct arm_cpu_option_table arm_cpus[] =
13252{
13253 {"all", ARM_ANY, FPU_ARCH_FPA},
13254 {"arm1", ARM_ARCH_V1, FPU_ARCH_FPA},
13255 {"arm2", ARM_ARCH_V2, FPU_ARCH_FPA},
13256 {"arm250", ARM_ARCH_V2S, FPU_ARCH_FPA},
13257 {"arm3", ARM_ARCH_V2S, FPU_ARCH_FPA},
13258 {"arm6", ARM_ARCH_V3, FPU_ARCH_FPA},
13259 {"arm60", ARM_ARCH_V3, FPU_ARCH_FPA},
13260 {"arm600", ARM_ARCH_V3, FPU_ARCH_FPA},
13261 {"arm610", ARM_ARCH_V3, FPU_ARCH_FPA},
13262 {"arm620", ARM_ARCH_V3, FPU_ARCH_FPA},
13263 {"arm7", ARM_ARCH_V3, FPU_ARCH_FPA},
13264 {"arm7m", ARM_ARCH_V3M, FPU_ARCH_FPA},
13265 {"arm7d", ARM_ARCH_V3, FPU_ARCH_FPA},
13266 {"arm7dm", ARM_ARCH_V3M, FPU_ARCH_FPA},
13267 {"arm7di", ARM_ARCH_V3, FPU_ARCH_FPA},
13268 {"arm7dmi", ARM_ARCH_V3M, FPU_ARCH_FPA},
13269 {"arm70", ARM_ARCH_V3, FPU_ARCH_FPA},
13270 {"arm700", ARM_ARCH_V3, FPU_ARCH_FPA},
13271 {"arm700i", ARM_ARCH_V3, FPU_ARCH_FPA},
13272 {"arm710", ARM_ARCH_V3, FPU_ARCH_FPA},
13273 {"arm710t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13274 {"arm720", ARM_ARCH_V3, FPU_ARCH_FPA},
13275 {"arm720t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13276 {"arm740t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13277 {"arm710c", ARM_ARCH_V3, FPU_ARCH_FPA},
13278 {"arm7100", ARM_ARCH_V3, FPU_ARCH_FPA},
13279 {"arm7500", ARM_ARCH_V3, FPU_ARCH_FPA},
13280 {"arm7500fe", ARM_ARCH_V3, FPU_ARCH_FPA},
13281 {"arm7t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13282 {"arm7tdmi", ARM_ARCH_V4T, FPU_ARCH_FPA},
8783612f 13283 {"arm7tdmi-s", ARM_ARCH_V4T, FPU_ARCH_FPA},
03b1477f
RE
13284 {"arm8", ARM_ARCH_V4, FPU_ARCH_FPA},
13285 {"arm810", ARM_ARCH_V4, FPU_ARCH_FPA},
13286 {"strongarm", ARM_ARCH_V4, FPU_ARCH_FPA},
13287 {"strongarm1", ARM_ARCH_V4, FPU_ARCH_FPA},
13288 {"strongarm110", ARM_ARCH_V4, FPU_ARCH_FPA},
13289 {"strongarm1100", ARM_ARCH_V4, FPU_ARCH_FPA},
13290 {"strongarm1110", ARM_ARCH_V4, FPU_ARCH_FPA},
13291 {"arm9", ARM_ARCH_V4T, FPU_ARCH_FPA},
13292 {"arm920", ARM_ARCH_V4T, FPU_ARCH_FPA},
13293 {"arm920t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13294 {"arm922t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13295 {"arm940t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13296 {"arm9tdmi", ARM_ARCH_V4T, FPU_ARCH_FPA},
13297 /* For V5 or later processors we default to using VFP; but the user
13298 should really set the FPU type explicitly. */
13299 {"arm9e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
13300 {"arm9e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
ea6ef066 13301 {"arm926ej", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
7de9afa2 13302 {"arm926ejs", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
8783612f 13303 {"arm926ej-s", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
03b1477f
RE
13304 {"arm946e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
13305 {"arm946e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13306 {"arm966e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
13307 {"arm966e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13308 {"arm10t", ARM_ARCH_V5T, FPU_ARCH_VFP_V1},
13309 {"arm10e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13310 {"arm1020", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13311 {"arm1020t", ARM_ARCH_V5T, FPU_ARCH_VFP_V1},
13312 {"arm1020e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
7de9afa2 13313 {"arm1026ejs", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
8783612f 13314 {"arm1026ej-s", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
09d92015 13315 {"arm1136js", ARM_ARCH_V6, FPU_NONE},
9166bcd7 13316 {"arm1136j-s", ARM_ARCH_V6, FPU_NONE},
09d92015 13317 {"arm1136jfs", ARM_ARCH_V6, FPU_ARCH_VFP_V2},
8783612f 13318 {"arm1136jf-s", ARM_ARCH_V6, FPU_ARCH_VFP_V2},
03b1477f
RE
13319 /* ??? XSCALE is really an architecture. */
13320 {"xscale", ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2},
5a6c6817 13321 /* ??? iwmmxt is not a processor. */
e16bb312 13322 {"iwmmxt", ARM_ARCH_IWMMXT, FPU_ARCH_VFP_V2},
03b1477f
RE
13323 {"i80200", ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2},
13324 /* Maverick */
33a392fb 13325 {"ep9312", ARM_ARCH_V4T | ARM_CEXT_MAVERICK, FPU_ARCH_MAVERICK},
03b1477f
RE
13326 {NULL, 0, 0}
13327};
cc8a6dd0 13328
03b1477f
RE
13329struct arm_arch_option_table
13330{
13331 char *name;
13332 int value;
13333 int default_fpu;
13334};
13335
13336/* This list should, at a minimum, contain all the architecture names
13337 recognized by GCC. */
13338static struct arm_arch_option_table arm_archs[] =
13339{
13340 {"all", ARM_ANY, FPU_ARCH_FPA},
13341 {"armv1", ARM_ARCH_V1, FPU_ARCH_FPA},
13342 {"armv2", ARM_ARCH_V2, FPU_ARCH_FPA},
13343 {"armv2a", ARM_ARCH_V2S, FPU_ARCH_FPA},
13344 {"armv2s", ARM_ARCH_V2S, FPU_ARCH_FPA},
13345 {"armv3", ARM_ARCH_V3, FPU_ARCH_FPA},
13346 {"armv3m", ARM_ARCH_V3M, FPU_ARCH_FPA},
13347 {"armv4", ARM_ARCH_V4, FPU_ARCH_FPA},
13348 {"armv4xm", ARM_ARCH_V4xM, FPU_ARCH_FPA},
13349 {"armv4t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13350 {"armv4txm", ARM_ARCH_V4TxM, FPU_ARCH_FPA},
13351 {"armv5", ARM_ARCH_V5, FPU_ARCH_VFP},
13352 {"armv5t", ARM_ARCH_V5T, FPU_ARCH_VFP},
13353 {"armv5txm", ARM_ARCH_V5TxM, FPU_ARCH_VFP},
13354 {"armv5te", ARM_ARCH_V5TE, FPU_ARCH_VFP},
13355 {"armv5texp", ARM_ARCH_V5TExP, FPU_ARCH_VFP},
ea6ef066 13356 {"armv5tej", ARM_ARCH_V5TEJ, FPU_ARCH_VFP},
84255574 13357 {"armv6", ARM_ARCH_V6, FPU_ARCH_VFP},
1ddd7f43 13358 {"armv6j", ARM_ARCH_V6, FPU_ARCH_VFP},
03b1477f 13359 {"xscale", ARM_ARCH_XSCALE, FPU_ARCH_VFP},
8266886e 13360 {"iwmmxt", ARM_ARCH_IWMMXT, FPU_ARCH_VFP},
03b1477f
RE
13361 {NULL, 0, 0}
13362};
13363
13364/* ISA extensions in the co-processor space. */
13365struct arm_arch_extension_table
13366{
13367 char *name;
13368 int value;
13369};
13370
13371static struct arm_arch_extension_table arm_extensions[] =
13372{
13373 {"maverick", ARM_CEXT_MAVERICK},
13374 {"xscale", ARM_CEXT_XSCALE},
e16bb312 13375 {"iwmmxt", ARM_CEXT_IWMMXT},
03b1477f
RE
13376 {NULL, 0}
13377};
b99bd4ef 13378
03b1477f
RE
13379struct arm_fpu_option_table
13380{
13381 char *name;
13382 int value;
13383};
13384
13385/* This list should, at a minimum, contain all the fpu names
13386 recognized by GCC. */
13387static struct arm_fpu_option_table arm_fpus[] =
13388{
13389 {"softfpa", FPU_NONE},
13390 {"fpe", FPU_ARCH_FPE},
d193a22a
RE
13391 {"fpe2", FPU_ARCH_FPE},
13392 {"fpe3", FPU_ARCH_FPA}, /* Third release supports LFM/SFM. */
03b1477f
RE
13393 {"fpa", FPU_ARCH_FPA},
13394 {"fpa10", FPU_ARCH_FPA},
13395 {"fpa11", FPU_ARCH_FPA},
13396 {"arm7500fe", FPU_ARCH_FPA},
13397 {"softvfp", FPU_ARCH_VFP},
13398 {"softvfp+vfp", FPU_ARCH_VFP_V2},
13399 {"vfp", FPU_ARCH_VFP_V2},
13400 {"vfp9", FPU_ARCH_VFP_V2},
13401 {"vfp10", FPU_ARCH_VFP_V2},
13402 {"vfp10-r0", FPU_ARCH_VFP_V1},
13403 {"vfpxd", FPU_ARCH_VFP_V1xD},
13404 {"arm1020t", FPU_ARCH_VFP_V1},
13405 {"arm1020e", FPU_ARCH_VFP_V2},
09d92015 13406 {"arm1136jfs", FPU_ARCH_VFP_V2},
8783612f 13407 {"arm1136jf-s", FPU_ARCH_VFP_V2},
33a392fb
PB
13408 {"maverick", FPU_ARCH_MAVERICK},
13409 {NULL, 0}
13410};
13411
13412struct arm_float_abi_option_table
13413{
13414 char *name;
13415 int value;
13416};
13417
13418static struct arm_float_abi_option_table arm_float_abis[] =
13419{
13420 {"hard", ARM_FLOAT_ABI_HARD},
13421 {"softfp", ARM_FLOAT_ABI_SOFTFP},
13422 {"soft", ARM_FLOAT_ABI_SOFT},
03b1477f
RE
13423 {NULL, 0}
13424};
13425
d507cf36
PB
13426struct arm_eabi_option_table
13427{
13428 char *name;
13429 unsigned int value;
13430};
13431
7cc69913 13432#ifdef OBJ_ELF
d507cf36
PB
13433/* We only know hot to output GNU and ver 3 (AAELF) formats. */
13434static struct arm_eabi_option_table arm_eabis[] =
13435{
13436 {"gnu", EF_ARM_EABI_UNKNOWN},
13437 {"3", EF_ARM_EABI_VER3},
13438 {NULL, 0}
13439};
7cc69913 13440#endif
d507cf36 13441
03b1477f
RE
13442struct arm_long_option_table
13443{
13444 char *option; /* Substring to match. */
13445 char *help; /* Help information. */
13446 int (*func) PARAMS ((char *subopt)); /* Function to decode sub-option. */
13447 char *deprecated; /* If non-null, print this message. */
13448};
13449
13450static int
13451arm_parse_extension (str, opt_p)
13452 char *str;
13453 int *opt_p;
13454{
13455 while (str != NULL && *str != 0)
13456 {
13457 struct arm_arch_extension_table *opt;
13458 char *ext;
13459 int optlen;
13460
13461 if (*str != '+')
b99bd4ef 13462 {
03b1477f
RE
13463 as_bad (_("invalid architectural extension"));
13464 return 0;
13465 }
b99bd4ef 13466
03b1477f
RE
13467 str++;
13468 ext = strchr (str, '+');
b99bd4ef 13469
03b1477f
RE
13470 if (ext != NULL)
13471 optlen = ext - str;
13472 else
13473 optlen = strlen (str);
b99bd4ef 13474
03b1477f
RE
13475 if (optlen == 0)
13476 {
13477 as_bad (_("missing architectural extension"));
13478 return 0;
13479 }
b99bd4ef 13480
03b1477f
RE
13481 for (opt = arm_extensions; opt->name != NULL; opt++)
13482 if (strncmp (opt->name, str, optlen) == 0)
13483 {
13484 *opt_p |= opt->value;
13485 break;
13486 }
bfae80f2 13487
03b1477f
RE
13488 if (opt->name == NULL)
13489 {
13490 as_bad (_("unknown architectural extnsion `%s'"), str);
13491 return 0;
13492 }
b99bd4ef 13493
03b1477f
RE
13494 str = ext;
13495 };
b99bd4ef 13496
03b1477f
RE
13497 return 1;
13498}
b99bd4ef 13499
03b1477f
RE
13500static int
13501arm_parse_cpu (str)
13502 char *str;
13503{
13504 struct arm_cpu_option_table *opt;
13505 char *ext = strchr (str, '+');
13506 int optlen;
b99bd4ef 13507
03b1477f
RE
13508 if (ext != NULL)
13509 optlen = ext - str;
13510 else
13511 optlen = strlen (str);
b99bd4ef 13512
03b1477f
RE
13513 if (optlen == 0)
13514 {
13515 as_bad (_("missing cpu name `%s'"), str);
13516 return 0;
13517 }
b99bd4ef 13518
03b1477f
RE
13519 for (opt = arm_cpus; opt->name != NULL; opt++)
13520 if (strncmp (opt->name, str, optlen) == 0)
13521 {
13522 mcpu_cpu_opt = opt->value;
13523 mcpu_fpu_opt = opt->default_fpu;
b99bd4ef 13524
03b1477f
RE
13525 if (ext != NULL)
13526 return arm_parse_extension (ext, &mcpu_cpu_opt);
b99bd4ef 13527
03b1477f
RE
13528 return 1;
13529 }
b99bd4ef 13530
03b1477f
RE
13531 as_bad (_("unknown cpu `%s'"), str);
13532 return 0;
13533}
b99bd4ef 13534
03b1477f
RE
13535static int
13536arm_parse_arch (str)
13537 char *str;
13538{
13539 struct arm_arch_option_table *opt;
13540 char *ext = strchr (str, '+');
13541 int optlen;
b99bd4ef 13542
03b1477f
RE
13543 if (ext != NULL)
13544 optlen = ext - str;
13545 else
13546 optlen = strlen (str);
b99bd4ef 13547
03b1477f
RE
13548 if (optlen == 0)
13549 {
13550 as_bad (_("missing architecture name `%s'"), str);
13551 return 0;
13552 }
b99bd4ef 13553
b99bd4ef 13554
03b1477f
RE
13555 for (opt = arm_archs; opt->name != NULL; opt++)
13556 if (strcmp (opt->name, str) == 0)
13557 {
13558 march_cpu_opt = opt->value;
13559 march_fpu_opt = opt->default_fpu;
b99bd4ef 13560
03b1477f
RE
13561 if (ext != NULL)
13562 return arm_parse_extension (ext, &march_cpu_opt);
b99bd4ef 13563
03b1477f
RE
13564 return 1;
13565 }
b99bd4ef 13566
03b1477f
RE
13567 as_bad (_("unknown architecture `%s'\n"), str);
13568 return 0;
13569}
13570
13571static int
13572arm_parse_fpu (str)
13573 char *str;
13574{
13575 struct arm_fpu_option_table *opt;
b99bd4ef 13576
03b1477f
RE
13577 for (opt = arm_fpus; opt->name != NULL; opt++)
13578 if (strcmp (opt->name, str) == 0)
13579 {
13580 mfpu_opt = opt->value;
13581 return 1;
13582 }
b99bd4ef 13583
03b1477f
RE
13584 as_bad (_("unknown floating point format `%s'\n"), str);
13585 return 0;
13586}
b99bd4ef 13587
33a392fb
PB
13588static int
13589arm_parse_float_abi (str)
13590 char * str;
13591{
13592 struct arm_float_abi_option_table *opt;
13593
13594 for (opt = arm_float_abis; opt->name != NULL; opt++)
13595 if (strcmp (opt->name, str) == 0)
13596 {
13597 mfloat_abi_opt = opt->value;
13598 return 1;
13599 }
13600
13601 as_bad (_("unknown floating point abi `%s'\n"), str);
13602 return 0;
13603}
13604
7cc69913 13605#ifdef OBJ_ELF
d507cf36
PB
13606static int
13607arm_parse_eabi (str)
13608 char * str;
13609{
13610 struct arm_eabi_option_table *opt;
13611
13612 for (opt = arm_eabis; opt->name != NULL; opt++)
13613 if (strcmp (opt->name, str) == 0)
13614 {
13615 meabi_flags = opt->value;
13616 return 1;
13617 }
13618 as_bad (_("unknown EABI `%s'\n"), str);
13619 return 0;
13620}
7cc69913 13621#endif
d507cf36 13622
03b1477f
RE
13623struct arm_long_option_table arm_long_opts[] =
13624{
13625 {"mcpu=", N_("<cpu name>\t assemble for CPU <cpu name>"),
13626 arm_parse_cpu, NULL},
13627 {"march=", N_("<arch name>\t assemble for architecture <arch name>"),
13628 arm_parse_arch, NULL},
13629 {"mfpu=", N_("<fpu name>\t assemble for FPU architecture <fpu name>"),
13630 arm_parse_fpu, NULL},
33a392fb
PB
13631 {"mfloat-abi=", N_("<abi>\t assemble for floating point ABI <abi>"),
13632 arm_parse_float_abi, NULL},
7cc69913 13633#ifdef OBJ_ELF
d507cf36
PB
13634 {"meabi=", N_("<ver>\t assemble for eabi version <ver>"),
13635 arm_parse_eabi, NULL},
7cc69913 13636#endif
03b1477f
RE
13637 {NULL, NULL, 0, NULL}
13638};
b99bd4ef 13639
03b1477f
RE
13640int
13641md_parse_option (c, arg)
13642 int c;
13643 char * arg;
13644{
13645 struct arm_option_table *opt;
13646 struct arm_long_option_table *lopt;
b99bd4ef 13647
03b1477f
RE
13648 switch (c)
13649 {
13650#ifdef OPTION_EB
13651 case OPTION_EB:
13652 target_big_endian = 1;
b99bd4ef 13653 break;
03b1477f 13654#endif
b99bd4ef 13655
03b1477f
RE
13656#ifdef OPTION_EL
13657 case OPTION_EL:
13658 target_big_endian = 0;
b99bd4ef
NC
13659 break;
13660#endif
13661
03b1477f 13662 case 'a':
cc8a6dd0 13663 /* Listing option. Just ignore these, we don't support additional
03b1477f
RE
13664 ones. */
13665 return 0;
13666
b99bd4ef 13667 default:
03b1477f
RE
13668 for (opt = arm_opts; opt->option != NULL; opt++)
13669 {
13670 if (c == opt->option[0]
13671 && ((arg == NULL && opt->option[1] == 0)
13672 || strcmp (arg, opt->option + 1) == 0))
13673 {
13674#if WARN_DEPRECATED
13675 /* If the option is deprecated, tell the user. */
13676 if (opt->deprecated != NULL)
13677 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c,
13678 arg ? arg : "", _(opt->deprecated));
13679#endif
13680
13681 if (opt->var != NULL)
13682 *opt->var = opt->value;
13683
13684 return 1;
13685 }
13686 }
13687
13688 for (lopt = arm_long_opts; lopt->option != NULL; lopt++)
13689 {
cc8a6dd0 13690 /* These options are expected to have an argument. */
03b1477f
RE
13691 if (c == lopt->option[0]
13692 && arg != NULL
cc8a6dd0 13693 && strncmp (arg, lopt->option + 1,
03b1477f
RE
13694 strlen (lopt->option + 1)) == 0)
13695 {
13696#if WARN_DEPRECATED
13697 /* If the option is deprecated, tell the user. */
13698 if (lopt->deprecated != NULL)
13699 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c, arg,
13700 _(lopt->deprecated));
13701#endif
13702
13703 /* Call the sup-option parser. */
13704 return (*lopt->func)(arg + strlen (lopt->option) - 1);
13705 }
13706 }
13707
b99bd4ef
NC
13708 return 0;
13709 }
13710
13711 return 1;
13712}
13713
13714void
13715md_show_usage (fp)
13716 FILE * fp;
13717{
03b1477f
RE
13718 struct arm_option_table *opt;
13719 struct arm_long_option_table *lopt;
13720
13721 fprintf (fp, _(" ARM-specific assembler options:\n"));
13722
13723 for (opt = arm_opts; opt->option != NULL; opt++)
13724 if (opt->help != NULL)
13725 fprintf (fp, " -%-23s%s\n", opt->option, _(opt->help));
13726
13727 for (lopt = arm_long_opts; lopt->option != NULL; lopt++)
13728 if (lopt->help != NULL)
13729 fprintf (fp, " -%s%s\n", lopt->option, _(lopt->help));
13730
13731#ifdef OPTION_EB
b99bd4ef 13732 fprintf (fp, _("\
03b1477f 13733 -EB assemble code for a big-endian cpu\n"));
b99bd4ef 13734#endif
03b1477f
RE
13735
13736#ifdef OPTION_EL
b99bd4ef 13737 fprintf (fp, _("\
03b1477f 13738 -EL assemble code for a little-endian cpu\n"));
b99bd4ef
NC
13739#endif
13740}
13741
13742/* We need to be able to fix up arbitrary expressions in some statements.
13743 This is so that we can handle symbols that are an arbitrary distance from
13744 the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
13745 which returns part of an address in a form which will be valid for
13746 a data instruction. We do this by pushing the expression into a symbol
13747 in the expr_section, and creating a fix for that. */
13748
13749static void
13750fix_new_arm (frag, where, size, exp, pc_rel, reloc)
13751 fragS * frag;
13752 int where;
13753 short int size;
13754 expressionS * exp;
13755 int pc_rel;
13756 int reloc;
13757{
13758 fixS * new_fix;
13759 arm_fix_data * arm_data;
13760
13761 switch (exp->X_op)
13762 {
13763 case O_constant:
13764 case O_symbol:
13765 case O_add:
13766 case O_subtract:
13767 new_fix = fix_new_exp (frag, where, size, exp, pc_rel, reloc);
13768 break;
13769
13770 default:
13771 new_fix = fix_new (frag, where, size, make_expr_symbol (exp), 0,
13772 pc_rel, reloc);
13773 break;
13774 }
13775
13776 /* Mark whether the fix is to a THUMB instruction, or an ARM
13777 instruction. */
13778 arm_data = (arm_fix_data *) obstack_alloc (& notes, sizeof (arm_fix_data));
13779 new_fix->tc_fix_data = (PTR) arm_data;
13780 arm_data->thumb_mode = thumb_mode;
b99bd4ef
NC
13781}
13782
13783/* This fix_new is called by cons via TC_CONS_FIX_NEW. */
13784
13785void
13786cons_fix_new_arm (frag, where, size, exp)
13787 fragS * frag;
13788 int where;
13789 int size;
13790 expressionS * exp;
13791{
13792 bfd_reloc_code_real_type type;
13793 int pcrel = 0;
13794
13795 /* Pick a reloc.
13796 FIXME: @@ Should look at CPU word size. */
13797 switch (size)
13798 {
13799 case 1:
13800 type = BFD_RELOC_8;
13801 break;
13802 case 2:
13803 type = BFD_RELOC_16;
13804 break;
13805 case 4:
13806 default:
13807 type = BFD_RELOC_32;
13808 break;
13809 case 8:
13810 type = BFD_RELOC_64;
13811 break;
13812 }
13813
13814 fix_new_exp (frag, where, (int) size, exp, pcrel, type);
13815}
13816
13817/* A good place to do this, although this was probably not intended
13818 for this kind of use. We need to dump the literal pool before
13819 references are made to a null symbol pointer. */
13820
13821void
13822arm_cleanup ()
13823{
3d0c9500 13824 literal_pool * pool;
b99bd4ef 13825
3d0c9500
NC
13826 for (pool = list_of_pools; pool; pool = pool->next)
13827 {
13828 /* Put it at the end of the relevent section. */
13829 subseg_set (pool->section, pool->sub_section);
69b97547
NC
13830#ifdef OBJ_ELF
13831 arm_elf_change_section ();
13832#endif
3d0c9500
NC
13833 s_ltorg (0);
13834 }
b99bd4ef
NC
13835}
13836
13837void
13838arm_start_line_hook ()
13839{
13840 last_label_seen = NULL;
13841}
13842
13843void
13844arm_frob_label (sym)
13845 symbolS * sym;
13846{
13847 last_label_seen = sym;
13848
13849 ARM_SET_THUMB (sym, thumb_mode);
13850
13851#if defined OBJ_COFF || defined OBJ_ELF
13852 ARM_SET_INTERWORK (sym, support_interwork);
13853#endif
13854
13855 /* Note - do not allow local symbols (.Lxxx) to be labeled
13856 as Thumb functions. This is because these labels, whilst
13857 they exist inside Thumb code, are not the entry points for
13858 possible ARM->Thumb calls. Also, these labels can be used
13859 as part of a computed goto or switch statement. eg gcc
13860 can generate code that looks like this:
13861
13862 ldr r2, [pc, .Laaa]
13863 lsl r3, r3, #2
13864 ldr r2, [r3, r2]
13865 mov pc, r2
cc8a6dd0 13866
b99bd4ef
NC
13867 .Lbbb: .word .Lxxx
13868 .Lccc: .word .Lyyy
13869 ..etc...
13870 .Laaa: .word Lbbb
13871
13872 The first instruction loads the address of the jump table.
13873 The second instruction converts a table index into a byte offset.
13874 The third instruction gets the jump address out of the table.
13875 The fourth instruction performs the jump.
cc8a6dd0 13876
b99bd4ef
NC
13877 If the address stored at .Laaa is that of a symbol which has the
13878 Thumb_Func bit set, then the linker will arrange for this address
13879 to have the bottom bit set, which in turn would mean that the
13880 address computation performed by the third instruction would end
13881 up with the bottom bit set. Since the ARM is capable of unaligned
13882 word loads, the instruction would then load the incorrect address
13883 out of the jump table, and chaos would ensue. */
13884 if (label_is_thumb_function_name
13885 && (S_GET_NAME (sym)[0] != '.' || S_GET_NAME (sym)[1] != 'L')
13886 && (bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
13887 {
13888 /* When the address of a Thumb function is taken the bottom
13889 bit of that address should be set. This will allow
13890 interworking between Arm and Thumb functions to work
13891 correctly. */
13892
13893 THUMB_SET_FUNC (sym, 1);
13894
b34976b6 13895 label_is_thumb_function_name = FALSE;
b99bd4ef
NC
13896 }
13897}
13898
13899/* Adjust the symbol table. This marks Thumb symbols as distinct from
13900 ARM ones. */
13901
13902void
13903arm_adjust_symtab ()
13904{
13905#ifdef OBJ_COFF
13906 symbolS * sym;
13907
13908 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
13909 {
13910 if (ARM_IS_THUMB (sym))
13911 {
13912 if (THUMB_IS_FUNC (sym))
13913 {
13914 /* Mark the symbol as a Thumb function. */
13915 if ( S_GET_STORAGE_CLASS (sym) == C_STAT
13916 || S_GET_STORAGE_CLASS (sym) == C_LABEL) /* This can happen! */
13917 S_SET_STORAGE_CLASS (sym, C_THUMBSTATFUNC);
13918
13919 else if (S_GET_STORAGE_CLASS (sym) == C_EXT)
13920 S_SET_STORAGE_CLASS (sym, C_THUMBEXTFUNC);
13921 else
13922 as_bad (_("%s: unexpected function type: %d"),
13923 S_GET_NAME (sym), S_GET_STORAGE_CLASS (sym));
13924 }
cc8a6dd0 13925 else switch (S_GET_STORAGE_CLASS (sym))
b99bd4ef
NC
13926 {
13927 case C_EXT:
13928 S_SET_STORAGE_CLASS (sym, C_THUMBEXT);
13929 break;
13930 case C_STAT:
13931 S_SET_STORAGE_CLASS (sym, C_THUMBSTAT);
13932 break;
13933 case C_LABEL:
13934 S_SET_STORAGE_CLASS (sym, C_THUMBLABEL);
13935 break;
13936 default:
13937 /* Do nothing. */
13938 break;
13939 }
13940 }
13941
13942 if (ARM_IS_INTERWORK (sym))
13943 coffsymbol (symbol_get_bfdsym (sym))->native->u.syment.n_flags = 0xFF;
13944 }
13945#endif
13946#ifdef OBJ_ELF
13947 symbolS * sym;
13948 char bind;
13949
13950 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
13951 {
13952 if (ARM_IS_THUMB (sym))
13953 {
13954 elf_symbol_type * elf_sym;
13955
13956 elf_sym = elf_symbol (symbol_get_bfdsym (sym));
13957 bind = ELF_ST_BIND (elf_sym);
13958
13959 /* If it's a .thumb_func, declare it as so,
13960 otherwise tag label as .code 16. */
13961 if (THUMB_IS_FUNC (sym))
13962 elf_sym->internal_elf_sym.st_info =
13963 ELF_ST_INFO (bind, STT_ARM_TFUNC);
13964 else
13965 elf_sym->internal_elf_sym.st_info =
13966 ELF_ST_INFO (bind, STT_ARM_16BIT);
13967 }
13968 }
13969#endif
13970}
13971
13972int
13973arm_data_in_code ()
13974{
13975 if (thumb_mode && ! strncmp (input_line_pointer + 1, "data:", 5))
13976 {
13977 *input_line_pointer = '/';
13978 input_line_pointer += 5;
13979 *input_line_pointer = 0;
13980 return 1;
13981 }
13982
13983 return 0;
13984}
13985
13986char *
13987arm_canonicalize_symbol_name (name)
13988 char * name;
13989{
13990 int len;
13991
13992 if (thumb_mode && (len = strlen (name)) > 5
13993 && streq (name + len - 5, "/data"))
13994 *(name + len - 5) = 0;
13995
13996 return name;
13997}
13998
bfc866a6 13999#if defined OBJ_COFF || defined OBJ_ELF
a161fe53 14000void
b99bd4ef
NC
14001arm_validate_fix (fixP)
14002 fixS * fixP;
14003{
14004 /* If the destination of the branch is a defined symbol which does not have
14005 the THUMB_FUNC attribute, then we must be calling a function which has
14006 the (interfacearm) attribute. We look for the Thumb entry point to that
14007 function and change the branch to refer to that function instead. */
14008 if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23
14009 && fixP->fx_addsy != NULL
14010 && S_IS_DEFINED (fixP->fx_addsy)
14011 && ! THUMB_IS_FUNC (fixP->fx_addsy))
14012 {
14013 fixP->fx_addsy = find_real_start (fixP->fx_addsy);
b99bd4ef 14014 }
b99bd4ef 14015}
bfc866a6 14016#endif
b99bd4ef 14017
114424c6
AM
14018int
14019arm_force_relocation (fixp)
14020 struct fix * fixp;
14021{
14022#if defined (OBJ_COFF) && defined (TE_PE)
14023 if (fixp->fx_r_type == BFD_RELOC_RVA)
14024 return 1;
14025#endif
14026#ifdef OBJ_ELF
ae6063d4 14027 if (fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH
114424c6
AM
14028 || fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BLX
14029 || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX
14030 || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23)
14031 return 1;
14032#endif
14033
14034 /* Resolve these relocations even if the symbol is extern or weak. */
14035 if (fixp->fx_r_type == BFD_RELOC_ARM_IMMEDIATE
47281638 14036 || fixp->fx_r_type == BFD_RELOC_ARM_OFFSET_IMM
114424c6
AM
14037 || fixp->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE)
14038 return 0;
14039
ae6063d4 14040 return generic_force_reloc (fixp);
114424c6
AM
14041}
14042
b99bd4ef
NC
14043#ifdef OBJ_COFF
14044/* This is a little hack to help the gas/arm/adrl.s test. It prevents
14045 local labels from being added to the output symbol table when they
14046 are used with the ADRL pseudo op. The ADRL relocation should always
14047 be resolved before the binbary is emitted, so it is safe to say that
14048 it is adjustable. */
14049
b34976b6 14050bfd_boolean
b99bd4ef
NC
14051arm_fix_adjustable (fixP)
14052 fixS * fixP;
14053{
14054 if (fixP->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE)
14055 return 1;
14056 return 0;
14057}
14058#endif
114424c6 14059
b99bd4ef
NC
14060#ifdef OBJ_ELF
14061/* Relocations against Thumb function names must be left unadjusted,
14062 so that the linker can use this information to correctly set the
14063 bottom bit of their addresses. The MIPS version of this function
14064 also prevents relocations that are mips-16 specific, but I do not
14065 know why it does this.
14066
14067 FIXME:
14068 There is one other problem that ought to be addressed here, but
14069 which currently is not: Taking the address of a label (rather
14070 than a function) and then later jumping to that address. Such
14071 addresses also ought to have their bottom bit set (assuming that
14072 they reside in Thumb code), but at the moment they will not. */
14073
b34976b6 14074bfd_boolean
b99bd4ef
NC
14075arm_fix_adjustable (fixP)
14076 fixS * fixP;
14077{
14078 if (fixP->fx_addsy == NULL)
14079 return 1;
14080
b99bd4ef
NC
14081 if (THUMB_IS_FUNC (fixP->fx_addsy)
14082 && fixP->fx_subsy == NULL)
14083 return 0;
14084
14085 /* We need the symbol name for the VTABLE entries. */
14086 if ( fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
14087 || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
14088 return 0;
14089
a161fe53
AM
14090 /* Don't allow symbols to be discarded on GOT related relocs. */
14091 if (fixP->fx_r_type == BFD_RELOC_ARM_PLT32
14092 || fixP->fx_r_type == BFD_RELOC_ARM_GOT32
14093 || fixP->fx_r_type == BFD_RELOC_ARM_GOTOFF)
14094 return 0;
14095
b99bd4ef
NC
14096 return 1;
14097}
14098
14099const char *
14100elf32_arm_target_format ()
14101{
e5a52504
MM
14102#ifdef TE_SYMBIAN
14103 return (target_big_endian
14104 ? "elf32-bigarm-symbian"
14105 : "elf32-littlearm-symbian");
14106#else
b99bd4ef
NC
14107 if (target_big_endian)
14108 {
14109 if (target_oabi)
14110 return "elf32-bigarm-oabi";
14111 else
14112 return "elf32-bigarm";
14113 }
14114 else
14115 {
14116 if (target_oabi)
14117 return "elf32-littlearm-oabi";
14118 else
14119 return "elf32-littlearm";
14120 }
e5a52504 14121#endif
b99bd4ef
NC
14122}
14123
14124void
14125armelf_frob_symbol (symp, puntp)
14126 symbolS * symp;
14127 int * puntp;
14128{
14129 elf_frob_symbol (symp, puntp);
14130}
14131
b99bd4ef
NC
14132static bfd_reloc_code_real_type
14133arm_parse_reloc ()
14134{
14135 char id [16];
14136 char * ip;
14137 unsigned int i;
14138 static struct
14139 {
14140 char * str;
14141 int len;
14142 bfd_reloc_code_real_type reloc;
14143 }
14144 reloc_map[] =
14145 {
14146#define MAP(str,reloc) { str, sizeof (str) - 1, reloc }
14147 MAP ("(got)", BFD_RELOC_ARM_GOT32),
14148 MAP ("(gotoff)", BFD_RELOC_ARM_GOTOFF),
14149 /* ScottB: Jan 30, 1998 - Added support for parsing "var(PLT)"
14150 branch instructions generated by GCC for PLT relocs. */
14151 MAP ("(plt)", BFD_RELOC_ARM_PLT32),
db6579d4
PB
14152 MAP ("(relabs)", BFD_RELOC_ARM_RELABS32),
14153 MAP ("(sbrel)", BFD_RELOC_ARM_SBREL32),
b99bd4ef
NC
14154 { NULL, 0, BFD_RELOC_UNUSED }
14155#undef MAP
14156 };
14157
14158 for (i = 0, ip = input_line_pointer;
3882b010 14159 i < sizeof (id) && (ISALNUM (*ip) || ISPUNCT (*ip));
b99bd4ef 14160 i++, ip++)
3882b010 14161 id[i] = TOLOWER (*ip);
b99bd4ef
NC
14162
14163 for (i = 0; reloc_map[i].str; i++)
14164 if (strncmp (id, reloc_map[i].str, reloc_map[i].len) == 0)
14165 break;
14166
14167 input_line_pointer += reloc_map[i].len;
14168
14169 return reloc_map[i].reloc;
14170}
14171
14172static void
14173s_arm_elf_cons (nbytes)
14174 int nbytes;
14175{
14176 expressionS exp;
14177
14178#ifdef md_flush_pending_output
14179 md_flush_pending_output ();
14180#endif
14181
14182 if (is_it_end_of_statement ())
14183 {
14184 demand_empty_rest_of_line ();
14185 return;
14186 }
14187
14188#ifdef md_cons_align
14189 md_cons_align (nbytes);
14190#endif
14191
6057a28f 14192 mapping_state (MAP_DATA);
b99bd4ef
NC
14193 do
14194 {
14195 bfd_reloc_code_real_type reloc;
14196
14197 expression (& exp);
14198
14199 if (exp.X_op == O_symbol
14200 && * input_line_pointer == '('
14201 && (reloc = arm_parse_reloc ()) != BFD_RELOC_UNUSED)
14202 {
14203 reloc_howto_type *howto = bfd_reloc_type_lookup (stdoutput, reloc);
14204 int size = bfd_get_reloc_size (howto);
14205
14206 if (size > nbytes)
14207 as_bad ("%s relocations do not fit in %d bytes",
14208 howto->name, nbytes);
14209 else
14210 {
14211 register char *p = frag_more ((int) nbytes);
14212 int offset = nbytes - size;
14213
14214 fix_new_exp (frag_now, p - frag_now->fr_literal + offset, size,
14215 &exp, 0, reloc);
14216 }
14217 }
14218 else
14219 emit_expr (&exp, (unsigned int) nbytes);
14220 }
14221 while (*input_line_pointer++ == ',');
14222
14223 /* Put terminator back into stream. */
14224 input_line_pointer --;
14225 demand_empty_rest_of_line ();
14226}
14227
14228#endif /* OBJ_ELF */
14229
14230/* This is called from HANDLE_ALIGN in write.c. Fill in the contents
14231 of an rs_align_code fragment. */
14232
14233void
14234arm_handle_align (fragP)
14235 fragS *fragP;
14236{
14237 static char const arm_noop[4] = { 0x00, 0x00, 0xa0, 0xe1 };
14238 static char const thumb_noop[2] = { 0xc0, 0x46 };
14239 static char const arm_bigend_noop[4] = { 0xe1, 0xa0, 0x00, 0x00 };
14240 static char const thumb_bigend_noop[2] = { 0x46, 0xc0 };
14241
14242 int bytes, fix, noop_size;
14243 char * p;
14244 const char * noop;
cc8a6dd0 14245
b99bd4ef
NC
14246 if (fragP->fr_type != rs_align_code)
14247 return;
14248
14249 bytes = fragP->fr_next->fr_address - fragP->fr_address - fragP->fr_fix;
14250 p = fragP->fr_literal + fragP->fr_fix;
14251 fix = 0;
cc8a6dd0 14252
b99bd4ef
NC
14253 if (bytes > MAX_MEM_FOR_RS_ALIGN_CODE)
14254 bytes &= MAX_MEM_FOR_RS_ALIGN_CODE;
cc8a6dd0 14255
b99bd4ef
NC
14256 if (fragP->tc_frag_data)
14257 {
14258 if (target_big_endian)
14259 noop = thumb_bigend_noop;
14260 else
14261 noop = thumb_noop;
14262 noop_size = sizeof (thumb_noop);
14263 }
14264 else
14265 {
14266 if (target_big_endian)
14267 noop = arm_bigend_noop;
14268 else
14269 noop = arm_noop;
14270 noop_size = sizeof (arm_noop);
14271 }
cc8a6dd0 14272
b99bd4ef
NC
14273 if (bytes & (noop_size - 1))
14274 {
14275 fix = bytes & (noop_size - 1);
14276 memset (p, 0, fix);
14277 p += fix;
14278 bytes -= fix;
14279 }
14280
14281 while (bytes >= noop_size)
14282 {
14283 memcpy (p, noop, noop_size);
14284 p += noop_size;
14285 bytes -= noop_size;
14286 fix += noop_size;
14287 }
cc8a6dd0 14288
b99bd4ef
NC
14289 fragP->fr_fix += fix;
14290 fragP->fr_var = noop_size;
14291}
14292
14293/* Called from md_do_align. Used to create an alignment
14294 frag in a code section. */
14295
14296void
14297arm_frag_align_code (n, max)
14298 int n;
14299 int max;
14300{
14301 char * p;
14302
2d2255b5 14303 /* We assume that there will never be a requirement
b99bd4ef
NC
14304 to support alignments greater than 32 bytes. */
14305 if (max > MAX_MEM_FOR_RS_ALIGN_CODE)
14306 as_fatal (_("alignments greater than 32 bytes not supported in .text sections."));
cc8a6dd0 14307
b99bd4ef
NC
14308 p = frag_var (rs_align_code,
14309 MAX_MEM_FOR_RS_ALIGN_CODE,
14310 1,
14311 (relax_substateT) max,
14312 (symbolS *) NULL,
14313 (offsetT) n,
14314 (char *) NULL);
14315 *p = 0;
14316
14317}
14318
14319/* Perform target specific initialisation of a frag. */
14320
14321void
14322arm_init_frag (fragP)
14323 fragS *fragP;
14324{
14325 /* Record whether this frag is in an ARM or a THUMB area. */
14326 fragP->tc_frag_data = thumb_mode;
14327}