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