2004-09-30 Andrew Cagney <cagney@gnu.org>
[deliverable/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 2447static void s_arm_elf_cons PARAMS ((int));
eb043451 2448static void s_arm_rel31 (int nbytes);
b99bd4ef
NC
2449#endif
2450
2451static int my_get_expression PARAMS ((expressionS *, char **));
2452
05d2d07e 2453const pseudo_typeS md_pseudo_table[] =
b99bd4ef 2454{
0bbf2aa4 2455 /* Never called because '.req' does not start a line. */
b99bd4ef 2456 { "req", s_req, 0 },
0bbf2aa4 2457 { "unreq", s_unreq, 0 },
b99bd4ef
NC
2458 { "bss", s_bss, 0 },
2459 { "align", s_align, 0 },
2460 { "arm", s_arm, 0 },
2461 { "thumb", s_thumb, 0 },
2462 { "code", s_code, 0 },
2463 { "force_thumb", s_force_thumb, 0 },
2464 { "thumb_func", s_thumb_func, 0 },
2465 { "thumb_set", s_thumb_set, 0 },
2466 { "even", s_even, 0 },
2467 { "ltorg", s_ltorg, 0 },
2468 { "pool", s_ltorg, 0 },
76feaaf3 2469#ifdef OBJ_ELF
b99bd4ef
NC
2470 { "word", s_arm_elf_cons, 4 },
2471 { "long", s_arm_elf_cons, 4 },
eb043451 2472 { "rel31", s_arm_rel31, 0 },
b99bd4ef
NC
2473#else
2474 { "word", cons, 4},
2475#endif
2476 { "extend", float_cons, 'x' },
2477 { "ldouble", float_cons, 'x' },
2478 { "packed", float_cons, 'p' },
2479 { 0, 0, 0 }
2480};
2481
03b1477f
RE
2482/* Other internal functions. */
2483static int arm_parse_extension PARAMS ((char *, int *));
2484static int arm_parse_cpu PARAMS ((char *));
2485static int arm_parse_arch PARAMS ((char *));
2486static int arm_parse_fpu PARAMS ((char *));
33a392fb 2487static int arm_parse_float_abi PARAMS ((char *));
7cc69913 2488#ifdef OBJ_ELF
d507cf36 2489static int arm_parse_eabi PARAMS ((char *));
7cc69913 2490#endif
0bbf2aa4 2491#if 0 /* Suppressed - for now. */
5a6c6817
NC
2492#if defined OBJ_COFF || defined OBJ_ELF
2493static void arm_add_note PARAMS ((const char *, const char *, unsigned int));
2494#endif
0bbf2aa4 2495#endif
03b1477f 2496
b99bd4ef
NC
2497/* Stuff needed to resolve the label ambiguity
2498 As:
2499 ...
2500 label: <insn>
2501 may differ from:
2502 ...
2503 label:
2504 <insn>
2505*/
2506
2507symbolS * last_label_seen;
b34976b6 2508static int label_is_thumb_function_name = FALSE;
b99bd4ef 2509
3d0c9500 2510/* Literal Pool stuff. */
b99bd4ef
NC
2511
2512#define MAX_LITERAL_POOL_SIZE 1024
2513
3d0c9500
NC
2514/* Literal pool structure. Held on a per-section
2515 and per-sub-section basis. */
2516typedef struct literal_pool
b99bd4ef 2517{
3d0c9500
NC
2518 expressionS literals [MAX_LITERAL_POOL_SIZE];
2519 unsigned int next_free_entry;
2520 unsigned int id;
2521 symbolS * symbol;
2522 segT section;
2523 subsegT sub_section;
61b5f74b 2524 struct literal_pool * next;
3d0c9500 2525} literal_pool;
b99bd4ef 2526
3d0c9500
NC
2527/* Pointer to a linked list of literal pools. */
2528literal_pool * list_of_pools = NULL;
b99bd4ef 2529
3d0c9500
NC
2530static literal_pool * find_literal_pool PARAMS ((void));
2531static literal_pool * find_or_make_literal_pool PARAMS ((void));
b99bd4ef 2532
3d0c9500
NC
2533static literal_pool *
2534find_literal_pool ()
2535{
2536 literal_pool * pool;
2537
2538 for (pool = list_of_pools; pool != NULL; pool = pool->next)
2539 {
2540 if (pool->section == now_seg
2541 && pool->sub_section == now_subseg)
2542 break;
2543 }
2544
2545 return pool;
2546}
b99bd4ef 2547
3d0c9500
NC
2548static literal_pool *
2549find_or_make_literal_pool ()
2550{
2551 /* Next literal pool ID number. */
2552 static unsigned int latest_pool_num = 1;
2553 literal_pool * pool;
2554
2555 pool = find_literal_pool ();
b99bd4ef 2556
3d0c9500
NC
2557 if (pool == NULL)
2558 {
2559 /* Create a new pool. */
2560 pool = (literal_pool *) xmalloc (sizeof (* pool));
2561 if (! pool)
2562 return NULL;
2563
2564 pool->next_free_entry = 0;
2565 pool->section = now_seg;
2566 pool->sub_section = now_subseg;
2567 pool->next = list_of_pools;
2568 pool->symbol = NULL;
2569
2570 /* Add it to the list. */
2571 list_of_pools = pool;
2572 }
2573
2574 /* New pools, and emptied pools, will have a NULL symbol. */
2575 if (pool->symbol == NULL)
2576 {
2577 pool->symbol = symbol_create (FAKE_LABEL_NAME, undefined_section,
2578 (valueT) 0, &zero_address_frag);
2579 pool->id = latest_pool_num ++;
2580 }
2581
2582 /* Done. */
2583 return pool;
2584}
2585
2586/* Add the literal in the global 'inst'
2587 structure to the relevent literal pool. */
b99bd4ef
NC
2588static int
2589add_to_lit_pool ()
2590{
61b5f74b 2591 literal_pool * pool;
3d0c9500 2592 unsigned int entry;
b99bd4ef 2593
3d0c9500 2594 pool = find_or_make_literal_pool ();
b99bd4ef 2595
3d0c9500
NC
2596 /* Check if this literal value is already in the pool. */
2597 for (entry = 0; entry < pool->next_free_entry; entry ++)
b99bd4ef 2598 {
3d0c9500
NC
2599 if ((pool->literals[entry].X_op == inst.reloc.exp.X_op)
2600 && (inst.reloc.exp.X_op == O_constant)
2601 && (pool->literals[entry].X_add_number
b99bd4ef 2602 == inst.reloc.exp.X_add_number)
3d0c9500
NC
2603 && (pool->literals[entry].X_unsigned
2604 == inst.reloc.exp.X_unsigned))
b99bd4ef
NC
2605 break;
2606
3d0c9500
NC
2607 if ((pool->literals[entry].X_op == inst.reloc.exp.X_op)
2608 && (inst.reloc.exp.X_op == O_symbol)
2609 && (pool->literals[entry].X_add_number
b99bd4ef 2610 == inst.reloc.exp.X_add_number)
3d0c9500 2611 && (pool->literals[entry].X_add_symbol
b99bd4ef 2612 == inst.reloc.exp.X_add_symbol)
3d0c9500 2613 && (pool->literals[entry].X_op_symbol
b99bd4ef 2614 == inst.reloc.exp.X_op_symbol))
3d0c9500 2615 break;
b99bd4ef
NC
2616 }
2617
3d0c9500
NC
2618 /* Do we need to create a new entry? */
2619 if (entry == pool->next_free_entry)
b99bd4ef 2620 {
3d0c9500 2621 if (entry >= MAX_LITERAL_POOL_SIZE)
b99bd4ef 2622 {
ed71e111 2623 inst.error = _("literal pool overflow");
b99bd4ef
NC
2624 return FAIL;
2625 }
2626
3d0c9500
NC
2627 pool->literals[entry] = inst.reloc.exp;
2628 pool->next_free_entry += 1;
b99bd4ef
NC
2629 }
2630
3d0c9500 2631 inst.reloc.exp.X_op = O_symbol;
08df2379 2632 inst.reloc.exp.X_add_number = ((int) entry) * 4 - 8;
3d0c9500 2633 inst.reloc.exp.X_add_symbol = pool->symbol;
b99bd4ef
NC
2634
2635 return SUCCESS;
2636}
2637
2638/* Can't use symbol_new here, so have to create a symbol and then at
2639 a later date assign it a value. Thats what these functions do. */
2640
2641static void
2642symbol_locate (symbolP, name, segment, valu, frag)
2643 symbolS * symbolP;
05d2d07e 2644 const char * name; /* It is copied, the caller can modify. */
b99bd4ef
NC
2645 segT segment; /* Segment identifier (SEG_<something>). */
2646 valueT valu; /* Symbol value. */
2647 fragS * frag; /* Associated fragment. */
2648{
2649 unsigned int name_length;
2650 char * preserved_copy_of_name;
2651
2652 name_length = strlen (name) + 1; /* +1 for \0. */
2653 obstack_grow (&notes, name, name_length);
2654 preserved_copy_of_name = obstack_finish (&notes);
2655#ifdef STRIP_UNDERSCORE
2656 if (preserved_copy_of_name[0] == '_')
2657 preserved_copy_of_name++;
2658#endif
2659
2660#ifdef tc_canonicalize_symbol_name
2661 preserved_copy_of_name =
2662 tc_canonicalize_symbol_name (preserved_copy_of_name);
2663#endif
2664
2665 S_SET_NAME (symbolP, preserved_copy_of_name);
2666
2667 S_SET_SEGMENT (symbolP, segment);
2668 S_SET_VALUE (symbolP, valu);
c62e1cc3 2669 symbol_clear_list_pointers (symbolP);
b99bd4ef
NC
2670
2671 symbol_set_frag (symbolP, frag);
2672
2673 /* Link to end of symbol chain. */
2674 {
2675 extern int symbol_table_frozen;
2676 if (symbol_table_frozen)
2677 abort ();
2678 }
2679
2680 symbol_append (symbolP, symbol_lastP, & symbol_rootP, & symbol_lastP);
2681
2682 obj_symbol_new_hook (symbolP);
2683
2684#ifdef tc_symbol_new_hook
2685 tc_symbol_new_hook (symbolP);
2686#endif
2687
2688#ifdef DEBUG_SYMS
2689 verify_symbol_chain (symbol_rootP, symbol_lastP);
2690#endif /* DEBUG_SYMS */
2691}
2692
2693/* Check that an immediate is valid.
2694 If so, convert it to the right format. */
2695
2696static unsigned int
2697validate_immediate (val)
2698 unsigned int val;
2699{
2700 unsigned int a;
2701 unsigned int i;
2702
2703#define rotate_left(v, n) (v << n | v >> (32 - n))
2704
2705 for (i = 0; i < 32; i += 2)
2706 if ((a = rotate_left (val, i)) <= 0xff)
2707 return a | (i << 7); /* 12-bit pack: [shift-cnt,const]. */
2708
2709 return FAIL;
2710}
2711
2d2255b5 2712/* Check to see if an immediate can be computed as two separate immediate
b99bd4ef
NC
2713 values, added together. We already know that this value cannot be
2714 computed by just one ARM instruction. */
2715
2716static unsigned int
2717validate_immediate_twopart (val, highpart)
2718 unsigned int val;
2719 unsigned int * highpart;
2720{
2721 unsigned int a;
2722 unsigned int i;
2723
2724 for (i = 0; i < 32; i += 2)
2725 if (((a = rotate_left (val, i)) & 0xff) != 0)
2726 {
2727 if (a & 0xff00)
2728 {
2729 if (a & ~ 0xffff)
2730 continue;
2731 * highpart = (a >> 8) | ((i + 24) << 7);
2732 }
2733 else if (a & 0xff0000)
2734 {
2735 if (a & 0xff000000)
2736 continue;
2737 * highpart = (a >> 16) | ((i + 16) << 7);
2738 }
2739 else
2740 {
2741 assert (a & 0xff000000);
2742 * highpart = (a >> 24) | ((i + 8) << 7);
2743 }
2744
2745 return (a & 0xff) | (i << 7);
2746 }
2747
2748 return FAIL;
2749}
2750
2751static int
2752validate_offset_imm (val, hwse)
2753 unsigned int val;
2754 int hwse;
2755{
2756 if ((hwse && val > 255) || val > 4095)
2757 return FAIL;
2758 return val;
2759}
2760
6057a28f
NC
2761\f
2762#ifdef OBJ_ELF
6057a28f
NC
2763/* This code is to handle mapping symbols as defined in the ARM ELF spec.
2764 (This text is taken from version B-02 of the spec):
2765
2766 4.4.7 Mapping and tagging symbols
2767
2768 A section of an ARM ELF file can contain a mixture of ARM code,
2769 Thumb code, and data. There are inline transitions between code
2770 and data at literal pool boundaries. There can also be inline
2771 transitions between ARM code and Thumb code, for example in
2772 ARM-Thumb inter-working veneers. Linkers, machine-level
2773 debuggers, profiling tools, and disassembly tools need to map
2774 images accurately. For example, setting an ARM breakpoint on a
2775 Thumb location, or in a literal pool, can crash the program
2776 being debugged, ruining the debugging session.
2777
2778 ARM ELF entities are mapped (see section 4.4.7.1 below) and
2779 tagged (see section 4.4.7.2 below) using local symbols (with
2780 binding STB_LOCAL). To assist consumers, mapping and tagging
2781 symbols should be collated first in the symbol table, before
2782 other symbols with binding STB_LOCAL.
2783
2784 To allow properly collated mapping and tagging symbols to be
2785 skipped by consumers that have no interest in them, the first
2786 such symbol should have the name $m and its st_value field equal
2787 to the total number of mapping and tagging symbols (including
2788 the $m) in the symbol table.
2789
2790 4.4.7.1 Mapping symbols
2791
2792 $a Labels the first byte of a sequence of ARM instructions.
2793 Its type is STT_FUNC.
2794
2795 $d Labels the first byte of a sequence of data items.
2796 Its type is STT_OBJECT.
2797
2798 $t Labels the first byte of a sequence of Thumb instructions.
2799 Its type is STT_FUNC.
2800
2801 This list of mapping symbols may be extended in the future.
2802
2803 Section-relative mapping symbols
2804
2805 Mapping symbols defined in a section define a sequence of
2806 half-open address intervals that cover the address range of the
2807 section. Each interval starts at the address defined by a
2808 mapping symbol, and continues up to, but not including, the
2809 address defined by the next (in address order) mapping symbol or
2810 the end of the section. A corollary is that there must be a
2811 mapping symbol defined at the beginning of each section.
2812 Consumers can ignore the size of a section-relative mapping
2813 symbol. Producers can set it to 0.
2814
2815 Absolute mapping symbols
2816
2817 Because of the need to crystallize a Thumb address with the
2818 Thumb-bit set, absolute symbol of type STT_FUNC (symbols of type
2819 STT_FUNC defined in section SHN_ABS) need to be mapped with $a
2820 or $t.
2821
2822 The extent of a mapping symbol defined in SHN_ABS is [st_value,
2823 st_value + st_size), or [st_value, st_value + 1) if st_size = 0,
2824 where [x, y) denotes the half-open address range from x,
2825 inclusive, to y, exclusive.
2826
2827 In the absence of a mapping symbol, a consumer can interpret a
2828 function symbol with an odd value as the Thumb code address
2829 obtained by clearing the least significant bit of the
2830 value. This interpretation is deprecated, and it may not work in
2831 the future.
2832
2833 Note - the Tagging symbols ($b, $f, $p $m) have been dropped from
2834 the EABI (which is still under development), so they are not
2835 implemented here. */
2836
69b97547
NC
2837static enum mstate mapstate = MAP_UNDEFINED;
2838
6057a28f
NC
2839static void
2840mapping_state (enum mstate state)
2841{
6057a28f
NC
2842 symbolS * symbolP;
2843 const char * symname;
2844 int type;
2845
2846 if (mapstate == state)
2847 /* The mapping symbol has already been emitted.
2848 There is nothing else to do. */
2849 return;
2850
2851 mapstate = state;
2852
2853 switch (state)
2854 {
2855 case MAP_DATA:
2856 symname = "$d";
2857 type = BSF_OBJECT;
2858 break;
2859 case MAP_ARM:
2860 symname = "$a";
2861 type = BSF_FUNCTION;
2862 break;
2863 case MAP_THUMB:
2864 symname = "$t";
2865 type = BSF_FUNCTION;
2866 break;
69b97547
NC
2867 case MAP_UNDEFINED:
2868 return;
6057a28f
NC
2869 default:
2870 abort ();
2871 }
2872
69b97547
NC
2873 seg_info (now_seg)->tc_segment_info_data = state;
2874
6057a28f
NC
2875 symbolP = symbol_new (symname, now_seg, (valueT) frag_now_fix (), frag_now);
2876 symbol_table_insert (symbolP);
2877 symbol_get_bfdsym (symbolP)->flags |= type | BSF_LOCAL;
2878
2879 switch (state)
2880 {
2881 case MAP_ARM:
2882 THUMB_SET_FUNC (symbolP, 0);
2883 ARM_SET_THUMB (symbolP, 0);
2884 ARM_SET_INTERWORK (symbolP, support_interwork);
2885 break;
2886
2887 case MAP_THUMB:
2888 THUMB_SET_FUNC (symbolP, 1);
2889 ARM_SET_THUMB (symbolP, 1);
2890 ARM_SET_INTERWORK (symbolP, support_interwork);
2891 break;
2892
2893 case MAP_DATA:
2894 default:
2895 return;
2896 }
2897}
2898
2899/* When we change sections we need to issue a new mapping symbol. */
2900
9ce887a1 2901void
6057a28f
NC
2902arm_elf_change_section (void)
2903{
2904 flagword flags;
2905
2906 if (!SEG_NORMAL (now_seg))
2907 return;
2908
2909 flags = bfd_get_section_flags (stdoutput, now_seg);
2910
2911 /* We can ignore sections that only contain debug info. */
2912 if ((flags & SEC_ALLOC) == 0)
2913 return;
2914
69b97547 2915 mapstate = seg_info (now_seg)->tc_segment_info_data;
6057a28f
NC
2916}
2917#else
2918#define mapping_state(a)
2919#endif /* OBJ_ELF */
2920\f
2921
b99bd4ef
NC
2922static void
2923s_req (a)
2924 int a ATTRIBUTE_UNUSED;
2925{
f03698e6 2926 as_bad (_("invalid syntax for .req directive"));
b99bd4ef
NC
2927}
2928
0bbf2aa4
NC
2929/* The .unreq directive deletes an alias which was previously defined
2930 by .req. For example:
2931
2932 my_alias .req r11
2933 .unreq my_alias */
2934
2935static void
2936s_unreq (int a ATTRIBUTE_UNUSED)
2937{
2938 char *name;
2939 char saved_char;
2940
2941 skip_whitespace (input_line_pointer);
2942 name = input_line_pointer;
2943
2944 while (*input_line_pointer != 0
2945 && *input_line_pointer != ' '
2946 && *input_line_pointer != '\n')
2947 ++input_line_pointer;
2948
2949 saved_char = *input_line_pointer;
2950 *input_line_pointer = 0;
2951
2952 if (*name)
2953 {
2954 enum arm_reg_type req_type = arm_reg_parse_any (name);
2955
2956 if (req_type != REG_TYPE_MAX)
2957 {
2958 char *temp_name = name;
2959 int req_no = arm_reg_parse (&temp_name, all_reg_maps[req_type].htab);
2960
2961 if (req_no != FAIL)
2962 {
2963 struct reg_entry *req_entry;
2964
2965 /* Check to see if this alias is a builtin one. */
2966 req_entry = hash_delete (all_reg_maps[req_type].htab, name);
2967
2968 if (!req_entry)
2969 as_bad (_("unreq: missing hash entry for \"%s\""), name);
2970 else if (req_entry->builtin)
67c1ffbe 2971 /* FIXME: We are deleting a built in register alias which
0bbf2aa4
NC
2972 points to a const data structure, so we only need to
2973 free up the memory used by the key in the hash table.
2974 Unfortunately we have not recorded this value, so this
2975 is a memory leak. */
2976 /* FIXME: Should we issue a warning message ? */
2977 ;
2978 else
2979 {
67c1ffbe 2980 /* Deleting a user defined alias. We need to free the
0bbf2aa4
NC
2981 key and the value, but fortunately the key is the same
2982 as the value->name field. */
2983 free ((char *) req_entry->name);
2984 free (req_entry);
2985 }
2986 }
2987 else
2988 as_bad (_(".unreq: unrecognized symbol \"%s\""), name);
2989 }
2990 else
2991 as_bad (_(".unreq: unrecognized symbol \"%s\""), name);
2992 }
2993 else
2994 as_bad (_("invalid syntax for .unreq directive"));
2995
2996 *input_line_pointer = saved_char;
2997 demand_empty_rest_of_line ();
2998}
2999
b99bd4ef
NC
3000static void
3001s_bss (ignore)
3002 int ignore ATTRIBUTE_UNUSED;
3003{
3004 /* We don't support putting frags in the BSS segment, we fake it by
3005 marking in_bss, then looking at s_skip for clues. */
3006 subseg_set (bss_section, 0);
3007 demand_empty_rest_of_line ();
6057a28f 3008 mapping_state (MAP_DATA);
b99bd4ef
NC
3009}
3010
3011static void
3012s_even (ignore)
3013 int ignore ATTRIBUTE_UNUSED;
3014{
3015 /* Never make frag if expect extra pass. */
3016 if (!need_pass_2)
3017 frag_align (1, 0, 0);
3018
3019 record_alignment (now_seg, 1);
3020
3021 demand_empty_rest_of_line ();
3022}
3023
3024static void
3025s_ltorg (ignored)
3026 int ignored ATTRIBUTE_UNUSED;
3027{
3d0c9500
NC
3028 unsigned int entry;
3029 literal_pool * pool;
b99bd4ef
NC
3030 char sym_name[20];
3031
3d0c9500
NC
3032 pool = find_literal_pool ();
3033 if (pool == NULL
3034 || pool->symbol == NULL
3035 || pool->next_free_entry == 0)
b99bd4ef
NC
3036 return;
3037
69b97547
NC
3038 mapping_state (MAP_DATA);
3039
b99bd4ef
NC
3040 /* Align pool as you have word accesses.
3041 Only make a frag if we have to. */
3042 if (!need_pass_2)
3043 frag_align (2, 0, 0);
3044
3045 record_alignment (now_seg, 2);
3046
3d0c9500 3047 sprintf (sym_name, "$$lit_\002%x", pool->id);
b99bd4ef 3048
3d0c9500 3049 symbol_locate (pool->symbol, sym_name, now_seg,
b99bd4ef 3050 (valueT) frag_now_fix (), frag_now);
3d0c9500 3051 symbol_table_insert (pool->symbol);
b99bd4ef 3052
3d0c9500 3053 ARM_SET_THUMB (pool->symbol, thumb_mode);
b99bd4ef
NC
3054
3055#if defined OBJ_COFF || defined OBJ_ELF
3d0c9500 3056 ARM_SET_INTERWORK (pool->symbol, support_interwork);
b99bd4ef
NC
3057#endif
3058
3d0c9500 3059 for (entry = 0; entry < pool->next_free_entry; entry ++)
b99bd4ef 3060 /* First output the expression in the instruction to the pool. */
3d0c9500 3061 emit_expr (&(pool->literals[entry]), 4); /* .word */
b99bd4ef 3062
3d0c9500
NC
3063 /* Mark the pool as empty. */
3064 pool->next_free_entry = 0;
3065 pool->symbol = NULL;
b99bd4ef
NC
3066}
3067
3068/* Same as s_align_ptwo but align 0 => align 2. */
3069
3070static void
3071s_align (unused)
3072 int unused ATTRIBUTE_UNUSED;
3073{
3074 register int temp;
3075 register long temp_fill;
3076 long max_alignment = 15;
3077
3078 temp = get_absolute_expression ();
3079 if (temp > max_alignment)
f03698e6 3080 as_bad (_("alignment too large: %d assumed"), temp = max_alignment);
b99bd4ef
NC
3081 else if (temp < 0)
3082 {
f03698e6 3083 as_bad (_("alignment negative. 0 assumed."));
b99bd4ef
NC
3084 temp = 0;
3085 }
3086
3087 if (*input_line_pointer == ',')
3088 {
3089 input_line_pointer++;
3090 temp_fill = get_absolute_expression ();
3091 }
3092 else
3093 temp_fill = 0;
3094
3095 if (!temp)
3096 temp = 2;
3097
3098 /* Only make a frag if we HAVE to. */
3099 if (temp && !need_pass_2)
3100 frag_align (temp, (int) temp_fill, 0);
3101 demand_empty_rest_of_line ();
3102
3103 record_alignment (now_seg, temp);
3104}
3105
3106static void
3107s_force_thumb (ignore)
3108 int ignore ATTRIBUTE_UNUSED;
3109{
3110 /* If we are not already in thumb mode go into it, EVEN if
3111 the target processor does not support thumb instructions.
3112 This is used by gcc/config/arm/lib1funcs.asm for example
3113 to compile interworking support functions even if the
3114 target processor should not support interworking. */
3115 if (! thumb_mode)
3116 {
3117 thumb_mode = 2;
3118
3119 record_alignment (now_seg, 1);
3120 }
3121
3122 demand_empty_rest_of_line ();
3123}
3124
3125static void
3126s_thumb_func (ignore)
3127 int ignore ATTRIBUTE_UNUSED;
3128{
3129 if (! thumb_mode)
3130 opcode_select (16);
3131
3132 /* The following label is the name/address of the start of a Thumb function.
3133 We need to know this for the interworking support. */
b34976b6 3134 label_is_thumb_function_name = TRUE;
b99bd4ef
NC
3135
3136 demand_empty_rest_of_line ();
3137}
3138
3139/* Perform a .set directive, but also mark the alias as
3140 being a thumb function. */
3141
3142static void
3143s_thumb_set (equiv)
3144 int equiv;
3145{
3146 /* XXX the following is a duplicate of the code for s_set() in read.c
3147 We cannot just call that code as we need to get at the symbol that
3148 is created. */
3149 register char * name;
3150 register char delim;
3151 register char * end_name;
3152 register symbolS * symbolP;
3153
3154 /* Especial apologies for the random logic:
3155 This just grew, and could be parsed much more simply!
3156 Dean - in haste. */
3157 name = input_line_pointer;
3158 delim = get_symbol_end ();
3159 end_name = input_line_pointer;
3160 *end_name = delim;
3161
3162 SKIP_WHITESPACE ();
3163
3164 if (*input_line_pointer != ',')
3165 {
3166 *end_name = 0;
f03698e6 3167 as_bad (_("expected comma after name \"%s\""), name);
b99bd4ef
NC
3168 *end_name = delim;
3169 ignore_rest_of_line ();
3170 return;
3171 }
3172
3173 input_line_pointer++;
3174 *end_name = 0;
3175
3176 if (name[0] == '.' && name[1] == '\0')
3177 {
3178 /* XXX - this should not happen to .thumb_set. */
3179 abort ();
3180 }
3181
3182 if ((symbolP = symbol_find (name)) == NULL
3183 && (symbolP = md_undefined_symbol (name)) == NULL)
3184 {
3185#ifndef NO_LISTING
3186 /* When doing symbol listings, play games with dummy fragments living
3187 outside the normal fragment chain to record the file and line info
3188 for this symbol. */
3189 if (listing & LISTING_SYMBOLS)
3190 {
3191 extern struct list_info_struct * listing_tail;
3192 fragS * dummy_frag = (fragS *) xmalloc (sizeof (fragS));
3193
3194 memset (dummy_frag, 0, sizeof (fragS));
3195 dummy_frag->fr_type = rs_fill;
3196 dummy_frag->line = listing_tail;
3197 symbolP = symbol_new (name, undefined_section, 0, dummy_frag);
3198 dummy_frag->fr_symbol = symbolP;
3199 }
3200 else
3201#endif
3202 symbolP = symbol_new (name, undefined_section, 0, &zero_address_frag);
3203
3204#ifdef OBJ_COFF
3205 /* "set" symbols are local unless otherwise specified. */
3206 SF_SET_LOCAL (symbolP);
3207#endif /* OBJ_COFF */
3208 } /* Make a new symbol. */
3209
3210 symbol_table_insert (symbolP);
3211
3212 * end_name = delim;
3213
3214 if (equiv
3215 && S_IS_DEFINED (symbolP)
3216 && S_GET_SEGMENT (symbolP) != reg_section)
3217 as_bad (_("symbol `%s' already defined"), S_GET_NAME (symbolP));
3218
3219 pseudo_set (symbolP);
3220
3221 demand_empty_rest_of_line ();
3222
3223 /* XXX Now we come to the Thumb specific bit of code. */
3224
3225 THUMB_SET_FUNC (symbolP, 1);
3226 ARM_SET_THUMB (symbolP, 1);
3227#if defined OBJ_ELF || defined OBJ_COFF
3228 ARM_SET_INTERWORK (symbolP, support_interwork);
3229#endif
3230}
3231
b99bd4ef
NC
3232static void
3233opcode_select (width)
3234 int width;
3235{
3236 switch (width)
3237 {
3238 case 16:
3239 if (! thumb_mode)
3240 {
b89dddec 3241 if (! (cpu_variant & ARM_EXT_V4T))
b99bd4ef
NC
3242 as_bad (_("selected processor does not support THUMB opcodes"));
3243
3244 thumb_mode = 1;
3245 /* No need to force the alignment, since we will have been
3246 coming from ARM mode, which is word-aligned. */
3247 record_alignment (now_seg, 1);
3248 }
6057a28f 3249 mapping_state (MAP_THUMB);
b99bd4ef
NC
3250 break;
3251
3252 case 32:
3253 if (thumb_mode)
3254 {
03b1477f 3255 if ((cpu_variant & ARM_ALL) == ARM_EXT_V4T)
b99bd4ef
NC
3256 as_bad (_("selected processor does not support ARM opcodes"));
3257
3258 thumb_mode = 0;
3259
3260 if (!need_pass_2)
cc8a6dd0 3261 frag_align (2, 0, 0);
b99bd4ef 3262
cc8a6dd0 3263 record_alignment (now_seg, 1);
b99bd4ef 3264 }
6057a28f 3265 mapping_state (MAP_ARM);
b99bd4ef
NC
3266 break;
3267
3268 default:
3269 as_bad (_("invalid instruction size selected (%d)"), width);
3270 }
3271}
3272
3273static void
3274s_arm (ignore)
3275 int ignore ATTRIBUTE_UNUSED;
3276{
3277 opcode_select (32);
3278 demand_empty_rest_of_line ();
3279}
3280
3281static void
3282s_thumb (ignore)
3283 int ignore ATTRIBUTE_UNUSED;
3284{
3285 opcode_select (16);
3286 demand_empty_rest_of_line ();
3287}
3288
3289static void
3290s_code (unused)
3291 int unused ATTRIBUTE_UNUSED;
3292{
3293 register int temp;
3294
3295 temp = get_absolute_expression ();
3296 switch (temp)
3297 {
3298 case 16:
3299 case 32:
3300 opcode_select (temp);
3301 break;
3302
3303 default:
3304 as_bad (_("invalid operand to .code directive (%d) (expecting 16 or 32)"), temp);
3305 }
3306}
3307
3308static void
3309end_of_line (str)
f03698e6 3310 char *str;
b99bd4ef
NC
3311{
3312 skip_whitespace (str);
3313
f03698e6
RE
3314 if (*str != '\0' && !inst.error)
3315 inst.error = _("garbage following instruction");
b99bd4ef
NC
3316}
3317
3318static int
3319skip_past_comma (str)
3320 char ** str;
3321{
3322 char * p = * str, c;
3323 int comma = 0;
3324
3325 while ((c = *p) == ' ' || c == ',')
3326 {
3327 p++;
3328 if (c == ',' && comma++)
3329 return FAIL;
3330 }
3331
3332 if (c == '\0')
3333 return FAIL;
3334
3335 *str = p;
3336 return comma ? SUCCESS : FAIL;
3337}
3338
3339/* A standard register must be given at this point.
3340 SHIFT is the place to put it in inst.instruction.
3341 Restores input start point on error.
3342 Returns the reg#, or FAIL. */
3343
3344static int
3345reg_required_here (str, shift)
3346 char ** str;
3347 int shift;
3348{
3349 static char buff [128]; /* XXX */
3350 int reg;
3351 char * start = * str;
3352
6c43fab6 3353 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_RN].htab)) != FAIL)
b99bd4ef
NC
3354 {
3355 if (shift >= 0)
3356 inst.instruction |= reg << shift;
3357 return reg;
3358 }
3359
3360 /* Restore the start point, we may have got a reg of the wrong class. */
3361 *str = start;
3362
3363 /* In the few cases where we might be able to accept something else
3364 this error can be overridden. */
f03698e6 3365 sprintf (buff, _("register expected, not '%.100s'"), start);
b99bd4ef
NC
3366 inst.error = buff;
3367
3368 return FAIL;
3369}
3370
5a6c6817 3371/* A Intel Wireless MMX technology register
e16bb312
NC
3372 must be given at this point.
3373 Shift is the place to put it in inst.instruction.
3374 Restores input start point on err.
3375 Returns the reg#, or FAIL. */
3376
3377static int
3378wreg_required_here (str, shift, reg_type)
3379 char ** str;
3380 int shift;
3381 enum wreg_type reg_type;
3382{
3383 static char buff [128];
3384 int reg;
3385 char * start = *str;
3386
3387 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_IWMMXT].htab)) != FAIL)
3388 {
3389 if (wr_register (reg)
3390 && (reg_type == IWMMXT_REG_WR || reg_type == IWMMXT_REG_WR_OR_WC))
3391 {
3392 if (shift >= 0)
3393 inst.instruction |= (reg ^ WR_PREFIX) << shift;
3394 return reg;
3395 }
3396 else if (wc_register (reg)
3397 && (reg_type == IWMMXT_REG_WC || reg_type == IWMMXT_REG_WR_OR_WC))
3398 {
3399 if (shift >= 0)
3400 inst.instruction |= (reg ^ WC_PREFIX) << shift;
3401 return reg;
3402 }
3403 else if ((wcg_register (reg) && reg_type == IWMMXT_REG_WCG))
3404 {
3405 if (shift >= 0)
3406 inst.instruction |= ((reg ^ WC_PREFIX) - 8) << shift;
3407 return reg;
3408 }
3409 }
3410
3411 /* Restore the start point, we may have got a reg of the wrong class. */
3412 *str = start;
3413
3414 /* In the few cases where we might be able to accept
3415 something else this error can be overridden. */
5a6c6817 3416 sprintf (buff, _("Intel Wireless MMX technology register expected, not '%.100s'"), start);
e16bb312
NC
3417 inst.error = buff;
3418
3419 return FAIL;
3420}
3421
05d2d07e 3422static const struct asm_psr *
b99bd4ef
NC
3423arm_psr_parse (ccp)
3424 register char ** ccp;
3425{
3426 char * start = * ccp;
3427 char c;
3428 char * p;
05d2d07e 3429 const struct asm_psr * psr;
b99bd4ef
NC
3430
3431 p = start;
3432
3433 /* Skip to the end of the next word in the input stream. */
3434 do
3435 {
3436 c = *p++;
3437 }
3882b010 3438 while (ISALPHA (c) || c == '_');
b99bd4ef
NC
3439
3440 /* Terminate the word. */
3441 *--p = 0;
3442
3443 /* CPSR's and SPSR's can now be lowercase. This is just a convenience
3444 feature for ease of use and backwards compatibility. */
3445 if (!strncmp (start, "cpsr", 4))
3446 strncpy (start, "CPSR", 4);
3447 else if (!strncmp (start, "spsr", 4))
3448 strncpy (start, "SPSR", 4);
3449
3450 /* Now locate the word in the psr hash table. */
05d2d07e 3451 psr = (const struct asm_psr *) hash_find (arm_psr_hsh, start);
b99bd4ef
NC
3452
3453 /* Restore the input stream. */
3454 *p = c;
3455
3456 /* If we found a valid match, advance the
3457 stream pointer past the end of the word. */
3458 *ccp = p;
3459
3460 return psr;
3461}
3462
3463/* Parse the input looking for a PSR flag. */
3464
3465static int
3466psr_required_here (str)
3467 char ** str;
3468{
3469 char * start = * str;
05d2d07e 3470 const struct asm_psr * psr;
b99bd4ef
NC
3471
3472 psr = arm_psr_parse (str);
3473
3474 if (psr)
3475 {
3476 /* If this is the SPSR that is being modified, set the R bit. */
3477 if (! psr->cpsr)
3478 inst.instruction |= SPSR_BIT;
3479
3480 /* Set the psr flags in the MSR instruction. */
3481 inst.instruction |= psr->field << PSR_SHIFT;
3482
3483 return SUCCESS;
3484 }
3485
3486 /* In the few cases where we might be able to accept
3487 something else this error can be overridden. */
3488 inst.error = _("flag for {c}psr instruction expected");
3489
3490 /* Restore the start point. */
3491 *str = start;
3492 return FAIL;
3493}
3494
3495static int
3496co_proc_number (str)
6c43fab6 3497 char **str;
b99bd4ef
NC
3498{
3499 int processor, pchar;
6c43fab6 3500 char *start;
b99bd4ef 3501
6c43fab6
RE
3502 skip_whitespace (*str);
3503 start = *str;
b99bd4ef
NC
3504
3505 /* The data sheet seems to imply that just a number on its own is valid
3506 here, but the RISC iX assembler seems to accept a prefix 'p'. We will
3507 accept either. */
6c43fab6
RE
3508 if ((processor = arm_reg_parse (str, all_reg_maps[REG_TYPE_CP].htab))
3509 == FAIL)
b99bd4ef 3510 {
6c43fab6
RE
3511 *str = start;
3512
3513 pchar = *(*str)++;
3514 if (pchar >= '0' && pchar <= '9')
b99bd4ef 3515 {
6c43fab6
RE
3516 processor = pchar - '0';
3517 if (**str >= '0' && **str <= '9')
b99bd4ef 3518 {
6c43fab6
RE
3519 processor = processor * 10 + *(*str)++ - '0';
3520 if (processor > 15)
3521 {
f03698e6 3522 inst.error = _("illegal co-processor number");
6c43fab6
RE
3523 return FAIL;
3524 }
b99bd4ef
NC
3525 }
3526 }
6c43fab6
RE
3527 else
3528 {
376eb240 3529 inst.error = all_reg_maps[REG_TYPE_CP].expected;
6c43fab6
RE
3530 return FAIL;
3531 }
b99bd4ef
NC
3532 }
3533
3534 inst.instruction |= processor << 8;
3535 return SUCCESS;
3536}
3537
3538static int
3539cp_opc_expr (str, where, length)
3540 char ** str;
3541 int where;
3542 int length;
3543{
3544 expressionS expr;
3545
3546 skip_whitespace (* str);
3547
3548 memset (&expr, '\0', sizeof (expr));
3549
3550 if (my_get_expression (&expr, str))
3551 return FAIL;
3552 if (expr.X_op != O_constant)
3553 {
3554 inst.error = _("bad or missing expression");
3555 return FAIL;
3556 }
3557
3558 if ((expr.X_add_number & ((1 << length) - 1)) != expr.X_add_number)
3559 {
3560 inst.error = _("immediate co-processor expression too large");
3561 return FAIL;
3562 }
3563
3564 inst.instruction |= expr.X_add_number << where;
3565 return SUCCESS;
3566}
3567
3568static int
3569cp_reg_required_here (str, where)
3570 char ** str;
3571 int where;
3572{
3573 int reg;
3574 char * start = *str;
3575
6c43fab6 3576 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_CN].htab)) != FAIL)
b99bd4ef 3577 {
b99bd4ef
NC
3578 inst.instruction |= reg << where;
3579 return reg;
3580 }
3581
3582 /* In the few cases where we might be able to accept something else
3583 this error can be overridden. */
376eb240 3584 inst.error = all_reg_maps[REG_TYPE_CN].expected;
b99bd4ef
NC
3585
3586 /* Restore the start point. */
3587 *str = start;
3588 return FAIL;
3589}
3590
3591static int
3592fp_reg_required_here (str, where)
3593 char ** str;
3594 int where;
3595{
3596 int reg;
3597 char * start = * str;
3598
6c43fab6 3599 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_FN].htab)) != FAIL)
b99bd4ef 3600 {
b99bd4ef
NC
3601 inst.instruction |= reg << where;
3602 return reg;
3603 }
3604
3605 /* In the few cases where we might be able to accept something else
3606 this error can be overridden. */
376eb240 3607 inst.error = all_reg_maps[REG_TYPE_FN].expected;
b99bd4ef
NC
3608
3609 /* Restore the start point. */
3610 *str = start;
3611 return FAIL;
3612}
3613
3614static int
3615cp_address_offset (str)
3616 char ** str;
3617{
3618 int offset;
3619
3620 skip_whitespace (* str);
3621
3622 if (! is_immediate_prefix (**str))
3623 {
3624 inst.error = _("immediate expression expected");
3625 return FAIL;
3626 }
3627
3628 (*str)++;
3629
3630 if (my_get_expression (& inst.reloc.exp, str))
3631 return FAIL;
3632
3633 if (inst.reloc.exp.X_op == O_constant)
3634 {
3635 offset = inst.reloc.exp.X_add_number;
3636
3637 if (offset & 3)
3638 {
3639 inst.error = _("co-processor address must be word aligned");
3640 return FAIL;
3641 }
3642
3643 if (offset > 1023 || offset < -1023)
3644 {
3645 inst.error = _("offset too large");
3646 return FAIL;
3647 }
3648
3649 if (offset >= 0)
3650 inst.instruction |= INDEX_UP;
3651 else
3652 offset = -offset;
3653
3654 inst.instruction |= offset >> 2;
3655 }
3656 else
3657 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
3658
3659 return SUCCESS;
3660}
3661
3662static int
bfae80f2 3663cp_address_required_here (str, wb_ok)
b99bd4ef 3664 char ** str;
bfae80f2 3665 int wb_ok;
b99bd4ef
NC
3666{
3667 char * p = * str;
3668 int pre_inc = 0;
3669 int write_back = 0;
3670
3671 if (*p == '[')
3672 {
3673 int reg;
3674
3675 p++;
3676 skip_whitespace (p);
3677
3678 if ((reg = reg_required_here (& p, 16)) == FAIL)
3679 return FAIL;
3680
3681 skip_whitespace (p);
3682
3683 if (*p == ']')
3684 {
3685 p++;
3686
f02232aa
NC
3687 skip_whitespace (p);
3688
3689 if (*p == '\0')
b99bd4ef 3690 {
f02232aa
NC
3691 /* As an extension to the official ARM syntax we allow:
3692
3693 [Rn]
3694
3695 as a short hand for:
3696
3697 [Rn,#0] */
3698 inst.instruction |= PRE_INDEX | INDEX_UP;
3699 *str = p;
3700 return SUCCESS;
3701 }
3702
3703 if (skip_past_comma (& p) == FAIL)
3704 {
3705 inst.error = _("comma expected after closing square bracket");
3706 return FAIL;
3707 }
b99bd4ef 3708
f02232aa
NC
3709 skip_whitespace (p);
3710
3711 if (*p == '#')
3712 {
3713 if (wb_ok)
b99bd4ef 3714 {
f02232aa
NC
3715 /* [Rn], #expr */
3716 write_back = WRITE_BACK;
3717
3718 if (reg == REG_PC)
3719 {
3720 inst.error = _("pc may not be used in post-increment");
3721 return FAIL;
3722 }
3723
3724 if (cp_address_offset (& p) == FAIL)
3725 return FAIL;
b99bd4ef 3726 }
f02232aa
NC
3727 else
3728 pre_inc = PRE_INDEX | INDEX_UP;
3729 }
3730 else if (*p == '{')
3731 {
3732 int option;
b99bd4ef 3733
f02232aa
NC
3734 /* [Rn], {<expr>} */
3735 p++;
3736
3737 skip_whitespace (p);
3738
3739 if (my_get_expression (& inst.reloc.exp, & p))
b99bd4ef 3740 return FAIL;
f02232aa
NC
3741
3742 if (inst.reloc.exp.X_op == O_constant)
3743 {
3744 option = inst.reloc.exp.X_add_number;
3745
3746 if (option > 255 || option < 0)
3747 {
3748 inst.error = _("'option' field too large");
3749 return FAIL;
3750 }
3751
3752 skip_whitespace (p);
3753
3754 if (*p != '}')
3755 {
3756 inst.error = _("'}' expected at end of 'option' field");
3757 return FAIL;
3758 }
3759 else
3760 {
3761 p++;
3762 inst.instruction |= option;
3763 inst.instruction |= INDEX_UP;
3764 }
3765 }
3766 else
3767 {
3768 inst.error = _("non-constant expressions for 'option' field not supported");
3769 return FAIL;
3770 }
b99bd4ef
NC
3771 }
3772 else
f02232aa
NC
3773 {
3774 inst.error = _("# or { expected after comma");
3775 return FAIL;
3776 }
b99bd4ef
NC
3777 }
3778 else
3779 {
3780 /* '['Rn, #expr']'[!] */
3781
3782 if (skip_past_comma (& p) == FAIL)
3783 {
3784 inst.error = _("pre-indexed expression expected");
3785 return FAIL;
3786 }
3787
3788 pre_inc = PRE_INDEX;
3789
3790 if (cp_address_offset (& p) == FAIL)
3791 return FAIL;
3792
3793 skip_whitespace (p);
3794
3795 if (*p++ != ']')
3796 {
3797 inst.error = _("missing ]");
3798 return FAIL;
3799 }
3800
3801 skip_whitespace (p);
3802
bfae80f2 3803 if (wb_ok && *p == '!')
b99bd4ef
NC
3804 {
3805 if (reg == REG_PC)
3806 {
3807 inst.error = _("pc may not be used with write-back");
3808 return FAIL;
3809 }
3810
3811 p++;
3812 write_back = WRITE_BACK;
3813 }
3814 }
3815 }
3816 else
3817 {
3818 if (my_get_expression (&inst.reloc.exp, &p))
3819 return FAIL;
3820
3821 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
3822 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
3823 inst.reloc.pc_rel = 1;
3824 inst.instruction |= (REG_PC << 16);
3825 pre_inc = PRE_INDEX;
3826 }
3827
3828 inst.instruction |= write_back | pre_inc;
3829 *str = p;
3830 return SUCCESS;
3831}
3832
e16bb312
NC
3833static int
3834cp_byte_address_offset (str)
3835 char ** str;
3836{
3837 int offset;
3838
3839 skip_whitespace (* str);
3840
3841 if (! is_immediate_prefix (**str))
3842 {
3843 inst.error = _("immediate expression expected");
3844 return FAIL;
3845 }
3846
3847 (*str)++;
3848
3849 if (my_get_expression (& inst.reloc.exp, str))
3850 return FAIL;
3851
3852 if (inst.reloc.exp.X_op == O_constant)
3853 {
3854 offset = inst.reloc.exp.X_add_number;
3855
3856 if (offset > 255 || offset < -255)
3857 {
3858 inst.error = _("offset too large");
3859 return FAIL;
3860 }
3861
3862 if (offset >= 0)
3863 inst.instruction |= INDEX_UP;
3864 else
3865 offset = -offset;
3866
3867 inst.instruction |= offset;
3868 }
3869 else
3870 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM_S2;
3871
3872 return SUCCESS;
3873}
3874
3875static int
3876cp_byte_address_required_here (str)
3877 char ** str;
3878{
3879 char * p = * str;
3880 int pre_inc = 0;
3881 int write_back = 0;
3882
3883 if (*p == '[')
3884 {
3885 int reg;
3886
3887 p++;
3888 skip_whitespace (p);
3889
3890 if ((reg = reg_required_here (& p, 16)) == FAIL)
3891 return FAIL;
3892
3893 skip_whitespace (p);
3894
3895 if (*p == ']')
3896 {
3897 p++;
3898
3899 if (skip_past_comma (& p) == SUCCESS)
3900 {
3901 /* [Rn], #expr */
3902 write_back = WRITE_BACK;
3903
3904 if (reg == REG_PC)
3905 {
3906 inst.error = _("pc may not be used in post-increment");
3907 return FAIL;
3908 }
3909
3910 if (cp_byte_address_offset (& p) == FAIL)
3911 return FAIL;
3912 }
3913 else
3914 pre_inc = PRE_INDEX | INDEX_UP;
3915 }
3916 else
3917 {
3918 /* '['Rn, #expr']'[!] */
3919
3920 if (skip_past_comma (& p) == FAIL)
3921 {
3922 inst.error = _("pre-indexed expression expected");
3923 return FAIL;
3924 }
3925
3926 pre_inc = PRE_INDEX;
3927
3928 if (cp_byte_address_offset (& p) == FAIL)
3929 return FAIL;
3930
3931 skip_whitespace (p);
3932
3933 if (*p++ != ']')
3934 {
3935 inst.error = _("missing ]");
3936 return FAIL;
3937 }
3938
3939 skip_whitespace (p);
3940
3941 if (*p == '!')
3942 {
3943 if (reg == REG_PC)
3944 {
3945 inst.error = _("pc may not be used with write-back");
3946 return FAIL;
3947 }
3948
3949 p++;
3950 write_back = WRITE_BACK;
3951 }
3952 }
3953 }
3954 else
3955 {
3956 if (my_get_expression (&inst.reloc.exp, &p))
3957 return FAIL;
3958
3959 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM_S2;
3960 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
3961 inst.reloc.pc_rel = 1;
3962 inst.instruction |= (REG_PC << 16);
3963 pre_inc = PRE_INDEX;
3964 }
3965
3966 inst.instruction |= write_back | pre_inc;
3967 *str = p;
3968 return SUCCESS;
3969}
3970
b99bd4ef 3971static void
f2b7cb0a 3972do_empty (str)
b99bd4ef 3973 char * str;
b99bd4ef
NC
3974{
3975 /* Do nothing really. */
b99bd4ef 3976 end_of_line (str);
b99bd4ef
NC
3977}
3978
3979static void
f2b7cb0a 3980do_mrs (str)
b99bd4ef 3981 char *str;
b99bd4ef
NC
3982{
3983 int skip = 0;
3984
3985 /* Only one syntax. */
3986 skip_whitespace (str);
3987
3988 if (reg_required_here (&str, 12) == FAIL)
3989 {
3990 inst.error = BAD_ARGS;
3991 return;
3992 }
3993
3994 if (skip_past_comma (&str) == FAIL)
3995 {
3996 inst.error = _("comma expected after register name");
3997 return;
3998 }
3999
4000 skip_whitespace (str);
4001
4002 if ( strcmp (str, "CPSR") == 0
4003 || strcmp (str, "SPSR") == 0
2d2255b5 4004 /* Lower case versions for backwards compatibility. */
b99bd4ef
NC
4005 || strcmp (str, "cpsr") == 0
4006 || strcmp (str, "spsr") == 0)
4007 skip = 4;
4008
2d2255b5 4009 /* This is for backwards compatibility with older toolchains. */
b99bd4ef
NC
4010 else if ( strcmp (str, "cpsr_all") == 0
4011 || strcmp (str, "spsr_all") == 0)
4012 skip = 8;
4013 else
4014 {
f03698e6 4015 inst.error = _("CPSR or SPSR expected");
b99bd4ef
NC
4016 return;
4017 }
4018
4019 if (* str == 's' || * str == 'S')
4020 inst.instruction |= SPSR_BIT;
4021 str += skip;
4022
b99bd4ef
NC
4023 end_of_line (str);
4024}
4025
4026/* Two possible forms:
4027 "{C|S}PSR_<field>, Rm",
4028 "{C|S}PSR_f, #expression". */
4029
4030static void
f2b7cb0a 4031do_msr (str)
b99bd4ef 4032 char * str;
b99bd4ef
NC
4033{
4034 skip_whitespace (str);
4035
4036 if (psr_required_here (& str) == FAIL)
4037 return;
4038
4039 if (skip_past_comma (& str) == FAIL)
4040 {
4041 inst.error = _("comma missing after psr flags");
4042 return;
4043 }
4044
4045 skip_whitespace (str);
4046
4047 if (reg_required_here (& str, 0) != FAIL)
4048 {
4049 inst.error = NULL;
b99bd4ef
NC
4050 end_of_line (str);
4051 return;
4052 }
4053
4054 if (! is_immediate_prefix (* str))
4055 {
4056 inst.error =
4057 _("only a register or immediate value can follow a psr flag");
4058 return;
4059 }
4060
4061 str ++;
4062 inst.error = NULL;
4063
4064 if (my_get_expression (& inst.reloc.exp, & str))
4065 {
4066 inst.error =
4067 _("only a register or immediate value can follow a psr flag");
4068 return;
4069 }
4070
4071#if 0 /* The first edition of the ARM architecture manual stated that
4072 writing anything other than the flags with an immediate operation
4073 had UNPREDICTABLE effects. This constraint was removed in the
4074 second edition of the specification. */
4075 if ((cpu_variant & ARM_EXT_V5) != ARM_EXT_V5
4076 && inst.instruction & ((PSR_c | PSR_x | PSR_s) << PSR_SHIFT))
4077 {
4078 inst.error = _("immediate value cannot be used to set this field");
4079 return;
4080 }
4081#endif
4082
f2b7cb0a 4083 inst.instruction |= INST_IMMEDIATE;
b99bd4ef
NC
4084
4085 if (inst.reloc.exp.X_add_symbol)
4086 {
4087 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
4088 inst.reloc.pc_rel = 0;
4089 }
4090 else
4091 {
4092 unsigned value = validate_immediate (inst.reloc.exp.X_add_number);
4093
4094 if (value == (unsigned) FAIL)
4095 {
f03698e6 4096 inst.error = _("invalid constant");
b99bd4ef
NC
4097 return;
4098 }
4099
4100 inst.instruction |= value;
4101 }
4102
4103 inst.error = NULL;
b99bd4ef
NC
4104 end_of_line (str);
4105}
4106
4107/* Long Multiply Parser
4108 UMULL RdLo, RdHi, Rm, Rs
4109 SMULL RdLo, RdHi, Rm, Rs
4110 UMLAL RdLo, RdHi, Rm, Rs
4111 SMLAL RdLo, RdHi, Rm, Rs. */
4112
4113static void
f2b7cb0a 4114do_mull (str)
b99bd4ef 4115 char * str;
b99bd4ef
NC
4116{
4117 int rdlo, rdhi, rm, rs;
4118
4119 /* Only one format "rdlo, rdhi, rm, rs". */
4120 skip_whitespace (str);
4121
4122 if ((rdlo = reg_required_here (&str, 12)) == FAIL)
4123 {
4124 inst.error = BAD_ARGS;
4125 return;
4126 }
4127
4128 if (skip_past_comma (&str) == FAIL
4129 || (rdhi = reg_required_here (&str, 16)) == FAIL)
4130 {
4131 inst.error = BAD_ARGS;
4132 return;
4133 }
4134
4135 if (skip_past_comma (&str) == FAIL
4136 || (rm = reg_required_here (&str, 0)) == FAIL)
4137 {
4138 inst.error = BAD_ARGS;
4139 return;
4140 }
4141
4142 /* rdhi, rdlo and rm must all be different. */
4143 if (rdlo == rdhi || rdlo == rm || rdhi == rm)
4144 as_tsktsk (_("rdhi, rdlo and rm must all be different"));
4145
4146 if (skip_past_comma (&str) == FAIL
4147 || (rs = reg_required_here (&str, 8)) == FAIL)
4148 {
4149 inst.error = BAD_ARGS;
4150 return;
4151 }
4152
4153 if (rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC)
4154 {
4155 inst.error = BAD_PC;
4156 return;
4157 }
4158
b99bd4ef 4159 end_of_line (str);
b99bd4ef
NC
4160}
4161
4162static void
f2b7cb0a 4163do_mul (str)
b99bd4ef 4164 char * str;
b99bd4ef
NC
4165{
4166 int rd, rm;
4167
4168 /* Only one format "rd, rm, rs". */
4169 skip_whitespace (str);
4170
4171 if ((rd = reg_required_here (&str, 16)) == FAIL)
4172 {
4173 inst.error = BAD_ARGS;
4174 return;
4175 }
4176
4177 if (rd == REG_PC)
4178 {
4179 inst.error = BAD_PC;
4180 return;
4181 }
4182
4183 if (skip_past_comma (&str) == FAIL
4184 || (rm = reg_required_here (&str, 0)) == FAIL)
4185 {
4186 inst.error = BAD_ARGS;
4187 return;
4188 }
4189
4190 if (rm == REG_PC)
4191 {
4192 inst.error = BAD_PC;
4193 return;
4194 }
4195
4196 if (rm == rd)
4197 as_tsktsk (_("rd and rm should be different in mul"));
4198
4199 if (skip_past_comma (&str) == FAIL
4200 || (rm = reg_required_here (&str, 8)) == FAIL)
4201 {
4202 inst.error = BAD_ARGS;
4203 return;
4204 }
4205
4206 if (rm == REG_PC)
4207 {
4208 inst.error = BAD_PC;
4209 return;
4210 }
4211
b99bd4ef 4212 end_of_line (str);
b99bd4ef
NC
4213}
4214
4215static void
f2b7cb0a 4216do_mla (str)
b99bd4ef 4217 char * str;
b99bd4ef
NC
4218{
4219 int rd, rm;
4220
4221 /* Only one format "rd, rm, rs, rn". */
4222 skip_whitespace (str);
4223
4224 if ((rd = reg_required_here (&str, 16)) == FAIL)
4225 {
4226 inst.error = BAD_ARGS;
4227 return;
4228 }
4229
4230 if (rd == REG_PC)
4231 {
4232 inst.error = BAD_PC;
4233 return;
4234 }
4235
4236 if (skip_past_comma (&str) == FAIL
4237 || (rm = reg_required_here (&str, 0)) == FAIL)
4238 {
4239 inst.error = BAD_ARGS;
4240 return;
4241 }
4242
4243 if (rm == REG_PC)
4244 {
4245 inst.error = BAD_PC;
4246 return;
4247 }
4248
4249 if (rm == rd)
4250 as_tsktsk (_("rd and rm should be different in mla"));
4251
4252 if (skip_past_comma (&str) == FAIL
4253 || (rd = reg_required_here (&str, 8)) == FAIL
4254 || skip_past_comma (&str) == FAIL
4255 || (rm = reg_required_here (&str, 12)) == FAIL)
4256 {
4257 inst.error = BAD_ARGS;
4258 return;
4259 }
4260
4261 if (rd == REG_PC || rm == REG_PC)
4262 {
4263 inst.error = BAD_PC;
4264 return;
4265 }
4266
b99bd4ef 4267 end_of_line (str);
b99bd4ef
NC
4268}
4269
4270/* Expects *str -> the characters "acc0", possibly with leading blanks.
4271 Advances *str to the next non-alphanumeric.
4272 Returns 0, or else FAIL (in which case sets inst.error).
4273
4274 (In a future XScale, there may be accumulators other than zero.
4275 At that time this routine and its callers can be upgraded to suit.) */
4276
4277static int
4278accum0_required_here (str)
4279 char ** str;
4280{
4281 static char buff [128]; /* Note the address is taken. Hence, static. */
4282 char * p = * str;
4283 char c;
4284 int result = 0; /* The accum number. */
4285
4286 skip_whitespace (p);
4287
4288 *str = p; /* Advance caller's string pointer too. */
4289 c = *p++;
3882b010 4290 while (ISALNUM (c))
b99bd4ef
NC
4291 c = *p++;
4292
4293 *--p = 0; /* Aap nul into input buffer at non-alnum. */
4294
4295 if (! ( streq (*str, "acc0") || streq (*str, "ACC0")))
4296 {
4297 sprintf (buff, _("acc0 expected, not '%.100s'"), *str);
4298 inst.error = buff;
4299 result = FAIL;
4300 }
4301
4302 *p = c; /* Unzap. */
4303 *str = p; /* Caller's string pointer to after match. */
4304 return result;
4305}
4306
4307/* Expects **str -> after a comma. May be leading blanks.
4308 Advances *str, recognizing a load mode, and setting inst.instruction.
4309 Returns rn, or else FAIL (in which case may set inst.error
4310 and not advance str)
4311
4312 Note: doesn't know Rd, so no err checks that require such knowledge. */
4313
4314static int
4315ld_mode_required_here (string)
4316 char ** string;
4317{
4318 char * str = * string;
4319 int rn;
4320 int pre_inc = 0;
4321
4322 skip_whitespace (str);
4323
4324 if (* str == '[')
4325 {
4326 str++;
4327
4328 skip_whitespace (str);
4329
4330 if ((rn = reg_required_here (& str, 16)) == FAIL)
4331 return FAIL;
4332
4333 skip_whitespace (str);
4334
4335 if (* str == ']')
4336 {
4337 str ++;
4338
4339 if (skip_past_comma (& str) == SUCCESS)
4340 {
4341 /* [Rn],... (post inc) */
90e4755a 4342 if (ldst_extend_v4 (&str) == FAIL)
b99bd4ef
NC
4343 return FAIL;
4344 }
4345 else /* [Rn] */
4346 {
cc8a6dd0 4347 skip_whitespace (str);
b99bd4ef 4348
cc8a6dd0
KH
4349 if (* str == '!')
4350 {
4351 str ++;
4352 inst.instruction |= WRITE_BACK;
4353 }
b99bd4ef
NC
4354
4355 inst.instruction |= INDEX_UP | HWOFFSET_IMM;
4356 pre_inc = 1;
4357 }
4358 }
4359 else /* [Rn,...] */
4360 {
4361 if (skip_past_comma (& str) == FAIL)
4362 {
4363 inst.error = _("pre-indexed expression expected");
4364 return FAIL;
4365 }
4366
4367 pre_inc = 1;
4368
90e4755a 4369 if (ldst_extend_v4 (&str) == FAIL)
b99bd4ef
NC
4370 return FAIL;
4371
4372 skip_whitespace (str);
4373
4374 if (* str ++ != ']')
4375 {
4376 inst.error = _("missing ]");
4377 return FAIL;
4378 }
4379
4380 skip_whitespace (str);
4381
4382 if (* str == '!')
4383 {
4384 str ++;
4385 inst.instruction |= WRITE_BACK;
4386 }
4387 }
4388 }
4389 else if (* str == '=') /* ldr's "r,=label" syntax */
4390 /* We should never reach here, because <text> = <expression> is
4391 caught gas/read.c read_a_source_file() as a .set operation. */
4392 return FAIL;
4393 else /* PC +- 8 bit immediate offset. */
4394 {
4395 if (my_get_expression (& inst.reloc.exp, & str))
4396 return FAIL;
4397
4398 inst.instruction |= HWOFFSET_IMM; /* The I bit. */
4399 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
4400 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
4401 inst.reloc.pc_rel = 1;
4402 inst.instruction |= (REG_PC << 16);
4403
4404 rn = REG_PC;
4405 pre_inc = 1;
4406 }
4407
4408 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
4409 * string = str;
4410
4411 return rn;
4412}
4413
4414/* ARM V5E (El Segundo) signed-multiply-accumulate (argument parse)
4415 SMLAxy{cond} Rd,Rm,Rs,Rn
4416 SMLAWy{cond} Rd,Rm,Rs,Rn
4417 Error if any register is R15. */
4418
4419static void
f2b7cb0a 4420do_smla (str)
b99bd4ef 4421 char * str;
b99bd4ef
NC
4422{
4423 int rd, rm, rs, rn;
4424
4425 skip_whitespace (str);
4426
4427 if ((rd = reg_required_here (& str, 16)) == FAIL
4428 || skip_past_comma (& str) == FAIL
4429 || (rm = reg_required_here (& str, 0)) == FAIL
4430 || skip_past_comma (& str) == FAIL
4431 || (rs = reg_required_here (& str, 8)) == FAIL
4432 || skip_past_comma (& str) == FAIL
4433 || (rn = reg_required_here (& str, 12)) == FAIL)
4434 inst.error = BAD_ARGS;
4435
4436 else if (rd == REG_PC || rm == REG_PC || rs == REG_PC || rn == REG_PC)
4437 inst.error = BAD_PC;
4438
b99bd4ef
NC
4439 else
4440 end_of_line (str);
4441}
4442
4443/* ARM V5E (El Segundo) signed-multiply-accumulate-long (argument parse)
4444 SMLALxy{cond} Rdlo,Rdhi,Rm,Rs
4445 Error if any register is R15.
4446 Warning if Rdlo == Rdhi. */
4447
4448static void
f2b7cb0a 4449do_smlal (str)
b99bd4ef 4450 char * str;
b99bd4ef
NC
4451{
4452 int rdlo, rdhi, rm, rs;
4453
4454 skip_whitespace (str);
4455
4456 if ((rdlo = reg_required_here (& str, 12)) == FAIL
4457 || skip_past_comma (& str) == FAIL
4458 || (rdhi = reg_required_here (& str, 16)) == FAIL
4459 || skip_past_comma (& str) == FAIL
4460 || (rm = reg_required_here (& str, 0)) == FAIL
4461 || skip_past_comma (& str) == FAIL
4462 || (rs = reg_required_here (& str, 8)) == FAIL)
4463 {
4464 inst.error = BAD_ARGS;
4465 return;
4466 }
4467
4468 if (rdlo == REG_PC || rdhi == REG_PC || rm == REG_PC || rs == REG_PC)
4469 {
4470 inst.error = BAD_PC;
4471 return;
4472 }
4473
4474 if (rdlo == rdhi)
4475 as_tsktsk (_("rdhi and rdlo must be different"));
4476
f2b7cb0a 4477 end_of_line (str);
b99bd4ef
NC
4478}
4479
4480/* ARM V5E (El Segundo) signed-multiply (argument parse)
4481 SMULxy{cond} Rd,Rm,Rs
4482 Error if any register is R15. */
4483
4484static void
f2b7cb0a 4485do_smul (str)
b99bd4ef 4486 char * str;
b99bd4ef
NC
4487{
4488 int rd, rm, rs;
4489
4490 skip_whitespace (str);
4491
4492 if ((rd = reg_required_here (& str, 16)) == FAIL
4493 || skip_past_comma (& str) == FAIL
4494 || (rm = reg_required_here (& str, 0)) == FAIL
4495 || skip_past_comma (& str) == FAIL
4496 || (rs = reg_required_here (& str, 8)) == FAIL)
4497 inst.error = BAD_ARGS;
4498
4499 else if (rd == REG_PC || rm == REG_PC || rs == REG_PC)
4500 inst.error = BAD_PC;
4501
b99bd4ef
NC
4502 else
4503 end_of_line (str);
4504}
4505
4506/* ARM V5E (El Segundo) saturating-add/subtract (argument parse)
4507 Q[D]{ADD,SUB}{cond} Rd,Rm,Rn
4508 Error if any register is R15. */
4509
4510static void
f2b7cb0a 4511do_qadd (str)
b99bd4ef 4512 char * str;
b99bd4ef
NC
4513{
4514 int rd, rm, rn;
4515
4516 skip_whitespace (str);
4517
4518 if ((rd = reg_required_here (& str, 12)) == FAIL
4519 || skip_past_comma (& str) == FAIL
4520 || (rm = reg_required_here (& str, 0)) == FAIL
4521 || skip_past_comma (& str) == FAIL
4522 || (rn = reg_required_here (& str, 16)) == FAIL)
4523 inst.error = BAD_ARGS;
4524
4525 else if (rd == REG_PC || rm == REG_PC || rn == REG_PC)
4526 inst.error = BAD_PC;
4527
b99bd4ef
NC
4528 else
4529 end_of_line (str);
4530}
4531
4532/* ARM V5E (el Segundo)
4533 MCRRcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
4534 MRRCcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
4535
4536 These are equivalent to the XScale instructions MAR and MRA,
4537 respectively, when coproc == 0, opcode == 0, and CRm == 0.
4538
4539 Result unpredicatable if Rd or Rn is R15. */
4540
4541static void
f2b7cb0a 4542do_co_reg2c (str)
b99bd4ef 4543 char * str;
b99bd4ef
NC
4544{
4545 int rd, rn;
4546
4547 skip_whitespace (str);
4548
4549 if (co_proc_number (& str) == FAIL)
4550 {
4551 if (!inst.error)
4552 inst.error = BAD_ARGS;
4553 return;
4554 }
4555
4556 if (skip_past_comma (& str) == FAIL
4557 || cp_opc_expr (& str, 4, 4) == FAIL)
4558 {
4559 if (!inst.error)
4560 inst.error = BAD_ARGS;
4561 return;
4562 }
4563
4564 if (skip_past_comma (& str) == FAIL
4565 || (rd = reg_required_here (& str, 12)) == FAIL)
4566 {
4567 if (!inst.error)
4568 inst.error = BAD_ARGS;
4569 return;
4570 }
4571
4572 if (skip_past_comma (& str) == FAIL
4573 || (rn = reg_required_here (& str, 16)) == FAIL)
4574 {
4575 if (!inst.error)
4576 inst.error = BAD_ARGS;
4577 return;
4578 }
4579
09d92015
MM
4580 /* Unpredictable result if rd or rn is R15. */
4581 if (rd == REG_PC || rn == REG_PC)
4582 as_tsktsk
4583 (_("Warning: instruction unpredictable when using r15"));
4584
4585 if (skip_past_comma (& str) == FAIL
4586 || cp_reg_required_here (& str, 0) == FAIL)
4587 {
4588 if (!inst.error)
4589 inst.error = BAD_ARGS;
4590 return;
4591 }
4592
4593 end_of_line (str);
4594}
4595
4596/* ARM V5 count-leading-zeroes instruction (argument parse)
4597 CLZ{<cond>} <Rd>, <Rm>
4598 Condition defaults to COND_ALWAYS.
4599 Error if Rd or Rm are R15. */
4600
4601static void
4602do_clz (str)
4603 char * str;
4604{
4605 int rd, rm;
4606
4607 skip_whitespace (str);
4608
4609 if (((rd = reg_required_here (& str, 12)) == FAIL)
4610 || (skip_past_comma (& str) == FAIL)
4611 || ((rm = reg_required_here (& str, 0)) == FAIL))
4612 inst.error = BAD_ARGS;
4613
4614 else if (rd == REG_PC || rm == REG_PC )
4615 inst.error = BAD_PC;
4616
4617 else
4618 end_of_line (str);
4619}
4620
4621/* ARM V5 (argument parse)
4622 LDC2{L} <coproc>, <CRd>, <addressing mode>
4623 STC2{L} <coproc>, <CRd>, <addressing mode>
4624 Instruction is not conditional, and has 0xf in the condition field.
4625 Otherwise, it's the same as LDC/STC. */
4626
4627static void
4628do_lstc2 (str)
4629 char * str;
4630{
4631 skip_whitespace (str);
4632
4633 if (co_proc_number (& str) == FAIL)
4634 {
4635 if (!inst.error)
4636 inst.error = BAD_ARGS;
4637 }
4638 else if (skip_past_comma (& str) == FAIL
4639 || cp_reg_required_here (& str, 12) == FAIL)
4640 {
4641 if (!inst.error)
4642 inst.error = BAD_ARGS;
4643 }
4644 else if (skip_past_comma (& str) == FAIL
4645 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
4646 {
4647 if (! inst.error)
4648 inst.error = BAD_ARGS;
4649 }
4650 else
4651 end_of_line (str);
4652}
4653
4654/* ARM V5 (argument parse)
4655 CDP2 <coproc>, <opcode_1>, <CRd>, <CRn>, <CRm>, <opcode_2>
4656 Instruction is not conditional, and has 0xf in the condition field.
4657 Otherwise, it's the same as CDP. */
4658
4659static void
4660do_cdp2 (str)
4661 char * str;
4662{
4663 skip_whitespace (str);
4664
4665 if (co_proc_number (& str) == FAIL)
4666 {
4667 if (!inst.error)
4668 inst.error = BAD_ARGS;
4669 return;
4670 }
4671
4672 if (skip_past_comma (& str) == FAIL
4673 || cp_opc_expr (& str, 20,4) == FAIL)
4674 {
4675 if (!inst.error)
4676 inst.error = BAD_ARGS;
4677 return;
4678 }
4679
4680 if (skip_past_comma (& str) == FAIL
4681 || cp_reg_required_here (& str, 12) == FAIL)
4682 {
4683 if (!inst.error)
4684 inst.error = BAD_ARGS;
4685 return;
4686 }
4687
4688 if (skip_past_comma (& str) == FAIL
4689 || cp_reg_required_here (& str, 16) == FAIL)
4690 {
4691 if (!inst.error)
4692 inst.error = BAD_ARGS;
4693 return;
4694 }
4695
4696 if (skip_past_comma (& str) == FAIL
4697 || cp_reg_required_here (& str, 0) == FAIL)
4698 {
4699 if (!inst.error)
4700 inst.error = BAD_ARGS;
4701 return;
4702 }
4703
4704 if (skip_past_comma (& str) == SUCCESS)
4705 {
4706 if (cp_opc_expr (& str, 5, 3) == FAIL)
4707 {
4708 if (!inst.error)
4709 inst.error = BAD_ARGS;
4710 return;
4711 }
4712 }
4713
4714 end_of_line (str);
4715}
4716
4717/* ARM V5 (argument parse)
4718 MCR2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
4719 MRC2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
4720 Instruction is not conditional, and has 0xf in the condition field.
4721 Otherwise, it's the same as MCR/MRC. */
4722
4723static void
4724do_co_reg2 (str)
4725 char * str;
4726{
4727 skip_whitespace (str);
4728
4729 if (co_proc_number (& str) == FAIL)
4730 {
4731 if (!inst.error)
4732 inst.error = BAD_ARGS;
4733 return;
4734 }
4735
4736 if (skip_past_comma (& str) == FAIL
4737 || cp_opc_expr (& str, 21, 3) == FAIL)
4738 {
4739 if (!inst.error)
4740 inst.error = BAD_ARGS;
4741 return;
4742 }
4743
4744 if (skip_past_comma (& str) == FAIL
4745 || reg_required_here (& str, 12) == FAIL)
4746 {
4747 if (!inst.error)
4748 inst.error = BAD_ARGS;
4749 return;
4750 }
4751
4752 if (skip_past_comma (& str) == FAIL
4753 || cp_reg_required_here (& str, 16) == FAIL)
4754 {
4755 if (!inst.error)
4756 inst.error = BAD_ARGS;
4757 return;
4758 }
4759
4760 if (skip_past_comma (& str) == FAIL
4761 || cp_reg_required_here (& str, 0) == FAIL)
4762 {
4763 if (!inst.error)
4764 inst.error = BAD_ARGS;
4765 return;
4766 }
4767
4768 if (skip_past_comma (& str) == SUCCESS)
4769 {
4770 if (cp_opc_expr (& str, 5, 3) == FAIL)
4771 {
4772 if (!inst.error)
4773 inst.error = BAD_ARGS;
4774 return;
4775 }
4776 }
4777
4778 end_of_line (str);
4779}
4780
4781/* ARM v5TEJ. Jump to Jazelle code. */
4782static void
4783do_bxj (str)
4784 char * str;
4785{
4786 int reg;
4787
4788 skip_whitespace (str);
4789
4790 if ((reg = reg_required_here (&str, 0)) == FAIL)
4791 {
4792 inst.error = BAD_ARGS;
4793 return;
4794 }
4795
4796 /* Note - it is not illegal to do a "bxj pc". Useless, but not illegal. */
4797 if (reg == REG_PC)
4798 as_tsktsk (_("use of r15 in bxj is not really useful"));
4799
4800 end_of_line (str);
4801}
4802
4803/* ARM V6 umaal (argument parse). */
4804
4805static void
4806do_umaal (str)
4807 char *str;
4808{
4809
4810 int rdlo, rdhi, rm, rs;
4811
4812 skip_whitespace (str);
4813 if ((rdlo = reg_required_here (& str, 12)) == FAIL
4814 || skip_past_comma (& str) == FAIL
4815 || (rdhi = reg_required_here (& str, 16)) == FAIL
4816 || skip_past_comma (& str) == FAIL
4817 || (rm = reg_required_here (& str, 0)) == FAIL
4818 || skip_past_comma (& str) == FAIL
5533419b 4819 || (rs = reg_required_here (& str, 8)) == FAIL)
09d92015
MM
4820 {
4821 inst.error = BAD_ARGS;
4822 return;
4823 }
4824
4825 if (rdlo == REG_PC || rdhi == REG_PC || rm == REG_PC || rs == REG_PC)
4826 {
4827 inst.error = BAD_PC;
4828 return;
4829 }
4830
4831 end_of_line (str);
4832}
4833
4834/* ARM V6 strex (argument parse). */
4835
4836static void
4837do_strex (str)
4838 char *str;
4839{
4840 int rd, rm, rn;
4841
4842 /* Parse Rd, Rm,. */
4843 skip_whitespace (str);
4844 if ((rd = reg_required_here (& str, 12)) == FAIL
4845 || skip_past_comma (& str) == FAIL
4846 || (rm = reg_required_here (& str, 0)) == FAIL
4847 || skip_past_comma (& str) == FAIL)
4848 {
4849 inst.error = BAD_ARGS;
4850 return;
4851 }
4852 if (rd == REG_PC || rm == REG_PC)
4853 {
4854 inst.error = BAD_PC;
4855 return;
4856 }
4857 if (rd == rm)
4858 {
4859 inst.error = _("Rd equal to Rm or Rn yields unpredictable results");
4860 return;
4861 }
4862
4863 /* Skip past '['. */
4864 if ((strlen (str) >= 1)
4865 && strncmp (str, "[", 1) == 0)
4866 str+=1;
4867 skip_whitespace (str);
4868
4869 /* Parse Rn. */
4870 if ((rn = reg_required_here (& str, 16)) == FAIL)
4871 {
4872 inst.error = BAD_ARGS;
4873 return;
4874 }
4875 else if (rn == REG_PC)
4876 {
4877 inst.error = BAD_PC;
4878 return;
4879 }
4880 if (rd == rn)
4881 {
4882 inst.error = _("Rd equal to Rm or Rn yields unpredictable results");
4883 return;
4884 }
4885 skip_whitespace (str);
4886
4887 /* Skip past ']'. */
4888 if ((strlen (str) >= 1)
4889 && strncmp (str, "]", 1) == 0)
4890 str+=1;
4891
4892 end_of_line (str);
4893}
4894
4895/* ARM V6 ssat (argument parse). */
4896
4897static void
4898do_ssat (str)
4899 char* str;
4900{
4901 do_sat (&str, /*bias=*/-1);
4902 end_of_line (str);
4903}
4904
4905/* ARM V6 usat (argument parse). */
4906
4907static void
4908do_usat (str)
4909 char* str;
4910{
4911 do_sat (&str, /*bias=*/0);
4912 end_of_line (str);
4913}
4914
4915static void
4916do_sat (str, bias)
4917 char **str;
4918 int bias;
4919{
4920 int rd, rm;
4921 expressionS expr;
4922
4923 skip_whitespace (*str);
4924
4925 /* Parse <Rd>, field. */
4926 if ((rd = reg_required_here (str, 12)) == FAIL
4927 || skip_past_comma (str) == FAIL)
4928 {
4929 inst.error = BAD_ARGS;
4930 return;
4931 }
4932 if (rd == REG_PC)
4933 {
4934 inst.error = BAD_PC;
4935 return;
4936 }
4937
4938 /* Parse #<immed>, field. */
4939 if (is_immediate_prefix (**str))
4940 (*str)++;
4941 else
4942 {
4943 inst.error = _("immediate expression expected");
4944 return;
4945 }
4946 if (my_get_expression (&expr, str))
4947 {
4948 inst.error = _("bad expression");
4949 return;
4950 }
4951 if (expr.X_op != O_constant)
4952 {
4953 inst.error = _("constant expression expected");
4954 return;
4955 }
4956 if (expr.X_add_number + bias < 0
4957 || expr.X_add_number + bias > 31)
4958 {
4959 inst.error = _("immediate value out of range");
4960 return;
4961 }
4962 inst.instruction |= (expr.X_add_number + bias) << 16;
4963 if (skip_past_comma (str) == FAIL)
4964 {
4965 inst.error = BAD_ARGS;
4966 return;
4967 }
4968
4969 /* Parse <Rm> field. */
4970 if ((rm = reg_required_here (str, 0)) == FAIL)
4971 {
4972 inst.error = BAD_ARGS;
4973 return;
4974 }
4975 if (rm == REG_PC)
4976 {
4977 inst.error = BAD_PC;
4978 return;
4979 }
4980
4981 if (skip_past_comma (str) == SUCCESS)
4982 decode_shift (str, SHIFT_LSL_OR_ASR_IMMEDIATE);
4983}
4984
4985/* ARM V6 ssat16 (argument parse). */
4986
4987static void
4988do_ssat16 (str)
4989 char *str;
4990{
4991 do_sat16 (&str, /*bias=*/-1);
4992 end_of_line (str);
4993}
4994
4995static void
4996do_usat16 (str)
4997 char *str;
4998{
4999 do_sat16 (&str, /*bias=*/0);
5000 end_of_line (str);
5001}
5002
5003static void
5004do_sat16 (str, bias)
5005 char **str;
5006 int bias;
5007{
5008 int rd, rm;
5009 expressionS expr;
5010
5011 skip_whitespace (*str);
5012
5013 /* Parse the <Rd> field. */
5014 if ((rd = reg_required_here (str, 12)) == FAIL
5015 || skip_past_comma (str) == FAIL)
5016 {
5017 inst.error = BAD_ARGS;
5018 return;
5019 }
5020 if (rd == REG_PC)
5021 {
5022 inst.error = BAD_PC;
5023 return;
5024 }
5025
5026 /* Parse #<immed>, field. */
5027 if (is_immediate_prefix (**str))
5028 (*str)++;
5029 else
5030 {
5031 inst.error = _("immediate expression expected");
5032 return;
5033 }
5034 if (my_get_expression (&expr, str))
5035 {
5036 inst.error = _("bad expression");
5037 return;
5038 }
5039 if (expr.X_op != O_constant)
5040 {
5041 inst.error = _("constant expression expected");
5042 return;
5043 }
5044 if (expr.X_add_number + bias < 0
5045 || expr.X_add_number + bias > 15)
5046 {
5047 inst.error = _("immediate value out of range");
5048 return;
5049 }
5050 inst.instruction |= (expr.X_add_number + bias) << 16;
5051 if (skip_past_comma (str) == FAIL)
5052 {
5053 inst.error = BAD_ARGS;
5054 return;
5055 }
5056
5057 /* Parse <Rm> field. */
5058 if ((rm = reg_required_here (str, 0)) == FAIL)
5059 {
5060 inst.error = BAD_ARGS;
5061 return;
5062 }
5063 if (rm == REG_PC)
5064 {
5065 inst.error = BAD_PC;
5066 return;
5067 }
5068}
5069
5070/* ARM V6 srs (argument parse). */
5071
5072static void
5073do_srs (str)
5074 char* str;
5075{
5076 char *exclam;
5077 skip_whitespace (str);
5078 exclam = strchr (str, '!');
5079 if (exclam)
5080 *exclam = '\0';
5081 do_cps_mode (&str);
5082 if (exclam)
5083 *exclam = '!';
5084 if (*str == '!')
5085 {
5086 inst.instruction |= WRITE_BACK;
5087 str++;
5088 }
5089 end_of_line (str);
5090}
5091
5092/* ARM V6 SMMUL (argument parse). */
5093
5094static void
5095do_smmul (str)
5096 char* str;
5097{
5098 int rd, rm, rs;
5099
5100 skip_whitespace (str);
5101 if ((rd = reg_required_here (&str, 16)) == FAIL
5102 || skip_past_comma (&str) == FAIL
5103 || (rm = reg_required_here (&str, 0)) == FAIL
5104 || skip_past_comma (&str) == FAIL
5105 || (rs = reg_required_here (&str, 8)) == FAIL)
5106 {
5107 inst.error = BAD_ARGS;
5108 return;
5109 }
5110
5111 if (rd == REG_PC
5112 || rm == REG_PC
5113 || rs == REG_PC)
5114 {
5115 inst.error = BAD_PC;
5116 return;
5117 }
5118
5119 end_of_line (str);
5120
5121}
5122
5123/* ARM V6 SMLALD (argument parse). */
5124
5125static void
5126do_smlald (str)
5127 char* str;
5128{
5129 int rdlo, rdhi, rm, rs;
5130 skip_whitespace (str);
5131 if ((rdlo = reg_required_here (&str, 12)) == FAIL
5132 || skip_past_comma (&str) == FAIL
5133 || (rdhi = reg_required_here (&str, 16)) == FAIL
5134 || skip_past_comma (&str) == FAIL
5135 || (rm = reg_required_here (&str, 0)) == FAIL
5136 || skip_past_comma (&str) == FAIL
5137 || (rs = reg_required_here (&str, 8)) == FAIL)
5138 {
5139 inst.error = BAD_ARGS;
5140 return;
5141 }
5142
5143 if (rdlo == REG_PC
5144 || rdhi == REG_PC
5145 || rm == REG_PC
5146 || rs == REG_PC)
5147 {
5148 inst.error = BAD_PC;
5149 return;
5150 }
5151
5152 end_of_line (str);
5153}
5154
5155/* ARM V6 SMLAD (argument parse). Signed multiply accumulate dual.
5156 smlad{x}{<cond>} Rd, Rm, Rs, Rn */
5157
5158static void
5159do_smlad (str)
5160 char *str;
5161{
5162 int rd, rm, rs, rn;
5163
5164 skip_whitespace (str);
5165 if ((rd = reg_required_here (&str, 16)) == FAIL
5166 || skip_past_comma (&str) == FAIL
5167 || (rm = reg_required_here (&str, 0)) == FAIL
5168 || skip_past_comma (&str) == FAIL
5169 || (rs = reg_required_here (&str, 8)) == FAIL
5170 || skip_past_comma (&str) == FAIL
5171 || (rn = reg_required_here (&str, 12)) == FAIL)
5172 {
5173 inst.error = BAD_ARGS;
5174 return;
5175 }
5176
5177 if (rd == REG_PC
5178 || rn == REG_PC
5179 || rs == REG_PC
5180 || rm == REG_PC)
5181 {
5182 inst.error = BAD_PC;
5183 return;
5184 }
5185
5186 end_of_line (str);
5187}
5188
5189/* ARM V6 SETEND (argument parse). Sets the E bit in the CPSR while
5190 preserving the other bits.
5191
5192 setend <endian_specifier>, where <endian_specifier> is either
5193 BE or LE. */
5194
5195static void
5196do_setend (str)
5197 char *str;
5198{
5199 if (do_endian_specifier (str))
5200 inst.instruction |= 0x200;
5201}
5202
5203/* Returns true if the endian-specifier indicates big-endianness. */
5204
5205static int
5206do_endian_specifier (str)
5207 char *str;
5208{
5209 int big_endian = 0;
5210
5211 skip_whitespace (str);
5212 if (strlen (str) < 2)
5213 inst.error = _("missing endian specifier");
5214 else if (strncasecmp (str, "BE", 2) == 0)
5215 {
5216 str += 2;
5217 big_endian = 1;
5218 }
5219 else if (strncasecmp (str, "LE", 2) == 0)
5220 str += 2;
5221 else
5222 inst.error = _("valid endian specifiers are be or le");
5223
5224 end_of_line (str);
5225
5226 return big_endian;
5227}
5228
5229/* ARM V6 SXTH.
5230
5231 SXTH {<cond>} <Rd>, <Rm>{, <rotation>}
5232 Condition defaults to COND_ALWAYS.
5233 Error if any register uses R15. */
5234
5235static void
5236do_sxth (str)
5237 char *str;
5238{
5239 int rd, rm;
5240 expressionS expr;
5241 int rotation_clear_mask = 0xfffff3ff;
5242 int rotation_eight_mask = 0x00000400;
5243 int rotation_sixteen_mask = 0x00000800;
5244 int rotation_twenty_four_mask = 0x00000c00;
5245
5246 skip_whitespace (str);
5247 if ((rd = reg_required_here (&str, 12)) == FAIL
5248 || skip_past_comma (&str) == FAIL
5249 || (rm = reg_required_here (&str, 0)) == FAIL)
5250 {
5251 inst.error = BAD_ARGS;
5252 return;
5253 }
5254
5255 else if (rd == REG_PC || rm == REG_PC)
5256 {
5257 inst.error = BAD_PC;
5258 return;
5259 }
5260
5261 /* Zero out the rotation field. */
5262 inst.instruction &= rotation_clear_mask;
5263
5264 /* Check for lack of optional rotation field. */
5265 if (skip_past_comma (&str) == FAIL)
5266 {
5267 end_of_line (str);
5268 return;
5269 }
5270
5271 /* Move past 'ROR'. */
5272 skip_whitespace (str);
5273 if (strncasecmp (str, "ROR", 3) == 0)
5274 str+=3;
5275 else
5276 {
5277 inst.error = _("missing rotation field after comma");
5278 return;
5279 }
5280
5281 /* Get the immediate constant. */
5282 skip_whitespace (str);
5283 if (is_immediate_prefix (* str))
5284 str++;
5285 else
5286 {
5287 inst.error = _("immediate expression expected");
5288 return;
5289 }
5290
5291 if (my_get_expression (&expr, &str))
5292 {
5293 inst.error = _("bad expression");
5294 return;
5295 }
5296
5297 if (expr.X_op != O_constant)
5298 {
5299 inst.error = _("constant expression expected");
5300 return;
5301 }
5302
5303 switch (expr.X_add_number)
5304 {
5305 case 0:
5306 /* Rotation field has already been zeroed. */
5307 break;
5308 case 8:
5309 inst.instruction |= rotation_eight_mask;
5310 break;
5311
5312 case 16:
5313 inst.instruction |= rotation_sixteen_mask;
5314 break;
5315
5316 case 24:
5317 inst.instruction |= rotation_twenty_four_mask;
5318 break;
5319
5320 default:
5321 inst.error = _("rotation can be 8, 16, 24 or 0 when field is ommited");
5322 break;
5323 }
5324
5325 end_of_line (str);
5326
5327}
5328
5329/* ARM V6 SXTAH extracts a 16-bit value from a register, sign
5330 extends it to 32-bits, and adds the result to a value in another
5331 register. You can specify a rotation by 0, 8, 16, or 24 bits
5332 before extracting the 16-bit value.
5333 SXTAH{<cond>} <Rd>, <Rn>, <Rm>{, <rotation>}
5334 Condition defaults to COND_ALWAYS.
5335 Error if any register uses R15. */
5336
5337static void
5338do_sxtah (str)
5339 char *str;
5340{
5341 int rd, rn, rm;
5342 expressionS expr;
5343 int rotation_clear_mask = 0xfffff3ff;
5344 int rotation_eight_mask = 0x00000400;
5345 int rotation_sixteen_mask = 0x00000800;
5346 int rotation_twenty_four_mask = 0x00000c00;
5347
5348 skip_whitespace (str);
5349 if ((rd = reg_required_here (&str, 12)) == FAIL
5350 || skip_past_comma (&str) == FAIL
5351 || (rn = reg_required_here (&str, 16)) == FAIL
5352 || skip_past_comma (&str) == FAIL
5353 || (rm = reg_required_here (&str, 0)) == FAIL)
5354 {
5355 inst.error = BAD_ARGS;
5356 return;
5357 }
5358
5359 else if (rd == REG_PC || rn == REG_PC || rm == REG_PC)
5360 {
5361 inst.error = BAD_PC;
5362 return;
5363 }
5364
5365 /* Zero out the rotation field. */
5366 inst.instruction &= rotation_clear_mask;
5367
5368 /* Check for lack of optional rotation field. */
5369 if (skip_past_comma (&str) == FAIL)
5370 {
5371 end_of_line (str);
5372 return;
5373 }
5374
5375 /* Move past 'ROR'. */
5376 skip_whitespace (str);
5377 if (strncasecmp (str, "ROR", 3) == 0)
5378 str+=3;
5379 else
5380 {
5381 inst.error = _("missing rotation field after comma");
5382 return;
5383 }
5384
5385 /* Get the immediate constant. */
5386 skip_whitespace (str);
5387 if (is_immediate_prefix (* str))
5388 str++;
5389 else
5390 {
5391 inst.error = _("immediate expression expected");
5392 return;
5393 }
5394
5395 if (my_get_expression (&expr, &str))
5396 {
5397 inst.error = _("bad expression");
5398 return;
5399 }
5400
5401 if (expr.X_op != O_constant)
5402 {
5403 inst.error = _("constant expression expected");
5404 return;
5405 }
5406
5407 switch (expr.X_add_number)
5408 {
5409 case 0:
5410 /* Rotation field has already been zeroed. */
5411 break;
5412
5413 case 8:
5414 inst.instruction |= rotation_eight_mask;
5415 break;
5416
5417 case 16:
5418 inst.instruction |= rotation_sixteen_mask;
5419 break;
5420
5421 case 24:
5422 inst.instruction |= rotation_twenty_four_mask;
5423 break;
5424
5425 default:
5426 inst.error = _("rotation can be 8, 16, 24 or 0 when field is ommited");
5427 break;
5428 }
5429
5430 end_of_line (str);
5431
5432}
5433
5434
5435/* ARM V6 RFE (Return from Exception) loads the PC and CPSR from the
5436 word at the specified address and the following word
5437 respectively.
5438 Unconditionally executed.
5439 Error if Rn is R15.
5440*/
5441
5442static void
5443do_rfe (str)
5444 char *str;
5445{
5446 int rn;
5447
5448 skip_whitespace (str);
5449
5450 if ((rn = reg_required_here (&str, 16)) == FAIL)
5451 return;
b99bd4ef 5452
09d92015 5453 if (rn == REG_PC)
b99bd4ef 5454 {
09d92015 5455 inst.error = BAD_PC;
b99bd4ef
NC
5456 return;
5457 }
5458
09d92015
MM
5459 skip_whitespace (str);
5460
5461 if (*str == '!')
5462 {
5463 inst.instruction |= WRITE_BACK;
5464 str++;
5465 }
b99bd4ef
NC
5466 end_of_line (str);
5467}
5468
09d92015
MM
5469/* ARM V6 REV (Byte Reverse Word) reverses the byte order in a 32-bit
5470 register (argument parse).
5471 REV{<cond>} Rd, Rm.
5472 Condition defaults to COND_ALWAYS.
5473 Error if Rd or Rm are R15. */
b99bd4ef
NC
5474
5475static void
09d92015
MM
5476do_rev (str)
5477 char* str;
b99bd4ef
NC
5478{
5479 int rd, rm;
5480
b99bd4ef
NC
5481 skip_whitespace (str);
5482
09d92015
MM
5483 if ((rd = reg_required_here (&str, 12)) == FAIL
5484 || skip_past_comma (&str) == FAIL
5485 || (rm = reg_required_here (&str, 0)) == FAIL)
b99bd4ef
NC
5486 inst.error = BAD_ARGS;
5487
09d92015 5488 else if (rd == REG_PC || rm == REG_PC)
b99bd4ef
NC
5489 inst.error = BAD_PC;
5490
5491 else
5492 end_of_line (str);
5493}
5494
09d92015
MM
5495/* ARM V6 Perform Two Sixteen Bit Integer Additions. (argument parse).
5496 QADD16{<cond>} <Rd>, <Rn>, <Rm>
5497 Condition defaults to COND_ALWAYS.
5498 Error if Rd, Rn or Rm are R15. */
b99bd4ef
NC
5499
5500static void
09d92015
MM
5501do_qadd16 (str)
5502 char* str;
b99bd4ef 5503{
09d92015
MM
5504 int rd, rm, rn;
5505
b99bd4ef
NC
5506 skip_whitespace (str);
5507
09d92015
MM
5508 if ((rd = reg_required_here (&str, 12)) == FAIL
5509 || skip_past_comma (&str) == FAIL
5510 || (rn = reg_required_here (&str, 16)) == FAIL
5511 || skip_past_comma (&str) == FAIL
5512 || (rm = reg_required_here (&str, 0)) == FAIL)
5513 inst.error = BAD_ARGS;
5514
5515 else if (rd == REG_PC || rm == REG_PC || rn == REG_PC)
5516 inst.error = BAD_PC;
5517
b99bd4ef
NC
5518 else
5519 end_of_line (str);
5520}
5521
09d92015
MM
5522/* ARM V6 Pack Halfword Bottom Top instruction (argument parse).
5523 PKHBT {<cond>} <Rd>, <Rn>, <Rm> {, LSL #<shift_imm>}
5524 Condition defaults to COND_ALWAYS.
5525 Error if Rd, Rn or Rm are R15. */
5526
5527static void
5528do_pkhbt (str)
5529 char* str;
5530{
5531 do_pkh_core (str, SHIFT_LSL_IMMEDIATE);
5532}
5533
5534/* ARM V6 PKHTB (Argument Parse). */
5535
5536static void
5537do_pkhtb (str)
5538 char* str;
5539{
5540 do_pkh_core (str, SHIFT_ASR_IMMEDIATE);
5541}
b99bd4ef
NC
5542
5543static void
09d92015
MM
5544do_pkh_core (str, shift)
5545 char* str;
5546 int shift;
b99bd4ef 5547{
09d92015 5548 int rd, rn, rm;
b99bd4ef 5549
09d92015
MM
5550 skip_whitespace (str);
5551 if (((rd = reg_required_here (&str, 12)) == FAIL)
5552 || (skip_past_comma (&str) == FAIL)
5553 || ((rn = reg_required_here (&str, 16)) == FAIL)
5554 || (skip_past_comma (&str) == FAIL)
5555 || ((rm = reg_required_here (&str, 0)) == FAIL))
b99bd4ef 5556 {
09d92015 5557 inst.error = BAD_ARGS;
b99bd4ef
NC
5558 return;
5559 }
5560
09d92015 5561 else if (rd == REG_PC || rn == REG_PC || rm == REG_PC)
b99bd4ef 5562 {
09d92015 5563 inst.error = BAD_PC;
b99bd4ef
NC
5564 return;
5565 }
5566
09d92015
MM
5567 /* Check for optional shift immediate constant. */
5568 if (skip_past_comma (&str) == FAIL)
b99bd4ef 5569 {
09d92015
MM
5570 if (shift == SHIFT_ASR_IMMEDIATE)
5571 {
5572 /* If the shift specifier is ommited, turn the instruction
5573 into pkhbt rd, rm, rn. First, switch the instruction
5574 code, and clear the rn and rm fields. */
5575 inst.instruction &= 0xfff0f010;
5576 /* Now, re-encode the registers. */
5577 inst.instruction |= (rm << 16) | rn;
5578 }
b99bd4ef
NC
5579 return;
5580 }
5581
09d92015
MM
5582 decode_shift (&str, shift);
5583}
5584
5585/* ARM V6 Load Register Exclusive instruction (argument parse).
5586 LDREX{<cond>} <Rd, [<Rn>]
5587 Condition defaults to COND_ALWAYS.
5588 Error if Rd or Rn are R15.
5589 See ARMARMv6 A4.1.27: LDREX. */
5590
5591
5592static void
5593do_ldrex (str)
5594 char * str;
5595{
5596 int rd, rn;
5597
5598 skip_whitespace (str);
5599
5600 /* Parse Rd. */
5601 if (((rd = reg_required_here (&str, 12)) == FAIL)
5602 || (skip_past_comma (&str) == FAIL))
b99bd4ef 5603 {
09d92015 5604 inst.error = BAD_ARGS;
b99bd4ef
NC
5605 return;
5606 }
09d92015 5607 else if (rd == REG_PC)
b99bd4ef 5608 {
09d92015 5609 inst.error = BAD_PC;
b99bd4ef
NC
5610 return;
5611 }
09d92015 5612 skip_whitespace (str);
b99bd4ef 5613
09d92015
MM
5614 /* Skip past '['. */
5615 if ((strlen (str) >= 1)
5616 &&strncmp (str, "[", 1) == 0)
5617 str+=1;
5618 skip_whitespace (str);
5619
5620 /* Parse Rn. */
5621 if ((rn = reg_required_here (&str, 16)) == FAIL)
b99bd4ef 5622 {
09d92015
MM
5623 inst.error = BAD_ARGS;
5624 return;
b99bd4ef 5625 }
09d92015
MM
5626 else if (rn == REG_PC)
5627 {
5628 inst.error = BAD_PC;
5629 return;
5630 }
5631 skip_whitespace (str);
b99bd4ef 5632
09d92015
MM
5633 /* Skip past ']'. */
5634 if ((strlen (str) >= 1)
5635 && strncmp (str, "]", 1) == 0)
5636 str+=1;
5637
b99bd4ef
NC
5638 end_of_line (str);
5639}
5640
09d92015
MM
5641/* ARM V6 change processor state instruction (argument parse)
5642 CPS, CPSIE, CSPID . */
b99bd4ef
NC
5643
5644static void
09d92015
MM
5645do_cps (str)
5646 char * str;
b99bd4ef 5647{
09d92015
MM
5648 do_cps_mode (&str);
5649 end_of_line (str);
5650}
b99bd4ef 5651
09d92015
MM
5652static void
5653do_cpsi (str)
5654 char * str;
5655{
5656 do_cps_flags (&str, /*thumb_p=*/0);
b99bd4ef 5657
09d92015 5658 if (skip_past_comma (&str) == SUCCESS)
b99bd4ef 5659 {
09d92015
MM
5660 skip_whitespace (str);
5661 do_cps_mode (&str);
b99bd4ef 5662 }
09d92015
MM
5663 end_of_line (str);
5664}
b99bd4ef 5665
09d92015
MM
5666static void
5667do_cps_mode (str)
5668 char **str;
5669{
5670 expressionS expr;
5671
5672 skip_whitespace (*str);
5673
5674 if (! is_immediate_prefix (**str))
b99bd4ef 5675 {
09d92015 5676 inst.error = _("immediate expression expected");
b99bd4ef
NC
5677 return;
5678 }
5679
09d92015
MM
5680 (*str)++; /* Strip off the immediate signifier. */
5681 if (my_get_expression (&expr, str))
b99bd4ef 5682 {
09d92015 5683 inst.error = _("bad expression");
b99bd4ef
NC
5684 return;
5685 }
5686
09d92015 5687 if (expr.X_op != O_constant)
b99bd4ef 5688 {
09d92015 5689 inst.error = _("constant expression expected");
b99bd4ef
NC
5690 return;
5691 }
09d92015
MM
5692
5693 /* The mode is a 5 bit field. Valid values are 0-31. */
5694 if (((unsigned) expr.X_add_number) > 31
5695 || (inst.reloc.exp.X_add_number) < 0)
b99bd4ef 5696 {
09d92015
MM
5697 inst.error = _("invalid constant");
5698 return;
b99bd4ef 5699 }
09d92015
MM
5700
5701 inst.instruction |= expr.X_add_number;
b99bd4ef
NC
5702}
5703
ea6ef066 5704static void
09d92015
MM
5705do_cps_flags (str, thumb_p)
5706 char **str;
5707 int thumb_p;
ea6ef066 5708{
09d92015
MM
5709 struct cps_flag {
5710 char character;
5711 unsigned long arm_value;
5712 unsigned long thumb_value;
5713 };
5714 static struct cps_flag flag_table[] = {
5715 {'a', 0x100, 0x4 },
5716 {'i', 0x080, 0x2 },
5717 {'f', 0x040, 0x1 }
5718 };
ea6ef066 5719
09d92015 5720 int saw_a_flag = 0;
ea6ef066 5721
09d92015
MM
5722 skip_whitespace (*str);
5723
5724 /* Get the a, f and i flags. */
5725 while (**str && **str != ',')
ea6ef066 5726 {
09d92015
MM
5727 struct cps_flag *p;
5728 struct cps_flag *q = flag_table + sizeof (flag_table)/sizeof (*p);
5729 for (p = flag_table; p < q; ++p)
5730 if (strncasecmp (*str, &p->character, 1) == 0)
5731 {
5732 inst.instruction |= (thumb_p ? p->thumb_value : p->arm_value);
5733 saw_a_flag = 1;
5734 break;
5735 }
5736 if (p == q)
5737 {
5738 inst.error = _("unrecognized flag");
5739 return;
5740 }
5741 (*str)++;
ea6ef066 5742 }
09d92015
MM
5743 if (!saw_a_flag)
5744 inst.error = _("no 'a', 'i', or 'f' flags for 'cps'");
ea6ef066
RE
5745}
5746
b99bd4ef
NC
5747/* THUMB V5 breakpoint instruction (argument parse)
5748 BKPT <immed_8>. */
5749
5750static void
5751do_t_bkpt (str)
5752 char * str;
5753{
5754 expressionS expr;
5755 unsigned long number;
5756
5757 skip_whitespace (str);
5758
5759 /* Allow optional leading '#'. */
5760 if (is_immediate_prefix (*str))
5761 str ++;
5762
5763 memset (& expr, '\0', sizeof (expr));
143c8e19
NC
5764 if (my_get_expression (& expr, & str)
5765 || (expr.X_op != O_constant
5766 /* As a convenience we allow 'bkpt' without an operand. */
5767 && expr.X_op != O_absent))
b99bd4ef 5768 {
143c8e19 5769 inst.error = _("bad expression");
b99bd4ef
NC
5770 return;
5771 }
5772
5773 number = expr.X_add_number;
5774
5775 /* Check it fits an 8 bit unsigned. */
5776 if (number != (number & 0xff))
5777 {
5778 inst.error = _("immediate value out of range");
5779 return;
5780 }
5781
5782 inst.instruction |= number;
5783
5784 end_of_line (str);
5785}
5786
5787/* ARM V5 branch-link-exchange (argument parse) for BLX(1) only.
5788 Expects inst.instruction is set for BLX(1).
5789 Note: this is cloned from do_branch, and the reloc changed to be a
5790 new one that can cope with setting one extra bit (the H bit). */
5791
5792static void
f2b7cb0a 5793do_branch25 (str)
b99bd4ef 5794 char * str;
b99bd4ef
NC
5795{
5796 if (my_get_expression (& inst.reloc.exp, & str))
5797 return;
5798
5799#ifdef OBJ_ELF
5800 {
5801 char * save_in;
5802
5803 /* ScottB: February 5, 1998 */
5804 /* Check to see of PLT32 reloc required for the instruction. */
5805
5806 /* arm_parse_reloc() works on input_line_pointer.
5807 We actually want to parse the operands to the branch instruction
5808 passed in 'str'. Save the input pointer and restore it later. */
5809 save_in = input_line_pointer;
5810 input_line_pointer = str;
5811
5812 if (inst.reloc.exp.X_op == O_symbol
5813 && *str == '('
5814 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
5815 {
5816 inst.reloc.type = BFD_RELOC_ARM_PLT32;
5817 inst.reloc.pc_rel = 0;
5818 /* Modify str to point to after parsed operands, otherwise
5819 end_of_line() will complain about the (PLT) left in str. */
5820 str = input_line_pointer;
5821 }
5822 else
5823 {
5824 inst.reloc.type = BFD_RELOC_ARM_PCREL_BLX;
5825 inst.reloc.pc_rel = 1;
5826 }
5827
5828 input_line_pointer = save_in;
5829 }
5830#else
5831 inst.reloc.type = BFD_RELOC_ARM_PCREL_BLX;
5832 inst.reloc.pc_rel = 1;
5833#endif /* OBJ_ELF */
5834
5835 end_of_line (str);
5836}
5837
5838/* ARM V5 branch-link-exchange instruction (argument parse)
5839 BLX <target_addr> ie BLX(1)
5840 BLX{<condition>} <Rm> ie BLX(2)
5841 Unfortunately, there are two different opcodes for this mnemonic.
5842 So, the insns[].value is not used, and the code here zaps values
5843 into inst.instruction.
5844 Also, the <target_addr> can be 25 bits, hence has its own reloc. */
5845
5846static void
f2b7cb0a 5847do_blx (str)
b99bd4ef 5848 char * str;
b99bd4ef
NC
5849{
5850 char * mystr = str;
5851 int rm;
5852
b99bd4ef
NC
5853 skip_whitespace (mystr);
5854 rm = reg_required_here (& mystr, 0);
5855
5856 /* The above may set inst.error. Ignore his opinion. */
5857 inst.error = 0;
5858
5859 if (rm != FAIL)
5860 {
5861 /* Arg is a register.
5862 Use the condition code our caller put in inst.instruction.
5863 Pass ourselves off as a BX with a funny opcode. */
5864 inst.instruction |= 0x012fff30;
f2b7cb0a 5865 do_bx (str);
b99bd4ef
NC
5866 }
5867 else
5868 {
5869 /* This must be is BLX <target address>, no condition allowed. */
5870 if (inst.instruction != COND_ALWAYS)
cc8a6dd0
KH
5871 {
5872 inst.error = BAD_COND;
b99bd4ef 5873 return;
cc8a6dd0 5874 }
b99bd4ef
NC
5875
5876 inst.instruction = 0xfafffffe;
5877
5878 /* Process like a B/BL, but with a different reloc.
5879 Note that B/BL expecte fffffe, not 0, offset in the opcode table. */
f2b7cb0a 5880 do_branch25 (str);
b99bd4ef
NC
5881 }
5882}
5883
5884/* ARM V5 Thumb BLX (argument parse)
5885 BLX <target_addr> which is BLX(1)
5886 BLX <Rm> which is BLX(2)
5887 Unfortunately, there are two different opcodes for this mnemonic.
5888 So, the tinsns[].value is not used, and the code here zaps values
5889 into inst.instruction. */
5890
5891static void
5892do_t_blx (str)
5893 char * str;
5894{
5895 char * mystr = str;
5896 int rm;
5897
5898 skip_whitespace (mystr);
5899 inst.instruction = 0x4780;
5900
5901 /* Note that this call is to the ARM register recognizer. BLX(2)
5902 uses the ARM register space, not the Thumb one, so a call to
5903 thumb_reg() would be wrong. */
5904 rm = reg_required_here (& mystr, 3);
5905 inst.error = 0;
5906
5907 if (rm != FAIL)
5908 {
5909 /* It's BLX(2). The .instruction was zapped with rm & is final. */
5910 inst.size = 2;
5911 }
5912 else
5913 {
5914 /* No ARM register. This must be BLX(1). Change the .instruction. */
5915 inst.instruction = 0xf7ffeffe;
5916 inst.size = 4;
5917
5918 if (my_get_expression (& inst.reloc.exp, & mystr))
5919 return;
5920
5921 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BLX;
5922 inst.reloc.pc_rel = 1;
5923 }
5924
5925 end_of_line (mystr);
5926}
5927
5928/* ARM V5 breakpoint instruction (argument parse)
5929 BKPT <16 bit unsigned immediate>
5930 Instruction is not conditional.
5931 The bit pattern given in insns[] has the COND_ALWAYS condition,
cc8a6dd0 5932 and it is an error if the caller tried to override that. */
b99bd4ef
NC
5933
5934static void
f2b7cb0a 5935do_bkpt (str)
b99bd4ef 5936 char * str;
b99bd4ef
NC
5937{
5938 expressionS expr;
5939 unsigned long number;
5940
5941 skip_whitespace (str);
5942
5943 /* Allow optional leading '#'. */
5944 if (is_immediate_prefix (* str))
5945 str++;
5946
5947 memset (& expr, '\0', sizeof (expr));
5948
143c8e19
NC
5949 if (my_get_expression (& expr, & str)
5950 || (expr.X_op != O_constant
5951 /* As a convenience we allow 'bkpt' without an operand. */
5952 && expr.X_op != O_absent))
b99bd4ef 5953 {
143c8e19 5954 inst.error = _("bad expression");
b99bd4ef
NC
5955 return;
5956 }
5957
5958 number = expr.X_add_number;
5959
5960 /* Check it fits a 16 bit unsigned. */
5961 if (number != (number & 0xffff))
5962 {
5963 inst.error = _("immediate value out of range");
5964 return;
5965 }
5966
5967 /* Top 12 of 16 bits to bits 19:8. */
5968 inst.instruction |= (number & 0xfff0) << 4;
5969
5970 /* Bottom 4 of 16 bits to bits 3:0. */
5971 inst.instruction |= number & 0xf;
5972
5973 end_of_line (str);
b99bd4ef
NC
5974}
5975
09d92015
MM
5976/* THUMB CPS instruction (argument parse). */
5977
5978static void
5979do_t_cps (str)
5980 char *str;
5981{
5982 do_cps_flags (&str, /*thumb_p=*/1);
5983 end_of_line (str);
5984}
5985
5986/* THUMB CPY instruction (argument parse). */
5987
5988static void
5989do_t_cpy (str)
5990 char *str;
5991{
5992 thumb_mov_compare (str, THUMB_CPY);
5993}
5994
5995/* THUMB SETEND instruction (argument parse). */
5996
5997static void
5998do_t_setend (str)
5999 char *str;
6000{
6001 if (do_endian_specifier (str))
6002 inst.instruction |= 0x8;
6003}
6004
e16bb312
NC
6005static unsigned long check_iwmmxt_insn PARAMS ((char *, enum iwmmxt_insn_type, int));
6006
6007/* Parse INSN_TYPE insn STR having a possible IMMEDIATE_SIZE immediate. */
6008
6009static unsigned long
6010check_iwmmxt_insn (str, insn_type, immediate_size)
6011 char * str;
6012 enum iwmmxt_insn_type insn_type;
6013 int immediate_size;
6014{
6015 int reg = 0;
6016 const char * inst_error;
6017 expressionS expr;
6018 unsigned long number;
6019
6020 inst_error = inst.error;
6021 if (!inst.error)
6022 inst.error = BAD_ARGS;
6023 skip_whitespace (str);
6024
6025 switch (insn_type)
6026 {
6027 case check_rd:
6028 if ((reg = reg_required_here (&str, 12)) == FAIL)
6029 return FAIL;
6030 break;
6031
6032 case check_wr:
6033 if ((wreg_required_here (&str, 0, IWMMXT_REG_WR)) == FAIL)
6034 return FAIL;
6035 break;
6036
6037 case check_wrwr:
6038 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
6039 || skip_past_comma (&str) == FAIL
6040 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL))
6041 return FAIL;
6042 break;
6043
6044 case check_wrwrwr:
6045 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
6046 || skip_past_comma (&str) == FAIL
6047 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6048 || skip_past_comma (&str) == FAIL
6049 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL))
6050 return FAIL;
6051 break;
6052
6053 case check_wrwrwcg:
6054 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
6055 || skip_past_comma (&str) == FAIL
6056 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6057 || skip_past_comma (&str) == FAIL
6058 || wreg_required_here (&str, 0, IWMMXT_REG_WCG) == FAIL))
6059 return FAIL;
6060 break;
6061
6062 case check_tbcst:
6063 if ((wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6064 || skip_past_comma (&str) == FAIL
6065 || reg_required_here (&str, 12) == FAIL))
6066 return FAIL;
6067 break;
6068
6069 case check_tmovmsk:
6070 if ((reg_required_here (&str, 12) == FAIL
6071 || skip_past_comma (&str) == FAIL
6072 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL))
6073 return FAIL;
6074 break;
6075
6076 case check_tmia:
6077 if ((wreg_required_here (&str, 5, IWMMXT_REG_WR) == FAIL
6078 || skip_past_comma (&str) == FAIL
6079 || reg_required_here (&str, 0) == FAIL
6080 || skip_past_comma (&str) == FAIL
6081 || reg_required_here (&str, 12) == FAIL))
6082 return FAIL;
6083 break;
6084
6085 case check_tmcrr:
6086 if ((wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL
6087 || skip_past_comma (&str) == FAIL
6088 || reg_required_here (&str, 12) == FAIL
6089 || skip_past_comma (&str) == FAIL
6090 || reg_required_here (&str, 16) == FAIL))
6091 return FAIL;
6092 break;
6093
6094 case check_tmrrc:
6095 if ((reg_required_here (&str, 12) == FAIL
6096 || skip_past_comma (&str) == FAIL
6097 || reg_required_here (&str, 16) == FAIL
6098 || skip_past_comma (&str) == FAIL
6099 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL))
6100 return FAIL;
6101 break;
6102
6103 case check_tmcr:
6104 if ((wreg_required_here (&str, 16, IWMMXT_REG_WC) == FAIL
6105 || skip_past_comma (&str) == FAIL
6106 || reg_required_here (&str, 12) == FAIL))
6107 return FAIL;
6108 break;
6109
6110 case check_tmrc:
6111 if ((reg_required_here (&str, 12) == FAIL
6112 || skip_past_comma (&str) == FAIL
6113 || wreg_required_here (&str, 16, IWMMXT_REG_WC) == FAIL))
6114 return FAIL;
6115 break;
6116
6117 case check_tinsr:
6118 if ((wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6119 || skip_past_comma (&str) == FAIL
6120 || reg_required_here (&str, 12) == FAIL
6121 || skip_past_comma (&str) == FAIL))
6122 return FAIL;
6123 break;
6124
6125 case check_textrc:
6126 if ((reg_required_here (&str, 12) == FAIL
6127 || skip_past_comma (&str) == FAIL))
6128 return FAIL;
6129 break;
6130
6131 case check_waligni:
6132 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
6133 || skip_past_comma (&str) == FAIL
6134 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6135 || skip_past_comma (&str) == FAIL
6136 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL
6137 || skip_past_comma (&str) == FAIL))
6138 return FAIL;
6139 break;
6140
6141 case check_textrm:
6142 if ((reg_required_here (&str, 12) == FAIL
6143 || skip_past_comma (&str) == FAIL
6144 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6145 || skip_past_comma (&str) == FAIL))
6146 return FAIL;
6147 break;
6148
6149 case check_wshufh:
6150 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
6151 || skip_past_comma (&str) == FAIL
6152 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6153 || skip_past_comma (&str) == FAIL))
6154 return FAIL;
6155 break;
6156 }
6157
6158 if (immediate_size == 0)
6159 {
6160 end_of_line (str);
6161 inst.error = inst_error;
6162 return reg;
6163 }
6164 else
6165 {
6166 skip_whitespace (str);
6167
6168 /* Allow optional leading '#'. */
6169 if (is_immediate_prefix (* str))
6170 str++;
6171
6172 memset (& expr, '\0', sizeof (expr));
6173
6174 if (my_get_expression (& expr, & str) || (expr.X_op != O_constant))
6175 {
6176 inst.error = _("bad or missing expression");
6177 return FAIL;
6178 }
6179
6180 number = expr.X_add_number;
6181
6182 if (number != (number & immediate_size))
6183 {
6184 inst.error = _("immediate value out of range");
6185 return FAIL;
6186 }
6187 end_of_line (str);
6188 inst.error = inst_error;
6189 return number;
6190 }
6191}
6192
6193static void
6194do_iwmmxt_byte_addr (str)
6195 char * str;
6196{
6197 int op = (inst.instruction & 0x300) >> 8;
6198 int reg;
6199
6200 inst.instruction &= ~0x300;
6201 inst.instruction |= (op & 1) << 22 | (op & 2) << 7;
6202
6203 skip_whitespace (str);
6204
6205 if ((reg = wreg_required_here (&str, 12, IWMMXT_REG_WR_OR_WC)) == FAIL
6206 || skip_past_comma (& str) == FAIL
6207 || cp_byte_address_required_here (&str) == FAIL)
6208 {
6209 if (! inst.error)
6210 inst.error = BAD_ARGS;
6211 }
6212 else
6213 end_of_line (str);
6214
6215 if (wc_register (reg))
6216 {
ece01a63 6217 as_bad (_("non-word size not supported with control register"));
e16bb312
NC
6218 inst.instruction |= 0xf0000100;
6219 inst.instruction &= ~0x00400000;
6220 }
6221}
6222
6223static void
6224do_iwmmxt_tandc (str)
6225 char * str;
6226{
6227 int reg;
6228
6229 reg = check_iwmmxt_insn (str, check_rd, 0);
6230
6231 if (reg != REG_PC && !inst.error)
6232 inst.error = _("only r15 allowed here");
e16bb312
NC
6233}
6234
6235static void
6236do_iwmmxt_tbcst (str)
6237 char * str;
6238{
6239 check_iwmmxt_insn (str, check_tbcst, 0);
e16bb312
NC
6240}
6241
6242static void
6243do_iwmmxt_textrc (str)
6244 char * str;
6245{
6246 unsigned long number;
6247
6248 if ((number = check_iwmmxt_insn (str, check_textrc, 7)) == (unsigned long) FAIL)
6249 return;
6250
6251 inst.instruction |= number & 0x7;
e16bb312
NC
6252}
6253
6254static void
6255do_iwmmxt_textrm (str)
6256 char * str;
6257{
6258 unsigned long number;
6259
6260 if ((number = check_iwmmxt_insn (str, check_textrm, 7)) == (unsigned long) FAIL)
6261 return;
6262
6263 inst.instruction |= number & 0x7;
6264}
6265
6266static void
6267do_iwmmxt_tinsr (str)
6268 char * str;
6269{
6270 unsigned long number;
6271
6272 if ((number = check_iwmmxt_insn (str, check_tinsr, 7)) == (unsigned long) FAIL)
6273 return;
6274
6275 inst.instruction |= number & 0x7;
e16bb312
NC
6276}
6277
6278static void
6279do_iwmmxt_tmcr (str)
6280 char * str;
6281{
6282 check_iwmmxt_insn (str, check_tmcr, 0);
e16bb312
NC
6283}
6284
6285static void
6286do_iwmmxt_tmcrr (str)
6287 char * str;
6288{
6289 check_iwmmxt_insn (str, check_tmcrr, 0);
e16bb312
NC
6290}
6291
6292static void
6293do_iwmmxt_tmia (str)
6294 char * str;
6295{
6296 check_iwmmxt_insn (str, check_tmia, 0);
e16bb312
NC
6297}
6298
6299static void
6300do_iwmmxt_tmovmsk (str)
6301 char * str;
6302{
6303 check_iwmmxt_insn (str, check_tmovmsk, 0);
e16bb312
NC
6304}
6305
6306static void
6307do_iwmmxt_tmrc (str)
6308 char * str;
6309{
6310 check_iwmmxt_insn (str, check_tmrc, 0);
e16bb312
NC
6311}
6312
6313static void
6314do_iwmmxt_tmrrc (str)
6315 char * str;
6316{
6317 check_iwmmxt_insn (str, check_tmrrc, 0);
e16bb312
NC
6318}
6319
6320static void
6321do_iwmmxt_torc (str)
6322 char * str;
6323{
6324 check_iwmmxt_insn (str, check_rd, 0);
e16bb312
NC
6325}
6326
6327static void
6328do_iwmmxt_waligni (str)
6329 char * str;
6330{
6331 unsigned long number;
6332
6333 if ((number = check_iwmmxt_insn (str, check_waligni, 7)) == (unsigned long) FAIL)
6334 return;
6335
6336 inst.instruction |= ((number & 0x7) << 20);
e16bb312
NC
6337}
6338
6339static void
6340do_iwmmxt_wmov (str)
6341 char * str;
6342{
6343 if (check_iwmmxt_insn (str, check_wrwr, 0) == (unsigned long) FAIL)
6344 return;
6345
6346 inst.instruction |= ((inst.instruction >> 16) & 0xf);
e16bb312
NC
6347}
6348
6349static void
6350do_iwmmxt_word_addr (str)
6351 char * str;
6352{
6353 int op = (inst.instruction & 0x300) >> 8;
6354 int reg;
6355
6356 inst.instruction &= ~0x300;
6357 inst.instruction |= (op & 1) << 22 | (op & 2) << 7;
6358
6359 skip_whitespace (str);
6360
6361 if ((reg = wreg_required_here (&str, 12, IWMMXT_REG_WR_OR_WC)) == FAIL
6362 || skip_past_comma (& str) == FAIL
6363 || cp_address_required_here (& str, CP_WB_OK) == FAIL)
6364 {
6365 if (! inst.error)
6366 inst.error = BAD_ARGS;
6367 }
6368 else
6369 end_of_line (str);
6370
6371 if (wc_register (reg))
6372 {
ece01a63
ILT
6373 if ((inst.instruction & COND_MASK) != COND_ALWAYS)
6374 as_bad (_("conditional execution not supported with control register"));
6375 if (op != 2)
6376 as_bad (_("non-word size not supported with control register"));
e16bb312
NC
6377 inst.instruction |= 0xf0000100;
6378 inst.instruction &= ~0x00400000;
6379 }
6380}
6381
6382static void
6383do_iwmmxt_wrwr (str)
6384 char * str;
6385{
6386 check_iwmmxt_insn (str, check_wrwr, 0);
e16bb312
NC
6387}
6388
6389static void
6390do_iwmmxt_wrwrwcg (str)
6391 char * str;
6392{
6393 check_iwmmxt_insn (str, check_wrwrwcg, 0);
e16bb312
NC
6394}
6395
6396static void
6397do_iwmmxt_wrwrwr (str)
6398 char * str;
6399{
6400 check_iwmmxt_insn (str, check_wrwrwr, 0);
e16bb312
NC
6401}
6402
6403static void
6404do_iwmmxt_wshufh (str)
6405 char * str;
6406{
6407 unsigned long number;
6408
6409 if ((number = check_iwmmxt_insn (str, check_wshufh, 0xff)) == (unsigned long) FAIL)
6410 return;
6411
6412 inst.instruction |= ((number & 0xf0) << 16) | (number & 0xf);
e16bb312
NC
6413}
6414
6415static void
6416do_iwmmxt_wzero (str)
6417 char * str;
6418{
6419 if (check_iwmmxt_insn (str, check_wr, 0) == (unsigned long) FAIL)
6420 return;
6421
6422 inst.instruction |= ((inst.instruction & 0xf) << 12) | ((inst.instruction & 0xf) << 16);
e16bb312
NC
6423}
6424
b99bd4ef
NC
6425/* Xscale multiply-accumulate (argument parse)
6426 MIAcc acc0,Rm,Rs
6427 MIAPHcc acc0,Rm,Rs
6428 MIAxycc acc0,Rm,Rs. */
6429
6430static void
63e63b07 6431do_xsc_mia (str)
b99bd4ef 6432 char * str;
b99bd4ef
NC
6433{
6434 int rs;
6435 int rm;
6436
f2b7cb0a 6437 if (accum0_required_here (& str) == FAIL)
b99bd4ef
NC
6438 inst.error = ERR_NO_ACCUM;
6439
6440 else if (skip_past_comma (& str) == FAIL
6441 || (rm = reg_required_here (& str, 0)) == FAIL)
6442 inst.error = BAD_ARGS;
6443
6444 else if (skip_past_comma (& str) == FAIL
6445 || (rs = reg_required_here (& str, 12)) == FAIL)
6446 inst.error = BAD_ARGS;
6447
6448 /* inst.instruction has now been zapped with both rm and rs. */
6449 else if (rm == REG_PC || rs == REG_PC)
6450 inst.error = BAD_PC; /* Undefined result if rm or rs is R15. */
6451
6452 else
6453 end_of_line (str);
6454}
6455
6456/* Xscale move-accumulator-register (argument parse)
6457
6458 MARcc acc0,RdLo,RdHi. */
6459
6460static void
63e63b07 6461do_xsc_mar (str)
b99bd4ef 6462 char * str;
b99bd4ef
NC
6463{
6464 int rdlo, rdhi;
6465
f2b7cb0a 6466 if (accum0_required_here (& str) == FAIL)
b99bd4ef
NC
6467 inst.error = ERR_NO_ACCUM;
6468
6469 else if (skip_past_comma (& str) == FAIL
6470 || (rdlo = reg_required_here (& str, 12)) == FAIL)
6471 inst.error = BAD_ARGS;
6472
6473 else if (skip_past_comma (& str) == FAIL
6474 || (rdhi = reg_required_here (& str, 16)) == FAIL)
6475 inst.error = BAD_ARGS;
6476
6477 /* inst.instruction has now been zapped with both rdlo and rdhi. */
6478 else if (rdlo == REG_PC || rdhi == REG_PC)
6479 inst.error = BAD_PC; /* Undefined result if rdlo or rdhi is R15. */
6480
6481 else
6482 end_of_line (str);
6483}
6484
6485/* Xscale move-register-accumulator (argument parse)
6486
6487 MRAcc RdLo,RdHi,acc0. */
6488
6489static void
63e63b07 6490do_xsc_mra (str)
b99bd4ef 6491 char * str;
b99bd4ef
NC
6492{
6493 int rdlo;
6494 int rdhi;
6495
b99bd4ef
NC
6496 skip_whitespace (str);
6497
6498 if ((rdlo = reg_required_here (& str, 12)) == FAIL)
6499 inst.error = BAD_ARGS;
6500
6501 else if (skip_past_comma (& str) == FAIL
6502 || (rdhi = reg_required_here (& str, 16)) == FAIL)
6503 inst.error = BAD_ARGS;
6504
6505 else if (skip_past_comma (& str) == FAIL
6506 || accum0_required_here (& str) == FAIL)
6507 inst.error = ERR_NO_ACCUM;
6508
6509 /* inst.instruction has now been zapped with both rdlo and rdhi. */
6510 else if (rdlo == rdhi)
6511 inst.error = BAD_ARGS; /* Undefined result if 2 writes to same reg. */
6512
6513 else if (rdlo == REG_PC || rdhi == REG_PC)
6514 inst.error = BAD_PC; /* Undefined result if rdlo or rdhi is R15. */
6515 else
6516 end_of_line (str);
6517}
6518
c9b604bd 6519/* ARMv5TE: Preload-Cache
b99bd4ef
NC
6520
6521 PLD <addr_mode>
6522
6523 Syntactically, like LDR with B=1, W=0, L=1. */
6524
6525static void
f2b7cb0a 6526do_pld (str)
b99bd4ef 6527 char * str;
b99bd4ef
NC
6528{
6529 int rd;
6530
b99bd4ef
NC
6531 skip_whitespace (str);
6532
6533 if (* str != '[')
6534 {
6535 inst.error = _("'[' expected after PLD mnemonic");
6536 return;
6537 }
6538
90e4755a 6539 ++str;
b99bd4ef
NC
6540 skip_whitespace (str);
6541
6542 if ((rd = reg_required_here (& str, 16)) == FAIL)
6543 return;
6544
6545 skip_whitespace (str);
6546
90e4755a 6547 if (*str == ']')
b99bd4ef
NC
6548 {
6549 /* [Rn], ... ? */
90e4755a 6550 ++str;
b99bd4ef
NC
6551 skip_whitespace (str);
6552
90e4755a
RE
6553 /* Post-indexed addressing is not allowed with PLD. */
6554 if (skip_past_comma (&str) == SUCCESS)
b99bd4ef 6555 {
90e4755a
RE
6556 inst.error
6557 = _("post-indexed expression used in preload instruction");
6558 return;
b99bd4ef 6559 }
90e4755a 6560 else if (*str == '!') /* [Rn]! */
b99bd4ef
NC
6561 {
6562 inst.error = _("writeback used in preload instruction");
90e4755a 6563 ++str;
b99bd4ef
NC
6564 }
6565 else /* [Rn] */
6566 inst.instruction |= INDEX_UP | PRE_INDEX;
6567 }
6568 else /* [Rn, ...] */
6569 {
6570 if (skip_past_comma (& str) == FAIL)
6571 {
6572 inst.error = _("pre-indexed expression expected");
6573 return;
6574 }
6575
90e4755a 6576 if (ldst_extend (&str) == FAIL)
b99bd4ef
NC
6577 return;
6578
6579 skip_whitespace (str);
6580
6581 if (* str != ']')
6582 {
6583 inst.error = _("missing ]");
6584 return;
6585 }
6586
6587 ++ str;
6588 skip_whitespace (str);
6589
6590 if (* str == '!') /* [Rn]! */
6591 {
6592 inst.error = _("writeback used in preload instruction");
6593 ++ str;
6594 }
6595
6596 inst.instruction |= PRE_INDEX;
6597 }
6598
6599 end_of_line (str);
6600}
6601
c9b604bd 6602/* ARMv5TE load-consecutive (argument parse)
b99bd4ef
NC
6603 Mode is like LDRH.
6604
6605 LDRccD R, mode
6606 STRccD R, mode. */
6607
6608static void
f2b7cb0a 6609do_ldrd (str)
b99bd4ef 6610 char * str;
b99bd4ef
NC
6611{
6612 int rd;
6613 int rn;
6614
b99bd4ef
NC
6615 skip_whitespace (str);
6616
6617 if ((rd = reg_required_here (& str, 12)) == FAIL)
6618 {
6619 inst.error = BAD_ARGS;
6620 return;
6621 }
6622
6623 if (skip_past_comma (& str) == FAIL
6624 || (rn = ld_mode_required_here (& str)) == FAIL)
6625 {
6626 if (!inst.error)
cc8a6dd0 6627 inst.error = BAD_ARGS;
b99bd4ef
NC
6628 return;
6629 }
6630
6631 /* inst.instruction has now been zapped with Rd and the addressing mode. */
6632 if (rd & 1) /* Unpredictable result if Rd is odd. */
6633 {
f03698e6 6634 inst.error = _("destination register must be even");
b99bd4ef
NC
6635 return;
6636 }
6637
90e4755a 6638 if (rd == REG_LR)
b99bd4ef 6639 {
f2b7cb0a 6640 inst.error = _("r14 not allowed here");
b99bd4ef
NC
6641 return;
6642 }
6643
6644 if (((rd == rn) || (rd + 1 == rn))
90e4755a
RE
6645 && ((inst.instruction & WRITE_BACK)
6646 || (!(inst.instruction & PRE_INDEX))))
b99bd4ef
NC
6647 as_warn (_("pre/post-indexing used when modified address register is destination"));
6648
90e4755a
RE
6649 /* For an index-register load, the index register must not overlap the
6650 destination (even if not write-back). */
6651 if ((inst.instruction & V4_STR_BIT) == 0
6652 && (inst.instruction & HWOFFSET_IMM) == 0)
6653 {
6654 int rm = inst.instruction & 0x0000000f;
6655
6656 if (rm == rd || (rm == rd + 1))
6657 as_warn (_("ldrd destination registers must not overlap index register"));
6658 }
6659
b99bd4ef
NC
6660 end_of_line (str);
6661}
6662
6663/* Returns the index into fp_values of a floating point number,
6664 or -1 if not in the table. */
6665
6666static int
6667my_get_float_expression (str)
6668 char ** str;
6669{
6670 LITTLENUM_TYPE words[MAX_LITTLENUMS];
6671 char * save_in;
6672 expressionS exp;
6673 int i;
6674 int j;
6675
6676 memset (words, 0, MAX_LITTLENUMS * sizeof (LITTLENUM_TYPE));
6677
6678 /* Look for a raw floating point number. */
6679 if ((save_in = atof_ieee (*str, 'x', words)) != NULL
6680 && is_end_of_line[(unsigned char) *save_in])
6681 {
6682 for (i = 0; i < NUM_FLOAT_VALS; i++)
6683 {
6684 for (j = 0; j < MAX_LITTLENUMS; j++)
6685 {
6686 if (words[j] != fp_values[i][j])
6687 break;
6688 }
6689
6690 if (j == MAX_LITTLENUMS)
6691 {
6692 *str = save_in;
6693 return i;
6694 }
6695 }
6696 }
6697
6698 /* Try and parse a more complex expression, this will probably fail
6699 unless the code uses a floating point prefix (eg "0f"). */
6700 save_in = input_line_pointer;
6701 input_line_pointer = *str;
6702 if (expression (&exp) == absolute_section
6703 && exp.X_op == O_big
6704 && exp.X_add_number < 0)
6705 {
6706 /* FIXME: 5 = X_PRECISION, should be #define'd where we can use it.
6707 Ditto for 15. */
6708 if (gen_to_words (words, 5, (long) 15) == 0)
6709 {
6710 for (i = 0; i < NUM_FLOAT_VALS; i++)
6711 {
6712 for (j = 0; j < MAX_LITTLENUMS; j++)
6713 {
6714 if (words[j] != fp_values[i][j])
6715 break;
6716 }
6717
6718 if (j == MAX_LITTLENUMS)
6719 {
6720 *str = input_line_pointer;
6721 input_line_pointer = save_in;
6722 return i;
6723 }
6724 }
6725 }
6726 }
6727
6728 *str = input_line_pointer;
6729 input_line_pointer = save_in;
6730 return -1;
6731}
6732
b34976b6 6733/* Return TRUE if anything in the expression is a bignum. */
b99bd4ef
NC
6734
6735static int
6736walk_no_bignums (sp)
6737 symbolS * sp;
6738{
6739 if (symbol_get_value_expression (sp)->X_op == O_big)
6740 return 1;
6741
6742 if (symbol_get_value_expression (sp)->X_add_symbol)
6743 {
6744 return (walk_no_bignums (symbol_get_value_expression (sp)->X_add_symbol)
6745 || (symbol_get_value_expression (sp)->X_op_symbol
6746 && walk_no_bignums (symbol_get_value_expression (sp)->X_op_symbol)));
6747 }
6748
6749 return 0;
6750}
6751
f03698e6
RE
6752static int in_my_get_expression = 0;
6753
b99bd4ef
NC
6754static int
6755my_get_expression (ep, str)
6756 expressionS * ep;
6757 char ** str;
6758{
6759 char * save_in;
6760 segT seg;
6761
6762 save_in = input_line_pointer;
6763 input_line_pointer = *str;
f03698e6 6764 in_my_get_expression = 1;
b99bd4ef 6765 seg = expression (ep);
f03698e6
RE
6766 in_my_get_expression = 0;
6767
6768 if (ep->X_op == O_illegal)
6769 {
6770 /* We found a bad expression in md_operand(). */
6771 *str = input_line_pointer;
6772 input_line_pointer = save_in;
6773 return 1;
6774 }
b99bd4ef
NC
6775
6776#ifdef OBJ_AOUT
6777 if (seg != absolute_section
6778 && seg != text_section
6779 && seg != data_section
6780 && seg != bss_section
6781 && seg != undefined_section)
6782 {
6783 inst.error = _("bad_segment");
6784 *str = input_line_pointer;
6785 input_line_pointer = save_in;
6786 return 1;
6787 }
6788#endif
6789
6790 /* Get rid of any bignums now, so that we don't generate an error for which
6791 we can't establish a line number later on. Big numbers are never valid
6792 in instructions, which is where this routine is always called. */
6793 if (ep->X_op == O_big
6794 || (ep->X_add_symbol
6795 && (walk_no_bignums (ep->X_add_symbol)
6796 || (ep->X_op_symbol
6797 && walk_no_bignums (ep->X_op_symbol)))))
6798 {
f03698e6 6799 inst.error = _("invalid constant");
b99bd4ef
NC
6800 *str = input_line_pointer;
6801 input_line_pointer = save_in;
6802 return 1;
6803 }
6804
6805 *str = input_line_pointer;
6806 input_line_pointer = save_in;
6807 return 0;
6808}
6809
cc8a6dd0 6810/* We handle all bad expressions here, so that we can report the faulty
f03698e6
RE
6811 instruction in the error message. */
6812void
ce058b6c 6813md_operand (expr)
f03698e6
RE
6814 expressionS *expr;
6815{
6816 if (in_my_get_expression)
6817 {
6818 expr->X_op = O_illegal;
6819 if (inst.error == NULL)
6820 inst.error = _("bad expression");
6821 }
6822}
6823
09d92015 6824/* KIND indicates what kind of shifts are accepted. */
b99bd4ef
NC
6825
6826static int
09d92015 6827decode_shift (str, kind)
b99bd4ef 6828 char ** str;
09d92015 6829 int kind;
b99bd4ef
NC
6830{
6831 const struct asm_shift_name * shift;
6832 char * p;
6833 char c;
6834
6835 skip_whitespace (* str);
6836
3882b010 6837 for (p = * str; ISALPHA (* p); p ++)
b99bd4ef
NC
6838 ;
6839
6840 if (p == * str)
6841 {
f03698e6 6842 inst.error = _("shift expression expected");
b99bd4ef
NC
6843 return FAIL;
6844 }
6845
6846 c = * p;
6847 * p = '\0';
6848 shift = (const struct asm_shift_name *) hash_find (arm_shift_hsh, * str);
6849 * p = c;
6850
6851 if (shift == NULL)
6852 {
f03698e6 6853 inst.error = _("shift expression expected");
b99bd4ef
NC
6854 return FAIL;
6855 }
6856
6857 assert (shift->properties->index == shift_properties[shift->properties->index].index);
6858
09d92015
MM
6859 if (kind == SHIFT_LSL_OR_ASR_IMMEDIATE
6860 && shift->properties->index != SHIFT_LSL
6861 && shift->properties->index != SHIFT_ASR)
6862 {
6863 inst.error = _("'LSL' or 'ASR' required");
6864 return FAIL;
6865 }
6866 else if (kind == SHIFT_LSL_IMMEDIATE
6867 && shift->properties->index != SHIFT_LSL)
6868 {
6869 inst.error = _("'LSL' required");
6870 return FAIL;
6871 }
6872 else if (kind == SHIFT_ASR_IMMEDIATE
6873 && shift->properties->index != SHIFT_ASR)
6874 {
6875 inst.error = _("'ASR' required");
6876 return FAIL;
6877 }
6878
b99bd4ef
NC
6879 if (shift->properties->index == SHIFT_RRX)
6880 {
6881 * str = p;
6882 inst.instruction |= shift->properties->bit_field;
6883 return SUCCESS;
6884 }
6885
6886 skip_whitespace (p);
6887
09d92015 6888 if (kind == NO_SHIFT_RESTRICT && reg_required_here (& p, 8) != FAIL)
b99bd4ef
NC
6889 {
6890 inst.instruction |= shift->properties->bit_field | SHIFT_BY_REG;
6891 * str = p;
6892 return SUCCESS;
6893 }
6894 else if (! is_immediate_prefix (* p))
6895 {
09d92015 6896 inst.error = (NO_SHIFT_RESTRICT
b99bd4ef
NC
6897 ? _("shift requires register or #expression")
6898 : _("shift requires #expression"));
6899 * str = p;
6900 return FAIL;
6901 }
6902
6903 inst.error = NULL;
6904 p ++;
6905
6906 if (my_get_expression (& inst.reloc.exp, & p))
6907 return FAIL;
6908
6909 /* Validate some simple #expressions. */
6910 if (inst.reloc.exp.X_op == O_constant)
6911 {
6912 unsigned num = inst.reloc.exp.X_add_number;
6913
6914 /* Reject operations greater than 32. */
6915 if (num > 32
6916 /* Reject a shift of 0 unless the mode allows it. */
6917 || (num == 0 && shift->properties->allows_0 == 0)
6918 /* Reject a shift of 32 unless the mode allows it. */
6919 || (num == 32 && shift->properties->allows_32 == 0)
6920 )
6921 {
6922 /* As a special case we allow a shift of zero for
6923 modes that do not support it to be recoded as an
6924 logical shift left of zero (ie nothing). We warn
6925 about this though. */
6926 if (num == 0)
6927 {
f03698e6 6928 as_warn (_("shift of 0 ignored."));
b99bd4ef
NC
6929 shift = & shift_names[0];
6930 assert (shift->properties->index == SHIFT_LSL);
6931 }
6932 else
6933 {
f03698e6 6934 inst.error = _("invalid immediate shift");
b99bd4ef
NC
6935 return FAIL;
6936 }
6937 }
6938
6939 /* Shifts of 32 are encoded as 0, for those shifts that
6940 support it. */
6941 if (num == 32)
6942 num = 0;
6943
6944 inst.instruction |= (num << 7) | shift->properties->bit_field;
6945 }
6946 else
6947 {
6948 inst.reloc.type = BFD_RELOC_ARM_SHIFT_IMM;
6949 inst.reloc.pc_rel = 0;
6950 inst.instruction |= shift->properties->bit_field;
6951 }
6952
6953 * str = p;
6954 return SUCCESS;
6955}
6956
6957/* Do those data_ops which can take a negative immediate constant
2d2255b5 6958 by altering the instruction. A bit of a hack really.
b99bd4ef
NC
6959 MOV <-> MVN
6960 AND <-> BIC
6961 ADC <-> SBC
6962 by inverting the second operand, and
6963 ADD <-> SUB
6964 CMP <-> CMN
6965 by negating the second operand. */
6966
6967static int
6968negate_data_op (instruction, value)
6969 unsigned long * instruction;
6970 unsigned long value;
6971{
6972 int op, new_inst;
6973 unsigned long negated, inverted;
6974
6975 negated = validate_immediate (-value);
6976 inverted = validate_immediate (~value);
6977
6978 op = (*instruction >> DATA_OP_SHIFT) & 0xf;
6979 switch (op)
6980 {
6981 /* First negates. */
6982 case OPCODE_SUB: /* ADD <-> SUB */
6983 new_inst = OPCODE_ADD;
6984 value = negated;
6985 break;
6986
6987 case OPCODE_ADD:
6988 new_inst = OPCODE_SUB;
6989 value = negated;
6990 break;
6991
6992 case OPCODE_CMP: /* CMP <-> CMN */
6993 new_inst = OPCODE_CMN;
6994 value = negated;
6995 break;
6996
6997 case OPCODE_CMN:
6998 new_inst = OPCODE_CMP;
6999 value = negated;
7000 break;
7001
7002 /* Now Inverted ops. */
7003 case OPCODE_MOV: /* MOV <-> MVN */
7004 new_inst = OPCODE_MVN;
7005 value = inverted;
7006 break;
7007
7008 case OPCODE_MVN:
7009 new_inst = OPCODE_MOV;
7010 value = inverted;
7011 break;
7012
7013 case OPCODE_AND: /* AND <-> BIC */
7014 new_inst = OPCODE_BIC;
7015 value = inverted;
7016 break;
7017
7018 case OPCODE_BIC:
7019 new_inst = OPCODE_AND;
7020 value = inverted;
7021 break;
7022
7023 case OPCODE_ADC: /* ADC <-> SBC */
7024 new_inst = OPCODE_SBC;
7025 value = inverted;
7026 break;
7027
7028 case OPCODE_SBC:
7029 new_inst = OPCODE_ADC;
7030 value = inverted;
7031 break;
7032
7033 /* We cannot do anything. */
7034 default:
7035 return FAIL;
7036 }
7037
7038 if (value == (unsigned) FAIL)
7039 return FAIL;
7040
7041 *instruction &= OPCODE_MASK;
7042 *instruction |= new_inst << DATA_OP_SHIFT;
7043 return value;
7044}
7045
7046static int
7047data_op2 (str)
7048 char ** str;
7049{
7050 int value;
7051 expressionS expr;
7052
7053 skip_whitespace (* str);
7054
7055 if (reg_required_here (str, 0) != FAIL)
7056 {
7057 if (skip_past_comma (str) == SUCCESS)
7058 /* Shift operation on register. */
7059 return decode_shift (str, NO_SHIFT_RESTRICT);
7060
7061 return SUCCESS;
7062 }
7063 else
7064 {
7065 /* Immediate expression. */
7066 if (is_immediate_prefix (**str))
7067 {
7068 (*str)++;
7069 inst.error = NULL;
7070
7071 if (my_get_expression (&inst.reloc.exp, str))
7072 return FAIL;
7073
7074 if (inst.reloc.exp.X_add_symbol)
7075 {
7076 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
7077 inst.reloc.pc_rel = 0;
7078 }
7079 else
7080 {
7081 if (skip_past_comma (str) == SUCCESS)
7082 {
7083 /* #x, y -- ie explicit rotation by Y. */
7084 if (my_get_expression (&expr, str))
7085 return FAIL;
7086
7087 if (expr.X_op != O_constant)
7088 {
f03698e6 7089 inst.error = _("constant expression expected");
b99bd4ef
NC
7090 return FAIL;
7091 }
7092
7093 /* Rotate must be a multiple of 2. */
7094 if (((unsigned) expr.X_add_number) > 30
7095 || (expr.X_add_number & 1) != 0
7096 || ((unsigned) inst.reloc.exp.X_add_number) > 255)
7097 {
f03698e6 7098 inst.error = _("invalid constant");
b99bd4ef
NC
7099 return FAIL;
7100 }
7101 inst.instruction |= INST_IMMEDIATE;
7102 inst.instruction |= inst.reloc.exp.X_add_number;
7103 inst.instruction |= expr.X_add_number << 7;
7104 return SUCCESS;
7105 }
7106
7107 /* Implicit rotation, select a suitable one. */
7108 value = validate_immediate (inst.reloc.exp.X_add_number);
7109
7110 if (value == FAIL)
7111 {
7112 /* Can't be done. Perhaps the code reads something like
7113 "add Rd, Rn, #-n", where "sub Rd, Rn, #n" would be OK. */
7114 if ((value = negate_data_op (&inst.instruction,
7115 inst.reloc.exp.X_add_number))
7116 == FAIL)
7117 {
f03698e6 7118 inst.error = _("invalid constant");
b99bd4ef
NC
7119 return FAIL;
7120 }
7121 }
7122
7123 inst.instruction |= value;
7124 }
7125
7126 inst.instruction |= INST_IMMEDIATE;
7127 return SUCCESS;
7128 }
7129
7130 (*str)++;
f03698e6 7131 inst.error = _("register or shift expression expected");
b99bd4ef
NC
7132 return FAIL;
7133 }
7134}
7135
7136static int
7137fp_op2 (str)
7138 char ** str;
7139{
7140 skip_whitespace (* str);
7141
7142 if (fp_reg_required_here (str, 0) != FAIL)
7143 return SUCCESS;
7144 else
7145 {
7146 /* Immediate expression. */
7147 if (*((*str)++) == '#')
7148 {
7149 int i;
7150
7151 inst.error = NULL;
7152
7153 skip_whitespace (* str);
7154
7155 /* First try and match exact strings, this is to guarantee
7156 that some formats will work even for cross assembly. */
7157
7158 for (i = 0; fp_const[i]; i++)
7159 {
7160 if (strncmp (*str, fp_const[i], strlen (fp_const[i])) == 0)
7161 {
7162 char *start = *str;
7163
7164 *str += strlen (fp_const[i]);
7165 if (is_end_of_line[(unsigned char) **str])
7166 {
7167 inst.instruction |= i + 8;
7168 return SUCCESS;
7169 }
7170 *str = start;
7171 }
7172 }
7173
7174 /* Just because we didn't get a match doesn't mean that the
7175 constant isn't valid, just that it is in a format that we
7176 don't automatically recognize. Try parsing it with
7177 the standard expression routines. */
7178 if ((i = my_get_float_expression (str)) >= 0)
7179 {
7180 inst.instruction |= i + 8;
7181 return SUCCESS;
7182 }
7183
f03698e6 7184 inst.error = _("invalid floating point immediate expression");
b99bd4ef
NC
7185 return FAIL;
7186 }
7187 inst.error =
f03698e6 7188 _("floating point register or immediate expression expected");
b99bd4ef
NC
7189 return FAIL;
7190 }
7191}
7192
7193static void
f2b7cb0a 7194do_arit (str)
b99bd4ef 7195 char * str;
b99bd4ef
NC
7196{
7197 skip_whitespace (str);
7198
7199 if (reg_required_here (&str, 12) == FAIL
7200 || skip_past_comma (&str) == FAIL
7201 || reg_required_here (&str, 16) == FAIL
7202 || skip_past_comma (&str) == FAIL
7203 || data_op2 (&str) == FAIL)
7204 {
7205 if (!inst.error)
7206 inst.error = BAD_ARGS;
7207 return;
7208 }
7209
b99bd4ef 7210 end_of_line (str);
b99bd4ef
NC
7211}
7212
7213static void
f2b7cb0a 7214do_adr (str)
b99bd4ef 7215 char * str;
b99bd4ef 7216{
90e4755a
RE
7217 /* This is a pseudo-op of the form "adr rd, label" to be converted
7218 into a relative address of the form "add rd, pc, #label-.-8". */
7219 skip_whitespace (str);
7220
7221 if (reg_required_here (&str, 12) == FAIL
7222 || skip_past_comma (&str) == FAIL
7223 || my_get_expression (&inst.reloc.exp, &str))
7224 {
7225 if (!inst.error)
7226 inst.error = BAD_ARGS;
7227 return;
7228 }
7229
7230 /* Frag hacking will turn this into a sub instruction if the offset turns
7231 out to be negative. */
7232 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
250355db 7233#ifndef TE_WINCE
90e4755a 7234 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust. */
250355db 7235#endif
90e4755a
RE
7236 inst.reloc.pc_rel = 1;
7237
7238 end_of_line (str);
7239}
7240
7241static void
f2b7cb0a 7242do_adrl (str)
90e4755a 7243 char * str;
90e4755a
RE
7244{
7245 /* This is a pseudo-op of the form "adrl rd, label" to be converted
7246 into a relative address of the form:
7247 add rd, pc, #low(label-.-8)"
7248 add rd, rd, #high(label-.-8)" */
7249
7250 skip_whitespace (str);
7251
7252 if (reg_required_here (&str, 12) == FAIL
7253 || skip_past_comma (&str) == FAIL
7254 || my_get_expression (&inst.reloc.exp, &str))
7255 {
7256 if (!inst.error)
7257 inst.error = BAD_ARGS;
7258
7259 return;
7260 }
7261
7262 end_of_line (str);
7263 /* Frag hacking will turn this into a sub instruction if the offset turns
7264 out to be negative. */
7265 inst.reloc.type = BFD_RELOC_ARM_ADRL_IMMEDIATE;
250355db 7266#ifndef TE_WINCE
90e4755a 7267 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust */
250355db 7268#endif
90e4755a
RE
7269 inst.reloc.pc_rel = 1;
7270 inst.size = INSN_SIZE * 2;
90e4755a
RE
7271}
7272
7273static void
f2b7cb0a 7274do_cmp (str)
90e4755a 7275 char * str;
90e4755a
RE
7276{
7277 skip_whitespace (str);
7278
7279 if (reg_required_here (&str, 16) == FAIL)
7280 {
7281 if (!inst.error)
7282 inst.error = BAD_ARGS;
7283 return;
7284 }
7285
7286 if (skip_past_comma (&str) == FAIL
7287 || data_op2 (&str) == FAIL)
7288 {
7289 if (!inst.error)
7290 inst.error = BAD_ARGS;
7291 return;
7292 }
7293
90e4755a 7294 end_of_line (str);
90e4755a
RE
7295}
7296
7297static void
f2b7cb0a 7298do_mov (str)
90e4755a 7299 char * str;
90e4755a
RE
7300{
7301 skip_whitespace (str);
7302
7303 if (reg_required_here (&str, 12) == FAIL)
7304 {
7305 if (!inst.error)
7306 inst.error = BAD_ARGS;
7307 return;
7308 }
7309
7310 if (skip_past_comma (&str) == FAIL
7311 || data_op2 (&str) == FAIL)
7312 {
7313 if (!inst.error)
7314 inst.error = BAD_ARGS;
7315 return;
7316 }
7317
90e4755a 7318 end_of_line (str);
90e4755a
RE
7319}
7320
7321static int
7322ldst_extend (str)
7323 char ** str;
7324{
7325 int add = INDEX_UP;
7326
7327 switch (**str)
7328 {
7329 case '#':
7330 case '$':
7331 (*str)++;
7332 if (my_get_expression (& inst.reloc.exp, str))
7333 return FAIL;
7334
7335 if (inst.reloc.exp.X_op == O_constant)
7336 {
7337 int value = inst.reloc.exp.X_add_number;
7338
7339 if (value < -4095 || value > 4095)
7340 {
7341 inst.error = _("address offset too large");
7342 return FAIL;
7343 }
7344
7345 if (value < 0)
7346 {
7347 value = -value;
7348 add = 0;
7349 }
7350
7351 inst.instruction |= add | value;
7352 }
7353 else
7354 {
7355 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
7356 inst.reloc.pc_rel = 0;
7357 }
7358 return SUCCESS;
7359
7360 case '-':
7361 add = 0;
7362 /* Fall through. */
7363
7364 case '+':
7365 (*str)++;
7366 /* Fall through. */
7367
7368 default:
7369 if (reg_required_here (str, 0) == FAIL)
7370 return FAIL;
7371
7372 inst.instruction |= add | OFFSET_REG;
7373 if (skip_past_comma (str) == SUCCESS)
09d92015 7374 return decode_shift (str, SHIFT_IMMEDIATE);
90e4755a
RE
7375
7376 return SUCCESS;
7377 }
7378}
7379
7380static void
f2b7cb0a 7381do_ldst (str)
90e4755a 7382 char * str;
90e4755a
RE
7383{
7384 int pre_inc = 0;
7385 int conflict_reg;
7386 int value;
7387
b99bd4ef
NC
7388 skip_whitespace (str);
7389
90e4755a
RE
7390 if ((conflict_reg = reg_required_here (&str, 12)) == FAIL)
7391 {
7392 if (!inst.error)
7393 inst.error = BAD_ARGS;
7394 return;
7395 }
7396
7397 if (skip_past_comma (&str) == FAIL)
7398 {
f03698e6 7399 inst.error = _("address expected");
90e4755a
RE
7400 return;
7401 }
7402
90e4755a
RE
7403 if (*str == '[')
7404 {
7405 int reg;
7406
7407 str++;
7408
7409 skip_whitespace (str);
7410
7411 if ((reg = reg_required_here (&str, 16)) == FAIL)
7412 return;
7413
7414 /* Conflicts can occur on stores as well as loads. */
7415 conflict_reg = (conflict_reg == reg);
7416
7417 skip_whitespace (str);
7418
7419 if (*str == ']')
7420 {
7421 str ++;
7422
7423 if (skip_past_comma (&str) == SUCCESS)
7424 {
7425 /* [Rn],... (post inc) */
7426 if (ldst_extend (&str) == FAIL)
7427 return;
7428 if (conflict_reg)
7429 as_warn (_("%s register same as write-back base"),
7430 ((inst.instruction & LOAD_BIT)
7431 ? _("destination") : _("source")));
7432 }
7433 else
7434 {
7435 /* [Rn] */
7436 skip_whitespace (str);
7437
7438 if (*str == '!')
7439 {
7440 if (conflict_reg)
7441 as_warn (_("%s register same as write-back base"),
7442 ((inst.instruction & LOAD_BIT)
7443 ? _("destination") : _("source")));
7444 str++;
7445 inst.instruction |= WRITE_BACK;
7446 }
7447
7448 inst.instruction |= INDEX_UP;
7449 pre_inc = 1;
7450 }
7451 }
7452 else
7453 {
7454 /* [Rn,...] */
7455 if (skip_past_comma (&str) == FAIL)
7456 {
7457 inst.error = _("pre-indexed expression expected");
7458 return;
7459 }
7460
7461 pre_inc = 1;
7462 if (ldst_extend (&str) == FAIL)
7463 return;
7464
7465 skip_whitespace (str);
7466
7467 if (*str++ != ']')
7468 {
7469 inst.error = _("missing ]");
7470 return;
7471 }
7472
7473 skip_whitespace (str);
7474
7475 if (*str == '!')
7476 {
7477 if (conflict_reg)
7478 as_warn (_("%s register same as write-back base"),
7479 ((inst.instruction & LOAD_BIT)
7480 ? _("destination") : _("source")));
7481 str++;
7482 inst.instruction |= WRITE_BACK;
7483 }
7484 }
7485 }
7486 else if (*str == '=')
7487 {
f03698e6
RE
7488 if ((inst.instruction & LOAD_BIT) == 0)
7489 {
7490 inst.error = _("invalid pseudo operation");
7491 return;
7492 }
7493
90e4755a
RE
7494 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
7495 str++;
7496
7497 skip_whitespace (str);
7498
7499 if (my_get_expression (&inst.reloc.exp, &str))
7500 return;
7501
7502 if (inst.reloc.exp.X_op != O_constant
7503 && inst.reloc.exp.X_op != O_symbol)
7504 {
f03698e6 7505 inst.error = _("constant expression expected");
90e4755a
RE
7506 return;
7507 }
7508
e28cd48c 7509 if (inst.reloc.exp.X_op == O_constant)
90e4755a 7510 {
e28cd48c
RE
7511 value = validate_immediate (inst.reloc.exp.X_add_number);
7512
7513 if (value != FAIL)
90e4755a 7514 {
e28cd48c
RE
7515 /* This can be done with a mov instruction. */
7516 inst.instruction &= LITERAL_MASK;
7517 inst.instruction |= (INST_IMMEDIATE
7518 | (OPCODE_MOV << DATA_OP_SHIFT));
7519 inst.instruction |= value & 0xfff;
7520 end_of_line (str);
90e4755a
RE
7521 return;
7522 }
b99bd4ef 7523
e28cd48c
RE
7524 value = validate_immediate (~inst.reloc.exp.X_add_number);
7525
7526 if (value != FAIL)
7527 {
7528 /* This can be done with a mvn instruction. */
7529 inst.instruction &= LITERAL_MASK;
7530 inst.instruction |= (INST_IMMEDIATE
7531 | (OPCODE_MVN << DATA_OP_SHIFT));
7532 inst.instruction |= value & 0xfff;
7533 end_of_line (str);
7534 return;
7535 }
90e4755a 7536 }
e28cd48c
RE
7537
7538 /* Insert into literal pool. */
7539 if (add_to_lit_pool () == FAIL)
7540 {
7541 if (!inst.error)
7542 inst.error = _("literal pool insertion failed");
7543 return;
7544 }
7545
7546 /* Change the instruction exp to point to the pool. */
7547 inst.reloc.type = BFD_RELOC_ARM_LITERAL;
7548 inst.reloc.pc_rel = 1;
7549 inst.instruction |= (REG_PC << 16);
7550 pre_inc = 1;
1cac9012
NC
7551 }
7552 else
7553 {
90e4755a
RE
7554 if (my_get_expression (&inst.reloc.exp, &str))
7555 return;
7556
7557 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
7558#ifndef TE_WINCE
7559 /* PC rel adjust. */
7560 inst.reloc.exp.X_add_number -= 8;
7561#endif
1cac9012 7562 inst.reloc.pc_rel = 1;
90e4755a
RE
7563 inst.instruction |= (REG_PC << 16);
7564 pre_inc = 1;
b99bd4ef
NC
7565 }
7566
90e4755a 7567 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
b99bd4ef 7568 end_of_line (str);
b99bd4ef
NC
7569}
7570
7571static void
f2b7cb0a 7572do_ldstt (str)
90e4755a 7573 char * str;
b99bd4ef 7574{
90e4755a
RE
7575 int conflict_reg;
7576
b99bd4ef
NC
7577 skip_whitespace (str);
7578
90e4755a 7579 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
b99bd4ef
NC
7580 {
7581 if (!inst.error)
7582 inst.error = BAD_ARGS;
7583 return;
7584 }
7585
90e4755a 7586 if (skip_past_comma (& str) == FAIL)
b99bd4ef 7587 {
f03698e6 7588 inst.error = _("address expected");
b99bd4ef
NC
7589 return;
7590 }
7591
90e4755a
RE
7592 if (*str == '[')
7593 {
7594 int reg;
b99bd4ef 7595
90e4755a 7596 str++;
b99bd4ef 7597
90e4755a 7598 skip_whitespace (str);
b99bd4ef 7599
90e4755a
RE
7600 if ((reg = reg_required_here (&str, 16)) == FAIL)
7601 return;
b99bd4ef 7602
90e4755a
RE
7603 /* ldrt/strt always use post-indexed addressing, so if the base is
7604 the same as Rd, we warn. */
7605 if (conflict_reg == reg)
7606 as_warn (_("%s register same as write-back base"),
7607 ((inst.instruction & LOAD_BIT)
7608 ? _("destination") : _("source")));
7609
7610 skip_whitespace (str);
7611
7612 if (*str == ']')
7613 {
7614 str ++;
7615
7616 if (skip_past_comma (&str) == SUCCESS)
7617 {
7618 /* [Rn],... (post inc) */
7619 if (ldst_extend (&str) == FAIL)
7620 return;
7621 }
7622 else
7623 {
7624 /* [Rn] */
7625 skip_whitespace (str);
7626
7627 /* Skip a write-back '!'. */
7628 if (*str == '!')
7629 str++;
7630
7631 inst.instruction |= INDEX_UP;
7632 }
7633 }
7634 else
7635 {
7636 inst.error = _("post-indexed expression expected");
7637 return;
7638 }
7639 }
7640 else
b99bd4ef 7641 {
90e4755a 7642 inst.error = _("post-indexed expression expected");
b99bd4ef
NC
7643 return;
7644 }
7645
b99bd4ef 7646 end_of_line (str);
b99bd4ef
NC
7647}
7648
7649static int
90e4755a 7650ldst_extend_v4 (str)
b99bd4ef 7651 char ** str;
b99bd4ef
NC
7652{
7653 int add = INDEX_UP;
7654
7655 switch (**str)
7656 {
7657 case '#':
7658 case '$':
7659 (*str)++;
7660 if (my_get_expression (& inst.reloc.exp, str))
7661 return FAIL;
7662
7663 if (inst.reloc.exp.X_op == O_constant)
7664 {
7665 int value = inst.reloc.exp.X_add_number;
7666
90e4755a 7667 if (value < -255 || value > 255)
b99bd4ef
NC
7668 {
7669 inst.error = _("address offset too large");
7670 return FAIL;
7671 }
7672
7673 if (value < 0)
7674 {
7675 value = -value;
7676 add = 0;
7677 }
7678
7679 /* Halfword and signextension instructions have the
7680 immediate value split across bits 11..8 and bits 3..0. */
90e4755a
RE
7681 inst.instruction |= (add | HWOFFSET_IMM
7682 | ((value >> 4) << 8) | (value & 0xF));
b99bd4ef
NC
7683 }
7684 else
7685 {
90e4755a
RE
7686 inst.instruction |= HWOFFSET_IMM;
7687 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
b99bd4ef
NC
7688 inst.reloc.pc_rel = 0;
7689 }
7690 return SUCCESS;
7691
7692 case '-':
7693 add = 0;
7694 /* Fall through. */
7695
7696 case '+':
7697 (*str)++;
7698 /* Fall through. */
7699
7700 default:
7701 if (reg_required_here (str, 0) == FAIL)
7702 return FAIL;
7703
90e4755a 7704 inst.instruction |= add;
b99bd4ef
NC
7705 return SUCCESS;
7706 }
7707}
7708
90e4755a 7709/* Halfword and signed-byte load/store operations. */
b99bd4ef 7710static void
f2b7cb0a 7711do_ldstv4 (str)
b99bd4ef 7712 char * str;
b99bd4ef 7713{
b99bd4ef
NC
7714 int pre_inc = 0;
7715 int conflict_reg;
7716 int value;
7717
b99bd4ef
NC
7718 skip_whitespace (str);
7719
7720 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
7721 {
7722 if (!inst.error)
7723 inst.error = BAD_ARGS;
7724 return;
7725 }
7726
7727 if (skip_past_comma (& str) == FAIL)
7728 {
f03698e6 7729 inst.error = _("address expected");
b99bd4ef
NC
7730 return;
7731 }
7732
7733 if (*str == '[')
7734 {
7735 int reg;
7736
7737 str++;
7738
7739 skip_whitespace (str);
7740
7741 if ((reg = reg_required_here (&str, 16)) == FAIL)
7742 return;
7743
7744 /* Conflicts can occur on stores as well as loads. */
7745 conflict_reg = (conflict_reg == reg);
7746
7747 skip_whitespace (str);
7748
7749 if (*str == ']')
7750 {
7751 str ++;
7752
7753 if (skip_past_comma (&str) == SUCCESS)
7754 {
7755 /* [Rn],... (post inc) */
90e4755a 7756 if (ldst_extend_v4 (&str) == FAIL)
b99bd4ef
NC
7757 return;
7758 if (conflict_reg)
90e4755a
RE
7759 as_warn (_("%s register same as write-back base"),
7760 ((inst.instruction & LOAD_BIT)
7761 ? _("destination") : _("source")));
b99bd4ef
NC
7762 }
7763 else
7764 {
7765 /* [Rn] */
90e4755a 7766 inst.instruction |= HWOFFSET_IMM;
b99bd4ef
NC
7767
7768 skip_whitespace (str);
7769
7770 if (*str == '!')
7771 {
7772 if (conflict_reg)
7773 as_warn (_("%s register same as write-back base"),
7774 ((inst.instruction & LOAD_BIT)
7775 ? _("destination") : _("source")));
7776 str++;
7777 inst.instruction |= WRITE_BACK;
7778 }
7779
90e4755a
RE
7780 inst.instruction |= INDEX_UP;
7781 pre_inc = 1;
b99bd4ef
NC
7782 }
7783 }
7784 else
7785 {
7786 /* [Rn,...] */
7787 if (skip_past_comma (&str) == FAIL)
7788 {
7789 inst.error = _("pre-indexed expression expected");
7790 return;
7791 }
7792
7793 pre_inc = 1;
90e4755a 7794 if (ldst_extend_v4 (&str) == FAIL)
b99bd4ef
NC
7795 return;
7796
7797 skip_whitespace (str);
7798
7799 if (*str++ != ']')
7800 {
7801 inst.error = _("missing ]");
7802 return;
7803 }
7804
7805 skip_whitespace (str);
7806
7807 if (*str == '!')
7808 {
7809 if (conflict_reg)
7810 as_warn (_("%s register same as write-back base"),
7811 ((inst.instruction & LOAD_BIT)
7812 ? _("destination") : _("source")));
7813 str++;
7814 inst.instruction |= WRITE_BACK;
7815 }
7816 }
7817 }
7818 else if (*str == '=')
7819 {
f03698e6
RE
7820 if ((inst.instruction & LOAD_BIT) == 0)
7821 {
7822 inst.error = _("invalid pseudo operation");
7823 return;
7824 }
7825
90e4755a 7826 /* XXX Does this work correctly for half-word/byte ops? */
b99bd4ef
NC
7827 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
7828 str++;
7829
7830 skip_whitespace (str);
7831
7832 if (my_get_expression (&inst.reloc.exp, &str))
7833 return;
7834
7835 if (inst.reloc.exp.X_op != O_constant
7836 && inst.reloc.exp.X_op != O_symbol)
7837 {
f03698e6 7838 inst.error = _("constant expression expected");
b99bd4ef
NC
7839 return;
7840 }
7841
d8273442 7842 if (inst.reloc.exp.X_op == O_constant)
b99bd4ef 7843 {
d8273442
NC
7844 value = validate_immediate (inst.reloc.exp.X_add_number);
7845
7846 if (value != FAIL)
b99bd4ef 7847 {
d8273442
NC
7848 /* This can be done with a mov instruction. */
7849 inst.instruction &= LITERAL_MASK;
7850 inst.instruction |= INST_IMMEDIATE | (OPCODE_MOV << DATA_OP_SHIFT);
90e4755a 7851 inst.instruction |= value & 0xfff;
d8273442 7852 end_of_line (str);
b99bd4ef
NC
7853 return;
7854 }
cc8a6dd0 7855
d8273442 7856 value = validate_immediate (~ inst.reloc.exp.X_add_number);
b99bd4ef 7857
d8273442 7858 if (value != FAIL)
b99bd4ef 7859 {
d8273442
NC
7860 /* This can be done with a mvn instruction. */
7861 inst.instruction &= LITERAL_MASK;
7862 inst.instruction |= INST_IMMEDIATE | (OPCODE_MVN << DATA_OP_SHIFT);
90e4755a 7863 inst.instruction |= value & 0xfff;
d8273442
NC
7864 end_of_line (str);
7865 return;
b99bd4ef 7866 }
b99bd4ef 7867 }
d8273442
NC
7868
7869 /* Insert into literal pool. */
7870 if (add_to_lit_pool () == FAIL)
7871 {
7872 if (!inst.error)
7873 inst.error = _("literal pool insertion failed");
7874 return;
7875 }
7876
7877 /* Change the instruction exp to point to the pool. */
90e4755a
RE
7878 inst.instruction |= HWOFFSET_IMM;
7879 inst.reloc.type = BFD_RELOC_ARM_HWLITERAL;
d8273442
NC
7880 inst.reloc.pc_rel = 1;
7881 inst.instruction |= (REG_PC << 16);
7882 pre_inc = 1;
b99bd4ef
NC
7883 }
7884 else
7885 {
7886 if (my_get_expression (&inst.reloc.exp, &str))
7887 return;
7888
90e4755a
RE
7889 inst.instruction |= HWOFFSET_IMM;
7890 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
b99bd4ef
NC
7891#ifndef TE_WINCE
7892 /* PC rel adjust. */
7893 inst.reloc.exp.X_add_number -= 8;
7894#endif
7895 inst.reloc.pc_rel = 1;
7896 inst.instruction |= (REG_PC << 16);
7897 pre_inc = 1;
7898 }
7899
90e4755a 7900 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
b99bd4ef 7901 end_of_line (str);
b99bd4ef
NC
7902}
7903
7904static long
7905reg_list (strp)
7906 char ** strp;
7907{
7908 char * str = * strp;
7909 long range = 0;
7910 int another_range;
7911
7912 /* We come back here if we get ranges concatenated by '+' or '|'. */
7913 do
7914 {
7915 another_range = 0;
7916
7917 if (*str == '{')
7918 {
7919 int in_range = 0;
7920 int cur_reg = -1;
7921
7922 str++;
7923 do
7924 {
7925 int reg;
7926
7927 skip_whitespace (str);
7928
7929 if ((reg = reg_required_here (& str, -1)) == FAIL)
7930 return FAIL;
7931
7932 if (in_range)
7933 {
7934 int i;
7935
7936 if (reg <= cur_reg)
7937 {
f03698e6 7938 inst.error = _("bad range in register list");
b99bd4ef
NC
7939 return FAIL;
7940 }
7941
7942 for (i = cur_reg + 1; i < reg; i++)
7943 {
7944 if (range & (1 << i))
7945 as_tsktsk
f03698e6 7946 (_("Warning: duplicated register (r%d) in register list"),
b99bd4ef
NC
7947 i);
7948 else
7949 range |= 1 << i;
7950 }
7951 in_range = 0;
7952 }
7953
7954 if (range & (1 << reg))
f03698e6 7955 as_tsktsk (_("Warning: duplicated register (r%d) in register list"),
b99bd4ef
NC
7956 reg);
7957 else if (reg <= cur_reg)
f03698e6 7958 as_tsktsk (_("Warning: register range not in ascending order"));
b99bd4ef
NC
7959
7960 range |= 1 << reg;
7961 cur_reg = reg;
7962 }
7963 while (skip_past_comma (&str) != FAIL
7964 || (in_range = 1, *str++ == '-'));
7965 str--;
7966 skip_whitespace (str);
7967
7968 if (*str++ != '}')
7969 {
f03698e6 7970 inst.error = _("missing `}'");
b99bd4ef
NC
7971 return FAIL;
7972 }
7973 }
7974 else
7975 {
7976 expressionS expr;
7977
7978 if (my_get_expression (&expr, &str))
7979 return FAIL;
7980
7981 if (expr.X_op == O_constant)
7982 {
7983 if (expr.X_add_number
7984 != (expr.X_add_number & 0x0000ffff))
7985 {
7986 inst.error = _("invalid register mask");
7987 return FAIL;
7988 }
7989
7990 if ((range & expr.X_add_number) != 0)
7991 {
7992 int regno = range & expr.X_add_number;
7993
7994 regno &= -regno;
7995 regno = (1 << regno) - 1;
7996 as_tsktsk
f03698e6 7997 (_("Warning: duplicated register (r%d) in register list"),
b99bd4ef
NC
7998 regno);
7999 }
8000
8001 range |= expr.X_add_number;
8002 }
8003 else
8004 {
8005 if (inst.reloc.type != 0)
8006 {
8007 inst.error = _("expression too complex");
8008 return FAIL;
8009 }
8010
8011 memcpy (&inst.reloc.exp, &expr, sizeof (expressionS));
8012 inst.reloc.type = BFD_RELOC_ARM_MULTI;
8013 inst.reloc.pc_rel = 0;
8014 }
8015 }
8016
8017 skip_whitespace (str);
8018
8019 if (*str == '|' || *str == '+')
8020 {
8021 str++;
8022 another_range = 1;
8023 }
8024 }
8025 while (another_range);
8026
8027 *strp = str;
8028 return range;
8029}
8030
8031static void
f2b7cb0a 8032do_ldmstm (str)
b99bd4ef 8033 char * str;
b99bd4ef
NC
8034{
8035 int base_reg;
8036 long range;
8037
8038 skip_whitespace (str);
8039
8040 if ((base_reg = reg_required_here (&str, 16)) == FAIL)
8041 return;
8042
8043 if (base_reg == REG_PC)
8044 {
8045 inst.error = _("r15 not allowed as base register");
8046 return;
8047 }
8048
8049 skip_whitespace (str);
8050
8051 if (*str == '!')
8052 {
90e4755a 8053 inst.instruction |= WRITE_BACK;
b99bd4ef
NC
8054 str++;
8055 }
8056
8057 if (skip_past_comma (&str) == FAIL
8058 || (range = reg_list (&str)) == FAIL)
8059 {
8060 if (! inst.error)
8061 inst.error = BAD_ARGS;
8062 return;
8063 }
8064
8065 if (*str == '^')
8066 {
8067 str++;
90e4755a 8068 inst.instruction |= LDM_TYPE_2_OR_3;
b99bd4ef
NC
8069 }
8070
6189168b
NC
8071 if (inst.instruction & WRITE_BACK)
8072 {
8073 /* Check for unpredictable uses of writeback. */
8074 if (inst.instruction & LOAD_BIT)
8075 {
8076 /* Not allowed in LDM type 2. */
8077 if ((inst.instruction & LDM_TYPE_2_OR_3)
8078 && ((range & (1 << REG_PC)) == 0))
8079 as_warn (_("writeback of base register is UNPREDICTABLE"));
8080 /* Only allowed if base reg not in list for other types. */
8081 else if (range & (1 << base_reg))
8082 as_warn (_("writeback of base register when in register list is UNPREDICTABLE"));
8083 }
8084 else /* STM. */
8085 {
8086 /* Not allowed for type 2. */
8087 if (inst.instruction & LDM_TYPE_2_OR_3)
8088 as_warn (_("writeback of base register is UNPREDICTABLE"));
8089 /* Only allowed if base reg not in list, or first in list. */
8090 else if ((range & (1 << base_reg))
8091 && (range & ((1 << base_reg) - 1)))
8092 as_warn (_("if writeback register is in list, it must be the lowest reg in the list"));
8093 }
8094 }
61b5f74b 8095
f2b7cb0a 8096 inst.instruction |= range;
b99bd4ef 8097 end_of_line (str);
b99bd4ef
NC
8098}
8099
8100static void
f2b7cb0a 8101do_swi (str)
b99bd4ef 8102 char * str;
b99bd4ef
NC
8103{
8104 skip_whitespace (str);
8105
8106 /* Allow optional leading '#'. */
8107 if (is_immediate_prefix (*str))
8108 str++;
8109
8110 if (my_get_expression (& inst.reloc.exp, & str))
8111 return;
8112
8113 inst.reloc.type = BFD_RELOC_ARM_SWI;
8114 inst.reloc.pc_rel = 0;
b99bd4ef 8115 end_of_line (str);
b99bd4ef
NC
8116}
8117
8118static void
f2b7cb0a 8119do_swap (str)
b99bd4ef 8120 char * str;
b99bd4ef
NC
8121{
8122 int reg;
8123
8124 skip_whitespace (str);
8125
8126 if ((reg = reg_required_here (&str, 12)) == FAIL)
8127 return;
8128
8129 if (reg == REG_PC)
8130 {
8131 inst.error = _("r15 not allowed in swap");
8132 return;
8133 }
8134
8135 if (skip_past_comma (&str) == FAIL
8136 || (reg = reg_required_here (&str, 0)) == FAIL)
8137 {
8138 if (!inst.error)
8139 inst.error = BAD_ARGS;
8140 return;
8141 }
8142
8143 if (reg == REG_PC)
8144 {
8145 inst.error = _("r15 not allowed in swap");
8146 return;
8147 }
8148
8149 if (skip_past_comma (&str) == FAIL
8150 || *str++ != '[')
8151 {
8152 inst.error = BAD_ARGS;
8153 return;
8154 }
8155
8156 skip_whitespace (str);
8157
8158 if ((reg = reg_required_here (&str, 16)) == FAIL)
8159 return;
8160
8161 if (reg == REG_PC)
8162 {
8163 inst.error = BAD_PC;
8164 return;
8165 }
8166
8167 skip_whitespace (str);
8168
8169 if (*str++ != ']')
8170 {
8171 inst.error = _("missing ]");
8172 return;
8173 }
8174
b99bd4ef 8175 end_of_line (str);
b99bd4ef
NC
8176}
8177
8178static void
f2b7cb0a 8179do_branch (str)
b99bd4ef 8180 char * str;
b99bd4ef
NC
8181{
8182 if (my_get_expression (&inst.reloc.exp, &str))
8183 return;
8184
8185#ifdef OBJ_ELF
8186 {
8187 char * save_in;
8188
8189 /* ScottB: February 5, 1998 - Check to see of PLT32 reloc
8190 required for the instruction. */
8191
8192 /* arm_parse_reloc () works on input_line_pointer.
8193 We actually want to parse the operands to the branch instruction
8194 passed in 'str'. Save the input pointer and restore it later. */
8195 save_in = input_line_pointer;
8196 input_line_pointer = str;
8197 if (inst.reloc.exp.X_op == O_symbol
8198 && *str == '('
8199 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
8200 {
8201 inst.reloc.type = BFD_RELOC_ARM_PLT32;
8202 inst.reloc.pc_rel = 0;
8203 /* Modify str to point to after parsed operands, otherwise
8204 end_of_line() will complain about the (PLT) left in str. */
8205 str = input_line_pointer;
8206 }
8207 else
8208 {
8209 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
8210 inst.reloc.pc_rel = 1;
8211 }
8212 input_line_pointer = save_in;
8213 }
8214#else
8215 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
8216 inst.reloc.pc_rel = 1;
8217#endif /* OBJ_ELF */
8218
8219 end_of_line (str);
b99bd4ef
NC
8220}
8221
8222static void
f2b7cb0a 8223do_bx (str)
b99bd4ef 8224 char * str;
b99bd4ef
NC
8225{
8226 int reg;
8227
8228 skip_whitespace (str);
8229
8230 if ((reg = reg_required_here (&str, 0)) == FAIL)
8231 {
8232 inst.error = BAD_ARGS;
8233 return;
8234 }
8235
8236 /* Note - it is not illegal to do a "bx pc". Useless, but not illegal. */
8237 if (reg == REG_PC)
f03698e6 8238 as_tsktsk (_("use of r15 in bx in ARM mode is not really useful"));
b99bd4ef
NC
8239
8240 end_of_line (str);
8241}
8242
8243static void
f2b7cb0a 8244do_cdp (str)
b99bd4ef 8245 char * str;
b99bd4ef
NC
8246{
8247 /* Co-processor data operation.
8248 Format: CDP{cond} CP#,<expr>,CRd,CRn,CRm{,<expr>} */
8249 skip_whitespace (str);
8250
8251 if (co_proc_number (&str) == FAIL)
8252 {
8253 if (!inst.error)
8254 inst.error = BAD_ARGS;
8255 return;
8256 }
8257
8258 if (skip_past_comma (&str) == FAIL
8259 || cp_opc_expr (&str, 20,4) == FAIL)
8260 {
8261 if (!inst.error)
8262 inst.error = BAD_ARGS;
8263 return;
8264 }
8265
8266 if (skip_past_comma (&str) == FAIL
8267 || cp_reg_required_here (&str, 12) == FAIL)
8268 {
8269 if (!inst.error)
8270 inst.error = BAD_ARGS;
8271 return;
8272 }
8273
8274 if (skip_past_comma (&str) == FAIL
8275 || cp_reg_required_here (&str, 16) == FAIL)
8276 {
8277 if (!inst.error)
8278 inst.error = BAD_ARGS;
8279 return;
8280 }
8281
8282 if (skip_past_comma (&str) == FAIL
8283 || cp_reg_required_here (&str, 0) == FAIL)
8284 {
8285 if (!inst.error)
8286 inst.error = BAD_ARGS;
8287 return;
8288 }
8289
8290 if (skip_past_comma (&str) == SUCCESS)
8291 {
8292 if (cp_opc_expr (&str, 5, 3) == FAIL)
8293 {
8294 if (!inst.error)
8295 inst.error = BAD_ARGS;
8296 return;
8297 }
8298 }
8299
8300 end_of_line (str);
b99bd4ef
NC
8301}
8302
8303static void
f2b7cb0a 8304do_lstc (str)
b99bd4ef 8305 char * str;
b99bd4ef
NC
8306{
8307 /* Co-processor register load/store.
8308 Format: <LDC|STC{cond}[L] CP#,CRd,<address> */
8309
8310 skip_whitespace (str);
8311
8312 if (co_proc_number (&str) == FAIL)
8313 {
8314 if (!inst.error)
8315 inst.error = BAD_ARGS;
8316 return;
8317 }
8318
8319 if (skip_past_comma (&str) == FAIL
8320 || cp_reg_required_here (&str, 12) == FAIL)
8321 {
8322 if (!inst.error)
8323 inst.error = BAD_ARGS;
8324 return;
8325 }
8326
8327 if (skip_past_comma (&str) == FAIL
bfae80f2 8328 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
b99bd4ef
NC
8329 {
8330 if (! inst.error)
8331 inst.error = BAD_ARGS;
8332 return;
8333 }
8334
b99bd4ef 8335 end_of_line (str);
b99bd4ef
NC
8336}
8337
8338static void
f2b7cb0a 8339do_co_reg (str)
b99bd4ef 8340 char * str;
b99bd4ef
NC
8341{
8342 /* Co-processor register transfer.
8343 Format: <MCR|MRC>{cond} CP#,<expr1>,Rd,CRn,CRm{,<expr2>} */
8344
8345 skip_whitespace (str);
8346
8347 if (co_proc_number (&str) == FAIL)
8348 {
8349 if (!inst.error)
8350 inst.error = BAD_ARGS;
8351 return;
8352 }
8353
8354 if (skip_past_comma (&str) == FAIL
8355 || cp_opc_expr (&str, 21, 3) == FAIL)
8356 {
8357 if (!inst.error)
8358 inst.error = BAD_ARGS;
8359 return;
8360 }
8361
8362 if (skip_past_comma (&str) == FAIL
8363 || reg_required_here (&str, 12) == FAIL)
8364 {
8365 if (!inst.error)
8366 inst.error = BAD_ARGS;
8367 return;
8368 }
8369
8370 if (skip_past_comma (&str) == FAIL
8371 || cp_reg_required_here (&str, 16) == FAIL)
8372 {
8373 if (!inst.error)
8374 inst.error = BAD_ARGS;
8375 return;
8376 }
8377
8378 if (skip_past_comma (&str) == FAIL
8379 || cp_reg_required_here (&str, 0) == FAIL)
8380 {
8381 if (!inst.error)
8382 inst.error = BAD_ARGS;
8383 return;
8384 }
8385
8386 if (skip_past_comma (&str) == SUCCESS)
8387 {
8388 if (cp_opc_expr (&str, 5, 3) == FAIL)
8389 {
8390 if (!inst.error)
8391 inst.error = BAD_ARGS;
8392 return;
8393 }
8394 }
b99bd4ef
NC
8395
8396 end_of_line (str);
b99bd4ef
NC
8397}
8398
8399static void
f2b7cb0a 8400do_fpa_ctrl (str)
b99bd4ef 8401 char * str;
b99bd4ef
NC
8402{
8403 /* FP control registers.
8404 Format: <WFS|RFS|WFC|RFC>{cond} Rn */
8405
8406 skip_whitespace (str);
8407
8408 if (reg_required_here (&str, 12) == FAIL)
8409 {
8410 if (!inst.error)
8411 inst.error = BAD_ARGS;
8412 return;
8413 }
8414
8415 end_of_line (str);
b99bd4ef
NC
8416}
8417
8418static void
f2b7cb0a 8419do_fpa_ldst (str)
b99bd4ef 8420 char * str;
b99bd4ef
NC
8421{
8422 skip_whitespace (str);
8423
b99bd4ef
NC
8424 if (fp_reg_required_here (&str, 12) == FAIL)
8425 {
8426 if (!inst.error)
8427 inst.error = BAD_ARGS;
8428 return;
8429 }
8430
8431 if (skip_past_comma (&str) == FAIL
bfae80f2 8432 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
b99bd4ef
NC
8433 {
8434 if (!inst.error)
8435 inst.error = BAD_ARGS;
8436 return;
8437 }
8438
8439 end_of_line (str);
8440}
8441
8442static void
f2b7cb0a 8443do_fpa_ldmstm (str)
b99bd4ef 8444 char * str;
b99bd4ef
NC
8445{
8446 int num_regs;
8447
8448 skip_whitespace (str);
8449
8450 if (fp_reg_required_here (&str, 12) == FAIL)
8451 {
8452 if (! inst.error)
8453 inst.error = BAD_ARGS;
8454 return;
8455 }
8456
8457 /* Get Number of registers to transfer. */
8458 if (skip_past_comma (&str) == FAIL
8459 || my_get_expression (&inst.reloc.exp, &str))
8460 {
8461 if (! inst.error)
8462 inst.error = _("constant expression expected");
8463 return;
8464 }
8465
8466 if (inst.reloc.exp.X_op != O_constant)
8467 {
f03698e6 8468 inst.error = _("constant value required for number of registers");
b99bd4ef
NC
8469 return;
8470 }
8471
8472 num_regs = inst.reloc.exp.X_add_number;
8473
8474 if (num_regs < 1 || num_regs > 4)
8475 {
8476 inst.error = _("number of registers must be in the range [1:4]");
8477 return;
8478 }
8479
8480 switch (num_regs)
8481 {
8482 case 1:
8483 inst.instruction |= CP_T_X;
8484 break;
8485 case 2:
8486 inst.instruction |= CP_T_Y;
8487 break;
8488 case 3:
8489 inst.instruction |= CP_T_Y | CP_T_X;
8490 break;
8491 case 4:
8492 break;
8493 default:
8494 abort ();
8495 }
8496
e28cd48c 8497 if (inst.instruction & (CP_T_Pre | CP_T_UD)) /* ea/fd format. */
b99bd4ef
NC
8498 {
8499 int reg;
8500 int write_back;
8501 int offset;
8502
8503 /* The instruction specified "ea" or "fd", so we can only accept
8504 [Rn]{!}. The instruction does not really support stacking or
8505 unstacking, so we have to emulate these by setting appropriate
8506 bits and offsets. */
8507 if (skip_past_comma (&str) == FAIL
8508 || *str != '[')
8509 {
8510 if (! inst.error)
8511 inst.error = BAD_ARGS;
8512 return;
8513 }
8514
8515 str++;
8516 skip_whitespace (str);
8517
8518 if ((reg = reg_required_here (&str, 16)) == FAIL)
8519 return;
8520
8521 skip_whitespace (str);
8522
8523 if (*str != ']')
8524 {
8525 inst.error = BAD_ARGS;
8526 return;
8527 }
8528
8529 str++;
8530 if (*str == '!')
8531 {
8532 write_back = 1;
8533 str++;
8534 if (reg == REG_PC)
8535 {
8536 inst.error =
f03698e6 8537 _("r15 not allowed as base register with write-back");
b99bd4ef
NC
8538 return;
8539 }
8540 }
8541 else
8542 write_back = 0;
8543
90e4755a 8544 if (inst.instruction & CP_T_Pre)
b99bd4ef
NC
8545 {
8546 /* Pre-decrement. */
8547 offset = 3 * num_regs;
8548 if (write_back)
90e4755a 8549 inst.instruction |= CP_T_WB;
b99bd4ef
NC
8550 }
8551 else
8552 {
8553 /* Post-increment. */
8554 if (write_back)
8555 {
90e4755a 8556 inst.instruction |= CP_T_WB;
b99bd4ef
NC
8557 offset = 3 * num_regs;
8558 }
8559 else
8560 {
8561 /* No write-back, so convert this into a standard pre-increment
8562 instruction -- aesthetically more pleasing. */
90e4755a 8563 inst.instruction |= CP_T_Pre | CP_T_UD;
b99bd4ef
NC
8564 offset = 0;
8565 }
8566 }
8567
f2b7cb0a 8568 inst.instruction |= offset;
b99bd4ef
NC
8569 }
8570 else if (skip_past_comma (&str) == FAIL
bfae80f2 8571 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
b99bd4ef
NC
8572 {
8573 if (! inst.error)
8574 inst.error = BAD_ARGS;
8575 return;
8576 }
8577
8578 end_of_line (str);
8579}
8580
8581static void
f2b7cb0a 8582do_fpa_dyadic (str)
b99bd4ef 8583 char * str;
b99bd4ef
NC
8584{
8585 skip_whitespace (str);
8586
b99bd4ef
NC
8587 if (fp_reg_required_here (&str, 12) == FAIL)
8588 {
8589 if (! inst.error)
8590 inst.error = BAD_ARGS;
8591 return;
8592 }
8593
8594 if (skip_past_comma (&str) == FAIL
8595 || fp_reg_required_here (&str, 16) == FAIL)
8596 {
8597 if (! inst.error)
8598 inst.error = BAD_ARGS;
8599 return;
8600 }
8601
8602 if (skip_past_comma (&str) == FAIL
8603 || fp_op2 (&str) == FAIL)
8604 {
8605 if (! inst.error)
8606 inst.error = BAD_ARGS;
8607 return;
8608 }
8609
b99bd4ef 8610 end_of_line (str);
b99bd4ef
NC
8611}
8612
8613static void
f2b7cb0a 8614do_fpa_monadic (str)
b99bd4ef 8615 char * str;
b99bd4ef
NC
8616{
8617 skip_whitespace (str);
8618
b99bd4ef
NC
8619 if (fp_reg_required_here (&str, 12) == FAIL)
8620 {
8621 if (! inst.error)
8622 inst.error = BAD_ARGS;
8623 return;
8624 }
8625
8626 if (skip_past_comma (&str) == FAIL
8627 || fp_op2 (&str) == FAIL)
8628 {
8629 if (! inst.error)
8630 inst.error = BAD_ARGS;
8631 return;
8632 }
8633
b99bd4ef 8634 end_of_line (str);
b99bd4ef
NC
8635}
8636
8637static void
f2b7cb0a 8638do_fpa_cmp (str)
b99bd4ef 8639 char * str;
b99bd4ef
NC
8640{
8641 skip_whitespace (str);
8642
8643 if (fp_reg_required_here (&str, 16) == FAIL)
8644 {
8645 if (! inst.error)
8646 inst.error = BAD_ARGS;
8647 return;
8648 }
8649
8650 if (skip_past_comma (&str) == FAIL
8651 || fp_op2 (&str) == FAIL)
8652 {
8653 if (! inst.error)
8654 inst.error = BAD_ARGS;
8655 return;
8656 }
8657
b99bd4ef 8658 end_of_line (str);
b99bd4ef
NC
8659}
8660
8661static void
f2b7cb0a 8662do_fpa_from_reg (str)
b99bd4ef 8663 char * str;
b99bd4ef
NC
8664{
8665 skip_whitespace (str);
8666
b99bd4ef
NC
8667 if (fp_reg_required_here (&str, 16) == FAIL)
8668 {
8669 if (! inst.error)
8670 inst.error = BAD_ARGS;
8671 return;
8672 }
8673
8674 if (skip_past_comma (&str) == FAIL
8675 || reg_required_here (&str, 12) == FAIL)
8676 {
8677 if (! inst.error)
8678 inst.error = BAD_ARGS;
8679 return;
8680 }
8681
b99bd4ef 8682 end_of_line (str);
b99bd4ef
NC
8683}
8684
8685static void
f2b7cb0a 8686do_fpa_to_reg (str)
b99bd4ef 8687 char * str;
b99bd4ef
NC
8688{
8689 skip_whitespace (str);
8690
8691 if (reg_required_here (&str, 12) == FAIL)
8692 return;
8693
8694 if (skip_past_comma (&str) == FAIL
8695 || fp_reg_required_here (&str, 0) == FAIL)
8696 {
8697 if (! inst.error)
8698 inst.error = BAD_ARGS;
8699 return;
8700 }
8701
b99bd4ef 8702 end_of_line (str);
b99bd4ef
NC
8703}
8704
b99bd4ef 8705static int
bfae80f2
RE
8706vfp_sp_reg_required_here (str, pos)
8707 char **str;
8708 enum vfp_sp_reg_pos pos;
b99bd4ef 8709{
bfae80f2
RE
8710 int reg;
8711 char *start = *str;
b99bd4ef 8712
bfae80f2 8713 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_SN].htab)) != FAIL)
b99bd4ef 8714 {
bfae80f2 8715 switch (pos)
b99bd4ef 8716 {
bfae80f2
RE
8717 case VFP_REG_Sd:
8718 inst.instruction |= ((reg >> 1) << 12) | ((reg & 1) << 22);
8719 break;
8720
8721 case VFP_REG_Sn:
8722 inst.instruction |= ((reg >> 1) << 16) | ((reg & 1) << 7);
8723 break;
8724
8725 case VFP_REG_Sm:
8726 inst.instruction |= ((reg >> 1) << 0) | ((reg & 1) << 5);
8727 break;
8728
8729 default:
8730 abort ();
b99bd4ef 8731 }
bfae80f2
RE
8732 return reg;
8733 }
b99bd4ef 8734
bfae80f2
RE
8735 /* In the few cases where we might be able to accept something else
8736 this error can be overridden. */
8737 inst.error = _(all_reg_maps[REG_TYPE_SN].expected);
8738
8739 /* Restore the start point. */
8740 *str = start;
8741 return FAIL;
8742}
8743
8744static int
8745vfp_dp_reg_required_here (str, pos)
8746 char **str;
f201ccb3 8747 enum vfp_dp_reg_pos pos;
bfae80f2
RE
8748{
8749 int reg;
8750 char *start = *str;
8751
8752 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_DN].htab)) != FAIL)
8753 {
8754 switch (pos)
b99bd4ef 8755 {
bfae80f2
RE
8756 case VFP_REG_Dd:
8757 inst.instruction |= reg << 12;
8758 break;
b99bd4ef 8759
bfae80f2
RE
8760 case VFP_REG_Dn:
8761 inst.instruction |= reg << 16;
8762 break;
8763
8764 case VFP_REG_Dm:
8765 inst.instruction |= reg << 0;
8766 break;
8767
8768 default:
8769 abort ();
8770 }
8771 return reg;
b99bd4ef
NC
8772 }
8773
bfae80f2
RE
8774 /* In the few cases where we might be able to accept something else
8775 this error can be overridden. */
8776 inst.error = _(all_reg_maps[REG_TYPE_DN].expected);
b99bd4ef 8777
bfae80f2
RE
8778 /* Restore the start point. */
8779 *str = start;
8780 return FAIL;
8781}
b99bd4ef
NC
8782
8783static void
bfae80f2
RE
8784do_vfp_sp_monadic (str)
8785 char *str;
b99bd4ef 8786{
b99bd4ef
NC
8787 skip_whitespace (str);
8788
bfae80f2
RE
8789 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
8790 return;
8791
8792 if (skip_past_comma (&str) == FAIL
8793 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
b99bd4ef
NC
8794 {
8795 if (! inst.error)
8796 inst.error = BAD_ARGS;
8797 return;
8798 }
8799
bfae80f2 8800 end_of_line (str);
bfae80f2
RE
8801}
8802
8803static void
8804do_vfp_dp_monadic (str)
8805 char *str;
8806{
8807 skip_whitespace (str);
8808
8809 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
8810 return;
8811
8812 if (skip_past_comma (&str) == FAIL
8813 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
b99bd4ef 8814 {
bfae80f2
RE
8815 if (! inst.error)
8816 inst.error = BAD_ARGS;
8817 return;
b99bd4ef 8818 }
b99bd4ef 8819
bfae80f2 8820 end_of_line (str);
bfae80f2 8821}
b99bd4ef 8822
bfae80f2
RE
8823static void
8824do_vfp_sp_dyadic (str)
8825 char *str;
8826{
8827 skip_whitespace (str);
b99bd4ef 8828
bfae80f2
RE
8829 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
8830 return;
b99bd4ef 8831
bfae80f2
RE
8832 if (skip_past_comma (&str) == FAIL
8833 || vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL
8834 || skip_past_comma (&str) == FAIL
8835 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
b99bd4ef 8836 {
bfae80f2
RE
8837 if (! inst.error)
8838 inst.error = BAD_ARGS;
8839 return;
8840 }
b99bd4ef 8841
bfae80f2 8842 end_of_line (str);
bfae80f2 8843}
b99bd4ef 8844
bfae80f2
RE
8845static void
8846do_vfp_dp_dyadic (str)
8847 char *str;
8848{
8849 skip_whitespace (str);
b99bd4ef 8850
bfae80f2
RE
8851 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
8852 return;
b99bd4ef 8853
bfae80f2
RE
8854 if (skip_past_comma (&str) == FAIL
8855 || vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL
8856 || skip_past_comma (&str) == FAIL
8857 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
8858 {
8859 if (! inst.error)
8860 inst.error = BAD_ARGS;
8861 return;
8862 }
b99bd4ef 8863
bfae80f2 8864 end_of_line (str);
bfae80f2 8865}
b99bd4ef 8866
bfae80f2
RE
8867static void
8868do_vfp_reg_from_sp (str)
8869 char *str;
8870{
8871 skip_whitespace (str);
8872
8873 if (reg_required_here (&str, 12) == FAIL)
8874 return;
8875
8876 if (skip_past_comma (&str) == FAIL
8877 || vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL)
8878 {
8879 if (! inst.error)
8880 inst.error = BAD_ARGS;
8881 return;
8882 }
8883
8884 end_of_line (str);
bfae80f2
RE
8885}
8886
8887static void
e45d0630 8888do_vfp_reg2_from_sp2 (str)
bfae80f2
RE
8889 char *str;
8890{
8891 skip_whitespace (str);
8892
e45d0630
PB
8893 if (reg_required_here (&str, 12) == FAIL
8894 || skip_past_comma (&str) == FAIL
bfae80f2
RE
8895 || reg_required_here (&str, 16) == FAIL
8896 || skip_past_comma (&str) == FAIL)
8897 {
8898 if (! inst.error)
8899 inst.error = BAD_ARGS;
8900 return;
8901 }
8902
8903 /* We require exactly two consecutive SP registers. */
8904 if (vfp_sp_reg_list (&str, VFP_REG_Sm) != 2)
8905 {
8906 if (! inst.error)
8907 inst.error = _("only two consecutive VFP SP registers allowed here");
8908 }
8909
8910 end_of_line (str);
bfae80f2
RE
8911}
8912
8913static void
8914do_vfp_sp_from_reg (str)
8915 char *str;
8916{
8917 skip_whitespace (str);
8918
8919 if (vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL)
8920 return;
8921
8922 if (skip_past_comma (&str) == FAIL
8923 || reg_required_here (&str, 12) == FAIL)
8924 {
8925 if (! inst.error)
8926 inst.error = BAD_ARGS;
8927 return;
8928 }
8929
8930 end_of_line (str);
bfae80f2
RE
8931}
8932
e45d0630
PB
8933static void
8934do_vfp_sp2_from_reg2 (str)
8935 char *str;
8936{
8937 skip_whitespace (str);
8938
8939 /* We require exactly two consecutive SP registers. */
8940 if (vfp_sp_reg_list (&str, VFP_REG_Sm) != 2)
8941 {
8942 if (! inst.error)
8943 inst.error = _("only two consecutive VFP SP registers allowed here");
8944 }
8945
8946 if (skip_past_comma (&str) == FAIL
8947 || reg_required_here (&str, 12) == FAIL
8948 || skip_past_comma (&str) == FAIL
8949 || reg_required_here (&str, 16) == FAIL)
8950 {
8951 if (! inst.error)
8952 inst.error = BAD_ARGS;
8953 return;
8954 }
8955
8956 end_of_line (str);
8957}
8958
bfae80f2
RE
8959static void
8960do_vfp_reg_from_dp (str)
8961 char *str;
8962{
8963 skip_whitespace (str);
8964
8965 if (reg_required_here (&str, 12) == FAIL)
8966 return;
8967
8968 if (skip_past_comma (&str) == FAIL
8969 || vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL)
8970 {
8971 if (! inst.error)
8972 inst.error = BAD_ARGS;
8973 return;
8974 }
8975
8976 end_of_line (str);
bfae80f2
RE
8977}
8978
8979static void
8980do_vfp_reg2_from_dp (str)
8981 char *str;
8982{
8983 skip_whitespace (str);
8984
8985 if (reg_required_here (&str, 12) == FAIL)
8986 return;
8987
8988 if (skip_past_comma (&str) == FAIL
8989 || reg_required_here (&str, 16) == FAIL
8990 || skip_past_comma (&str) == FAIL
8991 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
8992 {
8993 if (! inst.error)
8994 inst.error = BAD_ARGS;
8995 return;
8996 }
8997
8998 end_of_line (str);
bfae80f2
RE
8999}
9000
9001static void
9002do_vfp_dp_from_reg (str)
9003 char *str;
9004{
9005 skip_whitespace (str);
9006
9007 if (vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL)
9008 return;
9009
9010 if (skip_past_comma (&str) == FAIL
9011 || reg_required_here (&str, 12) == FAIL)
9012 {
9013 if (! inst.error)
9014 inst.error = BAD_ARGS;
9015 return;
9016 }
9017
9018 end_of_line (str);
bfae80f2
RE
9019}
9020
9021static void
9022do_vfp_dp_from_reg2 (str)
9023 char *str;
9024{
9025 skip_whitespace (str);
9026
9027 if (vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
9028 return;
9029
9030 if (skip_past_comma (&str) == FAIL
9031 || reg_required_here (&str, 12) == FAIL
9032 || skip_past_comma (&str) == FAIL
e45d0630 9033 || reg_required_here (&str, 16) == FAIL)
bfae80f2
RE
9034 {
9035 if (! inst.error)
9036 inst.error = BAD_ARGS;
9037 return;
9038 }
9039
9040 end_of_line (str);
bfae80f2
RE
9041}
9042
9043static const struct vfp_reg *
9044vfp_psr_parse (str)
9045 char **str;
9046{
9047 char *start = *str;
9048 char c;
9049 char *p;
9050 const struct vfp_reg *vreg;
9051
9052 p = start;
9053
9054 /* Find the end of the current token. */
9055 do
9056 {
9057 c = *p++;
9058 }
9059 while (ISALPHA (c));
9060
9061 /* Mark it. */
9062 *--p = 0;
9063
cc8a6dd0 9064 for (vreg = vfp_regs + 0;
bfae80f2
RE
9065 vreg < vfp_regs + sizeof (vfp_regs) / sizeof (struct vfp_reg);
9066 vreg++)
9067 {
9068 if (strcmp (start, vreg->name) == 0)
9069 {
9070 *p = c;
9071 *str = p;
9072 return vreg;
9073 }
9074 }
9075
9076 *p = c;
9077 return NULL;
9078}
9079
9080static int
9081vfp_psr_required_here (str)
9082 char **str;
9083{
9084 char *start = *str;
9085 const struct vfp_reg *vreg;
9086
9087 vreg = vfp_psr_parse (str);
9088
9089 if (vreg)
9090 {
9091 inst.instruction |= vreg->regno;
9092 return SUCCESS;
9093 }
9094
9095 inst.error = _("VFP system register expected");
9096
9097 *str = start;
9098 return FAIL;
9099}
9100
9101static void
9102do_vfp_reg_from_ctrl (str)
9103 char *str;
9104{
9105 skip_whitespace (str);
9106
9107 if (reg_required_here (&str, 12) == FAIL)
9108 return;
9109
9110 if (skip_past_comma (&str) == FAIL
9111 || vfp_psr_required_here (&str) == FAIL)
9112 {
9113 if (! inst.error)
9114 inst.error = BAD_ARGS;
9115 return;
9116 }
9117
9118 end_of_line (str);
bfae80f2
RE
9119}
9120
9121static void
9122do_vfp_ctrl_from_reg (str)
9123 char *str;
9124{
9125 skip_whitespace (str);
9126
9127 if (vfp_psr_required_here (&str) == FAIL)
9128 return;
9129
9130 if (skip_past_comma (&str) == FAIL
9131 || reg_required_here (&str, 12) == FAIL)
9132 {
9133 if (! inst.error)
9134 inst.error = BAD_ARGS;
9135 return;
9136 }
9137
9138 end_of_line (str);
bfae80f2
RE
9139}
9140
9141static void
9142do_vfp_sp_ldst (str)
9143 char *str;
9144{
9145 skip_whitespace (str);
9146
9147 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
9148 {
9149 if (!inst.error)
9150 inst.error = BAD_ARGS;
9151 return;
9152 }
9153
9154 if (skip_past_comma (&str) == FAIL
9155 || cp_address_required_here (&str, CP_NO_WB) == FAIL)
9156 {
9157 if (!inst.error)
9158 inst.error = BAD_ARGS;
9159 return;
9160 }
9161
9162 end_of_line (str);
bfae80f2
RE
9163}
9164
9165static void
9166do_vfp_dp_ldst (str)
9167 char *str;
9168{
9169 skip_whitespace (str);
9170
9171 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
9172 {
9173 if (!inst.error)
9174 inst.error = BAD_ARGS;
9175 return;
9176 }
9177
9178 if (skip_past_comma (&str) == FAIL
9179 || cp_address_required_here (&str, CP_NO_WB) == FAIL)
9180 {
9181 if (!inst.error)
9182 inst.error = BAD_ARGS;
9183 return;
9184 }
9185
9186 end_of_line (str);
bfae80f2
RE
9187}
9188
9189/* Parse and encode a VFP SP register list, storing the initial
9190 register in position POS and returning the range as the result. If
9191 the string is invalid return FAIL (an invalid range). */
9192static long
9193vfp_sp_reg_list (str, pos)
9194 char **str;
9195 enum vfp_sp_reg_pos pos;
9196{
9197 long range = 0;
9198 int base_reg = 0;
9199 int new_base;
9200 long base_bits = 0;
9201 int count = 0;
9202 long tempinst;
9203 unsigned long mask = 0;
9204 int warned = 0;
9205
9206 if (**str != '{')
9207 return FAIL;
9208
9209 (*str)++;
9210 skip_whitespace (*str);
9211
9212 tempinst = inst.instruction;
9213
9214 do
9215 {
9216 inst.instruction = 0;
9217
9218 if ((new_base = vfp_sp_reg_required_here (str, pos)) == FAIL)
9219 return FAIL;
9220
9221 if (count == 0 || base_reg > new_base)
9222 {
9223 base_reg = new_base;
9224 base_bits = inst.instruction;
9225 }
9226
9227 if (mask & (1 << new_base))
9228 {
9229 inst.error = _("invalid register list");
9230 return FAIL;
9231 }
9232
9233 if ((mask >> new_base) != 0 && ! warned)
9234 {
9235 as_tsktsk (_("register list not in ascending order"));
9236 warned = 1;
9237 }
9238
9239 mask |= 1 << new_base;
9240 count++;
9241
9242 skip_whitespace (*str);
9243
9244 if (**str == '-') /* We have the start of a range expression */
9245 {
9246 int high_range;
9247
9248 (*str)++;
9249
9250 if ((high_range
9251 = arm_reg_parse (str, all_reg_maps[REG_TYPE_SN].htab))
9252 == FAIL)
9253 {
9254 inst.error = _(all_reg_maps[REG_TYPE_SN].expected);
9255 return FAIL;
9256 }
9257
9258 if (high_range <= new_base)
9259 {
9260 inst.error = _("register range not in ascending order");
9261 return FAIL;
9262 }
9263
9264 for (new_base++; new_base <= high_range; new_base++)
9265 {
9266 if (mask & (1 << new_base))
9267 {
9268 inst.error = _("invalid register list");
9269 return FAIL;
9270 }
9271
9272 mask |= 1 << new_base;
9273 count++;
9274 }
9275 }
9276 }
9277 while (skip_past_comma (str) != FAIL);
9278
9279 if (**str != '}')
9280 {
9281 inst.error = _("invalid register list");
9282 return FAIL;
9283 }
9284
9285 (*str)++;
9286
9287 range = count;
9288
9289 /* Sanity check -- should have raised a parse error above. */
9290 if (count == 0 || count > 32)
c62e1cc3 9291 abort ();
bfae80f2
RE
9292
9293 /* Final test -- the registers must be consecutive. */
9294 while (count--)
9295 {
9296 if ((mask & (1 << base_reg++)) == 0)
9297 {
9298 inst.error = _("non-contiguous register range");
9299 return FAIL;
9300 }
9301 }
9302
9303 inst.instruction = tempinst | base_bits;
9304 return range;
9305}
9306
9307static long
9308vfp_dp_reg_list (str)
9309 char **str;
9310{
9311 long range = 0;
9312 int base_reg = 0;
9313 int new_base;
9314 int count = 0;
9315 long tempinst;
9316 unsigned long mask = 0;
9317 int warned = 0;
9318
9319 if (**str != '{')
9320 return FAIL;
9321
9322 (*str)++;
9323 skip_whitespace (*str);
9324
9325 tempinst = inst.instruction;
9326
9327 do
9328 {
9329 inst.instruction = 0;
9330
9331 if ((new_base = vfp_dp_reg_required_here (str, VFP_REG_Dd)) == FAIL)
9332 return FAIL;
9333
9334 if (count == 0 || base_reg > new_base)
9335 {
9336 base_reg = new_base;
9337 range = inst.instruction;
9338 }
9339
9340 if (mask & (1 << new_base))
9341 {
9342 inst.error = _("invalid register list");
9343 return FAIL;
9344 }
9345
9346 if ((mask >> new_base) != 0 && ! warned)
9347 {
9348 as_tsktsk (_("register list not in ascending order"));
9349 warned = 1;
9350 }
9351
9352 mask |= 1 << new_base;
9353 count++;
9354
9355 skip_whitespace (*str);
9356
9357 if (**str == '-') /* We have the start of a range expression */
9358 {
9359 int high_range;
9360
9361 (*str)++;
9362
9363 if ((high_range
9364 = arm_reg_parse (str, all_reg_maps[REG_TYPE_DN].htab))
9365 == FAIL)
9366 {
9367 inst.error = _(all_reg_maps[REG_TYPE_DN].expected);
9368 return FAIL;
9369 }
9370
9371 if (high_range <= new_base)
9372 {
9373 inst.error = _("register range not in ascending order");
9374 return FAIL;
9375 }
9376
9377 for (new_base++; new_base <= high_range; new_base++)
9378 {
9379 if (mask & (1 << new_base))
9380 {
9381 inst.error = _("invalid register list");
9382 return FAIL;
9383 }
9384
9385 mask |= 1 << new_base;
9386 count++;
9387 }
9388 }
9389 }
9390 while (skip_past_comma (str) != FAIL);
9391
9392 if (**str != '}')
9393 {
9394 inst.error = _("invalid register list");
9395 return FAIL;
9396 }
9397
9398 (*str)++;
9399
9400 range |= 2 * count;
9401
9402 /* Sanity check -- should have raised a parse error above. */
9403 if (count == 0 || count > 16)
c62e1cc3 9404 abort ();
bfae80f2
RE
9405
9406 /* Final test -- the registers must be consecutive. */
9407 while (count--)
9408 {
9409 if ((mask & (1 << base_reg++)) == 0)
9410 {
9411 inst.error = _("non-contiguous register range");
9412 return FAIL;
9413 }
9414 }
9415
9416 inst.instruction = tempinst;
9417 return range;
9418}
9419
9420static void
c62e1cc3 9421vfp_sp_ldstm (str, ldstm_type)
bfae80f2
RE
9422 char *str;
9423 enum vfp_ldstm_type ldstm_type;
9424{
9425 long range;
9426
9427 skip_whitespace (str);
9428
9429 if (reg_required_here (&str, 16) == FAIL)
9430 return;
9431
9432 skip_whitespace (str);
9433
9434 if (*str == '!')
9435 {
9436 inst.instruction |= WRITE_BACK;
9437 str++;
9438 }
9439 else if (ldstm_type != VFP_LDSTMIA)
9440 {
9441 inst.error = _("this addressing mode requires base-register writeback");
9442 return;
9443 }
9444
9445 if (skip_past_comma (&str) == FAIL
9446 || (range = vfp_sp_reg_list (&str, VFP_REG_Sd)) == FAIL)
9447 {
9448 if (!inst.error)
9449 inst.error = BAD_ARGS;
9450 return;
9451 }
9452
9453 inst.instruction |= range;
9454 end_of_line (str);
9455}
9456
9457static void
c62e1cc3 9458vfp_dp_ldstm (str, ldstm_type)
bfae80f2
RE
9459 char *str;
9460 enum vfp_ldstm_type ldstm_type;
9461{
9462 long range;
9463
9464 skip_whitespace (str);
9465
9466 if (reg_required_here (&str, 16) == FAIL)
9467 return;
9468
9469 skip_whitespace (str);
9470
9471 if (*str == '!')
9472 {
9473 inst.instruction |= WRITE_BACK;
9474 str++;
9475 }
9476 else if (ldstm_type != VFP_LDSTMIA && ldstm_type != VFP_LDSTMIAX)
9477 {
9478 inst.error = _("this addressing mode requires base-register writeback");
9479 return;
9480 }
9481
9482 if (skip_past_comma (&str) == FAIL
9483 || (range = vfp_dp_reg_list (&str)) == FAIL)
9484 {
9485 if (!inst.error)
9486 inst.error = BAD_ARGS;
9487 return;
9488 }
9489
9490 if (ldstm_type == VFP_LDSTMIAX || ldstm_type == VFP_LDSTMDBX)
9491 range += 1;
9492
9493 inst.instruction |= range;
9494 end_of_line (str);
9495}
9496
9497static void
9498do_vfp_sp_ldstmia (str)
9499 char *str;
9500{
9501 vfp_sp_ldstm (str, VFP_LDSTMIA);
9502}
9503
9504static void
9505do_vfp_sp_ldstmdb (str)
9506 char *str;
9507{
9508 vfp_sp_ldstm (str, VFP_LDSTMDB);
9509}
9510
9511static void
9512do_vfp_dp_ldstmia (str)
9513 char *str;
9514{
9515 vfp_dp_ldstm (str, VFP_LDSTMIA);
9516}
9517
9518static void
9519do_vfp_dp_ldstmdb (str)
9520 char *str;
9521{
9522 vfp_dp_ldstm (str, VFP_LDSTMDB);
9523}
9524
9525static void
9526do_vfp_xp_ldstmia (str)
9527 char *str;
9528{
9529 vfp_dp_ldstm (str, VFP_LDSTMIAX);
9530}
9531
9532static void
9533do_vfp_xp_ldstmdb (str)
9534 char *str;
9535{
9536 vfp_dp_ldstm (str, VFP_LDSTMDBX);
9537}
9538
9539static void
9540do_vfp_sp_compare_z (str)
9541 char *str;
9542{
9543 skip_whitespace (str);
9544
9545 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
9546 {
9547 if (!inst.error)
9548 inst.error = BAD_ARGS;
9549 return;
9550 }
9551
9552 end_of_line (str);
bfae80f2
RE
9553}
9554
9555static void
9556do_vfp_dp_compare_z (str)
9557 char *str;
9558{
9559 skip_whitespace (str);
9560
9561 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
9562 {
9563 if (!inst.error)
9564 inst.error = BAD_ARGS;
9565 return;
9566 }
9567
9568 end_of_line (str);
bfae80f2
RE
9569}
9570
9571static void
9572do_vfp_dp_sp_cvt (str)
9573 char *str;
9574{
9575 skip_whitespace (str);
9576
9577 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
9578 return;
9579
9580 if (skip_past_comma (&str) == FAIL
9581 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
9582 {
9583 if (! inst.error)
9584 inst.error = BAD_ARGS;
9585 return;
9586 }
9587
9588 end_of_line (str);
bfae80f2
RE
9589}
9590
9591static void
9592do_vfp_sp_dp_cvt (str)
9593 char *str;
9594{
9595 skip_whitespace (str);
9596
9597 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
9598 return;
9599
9600 if (skip_past_comma (&str) == FAIL
9601 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
9602 {
9603 if (! inst.error)
9604 inst.error = BAD_ARGS;
9605 return;
9606 }
9607
9608 end_of_line (str);
bfae80f2
RE
9609}
9610
9611/* Thumb specific routines. */
9612
9613/* Parse and validate that a register is of the right form, this saves
9614 repeated checking of this information in many similar cases.
9615 Unlike the 32-bit case we do not insert the register into the opcode
9616 here, since the position is often unknown until the full instruction
9617 has been parsed. */
9618
9619static int
9620thumb_reg (strp, hi_lo)
9621 char ** strp;
9622 int hi_lo;
9623{
9624 int reg;
9625
9626 if ((reg = reg_required_here (strp, -1)) == FAIL)
9627 return FAIL;
9628
9629 switch (hi_lo)
9630 {
9631 case THUMB_REG_LO:
9632 if (reg > 7)
9633 {
9634 inst.error = _("lo register required");
9635 return FAIL;
9636 }
9637 break;
9638
9639 case THUMB_REG_HI:
9640 if (reg < 8)
9641 {
9642 inst.error = _("hi register required");
9643 return FAIL;
9644 }
9645 break;
9646
9647 default:
9648 break;
9649 }
9650
9651 return reg;
9652}
9653
9654/* Parse an add or subtract instruction, SUBTRACT is non-zero if the opcode
9655 was SUB. */
9656
9657static void
9658thumb_add_sub (str, subtract)
9659 char * str;
9660 int subtract;
9661{
9662 int Rd, Rs, Rn = FAIL;
9663
9664 skip_whitespace (str);
9665
9666 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
9667 || skip_past_comma (&str) == FAIL)
9668 {
9669 if (! inst.error)
9670 inst.error = BAD_ARGS;
9671 return;
9672 }
9673
9674 if (is_immediate_prefix (*str))
9675 {
9676 Rs = Rd;
9677 str++;
9678 if (my_get_expression (&inst.reloc.exp, &str))
9679 return;
9680 }
9681 else
9682 {
9683 if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
9684 return;
9685
9686 if (skip_past_comma (&str) == FAIL)
9687 {
9688 /* Two operand format, shuffle the registers
9689 and pretend there are 3. */
9690 Rn = Rs;
9691 Rs = Rd;
9692 }
9693 else if (is_immediate_prefix (*str))
9694 {
9695 str++;
9696 if (my_get_expression (&inst.reloc.exp, &str))
9697 return;
9698 }
9699 else if ((Rn = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
9700 return;
9701 }
9702
9703 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
9704 for the latter case, EXPR contains the immediate that was found. */
9705 if (Rn != FAIL)
9706 {
9707 /* All register format. */
9708 if (Rd > 7 || Rs > 7 || Rn > 7)
9709 {
9710 if (Rs != Rd)
9711 {
9712 inst.error = _("dest and source1 must be the same register");
9713 return;
9714 }
9715
9716 /* Can't do this for SUB. */
9717 if (subtract)
9718 {
9719 inst.error = _("subtract valid only on lo regs");
9720 return;
9721 }
9722
9723 inst.instruction = (T_OPCODE_ADD_HI
9724 | (Rd > 7 ? THUMB_H1 : 0)
9725 | (Rn > 7 ? THUMB_H2 : 0));
9726 inst.instruction |= (Rd & 7) | ((Rn & 7) << 3);
9727 }
9728 else
9729 {
9730 inst.instruction = subtract ? T_OPCODE_SUB_R3 : T_OPCODE_ADD_R3;
9731 inst.instruction |= Rd | (Rs << 3) | (Rn << 6);
9732 }
9733 }
9734 else
9735 {
9736 /* Immediate expression, now things start to get nasty. */
9737
9738 /* First deal with HI regs, only very restricted cases allowed:
9739 Adjusting SP, and using PC or SP to get an address. */
9740 if ((Rd > 7 && (Rd != REG_SP || Rs != REG_SP))
9741 || (Rs > 7 && Rs != REG_SP && Rs != REG_PC))
9742 {
9743 inst.error = _("invalid Hi register with immediate");
9744 return;
9745 }
9746
9747 if (inst.reloc.exp.X_op != O_constant)
9748 {
9749 /* Value isn't known yet, all we can do is store all the fragments
9750 we know about in the instruction and let the reloc hacking
9751 work it all out. */
9752 inst.instruction = (subtract ? 0x8000 : 0) | (Rd << 4) | Rs;
9753 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
9754 }
9755 else
9756 {
9757 int offset = inst.reloc.exp.X_add_number;
9758
9759 if (subtract)
358b94bd 9760 offset = - offset;
bfae80f2
RE
9761
9762 if (offset < 0)
9763 {
358b94bd 9764 offset = - offset;
bfae80f2
RE
9765 subtract = 1;
9766
9767 /* Quick check, in case offset is MIN_INT. */
9768 if (offset < 0)
9769 {
9770 inst.error = _("immediate value out of range");
9771 return;
9772 }
9773 }
358b94bd
NC
9774 /* Note - you cannot convert a subtract of 0 into an
9775 add of 0 because the carry flag is set differently. */
9776 else if (offset > 0)
bfae80f2
RE
9777 subtract = 0;
9778
9779 if (Rd == REG_SP)
9780 {
9781 if (offset & ~0x1fc)
9782 {
9783 inst.error = _("invalid immediate value for stack adjust");
9784 return;
b99bd4ef
NC
9785 }
9786 inst.instruction = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
9787 inst.instruction |= offset >> 2;
9788 }
9789 else if (Rs == REG_PC || Rs == REG_SP)
9790 {
9791 if (subtract
9792 || (offset & ~0x3fc))
9793 {
9794 inst.error = _("invalid immediate for address calculation");
9795 return;
9796 }
9797 inst.instruction = (Rs == REG_PC ? T_OPCODE_ADD_PC
9798 : T_OPCODE_ADD_SP);
9799 inst.instruction |= (Rd << 8) | (offset >> 2);
9800 }
9801 else if (Rs == Rd)
9802 {
9803 if (offset & ~0xff)
9804 {
9805 inst.error = _("immediate value out of range");
9806 return;
9807 }
9808 inst.instruction = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
9809 inst.instruction |= (Rd << 8) | offset;
9810 }
9811 else
9812 {
9813 if (offset & ~0x7)
9814 {
9815 inst.error = _("immediate value out of range");
9816 return;
9817 }
9818 inst.instruction = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
9819 inst.instruction |= Rd | (Rs << 3) | (offset << 6);
9820 }
9821 }
9822 }
9823
9824 end_of_line (str);
9825}
9826
9827static void
9828thumb_shift (str, shift)
9829 char * str;
9830 int shift;
9831{
9832 int Rd, Rs, Rn = FAIL;
9833
9834 skip_whitespace (str);
9835
9836 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9837 || skip_past_comma (&str) == FAIL)
9838 {
9839 if (! inst.error)
9840 inst.error = BAD_ARGS;
9841 return;
9842 }
9843
9844 if (is_immediate_prefix (*str))
9845 {
9846 /* Two operand immediate format, set Rs to Rd. */
9847 Rs = Rd;
9848 str ++;
9849 if (my_get_expression (&inst.reloc.exp, &str))
9850 return;
9851 }
9852 else
9853 {
9854 if ((Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9855 return;
9856
9857 if (skip_past_comma (&str) == FAIL)
9858 {
9859 /* Two operand format, shuffle the registers
9860 and pretend there are 3. */
9861 Rn = Rs;
9862 Rs = Rd;
9863 }
9864 else if (is_immediate_prefix (*str))
9865 {
9866 str++;
9867 if (my_get_expression (&inst.reloc.exp, &str))
9868 return;
9869 }
9870 else if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9871 return;
9872 }
9873
9874 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
9875 for the latter case, EXPR contains the immediate that was found. */
9876
9877 if (Rn != FAIL)
9878 {
9879 if (Rs != Rd)
9880 {
9881 inst.error = _("source1 and dest must be same register");
9882 return;
9883 }
9884
9885 switch (shift)
9886 {
9887 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_R; break;
9888 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_R; break;
9889 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_R; break;
9890 }
9891
9892 inst.instruction |= Rd | (Rn << 3);
9893 }
9894 else
9895 {
9896 switch (shift)
9897 {
9898 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_I; break;
9899 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_I; break;
9900 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_I; break;
9901 }
9902
9903 if (inst.reloc.exp.X_op != O_constant)
9904 {
9905 /* Value isn't known yet, create a dummy reloc and let reloc
9906 hacking fix it up. */
9907 inst.reloc.type = BFD_RELOC_ARM_THUMB_SHIFT;
9908 }
9909 else
9910 {
9911 unsigned shift_value = inst.reloc.exp.X_add_number;
9912
9913 if (shift_value > 32 || (shift_value == 32 && shift == THUMB_LSL))
9914 {
f03698e6 9915 inst.error = _("invalid immediate for shift");
b99bd4ef
NC
9916 return;
9917 }
9918
9919 /* Shifts of zero are handled by converting to LSL. */
9920 if (shift_value == 0)
9921 inst.instruction = T_OPCODE_LSL_I;
9922
9923 /* Shifts of 32 are encoded as a shift of zero. */
9924 if (shift_value == 32)
9925 shift_value = 0;
9926
9927 inst.instruction |= shift_value << 6;
9928 }
9929
9930 inst.instruction |= Rd | (Rs << 3);
9931 }
9932
9933 end_of_line (str);
9934}
9935
9936static void
9937thumb_mov_compare (str, move)
9938 char * str;
9939 int move;
9940{
9941 int Rd, Rs = FAIL;
9942
9943 skip_whitespace (str);
9944
9945 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
9946 || skip_past_comma (&str) == FAIL)
9947 {
9948 if (! inst.error)
9949 inst.error = BAD_ARGS;
9950 return;
9951 }
9952
09d92015 9953 if (move != THUMB_CPY && is_immediate_prefix (*str))
b99bd4ef
NC
9954 {
9955 str++;
9956 if (my_get_expression (&inst.reloc.exp, &str))
9957 return;
9958 }
9959 else if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
9960 return;
9961
9962 if (Rs != FAIL)
9963 {
09d92015 9964 if (move != THUMB_CPY && Rs < 8 && Rd < 8)
b99bd4ef
NC
9965 {
9966 if (move == THUMB_MOVE)
9967 /* A move of two lowregs is encoded as ADD Rd, Rs, #0
9968 since a MOV instruction produces unpredictable results. */
9969 inst.instruction = T_OPCODE_ADD_I3;
9970 else
9971 inst.instruction = T_OPCODE_CMP_LR;
9972 inst.instruction |= Rd | (Rs << 3);
9973 }
9974 else
9975 {
9976 if (move == THUMB_MOVE)
9977 inst.instruction = T_OPCODE_MOV_HR;
09d92015 9978 else if (move != THUMB_CPY)
b99bd4ef
NC
9979 inst.instruction = T_OPCODE_CMP_HR;
9980
9981 if (Rd > 7)
9982 inst.instruction |= THUMB_H1;
9983
9984 if (Rs > 7)
9985 inst.instruction |= THUMB_H2;
9986
9987 inst.instruction |= (Rd & 7) | ((Rs & 7) << 3);
9988 }
9989 }
9990 else
9991 {
9992 if (Rd > 7)
9993 {
9994 inst.error = _("only lo regs allowed with immediate");
9995 return;
9996 }
9997
9998 if (move == THUMB_MOVE)
9999 inst.instruction = T_OPCODE_MOV_I8;
10000 else
10001 inst.instruction = T_OPCODE_CMP_I8;
10002
10003 inst.instruction |= Rd << 8;
10004
10005 if (inst.reloc.exp.X_op != O_constant)
10006 inst.reloc.type = BFD_RELOC_ARM_THUMB_IMM;
10007 else
10008 {
10009 unsigned value = inst.reloc.exp.X_add_number;
10010
10011 if (value > 255)
10012 {
10013 inst.error = _("invalid immediate");
10014 return;
10015 }
10016
10017 inst.instruction |= value;
10018 }
10019 }
10020
10021 end_of_line (str);
10022}
10023
10024static void
10025thumb_load_store (str, load_store, size)
10026 char * str;
10027 int load_store;
10028 int size;
10029{
10030 int Rd, Rb, Ro = FAIL;
10031
10032 skip_whitespace (str);
10033
10034 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
10035 || skip_past_comma (&str) == FAIL)
10036 {
10037 if (! inst.error)
10038 inst.error = BAD_ARGS;
10039 return;
10040 }
10041
10042 if (*str == '[')
10043 {
10044 str++;
10045 if ((Rb = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
10046 return;
10047
10048 if (skip_past_comma (&str) != FAIL)
10049 {
10050 if (is_immediate_prefix (*str))
10051 {
10052 str++;
10053 if (my_get_expression (&inst.reloc.exp, &str))
10054 return;
10055 }
10056 else if ((Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
10057 return;
10058 }
10059 else
10060 {
10061 inst.reloc.exp.X_op = O_constant;
10062 inst.reloc.exp.X_add_number = 0;
10063 }
10064
10065 if (*str != ']')
10066 {
10067 inst.error = _("expected ']'");
10068 return;
10069 }
10070 str++;
10071 }
10072 else if (*str == '=')
10073 {
f03698e6
RE
10074 if (load_store != THUMB_LOAD)
10075 {
10076 inst.error = _("invalid pseudo operation");
10077 return;
10078 }
10079
b99bd4ef
NC
10080 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
10081 str++;
10082
10083 skip_whitespace (str);
10084
10085 if (my_get_expression (& inst.reloc.exp, & str))
10086 return;
10087
10088 end_of_line (str);
10089
10090 if ( inst.reloc.exp.X_op != O_constant
10091 && inst.reloc.exp.X_op != O_symbol)
10092 {
10093 inst.error = "Constant expression expected";
10094 return;
10095 }
10096
10097 if (inst.reloc.exp.X_op == O_constant
10098 && ((inst.reloc.exp.X_add_number & ~0xFF) == 0))
10099 {
10100 /* This can be done with a mov instruction. */
10101
10102 inst.instruction = T_OPCODE_MOV_I8 | (Rd << 8);
10103 inst.instruction |= inst.reloc.exp.X_add_number;
10104 return;
10105 }
10106
10107 /* Insert into literal pool. */
10108 if (add_to_lit_pool () == FAIL)
10109 {
10110 if (!inst.error)
10111 inst.error = "literal pool insertion failed";
10112 return;
10113 }
10114
10115 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
10116 inst.reloc.pc_rel = 1;
10117 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
10118 /* Adjust ARM pipeline offset to Thumb. */
10119 inst.reloc.exp.X_add_number += 4;
10120
10121 return;
10122 }
10123 else
10124 {
10125 if (my_get_expression (&inst.reloc.exp, &str))
10126 return;
10127
10128 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
10129 inst.reloc.pc_rel = 1;
10130 inst.reloc.exp.X_add_number -= 4; /* Pipeline offset. */
10131 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
10132 end_of_line (str);
10133 return;
10134 }
10135
10136 if (Rb == REG_PC || Rb == REG_SP)
10137 {
10138 if (size != THUMB_WORD)
10139 {
10140 inst.error = _("byte or halfword not valid for base register");
10141 return;
10142 }
10143 else if (Rb == REG_PC && load_store != THUMB_LOAD)
10144 {
f03698e6 10145 inst.error = _("r15 based store not allowed");
b99bd4ef
NC
10146 return;
10147 }
10148 else if (Ro != FAIL)
10149 {
f03698e6 10150 inst.error = _("invalid base register for register offset");
b99bd4ef
NC
10151 return;
10152 }
10153
10154 if (Rb == REG_PC)
10155 inst.instruction = T_OPCODE_LDR_PC;
10156 else if (load_store == THUMB_LOAD)
10157 inst.instruction = T_OPCODE_LDR_SP;
10158 else
10159 inst.instruction = T_OPCODE_STR_SP;
10160
10161 inst.instruction |= Rd << 8;
10162 if (inst.reloc.exp.X_op == O_constant)
10163 {
10164 unsigned offset = inst.reloc.exp.X_add_number;
10165
10166 if (offset & ~0x3fc)
10167 {
10168 inst.error = _("invalid offset");
10169 return;
10170 }
10171
10172 inst.instruction |= offset >> 2;
10173 }
10174 else
10175 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
10176 }
10177 else if (Rb > 7)
10178 {
10179 inst.error = _("invalid base register in load/store");
10180 return;
10181 }
10182 else if (Ro == FAIL)
10183 {
10184 /* Immediate offset. */
10185 if (size == THUMB_WORD)
10186 inst.instruction = (load_store == THUMB_LOAD
10187 ? T_OPCODE_LDR_IW : T_OPCODE_STR_IW);
10188 else if (size == THUMB_HALFWORD)
10189 inst.instruction = (load_store == THUMB_LOAD
10190 ? T_OPCODE_LDR_IH : T_OPCODE_STR_IH);
10191 else
10192 inst.instruction = (load_store == THUMB_LOAD
10193 ? T_OPCODE_LDR_IB : T_OPCODE_STR_IB);
10194
10195 inst.instruction |= Rd | (Rb << 3);
10196
10197 if (inst.reloc.exp.X_op == O_constant)
10198 {
10199 unsigned offset = inst.reloc.exp.X_add_number;
10200
10201 if (offset & ~(0x1f << size))
10202 {
f03698e6 10203 inst.error = _("invalid offset");
b99bd4ef
NC
10204 return;
10205 }
10206 inst.instruction |= (offset >> size) << 6;
10207 }
10208 else
10209 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
10210 }
10211 else
10212 {
10213 /* Register offset. */
10214 if (size == THUMB_WORD)
10215 inst.instruction = (load_store == THUMB_LOAD
10216 ? T_OPCODE_LDR_RW : T_OPCODE_STR_RW);
10217 else if (size == THUMB_HALFWORD)
10218 inst.instruction = (load_store == THUMB_LOAD
10219 ? T_OPCODE_LDR_RH : T_OPCODE_STR_RH);
10220 else
10221 inst.instruction = (load_store == THUMB_LOAD
10222 ? T_OPCODE_LDR_RB : T_OPCODE_STR_RB);
10223
10224 inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
10225 }
10226
10227 end_of_line (str);
10228}
10229
404ff6b5
AH
10230/* A register must be given at this point.
10231
404ff6b5
AH
10232 Shift is the place to put it in inst.instruction.
10233
404ff6b5
AH
10234 Restores input start point on err.
10235 Returns the reg#, or FAIL. */
10236
10237static int
63e63b07 10238mav_reg_required_here (str, shift, regtype)
404ff6b5
AH
10239 char ** str;
10240 int shift;
6c43fab6 10241 enum arm_reg_type regtype;
404ff6b5 10242{
6c43fab6
RE
10243 int reg;
10244 char *start = *str;
404ff6b5 10245
6c43fab6 10246 if ((reg = arm_reg_parse (str, all_reg_maps[regtype].htab)) != FAIL)
404ff6b5 10247 {
404ff6b5
AH
10248 if (shift >= 0)
10249 inst.instruction |= reg << shift;
10250
6c43fab6 10251 return reg;
404ff6b5
AH
10252 }
10253
6c43fab6 10254 /* Restore the start point. */
404ff6b5 10255 *str = start;
cc8a6dd0 10256
3631a3c8
NC
10257 /* Try generic coprocessor name if applicable. */
10258 if (regtype == REG_TYPE_MVF ||
10259 regtype == REG_TYPE_MVD ||
10260 regtype == REG_TYPE_MVFX ||
10261 regtype == REG_TYPE_MVDX)
10262 {
10263 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_CN].htab)) != FAIL)
10264 {
10265 if (shift >= 0)
10266 inst.instruction |= reg << shift;
10267
10268 return reg;
10269 }
10270
10271 /* Restore the start point. */
10272 *str = start;
10273 }
10274
404ff6b5
AH
10275 /* In the few cases where we might be able to accept something else
10276 this error can be overridden. */
6c43fab6 10277 inst.error = _(all_reg_maps[regtype].expected);
cc8a6dd0 10278
404ff6b5
AH
10279 return FAIL;
10280}
10281
63e63b07 10282/* Cirrus Maverick Instructions. */
404ff6b5
AH
10283
10284/* Wrapper functions. */
10285
10286static void
63e63b07 10287do_mav_binops_1a (str)
6c43fab6
RE
10288 char * str;
10289{
63e63b07 10290 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVF);
6c43fab6
RE
10291}
10292
10293static void
63e63b07 10294do_mav_binops_1b (str)
6c43fab6
RE
10295 char * str;
10296{
63e63b07 10297 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVD);
6c43fab6
RE
10298}
10299
10300static void
63e63b07 10301do_mav_binops_1c (str)
404ff6b5 10302 char * str;
404ff6b5 10303{
63e63b07 10304 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVDX);
404ff6b5
AH
10305}
10306
10307static void
63e63b07 10308do_mav_binops_1d (str)
404ff6b5 10309 char * str;
404ff6b5 10310{
63e63b07 10311 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVF);
404ff6b5
AH
10312}
10313
10314static void
63e63b07 10315do_mav_binops_1e (str)
404ff6b5 10316 char * str;
404ff6b5 10317{
63e63b07 10318 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVD);
404ff6b5
AH
10319}
10320
10321static void
63e63b07 10322do_mav_binops_1f (str)
404ff6b5 10323 char * str;
404ff6b5 10324{
63e63b07 10325 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVF);
404ff6b5
AH
10326}
10327
10328static void
63e63b07 10329do_mav_binops_1g (str)
404ff6b5 10330 char * str;
404ff6b5 10331{
63e63b07 10332 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVD);
404ff6b5
AH
10333}
10334
10335static void
63e63b07 10336do_mav_binops_1h (str)
404ff6b5 10337 char * str;
404ff6b5 10338{
63e63b07 10339 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVFX);
404ff6b5
AH
10340}
10341
6c43fab6 10342static void
63e63b07 10343do_mav_binops_1i (str)
6c43fab6
RE
10344 char * str;
10345{
63e63b07 10346 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVFX);
6c43fab6
RE
10347}
10348
10349static void
63e63b07 10350do_mav_binops_1j (str)
6c43fab6
RE
10351 char * str;
10352{
63e63b07 10353 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVDX);
6c43fab6
RE
10354}
10355
10356static void
63e63b07 10357do_mav_binops_1k (str)
6c43fab6
RE
10358 char * str;
10359{
63e63b07 10360 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVDX);
6c43fab6
RE
10361}
10362
10363static void
63e63b07 10364do_mav_binops_1l (str)
6c43fab6
RE
10365 char * str;
10366{
63e63b07 10367 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVF);
6c43fab6
RE
10368}
10369
10370static void
63e63b07 10371do_mav_binops_1m (str)
6c43fab6
RE
10372 char * str;
10373{
63e63b07 10374 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVD);
6c43fab6
RE
10375}
10376
10377static void
63e63b07 10378do_mav_binops_1n (str)
6c43fab6
RE
10379 char * str;
10380{
63e63b07 10381 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVFX);
6c43fab6
RE
10382}
10383
10384static void
63e63b07 10385do_mav_binops_1o (str)
6c43fab6
RE
10386 char * str;
10387{
63e63b07 10388 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVDX, REG_TYPE_MVDX);
6c43fab6
RE
10389}
10390
10391static void
63e63b07 10392do_mav_binops_2a (str)
6c43fab6
RE
10393 char * str;
10394{
63e63b07 10395 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVF, REG_TYPE_RN);
6c43fab6
RE
10396}
10397
10398static void
63e63b07 10399do_mav_binops_2b (str)
6c43fab6
RE
10400 char * str;
10401{
63e63b07 10402 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVD, REG_TYPE_RN);
6c43fab6
RE
10403}
10404
10405static void
63e63b07 10406do_mav_binops_2c (str)
6c43fab6
RE
10407 char * str;
10408{
63e63b07 10409 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVDX, REG_TYPE_RN);
6c43fab6
RE
10410}
10411
10412static void
63e63b07 10413do_mav_binops_3a (str)
6c43fab6
RE
10414 char * str;
10415{
63e63b07 10416 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVAX, REG_TYPE_MVFX);
6c43fab6
RE
10417}
10418
10419static void
63e63b07 10420do_mav_binops_3b (str)
6c43fab6
RE
10421 char * str;
10422{
63e63b07 10423 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVFX, REG_TYPE_MVAX);
6c43fab6
RE
10424}
10425
10426static void
63e63b07 10427do_mav_binops_3c (str)
6c43fab6
RE
10428 char * str;
10429{
63e63b07 10430 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVAX, REG_TYPE_MVDX);
6c43fab6
RE
10431}
10432
10433static void
63e63b07 10434do_mav_binops_3d (str)
6c43fab6
RE
10435 char * str;
10436{
63e63b07 10437 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVDX, REG_TYPE_MVAX);
6c43fab6
RE
10438}
10439
10440static void
63e63b07 10441do_mav_triple_4a (str)
6c43fab6
RE
10442 char * str;
10443{
63e63b07 10444 do_mav_triple (str, MAV_MODE4, REG_TYPE_MVFX, REG_TYPE_MVFX, REG_TYPE_RN);
6c43fab6
RE
10445}
10446
10447static void
63e63b07 10448do_mav_triple_4b (str)
6c43fab6
RE
10449 char * str;
10450{
63e63b07 10451 do_mav_triple (str, MAV_MODE4, REG_TYPE_MVDX, REG_TYPE_MVDX, REG_TYPE_RN);
6c43fab6
RE
10452}
10453
10454static void
63e63b07 10455do_mav_triple_5a (str)
6c43fab6
RE
10456 char * str;
10457{
63e63b07 10458 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVF, REG_TYPE_MVF);
6c43fab6
RE
10459}
10460
10461static void
63e63b07 10462do_mav_triple_5b (str)
6c43fab6
RE
10463 char * str;
10464{
63e63b07 10465 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVD, REG_TYPE_MVD);
6c43fab6
RE
10466}
10467
10468static void
63e63b07 10469do_mav_triple_5c (str)
6c43fab6
RE
10470 char * str;
10471{
63e63b07 10472 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVFX, REG_TYPE_MVFX);
6c43fab6
RE
10473}
10474
10475static void
63e63b07 10476do_mav_triple_5d (str)
6c43fab6
RE
10477 char * str;
10478{
63e63b07 10479 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVDX, REG_TYPE_MVDX);
6c43fab6
RE
10480}
10481
10482static void
63e63b07 10483do_mav_triple_5e (str)
6c43fab6
RE
10484 char * str;
10485{
63e63b07 10486 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVF, REG_TYPE_MVF, REG_TYPE_MVF);
6c43fab6
RE
10487}
10488
10489static void
63e63b07 10490do_mav_triple_5f (str)
6c43fab6
RE
10491 char * str;
10492{
63e63b07 10493 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVD, REG_TYPE_MVD, REG_TYPE_MVD);
6c43fab6
RE
10494}
10495
10496static void
63e63b07 10497do_mav_triple_5g (str)
6c43fab6
RE
10498 char * str;
10499{
63e63b07 10500 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVFX, REG_TYPE_MVFX, REG_TYPE_MVFX);
6c43fab6
RE
10501}
10502
10503static void
63e63b07 10504do_mav_triple_5h (str)
6c43fab6
RE
10505 char * str;
10506{
63e63b07 10507 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVDX, REG_TYPE_MVDX, REG_TYPE_MVDX);
6c43fab6
RE
10508}
10509
10510static void
63e63b07 10511do_mav_quad_6a (str)
6c43fab6
RE
10512 char * str;
10513{
63e63b07 10514 do_mav_quad (str, MAV_MODE6, REG_TYPE_MVAX, REG_TYPE_MVFX, REG_TYPE_MVFX,
3631a3c8 10515 REG_TYPE_MVFX);
6c43fab6
RE
10516}
10517
10518static void
63e63b07 10519do_mav_quad_6b (str)
6c43fab6
RE
10520 char * str;
10521{
63e63b07 10522 do_mav_quad (str, MAV_MODE6, REG_TYPE_MVAX, REG_TYPE_MVAX, REG_TYPE_MVFX,
3631a3c8 10523 REG_TYPE_MVFX);
6c43fab6
RE
10524}
10525
34920d91 10526/* cfmvsc32<cond> DSPSC,MVDX[15:0]. */
404ff6b5 10527static void
63e63b07 10528do_mav_dspsc_1 (str)
404ff6b5 10529 char * str;
404ff6b5 10530{
6c43fab6
RE
10531 skip_whitespace (str);
10532
10533 /* cfmvsc32. */
63e63b07 10534 if (mav_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL
6c43fab6 10535 || skip_past_comma (&str) == FAIL
34920d91 10536 || mav_reg_required_here (&str, 12, REG_TYPE_MVDX) == FAIL)
6c43fab6
RE
10537 {
10538 if (!inst.error)
10539 inst.error = BAD_ARGS;
10540
10541 return;
10542 }
10543
10544 end_of_line (str);
404ff6b5
AH
10545}
10546
34920d91 10547/* cfmv32sc<cond> MVDX[15:0],DSPSC. */
404ff6b5 10548static void
63e63b07 10549do_mav_dspsc_2 (str)
404ff6b5 10550 char * str;
404ff6b5 10551{
6c43fab6
RE
10552 skip_whitespace (str);
10553
10554 /* cfmv32sc. */
34920d91 10555 if (mav_reg_required_here (&str, 12, REG_TYPE_MVDX) == FAIL
6c43fab6 10556 || skip_past_comma (&str) == FAIL
63e63b07 10557 || mav_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL)
6c43fab6
RE
10558 {
10559 if (!inst.error)
10560 inst.error = BAD_ARGS;
10561
10562 return;
10563 }
10564
10565 end_of_line (str);
404ff6b5
AH
10566}
10567
10568static void
63e63b07 10569do_mav_shift_1 (str)
404ff6b5 10570 char * str;
404ff6b5 10571{
63e63b07 10572 do_mav_shift (str, REG_TYPE_MVFX, REG_TYPE_MVFX);
404ff6b5
AH
10573}
10574
10575static void
63e63b07 10576do_mav_shift_2 (str)
404ff6b5 10577 char * str;
404ff6b5 10578{
63e63b07 10579 do_mav_shift (str, REG_TYPE_MVDX, REG_TYPE_MVDX);
404ff6b5
AH
10580}
10581
10582static void
63e63b07 10583do_mav_ldst_1 (str)
404ff6b5 10584 char * str;
404ff6b5 10585{
63e63b07 10586 do_mav_ldst (str, REG_TYPE_MVF);
404ff6b5
AH
10587}
10588
10589static void
63e63b07 10590do_mav_ldst_2 (str)
404ff6b5 10591 char * str;
404ff6b5 10592{
63e63b07 10593 do_mav_ldst (str, REG_TYPE_MVD);
404ff6b5
AH
10594}
10595
10596static void
63e63b07 10597do_mav_ldst_3 (str)
404ff6b5 10598 char * str;
404ff6b5 10599{
63e63b07 10600 do_mav_ldst (str, REG_TYPE_MVFX);
404ff6b5
AH
10601}
10602
10603static void
63e63b07 10604do_mav_ldst_4 (str)
404ff6b5 10605 char * str;
404ff6b5 10606{
63e63b07 10607 do_mav_ldst (str, REG_TYPE_MVDX);
404ff6b5
AH
10608}
10609
10610/* Isnsn like "foo X,Y". */
10611
10612static void
63e63b07 10613do_mav_binops (str, mode, reg0, reg1)
404ff6b5 10614 char * str;
404ff6b5 10615 int mode;
6c43fab6
RE
10616 enum arm_reg_type reg0;
10617 enum arm_reg_type reg1;
404ff6b5 10618{
6c43fab6 10619 int shift0, shift1;
404ff6b5 10620
6c43fab6
RE
10621 shift0 = mode & 0xff;
10622 shift1 = (mode >> 8) & 0xff;
404ff6b5
AH
10623
10624 skip_whitespace (str);
10625
63e63b07 10626 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
404ff6b5 10627 || skip_past_comma (&str) == FAIL
63e63b07 10628 || mav_reg_required_here (&str, shift1, reg1) == FAIL)
404ff6b5
AH
10629 {
10630 if (!inst.error)
10631 inst.error = BAD_ARGS;
10632 }
10633 else
10634 end_of_line (str);
404ff6b5
AH
10635}
10636
10637/* Isnsn like "foo X,Y,Z". */
10638
10639static void
63e63b07 10640do_mav_triple (str, mode, reg0, reg1, reg2)
404ff6b5 10641 char * str;
404ff6b5 10642 int mode;
6c43fab6
RE
10643 enum arm_reg_type reg0;
10644 enum arm_reg_type reg1;
10645 enum arm_reg_type reg2;
404ff6b5 10646{
6c43fab6 10647 int shift0, shift1, shift2;
404ff6b5 10648
6c43fab6
RE
10649 shift0 = mode & 0xff;
10650 shift1 = (mode >> 8) & 0xff;
10651 shift2 = (mode >> 16) & 0xff;
404ff6b5
AH
10652
10653 skip_whitespace (str);
10654
63e63b07 10655 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
404ff6b5 10656 || skip_past_comma (&str) == FAIL
63e63b07 10657 || mav_reg_required_here (&str, shift1, reg1) == FAIL
404ff6b5 10658 || skip_past_comma (&str) == FAIL
63e63b07 10659 || mav_reg_required_here (&str, shift2, reg2) == FAIL)
404ff6b5
AH
10660 {
10661 if (!inst.error)
10662 inst.error = BAD_ARGS;
10663 }
10664 else
10665 end_of_line (str);
404ff6b5
AH
10666}
10667
10668/* Isnsn like "foo W,X,Y,Z".
10669 where W=MVAX[0:3] and X,Y,Z=MVFX[0:15]. */
10670
10671static void
63e63b07 10672do_mav_quad (str, mode, reg0, reg1, reg2, reg3)
404ff6b5 10673 char * str;
404ff6b5 10674 int mode;
6c43fab6
RE
10675 enum arm_reg_type reg0;
10676 enum arm_reg_type reg1;
10677 enum arm_reg_type reg2;
10678 enum arm_reg_type reg3;
404ff6b5 10679{
6c43fab6 10680 int shift0, shift1, shift2, shift3;
404ff6b5 10681
6c43fab6
RE
10682 shift0= mode & 0xff;
10683 shift1 = (mode >> 8) & 0xff;
10684 shift2 = (mode >> 16) & 0xff;
10685 shift3 = (mode >> 24) & 0xff;
404ff6b5
AH
10686
10687 skip_whitespace (str);
10688
63e63b07 10689 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
404ff6b5 10690 || skip_past_comma (&str) == FAIL
63e63b07 10691 || mav_reg_required_here (&str, shift1, reg1) == FAIL
404ff6b5 10692 || skip_past_comma (&str) == FAIL
63e63b07 10693 || mav_reg_required_here (&str, shift2, reg2) == FAIL
404ff6b5 10694 || skip_past_comma (&str) == FAIL
63e63b07 10695 || mav_reg_required_here (&str, shift3, reg3) == FAIL)
404ff6b5
AH
10696 {
10697 if (!inst.error)
10698 inst.error = BAD_ARGS;
10699 }
10700 else
10701 end_of_line (str);
404ff6b5
AH
10702}
10703
63e63b07 10704/* Maverick shift immediate instructions.
404ff6b5
AH
10705 cfsh32<cond> MVFX[15:0],MVFX[15:0],Shift[6:0].
10706 cfsh64<cond> MVDX[15:0],MVDX[15:0],Shift[6:0]. */
10707
10708static void
63e63b07 10709do_mav_shift (str, reg0, reg1)
404ff6b5 10710 char * str;
6c43fab6
RE
10711 enum arm_reg_type reg0;
10712 enum arm_reg_type reg1;
404ff6b5
AH
10713{
10714 int error;
10715 int imm, neg = 0;
10716
10717 skip_whitespace (str);
10718
10719 error = 0;
10720
63e63b07 10721 if (mav_reg_required_here (&str, 12, reg0) == FAIL
404ff6b5 10722 || skip_past_comma (&str) == FAIL
63e63b07 10723 || mav_reg_required_here (&str, 16, reg1) == FAIL
404ff6b5
AH
10724 || skip_past_comma (&str) == FAIL)
10725 {
10726 if (!inst.error)
10727 inst.error = BAD_ARGS;
10728 return;
10729 }
10730
10731 /* Calculate the immediate operand.
10732 The operand is a 7bit signed number. */
10733 skip_whitespace (str);
10734
10735 if (*str == '#')
10736 ++str;
10737
8420dfca 10738 if (!ISDIGIT (*str) && *str != '-')
404ff6b5
AH
10739 {
10740 inst.error = _("expecting immediate, 7bit operand");
10741 return;
10742 }
10743
10744 if (*str == '-')
10745 {
10746 neg = 1;
10747 ++str;
10748 }
10749
8420dfca 10750 for (imm = 0; *str && ISDIGIT (*str); ++str)
404ff6b5
AH
10751 imm = imm * 10 + *str - '0';
10752
10753 if (imm > 64)
10754 {
10755 inst.error = _("immediate out of range");
10756 return;
10757 }
10758
10759 /* Make negative imm's into 7bit signed numbers. */
10760 if (neg)
10761 {
10762 imm = -imm;
10763 imm &= 0x0000007f;
10764 }
10765
10766 /* Bits 0-3 of the insn should have bits 0-3 of the immediate.
10767 Bits 5-7 of the insn should have bits 4-6 of the immediate.
10768 Bit 4 should be 0. */
10769 imm = (imm & 0xf) | ((imm & 0x70) << 1);
10770
10771 inst.instruction |= imm;
404ff6b5 10772 end_of_line (str);
404ff6b5
AH
10773}
10774
10775static int
63e63b07 10776mav_parse_offset (str, negative)
404ff6b5
AH
10777 char ** str;
10778 int *negative;
10779{
10780 char * p = *str;
10781 int offset;
10782
10783 *negative = 0;
10784
10785 skip_whitespace (p);
10786
10787 if (*p == '#')
10788 ++p;
10789
10790 if (*p == '-')
10791 {
10792 *negative = 1;
10793 ++p;
10794 }
10795
8420dfca 10796 if (!ISDIGIT (*p))
404ff6b5
AH
10797 {
10798 inst.error = _("offset expected");
10799 return 0;
10800 }
10801
8420dfca 10802 for (offset = 0; *p && ISDIGIT (*p); ++p)
404ff6b5
AH
10803 offset = offset * 10 + *p - '0';
10804
06516a5e 10805 if (offset > 0x3fc)
404ff6b5
AH
10806 {
10807 inst.error = _("offset out of range");
10808 return 0;
10809 }
06516a5e
PB
10810 if (offset & 0x3)
10811 {
10812 inst.error = _("offset not a multiple of 4");
10813 return 0;
10814 }
404ff6b5
AH
10815
10816 *str = p;
10817
10818 return *negative ? -offset : offset;
10819}
10820
63e63b07 10821/* Maverick load/store instructions.
404ff6b5
AH
10822 <insn><cond> CRd,[Rn,<offset>]{!}.
10823 <insn><cond> CRd,[Rn],<offset>. */
10824
10825static void
63e63b07 10826do_mav_ldst (str, reg0)
404ff6b5 10827 char * str;
6c43fab6 10828 enum arm_reg_type reg0;
404ff6b5
AH
10829{
10830 int offset, negative;
404ff6b5
AH
10831
10832 skip_whitespace (str);
10833
63e63b07 10834 if (mav_reg_required_here (&str, 12, reg0) == FAIL
6c43fab6 10835 || skip_past_comma (&str) == FAIL
404ff6b5 10836 || *str++ != '['
6c43fab6 10837 || reg_required_here (&str, 16) == FAIL)
404ff6b5
AH
10838 goto fail_ldst;
10839
6c43fab6 10840 if (skip_past_comma (&str) == SUCCESS)
404ff6b5
AH
10841 {
10842 /* You are here: "<offset>]{!}". */
10843 inst.instruction |= PRE_INDEX;
10844
63e63b07 10845 offset = mav_parse_offset (&str, &negative);
404ff6b5
AH
10846
10847 if (inst.error)
10848 return;
10849
10850 if (*str++ != ']')
10851 {
10852 inst.error = _("missing ]");
10853 return;
10854 }
10855
10856 if (*str == '!')
10857 {
10858 inst.instruction |= WRITE_BACK;
10859 ++str;
10860 }
10861 }
10862 else
10863 {
10864 /* You are here: "], <offset>". */
10865 if (*str++ != ']')
10866 {
10867 inst.error = _("missing ]");
10868 return;
10869 }
10870
10871 if (skip_past_comma (&str) == FAIL
63e63b07 10872 || (offset = mav_parse_offset (&str, &negative), inst.error))
404ff6b5
AH
10873 goto fail_ldst;
10874
10875 inst.instruction |= CP_T_WB; /* Post indexed, set bit W. */
10876 }
10877
10878 if (negative)
10879 offset = -offset;
10880 else
2d2255b5 10881 inst.instruction |= CP_T_UD; /* Positive, so set bit U. */
404ff6b5
AH
10882
10883 inst.instruction |= offset >> 2;
404ff6b5
AH
10884 end_of_line (str);
10885 return;
10886
10887fail_ldst:
10888 if (!inst.error)
10889 inst.error = BAD_ARGS;
404ff6b5
AH
10890}
10891
b99bd4ef
NC
10892static void
10893do_t_nop (str)
10894 char * str;
10895{
10896 /* Do nothing. */
10897 end_of_line (str);
b99bd4ef
NC
10898}
10899
10900/* Handle the Format 4 instructions that do not have equivalents in other
10901 formats. That is, ADC, AND, EOR, SBC, ROR, TST, NEG, CMN, ORR, MUL,
10902 BIC and MVN. */
10903
10904static void
10905do_t_arit (str)
10906 char * str;
10907{
10908 int Rd, Rs, Rn;
10909
10910 skip_whitespace (str);
10911
10912 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
10913 || skip_past_comma (&str) == FAIL
10914 || (Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
10915 {
10916 inst.error = BAD_ARGS;
10917 return;
10918 }
10919
10920 if (skip_past_comma (&str) != FAIL)
10921 {
10922 /* Three operand format not allowed for TST, CMN, NEG and MVN.
10923 (It isn't allowed for CMP either, but that isn't handled by this
10924 function.) */
10925 if (inst.instruction == T_OPCODE_TST
10926 || inst.instruction == T_OPCODE_CMN
10927 || inst.instruction == T_OPCODE_NEG
10928 || inst.instruction == T_OPCODE_MVN)
10929 {
10930 inst.error = BAD_ARGS;
10931 return;
10932 }
10933
10934 if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
10935 return;
10936
10937 if (Rs != Rd)
10938 {
10939 inst.error = _("dest and source1 must be the same register");
10940 return;
10941 }
10942 Rs = Rn;
10943 }
10944
10945 if (inst.instruction == T_OPCODE_MUL
10946 && Rs == Rd)
10947 as_tsktsk (_("Rs and Rd must be different in MUL"));
10948
10949 inst.instruction |= Rd | (Rs << 3);
10950 end_of_line (str);
10951}
10952
10953static void
10954do_t_add (str)
10955 char * str;
10956{
10957 thumb_add_sub (str, 0);
10958}
10959
10960static void
10961do_t_asr (str)
10962 char * str;
10963{
10964 thumb_shift (str, THUMB_ASR);
10965}
10966
10967static void
10968do_t_branch9 (str)
10969 char * str;
10970{
10971 if (my_get_expression (&inst.reloc.exp, &str))
10972 return;
10973 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH9;
10974 inst.reloc.pc_rel = 1;
10975 end_of_line (str);
10976}
10977
10978static void
10979do_t_branch12 (str)
10980 char * str;
10981{
10982 if (my_get_expression (&inst.reloc.exp, &str))
10983 return;
10984 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH12;
10985 inst.reloc.pc_rel = 1;
10986 end_of_line (str);
10987}
10988
10989/* Find the real, Thumb encoded start of a Thumb function. */
10990
10991static symbolS *
10992find_real_start (symbolP)
10993 symbolS * symbolP;
10994{
10995 char * real_start;
10996 const char * name = S_GET_NAME (symbolP);
10997 symbolS * new_target;
10998
2d2255b5 10999 /* This definition must agree with the one in gcc/config/arm/thumb.c. */
b99bd4ef
NC
11000#define STUB_NAME ".real_start_of"
11001
11002 if (name == NULL)
11003 abort ();
11004
11005 /* Names that start with '.' are local labels, not function entry points.
11006 The compiler may generate BL instructions to these labels because it
11007 needs to perform a branch to a far away location. */
11008 if (name[0] == '.')
11009 return symbolP;
11010
11011 real_start = malloc (strlen (name) + strlen (STUB_NAME) + 1);
11012 sprintf (real_start, "%s%s", STUB_NAME, name);
11013
11014 new_target = symbol_find (real_start);
11015
11016 if (new_target == NULL)
11017 {
11018 as_warn ("Failed to find real start of function: %s\n", name);
11019 new_target = symbolP;
11020 }
11021
11022 free (real_start);
11023
11024 return new_target;
11025}
11026
11027static void
11028do_t_branch23 (str)
11029 char * str;
11030{
11031 if (my_get_expression (& inst.reloc.exp, & str))
11032 return;
11033
11034 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH23;
11035 inst.reloc.pc_rel = 1;
11036 end_of_line (str);
11037
11038 /* If the destination of the branch is a defined symbol which does not have
11039 the THUMB_FUNC attribute, then we must be calling a function which has
11040 the (interfacearm) attribute. We look for the Thumb entry point to that
11041 function and change the branch to refer to that function instead. */
11042 if ( inst.reloc.exp.X_op == O_symbol
11043 && inst.reloc.exp.X_add_symbol != NULL
11044 && S_IS_DEFINED (inst.reloc.exp.X_add_symbol)
11045 && ! THUMB_IS_FUNC (inst.reloc.exp.X_add_symbol))
11046 inst.reloc.exp.X_add_symbol =
11047 find_real_start (inst.reloc.exp.X_add_symbol);
11048}
11049
11050static void
11051do_t_bx (str)
11052 char * str;
11053{
11054 int reg;
11055
11056 skip_whitespace (str);
11057
11058 if ((reg = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
11059 return;
11060
11061 /* This sets THUMB_H2 from the top bit of reg. */
11062 inst.instruction |= reg << 3;
11063
11064 /* ??? FIXME: Should add a hacky reloc here if reg is REG_PC. The reloc
11065 should cause the alignment to be checked once it is known. This is
11066 because BX PC only works if the instruction is word aligned. */
11067
11068 end_of_line (str);
11069}
11070
11071static void
11072do_t_compare (str)
11073 char * str;
11074{
11075 thumb_mov_compare (str, THUMB_COMPARE);
11076}
11077
11078static void
11079do_t_ldmstm (str)
11080 char * str;
11081{
11082 int Rb;
11083 long range;
11084
11085 skip_whitespace (str);
11086
11087 if ((Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
11088 return;
11089
11090 if (*str != '!')
f03698e6 11091 as_warn (_("inserted missing '!': load/store multiple always writes back base register"));
b99bd4ef
NC
11092 else
11093 str++;
11094
11095 if (skip_past_comma (&str) == FAIL
11096 || (range = reg_list (&str)) == FAIL)
11097 {
11098 if (! inst.error)
11099 inst.error = BAD_ARGS;
11100 return;
11101 }
11102
11103 if (inst.reloc.type != BFD_RELOC_NONE)
11104 {
11105 /* This really doesn't seem worth it. */
11106 inst.reloc.type = BFD_RELOC_NONE;
f03698e6 11107 inst.error = _("expression too complex");
b99bd4ef
NC
11108 return;
11109 }
11110
11111 if (range & ~0xff)
11112 {
11113 inst.error = _("only lo-regs valid in load/store multiple");
11114 return;
11115 }
11116
11117 inst.instruction |= (Rb << 8) | range;
11118 end_of_line (str);
11119}
11120
11121static void
11122do_t_ldr (str)
11123 char * str;
11124{
11125 thumb_load_store (str, THUMB_LOAD, THUMB_WORD);
11126}
11127
11128static void
11129do_t_ldrb (str)
11130 char * str;
11131{
11132 thumb_load_store (str, THUMB_LOAD, THUMB_BYTE);
11133}
11134
11135static void
11136do_t_ldrh (str)
11137 char * str;
11138{
11139 thumb_load_store (str, THUMB_LOAD, THUMB_HALFWORD);
11140}
11141
11142static void
11143do_t_lds (str)
11144 char * str;
11145{
11146 int Rd, Rb, Ro;
11147
11148 skip_whitespace (str);
11149
11150 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
11151 || skip_past_comma (&str) == FAIL
11152 || *str++ != '['
11153 || (Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL
11154 || skip_past_comma (&str) == FAIL
11155 || (Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL
11156 || *str++ != ']')
11157 {
11158 if (! inst.error)
f03698e6 11159 inst.error = _("syntax: ldrs[b] Rd, [Rb, Ro]");
b99bd4ef
NC
11160 return;
11161 }
11162
11163 inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
11164 end_of_line (str);
11165}
11166
11167static void
11168do_t_lsl (str)
11169 char * str;
11170{
11171 thumb_shift (str, THUMB_LSL);
11172}
11173
11174static void
11175do_t_lsr (str)
11176 char * str;
11177{
11178 thumb_shift (str, THUMB_LSR);
11179}
11180
11181static void
11182do_t_mov (str)
11183 char * str;
11184{
11185 thumb_mov_compare (str, THUMB_MOVE);
11186}
11187
11188static void
11189do_t_push_pop (str)
11190 char * str;
11191{
11192 long range;
11193
11194 skip_whitespace (str);
11195
11196 if ((range = reg_list (&str)) == FAIL)
11197 {
11198 if (! inst.error)
11199 inst.error = BAD_ARGS;
11200 return;
11201 }
11202
11203 if (inst.reloc.type != BFD_RELOC_NONE)
11204 {
11205 /* This really doesn't seem worth it. */
11206 inst.reloc.type = BFD_RELOC_NONE;
f03698e6 11207 inst.error = _("expression too complex");
b99bd4ef
NC
11208 return;
11209 }
11210
11211 if (range & ~0xff)
11212 {
11213 if ((inst.instruction == T_OPCODE_PUSH
11214 && (range & ~0xff) == 1 << REG_LR)
11215 || (inst.instruction == T_OPCODE_POP
11216 && (range & ~0xff) == 1 << REG_PC))
11217 {
11218 inst.instruction |= THUMB_PP_PC_LR;
11219 range &= 0xff;
11220 }
11221 else
11222 {
11223 inst.error = _("invalid register list to push/pop instruction");
11224 return;
11225 }
11226 }
11227
11228 inst.instruction |= range;
11229 end_of_line (str);
11230}
11231
11232static void
11233do_t_str (str)
11234 char * str;
11235{
11236 thumb_load_store (str, THUMB_STORE, THUMB_WORD);
11237}
11238
11239static void
11240do_t_strb (str)
11241 char * str;
11242{
11243 thumb_load_store (str, THUMB_STORE, THUMB_BYTE);
11244}
11245
11246static void
11247do_t_strh (str)
11248 char * str;
11249{
11250 thumb_load_store (str, THUMB_STORE, THUMB_HALFWORD);
11251}
11252
11253static void
11254do_t_sub (str)
11255 char * str;
11256{
11257 thumb_add_sub (str, 1);
11258}
11259
11260static void
11261do_t_swi (str)
11262 char * str;
11263{
11264 skip_whitespace (str);
11265
11266 if (my_get_expression (&inst.reloc.exp, &str))
11267 return;
11268
11269 inst.reloc.type = BFD_RELOC_ARM_SWI;
11270 end_of_line (str);
b99bd4ef
NC
11271}
11272
11273static void
11274do_t_adr (str)
11275 char * str;
11276{
11277 int reg;
11278
11279 /* This is a pseudo-op of the form "adr rd, label" to be converted
11280 into a relative address of the form "add rd, pc, #label-.-4". */
11281 skip_whitespace (str);
11282
11283 /* Store Rd in temporary location inside instruction. */
11284 if ((reg = reg_required_here (&str, 4)) == FAIL
11285 || (reg > 7) /* For Thumb reg must be r0..r7. */
11286 || skip_past_comma (&str) == FAIL
11287 || my_get_expression (&inst.reloc.exp, &str))
11288 {
11289 if (!inst.error)
11290 inst.error = BAD_ARGS;
11291 return;
11292 }
11293
11294 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
11295 inst.reloc.exp.X_add_number -= 4; /* PC relative adjust. */
11296 inst.reloc.pc_rel = 1;
11297 inst.instruction |= REG_PC; /* Rd is already placed into the instruction. */
11298
11299 end_of_line (str);
11300}
11301
11302static void
6c43fab6
RE
11303insert_reg (r, htab)
11304 const struct reg_entry *r;
11305 struct hash_control *htab;
b99bd4ef 11306{
6c43fab6 11307 int len = strlen (r->name) + 2;
b99bd4ef
NC
11308 char * buf = (char *) xmalloc (len);
11309 char * buf2 = (char *) xmalloc (len);
11310 int i = 0;
11311
11312#ifdef REGISTER_PREFIX
11313 buf[i++] = REGISTER_PREFIX;
11314#endif
11315
6c43fab6 11316 strcpy (buf + i, r->name);
b99bd4ef
NC
11317
11318 for (i = 0; buf[i]; i++)
3882b010 11319 buf2[i] = TOUPPER (buf[i]);
b99bd4ef
NC
11320
11321 buf2[i] = '\0';
11322
6c43fab6
RE
11323 hash_insert (htab, buf, (PTR) r);
11324 hash_insert (htab, buf2, (PTR) r);
b99bd4ef
NC
11325}
11326
11327static void
6c43fab6
RE
11328build_reg_hsh (map)
11329 struct reg_map *map;
11330{
11331 const struct reg_entry *r;
11332
11333 if ((map->htab = hash_new ()) == NULL)
f03698e6 11334 as_fatal (_("virtual memory exhausted"));
6c43fab6
RE
11335
11336 for (r = map->names; r->name != NULL; r++)
11337 insert_reg (r, map->htab);
11338}
11339
11340static void
11341insert_reg_alias (str, regnum, htab)
b99bd4ef
NC
11342 char *str;
11343 int regnum;
6c43fab6 11344 struct hash_control *htab;
b99bd4ef 11345{
0bbf2aa4
NC
11346 const char *error;
11347 struct reg_entry *new = xmalloc (sizeof (struct reg_entry));
11348 const char *name = xmalloc (strlen (str) + 1);
11349
11350 strcpy ((char *) name, str);
11351
b99bd4ef
NC
11352 new->name = name;
11353 new->number = regnum;
0bbf2aa4 11354 new->builtin = FALSE;
b99bd4ef 11355
0bbf2aa4
NC
11356 error = hash_insert (htab, name, (PTR) new);
11357 if (error)
11358 {
11359 as_bad (_("failed to create an alias for %s, reason: %s"),
11360 str, error);
11361 free ((char *) name);
11362 free (new);
11363 }
b99bd4ef
NC
11364}
11365
6c43fab6
RE
11366/* Look for the .req directive. This is of the form:
11367
0bbf2aa4 11368 new_register_name .req existing_register_name
6c43fab6
RE
11369
11370 If we find one, or if it looks sufficiently like one that we want to
11371 handle any error here, return non-zero. Otherwise return zero. */
11372static int
11373create_register_alias (newname, p)
11374 char *newname;
11375 char *p;
11376{
11377 char *q;
11378 char c;
11379
11380 q = p;
11381 skip_whitespace (q);
11382
11383 c = *p;
11384 *p = '\0';
11385
11386 if (*q && !strncmp (q, ".req ", 5))
11387 {
11388 char *copy_of_str;
11389 char *r;
11390
376eb240 11391#ifndef IGNORE_OPCODE_CASE
6c43fab6
RE
11392 newname = original_case_string;
11393#endif
11394 copy_of_str = newname;
11395
11396 q += 4;
11397 skip_whitespace (q);
11398
11399 for (r = q; *r != '\0'; r++)
11400 if (*r == ' ')
11401 break;
11402
11403 if (r != q)
11404 {
11405 enum arm_reg_type new_type, old_type;
11406 int old_regno;
11407 char d = *r;
11408
11409 *r = '\0';
11410 old_type = arm_reg_parse_any (q);
11411 *r = d;
11412
11413 new_type = arm_reg_parse_any (newname);
11414
11415 if (new_type == REG_TYPE_MAX)
11416 {
11417 if (old_type != REG_TYPE_MAX)
11418 {
11419 old_regno = arm_reg_parse (&q, all_reg_maps[old_type].htab);
11420 insert_reg_alias (newname, old_regno,
11421 all_reg_maps[old_type].htab);
11422 }
11423 else
11424 as_warn (_("register '%s' does not exist\n"), q);
11425 }
11426 else if (old_type == REG_TYPE_MAX)
11427 {
11428 as_warn (_("ignoring redefinition of register alias '%s' to non-existant register '%s'"),
11429 copy_of_str, q);
11430 }
11431 else
11432 {
11433 /* Do not warn about redefinitions to the same alias. */
11434 if (new_type != old_type
11435 || (arm_reg_parse (&q, all_reg_maps[old_type].htab)
11436 != arm_reg_parse (&q, all_reg_maps[new_type].htab)))
11437 as_warn (_("ignoring redefinition of register alias '%s'"),
11438 copy_of_str);
11439
11440 }
11441 }
11442 else
11443 as_warn (_("ignoring incomplete .req pseuso op"));
11444
11445 *p = c;
11446 return 1;
11447 }
0bbf2aa4 11448
6c43fab6
RE
11449 *p = c;
11450 return 0;
11451}
cc8a6dd0 11452
b99bd4ef
NC
11453static void
11454set_constant_flonums ()
11455{
11456 int i;
11457
11458 for (i = 0; i < NUM_FLOAT_VALS; i++)
11459 if (atof_ieee ((char *) fp_const[i], 'x', fp_values[i]) == NULL)
11460 abort ();
11461}
11462
90e4755a
RE
11463/* Iterate over the base tables to create the instruction patterns. */
11464static void
11465build_arm_ops_hsh ()
11466{
11467 unsigned int i;
11468 unsigned int j;
11469 static struct obstack insn_obstack;
11470
11471 obstack_begin (&insn_obstack, 4000);
11472
11473 for (i = 0; i < sizeof (insns) / sizeof (struct asm_opcode); i++)
11474 {
6c43fab6 11475 const struct asm_opcode *insn = insns + i;
90e4755a
RE
11476
11477 if (insn->cond_offset != 0)
11478 {
11479 /* Insn supports conditional execution. Build the varaints
11480 and insert them in the hash table. */
11481 for (j = 0; j < sizeof (conds) / sizeof (struct asm_cond); j++)
11482 {
11483 unsigned len = strlen (insn->template);
11484 struct asm_opcode *new;
11485 char *template;
11486
11487 new = obstack_alloc (&insn_obstack, sizeof (struct asm_opcode));
11488 /* All condition codes are two characters. */
11489 template = obstack_alloc (&insn_obstack, len + 3);
11490
11491 strncpy (template, insn->template, insn->cond_offset);
11492 strcpy (template + insn->cond_offset, conds[j].template);
11493 if (len > insn->cond_offset)
11494 strcpy (template + insn->cond_offset + 2,
11495 insn->template + insn->cond_offset);
11496 new->template = template;
11497 new->cond_offset = 0;
11498 new->variant = insn->variant;
11499 new->parms = insn->parms;
11500 new->value = (insn->value & ~COND_MASK) | conds[j].value;
11501
11502 hash_insert (arm_ops_hsh, new->template, (PTR) new);
11503 }
11504 }
11505 /* Finally, insert the unconditional insn in the table directly;
11506 no need to build a copy. */
11507 hash_insert (arm_ops_hsh, insn->template, (PTR) insn);
11508 }
11509}
11510
0bbf2aa4 11511#if 0 /* Suppressed - for now. */
5a6c6817
NC
11512#if defined OBJ_ELF || defined OBJ_COFF
11513
11514#ifdef OBJ_ELF
11515#define arm_Note Elf_External_Note
11516#else
11517typedef struct
11518{
11519 unsigned char namesz[4]; /* Size of entry's owner string. */
11520 unsigned char descsz[4]; /* Size of the note descriptor. */
11521 unsigned char type[4]; /* Interpretation of the descriptor. */
11522 char name[1]; /* Start of the name+desc data. */
11523} arm_Note;
11524#endif
11525
11526/* The description is kept to a fix sized in order to make updating
11527 it and merging it easier. */
11528#define ARM_NOTE_DESCRIPTION_LENGTH 8
11529
11530static void
11531arm_add_note (name, description, type)
11532 const char * name;
11533 const char * description;
11534 unsigned int type;
11535{
11536 arm_Note note ATTRIBUTE_UNUSED;
11537 char * p;
11538 unsigned int name_len;
11539
11540 name_len = (strlen (name) + 1 + 3) & ~3;
11541
11542 p = frag_more (sizeof (note.namesz));
11543 md_number_to_chars (p, (valueT) name_len, sizeof (note.namesz));
11544
11545 p = frag_more (sizeof (note.descsz));
11546 md_number_to_chars (p, (valueT) ARM_NOTE_DESCRIPTION_LENGTH, sizeof (note.descsz));
11547
11548 p = frag_more (sizeof (note.type));
11549 md_number_to_chars (p, (valueT) type, sizeof (note.type));
11550
11551 p = frag_more (name_len);
11552 strcpy (p, name);
11553
11554 p = frag_more (ARM_NOTE_DESCRIPTION_LENGTH);
11555 strncpy (p, description, ARM_NOTE_DESCRIPTION_LENGTH);
11556 frag_align (2, 0, 0);
11557}
11558#endif
0bbf2aa4 11559#endif
5a6c6817 11560
b99bd4ef
NC
11561void
11562md_begin ()
11563{
11564 unsigned mach;
11565 unsigned int i;
11566
11567 if ( (arm_ops_hsh = hash_new ()) == NULL
11568 || (arm_tops_hsh = hash_new ()) == NULL
11569 || (arm_cond_hsh = hash_new ()) == NULL
11570 || (arm_shift_hsh = hash_new ()) == NULL
b99bd4ef 11571 || (arm_psr_hsh = hash_new ()) == NULL)
f03698e6 11572 as_fatal (_("virtual memory exhausted"));
b99bd4ef 11573
90e4755a 11574 build_arm_ops_hsh ();
b99bd4ef
NC
11575 for (i = 0; i < sizeof (tinsns) / sizeof (struct thumb_opcode); i++)
11576 hash_insert (arm_tops_hsh, tinsns[i].template, (PTR) (tinsns + i));
11577 for (i = 0; i < sizeof (conds) / sizeof (struct asm_cond); i++)
11578 hash_insert (arm_cond_hsh, conds[i].template, (PTR) (conds + i));
11579 for (i = 0; i < sizeof (shift_names) / sizeof (struct asm_shift_name); i++)
11580 hash_insert (arm_shift_hsh, shift_names[i].name, (PTR) (shift_names + i));
11581 for (i = 0; i < sizeof (psrs) / sizeof (struct asm_psr); i++)
11582 hash_insert (arm_psr_hsh, psrs[i].template, (PTR) (psrs + i));
11583
6c43fab6
RE
11584 for (i = (int) REG_TYPE_FIRST; i < (int) REG_TYPE_MAX; i++)
11585 build_reg_hsh (all_reg_maps + i);
b99bd4ef
NC
11586
11587 set_constant_flonums ();
11588
03b1477f
RE
11589 /* Set the cpu variant based on the command-line options. We prefer
11590 -mcpu= over -march= if both are set (as for GCC); and we prefer
11591 -mfpu= over any other way of setting the floating point unit.
11592 Use of legacy options with new options are faulted. */
11593 if (legacy_cpu != -1)
11594 {
11595 if (mcpu_cpu_opt != -1 || march_cpu_opt != -1)
11596 as_bad (_("use of old and new-style options to set CPU type"));
11597
11598 mcpu_cpu_opt = legacy_cpu;
11599 }
11600 else if (mcpu_cpu_opt == -1)
11601 mcpu_cpu_opt = march_cpu_opt;
11602
11603 if (legacy_fpu != -1)
11604 {
11605 if (mfpu_opt != -1)
11606 as_bad (_("use of old and new-style options to set FPU type"));
11607
11608 mfpu_opt = legacy_fpu;
11609 }
11610 else if (mfpu_opt == -1)
11611 {
39c2da32
RE
11612#if !(defined (TE_LINUX) || defined (TE_NetBSD))
11613 /* Some environments specify a default FPU. If they don't, infer it
11614 from the processor. */
03b1477f
RE
11615 if (mcpu_fpu_opt != -1)
11616 mfpu_opt = mcpu_fpu_opt;
11617 else
11618 mfpu_opt = march_fpu_opt;
39c2da32
RE
11619#else
11620 mfpu_opt = FPU_DEFAULT;
11621#endif
03b1477f
RE
11622 }
11623
11624 if (mfpu_opt == -1)
11625 {
11626 if (mcpu_cpu_opt == -1)
11627 mfpu_opt = FPU_DEFAULT;
11628 else if (mcpu_cpu_opt & ARM_EXT_V5)
11629 mfpu_opt = FPU_ARCH_VFP_V2;
11630 else
11631 mfpu_opt = FPU_ARCH_FPA;
11632 }
11633
11634 if (mcpu_cpu_opt == -1)
11635 mcpu_cpu_opt = CPU_DEFAULT;
11636
11637 cpu_variant = mcpu_cpu_opt | mfpu_opt;
11638
b99bd4ef 11639 {
7cc69913
NC
11640 unsigned int flags = 0;
11641
11642#if defined OBJ_ELF
11643 flags = meabi_flags;
d507cf36
PB
11644
11645 switch (meabi_flags)
33a392fb 11646 {
d507cf36 11647 case EF_ARM_EABI_UNKNOWN:
7cc69913
NC
11648#endif
11649#if defined OBJ_COFF || defined OBJ_ELF
d507cf36
PB
11650 /* Set the flags in the private structure. */
11651 if (uses_apcs_26) flags |= F_APCS26;
11652 if (support_interwork) flags |= F_INTERWORK;
11653 if (uses_apcs_float) flags |= F_APCS_FLOAT;
11654 if (pic_code) flags |= F_PIC;
11655 if ((cpu_variant & FPU_ANY) == FPU_NONE
11656 || (cpu_variant & FPU_ANY) == FPU_ARCH_VFP) /* VFP layout only. */
7cc69913
NC
11657 flags |= F_SOFT_FLOAT;
11658
d507cf36
PB
11659 switch (mfloat_abi_opt)
11660 {
11661 case ARM_FLOAT_ABI_SOFT:
11662 case ARM_FLOAT_ABI_SOFTFP:
11663 flags |= F_SOFT_FLOAT;
11664 break;
33a392fb 11665
d507cf36
PB
11666 case ARM_FLOAT_ABI_HARD:
11667 if (flags & F_SOFT_FLOAT)
11668 as_bad (_("hard-float conflicts with specified fpu"));
11669 break;
11670 }
03b1477f 11671
7cc69913
NC
11672 /* Using VFP conventions (even if soft-float). */
11673 if (cpu_variant & FPU_VFP_EXT_NONE)
11674 flags |= F_VFP_FLOAT;
11675#endif
fde78edd 11676#if defined OBJ_ELF
d507cf36
PB
11677 if (cpu_variant & FPU_ARCH_MAVERICK)
11678 flags |= EF_ARM_MAVERICK_FLOAT;
d507cf36
PB
11679 break;
11680
11681 case EF_ARM_EABI_VER3:
11682 /* No additional flags to set. */
11683 break;
11684
11685 default:
11686 abort ();
11687 }
7cc69913
NC
11688#endif
11689#if defined OBJ_COFF || defined OBJ_ELF
b99bd4ef
NC
11690 bfd_set_private_flags (stdoutput, flags);
11691
11692 /* We have run out flags in the COFF header to encode the
11693 status of ATPCS support, so instead we create a dummy,
11694 empty, debug section called .arm.atpcs. */
11695 if (atpcs)
11696 {
11697 asection * sec;
11698
11699 sec = bfd_make_section (stdoutput, ".arm.atpcs");
11700
11701 if (sec != NULL)
11702 {
11703 bfd_set_section_flags
11704 (stdoutput, sec, SEC_READONLY | SEC_DEBUGGING /* | SEC_HAS_CONTENTS */);
11705 bfd_set_section_size (stdoutput, sec, 0);
11706 bfd_set_section_contents (stdoutput, sec, NULL, 0, 0);
11707 }
11708 }
b99bd4ef 11709#endif
7cc69913 11710 }
b99bd4ef
NC
11711
11712 /* Record the CPU type as well. */
11713 switch (cpu_variant & ARM_CPU_MASK)
11714 {
11715 case ARM_2:
11716 mach = bfd_mach_arm_2;
11717 break;
11718
11719 case ARM_3: /* Also ARM_250. */
11720 mach = bfd_mach_arm_2a;
11721 break;
11722
b89dddec
RE
11723 case ARM_6: /* Also ARM_7. */
11724 mach = bfd_mach_arm_3;
11725 break;
11726
b99bd4ef 11727 default:
5a6c6817 11728 mach = bfd_mach_arm_unknown;
b99bd4ef 11729 break;
b99bd4ef
NC
11730 }
11731
11732 /* Catch special cases. */
e16bb312
NC
11733 if (cpu_variant & ARM_CEXT_IWMMXT)
11734 mach = bfd_mach_arm_iWMMXt;
11735 else if (cpu_variant & ARM_CEXT_XSCALE)
b99bd4ef 11736 mach = bfd_mach_arm_XScale;
fde78edd
NC
11737 else if (cpu_variant & ARM_CEXT_MAVERICK)
11738 mach = bfd_mach_arm_ep9312;
b99bd4ef
NC
11739 else if (cpu_variant & ARM_EXT_V5E)
11740 mach = bfd_mach_arm_5TE;
11741 else if (cpu_variant & ARM_EXT_V5)
11742 {
b89dddec 11743 if (cpu_variant & ARM_EXT_V4T)
b99bd4ef
NC
11744 mach = bfd_mach_arm_5T;
11745 else
11746 mach = bfd_mach_arm_5;
11747 }
b89dddec 11748 else if (cpu_variant & ARM_EXT_V4)
b99bd4ef 11749 {
b89dddec 11750 if (cpu_variant & ARM_EXT_V4T)
b99bd4ef
NC
11751 mach = bfd_mach_arm_4T;
11752 else
11753 mach = bfd_mach_arm_4;
11754 }
b89dddec 11755 else if (cpu_variant & ARM_EXT_V3M)
b99bd4ef
NC
11756 mach = bfd_mach_arm_3M;
11757
5a6c6817 11758#if 0 /* Suppressed - for now. */
e16bb312 11759#if defined (OBJ_ELF) || defined (OBJ_COFF)
5a6c6817
NC
11760
11761 /* Create a .note section to fully identify this arm binary. */
11762
11763#define NOTE_ARCH_STRING "arch: "
11764
11765#if defined OBJ_COFF && ! defined NT_VERSION
11766#define NT_VERSION 1
11767#define NT_ARCH 2
11768#endif
11769
e16bb312 11770 {
e16bb312
NC
11771 segT current_seg = now_seg;
11772 subsegT current_subseg = now_subseg;
11773 asection * arm_arch;
5a6c6817
NC
11774 const char * arch_string;
11775
e16bb312
NC
11776 arm_arch = bfd_make_section_old_way (stdoutput, ARM_NOTE_SECTION);
11777
11778#ifdef OBJ_COFF
11779 bfd_set_section_flags (stdoutput, arm_arch,
11780 SEC_DATA | SEC_ALLOC | SEC_LOAD | SEC_LINK_ONCE \
11781 | SEC_HAS_CONTENTS);
e41f12f3
DJ
11782#else
11783 bfd_set_section_flags (stdoutput, arm_arch,
11784 SEC_READONLY | SEC_HAS_CONTENTS);
e16bb312
NC
11785#endif
11786 arm_arch->output_section = arm_arch;
11787 subseg_set (arm_arch, 0);
e16bb312 11788
5a6c6817
NC
11789 switch (mach)
11790 {
11791 default:
11792 case bfd_mach_arm_unknown: arch_string = "unknown"; break;
11793 case bfd_mach_arm_2: arch_string = "armv2"; break;
11794 case bfd_mach_arm_2a: arch_string = "armv2a"; break;
11795 case bfd_mach_arm_3: arch_string = "armv3"; break;
11796 case bfd_mach_arm_3M: arch_string = "armv3M"; break;
11797 case bfd_mach_arm_4: arch_string = "armv4"; break;
11798 case bfd_mach_arm_4T: arch_string = "armv4t"; break;
11799 case bfd_mach_arm_5: arch_string = "armv5"; break;
11800 case bfd_mach_arm_5T: arch_string = "armv5t"; break;
11801 case bfd_mach_arm_5TE: arch_string = "armv5te"; break;
11802 case bfd_mach_arm_XScale: arch_string = "XScale"; break;
11803 case bfd_mach_arm_ep9312: arch_string = "ep9312"; break;
11804 case bfd_mach_arm_iWMMXt: arch_string = "iWMMXt"; break;
11805 }
11806
11807 arm_add_note (NOTE_ARCH_STRING, arch_string, NT_ARCH);
e16bb312
NC
11808
11809 subseg_set (current_seg, current_subseg);
11810 }
11811#endif
5a6c6817
NC
11812#endif /* Suppressed code. */
11813
b99bd4ef
NC
11814 bfd_set_arch_mach (stdoutput, TARGET_ARCH, mach);
11815}
11816
11817/* Turn an integer of n bytes (in val) into a stream of bytes appropriate
11818 for use in the a.out file, and stores them in the array pointed to by buf.
11819 This knows about the endian-ness of the target machine and does
11820 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
11821 2 (short) and 4 (long) Floating numbers are put out as a series of
11822 LITTLENUMS (shorts, here at least). */
11823
11824void
11825md_number_to_chars (buf, val, n)
11826 char * buf;
11827 valueT val;
11828 int n;
11829{
11830 if (target_big_endian)
11831 number_to_chars_bigendian (buf, val, n);
11832 else
11833 number_to_chars_littleendian (buf, val, n);
11834}
11835
11836static valueT
11837md_chars_to_number (buf, n)
11838 char * buf;
11839 int n;
11840{
11841 valueT result = 0;
11842 unsigned char * where = (unsigned char *) buf;
11843
11844 if (target_big_endian)
11845 {
11846 while (n--)
11847 {
11848 result <<= 8;
11849 result |= (*where++ & 255);
11850 }
11851 }
11852 else
11853 {
11854 while (n--)
11855 {
11856 result <<= 8;
11857 result |= (where[n] & 255);
11858 }
11859 }
11860
11861 return result;
11862}
11863
11864/* Turn a string in input_line_pointer into a floating point constant
11865 of type TYPE, and store the appropriate bytes in *LITP. The number
11866 of LITTLENUMS emitted is stored in *SIZEP. An error message is
11867 returned, or NULL on OK.
11868
11869 Note that fp constants aren't represent in the normal way on the ARM.
11870 In big endian mode, things are as expected. However, in little endian
11871 mode fp constants are big-endian word-wise, and little-endian byte-wise
11872 within the words. For example, (double) 1.1 in big endian mode is
11873 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
11874 the byte sequence 99 99 f1 3f 9a 99 99 99.
11875
11876 ??? The format of 12 byte floats is uncertain according to gcc's arm.h. */
11877
11878char *
11879md_atof (type, litP, sizeP)
11880 char type;
11881 char * litP;
11882 int * sizeP;
11883{
11884 int prec;
11885 LITTLENUM_TYPE words[MAX_LITTLENUMS];
11886 char *t;
11887 int i;
11888
11889 switch (type)
11890 {
11891 case 'f':
11892 case 'F':
11893 case 's':
11894 case 'S':
11895 prec = 2;
11896 break;
11897
11898 case 'd':
11899 case 'D':
11900 case 'r':
11901 case 'R':
11902 prec = 4;
11903 break;
11904
11905 case 'x':
11906 case 'X':
11907 prec = 6;
11908 break;
11909
11910 case 'p':
11911 case 'P':
11912 prec = 6;
11913 break;
11914
11915 default:
11916 *sizeP = 0;
f03698e6 11917 return _("bad call to MD_ATOF()");
b99bd4ef
NC
11918 }
11919
11920 t = atof_ieee (input_line_pointer, type, words);
11921 if (t)
11922 input_line_pointer = t;
11923 *sizeP = prec * 2;
11924
11925 if (target_big_endian)
11926 {
11927 for (i = 0; i < prec; i++)
11928 {
11929 md_number_to_chars (litP, (valueT) words[i], 2);
11930 litP += 2;
11931 }
11932 }
11933 else
11934 {
bfae80f2
RE
11935 if (cpu_variant & FPU_ARCH_VFP)
11936 for (i = prec - 1; i >= 0; i--)
11937 {
11938 md_number_to_chars (litP, (valueT) words[i], 2);
11939 litP += 2;
11940 }
11941 else
11942 /* For a 4 byte float the order of elements in `words' is 1 0.
11943 For an 8 byte float the order is 1 0 3 2. */
11944 for (i = 0; i < prec; i += 2)
11945 {
11946 md_number_to_chars (litP, (valueT) words[i + 1], 2);
11947 md_number_to_chars (litP + 2, (valueT) words[i], 2);
11948 litP += 4;
11949 }
b99bd4ef
NC
11950 }
11951
11952 return 0;
11953}
11954
11955/* The knowledge of the PC's pipeline offset is built into the insns
11956 themselves. */
11957
11958long
11959md_pcrel_from (fixP)
11960 fixS * fixP;
11961{
11962 if (fixP->fx_addsy
11963 && S_GET_SEGMENT (fixP->fx_addsy) == undefined_section
11964 && fixP->fx_subsy == NULL)
11965 return 0;
11966
11967 if (fixP->fx_pcrel && (fixP->fx_r_type == BFD_RELOC_ARM_THUMB_ADD))
11968 {
11969 /* PC relative addressing on the Thumb is slightly odd
11970 as the bottom two bits of the PC are forced to zero
11971 for the calculation. */
11972 return (fixP->fx_where + fixP->fx_frag->fr_address) & ~3;
11973 }
11974
11975#ifdef TE_WINCE
2d2255b5
KH
11976 /* The pattern was adjusted to accommodate CE's off-by-one fixups,
11977 so we un-adjust here to compensate for the accommodation. */
b99bd4ef
NC
11978 return fixP->fx_where + fixP->fx_frag->fr_address + 8;
11979#else
11980 return fixP->fx_where + fixP->fx_frag->fr_address;
11981#endif
11982}
11983
11984/* Round up a section size to the appropriate boundary. */
11985
11986valueT
11987md_section_align (segment, size)
11988 segT segment ATTRIBUTE_UNUSED;
11989 valueT size;
11990{
11991#ifdef OBJ_ELF
11992 return size;
11993#else
11994 /* Round all sects to multiple of 4. */
11995 return (size + 3) & ~3;
11996#endif
11997}
11998
11999/* Under ELF we need to default _GLOBAL_OFFSET_TABLE.
12000 Otherwise we have no need to default values of symbols. */
12001
12002symbolS *
12003md_undefined_symbol (name)
12004 char * name ATTRIBUTE_UNUSED;
12005{
12006#ifdef OBJ_ELF
12007 if (name[0] == '_' && name[1] == 'G'
12008 && streq (name, GLOBAL_OFFSET_TABLE_NAME))
12009 {
12010 if (!GOT_symbol)
12011 {
12012 if (symbol_find (name))
12013 as_bad ("GOT already in the symbol table");
12014
12015 GOT_symbol = symbol_new (name, undefined_section,
12016 (valueT) 0, & zero_address_frag);
12017 }
12018
12019 return GOT_symbol;
12020 }
12021#endif
12022
12023 return 0;
12024}
12025
12026/* arm_reg_parse () := if it looks like a register, return its token and
12027 advance the pointer. */
12028
12029static int
6c43fab6 12030arm_reg_parse (ccp, htab)
b99bd4ef 12031 register char ** ccp;
6c43fab6 12032 struct hash_control *htab;
b99bd4ef
NC
12033{
12034 char * start = * ccp;
12035 char c;
12036 char * p;
12037 struct reg_entry * reg;
12038
12039#ifdef REGISTER_PREFIX
12040 if (*start != REGISTER_PREFIX)
12041 return FAIL;
12042 p = start + 1;
12043#else
12044 p = start;
12045#ifdef OPTIONAL_REGISTER_PREFIX
12046 if (*p == OPTIONAL_REGISTER_PREFIX)
12047 p++, start++;
12048#endif
12049#endif
3882b010 12050 if (!ISALPHA (*p) || !is_name_beginner (*p))
b99bd4ef
NC
12051 return FAIL;
12052
12053 c = *p++;
3882b010 12054 while (ISALPHA (c) || ISDIGIT (c) || c == '_')
b99bd4ef
NC
12055 c = *p++;
12056
12057 *--p = 0;
6c43fab6 12058 reg = (struct reg_entry *) hash_find (htab, start);
b99bd4ef
NC
12059 *p = c;
12060
12061 if (reg)
12062 {
12063 *ccp = p;
12064 return reg->number;
12065 }
12066
12067 return FAIL;
12068}
12069
6c43fab6
RE
12070/* Search for the following register name in each of the possible reg name
12071 tables. Return the classification if found, or REG_TYPE_MAX if not
12072 present. */
12073static enum arm_reg_type
12074arm_reg_parse_any (cp)
12075 char *cp;
12076{
12077 int i;
12078
12079 for (i = (int) REG_TYPE_FIRST; i < (int) REG_TYPE_MAX; i++)
12080 if (arm_reg_parse (&cp, all_reg_maps[i].htab) != FAIL)
12081 return (enum arm_reg_type) i;
12082
12083 return REG_TYPE_MAX;
12084}
12085
94f592af
NC
12086void
12087md_apply_fix3 (fixP, valP, seg)
b99bd4ef 12088 fixS * fixP;
94f592af 12089 valueT * valP;
b99bd4ef
NC
12090 segT seg;
12091{
94f592af 12092 offsetT value = * valP;
b99bd4ef
NC
12093 offsetT newval;
12094 unsigned int newimm;
12095 unsigned long temp;
12096 int sign;
12097 char * buf = fixP->fx_where + fixP->fx_frag->fr_literal;
12098 arm_fix_data * arm_data = (arm_fix_data *) fixP->tc_fix_data;
12099
12100 assert (fixP->fx_r_type < BFD_RELOC_UNUSED);
12101
12102 /* Note whether this will delete the relocation. */
12103#if 0
12104 /* Patch from REarnshaw to JDavis (disabled for the moment, since it
12105 doesn't work fully.) */
12106 if ((fixP->fx_addsy == 0 || symbol_constant_p (fixP->fx_addsy))
12107 && !fixP->fx_pcrel)
12108#else
12109 if (fixP->fx_addsy == 0 && !fixP->fx_pcrel)
12110#endif
12111 fixP->fx_done = 1;
12112
12113 /* If this symbol is in a different section then we need to leave it for
12114 the linker to deal with. Unfortunately, md_pcrel_from can't tell,
12115 so we have to undo it's effects here. */
12116 if (fixP->fx_pcrel)
12117 {
12118 if (fixP->fx_addsy != NULL
12119 && S_IS_DEFINED (fixP->fx_addsy)
12120 && S_GET_SEGMENT (fixP->fx_addsy) != seg)
12121 {
12122 if (target_oabi
12123 && (fixP->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH
12124 || fixP->fx_r_type == BFD_RELOC_ARM_PCREL_BLX
12125 ))
12126 value = 0;
12127 else
12128 value += md_pcrel_from (fixP);
12129 }
12130 }
12131
12132 /* Remember value for emit_reloc. */
12133 fixP->fx_addnumber = value;
12134
12135 switch (fixP->fx_r_type)
12136 {
12137 case BFD_RELOC_ARM_IMMEDIATE:
310ea308
NC
12138 /* We claim that this fixup has been processed here,
12139 even if in fact we generate an error because we do
12140 not have a reloc for it, so tc_gen_reloc will reject it. */
12141 fixP->fx_done = 1;
12142
12143 if (fixP->fx_addsy
12144 && ! S_IS_DEFINED (fixP->fx_addsy))
12145 {
12146 as_bad_where (fixP->fx_file, fixP->fx_line,
12147 _("undefined symbol %s used as an immediate value"),
12148 S_GET_NAME (fixP->fx_addsy));
12149 break;
12150 }
12151
b99bd4ef
NC
12152 newimm = validate_immediate (value);
12153 temp = md_chars_to_number (buf, INSN_SIZE);
12154
12155 /* If the instruction will fail, see if we can fix things up by
12156 changing the opcode. */
12157 if (newimm == (unsigned int) FAIL
12158 && (newimm = negate_data_op (&temp, value)) == (unsigned int) FAIL)
12159 {
12160 as_bad_where (fixP->fx_file, fixP->fx_line,
12161 _("invalid constant (%lx) after fixup"),
12162 (unsigned long) value);
12163 break;
12164 }
12165
12166 newimm |= (temp & 0xfffff000);
12167 md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
12168 break;
12169
12170 case BFD_RELOC_ARM_ADRL_IMMEDIATE:
12171 {
12172 unsigned int highpart = 0;
12173 unsigned int newinsn = 0xe1a00000; /* nop. */
6189168b 12174
b99bd4ef
NC
12175 newimm = validate_immediate (value);
12176 temp = md_chars_to_number (buf, INSN_SIZE);
12177
12178 /* If the instruction will fail, see if we can fix things up by
12179 changing the opcode. */
12180 if (newimm == (unsigned int) FAIL
12181 && (newimm = negate_data_op (& temp, value)) == (unsigned int) FAIL)
12182 {
12183 /* No ? OK - try using two ADD instructions to generate
12184 the value. */
12185 newimm = validate_immediate_twopart (value, & highpart);
12186
12187 /* Yes - then make sure that the second instruction is
12188 also an add. */
12189 if (newimm != (unsigned int) FAIL)
12190 newinsn = temp;
12191 /* Still No ? Try using a negated value. */
12192 else if ((newimm = validate_immediate_twopart (- value, & highpart)) != (unsigned int) FAIL)
12193 temp = newinsn = (temp & OPCODE_MASK) | OPCODE_SUB << DATA_OP_SHIFT;
12194 /* Otherwise - give up. */
12195 else
12196 {
12197 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12198 _("unable to compute ADRL instructions for PC offset of 0x%lx"),
08df2379 12199 (long) value);
b99bd4ef
NC
12200 break;
12201 }
12202
12203 /* Replace the first operand in the 2nd instruction (which
12204 is the PC) with the destination register. We have
12205 already added in the PC in the first instruction and we
12206 do not want to do it again. */
12207 newinsn &= ~ 0xf0000;
12208 newinsn |= ((newinsn & 0x0f000) << 4);
12209 }
12210
12211 newimm |= (temp & 0xfffff000);
12212 md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
12213
12214 highpart |= (newinsn & 0xfffff000);
12215 md_number_to_chars (buf + INSN_SIZE, (valueT) highpart, INSN_SIZE);
12216 }
12217 break;
12218
12219 case BFD_RELOC_ARM_OFFSET_IMM:
12220 sign = value >= 0;
12221
12222 if (value < 0)
12223 value = - value;
12224
12225 if (validate_offset_imm (value, 0) == FAIL)
12226 {
12227 as_bad_where (fixP->fx_file, fixP->fx_line,
12228 _("bad immediate value for offset (%ld)"),
12229 (long) value);
12230 break;
12231 }
12232
12233 newval = md_chars_to_number (buf, INSN_SIZE);
12234 newval &= 0xff7ff000;
12235 newval |= value | (sign ? INDEX_UP : 0);
12236 md_number_to_chars (buf, newval, INSN_SIZE);
12237 break;
12238
12239 case BFD_RELOC_ARM_OFFSET_IMM8:
12240 case BFD_RELOC_ARM_HWLITERAL:
12241 sign = value >= 0;
12242
12243 if (value < 0)
12244 value = - value;
12245
12246 if (validate_offset_imm (value, 1) == FAIL)
12247 {
12248 if (fixP->fx_r_type == BFD_RELOC_ARM_HWLITERAL)
12249 as_bad_where (fixP->fx_file, fixP->fx_line,
12250 _("invalid literal constant: pool needs to be closer"));
12251 else
12252 as_bad (_("bad immediate value for half-word offset (%ld)"),
12253 (long) value);
12254 break;
12255 }
12256
12257 newval = md_chars_to_number (buf, INSN_SIZE);
12258 newval &= 0xff7ff0f0;
12259 newval |= ((value >> 4) << 8) | (value & 0xf) | (sign ? INDEX_UP : 0);
12260 md_number_to_chars (buf, newval, INSN_SIZE);
12261 break;
12262
12263 case BFD_RELOC_ARM_LITERAL:
12264 sign = value >= 0;
12265
12266 if (value < 0)
12267 value = - value;
12268
12269 if (validate_offset_imm (value, 0) == FAIL)
12270 {
12271 as_bad_where (fixP->fx_file, fixP->fx_line,
12272 _("invalid literal constant: pool needs to be closer"));
12273 break;
12274 }
12275
12276 newval = md_chars_to_number (buf, INSN_SIZE);
12277 newval &= 0xff7ff000;
12278 newval |= value | (sign ? INDEX_UP : 0);
12279 md_number_to_chars (buf, newval, INSN_SIZE);
12280 break;
12281
12282 case BFD_RELOC_ARM_SHIFT_IMM:
12283 newval = md_chars_to_number (buf, INSN_SIZE);
12284 if (((unsigned long) value) > 32
12285 || (value == 32
12286 && (((newval & 0x60) == 0) || (newval & 0x60) == 0x60)))
12287 {
12288 as_bad_where (fixP->fx_file, fixP->fx_line,
12289 _("shift expression is too large"));
12290 break;
12291 }
12292
12293 if (value == 0)
12294 /* Shifts of zero must be done as lsl. */
12295 newval &= ~0x60;
12296 else if (value == 32)
12297 value = 0;
12298 newval &= 0xfffff07f;
12299 newval |= (value & 0x1f) << 7;
12300 md_number_to_chars (buf, newval, INSN_SIZE);
12301 break;
12302
12303 case BFD_RELOC_ARM_SWI:
12304 if (arm_data->thumb_mode)
12305 {
12306 if (((unsigned long) value) > 0xff)
12307 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12308 _("invalid swi expression"));
b99bd4ef
NC
12309 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xff00;
12310 newval |= value;
12311 md_number_to_chars (buf, newval, THUMB_SIZE);
12312 }
12313 else
12314 {
12315 if (((unsigned long) value) > 0x00ffffff)
12316 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12317 _("invalid swi expression"));
b99bd4ef
NC
12318 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff000000;
12319 newval |= value;
12320 md_number_to_chars (buf, newval, INSN_SIZE);
12321 }
12322 break;
12323
12324 case BFD_RELOC_ARM_MULTI:
12325 if (((unsigned long) value) > 0xffff)
12326 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12327 _("invalid expression in load/store multiple"));
b99bd4ef
NC
12328 newval = value | md_chars_to_number (buf, INSN_SIZE);
12329 md_number_to_chars (buf, newval, INSN_SIZE);
12330 break;
12331
12332 case BFD_RELOC_ARM_PCREL_BRANCH:
12333 newval = md_chars_to_number (buf, INSN_SIZE);
12334
12335 /* Sign-extend a 24-bit number. */
12336#define SEXT24(x) ((((x) & 0xffffff) ^ (~ 0x7fffff)) + 0x800000)
12337
12338#ifdef OBJ_ELF
12339 if (! target_oabi)
12340 value = fixP->fx_offset;
12341#endif
12342
12343 /* We are going to store value (shifted right by two) in the
12344 instruction, in a 24 bit, signed field. Thus we need to check
12345 that none of the top 8 bits of the shifted value (top 7 bits of
12346 the unshifted, unsigned value) are set, or that they are all set. */
12347 if ((value & ~ ((offsetT) 0x1ffffff)) != 0
12348 && ((value & ~ ((offsetT) 0x1ffffff)) != ~ ((offsetT) 0x1ffffff)))
12349 {
12350#ifdef OBJ_ELF
12351 /* Normally we would be stuck at this point, since we cannot store
12352 the absolute address that is the destination of the branch in the
12353 24 bits of the branch instruction. If however, we happen to know
12354 that the destination of the branch is in the same section as the
2d2255b5 12355 branch instruction itself, then we can compute the relocation for
b99bd4ef
NC
12356 ourselves and not have to bother the linker with it.
12357
12358 FIXME: The tests for OBJ_ELF and ! target_oabi are only here
12359 because I have not worked out how to do this for OBJ_COFF or
12360 target_oabi. */
12361 if (! target_oabi
12362 && fixP->fx_addsy != NULL
12363 && S_IS_DEFINED (fixP->fx_addsy)
12364 && S_GET_SEGMENT (fixP->fx_addsy) == seg)
12365 {
12366 /* Get pc relative value to go into the branch. */
94f592af 12367 value = * valP;
b99bd4ef
NC
12368
12369 /* Permit a backward branch provided that enough bits
12370 are set. Allow a forwards branch, provided that
12371 enough bits are clear. */
12372 if ( (value & ~ ((offsetT) 0x1ffffff)) == ~ ((offsetT) 0x1ffffff)
12373 || (value & ~ ((offsetT) 0x1ffffff)) == 0)
12374 fixP->fx_done = 1;
12375 }
12376
12377 if (! fixP->fx_done)
12378#endif
12379 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12380 _("GAS can't handle same-section branch dest >= 0x04000000"));
b99bd4ef
NC
12381 }
12382
12383 value >>= 2;
12384 value += SEXT24 (newval);
12385
12386 if ( (value & ~ ((offsetT) 0xffffff)) != 0
12387 && ((value & ~ ((offsetT) 0xffffff)) != ~ ((offsetT) 0xffffff)))
12388 as_bad_where (fixP->fx_file, fixP->fx_line,
12389 _("out of range branch"));
12390
12391 newval = (value & 0x00ffffff) | (newval & 0xff000000);
12392 md_number_to_chars (buf, newval, INSN_SIZE);
12393 break;
12394
12395 case BFD_RELOC_ARM_PCREL_BLX:
12396 {
12397 offsetT hbit;
12398 newval = md_chars_to_number (buf, INSN_SIZE);
12399
12400#ifdef OBJ_ELF
12401 if (! target_oabi)
12402 value = fixP->fx_offset;
12403#endif
12404 hbit = (value >> 1) & 1;
12405 value = (value >> 2) & 0x00ffffff;
12406 value = (value + (newval & 0x00ffffff)) & 0x00ffffff;
12407 newval = value | (newval & 0xfe000000) | (hbit << 24);
12408 md_number_to_chars (buf, newval, INSN_SIZE);
12409 }
12410 break;
12411
12412 case BFD_RELOC_THUMB_PCREL_BRANCH9: /* Conditional branch. */
12413 newval = md_chars_to_number (buf, THUMB_SIZE);
12414 {
12415 addressT diff = (newval & 0xff) << 1;
12416 if (diff & 0x100)
12417 diff |= ~0xff;
12418
12419 value += diff;
12420 if ((value & ~0xff) && ((value & ~0xff) != ~0xff))
12421 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12422 _("branch out of range"));
b99bd4ef
NC
12423 newval = (newval & 0xff00) | ((value & 0x1ff) >> 1);
12424 }
12425 md_number_to_chars (buf, newval, THUMB_SIZE);
12426 break;
12427
12428 case BFD_RELOC_THUMB_PCREL_BRANCH12: /* Unconditional branch. */
12429 newval = md_chars_to_number (buf, THUMB_SIZE);
12430 {
12431 addressT diff = (newval & 0x7ff) << 1;
12432 if (diff & 0x800)
12433 diff |= ~0x7ff;
12434
12435 value += diff;
12436 if ((value & ~0x7ff) && ((value & ~0x7ff) != ~0x7ff))
12437 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12438 _("branch out of range"));
b99bd4ef
NC
12439 newval = (newval & 0xf800) | ((value & 0xfff) >> 1);
12440 }
12441 md_number_to_chars (buf, newval, THUMB_SIZE);
12442 break;
12443
12444 case BFD_RELOC_THUMB_PCREL_BLX:
12445 case BFD_RELOC_THUMB_PCREL_BRANCH23:
12446 {
12447 offsetT newval2;
12448 addressT diff;
12449
12450 newval = md_chars_to_number (buf, THUMB_SIZE);
12451 newval2 = md_chars_to_number (buf + THUMB_SIZE, THUMB_SIZE);
12452 diff = ((newval & 0x7ff) << 12) | ((newval2 & 0x7ff) << 1);
12453 if (diff & 0x400000)
12454 diff |= ~0x3fffff;
12455#ifdef OBJ_ELF
12456 value = fixP->fx_offset;
12457#endif
12458 value += diff;
c62e1cc3 12459
b99bd4ef
NC
12460 if ((value & ~0x3fffff) && ((value & ~0x3fffff) != ~0x3fffff))
12461 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12462 _("branch with link out of range"));
b99bd4ef
NC
12463
12464 newval = (newval & 0xf800) | ((value & 0x7fffff) >> 12);
12465 newval2 = (newval2 & 0xf800) | ((value & 0xfff) >> 1);
12466 if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX)
c62e1cc3
NC
12467 /* For a BLX instruction, make sure that the relocation is rounded up
12468 to a word boundary. This follows the semantics of the instruction
12469 which specifies that bit 1 of the target address will come from bit
12470 1 of the base address. */
12471 newval2 = (newval2 + 1) & ~ 1;
b99bd4ef
NC
12472 md_number_to_chars (buf, newval, THUMB_SIZE);
12473 md_number_to_chars (buf + THUMB_SIZE, newval2, THUMB_SIZE);
12474 }
12475 break;
12476
12477 case BFD_RELOC_8:
12478 if (fixP->fx_done || fixP->fx_pcrel)
12479 md_number_to_chars (buf, value, 1);
12480#ifdef OBJ_ELF
12481 else if (!target_oabi)
12482 {
12483 value = fixP->fx_offset;
12484 md_number_to_chars (buf, value, 1);
12485 }
12486#endif
12487 break;
12488
12489 case BFD_RELOC_16:
12490 if (fixP->fx_done || fixP->fx_pcrel)
12491 md_number_to_chars (buf, value, 2);
12492#ifdef OBJ_ELF
12493 else if (!target_oabi)
12494 {
12495 value = fixP->fx_offset;
12496 md_number_to_chars (buf, value, 2);
12497 }
12498#endif
12499 break;
12500
12501#ifdef OBJ_ELF
12502 case BFD_RELOC_ARM_GOT32:
12503 case BFD_RELOC_ARM_GOTOFF:
eb043451 12504 case BFD_RELOC_ARM_TARGET2:
b99bd4ef
NC
12505 md_number_to_chars (buf, 0, 4);
12506 break;
12507#endif
12508
12509 case BFD_RELOC_RVA:
12510 case BFD_RELOC_32:
9c504268 12511 case BFD_RELOC_ARM_TARGET1:
db6579d4
PB
12512 case BFD_RELOC_ARM_ROSEGREL32:
12513 case BFD_RELOC_ARM_SBREL32:
eb043451 12514 case BFD_RELOC_32_PCREL:
b99bd4ef
NC
12515 if (fixP->fx_done || fixP->fx_pcrel)
12516 md_number_to_chars (buf, value, 4);
12517#ifdef OBJ_ELF
12518 else if (!target_oabi)
12519 {
12520 value = fixP->fx_offset;
12521 md_number_to_chars (buf, value, 4);
12522 }
12523#endif
12524 break;
12525
12526#ifdef OBJ_ELF
eb043451
PB
12527 case BFD_RELOC_ARM_PREL31:
12528 if (fixP->fx_done || fixP->fx_pcrel)
12529 {
12530 newval = md_chars_to_number (buf, 4) & 0x80000000;
12531 if ((value ^ (value >> 1)) & 0x40000000)
12532 {
12533 as_bad_where (fixP->fx_file, fixP->fx_line,
12534 _("rel31 relocation overflow"));
12535 }
12536 newval |= value & 0x7fffffff;
12537 md_number_to_chars (buf, newval, 4);
12538 }
12539 break;
12540
b99bd4ef
NC
12541 case BFD_RELOC_ARM_PLT32:
12542 /* It appears the instruction is fully prepared at this point. */
12543 break;
12544#endif
12545
b99bd4ef
NC
12546 case BFD_RELOC_ARM_CP_OFF_IMM:
12547 sign = value >= 0;
12548 if (value < -1023 || value > 1023 || (value & 3))
12549 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12550 _("illegal value for co-processor offset"));
b99bd4ef
NC
12551 if (value < 0)
12552 value = -value;
12553 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
12554 newval |= (value >> 2) | (sign ? INDEX_UP : 0);
12555 md_number_to_chars (buf, newval, INSN_SIZE);
12556 break;
12557
e16bb312
NC
12558 case BFD_RELOC_ARM_CP_OFF_IMM_S2:
12559 sign = value >= 0;
12560 if (value < -255 || value > 255)
12561 as_bad_where (fixP->fx_file, fixP->fx_line,
12562 _("Illegal value for co-processor offset"));
12563 if (value < 0)
12564 value = -value;
12565 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
12566 newval |= value | (sign ? INDEX_UP : 0);
12567 md_number_to_chars (buf, newval , INSN_SIZE);
12568 break;
12569
b99bd4ef
NC
12570 case BFD_RELOC_ARM_THUMB_OFFSET:
12571 newval = md_chars_to_number (buf, THUMB_SIZE);
12572 /* Exactly what ranges, and where the offset is inserted depends
12573 on the type of instruction, we can establish this from the
12574 top 4 bits. */
12575 switch (newval >> 12)
12576 {
12577 case 4: /* PC load. */
12578 /* Thumb PC loads are somewhat odd, bit 1 of the PC is
12579 forced to zero for these loads, so we will need to round
12580 up the offset if the instruction address is not word
12581 aligned (since the final address produced must be, and
12582 we can only describe word-aligned immediate offsets). */
12583
12584 if ((fixP->fx_frag->fr_address + fixP->fx_where + value) & 3)
12585 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12586 _("invalid offset, target not word aligned (0x%08X)"),
b99bd4ef
NC
12587 (unsigned int) (fixP->fx_frag->fr_address
12588 + fixP->fx_where + value));
12589
12590 if ((value + 2) & ~0x3fe)
12591 as_bad_where (fixP->fx_file, fixP->fx_line,
08df2379
NC
12592 _("invalid offset, value too big (0x%08lX)"),
12593 (long) value);
b99bd4ef
NC
12594
12595 /* Round up, since pc will be rounded down. */
12596 newval |= (value + 2) >> 2;
12597 break;
12598
12599 case 9: /* SP load/store. */
12600 if (value & ~0x3fc)
12601 as_bad_where (fixP->fx_file, fixP->fx_line,
08df2379
NC
12602 _("invalid offset, value too big (0x%08lX)"),
12603 (long) value);
b99bd4ef
NC
12604 newval |= value >> 2;
12605 break;
12606
12607 case 6: /* Word load/store. */
12608 if (value & ~0x7c)
12609 as_bad_where (fixP->fx_file, fixP->fx_line,
08df2379
NC
12610 _("invalid offset, value too big (0x%08lX)"),
12611 (long) value);
b99bd4ef
NC
12612 newval |= value << 4; /* 6 - 2. */
12613 break;
12614
12615 case 7: /* Byte load/store. */
12616 if (value & ~0x1f)
12617 as_bad_where (fixP->fx_file, fixP->fx_line,
08df2379
NC
12618 _("invalid offset, value too big (0x%08lX)"),
12619 (long) value);
b99bd4ef
NC
12620 newval |= value << 6;
12621 break;
12622
12623 case 8: /* Halfword load/store. */
12624 if (value & ~0x3e)
12625 as_bad_where (fixP->fx_file, fixP->fx_line,
08df2379
NC
12626 _("invalid offset, value too big (0x%08lX)"),
12627 (long) value);
b99bd4ef
NC
12628 newval |= value << 5; /* 6 - 1. */
12629 break;
12630
12631 default:
12632 as_bad_where (fixP->fx_file, fixP->fx_line,
12633 "Unable to process relocation for thumb opcode: %lx",
12634 (unsigned long) newval);
12635 break;
12636 }
12637 md_number_to_chars (buf, newval, THUMB_SIZE);
12638 break;
12639
12640 case BFD_RELOC_ARM_THUMB_ADD:
12641 /* This is a complicated relocation, since we use it for all of
12642 the following immediate relocations:
12643
12644 3bit ADD/SUB
12645 8bit ADD/SUB
12646 9bit ADD/SUB SP word-aligned
12647 10bit ADD PC/SP word-aligned
12648
12649 The type of instruction being processed is encoded in the
12650 instruction field:
12651
12652 0x8000 SUB
12653 0x00F0 Rd
12654 0x000F Rs
12655 */
12656 newval = md_chars_to_number (buf, THUMB_SIZE);
12657 {
12658 int rd = (newval >> 4) & 0xf;
12659 int rs = newval & 0xf;
12660 int subtract = newval & 0x8000;
12661
12662 if (rd == REG_SP)
12663 {
12664 if (value & ~0x1fc)
12665 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12666 _("invalid immediate for stack address calculation"));
b99bd4ef
NC
12667 newval = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
12668 newval |= value >> 2;
12669 }
12670 else if (rs == REG_PC || rs == REG_SP)
12671 {
12672 if (subtract ||
12673 value & ~0x3fc)
12674 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12675 _("invalid immediate for address calculation (value = 0x%08lX)"),
b99bd4ef
NC
12676 (unsigned long) value);
12677 newval = (rs == REG_PC ? T_OPCODE_ADD_PC : T_OPCODE_ADD_SP);
12678 newval |= rd << 8;
12679 newval |= value >> 2;
12680 }
12681 else if (rs == rd)
12682 {
12683 if (value & ~0xff)
12684 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12685 _("invalid 8bit immediate"));
b99bd4ef
NC
12686 newval = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
12687 newval |= (rd << 8) | value;
12688 }
12689 else
12690 {
12691 if (value & ~0x7)
12692 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12693 _("invalid 3bit immediate"));
b99bd4ef
NC
12694 newval = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
12695 newval |= rd | (rs << 3) | (value << 6);
12696 }
12697 }
12698 md_number_to_chars (buf, newval, THUMB_SIZE);
12699 break;
12700
12701 case BFD_RELOC_ARM_THUMB_IMM:
12702 newval = md_chars_to_number (buf, THUMB_SIZE);
12703 switch (newval >> 11)
12704 {
12705 case 0x04: /* 8bit immediate MOV. */
12706 case 0x05: /* 8bit immediate CMP. */
12707 if (value < 0 || value > 255)
12708 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12709 _("invalid immediate: %ld is too large"),
b99bd4ef
NC
12710 (long) value);
12711 newval |= value;
12712 break;
12713
12714 default:
12715 abort ();
12716 }
12717 md_number_to_chars (buf, newval, THUMB_SIZE);
12718 break;
12719
12720 case BFD_RELOC_ARM_THUMB_SHIFT:
12721 /* 5bit shift value (0..31). */
12722 if (value < 0 || value > 31)
12723 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12724 _("illegal Thumb shift value: %ld"), (long) value);
b99bd4ef
NC
12725 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xf03f;
12726 newval |= value << 6;
12727 md_number_to_chars (buf, newval, THUMB_SIZE);
12728 break;
12729
12730 case BFD_RELOC_VTABLE_INHERIT:
12731 case BFD_RELOC_VTABLE_ENTRY:
12732 fixP->fx_done = 0;
94f592af 12733 return;
b99bd4ef
NC
12734
12735 case BFD_RELOC_NONE:
12736 default:
12737 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12738 _("bad relocation fixup type (%d)"), fixP->fx_r_type);
b99bd4ef 12739 }
b99bd4ef
NC
12740}
12741
12742/* Translate internal representation of relocation info to BFD target
12743 format. */
12744
12745arelent *
12746tc_gen_reloc (section, fixp)
12747 asection * section ATTRIBUTE_UNUSED;
12748 fixS * fixp;
12749{
12750 arelent * reloc;
12751 bfd_reloc_code_real_type code;
12752
12753 reloc = (arelent *) xmalloc (sizeof (arelent));
12754
12755 reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
12756 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
12757 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
12758
12759 /* @@ Why fx_addnumber sometimes and fx_offset other times? */
12760#ifndef OBJ_ELF
12761 if (fixp->fx_pcrel == 0)
12762 reloc->addend = fixp->fx_offset;
12763 else
12764 reloc->addend = fixp->fx_offset = reloc->address;
12765#else /* OBJ_ELF */
12766 reloc->addend = fixp->fx_offset;
12767#endif
12768
12769 switch (fixp->fx_r_type)
12770 {
12771 case BFD_RELOC_8:
12772 if (fixp->fx_pcrel)
12773 {
12774 code = BFD_RELOC_8_PCREL;
12775 break;
12776 }
12777
12778 case BFD_RELOC_16:
12779 if (fixp->fx_pcrel)
12780 {
12781 code = BFD_RELOC_16_PCREL;
12782 break;
12783 }
12784
12785 case BFD_RELOC_32:
12786 if (fixp->fx_pcrel)
12787 {
12788 code = BFD_RELOC_32_PCREL;
12789 break;
12790 }
12791
12792 case BFD_RELOC_ARM_PCREL_BRANCH:
12793 case BFD_RELOC_ARM_PCREL_BLX:
12794 case BFD_RELOC_RVA:
12795 case BFD_RELOC_THUMB_PCREL_BRANCH9:
12796 case BFD_RELOC_THUMB_PCREL_BRANCH12:
12797 case BFD_RELOC_THUMB_PCREL_BRANCH23:
12798 case BFD_RELOC_THUMB_PCREL_BLX:
12799 case BFD_RELOC_VTABLE_ENTRY:
12800 case BFD_RELOC_VTABLE_INHERIT:
12801 code = fixp->fx_r_type;
12802 break;
12803
12804 case BFD_RELOC_ARM_LITERAL:
12805 case BFD_RELOC_ARM_HWLITERAL:
3d0c9500
NC
12806 /* If this is called then the a literal has
12807 been referenced across a section boundary. */
b99bd4ef 12808 as_bad_where (fixp->fx_file, fixp->fx_line,
61b5f74b 12809 _("literal referenced across section boundary"));
b99bd4ef
NC
12810 return NULL;
12811
12812#ifdef OBJ_ELF
12813 case BFD_RELOC_ARM_GOT32:
12814 case BFD_RELOC_ARM_GOTOFF:
12815 case BFD_RELOC_ARM_PLT32:
9c504268 12816 case BFD_RELOC_ARM_TARGET1:
db6579d4
PB
12817 case BFD_RELOC_ARM_ROSEGREL32:
12818 case BFD_RELOC_ARM_SBREL32:
eb043451
PB
12819 case BFD_RELOC_ARM_PREL31:
12820 case BFD_RELOC_ARM_TARGET2:
b99bd4ef
NC
12821 code = fixp->fx_r_type;
12822 break;
12823#endif
12824
12825 case BFD_RELOC_ARM_IMMEDIATE:
12826 as_bad_where (fixp->fx_file, fixp->fx_line,
6189168b 12827 _("internal relocation (type: IMMEDIATE) not fixed up"));
b99bd4ef
NC
12828 return NULL;
12829
12830 case BFD_RELOC_ARM_ADRL_IMMEDIATE:
12831 as_bad_where (fixp->fx_file, fixp->fx_line,
12832 _("ADRL used for a symbol not defined in the same file"));
12833 return NULL;
12834
12835 case BFD_RELOC_ARM_OFFSET_IMM:
c3ba240c
DJ
12836 if (fixp->fx_addsy != NULL
12837 && !S_IS_DEFINED (fixp->fx_addsy)
12838 && S_IS_LOCAL (fixp->fx_addsy))
12839 {
12840 as_bad_where (fixp->fx_file, fixp->fx_line,
12841 _("undefined local label `%s'"),
12842 S_GET_NAME (fixp->fx_addsy));
12843 return NULL;
12844 }
12845
b99bd4ef 12846 as_bad_where (fixp->fx_file, fixp->fx_line,
6189168b 12847 _("internal_relocation (type: OFFSET_IMM) not fixed up"));
b99bd4ef
NC
12848 return NULL;
12849
12850 default:
12851 {
12852 char * type;
12853
12854 switch (fixp->fx_r_type)
12855 {
b99bd4ef
NC
12856 case BFD_RELOC_ARM_OFFSET_IMM8: type = "OFFSET_IMM8"; break;
12857 case BFD_RELOC_ARM_SHIFT_IMM: type = "SHIFT_IMM"; break;
12858 case BFD_RELOC_ARM_SWI: type = "SWI"; break;
12859 case BFD_RELOC_ARM_MULTI: type = "MULTI"; break;
12860 case BFD_RELOC_ARM_CP_OFF_IMM: type = "CP_OFF_IMM"; break;
12861 case BFD_RELOC_ARM_THUMB_ADD: type = "THUMB_ADD"; break;
12862 case BFD_RELOC_ARM_THUMB_SHIFT: type = "THUMB_SHIFT"; break;
12863 case BFD_RELOC_ARM_THUMB_IMM: type = "THUMB_IMM"; break;
12864 case BFD_RELOC_ARM_THUMB_OFFSET: type = "THUMB_OFFSET"; break;
12865 default: type = _("<unknown>"); break;
12866 }
12867 as_bad_where (fixp->fx_file, fixp->fx_line,
f03698e6 12868 _("cannot represent %s relocation in this object file format"),
b99bd4ef
NC
12869 type);
12870 return NULL;
12871 }
12872 }
12873
12874#ifdef OBJ_ELF
8df7094c 12875 if ((code == BFD_RELOC_32_PCREL || code == BFD_RELOC_32)
b99bd4ef
NC
12876 && GOT_symbol
12877 && fixp->fx_addsy == GOT_symbol)
12878 {
12879 code = BFD_RELOC_ARM_GOTPC;
12880 reloc->addend = fixp->fx_offset = reloc->address;
12881 }
12882#endif
12883
12884 reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
12885
12886 if (reloc->howto == NULL)
12887 {
12888 as_bad_where (fixp->fx_file, fixp->fx_line,
f03698e6 12889 _("cannot represent %s relocation in this object file format"),
b99bd4ef
NC
12890 bfd_get_reloc_code_name (code));
12891 return NULL;
12892 }
12893
12894 /* HACK: Since arm ELF uses Rel instead of Rela, encode the
12895 vtable entry to be used in the relocation's section offset. */
12896 if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
12897 reloc->address = fixp->fx_offset;
12898
12899 return reloc;
12900}
12901
12902int
12903md_estimate_size_before_relax (fragP, segtype)
12904 fragS * fragP ATTRIBUTE_UNUSED;
12905 segT segtype ATTRIBUTE_UNUSED;
12906{
12907 as_fatal (_("md_estimate_size_before_relax\n"));
12908 return 1;
12909}
12910
12911static void
f03698e6
RE
12912output_inst (str)
12913 const char *str;
b99bd4ef
NC
12914{
12915 char * to = NULL;
12916
12917 if (inst.error)
12918 {
f03698e6 12919 as_bad ("%s -- `%s'", inst.error, str);
b99bd4ef
NC
12920 return;
12921 }
12922
12923 to = frag_more (inst.size);
12924
12925 if (thumb_mode && (inst.size > THUMB_SIZE))
12926 {
12927 assert (inst.size == (2 * THUMB_SIZE));
12928 md_number_to_chars (to, inst.instruction >> 16, THUMB_SIZE);
12929 md_number_to_chars (to + THUMB_SIZE, inst.instruction, THUMB_SIZE);
12930 }
12931 else if (inst.size > INSN_SIZE)
12932 {
12933 assert (inst.size == (2 * INSN_SIZE));
12934 md_number_to_chars (to, inst.instruction, INSN_SIZE);
12935 md_number_to_chars (to + INSN_SIZE, inst.instruction, INSN_SIZE);
12936 }
12937 else
12938 md_number_to_chars (to, inst.instruction, inst.size);
12939
12940 if (inst.reloc.type != BFD_RELOC_NONE)
12941 fix_new_arm (frag_now, to - frag_now->fr_literal,
12942 inst.size, & inst.reloc.exp, inst.reloc.pc_rel,
12943 inst.reloc.type);
12944
12945#ifdef OBJ_ELF
12946 dwarf2_emit_insn (inst.size);
12947#endif
12948}
12949
12950void
12951md_assemble (str)
12952 char * str;
12953{
6c43fab6
RE
12954 char c;
12955 char *p;
12956 char *start;
b99bd4ef
NC
12957
12958 /* Align the instruction.
12959 This may not be the right thing to do but ... */
12960#if 0
12961 arm_align (2, 0);
12962#endif
b99bd4ef
NC
12963
12964 /* Align the previous label if needed. */
12965 if (last_label_seen != NULL)
12966 {
12967 symbol_set_frag (last_label_seen, frag_now);
12968 S_SET_VALUE (last_label_seen, (valueT) frag_now_fix ());
12969 S_SET_SEGMENT (last_label_seen, now_seg);
12970 }
12971
12972 memset (&inst, '\0', sizeof (inst));
12973 inst.reloc.type = BFD_RELOC_NONE;
12974
12975 skip_whitespace (str);
12976
12977 /* Scan up to the end of the op-code, which must end in white space or
12978 end of string. */
12979 for (start = p = str; *p != '\0'; p++)
12980 if (*p == ' ')
12981 break;
12982
12983 if (p == str)
12984 {
f03698e6 12985 as_bad (_("no operator -- statement `%s'\n"), str);
b99bd4ef
NC
12986 return;
12987 }
12988
12989 if (thumb_mode)
12990 {
05d2d07e 12991 const struct thumb_opcode * opcode;
b99bd4ef
NC
12992
12993 c = *p;
12994 *p = '\0';
05d2d07e 12995 opcode = (const struct thumb_opcode *) hash_find (arm_tops_hsh, str);
b99bd4ef
NC
12996 *p = c;
12997
12998 if (opcode)
12999 {
13000 /* Check that this instruction is supported for this CPU. */
90e4755a 13001 if (thumb_mode == 1 && (opcode->variant & cpu_variant) == 0)
b99bd4ef 13002 {
f03698e6 13003 as_bad (_("selected processor does not support `%s'"), str);
b99bd4ef
NC
13004 return;
13005 }
13006
6057a28f 13007 mapping_state (MAP_THUMB);
b99bd4ef
NC
13008 inst.instruction = opcode->value;
13009 inst.size = opcode->size;
13010 (*opcode->parms) (p);
f03698e6 13011 output_inst (str);
b99bd4ef
NC
13012 return;
13013 }
13014 }
13015 else
13016 {
05d2d07e 13017 const struct asm_opcode * opcode;
b99bd4ef 13018
90e4755a
RE
13019 c = *p;
13020 *p = '\0';
6c43fab6 13021 opcode = (const struct asm_opcode *) hash_find (arm_ops_hsh, str);
90e4755a 13022 *p = c;
b99bd4ef 13023
90e4755a 13024 if (opcode)
b99bd4ef 13025 {
90e4755a
RE
13026 /* Check that this instruction is supported for this CPU. */
13027 if ((opcode->variant & cpu_variant) == 0)
b99bd4ef 13028 {
f03698e6 13029 as_bad (_("selected processor does not support `%s'"), str);
b99bd4ef
NC
13030 return;
13031 }
13032
6057a28f 13033 mapping_state (MAP_ARM);
90e4755a
RE
13034 inst.instruction = opcode->value;
13035 inst.size = INSN_SIZE;
f2b7cb0a 13036 (*opcode->parms) (p);
f03698e6 13037 output_inst (str);
90e4755a 13038 return;
b99bd4ef
NC
13039 }
13040 }
13041
13042 /* It wasn't an instruction, but it might be a register alias of the form
13043 alias .req reg. */
6c43fab6
RE
13044 if (create_register_alias (str, p))
13045 return;
b99bd4ef 13046
b99bd4ef
NC
13047 as_bad (_("bad instruction `%s'"), start);
13048}
13049
13050/* md_parse_option
13051 Invocation line includes a switch not recognized by the base assembler.
cc8a6dd0 13052 See if it's a processor-specific option.
03b1477f
RE
13053
13054 This routine is somewhat complicated by the need for backwards
13055 compatibility (since older releases of gcc can't be changed).
13056 The new options try to make the interface as compatible as
13057 possible with GCC.
13058
13059 New options (supported) are:
13060
13061 -mcpu=<cpu name> Assemble for selected processor
13062 -march=<architecture name> Assemble for selected architecture
13063 -mfpu=<fpu architecture> Assemble for selected FPU.
13064 -EB/-mbig-endian Big-endian
13065 -EL/-mlittle-endian Little-endian
13066 -k Generate PIC code
13067 -mthumb Start in Thumb mode
13068 -mthumb-interwork Code supports ARM/Thumb interworking
13069
3d0c9500 13070 For now we will also provide support for:
03b1477f
RE
13071
13072 -mapcs-32 32-bit Program counter
13073 -mapcs-26 26-bit Program counter
13074 -macps-float Floats passed in FP registers
13075 -mapcs-reentrant Reentrant code
13076 -matpcs
13077 (sometime these will probably be replaced with -mapcs=<list of options>
13078 and -matpcs=<list of options>)
13079
13080 The remaining options are only supported for back-wards compatibility.
b99bd4ef
NC
13081 Cpu variants, the arm part is optional:
13082 -m[arm]1 Currently not supported.
13083 -m[arm]2, -m[arm]250 Arm 2 and Arm 250 processor
13084 -m[arm]3 Arm 3 processor
13085 -m[arm]6[xx], Arm 6 processors
13086 -m[arm]7[xx][t][[d]m] Arm 7 processors
13087 -m[arm]8[10] Arm 8 processors
13088 -m[arm]9[20][tdmi] Arm 9 processors
13089 -mstrongarm[110[0]] StrongARM processors
13090 -mxscale XScale processors
13091 -m[arm]v[2345[t[e]]] Arm architectures
13092 -mall All (except the ARM1)
13093 FP variants:
13094 -mfpa10, -mfpa11 FPA10 and 11 co-processor instructions
13095 -mfpe-old (No float load/store multiples)
bfae80f2
RE
13096 -mvfpxd VFP Single precision
13097 -mvfp All VFP
b99bd4ef 13098 -mno-fpu Disable all floating point instructions
b99bd4ef 13099
03b1477f
RE
13100 The following CPU names are recognized:
13101 arm1, arm2, arm250, arm3, arm6, arm600, arm610, arm620,
13102 arm7, arm7m, arm7d, arm7dm, arm7di, arm7dmi, arm70, arm700,
13103 arm700i, arm710 arm710t, arm720, arm720t, arm740t, arm710c,
13104 arm7100, arm7500, arm7500fe, arm7tdmi, arm8, arm810, arm9,
13105 arm920, arm920t, arm940t, arm946, arm966, arm9tdmi, arm9e,
13106 arm10t arm10e, arm1020t, arm1020e, arm10200e,
13107 strongarm, strongarm110, strongarm1100, strongarm1110, xscale.
13108
13109 */
13110
5a38dc70 13111const char * md_shortopts = "m:k";
03b1477f 13112
b99bd4ef
NC
13113#ifdef ARM_BI_ENDIAN
13114#define OPTION_EB (OPTION_MD_BASE + 0)
b99bd4ef 13115#define OPTION_EL (OPTION_MD_BASE + 1)
21f0f23a 13116#else
21f0f23a
RE
13117#if TARGET_BYTES_BIG_ENDIAN
13118#define OPTION_EB (OPTION_MD_BASE + 0)
21f0f23a
RE
13119#else
13120#define OPTION_EL (OPTION_MD_BASE + 1)
21f0f23a 13121#endif
ce058b6c 13122#endif
03b1477f
RE
13123
13124struct option md_longopts[] =
13125{
13126#ifdef OPTION_EB
13127 {"EB", no_argument, NULL, OPTION_EB},
13128#endif
13129#ifdef OPTION_EL
13130 {"EL", no_argument, NULL, OPTION_EL},
b99bd4ef
NC
13131#endif
13132 {NULL, no_argument, NULL, 0}
13133};
13134
13135size_t md_longopts_size = sizeof (md_longopts);
13136
03b1477f 13137struct arm_option_table
b99bd4ef 13138{
03b1477f
RE
13139 char *option; /* Option name to match. */
13140 char *help; /* Help information. */
13141 int *var; /* Variable to change. */
13142 int value; /* What to change it to. */
13143 char *deprecated; /* If non-null, print this message. */
13144};
b99bd4ef 13145
cc8a6dd0 13146struct arm_option_table arm_opts[] =
03b1477f
RE
13147{
13148 {"k", N_("generate PIC code"), &pic_code, 1, NULL},
13149 {"mthumb", N_("assemble Thumb code"), &thumb_mode, 1, NULL},
13150 {"mthumb-interwork", N_("support ARM/Thumb interworking"),
13151 &support_interwork, 1, NULL},
13152 {"moabi", N_("use old ABI (ELF only)"), &target_oabi, 1, NULL},
13153 {"mapcs-32", N_("code uses 32-bit program counter"), &uses_apcs_26, 0, NULL},
13154 {"mapcs-26", N_("code uses 26-bit program counter"), &uses_apcs_26, 1, NULL},
13155 {"mapcs-float", N_("floating point args are in fp regs"), &uses_apcs_float,
13156 1, NULL},
13157 {"mapcs-reentrant", N_("re-entrant code"), &pic_code, 1, NULL},
13158 {"matpcs", N_("code is ATPCS conformant"), &atpcs, 1, NULL},
13159 {"mbig-endian", N_("assemble for big-endian"), &target_big_endian, 1, NULL},
13160 {"mlittle-endian", N_("assemble for little-endian"), &target_big_endian, 1,
13161 NULL},
13162
13163 /* These are recognized by the assembler, but have no affect on code. */
13164 {"mapcs-frame", N_("use frame pointer"), NULL, 0, NULL},
13165 {"mapcs-stack-check", N_("use stack size checking"), NULL, 0, NULL},
13166
13167 /* DON'T add any new processors to this list -- we want the whole list
13168 to go away... Add them to the processors table instead. */
13169 {"marm1", NULL, &legacy_cpu, ARM_ARCH_V1, N_("use -mcpu=arm1")},
13170 {"m1", NULL, &legacy_cpu, ARM_ARCH_V1, N_("use -mcpu=arm1")},
13171 {"marm2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -mcpu=arm2")},
13172 {"m2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -mcpu=arm2")},
13173 {"marm250", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm250")},
13174 {"m250", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm250")},
13175 {"marm3", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm3")},
13176 {"m3", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm3")},
13177 {"marm6", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm6")},
13178 {"m6", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm6")},
13179 {"marm600", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm600")},
13180 {"m600", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm600")},
13181 {"marm610", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm610")},
13182 {"m610", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm610")},
13183 {"marm620", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm620")},
13184 {"m620", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm620")},
13185 {"marm7", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7")},
13186 {"m7", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7")},
13187 {"marm70", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm70")},
13188 {"m70", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm70")},
13189 {"marm700", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700")},
13190 {"m700", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700")},
13191 {"marm700i", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700i")},
13192 {"m700i", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700i")},
13193 {"marm710", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710")},
13194 {"m710", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710")},
13195 {"marm710c", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710c")},
13196 {"m710c", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710c")},
13197 {"marm720", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm720")},
13198 {"m720", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm720")},
13199 {"marm7d", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7d")},
13200 {"m7d", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7d")},
13201 {"marm7di", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7di")},
13202 {"m7di", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7di")},
13203 {"marm7m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7m")},
13204 {"m7m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7m")},
13205 {"marm7dm", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dm")},
13206 {"m7dm", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dm")},
13207 {"marm7dmi", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dmi")},
13208 {"m7dmi", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dmi")},
13209 {"marm7100", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7100")},
13210 {"m7100", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7100")},
13211 {"marm7500", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500")},
13212 {"m7500", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500")},
13213 {"marm7500fe", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500fe")},
13214 {"m7500fe", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500fe")},
13215 {"marm7t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
13216 {"m7t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
13217 {"marm7tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
13218 {"m7tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
13219 {"marm710t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm710t")},
13220 {"m710t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm710t")},
13221 {"marm720t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm720t")},
13222 {"m720t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm720t")},
13223 {"marm740t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm740t")},
13224 {"m740t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm740t")},
13225 {"marm8", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm8")},
13226 {"m8", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm8")},
13227 {"marm810", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm810")},
13228 {"m810", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm810")},
13229 {"marm9", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9")},
13230 {"m9", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9")},
13231 {"marm9tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9tdmi")},
13232 {"m9tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9tdmi")},
13233 {"marm920", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm920")},
13234 {"m920", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm920")},
13235 {"marm940", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm940")},
13236 {"m940", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm940")},
13237 {"mstrongarm", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=strongarm")},
13238 {"mstrongarm110", NULL, &legacy_cpu, ARM_ARCH_V4,
13239 N_("use -mcpu=strongarm110")},
13240 {"mstrongarm1100", NULL, &legacy_cpu, ARM_ARCH_V4,
13241 N_("use -mcpu=strongarm1100")},
13242 {"mstrongarm1110", NULL, &legacy_cpu, ARM_ARCH_V4,
13243 N_("use -mcpu=strongarm1110")},
13244 {"mxscale", NULL, &legacy_cpu, ARM_ARCH_XSCALE, N_("use -mcpu=xscale")},
e16bb312 13245 {"miwmmxt", NULL, &legacy_cpu, ARM_ARCH_IWMMXT, N_("use -mcpu=iwmmxt")},
03b1477f
RE
13246 {"mall", NULL, &legacy_cpu, ARM_ANY, N_("use -mcpu=all")},
13247
13248 /* Architecture variants -- don't add any more to this list either. */
13249 {"mv2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -march=armv2")},
13250 {"marmv2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -march=armv2")},
13251 {"mv2a", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -march=armv2a")},
13252 {"marmv2a", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -march=armv2a")},
13253 {"mv3", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -march=armv3")},
13254 {"marmv3", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -march=armv3")},
13255 {"mv3m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -march=armv3m")},
13256 {"marmv3m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -march=armv3m")},
13257 {"mv4", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -march=armv4")},
13258 {"marmv4", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -march=armv4")},
13259 {"mv4t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -march=armv4t")},
13260 {"marmv4t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -march=armv4t")},
13261 {"mv5", NULL, &legacy_cpu, ARM_ARCH_V5, N_("use -march=armv5")},
13262 {"marmv5", NULL, &legacy_cpu, ARM_ARCH_V5, N_("use -march=armv5")},
13263 {"mv5t", NULL, &legacy_cpu, ARM_ARCH_V5T, N_("use -march=armv5t")},
13264 {"marmv5t", NULL, &legacy_cpu, ARM_ARCH_V5T, N_("use -march=armv5t")},
13265 {"mv5e", NULL, &legacy_cpu, ARM_ARCH_V5TE, N_("use -march=armv5te")},
13266 {"marmv5e", NULL, &legacy_cpu, ARM_ARCH_V5TE, N_("use -march=armv5te")},
13267
13268 /* Floating point variants -- don't add any more to this list either. */
13269 {"mfpe-old", NULL, &legacy_fpu, FPU_ARCH_FPE, N_("use -mfpu=fpe")},
13270 {"mfpa10", NULL, &legacy_fpu, FPU_ARCH_FPA, N_("use -mfpu=fpa10")},
13271 {"mfpa11", NULL, &legacy_fpu, FPU_ARCH_FPA, N_("use -mfpu=fpa11")},
13272 {"mno-fpu", NULL, &legacy_fpu, 0,
13273 N_("use either -mfpu=softfpa or -mfpu=softvfp")},
13274
13275 {NULL, NULL, NULL, 0, NULL}
13276};
21f0f23a 13277
03b1477f
RE
13278struct arm_cpu_option_table
13279{
13280 char *name;
13281 int value;
13282 /* For some CPUs we assume an FPU unless the user explicitly sets
13283 -mfpu=... */
13284 int default_fpu;
13285};
13286
13287/* This list should, at a minimum, contain all the cpu names
13288 recognized by GCC. */
13289static struct arm_cpu_option_table arm_cpus[] =
13290{
13291 {"all", ARM_ANY, FPU_ARCH_FPA},
13292 {"arm1", ARM_ARCH_V1, FPU_ARCH_FPA},
13293 {"arm2", ARM_ARCH_V2, FPU_ARCH_FPA},
13294 {"arm250", ARM_ARCH_V2S, FPU_ARCH_FPA},
13295 {"arm3", ARM_ARCH_V2S, FPU_ARCH_FPA},
13296 {"arm6", ARM_ARCH_V3, FPU_ARCH_FPA},
13297 {"arm60", ARM_ARCH_V3, FPU_ARCH_FPA},
13298 {"arm600", ARM_ARCH_V3, FPU_ARCH_FPA},
13299 {"arm610", ARM_ARCH_V3, FPU_ARCH_FPA},
13300 {"arm620", ARM_ARCH_V3, FPU_ARCH_FPA},
13301 {"arm7", ARM_ARCH_V3, FPU_ARCH_FPA},
13302 {"arm7m", ARM_ARCH_V3M, FPU_ARCH_FPA},
13303 {"arm7d", ARM_ARCH_V3, FPU_ARCH_FPA},
13304 {"arm7dm", ARM_ARCH_V3M, FPU_ARCH_FPA},
13305 {"arm7di", ARM_ARCH_V3, FPU_ARCH_FPA},
13306 {"arm7dmi", ARM_ARCH_V3M, FPU_ARCH_FPA},
13307 {"arm70", ARM_ARCH_V3, FPU_ARCH_FPA},
13308 {"arm700", ARM_ARCH_V3, FPU_ARCH_FPA},
13309 {"arm700i", ARM_ARCH_V3, FPU_ARCH_FPA},
13310 {"arm710", ARM_ARCH_V3, FPU_ARCH_FPA},
13311 {"arm710t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13312 {"arm720", ARM_ARCH_V3, FPU_ARCH_FPA},
13313 {"arm720t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13314 {"arm740t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13315 {"arm710c", ARM_ARCH_V3, FPU_ARCH_FPA},
13316 {"arm7100", ARM_ARCH_V3, FPU_ARCH_FPA},
13317 {"arm7500", ARM_ARCH_V3, FPU_ARCH_FPA},
13318 {"arm7500fe", ARM_ARCH_V3, FPU_ARCH_FPA},
13319 {"arm7t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13320 {"arm7tdmi", ARM_ARCH_V4T, FPU_ARCH_FPA},
8783612f 13321 {"arm7tdmi-s", ARM_ARCH_V4T, FPU_ARCH_FPA},
03b1477f
RE
13322 {"arm8", ARM_ARCH_V4, FPU_ARCH_FPA},
13323 {"arm810", ARM_ARCH_V4, FPU_ARCH_FPA},
13324 {"strongarm", ARM_ARCH_V4, FPU_ARCH_FPA},
13325 {"strongarm1", ARM_ARCH_V4, FPU_ARCH_FPA},
13326 {"strongarm110", ARM_ARCH_V4, FPU_ARCH_FPA},
13327 {"strongarm1100", ARM_ARCH_V4, FPU_ARCH_FPA},
13328 {"strongarm1110", ARM_ARCH_V4, FPU_ARCH_FPA},
13329 {"arm9", ARM_ARCH_V4T, FPU_ARCH_FPA},
13330 {"arm920", ARM_ARCH_V4T, FPU_ARCH_FPA},
13331 {"arm920t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13332 {"arm922t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13333 {"arm940t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13334 {"arm9tdmi", ARM_ARCH_V4T, FPU_ARCH_FPA},
13335 /* For V5 or later processors we default to using VFP; but the user
13336 should really set the FPU type explicitly. */
13337 {"arm9e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
13338 {"arm9e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
ea6ef066 13339 {"arm926ej", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
7de9afa2 13340 {"arm926ejs", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
8783612f 13341 {"arm926ej-s", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
03b1477f
RE
13342 {"arm946e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
13343 {"arm946e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13344 {"arm966e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
13345 {"arm966e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13346 {"arm10t", ARM_ARCH_V5T, FPU_ARCH_VFP_V1},
13347 {"arm10e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13348 {"arm1020", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13349 {"arm1020t", ARM_ARCH_V5T, FPU_ARCH_VFP_V1},
13350 {"arm1020e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
7de9afa2 13351 {"arm1026ejs", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
8783612f 13352 {"arm1026ej-s", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
09d92015 13353 {"arm1136js", ARM_ARCH_V6, FPU_NONE},
9166bcd7 13354 {"arm1136j-s", ARM_ARCH_V6, FPU_NONE},
09d92015 13355 {"arm1136jfs", ARM_ARCH_V6, FPU_ARCH_VFP_V2},
8783612f 13356 {"arm1136jf-s", ARM_ARCH_V6, FPU_ARCH_VFP_V2},
03b1477f
RE
13357 /* ??? XSCALE is really an architecture. */
13358 {"xscale", ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2},
5a6c6817 13359 /* ??? iwmmxt is not a processor. */
e16bb312 13360 {"iwmmxt", ARM_ARCH_IWMMXT, FPU_ARCH_VFP_V2},
03b1477f
RE
13361 {"i80200", ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2},
13362 /* Maverick */
33a392fb 13363 {"ep9312", ARM_ARCH_V4T | ARM_CEXT_MAVERICK, FPU_ARCH_MAVERICK},
03b1477f
RE
13364 {NULL, 0, 0}
13365};
cc8a6dd0 13366
03b1477f
RE
13367struct arm_arch_option_table
13368{
13369 char *name;
13370 int value;
13371 int default_fpu;
13372};
13373
13374/* This list should, at a minimum, contain all the architecture names
13375 recognized by GCC. */
13376static struct arm_arch_option_table arm_archs[] =
13377{
13378 {"all", ARM_ANY, FPU_ARCH_FPA},
13379 {"armv1", ARM_ARCH_V1, FPU_ARCH_FPA},
13380 {"armv2", ARM_ARCH_V2, FPU_ARCH_FPA},
13381 {"armv2a", ARM_ARCH_V2S, FPU_ARCH_FPA},
13382 {"armv2s", ARM_ARCH_V2S, FPU_ARCH_FPA},
13383 {"armv3", ARM_ARCH_V3, FPU_ARCH_FPA},
13384 {"armv3m", ARM_ARCH_V3M, FPU_ARCH_FPA},
13385 {"armv4", ARM_ARCH_V4, FPU_ARCH_FPA},
13386 {"armv4xm", ARM_ARCH_V4xM, FPU_ARCH_FPA},
13387 {"armv4t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13388 {"armv4txm", ARM_ARCH_V4TxM, FPU_ARCH_FPA},
13389 {"armv5", ARM_ARCH_V5, FPU_ARCH_VFP},
13390 {"armv5t", ARM_ARCH_V5T, FPU_ARCH_VFP},
13391 {"armv5txm", ARM_ARCH_V5TxM, FPU_ARCH_VFP},
13392 {"armv5te", ARM_ARCH_V5TE, FPU_ARCH_VFP},
13393 {"armv5texp", ARM_ARCH_V5TExP, FPU_ARCH_VFP},
ea6ef066 13394 {"armv5tej", ARM_ARCH_V5TEJ, FPU_ARCH_VFP},
84255574 13395 {"armv6", ARM_ARCH_V6, FPU_ARCH_VFP},
1ddd7f43 13396 {"armv6j", ARM_ARCH_V6, FPU_ARCH_VFP},
03b1477f 13397 {"xscale", ARM_ARCH_XSCALE, FPU_ARCH_VFP},
8266886e 13398 {"iwmmxt", ARM_ARCH_IWMMXT, FPU_ARCH_VFP},
03b1477f
RE
13399 {NULL, 0, 0}
13400};
13401
13402/* ISA extensions in the co-processor space. */
13403struct arm_arch_extension_table
13404{
13405 char *name;
13406 int value;
13407};
13408
13409static struct arm_arch_extension_table arm_extensions[] =
13410{
13411 {"maverick", ARM_CEXT_MAVERICK},
13412 {"xscale", ARM_CEXT_XSCALE},
e16bb312 13413 {"iwmmxt", ARM_CEXT_IWMMXT},
03b1477f
RE
13414 {NULL, 0}
13415};
b99bd4ef 13416
03b1477f
RE
13417struct arm_fpu_option_table
13418{
13419 char *name;
13420 int value;
13421};
13422
13423/* This list should, at a minimum, contain all the fpu names
13424 recognized by GCC. */
13425static struct arm_fpu_option_table arm_fpus[] =
13426{
13427 {"softfpa", FPU_NONE},
13428 {"fpe", FPU_ARCH_FPE},
d193a22a
RE
13429 {"fpe2", FPU_ARCH_FPE},
13430 {"fpe3", FPU_ARCH_FPA}, /* Third release supports LFM/SFM. */
03b1477f
RE
13431 {"fpa", FPU_ARCH_FPA},
13432 {"fpa10", FPU_ARCH_FPA},
13433 {"fpa11", FPU_ARCH_FPA},
13434 {"arm7500fe", FPU_ARCH_FPA},
13435 {"softvfp", FPU_ARCH_VFP},
13436 {"softvfp+vfp", FPU_ARCH_VFP_V2},
13437 {"vfp", FPU_ARCH_VFP_V2},
13438 {"vfp9", FPU_ARCH_VFP_V2},
13439 {"vfp10", FPU_ARCH_VFP_V2},
13440 {"vfp10-r0", FPU_ARCH_VFP_V1},
13441 {"vfpxd", FPU_ARCH_VFP_V1xD},
13442 {"arm1020t", FPU_ARCH_VFP_V1},
13443 {"arm1020e", FPU_ARCH_VFP_V2},
09d92015 13444 {"arm1136jfs", FPU_ARCH_VFP_V2},
8783612f 13445 {"arm1136jf-s", FPU_ARCH_VFP_V2},
33a392fb
PB
13446 {"maverick", FPU_ARCH_MAVERICK},
13447 {NULL, 0}
13448};
13449
13450struct arm_float_abi_option_table
13451{
13452 char *name;
13453 int value;
13454};
13455
13456static struct arm_float_abi_option_table arm_float_abis[] =
13457{
13458 {"hard", ARM_FLOAT_ABI_HARD},
13459 {"softfp", ARM_FLOAT_ABI_SOFTFP},
13460 {"soft", ARM_FLOAT_ABI_SOFT},
03b1477f
RE
13461 {NULL, 0}
13462};
13463
d507cf36
PB
13464struct arm_eabi_option_table
13465{
13466 char *name;
13467 unsigned int value;
13468};
13469
7cc69913 13470#ifdef OBJ_ELF
d507cf36
PB
13471/* We only know hot to output GNU and ver 3 (AAELF) formats. */
13472static struct arm_eabi_option_table arm_eabis[] =
13473{
13474 {"gnu", EF_ARM_EABI_UNKNOWN},
13475 {"3", EF_ARM_EABI_VER3},
13476 {NULL, 0}
13477};
7cc69913 13478#endif
d507cf36 13479
03b1477f
RE
13480struct arm_long_option_table
13481{
13482 char *option; /* Substring to match. */
13483 char *help; /* Help information. */
13484 int (*func) PARAMS ((char *subopt)); /* Function to decode sub-option. */
13485 char *deprecated; /* If non-null, print this message. */
13486};
13487
13488static int
13489arm_parse_extension (str, opt_p)
13490 char *str;
13491 int *opt_p;
13492{
13493 while (str != NULL && *str != 0)
13494 {
13495 struct arm_arch_extension_table *opt;
13496 char *ext;
13497 int optlen;
13498
13499 if (*str != '+')
b99bd4ef 13500 {
03b1477f
RE
13501 as_bad (_("invalid architectural extension"));
13502 return 0;
13503 }
b99bd4ef 13504
03b1477f
RE
13505 str++;
13506 ext = strchr (str, '+');
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 architectural extension"));
13516 return 0;
13517 }
b99bd4ef 13518
03b1477f
RE
13519 for (opt = arm_extensions; opt->name != NULL; opt++)
13520 if (strncmp (opt->name, str, optlen) == 0)
13521 {
13522 *opt_p |= opt->value;
13523 break;
13524 }
bfae80f2 13525
03b1477f
RE
13526 if (opt->name == NULL)
13527 {
13528 as_bad (_("unknown architectural extnsion `%s'"), str);
13529 return 0;
13530 }
b99bd4ef 13531
03b1477f
RE
13532 str = ext;
13533 };
b99bd4ef 13534
03b1477f
RE
13535 return 1;
13536}
b99bd4ef 13537
03b1477f
RE
13538static int
13539arm_parse_cpu (str)
13540 char *str;
13541{
13542 struct arm_cpu_option_table *opt;
13543 char *ext = strchr (str, '+');
13544 int optlen;
b99bd4ef 13545
03b1477f
RE
13546 if (ext != NULL)
13547 optlen = ext - str;
13548 else
13549 optlen = strlen (str);
b99bd4ef 13550
03b1477f
RE
13551 if (optlen == 0)
13552 {
13553 as_bad (_("missing cpu name `%s'"), str);
13554 return 0;
13555 }
b99bd4ef 13556
03b1477f
RE
13557 for (opt = arm_cpus; opt->name != NULL; opt++)
13558 if (strncmp (opt->name, str, optlen) == 0)
13559 {
13560 mcpu_cpu_opt = opt->value;
13561 mcpu_fpu_opt = opt->default_fpu;
b99bd4ef 13562
03b1477f
RE
13563 if (ext != NULL)
13564 return arm_parse_extension (ext, &mcpu_cpu_opt);
b99bd4ef 13565
03b1477f
RE
13566 return 1;
13567 }
b99bd4ef 13568
03b1477f
RE
13569 as_bad (_("unknown cpu `%s'"), str);
13570 return 0;
13571}
b99bd4ef 13572
03b1477f
RE
13573static int
13574arm_parse_arch (str)
13575 char *str;
13576{
13577 struct arm_arch_option_table *opt;
13578 char *ext = strchr (str, '+');
13579 int optlen;
b99bd4ef 13580
03b1477f
RE
13581 if (ext != NULL)
13582 optlen = ext - str;
13583 else
13584 optlen = strlen (str);
b99bd4ef 13585
03b1477f
RE
13586 if (optlen == 0)
13587 {
13588 as_bad (_("missing architecture name `%s'"), str);
13589 return 0;
13590 }
b99bd4ef 13591
b99bd4ef 13592
03b1477f
RE
13593 for (opt = arm_archs; opt->name != NULL; opt++)
13594 if (strcmp (opt->name, str) == 0)
13595 {
13596 march_cpu_opt = opt->value;
13597 march_fpu_opt = opt->default_fpu;
b99bd4ef 13598
03b1477f
RE
13599 if (ext != NULL)
13600 return arm_parse_extension (ext, &march_cpu_opt);
b99bd4ef 13601
03b1477f
RE
13602 return 1;
13603 }
b99bd4ef 13604
03b1477f
RE
13605 as_bad (_("unknown architecture `%s'\n"), str);
13606 return 0;
13607}
13608
13609static int
13610arm_parse_fpu (str)
13611 char *str;
13612{
13613 struct arm_fpu_option_table *opt;
b99bd4ef 13614
03b1477f
RE
13615 for (opt = arm_fpus; opt->name != NULL; opt++)
13616 if (strcmp (opt->name, str) == 0)
13617 {
13618 mfpu_opt = opt->value;
13619 return 1;
13620 }
b99bd4ef 13621
03b1477f
RE
13622 as_bad (_("unknown floating point format `%s'\n"), str);
13623 return 0;
13624}
b99bd4ef 13625
33a392fb
PB
13626static int
13627arm_parse_float_abi (str)
13628 char * str;
13629{
13630 struct arm_float_abi_option_table *opt;
13631
13632 for (opt = arm_float_abis; opt->name != NULL; opt++)
13633 if (strcmp (opt->name, str) == 0)
13634 {
13635 mfloat_abi_opt = opt->value;
13636 return 1;
13637 }
13638
13639 as_bad (_("unknown floating point abi `%s'\n"), str);
13640 return 0;
13641}
13642
7cc69913 13643#ifdef OBJ_ELF
d507cf36
PB
13644static int
13645arm_parse_eabi (str)
13646 char * str;
13647{
13648 struct arm_eabi_option_table *opt;
13649
13650 for (opt = arm_eabis; opt->name != NULL; opt++)
13651 if (strcmp (opt->name, str) == 0)
13652 {
13653 meabi_flags = opt->value;
13654 return 1;
13655 }
13656 as_bad (_("unknown EABI `%s'\n"), str);
13657 return 0;
13658}
7cc69913 13659#endif
d507cf36 13660
03b1477f
RE
13661struct arm_long_option_table arm_long_opts[] =
13662{
13663 {"mcpu=", N_("<cpu name>\t assemble for CPU <cpu name>"),
13664 arm_parse_cpu, NULL},
13665 {"march=", N_("<arch name>\t assemble for architecture <arch name>"),
13666 arm_parse_arch, NULL},
13667 {"mfpu=", N_("<fpu name>\t assemble for FPU architecture <fpu name>"),
13668 arm_parse_fpu, NULL},
33a392fb
PB
13669 {"mfloat-abi=", N_("<abi>\t assemble for floating point ABI <abi>"),
13670 arm_parse_float_abi, NULL},
7cc69913 13671#ifdef OBJ_ELF
d507cf36
PB
13672 {"meabi=", N_("<ver>\t assemble for eabi version <ver>"),
13673 arm_parse_eabi, NULL},
7cc69913 13674#endif
03b1477f
RE
13675 {NULL, NULL, 0, NULL}
13676};
b99bd4ef 13677
03b1477f
RE
13678int
13679md_parse_option (c, arg)
13680 int c;
13681 char * arg;
13682{
13683 struct arm_option_table *opt;
13684 struct arm_long_option_table *lopt;
b99bd4ef 13685
03b1477f
RE
13686 switch (c)
13687 {
13688#ifdef OPTION_EB
13689 case OPTION_EB:
13690 target_big_endian = 1;
b99bd4ef 13691 break;
03b1477f 13692#endif
b99bd4ef 13693
03b1477f
RE
13694#ifdef OPTION_EL
13695 case OPTION_EL:
13696 target_big_endian = 0;
b99bd4ef
NC
13697 break;
13698#endif
13699
03b1477f 13700 case 'a':
cc8a6dd0 13701 /* Listing option. Just ignore these, we don't support additional
03b1477f
RE
13702 ones. */
13703 return 0;
13704
b99bd4ef 13705 default:
03b1477f
RE
13706 for (opt = arm_opts; opt->option != NULL; opt++)
13707 {
13708 if (c == opt->option[0]
13709 && ((arg == NULL && opt->option[1] == 0)
13710 || strcmp (arg, opt->option + 1) == 0))
13711 {
13712#if WARN_DEPRECATED
13713 /* If the option is deprecated, tell the user. */
13714 if (opt->deprecated != NULL)
13715 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c,
13716 arg ? arg : "", _(opt->deprecated));
13717#endif
13718
13719 if (opt->var != NULL)
13720 *opt->var = opt->value;
13721
13722 return 1;
13723 }
13724 }
13725
13726 for (lopt = arm_long_opts; lopt->option != NULL; lopt++)
13727 {
cc8a6dd0 13728 /* These options are expected to have an argument. */
03b1477f
RE
13729 if (c == lopt->option[0]
13730 && arg != NULL
cc8a6dd0 13731 && strncmp (arg, lopt->option + 1,
03b1477f
RE
13732 strlen (lopt->option + 1)) == 0)
13733 {
13734#if WARN_DEPRECATED
13735 /* If the option is deprecated, tell the user. */
13736 if (lopt->deprecated != NULL)
13737 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c, arg,
13738 _(lopt->deprecated));
13739#endif
13740
13741 /* Call the sup-option parser. */
13742 return (*lopt->func)(arg + strlen (lopt->option) - 1);
13743 }
13744 }
13745
b99bd4ef
NC
13746 return 0;
13747 }
13748
13749 return 1;
13750}
13751
13752void
13753md_show_usage (fp)
13754 FILE * fp;
13755{
03b1477f
RE
13756 struct arm_option_table *opt;
13757 struct arm_long_option_table *lopt;
13758
13759 fprintf (fp, _(" ARM-specific assembler options:\n"));
13760
13761 for (opt = arm_opts; opt->option != NULL; opt++)
13762 if (opt->help != NULL)
13763 fprintf (fp, " -%-23s%s\n", opt->option, _(opt->help));
13764
13765 for (lopt = arm_long_opts; lopt->option != NULL; lopt++)
13766 if (lopt->help != NULL)
13767 fprintf (fp, " -%s%s\n", lopt->option, _(lopt->help));
13768
13769#ifdef OPTION_EB
b99bd4ef 13770 fprintf (fp, _("\
03b1477f 13771 -EB assemble code for a big-endian cpu\n"));
b99bd4ef 13772#endif
03b1477f
RE
13773
13774#ifdef OPTION_EL
b99bd4ef 13775 fprintf (fp, _("\
03b1477f 13776 -EL assemble code for a little-endian cpu\n"));
b99bd4ef
NC
13777#endif
13778}
13779
13780/* We need to be able to fix up arbitrary expressions in some statements.
13781 This is so that we can handle symbols that are an arbitrary distance from
13782 the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
13783 which returns part of an address in a form which will be valid for
13784 a data instruction. We do this by pushing the expression into a symbol
13785 in the expr_section, and creating a fix for that. */
13786
13787static void
13788fix_new_arm (frag, where, size, exp, pc_rel, reloc)
13789 fragS * frag;
13790 int where;
13791 short int size;
13792 expressionS * exp;
13793 int pc_rel;
13794 int reloc;
13795{
13796 fixS * new_fix;
13797 arm_fix_data * arm_data;
13798
13799 switch (exp->X_op)
13800 {
13801 case O_constant:
13802 case O_symbol:
13803 case O_add:
13804 case O_subtract:
13805 new_fix = fix_new_exp (frag, where, size, exp, pc_rel, reloc);
13806 break;
13807
13808 default:
13809 new_fix = fix_new (frag, where, size, make_expr_symbol (exp), 0,
13810 pc_rel, reloc);
13811 break;
13812 }
13813
13814 /* Mark whether the fix is to a THUMB instruction, or an ARM
13815 instruction. */
13816 arm_data = (arm_fix_data *) obstack_alloc (& notes, sizeof (arm_fix_data));
13817 new_fix->tc_fix_data = (PTR) arm_data;
13818 arm_data->thumb_mode = thumb_mode;
b99bd4ef
NC
13819}
13820
13821/* This fix_new is called by cons via TC_CONS_FIX_NEW. */
13822
13823void
13824cons_fix_new_arm (frag, where, size, exp)
13825 fragS * frag;
13826 int where;
13827 int size;
13828 expressionS * exp;
13829{
13830 bfd_reloc_code_real_type type;
13831 int pcrel = 0;
13832
13833 /* Pick a reloc.
13834 FIXME: @@ Should look at CPU word size. */
13835 switch (size)
13836 {
13837 case 1:
13838 type = BFD_RELOC_8;
13839 break;
13840 case 2:
13841 type = BFD_RELOC_16;
13842 break;
13843 case 4:
13844 default:
13845 type = BFD_RELOC_32;
13846 break;
13847 case 8:
13848 type = BFD_RELOC_64;
13849 break;
13850 }
13851
13852 fix_new_exp (frag, where, (int) size, exp, pcrel, type);
13853}
13854
13855/* A good place to do this, although this was probably not intended
13856 for this kind of use. We need to dump the literal pool before
13857 references are made to a null symbol pointer. */
13858
13859void
13860arm_cleanup ()
13861{
3d0c9500 13862 literal_pool * pool;
b99bd4ef 13863
3d0c9500
NC
13864 for (pool = list_of_pools; pool; pool = pool->next)
13865 {
13866 /* Put it at the end of the relevent section. */
13867 subseg_set (pool->section, pool->sub_section);
69b97547
NC
13868#ifdef OBJ_ELF
13869 arm_elf_change_section ();
13870#endif
3d0c9500
NC
13871 s_ltorg (0);
13872 }
b99bd4ef
NC
13873}
13874
13875void
13876arm_start_line_hook ()
13877{
13878 last_label_seen = NULL;
13879}
13880
13881void
13882arm_frob_label (sym)
13883 symbolS * sym;
13884{
13885 last_label_seen = sym;
13886
13887 ARM_SET_THUMB (sym, thumb_mode);
13888
13889#if defined OBJ_COFF || defined OBJ_ELF
13890 ARM_SET_INTERWORK (sym, support_interwork);
13891#endif
13892
13893 /* Note - do not allow local symbols (.Lxxx) to be labeled
13894 as Thumb functions. This is because these labels, whilst
13895 they exist inside Thumb code, are not the entry points for
13896 possible ARM->Thumb calls. Also, these labels can be used
13897 as part of a computed goto or switch statement. eg gcc
13898 can generate code that looks like this:
13899
13900 ldr r2, [pc, .Laaa]
13901 lsl r3, r3, #2
13902 ldr r2, [r3, r2]
13903 mov pc, r2
cc8a6dd0 13904
b99bd4ef
NC
13905 .Lbbb: .word .Lxxx
13906 .Lccc: .word .Lyyy
13907 ..etc...
13908 .Laaa: .word Lbbb
13909
13910 The first instruction loads the address of the jump table.
13911 The second instruction converts a table index into a byte offset.
13912 The third instruction gets the jump address out of the table.
13913 The fourth instruction performs the jump.
cc8a6dd0 13914
b99bd4ef
NC
13915 If the address stored at .Laaa is that of a symbol which has the
13916 Thumb_Func bit set, then the linker will arrange for this address
13917 to have the bottom bit set, which in turn would mean that the
13918 address computation performed by the third instruction would end
13919 up with the bottom bit set. Since the ARM is capable of unaligned
13920 word loads, the instruction would then load the incorrect address
13921 out of the jump table, and chaos would ensue. */
13922 if (label_is_thumb_function_name
13923 && (S_GET_NAME (sym)[0] != '.' || S_GET_NAME (sym)[1] != 'L')
13924 && (bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
13925 {
13926 /* When the address of a Thumb function is taken the bottom
13927 bit of that address should be set. This will allow
13928 interworking between Arm and Thumb functions to work
13929 correctly. */
13930
13931 THUMB_SET_FUNC (sym, 1);
13932
b34976b6 13933 label_is_thumb_function_name = FALSE;
b99bd4ef
NC
13934 }
13935}
13936
13937/* Adjust the symbol table. This marks Thumb symbols as distinct from
13938 ARM ones. */
13939
13940void
13941arm_adjust_symtab ()
13942{
13943#ifdef OBJ_COFF
13944 symbolS * sym;
13945
13946 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
13947 {
13948 if (ARM_IS_THUMB (sym))
13949 {
13950 if (THUMB_IS_FUNC (sym))
13951 {
13952 /* Mark the symbol as a Thumb function. */
13953 if ( S_GET_STORAGE_CLASS (sym) == C_STAT
13954 || S_GET_STORAGE_CLASS (sym) == C_LABEL) /* This can happen! */
13955 S_SET_STORAGE_CLASS (sym, C_THUMBSTATFUNC);
13956
13957 else if (S_GET_STORAGE_CLASS (sym) == C_EXT)
13958 S_SET_STORAGE_CLASS (sym, C_THUMBEXTFUNC);
13959 else
13960 as_bad (_("%s: unexpected function type: %d"),
13961 S_GET_NAME (sym), S_GET_STORAGE_CLASS (sym));
13962 }
cc8a6dd0 13963 else switch (S_GET_STORAGE_CLASS (sym))
b99bd4ef
NC
13964 {
13965 case C_EXT:
13966 S_SET_STORAGE_CLASS (sym, C_THUMBEXT);
13967 break;
13968 case C_STAT:
13969 S_SET_STORAGE_CLASS (sym, C_THUMBSTAT);
13970 break;
13971 case C_LABEL:
13972 S_SET_STORAGE_CLASS (sym, C_THUMBLABEL);
13973 break;
13974 default:
13975 /* Do nothing. */
13976 break;
13977 }
13978 }
13979
13980 if (ARM_IS_INTERWORK (sym))
13981 coffsymbol (symbol_get_bfdsym (sym))->native->u.syment.n_flags = 0xFF;
13982 }
13983#endif
13984#ifdef OBJ_ELF
13985 symbolS * sym;
13986 char bind;
13987
13988 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
13989 {
13990 if (ARM_IS_THUMB (sym))
13991 {
13992 elf_symbol_type * elf_sym;
13993
13994 elf_sym = elf_symbol (symbol_get_bfdsym (sym));
13995 bind = ELF_ST_BIND (elf_sym);
13996
13997 /* If it's a .thumb_func, declare it as so,
13998 otherwise tag label as .code 16. */
13999 if (THUMB_IS_FUNC (sym))
14000 elf_sym->internal_elf_sym.st_info =
14001 ELF_ST_INFO (bind, STT_ARM_TFUNC);
14002 else
14003 elf_sym->internal_elf_sym.st_info =
14004 ELF_ST_INFO (bind, STT_ARM_16BIT);
14005 }
14006 }
14007#endif
14008}
14009
14010int
14011arm_data_in_code ()
14012{
14013 if (thumb_mode && ! strncmp (input_line_pointer + 1, "data:", 5))
14014 {
14015 *input_line_pointer = '/';
14016 input_line_pointer += 5;
14017 *input_line_pointer = 0;
14018 return 1;
14019 }
14020
14021 return 0;
14022}
14023
14024char *
14025arm_canonicalize_symbol_name (name)
14026 char * name;
14027{
14028 int len;
14029
14030 if (thumb_mode && (len = strlen (name)) > 5
14031 && streq (name + len - 5, "/data"))
14032 *(name + len - 5) = 0;
14033
14034 return name;
14035}
14036
bfc866a6 14037#if defined OBJ_COFF || defined OBJ_ELF
a161fe53 14038void
b99bd4ef
NC
14039arm_validate_fix (fixP)
14040 fixS * fixP;
14041{
14042 /* If the destination of the branch is a defined symbol which does not have
14043 the THUMB_FUNC attribute, then we must be calling a function which has
14044 the (interfacearm) attribute. We look for the Thumb entry point to that
14045 function and change the branch to refer to that function instead. */
14046 if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23
14047 && fixP->fx_addsy != NULL
14048 && S_IS_DEFINED (fixP->fx_addsy)
14049 && ! THUMB_IS_FUNC (fixP->fx_addsy))
14050 {
14051 fixP->fx_addsy = find_real_start (fixP->fx_addsy);
b99bd4ef 14052 }
b99bd4ef 14053}
bfc866a6 14054#endif
b99bd4ef 14055
114424c6
AM
14056int
14057arm_force_relocation (fixp)
14058 struct fix * fixp;
14059{
14060#if defined (OBJ_COFF) && defined (TE_PE)
14061 if (fixp->fx_r_type == BFD_RELOC_RVA)
14062 return 1;
14063#endif
14064#ifdef OBJ_ELF
ae6063d4 14065 if (fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH
114424c6
AM
14066 || fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BLX
14067 || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX
14068 || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23)
14069 return 1;
14070#endif
14071
14072 /* Resolve these relocations even if the symbol is extern or weak. */
14073 if (fixp->fx_r_type == BFD_RELOC_ARM_IMMEDIATE
47281638 14074 || fixp->fx_r_type == BFD_RELOC_ARM_OFFSET_IMM
114424c6
AM
14075 || fixp->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE)
14076 return 0;
14077
ae6063d4 14078 return generic_force_reloc (fixp);
114424c6
AM
14079}
14080
b99bd4ef
NC
14081#ifdef OBJ_COFF
14082/* This is a little hack to help the gas/arm/adrl.s test. It prevents
14083 local labels from being added to the output symbol table when they
14084 are used with the ADRL pseudo op. The ADRL relocation should always
14085 be resolved before the binbary is emitted, so it is safe to say that
14086 it is adjustable. */
14087
b34976b6 14088bfd_boolean
b99bd4ef
NC
14089arm_fix_adjustable (fixP)
14090 fixS * fixP;
14091{
14092 if (fixP->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE)
14093 return 1;
14094 return 0;
14095}
14096#endif
114424c6 14097
b99bd4ef
NC
14098#ifdef OBJ_ELF
14099/* Relocations against Thumb function names must be left unadjusted,
14100 so that the linker can use this information to correctly set the
14101 bottom bit of their addresses. The MIPS version of this function
14102 also prevents relocations that are mips-16 specific, but I do not
14103 know why it does this.
14104
14105 FIXME:
14106 There is one other problem that ought to be addressed here, but
14107 which currently is not: Taking the address of a label (rather
14108 than a function) and then later jumping to that address. Such
14109 addresses also ought to have their bottom bit set (assuming that
14110 they reside in Thumb code), but at the moment they will not. */
14111
b34976b6 14112bfd_boolean
b99bd4ef
NC
14113arm_fix_adjustable (fixP)
14114 fixS * fixP;
14115{
14116 if (fixP->fx_addsy == NULL)
14117 return 1;
14118
b99bd4ef
NC
14119 if (THUMB_IS_FUNC (fixP->fx_addsy)
14120 && fixP->fx_subsy == NULL)
14121 return 0;
14122
14123 /* We need the symbol name for the VTABLE entries. */
14124 if ( fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
14125 || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
14126 return 0;
14127
a161fe53
AM
14128 /* Don't allow symbols to be discarded on GOT related relocs. */
14129 if (fixP->fx_r_type == BFD_RELOC_ARM_PLT32
14130 || fixP->fx_r_type == BFD_RELOC_ARM_GOT32
eb043451
PB
14131 || fixP->fx_r_type == BFD_RELOC_ARM_GOTOFF
14132 || fixP->fx_r_type == BFD_RELOC_ARM_TARGET2)
a161fe53
AM
14133 return 0;
14134
b99bd4ef
NC
14135 return 1;
14136}
14137
14138const char *
14139elf32_arm_target_format ()
14140{
e5a52504
MM
14141#ifdef TE_SYMBIAN
14142 return (target_big_endian
14143 ? "elf32-bigarm-symbian"
14144 : "elf32-littlearm-symbian");
14145#else
b99bd4ef
NC
14146 if (target_big_endian)
14147 {
14148 if (target_oabi)
14149 return "elf32-bigarm-oabi";
14150 else
14151 return "elf32-bigarm";
14152 }
14153 else
14154 {
14155 if (target_oabi)
14156 return "elf32-littlearm-oabi";
14157 else
14158 return "elf32-littlearm";
14159 }
e5a52504 14160#endif
b99bd4ef
NC
14161}
14162
14163void
14164armelf_frob_symbol (symp, puntp)
14165 symbolS * symp;
14166 int * puntp;
14167{
14168 elf_frob_symbol (symp, puntp);
14169}
14170
b99bd4ef
NC
14171static bfd_reloc_code_real_type
14172arm_parse_reloc ()
14173{
14174 char id [16];
14175 char * ip;
14176 unsigned int i;
14177 static struct
14178 {
14179 char * str;
14180 int len;
14181 bfd_reloc_code_real_type reloc;
14182 }
14183 reloc_map[] =
14184 {
14185#define MAP(str,reloc) { str, sizeof (str) - 1, reloc }
14186 MAP ("(got)", BFD_RELOC_ARM_GOT32),
14187 MAP ("(gotoff)", BFD_RELOC_ARM_GOTOFF),
14188 /* ScottB: Jan 30, 1998 - Added support for parsing "var(PLT)"
14189 branch instructions generated by GCC for PLT relocs. */
14190 MAP ("(plt)", BFD_RELOC_ARM_PLT32),
9c504268 14191 MAP ("(target1)", BFD_RELOC_ARM_TARGET1),
db6579d4 14192 MAP ("(sbrel)", BFD_RELOC_ARM_SBREL32),
eb043451 14193 MAP ("(target2)", BFD_RELOC_ARM_TARGET2),
b99bd4ef
NC
14194 { NULL, 0, BFD_RELOC_UNUSED }
14195#undef MAP
14196 };
14197
14198 for (i = 0, ip = input_line_pointer;
3882b010 14199 i < sizeof (id) && (ISALNUM (*ip) || ISPUNCT (*ip));
b99bd4ef 14200 i++, ip++)
3882b010 14201 id[i] = TOLOWER (*ip);
b99bd4ef
NC
14202
14203 for (i = 0; reloc_map[i].str; i++)
14204 if (strncmp (id, reloc_map[i].str, reloc_map[i].len) == 0)
14205 break;
14206
14207 input_line_pointer += reloc_map[i].len;
14208
14209 return reloc_map[i].reloc;
14210}
14211
14212static void
14213s_arm_elf_cons (nbytes)
14214 int nbytes;
14215{
14216 expressionS exp;
14217
14218#ifdef md_flush_pending_output
14219 md_flush_pending_output ();
14220#endif
14221
14222 if (is_it_end_of_statement ())
14223 {
14224 demand_empty_rest_of_line ();
14225 return;
14226 }
14227
14228#ifdef md_cons_align
14229 md_cons_align (nbytes);
14230#endif
14231
6057a28f 14232 mapping_state (MAP_DATA);
b99bd4ef
NC
14233 do
14234 {
14235 bfd_reloc_code_real_type reloc;
14236
14237 expression (& exp);
14238
14239 if (exp.X_op == O_symbol
14240 && * input_line_pointer == '('
14241 && (reloc = arm_parse_reloc ()) != BFD_RELOC_UNUSED)
14242 {
14243 reloc_howto_type *howto = bfd_reloc_type_lookup (stdoutput, reloc);
14244 int size = bfd_get_reloc_size (howto);
14245
14246 if (size > nbytes)
14247 as_bad ("%s relocations do not fit in %d bytes",
14248 howto->name, nbytes);
14249 else
14250 {
14251 register char *p = frag_more ((int) nbytes);
14252 int offset = nbytes - size;
14253
14254 fix_new_exp (frag_now, p - frag_now->fr_literal + offset, size,
14255 &exp, 0, reloc);
14256 }
14257 }
14258 else
14259 emit_expr (&exp, (unsigned int) nbytes);
14260 }
14261 while (*input_line_pointer++ == ',');
14262
14263 /* Put terminator back into stream. */
14264 input_line_pointer --;
14265 demand_empty_rest_of_line ();
14266}
14267
eb043451
PB
14268
14269/* Parse a .rel31 directive. */
14270
14271static void
14272s_arm_rel31 (int ignored ATTRIBUTE_UNUSED)
14273{
14274 expressionS exp;
14275 char *p;
14276 valueT highbit;
14277
14278 SKIP_WHITESPACE ();
14279
14280 highbit = 0;
14281 if (*input_line_pointer == '1')
14282 highbit = 0x80000000;
14283 else if (*input_line_pointer != '0')
14284 as_bad (_("expected 0 or 1"));
14285
14286 input_line_pointer++;
14287 SKIP_WHITESPACE ();
14288 if (*input_line_pointer != ',')
14289 as_bad (_("missing comma"));
14290 input_line_pointer++;
14291
14292#ifdef md_flush_pending_output
14293 md_flush_pending_output ();
14294#endif
14295
14296#ifdef md_cons_align
14297 md_cons_align (4);
14298#endif
14299
14300 mapping_state (MAP_DATA);
14301
14302 expression (&exp);
14303
14304 p = frag_more (4);
14305 md_number_to_chars (p, highbit, 4);
14306 fix_new_arm (frag_now, p - frag_now->fr_literal, 4, &exp, 1,
14307 BFD_RELOC_ARM_PREL31);
14308
14309 demand_empty_rest_of_line ();
14310}
14311
b99bd4ef
NC
14312#endif /* OBJ_ELF */
14313
14314/* This is called from HANDLE_ALIGN in write.c. Fill in the contents
14315 of an rs_align_code fragment. */
14316
14317void
14318arm_handle_align (fragP)
14319 fragS *fragP;
14320{
14321 static char const arm_noop[4] = { 0x00, 0x00, 0xa0, 0xe1 };
14322 static char const thumb_noop[2] = { 0xc0, 0x46 };
14323 static char const arm_bigend_noop[4] = { 0xe1, 0xa0, 0x00, 0x00 };
14324 static char const thumb_bigend_noop[2] = { 0x46, 0xc0 };
14325
14326 int bytes, fix, noop_size;
14327 char * p;
14328 const char * noop;
cc8a6dd0 14329
b99bd4ef
NC
14330 if (fragP->fr_type != rs_align_code)
14331 return;
14332
14333 bytes = fragP->fr_next->fr_address - fragP->fr_address - fragP->fr_fix;
14334 p = fragP->fr_literal + fragP->fr_fix;
14335 fix = 0;
cc8a6dd0 14336
b99bd4ef
NC
14337 if (bytes > MAX_MEM_FOR_RS_ALIGN_CODE)
14338 bytes &= MAX_MEM_FOR_RS_ALIGN_CODE;
cc8a6dd0 14339
b99bd4ef
NC
14340 if (fragP->tc_frag_data)
14341 {
14342 if (target_big_endian)
14343 noop = thumb_bigend_noop;
14344 else
14345 noop = thumb_noop;
14346 noop_size = sizeof (thumb_noop);
14347 }
14348 else
14349 {
14350 if (target_big_endian)
14351 noop = arm_bigend_noop;
14352 else
14353 noop = arm_noop;
14354 noop_size = sizeof (arm_noop);
14355 }
cc8a6dd0 14356
b99bd4ef
NC
14357 if (bytes & (noop_size - 1))
14358 {
14359 fix = bytes & (noop_size - 1);
14360 memset (p, 0, fix);
14361 p += fix;
14362 bytes -= fix;
14363 }
14364
14365 while (bytes >= noop_size)
14366 {
14367 memcpy (p, noop, noop_size);
14368 p += noop_size;
14369 bytes -= noop_size;
14370 fix += noop_size;
14371 }
cc8a6dd0 14372
b99bd4ef
NC
14373 fragP->fr_fix += fix;
14374 fragP->fr_var = noop_size;
14375}
14376
14377/* Called from md_do_align. Used to create an alignment
14378 frag in a code section. */
14379
14380void
14381arm_frag_align_code (n, max)
14382 int n;
14383 int max;
14384{
14385 char * p;
14386
2d2255b5 14387 /* We assume that there will never be a requirement
b99bd4ef
NC
14388 to support alignments greater than 32 bytes. */
14389 if (max > MAX_MEM_FOR_RS_ALIGN_CODE)
14390 as_fatal (_("alignments greater than 32 bytes not supported in .text sections."));
cc8a6dd0 14391
b99bd4ef
NC
14392 p = frag_var (rs_align_code,
14393 MAX_MEM_FOR_RS_ALIGN_CODE,
14394 1,
14395 (relax_substateT) max,
14396 (symbolS *) NULL,
14397 (offsetT) n,
14398 (char *) NULL);
14399 *p = 0;
14400
14401}
14402
14403/* Perform target specific initialisation of a frag. */
14404
14405void
14406arm_init_frag (fragP)
14407 fragS *fragP;
14408{
14409 /* Record whether this frag is in an ARM or a THUMB area. */
14410 fragP->tc_frag_data = thumb_mode;
14411}
This page took 0.943736 seconds and 4 git commands to generate.