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