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