]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gas/config/tc-arm.c
* arm-opc.h (arm_opcodes): Add patterns for VFP instructions.
[thirdparty/binutils-gdb.git] / gas / config / tc-arm.c
CommitLineData
b99bd4ef 1/* tc-arm.c -- Assemble for the ARM
f03698e6 2 Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
b99bd4ef
NC
3 Free Software Foundation, Inc.
4 Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org)
5 Modified by David Taylor (dtaylor@armltd.co.uk)
22d9c8c5 6 Cirrus coprocessor mods by Aldy Hernandez (aldyh@redhat.com)
b99bd4ef
NC
7
8 This file is part of GAS, the GNU Assembler.
9
10 GAS is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2, or (at your option)
13 any later version.
14
15 GAS is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with GAS; see the file COPYING. If not, write to the Free
22 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
23 02111-1307, USA. */
24
b99bd4ef
NC
25#include <string.h>
26#define NO_RELOC 0
27#include "as.h"
3882b010 28#include "safe-ctype.h"
b99bd4ef
NC
29
30/* Need TARGET_CPU. */
31#include "config.h"
32#include "subsegs.h"
33#include "obstack.h"
34#include "symbols.h"
35#include "listing.h"
36
37#ifdef OBJ_ELF
38#include "elf/arm.h"
39#include "dwarf2dbg.h"
40#endif
41
b89dddec
RE
42/* The following bitmasks control CPU extensions: */
43#define ARM_EXT_V1 0x00000001 /* All processors (core set). */
44#define ARM_EXT_V2 0x00000002 /* Multiply instructions. */
45#define ARM_EXT_V2S 0x00000004 /* SWP instructions. */
46#define ARM_EXT_V3 0x00000008 /* MSR MRS. */
47#define ARM_EXT_V3M 0x00000010 /* Allow long multiplies. */
48#define ARM_EXT_V4 0x00000020 /* Allow half word loads. */
49#define ARM_EXT_V4T 0x00000040 /* Thumb v1. */
50#define ARM_EXT_V5 0x00000080 /* Allow CLZ, etc. */
51#define ARM_EXT_V5T 0x00000100 /* Thumb v2. */
52#define ARM_EXT_V5ExP 0x00000200 /* DSP core set. */
53#define ARM_EXT_V5E 0x00000400 /* DSP Double transfers. */
54/* Processor specific extensions. */
55#define ARM_EXT_XSCALE 0x00000800 /* Allow MIA etc. */
56#define ARM_EXT_MAVERICK 0x00001000 /* Use Cirrus/DSP coprocessor. */
57
58/* Architectures are the sum of the base and extensions. The ARM ARM (rev E)
59 defines the following: ARMv3, ARMv3M, ARMv4xM, ARMv4, ARMv4TxM, ARMv4T,
60 ARMv5xM, ARMv5, ARMv5TxM, ARMv5T, ARMv5TExP, ARMv5TE. To these we add
61 three more to cover cores prior to ARM6. Finally, there are cores which
62 implement further extensions in the co-processor space. */
63#define ARM_ARCH_V1 ARM_EXT_V1
64#define ARM_ARCH_V2 (ARM_ARCH_V1 | ARM_EXT_V2)
65#define ARM_ARCH_V2S (ARM_ARCH_V2 | ARM_EXT_V2S)
66#define ARM_ARCH_V3 (ARM_ARCH_V2S | ARM_EXT_V3)
67#define ARM_ARCH_V3M (ARM_ARCH_V3 | ARM_EXT_V3M)
68#define ARM_ARCH_V4xM (ARM_ARCH_V3 | ARM_EXT_V4)
69#define ARM_ARCH_V4 (ARM_ARCH_V3M | ARM_EXT_V4)
70#define ARM_ARCH_V4TxM (ARM_ARCH_V4xM | ARM_EXT_V4T)
71#define ARM_ARCH_V4T (ARM_ARCH_V4 | ARM_EXT_V4T)
72#define ARM_ARCH_V5xM (ARM_ARCH_V4xM | ARM_EXT_V5)
73#define ARM_ARCH_V5 (ARM_ARCH_V4 | ARM_EXT_V5)
74#define ARM_ARCH_V5TxM (ARM_ARCH_V5xM | ARM_EXT_V4T | ARM_EXT_V5T)
75#define ARM_ARCH_V5T (ARM_ARCH_V5 | ARM_EXT_V4T | ARM_EXT_V5T)
76#define ARM_ARCH_V5TExP (ARM_ARCH_V5T | ARM_EXT_V5ExP)
77#define ARM_ARCH_V5TE (ARM_ARCH_V5TExP | ARM_EXT_V5E)
78/* Processors with specific extensions in the co-processor space. */
79#define ARM_ARCH_XSCALE (ARM_ARCH_V5TE | ARM_EXT_XSCALE)
b99bd4ef
NC
80
81/* Some useful combinations: */
82#define ARM_ANY 0x00ffffff
b89dddec 83#define ARM_ALL ARM_ANY
b99bd4ef 84
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")},
f03698e6
RE
595 {cp_table, 15, NULL, N_("bad or missing co-processor number")},
596 {cn_table, 15, NULL, N_("co-processor register expected")},
6c43fab6
RE
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 *));
f03698e6 803static void output_inst PARAMS ((const char *));
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
f03698e6 1791#define BAD_ARGS _("bad arguments to instruction")
b99bd4ef 1792#define BAD_PC _("r15 not allowed here")
f03698e6 1793#define BAD_COND _("instruction is not conditional")
b99bd4ef
NC
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 {
f03698e6 1933 inst.error = _("literal pool overflow");
b99bd4ef
NC
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{
f03698e6 2075 as_bad (_("invalid syntax for .req directive"));
b99bd4ef
NC
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)
f03698e6 2150 as_bad (_("alignment too large: %d assumed"), temp = max_alignment);
b99bd4ef
NC
2151 else if (temp < 0)
2152 {
f03698e6 2153 as_bad (_("alignment negative. 0 assumed."));
b99bd4ef
NC
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;
f03698e6 2237 as_bad (_("expected comma after name \"%s\""), name);
b99bd4ef
NC
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)
f03698e6 2424 char *str;
b99bd4ef
NC
2425{
2426 skip_whitespace (str);
2427
f03698e6
RE
2428 if (*str != '\0' && !inst.error)
2429 inst.error = _("garbage following instruction");
b99bd4ef
NC
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. */
f03698e6 2479 sprintf (buff, _("register expected, not '%.100s'"), start);
b99bd4ef
NC
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 {
f03698e6 2585 inst.error = _("illegal co-processor number");
6c43fab6
RE
2586 return FAIL;
2587 }
b99bd4ef
NC
2588 }
2589 }
6c43fab6
RE
2590 else
2591 {
f03698e6 2592 inst.error = _("bad or missing co-processor number");
6c43fab6
RE
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. */
f03698e6 2647 inst.error = _("co-processor register expected");
b99bd4ef
NC
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. */
f03698e6 2670 inst.error = _("floating point register expected");
b99bd4ef
NC
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 {
f03698e6 2866 inst.error = _("CPSR or SPSR expected");
b99bd4ef
NC
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 {
f03698e6 2947 inst.error = _("invalid constant");
b99bd4ef
NC
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
f03698e6 3437 (_("Warning: instruction unpredictable when using r15"));
b99bd4ef
NC
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 {
f03698e6 4067 inst.error = _("destination register must be even");
b99bd4ef
NC
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
f03698e6
RE
4185static int in_my_get_expression = 0;
4186
b99bd4ef
NC
4187static int
4188my_get_expression (ep, str)
4189 expressionS * ep;
4190 char ** str;
4191{
4192 char * save_in;
4193 segT seg;
4194
4195 save_in = input_line_pointer;
4196 input_line_pointer = *str;
f03698e6 4197 in_my_get_expression = 1;
b99bd4ef 4198 seg = expression (ep);
f03698e6
RE
4199 in_my_get_expression = 0;
4200
4201 if (ep->X_op == O_illegal)
4202 {
4203 /* We found a bad expression in md_operand(). */
4204 *str = input_line_pointer;
4205 input_line_pointer = save_in;
4206 return 1;
4207 }
b99bd4ef
NC
4208
4209#ifdef OBJ_AOUT
4210 if (seg != absolute_section
4211 && seg != text_section
4212 && seg != data_section
4213 && seg != bss_section
4214 && seg != undefined_section)
4215 {
4216 inst.error = _("bad_segment");
4217 *str = input_line_pointer;
4218 input_line_pointer = save_in;
4219 return 1;
4220 }
4221#endif
4222
4223 /* Get rid of any bignums now, so that we don't generate an error for which
4224 we can't establish a line number later on. Big numbers are never valid
4225 in instructions, which is where this routine is always called. */
4226 if (ep->X_op == O_big
4227 || (ep->X_add_symbol
4228 && (walk_no_bignums (ep->X_add_symbol)
4229 || (ep->X_op_symbol
4230 && walk_no_bignums (ep->X_op_symbol)))))
4231 {
f03698e6 4232 inst.error = _("invalid constant");
b99bd4ef
NC
4233 *str = input_line_pointer;
4234 input_line_pointer = save_in;
4235 return 1;
4236 }
4237
4238 *str = input_line_pointer;
4239 input_line_pointer = save_in;
4240 return 0;
4241}
4242
f03698e6
RE
4243/* We handle all bad expressions here, so that we can report the faulty
4244 instruction in the error message. */
4245void
ce058b6c 4246md_operand (expr)
f03698e6
RE
4247 expressionS *expr;
4248{
4249 if (in_my_get_expression)
4250 {
4251 expr->X_op = O_illegal;
4252 if (inst.error == NULL)
4253 inst.error = _("bad expression");
4254 }
4255}
4256
b99bd4ef
NC
4257/* UNRESTRICT should be one if <shift> <register> is permitted for this
4258 instruction. */
4259
4260static int
4261decode_shift (str, unrestrict)
4262 char ** str;
4263 int unrestrict;
4264{
4265 const struct asm_shift_name * shift;
4266 char * p;
4267 char c;
4268
4269 skip_whitespace (* str);
4270
3882b010 4271 for (p = * str; ISALPHA (* p); p ++)
b99bd4ef
NC
4272 ;
4273
4274 if (p == * str)
4275 {
f03698e6 4276 inst.error = _("shift expression expected");
b99bd4ef
NC
4277 return FAIL;
4278 }
4279
4280 c = * p;
4281 * p = '\0';
4282 shift = (const struct asm_shift_name *) hash_find (arm_shift_hsh, * str);
4283 * p = c;
4284
4285 if (shift == NULL)
4286 {
f03698e6 4287 inst.error = _("shift expression expected");
b99bd4ef
NC
4288 return FAIL;
4289 }
4290
4291 assert (shift->properties->index == shift_properties[shift->properties->index].index);
4292
4293 if (shift->properties->index == SHIFT_RRX)
4294 {
4295 * str = p;
4296 inst.instruction |= shift->properties->bit_field;
4297 return SUCCESS;
4298 }
4299
4300 skip_whitespace (p);
4301
4302 if (unrestrict && reg_required_here (& p, 8) != FAIL)
4303 {
4304 inst.instruction |= shift->properties->bit_field | SHIFT_BY_REG;
4305 * str = p;
4306 return SUCCESS;
4307 }
4308 else if (! is_immediate_prefix (* p))
4309 {
4310 inst.error = (unrestrict
4311 ? _("shift requires register or #expression")
4312 : _("shift requires #expression"));
4313 * str = p;
4314 return FAIL;
4315 }
4316
4317 inst.error = NULL;
4318 p ++;
4319
4320 if (my_get_expression (& inst.reloc.exp, & p))
4321 return FAIL;
4322
4323 /* Validate some simple #expressions. */
4324 if (inst.reloc.exp.X_op == O_constant)
4325 {
4326 unsigned num = inst.reloc.exp.X_add_number;
4327
4328 /* Reject operations greater than 32. */
4329 if (num > 32
4330 /* Reject a shift of 0 unless the mode allows it. */
4331 || (num == 0 && shift->properties->allows_0 == 0)
4332 /* Reject a shift of 32 unless the mode allows it. */
4333 || (num == 32 && shift->properties->allows_32 == 0)
4334 )
4335 {
4336 /* As a special case we allow a shift of zero for
4337 modes that do not support it to be recoded as an
4338 logical shift left of zero (ie nothing). We warn
4339 about this though. */
4340 if (num == 0)
4341 {
f03698e6 4342 as_warn (_("shift of 0 ignored."));
b99bd4ef
NC
4343 shift = & shift_names[0];
4344 assert (shift->properties->index == SHIFT_LSL);
4345 }
4346 else
4347 {
f03698e6 4348 inst.error = _("invalid immediate shift");
b99bd4ef
NC
4349 return FAIL;
4350 }
4351 }
4352
4353 /* Shifts of 32 are encoded as 0, for those shifts that
4354 support it. */
4355 if (num == 32)
4356 num = 0;
4357
4358 inst.instruction |= (num << 7) | shift->properties->bit_field;
4359 }
4360 else
4361 {
4362 inst.reloc.type = BFD_RELOC_ARM_SHIFT_IMM;
4363 inst.reloc.pc_rel = 0;
4364 inst.instruction |= shift->properties->bit_field;
4365 }
4366
4367 * str = p;
4368 return SUCCESS;
4369}
4370
4371/* Do those data_ops which can take a negative immediate constant
4372 by altering the instuction. A bit of a hack really.
4373 MOV <-> MVN
4374 AND <-> BIC
4375 ADC <-> SBC
4376 by inverting the second operand, and
4377 ADD <-> SUB
4378 CMP <-> CMN
4379 by negating the second operand. */
4380
4381static int
4382negate_data_op (instruction, value)
4383 unsigned long * instruction;
4384 unsigned long value;
4385{
4386 int op, new_inst;
4387 unsigned long negated, inverted;
4388
4389 negated = validate_immediate (-value);
4390 inverted = validate_immediate (~value);
4391
4392 op = (*instruction >> DATA_OP_SHIFT) & 0xf;
4393 switch (op)
4394 {
4395 /* First negates. */
4396 case OPCODE_SUB: /* ADD <-> SUB */
4397 new_inst = OPCODE_ADD;
4398 value = negated;
4399 break;
4400
4401 case OPCODE_ADD:
4402 new_inst = OPCODE_SUB;
4403 value = negated;
4404 break;
4405
4406 case OPCODE_CMP: /* CMP <-> CMN */
4407 new_inst = OPCODE_CMN;
4408 value = negated;
4409 break;
4410
4411 case OPCODE_CMN:
4412 new_inst = OPCODE_CMP;
4413 value = negated;
4414 break;
4415
4416 /* Now Inverted ops. */
4417 case OPCODE_MOV: /* MOV <-> MVN */
4418 new_inst = OPCODE_MVN;
4419 value = inverted;
4420 break;
4421
4422 case OPCODE_MVN:
4423 new_inst = OPCODE_MOV;
4424 value = inverted;
4425 break;
4426
4427 case OPCODE_AND: /* AND <-> BIC */
4428 new_inst = OPCODE_BIC;
4429 value = inverted;
4430 break;
4431
4432 case OPCODE_BIC:
4433 new_inst = OPCODE_AND;
4434 value = inverted;
4435 break;
4436
4437 case OPCODE_ADC: /* ADC <-> SBC */
4438 new_inst = OPCODE_SBC;
4439 value = inverted;
4440 break;
4441
4442 case OPCODE_SBC:
4443 new_inst = OPCODE_ADC;
4444 value = inverted;
4445 break;
4446
4447 /* We cannot do anything. */
4448 default:
4449 return FAIL;
4450 }
4451
4452 if (value == (unsigned) FAIL)
4453 return FAIL;
4454
4455 *instruction &= OPCODE_MASK;
4456 *instruction |= new_inst << DATA_OP_SHIFT;
4457 return value;
4458}
4459
4460static int
4461data_op2 (str)
4462 char ** str;
4463{
4464 int value;
4465 expressionS expr;
4466
4467 skip_whitespace (* str);
4468
4469 if (reg_required_here (str, 0) != FAIL)
4470 {
4471 if (skip_past_comma (str) == SUCCESS)
4472 /* Shift operation on register. */
4473 return decode_shift (str, NO_SHIFT_RESTRICT);
4474
4475 return SUCCESS;
4476 }
4477 else
4478 {
4479 /* Immediate expression. */
4480 if (is_immediate_prefix (**str))
4481 {
4482 (*str)++;
4483 inst.error = NULL;
4484
4485 if (my_get_expression (&inst.reloc.exp, str))
4486 return FAIL;
4487
4488 if (inst.reloc.exp.X_add_symbol)
4489 {
4490 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
4491 inst.reloc.pc_rel = 0;
4492 }
4493 else
4494 {
4495 if (skip_past_comma (str) == SUCCESS)
4496 {
4497 /* #x, y -- ie explicit rotation by Y. */
4498 if (my_get_expression (&expr, str))
4499 return FAIL;
4500
4501 if (expr.X_op != O_constant)
4502 {
f03698e6 4503 inst.error = _("constant expression expected");
b99bd4ef
NC
4504 return FAIL;
4505 }
4506
4507 /* Rotate must be a multiple of 2. */
4508 if (((unsigned) expr.X_add_number) > 30
4509 || (expr.X_add_number & 1) != 0
4510 || ((unsigned) inst.reloc.exp.X_add_number) > 255)
4511 {
f03698e6 4512 inst.error = _("invalid constant");
b99bd4ef
NC
4513 return FAIL;
4514 }
4515 inst.instruction |= INST_IMMEDIATE;
4516 inst.instruction |= inst.reloc.exp.X_add_number;
4517 inst.instruction |= expr.X_add_number << 7;
4518 return SUCCESS;
4519 }
4520
4521 /* Implicit rotation, select a suitable one. */
4522 value = validate_immediate (inst.reloc.exp.X_add_number);
4523
4524 if (value == FAIL)
4525 {
4526 /* Can't be done. Perhaps the code reads something like
4527 "add Rd, Rn, #-n", where "sub Rd, Rn, #n" would be OK. */
4528 if ((value = negate_data_op (&inst.instruction,
4529 inst.reloc.exp.X_add_number))
4530 == FAIL)
4531 {
f03698e6 4532 inst.error = _("invalid constant");
b99bd4ef
NC
4533 return FAIL;
4534 }
4535 }
4536
4537 inst.instruction |= value;
4538 }
4539
4540 inst.instruction |= INST_IMMEDIATE;
4541 return SUCCESS;
4542 }
4543
4544 (*str)++;
f03698e6 4545 inst.error = _("register or shift expression expected");
b99bd4ef
NC
4546 return FAIL;
4547 }
4548}
4549
4550static int
4551fp_op2 (str)
4552 char ** str;
4553{
4554 skip_whitespace (* str);
4555
4556 if (fp_reg_required_here (str, 0) != FAIL)
4557 return SUCCESS;
4558 else
4559 {
4560 /* Immediate expression. */
4561 if (*((*str)++) == '#')
4562 {
4563 int i;
4564
4565 inst.error = NULL;
4566
4567 skip_whitespace (* str);
4568
4569 /* First try and match exact strings, this is to guarantee
4570 that some formats will work even for cross assembly. */
4571
4572 for (i = 0; fp_const[i]; i++)
4573 {
4574 if (strncmp (*str, fp_const[i], strlen (fp_const[i])) == 0)
4575 {
4576 char *start = *str;
4577
4578 *str += strlen (fp_const[i]);
4579 if (is_end_of_line[(unsigned char) **str])
4580 {
4581 inst.instruction |= i + 8;
4582 return SUCCESS;
4583 }
4584 *str = start;
4585 }
4586 }
4587
4588 /* Just because we didn't get a match doesn't mean that the
4589 constant isn't valid, just that it is in a format that we
4590 don't automatically recognize. Try parsing it with
4591 the standard expression routines. */
4592 if ((i = my_get_float_expression (str)) >= 0)
4593 {
4594 inst.instruction |= i + 8;
4595 return SUCCESS;
4596 }
4597
f03698e6 4598 inst.error = _("invalid floating point immediate expression");
b99bd4ef
NC
4599 return FAIL;
4600 }
4601 inst.error =
f03698e6 4602 _("floating point register or immediate expression expected");
b99bd4ef
NC
4603 return FAIL;
4604 }
4605}
4606
4607static void
f2b7cb0a 4608do_arit (str)
b99bd4ef 4609 char * str;
b99bd4ef
NC
4610{
4611 skip_whitespace (str);
4612
4613 if (reg_required_here (&str, 12) == FAIL
4614 || skip_past_comma (&str) == FAIL
4615 || reg_required_here (&str, 16) == FAIL
4616 || skip_past_comma (&str) == FAIL
4617 || data_op2 (&str) == FAIL)
4618 {
4619 if (!inst.error)
4620 inst.error = BAD_ARGS;
4621 return;
4622 }
4623
b99bd4ef
NC
4624 end_of_line (str);
4625 return;
4626}
4627
4628static void
f2b7cb0a 4629do_adr (str)
b99bd4ef 4630 char * str;
b99bd4ef 4631{
90e4755a
RE
4632 /* This is a pseudo-op of the form "adr rd, label" to be converted
4633 into a relative address of the form "add rd, pc, #label-.-8". */
4634 skip_whitespace (str);
4635
4636 if (reg_required_here (&str, 12) == FAIL
4637 || skip_past_comma (&str) == FAIL
4638 || my_get_expression (&inst.reloc.exp, &str))
4639 {
4640 if (!inst.error)
4641 inst.error = BAD_ARGS;
4642 return;
4643 }
4644
4645 /* Frag hacking will turn this into a sub instruction if the offset turns
4646 out to be negative. */
4647 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
4648 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust. */
4649 inst.reloc.pc_rel = 1;
4650
4651 end_of_line (str);
4652}
4653
4654static void
f2b7cb0a 4655do_adrl (str)
90e4755a 4656 char * str;
90e4755a
RE
4657{
4658 /* This is a pseudo-op of the form "adrl rd, label" to be converted
4659 into a relative address of the form:
4660 add rd, pc, #low(label-.-8)"
4661 add rd, rd, #high(label-.-8)" */
4662
4663 skip_whitespace (str);
4664
4665 if (reg_required_here (&str, 12) == FAIL
4666 || skip_past_comma (&str) == FAIL
4667 || my_get_expression (&inst.reloc.exp, &str))
4668 {
4669 if (!inst.error)
4670 inst.error = BAD_ARGS;
4671
4672 return;
4673 }
4674
4675 end_of_line (str);
4676 /* Frag hacking will turn this into a sub instruction if the offset turns
4677 out to be negative. */
4678 inst.reloc.type = BFD_RELOC_ARM_ADRL_IMMEDIATE;
4679 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust */
4680 inst.reloc.pc_rel = 1;
4681 inst.size = INSN_SIZE * 2;
4682
4683 return;
4684}
4685
4686static void
f2b7cb0a 4687do_cmp (str)
90e4755a 4688 char * str;
90e4755a
RE
4689{
4690 skip_whitespace (str);
4691
4692 if (reg_required_here (&str, 16) == FAIL)
4693 {
4694 if (!inst.error)
4695 inst.error = BAD_ARGS;
4696 return;
4697 }
4698
4699 if (skip_past_comma (&str) == FAIL
4700 || data_op2 (&str) == FAIL)
4701 {
4702 if (!inst.error)
4703 inst.error = BAD_ARGS;
4704 return;
4705 }
4706
90e4755a
RE
4707 end_of_line (str);
4708 return;
4709}
4710
4711static void
f2b7cb0a 4712do_mov (str)
90e4755a 4713 char * str;
90e4755a
RE
4714{
4715 skip_whitespace (str);
4716
4717 if (reg_required_here (&str, 12) == FAIL)
4718 {
4719 if (!inst.error)
4720 inst.error = BAD_ARGS;
4721 return;
4722 }
4723
4724 if (skip_past_comma (&str) == FAIL
4725 || data_op2 (&str) == FAIL)
4726 {
4727 if (!inst.error)
4728 inst.error = BAD_ARGS;
4729 return;
4730 }
4731
90e4755a
RE
4732 end_of_line (str);
4733 return;
4734}
4735
4736static int
4737ldst_extend (str)
4738 char ** str;
4739{
4740 int add = INDEX_UP;
4741
4742 switch (**str)
4743 {
4744 case '#':
4745 case '$':
4746 (*str)++;
4747 if (my_get_expression (& inst.reloc.exp, str))
4748 return FAIL;
4749
4750 if (inst.reloc.exp.X_op == O_constant)
4751 {
4752 int value = inst.reloc.exp.X_add_number;
4753
4754 if (value < -4095 || value > 4095)
4755 {
4756 inst.error = _("address offset too large");
4757 return FAIL;
4758 }
4759
4760 if (value < 0)
4761 {
4762 value = -value;
4763 add = 0;
4764 }
4765
4766 inst.instruction |= add | value;
4767 }
4768 else
4769 {
4770 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
4771 inst.reloc.pc_rel = 0;
4772 }
4773 return SUCCESS;
4774
4775 case '-':
4776 add = 0;
4777 /* Fall through. */
4778
4779 case '+':
4780 (*str)++;
4781 /* Fall through. */
4782
4783 default:
4784 if (reg_required_here (str, 0) == FAIL)
4785 return FAIL;
4786
4787 inst.instruction |= add | OFFSET_REG;
4788 if (skip_past_comma (str) == SUCCESS)
4789 return decode_shift (str, SHIFT_RESTRICT);
4790
4791 return SUCCESS;
4792 }
4793}
4794
4795static void
f2b7cb0a 4796do_ldst (str)
90e4755a 4797 char * str;
90e4755a
RE
4798{
4799 int pre_inc = 0;
4800 int conflict_reg;
4801 int value;
4802
b99bd4ef
NC
4803 skip_whitespace (str);
4804
90e4755a
RE
4805 if ((conflict_reg = reg_required_here (&str, 12)) == FAIL)
4806 {
4807 if (!inst.error)
4808 inst.error = BAD_ARGS;
4809 return;
4810 }
4811
4812 if (skip_past_comma (&str) == FAIL)
4813 {
f03698e6 4814 inst.error = _("address expected");
90e4755a
RE
4815 return;
4816 }
4817
90e4755a
RE
4818 if (*str == '[')
4819 {
4820 int reg;
4821
4822 str++;
4823
4824 skip_whitespace (str);
4825
4826 if ((reg = reg_required_here (&str, 16)) == FAIL)
4827 return;
4828
4829 /* Conflicts can occur on stores as well as loads. */
4830 conflict_reg = (conflict_reg == reg);
4831
4832 skip_whitespace (str);
4833
4834 if (*str == ']')
4835 {
4836 str ++;
4837
4838 if (skip_past_comma (&str) == SUCCESS)
4839 {
4840 /* [Rn],... (post inc) */
4841 if (ldst_extend (&str) == FAIL)
4842 return;
4843 if (conflict_reg)
4844 as_warn (_("%s register same as write-back base"),
4845 ((inst.instruction & LOAD_BIT)
4846 ? _("destination") : _("source")));
4847 }
4848 else
4849 {
4850 /* [Rn] */
4851 skip_whitespace (str);
4852
4853 if (*str == '!')
4854 {
4855 if (conflict_reg)
4856 as_warn (_("%s register same as write-back base"),
4857 ((inst.instruction & LOAD_BIT)
4858 ? _("destination") : _("source")));
4859 str++;
4860 inst.instruction |= WRITE_BACK;
4861 }
4862
4863 inst.instruction |= INDEX_UP;
4864 pre_inc = 1;
4865 }
4866 }
4867 else
4868 {
4869 /* [Rn,...] */
4870 if (skip_past_comma (&str) == FAIL)
4871 {
4872 inst.error = _("pre-indexed expression expected");
4873 return;
4874 }
4875
4876 pre_inc = 1;
4877 if (ldst_extend (&str) == FAIL)
4878 return;
4879
4880 skip_whitespace (str);
4881
4882 if (*str++ != ']')
4883 {
4884 inst.error = _("missing ]");
4885 return;
4886 }
4887
4888 skip_whitespace (str);
4889
4890 if (*str == '!')
4891 {
4892 if (conflict_reg)
4893 as_warn (_("%s register same as write-back base"),
4894 ((inst.instruction & LOAD_BIT)
4895 ? _("destination") : _("source")));
4896 str++;
4897 inst.instruction |= WRITE_BACK;
4898 }
4899 }
4900 }
4901 else if (*str == '=')
4902 {
f03698e6
RE
4903 if ((inst.instruction & LOAD_BIT) == 0)
4904 {
4905 inst.error = _("invalid pseudo operation");
4906 return;
4907 }
4908
90e4755a
RE
4909 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
4910 str++;
4911
4912 skip_whitespace (str);
4913
4914 if (my_get_expression (&inst.reloc.exp, &str))
4915 return;
4916
4917 if (inst.reloc.exp.X_op != O_constant
4918 && inst.reloc.exp.X_op != O_symbol)
4919 {
f03698e6 4920 inst.error = _("constant expression expected");
90e4755a
RE
4921 return;
4922 }
4923
e28cd48c 4924 if (inst.reloc.exp.X_op == O_constant)
90e4755a 4925 {
e28cd48c
RE
4926 value = validate_immediate (inst.reloc.exp.X_add_number);
4927
4928 if (value != FAIL)
90e4755a 4929 {
e28cd48c
RE
4930 /* This can be done with a mov instruction. */
4931 inst.instruction &= LITERAL_MASK;
4932 inst.instruction |= (INST_IMMEDIATE
4933 | (OPCODE_MOV << DATA_OP_SHIFT));
4934 inst.instruction |= value & 0xfff;
4935 end_of_line (str);
90e4755a
RE
4936 return;
4937 }
b99bd4ef 4938
e28cd48c
RE
4939 value = validate_immediate (~inst.reloc.exp.X_add_number);
4940
4941 if (value != FAIL)
4942 {
4943 /* This can be done with a mvn instruction. */
4944 inst.instruction &= LITERAL_MASK;
4945 inst.instruction |= (INST_IMMEDIATE
4946 | (OPCODE_MVN << DATA_OP_SHIFT));
4947 inst.instruction |= value & 0xfff;
4948 end_of_line (str);
4949 return;
4950 }
90e4755a 4951 }
e28cd48c
RE
4952
4953 /* Insert into literal pool. */
4954 if (add_to_lit_pool () == FAIL)
4955 {
4956 if (!inst.error)
4957 inst.error = _("literal pool insertion failed");
4958 return;
4959 }
4960
4961 /* Change the instruction exp to point to the pool. */
4962 inst.reloc.type = BFD_RELOC_ARM_LITERAL;
4963 inst.reloc.pc_rel = 1;
4964 inst.instruction |= (REG_PC << 16);
4965 pre_inc = 1;
1cac9012
NC
4966 }
4967 else
4968 {
90e4755a
RE
4969 if (my_get_expression (&inst.reloc.exp, &str))
4970 return;
4971
4972 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
4973#ifndef TE_WINCE
4974 /* PC rel adjust. */
4975 inst.reloc.exp.X_add_number -= 8;
4976#endif
1cac9012 4977 inst.reloc.pc_rel = 1;
90e4755a
RE
4978 inst.instruction |= (REG_PC << 16);
4979 pre_inc = 1;
b99bd4ef
NC
4980 }
4981
90e4755a 4982 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
b99bd4ef 4983 end_of_line (str);
90e4755a 4984 return;
b99bd4ef
NC
4985}
4986
4987static void
f2b7cb0a 4988do_ldstt (str)
90e4755a 4989 char * str;
b99bd4ef 4990{
90e4755a
RE
4991 int conflict_reg;
4992
b99bd4ef
NC
4993 skip_whitespace (str);
4994
90e4755a 4995 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
b99bd4ef
NC
4996 {
4997 if (!inst.error)
4998 inst.error = BAD_ARGS;
4999 return;
5000 }
5001
90e4755a 5002 if (skip_past_comma (& str) == FAIL)
b99bd4ef 5003 {
f03698e6 5004 inst.error = _("address expected");
b99bd4ef
NC
5005 return;
5006 }
5007
90e4755a
RE
5008 if (*str == '[')
5009 {
5010 int reg;
b99bd4ef 5011
90e4755a 5012 str++;
b99bd4ef 5013
90e4755a 5014 skip_whitespace (str);
b99bd4ef 5015
90e4755a
RE
5016 if ((reg = reg_required_here (&str, 16)) == FAIL)
5017 return;
b99bd4ef 5018
90e4755a
RE
5019 /* ldrt/strt always use post-indexed addressing, so if the base is
5020 the same as Rd, we warn. */
5021 if (conflict_reg == reg)
5022 as_warn (_("%s register same as write-back base"),
5023 ((inst.instruction & LOAD_BIT)
5024 ? _("destination") : _("source")));
5025
5026 skip_whitespace (str);
5027
5028 if (*str == ']')
5029 {
5030 str ++;
5031
5032 if (skip_past_comma (&str) == SUCCESS)
5033 {
5034 /* [Rn],... (post inc) */
5035 if (ldst_extend (&str) == FAIL)
5036 return;
5037 }
5038 else
5039 {
5040 /* [Rn] */
5041 skip_whitespace (str);
5042
5043 /* Skip a write-back '!'. */
5044 if (*str == '!')
5045 str++;
5046
5047 inst.instruction |= INDEX_UP;
5048 }
5049 }
5050 else
5051 {
5052 inst.error = _("post-indexed expression expected");
5053 return;
5054 }
5055 }
5056 else
b99bd4ef 5057 {
90e4755a 5058 inst.error = _("post-indexed expression expected");
b99bd4ef
NC
5059 return;
5060 }
5061
b99bd4ef
NC
5062 end_of_line (str);
5063 return;
5064}
5065
5066static int
90e4755a 5067ldst_extend_v4 (str)
b99bd4ef 5068 char ** str;
b99bd4ef
NC
5069{
5070 int add = INDEX_UP;
5071
5072 switch (**str)
5073 {
5074 case '#':
5075 case '$':
5076 (*str)++;
5077 if (my_get_expression (& inst.reloc.exp, str))
5078 return FAIL;
5079
5080 if (inst.reloc.exp.X_op == O_constant)
5081 {
5082 int value = inst.reloc.exp.X_add_number;
5083
90e4755a 5084 if (value < -255 || value > 255)
b99bd4ef
NC
5085 {
5086 inst.error = _("address offset too large");
5087 return FAIL;
5088 }
5089
5090 if (value < 0)
5091 {
5092 value = -value;
5093 add = 0;
5094 }
5095
5096 /* Halfword and signextension instructions have the
5097 immediate value split across bits 11..8 and bits 3..0. */
90e4755a
RE
5098 inst.instruction |= (add | HWOFFSET_IMM
5099 | ((value >> 4) << 8) | (value & 0xF));
b99bd4ef
NC
5100 }
5101 else
5102 {
90e4755a
RE
5103 inst.instruction |= HWOFFSET_IMM;
5104 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
b99bd4ef
NC
5105 inst.reloc.pc_rel = 0;
5106 }
5107 return SUCCESS;
5108
5109 case '-':
5110 add = 0;
5111 /* Fall through. */
5112
5113 case '+':
5114 (*str)++;
5115 /* Fall through. */
5116
5117 default:
5118 if (reg_required_here (str, 0) == FAIL)
5119 return FAIL;
5120
90e4755a 5121 inst.instruction |= add;
b99bd4ef
NC
5122 return SUCCESS;
5123 }
5124}
5125
90e4755a 5126/* Halfword and signed-byte load/store operations. */
b99bd4ef 5127static void
f2b7cb0a 5128do_ldstv4 (str)
b99bd4ef 5129 char * str;
b99bd4ef 5130{
b99bd4ef
NC
5131 int pre_inc = 0;
5132 int conflict_reg;
5133 int value;
5134
b99bd4ef
NC
5135 skip_whitespace (str);
5136
5137 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
5138 {
5139 if (!inst.error)
5140 inst.error = BAD_ARGS;
5141 return;
5142 }
5143
5144 if (skip_past_comma (& str) == FAIL)
5145 {
f03698e6 5146 inst.error = _("address expected");
b99bd4ef
NC
5147 return;
5148 }
5149
5150 if (*str == '[')
5151 {
5152 int reg;
5153
5154 str++;
5155
5156 skip_whitespace (str);
5157
5158 if ((reg = reg_required_here (&str, 16)) == FAIL)
5159 return;
5160
5161 /* Conflicts can occur on stores as well as loads. */
5162 conflict_reg = (conflict_reg == reg);
5163
5164 skip_whitespace (str);
5165
5166 if (*str == ']')
5167 {
5168 str ++;
5169
5170 if (skip_past_comma (&str) == SUCCESS)
5171 {
5172 /* [Rn],... (post inc) */
90e4755a 5173 if (ldst_extend_v4 (&str) == FAIL)
b99bd4ef
NC
5174 return;
5175 if (conflict_reg)
90e4755a
RE
5176 as_warn (_("%s register same as write-back base"),
5177 ((inst.instruction & LOAD_BIT)
5178 ? _("destination") : _("source")));
b99bd4ef
NC
5179 }
5180 else
5181 {
5182 /* [Rn] */
90e4755a 5183 inst.instruction |= HWOFFSET_IMM;
b99bd4ef
NC
5184
5185 skip_whitespace (str);
5186
5187 if (*str == '!')
5188 {
5189 if (conflict_reg)
5190 as_warn (_("%s register same as write-back base"),
5191 ((inst.instruction & LOAD_BIT)
5192 ? _("destination") : _("source")));
5193 str++;
5194 inst.instruction |= WRITE_BACK;
5195 }
5196
90e4755a
RE
5197 inst.instruction |= INDEX_UP;
5198 pre_inc = 1;
b99bd4ef
NC
5199 }
5200 }
5201 else
5202 {
5203 /* [Rn,...] */
5204 if (skip_past_comma (&str) == FAIL)
5205 {
5206 inst.error = _("pre-indexed expression expected");
5207 return;
5208 }
5209
5210 pre_inc = 1;
90e4755a 5211 if (ldst_extend_v4 (&str) == FAIL)
b99bd4ef
NC
5212 return;
5213
5214 skip_whitespace (str);
5215
5216 if (*str++ != ']')
5217 {
5218 inst.error = _("missing ]");
5219 return;
5220 }
5221
5222 skip_whitespace (str);
5223
5224 if (*str == '!')
5225 {
5226 if (conflict_reg)
5227 as_warn (_("%s register same as write-back base"),
5228 ((inst.instruction & LOAD_BIT)
5229 ? _("destination") : _("source")));
5230 str++;
5231 inst.instruction |= WRITE_BACK;
5232 }
5233 }
5234 }
5235 else if (*str == '=')
5236 {
f03698e6
RE
5237 if ((inst.instruction & LOAD_BIT) == 0)
5238 {
5239 inst.error = _("invalid pseudo operation");
5240 return;
5241 }
5242
90e4755a 5243 /* XXX Does this work correctly for half-word/byte ops? */
b99bd4ef
NC
5244 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
5245 str++;
5246
5247 skip_whitespace (str);
5248
5249 if (my_get_expression (&inst.reloc.exp, &str))
5250 return;
5251
5252 if (inst.reloc.exp.X_op != O_constant
5253 && inst.reloc.exp.X_op != O_symbol)
5254 {
f03698e6 5255 inst.error = _("constant expression expected");
b99bd4ef
NC
5256 return;
5257 }
5258
d8273442 5259 if (inst.reloc.exp.X_op == O_constant)
b99bd4ef 5260 {
d8273442
NC
5261 value = validate_immediate (inst.reloc.exp.X_add_number);
5262
5263 if (value != FAIL)
b99bd4ef 5264 {
d8273442
NC
5265 /* This can be done with a mov instruction. */
5266 inst.instruction &= LITERAL_MASK;
5267 inst.instruction |= INST_IMMEDIATE | (OPCODE_MOV << DATA_OP_SHIFT);
90e4755a 5268 inst.instruction |= value & 0xfff;
d8273442 5269 end_of_line (str);
b99bd4ef
NC
5270 return;
5271 }
d8273442
NC
5272
5273 value = validate_immediate (~ inst.reloc.exp.X_add_number);
b99bd4ef 5274
d8273442 5275 if (value != FAIL)
b99bd4ef 5276 {
d8273442
NC
5277 /* This can be done with a mvn instruction. */
5278 inst.instruction &= LITERAL_MASK;
5279 inst.instruction |= INST_IMMEDIATE | (OPCODE_MVN << DATA_OP_SHIFT);
90e4755a 5280 inst.instruction |= value & 0xfff;
d8273442
NC
5281 end_of_line (str);
5282 return;
b99bd4ef 5283 }
b99bd4ef 5284 }
d8273442
NC
5285
5286 /* Insert into literal pool. */
5287 if (add_to_lit_pool () == FAIL)
5288 {
5289 if (!inst.error)
5290 inst.error = _("literal pool insertion failed");
5291 return;
5292 }
5293
5294 /* Change the instruction exp to point to the pool. */
90e4755a
RE
5295 inst.instruction |= HWOFFSET_IMM;
5296 inst.reloc.type = BFD_RELOC_ARM_HWLITERAL;
d8273442
NC
5297 inst.reloc.pc_rel = 1;
5298 inst.instruction |= (REG_PC << 16);
5299 pre_inc = 1;
b99bd4ef
NC
5300 }
5301 else
5302 {
5303 if (my_get_expression (&inst.reloc.exp, &str))
5304 return;
5305
90e4755a
RE
5306 inst.instruction |= HWOFFSET_IMM;
5307 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
b99bd4ef
NC
5308#ifndef TE_WINCE
5309 /* PC rel adjust. */
5310 inst.reloc.exp.X_add_number -= 8;
5311#endif
5312 inst.reloc.pc_rel = 1;
5313 inst.instruction |= (REG_PC << 16);
5314 pre_inc = 1;
5315 }
5316
90e4755a 5317 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
b99bd4ef
NC
5318 end_of_line (str);
5319 return;
5320}
5321
5322static long
5323reg_list (strp)
5324 char ** strp;
5325{
5326 char * str = * strp;
5327 long range = 0;
5328 int another_range;
5329
5330 /* We come back here if we get ranges concatenated by '+' or '|'. */
5331 do
5332 {
5333 another_range = 0;
5334
5335 if (*str == '{')
5336 {
5337 int in_range = 0;
5338 int cur_reg = -1;
5339
5340 str++;
5341 do
5342 {
5343 int reg;
5344
5345 skip_whitespace (str);
5346
5347 if ((reg = reg_required_here (& str, -1)) == FAIL)
5348 return FAIL;
5349
5350 if (in_range)
5351 {
5352 int i;
5353
5354 if (reg <= cur_reg)
5355 {
f03698e6 5356 inst.error = _("bad range in register list");
b99bd4ef
NC
5357 return FAIL;
5358 }
5359
5360 for (i = cur_reg + 1; i < reg; i++)
5361 {
5362 if (range & (1 << i))
5363 as_tsktsk
f03698e6 5364 (_("Warning: duplicated register (r%d) in register list"),
b99bd4ef
NC
5365 i);
5366 else
5367 range |= 1 << i;
5368 }
5369 in_range = 0;
5370 }
5371
5372 if (range & (1 << reg))
f03698e6 5373 as_tsktsk (_("Warning: duplicated register (r%d) in register list"),
b99bd4ef
NC
5374 reg);
5375 else if (reg <= cur_reg)
f03698e6 5376 as_tsktsk (_("Warning: register range not in ascending order"));
b99bd4ef
NC
5377
5378 range |= 1 << reg;
5379 cur_reg = reg;
5380 }
5381 while (skip_past_comma (&str) != FAIL
5382 || (in_range = 1, *str++ == '-'));
5383 str--;
5384 skip_whitespace (str);
5385
5386 if (*str++ != '}')
5387 {
f03698e6 5388 inst.error = _("missing `}'");
b99bd4ef
NC
5389 return FAIL;
5390 }
5391 }
5392 else
5393 {
5394 expressionS expr;
5395
5396 if (my_get_expression (&expr, &str))
5397 return FAIL;
5398
5399 if (expr.X_op == O_constant)
5400 {
5401 if (expr.X_add_number
5402 != (expr.X_add_number & 0x0000ffff))
5403 {
5404 inst.error = _("invalid register mask");
5405 return FAIL;
5406 }
5407
5408 if ((range & expr.X_add_number) != 0)
5409 {
5410 int regno = range & expr.X_add_number;
5411
5412 regno &= -regno;
5413 regno = (1 << regno) - 1;
5414 as_tsktsk
f03698e6 5415 (_("Warning: duplicated register (r%d) in register list"),
b99bd4ef
NC
5416 regno);
5417 }
5418
5419 range |= expr.X_add_number;
5420 }
5421 else
5422 {
5423 if (inst.reloc.type != 0)
5424 {
5425 inst.error = _("expression too complex");
5426 return FAIL;
5427 }
5428
5429 memcpy (&inst.reloc.exp, &expr, sizeof (expressionS));
5430 inst.reloc.type = BFD_RELOC_ARM_MULTI;
5431 inst.reloc.pc_rel = 0;
5432 }
5433 }
5434
5435 skip_whitespace (str);
5436
5437 if (*str == '|' || *str == '+')
5438 {
5439 str++;
5440 another_range = 1;
5441 }
5442 }
5443 while (another_range);
5444
5445 *strp = str;
5446 return range;
5447}
5448
5449static void
f2b7cb0a 5450do_ldmstm (str)
b99bd4ef 5451 char * str;
b99bd4ef
NC
5452{
5453 int base_reg;
5454 long range;
5455
5456 skip_whitespace (str);
5457
5458 if ((base_reg = reg_required_here (&str, 16)) == FAIL)
5459 return;
5460
5461 if (base_reg == REG_PC)
5462 {
5463 inst.error = _("r15 not allowed as base register");
5464 return;
5465 }
5466
5467 skip_whitespace (str);
5468
5469 if (*str == '!')
5470 {
90e4755a 5471 inst.instruction |= WRITE_BACK;
b99bd4ef
NC
5472 str++;
5473 }
5474
5475 if (skip_past_comma (&str) == FAIL
5476 || (range = reg_list (&str)) == FAIL)
5477 {
5478 if (! inst.error)
5479 inst.error = BAD_ARGS;
5480 return;
5481 }
5482
5483 if (*str == '^')
5484 {
5485 str++;
90e4755a 5486 inst.instruction |= LDM_TYPE_2_OR_3;
b99bd4ef
NC
5487 }
5488
f2b7cb0a 5489 inst.instruction |= range;
b99bd4ef
NC
5490 end_of_line (str);
5491 return;
5492}
5493
5494static void
f2b7cb0a 5495do_swi (str)
b99bd4ef 5496 char * str;
b99bd4ef
NC
5497{
5498 skip_whitespace (str);
5499
5500 /* Allow optional leading '#'. */
5501 if (is_immediate_prefix (*str))
5502 str++;
5503
5504 if (my_get_expression (& inst.reloc.exp, & str))
5505 return;
5506
5507 inst.reloc.type = BFD_RELOC_ARM_SWI;
5508 inst.reloc.pc_rel = 0;
b99bd4ef
NC
5509 end_of_line (str);
5510
5511 return;
5512}
5513
5514static void
f2b7cb0a 5515do_swap (str)
b99bd4ef 5516 char * str;
b99bd4ef
NC
5517{
5518 int reg;
5519
5520 skip_whitespace (str);
5521
5522 if ((reg = reg_required_here (&str, 12)) == FAIL)
5523 return;
5524
5525 if (reg == REG_PC)
5526 {
5527 inst.error = _("r15 not allowed in swap");
5528 return;
5529 }
5530
5531 if (skip_past_comma (&str) == FAIL
5532 || (reg = reg_required_here (&str, 0)) == FAIL)
5533 {
5534 if (!inst.error)
5535 inst.error = BAD_ARGS;
5536 return;
5537 }
5538
5539 if (reg == REG_PC)
5540 {
5541 inst.error = _("r15 not allowed in swap");
5542 return;
5543 }
5544
5545 if (skip_past_comma (&str) == FAIL
5546 || *str++ != '[')
5547 {
5548 inst.error = BAD_ARGS;
5549 return;
5550 }
5551
5552 skip_whitespace (str);
5553
5554 if ((reg = reg_required_here (&str, 16)) == FAIL)
5555 return;
5556
5557 if (reg == REG_PC)
5558 {
5559 inst.error = BAD_PC;
5560 return;
5561 }
5562
5563 skip_whitespace (str);
5564
5565 if (*str++ != ']')
5566 {
5567 inst.error = _("missing ]");
5568 return;
5569 }
5570
b99bd4ef
NC
5571 end_of_line (str);
5572 return;
5573}
5574
5575static void
f2b7cb0a 5576do_branch (str)
b99bd4ef 5577 char * str;
b99bd4ef
NC
5578{
5579 if (my_get_expression (&inst.reloc.exp, &str))
5580 return;
5581
5582#ifdef OBJ_ELF
5583 {
5584 char * save_in;
5585
5586 /* ScottB: February 5, 1998 - Check to see of PLT32 reloc
5587 required for the instruction. */
5588
5589 /* arm_parse_reloc () works on input_line_pointer.
5590 We actually want to parse the operands to the branch instruction
5591 passed in 'str'. Save the input pointer and restore it later. */
5592 save_in = input_line_pointer;
5593 input_line_pointer = str;
5594 if (inst.reloc.exp.X_op == O_symbol
5595 && *str == '('
5596 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
5597 {
5598 inst.reloc.type = BFD_RELOC_ARM_PLT32;
5599 inst.reloc.pc_rel = 0;
5600 /* Modify str to point to after parsed operands, otherwise
5601 end_of_line() will complain about the (PLT) left in str. */
5602 str = input_line_pointer;
5603 }
5604 else
5605 {
5606 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
5607 inst.reloc.pc_rel = 1;
5608 }
5609 input_line_pointer = save_in;
5610 }
5611#else
5612 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
5613 inst.reloc.pc_rel = 1;
5614#endif /* OBJ_ELF */
5615
5616 end_of_line (str);
5617 return;
5618}
5619
5620static void
f2b7cb0a 5621do_bx (str)
b99bd4ef 5622 char * str;
b99bd4ef
NC
5623{
5624 int reg;
5625
5626 skip_whitespace (str);
5627
5628 if ((reg = reg_required_here (&str, 0)) == FAIL)
5629 {
5630 inst.error = BAD_ARGS;
5631 return;
5632 }
5633
5634 /* Note - it is not illegal to do a "bx pc". Useless, but not illegal. */
5635 if (reg == REG_PC)
f03698e6 5636 as_tsktsk (_("use of r15 in bx in ARM mode is not really useful"));
b99bd4ef
NC
5637
5638 end_of_line (str);
5639}
5640
5641static void
f2b7cb0a 5642do_cdp (str)
b99bd4ef 5643 char * str;
b99bd4ef
NC
5644{
5645 /* Co-processor data operation.
5646 Format: CDP{cond} CP#,<expr>,CRd,CRn,CRm{,<expr>} */
5647 skip_whitespace (str);
5648
5649 if (co_proc_number (&str) == FAIL)
5650 {
5651 if (!inst.error)
5652 inst.error = BAD_ARGS;
5653 return;
5654 }
5655
5656 if (skip_past_comma (&str) == FAIL
5657 || cp_opc_expr (&str, 20,4) == FAIL)
5658 {
5659 if (!inst.error)
5660 inst.error = BAD_ARGS;
5661 return;
5662 }
5663
5664 if (skip_past_comma (&str) == FAIL
5665 || cp_reg_required_here (&str, 12) == FAIL)
5666 {
5667 if (!inst.error)
5668 inst.error = BAD_ARGS;
5669 return;
5670 }
5671
5672 if (skip_past_comma (&str) == FAIL
5673 || cp_reg_required_here (&str, 16) == 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, 0) == FAIL)
5682 {
5683 if (!inst.error)
5684 inst.error = BAD_ARGS;
5685 return;
5686 }
5687
5688 if (skip_past_comma (&str) == SUCCESS)
5689 {
5690 if (cp_opc_expr (&str, 5, 3) == FAIL)
5691 {
5692 if (!inst.error)
5693 inst.error = BAD_ARGS;
5694 return;
5695 }
5696 }
5697
5698 end_of_line (str);
5699 return;
5700}
5701
5702static void
f2b7cb0a 5703do_lstc (str)
b99bd4ef 5704 char * str;
b99bd4ef
NC
5705{
5706 /* Co-processor register load/store.
5707 Format: <LDC|STC{cond}[L] CP#,CRd,<address> */
5708
5709 skip_whitespace (str);
5710
5711 if (co_proc_number (&str) == FAIL)
5712 {
5713 if (!inst.error)
5714 inst.error = BAD_ARGS;
5715 return;
5716 }
5717
5718 if (skip_past_comma (&str) == FAIL
5719 || cp_reg_required_here (&str, 12) == FAIL)
5720 {
5721 if (!inst.error)
5722 inst.error = BAD_ARGS;
5723 return;
5724 }
5725
5726 if (skip_past_comma (&str) == FAIL
5727 || cp_address_required_here (&str) == FAIL)
5728 {
5729 if (! inst.error)
5730 inst.error = BAD_ARGS;
5731 return;
5732 }
5733
b99bd4ef
NC
5734 end_of_line (str);
5735 return;
5736}
5737
5738static void
f2b7cb0a 5739do_co_reg (str)
b99bd4ef 5740 char * str;
b99bd4ef
NC
5741{
5742 /* Co-processor register transfer.
5743 Format: <MCR|MRC>{cond} CP#,<expr1>,Rd,CRn,CRm{,<expr2>} */
5744
5745 skip_whitespace (str);
5746
5747 if (co_proc_number (&str) == FAIL)
5748 {
5749 if (!inst.error)
5750 inst.error = BAD_ARGS;
5751 return;
5752 }
5753
5754 if (skip_past_comma (&str) == FAIL
5755 || cp_opc_expr (&str, 21, 3) == FAIL)
5756 {
5757 if (!inst.error)
5758 inst.error = BAD_ARGS;
5759 return;
5760 }
5761
5762 if (skip_past_comma (&str) == FAIL
5763 || reg_required_here (&str, 12) == FAIL)
5764 {
5765 if (!inst.error)
5766 inst.error = BAD_ARGS;
5767 return;
5768 }
5769
5770 if (skip_past_comma (&str) == FAIL
5771 || cp_reg_required_here (&str, 16) == FAIL)
5772 {
5773 if (!inst.error)
5774 inst.error = BAD_ARGS;
5775 return;
5776 }
5777
5778 if (skip_past_comma (&str) == FAIL
5779 || cp_reg_required_here (&str, 0) == FAIL)
5780 {
5781 if (!inst.error)
5782 inst.error = BAD_ARGS;
5783 return;
5784 }
5785
5786 if (skip_past_comma (&str) == SUCCESS)
5787 {
5788 if (cp_opc_expr (&str, 5, 3) == FAIL)
5789 {
5790 if (!inst.error)
5791 inst.error = BAD_ARGS;
5792 return;
5793 }
5794 }
b99bd4ef
NC
5795
5796 end_of_line (str);
5797 return;
5798}
5799
5800static void
f2b7cb0a 5801do_fpa_ctrl (str)
b99bd4ef 5802 char * str;
b99bd4ef
NC
5803{
5804 /* FP control registers.
5805 Format: <WFS|RFS|WFC|RFC>{cond} Rn */
5806
5807 skip_whitespace (str);
5808
5809 if (reg_required_here (&str, 12) == FAIL)
5810 {
5811 if (!inst.error)
5812 inst.error = BAD_ARGS;
5813 return;
5814 }
5815
5816 end_of_line (str);
5817 return;
5818}
5819
5820static void
f2b7cb0a 5821do_fpa_ldst (str)
b99bd4ef 5822 char * str;
b99bd4ef
NC
5823{
5824 skip_whitespace (str);
5825
b99bd4ef
NC
5826 if (fp_reg_required_here (&str, 12) == FAIL)
5827 {
5828 if (!inst.error)
5829 inst.error = BAD_ARGS;
5830 return;
5831 }
5832
5833 if (skip_past_comma (&str) == FAIL
5834 || cp_address_required_here (&str) == FAIL)
5835 {
5836 if (!inst.error)
5837 inst.error = BAD_ARGS;
5838 return;
5839 }
5840
5841 end_of_line (str);
5842}
5843
5844static void
f2b7cb0a 5845do_fpa_ldmstm (str)
b99bd4ef 5846 char * str;
b99bd4ef
NC
5847{
5848 int num_regs;
5849
5850 skip_whitespace (str);
5851
5852 if (fp_reg_required_here (&str, 12) == FAIL)
5853 {
5854 if (! inst.error)
5855 inst.error = BAD_ARGS;
5856 return;
5857 }
5858
5859 /* Get Number of registers to transfer. */
5860 if (skip_past_comma (&str) == FAIL
5861 || my_get_expression (&inst.reloc.exp, &str))
5862 {
5863 if (! inst.error)
5864 inst.error = _("constant expression expected");
5865 return;
5866 }
5867
5868 if (inst.reloc.exp.X_op != O_constant)
5869 {
f03698e6 5870 inst.error = _("constant value required for number of registers");
b99bd4ef
NC
5871 return;
5872 }
5873
5874 num_regs = inst.reloc.exp.X_add_number;
5875
5876 if (num_regs < 1 || num_regs > 4)
5877 {
5878 inst.error = _("number of registers must be in the range [1:4]");
5879 return;
5880 }
5881
5882 switch (num_regs)
5883 {
5884 case 1:
5885 inst.instruction |= CP_T_X;
5886 break;
5887 case 2:
5888 inst.instruction |= CP_T_Y;
5889 break;
5890 case 3:
5891 inst.instruction |= CP_T_Y | CP_T_X;
5892 break;
5893 case 4:
5894 break;
5895 default:
5896 abort ();
5897 }
5898
e28cd48c 5899 if (inst.instruction & (CP_T_Pre | CP_T_UD)) /* ea/fd format. */
b99bd4ef
NC
5900 {
5901 int reg;
5902 int write_back;
5903 int offset;
5904
5905 /* The instruction specified "ea" or "fd", so we can only accept
5906 [Rn]{!}. The instruction does not really support stacking or
5907 unstacking, so we have to emulate these by setting appropriate
5908 bits and offsets. */
5909 if (skip_past_comma (&str) == FAIL
5910 || *str != '[')
5911 {
5912 if (! inst.error)
5913 inst.error = BAD_ARGS;
5914 return;
5915 }
5916
5917 str++;
5918 skip_whitespace (str);
5919
5920 if ((reg = reg_required_here (&str, 16)) == FAIL)
5921 return;
5922
5923 skip_whitespace (str);
5924
5925 if (*str != ']')
5926 {
5927 inst.error = BAD_ARGS;
5928 return;
5929 }
5930
5931 str++;
5932 if (*str == '!')
5933 {
5934 write_back = 1;
5935 str++;
5936 if (reg == REG_PC)
5937 {
5938 inst.error =
f03698e6 5939 _("r15 not allowed as base register with write-back");
b99bd4ef
NC
5940 return;
5941 }
5942 }
5943 else
5944 write_back = 0;
5945
90e4755a 5946 if (inst.instruction & CP_T_Pre)
b99bd4ef
NC
5947 {
5948 /* Pre-decrement. */
5949 offset = 3 * num_regs;
5950 if (write_back)
90e4755a 5951 inst.instruction |= CP_T_WB;
b99bd4ef
NC
5952 }
5953 else
5954 {
5955 /* Post-increment. */
5956 if (write_back)
5957 {
90e4755a 5958 inst.instruction |= CP_T_WB;
b99bd4ef
NC
5959 offset = 3 * num_regs;
5960 }
5961 else
5962 {
5963 /* No write-back, so convert this into a standard pre-increment
5964 instruction -- aesthetically more pleasing. */
90e4755a 5965 inst.instruction |= CP_T_Pre | CP_T_UD;
b99bd4ef
NC
5966 offset = 0;
5967 }
5968 }
5969
f2b7cb0a 5970 inst.instruction |= offset;
b99bd4ef
NC
5971 }
5972 else if (skip_past_comma (&str) == FAIL
5973 || cp_address_required_here (&str) == FAIL)
5974 {
5975 if (! inst.error)
5976 inst.error = BAD_ARGS;
5977 return;
5978 }
5979
5980 end_of_line (str);
5981}
5982
5983static void
f2b7cb0a 5984do_fpa_dyadic (str)
b99bd4ef 5985 char * str;
b99bd4ef
NC
5986{
5987 skip_whitespace (str);
5988
b99bd4ef
NC
5989 if (fp_reg_required_here (&str, 12) == FAIL)
5990 {
5991 if (! inst.error)
5992 inst.error = BAD_ARGS;
5993 return;
5994 }
5995
5996 if (skip_past_comma (&str) == FAIL
5997 || fp_reg_required_here (&str, 16) == FAIL)
5998 {
5999 if (! inst.error)
6000 inst.error = BAD_ARGS;
6001 return;
6002 }
6003
6004 if (skip_past_comma (&str) == FAIL
6005 || fp_op2 (&str) == FAIL)
6006 {
6007 if (! inst.error)
6008 inst.error = BAD_ARGS;
6009 return;
6010 }
6011
b99bd4ef
NC
6012 end_of_line (str);
6013 return;
6014}
6015
6016static void
f2b7cb0a 6017do_fpa_monadic (str)
b99bd4ef 6018 char * str;
b99bd4ef
NC
6019{
6020 skip_whitespace (str);
6021
b99bd4ef
NC
6022 if (fp_reg_required_here (&str, 12) == FAIL)
6023 {
6024 if (! inst.error)
6025 inst.error = BAD_ARGS;
6026 return;
6027 }
6028
6029 if (skip_past_comma (&str) == FAIL
6030 || fp_op2 (&str) == FAIL)
6031 {
6032 if (! inst.error)
6033 inst.error = BAD_ARGS;
6034 return;
6035 }
6036
b99bd4ef
NC
6037 end_of_line (str);
6038 return;
6039}
6040
6041static void
f2b7cb0a 6042do_fpa_cmp (str)
b99bd4ef 6043 char * str;
b99bd4ef
NC
6044{
6045 skip_whitespace (str);
6046
6047 if (fp_reg_required_here (&str, 16) == FAIL)
6048 {
6049 if (! inst.error)
6050 inst.error = BAD_ARGS;
6051 return;
6052 }
6053
6054 if (skip_past_comma (&str) == FAIL
6055 || fp_op2 (&str) == FAIL)
6056 {
6057 if (! inst.error)
6058 inst.error = BAD_ARGS;
6059 return;
6060 }
6061
b99bd4ef
NC
6062 end_of_line (str);
6063 return;
6064}
6065
6066static void
f2b7cb0a 6067do_fpa_from_reg (str)
b99bd4ef 6068 char * str;
b99bd4ef
NC
6069{
6070 skip_whitespace (str);
6071
b99bd4ef
NC
6072 if (fp_reg_required_here (&str, 16) == FAIL)
6073 {
6074 if (! inst.error)
6075 inst.error = BAD_ARGS;
6076 return;
6077 }
6078
6079 if (skip_past_comma (&str) == FAIL
6080 || reg_required_here (&str, 12) == FAIL)
6081 {
6082 if (! inst.error)
6083 inst.error = BAD_ARGS;
6084 return;
6085 }
6086
b99bd4ef
NC
6087 end_of_line (str);
6088 return;
6089}
6090
6091static void
f2b7cb0a 6092do_fpa_to_reg (str)
b99bd4ef 6093 char * str;
b99bd4ef
NC
6094{
6095 skip_whitespace (str);
6096
6097 if (reg_required_here (&str, 12) == FAIL)
6098 return;
6099
6100 if (skip_past_comma (&str) == FAIL
6101 || fp_reg_required_here (&str, 0) == FAIL)
6102 {
6103 if (! inst.error)
6104 inst.error = BAD_ARGS;
6105 return;
6106 }
6107
b99bd4ef
NC
6108 end_of_line (str);
6109 return;
6110}
6111
6112/* Thumb specific routines. */
6113
6114/* Parse and validate that a register is of the right form, this saves
6115 repeated checking of this information in many similar cases.
6116 Unlike the 32-bit case we do not insert the register into the opcode
6117 here, since the position is often unknown until the full instruction
6118 has been parsed. */
6119
6120static int
6121thumb_reg (strp, hi_lo)
6122 char ** strp;
6123 int hi_lo;
6124{
6125 int reg;
6126
6127 if ((reg = reg_required_here (strp, -1)) == FAIL)
6128 return FAIL;
6129
6130 switch (hi_lo)
6131 {
6132 case THUMB_REG_LO:
6133 if (reg > 7)
6134 {
6135 inst.error = _("lo register required");
6136 return FAIL;
6137 }
6138 break;
6139
6140 case THUMB_REG_HI:
6141 if (reg < 8)
6142 {
6143 inst.error = _("hi register required");
6144 return FAIL;
6145 }
6146 break;
6147
6148 default:
6149 break;
6150 }
6151
6152 return reg;
6153}
6154
6155/* Parse an add or subtract instruction, SUBTRACT is non-zero if the opcode
6156 was SUB. */
6157
6158static void
6159thumb_add_sub (str, subtract)
6160 char * str;
6161 int subtract;
6162{
6163 int Rd, Rs, Rn = FAIL;
6164
6165 skip_whitespace (str);
6166
6167 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
6168 || skip_past_comma (&str) == FAIL)
6169 {
6170 if (! inst.error)
6171 inst.error = BAD_ARGS;
6172 return;
6173 }
6174
6175 if (is_immediate_prefix (*str))
6176 {
6177 Rs = Rd;
6178 str++;
6179 if (my_get_expression (&inst.reloc.exp, &str))
6180 return;
6181 }
6182 else
6183 {
6184 if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
6185 return;
6186
6187 if (skip_past_comma (&str) == FAIL)
6188 {
6189 /* Two operand format, shuffle the registers
6190 and pretend there are 3. */
6191 Rn = Rs;
6192 Rs = Rd;
6193 }
6194 else if (is_immediate_prefix (*str))
6195 {
6196 str++;
6197 if (my_get_expression (&inst.reloc.exp, &str))
6198 return;
6199 }
6200 else if ((Rn = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
6201 return;
6202 }
6203
6204 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
6205 for the latter case, EXPR contains the immediate that was found. */
6206 if (Rn != FAIL)
6207 {
6208 /* All register format. */
6209 if (Rd > 7 || Rs > 7 || Rn > 7)
6210 {
6211 if (Rs != Rd)
6212 {
6213 inst.error = _("dest and source1 must be the same register");
6214 return;
6215 }
6216
6217 /* Can't do this for SUB. */
6218 if (subtract)
6219 {
6220 inst.error = _("subtract valid only on lo regs");
6221 return;
6222 }
6223
6224 inst.instruction = (T_OPCODE_ADD_HI
6225 | (Rd > 7 ? THUMB_H1 : 0)
6226 | (Rn > 7 ? THUMB_H2 : 0));
6227 inst.instruction |= (Rd & 7) | ((Rn & 7) << 3);
6228 }
6229 else
6230 {
6231 inst.instruction = subtract ? T_OPCODE_SUB_R3 : T_OPCODE_ADD_R3;
6232 inst.instruction |= Rd | (Rs << 3) | (Rn << 6);
6233 }
6234 }
6235 else
6236 {
6237 /* Immediate expression, now things start to get nasty. */
6238
6239 /* First deal with HI regs, only very restricted cases allowed:
6240 Adjusting SP, and using PC or SP to get an address. */
6241 if ((Rd > 7 && (Rd != REG_SP || Rs != REG_SP))
6242 || (Rs > 7 && Rs != REG_SP && Rs != REG_PC))
6243 {
6244 inst.error = _("invalid Hi register with immediate");
6245 return;
6246 }
6247
6248 if (inst.reloc.exp.X_op != O_constant)
6249 {
6250 /* Value isn't known yet, all we can do is store all the fragments
6251 we know about in the instruction and let the reloc hacking
6252 work it all out. */
6253 inst.instruction = (subtract ? 0x8000 : 0) | (Rd << 4) | Rs;
6254 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
6255 }
6256 else
6257 {
6258 int offset = inst.reloc.exp.X_add_number;
6259
6260 if (subtract)
6261 offset = -offset;
6262
6263 if (offset < 0)
6264 {
6265 offset = -offset;
6266 subtract = 1;
6267
6268 /* Quick check, in case offset is MIN_INT. */
6269 if (offset < 0)
6270 {
6271 inst.error = _("immediate value out of range");
6272 return;
6273 }
6274 }
6275 else
6276 subtract = 0;
6277
6278 if (Rd == REG_SP)
6279 {
6280 if (offset & ~0x1fc)
6281 {
6282 inst.error = _("invalid immediate value for stack adjust");
6283 return;
6284 }
6285 inst.instruction = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
6286 inst.instruction |= offset >> 2;
6287 }
6288 else if (Rs == REG_PC || Rs == REG_SP)
6289 {
6290 if (subtract
6291 || (offset & ~0x3fc))
6292 {
6293 inst.error = _("invalid immediate for address calculation");
6294 return;
6295 }
6296 inst.instruction = (Rs == REG_PC ? T_OPCODE_ADD_PC
6297 : T_OPCODE_ADD_SP);
6298 inst.instruction |= (Rd << 8) | (offset >> 2);
6299 }
6300 else if (Rs == Rd)
6301 {
6302 if (offset & ~0xff)
6303 {
6304 inst.error = _("immediate value out of range");
6305 return;
6306 }
6307 inst.instruction = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
6308 inst.instruction |= (Rd << 8) | offset;
6309 }
6310 else
6311 {
6312 if (offset & ~0x7)
6313 {
6314 inst.error = _("immediate value out of range");
6315 return;
6316 }
6317 inst.instruction = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
6318 inst.instruction |= Rd | (Rs << 3) | (offset << 6);
6319 }
6320 }
6321 }
6322
6323 end_of_line (str);
6324}
6325
6326static void
6327thumb_shift (str, shift)
6328 char * str;
6329 int shift;
6330{
6331 int Rd, Rs, Rn = FAIL;
6332
6333 skip_whitespace (str);
6334
6335 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
6336 || skip_past_comma (&str) == FAIL)
6337 {
6338 if (! inst.error)
6339 inst.error = BAD_ARGS;
6340 return;
6341 }
6342
6343 if (is_immediate_prefix (*str))
6344 {
6345 /* Two operand immediate format, set Rs to Rd. */
6346 Rs = Rd;
6347 str ++;
6348 if (my_get_expression (&inst.reloc.exp, &str))
6349 return;
6350 }
6351 else
6352 {
6353 if ((Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
6354 return;
6355
6356 if (skip_past_comma (&str) == FAIL)
6357 {
6358 /* Two operand format, shuffle the registers
6359 and pretend there are 3. */
6360 Rn = Rs;
6361 Rs = Rd;
6362 }
6363 else if (is_immediate_prefix (*str))
6364 {
6365 str++;
6366 if (my_get_expression (&inst.reloc.exp, &str))
6367 return;
6368 }
6369 else if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
6370 return;
6371 }
6372
6373 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
6374 for the latter case, EXPR contains the immediate that was found. */
6375
6376 if (Rn != FAIL)
6377 {
6378 if (Rs != Rd)
6379 {
6380 inst.error = _("source1 and dest must be same register");
6381 return;
6382 }
6383
6384 switch (shift)
6385 {
6386 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_R; break;
6387 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_R; break;
6388 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_R; break;
6389 }
6390
6391 inst.instruction |= Rd | (Rn << 3);
6392 }
6393 else
6394 {
6395 switch (shift)
6396 {
6397 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_I; break;
6398 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_I; break;
6399 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_I; break;
6400 }
6401
6402 if (inst.reloc.exp.X_op != O_constant)
6403 {
6404 /* Value isn't known yet, create a dummy reloc and let reloc
6405 hacking fix it up. */
6406 inst.reloc.type = BFD_RELOC_ARM_THUMB_SHIFT;
6407 }
6408 else
6409 {
6410 unsigned shift_value = inst.reloc.exp.X_add_number;
6411
6412 if (shift_value > 32 || (shift_value == 32 && shift == THUMB_LSL))
6413 {
f03698e6 6414 inst.error = _("invalid immediate for shift");
b99bd4ef
NC
6415 return;
6416 }
6417
6418 /* Shifts of zero are handled by converting to LSL. */
6419 if (shift_value == 0)
6420 inst.instruction = T_OPCODE_LSL_I;
6421
6422 /* Shifts of 32 are encoded as a shift of zero. */
6423 if (shift_value == 32)
6424 shift_value = 0;
6425
6426 inst.instruction |= shift_value << 6;
6427 }
6428
6429 inst.instruction |= Rd | (Rs << 3);
6430 }
6431
6432 end_of_line (str);
6433}
6434
6435static void
6436thumb_mov_compare (str, move)
6437 char * str;
6438 int move;
6439{
6440 int Rd, Rs = FAIL;
6441
6442 skip_whitespace (str);
6443
6444 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
6445 || skip_past_comma (&str) == FAIL)
6446 {
6447 if (! inst.error)
6448 inst.error = BAD_ARGS;
6449 return;
6450 }
6451
6452 if (is_immediate_prefix (*str))
6453 {
6454 str++;
6455 if (my_get_expression (&inst.reloc.exp, &str))
6456 return;
6457 }
6458 else if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
6459 return;
6460
6461 if (Rs != FAIL)
6462 {
6463 if (Rs < 8 && Rd < 8)
6464 {
6465 if (move == THUMB_MOVE)
6466 /* A move of two lowregs is encoded as ADD Rd, Rs, #0
6467 since a MOV instruction produces unpredictable results. */
6468 inst.instruction = T_OPCODE_ADD_I3;
6469 else
6470 inst.instruction = T_OPCODE_CMP_LR;
6471 inst.instruction |= Rd | (Rs << 3);
6472 }
6473 else
6474 {
6475 if (move == THUMB_MOVE)
6476 inst.instruction = T_OPCODE_MOV_HR;
6477 else
6478 inst.instruction = T_OPCODE_CMP_HR;
6479
6480 if (Rd > 7)
6481 inst.instruction |= THUMB_H1;
6482
6483 if (Rs > 7)
6484 inst.instruction |= THUMB_H2;
6485
6486 inst.instruction |= (Rd & 7) | ((Rs & 7) << 3);
6487 }
6488 }
6489 else
6490 {
6491 if (Rd > 7)
6492 {
6493 inst.error = _("only lo regs allowed with immediate");
6494 return;
6495 }
6496
6497 if (move == THUMB_MOVE)
6498 inst.instruction = T_OPCODE_MOV_I8;
6499 else
6500 inst.instruction = T_OPCODE_CMP_I8;
6501
6502 inst.instruction |= Rd << 8;
6503
6504 if (inst.reloc.exp.X_op != O_constant)
6505 inst.reloc.type = BFD_RELOC_ARM_THUMB_IMM;
6506 else
6507 {
6508 unsigned value = inst.reloc.exp.X_add_number;
6509
6510 if (value > 255)
6511 {
6512 inst.error = _("invalid immediate");
6513 return;
6514 }
6515
6516 inst.instruction |= value;
6517 }
6518 }
6519
6520 end_of_line (str);
6521}
6522
6523static void
6524thumb_load_store (str, load_store, size)
6525 char * str;
6526 int load_store;
6527 int size;
6528{
6529 int Rd, Rb, Ro = FAIL;
6530
6531 skip_whitespace (str);
6532
6533 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
6534 || skip_past_comma (&str) == FAIL)
6535 {
6536 if (! inst.error)
6537 inst.error = BAD_ARGS;
6538 return;
6539 }
6540
6541 if (*str == '[')
6542 {
6543 str++;
6544 if ((Rb = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
6545 return;
6546
6547 if (skip_past_comma (&str) != FAIL)
6548 {
6549 if (is_immediate_prefix (*str))
6550 {
6551 str++;
6552 if (my_get_expression (&inst.reloc.exp, &str))
6553 return;
6554 }
6555 else if ((Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
6556 return;
6557 }
6558 else
6559 {
6560 inst.reloc.exp.X_op = O_constant;
6561 inst.reloc.exp.X_add_number = 0;
6562 }
6563
6564 if (*str != ']')
6565 {
6566 inst.error = _("expected ']'");
6567 return;
6568 }
6569 str++;
6570 }
6571 else if (*str == '=')
6572 {
f03698e6
RE
6573 if (load_store != THUMB_LOAD)
6574 {
6575 inst.error = _("invalid pseudo operation");
6576 return;
6577 }
6578
b99bd4ef
NC
6579 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
6580 str++;
6581
6582 skip_whitespace (str);
6583
6584 if (my_get_expression (& inst.reloc.exp, & str))
6585 return;
6586
6587 end_of_line (str);
6588
6589 if ( inst.reloc.exp.X_op != O_constant
6590 && inst.reloc.exp.X_op != O_symbol)
6591 {
6592 inst.error = "Constant expression expected";
6593 return;
6594 }
6595
6596 if (inst.reloc.exp.X_op == O_constant
6597 && ((inst.reloc.exp.X_add_number & ~0xFF) == 0))
6598 {
6599 /* This can be done with a mov instruction. */
6600
6601 inst.instruction = T_OPCODE_MOV_I8 | (Rd << 8);
6602 inst.instruction |= inst.reloc.exp.X_add_number;
6603 return;
6604 }
6605
6606 /* Insert into literal pool. */
6607 if (add_to_lit_pool () == FAIL)
6608 {
6609 if (!inst.error)
6610 inst.error = "literal pool insertion failed";
6611 return;
6612 }
6613
6614 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
6615 inst.reloc.pc_rel = 1;
6616 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
6617 /* Adjust ARM pipeline offset to Thumb. */
6618 inst.reloc.exp.X_add_number += 4;
6619
6620 return;
6621 }
6622 else
6623 {
6624 if (my_get_expression (&inst.reloc.exp, &str))
6625 return;
6626
6627 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
6628 inst.reloc.pc_rel = 1;
6629 inst.reloc.exp.X_add_number -= 4; /* Pipeline offset. */
6630 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
6631 end_of_line (str);
6632 return;
6633 }
6634
6635 if (Rb == REG_PC || Rb == REG_SP)
6636 {
6637 if (size != THUMB_WORD)
6638 {
6639 inst.error = _("byte or halfword not valid for base register");
6640 return;
6641 }
6642 else if (Rb == REG_PC && load_store != THUMB_LOAD)
6643 {
f03698e6 6644 inst.error = _("r15 based store not allowed");
b99bd4ef
NC
6645 return;
6646 }
6647 else if (Ro != FAIL)
6648 {
f03698e6 6649 inst.error = _("invalid base register for register offset");
b99bd4ef
NC
6650 return;
6651 }
6652
6653 if (Rb == REG_PC)
6654 inst.instruction = T_OPCODE_LDR_PC;
6655 else if (load_store == THUMB_LOAD)
6656 inst.instruction = T_OPCODE_LDR_SP;
6657 else
6658 inst.instruction = T_OPCODE_STR_SP;
6659
6660 inst.instruction |= Rd << 8;
6661 if (inst.reloc.exp.X_op == O_constant)
6662 {
6663 unsigned offset = inst.reloc.exp.X_add_number;
6664
6665 if (offset & ~0x3fc)
6666 {
6667 inst.error = _("invalid offset");
6668 return;
6669 }
6670
6671 inst.instruction |= offset >> 2;
6672 }
6673 else
6674 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
6675 }
6676 else if (Rb > 7)
6677 {
6678 inst.error = _("invalid base register in load/store");
6679 return;
6680 }
6681 else if (Ro == FAIL)
6682 {
6683 /* Immediate offset. */
6684 if (size == THUMB_WORD)
6685 inst.instruction = (load_store == THUMB_LOAD
6686 ? T_OPCODE_LDR_IW : T_OPCODE_STR_IW);
6687 else if (size == THUMB_HALFWORD)
6688 inst.instruction = (load_store == THUMB_LOAD
6689 ? T_OPCODE_LDR_IH : T_OPCODE_STR_IH);
6690 else
6691 inst.instruction = (load_store == THUMB_LOAD
6692 ? T_OPCODE_LDR_IB : T_OPCODE_STR_IB);
6693
6694 inst.instruction |= Rd | (Rb << 3);
6695
6696 if (inst.reloc.exp.X_op == O_constant)
6697 {
6698 unsigned offset = inst.reloc.exp.X_add_number;
6699
6700 if (offset & ~(0x1f << size))
6701 {
f03698e6 6702 inst.error = _("invalid offset");
b99bd4ef
NC
6703 return;
6704 }
6705 inst.instruction |= (offset >> size) << 6;
6706 }
6707 else
6708 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
6709 }
6710 else
6711 {
6712 /* Register offset. */
6713 if (size == THUMB_WORD)
6714 inst.instruction = (load_store == THUMB_LOAD
6715 ? T_OPCODE_LDR_RW : T_OPCODE_STR_RW);
6716 else if (size == THUMB_HALFWORD)
6717 inst.instruction = (load_store == THUMB_LOAD
6718 ? T_OPCODE_LDR_RH : T_OPCODE_STR_RH);
6719 else
6720 inst.instruction = (load_store == THUMB_LOAD
6721 ? T_OPCODE_LDR_RB : T_OPCODE_STR_RB);
6722
6723 inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
6724 }
6725
6726 end_of_line (str);
6727}
6728
404ff6b5
AH
6729/* A register must be given at this point.
6730
404ff6b5
AH
6731 Shift is the place to put it in inst.instruction.
6732
404ff6b5
AH
6733 Restores input start point on err.
6734 Returns the reg#, or FAIL. */
6735
6736static int
6737cirrus_reg_required_here (str, shift, regtype)
6738 char ** str;
6739 int shift;
6c43fab6 6740 enum arm_reg_type regtype;
404ff6b5 6741{
6c43fab6
RE
6742 int reg;
6743 char *start = *str;
404ff6b5 6744
6c43fab6 6745 if ((reg = arm_reg_parse (str, all_reg_maps[regtype].htab)) != FAIL)
404ff6b5 6746 {
404ff6b5
AH
6747 if (shift >= 0)
6748 inst.instruction |= reg << shift;
6749
6c43fab6 6750 return reg;
404ff6b5
AH
6751 }
6752
6c43fab6 6753 /* Restore the start point. */
404ff6b5
AH
6754 *str = start;
6755
6756 /* In the few cases where we might be able to accept something else
6757 this error can be overridden. */
6c43fab6 6758 inst.error = _(all_reg_maps[regtype].expected);
404ff6b5
AH
6759
6760 return FAIL;
6761}
6762
6763/* Cirrus Instructions. */
6764
6765/* Wrapper functions. */
6766
6767static void
6c43fab6
RE
6768do_c_binops_1a (str)
6769 char * str;
6770{
6771 do_c_binops (str, CIRRUS_MODE1, REG_TYPE_RN, REG_TYPE_MVF);
6772}
6773
6774static void
6775do_c_binops_1b (str)
6776 char * str;
6777{
6778 do_c_binops (str, CIRRUS_MODE1, REG_TYPE_RN, REG_TYPE_MVD);
6779}
6780
6781static void
6782do_c_binops_1c (str)
404ff6b5 6783 char * str;
404ff6b5 6784{
6c43fab6 6785 do_c_binops (str, CIRRUS_MODE1, REG_TYPE_RN, REG_TYPE_MVDX);
404ff6b5
AH
6786}
6787
6788static void
6c43fab6 6789do_c_binops_1d (str)
404ff6b5 6790 char * str;
404ff6b5 6791{
6c43fab6 6792 do_c_binops (str, CIRRUS_MODE1, REG_TYPE_MVF, REG_TYPE_MVF);
404ff6b5
AH
6793}
6794
6795static void
6c43fab6 6796do_c_binops_1e (str)
404ff6b5 6797 char * str;
404ff6b5 6798{
6c43fab6 6799 do_c_binops (str, CIRRUS_MODE1, REG_TYPE_MVD, REG_TYPE_MVD);
404ff6b5
AH
6800}
6801
6802static void
6c43fab6 6803do_c_binops_1f (str)
404ff6b5 6804 char * str;
404ff6b5 6805{
6c43fab6 6806 do_c_binops (str, CIRRUS_MODE1, REG_TYPE_MVD, REG_TYPE_MVF);
404ff6b5
AH
6807}
6808
6809static void
6c43fab6 6810do_c_binops_1g (str)
404ff6b5 6811 char * str;
404ff6b5 6812{
6c43fab6 6813 do_c_binops (str, CIRRUS_MODE1, REG_TYPE_MVF, REG_TYPE_MVD);
404ff6b5
AH
6814}
6815
6816static void
6c43fab6 6817do_c_binops_1h (str)
404ff6b5 6818 char * str;
404ff6b5 6819{
6c43fab6 6820 do_c_binops (str, CIRRUS_MODE1, REG_TYPE_MVF, REG_TYPE_MVFX);
404ff6b5
AH
6821}
6822
6c43fab6
RE
6823static void
6824do_c_binops_1i (str)
6825 char * str;
6826{
6827 do_c_binops (str, CIRRUS_MODE1, REG_TYPE_MVD, REG_TYPE_MVFX);
6828}
6829
6830static void
6831do_c_binops_1j (str)
6832 char * str;
6833{
6834 do_c_binops (str, CIRRUS_MODE1, REG_TYPE_MVF, REG_TYPE_MVDX);
6835}
6836
6837static void
6838do_c_binops_1k (str)
6839 char * str;
6840{
6841 do_c_binops (str, CIRRUS_MODE1, REG_TYPE_MVD, REG_TYPE_MVDX);
6842}
6843
6844static void
6845do_c_binops_1l (str)
6846 char * str;
6847{
6848 do_c_binops (str, CIRRUS_MODE1, REG_TYPE_MVFX, REG_TYPE_MVF);
6849}
6850
6851static void
6852do_c_binops_1m (str)
6853 char * str;
6854{
6855 do_c_binops (str, CIRRUS_MODE1, REG_TYPE_MVFX, REG_TYPE_MVD);
6856}
6857
6858static void
6859do_c_binops_1n (str)
6860 char * str;
6861{
6862 do_c_binops (str, CIRRUS_MODE1, REG_TYPE_MVFX, REG_TYPE_MVFX);
6863}
6864
6865static void
6866do_c_binops_1o (str)
6867 char * str;
6868{
6869 do_c_binops (str, CIRRUS_MODE1, REG_TYPE_MVDX, REG_TYPE_MVDX);
6870}
6871
6872static void
6873do_c_binops_2a (str)
6874 char * str;
6875{
6876 do_c_binops (str, CIRRUS_MODE2, REG_TYPE_MVF, REG_TYPE_RN);
6877}
6878
6879static void
6880do_c_binops_2b (str)
6881 char * str;
6882{
6883 do_c_binops (str, CIRRUS_MODE2, REG_TYPE_MVD, REG_TYPE_RN);
6884}
6885
6886static void
6887do_c_binops_2c (str)
6888 char * str;
6889{
6890 do_c_binops (str, CIRRUS_MODE2, REG_TYPE_MVDX, REG_TYPE_RN);
6891}
6892
6893static void
6894do_c_binops_3a (str)
6895 char * str;
6896{
6897 do_c_binops (str, CIRRUS_MODE3, REG_TYPE_MVAX, REG_TYPE_MVFX);
6898}
6899
6900static void
6901do_c_binops_3b (str)
6902 char * str;
6903{
6904 do_c_binops (str, CIRRUS_MODE3, REG_TYPE_MVFX, REG_TYPE_MVAX);
6905}
6906
6907static void
6908do_c_binops_3c (str)
6909 char * str;
6910{
6911 do_c_binops (str, CIRRUS_MODE3, REG_TYPE_MVAX, REG_TYPE_MVDX);
6912}
6913
6914static void
6915do_c_binops_3d (str)
6916 char * str;
6917{
6918 do_c_binops (str, CIRRUS_MODE3, REG_TYPE_MVDX, REG_TYPE_MVAX);
6919}
6920
6921static void
6922do_c_triple_4a (str)
6923 char * str;
6924{
6925 do_c_triple (str, CIRRUS_MODE4, REG_TYPE_MVFX, REG_TYPE_MVFX, REG_TYPE_RN);
6926}
6927
6928static void
6929do_c_triple_4b (str)
6930 char * str;
6931{
6932 do_c_triple (str, CIRRUS_MODE4, REG_TYPE_MVDX, REG_TYPE_MVDX, REG_TYPE_RN);
6933}
6934
6935static void
6936do_c_triple_5a (str)
6937 char * str;
6938{
6939 do_c_triple (str, CIRRUS_MODE5, REG_TYPE_RN, REG_TYPE_MVF, REG_TYPE_MVF);
6940}
6941
6942static void
6943do_c_triple_5b (str)
6944 char * str;
6945{
6946 do_c_triple (str, CIRRUS_MODE5, REG_TYPE_RN, REG_TYPE_MVD, REG_TYPE_MVD);
6947}
6948
6949static void
6950do_c_triple_5c (str)
6951 char * str;
6952{
6953 do_c_triple (str, CIRRUS_MODE5, REG_TYPE_RN, REG_TYPE_MVFX, REG_TYPE_MVFX);
6954}
6955
6956static void
6957do_c_triple_5d (str)
6958 char * str;
6959{
6960 do_c_triple (str, CIRRUS_MODE5, REG_TYPE_RN, REG_TYPE_MVDX, REG_TYPE_MVDX);
6961}
6962
6963static void
6964do_c_triple_5e (str)
6965 char * str;
6966{
6967 do_c_triple (str, CIRRUS_MODE5, REG_TYPE_MVF, REG_TYPE_MVF, REG_TYPE_MVF);
6968}
6969
6970static void
6971do_c_triple_5f (str)
6972 char * str;
6973{
6974 do_c_triple (str, CIRRUS_MODE5, REG_TYPE_MVD, REG_TYPE_MVD, REG_TYPE_MVD);
6975}
6976
6977static void
6978do_c_triple_5g (str)
6979 char * str;
6980{
6981 do_c_triple (str, CIRRUS_MODE5, REG_TYPE_MVFX, REG_TYPE_MVFX, REG_TYPE_MVFX);
6982}
6983
6984static void
6985do_c_triple_5h (str)
6986 char * str;
6987{
6988 do_c_triple (str, CIRRUS_MODE5, REG_TYPE_MVDX, REG_TYPE_MVDX, REG_TYPE_MVDX);
6989}
6990
6991static void
6992do_c_quad_6a (str)
6993 char * str;
6994{
6995 do_c_quad (str, CIRRUS_MODE6, REG_TYPE_MVAX, REG_TYPE_MVFX, REG_TYPE_MVFX,
6996 REG_TYPE_MVFX);
6997}
6998
6999static void
7000do_c_quad_6b (str)
7001 char * str;
7002{
7003 do_c_quad (str, CIRRUS_MODE6, REG_TYPE_MVAX, REG_TYPE_MVAX, REG_TYPE_MVFX,
7004 REG_TYPE_MVFX);
7005}
7006
7007/* cfmvsc32<cond> DSPSC,MVFX[15:0]. */
404ff6b5 7008static void
f2b7cb0a 7009do_c_dspsc_1 (str)
404ff6b5 7010 char * str;
404ff6b5 7011{
6c43fab6
RE
7012 skip_whitespace (str);
7013
7014 /* cfmvsc32. */
7015 if (cirrus_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL
7016 || skip_past_comma (&str) == FAIL
7017 || cirrus_reg_required_here (&str, 16, REG_TYPE_MVFX) == FAIL)
7018 {
7019 if (!inst.error)
7020 inst.error = BAD_ARGS;
7021
7022 return;
7023 }
7024
7025 end_of_line (str);
404ff6b5
AH
7026}
7027
6c43fab6 7028/* cfmv32sc<cond> MVFX[15:0],DSPSC. */
404ff6b5 7029static void
f2b7cb0a 7030do_c_dspsc_2 (str)
404ff6b5 7031 char * str;
404ff6b5 7032{
6c43fab6
RE
7033 skip_whitespace (str);
7034
7035 /* cfmv32sc. */
7036 if (cirrus_reg_required_here (&str, 0, REG_TYPE_MVFX) == FAIL
7037 || skip_past_comma (&str) == FAIL
7038 || cirrus_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL)
7039 {
7040 if (!inst.error)
7041 inst.error = BAD_ARGS;
7042
7043 return;
7044 }
7045
7046 end_of_line (str);
404ff6b5
AH
7047}
7048
7049static void
f2b7cb0a 7050do_c_shift_1 (str)
404ff6b5 7051 char * str;
404ff6b5 7052{
6c43fab6 7053 do_c_shift (str, REG_TYPE_MVFX, REG_TYPE_MVFX);
404ff6b5
AH
7054}
7055
7056static void
f2b7cb0a 7057do_c_shift_2 (str)
404ff6b5 7058 char * str;
404ff6b5 7059{
6c43fab6 7060 do_c_shift (str, REG_TYPE_MVDX, REG_TYPE_MVDX);
404ff6b5
AH
7061}
7062
7063static void
f2b7cb0a 7064do_c_ldst_1 (str)
404ff6b5 7065 char * str;
404ff6b5 7066{
6c43fab6 7067 do_c_ldst (str, REG_TYPE_MVF);
404ff6b5
AH
7068}
7069
7070static void
f2b7cb0a 7071do_c_ldst_2 (str)
404ff6b5 7072 char * str;
404ff6b5 7073{
6c43fab6 7074 do_c_ldst (str, REG_TYPE_MVD);
404ff6b5
AH
7075}
7076
7077static void
f2b7cb0a 7078do_c_ldst_3 (str)
404ff6b5 7079 char * str;
404ff6b5 7080{
6c43fab6 7081 do_c_ldst (str, REG_TYPE_MVFX);
404ff6b5
AH
7082}
7083
7084static void
f2b7cb0a 7085do_c_ldst_4 (str)
404ff6b5 7086 char * str;
404ff6b5 7087{
6c43fab6 7088 do_c_ldst (str, REG_TYPE_MVDX);
404ff6b5
AH
7089}
7090
7091/* Isnsn like "foo X,Y". */
7092
7093static void
6c43fab6 7094do_c_binops (str, mode, reg0, reg1)
404ff6b5 7095 char * str;
404ff6b5 7096 int mode;
6c43fab6
RE
7097 enum arm_reg_type reg0;
7098 enum arm_reg_type reg1;
404ff6b5 7099{
6c43fab6 7100 int shift0, shift1;
404ff6b5 7101
6c43fab6
RE
7102 shift0 = mode & 0xff;
7103 shift1 = (mode >> 8) & 0xff;
404ff6b5
AH
7104
7105 skip_whitespace (str);
7106
6c43fab6 7107 if (cirrus_reg_required_here (&str, shift0, reg0) == FAIL
404ff6b5 7108 || skip_past_comma (&str) == FAIL
6c43fab6 7109 || cirrus_reg_required_here (&str, shift1, reg1) == FAIL)
404ff6b5
AH
7110 {
7111 if (!inst.error)
7112 inst.error = BAD_ARGS;
7113 }
7114 else
7115 end_of_line (str);
404ff6b5
AH
7116}
7117
7118/* Isnsn like "foo X,Y,Z". */
7119
7120static void
6c43fab6 7121do_c_triple (str, mode, reg0, reg1, reg2)
404ff6b5 7122 char * str;
404ff6b5 7123 int mode;
6c43fab6
RE
7124 enum arm_reg_type reg0;
7125 enum arm_reg_type reg1;
7126 enum arm_reg_type reg2;
404ff6b5 7127{
6c43fab6 7128 int shift0, shift1, shift2;
404ff6b5 7129
6c43fab6
RE
7130 shift0 = mode & 0xff;
7131 shift1 = (mode >> 8) & 0xff;
7132 shift2 = (mode >> 16) & 0xff;
404ff6b5
AH
7133
7134 skip_whitespace (str);
7135
6c43fab6 7136 if (cirrus_reg_required_here (&str, shift0, reg0) == FAIL
404ff6b5 7137 || skip_past_comma (&str) == FAIL
6c43fab6 7138 || cirrus_reg_required_here (&str, shift1, reg1) == FAIL
404ff6b5 7139 || skip_past_comma (&str) == FAIL
6c43fab6 7140 || cirrus_reg_required_here (&str, shift2, reg2) == FAIL)
404ff6b5
AH
7141 {
7142 if (!inst.error)
7143 inst.error = BAD_ARGS;
7144 }
7145 else
7146 end_of_line (str);
404ff6b5
AH
7147}
7148
7149/* Isnsn like "foo W,X,Y,Z".
7150 where W=MVAX[0:3] and X,Y,Z=MVFX[0:15]. */
7151
7152static void
6c43fab6 7153do_c_quad (str, mode, reg0, reg1, reg2, reg3)
404ff6b5 7154 char * str;
404ff6b5 7155 int mode;
6c43fab6
RE
7156 enum arm_reg_type reg0;
7157 enum arm_reg_type reg1;
7158 enum arm_reg_type reg2;
7159 enum arm_reg_type reg3;
404ff6b5 7160{
6c43fab6 7161 int shift0, shift1, shift2, shift3;
404ff6b5 7162
6c43fab6
RE
7163 shift0= mode & 0xff;
7164 shift1 = (mode >> 8) & 0xff;
7165 shift2 = (mode >> 16) & 0xff;
7166 shift3 = (mode >> 24) & 0xff;
404ff6b5
AH
7167
7168 skip_whitespace (str);
7169
6c43fab6 7170 if (cirrus_reg_required_here (&str, shift0, reg0) == FAIL
404ff6b5 7171 || skip_past_comma (&str) == FAIL
6c43fab6 7172 || cirrus_reg_required_here (&str, shift1, reg1) == FAIL
404ff6b5 7173 || skip_past_comma (&str) == FAIL
6c43fab6 7174 || cirrus_reg_required_here (&str, shift2, reg2) == FAIL
404ff6b5 7175 || skip_past_comma (&str) == FAIL
6c43fab6 7176 || cirrus_reg_required_here (&str, shift3, reg3) == FAIL)
404ff6b5
AH
7177 {
7178 if (!inst.error)
7179 inst.error = BAD_ARGS;
7180 }
7181 else
7182 end_of_line (str);
404ff6b5
AH
7183}
7184
404ff6b5
AH
7185/* Cirrus shift immediate instructions.
7186 cfsh32<cond> MVFX[15:0],MVFX[15:0],Shift[6:0].
7187 cfsh64<cond> MVDX[15:0],MVDX[15:0],Shift[6:0]. */
7188
7189static void
6c43fab6 7190do_c_shift (str, reg0, reg1)
404ff6b5 7191 char * str;
6c43fab6
RE
7192 enum arm_reg_type reg0;
7193 enum arm_reg_type reg1;
404ff6b5
AH
7194{
7195 int error;
7196 int imm, neg = 0;
7197
7198 skip_whitespace (str);
7199
7200 error = 0;
7201
6c43fab6 7202 if (cirrus_reg_required_here (&str, 12, reg0) == FAIL
404ff6b5 7203 || skip_past_comma (&str) == FAIL
6c43fab6 7204 || cirrus_reg_required_here (&str, 16, reg1) == FAIL
404ff6b5
AH
7205 || skip_past_comma (&str) == FAIL)
7206 {
7207 if (!inst.error)
7208 inst.error = BAD_ARGS;
7209 return;
7210 }
7211
7212 /* Calculate the immediate operand.
7213 The operand is a 7bit signed number. */
7214 skip_whitespace (str);
7215
7216 if (*str == '#')
7217 ++str;
7218
8420dfca 7219 if (!ISDIGIT (*str) && *str != '-')
404ff6b5
AH
7220 {
7221 inst.error = _("expecting immediate, 7bit operand");
7222 return;
7223 }
7224
7225 if (*str == '-')
7226 {
7227 neg = 1;
7228 ++str;
7229 }
7230
8420dfca 7231 for (imm = 0; *str && ISDIGIT (*str); ++str)
404ff6b5
AH
7232 imm = imm * 10 + *str - '0';
7233
7234 if (imm > 64)
7235 {
7236 inst.error = _("immediate out of range");
7237 return;
7238 }
7239
7240 /* Make negative imm's into 7bit signed numbers. */
7241 if (neg)
7242 {
7243 imm = -imm;
7244 imm &= 0x0000007f;
7245 }
7246
7247 /* Bits 0-3 of the insn should have bits 0-3 of the immediate.
7248 Bits 5-7 of the insn should have bits 4-6 of the immediate.
7249 Bit 4 should be 0. */
7250 imm = (imm & 0xf) | ((imm & 0x70) << 1);
7251
7252 inst.instruction |= imm;
404ff6b5 7253 end_of_line (str);
404ff6b5
AH
7254}
7255
7256static int
7257cirrus_parse_offset (str, negative)
7258 char ** str;
7259 int *negative;
7260{
7261 char * p = *str;
7262 int offset;
7263
7264 *negative = 0;
7265
7266 skip_whitespace (p);
7267
7268 if (*p == '#')
7269 ++p;
7270
7271 if (*p == '-')
7272 {
7273 *negative = 1;
7274 ++p;
7275 }
7276
8420dfca 7277 if (!ISDIGIT (*p))
404ff6b5
AH
7278 {
7279 inst.error = _("offset expected");
7280 return 0;
7281 }
7282
8420dfca 7283 for (offset = 0; *p && ISDIGIT (*p); ++p)
404ff6b5
AH
7284 offset = offset * 10 + *p - '0';
7285
7286 if (offset > 0xff)
7287 {
7288 inst.error = _("offset out of range");
7289 return 0;
7290 }
7291
7292 *str = p;
7293
7294 return *negative ? -offset : offset;
7295}
7296
7297/* Cirrus load/store instructions.
7298 <insn><cond> CRd,[Rn,<offset>]{!}.
7299 <insn><cond> CRd,[Rn],<offset>. */
7300
7301static void
6c43fab6 7302do_c_ldst (str, reg0)
404ff6b5 7303 char * str;
6c43fab6 7304 enum arm_reg_type reg0;
404ff6b5
AH
7305{
7306 int offset, negative;
404ff6b5
AH
7307
7308 skip_whitespace (str);
7309
6c43fab6
RE
7310 if (cirrus_reg_required_here (&str, 12, reg0) == FAIL
7311 || skip_past_comma (&str) == FAIL
404ff6b5 7312 || *str++ != '['
6c43fab6 7313 || reg_required_here (&str, 16) == FAIL)
404ff6b5
AH
7314 goto fail_ldst;
7315
6c43fab6 7316 if (skip_past_comma (&str) == SUCCESS)
404ff6b5
AH
7317 {
7318 /* You are here: "<offset>]{!}". */
7319 inst.instruction |= PRE_INDEX;
7320
7321 offset = cirrus_parse_offset (&str, &negative);
7322
7323 if (inst.error)
7324 return;
7325
7326 if (*str++ != ']')
7327 {
7328 inst.error = _("missing ]");
7329 return;
7330 }
7331
7332 if (*str == '!')
7333 {
7334 inst.instruction |= WRITE_BACK;
7335 ++str;
7336 }
7337 }
7338 else
7339 {
7340 /* You are here: "], <offset>". */
7341 if (*str++ != ']')
7342 {
7343 inst.error = _("missing ]");
7344 return;
7345 }
7346
7347 if (skip_past_comma (&str) == FAIL
7348 || (offset = cirrus_parse_offset (&str, &negative), inst.error))
7349 goto fail_ldst;
7350
7351 inst.instruction |= CP_T_WB; /* Post indexed, set bit W. */
7352 }
7353
7354 if (negative)
7355 offset = -offset;
7356 else
7357 inst.instruction |= CP_T_UD; /* Postive, so set bit U. */
7358
7359 inst.instruction |= offset >> 2;
404ff6b5
AH
7360 end_of_line (str);
7361 return;
7362
7363fail_ldst:
7364 if (!inst.error)
7365 inst.error = BAD_ARGS;
7366 return;
7367}
7368
b99bd4ef
NC
7369static void
7370do_t_nop (str)
7371 char * str;
7372{
7373 /* Do nothing. */
7374 end_of_line (str);
7375 return;
7376}
7377
7378/* Handle the Format 4 instructions that do not have equivalents in other
7379 formats. That is, ADC, AND, EOR, SBC, ROR, TST, NEG, CMN, ORR, MUL,
7380 BIC and MVN. */
7381
7382static void
7383do_t_arit (str)
7384 char * str;
7385{
7386 int Rd, Rs, Rn;
7387
7388 skip_whitespace (str);
7389
7390 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
7391 || skip_past_comma (&str) == FAIL
7392 || (Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
7393 {
7394 inst.error = BAD_ARGS;
7395 return;
7396 }
7397
7398 if (skip_past_comma (&str) != FAIL)
7399 {
7400 /* Three operand format not allowed for TST, CMN, NEG and MVN.
7401 (It isn't allowed for CMP either, but that isn't handled by this
7402 function.) */
7403 if (inst.instruction == T_OPCODE_TST
7404 || inst.instruction == T_OPCODE_CMN
7405 || inst.instruction == T_OPCODE_NEG
7406 || inst.instruction == T_OPCODE_MVN)
7407 {
7408 inst.error = BAD_ARGS;
7409 return;
7410 }
7411
7412 if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
7413 return;
7414
7415 if (Rs != Rd)
7416 {
7417 inst.error = _("dest and source1 must be the same register");
7418 return;
7419 }
7420 Rs = Rn;
7421 }
7422
7423 if (inst.instruction == T_OPCODE_MUL
7424 && Rs == Rd)
7425 as_tsktsk (_("Rs and Rd must be different in MUL"));
7426
7427 inst.instruction |= Rd | (Rs << 3);
7428 end_of_line (str);
7429}
7430
7431static void
7432do_t_add (str)
7433 char * str;
7434{
7435 thumb_add_sub (str, 0);
7436}
7437
7438static void
7439do_t_asr (str)
7440 char * str;
7441{
7442 thumb_shift (str, THUMB_ASR);
7443}
7444
7445static void
7446do_t_branch9 (str)
7447 char * str;
7448{
7449 if (my_get_expression (&inst.reloc.exp, &str))
7450 return;
7451 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH9;
7452 inst.reloc.pc_rel = 1;
7453 end_of_line (str);
7454}
7455
7456static void
7457do_t_branch12 (str)
7458 char * str;
7459{
7460 if (my_get_expression (&inst.reloc.exp, &str))
7461 return;
7462 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH12;
7463 inst.reloc.pc_rel = 1;
7464 end_of_line (str);
7465}
7466
7467/* Find the real, Thumb encoded start of a Thumb function. */
7468
7469static symbolS *
7470find_real_start (symbolP)
7471 symbolS * symbolP;
7472{
7473 char * real_start;
7474 const char * name = S_GET_NAME (symbolP);
7475 symbolS * new_target;
7476
7477 /* This definiton must agree with the one in gcc/config/arm/thumb.c. */
7478#define STUB_NAME ".real_start_of"
7479
7480 if (name == NULL)
7481 abort ();
7482
7483 /* Names that start with '.' are local labels, not function entry points.
7484 The compiler may generate BL instructions to these labels because it
7485 needs to perform a branch to a far away location. */
7486 if (name[0] == '.')
7487 return symbolP;
7488
7489 real_start = malloc (strlen (name) + strlen (STUB_NAME) + 1);
7490 sprintf (real_start, "%s%s", STUB_NAME, name);
7491
7492 new_target = symbol_find (real_start);
7493
7494 if (new_target == NULL)
7495 {
7496 as_warn ("Failed to find real start of function: %s\n", name);
7497 new_target = symbolP;
7498 }
7499
7500 free (real_start);
7501
7502 return new_target;
7503}
7504
7505static void
7506do_t_branch23 (str)
7507 char * str;
7508{
7509 if (my_get_expression (& inst.reloc.exp, & str))
7510 return;
7511
7512 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH23;
7513 inst.reloc.pc_rel = 1;
7514 end_of_line (str);
7515
7516 /* If the destination of the branch is a defined symbol which does not have
7517 the THUMB_FUNC attribute, then we must be calling a function which has
7518 the (interfacearm) attribute. We look for the Thumb entry point to that
7519 function and change the branch to refer to that function instead. */
7520 if ( inst.reloc.exp.X_op == O_symbol
7521 && inst.reloc.exp.X_add_symbol != NULL
7522 && S_IS_DEFINED (inst.reloc.exp.X_add_symbol)
7523 && ! THUMB_IS_FUNC (inst.reloc.exp.X_add_symbol))
7524 inst.reloc.exp.X_add_symbol =
7525 find_real_start (inst.reloc.exp.X_add_symbol);
7526}
7527
7528static void
7529do_t_bx (str)
7530 char * str;
7531{
7532 int reg;
7533
7534 skip_whitespace (str);
7535
7536 if ((reg = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
7537 return;
7538
7539 /* This sets THUMB_H2 from the top bit of reg. */
7540 inst.instruction |= reg << 3;
7541
7542 /* ??? FIXME: Should add a hacky reloc here if reg is REG_PC. The reloc
7543 should cause the alignment to be checked once it is known. This is
7544 because BX PC only works if the instruction is word aligned. */
7545
7546 end_of_line (str);
7547}
7548
7549static void
7550do_t_compare (str)
7551 char * str;
7552{
7553 thumb_mov_compare (str, THUMB_COMPARE);
7554}
7555
7556static void
7557do_t_ldmstm (str)
7558 char * str;
7559{
7560 int Rb;
7561 long range;
7562
7563 skip_whitespace (str);
7564
7565 if ((Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
7566 return;
7567
7568 if (*str != '!')
f03698e6 7569 as_warn (_("inserted missing '!': load/store multiple always writes back base register"));
b99bd4ef
NC
7570 else
7571 str++;
7572
7573 if (skip_past_comma (&str) == FAIL
7574 || (range = reg_list (&str)) == FAIL)
7575 {
7576 if (! inst.error)
7577 inst.error = BAD_ARGS;
7578 return;
7579 }
7580
7581 if (inst.reloc.type != BFD_RELOC_NONE)
7582 {
7583 /* This really doesn't seem worth it. */
7584 inst.reloc.type = BFD_RELOC_NONE;
f03698e6 7585 inst.error = _("expression too complex");
b99bd4ef
NC
7586 return;
7587 }
7588
7589 if (range & ~0xff)
7590 {
7591 inst.error = _("only lo-regs valid in load/store multiple");
7592 return;
7593 }
7594
7595 inst.instruction |= (Rb << 8) | range;
7596 end_of_line (str);
7597}
7598
7599static void
7600do_t_ldr (str)
7601 char * str;
7602{
7603 thumb_load_store (str, THUMB_LOAD, THUMB_WORD);
7604}
7605
7606static void
7607do_t_ldrb (str)
7608 char * str;
7609{
7610 thumb_load_store (str, THUMB_LOAD, THUMB_BYTE);
7611}
7612
7613static void
7614do_t_ldrh (str)
7615 char * str;
7616{
7617 thumb_load_store (str, THUMB_LOAD, THUMB_HALFWORD);
7618}
7619
7620static void
7621do_t_lds (str)
7622 char * str;
7623{
7624 int Rd, Rb, Ro;
7625
7626 skip_whitespace (str);
7627
7628 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
7629 || skip_past_comma (&str) == FAIL
7630 || *str++ != '['
7631 || (Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL
7632 || skip_past_comma (&str) == FAIL
7633 || (Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL
7634 || *str++ != ']')
7635 {
7636 if (! inst.error)
f03698e6 7637 inst.error = _("syntax: ldrs[b] Rd, [Rb, Ro]");
b99bd4ef
NC
7638 return;
7639 }
7640
7641 inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
7642 end_of_line (str);
7643}
7644
7645static void
7646do_t_lsl (str)
7647 char * str;
7648{
7649 thumb_shift (str, THUMB_LSL);
7650}
7651
7652static void
7653do_t_lsr (str)
7654 char * str;
7655{
7656 thumb_shift (str, THUMB_LSR);
7657}
7658
7659static void
7660do_t_mov (str)
7661 char * str;
7662{
7663 thumb_mov_compare (str, THUMB_MOVE);
7664}
7665
7666static void
7667do_t_push_pop (str)
7668 char * str;
7669{
7670 long range;
7671
7672 skip_whitespace (str);
7673
7674 if ((range = reg_list (&str)) == FAIL)
7675 {
7676 if (! inst.error)
7677 inst.error = BAD_ARGS;
7678 return;
7679 }
7680
7681 if (inst.reloc.type != BFD_RELOC_NONE)
7682 {
7683 /* This really doesn't seem worth it. */
7684 inst.reloc.type = BFD_RELOC_NONE;
f03698e6 7685 inst.error = _("expression too complex");
b99bd4ef
NC
7686 return;
7687 }
7688
7689 if (range & ~0xff)
7690 {
7691 if ((inst.instruction == T_OPCODE_PUSH
7692 && (range & ~0xff) == 1 << REG_LR)
7693 || (inst.instruction == T_OPCODE_POP
7694 && (range & ~0xff) == 1 << REG_PC))
7695 {
7696 inst.instruction |= THUMB_PP_PC_LR;
7697 range &= 0xff;
7698 }
7699 else
7700 {
7701 inst.error = _("invalid register list to push/pop instruction");
7702 return;
7703 }
7704 }
7705
7706 inst.instruction |= range;
7707 end_of_line (str);
7708}
7709
7710static void
7711do_t_str (str)
7712 char * str;
7713{
7714 thumb_load_store (str, THUMB_STORE, THUMB_WORD);
7715}
7716
7717static void
7718do_t_strb (str)
7719 char * str;
7720{
7721 thumb_load_store (str, THUMB_STORE, THUMB_BYTE);
7722}
7723
7724static void
7725do_t_strh (str)
7726 char * str;
7727{
7728 thumb_load_store (str, THUMB_STORE, THUMB_HALFWORD);
7729}
7730
7731static void
7732do_t_sub (str)
7733 char * str;
7734{
7735 thumb_add_sub (str, 1);
7736}
7737
7738static void
7739do_t_swi (str)
7740 char * str;
7741{
7742 skip_whitespace (str);
7743
7744 if (my_get_expression (&inst.reloc.exp, &str))
7745 return;
7746
7747 inst.reloc.type = BFD_RELOC_ARM_SWI;
7748 end_of_line (str);
7749 return;
7750}
7751
7752static void
7753do_t_adr (str)
7754 char * str;
7755{
7756 int reg;
7757
7758 /* This is a pseudo-op of the form "adr rd, label" to be converted
7759 into a relative address of the form "add rd, pc, #label-.-4". */
7760 skip_whitespace (str);
7761
7762 /* Store Rd in temporary location inside instruction. */
7763 if ((reg = reg_required_here (&str, 4)) == FAIL
7764 || (reg > 7) /* For Thumb reg must be r0..r7. */
7765 || skip_past_comma (&str) == FAIL
7766 || my_get_expression (&inst.reloc.exp, &str))
7767 {
7768 if (!inst.error)
7769 inst.error = BAD_ARGS;
7770 return;
7771 }
7772
7773 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
7774 inst.reloc.exp.X_add_number -= 4; /* PC relative adjust. */
7775 inst.reloc.pc_rel = 1;
7776 inst.instruction |= REG_PC; /* Rd is already placed into the instruction. */
7777
7778 end_of_line (str);
7779}
7780
7781static void
6c43fab6
RE
7782insert_reg (r, htab)
7783 const struct reg_entry *r;
7784 struct hash_control *htab;
b99bd4ef 7785{
6c43fab6 7786 int len = strlen (r->name) + 2;
b99bd4ef
NC
7787 char * buf = (char *) xmalloc (len);
7788 char * buf2 = (char *) xmalloc (len);
7789 int i = 0;
7790
7791#ifdef REGISTER_PREFIX
7792 buf[i++] = REGISTER_PREFIX;
7793#endif
7794
6c43fab6 7795 strcpy (buf + i, r->name);
b99bd4ef
NC
7796
7797 for (i = 0; buf[i]; i++)
3882b010 7798 buf2[i] = TOUPPER (buf[i]);
b99bd4ef
NC
7799
7800 buf2[i] = '\0';
7801
6c43fab6
RE
7802 hash_insert (htab, buf, (PTR) r);
7803 hash_insert (htab, buf2, (PTR) r);
b99bd4ef
NC
7804}
7805
7806static void
6c43fab6
RE
7807build_reg_hsh (map)
7808 struct reg_map *map;
7809{
7810 const struct reg_entry *r;
7811
7812 if ((map->htab = hash_new ()) == NULL)
f03698e6 7813 as_fatal (_("virtual memory exhausted"));
6c43fab6
RE
7814
7815 for (r = map->names; r->name != NULL; r++)
7816 insert_reg (r, map->htab);
7817}
7818
7819static void
7820insert_reg_alias (str, regnum, htab)
b99bd4ef
NC
7821 char *str;
7822 int regnum;
6c43fab6 7823 struct hash_control *htab;
b99bd4ef
NC
7824{
7825 struct reg_entry *new =
7826 (struct reg_entry *) xmalloc (sizeof (struct reg_entry));
7827 char *name = xmalloc (strlen (str) + 1);
7828 strcpy (name, str);
7829
7830 new->name = name;
7831 new->number = regnum;
7832
6c43fab6 7833 hash_insert (htab, name, (PTR) new);
b99bd4ef
NC
7834}
7835
6c43fab6
RE
7836/* Look for the .req directive. This is of the form:
7837
7838 newname .req existing_name
7839
7840 If we find one, or if it looks sufficiently like one that we want to
7841 handle any error here, return non-zero. Otherwise return zero. */
7842static int
7843create_register_alias (newname, p)
7844 char *newname;
7845 char *p;
7846{
7847 char *q;
7848 char c;
7849
7850 q = p;
7851 skip_whitespace (q);
7852
7853 c = *p;
7854 *p = '\0';
7855
7856 if (*q && !strncmp (q, ".req ", 5))
7857 {
7858 char *copy_of_str;
7859 char *r;
7860
7861#ifdef IGNORE_OPCODE_CASE
7862 newname = original_case_string;
7863#endif
7864 copy_of_str = newname;
7865
7866 q += 4;
7867 skip_whitespace (q);
7868
7869 for (r = q; *r != '\0'; r++)
7870 if (*r == ' ')
7871 break;
7872
7873 if (r != q)
7874 {
7875 enum arm_reg_type new_type, old_type;
7876 int old_regno;
7877 char d = *r;
7878
7879 *r = '\0';
7880 old_type = arm_reg_parse_any (q);
7881 *r = d;
7882
7883 new_type = arm_reg_parse_any (newname);
7884
7885 if (new_type == REG_TYPE_MAX)
7886 {
7887 if (old_type != REG_TYPE_MAX)
7888 {
7889 old_regno = arm_reg_parse (&q, all_reg_maps[old_type].htab);
7890 insert_reg_alias (newname, old_regno,
7891 all_reg_maps[old_type].htab);
7892 }
7893 else
7894 as_warn (_("register '%s' does not exist\n"), q);
7895 }
7896 else if (old_type == REG_TYPE_MAX)
7897 {
7898 as_warn (_("ignoring redefinition of register alias '%s' to non-existant register '%s'"),
7899 copy_of_str, q);
7900 }
7901 else
7902 {
7903 /* Do not warn about redefinitions to the same alias. */
7904 if (new_type != old_type
7905 || (arm_reg_parse (&q, all_reg_maps[old_type].htab)
7906 != arm_reg_parse (&q, all_reg_maps[new_type].htab)))
7907 as_warn (_("ignoring redefinition of register alias '%s'"),
7908 copy_of_str);
7909
7910 }
7911 }
7912 else
7913 as_warn (_("ignoring incomplete .req pseuso op"));
7914
7915 *p = c;
7916 return 1;
7917 }
7918 *p = c;
7919 return 0;
7920}
7921
b99bd4ef
NC
7922static void
7923set_constant_flonums ()
7924{
7925 int i;
7926
7927 for (i = 0; i < NUM_FLOAT_VALS; i++)
7928 if (atof_ieee ((char *) fp_const[i], 'x', fp_values[i]) == NULL)
7929 abort ();
7930}
7931
90e4755a
RE
7932/* Iterate over the base tables to create the instruction patterns. */
7933static void
7934build_arm_ops_hsh ()
7935{
7936 unsigned int i;
7937 unsigned int j;
7938 static struct obstack insn_obstack;
7939
7940 obstack_begin (&insn_obstack, 4000);
7941
7942 for (i = 0; i < sizeof (insns) / sizeof (struct asm_opcode); i++)
7943 {
6c43fab6 7944 const struct asm_opcode *insn = insns + i;
90e4755a
RE
7945
7946 if (insn->cond_offset != 0)
7947 {
7948 /* Insn supports conditional execution. Build the varaints
7949 and insert them in the hash table. */
7950 for (j = 0; j < sizeof (conds) / sizeof (struct asm_cond); j++)
7951 {
7952 unsigned len = strlen (insn->template);
7953 struct asm_opcode *new;
7954 char *template;
7955
7956 new = obstack_alloc (&insn_obstack, sizeof (struct asm_opcode));
7957 /* All condition codes are two characters. */
7958 template = obstack_alloc (&insn_obstack, len + 3);
7959
7960 strncpy (template, insn->template, insn->cond_offset);
7961 strcpy (template + insn->cond_offset, conds[j].template);
7962 if (len > insn->cond_offset)
7963 strcpy (template + insn->cond_offset + 2,
7964 insn->template + insn->cond_offset);
7965 new->template = template;
7966 new->cond_offset = 0;
7967 new->variant = insn->variant;
7968 new->parms = insn->parms;
7969 new->value = (insn->value & ~COND_MASK) | conds[j].value;
7970
7971 hash_insert (arm_ops_hsh, new->template, (PTR) new);
7972 }
7973 }
7974 /* Finally, insert the unconditional insn in the table directly;
7975 no need to build a copy. */
7976 hash_insert (arm_ops_hsh, insn->template, (PTR) insn);
7977 }
7978}
7979
b99bd4ef
NC
7980void
7981md_begin ()
7982{
7983 unsigned mach;
7984 unsigned int i;
7985
7986 if ( (arm_ops_hsh = hash_new ()) == NULL
7987 || (arm_tops_hsh = hash_new ()) == NULL
7988 || (arm_cond_hsh = hash_new ()) == NULL
7989 || (arm_shift_hsh = hash_new ()) == NULL
b99bd4ef 7990 || (arm_psr_hsh = hash_new ()) == NULL)
f03698e6 7991 as_fatal (_("virtual memory exhausted"));
b99bd4ef 7992
90e4755a 7993 build_arm_ops_hsh ();
b99bd4ef
NC
7994 for (i = 0; i < sizeof (tinsns) / sizeof (struct thumb_opcode); i++)
7995 hash_insert (arm_tops_hsh, tinsns[i].template, (PTR) (tinsns + i));
7996 for (i = 0; i < sizeof (conds) / sizeof (struct asm_cond); i++)
7997 hash_insert (arm_cond_hsh, conds[i].template, (PTR) (conds + i));
7998 for (i = 0; i < sizeof (shift_names) / sizeof (struct asm_shift_name); i++)
7999 hash_insert (arm_shift_hsh, shift_names[i].name, (PTR) (shift_names + i));
8000 for (i = 0; i < sizeof (psrs) / sizeof (struct asm_psr); i++)
8001 hash_insert (arm_psr_hsh, psrs[i].template, (PTR) (psrs + i));
8002
6c43fab6
RE
8003 for (i = (int) REG_TYPE_FIRST; i < (int) REG_TYPE_MAX; i++)
8004 build_reg_hsh (all_reg_maps + i);
b99bd4ef
NC
8005
8006 set_constant_flonums ();
8007
8008#if defined OBJ_COFF || defined OBJ_ELF
8009 {
8010 unsigned int flags = 0;
8011
8012 /* Set the flags in the private structure. */
8013 if (uses_apcs_26) flags |= F_APCS26;
8014 if (support_interwork) flags |= F_INTERWORK;
8015 if (uses_apcs_float) flags |= F_APCS_FLOAT;
8016 if (pic_code) flags |= F_PIC;
b89dddec 8017 if ((cpu_variant & FPU_ANY) == FPU_NONE) flags |= F_SOFT_FLOAT;
b99bd4ef
NC
8018
8019 bfd_set_private_flags (stdoutput, flags);
8020
8021 /* We have run out flags in the COFF header to encode the
8022 status of ATPCS support, so instead we create a dummy,
8023 empty, debug section called .arm.atpcs. */
8024 if (atpcs)
8025 {
8026 asection * sec;
8027
8028 sec = bfd_make_section (stdoutput, ".arm.atpcs");
8029
8030 if (sec != NULL)
8031 {
8032 bfd_set_section_flags
8033 (stdoutput, sec, SEC_READONLY | SEC_DEBUGGING /* | SEC_HAS_CONTENTS */);
8034 bfd_set_section_size (stdoutput, sec, 0);
8035 bfd_set_section_contents (stdoutput, sec, NULL, 0, 0);
8036 }
8037 }
8038 }
8039#endif
8040
8041 /* Record the CPU type as well. */
8042 switch (cpu_variant & ARM_CPU_MASK)
8043 {
8044 case ARM_2:
8045 mach = bfd_mach_arm_2;
8046 break;
8047
8048 case ARM_3: /* Also ARM_250. */
8049 mach = bfd_mach_arm_2a;
8050 break;
8051
b89dddec
RE
8052 case ARM_6: /* Also ARM_7. */
8053 mach = bfd_mach_arm_3;
8054 break;
8055
b99bd4ef 8056 default:
b99bd4ef
NC
8057 mach = bfd_mach_arm_4;
8058 break;
b99bd4ef
NC
8059 }
8060
8061 /* Catch special cases. */
8062 if (cpu_variant & ARM_EXT_XSCALE)
8063 mach = bfd_mach_arm_XScale;
8064 else if (cpu_variant & ARM_EXT_V5E)
8065 mach = bfd_mach_arm_5TE;
8066 else if (cpu_variant & ARM_EXT_V5)
8067 {
b89dddec 8068 if (cpu_variant & ARM_EXT_V4T)
b99bd4ef
NC
8069 mach = bfd_mach_arm_5T;
8070 else
8071 mach = bfd_mach_arm_5;
8072 }
b89dddec 8073 else if (cpu_variant & ARM_EXT_V4)
b99bd4ef 8074 {
b89dddec 8075 if (cpu_variant & ARM_EXT_V4T)
b99bd4ef
NC
8076 mach = bfd_mach_arm_4T;
8077 else
8078 mach = bfd_mach_arm_4;
8079 }
b89dddec 8080 else if (cpu_variant & ARM_EXT_V3M)
b99bd4ef
NC
8081 mach = bfd_mach_arm_3M;
8082
8083 bfd_set_arch_mach (stdoutput, TARGET_ARCH, mach);
8084}
8085
8086/* Turn an integer of n bytes (in val) into a stream of bytes appropriate
8087 for use in the a.out file, and stores them in the array pointed to by buf.
8088 This knows about the endian-ness of the target machine and does
8089 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
8090 2 (short) and 4 (long) Floating numbers are put out as a series of
8091 LITTLENUMS (shorts, here at least). */
8092
8093void
8094md_number_to_chars (buf, val, n)
8095 char * buf;
8096 valueT val;
8097 int n;
8098{
8099 if (target_big_endian)
8100 number_to_chars_bigendian (buf, val, n);
8101 else
8102 number_to_chars_littleendian (buf, val, n);
8103}
8104
8105static valueT
8106md_chars_to_number (buf, n)
8107 char * buf;
8108 int n;
8109{
8110 valueT result = 0;
8111 unsigned char * where = (unsigned char *) buf;
8112
8113 if (target_big_endian)
8114 {
8115 while (n--)
8116 {
8117 result <<= 8;
8118 result |= (*where++ & 255);
8119 }
8120 }
8121 else
8122 {
8123 while (n--)
8124 {
8125 result <<= 8;
8126 result |= (where[n] & 255);
8127 }
8128 }
8129
8130 return result;
8131}
8132
8133/* Turn a string in input_line_pointer into a floating point constant
8134 of type TYPE, and store the appropriate bytes in *LITP. The number
8135 of LITTLENUMS emitted is stored in *SIZEP. An error message is
8136 returned, or NULL on OK.
8137
8138 Note that fp constants aren't represent in the normal way on the ARM.
8139 In big endian mode, things are as expected. However, in little endian
8140 mode fp constants are big-endian word-wise, and little-endian byte-wise
8141 within the words. For example, (double) 1.1 in big endian mode is
8142 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
8143 the byte sequence 99 99 f1 3f 9a 99 99 99.
8144
8145 ??? The format of 12 byte floats is uncertain according to gcc's arm.h. */
8146
8147char *
8148md_atof (type, litP, sizeP)
8149 char type;
8150 char * litP;
8151 int * sizeP;
8152{
8153 int prec;
8154 LITTLENUM_TYPE words[MAX_LITTLENUMS];
8155 char *t;
8156 int i;
8157
8158 switch (type)
8159 {
8160 case 'f':
8161 case 'F':
8162 case 's':
8163 case 'S':
8164 prec = 2;
8165 break;
8166
8167 case 'd':
8168 case 'D':
8169 case 'r':
8170 case 'R':
8171 prec = 4;
8172 break;
8173
8174 case 'x':
8175 case 'X':
8176 prec = 6;
8177 break;
8178
8179 case 'p':
8180 case 'P':
8181 prec = 6;
8182 break;
8183
8184 default:
8185 *sizeP = 0;
f03698e6 8186 return _("bad call to MD_ATOF()");
b99bd4ef
NC
8187 }
8188
8189 t = atof_ieee (input_line_pointer, type, words);
8190 if (t)
8191 input_line_pointer = t;
8192 *sizeP = prec * 2;
8193
8194 if (target_big_endian)
8195 {
8196 for (i = 0; i < prec; i++)
8197 {
8198 md_number_to_chars (litP, (valueT) words[i], 2);
8199 litP += 2;
8200 }
8201 }
8202 else
8203 {
8204 /* For a 4 byte float the order of elements in `words' is 1 0. For an
8205 8 byte float the order is 1 0 3 2. */
8206 for (i = 0; i < prec; i += 2)
8207 {
8208 md_number_to_chars (litP, (valueT) words[i + 1], 2);
8209 md_number_to_chars (litP + 2, (valueT) words[i], 2);
8210 litP += 4;
8211 }
8212 }
8213
8214 return 0;
8215}
8216
8217/* The knowledge of the PC's pipeline offset is built into the insns
8218 themselves. */
8219
8220long
8221md_pcrel_from (fixP)
8222 fixS * fixP;
8223{
8224 if (fixP->fx_addsy
8225 && S_GET_SEGMENT (fixP->fx_addsy) == undefined_section
8226 && fixP->fx_subsy == NULL)
8227 return 0;
8228
8229 if (fixP->fx_pcrel && (fixP->fx_r_type == BFD_RELOC_ARM_THUMB_ADD))
8230 {
8231 /* PC relative addressing on the Thumb is slightly odd
8232 as the bottom two bits of the PC are forced to zero
8233 for the calculation. */
8234 return (fixP->fx_where + fixP->fx_frag->fr_address) & ~3;
8235 }
8236
8237#ifdef TE_WINCE
8238 /* The pattern was adjusted to accomodate CE's off-by-one fixups,
8239 so we un-adjust here to compensate for the accomodation. */
8240 return fixP->fx_where + fixP->fx_frag->fr_address + 8;
8241#else
8242 return fixP->fx_where + fixP->fx_frag->fr_address;
8243#endif
8244}
8245
8246/* Round up a section size to the appropriate boundary. */
8247
8248valueT
8249md_section_align (segment, size)
8250 segT segment ATTRIBUTE_UNUSED;
8251 valueT size;
8252{
8253#ifdef OBJ_ELF
8254 return size;
8255#else
8256 /* Round all sects to multiple of 4. */
8257 return (size + 3) & ~3;
8258#endif
8259}
8260
8261/* Under ELF we need to default _GLOBAL_OFFSET_TABLE.
8262 Otherwise we have no need to default values of symbols. */
8263
8264symbolS *
8265md_undefined_symbol (name)
8266 char * name ATTRIBUTE_UNUSED;
8267{
8268#ifdef OBJ_ELF
8269 if (name[0] == '_' && name[1] == 'G'
8270 && streq (name, GLOBAL_OFFSET_TABLE_NAME))
8271 {
8272 if (!GOT_symbol)
8273 {
8274 if (symbol_find (name))
8275 as_bad ("GOT already in the symbol table");
8276
8277 GOT_symbol = symbol_new (name, undefined_section,
8278 (valueT) 0, & zero_address_frag);
8279 }
8280
8281 return GOT_symbol;
8282 }
8283#endif
8284
8285 return 0;
8286}
8287
8288/* arm_reg_parse () := if it looks like a register, return its token and
8289 advance the pointer. */
8290
8291static int
6c43fab6 8292arm_reg_parse (ccp, htab)
b99bd4ef 8293 register char ** ccp;
6c43fab6 8294 struct hash_control *htab;
b99bd4ef
NC
8295{
8296 char * start = * ccp;
8297 char c;
8298 char * p;
8299 struct reg_entry * reg;
8300
8301#ifdef REGISTER_PREFIX
8302 if (*start != REGISTER_PREFIX)
8303 return FAIL;
8304 p = start + 1;
8305#else
8306 p = start;
8307#ifdef OPTIONAL_REGISTER_PREFIX
8308 if (*p == OPTIONAL_REGISTER_PREFIX)
8309 p++, start++;
8310#endif
8311#endif
3882b010 8312 if (!ISALPHA (*p) || !is_name_beginner (*p))
b99bd4ef
NC
8313 return FAIL;
8314
8315 c = *p++;
3882b010 8316 while (ISALPHA (c) || ISDIGIT (c) || c == '_')
b99bd4ef
NC
8317 c = *p++;
8318
8319 *--p = 0;
6c43fab6 8320 reg = (struct reg_entry *) hash_find (htab, start);
b99bd4ef
NC
8321 *p = c;
8322
8323 if (reg)
8324 {
8325 *ccp = p;
8326 return reg->number;
8327 }
8328
8329 return FAIL;
8330}
8331
6c43fab6
RE
8332/* Search for the following register name in each of the possible reg name
8333 tables. Return the classification if found, or REG_TYPE_MAX if not
8334 present. */
8335static enum arm_reg_type
8336arm_reg_parse_any (cp)
8337 char *cp;
8338{
8339 int i;
8340
8341 for (i = (int) REG_TYPE_FIRST; i < (int) REG_TYPE_MAX; i++)
8342 if (arm_reg_parse (&cp, all_reg_maps[i].htab) != FAIL)
8343 return (enum arm_reg_type) i;
8344
8345 return REG_TYPE_MAX;
8346}
8347
94f592af
NC
8348void
8349md_apply_fix3 (fixP, valP, seg)
b99bd4ef 8350 fixS * fixP;
94f592af 8351 valueT * valP;
b99bd4ef
NC
8352 segT seg;
8353{
94f592af 8354 offsetT value = * valP;
b99bd4ef
NC
8355 offsetT newval;
8356 unsigned int newimm;
8357 unsigned long temp;
8358 int sign;
8359 char * buf = fixP->fx_where + fixP->fx_frag->fr_literal;
8360 arm_fix_data * arm_data = (arm_fix_data *) fixP->tc_fix_data;
8361
8362 assert (fixP->fx_r_type < BFD_RELOC_UNUSED);
8363
8364 /* Note whether this will delete the relocation. */
8365#if 0
8366 /* Patch from REarnshaw to JDavis (disabled for the moment, since it
8367 doesn't work fully.) */
8368 if ((fixP->fx_addsy == 0 || symbol_constant_p (fixP->fx_addsy))
8369 && !fixP->fx_pcrel)
8370#else
8371 if (fixP->fx_addsy == 0 && !fixP->fx_pcrel)
8372#endif
8373 fixP->fx_done = 1;
8374
8375 /* If this symbol is in a different section then we need to leave it for
8376 the linker to deal with. Unfortunately, md_pcrel_from can't tell,
8377 so we have to undo it's effects here. */
8378 if (fixP->fx_pcrel)
8379 {
8380 if (fixP->fx_addsy != NULL
8381 && S_IS_DEFINED (fixP->fx_addsy)
8382 && S_GET_SEGMENT (fixP->fx_addsy) != seg)
8383 {
8384 if (target_oabi
8385 && (fixP->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH
8386 || fixP->fx_r_type == BFD_RELOC_ARM_PCREL_BLX
8387 ))
8388 value = 0;
8389 else
8390 value += md_pcrel_from (fixP);
8391 }
8392 }
8393
8394 /* Remember value for emit_reloc. */
8395 fixP->fx_addnumber = value;
8396
8397 switch (fixP->fx_r_type)
8398 {
8399 case BFD_RELOC_ARM_IMMEDIATE:
8400 newimm = validate_immediate (value);
8401 temp = md_chars_to_number (buf, INSN_SIZE);
8402
8403 /* If the instruction will fail, see if we can fix things up by
8404 changing the opcode. */
8405 if (newimm == (unsigned int) FAIL
8406 && (newimm = negate_data_op (&temp, value)) == (unsigned int) FAIL)
8407 {
8408 as_bad_where (fixP->fx_file, fixP->fx_line,
8409 _("invalid constant (%lx) after fixup"),
8410 (unsigned long) value);
8411 break;
8412 }
8413
8414 newimm |= (temp & 0xfffff000);
8415 md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
8416 break;
8417
8418 case BFD_RELOC_ARM_ADRL_IMMEDIATE:
8419 {
8420 unsigned int highpart = 0;
8421 unsigned int newinsn = 0xe1a00000; /* nop. */
8422 newimm = validate_immediate (value);
8423 temp = md_chars_to_number (buf, INSN_SIZE);
8424
8425 /* If the instruction will fail, see if we can fix things up by
8426 changing the opcode. */
8427 if (newimm == (unsigned int) FAIL
8428 && (newimm = negate_data_op (& temp, value)) == (unsigned int) FAIL)
8429 {
8430 /* No ? OK - try using two ADD instructions to generate
8431 the value. */
8432 newimm = validate_immediate_twopart (value, & highpart);
8433
8434 /* Yes - then make sure that the second instruction is
8435 also an add. */
8436 if (newimm != (unsigned int) FAIL)
8437 newinsn = temp;
8438 /* Still No ? Try using a negated value. */
8439 else if ((newimm = validate_immediate_twopart (- value, & highpart)) != (unsigned int) FAIL)
8440 temp = newinsn = (temp & OPCODE_MASK) | OPCODE_SUB << DATA_OP_SHIFT;
8441 /* Otherwise - give up. */
8442 else
8443 {
8444 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 8445 _("unable to compute ADRL instructions for PC offset of 0x%lx"),
b99bd4ef
NC
8446 value);
8447 break;
8448 }
8449
8450 /* Replace the first operand in the 2nd instruction (which
8451 is the PC) with the destination register. We have
8452 already added in the PC in the first instruction and we
8453 do not want to do it again. */
8454 newinsn &= ~ 0xf0000;
8455 newinsn |= ((newinsn & 0x0f000) << 4);
8456 }
8457
8458 newimm |= (temp & 0xfffff000);
8459 md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
8460
8461 highpart |= (newinsn & 0xfffff000);
8462 md_number_to_chars (buf + INSN_SIZE, (valueT) highpart, INSN_SIZE);
8463 }
8464 break;
8465
8466 case BFD_RELOC_ARM_OFFSET_IMM:
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 _("bad immediate value for offset (%ld)"),
8476 (long) value);
8477 break;
8478 }
8479
8480 newval = md_chars_to_number (buf, INSN_SIZE);
8481 newval &= 0xff7ff000;
8482 newval |= value | (sign ? INDEX_UP : 0);
8483 md_number_to_chars (buf, newval, INSN_SIZE);
8484 break;
8485
8486 case BFD_RELOC_ARM_OFFSET_IMM8:
8487 case BFD_RELOC_ARM_HWLITERAL:
8488 sign = value >= 0;
8489
8490 if (value < 0)
8491 value = - value;
8492
8493 if (validate_offset_imm (value, 1) == FAIL)
8494 {
8495 if (fixP->fx_r_type == BFD_RELOC_ARM_HWLITERAL)
8496 as_bad_where (fixP->fx_file, fixP->fx_line,
8497 _("invalid literal constant: pool needs to be closer"));
8498 else
8499 as_bad (_("bad immediate value for half-word offset (%ld)"),
8500 (long) value);
8501 break;
8502 }
8503
8504 newval = md_chars_to_number (buf, INSN_SIZE);
8505 newval &= 0xff7ff0f0;
8506 newval |= ((value >> 4) << 8) | (value & 0xf) | (sign ? INDEX_UP : 0);
8507 md_number_to_chars (buf, newval, INSN_SIZE);
8508 break;
8509
8510 case BFD_RELOC_ARM_LITERAL:
8511 sign = value >= 0;
8512
8513 if (value < 0)
8514 value = - value;
8515
8516 if (validate_offset_imm (value, 0) == FAIL)
8517 {
8518 as_bad_where (fixP->fx_file, fixP->fx_line,
8519 _("invalid literal constant: pool needs to be closer"));
8520 break;
8521 }
8522
8523 newval = md_chars_to_number (buf, INSN_SIZE);
8524 newval &= 0xff7ff000;
8525 newval |= value | (sign ? INDEX_UP : 0);
8526 md_number_to_chars (buf, newval, INSN_SIZE);
8527 break;
8528
8529 case BFD_RELOC_ARM_SHIFT_IMM:
8530 newval = md_chars_to_number (buf, INSN_SIZE);
8531 if (((unsigned long) value) > 32
8532 || (value == 32
8533 && (((newval & 0x60) == 0) || (newval & 0x60) == 0x60)))
8534 {
8535 as_bad_where (fixP->fx_file, fixP->fx_line,
8536 _("shift expression is too large"));
8537 break;
8538 }
8539
8540 if (value == 0)
8541 /* Shifts of zero must be done as lsl. */
8542 newval &= ~0x60;
8543 else if (value == 32)
8544 value = 0;
8545 newval &= 0xfffff07f;
8546 newval |= (value & 0x1f) << 7;
8547 md_number_to_chars (buf, newval, INSN_SIZE);
8548 break;
8549
8550 case BFD_RELOC_ARM_SWI:
8551 if (arm_data->thumb_mode)
8552 {
8553 if (((unsigned long) value) > 0xff)
8554 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 8555 _("invalid swi expression"));
b99bd4ef
NC
8556 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xff00;
8557 newval |= value;
8558 md_number_to_chars (buf, newval, THUMB_SIZE);
8559 }
8560 else
8561 {
8562 if (((unsigned long) value) > 0x00ffffff)
8563 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 8564 _("invalid swi expression"));
b99bd4ef
NC
8565 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff000000;
8566 newval |= value;
8567 md_number_to_chars (buf, newval, INSN_SIZE);
8568 }
8569 break;
8570
8571 case BFD_RELOC_ARM_MULTI:
8572 if (((unsigned long) value) > 0xffff)
8573 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 8574 _("invalid expression in load/store multiple"));
b99bd4ef
NC
8575 newval = value | md_chars_to_number (buf, INSN_SIZE);
8576 md_number_to_chars (buf, newval, INSN_SIZE);
8577 break;
8578
8579 case BFD_RELOC_ARM_PCREL_BRANCH:
8580 newval = md_chars_to_number (buf, INSN_SIZE);
8581
8582 /* Sign-extend a 24-bit number. */
8583#define SEXT24(x) ((((x) & 0xffffff) ^ (~ 0x7fffff)) + 0x800000)
8584
8585#ifdef OBJ_ELF
8586 if (! target_oabi)
8587 value = fixP->fx_offset;
8588#endif
8589
8590 /* We are going to store value (shifted right by two) in the
8591 instruction, in a 24 bit, signed field. Thus we need to check
8592 that none of the top 8 bits of the shifted value (top 7 bits of
8593 the unshifted, unsigned value) are set, or that they are all set. */
8594 if ((value & ~ ((offsetT) 0x1ffffff)) != 0
8595 && ((value & ~ ((offsetT) 0x1ffffff)) != ~ ((offsetT) 0x1ffffff)))
8596 {
8597#ifdef OBJ_ELF
8598 /* Normally we would be stuck at this point, since we cannot store
8599 the absolute address that is the destination of the branch in the
8600 24 bits of the branch instruction. If however, we happen to know
8601 that the destination of the branch is in the same section as the
8602 branch instruciton itself, then we can compute the relocation for
8603 ourselves and not have to bother the linker with it.
8604
8605 FIXME: The tests for OBJ_ELF and ! target_oabi are only here
8606 because I have not worked out how to do this for OBJ_COFF or
8607 target_oabi. */
8608 if (! target_oabi
8609 && fixP->fx_addsy != NULL
8610 && S_IS_DEFINED (fixP->fx_addsy)
8611 && S_GET_SEGMENT (fixP->fx_addsy) == seg)
8612 {
8613 /* Get pc relative value to go into the branch. */
94f592af 8614 value = * valP;
b99bd4ef
NC
8615
8616 /* Permit a backward branch provided that enough bits
8617 are set. Allow a forwards branch, provided that
8618 enough bits are clear. */
8619 if ( (value & ~ ((offsetT) 0x1ffffff)) == ~ ((offsetT) 0x1ffffff)
8620 || (value & ~ ((offsetT) 0x1ffffff)) == 0)
8621 fixP->fx_done = 1;
8622 }
8623
8624 if (! fixP->fx_done)
8625#endif
8626 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 8627 _("GAS can't handle same-section branch dest >= 0x04000000"));
b99bd4ef
NC
8628 }
8629
8630 value >>= 2;
8631 value += SEXT24 (newval);
8632
8633 if ( (value & ~ ((offsetT) 0xffffff)) != 0
8634 && ((value & ~ ((offsetT) 0xffffff)) != ~ ((offsetT) 0xffffff)))
8635 as_bad_where (fixP->fx_file, fixP->fx_line,
8636 _("out of range branch"));
8637
8638 newval = (value & 0x00ffffff) | (newval & 0xff000000);
8639 md_number_to_chars (buf, newval, INSN_SIZE);
8640 break;
8641
8642 case BFD_RELOC_ARM_PCREL_BLX:
8643 {
8644 offsetT hbit;
8645 newval = md_chars_to_number (buf, INSN_SIZE);
8646
8647#ifdef OBJ_ELF
8648 if (! target_oabi)
8649 value = fixP->fx_offset;
8650#endif
8651 hbit = (value >> 1) & 1;
8652 value = (value >> 2) & 0x00ffffff;
8653 value = (value + (newval & 0x00ffffff)) & 0x00ffffff;
8654 newval = value | (newval & 0xfe000000) | (hbit << 24);
8655 md_number_to_chars (buf, newval, INSN_SIZE);
8656 }
8657 break;
8658
8659 case BFD_RELOC_THUMB_PCREL_BRANCH9: /* Conditional branch. */
8660 newval = md_chars_to_number (buf, THUMB_SIZE);
8661 {
8662 addressT diff = (newval & 0xff) << 1;
8663 if (diff & 0x100)
8664 diff |= ~0xff;
8665
8666 value += diff;
8667 if ((value & ~0xff) && ((value & ~0xff) != ~0xff))
8668 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 8669 _("branch out of range"));
b99bd4ef
NC
8670 newval = (newval & 0xff00) | ((value & 0x1ff) >> 1);
8671 }
8672 md_number_to_chars (buf, newval, THUMB_SIZE);
8673 break;
8674
8675 case BFD_RELOC_THUMB_PCREL_BRANCH12: /* Unconditional branch. */
8676 newval = md_chars_to_number (buf, THUMB_SIZE);
8677 {
8678 addressT diff = (newval & 0x7ff) << 1;
8679 if (diff & 0x800)
8680 diff |= ~0x7ff;
8681
8682 value += diff;
8683 if ((value & ~0x7ff) && ((value & ~0x7ff) != ~0x7ff))
8684 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 8685 _("branch out of range"));
b99bd4ef
NC
8686 newval = (newval & 0xf800) | ((value & 0xfff) >> 1);
8687 }
8688 md_number_to_chars (buf, newval, THUMB_SIZE);
8689 break;
8690
8691 case BFD_RELOC_THUMB_PCREL_BLX:
8692 case BFD_RELOC_THUMB_PCREL_BRANCH23:
8693 {
8694 offsetT newval2;
8695 addressT diff;
8696
8697 newval = md_chars_to_number (buf, THUMB_SIZE);
8698 newval2 = md_chars_to_number (buf + THUMB_SIZE, THUMB_SIZE);
8699 diff = ((newval & 0x7ff) << 12) | ((newval2 & 0x7ff) << 1);
8700 if (diff & 0x400000)
8701 diff |= ~0x3fffff;
8702#ifdef OBJ_ELF
8703 value = fixP->fx_offset;
8704#endif
8705 value += diff;
8706 if ((value & ~0x3fffff) && ((value & ~0x3fffff) != ~0x3fffff))
8707 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 8708 _("branch with link out of range"));
b99bd4ef
NC
8709
8710 newval = (newval & 0xf800) | ((value & 0x7fffff) >> 12);
8711 newval2 = (newval2 & 0xf800) | ((value & 0xfff) >> 1);
8712 if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX)
8713 /* Remove bit zero of the adjusted offset. Bit zero can only be
8714 set if the upper insn is at a half-word boundary, since the
8715 destination address, an ARM instruction, must always be on a
8716 word boundary. The semantics of the BLX (1) instruction, however,
8717 are that bit zero in the offset must always be zero, and the
8718 corresponding bit one in the target address will be set from bit
8719 one of the source address. */
8720 newval2 &= ~1;
8721 md_number_to_chars (buf, newval, THUMB_SIZE);
8722 md_number_to_chars (buf + THUMB_SIZE, newval2, THUMB_SIZE);
8723 }
8724 break;
8725
8726 case BFD_RELOC_8:
8727 if (fixP->fx_done || fixP->fx_pcrel)
8728 md_number_to_chars (buf, value, 1);
8729#ifdef OBJ_ELF
8730 else if (!target_oabi)
8731 {
8732 value = fixP->fx_offset;
8733 md_number_to_chars (buf, value, 1);
8734 }
8735#endif
8736 break;
8737
8738 case BFD_RELOC_16:
8739 if (fixP->fx_done || fixP->fx_pcrel)
8740 md_number_to_chars (buf, value, 2);
8741#ifdef OBJ_ELF
8742 else if (!target_oabi)
8743 {
8744 value = fixP->fx_offset;
8745 md_number_to_chars (buf, value, 2);
8746 }
8747#endif
8748 break;
8749
8750#ifdef OBJ_ELF
8751 case BFD_RELOC_ARM_GOT32:
8752 case BFD_RELOC_ARM_GOTOFF:
8753 md_number_to_chars (buf, 0, 4);
8754 break;
8755#endif
8756
8757 case BFD_RELOC_RVA:
8758 case BFD_RELOC_32:
8759 if (fixP->fx_done || fixP->fx_pcrel)
8760 md_number_to_chars (buf, value, 4);
8761#ifdef OBJ_ELF
8762 else if (!target_oabi)
8763 {
8764 value = fixP->fx_offset;
8765 md_number_to_chars (buf, value, 4);
8766 }
8767#endif
8768 break;
8769
8770#ifdef OBJ_ELF
8771 case BFD_RELOC_ARM_PLT32:
8772 /* It appears the instruction is fully prepared at this point. */
8773 break;
8774#endif
8775
8776 case BFD_RELOC_ARM_GOTPC:
8777 md_number_to_chars (buf, value, 4);
8778 break;
8779
8780 case BFD_RELOC_ARM_CP_OFF_IMM:
8781 sign = value >= 0;
8782 if (value < -1023 || value > 1023 || (value & 3))
8783 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 8784 _("illegal value for co-processor offset"));
b99bd4ef
NC
8785 if (value < 0)
8786 value = -value;
8787 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
8788 newval |= (value >> 2) | (sign ? INDEX_UP : 0);
8789 md_number_to_chars (buf, newval, INSN_SIZE);
8790 break;
8791
8792 case BFD_RELOC_ARM_THUMB_OFFSET:
8793 newval = md_chars_to_number (buf, THUMB_SIZE);
8794 /* Exactly what ranges, and where the offset is inserted depends
8795 on the type of instruction, we can establish this from the
8796 top 4 bits. */
8797 switch (newval >> 12)
8798 {
8799 case 4: /* PC load. */
8800 /* Thumb PC loads are somewhat odd, bit 1 of the PC is
8801 forced to zero for these loads, so we will need to round
8802 up the offset if the instruction address is not word
8803 aligned (since the final address produced must be, and
8804 we can only describe word-aligned immediate offsets). */
8805
8806 if ((fixP->fx_frag->fr_address + fixP->fx_where + value) & 3)
8807 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 8808 _("invalid offset, target not word aligned (0x%08X)"),
b99bd4ef
NC
8809 (unsigned int) (fixP->fx_frag->fr_address
8810 + fixP->fx_where + value));
8811
8812 if ((value + 2) & ~0x3fe)
8813 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 8814 _("invalid offset, value too big (0x%08lX)"), value);
b99bd4ef
NC
8815
8816 /* Round up, since pc will be rounded down. */
8817 newval |= (value + 2) >> 2;
8818 break;
8819
8820 case 9: /* SP load/store. */
8821 if (value & ~0x3fc)
8822 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 8823 _("invalid offset, value too big (0x%08lX)"), value);
b99bd4ef
NC
8824 newval |= value >> 2;
8825 break;
8826
8827 case 6: /* Word load/store. */
8828 if (value & ~0x7c)
8829 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 8830 _("invalid offset, value too big (0x%08lX)"), value);
b99bd4ef
NC
8831 newval |= value << 4; /* 6 - 2. */
8832 break;
8833
8834 case 7: /* Byte load/store. */
8835 if (value & ~0x1f)
8836 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 8837 _("invalid offset, value too big (0x%08lX)"), value);
b99bd4ef
NC
8838 newval |= value << 6;
8839 break;
8840
8841 case 8: /* Halfword load/store. */
8842 if (value & ~0x3e)
8843 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 8844 _("invalid offset, value too big (0x%08lX)"), value);
b99bd4ef
NC
8845 newval |= value << 5; /* 6 - 1. */
8846 break;
8847
8848 default:
8849 as_bad_where (fixP->fx_file, fixP->fx_line,
8850 "Unable to process relocation for thumb opcode: %lx",
8851 (unsigned long) newval);
8852 break;
8853 }
8854 md_number_to_chars (buf, newval, THUMB_SIZE);
8855 break;
8856
8857 case BFD_RELOC_ARM_THUMB_ADD:
8858 /* This is a complicated relocation, since we use it for all of
8859 the following immediate relocations:
8860
8861 3bit ADD/SUB
8862 8bit ADD/SUB
8863 9bit ADD/SUB SP word-aligned
8864 10bit ADD PC/SP word-aligned
8865
8866 The type of instruction being processed is encoded in the
8867 instruction field:
8868
8869 0x8000 SUB
8870 0x00F0 Rd
8871 0x000F Rs
8872 */
8873 newval = md_chars_to_number (buf, THUMB_SIZE);
8874 {
8875 int rd = (newval >> 4) & 0xf;
8876 int rs = newval & 0xf;
8877 int subtract = newval & 0x8000;
8878
8879 if (rd == REG_SP)
8880 {
8881 if (value & ~0x1fc)
8882 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 8883 _("invalid immediate for stack address calculation"));
b99bd4ef
NC
8884 newval = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
8885 newval |= value >> 2;
8886 }
8887 else if (rs == REG_PC || rs == REG_SP)
8888 {
8889 if (subtract ||
8890 value & ~0x3fc)
8891 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 8892 _("invalid immediate for address calculation (value = 0x%08lX)"),
b99bd4ef
NC
8893 (unsigned long) value);
8894 newval = (rs == REG_PC ? T_OPCODE_ADD_PC : T_OPCODE_ADD_SP);
8895 newval |= rd << 8;
8896 newval |= value >> 2;
8897 }
8898 else if (rs == rd)
8899 {
8900 if (value & ~0xff)
8901 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 8902 _("invalid 8bit immediate"));
b99bd4ef
NC
8903 newval = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
8904 newval |= (rd << 8) | value;
8905 }
8906 else
8907 {
8908 if (value & ~0x7)
8909 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 8910 _("invalid 3bit immediate"));
b99bd4ef
NC
8911 newval = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
8912 newval |= rd | (rs << 3) | (value << 6);
8913 }
8914 }
8915 md_number_to_chars (buf, newval, THUMB_SIZE);
8916 break;
8917
8918 case BFD_RELOC_ARM_THUMB_IMM:
8919 newval = md_chars_to_number (buf, THUMB_SIZE);
8920 switch (newval >> 11)
8921 {
8922 case 0x04: /* 8bit immediate MOV. */
8923 case 0x05: /* 8bit immediate CMP. */
8924 if (value < 0 || value > 255)
8925 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 8926 _("invalid immediate: %ld is too large"),
b99bd4ef
NC
8927 (long) value);
8928 newval |= value;
8929 break;
8930
8931 default:
8932 abort ();
8933 }
8934 md_number_to_chars (buf, newval, THUMB_SIZE);
8935 break;
8936
8937 case BFD_RELOC_ARM_THUMB_SHIFT:
8938 /* 5bit shift value (0..31). */
8939 if (value < 0 || value > 31)
8940 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 8941 _("illegal Thumb shift value: %ld"), (long) value);
b99bd4ef
NC
8942 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xf03f;
8943 newval |= value << 6;
8944 md_number_to_chars (buf, newval, THUMB_SIZE);
8945 break;
8946
8947 case BFD_RELOC_VTABLE_INHERIT:
8948 case BFD_RELOC_VTABLE_ENTRY:
8949 fixP->fx_done = 0;
94f592af 8950 return;
b99bd4ef
NC
8951
8952 case BFD_RELOC_NONE:
8953 default:
8954 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 8955 _("bad relocation fixup type (%d)"), fixP->fx_r_type);
b99bd4ef 8956 }
b99bd4ef
NC
8957}
8958
8959/* Translate internal representation of relocation info to BFD target
8960 format. */
8961
8962arelent *
8963tc_gen_reloc (section, fixp)
8964 asection * section ATTRIBUTE_UNUSED;
8965 fixS * fixp;
8966{
8967 arelent * reloc;
8968 bfd_reloc_code_real_type code;
8969
8970 reloc = (arelent *) xmalloc (sizeof (arelent));
8971
8972 reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
8973 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
8974 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
8975
8976 /* @@ Why fx_addnumber sometimes and fx_offset other times? */
8977#ifndef OBJ_ELF
8978 if (fixp->fx_pcrel == 0)
8979 reloc->addend = fixp->fx_offset;
8980 else
8981 reloc->addend = fixp->fx_offset = reloc->address;
8982#else /* OBJ_ELF */
8983 reloc->addend = fixp->fx_offset;
8984#endif
8985
8986 switch (fixp->fx_r_type)
8987 {
8988 case BFD_RELOC_8:
8989 if (fixp->fx_pcrel)
8990 {
8991 code = BFD_RELOC_8_PCREL;
8992 break;
8993 }
8994
8995 case BFD_RELOC_16:
8996 if (fixp->fx_pcrel)
8997 {
8998 code = BFD_RELOC_16_PCREL;
8999 break;
9000 }
9001
9002 case BFD_RELOC_32:
9003 if (fixp->fx_pcrel)
9004 {
9005 code = BFD_RELOC_32_PCREL;
9006 break;
9007 }
9008
9009 case BFD_RELOC_ARM_PCREL_BRANCH:
9010 case BFD_RELOC_ARM_PCREL_BLX:
9011 case BFD_RELOC_RVA:
9012 case BFD_RELOC_THUMB_PCREL_BRANCH9:
9013 case BFD_RELOC_THUMB_PCREL_BRANCH12:
9014 case BFD_RELOC_THUMB_PCREL_BRANCH23:
9015 case BFD_RELOC_THUMB_PCREL_BLX:
9016 case BFD_RELOC_VTABLE_ENTRY:
9017 case BFD_RELOC_VTABLE_INHERIT:
9018 code = fixp->fx_r_type;
9019 break;
9020
9021 case BFD_RELOC_ARM_LITERAL:
9022 case BFD_RELOC_ARM_HWLITERAL:
9023 /* If this is called then the a literal has been referenced across
9024 a section boundary - possibly due to an implicit dump. */
9025 as_bad_where (fixp->fx_file, fixp->fx_line,
f03698e6 9026 _("literal referenced across section boundary (Implicit dump?)"));
b99bd4ef
NC
9027 return NULL;
9028
9029#ifdef OBJ_ELF
9030 case BFD_RELOC_ARM_GOT32:
9031 case BFD_RELOC_ARM_GOTOFF:
9032 case BFD_RELOC_ARM_PLT32:
9033 code = fixp->fx_r_type;
9034 break;
9035#endif
9036
9037 case BFD_RELOC_ARM_IMMEDIATE:
9038 as_bad_where (fixp->fx_file, fixp->fx_line,
f03698e6 9039 _("internal relocation (type %d) not fixed up (IMMEDIATE)"),
b99bd4ef
NC
9040 fixp->fx_r_type);
9041 return NULL;
9042
9043 case BFD_RELOC_ARM_ADRL_IMMEDIATE:
9044 as_bad_where (fixp->fx_file, fixp->fx_line,
9045 _("ADRL used for a symbol not defined in the same file"));
9046 return NULL;
9047
9048 case BFD_RELOC_ARM_OFFSET_IMM:
9049 as_bad_where (fixp->fx_file, fixp->fx_line,
f03698e6 9050 _("internal_relocation (type %d) not fixed up (OFFSET_IMM)"),
b99bd4ef
NC
9051 fixp->fx_r_type);
9052 return NULL;
9053
9054 default:
9055 {
9056 char * type;
9057
9058 switch (fixp->fx_r_type)
9059 {
9060 case BFD_RELOC_ARM_IMMEDIATE: type = "IMMEDIATE"; break;
9061 case BFD_RELOC_ARM_OFFSET_IMM: type = "OFFSET_IMM"; break;
9062 case BFD_RELOC_ARM_OFFSET_IMM8: type = "OFFSET_IMM8"; break;
9063 case BFD_RELOC_ARM_SHIFT_IMM: type = "SHIFT_IMM"; break;
9064 case BFD_RELOC_ARM_SWI: type = "SWI"; break;
9065 case BFD_RELOC_ARM_MULTI: type = "MULTI"; break;
9066 case BFD_RELOC_ARM_CP_OFF_IMM: type = "CP_OFF_IMM"; break;
9067 case BFD_RELOC_ARM_THUMB_ADD: type = "THUMB_ADD"; break;
9068 case BFD_RELOC_ARM_THUMB_SHIFT: type = "THUMB_SHIFT"; break;
9069 case BFD_RELOC_ARM_THUMB_IMM: type = "THUMB_IMM"; break;
9070 case BFD_RELOC_ARM_THUMB_OFFSET: type = "THUMB_OFFSET"; break;
9071 default: type = _("<unknown>"); break;
9072 }
9073 as_bad_where (fixp->fx_file, fixp->fx_line,
f03698e6 9074 _("cannot represent %s relocation in this object file format"),
b99bd4ef
NC
9075 type);
9076 return NULL;
9077 }
9078 }
9079
9080#ifdef OBJ_ELF
9081 if (code == BFD_RELOC_32_PCREL
9082 && GOT_symbol
9083 && fixp->fx_addsy == GOT_symbol)
9084 {
9085 code = BFD_RELOC_ARM_GOTPC;
9086 reloc->addend = fixp->fx_offset = reloc->address;
9087 }
9088#endif
9089
9090 reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
9091
9092 if (reloc->howto == NULL)
9093 {
9094 as_bad_where (fixp->fx_file, fixp->fx_line,
f03698e6 9095 _("cannot represent %s relocation in this object file format"),
b99bd4ef
NC
9096 bfd_get_reloc_code_name (code));
9097 return NULL;
9098 }
9099
9100 /* HACK: Since arm ELF uses Rel instead of Rela, encode the
9101 vtable entry to be used in the relocation's section offset. */
9102 if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
9103 reloc->address = fixp->fx_offset;
9104
9105 return reloc;
9106}
9107
9108int
9109md_estimate_size_before_relax (fragP, segtype)
9110 fragS * fragP ATTRIBUTE_UNUSED;
9111 segT segtype ATTRIBUTE_UNUSED;
9112{
9113 as_fatal (_("md_estimate_size_before_relax\n"));
9114 return 1;
9115}
9116
9117static void
f03698e6
RE
9118output_inst (str)
9119 const char *str;
b99bd4ef
NC
9120{
9121 char * to = NULL;
9122
9123 if (inst.error)
9124 {
f03698e6 9125 as_bad ("%s -- `%s'", inst.error, str);
b99bd4ef
NC
9126 return;
9127 }
9128
9129 to = frag_more (inst.size);
9130
9131 if (thumb_mode && (inst.size > THUMB_SIZE))
9132 {
9133 assert (inst.size == (2 * THUMB_SIZE));
9134 md_number_to_chars (to, inst.instruction >> 16, THUMB_SIZE);
9135 md_number_to_chars (to + THUMB_SIZE, inst.instruction, THUMB_SIZE);
9136 }
9137 else if (inst.size > INSN_SIZE)
9138 {
9139 assert (inst.size == (2 * INSN_SIZE));
9140 md_number_to_chars (to, inst.instruction, INSN_SIZE);
9141 md_number_to_chars (to + INSN_SIZE, inst.instruction, INSN_SIZE);
9142 }
9143 else
9144 md_number_to_chars (to, inst.instruction, inst.size);
9145
9146 if (inst.reloc.type != BFD_RELOC_NONE)
9147 fix_new_arm (frag_now, to - frag_now->fr_literal,
9148 inst.size, & inst.reloc.exp, inst.reloc.pc_rel,
9149 inst.reloc.type);
9150
9151#ifdef OBJ_ELF
9152 dwarf2_emit_insn (inst.size);
9153#endif
9154}
9155
9156void
9157md_assemble (str)
9158 char * str;
9159{
6c43fab6
RE
9160 char c;
9161 char *p;
9162 char *start;
b99bd4ef
NC
9163
9164 /* Align the instruction.
9165 This may not be the right thing to do but ... */
9166#if 0
9167 arm_align (2, 0);
9168#endif
9169 listing_prev_line (); /* Defined in listing.h. */
9170
9171 /* Align the previous label if needed. */
9172 if (last_label_seen != NULL)
9173 {
9174 symbol_set_frag (last_label_seen, frag_now);
9175 S_SET_VALUE (last_label_seen, (valueT) frag_now_fix ());
9176 S_SET_SEGMENT (last_label_seen, now_seg);
9177 }
9178
9179 memset (&inst, '\0', sizeof (inst));
9180 inst.reloc.type = BFD_RELOC_NONE;
9181
9182 skip_whitespace (str);
9183
9184 /* Scan up to the end of the op-code, which must end in white space or
9185 end of string. */
9186 for (start = p = str; *p != '\0'; p++)
9187 if (*p == ' ')
9188 break;
9189
9190 if (p == str)
9191 {
f03698e6 9192 as_bad (_("no operator -- statement `%s'\n"), str);
b99bd4ef
NC
9193 return;
9194 }
9195
9196 if (thumb_mode)
9197 {
05d2d07e 9198 const struct thumb_opcode * opcode;
b99bd4ef
NC
9199
9200 c = *p;
9201 *p = '\0';
05d2d07e 9202 opcode = (const struct thumb_opcode *) hash_find (arm_tops_hsh, str);
b99bd4ef
NC
9203 *p = c;
9204
9205 if (opcode)
9206 {
9207 /* Check that this instruction is supported for this CPU. */
90e4755a 9208 if (thumb_mode == 1 && (opcode->variant & cpu_variant) == 0)
b99bd4ef 9209 {
f03698e6 9210 as_bad (_("selected processor does not support `%s'"), str);
b99bd4ef
NC
9211 return;
9212 }
9213
9214 inst.instruction = opcode->value;
9215 inst.size = opcode->size;
9216 (*opcode->parms) (p);
f03698e6 9217 output_inst (str);
b99bd4ef
NC
9218 return;
9219 }
9220 }
9221 else
9222 {
05d2d07e 9223 const struct asm_opcode * opcode;
b99bd4ef 9224
90e4755a
RE
9225 c = *p;
9226 *p = '\0';
6c43fab6 9227 opcode = (const struct asm_opcode *) hash_find (arm_ops_hsh, str);
90e4755a 9228 *p = c;
b99bd4ef 9229
90e4755a 9230 if (opcode)
b99bd4ef 9231 {
90e4755a
RE
9232 /* Check that this instruction is supported for this CPU. */
9233 if ((opcode->variant & cpu_variant) == 0)
b99bd4ef 9234 {
f03698e6 9235 as_bad (_("selected processor does not support `%s'"), str);
b99bd4ef
NC
9236 return;
9237 }
9238
90e4755a
RE
9239 inst.instruction = opcode->value;
9240 inst.size = INSN_SIZE;
f2b7cb0a 9241 (*opcode->parms) (p);
f03698e6 9242 output_inst (str);
90e4755a 9243 return;
b99bd4ef
NC
9244 }
9245 }
9246
9247 /* It wasn't an instruction, but it might be a register alias of the form
9248 alias .req reg. */
6c43fab6
RE
9249 if (create_register_alias (str, p))
9250 return;
b99bd4ef 9251
b99bd4ef
NC
9252 as_bad (_("bad instruction `%s'"), start);
9253}
9254
9255/* md_parse_option
9256 Invocation line includes a switch not recognized by the base assembler.
9257 See if it's a processor-specific option. These are:
9258 Cpu variants, the arm part is optional:
9259 -m[arm]1 Currently not supported.
9260 -m[arm]2, -m[arm]250 Arm 2 and Arm 250 processor
9261 -m[arm]3 Arm 3 processor
9262 -m[arm]6[xx], Arm 6 processors
9263 -m[arm]7[xx][t][[d]m] Arm 7 processors
9264 -m[arm]8[10] Arm 8 processors
9265 -m[arm]9[20][tdmi] Arm 9 processors
404ff6b5 9266 -marm9e Allow Cirrus/DSP instructions
b99bd4ef
NC
9267 -mstrongarm[110[0]] StrongARM processors
9268 -mxscale XScale processors
9269 -m[arm]v[2345[t[e]]] Arm architectures
9270 -mall All (except the ARM1)
9271 FP variants:
9272 -mfpa10, -mfpa11 FPA10 and 11 co-processor instructions
9273 -mfpe-old (No float load/store multiples)
9274 -mno-fpu Disable all floating point instructions
9275 Run-time endian selection:
9276 -EB big endian cpu
9277 -EL little endian cpu
9278 ARM Procedure Calling Standard:
9279 -mapcs-32 32 bit APCS
9280 -mapcs-26 26 bit APCS
9281 -mapcs-float Pass floats in float regs
9282 -mapcs-reentrant Position independent code
9283 -mthumb-interwork Code supports Arm/Thumb interworking
9284 -matpcs ARM/Thumb Procedure Call Standard
9285 -moabi Old ELF ABI */
9286
05d2d07e 9287const char * md_shortopts = "m:k";
b99bd4ef
NC
9288
9289struct option md_longopts[] =
9290{
9291#ifdef ARM_BI_ENDIAN
9292#define OPTION_EB (OPTION_MD_BASE + 0)
9293 {"EB", no_argument, NULL, OPTION_EB},
9294#define OPTION_EL (OPTION_MD_BASE + 1)
9295 {"EL", no_argument, NULL, OPTION_EL},
21f0f23a
RE
9296#else
9297 /* If the build isn't bi-endian, just support the flag that we are anyway.
9298 This makes things more portable. */
9299#if TARGET_BYTES_BIG_ENDIAN
9300#define OPTION_EB (OPTION_MD_BASE + 0)
9301 {"EB", no_argument, NULL, OPTION_EB},
9302#else
9303#define OPTION_EL (OPTION_MD_BASE + 1)
9304 {"EL", no_argument, NULL, OPTION_EL},
9305#endif
ce058b6c 9306#endif
b99bd4ef
NC
9307#ifdef OBJ_ELF
9308#define OPTION_OABI (OPTION_MD_BASE +2)
9309 {"oabi", no_argument, NULL, OPTION_OABI},
b99bd4ef
NC
9310#endif
9311 {NULL, no_argument, NULL, 0}
9312};
9313
9314size_t md_longopts_size = sizeof (md_longopts);
9315
9316int
9317md_parse_option (c, arg)
9318 int c;
9319 char * arg;
9320{
9321 char * str = arg;
9322
9323 switch (c)
9324 {
21f0f23a 9325#ifdef OPTION_EB
b99bd4ef
NC
9326 case OPTION_EB:
9327 target_big_endian = 1;
9328 break;
21f0f23a
RE
9329#endif
9330
9331#ifdef OPTION_EL
b99bd4ef
NC
9332 case OPTION_EL:
9333 target_big_endian = 0;
9334 break;
9335#endif
9336
9337 case 'm':
9338 switch (*str)
9339 {
9340 case 'f':
b89dddec
RE
9341 if (streq (str, "fpa10") || streq (str, "fpa11"))
9342 cpu_variant = (cpu_variant & ~FPU_ANY) | FPU_ARCH_FPA;
b99bd4ef 9343 else if (streq (str, "fpe-old"))
b89dddec 9344 cpu_variant = (cpu_variant & ~FPU_ANY) | FPU_ARCH_FPE;
b99bd4ef
NC
9345 else
9346 goto bad;
9347 break;
9348
9349 case 'n':
9350 if (streq (str, "no-fpu"))
b89dddec 9351 cpu_variant &= ~FPU_ANY;
b99bd4ef
NC
9352 break;
9353
9354#ifdef OBJ_ELF
9355 case 'o':
9356 if (streq (str, "oabi"))
9357 target_oabi = true;
9358 break;
9359#endif
9360
9361 case 't':
9362 /* Limit assembler to generating only Thumb instructions: */
9363 if (streq (str, "thumb"))
9364 {
b89dddec
RE
9365 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_EXT_V4T;
9366 cpu_variant = (cpu_variant & ~FPU_ANY) | FPU_NONE;
b99bd4ef
NC
9367 thumb_mode = 1;
9368 }
9369 else if (streq (str, "thumb-interwork"))
9370 {
b89dddec 9371 if ((cpu_variant & ARM_EXT_V4T) == 0)
b99bd4ef
NC
9372 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_ARCH_V4T;
9373#if defined OBJ_COFF || defined OBJ_ELF
9374 support_interwork = true;
9375#endif
9376 }
9377 else
9378 goto bad;
9379 break;
9380
9381 default:
9382 if (streq (str, "all"))
9383 {
b89dddec 9384 cpu_variant = ARM_ALL | FPU_DEFAULT;
b99bd4ef
NC
9385 return 1;
9386 }
9387#if defined OBJ_COFF || defined OBJ_ELF
9388 if (! strncmp (str, "apcs-", 5))
9389 {
9390 /* GCC passes on all command line options starting "-mapcs-..."
9391 to us, so we must parse them here. */
9392
9393 str += 5;
9394
9395 if (streq (str, "32"))
9396 {
9397 uses_apcs_26 = false;
9398 return 1;
9399 }
9400 else if (streq (str, "26"))
9401 {
9402 uses_apcs_26 = true;
9403 return 1;
9404 }
9405 else if (streq (str, "frame"))
9406 {
9407 /* Stack frames are being generated - does not affect
9408 linkage of code. */
9409 return 1;
9410 }
9411 else if (streq (str, "stack-check"))
9412 {
9413 /* Stack checking is being performed - does not affect
9414 linkage, but does require that the functions
9415 __rt_stkovf_split_small and __rt_stkovf_split_big be
9416 present in the final link. */
9417
9418 return 1;
9419 }
9420 else if (streq (str, "float"))
9421 {
9422 /* Floating point arguments are being passed in the floating
9423 point registers. This does affect linking, since this
9424 version of the APCS is incompatible with the version that
9425 passes floating points in the integer registers. */
9426
9427 uses_apcs_float = true;
9428 return 1;
9429 }
9430 else if (streq (str, "reentrant"))
9431 {
9432 /* Reentrant code has been generated. This does affect
9433 linking, since there is no point in linking reentrant/
9434 position independent code with absolute position code. */
9435 pic_code = true;
9436 return 1;
9437 }
9438
f03698e6 9439 as_bad (_("unrecognised APCS switch -m%s"), arg);
b99bd4ef
NC
9440 return 0;
9441 }
9442
9443 if (! strcmp (str, "atpcs"))
9444 {
9445 atpcs = true;
9446 return 1;
9447 }
9448#endif
9449 /* Strip off optional "arm". */
9450 if (! strncmp (str, "arm", 3))
9451 str += 3;
9452
9453 switch (*str)
9454 {
9455 case '1':
9456 if (streq (str, "1"))
9457 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_1;
9458 else
9459 goto bad;
9460 break;
9461
9462 case '2':
9463 if (streq (str, "2"))
9464 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_2;
9465 else if (streq (str, "250"))
9466 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_250;
9467 else
9468 goto bad;
9469 break;
9470
9471 case '3':
9472 if (streq (str, "3"))
9473 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_3;
9474 else
9475 goto bad;
9476 break;
9477
9478 case '6':
9479 switch (strtol (str, NULL, 10))
9480 {
9481 case 6:
9482 case 60:
9483 case 600:
9484 case 610:
9485 case 620:
9486 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_6;
9487 break;
9488 default:
9489 goto bad;
9490 }
9491 break;
9492
9493 case '7':
9494 /* Eat the processor name. */
9495 switch (strtol (str, & str, 10))
9496 {
9497 case 7:
9498 case 70:
9499 case 700:
9500 case 710:
9501 case 720:
9502 case 7100:
9503 case 7500:
9504 break;
9505 default:
9506 goto bad;
9507 }
9508 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_7;
9509 for (; *str; str++)
9510 {
9511 switch (*str)
9512 {
9513 case 't':
9514 cpu_variant |= ARM_ARCH_V4T;
9515 break;
9516
9517 case 'm':
b89dddec 9518 cpu_variant |= ARM_EXT_V3M;
b99bd4ef
NC
9519 break;
9520
9521 case 'f': /* fe => fp enabled cpu. */
9522 if (str[1] == 'e')
9523 ++ str;
9524 else
9525 goto bad;
9526
9527 case 'c': /* Left over from 710c processor name. */
9528 case 'd': /* Debug. */
9529 case 'i': /* Embedded ICE. */
9530 /* Included for completeness in ARM processor naming. */
9531 break;
9532
9533 default:
9534 goto bad;
9535 }
9536 }
9537 break;
9538
9539 case '8':
9540 if (streq (str, "8") || streq (str, "810"))
fcd6d8d6 9541 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_8;
b99bd4ef
NC
9542 else
9543 goto bad;
9544 break;
9545
9546 case '9':
9547 if (streq (str, "9"))
fcd6d8d6 9548 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_9;
b99bd4ef 9549 else if (streq (str, "920"))
fcd6d8d6 9550 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_9;
b99bd4ef 9551 else if (streq (str, "920t"))
fcd6d8d6 9552 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_9;
b99bd4ef 9553 else if (streq (str, "9tdmi"))
fcd6d8d6 9554 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_9;
404ff6b5 9555 else if (streq (str, "9e"))
fcd6d8d6 9556 /* XXX This is bogus: arm9e != maverick. */
404ff6b5 9557 cpu_variant = (cpu_variant & ~ARM_ANY)
fcd6d8d6 9558 | ARM_9 | ARM_EXT_MAVERICK;
b99bd4ef
NC
9559 else
9560 goto bad;
9561 break;
9562
9563 case 's':
9564 if (streq (str, "strongarm")
9565 || streq (str, "strongarm110")
9566 || streq (str, "strongarm1100"))
fcd6d8d6 9567 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_STRONG;
b99bd4ef
NC
9568 else
9569 goto bad;
9570 break;
9571
9572 case 'x':
9573 if (streq (str, "xscale"))
fcd6d8d6 9574 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_ARCH_XSCALE;
b99bd4ef
NC
9575 else
9576 goto bad;
9577 break;
9578
9579 case 'v':
9580 /* Select variant based on architecture rather than
9581 processor. */
9582 switch (*++str)
9583 {
9584 case '2':
9585 switch (*++str)
9586 {
9587 case 'a':
fcd6d8d6 9588 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_ARCH_V2S;
b99bd4ef
NC
9589 break;
9590 case 0:
fcd6d8d6 9591 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_ARCH_V2;
b99bd4ef
NC
9592 break;
9593 default:
f03698e6 9594 as_bad (_("invalid architecture variant -m%s"), arg);
b99bd4ef
NC
9595 break;
9596 }
9597 break;
9598
9599 case '3':
fcd6d8d6 9600 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_ARCH_V3;
b99bd4ef
NC
9601
9602 switch (*++str)
9603 {
b89dddec 9604 case 'm': cpu_variant |= ARM_EXT_V3M; break;
b99bd4ef
NC
9605 case 0: break;
9606 default:
f03698e6 9607 as_bad (_("invalid architecture variant -m%s"), arg);
b99bd4ef
NC
9608 break;
9609 }
9610 break;
9611
9612 case '4':
fcd6d8d6 9613 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_ARCH_V4;
b99bd4ef
NC
9614
9615 switch (*++str)
9616 {
b89dddec 9617 case 't': cpu_variant |= ARM_EXT_V4T; break;
b99bd4ef
NC
9618 case 0: break;
9619 default:
f03698e6 9620 as_bad (_("invalid architecture variant -m%s"), arg);
b99bd4ef
NC
9621 break;
9622 }
9623 break;
9624
9625 case '5':
fcd6d8d6 9626 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_ARCH_V5;
b99bd4ef
NC
9627 switch (*++str)
9628 {
fcd6d8d6 9629 case 't': cpu_variant |= ARM_EXT_V4T | ARM_EXT_V5T; break;
b99bd4ef
NC
9630 case 'e': cpu_variant |= ARM_EXT_V5E; break;
9631 case 0: break;
9632 default:
f03698e6 9633 as_bad (_("invalid architecture variant -m%s"), arg);
b99bd4ef
NC
9634 break;
9635 }
9636 break;
9637
9638 default:
f03698e6 9639 as_bad (_("invalid architecture variant -m%s"), arg);
b99bd4ef
NC
9640 break;
9641 }
9642 break;
9643
9644 default:
9645 bad:
f03698e6 9646 as_bad (_("invalid processor variant -m%s"), arg);
b99bd4ef
NC
9647 return 0;
9648 }
9649 }
9650 break;
9651
9652#if defined OBJ_ELF || defined OBJ_COFF
9653 case 'k':
9654 pic_code = 1;
9655 break;
9656#endif
9657
9658 default:
9659 return 0;
9660 }
9661
9662 return 1;
9663}
9664
9665void
9666md_show_usage (fp)
9667 FILE * fp;
9668{
9669 fprintf (fp, _("\
9670 ARM Specific Assembler Options:\n\
9671 -m[arm][<processor name>] select processor variant\n\
9672 -m[arm]v[2|2a|3|3m|4|4t|5[t][e]] select architecture variant\n\
404ff6b5 9673 -marm9e allow Cirrus/DSP instructions\n\
b99bd4ef
NC
9674 -mthumb only allow Thumb instructions\n\
9675 -mthumb-interwork mark the assembled code as supporting interworking\n\
9676 -mall allow any instruction\n\
9677 -mfpa10, -mfpa11 select floating point architecture\n\
9678 -mfpe-old don't allow floating-point multiple instructions\n\
9679 -mno-fpu don't allow any floating-point instructions.\n\
9680 -k generate PIC code.\n"));
9681#if defined OBJ_COFF || defined OBJ_ELF
9682 fprintf (fp, _("\
9683 -mapcs-32, -mapcs-26 specify which ARM Procedure Calling Standard to use\n\
9684 -matpcs use ARM/Thumb Procedure Calling Standard\n\
9685 -mapcs-float floating point args are passed in FP regs\n\
9686 -mapcs-reentrant the code is position independent/reentrant\n"));
9687#endif
9688#ifdef OBJ_ELF
9689 fprintf (fp, _("\
9690 -moabi support the old ELF ABI\n"));
9691#endif
9692#ifdef ARM_BI_ENDIAN
9693 fprintf (fp, _("\
9694 -EB assemble code for a big endian cpu\n\
9695 -EL assemble code for a little endian cpu\n"));
9696#endif
9697}
9698
9699/* We need to be able to fix up arbitrary expressions in some statements.
9700 This is so that we can handle symbols that are an arbitrary distance from
9701 the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
9702 which returns part of an address in a form which will be valid for
9703 a data instruction. We do this by pushing the expression into a symbol
9704 in the expr_section, and creating a fix for that. */
9705
9706static void
9707fix_new_arm (frag, where, size, exp, pc_rel, reloc)
9708 fragS * frag;
9709 int where;
9710 short int size;
9711 expressionS * exp;
9712 int pc_rel;
9713 int reloc;
9714{
9715 fixS * new_fix;
9716 arm_fix_data * arm_data;
9717
9718 switch (exp->X_op)
9719 {
9720 case O_constant:
9721 case O_symbol:
9722 case O_add:
9723 case O_subtract:
9724 new_fix = fix_new_exp (frag, where, size, exp, pc_rel, reloc);
9725 break;
9726
9727 default:
9728 new_fix = fix_new (frag, where, size, make_expr_symbol (exp), 0,
9729 pc_rel, reloc);
9730 break;
9731 }
9732
9733 /* Mark whether the fix is to a THUMB instruction, or an ARM
9734 instruction. */
9735 arm_data = (arm_fix_data *) obstack_alloc (& notes, sizeof (arm_fix_data));
9736 new_fix->tc_fix_data = (PTR) arm_data;
9737 arm_data->thumb_mode = thumb_mode;
9738
9739 return;
9740}
9741
9742/* This fix_new is called by cons via TC_CONS_FIX_NEW. */
9743
9744void
9745cons_fix_new_arm (frag, where, size, exp)
9746 fragS * frag;
9747 int where;
9748 int size;
9749 expressionS * exp;
9750{
9751 bfd_reloc_code_real_type type;
9752 int pcrel = 0;
9753
9754 /* Pick a reloc.
9755 FIXME: @@ Should look at CPU word size. */
9756 switch (size)
9757 {
9758 case 1:
9759 type = BFD_RELOC_8;
9760 break;
9761 case 2:
9762 type = BFD_RELOC_16;
9763 break;
9764 case 4:
9765 default:
9766 type = BFD_RELOC_32;
9767 break;
9768 case 8:
9769 type = BFD_RELOC_64;
9770 break;
9771 }
9772
9773 fix_new_exp (frag, where, (int) size, exp, pcrel, type);
9774}
9775
9776/* A good place to do this, although this was probably not intended
9777 for this kind of use. We need to dump the literal pool before
9778 references are made to a null symbol pointer. */
9779
9780void
9781arm_cleanup ()
9782{
9783 if (current_poolP == NULL)
9784 return;
9785
9786 /* Put it at the end of text section. */
9787 subseg_set (text_section, 0);
9788 s_ltorg (0);
9789 listing_prev_line ();
9790}
9791
9792void
9793arm_start_line_hook ()
9794{
9795 last_label_seen = NULL;
9796}
9797
9798void
9799arm_frob_label (sym)
9800 symbolS * sym;
9801{
9802 last_label_seen = sym;
9803
9804 ARM_SET_THUMB (sym, thumb_mode);
9805
9806#if defined OBJ_COFF || defined OBJ_ELF
9807 ARM_SET_INTERWORK (sym, support_interwork);
9808#endif
9809
9810 /* Note - do not allow local symbols (.Lxxx) to be labeled
9811 as Thumb functions. This is because these labels, whilst
9812 they exist inside Thumb code, are not the entry points for
9813 possible ARM->Thumb calls. Also, these labels can be used
9814 as part of a computed goto or switch statement. eg gcc
9815 can generate code that looks like this:
9816
9817 ldr r2, [pc, .Laaa]
9818 lsl r3, r3, #2
9819 ldr r2, [r3, r2]
9820 mov pc, r2
9821
9822 .Lbbb: .word .Lxxx
9823 .Lccc: .word .Lyyy
9824 ..etc...
9825 .Laaa: .word Lbbb
9826
9827 The first instruction loads the address of the jump table.
9828 The second instruction converts a table index into a byte offset.
9829 The third instruction gets the jump address out of the table.
9830 The fourth instruction performs the jump.
9831
9832 If the address stored at .Laaa is that of a symbol which has the
9833 Thumb_Func bit set, then the linker will arrange for this address
9834 to have the bottom bit set, which in turn would mean that the
9835 address computation performed by the third instruction would end
9836 up with the bottom bit set. Since the ARM is capable of unaligned
9837 word loads, the instruction would then load the incorrect address
9838 out of the jump table, and chaos would ensue. */
9839 if (label_is_thumb_function_name
9840 && (S_GET_NAME (sym)[0] != '.' || S_GET_NAME (sym)[1] != 'L')
9841 && (bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
9842 {
9843 /* When the address of a Thumb function is taken the bottom
9844 bit of that address should be set. This will allow
9845 interworking between Arm and Thumb functions to work
9846 correctly. */
9847
9848 THUMB_SET_FUNC (sym, 1);
9849
9850 label_is_thumb_function_name = false;
9851 }
9852}
9853
9854/* Adjust the symbol table. This marks Thumb symbols as distinct from
9855 ARM ones. */
9856
9857void
9858arm_adjust_symtab ()
9859{
9860#ifdef OBJ_COFF
9861 symbolS * sym;
9862
9863 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
9864 {
9865 if (ARM_IS_THUMB (sym))
9866 {
9867 if (THUMB_IS_FUNC (sym))
9868 {
9869 /* Mark the symbol as a Thumb function. */
9870 if ( S_GET_STORAGE_CLASS (sym) == C_STAT
9871 || S_GET_STORAGE_CLASS (sym) == C_LABEL) /* This can happen! */
9872 S_SET_STORAGE_CLASS (sym, C_THUMBSTATFUNC);
9873
9874 else if (S_GET_STORAGE_CLASS (sym) == C_EXT)
9875 S_SET_STORAGE_CLASS (sym, C_THUMBEXTFUNC);
9876 else
9877 as_bad (_("%s: unexpected function type: %d"),
9878 S_GET_NAME (sym), S_GET_STORAGE_CLASS (sym));
9879 }
9880 else switch (S_GET_STORAGE_CLASS (sym))
9881 {
9882 case C_EXT:
9883 S_SET_STORAGE_CLASS (sym, C_THUMBEXT);
9884 break;
9885 case C_STAT:
9886 S_SET_STORAGE_CLASS (sym, C_THUMBSTAT);
9887 break;
9888 case C_LABEL:
9889 S_SET_STORAGE_CLASS (sym, C_THUMBLABEL);
9890 break;
9891 default:
9892 /* Do nothing. */
9893 break;
9894 }
9895 }
9896
9897 if (ARM_IS_INTERWORK (sym))
9898 coffsymbol (symbol_get_bfdsym (sym))->native->u.syment.n_flags = 0xFF;
9899 }
9900#endif
9901#ifdef OBJ_ELF
9902 symbolS * sym;
9903 char bind;
9904
9905 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
9906 {
9907 if (ARM_IS_THUMB (sym))
9908 {
9909 elf_symbol_type * elf_sym;
9910
9911 elf_sym = elf_symbol (symbol_get_bfdsym (sym));
9912 bind = ELF_ST_BIND (elf_sym);
9913
9914 /* If it's a .thumb_func, declare it as so,
9915 otherwise tag label as .code 16. */
9916 if (THUMB_IS_FUNC (sym))
9917 elf_sym->internal_elf_sym.st_info =
9918 ELF_ST_INFO (bind, STT_ARM_TFUNC);
9919 else
9920 elf_sym->internal_elf_sym.st_info =
9921 ELF_ST_INFO (bind, STT_ARM_16BIT);
9922 }
9923 }
9924#endif
9925}
9926
9927int
9928arm_data_in_code ()
9929{
9930 if (thumb_mode && ! strncmp (input_line_pointer + 1, "data:", 5))
9931 {
9932 *input_line_pointer = '/';
9933 input_line_pointer += 5;
9934 *input_line_pointer = 0;
9935 return 1;
9936 }
9937
9938 return 0;
9939}
9940
9941char *
9942arm_canonicalize_symbol_name (name)
9943 char * name;
9944{
9945 int len;
9946
9947 if (thumb_mode && (len = strlen (name)) > 5
9948 && streq (name + len - 5, "/data"))
9949 *(name + len - 5) = 0;
9950
9951 return name;
9952}
9953
9954boolean
9955arm_validate_fix (fixP)
9956 fixS * fixP;
9957{
9958 /* If the destination of the branch is a defined symbol which does not have
9959 the THUMB_FUNC attribute, then we must be calling a function which has
9960 the (interfacearm) attribute. We look for the Thumb entry point to that
9961 function and change the branch to refer to that function instead. */
9962 if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23
9963 && fixP->fx_addsy != NULL
9964 && S_IS_DEFINED (fixP->fx_addsy)
9965 && ! THUMB_IS_FUNC (fixP->fx_addsy))
9966 {
9967 fixP->fx_addsy = find_real_start (fixP->fx_addsy);
9968 return true;
9969 }
9970
9971 return false;
9972}
9973
9974#ifdef OBJ_COFF
9975/* This is a little hack to help the gas/arm/adrl.s test. It prevents
9976 local labels from being added to the output symbol table when they
9977 are used with the ADRL pseudo op. The ADRL relocation should always
9978 be resolved before the binbary is emitted, so it is safe to say that
9979 it is adjustable. */
9980
9981boolean
9982arm_fix_adjustable (fixP)
9983 fixS * fixP;
9984{
9985 if (fixP->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE)
9986 return 1;
9987 return 0;
9988}
9989#endif
9990#ifdef OBJ_ELF
9991/* Relocations against Thumb function names must be left unadjusted,
9992 so that the linker can use this information to correctly set the
9993 bottom bit of their addresses. The MIPS version of this function
9994 also prevents relocations that are mips-16 specific, but I do not
9995 know why it does this.
9996
9997 FIXME:
9998 There is one other problem that ought to be addressed here, but
9999 which currently is not: Taking the address of a label (rather
10000 than a function) and then later jumping to that address. Such
10001 addresses also ought to have their bottom bit set (assuming that
10002 they reside in Thumb code), but at the moment they will not. */
10003
10004boolean
10005arm_fix_adjustable (fixP)
10006 fixS * fixP;
10007{
10008 if (fixP->fx_addsy == NULL)
10009 return 1;
10010
10011 /* Prevent all adjustments to global symbols. */
10012 if (S_IS_EXTERN (fixP->fx_addsy))
10013 return 0;
10014
10015 if (S_IS_WEAK (fixP->fx_addsy))
10016 return 0;
10017
10018 if (THUMB_IS_FUNC (fixP->fx_addsy)
10019 && fixP->fx_subsy == NULL)
10020 return 0;
10021
10022 /* We need the symbol name for the VTABLE entries. */
10023 if ( fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
10024 || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
10025 return 0;
10026
10027 return 1;
10028}
10029
10030const char *
10031elf32_arm_target_format ()
10032{
10033 if (target_big_endian)
10034 {
10035 if (target_oabi)
10036 return "elf32-bigarm-oabi";
10037 else
10038 return "elf32-bigarm";
10039 }
10040 else
10041 {
10042 if (target_oabi)
10043 return "elf32-littlearm-oabi";
10044 else
10045 return "elf32-littlearm";
10046 }
10047}
10048
10049void
10050armelf_frob_symbol (symp, puntp)
10051 symbolS * symp;
10052 int * puntp;
10053{
10054 elf_frob_symbol (symp, puntp);
10055}
10056
10057int
10058arm_force_relocation (fixp)
10059 struct fix * fixp;
10060{
10061 if ( fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT
10062 || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY
10063 || fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH
10064 || fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BLX
10065 || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX
10066 || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23)
10067 return 1;
10068
10069 return 0;
10070}
10071
10072static bfd_reloc_code_real_type
10073arm_parse_reloc ()
10074{
10075 char id [16];
10076 char * ip;
10077 unsigned int i;
10078 static struct
10079 {
10080 char * str;
10081 int len;
10082 bfd_reloc_code_real_type reloc;
10083 }
10084 reloc_map[] =
10085 {
10086#define MAP(str,reloc) { str, sizeof (str) - 1, reloc }
10087 MAP ("(got)", BFD_RELOC_ARM_GOT32),
10088 MAP ("(gotoff)", BFD_RELOC_ARM_GOTOFF),
10089 /* ScottB: Jan 30, 1998 - Added support for parsing "var(PLT)"
10090 branch instructions generated by GCC for PLT relocs. */
10091 MAP ("(plt)", BFD_RELOC_ARM_PLT32),
10092 { NULL, 0, BFD_RELOC_UNUSED }
10093#undef MAP
10094 };
10095
10096 for (i = 0, ip = input_line_pointer;
3882b010 10097 i < sizeof (id) && (ISALNUM (*ip) || ISPUNCT (*ip));
b99bd4ef 10098 i++, ip++)
3882b010 10099 id[i] = TOLOWER (*ip);
b99bd4ef
NC
10100
10101 for (i = 0; reloc_map[i].str; i++)
10102 if (strncmp (id, reloc_map[i].str, reloc_map[i].len) == 0)
10103 break;
10104
10105 input_line_pointer += reloc_map[i].len;
10106
10107 return reloc_map[i].reloc;
10108}
10109
10110static void
10111s_arm_elf_cons (nbytes)
10112 int nbytes;
10113{
10114 expressionS exp;
10115
10116#ifdef md_flush_pending_output
10117 md_flush_pending_output ();
10118#endif
10119
10120 if (is_it_end_of_statement ())
10121 {
10122 demand_empty_rest_of_line ();
10123 return;
10124 }
10125
10126#ifdef md_cons_align
10127 md_cons_align (nbytes);
10128#endif
10129
10130 do
10131 {
10132 bfd_reloc_code_real_type reloc;
10133
10134 expression (& exp);
10135
10136 if (exp.X_op == O_symbol
10137 && * input_line_pointer == '('
10138 && (reloc = arm_parse_reloc ()) != BFD_RELOC_UNUSED)
10139 {
10140 reloc_howto_type *howto = bfd_reloc_type_lookup (stdoutput, reloc);
10141 int size = bfd_get_reloc_size (howto);
10142
10143 if (size > nbytes)
10144 as_bad ("%s relocations do not fit in %d bytes",
10145 howto->name, nbytes);
10146 else
10147 {
10148 register char *p = frag_more ((int) nbytes);
10149 int offset = nbytes - size;
10150
10151 fix_new_exp (frag_now, p - frag_now->fr_literal + offset, size,
10152 &exp, 0, reloc);
10153 }
10154 }
10155 else
10156 emit_expr (&exp, (unsigned int) nbytes);
10157 }
10158 while (*input_line_pointer++ == ',');
10159
10160 /* Put terminator back into stream. */
10161 input_line_pointer --;
10162 demand_empty_rest_of_line ();
10163}
10164
10165#endif /* OBJ_ELF */
10166
10167/* This is called from HANDLE_ALIGN in write.c. Fill in the contents
10168 of an rs_align_code fragment. */
10169
10170void
10171arm_handle_align (fragP)
10172 fragS *fragP;
10173{
10174 static char const arm_noop[4] = { 0x00, 0x00, 0xa0, 0xe1 };
10175 static char const thumb_noop[2] = { 0xc0, 0x46 };
10176 static char const arm_bigend_noop[4] = { 0xe1, 0xa0, 0x00, 0x00 };
10177 static char const thumb_bigend_noop[2] = { 0x46, 0xc0 };
10178
10179 int bytes, fix, noop_size;
10180 char * p;
10181 const char * noop;
10182
10183 if (fragP->fr_type != rs_align_code)
10184 return;
10185
10186 bytes = fragP->fr_next->fr_address - fragP->fr_address - fragP->fr_fix;
10187 p = fragP->fr_literal + fragP->fr_fix;
10188 fix = 0;
10189
10190 if (bytes > MAX_MEM_FOR_RS_ALIGN_CODE)
10191 bytes &= MAX_MEM_FOR_RS_ALIGN_CODE;
10192
10193 if (fragP->tc_frag_data)
10194 {
10195 if (target_big_endian)
10196 noop = thumb_bigend_noop;
10197 else
10198 noop = thumb_noop;
10199 noop_size = sizeof (thumb_noop);
10200 }
10201 else
10202 {
10203 if (target_big_endian)
10204 noop = arm_bigend_noop;
10205 else
10206 noop = arm_noop;
10207 noop_size = sizeof (arm_noop);
10208 }
10209
10210 if (bytes & (noop_size - 1))
10211 {
10212 fix = bytes & (noop_size - 1);
10213 memset (p, 0, fix);
10214 p += fix;
10215 bytes -= fix;
10216 }
10217
10218 while (bytes >= noop_size)
10219 {
10220 memcpy (p, noop, noop_size);
10221 p += noop_size;
10222 bytes -= noop_size;
10223 fix += noop_size;
10224 }
10225
10226 fragP->fr_fix += fix;
10227 fragP->fr_var = noop_size;
10228}
10229
10230/* Called from md_do_align. Used to create an alignment
10231 frag in a code section. */
10232
10233void
10234arm_frag_align_code (n, max)
10235 int n;
10236 int max;
10237{
10238 char * p;
10239
10240 /* We assume that there will never be a requirment
10241 to support alignments greater than 32 bytes. */
10242 if (max > MAX_MEM_FOR_RS_ALIGN_CODE)
10243 as_fatal (_("alignments greater than 32 bytes not supported in .text sections."));
10244
10245 p = frag_var (rs_align_code,
10246 MAX_MEM_FOR_RS_ALIGN_CODE,
10247 1,
10248 (relax_substateT) max,
10249 (symbolS *) NULL,
10250 (offsetT) n,
10251 (char *) NULL);
10252 *p = 0;
10253
10254}
10255
10256/* Perform target specific initialisation of a frag. */
10257
10258void
10259arm_init_frag (fragP)
10260 fragS *fragP;
10261{
10262 /* Record whether this frag is in an ARM or a THUMB area. */
10263 fragP->tc_frag_data = thumb_mode;
10264}