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