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