* tc-arm.c (struct asm_opcode): Delete comp_suffix and flags. Add
[binutils.git] / gas / config / tc-arm.c
blob0eaf7bbe105baa1e6b78afa6727742104a82db7b
1 /* tc-arm.c -- Assemble for the ARM
2 Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
3 Free Software Foundation, Inc.
4 Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org)
5 Modified by David Taylor (dtaylor@armltd.co.uk)
6 Cirrus coprocessor mods by Aldy Hernandez (aldyh@redhat.com)
8 This file is part of GAS, the GNU Assembler.
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.
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.
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. */
25 #include <string.h>
26 #define NO_RELOC 0
27 #include "as.h"
28 #include "safe-ctype.h"
30 /* Need TARGET_CPU. */
31 #include "config.h"
32 #include "subsegs.h"
33 #include "obstack.h"
34 #include "symbols.h"
35 #include "listing.h"
37 #ifdef OBJ_ELF
38 #include "elf/arm.h"
39 #include "dwarf2dbg.h"
40 #endif
42 /* The following bitmasks control CPU extensions: */
43 #define ARM_EXT_V1 0x00000001 /* All processors (core set). */
44 #define ARM_EXT_V2 0x00000002 /* Multiply instructions. */
45 #define ARM_EXT_V2S 0x00000004 /* SWP instructions. */
46 #define ARM_EXT_V3 0x00000008 /* MSR MRS. */
47 #define ARM_EXT_V3M 0x00000010 /* Allow long multiplies. */
48 #define ARM_EXT_V4 0x00000020 /* Allow half word loads. */
49 #define ARM_EXT_V4T 0x00000040 /* Thumb v1. */
50 #define ARM_EXT_V5 0x00000080 /* Allow CLZ, etc. */
51 #define ARM_EXT_V5T 0x00000100 /* Thumb v2. */
52 #define ARM_EXT_V5ExP 0x00000200 /* DSP core set. */
53 #define ARM_EXT_V5E 0x00000400 /* DSP Double transfers. */
54 /* Processor specific extensions. */
55 #define ARM_EXT_XSCALE 0x00000800 /* Allow MIA etc. */
56 #define ARM_EXT_MAVERICK 0x00001000 /* Use Cirrus/DSP coprocessor. */
58 /* Architectures are the sum of the base and extensions. The ARM ARM (rev E)
59 defines the following: ARMv3, ARMv3M, ARMv4xM, ARMv4, ARMv4TxM, ARMv4T,
60 ARMv5xM, ARMv5, ARMv5TxM, ARMv5T, ARMv5TExP, ARMv5TE. To these we add
61 three more to cover cores prior to ARM6. Finally, there are cores which
62 implement further extensions in the co-processor space. */
63 #define ARM_ARCH_V1 ARM_EXT_V1
64 #define ARM_ARCH_V2 (ARM_ARCH_V1 | ARM_EXT_V2)
65 #define ARM_ARCH_V2S (ARM_ARCH_V2 | ARM_EXT_V2S)
66 #define ARM_ARCH_V3 (ARM_ARCH_V2S | ARM_EXT_V3)
67 #define ARM_ARCH_V3M (ARM_ARCH_V3 | ARM_EXT_V3M)
68 #define ARM_ARCH_V4xM (ARM_ARCH_V3 | ARM_EXT_V4)
69 #define ARM_ARCH_V4 (ARM_ARCH_V3M | ARM_EXT_V4)
70 #define ARM_ARCH_V4TxM (ARM_ARCH_V4xM | ARM_EXT_V4T)
71 #define ARM_ARCH_V4T (ARM_ARCH_V4 | ARM_EXT_V4T)
72 #define ARM_ARCH_V5xM (ARM_ARCH_V4xM | ARM_EXT_V5)
73 #define ARM_ARCH_V5 (ARM_ARCH_V4 | ARM_EXT_V5)
74 #define ARM_ARCH_V5TxM (ARM_ARCH_V5xM | ARM_EXT_V4T | ARM_EXT_V5T)
75 #define ARM_ARCH_V5T (ARM_ARCH_V5 | ARM_EXT_V4T | ARM_EXT_V5T)
76 #define ARM_ARCH_V5TExP (ARM_ARCH_V5T | ARM_EXT_V5ExP)
77 #define ARM_ARCH_V5TE (ARM_ARCH_V5TExP | ARM_EXT_V5E)
78 /* Processors with specific extensions in the co-processor space. */
79 #define ARM_ARCH_XSCALE (ARM_ARCH_V5TE | ARM_EXT_XSCALE)
81 /* Some useful combinations: */
82 #define ARM_ANY 0x00ffffff
83 #define ARM_ALL ARM_ANY
85 #define FPU_FPA_EXT_V1 0x80000000 /* Base FPA instruction set. */
86 #define FPU_FPA_EXT_V2 0x40000000 /* LFM/SFM. */
87 #define FPU_NONE 0
89 #define FPU_ARCH_FPE FPU_FPA_EXT_V1
90 #define FPU_ARCH_FPA (FPU_ARCH_FPE | FPU_FPA_EXT_V2)
92 /* Some useful combinations. */
93 #define FPU_ANY 0xff000000 /* Note this is ~ARM_ANY. */
95 /* Types of processor to assemble for. */
96 #define ARM_1 ARM_ARCH_V1
97 #define ARM_2 ARM_ARCH_V2
98 #define ARM_3 ARM_ARCH_V2S
99 #define ARM_250 ARM_ARCH_V2S
100 #define ARM_6 ARM_ARCH_V3
101 #define ARM_7 ARM_ARCH_V3
102 #define ARM_8 ARM_ARCH_V4
103 #define ARM_9 ARM_ARCH_V4T
104 #define ARM_STRONG ARM_ARCH_V4
105 #define ARM_CPU_MASK 0x0000000f /* XXX? */
107 #ifndef CPU_DEFAULT
108 #if defined __XSCALE__
109 #define CPU_DEFAULT (ARM_ARCH_XSCALE)
110 #else
111 #if defined __thumb__
112 #define CPU_DEFAULT (ARM_ARCH_V5T)
113 #else
114 #define CPU_DEFAULT ARM_ALL
115 #endif
116 #endif
117 #endif
119 #ifndef FPU_DEFAULT
120 #define FPU_DEFAULT FPU_ARCH_FPA
121 #endif
123 #define streq(a, b) (strcmp (a, b) == 0)
124 #define skip_whitespace(str) while (*(str) == ' ') ++(str)
126 static unsigned long cpu_variant = CPU_DEFAULT | FPU_DEFAULT;
127 static int target_oabi = 0;
129 #if defined OBJ_COFF || defined OBJ_ELF
130 /* Flags stored in private area of BFD structure. */
131 static boolean uses_apcs_26 = false;
132 static boolean atpcs = false;
133 static boolean support_interwork = false;
134 static boolean uses_apcs_float = false;
135 static boolean pic_code = false;
136 #endif
138 /* This array holds the chars that always start a comment. If the
139 pre-processor is disabled, these aren't very useful. */
140 const char comment_chars[] = "@";
142 /* This array holds the chars that only start a comment at the beginning of
143 a line. If the line seems to have the form '# 123 filename'
144 .line and .file directives will appear in the pre-processed output. */
145 /* Note that input_file.c hand checks for '#' at the beginning of the
146 first line of the input file. This is because the compiler outputs
147 #NO_APP at the beginning of its output. */
148 /* Also note that comments like this one will always work. */
149 const char line_comment_chars[] = "#";
151 const char line_separator_chars[] = ";";
153 /* Chars that can be used to separate mant
154 from exp in floating point numbers. */
155 const char EXP_CHARS[] = "eE";
157 /* Chars that mean this number is a floating point constant. */
158 /* As in 0f12.456 */
159 /* or 0d1.2345e12 */
161 const char FLT_CHARS[] = "rRsSfFdDxXeEpP";
163 /* Prefix characters that indicate the start of an immediate
164 value. */
165 #define is_immediate_prefix(C) ((C) == '#' || (C) == '$')
167 #ifdef OBJ_ELF
168 /* Pre-defined "_GLOBAL_OFFSET_TABLE_" */
169 symbolS * GOT_symbol;
170 #endif
172 /* Size of relocation record. */
173 const int md_reloc_size = 8;
175 /* 0: assemble for ARM,
176 1: assemble for Thumb,
177 2: assemble for Thumb even though target CPU does not support thumb
178 instructions. */
179 static int thumb_mode = 0;
181 typedef struct arm_fix
183 int thumb_mode;
184 } arm_fix_data;
186 struct arm_it
188 const char * error;
189 unsigned long instruction;
190 int size;
191 struct
193 bfd_reloc_code_real_type type;
194 expressionS exp;
195 int pc_rel;
196 } reloc;
199 struct arm_it inst;
201 enum asm_shift_index
203 SHIFT_LSL = 0,
204 SHIFT_LSR,
205 SHIFT_ASR,
206 SHIFT_ROR,
207 SHIFT_RRX
210 struct asm_shift_properties
212 enum asm_shift_index index;
213 unsigned long bit_field;
214 unsigned int allows_0 : 1;
215 unsigned int allows_32 : 1;
218 static const struct asm_shift_properties shift_properties [] =
220 { SHIFT_LSL, 0, 1, 0},
221 { SHIFT_LSR, 0x20, 0, 1},
222 { SHIFT_ASR, 0x40, 0, 1},
223 { SHIFT_ROR, 0x60, 0, 0},
224 { SHIFT_RRX, 0x60, 0, 0}
227 struct asm_shift_name
229 const char * name;
230 const struct asm_shift_properties * properties;
233 static const struct asm_shift_name shift_names [] =
235 { "asl", shift_properties + SHIFT_LSL },
236 { "lsl", shift_properties + SHIFT_LSL },
237 { "lsr", shift_properties + SHIFT_LSR },
238 { "asr", shift_properties + SHIFT_ASR },
239 { "ror", shift_properties + SHIFT_ROR },
240 { "rrx", shift_properties + SHIFT_RRX },
241 { "ASL", shift_properties + SHIFT_LSL },
242 { "LSL", shift_properties + SHIFT_LSL },
243 { "LSR", shift_properties + SHIFT_LSR },
244 { "ASR", shift_properties + SHIFT_ASR },
245 { "ROR", shift_properties + SHIFT_ROR },
246 { "RRX", shift_properties + SHIFT_RRX }
249 #define NO_SHIFT_RESTRICT 1
250 #define SHIFT_RESTRICT 0
252 #define NUM_FLOAT_VALS 8
254 const char * fp_const[] =
256 "0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0", 0
259 /* Number of littlenums required to hold an extended precision number. */
260 #define MAX_LITTLENUMS 6
262 LITTLENUM_TYPE fp_values[NUM_FLOAT_VALS][MAX_LITTLENUMS];
264 #define FAIL (-1)
265 #define SUCCESS (0)
267 #define SUFF_S 1
268 #define SUFF_D 2
269 #define SUFF_E 3
270 #define SUFF_P 4
272 #define CP_T_X 0x00008000
273 #define CP_T_Y 0x00400000
274 #define CP_T_Pre 0x01000000
275 #define CP_T_UD 0x00800000
276 #define CP_T_WB 0x00200000
278 #define CONDS_BIT 0x00100000
279 #define LOAD_BIT 0x00100000
281 #define DOUBLE_LOAD_FLAG 0x00000001
283 struct asm_cond
285 const char * template;
286 unsigned long value;
289 #define COND_ALWAYS 0xe0000000
290 #define COND_MASK 0xf0000000
292 static const struct asm_cond conds[] =
294 {"eq", 0x00000000},
295 {"ne", 0x10000000},
296 {"cs", 0x20000000}, {"hs", 0x20000000},
297 {"cc", 0x30000000}, {"ul", 0x30000000}, {"lo", 0x30000000},
298 {"mi", 0x40000000},
299 {"pl", 0x50000000},
300 {"vs", 0x60000000},
301 {"vc", 0x70000000},
302 {"hi", 0x80000000},
303 {"ls", 0x90000000},
304 {"ge", 0xa0000000},
305 {"lt", 0xb0000000},
306 {"gt", 0xc0000000},
307 {"le", 0xd0000000},
308 {"al", 0xe0000000},
309 {"nv", 0xf0000000}
312 struct asm_psr
314 const char * template;
315 boolean cpsr;
316 unsigned long field;
319 /* The bit that distnguishes CPSR and SPSR. */
320 #define SPSR_BIT (1 << 22)
322 /* How many bits to shift the PSR_xxx bits up by. */
323 #define PSR_SHIFT 16
325 #define PSR_c (1 << 0)
326 #define PSR_x (1 << 1)
327 #define PSR_s (1 << 2)
328 #define PSR_f (1 << 3)
330 static const struct asm_psr psrs[] =
332 {"CPSR", true, PSR_c | PSR_f},
333 {"CPSR_all", true, PSR_c | PSR_f},
334 {"SPSR", false, PSR_c | PSR_f},
335 {"SPSR_all", false, PSR_c | PSR_f},
336 {"CPSR_flg", true, PSR_f},
337 {"CPSR_f", true, PSR_f},
338 {"SPSR_flg", false, PSR_f},
339 {"SPSR_f", false, PSR_f},
340 {"CPSR_c", true, PSR_c},
341 {"CPSR_ctl", true, PSR_c},
342 {"SPSR_c", false, PSR_c},
343 {"SPSR_ctl", false, PSR_c},
344 {"CPSR_x", true, PSR_x},
345 {"CPSR_s", true, PSR_s},
346 {"SPSR_x", false, PSR_x},
347 {"SPSR_s", false, PSR_s},
348 /* Combinations of flags. */
349 {"CPSR_fs", true, PSR_f | PSR_s},
350 {"CPSR_fx", true, PSR_f | PSR_x},
351 {"CPSR_fc", true, PSR_f | PSR_c},
352 {"CPSR_sf", true, PSR_s | PSR_f},
353 {"CPSR_sx", true, PSR_s | PSR_x},
354 {"CPSR_sc", true, PSR_s | PSR_c},
355 {"CPSR_xf", true, PSR_x | PSR_f},
356 {"CPSR_xs", true, PSR_x | PSR_s},
357 {"CPSR_xc", true, PSR_x | PSR_c},
358 {"CPSR_cf", true, PSR_c | PSR_f},
359 {"CPSR_cs", true, PSR_c | PSR_s},
360 {"CPSR_cx", true, PSR_c | PSR_x},
361 {"CPSR_fsx", true, PSR_f | PSR_s | PSR_x},
362 {"CPSR_fsc", true, PSR_f | PSR_s | PSR_c},
363 {"CPSR_fxs", true, PSR_f | PSR_x | PSR_s},
364 {"CPSR_fxc", true, PSR_f | PSR_x | PSR_c},
365 {"CPSR_fcs", true, PSR_f | PSR_c | PSR_s},
366 {"CPSR_fcx", true, PSR_f | PSR_c | PSR_x},
367 {"CPSR_sfx", true, PSR_s | PSR_f | PSR_x},
368 {"CPSR_sfc", true, PSR_s | PSR_f | PSR_c},
369 {"CPSR_sxf", true, PSR_s | PSR_x | PSR_f},
370 {"CPSR_sxc", true, PSR_s | PSR_x | PSR_c},
371 {"CPSR_scf", true, PSR_s | PSR_c | PSR_f},
372 {"CPSR_scx", true, PSR_s | PSR_c | PSR_x},
373 {"CPSR_xfs", true, PSR_x | PSR_f | PSR_s},
374 {"CPSR_xfc", true, PSR_x | PSR_f | PSR_c},
375 {"CPSR_xsf", true, PSR_x | PSR_s | PSR_f},
376 {"CPSR_xsc", true, PSR_x | PSR_s | PSR_c},
377 {"CPSR_xcf", true, PSR_x | PSR_c | PSR_f},
378 {"CPSR_xcs", true, PSR_x | PSR_c | PSR_s},
379 {"CPSR_cfs", true, PSR_c | PSR_f | PSR_s},
380 {"CPSR_cfx", true, PSR_c | PSR_f | PSR_x},
381 {"CPSR_csf", true, PSR_c | PSR_s | PSR_f},
382 {"CPSR_csx", true, PSR_c | PSR_s | PSR_x},
383 {"CPSR_cxf", true, PSR_c | PSR_x | PSR_f},
384 {"CPSR_cxs", true, PSR_c | PSR_x | PSR_s},
385 {"CPSR_fsxc", true, PSR_f | PSR_s | PSR_x | PSR_c},
386 {"CPSR_fscx", true, PSR_f | PSR_s | PSR_c | PSR_x},
387 {"CPSR_fxsc", true, PSR_f | PSR_x | PSR_s | PSR_c},
388 {"CPSR_fxcs", true, PSR_f | PSR_x | PSR_c | PSR_s},
389 {"CPSR_fcsx", true, PSR_f | PSR_c | PSR_s | PSR_x},
390 {"CPSR_fcxs", true, PSR_f | PSR_c | PSR_x | PSR_s},
391 {"CPSR_sfxc", true, PSR_s | PSR_f | PSR_x | PSR_c},
392 {"CPSR_sfcx", true, PSR_s | PSR_f | PSR_c | PSR_x},
393 {"CPSR_sxfc", true, PSR_s | PSR_x | PSR_f | PSR_c},
394 {"CPSR_sxcf", true, PSR_s | PSR_x | PSR_c | PSR_f},
395 {"CPSR_scfx", true, PSR_s | PSR_c | PSR_f | PSR_x},
396 {"CPSR_scxf", true, PSR_s | PSR_c | PSR_x | PSR_f},
397 {"CPSR_xfsc", true, PSR_x | PSR_f | PSR_s | PSR_c},
398 {"CPSR_xfcs", true, PSR_x | PSR_f | PSR_c | PSR_s},
399 {"CPSR_xsfc", true, PSR_x | PSR_s | PSR_f | PSR_c},
400 {"CPSR_xscf", true, PSR_x | PSR_s | PSR_c | PSR_f},
401 {"CPSR_xcfs", true, PSR_x | PSR_c | PSR_f | PSR_s},
402 {"CPSR_xcsf", true, PSR_x | PSR_c | PSR_s | PSR_f},
403 {"CPSR_cfsx", true, PSR_c | PSR_f | PSR_s | PSR_x},
404 {"CPSR_cfxs", true, PSR_c | PSR_f | PSR_x | PSR_s},
405 {"CPSR_csfx", true, PSR_c | PSR_s | PSR_f | PSR_x},
406 {"CPSR_csxf", true, PSR_c | PSR_s | PSR_x | PSR_f},
407 {"CPSR_cxfs", true, PSR_c | PSR_x | PSR_f | PSR_s},
408 {"CPSR_cxsf", true, PSR_c | PSR_x | PSR_s | PSR_f},
409 {"SPSR_fs", false, PSR_f | PSR_s},
410 {"SPSR_fx", false, PSR_f | PSR_x},
411 {"SPSR_fc", false, PSR_f | PSR_c},
412 {"SPSR_sf", false, PSR_s | PSR_f},
413 {"SPSR_sx", false, PSR_s | PSR_x},
414 {"SPSR_sc", false, PSR_s | PSR_c},
415 {"SPSR_xf", false, PSR_x | PSR_f},
416 {"SPSR_xs", false, PSR_x | PSR_s},
417 {"SPSR_xc", false, PSR_x | PSR_c},
418 {"SPSR_cf", false, PSR_c | PSR_f},
419 {"SPSR_cs", false, PSR_c | PSR_s},
420 {"SPSR_cx", false, PSR_c | PSR_x},
421 {"SPSR_fsx", false, PSR_f | PSR_s | PSR_x},
422 {"SPSR_fsc", false, PSR_f | PSR_s | PSR_c},
423 {"SPSR_fxs", false, PSR_f | PSR_x | PSR_s},
424 {"SPSR_fxc", false, PSR_f | PSR_x | PSR_c},
425 {"SPSR_fcs", false, PSR_f | PSR_c | PSR_s},
426 {"SPSR_fcx", false, PSR_f | PSR_c | PSR_x},
427 {"SPSR_sfx", false, PSR_s | PSR_f | PSR_x},
428 {"SPSR_sfc", false, PSR_s | PSR_f | PSR_c},
429 {"SPSR_sxf", false, PSR_s | PSR_x | PSR_f},
430 {"SPSR_sxc", false, PSR_s | PSR_x | PSR_c},
431 {"SPSR_scf", false, PSR_s | PSR_c | PSR_f},
432 {"SPSR_scx", false, PSR_s | PSR_c | PSR_x},
433 {"SPSR_xfs", false, PSR_x | PSR_f | PSR_s},
434 {"SPSR_xfc", false, PSR_x | PSR_f | PSR_c},
435 {"SPSR_xsf", false, PSR_x | PSR_s | PSR_f},
436 {"SPSR_xsc", false, PSR_x | PSR_s | PSR_c},
437 {"SPSR_xcf", false, PSR_x | PSR_c | PSR_f},
438 {"SPSR_xcs", false, PSR_x | PSR_c | PSR_s},
439 {"SPSR_cfs", false, PSR_c | PSR_f | PSR_s},
440 {"SPSR_cfx", false, PSR_c | PSR_f | PSR_x},
441 {"SPSR_csf", false, PSR_c | PSR_s | PSR_f},
442 {"SPSR_csx", false, PSR_c | PSR_s | PSR_x},
443 {"SPSR_cxf", false, PSR_c | PSR_x | PSR_f},
444 {"SPSR_cxs", false, PSR_c | PSR_x | PSR_s},
445 {"SPSR_fsxc", false, PSR_f | PSR_s | PSR_x | PSR_c},
446 {"SPSR_fscx", false, PSR_f | PSR_s | PSR_c | PSR_x},
447 {"SPSR_fxsc", false, PSR_f | PSR_x | PSR_s | PSR_c},
448 {"SPSR_fxcs", false, PSR_f | PSR_x | PSR_c | PSR_s},
449 {"SPSR_fcsx", false, PSR_f | PSR_c | PSR_s | PSR_x},
450 {"SPSR_fcxs", false, PSR_f | PSR_c | PSR_x | PSR_s},
451 {"SPSR_sfxc", false, PSR_s | PSR_f | PSR_x | PSR_c},
452 {"SPSR_sfcx", false, PSR_s | PSR_f | PSR_c | PSR_x},
453 {"SPSR_sxfc", false, PSR_s | PSR_x | PSR_f | PSR_c},
454 {"SPSR_sxcf", false, PSR_s | PSR_x | PSR_c | PSR_f},
455 {"SPSR_scfx", false, PSR_s | PSR_c | PSR_f | PSR_x},
456 {"SPSR_scxf", false, PSR_s | PSR_c | PSR_x | PSR_f},
457 {"SPSR_xfsc", false, PSR_x | PSR_f | PSR_s | PSR_c},
458 {"SPSR_xfcs", false, PSR_x | PSR_f | PSR_c | PSR_s},
459 {"SPSR_xsfc", false, PSR_x | PSR_s | PSR_f | PSR_c},
460 {"SPSR_xscf", false, PSR_x | PSR_s | PSR_c | PSR_f},
461 {"SPSR_xcfs", false, PSR_x | PSR_c | PSR_f | PSR_s},
462 {"SPSR_xcsf", false, PSR_x | PSR_c | PSR_s | PSR_f},
463 {"SPSR_cfsx", false, PSR_c | PSR_f | PSR_s | PSR_x},
464 {"SPSR_cfxs", false, PSR_c | PSR_f | PSR_x | PSR_s},
465 {"SPSR_csfx", false, PSR_c | PSR_s | PSR_f | PSR_x},
466 {"SPSR_csxf", false, PSR_c | PSR_s | PSR_x | PSR_f},
467 {"SPSR_cxfs", false, PSR_c | PSR_x | PSR_f | PSR_s},
468 {"SPSR_cxsf", false, PSR_c | PSR_x | PSR_s | PSR_f},
471 enum cirrus_regtype
473 CIRRUS_REGTYPE_MVF = 1,
474 CIRRUS_REGTYPE_MVFX = 2,
475 CIRRUS_REGTYPE_MVD = 3,
476 CIRRUS_REGTYPE_MVDX = 4,
477 CIRRUS_REGTYPE_MVAX = 5,
478 CIRRUS_REGTYPE_DSPSC = 6,
479 CIRRUS_REGTYPE_ANY = 7
482 /* Functions called by parser. */
483 /* ARM instructions. */
484 static void do_arit PARAMS ((char *, unsigned long));
485 static void do_cmp PARAMS ((char *, unsigned long));
486 static void do_mov PARAMS ((char *, unsigned long));
487 static void do_ldst PARAMS ((char *, unsigned long));
488 static void do_ldstt PARAMS ((char *, unsigned long));
489 static void do_ldmstm PARAMS ((char *, unsigned long));
490 static void do_branch PARAMS ((char *, unsigned long));
491 static void do_swi PARAMS ((char *, unsigned long));
493 /* Pseudo Op codes. */
494 static void do_adr PARAMS ((char *, unsigned long));
495 static void do_adrl PARAMS ((char *, unsigned long));
496 static void do_empty PARAMS ((char *, unsigned long));
498 /* ARM v2. */
499 static void do_mul PARAMS ((char *, unsigned long));
500 static void do_mla PARAMS ((char *, unsigned long));
502 /* ARM v2S. */
503 static void do_swap PARAMS ((char *, unsigned long));
505 /* ARM v3. */
506 static void do_msr PARAMS ((char *, unsigned long));
507 static void do_mrs PARAMS ((char *, unsigned long));
509 /* ARM v3M. */
510 static void do_mull PARAMS ((char *, unsigned long));
512 /* ARM v4. */
513 static void do_ldstv4 PARAMS ((char *, unsigned long));
515 /* ARM v4T. */
516 static void do_bx PARAMS ((char *, unsigned long));
518 /* ARM v5. */
519 static void do_blx PARAMS ((char *, unsigned long));
520 static void do_bkpt PARAMS ((char *, unsigned long));
521 static void do_clz PARAMS ((char *, unsigned long));
522 static void do_lstc2 PARAMS ((char *, unsigned long));
523 static void do_cdp2 PARAMS ((char *, unsigned long));
524 static void do_co_reg2 PARAMS ((char *, unsigned long));
526 /* ARM v5ExP. */
527 static void do_smla PARAMS ((char *, unsigned long));
528 static void do_smlal PARAMS ((char *, unsigned long));
529 static void do_smul PARAMS ((char *, unsigned long));
530 static void do_qadd PARAMS ((char *, unsigned long));
532 /* ARM v5E. */
533 static void do_pld PARAMS ((char *, unsigned long));
534 static void do_ldrd PARAMS ((char *, unsigned long));
535 static void do_co_reg2c PARAMS ((char *, unsigned long));
537 /* Coprocessor Instructions. */
538 static void do_cdp PARAMS ((char *, unsigned long));
539 static void do_lstc PARAMS ((char *, unsigned long));
540 static void do_co_reg PARAMS ((char *, unsigned long));
542 /* FPA instructions. */
543 static void do_fpa_ctrl PARAMS ((char *, unsigned long));
544 static void do_fpa_ldst PARAMS ((char *, unsigned long));
545 static void do_fpa_ldmstm PARAMS ((char *, unsigned long));
546 static void do_fpa_dyadic PARAMS ((char *, unsigned long));
547 static void do_fpa_monadic PARAMS ((char *, unsigned long));
548 static void do_fpa_cmp PARAMS ((char *, unsigned long));
549 static void do_fpa_from_reg PARAMS ((char *, unsigned long));
550 static void do_fpa_to_reg PARAMS ((char *, unsigned long));
552 /* XScale. */
553 static void do_mia PARAMS ((char *, unsigned long));
554 static void do_mar PARAMS ((char *, unsigned long));
555 static void do_mra PARAMS ((char *, unsigned long));
557 /* ARM_EXT_MAVERICK. */
558 static void do_c_binops PARAMS ((char *, unsigned long, int));
559 static void do_c_binops_1 PARAMS ((char *, unsigned long));
560 static void do_c_binops_2 PARAMS ((char *, unsigned long));
561 static void do_c_binops_3 PARAMS ((char *, unsigned long));
562 static void do_c_triple PARAMS ((char *, unsigned long, int));
563 static void do_c_triple_4 PARAMS ((char *, unsigned long));
564 static void do_c_triple_5 PARAMS ((char *, unsigned long));
565 static void do_c_quad PARAMS ((char *, unsigned long, int));
566 static void do_c_quad_6 PARAMS ((char *, unsigned long));
567 static void do_c_dspsc PARAMS ((char *, unsigned long, int));
568 static void do_c_dspsc_1 PARAMS ((char *, unsigned long));
569 static void do_c_dspsc_2 PARAMS ((char *, unsigned long));
570 static void do_c_shift PARAMS ((char *, unsigned long, int));
571 static void do_c_shift_1 PARAMS ((char *, unsigned long));
572 static void do_c_shift_2 PARAMS ((char *, unsigned long));
573 static void do_c_ldst PARAMS ((char *, unsigned long, int));
574 static void do_c_ldst_1 PARAMS ((char *, unsigned long));
575 static void do_c_ldst_2 PARAMS ((char *, unsigned long));
576 static void do_c_ldst_3 PARAMS ((char *, unsigned long));
577 static void do_c_ldst_4 PARAMS ((char *, unsigned long));
578 static int cirrus_reg_required_here PARAMS ((char **, int,
579 enum cirrus_regtype));
580 static int cirrus_valid_reg PARAMS ((int, enum cirrus_regtype));
581 static int cirrus_parse_offset PARAMS ((char **, int *));
583 static void fix_new_arm PARAMS ((fragS *, int, short, expressionS *,
584 int, int));
585 static int arm_reg_parse PARAMS ((char **));
586 static const struct asm_psr * arm_psr_parse PARAMS ((char **));
587 static void symbol_locate PARAMS ((symbolS *, const char *, segT, valueT,
588 fragS *));
589 static int add_to_lit_pool PARAMS ((void));
590 static unsigned validate_immediate PARAMS ((unsigned));
591 static unsigned validate_immediate_twopart PARAMS ((unsigned int,
592 unsigned int *));
593 static int validate_offset_imm PARAMS ((unsigned int, int));
594 static void opcode_select PARAMS ((int));
595 static void end_of_line PARAMS ((char *));
596 static int reg_required_here PARAMS ((char **, int));
597 static int psr_required_here PARAMS ((char **));
598 static int co_proc_number PARAMS ((char **));
599 static int cp_opc_expr PARAMS ((char **, int, int));
600 static int cp_reg_required_here PARAMS ((char **, int));
601 static int fp_reg_required_here PARAMS ((char **, int));
602 static int cp_address_offset PARAMS ((char **));
603 static int cp_address_required_here PARAMS ((char **));
604 static int my_get_float_expression PARAMS ((char **));
605 static int skip_past_comma PARAMS ((char **));
606 static int walk_no_bignums PARAMS ((symbolS *));
607 static int negate_data_op PARAMS ((unsigned long *, unsigned long));
608 static int data_op2 PARAMS ((char **));
609 static int fp_op2 PARAMS ((char **));
610 static long reg_list PARAMS ((char **));
611 static void thumb_load_store PARAMS ((char *, int, int));
612 static int decode_shift PARAMS ((char **, int));
613 static int ldst_extend PARAMS ((char **));
614 static int ldst_extend_v4 PARAMS ((char **));
615 static void thumb_add_sub PARAMS ((char *, int));
616 static void insert_reg PARAMS ((int));
617 static void thumb_shift PARAMS ((char *, int));
618 static void thumb_mov_compare PARAMS ((char *, int));
619 static void set_constant_flonums PARAMS ((void));
620 static valueT md_chars_to_number PARAMS ((char *, int));
621 static void insert_reg_alias PARAMS ((char *, int));
622 static void output_inst PARAMS ((void));
623 static int accum0_required_here PARAMS ((char **));
624 static int ld_mode_required_here PARAMS ((char **));
625 static void do_branch25 PARAMS ((char *, unsigned long));
626 static symbolS * find_real_start PARAMS ((symbolS *));
627 #ifdef OBJ_ELF
628 static bfd_reloc_code_real_type arm_parse_reloc PARAMS ((void));
629 #endif
631 /* ARM instructions take 4bytes in the object file, Thumb instructions
632 take 2: */
633 #define INSN_SIZE 4
635 /* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
636 #define CIRRUS_MODE1 0x100c
638 /* "INSN<cond> X,Y" where X:bit16, Y:bit12. */
639 #define CIRRUS_MODE2 0x0c10
641 /* "INSN<cond> X,Y" where X:0, Y:bit16. */
642 #define CIRRUS_MODE3 0x1000
644 /* "INSN<cond> X,Y,Z" where X:16, Y:0, Z:12. */
645 #define CIRRUS_MODE4 0x0c0010
647 /* "INSN<cond> X,Y,Z" where X:12, Y:16, Z:0. */
648 #define CIRRUS_MODE5 0x00100c
650 /* "INSN<cond> W,X,Y,Z" where W:5, X:12, Y:16, Z:0. */
651 #define CIRRUS_MODE6 0x00100c05
653 struct asm_opcode
655 /* Basic string to match. */
656 const char * template;
658 /* Basic instruction code. */
659 unsigned long value;
661 /* Offset into the template where the condition code (if any) will be.
662 If zero, then the instruction is never conditional. */
663 unsigned cond_offset;
665 /* Which architecture variant provides this instruction. */
666 unsigned long variant;
668 /* Function to call to parse args. */
669 void (* parms) PARAMS ((char *, unsigned long));
672 static const struct asm_opcode insns[] =
674 /* Core ARM Instructions. */
675 {"and", 0xe0000000, 3, ARM_EXT_V1, do_arit},
676 {"ands", 0xe0100000, 3, ARM_EXT_V1, do_arit},
677 {"eor", 0xe0200000, 3, ARM_EXT_V1, do_arit},
678 {"eors", 0xe0300000, 3, ARM_EXT_V1, do_arit},
679 {"sub", 0xe0400000, 3, ARM_EXT_V1, do_arit},
680 {"subs", 0xe0500000, 3, ARM_EXT_V1, do_arit},
681 {"rsb", 0xe0600000, 3, ARM_EXT_V1, do_arit},
682 {"rsbs", 0xe0700000, 3, ARM_EXT_V1, do_arit},
683 {"add", 0xe0800000, 3, ARM_EXT_V1, do_arit},
684 {"adds", 0xe0900000, 3, ARM_EXT_V1, do_arit},
685 {"adc", 0xe0a00000, 3, ARM_EXT_V1, do_arit},
686 {"adcs", 0xe0b00000, 3, ARM_EXT_V1, do_arit},
687 {"sbc", 0xe0c00000, 3, ARM_EXT_V1, do_arit},
688 {"sbcs", 0xe0d00000, 3, ARM_EXT_V1, do_arit},
689 {"rsc", 0xe0e00000, 3, ARM_EXT_V1, do_arit},
690 {"rscs", 0xe0f00000, 3, ARM_EXT_V1, do_arit},
691 {"orr", 0xe1800000, 3, ARM_EXT_V1, do_arit},
692 {"orrs", 0xe1900000, 3, ARM_EXT_V1, do_arit},
693 {"bic", 0xe1c00000, 3, ARM_EXT_V1, do_arit},
694 {"bics", 0xe1d00000, 3, ARM_EXT_V1, do_arit},
696 {"tst", 0xe1100000, 3, ARM_EXT_V1, do_cmp},
697 {"tsts", 0xe1100000, 3, ARM_EXT_V1, do_cmp},
698 {"tstp", 0xe110f000, 3, ARM_EXT_V1, do_cmp},
699 {"teq", 0xe1300000, 3, ARM_EXT_V1, do_cmp},
700 {"teqs", 0xe1300000, 3, ARM_EXT_V1, do_cmp},
701 {"teqp", 0xe130f000, 3, ARM_EXT_V1, do_cmp},
702 {"cmp", 0xe1500000, 3, ARM_EXT_V1, do_cmp},
703 {"cmps", 0xe1500000, 3, ARM_EXT_V1, do_cmp},
704 {"cmpp", 0xe150f000, 3, ARM_EXT_V1, do_cmp},
705 {"cmn", 0xe1700000, 3, ARM_EXT_V1, do_cmp},
706 {"cmns", 0xe1700000, 3, ARM_EXT_V1, do_cmp},
707 {"cmnp", 0xe170f000, 3, ARM_EXT_V1, do_cmp},
709 {"mov", 0xe1a00000, 3, ARM_EXT_V1, do_mov},
710 {"movs", 0xe1b00000, 3, ARM_EXT_V1, do_mov},
711 {"mvn", 0xe1e00000, 3, ARM_EXT_V1, do_mov},
712 {"mvns", 0xe1f00000, 3, ARM_EXT_V1, do_mov},
714 {"ldr", 0xe4100000, 3, ARM_EXT_V1, do_ldst},
715 {"ldrb", 0xe4500000, 3, ARM_EXT_V1, do_ldst},
716 {"ldrt", 0xe4300000, 3, ARM_EXT_V1, do_ldstt},
717 {"ldrbt", 0xe4700000, 3, ARM_EXT_V1, do_ldstt},
718 {"str", 0xe4000000, 3, ARM_EXT_V1, do_ldst},
719 {"strb", 0xe4400000, 3, ARM_EXT_V1, do_ldst},
720 {"strt", 0xe4200000, 3, ARM_EXT_V1, do_ldstt},
721 {"strbt", 0xe4600000, 3, ARM_EXT_V1, do_ldstt},
723 {"stmia", 0xe8800000, 3, ARM_EXT_V1, do_ldmstm},
724 {"stmib", 0xe9800000, 3, ARM_EXT_V1, do_ldmstm},
725 {"stmda", 0xe8000000, 3, ARM_EXT_V1, do_ldmstm},
726 {"stmdb", 0xe9000000, 3, ARM_EXT_V1, do_ldmstm},
727 {"stmfd", 0xe9000000, 3, ARM_EXT_V1, do_ldmstm},
728 {"stmfa", 0xe9800000, 3, ARM_EXT_V1, do_ldmstm},
729 {"stmea", 0xe8800000, 3, ARM_EXT_V1, do_ldmstm},
730 {"stmed", 0xe8000000, 3, ARM_EXT_V1, do_ldmstm},
732 {"ldmia", 0xe8900000, 3, ARM_EXT_V1, do_ldmstm},
733 {"ldmib", 0xe9900000, 3, ARM_EXT_V1, do_ldmstm},
734 {"ldmda", 0xe8100000, 3, ARM_EXT_V1, do_ldmstm},
735 {"ldmdb", 0xe9100000, 3, ARM_EXT_V1, do_ldmstm},
736 {"ldmfd", 0xe8900000, 3, ARM_EXT_V1, do_ldmstm},
737 {"ldmfa", 0xe8100000, 3, ARM_EXT_V1, do_ldmstm},
738 {"ldmea", 0xe9100000, 3, ARM_EXT_V1, do_ldmstm},
739 {"ldmed", 0xe9900000, 3, ARM_EXT_V1, do_ldmstm},
741 {"swi", 0xef000000, 3, ARM_EXT_V1, do_swi},
742 #ifdef TE_WINCE
743 /* XXX This is the wrong place to do this. Think multi-arch. */
744 {"bl", 0xeb000000, 2, ARM_EXT_V1, do_branch},
745 {"b", 0xea000000, 1, ARM_EXT_V1, do_branch},
746 #else
747 {"bl", 0xebfffffe, 2, ARM_EXT_V1, do_branch},
748 {"b", 0xeafffffe, 1, ARM_EXT_V1, do_branch},
749 #endif
751 /* Pseudo ops. */
752 {"adr", 0xe28f0000, 3, ARM_EXT_V1, do_adr},
753 {"adrl", 0xe28f0000, 3, ARM_EXT_V1, do_adrl},
754 {"nop", 0xe1a00000, 3, ARM_EXT_V1, do_empty},
756 /* ARM 2 multiplies. */
757 {"mul", 0xe0000090, 3, ARM_EXT_V2, do_mul},
758 {"muls", 0xe0100090, 3, ARM_EXT_V2, do_mul},
759 {"mla", 0xe0200090, 3, ARM_EXT_V2, do_mla},
760 {"mlas", 0xe0300090, 3, ARM_EXT_V2, do_mla},
762 /* Generic copressor instructions. */
763 {"cdp", 0xee000000, 3, ARM_EXT_V2, do_cdp},
764 {"ldc", 0xec100000, 3, ARM_EXT_V2, do_lstc},
765 {"ldcl", 0xec500000, 3, ARM_EXT_V2, do_lstc},
766 {"stc", 0xec000000, 3, ARM_EXT_V2, do_lstc},
767 {"stcl", 0xec400000, 3, ARM_EXT_V2, do_lstc},
768 {"mcr", 0xee000010, 3, ARM_EXT_V2, do_co_reg},
769 {"mrc", 0xee100010, 3, ARM_EXT_V2, do_co_reg},
771 /* ARM 3 - swp instructions. */
772 {"swp", 0xe1000090, 3, ARM_EXT_V2S, do_swap},
773 {"swpb", 0xe1400090, 3, ARM_EXT_V2S, do_swap},
775 /* ARM 6 Status register instructions. */
776 {"mrs", 0xe10f0000, 3, ARM_EXT_V3, do_mrs},
777 {"msr", 0xe120f000, 3, ARM_EXT_V3, do_msr},
778 /* ScottB: our code uses 0xe128f000 for msr.
779 NickC: but this is wrong because the bits 16 through 19 are
780 handled by the PSR_xxx defines above. */
782 /* ARM 7M long multiplies - need signed/unsigned flags! */
783 {"smull", 0xe0c00090, 5, ARM_EXT_V3M, do_mull},
784 {"smulls", 0xe0d00090, 5, ARM_EXT_V3M, do_mull},
785 {"umull", 0xe0800090, 5, ARM_EXT_V3M, do_mull},
786 {"umulls", 0xe0900090, 5, ARM_EXT_V3M, do_mull},
787 {"smlal", 0xe0e00090, 5, ARM_EXT_V3M, do_mull},
788 {"smlals", 0xe0f00090, 5, ARM_EXT_V3M, do_mull},
789 {"umlal", 0xe0a00090, 5, ARM_EXT_V3M, do_mull},
790 {"umlals", 0xe0b00090, 5, ARM_EXT_V3M, do_mull},
792 /* ARM Architecture 4. */
793 {"ldrh", 0xe01000b0, 3, ARM_EXT_V4, do_ldstv4},
794 {"ldrsh", 0xe01000f0, 3, ARM_EXT_V4, do_ldstv4},
795 {"ldrsb", 0xe01000d0, 3, ARM_EXT_V4, do_ldstv4},
796 {"strh", 0xe00000b0, 3, ARM_EXT_V4, do_ldstv4},
798 /* ARM Architecture 4T. */
799 /* Note: bx (and blx) are required on V5, even if the processor does
800 not support Thumb. */
801 {"bx", 0xe12fff10, 2, ARM_EXT_V4T | ARM_EXT_V5, do_bx},
803 /* ARM Architecture 5. */
804 /* Note: blx has 2 variants, so the .value is set dynamically.
805 Only one of the variants has conditional execution. */
806 {"blx", 0xe0000000, 3, ARM_EXT_V5, do_blx},
807 {"clz", 0xe16f0f10, 3, ARM_EXT_V5, do_clz},
808 {"bkpt", 0xe1200070, 0, ARM_EXT_V5, do_bkpt},
809 {"ldc2", 0xfc100000, 0, ARM_EXT_V5, do_lstc2},
810 {"ldc2l", 0xfc500000, 0, ARM_EXT_V5, do_lstc2},
811 {"stc2", 0xfc000000, 0, ARM_EXT_V5, do_lstc2},
812 {"stc2l", 0xfc400000, 0, ARM_EXT_V5, do_lstc2},
813 {"cdp2", 0xfe000000, 0, ARM_EXT_V5, do_cdp2},
814 {"mcr2", 0xfe000010, 0, ARM_EXT_V5, do_co_reg2},
815 {"mrc2", 0xfe100010, 0, ARM_EXT_V5, do_co_reg2},
817 /* ARM Architecture 5ExP. */
818 {"smlabb", 0xe1000080, 6, ARM_EXT_V5ExP, do_smla},
819 {"smlatb", 0xe10000a0, 6, ARM_EXT_V5ExP, do_smla},
820 {"smlabt", 0xe10000c0, 6, ARM_EXT_V5ExP, do_smla},
821 {"smlatt", 0xe10000e0, 6, ARM_EXT_V5ExP, do_smla},
823 {"smlawb", 0xe1200080, 6, ARM_EXT_V5ExP, do_smla},
824 {"smlawt", 0xe12000c0, 6, ARM_EXT_V5ExP, do_smla},
826 {"smlalbb", 0xe1400080, 7, ARM_EXT_V5ExP, do_smlal},
827 {"smlaltb", 0xe14000a0, 7, ARM_EXT_V5ExP, do_smlal},
828 {"smlalbt", 0xe14000c0, 7, ARM_EXT_V5ExP, do_smlal},
829 {"smlaltt", 0xe14000e0, 7, ARM_EXT_V5ExP, do_smlal},
831 {"smulbb", 0xe1600080, 6, ARM_EXT_V5ExP, do_smul},
832 {"smultb", 0xe16000a0, 6, ARM_EXT_V5ExP, do_smul},
833 {"smulbt", 0xe16000c0, 6, ARM_EXT_V5ExP, do_smul},
834 {"smultt", 0xe16000e0, 6, ARM_EXT_V5ExP, do_smul},
836 {"smulwb", 0xe12000a0, 6, ARM_EXT_V5ExP, do_smul},
837 {"smulwt", 0xe12000e0, 6, ARM_EXT_V5ExP, do_smul},
839 {"qadd", 0xe1000050, 4, ARM_EXT_V5ExP, do_qadd},
840 {"qdadd", 0xe1400050, 5, ARM_EXT_V5ExP, do_qadd},
841 {"qsub", 0xe1200050, 4, ARM_EXT_V5ExP, do_qadd},
842 {"qdsub", 0xe1600050, 5, ARM_EXT_V5ExP, do_qadd},
844 /* ARM Architecture 5E. */
845 {"pld", 0xf450f000, 0, ARM_EXT_V5E, do_pld},
846 {"ldrd", 0xe00000d0, 3, ARM_EXT_V5E, do_ldrd},
847 {"strd", 0xe00000f0, 3, ARM_EXT_V5E, do_ldrd},
849 {"mcrr", 0xec400000, 4, ARM_EXT_V5E, do_co_reg2c},
850 {"mrrc", 0xec500000, 4, ARM_EXT_V5E, do_co_reg2c},
852 /* Core FPA instruction set (V1). */
853 {"wfs", 0xee200110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
854 {"rfs", 0xee300110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
855 {"wfc", 0xee400110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
856 {"rfc", 0xee500110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
858 {"ldfs", 0xec100100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
859 {"ldfd", 0xec108100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
860 {"ldfe", 0xec500100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
861 {"ldfp", 0xec508100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
863 {"stfs", 0xec000100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
864 {"stfd", 0xec008100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
865 {"stfe", 0xec400100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
866 {"stfp", 0xec408100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
868 {"mvfs", 0xee008100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
869 {"mvfsp", 0xee008120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
870 {"mvfsm", 0xee008140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
871 {"mvfsz", 0xee008160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
872 {"mvfd", 0xee008180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
873 {"mvfdp", 0xee0081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
874 {"mvfdm", 0xee0081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
875 {"mvfdz", 0xee0081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
876 {"mvfe", 0xee088100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
877 {"mvfep", 0xee088120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
878 {"mvfem", 0xee088140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
879 {"mvfez", 0xee088160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
881 {"mnfs", 0xee108100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
882 {"mnfsp", 0xee108120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
883 {"mnfsm", 0xee108140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
884 {"mnfsz", 0xee108160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
885 {"mnfd", 0xee108180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
886 {"mnfdp", 0xee1081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
887 {"mnfdm", 0xee1081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
888 {"mnfdz", 0xee1081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
889 {"mnfe", 0xee188100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
890 {"mnfep", 0xee188120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
891 {"mnfem", 0xee188140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
892 {"mnfez", 0xee188160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
894 {"abss", 0xee208100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
895 {"abssp", 0xee208120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
896 {"abssm", 0xee208140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
897 {"abssz", 0xee208160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
898 {"absd", 0xee208180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
899 {"absdp", 0xee2081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
900 {"absdm", 0xee2081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
901 {"absdz", 0xee2081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
902 {"abse", 0xee288100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
903 {"absep", 0xee288120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
904 {"absem", 0xee288140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
905 {"absez", 0xee288160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
907 {"rnds", 0xee308100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
908 {"rndsp", 0xee308120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
909 {"rndsm", 0xee308140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
910 {"rndsz", 0xee308160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
911 {"rndd", 0xee308180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
912 {"rnddp", 0xee3081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
913 {"rnddm", 0xee3081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
914 {"rnddz", 0xee3081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
915 {"rnde", 0xee388100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
916 {"rndep", 0xee388120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
917 {"rndem", 0xee388140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
918 {"rndez", 0xee388160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
920 {"sqts", 0xee408100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
921 {"sqtsp", 0xee408120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
922 {"sqtsm", 0xee408140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
923 {"sqtsz", 0xee408160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
924 {"sqtd", 0xee408180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
925 {"sqtdp", 0xee4081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
926 {"sqtdm", 0xee4081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
927 {"sqtdz", 0xee4081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
928 {"sqte", 0xee488100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
929 {"sqtep", 0xee488120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
930 {"sqtem", 0xee488140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
931 {"sqtez", 0xee488160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
933 {"logs", 0xee508100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
934 {"logsp", 0xee508120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
935 {"logsm", 0xee508140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
936 {"logsz", 0xee508160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
937 {"logd", 0xee508180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
938 {"logdp", 0xee5081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
939 {"logdm", 0xee5081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
940 {"logdz", 0xee5081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
941 {"loge", 0xee588100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
942 {"logep", 0xee588120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
943 {"logem", 0xee588140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
944 {"logez", 0xee588160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
946 {"lgns", 0xee608100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
947 {"lgnsp", 0xee608120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
948 {"lgnsm", 0xee608140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
949 {"lgnsz", 0xee608160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
950 {"lgnd", 0xee608180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
951 {"lgndp", 0xee6081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
952 {"lgndm", 0xee6081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
953 {"lgndz", 0xee6081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
954 {"lgne", 0xee688100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
955 {"lgnep", 0xee688120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
956 {"lgnem", 0xee688140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
957 {"lgnez", 0xee688160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
959 {"exps", 0xee708100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
960 {"expsp", 0xee708120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
961 {"expsm", 0xee708140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
962 {"expsz", 0xee708160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
963 {"expd", 0xee708180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
964 {"expdp", 0xee7081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
965 {"expdm", 0xee7081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
966 {"expdz", 0xee7081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
967 {"expe", 0xee788100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
968 {"expep", 0xee788120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
969 {"expem", 0xee788140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
970 {"expdz", 0xee788160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
972 {"sins", 0xee808100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
973 {"sinsp", 0xee808120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
974 {"sinsm", 0xee808140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
975 {"sinsz", 0xee808160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
976 {"sind", 0xee808180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
977 {"sindp", 0xee8081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
978 {"sindm", 0xee8081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
979 {"sindz", 0xee8081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
980 {"sine", 0xee888100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
981 {"sinep", 0xee888120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
982 {"sinem", 0xee888140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
983 {"sinez", 0xee888160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
985 {"coss", 0xee908100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
986 {"cossp", 0xee908120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
987 {"cossm", 0xee908140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
988 {"cossz", 0xee908160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
989 {"cosd", 0xee908180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
990 {"cosdp", 0xee9081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
991 {"cosdm", 0xee9081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
992 {"cosdz", 0xee9081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
993 {"cose", 0xee988100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
994 {"cosep", 0xee988120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
995 {"cosem", 0xee988140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
996 {"cosez", 0xee988160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
998 {"tans", 0xeea08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
999 {"tansp", 0xeea08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1000 {"tansm", 0xeea08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1001 {"tansz", 0xeea08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1002 {"tand", 0xeea08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1003 {"tandp", 0xeea081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1004 {"tandm", 0xeea081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1005 {"tandz", 0xeea081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1006 {"tane", 0xeea88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1007 {"tanep", 0xeea88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1008 {"tanem", 0xeea88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1009 {"tanez", 0xeea88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1011 {"asns", 0xeeb08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1012 {"asnsp", 0xeeb08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1013 {"asnsm", 0xeeb08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1014 {"asnsz", 0xeeb08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1015 {"asnd", 0xeeb08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1016 {"asndp", 0xeeb081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1017 {"asndm", 0xeeb081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1018 {"asndz", 0xeeb081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1019 {"asne", 0xeeb88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1020 {"asnep", 0xeeb88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1021 {"asnem", 0xeeb88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1022 {"asnez", 0xeeb88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1024 {"acss", 0xeec08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1025 {"acssp", 0xeec08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1026 {"acssm", 0xeec08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1027 {"acssz", 0xeec08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1028 {"acsd", 0xeec08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1029 {"acsdp", 0xeec081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1030 {"acsdm", 0xeec081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1031 {"acsdz", 0xeec081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1032 {"acse", 0xeec88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1033 {"acsep", 0xeec88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1034 {"acsem", 0xeec88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1035 {"acsez", 0xeec88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1037 {"atns", 0xeed08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1038 {"atnsp", 0xeed08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1039 {"atnsm", 0xeed08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1040 {"atnsz", 0xeed08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1041 {"atnd", 0xeed08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1042 {"atndp", 0xeed081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1043 {"atndm", 0xeed081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1044 {"atndz", 0xeed081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1045 {"atne", 0xeed88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1046 {"atnep", 0xeed88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1047 {"atnem", 0xeed88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1048 {"atnez", 0xeed88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1050 {"urds", 0xeee08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1051 {"urdsp", 0xeee08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1052 {"urdsm", 0xeee08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1053 {"urdsz", 0xeee08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1054 {"urdd", 0xeee08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1055 {"urddp", 0xeee081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1056 {"urddm", 0xeee081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1057 {"urddz", 0xeee081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1058 {"urde", 0xeee88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1059 {"urdep", 0xeee88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1060 {"urdem", 0xeee88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1061 {"urdez", 0xeee88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1063 {"nrms", 0xeef08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1064 {"nrmsp", 0xeef08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1065 {"nrmsm", 0xeef08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1066 {"nrmsz", 0xeef08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1067 {"nrmd", 0xeef08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1068 {"nrmdp", 0xeef081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1069 {"nrmdm", 0xeef081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1070 {"nrmdz", 0xeef081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1071 {"nrme", 0xeef88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1072 {"nrmep", 0xeef88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1073 {"nrmem", 0xeef88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1074 {"nrmez", 0xeef88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1076 {"adfs", 0xee000100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1077 {"adfsp", 0xee000120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1078 {"adfsm", 0xee000140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1079 {"adfsz", 0xee000160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1080 {"adfd", 0xee000180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1081 {"adfdp", 0xee0001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1082 {"adfdm", 0xee0001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1083 {"adfdz", 0xee0001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1084 {"adfe", 0xee080100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1085 {"adfep", 0xee080120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1086 {"adfem", 0xee080140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1087 {"adfez", 0xee080160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1089 {"sufs", 0xee200100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1090 {"sufsp", 0xee200120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1091 {"sufsm", 0xee200140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1092 {"sufsz", 0xee200160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1093 {"sufd", 0xee200180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1094 {"sufdp", 0xee2001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1095 {"sufdm", 0xee2001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1096 {"sufdz", 0xee2001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1097 {"sufe", 0xee280100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1098 {"sufep", 0xee280120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1099 {"sufem", 0xee280140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1100 {"sufez", 0xee280160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1102 {"rsfs", 0xee300100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1103 {"rsfsp", 0xee300120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1104 {"rsfsm", 0xee300140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1105 {"rsfsz", 0xee300160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1106 {"rsfd", 0xee300180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1107 {"rsfdp", 0xee3001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1108 {"rsfdm", 0xee3001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1109 {"rsfdz", 0xee3001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1110 {"rsfe", 0xee380100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1111 {"rsfep", 0xee380120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1112 {"rsfem", 0xee380140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1113 {"rsfez", 0xee380160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1115 {"mufs", 0xee100100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1116 {"mufsp", 0xee100120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1117 {"mufsm", 0xee100140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1118 {"mufsz", 0xee100160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1119 {"mufd", 0xee100180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1120 {"mufdp", 0xee1001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1121 {"mufdm", 0xee1001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1122 {"mufdz", 0xee1001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1123 {"mufe", 0xee180100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1124 {"mufep", 0xee180120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1125 {"mufem", 0xee180140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1126 {"mufez", 0xee180160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1128 {"dvfs", 0xee400100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1129 {"dvfsp", 0xee400120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1130 {"dvfsm", 0xee400140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1131 {"dvfsz", 0xee400160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1132 {"dvfd", 0xee400180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1133 {"dvfdp", 0xee4001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1134 {"dvfdm", 0xee4001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1135 {"dvfdz", 0xee4001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1136 {"dvfe", 0xee480100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1137 {"dvfep", 0xee480120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1138 {"dvfem", 0xee480140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1139 {"dvfez", 0xee480160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1141 {"rdfs", 0xee500100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1142 {"rdfsp", 0xee500120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1143 {"rdfsm", 0xee500140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1144 {"rdfsz", 0xee500160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1145 {"rdfd", 0xee500180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1146 {"rdfdp", 0xee5001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1147 {"rdfdm", 0xee5001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1148 {"rdfdz", 0xee5001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1149 {"rdfe", 0xee580100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1150 {"rdfep", 0xee580120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1151 {"rdfem", 0xee580140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1152 {"rdfez", 0xee580160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1154 {"pows", 0xee600100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1155 {"powsp", 0xee600120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1156 {"powsm", 0xee600140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1157 {"powsz", 0xee600160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1158 {"powd", 0xee600180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1159 {"powdp", 0xee6001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1160 {"powdm", 0xee6001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1161 {"powdz", 0xee6001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1162 {"powe", 0xee680100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1163 {"powep", 0xee680120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1164 {"powem", 0xee680140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1165 {"powez", 0xee680160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1167 {"rpws", 0xee700100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1168 {"rpwsp", 0xee700120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1169 {"rpwsm", 0xee700140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1170 {"rpwsz", 0xee700160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1171 {"rpwd", 0xee700180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1172 {"rpwdp", 0xee7001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1173 {"rpwdm", 0xee7001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1174 {"rpwdz", 0xee7001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1175 {"rpwe", 0xee780100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1176 {"rpwep", 0xee780120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1177 {"rpwem", 0xee780140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1178 {"rpwez", 0xee780160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1180 {"rmfs", 0xee800100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1181 {"rmfsp", 0xee800120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1182 {"rmfsm", 0xee800140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1183 {"rmfsz", 0xee800160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1184 {"rmfd", 0xee800180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1185 {"rmfdp", 0xee8001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1186 {"rmfdm", 0xee8001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1187 {"rmfdz", 0xee8001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1188 {"rmfe", 0xee880100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1189 {"rmfep", 0xee880120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1190 {"rmfem", 0xee880140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1191 {"rmfez", 0xee880160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1193 {"fmls", 0xee900100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1194 {"fmlsp", 0xee900120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1195 {"fmlsm", 0xee900140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1196 {"fmlsz", 0xee900160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1197 {"fmld", 0xee900180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1198 {"fmldp", 0xee9001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1199 {"fmldm", 0xee9001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1200 {"fmldz", 0xee9001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1201 {"fmle", 0xee980100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1202 {"fmlep", 0xee980120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1203 {"fmlem", 0xee980140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1204 {"fmlez", 0xee980160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1206 {"fdvs", 0xeea00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1207 {"fdvsp", 0xeea00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1208 {"fdvsm", 0xeea00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1209 {"fdvsz", 0xeea00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1210 {"fdvd", 0xeea00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1211 {"fdvdp", 0xeea001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1212 {"fdvdm", 0xeea001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1213 {"fdvdz", 0xeea001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1214 {"fdve", 0xeea80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1215 {"fdvep", 0xeea80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1216 {"fdvem", 0xeea80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1217 {"fdvez", 0xeea80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1219 {"frds", 0xeeb00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1220 {"frdsp", 0xeeb00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1221 {"frdsm", 0xeeb00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1222 {"frdsz", 0xeeb00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1223 {"frdd", 0xeeb00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1224 {"frddp", 0xeeb001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1225 {"frddm", 0xeeb001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1226 {"frddz", 0xeeb001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1227 {"frde", 0xeeb80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1228 {"frdep", 0xeeb80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1229 {"frdem", 0xeeb80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1230 {"frdez", 0xeeb80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1232 {"pols", 0xeec00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1233 {"polsp", 0xeec00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1234 {"polsm", 0xeec00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1235 {"polsz", 0xeec00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1236 {"pold", 0xeec00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1237 {"poldp", 0xeec001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1238 {"poldm", 0xeec001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1239 {"poldz", 0xeec001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1240 {"pole", 0xeec80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1241 {"polep", 0xeec80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1242 {"polem", 0xeec80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1243 {"polez", 0xeec80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1245 {"cmf", 0xee90f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
1246 {"cmfe", 0xeed0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
1247 {"cnf", 0xeeb0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
1248 {"cnfe", 0xeef0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
1249 /* The FPA10 data sheet suggests that the 'E' of cmfe/cnfe should
1250 not be an optional suffix, but part of the instruction. To be
1251 compatible, we accept either. */
1252 {"cmfe", 0xeed0f110, 4, FPU_FPA_EXT_V1, do_fpa_cmp},
1253 {"cnfe", 0xeef0f110, 4, FPU_FPA_EXT_V1, do_fpa_cmp},
1255 {"flts", 0xee000110, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1256 {"fltsp", 0xee000130, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1257 {"fltsm", 0xee000150, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1258 {"fltsz", 0xee000170, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1259 {"fltd", 0xee000190, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1260 {"fltdp", 0xee0001b0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1261 {"fltdm", 0xee0001d0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1262 {"fltdz", 0xee0001f0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1263 {"flte", 0xee080110, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1264 {"fltep", 0xee080130, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1265 {"fltem", 0xee080150, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1266 {"fltez", 0xee080170, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1268 /* The implementation of the FIX instruction is broken on some
1269 assemblers, in that it accepts a precision specifier as well as a
1270 rounding specifier, despite the fact that this is meaningless.
1271 To be more compatible, we accept it as well, though of course it
1272 does not set any bits. */
1273 {"fix", 0xee100110, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1274 {"fixp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1275 {"fixm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1276 {"fixz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1277 {"fixsp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1278 {"fixsm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1279 {"fixsz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1280 {"fixdp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1281 {"fixdm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1282 {"fixdz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1283 {"fixep", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1284 {"fixem", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1285 {"fixez", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1287 /* Instructions that were new with the real FPA, call them V2. */
1288 {"lfm", 0xec100200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1289 {"lfmfd", 0xec900200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1290 {"lfmea", 0xed100200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1291 {"sfm", 0xec000200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1292 {"sfmfd", 0xed000200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1293 {"sfmea", 0xec800200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1295 /* Intel XScale extensions to ARM V5 ISA. (All use CP0). */
1296 {"mia", 0xee200010, 3, ARM_EXT_XSCALE, do_mia},
1297 {"miaph", 0xee280010, 5, ARM_EXT_XSCALE, do_mia},
1298 {"miabb", 0xee2c0010, 5, ARM_EXT_XSCALE, do_mia},
1299 {"miabt", 0xee2d0010, 5, ARM_EXT_XSCALE, do_mia},
1300 {"miatb", 0xee2e0010, 5, ARM_EXT_XSCALE, do_mia},
1301 {"miatt", 0xee2f0010, 5, ARM_EXT_XSCALE, do_mia},
1302 {"mar", 0xec400000, 3, ARM_EXT_XSCALE, do_mar},
1303 {"mra", 0xec500000, 3, ARM_EXT_XSCALE, do_mra},
1305 /* Cirrus DSP instructions. */
1306 {"cfldrs", 0xec100400, 6, ARM_EXT_MAVERICK, do_c_ldst_1},
1307 {"cfldrd", 0xec500400, 6, ARM_EXT_MAVERICK, do_c_ldst_2},
1308 {"cfldr32", 0xec100500, 7, ARM_EXT_MAVERICK, do_c_ldst_3},
1309 {"cfldr64", 0xec500500, 7, ARM_EXT_MAVERICK, do_c_ldst_4},
1310 {"cfstrs", 0xec000400, 6, ARM_EXT_MAVERICK, do_c_ldst_1},
1311 {"cfstrd", 0xec400400, 6, ARM_EXT_MAVERICK, do_c_ldst_2},
1312 {"cfstr32", 0xec000500, 7, ARM_EXT_MAVERICK, do_c_ldst_3},
1313 {"cfstr64", 0xec400500, 7, ARM_EXT_MAVERICK, do_c_ldst_4},
1314 {"cfmvsr", 0xee000450, 6, ARM_EXT_MAVERICK, do_c_binops_2},
1315 {"cfmvrs", 0xee100450, 6, ARM_EXT_MAVERICK, do_c_binops_1},
1316 {"cfmvdlr", 0xee000410, 7, ARM_EXT_MAVERICK, do_c_binops_2},
1317 {"cfmvrdl", 0xee100410, 7, ARM_EXT_MAVERICK, do_c_binops_1},
1318 {"cfmvdhr", 0xee000430, 7, ARM_EXT_MAVERICK, do_c_binops_2},
1319 {"cfmvrdh", 0xee100430, 7, ARM_EXT_MAVERICK, do_c_binops_1},
1320 {"cfmv64lr", 0xee000510, 8, ARM_EXT_MAVERICK, do_c_binops_2},
1321 {"cfmvr64l", 0xee100510, 8, ARM_EXT_MAVERICK, do_c_binops_1},
1322 {"cfmv64hr", 0xee000530, 8, ARM_EXT_MAVERICK, do_c_binops_2},
1323 {"cfmvr64h", 0xee100530, 8, ARM_EXT_MAVERICK, do_c_binops_1},
1324 {"cfmval32", 0xee100610, 8, ARM_EXT_MAVERICK, do_c_binops_3},
1325 {"cfmv32al", 0xee000610, 8, ARM_EXT_MAVERICK, do_c_binops_3},
1326 {"cfmvam32", 0xee100630, 8, ARM_EXT_MAVERICK, do_c_binops_3},
1327 {"cfmv32am", 0xee000630, 8, ARM_EXT_MAVERICK, do_c_binops_3},
1328 {"cfmvah32", 0xee100650, 8, ARM_EXT_MAVERICK, do_c_binops_3},
1329 {"cfmv32ah", 0xee000650, 8, ARM_EXT_MAVERICK, do_c_binops_3},
1330 {"cfmv32a", 0xee000670, 7, ARM_EXT_MAVERICK, do_c_binops_3},
1331 {"cfmva32", 0xee100670, 7, ARM_EXT_MAVERICK, do_c_binops_3},
1332 {"cfmv64a", 0xee000690, 7, ARM_EXT_MAVERICK, do_c_binops_3},
1333 {"cfmva64", 0xee100690, 7, ARM_EXT_MAVERICK, do_c_binops_3},
1334 {"cfmvsc32", 0xee1006b0, 8, ARM_EXT_MAVERICK, do_c_dspsc_1},
1335 {"cfmv32sc", 0xee0006b0, 8, ARM_EXT_MAVERICK, do_c_dspsc_2},
1336 {"cfcpys", 0xee000400, 6, ARM_EXT_MAVERICK, do_c_binops_1},
1337 {"cfcpyd", 0xee000420, 6, ARM_EXT_MAVERICK, do_c_binops_1},
1338 {"cfcvtsd", 0xee000460, 7, ARM_EXT_MAVERICK, do_c_binops_1},
1339 {"cfcvtds", 0xee000440, 7, ARM_EXT_MAVERICK, do_c_binops_1},
1340 {"cfcvt32s", 0xee000480, 8, ARM_EXT_MAVERICK, do_c_binops_1},
1341 {"cfcvt32d", 0xee0004a0, 8, ARM_EXT_MAVERICK, do_c_binops_1},
1342 {"cfcvt64s", 0xee0004c0, 8, ARM_EXT_MAVERICK, do_c_binops_1},
1343 {"cfcvt64d", 0xee0004e0, 8, ARM_EXT_MAVERICK, do_c_binops_1},
1344 {"cfcvts32", 0xee100580, 8, ARM_EXT_MAVERICK, do_c_binops_1},
1345 {"cfcvtd32", 0xee1005a0, 8, ARM_EXT_MAVERICK, do_c_binops_1},
1346 {"cftruncs32", 0xee1005c0, 10, ARM_EXT_MAVERICK, do_c_binops_1},
1347 {"cftruncd32", 0xee1005e0, 10, ARM_EXT_MAVERICK, do_c_binops_1},
1348 {"cfrshl32", 0xee000550, 8, ARM_EXT_MAVERICK, do_c_triple_4},
1349 {"cfrshl64", 0xee000570, 8, ARM_EXT_MAVERICK, do_c_triple_4},
1350 {"cfsh32", 0xee000500, 6, ARM_EXT_MAVERICK, do_c_shift_1},
1351 {"cfsh64", 0xee200500, 6, ARM_EXT_MAVERICK, do_c_shift_2},
1352 {"cfcmps", 0xee100490, 6, ARM_EXT_MAVERICK, do_c_triple_5},
1353 {"cfcmpd", 0xee1004b0, 6, ARM_EXT_MAVERICK, do_c_triple_5},
1354 {"cfcmp32", 0xee100590, 7, ARM_EXT_MAVERICK, do_c_triple_5},
1355 {"cfcmp64", 0xee1005b0, 7, ARM_EXT_MAVERICK, do_c_triple_5},
1356 {"cfabss", 0xee300400, 6, ARM_EXT_MAVERICK, do_c_binops_1},
1357 {"cfabsd", 0xee300420, 6, ARM_EXT_MAVERICK, do_c_binops_1},
1358 {"cfnegs", 0xee300440, 6, ARM_EXT_MAVERICK, do_c_binops_1},
1359 {"cfnegd", 0xee300460, 6, ARM_EXT_MAVERICK, do_c_binops_1},
1360 {"cfadds", 0xee300480, 6, ARM_EXT_MAVERICK, do_c_triple_5},
1361 {"cfaddd", 0xee3004a0, 6, ARM_EXT_MAVERICK, do_c_triple_5},
1362 {"cfsubs", 0xee3004c0, 6, ARM_EXT_MAVERICK, do_c_triple_5},
1363 {"cfsubd", 0xee3004e0, 6, ARM_EXT_MAVERICK, do_c_triple_5},
1364 {"cfmuls", 0xee100400, 6, ARM_EXT_MAVERICK, do_c_triple_5},
1365 {"cfmuld", 0xee100420, 6, ARM_EXT_MAVERICK, do_c_triple_5},
1366 {"cfabs32", 0xee300500, 7, ARM_EXT_MAVERICK, do_c_binops_1},
1367 {"cfabs64", 0xee300520, 7, ARM_EXT_MAVERICK, do_c_binops_1},
1368 {"cfneg32", 0xee300540, 7, ARM_EXT_MAVERICK, do_c_binops_1},
1369 {"cfneg64", 0xee300560, 7, ARM_EXT_MAVERICK, do_c_binops_1},
1370 {"cfadd32", 0xee300580, 7, ARM_EXT_MAVERICK, do_c_triple_5},
1371 {"cfadd64", 0xee3005a0, 7, ARM_EXT_MAVERICK, do_c_triple_5},
1372 {"cfsub32", 0xee3005c0, 7, ARM_EXT_MAVERICK, do_c_triple_5},
1373 {"cfsub64", 0xee3005e0, 7, ARM_EXT_MAVERICK, do_c_triple_5},
1374 {"cfmul32", 0xee100500, 7, ARM_EXT_MAVERICK, do_c_triple_5},
1375 {"cfmul64", 0xee100520, 7, ARM_EXT_MAVERICK, do_c_triple_5},
1376 {"cfmac32", 0xee100540, 7, ARM_EXT_MAVERICK, do_c_triple_5},
1377 {"cfmsc32", 0xee100560, 7, ARM_EXT_MAVERICK, do_c_triple_5},
1378 {"cfmadd32", 0xee000600, 8, ARM_EXT_MAVERICK, do_c_quad_6},
1379 {"cfmsub32", 0xee100600, 8, ARM_EXT_MAVERICK, do_c_quad_6},
1380 {"cfmadda32", 0xee200600, 9, ARM_EXT_MAVERICK, do_c_quad_6},
1381 {"cfmsuba32", 0xee300600, 9, ARM_EXT_MAVERICK, do_c_quad_6},
1384 /* Defines for various bits that we will want to toggle. */
1385 #define INST_IMMEDIATE 0x02000000
1386 #define OFFSET_REG 0x02000000
1387 #define HWOFFSET_IMM 0x00400000
1388 #define SHIFT_BY_REG 0x00000010
1389 #define PRE_INDEX 0x01000000
1390 #define INDEX_UP 0x00800000
1391 #define WRITE_BACK 0x00200000
1392 #define LDM_TYPE_2_OR_3 0x00400000
1394 #define LITERAL_MASK 0xf000f000
1395 #define OPCODE_MASK 0xfe1fffff
1396 #define V4_STR_BIT 0x00000020
1398 #define DATA_OP_SHIFT 21
1400 /* Codes to distinguish the arithmetic instructions. */
1401 #define OPCODE_AND 0
1402 #define OPCODE_EOR 1
1403 #define OPCODE_SUB 2
1404 #define OPCODE_RSB 3
1405 #define OPCODE_ADD 4
1406 #define OPCODE_ADC 5
1407 #define OPCODE_SBC 6
1408 #define OPCODE_RSC 7
1409 #define OPCODE_TST 8
1410 #define OPCODE_TEQ 9
1411 #define OPCODE_CMP 10
1412 #define OPCODE_CMN 11
1413 #define OPCODE_ORR 12
1414 #define OPCODE_MOV 13
1415 #define OPCODE_BIC 14
1416 #define OPCODE_MVN 15
1418 /* Thumb v1 (ARMv4T). */
1419 static void do_t_nop PARAMS ((char *));
1420 static void do_t_arit PARAMS ((char *));
1421 static void do_t_add PARAMS ((char *));
1422 static void do_t_asr PARAMS ((char *));
1423 static void do_t_branch9 PARAMS ((char *));
1424 static void do_t_branch12 PARAMS ((char *));
1425 static void do_t_branch23 PARAMS ((char *));
1426 static void do_t_bx PARAMS ((char *));
1427 static void do_t_compare PARAMS ((char *));
1428 static void do_t_ldmstm PARAMS ((char *));
1429 static void do_t_ldr PARAMS ((char *));
1430 static void do_t_ldrb PARAMS ((char *));
1431 static void do_t_ldrh PARAMS ((char *));
1432 static void do_t_lds PARAMS ((char *));
1433 static void do_t_lsl PARAMS ((char *));
1434 static void do_t_lsr PARAMS ((char *));
1435 static void do_t_mov PARAMS ((char *));
1436 static void do_t_push_pop PARAMS ((char *));
1437 static void do_t_str PARAMS ((char *));
1438 static void do_t_strb PARAMS ((char *));
1439 static void do_t_strh PARAMS ((char *));
1440 static void do_t_sub PARAMS ((char *));
1441 static void do_t_swi PARAMS ((char *));
1442 static void do_t_adr PARAMS ((char *));
1444 /* Thumb v2 (ARMv5T). */
1445 static void do_t_blx PARAMS ((char *));
1446 static void do_t_bkpt PARAMS ((char *));
1448 #define T_OPCODE_MUL 0x4340
1449 #define T_OPCODE_TST 0x4200
1450 #define T_OPCODE_CMN 0x42c0
1451 #define T_OPCODE_NEG 0x4240
1452 #define T_OPCODE_MVN 0x43c0
1454 #define T_OPCODE_ADD_R3 0x1800
1455 #define T_OPCODE_SUB_R3 0x1a00
1456 #define T_OPCODE_ADD_HI 0x4400
1457 #define T_OPCODE_ADD_ST 0xb000
1458 #define T_OPCODE_SUB_ST 0xb080
1459 #define T_OPCODE_ADD_SP 0xa800
1460 #define T_OPCODE_ADD_PC 0xa000
1461 #define T_OPCODE_ADD_I8 0x3000
1462 #define T_OPCODE_SUB_I8 0x3800
1463 #define T_OPCODE_ADD_I3 0x1c00
1464 #define T_OPCODE_SUB_I3 0x1e00
1466 #define T_OPCODE_ASR_R 0x4100
1467 #define T_OPCODE_LSL_R 0x4080
1468 #define T_OPCODE_LSR_R 0x40c0
1469 #define T_OPCODE_ASR_I 0x1000
1470 #define T_OPCODE_LSL_I 0x0000
1471 #define T_OPCODE_LSR_I 0x0800
1473 #define T_OPCODE_MOV_I8 0x2000
1474 #define T_OPCODE_CMP_I8 0x2800
1475 #define T_OPCODE_CMP_LR 0x4280
1476 #define T_OPCODE_MOV_HR 0x4600
1477 #define T_OPCODE_CMP_HR 0x4500
1479 #define T_OPCODE_LDR_PC 0x4800
1480 #define T_OPCODE_LDR_SP 0x9800
1481 #define T_OPCODE_STR_SP 0x9000
1482 #define T_OPCODE_LDR_IW 0x6800
1483 #define T_OPCODE_STR_IW 0x6000
1484 #define T_OPCODE_LDR_IH 0x8800
1485 #define T_OPCODE_STR_IH 0x8000
1486 #define T_OPCODE_LDR_IB 0x7800
1487 #define T_OPCODE_STR_IB 0x7000
1488 #define T_OPCODE_LDR_RW 0x5800
1489 #define T_OPCODE_STR_RW 0x5000
1490 #define T_OPCODE_LDR_RH 0x5a00
1491 #define T_OPCODE_STR_RH 0x5200
1492 #define T_OPCODE_LDR_RB 0x5c00
1493 #define T_OPCODE_STR_RB 0x5400
1495 #define T_OPCODE_PUSH 0xb400
1496 #define T_OPCODE_POP 0xbc00
1498 #define T_OPCODE_BRANCH 0xe7fe
1500 static int thumb_reg PARAMS ((char ** str, int hi_lo));
1502 #define THUMB_SIZE 2 /* Size of thumb instruction. */
1503 #define THUMB_REG_LO 0x1
1504 #define THUMB_REG_HI 0x2
1505 #define THUMB_REG_ANY 0x3
1507 #define THUMB_H1 0x0080
1508 #define THUMB_H2 0x0040
1510 #define THUMB_ASR 0
1511 #define THUMB_LSL 1
1512 #define THUMB_LSR 2
1514 #define THUMB_MOVE 0
1515 #define THUMB_COMPARE 1
1517 #define THUMB_LOAD 0
1518 #define THUMB_STORE 1
1520 #define THUMB_PP_PC_LR 0x0100
1522 /* These three are used for immediate shifts, do not alter. */
1523 #define THUMB_WORD 2
1524 #define THUMB_HALFWORD 1
1525 #define THUMB_BYTE 0
1527 struct thumb_opcode
1529 /* Basic string to match. */
1530 const char * template;
1532 /* Basic instruction code. */
1533 unsigned long value;
1535 int size;
1537 /* Which CPU variants this exists for. */
1538 unsigned long variant;
1540 /* Function to call to parse args. */
1541 void (* parms) PARAMS ((char *));
1544 static const struct thumb_opcode tinsns[] =
1546 /* Thumb v1 (ARMv4T). */
1547 {"adc", 0x4140, 2, ARM_EXT_V4T, do_t_arit},
1548 {"add", 0x0000, 2, ARM_EXT_V4T, do_t_add},
1549 {"and", 0x4000, 2, ARM_EXT_V4T, do_t_arit},
1550 {"asr", 0x0000, 2, ARM_EXT_V4T, do_t_asr},
1551 {"b", T_OPCODE_BRANCH, 2, ARM_EXT_V4T, do_t_branch12},
1552 {"beq", 0xd0fe, 2, ARM_EXT_V4T, do_t_branch9},
1553 {"bne", 0xd1fe, 2, ARM_EXT_V4T, do_t_branch9},
1554 {"bcs", 0xd2fe, 2, ARM_EXT_V4T, do_t_branch9},
1555 {"bhs", 0xd2fe, 2, ARM_EXT_V4T, do_t_branch9},
1556 {"bcc", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
1557 {"bul", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
1558 {"blo", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
1559 {"bmi", 0xd4fe, 2, ARM_EXT_V4T, do_t_branch9},
1560 {"bpl", 0xd5fe, 2, ARM_EXT_V4T, do_t_branch9},
1561 {"bvs", 0xd6fe, 2, ARM_EXT_V4T, do_t_branch9},
1562 {"bvc", 0xd7fe, 2, ARM_EXT_V4T, do_t_branch9},
1563 {"bhi", 0xd8fe, 2, ARM_EXT_V4T, do_t_branch9},
1564 {"bls", 0xd9fe, 2, ARM_EXT_V4T, do_t_branch9},
1565 {"bge", 0xdafe, 2, ARM_EXT_V4T, do_t_branch9},
1566 {"blt", 0xdbfe, 2, ARM_EXT_V4T, do_t_branch9},
1567 {"bgt", 0xdcfe, 2, ARM_EXT_V4T, do_t_branch9},
1568 {"ble", 0xddfe, 2, ARM_EXT_V4T, do_t_branch9},
1569 {"bal", 0xdefe, 2, ARM_EXT_V4T, do_t_branch9},
1570 {"bic", 0x4380, 2, ARM_EXT_V4T, do_t_arit},
1571 {"bl", 0xf7fffffe, 4, ARM_EXT_V4T, do_t_branch23},
1572 {"bx", 0x4700, 2, ARM_EXT_V4T, do_t_bx},
1573 {"cmn", T_OPCODE_CMN, 2, ARM_EXT_V4T, do_t_arit},
1574 {"cmp", 0x0000, 2, ARM_EXT_V4T, do_t_compare},
1575 {"eor", 0x4040, 2, ARM_EXT_V4T, do_t_arit},
1576 {"ldmia", 0xc800, 2, ARM_EXT_V4T, do_t_ldmstm},
1577 {"ldr", 0x0000, 2, ARM_EXT_V4T, do_t_ldr},
1578 {"ldrb", 0x0000, 2, ARM_EXT_V4T, do_t_ldrb},
1579 {"ldrh", 0x0000, 2, ARM_EXT_V4T, do_t_ldrh},
1580 {"ldrsb", 0x5600, 2, ARM_EXT_V4T, do_t_lds},
1581 {"ldrsh", 0x5e00, 2, ARM_EXT_V4T, do_t_lds},
1582 {"ldsb", 0x5600, 2, ARM_EXT_V4T, do_t_lds},
1583 {"ldsh", 0x5e00, 2, ARM_EXT_V4T, do_t_lds},
1584 {"lsl", 0x0000, 2, ARM_EXT_V4T, do_t_lsl},
1585 {"lsr", 0x0000, 2, ARM_EXT_V4T, do_t_lsr},
1586 {"mov", 0x0000, 2, ARM_EXT_V4T, do_t_mov},
1587 {"mul", T_OPCODE_MUL, 2, ARM_EXT_V4T, do_t_arit},
1588 {"mvn", T_OPCODE_MVN, 2, ARM_EXT_V4T, do_t_arit},
1589 {"neg", T_OPCODE_NEG, 2, ARM_EXT_V4T, do_t_arit},
1590 {"orr", 0x4300, 2, ARM_EXT_V4T, do_t_arit},
1591 {"pop", 0xbc00, 2, ARM_EXT_V4T, do_t_push_pop},
1592 {"push", 0xb400, 2, ARM_EXT_V4T, do_t_push_pop},
1593 {"ror", 0x41c0, 2, ARM_EXT_V4T, do_t_arit},
1594 {"sbc", 0x4180, 2, ARM_EXT_V4T, do_t_arit},
1595 {"stmia", 0xc000, 2, ARM_EXT_V4T, do_t_ldmstm},
1596 {"str", 0x0000, 2, ARM_EXT_V4T, do_t_str},
1597 {"strb", 0x0000, 2, ARM_EXT_V4T, do_t_strb},
1598 {"strh", 0x0000, 2, ARM_EXT_V4T, do_t_strh},
1599 {"swi", 0xdf00, 2, ARM_EXT_V4T, do_t_swi},
1600 {"sub", 0x0000, 2, ARM_EXT_V4T, do_t_sub},
1601 {"tst", T_OPCODE_TST, 2, ARM_EXT_V4T, do_t_arit},
1602 /* Pseudo ops: */
1603 {"adr", 0x0000, 2, ARM_EXT_V4T, do_t_adr},
1604 {"nop", 0x46C0, 2, ARM_EXT_V4T, do_t_nop}, /* mov r8,r8 */
1605 /* Thumb v2 (ARMv5T). */
1606 {"blx", 0, 0, ARM_EXT_V5T, do_t_blx},
1607 {"bkpt", 0xbe00, 2, ARM_EXT_V5T, do_t_bkpt},
1610 struct reg_entry
1612 const char * name;
1613 int number;
1616 #define int_register(reg) ((reg) >= 0 && (reg) <= 15)
1617 #define cp_register(reg) ((reg) >= 32 && (reg) <= 47)
1618 #define fp_register(reg) ((reg) >= 16 && (reg) <= 23)
1620 #define ARM_EXT_MAVERICKSC_REG 134
1622 #define cirrus_register(reg) ((reg) >= 50 && (reg) <= 134)
1623 #define cirrus_mvf_register(reg) ((reg) >= 50 && (reg) <= 65)
1624 #define cirrus_mvd_register(reg) ((reg) >= 70 && (reg) <= 85)
1625 #define cirrus_mvfx_register(reg) ((reg) >= 90 && (reg) <= 105)
1626 #define cirrus_mvdx_register(reg) ((reg) >= 110 && (reg) <= 125)
1627 #define cirrus_mvax_register(reg) ((reg) >= 130 && (reg) <= 133)
1628 #define ARM_EXT_MAVERICKsc_register(reg) ((reg) == ARM_EXT_MAVERICKSC_REG)
1630 #define REG_SP 13
1631 #define REG_LR 14
1632 #define REG_PC 15
1634 /* These are the standard names. Users can add aliases with .req. */
1635 static const struct reg_entry reg_table[] =
1637 /* Processor Register Numbers. */
1638 {"r0", 0}, {"r1", 1}, {"r2", 2}, {"r3", 3},
1639 {"r4", 4}, {"r5", 5}, {"r6", 6}, {"r7", 7},
1640 {"r8", 8}, {"r9", 9}, {"r10", 10}, {"r11", 11},
1641 {"r12", 12}, {"r13", REG_SP},{"r14", REG_LR},{"r15", REG_PC},
1642 /* APCS conventions. */
1643 {"a1", 0}, {"a2", 1}, {"a3", 2}, {"a4", 3},
1644 {"v1", 4}, {"v2", 5}, {"v3", 6}, {"v4", 7}, {"v5", 8},
1645 {"v6", 9}, {"sb", 9}, {"v7", 10}, {"sl", 10},
1646 {"fp", 11}, {"ip", 12}, {"sp", REG_SP},{"lr", REG_LR},{"pc", REG_PC},
1647 /* ATPCS additions to APCS conventions. */
1648 {"wr", 7}, {"v8", 11},
1649 /* FP Registers. */
1650 {"f0", 16}, {"f1", 17}, {"f2", 18}, {"f3", 19},
1651 {"f4", 20}, {"f5", 21}, {"f6", 22}, {"f7", 23},
1652 {"c0", 32}, {"c1", 33}, {"c2", 34}, {"c3", 35},
1653 {"c4", 36}, {"c5", 37}, {"c6", 38}, {"c7", 39},
1654 {"c8", 40}, {"c9", 41}, {"c10", 42}, {"c11", 43},
1655 {"c12", 44}, {"c13", 45}, {"c14", 46}, {"c15", 47},
1656 {"cr0", 32}, {"cr1", 33}, {"cr2", 34}, {"cr3", 35},
1657 {"cr4", 36}, {"cr5", 37}, {"cr6", 38}, {"cr7", 39},
1658 {"cr8", 40}, {"cr9", 41}, {"cr10", 42}, {"cr11", 43},
1659 {"cr12", 44}, {"cr13", 45}, {"cr14", 46}, {"cr15", 47},
1660 /* ATPCS additions to float register names. */
1661 {"s0",16}, {"s1",17}, {"s2",18}, {"s3",19},
1662 {"s4",20}, {"s5",21}, {"s6",22}, {"s7",23},
1663 {"d0",16}, {"d1",17}, {"d2",18}, {"d3",19},
1664 {"d4",20}, {"d5",21}, {"d6",22}, {"d7",23},
1665 /* Cirrus DSP coprocessor registers. */
1666 {"mvf0", 50}, {"mvf1", 51}, {"mvf2", 52}, {"mvf3", 53},
1667 {"mvf4", 54}, {"mvf5", 55}, {"mvf6", 56}, {"mvf7", 57},
1668 {"mvf8", 58}, {"mvf9", 59}, {"mvf10", 60}, {"mvf11", 61},
1669 {"mvf12", 62},{"mvf13", 63}, {"mvf14", 64}, {"mvf15", 65},
1670 {"mvd0", 70}, {"mvd1", 71}, {"mvd2", 72}, {"mvd3", 73},
1671 {"mvd4", 74}, {"mvd5", 75}, {"mvd6", 76}, {"mvd7", 77},
1672 {"mvd8", 78}, {"mvd9", 79}, {"mvd10", 80}, {"mvd11", 81},
1673 {"mvd12", 82},{"mvd13", 83}, {"mvd14", 84}, {"mvd15", 85},
1674 {"mvfx0", 90},{"mvfx1", 91}, {"mvfx2", 92}, {"mvfx3", 93},
1675 {"mvfx4", 94},{"mvfx5", 95}, {"mvfx6", 96}, {"mvfx7", 97},
1676 {"mvfx8", 98},{"mvfx9", 99}, {"mvfx10", 100},{"mvfx11", 101},
1677 {"mvfx12", 102},{"mvfx13", 103},{"mvfx14", 104},{"mvfx15", 105},
1678 {"mvdx0", 110}, {"mvdx1", 111}, {"mvdx2", 112}, {"mvdx3", 113},
1679 {"mvdx4", 114}, {"mvdx5", 115}, {"mvdx6", 116}, {"mvdx7", 117},
1680 {"mvdx8", 118}, {"mvdx9", 119}, {"mvdx10", 120},{"mvdx11", 121},
1681 {"mvdx12", 122},{"mvdx13", 123},{"mvdx14", 124},{"mvdx15", 125},
1682 {"mvax0", 130}, {"mvax1", 131}, {"mvax2", 132}, {"mvax3", 133},
1683 {"dspsc", ARM_EXT_MAVERICKSC_REG},
1684 /* FIXME: At some point we need to add VFP register names. */
1685 /* Array terminator. */
1686 {NULL, 0}
1689 #define BAD_ARGS _("Bad arguments to instruction")
1690 #define BAD_PC _("r15 not allowed here")
1691 #define BAD_FLAGS _("Instruction should not have flags")
1692 #define BAD_COND _("Instruction is not conditional")
1693 #define ERR_NO_ACCUM _("acc0 expected")
1695 static struct hash_control * arm_ops_hsh = NULL;
1696 static struct hash_control * arm_tops_hsh = NULL;
1697 static struct hash_control * arm_cond_hsh = NULL;
1698 static struct hash_control * arm_shift_hsh = NULL;
1699 static struct hash_control * arm_reg_hsh = NULL;
1700 static struct hash_control * arm_psr_hsh = NULL;
1702 /* This table describes all the machine specific pseudo-ops the assembler
1703 has to support. The fields are:
1704 pseudo-op name without dot
1705 function to call to execute this pseudo-op
1706 Integer arg to pass to the function. */
1708 static void s_req PARAMS ((int));
1709 static void s_align PARAMS ((int));
1710 static void s_bss PARAMS ((int));
1711 static void s_even PARAMS ((int));
1712 static void s_ltorg PARAMS ((int));
1713 static void s_arm PARAMS ((int));
1714 static void s_thumb PARAMS ((int));
1715 static void s_code PARAMS ((int));
1716 static void s_force_thumb PARAMS ((int));
1717 static void s_thumb_func PARAMS ((int));
1718 static void s_thumb_set PARAMS ((int));
1719 static void arm_s_text PARAMS ((int));
1720 static void arm_s_data PARAMS ((int));
1721 #ifdef OBJ_ELF
1722 static void arm_s_section PARAMS ((int));
1723 static void s_arm_elf_cons PARAMS ((int));
1724 #endif
1726 static int my_get_expression PARAMS ((expressionS *, char **));
1728 const pseudo_typeS md_pseudo_table[] =
1730 /* Never called becasue '.req' does not start line. */
1731 { "req", s_req, 0 },
1732 { "bss", s_bss, 0 },
1733 { "align", s_align, 0 },
1734 { "arm", s_arm, 0 },
1735 { "thumb", s_thumb, 0 },
1736 { "code", s_code, 0 },
1737 { "force_thumb", s_force_thumb, 0 },
1738 { "thumb_func", s_thumb_func, 0 },
1739 { "thumb_set", s_thumb_set, 0 },
1740 { "even", s_even, 0 },
1741 { "ltorg", s_ltorg, 0 },
1742 { "pool", s_ltorg, 0 },
1743 /* Allow for the effect of section changes. */
1744 { "text", arm_s_text, 0 },
1745 { "data", arm_s_data, 0 },
1746 #ifdef OBJ_ELF
1747 { "section", arm_s_section, 0 },
1748 { "section.s", arm_s_section, 0 },
1749 { "sect", arm_s_section, 0 },
1750 { "sect.s", arm_s_section, 0 },
1751 { "word", s_arm_elf_cons, 4 },
1752 { "long", s_arm_elf_cons, 4 },
1753 { "file", dwarf2_directive_file, 0 },
1754 { "loc", dwarf2_directive_loc, 0 },
1755 #else
1756 { "word", cons, 4},
1757 #endif
1758 { "extend", float_cons, 'x' },
1759 { "ldouble", float_cons, 'x' },
1760 { "packed", float_cons, 'p' },
1761 { 0, 0, 0 }
1764 /* Stuff needed to resolve the label ambiguity
1767 label: <insn>
1768 may differ from:
1770 label:
1771 <insn>
1774 symbolS * last_label_seen;
1775 static int label_is_thumb_function_name = false;
1777 /* Literal stuff. */
1779 #define MAX_LITERAL_POOL_SIZE 1024
1781 typedef struct literalS
1783 struct expressionS exp;
1784 struct arm_it * inst;
1785 } literalT;
1787 literalT literals[MAX_LITERAL_POOL_SIZE];
1789 /* Next free entry in the pool. */
1790 int next_literal_pool_place = 0;
1792 /* Next literal pool number. */
1793 int lit_pool_num = 1;
1795 symbolS * current_poolP = NULL;
1797 static int
1798 add_to_lit_pool ()
1800 int lit_count = 0;
1802 if (current_poolP == NULL)
1803 current_poolP = symbol_create (FAKE_LABEL_NAME, undefined_section,
1804 (valueT) 0, &zero_address_frag);
1806 /* Check if this literal value is already in the pool: */
1807 while (lit_count < next_literal_pool_place)
1809 if (literals[lit_count].exp.X_op == inst.reloc.exp.X_op
1810 && inst.reloc.exp.X_op == O_constant
1811 && (literals[lit_count].exp.X_add_number
1812 == inst.reloc.exp.X_add_number)
1813 && literals[lit_count].exp.X_unsigned == inst.reloc.exp.X_unsigned)
1814 break;
1816 if (literals[lit_count].exp.X_op == inst.reloc.exp.X_op
1817 && inst.reloc.exp.X_op == O_symbol
1818 && (literals[lit_count].exp.X_add_number
1819 == inst.reloc.exp.X_add_number)
1820 && (literals[lit_count].exp.X_add_symbol
1821 == inst.reloc.exp.X_add_symbol)
1822 && (literals[lit_count].exp.X_op_symbol
1823 == inst.reloc.exp.X_op_symbol))
1824 break;
1826 lit_count++;
1829 if (lit_count == next_literal_pool_place) /* New entry. */
1831 if (next_literal_pool_place >= MAX_LITERAL_POOL_SIZE)
1833 inst.error = _("Literal Pool Overflow");
1834 return FAIL;
1837 literals[next_literal_pool_place].exp = inst.reloc.exp;
1838 lit_count = next_literal_pool_place++;
1841 inst.reloc.exp.X_op = O_symbol;
1842 inst.reloc.exp.X_add_number = (lit_count) * 4 - 8;
1843 inst.reloc.exp.X_add_symbol = current_poolP;
1845 return SUCCESS;
1848 /* Can't use symbol_new here, so have to create a symbol and then at
1849 a later date assign it a value. Thats what these functions do. */
1851 static void
1852 symbol_locate (symbolP, name, segment, valu, frag)
1853 symbolS * symbolP;
1854 const char * name; /* It is copied, the caller can modify. */
1855 segT segment; /* Segment identifier (SEG_<something>). */
1856 valueT valu; /* Symbol value. */
1857 fragS * frag; /* Associated fragment. */
1859 unsigned int name_length;
1860 char * preserved_copy_of_name;
1862 name_length = strlen (name) + 1; /* +1 for \0. */
1863 obstack_grow (&notes, name, name_length);
1864 preserved_copy_of_name = obstack_finish (&notes);
1865 #ifdef STRIP_UNDERSCORE
1866 if (preserved_copy_of_name[0] == '_')
1867 preserved_copy_of_name++;
1868 #endif
1870 #ifdef tc_canonicalize_symbol_name
1871 preserved_copy_of_name =
1872 tc_canonicalize_symbol_name (preserved_copy_of_name);
1873 #endif
1875 S_SET_NAME (symbolP, preserved_copy_of_name);
1877 S_SET_SEGMENT (symbolP, segment);
1878 S_SET_VALUE (symbolP, valu);
1879 symbol_clear_list_pointers(symbolP);
1881 symbol_set_frag (symbolP, frag);
1883 /* Link to end of symbol chain. */
1885 extern int symbol_table_frozen;
1886 if (symbol_table_frozen)
1887 abort ();
1890 symbol_append (symbolP, symbol_lastP, & symbol_rootP, & symbol_lastP);
1892 obj_symbol_new_hook (symbolP);
1894 #ifdef tc_symbol_new_hook
1895 tc_symbol_new_hook (symbolP);
1896 #endif
1898 #ifdef DEBUG_SYMS
1899 verify_symbol_chain (symbol_rootP, symbol_lastP);
1900 #endif /* DEBUG_SYMS */
1903 /* Check that an immediate is valid.
1904 If so, convert it to the right format. */
1906 static unsigned int
1907 validate_immediate (val)
1908 unsigned int val;
1910 unsigned int a;
1911 unsigned int i;
1913 #define rotate_left(v, n) (v << n | v >> (32 - n))
1915 for (i = 0; i < 32; i += 2)
1916 if ((a = rotate_left (val, i)) <= 0xff)
1917 return a | (i << 7); /* 12-bit pack: [shift-cnt,const]. */
1919 return FAIL;
1922 /* Check to see if an immediate can be computed as two seperate immediate
1923 values, added together. We already know that this value cannot be
1924 computed by just one ARM instruction. */
1926 static unsigned int
1927 validate_immediate_twopart (val, highpart)
1928 unsigned int val;
1929 unsigned int * highpart;
1931 unsigned int a;
1932 unsigned int i;
1934 for (i = 0; i < 32; i += 2)
1935 if (((a = rotate_left (val, i)) & 0xff) != 0)
1937 if (a & 0xff00)
1939 if (a & ~ 0xffff)
1940 continue;
1941 * highpart = (a >> 8) | ((i + 24) << 7);
1943 else if (a & 0xff0000)
1945 if (a & 0xff000000)
1946 continue;
1947 * highpart = (a >> 16) | ((i + 16) << 7);
1949 else
1951 assert (a & 0xff000000);
1952 * highpart = (a >> 24) | ((i + 8) << 7);
1955 return (a & 0xff) | (i << 7);
1958 return FAIL;
1961 static int
1962 validate_offset_imm (val, hwse)
1963 unsigned int val;
1964 int hwse;
1966 if ((hwse && val > 255) || val > 4095)
1967 return FAIL;
1968 return val;
1971 static void
1972 s_req (a)
1973 int a ATTRIBUTE_UNUSED;
1975 as_bad (_("Invalid syntax for .req directive."));
1978 static void
1979 s_bss (ignore)
1980 int ignore ATTRIBUTE_UNUSED;
1982 /* We don't support putting frags in the BSS segment, we fake it by
1983 marking in_bss, then looking at s_skip for clues. */
1984 subseg_set (bss_section, 0);
1985 demand_empty_rest_of_line ();
1988 static void
1989 s_even (ignore)
1990 int ignore ATTRIBUTE_UNUSED;
1992 /* Never make frag if expect extra pass. */
1993 if (!need_pass_2)
1994 frag_align (1, 0, 0);
1996 record_alignment (now_seg, 1);
1998 demand_empty_rest_of_line ();
2001 static void
2002 s_ltorg (ignored)
2003 int ignored ATTRIBUTE_UNUSED;
2005 int lit_count = 0;
2006 char sym_name[20];
2008 if (current_poolP == NULL)
2009 return;
2011 /* Align pool as you have word accesses.
2012 Only make a frag if we have to. */
2013 if (!need_pass_2)
2014 frag_align (2, 0, 0);
2016 record_alignment (now_seg, 2);
2018 sprintf (sym_name, "$$lit_\002%x", lit_pool_num++);
2020 symbol_locate (current_poolP, sym_name, now_seg,
2021 (valueT) frag_now_fix (), frag_now);
2022 symbol_table_insert (current_poolP);
2024 ARM_SET_THUMB (current_poolP, thumb_mode);
2026 #if defined OBJ_COFF || defined OBJ_ELF
2027 ARM_SET_INTERWORK (current_poolP, support_interwork);
2028 #endif
2030 while (lit_count < next_literal_pool_place)
2031 /* First output the expression in the instruction to the pool. */
2032 emit_expr (&(literals[lit_count++].exp), 4); /* .word */
2034 next_literal_pool_place = 0;
2035 current_poolP = NULL;
2038 /* Same as s_align_ptwo but align 0 => align 2. */
2040 static void
2041 s_align (unused)
2042 int unused ATTRIBUTE_UNUSED;
2044 register int temp;
2045 register long temp_fill;
2046 long max_alignment = 15;
2048 temp = get_absolute_expression ();
2049 if (temp > max_alignment)
2050 as_bad (_("Alignment too large: %d. assumed."), temp = max_alignment);
2051 else if (temp < 0)
2053 as_bad (_("Alignment negative. 0 assumed."));
2054 temp = 0;
2057 if (*input_line_pointer == ',')
2059 input_line_pointer++;
2060 temp_fill = get_absolute_expression ();
2062 else
2063 temp_fill = 0;
2065 if (!temp)
2066 temp = 2;
2068 /* Only make a frag if we HAVE to. */
2069 if (temp && !need_pass_2)
2070 frag_align (temp, (int) temp_fill, 0);
2071 demand_empty_rest_of_line ();
2073 record_alignment (now_seg, temp);
2076 static void
2077 s_force_thumb (ignore)
2078 int ignore ATTRIBUTE_UNUSED;
2080 /* If we are not already in thumb mode go into it, EVEN if
2081 the target processor does not support thumb instructions.
2082 This is used by gcc/config/arm/lib1funcs.asm for example
2083 to compile interworking support functions even if the
2084 target processor should not support interworking. */
2085 if (! thumb_mode)
2087 thumb_mode = 2;
2089 record_alignment (now_seg, 1);
2092 demand_empty_rest_of_line ();
2095 static void
2096 s_thumb_func (ignore)
2097 int ignore ATTRIBUTE_UNUSED;
2099 if (! thumb_mode)
2100 opcode_select (16);
2102 /* The following label is the name/address of the start of a Thumb function.
2103 We need to know this for the interworking support. */
2104 label_is_thumb_function_name = true;
2106 demand_empty_rest_of_line ();
2109 /* Perform a .set directive, but also mark the alias as
2110 being a thumb function. */
2112 static void
2113 s_thumb_set (equiv)
2114 int equiv;
2116 /* XXX the following is a duplicate of the code for s_set() in read.c
2117 We cannot just call that code as we need to get at the symbol that
2118 is created. */
2119 register char * name;
2120 register char delim;
2121 register char * end_name;
2122 register symbolS * symbolP;
2124 /* Especial apologies for the random logic:
2125 This just grew, and could be parsed much more simply!
2126 Dean - in haste. */
2127 name = input_line_pointer;
2128 delim = get_symbol_end ();
2129 end_name = input_line_pointer;
2130 *end_name = delim;
2132 SKIP_WHITESPACE ();
2134 if (*input_line_pointer != ',')
2136 *end_name = 0;
2137 as_bad (_("Expected comma after name \"%s\""), name);
2138 *end_name = delim;
2139 ignore_rest_of_line ();
2140 return;
2143 input_line_pointer++;
2144 *end_name = 0;
2146 if (name[0] == '.' && name[1] == '\0')
2148 /* XXX - this should not happen to .thumb_set. */
2149 abort ();
2152 if ((symbolP = symbol_find (name)) == NULL
2153 && (symbolP = md_undefined_symbol (name)) == NULL)
2155 #ifndef NO_LISTING
2156 /* When doing symbol listings, play games with dummy fragments living
2157 outside the normal fragment chain to record the file and line info
2158 for this symbol. */
2159 if (listing & LISTING_SYMBOLS)
2161 extern struct list_info_struct * listing_tail;
2162 fragS * dummy_frag = (fragS *) xmalloc (sizeof (fragS));
2164 memset (dummy_frag, 0, sizeof (fragS));
2165 dummy_frag->fr_type = rs_fill;
2166 dummy_frag->line = listing_tail;
2167 symbolP = symbol_new (name, undefined_section, 0, dummy_frag);
2168 dummy_frag->fr_symbol = symbolP;
2170 else
2171 #endif
2172 symbolP = symbol_new (name, undefined_section, 0, &zero_address_frag);
2174 #ifdef OBJ_COFF
2175 /* "set" symbols are local unless otherwise specified. */
2176 SF_SET_LOCAL (symbolP);
2177 #endif /* OBJ_COFF */
2178 } /* Make a new symbol. */
2180 symbol_table_insert (symbolP);
2182 * end_name = delim;
2184 if (equiv
2185 && S_IS_DEFINED (symbolP)
2186 && S_GET_SEGMENT (symbolP) != reg_section)
2187 as_bad (_("symbol `%s' already defined"), S_GET_NAME (symbolP));
2189 pseudo_set (symbolP);
2191 demand_empty_rest_of_line ();
2193 /* XXX Now we come to the Thumb specific bit of code. */
2195 THUMB_SET_FUNC (symbolP, 1);
2196 ARM_SET_THUMB (symbolP, 1);
2197 #if defined OBJ_ELF || defined OBJ_COFF
2198 ARM_SET_INTERWORK (symbolP, support_interwork);
2199 #endif
2202 /* If we change section we must dump the literal pool first. */
2204 static void
2205 arm_s_text (ignore)
2206 int ignore;
2208 if (now_seg != text_section)
2209 s_ltorg (0);
2211 #ifdef OBJ_ELF
2212 obj_elf_text (ignore);
2213 #else
2214 s_text (ignore);
2215 #endif
2218 static void
2219 arm_s_data (ignore)
2220 int ignore;
2222 if (flag_readonly_data_in_text)
2224 if (now_seg != text_section)
2225 s_ltorg (0);
2227 else if (now_seg != data_section)
2228 s_ltorg (0);
2230 #ifdef OBJ_ELF
2231 obj_elf_data (ignore);
2232 #else
2233 s_data (ignore);
2234 #endif
2237 #ifdef OBJ_ELF
2238 static void
2239 arm_s_section (ignore)
2240 int ignore;
2242 s_ltorg (0);
2244 obj_elf_section (ignore);
2246 #endif
2248 static void
2249 opcode_select (width)
2250 int width;
2252 switch (width)
2254 case 16:
2255 if (! thumb_mode)
2257 if (! (cpu_variant & ARM_EXT_V4T))
2258 as_bad (_("selected processor does not support THUMB opcodes"));
2260 thumb_mode = 1;
2261 /* No need to force the alignment, since we will have been
2262 coming from ARM mode, which is word-aligned. */
2263 record_alignment (now_seg, 1);
2265 break;
2267 case 32:
2268 if (thumb_mode)
2270 if ((cpu_variant & ARM_ANY) == ARM_EXT_V4T)
2271 as_bad (_("selected processor does not support ARM opcodes"));
2273 thumb_mode = 0;
2275 if (!need_pass_2)
2276 frag_align (2, 0, 0);
2278 record_alignment (now_seg, 1);
2280 break;
2282 default:
2283 as_bad (_("invalid instruction size selected (%d)"), width);
2287 static void
2288 s_arm (ignore)
2289 int ignore ATTRIBUTE_UNUSED;
2291 opcode_select (32);
2292 demand_empty_rest_of_line ();
2295 static void
2296 s_thumb (ignore)
2297 int ignore ATTRIBUTE_UNUSED;
2299 opcode_select (16);
2300 demand_empty_rest_of_line ();
2303 static void
2304 s_code (unused)
2305 int unused ATTRIBUTE_UNUSED;
2307 register int temp;
2309 temp = get_absolute_expression ();
2310 switch (temp)
2312 case 16:
2313 case 32:
2314 opcode_select (temp);
2315 break;
2317 default:
2318 as_bad (_("invalid operand to .code directive (%d) (expecting 16 or 32)"), temp);
2322 static void
2323 end_of_line (str)
2324 char * str;
2326 skip_whitespace (str);
2328 if (* str != '\0')
2329 inst.error = _("Garbage following instruction");
2332 static int
2333 skip_past_comma (str)
2334 char ** str;
2336 char * p = * str, c;
2337 int comma = 0;
2339 while ((c = *p) == ' ' || c == ',')
2341 p++;
2342 if (c == ',' && comma++)
2343 return FAIL;
2346 if (c == '\0')
2347 return FAIL;
2349 *str = p;
2350 return comma ? SUCCESS : FAIL;
2353 /* A standard register must be given at this point.
2354 SHIFT is the place to put it in inst.instruction.
2355 Restores input start point on error.
2356 Returns the reg#, or FAIL. */
2358 static int
2359 reg_required_here (str, shift)
2360 char ** str;
2361 int shift;
2363 static char buff [128]; /* XXX */
2364 int reg;
2365 char * start = * str;
2367 if ((reg = arm_reg_parse (str)) != FAIL && int_register (reg))
2369 if (shift >= 0)
2370 inst.instruction |= reg << shift;
2371 return reg;
2374 /* Restore the start point, we may have got a reg of the wrong class. */
2375 *str = start;
2377 /* In the few cases where we might be able to accept something else
2378 this error can be overridden. */
2379 sprintf (buff, _("Register expected, not '%.100s'"), start);
2380 inst.error = buff;
2382 return FAIL;
2385 static const struct asm_psr *
2386 arm_psr_parse (ccp)
2387 register char ** ccp;
2389 char * start = * ccp;
2390 char c;
2391 char * p;
2392 const struct asm_psr * psr;
2394 p = start;
2396 /* Skip to the end of the next word in the input stream. */
2399 c = *p++;
2401 while (ISALPHA (c) || c == '_');
2403 /* Terminate the word. */
2404 *--p = 0;
2406 /* CPSR's and SPSR's can now be lowercase. This is just a convenience
2407 feature for ease of use and backwards compatibility. */
2408 if (!strncmp (start, "cpsr", 4))
2409 strncpy (start, "CPSR", 4);
2410 else if (!strncmp (start, "spsr", 4))
2411 strncpy (start, "SPSR", 4);
2413 /* Now locate the word in the psr hash table. */
2414 psr = (const struct asm_psr *) hash_find (arm_psr_hsh, start);
2416 /* Restore the input stream. */
2417 *p = c;
2419 /* If we found a valid match, advance the
2420 stream pointer past the end of the word. */
2421 *ccp = p;
2423 return psr;
2426 /* Parse the input looking for a PSR flag. */
2428 static int
2429 psr_required_here (str)
2430 char ** str;
2432 char * start = * str;
2433 const struct asm_psr * psr;
2435 psr = arm_psr_parse (str);
2437 if (psr)
2439 /* If this is the SPSR that is being modified, set the R bit. */
2440 if (! psr->cpsr)
2441 inst.instruction |= SPSR_BIT;
2443 /* Set the psr flags in the MSR instruction. */
2444 inst.instruction |= psr->field << PSR_SHIFT;
2446 return SUCCESS;
2449 /* In the few cases where we might be able to accept
2450 something else this error can be overridden. */
2451 inst.error = _("flag for {c}psr instruction expected");
2453 /* Restore the start point. */
2454 *str = start;
2455 return FAIL;
2458 static int
2459 co_proc_number (str)
2460 char ** str;
2462 int processor, pchar;
2464 skip_whitespace (* str);
2466 /* The data sheet seems to imply that just a number on its own is valid
2467 here, but the RISC iX assembler seems to accept a prefix 'p'. We will
2468 accept either. */
2469 if (**str == 'p' || **str == 'P')
2470 (*str)++;
2472 pchar = *(*str)++;
2473 if (pchar >= '0' && pchar <= '9')
2475 processor = pchar - '0';
2476 if (**str >= '0' && **str <= '9')
2478 processor = processor * 10 + *(*str)++ - '0';
2479 if (processor > 15)
2481 inst.error = _("Illegal co-processor number");
2482 return FAIL;
2486 else
2488 inst.error = _("Bad or missing co-processor number");
2489 return FAIL;
2492 inst.instruction |= processor << 8;
2493 return SUCCESS;
2496 static int
2497 cp_opc_expr (str, where, length)
2498 char ** str;
2499 int where;
2500 int length;
2502 expressionS expr;
2504 skip_whitespace (* str);
2506 memset (&expr, '\0', sizeof (expr));
2508 if (my_get_expression (&expr, str))
2509 return FAIL;
2510 if (expr.X_op != O_constant)
2512 inst.error = _("bad or missing expression");
2513 return FAIL;
2516 if ((expr.X_add_number & ((1 << length) - 1)) != expr.X_add_number)
2518 inst.error = _("immediate co-processor expression too large");
2519 return FAIL;
2522 inst.instruction |= expr.X_add_number << where;
2523 return SUCCESS;
2526 static int
2527 cp_reg_required_here (str, where)
2528 char ** str;
2529 int where;
2531 int reg;
2532 char * start = *str;
2534 if ((reg = arm_reg_parse (str)) != FAIL && cp_register (reg))
2536 reg &= 15;
2537 inst.instruction |= reg << where;
2538 return reg;
2541 /* In the few cases where we might be able to accept something else
2542 this error can be overridden. */
2543 inst.error = _("Co-processor register expected");
2545 /* Restore the start point. */
2546 *str = start;
2547 return FAIL;
2550 static int
2551 fp_reg_required_here (str, where)
2552 char ** str;
2553 int where;
2555 int reg;
2556 char * start = * str;
2558 if ((reg = arm_reg_parse (str)) != FAIL && fp_register (reg))
2560 reg &= 7;
2561 inst.instruction |= reg << where;
2562 return reg;
2565 /* In the few cases where we might be able to accept something else
2566 this error can be overridden. */
2567 inst.error = _("Floating point register expected");
2569 /* Restore the start point. */
2570 *str = start;
2571 return FAIL;
2574 static int
2575 cp_address_offset (str)
2576 char ** str;
2578 int offset;
2580 skip_whitespace (* str);
2582 if (! is_immediate_prefix (**str))
2584 inst.error = _("immediate expression expected");
2585 return FAIL;
2588 (*str)++;
2590 if (my_get_expression (& inst.reloc.exp, str))
2591 return FAIL;
2593 if (inst.reloc.exp.X_op == O_constant)
2595 offset = inst.reloc.exp.X_add_number;
2597 if (offset & 3)
2599 inst.error = _("co-processor address must be word aligned");
2600 return FAIL;
2603 if (offset > 1023 || offset < -1023)
2605 inst.error = _("offset too large");
2606 return FAIL;
2609 if (offset >= 0)
2610 inst.instruction |= INDEX_UP;
2611 else
2612 offset = -offset;
2614 inst.instruction |= offset >> 2;
2616 else
2617 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
2619 return SUCCESS;
2622 static int
2623 cp_address_required_here (str)
2624 char ** str;
2626 char * p = * str;
2627 int pre_inc = 0;
2628 int write_back = 0;
2630 if (*p == '[')
2632 int reg;
2634 p++;
2635 skip_whitespace (p);
2637 if ((reg = reg_required_here (& p, 16)) == FAIL)
2638 return FAIL;
2640 skip_whitespace (p);
2642 if (*p == ']')
2644 p++;
2646 if (skip_past_comma (& p) == SUCCESS)
2648 /* [Rn], #expr */
2649 write_back = WRITE_BACK;
2651 if (reg == REG_PC)
2653 inst.error = _("pc may not be used in post-increment");
2654 return FAIL;
2657 if (cp_address_offset (& p) == FAIL)
2658 return FAIL;
2660 else
2661 pre_inc = PRE_INDEX | INDEX_UP;
2663 else
2665 /* '['Rn, #expr']'[!] */
2667 if (skip_past_comma (& p) == FAIL)
2669 inst.error = _("pre-indexed expression expected");
2670 return FAIL;
2673 pre_inc = PRE_INDEX;
2675 if (cp_address_offset (& p) == FAIL)
2676 return FAIL;
2678 skip_whitespace (p);
2680 if (*p++ != ']')
2682 inst.error = _("missing ]");
2683 return FAIL;
2686 skip_whitespace (p);
2688 if (*p == '!')
2690 if (reg == REG_PC)
2692 inst.error = _("pc may not be used with write-back");
2693 return FAIL;
2696 p++;
2697 write_back = WRITE_BACK;
2701 else
2703 if (my_get_expression (&inst.reloc.exp, &p))
2704 return FAIL;
2706 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
2707 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
2708 inst.reloc.pc_rel = 1;
2709 inst.instruction |= (REG_PC << 16);
2710 pre_inc = PRE_INDEX;
2713 inst.instruction |= write_back | pre_inc;
2714 *str = p;
2715 return SUCCESS;
2718 static void
2719 do_empty (str, flags)
2720 char * str;
2721 unsigned long flags;
2723 /* Do nothing really. */
2724 inst.instruction |= flags; /* This is pointless. */
2725 end_of_line (str);
2726 return;
2729 static void
2730 do_mrs (str, flags)
2731 char *str;
2732 unsigned long flags;
2734 int skip = 0;
2736 /* Only one syntax. */
2737 skip_whitespace (str);
2739 if (reg_required_here (&str, 12) == FAIL)
2741 inst.error = BAD_ARGS;
2742 return;
2745 if (skip_past_comma (&str) == FAIL)
2747 inst.error = _("comma expected after register name");
2748 return;
2751 skip_whitespace (str);
2753 if ( strcmp (str, "CPSR") == 0
2754 || strcmp (str, "SPSR") == 0
2755 /* Lower case versions for backwards compatability. */
2756 || strcmp (str, "cpsr") == 0
2757 || strcmp (str, "spsr") == 0)
2758 skip = 4;
2760 /* This is for backwards compatability with older toolchains. */
2761 else if ( strcmp (str, "cpsr_all") == 0
2762 || strcmp (str, "spsr_all") == 0)
2763 skip = 8;
2764 else
2766 inst.error = _("{C|S}PSR expected");
2767 return;
2770 if (* str == 's' || * str == 'S')
2771 inst.instruction |= SPSR_BIT;
2772 str += skip;
2774 inst.instruction |= flags;
2775 end_of_line (str);
2778 /* Two possible forms:
2779 "{C|S}PSR_<field>, Rm",
2780 "{C|S}PSR_f, #expression". */
2782 static void
2783 do_msr (str, flags)
2784 char * str;
2785 unsigned long flags;
2787 skip_whitespace (str);
2789 if (psr_required_here (& str) == FAIL)
2790 return;
2792 if (skip_past_comma (& str) == FAIL)
2794 inst.error = _("comma missing after psr flags");
2795 return;
2798 skip_whitespace (str);
2800 if (reg_required_here (& str, 0) != FAIL)
2802 inst.error = NULL;
2803 inst.instruction |= flags;
2804 end_of_line (str);
2805 return;
2808 if (! is_immediate_prefix (* str))
2810 inst.error =
2811 _("only a register or immediate value can follow a psr flag");
2812 return;
2815 str ++;
2816 inst.error = NULL;
2818 if (my_get_expression (& inst.reloc.exp, & str))
2820 inst.error =
2821 _("only a register or immediate value can follow a psr flag");
2822 return;
2825 #if 0 /* The first edition of the ARM architecture manual stated that
2826 writing anything other than the flags with an immediate operation
2827 had UNPREDICTABLE effects. This constraint was removed in the
2828 second edition of the specification. */
2829 if ((cpu_variant & ARM_EXT_V5) != ARM_EXT_V5
2830 && inst.instruction & ((PSR_c | PSR_x | PSR_s) << PSR_SHIFT))
2832 inst.error = _("immediate value cannot be used to set this field");
2833 return;
2835 #endif
2837 flags |= INST_IMMEDIATE;
2839 if (inst.reloc.exp.X_add_symbol)
2841 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
2842 inst.reloc.pc_rel = 0;
2844 else
2846 unsigned value = validate_immediate (inst.reloc.exp.X_add_number);
2848 if (value == (unsigned) FAIL)
2850 inst.error = _("Invalid constant");
2851 return;
2854 inst.instruction |= value;
2857 inst.error = NULL;
2858 inst.instruction |= flags;
2859 end_of_line (str);
2862 /* Long Multiply Parser
2863 UMULL RdLo, RdHi, Rm, Rs
2864 SMULL RdLo, RdHi, Rm, Rs
2865 UMLAL RdLo, RdHi, Rm, Rs
2866 SMLAL RdLo, RdHi, Rm, Rs. */
2868 static void
2869 do_mull (str, flags)
2870 char * str;
2871 unsigned long flags;
2873 int rdlo, rdhi, rm, rs;
2875 /* Only one format "rdlo, rdhi, rm, rs". */
2876 skip_whitespace (str);
2878 if ((rdlo = reg_required_here (&str, 12)) == FAIL)
2880 inst.error = BAD_ARGS;
2881 return;
2884 if (skip_past_comma (&str) == FAIL
2885 || (rdhi = reg_required_here (&str, 16)) == FAIL)
2887 inst.error = BAD_ARGS;
2888 return;
2891 if (skip_past_comma (&str) == FAIL
2892 || (rm = reg_required_here (&str, 0)) == FAIL)
2894 inst.error = BAD_ARGS;
2895 return;
2898 /* rdhi, rdlo and rm must all be different. */
2899 if (rdlo == rdhi || rdlo == rm || rdhi == rm)
2900 as_tsktsk (_("rdhi, rdlo and rm must all be different"));
2902 if (skip_past_comma (&str) == FAIL
2903 || (rs = reg_required_here (&str, 8)) == FAIL)
2905 inst.error = BAD_ARGS;
2906 return;
2909 if (rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC)
2911 inst.error = BAD_PC;
2912 return;
2915 inst.instruction |= flags;
2916 end_of_line (str);
2917 return;
2920 static void
2921 do_mul (str, flags)
2922 char * str;
2923 unsigned long flags;
2925 int rd, rm;
2927 /* Only one format "rd, rm, rs". */
2928 skip_whitespace (str);
2930 if ((rd = reg_required_here (&str, 16)) == FAIL)
2932 inst.error = BAD_ARGS;
2933 return;
2936 if (rd == REG_PC)
2938 inst.error = BAD_PC;
2939 return;
2942 if (skip_past_comma (&str) == FAIL
2943 || (rm = reg_required_here (&str, 0)) == FAIL)
2945 inst.error = BAD_ARGS;
2946 return;
2949 if (rm == REG_PC)
2951 inst.error = BAD_PC;
2952 return;
2955 if (rm == rd)
2956 as_tsktsk (_("rd and rm should be different in mul"));
2958 if (skip_past_comma (&str) == FAIL
2959 || (rm = reg_required_here (&str, 8)) == FAIL)
2961 inst.error = BAD_ARGS;
2962 return;
2965 if (rm == REG_PC)
2967 inst.error = BAD_PC;
2968 return;
2971 inst.instruction |= flags;
2972 end_of_line (str);
2973 return;
2976 static void
2977 do_mla (str, flags)
2978 char * str;
2979 unsigned long flags;
2981 int rd, rm;
2983 /* Only one format "rd, rm, rs, rn". */
2984 skip_whitespace (str);
2986 if ((rd = reg_required_here (&str, 16)) == FAIL)
2988 inst.error = BAD_ARGS;
2989 return;
2992 if (rd == REG_PC)
2994 inst.error = BAD_PC;
2995 return;
2998 if (skip_past_comma (&str) == FAIL
2999 || (rm = reg_required_here (&str, 0)) == FAIL)
3001 inst.error = BAD_ARGS;
3002 return;
3005 if (rm == REG_PC)
3007 inst.error = BAD_PC;
3008 return;
3011 if (rm == rd)
3012 as_tsktsk (_("rd and rm should be different in mla"));
3014 if (skip_past_comma (&str) == FAIL
3015 || (rd = reg_required_here (&str, 8)) == FAIL
3016 || skip_past_comma (&str) == FAIL
3017 || (rm = reg_required_here (&str, 12)) == FAIL)
3019 inst.error = BAD_ARGS;
3020 return;
3023 if (rd == REG_PC || rm == REG_PC)
3025 inst.error = BAD_PC;
3026 return;
3029 inst.instruction |= flags;
3030 end_of_line (str);
3031 return;
3034 /* Expects *str -> the characters "acc0", possibly with leading blanks.
3035 Advances *str to the next non-alphanumeric.
3036 Returns 0, or else FAIL (in which case sets inst.error).
3038 (In a future XScale, there may be accumulators other than zero.
3039 At that time this routine and its callers can be upgraded to suit.) */
3041 static int
3042 accum0_required_here (str)
3043 char ** str;
3045 static char buff [128]; /* Note the address is taken. Hence, static. */
3046 char * p = * str;
3047 char c;
3048 int result = 0; /* The accum number. */
3050 skip_whitespace (p);
3052 *str = p; /* Advance caller's string pointer too. */
3053 c = *p++;
3054 while (ISALNUM (c))
3055 c = *p++;
3057 *--p = 0; /* Aap nul into input buffer at non-alnum. */
3059 if (! ( streq (*str, "acc0") || streq (*str, "ACC0")))
3061 sprintf (buff, _("acc0 expected, not '%.100s'"), *str);
3062 inst.error = buff;
3063 result = FAIL;
3066 *p = c; /* Unzap. */
3067 *str = p; /* Caller's string pointer to after match. */
3068 return result;
3071 /* Expects **str -> after a comma. May be leading blanks.
3072 Advances *str, recognizing a load mode, and setting inst.instruction.
3073 Returns rn, or else FAIL (in which case may set inst.error
3074 and not advance str)
3076 Note: doesn't know Rd, so no err checks that require such knowledge. */
3078 static int
3079 ld_mode_required_here (string)
3080 char ** string;
3082 char * str = * string;
3083 int rn;
3084 int pre_inc = 0;
3086 skip_whitespace (str);
3088 if (* str == '[')
3090 str++;
3092 skip_whitespace (str);
3094 if ((rn = reg_required_here (& str, 16)) == FAIL)
3095 return FAIL;
3097 skip_whitespace (str);
3099 if (* str == ']')
3101 str ++;
3103 if (skip_past_comma (& str) == SUCCESS)
3105 /* [Rn],... (post inc) */
3106 if (ldst_extend_v4 (&str) == FAIL)
3107 return FAIL;
3109 else /* [Rn] */
3111 skip_whitespace (str);
3113 if (* str == '!')
3115 str ++;
3116 inst.instruction |= WRITE_BACK;
3119 inst.instruction |= INDEX_UP | HWOFFSET_IMM;
3120 pre_inc = 1;
3123 else /* [Rn,...] */
3125 if (skip_past_comma (& str) == FAIL)
3127 inst.error = _("pre-indexed expression expected");
3128 return FAIL;
3131 pre_inc = 1;
3133 if (ldst_extend_v4 (&str) == FAIL)
3134 return FAIL;
3136 skip_whitespace (str);
3138 if (* str ++ != ']')
3140 inst.error = _("missing ]");
3141 return FAIL;
3144 skip_whitespace (str);
3146 if (* str == '!')
3148 str ++;
3149 inst.instruction |= WRITE_BACK;
3153 else if (* str == '=') /* ldr's "r,=label" syntax */
3154 /* We should never reach here, because <text> = <expression> is
3155 caught gas/read.c read_a_source_file() as a .set operation. */
3156 return FAIL;
3157 else /* PC +- 8 bit immediate offset. */
3159 if (my_get_expression (& inst.reloc.exp, & str))
3160 return FAIL;
3162 inst.instruction |= HWOFFSET_IMM; /* The I bit. */
3163 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
3164 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
3165 inst.reloc.pc_rel = 1;
3166 inst.instruction |= (REG_PC << 16);
3168 rn = REG_PC;
3169 pre_inc = 1;
3172 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
3173 * string = str;
3175 return rn;
3178 /* ARM V5E (El Segundo) signed-multiply-accumulate (argument parse)
3179 SMLAxy{cond} Rd,Rm,Rs,Rn
3180 SMLAWy{cond} Rd,Rm,Rs,Rn
3181 Error if any register is R15. */
3183 static void
3184 do_smla (str, flags)
3185 char * str;
3186 unsigned long flags;
3188 int rd, rm, rs, rn;
3190 skip_whitespace (str);
3192 if ((rd = reg_required_here (& str, 16)) == FAIL
3193 || skip_past_comma (& str) == FAIL
3194 || (rm = reg_required_here (& str, 0)) == FAIL
3195 || skip_past_comma (& str) == FAIL
3196 || (rs = reg_required_here (& str, 8)) == FAIL
3197 || skip_past_comma (& str) == FAIL
3198 || (rn = reg_required_here (& str, 12)) == FAIL)
3199 inst.error = BAD_ARGS;
3201 else if (rd == REG_PC || rm == REG_PC || rs == REG_PC || rn == REG_PC)
3202 inst.error = BAD_PC;
3204 else if (flags)
3205 inst.error = BAD_FLAGS;
3207 else
3208 end_of_line (str);
3211 /* ARM V5E (El Segundo) signed-multiply-accumulate-long (argument parse)
3212 SMLALxy{cond} Rdlo,Rdhi,Rm,Rs
3213 Error if any register is R15.
3214 Warning if Rdlo == Rdhi. */
3216 static void
3217 do_smlal (str, flags)
3218 char * str;
3219 unsigned long flags;
3221 int rdlo, rdhi, rm, rs;
3223 skip_whitespace (str);
3225 if ((rdlo = reg_required_here (& str, 12)) == FAIL
3226 || skip_past_comma (& str) == FAIL
3227 || (rdhi = reg_required_here (& str, 16)) == FAIL
3228 || skip_past_comma (& str) == FAIL
3229 || (rm = reg_required_here (& str, 0)) == FAIL
3230 || skip_past_comma (& str) == FAIL
3231 || (rs = reg_required_here (& str, 8)) == FAIL)
3233 inst.error = BAD_ARGS;
3234 return;
3237 if (rdlo == REG_PC || rdhi == REG_PC || rm == REG_PC || rs == REG_PC)
3239 inst.error = BAD_PC;
3240 return;
3243 if (rdlo == rdhi)
3244 as_tsktsk (_("rdhi and rdlo must be different"));
3246 if (flags)
3247 inst.error = BAD_FLAGS;
3248 else
3249 end_of_line (str);
3252 /* ARM V5E (El Segundo) signed-multiply (argument parse)
3253 SMULxy{cond} Rd,Rm,Rs
3254 Error if any register is R15. */
3256 static void
3257 do_smul (str, flags)
3258 char * str;
3259 unsigned long flags;
3261 int rd, rm, rs;
3263 skip_whitespace (str);
3265 if ((rd = reg_required_here (& str, 16)) == FAIL
3266 || skip_past_comma (& str) == FAIL
3267 || (rm = reg_required_here (& str, 0)) == FAIL
3268 || skip_past_comma (& str) == FAIL
3269 || (rs = reg_required_here (& str, 8)) == FAIL)
3270 inst.error = BAD_ARGS;
3272 else if (rd == REG_PC || rm == REG_PC || rs == REG_PC)
3273 inst.error = BAD_PC;
3275 else if (flags)
3276 inst.error = BAD_FLAGS;
3278 else
3279 end_of_line (str);
3282 /* ARM V5E (El Segundo) saturating-add/subtract (argument parse)
3283 Q[D]{ADD,SUB}{cond} Rd,Rm,Rn
3284 Error if any register is R15. */
3286 static void
3287 do_qadd (str, flags)
3288 char * str;
3289 unsigned long flags;
3291 int rd, rm, rn;
3293 skip_whitespace (str);
3295 if ((rd = reg_required_here (& str, 12)) == FAIL
3296 || skip_past_comma (& str) == FAIL
3297 || (rm = reg_required_here (& str, 0)) == FAIL
3298 || skip_past_comma (& str) == FAIL
3299 || (rn = reg_required_here (& str, 16)) == FAIL)
3300 inst.error = BAD_ARGS;
3302 else if (rd == REG_PC || rm == REG_PC || rn == REG_PC)
3303 inst.error = BAD_PC;
3305 else if (flags)
3306 inst.error = BAD_FLAGS;
3308 else
3309 end_of_line (str);
3312 /* ARM V5E (el Segundo)
3313 MCRRcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
3314 MRRCcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
3316 These are equivalent to the XScale instructions MAR and MRA,
3317 respectively, when coproc == 0, opcode == 0, and CRm == 0.
3319 Result unpredicatable if Rd or Rn is R15. */
3321 static void
3322 do_co_reg2c (str, flags)
3323 char * str;
3324 unsigned long flags;
3326 int rd, rn;
3328 skip_whitespace (str);
3330 if (co_proc_number (& str) == FAIL)
3332 if (!inst.error)
3333 inst.error = BAD_ARGS;
3334 return;
3337 if (skip_past_comma (& str) == FAIL
3338 || cp_opc_expr (& str, 4, 4) == FAIL)
3340 if (!inst.error)
3341 inst.error = BAD_ARGS;
3342 return;
3345 if (skip_past_comma (& str) == FAIL
3346 || (rd = reg_required_here (& str, 12)) == FAIL)
3348 if (!inst.error)
3349 inst.error = BAD_ARGS;
3350 return;
3353 if (skip_past_comma (& str) == FAIL
3354 || (rn = reg_required_here (& str, 16)) == FAIL)
3356 if (!inst.error)
3357 inst.error = BAD_ARGS;
3358 return;
3361 /* Unpredictable result if rd or rn is R15. */
3362 if (rd == REG_PC || rn == REG_PC)
3363 as_tsktsk
3364 (_("Warning: Instruction unpredictable when using r15"));
3366 if (skip_past_comma (& str) == FAIL
3367 || cp_reg_required_here (& str, 0) == FAIL)
3369 if (!inst.error)
3370 inst.error = BAD_ARGS;
3371 return;
3374 if (flags)
3375 inst.error = BAD_COND;
3377 end_of_line (str);
3380 /* ARM V5 count-leading-zeroes instruction (argument parse)
3381 CLZ{<cond>} <Rd>, <Rm>
3382 Condition defaults to COND_ALWAYS.
3383 Error if Rd or Rm are R15. */
3385 static void
3386 do_clz (str, flags)
3387 char * str;
3388 unsigned long flags;
3390 int rd, rm;
3392 if (flags)
3394 as_bad (BAD_FLAGS);
3395 return;
3398 skip_whitespace (str);
3400 if (((rd = reg_required_here (& str, 12)) == FAIL)
3401 || (skip_past_comma (& str) == FAIL)
3402 || ((rm = reg_required_here (& str, 0)) == FAIL))
3403 inst.error = BAD_ARGS;
3405 else if (rd == REG_PC || rm == REG_PC )
3406 inst.error = BAD_PC;
3408 else
3409 end_of_line (str);
3412 /* ARM V5 (argument parse)
3413 LDC2{L} <coproc>, <CRd>, <addressing mode>
3414 STC2{L} <coproc>, <CRd>, <addressing mode>
3415 Instruction is not conditional, and has 0xf in the codition field.
3416 Otherwise, it's the same as LDC/STC. */
3418 static void
3419 do_lstc2 (str, flags)
3420 char * str;
3421 unsigned long flags;
3423 if (flags)
3424 inst.error = BAD_COND;
3426 skip_whitespace (str);
3428 if (co_proc_number (& str) == FAIL)
3430 if (!inst.error)
3431 inst.error = BAD_ARGS;
3433 else if (skip_past_comma (& str) == FAIL
3434 || cp_reg_required_here (& str, 12) == FAIL)
3436 if (!inst.error)
3437 inst.error = BAD_ARGS;
3439 else if (skip_past_comma (& str) == FAIL
3440 || cp_address_required_here (& str) == FAIL)
3442 if (! inst.error)
3443 inst.error = BAD_ARGS;
3445 else
3446 end_of_line (str);
3449 /* ARM V5 (argument parse)
3450 CDP2 <coproc>, <opcode_1>, <CRd>, <CRn>, <CRm>, <opcode_2>
3451 Instruction is not conditional, and has 0xf in the condition field.
3452 Otherwise, it's the same as CDP. */
3454 static void
3455 do_cdp2 (str, flags)
3456 char * str;
3457 unsigned long flags;
3459 skip_whitespace (str);
3461 if (co_proc_number (& str) == FAIL)
3463 if (!inst.error)
3464 inst.error = BAD_ARGS;
3465 return;
3468 if (skip_past_comma (& str) == FAIL
3469 || cp_opc_expr (& str, 20,4) == FAIL)
3471 if (!inst.error)
3472 inst.error = BAD_ARGS;
3473 return;
3476 if (skip_past_comma (& str) == FAIL
3477 || cp_reg_required_here (& str, 12) == FAIL)
3479 if (!inst.error)
3480 inst.error = BAD_ARGS;
3481 return;
3484 if (skip_past_comma (& str) == FAIL
3485 || cp_reg_required_here (& str, 16) == FAIL)
3487 if (!inst.error)
3488 inst.error = BAD_ARGS;
3489 return;
3492 if (skip_past_comma (& str) == FAIL
3493 || cp_reg_required_here (& str, 0) == FAIL)
3495 if (!inst.error)
3496 inst.error = BAD_ARGS;
3497 return;
3500 if (skip_past_comma (& str) == SUCCESS)
3502 if (cp_opc_expr (& str, 5, 3) == FAIL)
3504 if (!inst.error)
3505 inst.error = BAD_ARGS;
3506 return;
3510 if (flags)
3511 inst.error = BAD_FLAGS;
3513 end_of_line (str);
3516 /* ARM V5 (argument parse)
3517 MCR2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
3518 MRC2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
3519 Instruction is not conditional, and has 0xf in the condition field.
3520 Otherwise, it's the same as MCR/MRC. */
3522 static void
3523 do_co_reg2 (str, flags)
3524 char * str;
3525 unsigned long flags;
3527 skip_whitespace (str);
3529 if (co_proc_number (& str) == FAIL)
3531 if (!inst.error)
3532 inst.error = BAD_ARGS;
3533 return;
3536 if (skip_past_comma (& str) == FAIL
3537 || cp_opc_expr (& str, 21, 3) == FAIL)
3539 if (!inst.error)
3540 inst.error = BAD_ARGS;
3541 return;
3544 if (skip_past_comma (& str) == FAIL
3545 || reg_required_here (& str, 12) == FAIL)
3547 if (!inst.error)
3548 inst.error = BAD_ARGS;
3549 return;
3552 if (skip_past_comma (& str) == FAIL
3553 || cp_reg_required_here (& str, 16) == FAIL)
3555 if (!inst.error)
3556 inst.error = BAD_ARGS;
3557 return;
3560 if (skip_past_comma (& str) == FAIL
3561 || cp_reg_required_here (& str, 0) == FAIL)
3563 if (!inst.error)
3564 inst.error = BAD_ARGS;
3565 return;
3568 if (skip_past_comma (& str) == SUCCESS)
3570 if (cp_opc_expr (& str, 5, 3) == FAIL)
3572 if (!inst.error)
3573 inst.error = BAD_ARGS;
3574 return;
3578 if (flags)
3579 inst.error = BAD_COND;
3581 end_of_line (str);
3584 /* THUMB V5 breakpoint instruction (argument parse)
3585 BKPT <immed_8>. */
3587 static void
3588 do_t_bkpt (str)
3589 char * str;
3591 expressionS expr;
3592 unsigned long number;
3594 skip_whitespace (str);
3596 /* Allow optional leading '#'. */
3597 if (is_immediate_prefix (*str))
3598 str ++;
3600 memset (& expr, '\0', sizeof (expr));
3601 if (my_get_expression (& expr, & str) || (expr.X_op != O_constant))
3603 inst.error = _("bad or missing expression");
3604 return;
3607 number = expr.X_add_number;
3609 /* Check it fits an 8 bit unsigned. */
3610 if (number != (number & 0xff))
3612 inst.error = _("immediate value out of range");
3613 return;
3616 inst.instruction |= number;
3618 end_of_line (str);
3621 /* ARM V5 branch-link-exchange (argument parse) for BLX(1) only.
3622 Expects inst.instruction is set for BLX(1).
3623 Note: this is cloned from do_branch, and the reloc changed to be a
3624 new one that can cope with setting one extra bit (the H bit). */
3626 static void
3627 do_branch25 (str, flags)
3628 char * str;
3629 unsigned long flags ATTRIBUTE_UNUSED;
3631 if (my_get_expression (& inst.reloc.exp, & str))
3632 return;
3634 #ifdef OBJ_ELF
3636 char * save_in;
3638 /* ScottB: February 5, 1998 */
3639 /* Check to see of PLT32 reloc required for the instruction. */
3641 /* arm_parse_reloc() works on input_line_pointer.
3642 We actually want to parse the operands to the branch instruction
3643 passed in 'str'. Save the input pointer and restore it later. */
3644 save_in = input_line_pointer;
3645 input_line_pointer = str;
3647 if (inst.reloc.exp.X_op == O_symbol
3648 && *str == '('
3649 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
3651 inst.reloc.type = BFD_RELOC_ARM_PLT32;
3652 inst.reloc.pc_rel = 0;
3653 /* Modify str to point to after parsed operands, otherwise
3654 end_of_line() will complain about the (PLT) left in str. */
3655 str = input_line_pointer;
3657 else
3659 inst.reloc.type = BFD_RELOC_ARM_PCREL_BLX;
3660 inst.reloc.pc_rel = 1;
3663 input_line_pointer = save_in;
3665 #else
3666 inst.reloc.type = BFD_RELOC_ARM_PCREL_BLX;
3667 inst.reloc.pc_rel = 1;
3668 #endif /* OBJ_ELF */
3670 end_of_line (str);
3673 /* ARM V5 branch-link-exchange instruction (argument parse)
3674 BLX <target_addr> ie BLX(1)
3675 BLX{<condition>} <Rm> ie BLX(2)
3676 Unfortunately, there are two different opcodes for this mnemonic.
3677 So, the insns[].value is not used, and the code here zaps values
3678 into inst.instruction.
3679 Also, the <target_addr> can be 25 bits, hence has its own reloc. */
3681 static void
3682 do_blx (str, flags)
3683 char * str;
3684 unsigned long flags;
3686 char * mystr = str;
3687 int rm;
3689 if (flags)
3691 as_bad (BAD_FLAGS);
3692 return;
3695 skip_whitespace (mystr);
3696 rm = reg_required_here (& mystr, 0);
3698 /* The above may set inst.error. Ignore his opinion. */
3699 inst.error = 0;
3701 if (rm != FAIL)
3703 /* Arg is a register.
3704 Use the condition code our caller put in inst.instruction.
3705 Pass ourselves off as a BX with a funny opcode. */
3706 inst.instruction |= 0x012fff30;
3707 do_bx (str, flags);
3709 else
3711 /* This must be is BLX <target address>, no condition allowed. */
3712 if (inst.instruction != COND_ALWAYS)
3714 inst.error = BAD_COND;
3715 return;
3718 inst.instruction = 0xfafffffe;
3720 /* Process like a B/BL, but with a different reloc.
3721 Note that B/BL expecte fffffe, not 0, offset in the opcode table. */
3722 do_branch25 (str, flags);
3726 /* ARM V5 Thumb BLX (argument parse)
3727 BLX <target_addr> which is BLX(1)
3728 BLX <Rm> which is BLX(2)
3729 Unfortunately, there are two different opcodes for this mnemonic.
3730 So, the tinsns[].value is not used, and the code here zaps values
3731 into inst.instruction. */
3733 static void
3734 do_t_blx (str)
3735 char * str;
3737 char * mystr = str;
3738 int rm;
3740 skip_whitespace (mystr);
3741 inst.instruction = 0x4780;
3743 /* Note that this call is to the ARM register recognizer. BLX(2)
3744 uses the ARM register space, not the Thumb one, so a call to
3745 thumb_reg() would be wrong. */
3746 rm = reg_required_here (& mystr, 3);
3747 inst.error = 0;
3749 if (rm != FAIL)
3751 /* It's BLX(2). The .instruction was zapped with rm & is final. */
3752 inst.size = 2;
3754 else
3756 /* No ARM register. This must be BLX(1). Change the .instruction. */
3757 inst.instruction = 0xf7ffeffe;
3758 inst.size = 4;
3760 if (my_get_expression (& inst.reloc.exp, & mystr))
3761 return;
3763 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BLX;
3764 inst.reloc.pc_rel = 1;
3767 end_of_line (mystr);
3770 /* ARM V5 breakpoint instruction (argument parse)
3771 BKPT <16 bit unsigned immediate>
3772 Instruction is not conditional.
3773 The bit pattern given in insns[] has the COND_ALWAYS condition,
3774 and it is an error if the caller tried to override that.
3775 Note "flags" is nonzero if a flag was supplied (which is an error). */
3777 static void
3778 do_bkpt (str, flags)
3779 char * str;
3780 unsigned long flags;
3782 expressionS expr;
3783 unsigned long number;
3785 skip_whitespace (str);
3787 /* Allow optional leading '#'. */
3788 if (is_immediate_prefix (* str))
3789 str++;
3791 memset (& expr, '\0', sizeof (expr));
3793 if (my_get_expression (& expr, & str) || (expr.X_op != O_constant))
3795 inst.error = _("bad or missing expression");
3796 return;
3799 number = expr.X_add_number;
3801 /* Check it fits a 16 bit unsigned. */
3802 if (number != (number & 0xffff))
3804 inst.error = _("immediate value out of range");
3805 return;
3808 /* Top 12 of 16 bits to bits 19:8. */
3809 inst.instruction |= (number & 0xfff0) << 4;
3811 /* Bottom 4 of 16 bits to bits 3:0. */
3812 inst.instruction |= number & 0xf;
3814 end_of_line (str);
3816 if (flags)
3817 inst.error = BAD_FLAGS;
3820 /* Xscale multiply-accumulate (argument parse)
3821 MIAcc acc0,Rm,Rs
3822 MIAPHcc acc0,Rm,Rs
3823 MIAxycc acc0,Rm,Rs. */
3825 static void
3826 do_mia (str, flags)
3827 char * str;
3828 unsigned long flags;
3830 int rs;
3831 int rm;
3833 if (flags)
3834 as_bad (BAD_FLAGS);
3836 else if (accum0_required_here (& str) == FAIL)
3837 inst.error = ERR_NO_ACCUM;
3839 else if (skip_past_comma (& str) == FAIL
3840 || (rm = reg_required_here (& str, 0)) == FAIL)
3841 inst.error = BAD_ARGS;
3843 else if (skip_past_comma (& str) == FAIL
3844 || (rs = reg_required_here (& str, 12)) == FAIL)
3845 inst.error = BAD_ARGS;
3847 /* inst.instruction has now been zapped with both rm and rs. */
3848 else if (rm == REG_PC || rs == REG_PC)
3849 inst.error = BAD_PC; /* Undefined result if rm or rs is R15. */
3851 else
3852 end_of_line (str);
3855 /* Xscale move-accumulator-register (argument parse)
3857 MARcc acc0,RdLo,RdHi. */
3859 static void
3860 do_mar (str, flags)
3861 char * str;
3862 unsigned long flags;
3864 int rdlo, rdhi;
3866 if (flags)
3867 as_bad (BAD_FLAGS);
3869 else if (accum0_required_here (& str) == FAIL)
3870 inst.error = ERR_NO_ACCUM;
3872 else if (skip_past_comma (& str) == FAIL
3873 || (rdlo = reg_required_here (& str, 12)) == FAIL)
3874 inst.error = BAD_ARGS;
3876 else if (skip_past_comma (& str) == FAIL
3877 || (rdhi = reg_required_here (& str, 16)) == FAIL)
3878 inst.error = BAD_ARGS;
3880 /* inst.instruction has now been zapped with both rdlo and rdhi. */
3881 else if (rdlo == REG_PC || rdhi == REG_PC)
3882 inst.error = BAD_PC; /* Undefined result if rdlo or rdhi is R15. */
3884 else
3885 end_of_line (str);
3888 /* Xscale move-register-accumulator (argument parse)
3890 MRAcc RdLo,RdHi,acc0. */
3892 static void
3893 do_mra (str, flags)
3894 char * str;
3895 unsigned long flags;
3897 int rdlo;
3898 int rdhi;
3900 if (flags)
3902 as_bad (BAD_FLAGS);
3903 return;
3906 skip_whitespace (str);
3908 if ((rdlo = reg_required_here (& str, 12)) == FAIL)
3909 inst.error = BAD_ARGS;
3911 else if (skip_past_comma (& str) == FAIL
3912 || (rdhi = reg_required_here (& str, 16)) == FAIL)
3913 inst.error = BAD_ARGS;
3915 else if (skip_past_comma (& str) == FAIL
3916 || accum0_required_here (& str) == FAIL)
3917 inst.error = ERR_NO_ACCUM;
3919 /* inst.instruction has now been zapped with both rdlo and rdhi. */
3920 else if (rdlo == rdhi)
3921 inst.error = BAD_ARGS; /* Undefined result if 2 writes to same reg. */
3923 else if (rdlo == REG_PC || rdhi == REG_PC)
3924 inst.error = BAD_PC; /* Undefined result if rdlo or rdhi is R15. */
3925 else
3926 end_of_line (str);
3929 /* ARMv5TE: Preload-Cache
3931 PLD <addr_mode>
3933 Syntactically, like LDR with B=1, W=0, L=1. */
3935 static void
3936 do_pld (str, flags)
3937 char * str;
3938 unsigned long flags;
3940 int rd;
3942 if (flags)
3944 as_bad (BAD_FLAGS);
3945 return;
3948 skip_whitespace (str);
3950 if (* str != '[')
3952 inst.error = _("'[' expected after PLD mnemonic");
3953 return;
3956 ++str;
3957 skip_whitespace (str);
3959 if ((rd = reg_required_here (& str, 16)) == FAIL)
3960 return;
3962 skip_whitespace (str);
3964 if (*str == ']')
3966 /* [Rn], ... ? */
3967 ++str;
3968 skip_whitespace (str);
3970 /* Post-indexed addressing is not allowed with PLD. */
3971 if (skip_past_comma (&str) == SUCCESS)
3973 inst.error
3974 = _("post-indexed expression used in preload instruction");
3975 return;
3977 else if (*str == '!') /* [Rn]! */
3979 inst.error = _("writeback used in preload instruction");
3980 ++str;
3982 else /* [Rn] */
3983 inst.instruction |= INDEX_UP | PRE_INDEX;
3985 else /* [Rn, ...] */
3987 if (skip_past_comma (& str) == FAIL)
3989 inst.error = _("pre-indexed expression expected");
3990 return;
3993 if (ldst_extend (&str) == FAIL)
3994 return;
3996 skip_whitespace (str);
3998 if (* str != ']')
4000 inst.error = _("missing ]");
4001 return;
4004 ++ str;
4005 skip_whitespace (str);
4007 if (* str == '!') /* [Rn]! */
4009 inst.error = _("writeback used in preload instruction");
4010 ++ str;
4013 inst.instruction |= PRE_INDEX;
4016 end_of_line (str);
4019 /* ARMv5TE load-consecutive (argument parse)
4020 Mode is like LDRH.
4022 LDRccD R, mode
4023 STRccD R, mode. */
4025 static void
4026 do_ldrd (str, flags)
4027 char * str;
4028 unsigned long flags;
4030 int rd;
4031 int rn;
4033 skip_whitespace (str);
4035 if ((rd = reg_required_here (& str, 12)) == FAIL)
4037 inst.error = BAD_ARGS;
4038 return;
4041 if (skip_past_comma (& str) == FAIL
4042 || (rn = ld_mode_required_here (& str)) == FAIL)
4044 if (!inst.error)
4045 inst.error = BAD_ARGS;
4046 return;
4049 /* inst.instruction has now been zapped with Rd and the addressing mode. */
4050 if (rd & 1) /* Unpredictable result if Rd is odd. */
4052 inst.error = _("Destination register must be even");
4053 return;
4056 if (rd == REG_LR)
4058 inst.error = _("r12 or r14 not allowed here");
4059 return;
4062 if (((rd == rn) || (rd + 1 == rn))
4063 && ((inst.instruction & WRITE_BACK)
4064 || (!(inst.instruction & PRE_INDEX))))
4065 as_warn (_("pre/post-indexing used when modified address register is destination"));
4067 /* For an index-register load, the index register must not overlap the
4068 destination (even if not write-back). */
4069 if ((inst.instruction & V4_STR_BIT) == 0
4070 && (inst.instruction & HWOFFSET_IMM) == 0)
4072 int rm = inst.instruction & 0x0000000f;
4074 if (rm == rd || (rm == rd + 1))
4075 as_warn (_("ldrd destination registers must not overlap index register"));
4078 end_of_line (str);
4081 /* Returns the index into fp_values of a floating point number,
4082 or -1 if not in the table. */
4084 static int
4085 my_get_float_expression (str)
4086 char ** str;
4088 LITTLENUM_TYPE words[MAX_LITTLENUMS];
4089 char * save_in;
4090 expressionS exp;
4091 int i;
4092 int j;
4094 memset (words, 0, MAX_LITTLENUMS * sizeof (LITTLENUM_TYPE));
4096 /* Look for a raw floating point number. */
4097 if ((save_in = atof_ieee (*str, 'x', words)) != NULL
4098 && is_end_of_line[(unsigned char) *save_in])
4100 for (i = 0; i < NUM_FLOAT_VALS; i++)
4102 for (j = 0; j < MAX_LITTLENUMS; j++)
4104 if (words[j] != fp_values[i][j])
4105 break;
4108 if (j == MAX_LITTLENUMS)
4110 *str = save_in;
4111 return i;
4116 /* Try and parse a more complex expression, this will probably fail
4117 unless the code uses a floating point prefix (eg "0f"). */
4118 save_in = input_line_pointer;
4119 input_line_pointer = *str;
4120 if (expression (&exp) == absolute_section
4121 && exp.X_op == O_big
4122 && exp.X_add_number < 0)
4124 /* FIXME: 5 = X_PRECISION, should be #define'd where we can use it.
4125 Ditto for 15. */
4126 if (gen_to_words (words, 5, (long) 15) == 0)
4128 for (i = 0; i < NUM_FLOAT_VALS; i++)
4130 for (j = 0; j < MAX_LITTLENUMS; j++)
4132 if (words[j] != fp_values[i][j])
4133 break;
4136 if (j == MAX_LITTLENUMS)
4138 *str = input_line_pointer;
4139 input_line_pointer = save_in;
4140 return i;
4146 *str = input_line_pointer;
4147 input_line_pointer = save_in;
4148 return -1;
4151 /* Return true if anything in the expression is a bignum. */
4153 static int
4154 walk_no_bignums (sp)
4155 symbolS * sp;
4157 if (symbol_get_value_expression (sp)->X_op == O_big)
4158 return 1;
4160 if (symbol_get_value_expression (sp)->X_add_symbol)
4162 return (walk_no_bignums (symbol_get_value_expression (sp)->X_add_symbol)
4163 || (symbol_get_value_expression (sp)->X_op_symbol
4164 && walk_no_bignums (symbol_get_value_expression (sp)->X_op_symbol)));
4167 return 0;
4170 static int
4171 my_get_expression (ep, str)
4172 expressionS * ep;
4173 char ** str;
4175 char * save_in;
4176 segT seg;
4178 save_in = input_line_pointer;
4179 input_line_pointer = *str;
4180 seg = expression (ep);
4182 #ifdef OBJ_AOUT
4183 if (seg != absolute_section
4184 && seg != text_section
4185 && seg != data_section
4186 && seg != bss_section
4187 && seg != undefined_section)
4189 inst.error = _("bad_segment");
4190 *str = input_line_pointer;
4191 input_line_pointer = save_in;
4192 return 1;
4194 #endif
4196 /* Get rid of any bignums now, so that we don't generate an error for which
4197 we can't establish a line number later on. Big numbers are never valid
4198 in instructions, which is where this routine is always called. */
4199 if (ep->X_op == O_big
4200 || (ep->X_add_symbol
4201 && (walk_no_bignums (ep->X_add_symbol)
4202 || (ep->X_op_symbol
4203 && walk_no_bignums (ep->X_op_symbol)))))
4205 inst.error = _("Invalid constant");
4206 *str = input_line_pointer;
4207 input_line_pointer = save_in;
4208 return 1;
4211 *str = input_line_pointer;
4212 input_line_pointer = save_in;
4213 return 0;
4216 /* UNRESTRICT should be one if <shift> <register> is permitted for this
4217 instruction. */
4219 static int
4220 decode_shift (str, unrestrict)
4221 char ** str;
4222 int unrestrict;
4224 const struct asm_shift_name * shift;
4225 char * p;
4226 char c;
4228 skip_whitespace (* str);
4230 for (p = * str; ISALPHA (* p); p ++)
4233 if (p == * str)
4235 inst.error = _("Shift expression expected");
4236 return FAIL;
4239 c = * p;
4240 * p = '\0';
4241 shift = (const struct asm_shift_name *) hash_find (arm_shift_hsh, * str);
4242 * p = c;
4244 if (shift == NULL)
4246 inst.error = _("Shift expression expected");
4247 return FAIL;
4250 assert (shift->properties->index == shift_properties[shift->properties->index].index);
4252 if (shift->properties->index == SHIFT_RRX)
4254 * str = p;
4255 inst.instruction |= shift->properties->bit_field;
4256 return SUCCESS;
4259 skip_whitespace (p);
4261 if (unrestrict && reg_required_here (& p, 8) != FAIL)
4263 inst.instruction |= shift->properties->bit_field | SHIFT_BY_REG;
4264 * str = p;
4265 return SUCCESS;
4267 else if (! is_immediate_prefix (* p))
4269 inst.error = (unrestrict
4270 ? _("shift requires register or #expression")
4271 : _("shift requires #expression"));
4272 * str = p;
4273 return FAIL;
4276 inst.error = NULL;
4277 p ++;
4279 if (my_get_expression (& inst.reloc.exp, & p))
4280 return FAIL;
4282 /* Validate some simple #expressions. */
4283 if (inst.reloc.exp.X_op == O_constant)
4285 unsigned num = inst.reloc.exp.X_add_number;
4287 /* Reject operations greater than 32. */
4288 if (num > 32
4289 /* Reject a shift of 0 unless the mode allows it. */
4290 || (num == 0 && shift->properties->allows_0 == 0)
4291 /* Reject a shift of 32 unless the mode allows it. */
4292 || (num == 32 && shift->properties->allows_32 == 0)
4295 /* As a special case we allow a shift of zero for
4296 modes that do not support it to be recoded as an
4297 logical shift left of zero (ie nothing). We warn
4298 about this though. */
4299 if (num == 0)
4301 as_warn (_("Shift of 0 ignored."));
4302 shift = & shift_names[0];
4303 assert (shift->properties->index == SHIFT_LSL);
4305 else
4307 inst.error = _("Invalid immediate shift");
4308 return FAIL;
4312 /* Shifts of 32 are encoded as 0, for those shifts that
4313 support it. */
4314 if (num == 32)
4315 num = 0;
4317 inst.instruction |= (num << 7) | shift->properties->bit_field;
4319 else
4321 inst.reloc.type = BFD_RELOC_ARM_SHIFT_IMM;
4322 inst.reloc.pc_rel = 0;
4323 inst.instruction |= shift->properties->bit_field;
4326 * str = p;
4327 return SUCCESS;
4330 /* Do those data_ops which can take a negative immediate constant
4331 by altering the instuction. A bit of a hack really.
4332 MOV <-> MVN
4333 AND <-> BIC
4334 ADC <-> SBC
4335 by inverting the second operand, and
4336 ADD <-> SUB
4337 CMP <-> CMN
4338 by negating the second operand. */
4340 static int
4341 negate_data_op (instruction, value)
4342 unsigned long * instruction;
4343 unsigned long value;
4345 int op, new_inst;
4346 unsigned long negated, inverted;
4348 negated = validate_immediate (-value);
4349 inverted = validate_immediate (~value);
4351 op = (*instruction >> DATA_OP_SHIFT) & 0xf;
4352 switch (op)
4354 /* First negates. */
4355 case OPCODE_SUB: /* ADD <-> SUB */
4356 new_inst = OPCODE_ADD;
4357 value = negated;
4358 break;
4360 case OPCODE_ADD:
4361 new_inst = OPCODE_SUB;
4362 value = negated;
4363 break;
4365 case OPCODE_CMP: /* CMP <-> CMN */
4366 new_inst = OPCODE_CMN;
4367 value = negated;
4368 break;
4370 case OPCODE_CMN:
4371 new_inst = OPCODE_CMP;
4372 value = negated;
4373 break;
4375 /* Now Inverted ops. */
4376 case OPCODE_MOV: /* MOV <-> MVN */
4377 new_inst = OPCODE_MVN;
4378 value = inverted;
4379 break;
4381 case OPCODE_MVN:
4382 new_inst = OPCODE_MOV;
4383 value = inverted;
4384 break;
4386 case OPCODE_AND: /* AND <-> BIC */
4387 new_inst = OPCODE_BIC;
4388 value = inverted;
4389 break;
4391 case OPCODE_BIC:
4392 new_inst = OPCODE_AND;
4393 value = inverted;
4394 break;
4396 case OPCODE_ADC: /* ADC <-> SBC */
4397 new_inst = OPCODE_SBC;
4398 value = inverted;
4399 break;
4401 case OPCODE_SBC:
4402 new_inst = OPCODE_ADC;
4403 value = inverted;
4404 break;
4406 /* We cannot do anything. */
4407 default:
4408 return FAIL;
4411 if (value == (unsigned) FAIL)
4412 return FAIL;
4414 *instruction &= OPCODE_MASK;
4415 *instruction |= new_inst << DATA_OP_SHIFT;
4416 return value;
4419 static int
4420 data_op2 (str)
4421 char ** str;
4423 int value;
4424 expressionS expr;
4426 skip_whitespace (* str);
4428 if (reg_required_here (str, 0) != FAIL)
4430 if (skip_past_comma (str) == SUCCESS)
4431 /* Shift operation on register. */
4432 return decode_shift (str, NO_SHIFT_RESTRICT);
4434 return SUCCESS;
4436 else
4438 /* Immediate expression. */
4439 if (is_immediate_prefix (**str))
4441 (*str)++;
4442 inst.error = NULL;
4444 if (my_get_expression (&inst.reloc.exp, str))
4445 return FAIL;
4447 if (inst.reloc.exp.X_add_symbol)
4449 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
4450 inst.reloc.pc_rel = 0;
4452 else
4454 if (skip_past_comma (str) == SUCCESS)
4456 /* #x, y -- ie explicit rotation by Y. */
4457 if (my_get_expression (&expr, str))
4458 return FAIL;
4460 if (expr.X_op != O_constant)
4462 inst.error = _("Constant expression expected");
4463 return FAIL;
4466 /* Rotate must be a multiple of 2. */
4467 if (((unsigned) expr.X_add_number) > 30
4468 || (expr.X_add_number & 1) != 0
4469 || ((unsigned) inst.reloc.exp.X_add_number) > 255)
4471 inst.error = _("Invalid constant");
4472 return FAIL;
4474 inst.instruction |= INST_IMMEDIATE;
4475 inst.instruction |= inst.reloc.exp.X_add_number;
4476 inst.instruction |= expr.X_add_number << 7;
4477 return SUCCESS;
4480 /* Implicit rotation, select a suitable one. */
4481 value = validate_immediate (inst.reloc.exp.X_add_number);
4483 if (value == FAIL)
4485 /* Can't be done. Perhaps the code reads something like
4486 "add Rd, Rn, #-n", where "sub Rd, Rn, #n" would be OK. */
4487 if ((value = negate_data_op (&inst.instruction,
4488 inst.reloc.exp.X_add_number))
4489 == FAIL)
4491 inst.error = _("Invalid constant");
4492 return FAIL;
4496 inst.instruction |= value;
4499 inst.instruction |= INST_IMMEDIATE;
4500 return SUCCESS;
4503 (*str)++;
4504 inst.error = _("Register or shift expression expected");
4505 return FAIL;
4509 static int
4510 fp_op2 (str)
4511 char ** str;
4513 skip_whitespace (* str);
4515 if (fp_reg_required_here (str, 0) != FAIL)
4516 return SUCCESS;
4517 else
4519 /* Immediate expression. */
4520 if (*((*str)++) == '#')
4522 int i;
4524 inst.error = NULL;
4526 skip_whitespace (* str);
4528 /* First try and match exact strings, this is to guarantee
4529 that some formats will work even for cross assembly. */
4531 for (i = 0; fp_const[i]; i++)
4533 if (strncmp (*str, fp_const[i], strlen (fp_const[i])) == 0)
4535 char *start = *str;
4537 *str += strlen (fp_const[i]);
4538 if (is_end_of_line[(unsigned char) **str])
4540 inst.instruction |= i + 8;
4541 return SUCCESS;
4543 *str = start;
4547 /* Just because we didn't get a match doesn't mean that the
4548 constant isn't valid, just that it is in a format that we
4549 don't automatically recognize. Try parsing it with
4550 the standard expression routines. */
4551 if ((i = my_get_float_expression (str)) >= 0)
4553 inst.instruction |= i + 8;
4554 return SUCCESS;
4557 inst.error = _("Invalid floating point immediate expression");
4558 return FAIL;
4560 inst.error =
4561 _("Floating point register or immediate expression expected");
4562 return FAIL;
4566 static void
4567 do_arit (str, flags)
4568 char * str;
4569 unsigned long flags;
4571 skip_whitespace (str);
4573 if (reg_required_here (&str, 12) == FAIL
4574 || skip_past_comma (&str) == FAIL
4575 || reg_required_here (&str, 16) == FAIL
4576 || skip_past_comma (&str) == FAIL
4577 || data_op2 (&str) == FAIL)
4579 if (!inst.error)
4580 inst.error = BAD_ARGS;
4581 return;
4584 inst.instruction |= flags;
4585 end_of_line (str);
4586 return;
4589 static void
4590 do_adr (str, flags)
4591 char * str;
4592 unsigned long flags;
4594 /* This is a pseudo-op of the form "adr rd, label" to be converted
4595 into a relative address of the form "add rd, pc, #label-.-8". */
4596 skip_whitespace (str);
4598 if (reg_required_here (&str, 12) == FAIL
4599 || skip_past_comma (&str) == FAIL
4600 || my_get_expression (&inst.reloc.exp, &str))
4602 if (!inst.error)
4603 inst.error = BAD_ARGS;
4604 return;
4607 /* Frag hacking will turn this into a sub instruction if the offset turns
4608 out to be negative. */
4609 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
4610 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust. */
4611 inst.reloc.pc_rel = 1;
4613 end_of_line (str);
4616 static void
4617 do_adrl (str, flags)
4618 char * str;
4619 unsigned long flags;
4621 /* This is a pseudo-op of the form "adrl rd, label" to be converted
4622 into a relative address of the form:
4623 add rd, pc, #low(label-.-8)"
4624 add rd, rd, #high(label-.-8)" */
4626 skip_whitespace (str);
4628 if (reg_required_here (&str, 12) == FAIL
4629 || skip_past_comma (&str) == FAIL
4630 || my_get_expression (&inst.reloc.exp, &str))
4632 if (!inst.error)
4633 inst.error = BAD_ARGS;
4635 return;
4638 end_of_line (str);
4639 /* Frag hacking will turn this into a sub instruction if the offset turns
4640 out to be negative. */
4641 inst.reloc.type = BFD_RELOC_ARM_ADRL_IMMEDIATE;
4642 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust */
4643 inst.reloc.pc_rel = 1;
4644 inst.size = INSN_SIZE * 2;
4646 return;
4649 static void
4650 do_cmp (str, flags)
4651 char * str;
4652 unsigned long flags;
4654 skip_whitespace (str);
4656 if (reg_required_here (&str, 16) == FAIL)
4658 if (!inst.error)
4659 inst.error = BAD_ARGS;
4660 return;
4663 if (skip_past_comma (&str) == FAIL
4664 || data_op2 (&str) == FAIL)
4666 if (!inst.error)
4667 inst.error = BAD_ARGS;
4668 return;
4671 inst.instruction |= flags;
4672 end_of_line (str);
4673 return;
4676 static void
4677 do_mov (str, flags)
4678 char * str;
4679 unsigned long flags;
4681 skip_whitespace (str);
4683 if (reg_required_here (&str, 12) == FAIL)
4685 if (!inst.error)
4686 inst.error = BAD_ARGS;
4687 return;
4690 if (skip_past_comma (&str) == FAIL
4691 || data_op2 (&str) == FAIL)
4693 if (!inst.error)
4694 inst.error = BAD_ARGS;
4695 return;
4698 inst.instruction |= flags;
4699 end_of_line (str);
4700 return;
4703 static int
4704 ldst_extend (str)
4705 char ** str;
4707 int add = INDEX_UP;
4709 switch (**str)
4711 case '#':
4712 case '$':
4713 (*str)++;
4714 if (my_get_expression (& inst.reloc.exp, str))
4715 return FAIL;
4717 if (inst.reloc.exp.X_op == O_constant)
4719 int value = inst.reloc.exp.X_add_number;
4721 if (value < -4095 || value > 4095)
4723 inst.error = _("address offset too large");
4724 return FAIL;
4727 if (value < 0)
4729 value = -value;
4730 add = 0;
4733 inst.instruction |= add | value;
4735 else
4737 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
4738 inst.reloc.pc_rel = 0;
4740 return SUCCESS;
4742 case '-':
4743 add = 0;
4744 /* Fall through. */
4746 case '+':
4747 (*str)++;
4748 /* Fall through. */
4750 default:
4751 if (reg_required_here (str, 0) == FAIL)
4752 return FAIL;
4754 inst.instruction |= add | OFFSET_REG;
4755 if (skip_past_comma (str) == SUCCESS)
4756 return decode_shift (str, SHIFT_RESTRICT);
4758 return SUCCESS;
4762 static void
4763 do_ldst (str, flags)
4764 char * str;
4765 unsigned long flags;
4767 int pre_inc = 0;
4768 int conflict_reg;
4769 int value;
4771 skip_whitespace (str);
4773 if ((conflict_reg = reg_required_here (&str, 12)) == FAIL)
4775 if (!inst.error)
4776 inst.error = BAD_ARGS;
4777 return;
4780 if (skip_past_comma (&str) == FAIL)
4782 inst.error = _("Address expected");
4783 return;
4786 flags = 0;
4788 if (*str == '[')
4790 int reg;
4792 str++;
4794 skip_whitespace (str);
4796 if ((reg = reg_required_here (&str, 16)) == FAIL)
4797 return;
4799 /* Conflicts can occur on stores as well as loads. */
4800 conflict_reg = (conflict_reg == reg);
4802 skip_whitespace (str);
4804 if (*str == ']')
4806 str ++;
4808 if (skip_past_comma (&str) == SUCCESS)
4810 /* [Rn],... (post inc) */
4811 if (ldst_extend (&str) == FAIL)
4812 return;
4813 if (conflict_reg)
4814 as_warn (_("%s register same as write-back base"),
4815 ((inst.instruction & LOAD_BIT)
4816 ? _("destination") : _("source")));
4818 else
4820 /* [Rn] */
4821 skip_whitespace (str);
4823 if (*str == '!')
4825 if (conflict_reg)
4826 as_warn (_("%s register same as write-back base"),
4827 ((inst.instruction & LOAD_BIT)
4828 ? _("destination") : _("source")));
4829 str++;
4830 inst.instruction |= WRITE_BACK;
4833 inst.instruction |= INDEX_UP;
4834 pre_inc = 1;
4837 else
4839 /* [Rn,...] */
4840 if (skip_past_comma (&str) == FAIL)
4842 inst.error = _("pre-indexed expression expected");
4843 return;
4846 pre_inc = 1;
4847 if (ldst_extend (&str) == FAIL)
4848 return;
4850 skip_whitespace (str);
4852 if (*str++ != ']')
4854 inst.error = _("missing ]");
4855 return;
4858 skip_whitespace (str);
4860 if (*str == '!')
4862 if (conflict_reg)
4863 as_warn (_("%s register same as write-back base"),
4864 ((inst.instruction & LOAD_BIT)
4865 ? _("destination") : _("source")));
4866 str++;
4867 inst.instruction |= WRITE_BACK;
4871 else if (*str == '=')
4873 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
4874 str++;
4876 skip_whitespace (str);
4878 if (my_get_expression (&inst.reloc.exp, &str))
4879 return;
4881 if (inst.reloc.exp.X_op != O_constant
4882 && inst.reloc.exp.X_op != O_symbol)
4884 inst.error = _("Constant expression expected");
4885 return;
4888 if (inst.reloc.exp.X_op == O_constant
4889 && (value = validate_immediate (inst.reloc.exp.X_add_number)) != FAIL)
4891 /* This can be done with a mov instruction. */
4892 inst.instruction &= LITERAL_MASK;
4893 inst.instruction |= INST_IMMEDIATE | (OPCODE_MOV << DATA_OP_SHIFT);
4894 inst.instruction |= (value & 0xfff);
4895 end_of_line (str);
4896 return;
4898 else
4900 /* Insert into literal pool. */
4901 if (add_to_lit_pool () == FAIL)
4903 if (!inst.error)
4904 inst.error = _("literal pool insertion failed");
4905 return;
4908 /* Change the instruction exp to point to the pool. */
4909 inst.reloc.type = BFD_RELOC_ARM_LITERAL;
4910 inst.reloc.pc_rel = 1;
4911 inst.instruction |= (REG_PC << 16);
4912 pre_inc = 1;
4915 else
4917 if (my_get_expression (&inst.reloc.exp, &str))
4918 return;
4920 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
4921 #ifndef TE_WINCE
4922 /* PC rel adjust. */
4923 inst.reloc.exp.X_add_number -= 8;
4924 #endif
4925 inst.reloc.pc_rel = 1;
4926 inst.instruction |= (REG_PC << 16);
4927 pre_inc = 1;
4930 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
4931 end_of_line (str);
4932 return;
4935 static void
4936 do_ldstt (str, flags)
4937 char * str;
4938 unsigned long flags;
4940 int conflict_reg;
4942 skip_whitespace (str);
4944 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
4946 if (!inst.error)
4947 inst.error = BAD_ARGS;
4948 return;
4951 if (skip_past_comma (& str) == FAIL)
4953 inst.error = _("Address expected");
4954 return;
4957 if (*str == '[')
4959 int reg;
4961 str++;
4963 skip_whitespace (str);
4965 if ((reg = reg_required_here (&str, 16)) == FAIL)
4966 return;
4968 /* ldrt/strt always use post-indexed addressing, so if the base is
4969 the same as Rd, we warn. */
4970 if (conflict_reg == reg)
4971 as_warn (_("%s register same as write-back base"),
4972 ((inst.instruction & LOAD_BIT)
4973 ? _("destination") : _("source")));
4975 skip_whitespace (str);
4977 if (*str == ']')
4979 str ++;
4981 if (skip_past_comma (&str) == SUCCESS)
4983 /* [Rn],... (post inc) */
4984 if (ldst_extend (&str) == FAIL)
4985 return;
4987 else
4989 /* [Rn] */
4990 skip_whitespace (str);
4992 /* Skip a write-back '!'. */
4993 if (*str == '!')
4994 str++;
4996 inst.instruction |= INDEX_UP;
4999 else
5001 inst.error = _("post-indexed expression expected");
5002 return;
5005 else
5007 inst.error = _("post-indexed expression expected");
5008 return;
5011 end_of_line (str);
5012 return;
5015 static int
5016 ldst_extend_v4 (str)
5017 char ** str;
5019 int add = INDEX_UP;
5021 switch (**str)
5023 case '#':
5024 case '$':
5025 (*str)++;
5026 if (my_get_expression (& inst.reloc.exp, str))
5027 return FAIL;
5029 if (inst.reloc.exp.X_op == O_constant)
5031 int value = inst.reloc.exp.X_add_number;
5033 if (value < -255 || value > 255)
5035 inst.error = _("address offset too large");
5036 return FAIL;
5039 if (value < 0)
5041 value = -value;
5042 add = 0;
5045 /* Halfword and signextension instructions have the
5046 immediate value split across bits 11..8 and bits 3..0. */
5047 inst.instruction |= (add | HWOFFSET_IMM
5048 | ((value >> 4) << 8) | (value & 0xF));
5050 else
5052 inst.instruction |= HWOFFSET_IMM;
5053 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
5054 inst.reloc.pc_rel = 0;
5056 return SUCCESS;
5058 case '-':
5059 add = 0;
5060 /* Fall through. */
5062 case '+':
5063 (*str)++;
5064 /* Fall through. */
5066 default:
5067 if (reg_required_here (str, 0) == FAIL)
5068 return FAIL;
5070 inst.instruction |= add;
5071 return SUCCESS;
5075 /* Halfword and signed-byte load/store operations. */
5076 static void
5077 do_ldstv4 (str, flags)
5078 char * str;
5079 unsigned long flags;
5081 int pre_inc = 0;
5082 int conflict_reg;
5083 int value;
5085 skip_whitespace (str);
5087 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
5089 if (!inst.error)
5090 inst.error = BAD_ARGS;
5091 return;
5094 if (skip_past_comma (& str) == FAIL)
5096 inst.error = _("Address expected");
5097 return;
5100 if (*str == '[')
5102 int reg;
5104 str++;
5106 skip_whitespace (str);
5108 if ((reg = reg_required_here (&str, 16)) == FAIL)
5109 return;
5111 /* Conflicts can occur on stores as well as loads. */
5112 conflict_reg = (conflict_reg == reg);
5114 skip_whitespace (str);
5116 if (*str == ']')
5118 str ++;
5120 if (skip_past_comma (&str) == SUCCESS)
5122 /* [Rn],... (post inc) */
5123 if (ldst_extend_v4 (&str) == FAIL)
5124 return;
5125 if (conflict_reg)
5126 as_warn (_("%s register same as write-back base"),
5127 ((inst.instruction & LOAD_BIT)
5128 ? _("destination") : _("source")));
5130 else
5132 /* [Rn] */
5133 inst.instruction |= HWOFFSET_IMM;
5135 skip_whitespace (str);
5137 if (*str == '!')
5139 if (conflict_reg)
5140 as_warn (_("%s register same as write-back base"),
5141 ((inst.instruction & LOAD_BIT)
5142 ? _("destination") : _("source")));
5143 str++;
5144 inst.instruction |= WRITE_BACK;
5147 inst.instruction |= INDEX_UP;
5148 pre_inc = 1;
5151 else
5153 /* [Rn,...] */
5154 if (skip_past_comma (&str) == FAIL)
5156 inst.error = _("pre-indexed expression expected");
5157 return;
5160 pre_inc = 1;
5161 if (ldst_extend_v4 (&str) == FAIL)
5162 return;
5164 skip_whitespace (str);
5166 if (*str++ != ']')
5168 inst.error = _("missing ]");
5169 return;
5172 skip_whitespace (str);
5174 if (*str == '!')
5176 if (conflict_reg)
5177 as_warn (_("%s register same as write-back base"),
5178 ((inst.instruction & LOAD_BIT)
5179 ? _("destination") : _("source")));
5180 str++;
5181 inst.instruction |= WRITE_BACK;
5185 else if (*str == '=')
5187 /* XXX Does this work correctly for half-word/byte ops? */
5188 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
5189 str++;
5191 skip_whitespace (str);
5193 if (my_get_expression (&inst.reloc.exp, &str))
5194 return;
5196 if (inst.reloc.exp.X_op != O_constant
5197 && inst.reloc.exp.X_op != O_symbol)
5199 inst.error = _("Constant expression expected");
5200 return;
5203 if (inst.reloc.exp.X_op == O_constant)
5205 value = validate_immediate (inst.reloc.exp.X_add_number);
5207 if (value != FAIL)
5209 /* This can be done with a mov instruction. */
5210 inst.instruction &= LITERAL_MASK;
5211 inst.instruction |= INST_IMMEDIATE | (OPCODE_MOV << DATA_OP_SHIFT);
5212 inst.instruction |= value & 0xfff;
5213 end_of_line (str);
5214 return;
5217 value = validate_immediate (~ inst.reloc.exp.X_add_number);
5219 if (value != FAIL)
5221 /* This can be done with a mvn instruction. */
5222 inst.instruction &= LITERAL_MASK;
5223 inst.instruction |= INST_IMMEDIATE | (OPCODE_MVN << DATA_OP_SHIFT);
5224 inst.instruction |= value & 0xfff;
5225 end_of_line (str);
5226 return;
5230 /* Insert into literal pool. */
5231 if (add_to_lit_pool () == FAIL)
5233 if (!inst.error)
5234 inst.error = _("literal pool insertion failed");
5235 return;
5238 /* Change the instruction exp to point to the pool. */
5239 inst.instruction |= HWOFFSET_IMM;
5240 inst.reloc.type = BFD_RELOC_ARM_HWLITERAL;
5241 inst.reloc.pc_rel = 1;
5242 inst.instruction |= (REG_PC << 16);
5243 pre_inc = 1;
5245 else
5247 if (my_get_expression (&inst.reloc.exp, &str))
5248 return;
5250 inst.instruction |= HWOFFSET_IMM;
5251 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
5252 #ifndef TE_WINCE
5253 /* PC rel adjust. */
5254 inst.reloc.exp.X_add_number -= 8;
5255 #endif
5256 inst.reloc.pc_rel = 1;
5257 inst.instruction |= (REG_PC << 16);
5258 pre_inc = 1;
5261 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
5262 end_of_line (str);
5263 return;
5266 static long
5267 reg_list (strp)
5268 char ** strp;
5270 char * str = * strp;
5271 long range = 0;
5272 int another_range;
5274 /* We come back here if we get ranges concatenated by '+' or '|'. */
5277 another_range = 0;
5279 if (*str == '{')
5281 int in_range = 0;
5282 int cur_reg = -1;
5284 str++;
5287 int reg;
5289 skip_whitespace (str);
5291 if ((reg = reg_required_here (& str, -1)) == FAIL)
5292 return FAIL;
5294 if (in_range)
5296 int i;
5298 if (reg <= cur_reg)
5300 inst.error = _("Bad range in register list");
5301 return FAIL;
5304 for (i = cur_reg + 1; i < reg; i++)
5306 if (range & (1 << i))
5307 as_tsktsk
5308 (_("Warning: Duplicated register (r%d) in register list"),
5310 else
5311 range |= 1 << i;
5313 in_range = 0;
5316 if (range & (1 << reg))
5317 as_tsktsk (_("Warning: Duplicated register (r%d) in register list"),
5318 reg);
5319 else if (reg <= cur_reg)
5320 as_tsktsk (_("Warning: Register range not in ascending order"));
5322 range |= 1 << reg;
5323 cur_reg = reg;
5325 while (skip_past_comma (&str) != FAIL
5326 || (in_range = 1, *str++ == '-'));
5327 str--;
5328 skip_whitespace (str);
5330 if (*str++ != '}')
5332 inst.error = _("Missing `}'");
5333 return FAIL;
5336 else
5338 expressionS expr;
5340 if (my_get_expression (&expr, &str))
5341 return FAIL;
5343 if (expr.X_op == O_constant)
5345 if (expr.X_add_number
5346 != (expr.X_add_number & 0x0000ffff))
5348 inst.error = _("invalid register mask");
5349 return FAIL;
5352 if ((range & expr.X_add_number) != 0)
5354 int regno = range & expr.X_add_number;
5356 regno &= -regno;
5357 regno = (1 << regno) - 1;
5358 as_tsktsk
5359 (_("Warning: Duplicated register (r%d) in register list"),
5360 regno);
5363 range |= expr.X_add_number;
5365 else
5367 if (inst.reloc.type != 0)
5369 inst.error = _("expression too complex");
5370 return FAIL;
5373 memcpy (&inst.reloc.exp, &expr, sizeof (expressionS));
5374 inst.reloc.type = BFD_RELOC_ARM_MULTI;
5375 inst.reloc.pc_rel = 0;
5379 skip_whitespace (str);
5381 if (*str == '|' || *str == '+')
5383 str++;
5384 another_range = 1;
5387 while (another_range);
5389 *strp = str;
5390 return range;
5393 static void
5394 do_ldmstm (str, flags)
5395 char * str;
5396 unsigned long flags;
5398 int base_reg;
5399 long range;
5401 skip_whitespace (str);
5403 if ((base_reg = reg_required_here (&str, 16)) == FAIL)
5404 return;
5406 if (base_reg == REG_PC)
5408 inst.error = _("r15 not allowed as base register");
5409 return;
5412 skip_whitespace (str);
5414 if (*str == '!')
5416 inst.instruction |= WRITE_BACK;
5417 str++;
5420 if (skip_past_comma (&str) == FAIL
5421 || (range = reg_list (&str)) == FAIL)
5423 if (! inst.error)
5424 inst.error = BAD_ARGS;
5425 return;
5428 if (*str == '^')
5430 str++;
5431 inst.instruction |= LDM_TYPE_2_OR_3;
5434 inst.instruction |= flags | range;
5435 end_of_line (str);
5436 return;
5439 static void
5440 do_swi (str, flags)
5441 char * str;
5442 unsigned long flags;
5444 skip_whitespace (str);
5446 /* Allow optional leading '#'. */
5447 if (is_immediate_prefix (*str))
5448 str++;
5450 if (my_get_expression (& inst.reloc.exp, & str))
5451 return;
5453 inst.reloc.type = BFD_RELOC_ARM_SWI;
5454 inst.reloc.pc_rel = 0;
5455 inst.instruction |= flags;
5457 end_of_line (str);
5459 return;
5462 static void
5463 do_swap (str, flags)
5464 char * str;
5465 unsigned long flags;
5467 int reg;
5469 skip_whitespace (str);
5471 if ((reg = reg_required_here (&str, 12)) == FAIL)
5472 return;
5474 if (reg == REG_PC)
5476 inst.error = _("r15 not allowed in swap");
5477 return;
5480 if (skip_past_comma (&str) == FAIL
5481 || (reg = reg_required_here (&str, 0)) == FAIL)
5483 if (!inst.error)
5484 inst.error = BAD_ARGS;
5485 return;
5488 if (reg == REG_PC)
5490 inst.error = _("r15 not allowed in swap");
5491 return;
5494 if (skip_past_comma (&str) == FAIL
5495 || *str++ != '[')
5497 inst.error = BAD_ARGS;
5498 return;
5501 skip_whitespace (str);
5503 if ((reg = reg_required_here (&str, 16)) == FAIL)
5504 return;
5506 if (reg == REG_PC)
5508 inst.error = BAD_PC;
5509 return;
5512 skip_whitespace (str);
5514 if (*str++ != ']')
5516 inst.error = _("missing ]");
5517 return;
5520 inst.instruction |= flags;
5521 end_of_line (str);
5522 return;
5525 static void
5526 do_branch (str, flags)
5527 char * str;
5528 unsigned long flags ATTRIBUTE_UNUSED;
5530 if (my_get_expression (&inst.reloc.exp, &str))
5531 return;
5533 #ifdef OBJ_ELF
5535 char * save_in;
5537 /* ScottB: February 5, 1998 - Check to see of PLT32 reloc
5538 required for the instruction. */
5540 /* arm_parse_reloc () works on input_line_pointer.
5541 We actually want to parse the operands to the branch instruction
5542 passed in 'str'. Save the input pointer and restore it later. */
5543 save_in = input_line_pointer;
5544 input_line_pointer = str;
5545 if (inst.reloc.exp.X_op == O_symbol
5546 && *str == '('
5547 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
5549 inst.reloc.type = BFD_RELOC_ARM_PLT32;
5550 inst.reloc.pc_rel = 0;
5551 /* Modify str to point to after parsed operands, otherwise
5552 end_of_line() will complain about the (PLT) left in str. */
5553 str = input_line_pointer;
5555 else
5557 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
5558 inst.reloc.pc_rel = 1;
5560 input_line_pointer = save_in;
5562 #else
5563 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
5564 inst.reloc.pc_rel = 1;
5565 #endif /* OBJ_ELF */
5567 end_of_line (str);
5568 return;
5571 static void
5572 do_bx (str, flags)
5573 char * str;
5574 unsigned long flags ATTRIBUTE_UNUSED;
5576 int reg;
5578 skip_whitespace (str);
5580 if ((reg = reg_required_here (&str, 0)) == FAIL)
5582 inst.error = BAD_ARGS;
5583 return;
5586 /* Note - it is not illegal to do a "bx pc". Useless, but not illegal. */
5587 if (reg == REG_PC)
5588 as_tsktsk (_("Use of r15 in bx in ARM mode is not really useful"));
5590 end_of_line (str);
5593 static void
5594 do_cdp (str, flags)
5595 char * str;
5596 unsigned long flags ATTRIBUTE_UNUSED;
5598 /* Co-processor data operation.
5599 Format: CDP{cond} CP#,<expr>,CRd,CRn,CRm{,<expr>} */
5600 skip_whitespace (str);
5602 if (co_proc_number (&str) == FAIL)
5604 if (!inst.error)
5605 inst.error = BAD_ARGS;
5606 return;
5609 if (skip_past_comma (&str) == FAIL
5610 || cp_opc_expr (&str, 20,4) == FAIL)
5612 if (!inst.error)
5613 inst.error = BAD_ARGS;
5614 return;
5617 if (skip_past_comma (&str) == FAIL
5618 || cp_reg_required_here (&str, 12) == FAIL)
5620 if (!inst.error)
5621 inst.error = BAD_ARGS;
5622 return;
5625 if (skip_past_comma (&str) == FAIL
5626 || cp_reg_required_here (&str, 16) == FAIL)
5628 if (!inst.error)
5629 inst.error = BAD_ARGS;
5630 return;
5633 if (skip_past_comma (&str) == FAIL
5634 || cp_reg_required_here (&str, 0) == FAIL)
5636 if (!inst.error)
5637 inst.error = BAD_ARGS;
5638 return;
5641 if (skip_past_comma (&str) == SUCCESS)
5643 if (cp_opc_expr (&str, 5, 3) == FAIL)
5645 if (!inst.error)
5646 inst.error = BAD_ARGS;
5647 return;
5651 end_of_line (str);
5652 return;
5655 static void
5656 do_lstc (str, flags)
5657 char * str;
5658 unsigned long flags;
5660 /* Co-processor register load/store.
5661 Format: <LDC|STC{cond}[L] CP#,CRd,<address> */
5663 skip_whitespace (str);
5665 if (co_proc_number (&str) == FAIL)
5667 if (!inst.error)
5668 inst.error = BAD_ARGS;
5669 return;
5672 if (skip_past_comma (&str) == FAIL
5673 || cp_reg_required_here (&str, 12) == FAIL)
5675 if (!inst.error)
5676 inst.error = BAD_ARGS;
5677 return;
5680 if (skip_past_comma (&str) == FAIL
5681 || cp_address_required_here (&str) == FAIL)
5683 if (! inst.error)
5684 inst.error = BAD_ARGS;
5685 return;
5688 inst.instruction |= flags;
5689 end_of_line (str);
5690 return;
5693 static void
5694 do_co_reg (str, flags)
5695 char * str;
5696 unsigned long flags;
5698 /* Co-processor register transfer.
5699 Format: <MCR|MRC>{cond} CP#,<expr1>,Rd,CRn,CRm{,<expr2>} */
5701 skip_whitespace (str);
5703 if (co_proc_number (&str) == FAIL)
5705 if (!inst.error)
5706 inst.error = BAD_ARGS;
5707 return;
5710 if (skip_past_comma (&str) == FAIL
5711 || cp_opc_expr (&str, 21, 3) == FAIL)
5713 if (!inst.error)
5714 inst.error = BAD_ARGS;
5715 return;
5718 if (skip_past_comma (&str) == FAIL
5719 || reg_required_here (&str, 12) == FAIL)
5721 if (!inst.error)
5722 inst.error = BAD_ARGS;
5723 return;
5726 if (skip_past_comma (&str) == FAIL
5727 || cp_reg_required_here (&str, 16) == FAIL)
5729 if (!inst.error)
5730 inst.error = BAD_ARGS;
5731 return;
5734 if (skip_past_comma (&str) == FAIL
5735 || cp_reg_required_here (&str, 0) == FAIL)
5737 if (!inst.error)
5738 inst.error = BAD_ARGS;
5739 return;
5742 if (skip_past_comma (&str) == SUCCESS)
5744 if (cp_opc_expr (&str, 5, 3) == FAIL)
5746 if (!inst.error)
5747 inst.error = BAD_ARGS;
5748 return;
5751 if (flags)
5753 inst.error = BAD_COND;
5756 end_of_line (str);
5757 return;
5760 static void
5761 do_fpa_ctrl (str, flags)
5762 char * str;
5763 unsigned long flags ATTRIBUTE_UNUSED;
5765 /* FP control registers.
5766 Format: <WFS|RFS|WFC|RFC>{cond} Rn */
5768 skip_whitespace (str);
5770 if (reg_required_here (&str, 12) == FAIL)
5772 if (!inst.error)
5773 inst.error = BAD_ARGS;
5774 return;
5777 end_of_line (str);
5778 return;
5781 static void
5782 do_fpa_ldst (str, flags)
5783 char * str;
5784 unsigned long flags ATTRIBUTE_UNUSED;
5786 skip_whitespace (str);
5788 if (fp_reg_required_here (&str, 12) == FAIL)
5790 if (!inst.error)
5791 inst.error = BAD_ARGS;
5792 return;
5795 if (skip_past_comma (&str) == FAIL
5796 || cp_address_required_here (&str) == FAIL)
5798 if (!inst.error)
5799 inst.error = BAD_ARGS;
5800 return;
5803 end_of_line (str);
5806 static void
5807 do_fpa_ldmstm (str, flags)
5808 char * str;
5809 unsigned long flags;
5811 int num_regs;
5813 skip_whitespace (str);
5815 if (fp_reg_required_here (&str, 12) == FAIL)
5817 if (! inst.error)
5818 inst.error = BAD_ARGS;
5819 return;
5822 /* Get Number of registers to transfer. */
5823 if (skip_past_comma (&str) == FAIL
5824 || my_get_expression (&inst.reloc.exp, &str))
5826 if (! inst.error)
5827 inst.error = _("constant expression expected");
5828 return;
5831 if (inst.reloc.exp.X_op != O_constant)
5833 inst.error = _("Constant value required for number of registers");
5834 return;
5837 num_regs = inst.reloc.exp.X_add_number;
5839 if (num_regs < 1 || num_regs > 4)
5841 inst.error = _("number of registers must be in the range [1:4]");
5842 return;
5845 switch (num_regs)
5847 case 1:
5848 inst.instruction |= CP_T_X;
5849 break;
5850 case 2:
5851 inst.instruction |= CP_T_Y;
5852 break;
5853 case 3:
5854 inst.instruction |= CP_T_Y | CP_T_X;
5855 break;
5856 case 4:
5857 break;
5858 default:
5859 abort ();
5862 if (inst.instruction & (CP_T_Pre | CP_T_UD)) /* ed/fd format. */
5864 int reg;
5865 int write_back;
5866 int offset;
5868 /* The instruction specified "ea" or "fd", so we can only accept
5869 [Rn]{!}. The instruction does not really support stacking or
5870 unstacking, so we have to emulate these by setting appropriate
5871 bits and offsets. */
5872 if (skip_past_comma (&str) == FAIL
5873 || *str != '[')
5875 if (! inst.error)
5876 inst.error = BAD_ARGS;
5877 return;
5880 str++;
5881 skip_whitespace (str);
5883 if ((reg = reg_required_here (&str, 16)) == FAIL)
5884 return;
5886 skip_whitespace (str);
5888 if (*str != ']')
5890 inst.error = BAD_ARGS;
5891 return;
5894 str++;
5895 if (*str == '!')
5897 write_back = 1;
5898 str++;
5899 if (reg == REG_PC)
5901 inst.error =
5902 _("R15 not allowed as base register with write-back");
5903 return;
5906 else
5907 write_back = 0;
5909 if (inst.instruction & CP_T_Pre)
5911 /* Pre-decrement. */
5912 offset = 3 * num_regs;
5913 if (write_back)
5914 inst.instruction |= CP_T_WB;
5916 else
5918 /* Post-increment. */
5919 if (write_back)
5921 inst.instruction |= CP_T_WB;
5922 offset = 3 * num_regs;
5924 else
5926 /* No write-back, so convert this into a standard pre-increment
5927 instruction -- aesthetically more pleasing. */
5928 inst.instruction |= CP_T_Pre | CP_T_UD;
5929 offset = 0;
5933 inst.instruction |= flags | offset;
5935 else if (skip_past_comma (&str) == FAIL
5936 || cp_address_required_here (&str) == FAIL)
5938 if (! inst.error)
5939 inst.error = BAD_ARGS;
5940 return;
5943 end_of_line (str);
5946 static void
5947 do_fpa_dyadic (str, flags)
5948 char * str;
5949 unsigned long flags;
5951 skip_whitespace (str);
5953 if (fp_reg_required_here (&str, 12) == FAIL)
5955 if (! inst.error)
5956 inst.error = BAD_ARGS;
5957 return;
5960 if (skip_past_comma (&str) == FAIL
5961 || fp_reg_required_here (&str, 16) == FAIL)
5963 if (! inst.error)
5964 inst.error = BAD_ARGS;
5965 return;
5968 if (skip_past_comma (&str) == FAIL
5969 || fp_op2 (&str) == FAIL)
5971 if (! inst.error)
5972 inst.error = BAD_ARGS;
5973 return;
5976 inst.instruction |= flags;
5977 end_of_line (str);
5978 return;
5981 static void
5982 do_fpa_monadic (str, flags)
5983 char * str;
5984 unsigned long flags;
5986 skip_whitespace (str);
5988 if (fp_reg_required_here (&str, 12) == FAIL)
5990 if (! inst.error)
5991 inst.error = BAD_ARGS;
5992 return;
5995 if (skip_past_comma (&str) == FAIL
5996 || fp_op2 (&str) == FAIL)
5998 if (! inst.error)
5999 inst.error = BAD_ARGS;
6000 return;
6003 inst.instruction |= flags;
6004 end_of_line (str);
6005 return;
6008 static void
6009 do_fpa_cmp (str, flags)
6010 char * str;
6011 unsigned long flags;
6013 skip_whitespace (str);
6015 if (fp_reg_required_here (&str, 16) == FAIL)
6017 if (! inst.error)
6018 inst.error = BAD_ARGS;
6019 return;
6022 if (skip_past_comma (&str) == FAIL
6023 || fp_op2 (&str) == FAIL)
6025 if (! inst.error)
6026 inst.error = BAD_ARGS;
6027 return;
6030 inst.instruction |= flags;
6031 end_of_line (str);
6032 return;
6035 static void
6036 do_fpa_from_reg (str, flags)
6037 char * str;
6038 unsigned long flags;
6040 skip_whitespace (str);
6042 if (fp_reg_required_here (&str, 16) == FAIL)
6044 if (! inst.error)
6045 inst.error = BAD_ARGS;
6046 return;
6049 if (skip_past_comma (&str) == FAIL
6050 || reg_required_here (&str, 12) == FAIL)
6052 if (! inst.error)
6053 inst.error = BAD_ARGS;
6054 return;
6057 inst.instruction |= flags;
6058 end_of_line (str);
6059 return;
6062 static void
6063 do_fpa_to_reg (str, flags)
6064 char * str;
6065 unsigned long flags;
6067 skip_whitespace (str);
6069 if (reg_required_here (&str, 12) == FAIL)
6070 return;
6072 if (skip_past_comma (&str) == FAIL
6073 || fp_reg_required_here (&str, 0) == FAIL)
6075 if (! inst.error)
6076 inst.error = BAD_ARGS;
6077 return;
6080 inst.instruction |= flags;
6081 end_of_line (str);
6082 return;
6085 /* Thumb specific routines. */
6087 /* Parse and validate that a register is of the right form, this saves
6088 repeated checking of this information in many similar cases.
6089 Unlike the 32-bit case we do not insert the register into the opcode
6090 here, since the position is often unknown until the full instruction
6091 has been parsed. */
6093 static int
6094 thumb_reg (strp, hi_lo)
6095 char ** strp;
6096 int hi_lo;
6098 int reg;
6100 if ((reg = reg_required_here (strp, -1)) == FAIL)
6101 return FAIL;
6103 switch (hi_lo)
6105 case THUMB_REG_LO:
6106 if (reg > 7)
6108 inst.error = _("lo register required");
6109 return FAIL;
6111 break;
6113 case THUMB_REG_HI:
6114 if (reg < 8)
6116 inst.error = _("hi register required");
6117 return FAIL;
6119 break;
6121 default:
6122 break;
6125 return reg;
6128 /* Parse an add or subtract instruction, SUBTRACT is non-zero if the opcode
6129 was SUB. */
6131 static void
6132 thumb_add_sub (str, subtract)
6133 char * str;
6134 int subtract;
6136 int Rd, Rs, Rn = FAIL;
6138 skip_whitespace (str);
6140 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
6141 || skip_past_comma (&str) == FAIL)
6143 if (! inst.error)
6144 inst.error = BAD_ARGS;
6145 return;
6148 if (is_immediate_prefix (*str))
6150 Rs = Rd;
6151 str++;
6152 if (my_get_expression (&inst.reloc.exp, &str))
6153 return;
6155 else
6157 if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
6158 return;
6160 if (skip_past_comma (&str) == FAIL)
6162 /* Two operand format, shuffle the registers
6163 and pretend there are 3. */
6164 Rn = Rs;
6165 Rs = Rd;
6167 else if (is_immediate_prefix (*str))
6169 str++;
6170 if (my_get_expression (&inst.reloc.exp, &str))
6171 return;
6173 else if ((Rn = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
6174 return;
6177 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
6178 for the latter case, EXPR contains the immediate that was found. */
6179 if (Rn != FAIL)
6181 /* All register format. */
6182 if (Rd > 7 || Rs > 7 || Rn > 7)
6184 if (Rs != Rd)
6186 inst.error = _("dest and source1 must be the same register");
6187 return;
6190 /* Can't do this for SUB. */
6191 if (subtract)
6193 inst.error = _("subtract valid only on lo regs");
6194 return;
6197 inst.instruction = (T_OPCODE_ADD_HI
6198 | (Rd > 7 ? THUMB_H1 : 0)
6199 | (Rn > 7 ? THUMB_H2 : 0));
6200 inst.instruction |= (Rd & 7) | ((Rn & 7) << 3);
6202 else
6204 inst.instruction = subtract ? T_OPCODE_SUB_R3 : T_OPCODE_ADD_R3;
6205 inst.instruction |= Rd | (Rs << 3) | (Rn << 6);
6208 else
6210 /* Immediate expression, now things start to get nasty. */
6212 /* First deal with HI regs, only very restricted cases allowed:
6213 Adjusting SP, and using PC or SP to get an address. */
6214 if ((Rd > 7 && (Rd != REG_SP || Rs != REG_SP))
6215 || (Rs > 7 && Rs != REG_SP && Rs != REG_PC))
6217 inst.error = _("invalid Hi register with immediate");
6218 return;
6221 if (inst.reloc.exp.X_op != O_constant)
6223 /* Value isn't known yet, all we can do is store all the fragments
6224 we know about in the instruction and let the reloc hacking
6225 work it all out. */
6226 inst.instruction = (subtract ? 0x8000 : 0) | (Rd << 4) | Rs;
6227 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
6229 else
6231 int offset = inst.reloc.exp.X_add_number;
6233 if (subtract)
6234 offset = -offset;
6236 if (offset < 0)
6238 offset = -offset;
6239 subtract = 1;
6241 /* Quick check, in case offset is MIN_INT. */
6242 if (offset < 0)
6244 inst.error = _("immediate value out of range");
6245 return;
6248 else
6249 subtract = 0;
6251 if (Rd == REG_SP)
6253 if (offset & ~0x1fc)
6255 inst.error = _("invalid immediate value for stack adjust");
6256 return;
6258 inst.instruction = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
6259 inst.instruction |= offset >> 2;
6261 else if (Rs == REG_PC || Rs == REG_SP)
6263 if (subtract
6264 || (offset & ~0x3fc))
6266 inst.error = _("invalid immediate for address calculation");
6267 return;
6269 inst.instruction = (Rs == REG_PC ? T_OPCODE_ADD_PC
6270 : T_OPCODE_ADD_SP);
6271 inst.instruction |= (Rd << 8) | (offset >> 2);
6273 else if (Rs == Rd)
6275 if (offset & ~0xff)
6277 inst.error = _("immediate value out of range");
6278 return;
6280 inst.instruction = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
6281 inst.instruction |= (Rd << 8) | offset;
6283 else
6285 if (offset & ~0x7)
6287 inst.error = _("immediate value out of range");
6288 return;
6290 inst.instruction = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
6291 inst.instruction |= Rd | (Rs << 3) | (offset << 6);
6296 end_of_line (str);
6299 static void
6300 thumb_shift (str, shift)
6301 char * str;
6302 int shift;
6304 int Rd, Rs, Rn = FAIL;
6306 skip_whitespace (str);
6308 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
6309 || skip_past_comma (&str) == FAIL)
6311 if (! inst.error)
6312 inst.error = BAD_ARGS;
6313 return;
6316 if (is_immediate_prefix (*str))
6318 /* Two operand immediate format, set Rs to Rd. */
6319 Rs = Rd;
6320 str ++;
6321 if (my_get_expression (&inst.reloc.exp, &str))
6322 return;
6324 else
6326 if ((Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
6327 return;
6329 if (skip_past_comma (&str) == FAIL)
6331 /* Two operand format, shuffle the registers
6332 and pretend there are 3. */
6333 Rn = Rs;
6334 Rs = Rd;
6336 else if (is_immediate_prefix (*str))
6338 str++;
6339 if (my_get_expression (&inst.reloc.exp, &str))
6340 return;
6342 else if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
6343 return;
6346 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
6347 for the latter case, EXPR contains the immediate that was found. */
6349 if (Rn != FAIL)
6351 if (Rs != Rd)
6353 inst.error = _("source1 and dest must be same register");
6354 return;
6357 switch (shift)
6359 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_R; break;
6360 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_R; break;
6361 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_R; break;
6364 inst.instruction |= Rd | (Rn << 3);
6366 else
6368 switch (shift)
6370 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_I; break;
6371 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_I; break;
6372 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_I; break;
6375 if (inst.reloc.exp.X_op != O_constant)
6377 /* Value isn't known yet, create a dummy reloc and let reloc
6378 hacking fix it up. */
6379 inst.reloc.type = BFD_RELOC_ARM_THUMB_SHIFT;
6381 else
6383 unsigned shift_value = inst.reloc.exp.X_add_number;
6385 if (shift_value > 32 || (shift_value == 32 && shift == THUMB_LSL))
6387 inst.error = _("Invalid immediate for shift");
6388 return;
6391 /* Shifts of zero are handled by converting to LSL. */
6392 if (shift_value == 0)
6393 inst.instruction = T_OPCODE_LSL_I;
6395 /* Shifts of 32 are encoded as a shift of zero. */
6396 if (shift_value == 32)
6397 shift_value = 0;
6399 inst.instruction |= shift_value << 6;
6402 inst.instruction |= Rd | (Rs << 3);
6405 end_of_line (str);
6408 static void
6409 thumb_mov_compare (str, move)
6410 char * str;
6411 int move;
6413 int Rd, Rs = FAIL;
6415 skip_whitespace (str);
6417 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
6418 || skip_past_comma (&str) == FAIL)
6420 if (! inst.error)
6421 inst.error = BAD_ARGS;
6422 return;
6425 if (is_immediate_prefix (*str))
6427 str++;
6428 if (my_get_expression (&inst.reloc.exp, &str))
6429 return;
6431 else if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
6432 return;
6434 if (Rs != FAIL)
6436 if (Rs < 8 && Rd < 8)
6438 if (move == THUMB_MOVE)
6439 /* A move of two lowregs is encoded as ADD Rd, Rs, #0
6440 since a MOV instruction produces unpredictable results. */
6441 inst.instruction = T_OPCODE_ADD_I3;
6442 else
6443 inst.instruction = T_OPCODE_CMP_LR;
6444 inst.instruction |= Rd | (Rs << 3);
6446 else
6448 if (move == THUMB_MOVE)
6449 inst.instruction = T_OPCODE_MOV_HR;
6450 else
6451 inst.instruction = T_OPCODE_CMP_HR;
6453 if (Rd > 7)
6454 inst.instruction |= THUMB_H1;
6456 if (Rs > 7)
6457 inst.instruction |= THUMB_H2;
6459 inst.instruction |= (Rd & 7) | ((Rs & 7) << 3);
6462 else
6464 if (Rd > 7)
6466 inst.error = _("only lo regs allowed with immediate");
6467 return;
6470 if (move == THUMB_MOVE)
6471 inst.instruction = T_OPCODE_MOV_I8;
6472 else
6473 inst.instruction = T_OPCODE_CMP_I8;
6475 inst.instruction |= Rd << 8;
6477 if (inst.reloc.exp.X_op != O_constant)
6478 inst.reloc.type = BFD_RELOC_ARM_THUMB_IMM;
6479 else
6481 unsigned value = inst.reloc.exp.X_add_number;
6483 if (value > 255)
6485 inst.error = _("invalid immediate");
6486 return;
6489 inst.instruction |= value;
6493 end_of_line (str);
6496 static void
6497 thumb_load_store (str, load_store, size)
6498 char * str;
6499 int load_store;
6500 int size;
6502 int Rd, Rb, Ro = FAIL;
6504 skip_whitespace (str);
6506 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
6507 || skip_past_comma (&str) == FAIL)
6509 if (! inst.error)
6510 inst.error = BAD_ARGS;
6511 return;
6514 if (*str == '[')
6516 str++;
6517 if ((Rb = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
6518 return;
6520 if (skip_past_comma (&str) != FAIL)
6522 if (is_immediate_prefix (*str))
6524 str++;
6525 if (my_get_expression (&inst.reloc.exp, &str))
6526 return;
6528 else if ((Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
6529 return;
6531 else
6533 inst.reloc.exp.X_op = O_constant;
6534 inst.reloc.exp.X_add_number = 0;
6537 if (*str != ']')
6539 inst.error = _("expected ']'");
6540 return;
6542 str++;
6544 else if (*str == '=')
6546 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
6547 str++;
6549 skip_whitespace (str);
6551 if (my_get_expression (& inst.reloc.exp, & str))
6552 return;
6554 end_of_line (str);
6556 if ( inst.reloc.exp.X_op != O_constant
6557 && inst.reloc.exp.X_op != O_symbol)
6559 inst.error = "Constant expression expected";
6560 return;
6563 if (inst.reloc.exp.X_op == O_constant
6564 && ((inst.reloc.exp.X_add_number & ~0xFF) == 0))
6566 /* This can be done with a mov instruction. */
6568 inst.instruction = T_OPCODE_MOV_I8 | (Rd << 8);
6569 inst.instruction |= inst.reloc.exp.X_add_number;
6570 return;
6573 /* Insert into literal pool. */
6574 if (add_to_lit_pool () == FAIL)
6576 if (!inst.error)
6577 inst.error = "literal pool insertion failed";
6578 return;
6581 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
6582 inst.reloc.pc_rel = 1;
6583 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
6584 /* Adjust ARM pipeline offset to Thumb. */
6585 inst.reloc.exp.X_add_number += 4;
6587 return;
6589 else
6591 if (my_get_expression (&inst.reloc.exp, &str))
6592 return;
6594 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
6595 inst.reloc.pc_rel = 1;
6596 inst.reloc.exp.X_add_number -= 4; /* Pipeline offset. */
6597 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
6598 end_of_line (str);
6599 return;
6602 if (Rb == REG_PC || Rb == REG_SP)
6604 if (size != THUMB_WORD)
6606 inst.error = _("byte or halfword not valid for base register");
6607 return;
6609 else if (Rb == REG_PC && load_store != THUMB_LOAD)
6611 inst.error = _("R15 based store not allowed");
6612 return;
6614 else if (Ro != FAIL)
6616 inst.error = _("Invalid base register for register offset");
6617 return;
6620 if (Rb == REG_PC)
6621 inst.instruction = T_OPCODE_LDR_PC;
6622 else if (load_store == THUMB_LOAD)
6623 inst.instruction = T_OPCODE_LDR_SP;
6624 else
6625 inst.instruction = T_OPCODE_STR_SP;
6627 inst.instruction |= Rd << 8;
6628 if (inst.reloc.exp.X_op == O_constant)
6630 unsigned offset = inst.reloc.exp.X_add_number;
6632 if (offset & ~0x3fc)
6634 inst.error = _("invalid offset");
6635 return;
6638 inst.instruction |= offset >> 2;
6640 else
6641 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
6643 else if (Rb > 7)
6645 inst.error = _("invalid base register in load/store");
6646 return;
6648 else if (Ro == FAIL)
6650 /* Immediate offset. */
6651 if (size == THUMB_WORD)
6652 inst.instruction = (load_store == THUMB_LOAD
6653 ? T_OPCODE_LDR_IW : T_OPCODE_STR_IW);
6654 else if (size == THUMB_HALFWORD)
6655 inst.instruction = (load_store == THUMB_LOAD
6656 ? T_OPCODE_LDR_IH : T_OPCODE_STR_IH);
6657 else
6658 inst.instruction = (load_store == THUMB_LOAD
6659 ? T_OPCODE_LDR_IB : T_OPCODE_STR_IB);
6661 inst.instruction |= Rd | (Rb << 3);
6663 if (inst.reloc.exp.X_op == O_constant)
6665 unsigned offset = inst.reloc.exp.X_add_number;
6667 if (offset & ~(0x1f << size))
6669 inst.error = _("Invalid offset");
6670 return;
6672 inst.instruction |= (offset >> size) << 6;
6674 else
6675 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
6677 else
6679 /* Register offset. */
6680 if (size == THUMB_WORD)
6681 inst.instruction = (load_store == THUMB_LOAD
6682 ? T_OPCODE_LDR_RW : T_OPCODE_STR_RW);
6683 else if (size == THUMB_HALFWORD)
6684 inst.instruction = (load_store == THUMB_LOAD
6685 ? T_OPCODE_LDR_RH : T_OPCODE_STR_RH);
6686 else
6687 inst.instruction = (load_store == THUMB_LOAD
6688 ? T_OPCODE_LDR_RB : T_OPCODE_STR_RB);
6690 inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
6693 end_of_line (str);
6696 /* Given a register and a register type, return 1 if
6697 the register is of the given type, else return 0. */
6699 static int
6700 cirrus_valid_reg (reg, regtype)
6701 int reg;
6702 enum cirrus_regtype regtype;
6704 switch (regtype)
6706 case CIRRUS_REGTYPE_ANY:
6707 return 1;
6709 case CIRRUS_REGTYPE_MVF:
6710 return cirrus_mvf_register (reg);
6712 case CIRRUS_REGTYPE_MVFX:
6713 return cirrus_mvfx_register (reg);
6715 case CIRRUS_REGTYPE_MVD:
6716 return cirrus_mvd_register (reg);
6718 case CIRRUS_REGTYPE_MVDX:
6719 return cirrus_mvdx_register (reg);
6721 case CIRRUS_REGTYPE_MVAX:
6722 return cirrus_mvax_register (reg);
6724 case CIRRUS_REGTYPE_DSPSC:
6725 return ARM_EXT_MAVERICKsc_register (reg);
6728 return 0;
6731 /* A register must be given at this point.
6733 If the register is a Cirrus register, convert it's reg# appropriately.
6735 Shift is the place to put it in inst.instruction.
6737 regtype is type register type expected, and is:
6738 CIRRUS_REGTYPE_MVF
6739 CIRRUS_REGTYPE_MVFX
6740 CIRRUS_REGTYPE_MVD
6741 CIRRUS_REGTYPE_MVDX
6742 CIRRUS_REGTYPE_MVAX
6743 CIRRUS_REGTYPE_DSPSC
6745 Restores input start point on err.
6746 Returns the reg#, or FAIL. */
6748 static int
6749 cirrus_reg_required_here (str, shift, regtype)
6750 char ** str;
6751 int shift;
6752 enum cirrus_regtype regtype;
6754 static char buff [135]; /* XXX */
6755 int reg;
6756 char * start = * str;
6758 if ((reg = arm_reg_parse (str)) != FAIL
6759 && (int_register (reg)
6760 || cirrus_register (reg)))
6762 int orig_reg = reg;
6764 /* Calculate actual register # for opcode. */
6765 if (cirrus_register (reg)
6766 && !ARM_EXT_MAVERICKsc_register (reg)) /* Leave this one as is. */
6768 if (reg >= 130)
6769 reg -= 130;
6770 else if (reg >= 110)
6771 reg -= 110;
6772 else if (reg >= 90)
6773 reg -= 90;
6774 else if (reg >= 70)
6775 reg -= 70;
6776 else if (reg >= 50)
6777 reg -= 50;
6780 if (!cirrus_valid_reg (orig_reg, regtype))
6782 sprintf (buff, _("invalid register type at '%.100s'"), start);
6783 inst.error = buff;
6784 return FAIL;
6787 if (shift >= 0)
6788 inst.instruction |= reg << shift;
6790 return orig_reg;
6793 /* Restore the start point, we may have got a reg of the wrong class. */
6794 *str = start;
6796 /* In the few cases where we might be able to accept something else
6797 this error can be overridden. */
6798 sprintf (buff, _("Cirrus register expected, not '%.100s'"), start);
6799 inst.error = buff;
6801 return FAIL;
6804 /* Cirrus Instructions. */
6806 /* Wrapper functions. */
6808 static void
6809 do_c_binops_1 (str, flags)
6810 char * str;
6811 unsigned long flags;
6813 do_c_binops (str, flags, CIRRUS_MODE1);
6816 static void
6817 do_c_binops_2 (str, flags)
6818 char * str;
6819 unsigned long flags;
6821 do_c_binops (str, flags, CIRRUS_MODE2);
6824 static void
6825 do_c_binops_3 (str, flags)
6826 char * str;
6827 unsigned long flags;
6829 do_c_binops (str, flags, CIRRUS_MODE3);
6832 static void
6833 do_c_triple_4 (str, flags)
6834 char * str;
6835 unsigned long flags;
6837 do_c_triple (str, flags, CIRRUS_MODE4);
6840 static void
6841 do_c_triple_5 (str, flags)
6842 char * str;
6843 unsigned long flags;
6845 do_c_triple (str, flags, CIRRUS_MODE5);
6848 static void
6849 do_c_quad_6 (str, flags)
6850 char * str;
6851 unsigned long flags;
6853 do_c_quad (str, flags, CIRRUS_MODE6);
6856 static void
6857 do_c_dspsc_1 (str, flags)
6858 char * str;
6859 unsigned long flags;
6861 do_c_dspsc (str, flags, CIRRUS_MODE1);
6864 static void
6865 do_c_dspsc_2 (str, flags)
6866 char * str;
6867 unsigned long flags;
6869 do_c_dspsc (str, flags, CIRRUS_MODE2);
6872 static void
6873 do_c_shift_1 (str, flags)
6874 char * str;
6875 unsigned long flags;
6877 do_c_shift (str, flags, CIRRUS_MODE1);
6880 static void
6881 do_c_shift_2 (str, flags)
6882 char * str;
6883 unsigned long flags;
6885 do_c_shift (str, flags, CIRRUS_MODE2);
6888 static void
6889 do_c_ldst_1 (str, flags)
6890 char * str;
6891 unsigned long flags;
6893 do_c_ldst (str, flags, CIRRUS_MODE1);
6896 static void
6897 do_c_ldst_2 (str, flags)
6898 char * str;
6899 unsigned long flags;
6901 do_c_ldst (str, flags, CIRRUS_MODE2);
6904 static void
6905 do_c_ldst_3 (str, flags)
6906 char * str;
6907 unsigned long flags;
6909 do_c_ldst (str, flags, CIRRUS_MODE3);
6912 static void
6913 do_c_ldst_4 (str, flags)
6914 char * str;
6915 unsigned long flags;
6917 do_c_ldst (str, flags, CIRRUS_MODE4);
6920 /* Isnsn like "foo X,Y". */
6922 static void
6923 do_c_binops (str, flags, mode)
6924 char * str;
6925 unsigned long flags;
6926 int mode;
6928 int shift1, shift2;
6930 shift1 = mode & 0xff;
6931 shift2 = (mode >> 8) & 0xff;
6933 skip_whitespace (str);
6935 if (cirrus_reg_required_here (&str, shift1, CIRRUS_REGTYPE_ANY) == FAIL
6936 || skip_past_comma (&str) == FAIL
6937 || cirrus_reg_required_here (&str, shift2, CIRRUS_REGTYPE_ANY) == FAIL)
6939 if (!inst.error)
6940 inst.error = BAD_ARGS;
6942 else
6943 end_of_line (str);
6945 inst.instruction |= flags;
6946 return;
6949 /* Isnsn like "foo X,Y,Z". */
6951 static void
6952 do_c_triple (str, flags, mode)
6953 char * str;
6954 unsigned long flags;
6955 int mode;
6957 int shift1, shift2, shift3;
6959 shift1 = mode & 0xff;
6960 shift2 = (mode >> 8) & 0xff;
6961 shift3 = (mode >> 16) & 0xff;
6963 skip_whitespace (str);
6965 if (cirrus_reg_required_here (&str, shift1, CIRRUS_REGTYPE_ANY) == FAIL
6966 || skip_past_comma (&str) == FAIL
6967 || cirrus_reg_required_here (&str, shift2, CIRRUS_REGTYPE_ANY) == FAIL
6968 || skip_past_comma (&str) == FAIL
6969 || cirrus_reg_required_here (&str, shift3, CIRRUS_REGTYPE_ANY) == FAIL)
6971 if (!inst.error)
6972 inst.error = BAD_ARGS;
6974 else
6975 end_of_line (str);
6977 inst.instruction |= flags;
6978 return;
6981 /* Isnsn like "foo W,X,Y,Z".
6982 where W=MVAX[0:3] and X,Y,Z=MVFX[0:15]. */
6984 static void
6985 do_c_quad (str, flags, mode)
6986 char * str;
6987 unsigned long flags;
6988 int mode;
6990 int shift1, shift2, shift3, shift4;
6991 enum cirrus_regtype rt;
6993 rt = (inst.instruction << 4 == 0xe2006000
6994 || inst.instruction << 4 == 0xe3006000) ? CIRRUS_REGTYPE_MVAX
6995 : CIRRUS_REGTYPE_MVFX;
6997 shift1 = mode & 0xff;
6998 shift2 = (mode >> 8) & 0xff;
6999 shift3 = (mode >> 16) & 0xff;
7000 shift4 = (mode >> 24) & 0xff;
7002 skip_whitespace (str);
7004 if (cirrus_reg_required_here (&str, shift1, CIRRUS_REGTYPE_MVAX) == FAIL
7005 || skip_past_comma (&str) == FAIL
7006 || cirrus_reg_required_here (&str, shift2, rt) == FAIL
7007 || skip_past_comma (&str) == FAIL
7008 || cirrus_reg_required_here (&str, shift3, CIRRUS_REGTYPE_MVFX) == FAIL
7009 || skip_past_comma (&str) == FAIL
7010 || cirrus_reg_required_here (&str, shift4, CIRRUS_REGTYPE_MVFX) == FAIL)
7012 if (!inst.error)
7013 inst.error = BAD_ARGS;
7015 else
7016 end_of_line (str);
7018 inst.instruction |= flags;
7019 return;
7022 /* cfmvsc32<cond> DSPSC,MVFX[15:0].
7023 cfmv32sc<cond> MVFX[15:0],DSPSC. */
7025 static void
7026 do_c_dspsc (str, flags, mode)
7027 char * str;
7028 unsigned long flags;
7029 int mode;
7031 int error;
7033 skip_whitespace (str);
7035 error = 0;
7037 if (mode == CIRRUS_MODE1)
7039 /* cfmvsc32. */
7040 if (cirrus_reg_required_here (&str, -1, CIRRUS_REGTYPE_DSPSC) == FAIL
7041 || skip_past_comma (&str) == FAIL
7042 || cirrus_reg_required_here (&str, 16, CIRRUS_REGTYPE_MVFX) == FAIL)
7043 error = 1;
7045 else
7047 /* cfmv32sc. */
7048 if (cirrus_reg_required_here (&str, 0, CIRRUS_REGTYPE_MVFX) == FAIL
7049 || skip_past_comma (&str) == FAIL
7050 || cirrus_reg_required_here (&str, -1, CIRRUS_REGTYPE_DSPSC) == FAIL)
7051 error = 1;
7054 if (error)
7056 if (!inst.error)
7057 inst.error = BAD_ARGS;
7059 else
7061 inst.instruction |= flags;
7062 end_of_line (str);
7065 return;
7068 /* Cirrus shift immediate instructions.
7069 cfsh32<cond> MVFX[15:0],MVFX[15:0],Shift[6:0].
7070 cfsh64<cond> MVDX[15:0],MVDX[15:0],Shift[6:0]. */
7072 static void
7073 do_c_shift (str, flags, mode)
7074 char * str;
7075 unsigned long flags;
7076 int mode;
7078 int error;
7079 int imm, neg = 0;
7081 skip_whitespace (str);
7083 error = 0;
7085 if (cirrus_reg_required_here (&str, 12,
7086 (mode == CIRRUS_MODE1)
7087 ? CIRRUS_REGTYPE_MVFX
7088 : CIRRUS_REGTYPE_MVDX) == FAIL
7089 || skip_past_comma (&str) == FAIL
7090 || cirrus_reg_required_here (&str, 16,
7091 (mode == CIRRUS_MODE1)
7092 ? CIRRUS_REGTYPE_MVFX
7093 : CIRRUS_REGTYPE_MVDX) == FAIL
7094 || skip_past_comma (&str) == FAIL)
7096 if (!inst.error)
7097 inst.error = BAD_ARGS;
7098 return;
7101 /* Calculate the immediate operand.
7102 The operand is a 7bit signed number. */
7103 skip_whitespace (str);
7105 if (*str == '#')
7106 ++str;
7108 if (!ISDIGIT (*str) && *str != '-')
7110 inst.error = _("expecting immediate, 7bit operand");
7111 return;
7114 if (*str == '-')
7116 neg = 1;
7117 ++str;
7120 for (imm = 0; *str && ISDIGIT (*str); ++str)
7121 imm = imm * 10 + *str - '0';
7123 if (imm > 64)
7125 inst.error = _("immediate out of range");
7126 return;
7129 /* Make negative imm's into 7bit signed numbers. */
7130 if (neg)
7132 imm = -imm;
7133 imm &= 0x0000007f;
7136 /* Bits 0-3 of the insn should have bits 0-3 of the immediate.
7137 Bits 5-7 of the insn should have bits 4-6 of the immediate.
7138 Bit 4 should be 0. */
7139 imm = (imm & 0xf) | ((imm & 0x70) << 1);
7141 inst.instruction |= imm;
7142 inst.instruction |= flags;
7144 end_of_line (str);
7146 return;
7149 static int
7150 cirrus_parse_offset (str, negative)
7151 char ** str;
7152 int *negative;
7154 char * p = *str;
7155 int offset;
7157 *negative = 0;
7159 skip_whitespace (p);
7161 if (*p == '#')
7162 ++p;
7164 if (*p == '-')
7166 *negative = 1;
7167 ++p;
7170 if (!ISDIGIT (*p))
7172 inst.error = _("offset expected");
7173 return 0;
7176 for (offset = 0; *p && ISDIGIT (*p); ++p)
7177 offset = offset * 10 + *p - '0';
7179 if (offset > 0xff)
7181 inst.error = _("offset out of range");
7182 return 0;
7185 *str = p;
7187 return *negative ? -offset : offset;
7190 /* Cirrus load/store instructions.
7191 <insn><cond> CRd,[Rn,<offset>]{!}.
7192 <insn><cond> CRd,[Rn],<offset>. */
7194 static void
7195 do_c_ldst (str, flags, mode)
7196 char * str;
7197 unsigned long flags;
7198 int mode;
7200 int offset, negative;
7201 enum cirrus_regtype rt;
7203 rt = mode == CIRRUS_MODE1 ? CIRRUS_REGTYPE_MVF
7204 : mode == CIRRUS_MODE2 ? CIRRUS_REGTYPE_MVD
7205 : mode == CIRRUS_MODE3 ? CIRRUS_REGTYPE_MVFX
7206 : mode == CIRRUS_MODE4 ? CIRRUS_REGTYPE_MVDX : CIRRUS_REGTYPE_MVF;
7208 skip_whitespace (str);
7210 if (cirrus_reg_required_here (& str, 12, rt) == FAIL
7211 || skip_past_comma (& str) == FAIL
7212 || *str++ != '['
7213 || reg_required_here (& str, 16) == FAIL)
7214 goto fail_ldst;
7216 if (skip_past_comma (& str) == SUCCESS)
7218 /* You are here: "<offset>]{!}". */
7219 inst.instruction |= PRE_INDEX;
7221 offset = cirrus_parse_offset (&str, &negative);
7223 if (inst.error)
7224 return;
7226 if (*str++ != ']')
7228 inst.error = _("missing ]");
7229 return;
7232 if (*str == '!')
7234 inst.instruction |= WRITE_BACK;
7235 ++str;
7238 else
7240 /* You are here: "], <offset>". */
7241 if (*str++ != ']')
7243 inst.error = _("missing ]");
7244 return;
7247 if (skip_past_comma (&str) == FAIL
7248 || (offset = cirrus_parse_offset (&str, &negative), inst.error))
7249 goto fail_ldst;
7251 inst.instruction |= CP_T_WB; /* Post indexed, set bit W. */
7254 if (negative)
7255 offset = -offset;
7256 else
7257 inst.instruction |= CP_T_UD; /* Postive, so set bit U. */
7259 inst.instruction |= offset >> 2;
7260 inst.instruction |= flags;
7262 end_of_line (str);
7263 return;
7265 fail_ldst:
7266 if (!inst.error)
7267 inst.error = BAD_ARGS;
7268 return;
7271 static void
7272 do_t_nop (str)
7273 char * str;
7275 /* Do nothing. */
7276 end_of_line (str);
7277 return;
7280 /* Handle the Format 4 instructions that do not have equivalents in other
7281 formats. That is, ADC, AND, EOR, SBC, ROR, TST, NEG, CMN, ORR, MUL,
7282 BIC and MVN. */
7284 static void
7285 do_t_arit (str)
7286 char * str;
7288 int Rd, Rs, Rn;
7290 skip_whitespace (str);
7292 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
7293 || skip_past_comma (&str) == FAIL
7294 || (Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
7296 inst.error = BAD_ARGS;
7297 return;
7300 if (skip_past_comma (&str) != FAIL)
7302 /* Three operand format not allowed for TST, CMN, NEG and MVN.
7303 (It isn't allowed for CMP either, but that isn't handled by this
7304 function.) */
7305 if (inst.instruction == T_OPCODE_TST
7306 || inst.instruction == T_OPCODE_CMN
7307 || inst.instruction == T_OPCODE_NEG
7308 || inst.instruction == T_OPCODE_MVN)
7310 inst.error = BAD_ARGS;
7311 return;
7314 if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
7315 return;
7317 if (Rs != Rd)
7319 inst.error = _("dest and source1 must be the same register");
7320 return;
7322 Rs = Rn;
7325 if (inst.instruction == T_OPCODE_MUL
7326 && Rs == Rd)
7327 as_tsktsk (_("Rs and Rd must be different in MUL"));
7329 inst.instruction |= Rd | (Rs << 3);
7330 end_of_line (str);
7333 static void
7334 do_t_add (str)
7335 char * str;
7337 thumb_add_sub (str, 0);
7340 static void
7341 do_t_asr (str)
7342 char * str;
7344 thumb_shift (str, THUMB_ASR);
7347 static void
7348 do_t_branch9 (str)
7349 char * str;
7351 if (my_get_expression (&inst.reloc.exp, &str))
7352 return;
7353 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH9;
7354 inst.reloc.pc_rel = 1;
7355 end_of_line (str);
7358 static void
7359 do_t_branch12 (str)
7360 char * str;
7362 if (my_get_expression (&inst.reloc.exp, &str))
7363 return;
7364 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH12;
7365 inst.reloc.pc_rel = 1;
7366 end_of_line (str);
7369 /* Find the real, Thumb encoded start of a Thumb function. */
7371 static symbolS *
7372 find_real_start (symbolP)
7373 symbolS * symbolP;
7375 char * real_start;
7376 const char * name = S_GET_NAME (symbolP);
7377 symbolS * new_target;
7379 /* This definiton must agree with the one in gcc/config/arm/thumb.c. */
7380 #define STUB_NAME ".real_start_of"
7382 if (name == NULL)
7383 abort ();
7385 /* Names that start with '.' are local labels, not function entry points.
7386 The compiler may generate BL instructions to these labels because it
7387 needs to perform a branch to a far away location. */
7388 if (name[0] == '.')
7389 return symbolP;
7391 real_start = malloc (strlen (name) + strlen (STUB_NAME) + 1);
7392 sprintf (real_start, "%s%s", STUB_NAME, name);
7394 new_target = symbol_find (real_start);
7396 if (new_target == NULL)
7398 as_warn ("Failed to find real start of function: %s\n", name);
7399 new_target = symbolP;
7402 free (real_start);
7404 return new_target;
7407 static void
7408 do_t_branch23 (str)
7409 char * str;
7411 if (my_get_expression (& inst.reloc.exp, & str))
7412 return;
7414 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH23;
7415 inst.reloc.pc_rel = 1;
7416 end_of_line (str);
7418 /* If the destination of the branch is a defined symbol which does not have
7419 the THUMB_FUNC attribute, then we must be calling a function which has
7420 the (interfacearm) attribute. We look for the Thumb entry point to that
7421 function and change the branch to refer to that function instead. */
7422 if ( inst.reloc.exp.X_op == O_symbol
7423 && inst.reloc.exp.X_add_symbol != NULL
7424 && S_IS_DEFINED (inst.reloc.exp.X_add_symbol)
7425 && ! THUMB_IS_FUNC (inst.reloc.exp.X_add_symbol))
7426 inst.reloc.exp.X_add_symbol =
7427 find_real_start (inst.reloc.exp.X_add_symbol);
7430 static void
7431 do_t_bx (str)
7432 char * str;
7434 int reg;
7436 skip_whitespace (str);
7438 if ((reg = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
7439 return;
7441 /* This sets THUMB_H2 from the top bit of reg. */
7442 inst.instruction |= reg << 3;
7444 /* ??? FIXME: Should add a hacky reloc here if reg is REG_PC. The reloc
7445 should cause the alignment to be checked once it is known. This is
7446 because BX PC only works if the instruction is word aligned. */
7448 end_of_line (str);
7451 static void
7452 do_t_compare (str)
7453 char * str;
7455 thumb_mov_compare (str, THUMB_COMPARE);
7458 static void
7459 do_t_ldmstm (str)
7460 char * str;
7462 int Rb;
7463 long range;
7465 skip_whitespace (str);
7467 if ((Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
7468 return;
7470 if (*str != '!')
7471 as_warn (_("Inserted missing '!': load/store multiple always writes back base register"));
7472 else
7473 str++;
7475 if (skip_past_comma (&str) == FAIL
7476 || (range = reg_list (&str)) == FAIL)
7478 if (! inst.error)
7479 inst.error = BAD_ARGS;
7480 return;
7483 if (inst.reloc.type != BFD_RELOC_NONE)
7485 /* This really doesn't seem worth it. */
7486 inst.reloc.type = BFD_RELOC_NONE;
7487 inst.error = _("Expression too complex");
7488 return;
7491 if (range & ~0xff)
7493 inst.error = _("only lo-regs valid in load/store multiple");
7494 return;
7497 inst.instruction |= (Rb << 8) | range;
7498 end_of_line (str);
7501 static void
7502 do_t_ldr (str)
7503 char * str;
7505 thumb_load_store (str, THUMB_LOAD, THUMB_WORD);
7508 static void
7509 do_t_ldrb (str)
7510 char * str;
7512 thumb_load_store (str, THUMB_LOAD, THUMB_BYTE);
7515 static void
7516 do_t_ldrh (str)
7517 char * str;
7519 thumb_load_store (str, THUMB_LOAD, THUMB_HALFWORD);
7522 static void
7523 do_t_lds (str)
7524 char * str;
7526 int Rd, Rb, Ro;
7528 skip_whitespace (str);
7530 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
7531 || skip_past_comma (&str) == FAIL
7532 || *str++ != '['
7533 || (Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL
7534 || skip_past_comma (&str) == FAIL
7535 || (Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL
7536 || *str++ != ']')
7538 if (! inst.error)
7539 inst.error = _("Syntax: ldrs[b] Rd, [Rb, Ro]");
7540 return;
7543 inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
7544 end_of_line (str);
7547 static void
7548 do_t_lsl (str)
7549 char * str;
7551 thumb_shift (str, THUMB_LSL);
7554 static void
7555 do_t_lsr (str)
7556 char * str;
7558 thumb_shift (str, THUMB_LSR);
7561 static void
7562 do_t_mov (str)
7563 char * str;
7565 thumb_mov_compare (str, THUMB_MOVE);
7568 static void
7569 do_t_push_pop (str)
7570 char * str;
7572 long range;
7574 skip_whitespace (str);
7576 if ((range = reg_list (&str)) == FAIL)
7578 if (! inst.error)
7579 inst.error = BAD_ARGS;
7580 return;
7583 if (inst.reloc.type != BFD_RELOC_NONE)
7585 /* This really doesn't seem worth it. */
7586 inst.reloc.type = BFD_RELOC_NONE;
7587 inst.error = _("Expression too complex");
7588 return;
7591 if (range & ~0xff)
7593 if ((inst.instruction == T_OPCODE_PUSH
7594 && (range & ~0xff) == 1 << REG_LR)
7595 || (inst.instruction == T_OPCODE_POP
7596 && (range & ~0xff) == 1 << REG_PC))
7598 inst.instruction |= THUMB_PP_PC_LR;
7599 range &= 0xff;
7601 else
7603 inst.error = _("invalid register list to push/pop instruction");
7604 return;
7608 inst.instruction |= range;
7609 end_of_line (str);
7612 static void
7613 do_t_str (str)
7614 char * str;
7616 thumb_load_store (str, THUMB_STORE, THUMB_WORD);
7619 static void
7620 do_t_strb (str)
7621 char * str;
7623 thumb_load_store (str, THUMB_STORE, THUMB_BYTE);
7626 static void
7627 do_t_strh (str)
7628 char * str;
7630 thumb_load_store (str, THUMB_STORE, THUMB_HALFWORD);
7633 static void
7634 do_t_sub (str)
7635 char * str;
7637 thumb_add_sub (str, 1);
7640 static void
7641 do_t_swi (str)
7642 char * str;
7644 skip_whitespace (str);
7646 if (my_get_expression (&inst.reloc.exp, &str))
7647 return;
7649 inst.reloc.type = BFD_RELOC_ARM_SWI;
7650 end_of_line (str);
7651 return;
7654 static void
7655 do_t_adr (str)
7656 char * str;
7658 int reg;
7660 /* This is a pseudo-op of the form "adr rd, label" to be converted
7661 into a relative address of the form "add rd, pc, #label-.-4". */
7662 skip_whitespace (str);
7664 /* Store Rd in temporary location inside instruction. */
7665 if ((reg = reg_required_here (&str, 4)) == FAIL
7666 || (reg > 7) /* For Thumb reg must be r0..r7. */
7667 || skip_past_comma (&str) == FAIL
7668 || my_get_expression (&inst.reloc.exp, &str))
7670 if (!inst.error)
7671 inst.error = BAD_ARGS;
7672 return;
7675 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
7676 inst.reloc.exp.X_add_number -= 4; /* PC relative adjust. */
7677 inst.reloc.pc_rel = 1;
7678 inst.instruction |= REG_PC; /* Rd is already placed into the instruction. */
7680 end_of_line (str);
7683 static void
7684 insert_reg (entry)
7685 int entry;
7687 int len = strlen (reg_table[entry].name) + 2;
7688 char * buf = (char *) xmalloc (len);
7689 char * buf2 = (char *) xmalloc (len);
7690 int i = 0;
7692 #ifdef REGISTER_PREFIX
7693 buf[i++] = REGISTER_PREFIX;
7694 #endif
7696 strcpy (buf + i, reg_table[entry].name);
7698 for (i = 0; buf[i]; i++)
7699 buf2[i] = TOUPPER (buf[i]);
7701 buf2[i] = '\0';
7703 hash_insert (arm_reg_hsh, buf, (PTR) & reg_table[entry]);
7704 hash_insert (arm_reg_hsh, buf2, (PTR) & reg_table[entry]);
7707 static void
7708 insert_reg_alias (str, regnum)
7709 char *str;
7710 int regnum;
7712 struct reg_entry *new =
7713 (struct reg_entry *) xmalloc (sizeof (struct reg_entry));
7714 char *name = xmalloc (strlen (str) + 1);
7715 strcpy (name, str);
7717 new->name = name;
7718 new->number = regnum;
7720 hash_insert (arm_reg_hsh, name, (PTR) new);
7723 static void
7724 set_constant_flonums ()
7726 int i;
7728 for (i = 0; i < NUM_FLOAT_VALS; i++)
7729 if (atof_ieee ((char *) fp_const[i], 'x', fp_values[i]) == NULL)
7730 abort ();
7733 /* Iterate over the base tables to create the instruction patterns. */
7734 static void
7735 build_arm_ops_hsh ()
7737 unsigned int i;
7738 unsigned int j;
7739 static struct obstack insn_obstack;
7741 obstack_begin (&insn_obstack, 4000);
7743 for (i = 0; i < sizeof (insns) / sizeof (struct asm_opcode); i++)
7745 CONST struct asm_opcode *insn = insns + i;
7747 if (insn->cond_offset != 0)
7749 /* Insn supports conditional execution. Build the varaints
7750 and insert them in the hash table. */
7751 for (j = 0; j < sizeof (conds) / sizeof (struct asm_cond); j++)
7753 unsigned len = strlen (insn->template);
7754 struct asm_opcode *new;
7755 char *template;
7757 new = obstack_alloc (&insn_obstack, sizeof (struct asm_opcode));
7758 /* All condition codes are two characters. */
7759 template = obstack_alloc (&insn_obstack, len + 3);
7761 strncpy (template, insn->template, insn->cond_offset);
7762 strcpy (template + insn->cond_offset, conds[j].template);
7763 if (len > insn->cond_offset)
7764 strcpy (template + insn->cond_offset + 2,
7765 insn->template + insn->cond_offset);
7766 new->template = template;
7767 new->cond_offset = 0;
7768 new->variant = insn->variant;
7769 new->parms = insn->parms;
7770 new->value = (insn->value & ~COND_MASK) | conds[j].value;
7772 hash_insert (arm_ops_hsh, new->template, (PTR) new);
7775 /* Finally, insert the unconditional insn in the table directly;
7776 no need to build a copy. */
7777 hash_insert (arm_ops_hsh, insn->template, (PTR) insn);
7781 void
7782 md_begin ()
7784 unsigned mach;
7785 unsigned int i;
7787 if ( (arm_ops_hsh = hash_new ()) == NULL
7788 || (arm_tops_hsh = hash_new ()) == NULL
7789 || (arm_cond_hsh = hash_new ()) == NULL
7790 || (arm_shift_hsh = hash_new ()) == NULL
7791 || (arm_reg_hsh = hash_new ()) == NULL
7792 || (arm_psr_hsh = hash_new ()) == NULL)
7793 as_fatal (_("Virtual memory exhausted"));
7795 build_arm_ops_hsh ();
7796 for (i = 0; i < sizeof (tinsns) / sizeof (struct thumb_opcode); i++)
7797 hash_insert (arm_tops_hsh, tinsns[i].template, (PTR) (tinsns + i));
7798 for (i = 0; i < sizeof (conds) / sizeof (struct asm_cond); i++)
7799 hash_insert (arm_cond_hsh, conds[i].template, (PTR) (conds + i));
7800 for (i = 0; i < sizeof (shift_names) / sizeof (struct asm_shift_name); i++)
7801 hash_insert (arm_shift_hsh, shift_names[i].name, (PTR) (shift_names + i));
7802 for (i = 0; i < sizeof (psrs) / sizeof (struct asm_psr); i++)
7803 hash_insert (arm_psr_hsh, psrs[i].template, (PTR) (psrs + i));
7805 for (i = 0; reg_table[i].name; i++)
7806 insert_reg (i);
7808 set_constant_flonums ();
7810 #if defined OBJ_COFF || defined OBJ_ELF
7812 unsigned int flags = 0;
7814 /* Set the flags in the private structure. */
7815 if (uses_apcs_26) flags |= F_APCS26;
7816 if (support_interwork) flags |= F_INTERWORK;
7817 if (uses_apcs_float) flags |= F_APCS_FLOAT;
7818 if (pic_code) flags |= F_PIC;
7819 if ((cpu_variant & FPU_ANY) == FPU_NONE) flags |= F_SOFT_FLOAT;
7821 bfd_set_private_flags (stdoutput, flags);
7823 /* We have run out flags in the COFF header to encode the
7824 status of ATPCS support, so instead we create a dummy,
7825 empty, debug section called .arm.atpcs. */
7826 if (atpcs)
7828 asection * sec;
7830 sec = bfd_make_section (stdoutput, ".arm.atpcs");
7832 if (sec != NULL)
7834 bfd_set_section_flags
7835 (stdoutput, sec, SEC_READONLY | SEC_DEBUGGING /* | SEC_HAS_CONTENTS */);
7836 bfd_set_section_size (stdoutput, sec, 0);
7837 bfd_set_section_contents (stdoutput, sec, NULL, 0, 0);
7841 #endif
7843 /* Record the CPU type as well. */
7844 switch (cpu_variant & ARM_CPU_MASK)
7846 case ARM_2:
7847 mach = bfd_mach_arm_2;
7848 break;
7850 case ARM_3: /* Also ARM_250. */
7851 mach = bfd_mach_arm_2a;
7852 break;
7854 case ARM_6: /* Also ARM_7. */
7855 mach = bfd_mach_arm_3;
7856 break;
7858 default:
7859 mach = bfd_mach_arm_4;
7860 break;
7864 /* Catch special cases. */
7865 if (cpu_variant & ARM_EXT_XSCALE)
7866 mach = bfd_mach_arm_XScale;
7867 else if (cpu_variant & ARM_EXT_V5E)
7868 mach = bfd_mach_arm_5TE;
7869 else if (cpu_variant & ARM_EXT_V5)
7871 if (cpu_variant & ARM_EXT_V4T)
7872 mach = bfd_mach_arm_5T;
7873 else
7874 mach = bfd_mach_arm_5;
7876 else if (cpu_variant & ARM_EXT_V4)
7878 if (cpu_variant & ARM_EXT_V4T)
7879 mach = bfd_mach_arm_4T;
7880 else
7881 mach = bfd_mach_arm_4;
7883 else if (cpu_variant & ARM_EXT_V3M)
7884 mach = bfd_mach_arm_3M;
7886 bfd_set_arch_mach (stdoutput, TARGET_ARCH, mach);
7889 /* Turn an integer of n bytes (in val) into a stream of bytes appropriate
7890 for use in the a.out file, and stores them in the array pointed to by buf.
7891 This knows about the endian-ness of the target machine and does
7892 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
7893 2 (short) and 4 (long) Floating numbers are put out as a series of
7894 LITTLENUMS (shorts, here at least). */
7896 void
7897 md_number_to_chars (buf, val, n)
7898 char * buf;
7899 valueT val;
7900 int n;
7902 if (target_big_endian)
7903 number_to_chars_bigendian (buf, val, n);
7904 else
7905 number_to_chars_littleendian (buf, val, n);
7908 static valueT
7909 md_chars_to_number (buf, n)
7910 char * buf;
7911 int n;
7913 valueT result = 0;
7914 unsigned char * where = (unsigned char *) buf;
7916 if (target_big_endian)
7918 while (n--)
7920 result <<= 8;
7921 result |= (*where++ & 255);
7924 else
7926 while (n--)
7928 result <<= 8;
7929 result |= (where[n] & 255);
7933 return result;
7936 /* Turn a string in input_line_pointer into a floating point constant
7937 of type TYPE, and store the appropriate bytes in *LITP. The number
7938 of LITTLENUMS emitted is stored in *SIZEP. An error message is
7939 returned, or NULL on OK.
7941 Note that fp constants aren't represent in the normal way on the ARM.
7942 In big endian mode, things are as expected. However, in little endian
7943 mode fp constants are big-endian word-wise, and little-endian byte-wise
7944 within the words. For example, (double) 1.1 in big endian mode is
7945 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
7946 the byte sequence 99 99 f1 3f 9a 99 99 99.
7948 ??? The format of 12 byte floats is uncertain according to gcc's arm.h. */
7950 char *
7951 md_atof (type, litP, sizeP)
7952 char type;
7953 char * litP;
7954 int * sizeP;
7956 int prec;
7957 LITTLENUM_TYPE words[MAX_LITTLENUMS];
7958 char *t;
7959 int i;
7961 switch (type)
7963 case 'f':
7964 case 'F':
7965 case 's':
7966 case 'S':
7967 prec = 2;
7968 break;
7970 case 'd':
7971 case 'D':
7972 case 'r':
7973 case 'R':
7974 prec = 4;
7975 break;
7977 case 'x':
7978 case 'X':
7979 prec = 6;
7980 break;
7982 case 'p':
7983 case 'P':
7984 prec = 6;
7985 break;
7987 default:
7988 *sizeP = 0;
7989 return _("Bad call to MD_ATOF()");
7992 t = atof_ieee (input_line_pointer, type, words);
7993 if (t)
7994 input_line_pointer = t;
7995 *sizeP = prec * 2;
7997 if (target_big_endian)
7999 for (i = 0; i < prec; i++)
8001 md_number_to_chars (litP, (valueT) words[i], 2);
8002 litP += 2;
8005 else
8007 /* For a 4 byte float the order of elements in `words' is 1 0. For an
8008 8 byte float the order is 1 0 3 2. */
8009 for (i = 0; i < prec; i += 2)
8011 md_number_to_chars (litP, (valueT) words[i + 1], 2);
8012 md_number_to_chars (litP + 2, (valueT) words[i], 2);
8013 litP += 4;
8017 return 0;
8020 /* The knowledge of the PC's pipeline offset is built into the insns
8021 themselves. */
8023 long
8024 md_pcrel_from (fixP)
8025 fixS * fixP;
8027 if (fixP->fx_addsy
8028 && S_GET_SEGMENT (fixP->fx_addsy) == undefined_section
8029 && fixP->fx_subsy == NULL)
8030 return 0;
8032 if (fixP->fx_pcrel && (fixP->fx_r_type == BFD_RELOC_ARM_THUMB_ADD))
8034 /* PC relative addressing on the Thumb is slightly odd
8035 as the bottom two bits of the PC are forced to zero
8036 for the calculation. */
8037 return (fixP->fx_where + fixP->fx_frag->fr_address) & ~3;
8040 #ifdef TE_WINCE
8041 /* The pattern was adjusted to accomodate CE's off-by-one fixups,
8042 so we un-adjust here to compensate for the accomodation. */
8043 return fixP->fx_where + fixP->fx_frag->fr_address + 8;
8044 #else
8045 return fixP->fx_where + fixP->fx_frag->fr_address;
8046 #endif
8049 /* Round up a section size to the appropriate boundary. */
8051 valueT
8052 md_section_align (segment, size)
8053 segT segment ATTRIBUTE_UNUSED;
8054 valueT size;
8056 #ifdef OBJ_ELF
8057 return size;
8058 #else
8059 /* Round all sects to multiple of 4. */
8060 return (size + 3) & ~3;
8061 #endif
8064 /* Under ELF we need to default _GLOBAL_OFFSET_TABLE.
8065 Otherwise we have no need to default values of symbols. */
8067 symbolS *
8068 md_undefined_symbol (name)
8069 char * name ATTRIBUTE_UNUSED;
8071 #ifdef OBJ_ELF
8072 if (name[0] == '_' && name[1] == 'G'
8073 && streq (name, GLOBAL_OFFSET_TABLE_NAME))
8075 if (!GOT_symbol)
8077 if (symbol_find (name))
8078 as_bad ("GOT already in the symbol table");
8080 GOT_symbol = symbol_new (name, undefined_section,
8081 (valueT) 0, & zero_address_frag);
8084 return GOT_symbol;
8086 #endif
8088 return 0;
8091 /* arm_reg_parse () := if it looks like a register, return its token and
8092 advance the pointer. */
8094 static int
8095 arm_reg_parse (ccp)
8096 register char ** ccp;
8098 char * start = * ccp;
8099 char c;
8100 char * p;
8101 struct reg_entry * reg;
8103 #ifdef REGISTER_PREFIX
8104 if (*start != REGISTER_PREFIX)
8105 return FAIL;
8106 p = start + 1;
8107 #else
8108 p = start;
8109 #ifdef OPTIONAL_REGISTER_PREFIX
8110 if (*p == OPTIONAL_REGISTER_PREFIX)
8111 p++, start++;
8112 #endif
8113 #endif
8114 if (!ISALPHA (*p) || !is_name_beginner (*p))
8115 return FAIL;
8117 c = *p++;
8118 while (ISALPHA (c) || ISDIGIT (c) || c == '_')
8119 c = *p++;
8121 *--p = 0;
8122 reg = (struct reg_entry *) hash_find (arm_reg_hsh, start);
8123 *p = c;
8125 if (reg)
8127 *ccp = p;
8128 return reg->number;
8131 return FAIL;
8134 void
8135 md_apply_fix3 (fixP, valP, seg)
8136 fixS * fixP;
8137 valueT * valP;
8138 segT seg;
8140 offsetT value = * valP;
8141 offsetT newval;
8142 unsigned int newimm;
8143 unsigned long temp;
8144 int sign;
8145 char * buf = fixP->fx_where + fixP->fx_frag->fr_literal;
8146 arm_fix_data * arm_data = (arm_fix_data *) fixP->tc_fix_data;
8148 assert (fixP->fx_r_type < BFD_RELOC_UNUSED);
8150 /* Note whether this will delete the relocation. */
8151 #if 0
8152 /* Patch from REarnshaw to JDavis (disabled for the moment, since it
8153 doesn't work fully.) */
8154 if ((fixP->fx_addsy == 0 || symbol_constant_p (fixP->fx_addsy))
8155 && !fixP->fx_pcrel)
8156 #else
8157 if (fixP->fx_addsy == 0 && !fixP->fx_pcrel)
8158 #endif
8159 fixP->fx_done = 1;
8161 /* If this symbol is in a different section then we need to leave it for
8162 the linker to deal with. Unfortunately, md_pcrel_from can't tell,
8163 so we have to undo it's effects here. */
8164 if (fixP->fx_pcrel)
8166 if (fixP->fx_addsy != NULL
8167 && S_IS_DEFINED (fixP->fx_addsy)
8168 && S_GET_SEGMENT (fixP->fx_addsy) != seg)
8170 if (target_oabi
8171 && (fixP->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH
8172 || fixP->fx_r_type == BFD_RELOC_ARM_PCREL_BLX
8174 value = 0;
8175 else
8176 value += md_pcrel_from (fixP);
8180 /* Remember value for emit_reloc. */
8181 fixP->fx_addnumber = value;
8183 switch (fixP->fx_r_type)
8185 case BFD_RELOC_ARM_IMMEDIATE:
8186 newimm = validate_immediate (value);
8187 temp = md_chars_to_number (buf, INSN_SIZE);
8189 /* If the instruction will fail, see if we can fix things up by
8190 changing the opcode. */
8191 if (newimm == (unsigned int) FAIL
8192 && (newimm = negate_data_op (&temp, value)) == (unsigned int) FAIL)
8194 as_bad_where (fixP->fx_file, fixP->fx_line,
8195 _("invalid constant (%lx) after fixup"),
8196 (unsigned long) value);
8197 break;
8200 newimm |= (temp & 0xfffff000);
8201 md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
8202 break;
8204 case BFD_RELOC_ARM_ADRL_IMMEDIATE:
8206 unsigned int highpart = 0;
8207 unsigned int newinsn = 0xe1a00000; /* nop. */
8208 newimm = validate_immediate (value);
8209 temp = md_chars_to_number (buf, INSN_SIZE);
8211 /* If the instruction will fail, see if we can fix things up by
8212 changing the opcode. */
8213 if (newimm == (unsigned int) FAIL
8214 && (newimm = negate_data_op (& temp, value)) == (unsigned int) FAIL)
8216 /* No ? OK - try using two ADD instructions to generate
8217 the value. */
8218 newimm = validate_immediate_twopart (value, & highpart);
8220 /* Yes - then make sure that the second instruction is
8221 also an add. */
8222 if (newimm != (unsigned int) FAIL)
8223 newinsn = temp;
8224 /* Still No ? Try using a negated value. */
8225 else if ((newimm = validate_immediate_twopart (- value, & highpart)) != (unsigned int) FAIL)
8226 temp = newinsn = (temp & OPCODE_MASK) | OPCODE_SUB << DATA_OP_SHIFT;
8227 /* Otherwise - give up. */
8228 else
8230 as_bad_where (fixP->fx_file, fixP->fx_line,
8231 _("Unable to compute ADRL instructions for PC offset of 0x%lx"),
8232 value);
8233 break;
8236 /* Replace the first operand in the 2nd instruction (which
8237 is the PC) with the destination register. We have
8238 already added in the PC in the first instruction and we
8239 do not want to do it again. */
8240 newinsn &= ~ 0xf0000;
8241 newinsn |= ((newinsn & 0x0f000) << 4);
8244 newimm |= (temp & 0xfffff000);
8245 md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
8247 highpart |= (newinsn & 0xfffff000);
8248 md_number_to_chars (buf + INSN_SIZE, (valueT) highpart, INSN_SIZE);
8250 break;
8252 case BFD_RELOC_ARM_OFFSET_IMM:
8253 sign = value >= 0;
8255 if (value < 0)
8256 value = - value;
8258 if (validate_offset_imm (value, 0) == FAIL)
8260 as_bad_where (fixP->fx_file, fixP->fx_line,
8261 _("bad immediate value for offset (%ld)"),
8262 (long) value);
8263 break;
8266 newval = md_chars_to_number (buf, INSN_SIZE);
8267 newval &= 0xff7ff000;
8268 newval |= value | (sign ? INDEX_UP : 0);
8269 md_number_to_chars (buf, newval, INSN_SIZE);
8270 break;
8272 case BFD_RELOC_ARM_OFFSET_IMM8:
8273 case BFD_RELOC_ARM_HWLITERAL:
8274 sign = value >= 0;
8276 if (value < 0)
8277 value = - value;
8279 if (validate_offset_imm (value, 1) == FAIL)
8281 if (fixP->fx_r_type == BFD_RELOC_ARM_HWLITERAL)
8282 as_bad_where (fixP->fx_file, fixP->fx_line,
8283 _("invalid literal constant: pool needs to be closer"));
8284 else
8285 as_bad (_("bad immediate value for half-word offset (%ld)"),
8286 (long) value);
8287 break;
8290 newval = md_chars_to_number (buf, INSN_SIZE);
8291 newval &= 0xff7ff0f0;
8292 newval |= ((value >> 4) << 8) | (value & 0xf) | (sign ? INDEX_UP : 0);
8293 md_number_to_chars (buf, newval, INSN_SIZE);
8294 break;
8296 case BFD_RELOC_ARM_LITERAL:
8297 sign = value >= 0;
8299 if (value < 0)
8300 value = - value;
8302 if (validate_offset_imm (value, 0) == FAIL)
8304 as_bad_where (fixP->fx_file, fixP->fx_line,
8305 _("invalid literal constant: pool needs to be closer"));
8306 break;
8309 newval = md_chars_to_number (buf, INSN_SIZE);
8310 newval &= 0xff7ff000;
8311 newval |= value | (sign ? INDEX_UP : 0);
8312 md_number_to_chars (buf, newval, INSN_SIZE);
8313 break;
8315 case BFD_RELOC_ARM_SHIFT_IMM:
8316 newval = md_chars_to_number (buf, INSN_SIZE);
8317 if (((unsigned long) value) > 32
8318 || (value == 32
8319 && (((newval & 0x60) == 0) || (newval & 0x60) == 0x60)))
8321 as_bad_where (fixP->fx_file, fixP->fx_line,
8322 _("shift expression is too large"));
8323 break;
8326 if (value == 0)
8327 /* Shifts of zero must be done as lsl. */
8328 newval &= ~0x60;
8329 else if (value == 32)
8330 value = 0;
8331 newval &= 0xfffff07f;
8332 newval |= (value & 0x1f) << 7;
8333 md_number_to_chars (buf, newval, INSN_SIZE);
8334 break;
8336 case BFD_RELOC_ARM_SWI:
8337 if (arm_data->thumb_mode)
8339 if (((unsigned long) value) > 0xff)
8340 as_bad_where (fixP->fx_file, fixP->fx_line,
8341 _("Invalid swi expression"));
8342 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xff00;
8343 newval |= value;
8344 md_number_to_chars (buf, newval, THUMB_SIZE);
8346 else
8348 if (((unsigned long) value) > 0x00ffffff)
8349 as_bad_where (fixP->fx_file, fixP->fx_line,
8350 _("Invalid swi expression"));
8351 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff000000;
8352 newval |= value;
8353 md_number_to_chars (buf, newval, INSN_SIZE);
8355 break;
8357 case BFD_RELOC_ARM_MULTI:
8358 if (((unsigned long) value) > 0xffff)
8359 as_bad_where (fixP->fx_file, fixP->fx_line,
8360 _("Invalid expression in load/store multiple"));
8361 newval = value | md_chars_to_number (buf, INSN_SIZE);
8362 md_number_to_chars (buf, newval, INSN_SIZE);
8363 break;
8365 case BFD_RELOC_ARM_PCREL_BRANCH:
8366 newval = md_chars_to_number (buf, INSN_SIZE);
8368 /* Sign-extend a 24-bit number. */
8369 #define SEXT24(x) ((((x) & 0xffffff) ^ (~ 0x7fffff)) + 0x800000)
8371 #ifdef OBJ_ELF
8372 if (! target_oabi)
8373 value = fixP->fx_offset;
8374 #endif
8376 /* We are going to store value (shifted right by two) in the
8377 instruction, in a 24 bit, signed field. Thus we need to check
8378 that none of the top 8 bits of the shifted value (top 7 bits of
8379 the unshifted, unsigned value) are set, or that they are all set. */
8380 if ((value & ~ ((offsetT) 0x1ffffff)) != 0
8381 && ((value & ~ ((offsetT) 0x1ffffff)) != ~ ((offsetT) 0x1ffffff)))
8383 #ifdef OBJ_ELF
8384 /* Normally we would be stuck at this point, since we cannot store
8385 the absolute address that is the destination of the branch in the
8386 24 bits of the branch instruction. If however, we happen to know
8387 that the destination of the branch is in the same section as the
8388 branch instruciton itself, then we can compute the relocation for
8389 ourselves and not have to bother the linker with it.
8391 FIXME: The tests for OBJ_ELF and ! target_oabi are only here
8392 because I have not worked out how to do this for OBJ_COFF or
8393 target_oabi. */
8394 if (! target_oabi
8395 && fixP->fx_addsy != NULL
8396 && S_IS_DEFINED (fixP->fx_addsy)
8397 && S_GET_SEGMENT (fixP->fx_addsy) == seg)
8399 /* Get pc relative value to go into the branch. */
8400 value = * valP;
8402 /* Permit a backward branch provided that enough bits
8403 are set. Allow a forwards branch, provided that
8404 enough bits are clear. */
8405 if ( (value & ~ ((offsetT) 0x1ffffff)) == ~ ((offsetT) 0x1ffffff)
8406 || (value & ~ ((offsetT) 0x1ffffff)) == 0)
8407 fixP->fx_done = 1;
8410 if (! fixP->fx_done)
8411 #endif
8412 as_bad_where (fixP->fx_file, fixP->fx_line,
8413 _("gas can't handle same-section branch dest >= 0x04000000"));
8416 value >>= 2;
8417 value += SEXT24 (newval);
8419 if ( (value & ~ ((offsetT) 0xffffff)) != 0
8420 && ((value & ~ ((offsetT) 0xffffff)) != ~ ((offsetT) 0xffffff)))
8421 as_bad_where (fixP->fx_file, fixP->fx_line,
8422 _("out of range branch"));
8424 newval = (value & 0x00ffffff) | (newval & 0xff000000);
8425 md_number_to_chars (buf, newval, INSN_SIZE);
8426 break;
8428 case BFD_RELOC_ARM_PCREL_BLX:
8430 offsetT hbit;
8431 newval = md_chars_to_number (buf, INSN_SIZE);
8433 #ifdef OBJ_ELF
8434 if (! target_oabi)
8435 value = fixP->fx_offset;
8436 #endif
8437 hbit = (value >> 1) & 1;
8438 value = (value >> 2) & 0x00ffffff;
8439 value = (value + (newval & 0x00ffffff)) & 0x00ffffff;
8440 newval = value | (newval & 0xfe000000) | (hbit << 24);
8441 md_number_to_chars (buf, newval, INSN_SIZE);
8443 break;
8445 case BFD_RELOC_THUMB_PCREL_BRANCH9: /* Conditional branch. */
8446 newval = md_chars_to_number (buf, THUMB_SIZE);
8448 addressT diff = (newval & 0xff) << 1;
8449 if (diff & 0x100)
8450 diff |= ~0xff;
8452 value += diff;
8453 if ((value & ~0xff) && ((value & ~0xff) != ~0xff))
8454 as_bad_where (fixP->fx_file, fixP->fx_line,
8455 _("Branch out of range"));
8456 newval = (newval & 0xff00) | ((value & 0x1ff) >> 1);
8458 md_number_to_chars (buf, newval, THUMB_SIZE);
8459 break;
8461 case BFD_RELOC_THUMB_PCREL_BRANCH12: /* Unconditional branch. */
8462 newval = md_chars_to_number (buf, THUMB_SIZE);
8464 addressT diff = (newval & 0x7ff) << 1;
8465 if (diff & 0x800)
8466 diff |= ~0x7ff;
8468 value += diff;
8469 if ((value & ~0x7ff) && ((value & ~0x7ff) != ~0x7ff))
8470 as_bad_where (fixP->fx_file, fixP->fx_line,
8471 _("Branch out of range"));
8472 newval = (newval & 0xf800) | ((value & 0xfff) >> 1);
8474 md_number_to_chars (buf, newval, THUMB_SIZE);
8475 break;
8477 case BFD_RELOC_THUMB_PCREL_BLX:
8478 case BFD_RELOC_THUMB_PCREL_BRANCH23:
8480 offsetT newval2;
8481 addressT diff;
8483 newval = md_chars_to_number (buf, THUMB_SIZE);
8484 newval2 = md_chars_to_number (buf + THUMB_SIZE, THUMB_SIZE);
8485 diff = ((newval & 0x7ff) << 12) | ((newval2 & 0x7ff) << 1);
8486 if (diff & 0x400000)
8487 diff |= ~0x3fffff;
8488 #ifdef OBJ_ELF
8489 value = fixP->fx_offset;
8490 #endif
8491 value += diff;
8492 if ((value & ~0x3fffff) && ((value & ~0x3fffff) != ~0x3fffff))
8493 as_bad_where (fixP->fx_file, fixP->fx_line,
8494 _("Branch with link out of range"));
8496 newval = (newval & 0xf800) | ((value & 0x7fffff) >> 12);
8497 newval2 = (newval2 & 0xf800) | ((value & 0xfff) >> 1);
8498 if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX)
8499 /* Remove bit zero of the adjusted offset. Bit zero can only be
8500 set if the upper insn is at a half-word boundary, since the
8501 destination address, an ARM instruction, must always be on a
8502 word boundary. The semantics of the BLX (1) instruction, however,
8503 are that bit zero in the offset must always be zero, and the
8504 corresponding bit one in the target address will be set from bit
8505 one of the source address. */
8506 newval2 &= ~1;
8507 md_number_to_chars (buf, newval, THUMB_SIZE);
8508 md_number_to_chars (buf + THUMB_SIZE, newval2, THUMB_SIZE);
8510 break;
8512 case BFD_RELOC_8:
8513 if (fixP->fx_done || fixP->fx_pcrel)
8514 md_number_to_chars (buf, value, 1);
8515 #ifdef OBJ_ELF
8516 else if (!target_oabi)
8518 value = fixP->fx_offset;
8519 md_number_to_chars (buf, value, 1);
8521 #endif
8522 break;
8524 case BFD_RELOC_16:
8525 if (fixP->fx_done || fixP->fx_pcrel)
8526 md_number_to_chars (buf, value, 2);
8527 #ifdef OBJ_ELF
8528 else if (!target_oabi)
8530 value = fixP->fx_offset;
8531 md_number_to_chars (buf, value, 2);
8533 #endif
8534 break;
8536 #ifdef OBJ_ELF
8537 case BFD_RELOC_ARM_GOT32:
8538 case BFD_RELOC_ARM_GOTOFF:
8539 md_number_to_chars (buf, 0, 4);
8540 break;
8541 #endif
8543 case BFD_RELOC_RVA:
8544 case BFD_RELOC_32:
8545 if (fixP->fx_done || fixP->fx_pcrel)
8546 md_number_to_chars (buf, value, 4);
8547 #ifdef OBJ_ELF
8548 else if (!target_oabi)
8550 value = fixP->fx_offset;
8551 md_number_to_chars (buf, value, 4);
8553 #endif
8554 break;
8556 #ifdef OBJ_ELF
8557 case BFD_RELOC_ARM_PLT32:
8558 /* It appears the instruction is fully prepared at this point. */
8559 break;
8560 #endif
8562 case BFD_RELOC_ARM_GOTPC:
8563 md_number_to_chars (buf, value, 4);
8564 break;
8566 case BFD_RELOC_ARM_CP_OFF_IMM:
8567 sign = value >= 0;
8568 if (value < -1023 || value > 1023 || (value & 3))
8569 as_bad_where (fixP->fx_file, fixP->fx_line,
8570 _("Illegal value for co-processor offset"));
8571 if (value < 0)
8572 value = -value;
8573 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
8574 newval |= (value >> 2) | (sign ? INDEX_UP : 0);
8575 md_number_to_chars (buf, newval, INSN_SIZE);
8576 break;
8578 case BFD_RELOC_ARM_THUMB_OFFSET:
8579 newval = md_chars_to_number (buf, THUMB_SIZE);
8580 /* Exactly what ranges, and where the offset is inserted depends
8581 on the type of instruction, we can establish this from the
8582 top 4 bits. */
8583 switch (newval >> 12)
8585 case 4: /* PC load. */
8586 /* Thumb PC loads are somewhat odd, bit 1 of the PC is
8587 forced to zero for these loads, so we will need to round
8588 up the offset if the instruction address is not word
8589 aligned (since the final address produced must be, and
8590 we can only describe word-aligned immediate offsets). */
8592 if ((fixP->fx_frag->fr_address + fixP->fx_where + value) & 3)
8593 as_bad_where (fixP->fx_file, fixP->fx_line,
8594 _("Invalid offset, target not word aligned (0x%08X)"),
8595 (unsigned int) (fixP->fx_frag->fr_address
8596 + fixP->fx_where + value));
8598 if ((value + 2) & ~0x3fe)
8599 as_bad_where (fixP->fx_file, fixP->fx_line,
8600 _("Invalid offset, value too big (0x%08lX)"), value);
8602 /* Round up, since pc will be rounded down. */
8603 newval |= (value + 2) >> 2;
8604 break;
8606 case 9: /* SP load/store. */
8607 if (value & ~0x3fc)
8608 as_bad_where (fixP->fx_file, fixP->fx_line,
8609 _("Invalid offset, value too big (0x%08lX)"), value);
8610 newval |= value >> 2;
8611 break;
8613 case 6: /* Word load/store. */
8614 if (value & ~0x7c)
8615 as_bad_where (fixP->fx_file, fixP->fx_line,
8616 _("Invalid offset, value too big (0x%08lX)"), value);
8617 newval |= value << 4; /* 6 - 2. */
8618 break;
8620 case 7: /* Byte load/store. */
8621 if (value & ~0x1f)
8622 as_bad_where (fixP->fx_file, fixP->fx_line,
8623 _("Invalid offset, value too big (0x%08lX)"), value);
8624 newval |= value << 6;
8625 break;
8627 case 8: /* Halfword load/store. */
8628 if (value & ~0x3e)
8629 as_bad_where (fixP->fx_file, fixP->fx_line,
8630 _("Invalid offset, value too big (0x%08lX)"), value);
8631 newval |= value << 5; /* 6 - 1. */
8632 break;
8634 default:
8635 as_bad_where (fixP->fx_file, fixP->fx_line,
8636 "Unable to process relocation for thumb opcode: %lx",
8637 (unsigned long) newval);
8638 break;
8640 md_number_to_chars (buf, newval, THUMB_SIZE);
8641 break;
8643 case BFD_RELOC_ARM_THUMB_ADD:
8644 /* This is a complicated relocation, since we use it for all of
8645 the following immediate relocations:
8647 3bit ADD/SUB
8648 8bit ADD/SUB
8649 9bit ADD/SUB SP word-aligned
8650 10bit ADD PC/SP word-aligned
8652 The type of instruction being processed is encoded in the
8653 instruction field:
8655 0x8000 SUB
8656 0x00F0 Rd
8657 0x000F Rs
8659 newval = md_chars_to_number (buf, THUMB_SIZE);
8661 int rd = (newval >> 4) & 0xf;
8662 int rs = newval & 0xf;
8663 int subtract = newval & 0x8000;
8665 if (rd == REG_SP)
8667 if (value & ~0x1fc)
8668 as_bad_where (fixP->fx_file, fixP->fx_line,
8669 _("Invalid immediate for stack address calculation"));
8670 newval = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
8671 newval |= value >> 2;
8673 else if (rs == REG_PC || rs == REG_SP)
8675 if (subtract ||
8676 value & ~0x3fc)
8677 as_bad_where (fixP->fx_file, fixP->fx_line,
8678 _("Invalid immediate for address calculation (value = 0x%08lX)"),
8679 (unsigned long) value);
8680 newval = (rs == REG_PC ? T_OPCODE_ADD_PC : T_OPCODE_ADD_SP);
8681 newval |= rd << 8;
8682 newval |= value >> 2;
8684 else if (rs == rd)
8686 if (value & ~0xff)
8687 as_bad_where (fixP->fx_file, fixP->fx_line,
8688 _("Invalid 8bit immediate"));
8689 newval = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
8690 newval |= (rd << 8) | value;
8692 else
8694 if (value & ~0x7)
8695 as_bad_where (fixP->fx_file, fixP->fx_line,
8696 _("Invalid 3bit immediate"));
8697 newval = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
8698 newval |= rd | (rs << 3) | (value << 6);
8701 md_number_to_chars (buf, newval, THUMB_SIZE);
8702 break;
8704 case BFD_RELOC_ARM_THUMB_IMM:
8705 newval = md_chars_to_number (buf, THUMB_SIZE);
8706 switch (newval >> 11)
8708 case 0x04: /* 8bit immediate MOV. */
8709 case 0x05: /* 8bit immediate CMP. */
8710 if (value < 0 || value > 255)
8711 as_bad_where (fixP->fx_file, fixP->fx_line,
8712 _("Invalid immediate: %ld is too large"),
8713 (long) value);
8714 newval |= value;
8715 break;
8717 default:
8718 abort ();
8720 md_number_to_chars (buf, newval, THUMB_SIZE);
8721 break;
8723 case BFD_RELOC_ARM_THUMB_SHIFT:
8724 /* 5bit shift value (0..31). */
8725 if (value < 0 || value > 31)
8726 as_bad_where (fixP->fx_file, fixP->fx_line,
8727 _("Illegal Thumb shift value: %ld"), (long) value);
8728 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xf03f;
8729 newval |= value << 6;
8730 md_number_to_chars (buf, newval, THUMB_SIZE);
8731 break;
8733 case BFD_RELOC_VTABLE_INHERIT:
8734 case BFD_RELOC_VTABLE_ENTRY:
8735 fixP->fx_done = 0;
8736 return;
8738 case BFD_RELOC_NONE:
8739 default:
8740 as_bad_where (fixP->fx_file, fixP->fx_line,
8741 _("Bad relocation fixup type (%d)"), fixP->fx_r_type);
8745 /* Translate internal representation of relocation info to BFD target
8746 format. */
8748 arelent *
8749 tc_gen_reloc (section, fixp)
8750 asection * section ATTRIBUTE_UNUSED;
8751 fixS * fixp;
8753 arelent * reloc;
8754 bfd_reloc_code_real_type code;
8756 reloc = (arelent *) xmalloc (sizeof (arelent));
8758 reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
8759 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
8760 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
8762 /* @@ Why fx_addnumber sometimes and fx_offset other times? */
8763 #ifndef OBJ_ELF
8764 if (fixp->fx_pcrel == 0)
8765 reloc->addend = fixp->fx_offset;
8766 else
8767 reloc->addend = fixp->fx_offset = reloc->address;
8768 #else /* OBJ_ELF */
8769 reloc->addend = fixp->fx_offset;
8770 #endif
8772 switch (fixp->fx_r_type)
8774 case BFD_RELOC_8:
8775 if (fixp->fx_pcrel)
8777 code = BFD_RELOC_8_PCREL;
8778 break;
8781 case BFD_RELOC_16:
8782 if (fixp->fx_pcrel)
8784 code = BFD_RELOC_16_PCREL;
8785 break;
8788 case BFD_RELOC_32:
8789 if (fixp->fx_pcrel)
8791 code = BFD_RELOC_32_PCREL;
8792 break;
8795 case BFD_RELOC_ARM_PCREL_BRANCH:
8796 case BFD_RELOC_ARM_PCREL_BLX:
8797 case BFD_RELOC_RVA:
8798 case BFD_RELOC_THUMB_PCREL_BRANCH9:
8799 case BFD_RELOC_THUMB_PCREL_BRANCH12:
8800 case BFD_RELOC_THUMB_PCREL_BRANCH23:
8801 case BFD_RELOC_THUMB_PCREL_BLX:
8802 case BFD_RELOC_VTABLE_ENTRY:
8803 case BFD_RELOC_VTABLE_INHERIT:
8804 code = fixp->fx_r_type;
8805 break;
8807 case BFD_RELOC_ARM_LITERAL:
8808 case BFD_RELOC_ARM_HWLITERAL:
8809 /* If this is called then the a literal has been referenced across
8810 a section boundary - possibly due to an implicit dump. */
8811 as_bad_where (fixp->fx_file, fixp->fx_line,
8812 _("Literal referenced across section boundary (Implicit dump?)"));
8813 return NULL;
8815 #ifdef OBJ_ELF
8816 case BFD_RELOC_ARM_GOT32:
8817 case BFD_RELOC_ARM_GOTOFF:
8818 case BFD_RELOC_ARM_PLT32:
8819 code = fixp->fx_r_type;
8820 break;
8821 #endif
8823 case BFD_RELOC_ARM_IMMEDIATE:
8824 as_bad_where (fixp->fx_file, fixp->fx_line,
8825 _("Internal_relocation (type %d) not fixed up (IMMEDIATE)"),
8826 fixp->fx_r_type);
8827 return NULL;
8829 case BFD_RELOC_ARM_ADRL_IMMEDIATE:
8830 as_bad_where (fixp->fx_file, fixp->fx_line,
8831 _("ADRL used for a symbol not defined in the same file"));
8832 return NULL;
8834 case BFD_RELOC_ARM_OFFSET_IMM:
8835 as_bad_where (fixp->fx_file, fixp->fx_line,
8836 _("Internal_relocation (type %d) not fixed up (OFFSET_IMM)"),
8837 fixp->fx_r_type);
8838 return NULL;
8840 default:
8842 char * type;
8844 switch (fixp->fx_r_type)
8846 case BFD_RELOC_ARM_IMMEDIATE: type = "IMMEDIATE"; break;
8847 case BFD_RELOC_ARM_OFFSET_IMM: type = "OFFSET_IMM"; break;
8848 case BFD_RELOC_ARM_OFFSET_IMM8: type = "OFFSET_IMM8"; break;
8849 case BFD_RELOC_ARM_SHIFT_IMM: type = "SHIFT_IMM"; break;
8850 case BFD_RELOC_ARM_SWI: type = "SWI"; break;
8851 case BFD_RELOC_ARM_MULTI: type = "MULTI"; break;
8852 case BFD_RELOC_ARM_CP_OFF_IMM: type = "CP_OFF_IMM"; break;
8853 case BFD_RELOC_ARM_THUMB_ADD: type = "THUMB_ADD"; break;
8854 case BFD_RELOC_ARM_THUMB_SHIFT: type = "THUMB_SHIFT"; break;
8855 case BFD_RELOC_ARM_THUMB_IMM: type = "THUMB_IMM"; break;
8856 case BFD_RELOC_ARM_THUMB_OFFSET: type = "THUMB_OFFSET"; break;
8857 default: type = _("<unknown>"); break;
8859 as_bad_where (fixp->fx_file, fixp->fx_line,
8860 _("Cannot represent %s relocation in this object file format"),
8861 type);
8862 return NULL;
8866 #ifdef OBJ_ELF
8867 if (code == BFD_RELOC_32_PCREL
8868 && GOT_symbol
8869 && fixp->fx_addsy == GOT_symbol)
8871 code = BFD_RELOC_ARM_GOTPC;
8872 reloc->addend = fixp->fx_offset = reloc->address;
8874 #endif
8876 reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
8878 if (reloc->howto == NULL)
8880 as_bad_where (fixp->fx_file, fixp->fx_line,
8881 _("Can not represent %s relocation in this object file format"),
8882 bfd_get_reloc_code_name (code));
8883 return NULL;
8886 /* HACK: Since arm ELF uses Rel instead of Rela, encode the
8887 vtable entry to be used in the relocation's section offset. */
8888 if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
8889 reloc->address = fixp->fx_offset;
8891 return reloc;
8895 md_estimate_size_before_relax (fragP, segtype)
8896 fragS * fragP ATTRIBUTE_UNUSED;
8897 segT segtype ATTRIBUTE_UNUSED;
8899 as_fatal (_("md_estimate_size_before_relax\n"));
8900 return 1;
8903 static void
8904 output_inst PARAMS ((void))
8906 char * to = NULL;
8908 if (inst.error)
8910 as_bad (inst.error);
8911 return;
8914 to = frag_more (inst.size);
8916 if (thumb_mode && (inst.size > THUMB_SIZE))
8918 assert (inst.size == (2 * THUMB_SIZE));
8919 md_number_to_chars (to, inst.instruction >> 16, THUMB_SIZE);
8920 md_number_to_chars (to + THUMB_SIZE, inst.instruction, THUMB_SIZE);
8922 else if (inst.size > INSN_SIZE)
8924 assert (inst.size == (2 * INSN_SIZE));
8925 md_number_to_chars (to, inst.instruction, INSN_SIZE);
8926 md_number_to_chars (to + INSN_SIZE, inst.instruction, INSN_SIZE);
8928 else
8929 md_number_to_chars (to, inst.instruction, inst.size);
8931 if (inst.reloc.type != BFD_RELOC_NONE)
8932 fix_new_arm (frag_now, to - frag_now->fr_literal,
8933 inst.size, & inst.reloc.exp, inst.reloc.pc_rel,
8934 inst.reloc.type);
8936 #ifdef OBJ_ELF
8937 dwarf2_emit_insn (inst.size);
8938 #endif
8941 void
8942 md_assemble (str)
8943 char * str;
8945 char c;
8946 char * p;
8947 char * q;
8948 char * start;
8950 /* Align the instruction.
8951 This may not be the right thing to do but ... */
8952 #if 0
8953 arm_align (2, 0);
8954 #endif
8955 listing_prev_line (); /* Defined in listing.h. */
8957 /* Align the previous label if needed. */
8958 if (last_label_seen != NULL)
8960 symbol_set_frag (last_label_seen, frag_now);
8961 S_SET_VALUE (last_label_seen, (valueT) frag_now_fix ());
8962 S_SET_SEGMENT (last_label_seen, now_seg);
8965 memset (&inst, '\0', sizeof (inst));
8966 inst.reloc.type = BFD_RELOC_NONE;
8968 skip_whitespace (str);
8970 /* Scan up to the end of the op-code, which must end in white space or
8971 end of string. */
8972 for (start = p = str; *p != '\0'; p++)
8973 if (*p == ' ')
8974 break;
8976 if (p == str)
8978 as_bad (_("No operator -- statement `%s'\n"), str);
8979 return;
8982 if (thumb_mode)
8984 const struct thumb_opcode * opcode;
8986 c = *p;
8987 *p = '\0';
8988 opcode = (const struct thumb_opcode *) hash_find (arm_tops_hsh, str);
8989 *p = c;
8991 if (opcode)
8993 /* Check that this instruction is supported for this CPU. */
8994 if (thumb_mode == 1 && (opcode->variant & cpu_variant) == 0)
8996 as_bad (_("selected processor does not support this opcode"));
8997 return;
9000 inst.instruction = opcode->value;
9001 inst.size = opcode->size;
9002 (*opcode->parms) (p);
9003 output_inst ();
9004 return;
9007 else
9009 const struct asm_opcode * opcode;
9011 c = *p;
9012 *p = '\0';
9013 opcode = (CONST struct asm_opcode *) hash_find (arm_ops_hsh, str);
9014 *p = c;
9016 if (opcode)
9018 /* Check that this instruction is supported for this CPU. */
9019 if ((opcode->variant & cpu_variant) == 0)
9021 as_bad (_("selected processor does not support this opcode"));
9022 return;
9025 inst.instruction = opcode->value;
9026 inst.size = INSN_SIZE;
9027 (*opcode->parms) (p, 0);
9028 output_inst ();
9029 return;
9033 /* It wasn't an instruction, but it might be a register alias of the form
9034 alias .req reg. */
9035 q = p;
9036 skip_whitespace (q);
9038 c = *p;
9039 *p = '\0';
9041 if (*q && !strncmp (q, ".req ", 4))
9043 int reg;
9044 char * copy_of_str;
9045 char * r;
9047 #ifdef IGNORE_OPCODE_CASE
9048 str = original_case_string;
9049 #endif
9050 copy_of_str = str;
9052 q += 4;
9053 skip_whitespace (q);
9055 for (r = q; *r != '\0'; r++)
9056 if (*r == ' ')
9057 break;
9059 if (r != q)
9061 int regnum;
9062 char d = *r;
9064 *r = '\0';
9065 regnum = arm_reg_parse (& q);
9066 *r = d;
9068 reg = arm_reg_parse (& str);
9070 if (reg == FAIL)
9072 if (regnum != FAIL)
9073 insert_reg_alias (str, regnum);
9074 else
9075 as_warn (_("register '%s' does not exist\n"), q);
9077 else if (regnum != FAIL)
9079 if (reg != regnum)
9080 as_warn (_("ignoring redefinition of register alias '%s'"),
9081 copy_of_str);
9083 /* Do not warn about redefinitions to the same alias. */
9085 else
9086 as_warn (_("ignoring redefinition of register alias '%s' to non-existant register '%s'"),
9087 copy_of_str, q);
9089 else
9090 as_warn (_("ignoring incomplete .req pseuso op"));
9092 *p = c;
9093 return;
9096 *p = c;
9097 as_bad (_("bad instruction `%s'"), start);
9100 /* md_parse_option
9101 Invocation line includes a switch not recognized by the base assembler.
9102 See if it's a processor-specific option. These are:
9103 Cpu variants, the arm part is optional:
9104 -m[arm]1 Currently not supported.
9105 -m[arm]2, -m[arm]250 Arm 2 and Arm 250 processor
9106 -m[arm]3 Arm 3 processor
9107 -m[arm]6[xx], Arm 6 processors
9108 -m[arm]7[xx][t][[d]m] Arm 7 processors
9109 -m[arm]8[10] Arm 8 processors
9110 -m[arm]9[20][tdmi] Arm 9 processors
9111 -marm9e Allow Cirrus/DSP instructions
9112 -mstrongarm[110[0]] StrongARM processors
9113 -mxscale XScale processors
9114 -m[arm]v[2345[t[e]]] Arm architectures
9115 -mall All (except the ARM1)
9116 FP variants:
9117 -mfpa10, -mfpa11 FPA10 and 11 co-processor instructions
9118 -mfpe-old (No float load/store multiples)
9119 -mno-fpu Disable all floating point instructions
9120 Run-time endian selection:
9121 -EB big endian cpu
9122 -EL little endian cpu
9123 ARM Procedure Calling Standard:
9124 -mapcs-32 32 bit APCS
9125 -mapcs-26 26 bit APCS
9126 -mapcs-float Pass floats in float regs
9127 -mapcs-reentrant Position independent code
9128 -mthumb-interwork Code supports Arm/Thumb interworking
9129 -matpcs ARM/Thumb Procedure Call Standard
9130 -moabi Old ELF ABI */
9132 const char * md_shortopts = "m:k";
9134 struct option md_longopts[] =
9136 #ifdef ARM_BI_ENDIAN
9137 #define OPTION_EB (OPTION_MD_BASE + 0)
9138 {"EB", no_argument, NULL, OPTION_EB},
9139 #define OPTION_EL (OPTION_MD_BASE + 1)
9140 {"EL", no_argument, NULL, OPTION_EL},
9141 #ifdef OBJ_ELF
9142 #define OPTION_OABI (OPTION_MD_BASE +2)
9143 {"oabi", no_argument, NULL, OPTION_OABI},
9144 #endif
9145 #endif
9146 {NULL, no_argument, NULL, 0}
9149 size_t md_longopts_size = sizeof (md_longopts);
9152 md_parse_option (c, arg)
9153 int c;
9154 char * arg;
9156 char * str = arg;
9158 switch (c)
9160 #ifdef ARM_BI_ENDIAN
9161 case OPTION_EB:
9162 target_big_endian = 1;
9163 break;
9164 case OPTION_EL:
9165 target_big_endian = 0;
9166 break;
9167 #endif
9169 case 'm':
9170 switch (*str)
9172 case 'f':
9173 if (streq (str, "fpa10") || streq (str, "fpa11"))
9174 cpu_variant = (cpu_variant & ~FPU_ANY) | FPU_ARCH_FPA;
9175 else if (streq (str, "fpe-old"))
9176 cpu_variant = (cpu_variant & ~FPU_ANY) | FPU_ARCH_FPE;
9177 else
9178 goto bad;
9179 break;
9181 case 'n':
9182 if (streq (str, "no-fpu"))
9183 cpu_variant &= ~FPU_ANY;
9184 break;
9186 #ifdef OBJ_ELF
9187 case 'o':
9188 if (streq (str, "oabi"))
9189 target_oabi = true;
9190 break;
9191 #endif
9193 case 't':
9194 /* Limit assembler to generating only Thumb instructions: */
9195 if (streq (str, "thumb"))
9197 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_EXT_V4T;
9198 cpu_variant = (cpu_variant & ~FPU_ANY) | FPU_NONE;
9199 thumb_mode = 1;
9201 else if (streq (str, "thumb-interwork"))
9203 if ((cpu_variant & ARM_EXT_V4T) == 0)
9204 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_ARCH_V4T;
9205 #if defined OBJ_COFF || defined OBJ_ELF
9206 support_interwork = true;
9207 #endif
9209 else
9210 goto bad;
9211 break;
9213 default:
9214 if (streq (str, "all"))
9216 cpu_variant = ARM_ALL | FPU_DEFAULT;
9217 return 1;
9219 #if defined OBJ_COFF || defined OBJ_ELF
9220 if (! strncmp (str, "apcs-", 5))
9222 /* GCC passes on all command line options starting "-mapcs-..."
9223 to us, so we must parse them here. */
9225 str += 5;
9227 if (streq (str, "32"))
9229 uses_apcs_26 = false;
9230 return 1;
9232 else if (streq (str, "26"))
9234 uses_apcs_26 = true;
9235 return 1;
9237 else if (streq (str, "frame"))
9239 /* Stack frames are being generated - does not affect
9240 linkage of code. */
9241 return 1;
9243 else if (streq (str, "stack-check"))
9245 /* Stack checking is being performed - does not affect
9246 linkage, but does require that the functions
9247 __rt_stkovf_split_small and __rt_stkovf_split_big be
9248 present in the final link. */
9250 return 1;
9252 else if (streq (str, "float"))
9254 /* Floating point arguments are being passed in the floating
9255 point registers. This does affect linking, since this
9256 version of the APCS is incompatible with the version that
9257 passes floating points in the integer registers. */
9259 uses_apcs_float = true;
9260 return 1;
9262 else if (streq (str, "reentrant"))
9264 /* Reentrant code has been generated. This does affect
9265 linking, since there is no point in linking reentrant/
9266 position independent code with absolute position code. */
9267 pic_code = true;
9268 return 1;
9271 as_bad (_("Unrecognised APCS switch -m%s"), arg);
9272 return 0;
9275 if (! strcmp (str, "atpcs"))
9277 atpcs = true;
9278 return 1;
9280 #endif
9281 /* Strip off optional "arm". */
9282 if (! strncmp (str, "arm", 3))
9283 str += 3;
9285 switch (*str)
9287 case '1':
9288 if (streq (str, "1"))
9289 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_1;
9290 else
9291 goto bad;
9292 break;
9294 case '2':
9295 if (streq (str, "2"))
9296 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_2;
9297 else if (streq (str, "250"))
9298 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_250;
9299 else
9300 goto bad;
9301 break;
9303 case '3':
9304 if (streq (str, "3"))
9305 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_3;
9306 else
9307 goto bad;
9308 break;
9310 case '6':
9311 switch (strtol (str, NULL, 10))
9313 case 6:
9314 case 60:
9315 case 600:
9316 case 610:
9317 case 620:
9318 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_6;
9319 break;
9320 default:
9321 goto bad;
9323 break;
9325 case '7':
9326 /* Eat the processor name. */
9327 switch (strtol (str, & str, 10))
9329 case 7:
9330 case 70:
9331 case 700:
9332 case 710:
9333 case 720:
9334 case 7100:
9335 case 7500:
9336 break;
9337 default:
9338 goto bad;
9340 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_7;
9341 for (; *str; str++)
9343 switch (*str)
9345 case 't':
9346 cpu_variant |= ARM_ARCH_V4T;
9347 break;
9349 case 'm':
9350 cpu_variant |= ARM_EXT_V3M;
9351 break;
9353 case 'f': /* fe => fp enabled cpu. */
9354 if (str[1] == 'e')
9355 ++ str;
9356 else
9357 goto bad;
9359 case 'c': /* Left over from 710c processor name. */
9360 case 'd': /* Debug. */
9361 case 'i': /* Embedded ICE. */
9362 /* Included for completeness in ARM processor naming. */
9363 break;
9365 default:
9366 goto bad;
9369 break;
9371 case '8':
9372 if (streq (str, "8") || streq (str, "810"))
9373 cpu_variant = (cpu_variant & ~ARM_ANY)
9374 | ARM_8 | ARM_ARCH_V4;
9375 else
9376 goto bad;
9377 break;
9379 case '9':
9380 if (streq (str, "9"))
9381 cpu_variant = (cpu_variant & ~ARM_ANY)
9382 | ARM_9 | ARM_ARCH_V4T;
9383 else if (streq (str, "920"))
9384 cpu_variant = (cpu_variant & ~ARM_ANY)
9385 | ARM_9 | ARM_ARCH_V4;
9386 else if (streq (str, "920t"))
9387 cpu_variant = (cpu_variant & ~ARM_ANY)
9388 | ARM_9 | ARM_ARCH_V4T;
9389 else if (streq (str, "9tdmi"))
9390 cpu_variant = (cpu_variant & ~ARM_ANY)
9391 | ARM_9 | ARM_ARCH_V4T;
9392 else if (streq (str, "9e"))
9393 cpu_variant = (cpu_variant & ~ARM_ANY)
9394 | ARM_9 | ARM_ARCH_V4T | ARM_EXT_MAVERICK;
9395 else
9396 goto bad;
9397 break;
9399 case 's':
9400 if (streq (str, "strongarm")
9401 || streq (str, "strongarm110")
9402 || streq (str, "strongarm1100"))
9403 cpu_variant = (cpu_variant & ~ARM_ANY)
9404 | ARM_8 | ARM_ARCH_V4;
9405 else
9406 goto bad;
9407 break;
9409 case 'x':
9410 if (streq (str, "xscale"))
9411 cpu_variant = (cpu_variant & ~ARM_ANY)
9412 | ARM_9 | ARM_ARCH_XSCALE;
9413 else
9414 goto bad;
9415 break;
9417 case 'v':
9418 /* Select variant based on architecture rather than
9419 processor. */
9420 switch (*++str)
9422 case '2':
9423 switch (*++str)
9425 case 'a':
9426 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_3;
9427 break;
9428 case 0:
9429 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_2;
9430 break;
9431 default:
9432 as_bad (_("Invalid architecture variant -m%s"), arg);
9433 break;
9435 break;
9437 case '3':
9438 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_7;
9440 switch (*++str)
9442 case 'm': cpu_variant |= ARM_EXT_V3M; break;
9443 case 0: break;
9444 default:
9445 as_bad (_("Invalid architecture variant -m%s"), arg);
9446 break;
9448 break;
9450 case '4':
9451 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_7 | ARM_ARCH_V4;
9453 switch (*++str)
9455 case 't': cpu_variant |= ARM_EXT_V4T; break;
9456 case 0: break;
9457 default:
9458 as_bad (_("Invalid architecture variant -m%s"), arg);
9459 break;
9461 break;
9463 case '5':
9464 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_9 | ARM_ARCH_V5;
9465 switch (*++str)
9467 case 't': cpu_variant |= ARM_EXT_V4T; break;
9468 case 'e': cpu_variant |= ARM_EXT_V5E; break;
9469 case 0: break;
9470 default:
9471 as_bad (_("Invalid architecture variant -m%s"), arg);
9472 break;
9474 break;
9476 default:
9477 as_bad (_("Invalid architecture variant -m%s"), arg);
9478 break;
9480 break;
9482 default:
9483 bad:
9484 as_bad (_("Invalid processor variant -m%s"), arg);
9485 return 0;
9488 break;
9490 #if defined OBJ_ELF || defined OBJ_COFF
9491 case 'k':
9492 pic_code = 1;
9493 break;
9494 #endif
9496 default:
9497 return 0;
9500 return 1;
9503 void
9504 md_show_usage (fp)
9505 FILE * fp;
9507 fprintf (fp, _("\
9508 ARM Specific Assembler Options:\n\
9509 -m[arm][<processor name>] select processor variant\n\
9510 -m[arm]v[2|2a|3|3m|4|4t|5[t][e]] select architecture variant\n\
9511 -marm9e allow Cirrus/DSP instructions\n\
9512 -mthumb only allow Thumb instructions\n\
9513 -mthumb-interwork mark the assembled code as supporting interworking\n\
9514 -mall allow any instruction\n\
9515 -mfpa10, -mfpa11 select floating point architecture\n\
9516 -mfpe-old don't allow floating-point multiple instructions\n\
9517 -mno-fpu don't allow any floating-point instructions.\n\
9518 -k generate PIC code.\n"));
9519 #if defined OBJ_COFF || defined OBJ_ELF
9520 fprintf (fp, _("\
9521 -mapcs-32, -mapcs-26 specify which ARM Procedure Calling Standard to use\n\
9522 -matpcs use ARM/Thumb Procedure Calling Standard\n\
9523 -mapcs-float floating point args are passed in FP regs\n\
9524 -mapcs-reentrant the code is position independent/reentrant\n"));
9525 #endif
9526 #ifdef OBJ_ELF
9527 fprintf (fp, _("\
9528 -moabi support the old ELF ABI\n"));
9529 #endif
9530 #ifdef ARM_BI_ENDIAN
9531 fprintf (fp, _("\
9532 -EB assemble code for a big endian cpu\n\
9533 -EL assemble code for a little endian cpu\n"));
9534 #endif
9537 /* We need to be able to fix up arbitrary expressions in some statements.
9538 This is so that we can handle symbols that are an arbitrary distance from
9539 the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
9540 which returns part of an address in a form which will be valid for
9541 a data instruction. We do this by pushing the expression into a symbol
9542 in the expr_section, and creating a fix for that. */
9544 static void
9545 fix_new_arm (frag, where, size, exp, pc_rel, reloc)
9546 fragS * frag;
9547 int where;
9548 short int size;
9549 expressionS * exp;
9550 int pc_rel;
9551 int reloc;
9553 fixS * new_fix;
9554 arm_fix_data * arm_data;
9556 switch (exp->X_op)
9558 case O_constant:
9559 case O_symbol:
9560 case O_add:
9561 case O_subtract:
9562 new_fix = fix_new_exp (frag, where, size, exp, pc_rel, reloc);
9563 break;
9565 default:
9566 new_fix = fix_new (frag, where, size, make_expr_symbol (exp), 0,
9567 pc_rel, reloc);
9568 break;
9571 /* Mark whether the fix is to a THUMB instruction, or an ARM
9572 instruction. */
9573 arm_data = (arm_fix_data *) obstack_alloc (& notes, sizeof (arm_fix_data));
9574 new_fix->tc_fix_data = (PTR) arm_data;
9575 arm_data->thumb_mode = thumb_mode;
9577 return;
9580 /* This fix_new is called by cons via TC_CONS_FIX_NEW. */
9582 void
9583 cons_fix_new_arm (frag, where, size, exp)
9584 fragS * frag;
9585 int where;
9586 int size;
9587 expressionS * exp;
9589 bfd_reloc_code_real_type type;
9590 int pcrel = 0;
9592 /* Pick a reloc.
9593 FIXME: @@ Should look at CPU word size. */
9594 switch (size)
9596 case 1:
9597 type = BFD_RELOC_8;
9598 break;
9599 case 2:
9600 type = BFD_RELOC_16;
9601 break;
9602 case 4:
9603 default:
9604 type = BFD_RELOC_32;
9605 break;
9606 case 8:
9607 type = BFD_RELOC_64;
9608 break;
9611 fix_new_exp (frag, where, (int) size, exp, pcrel, type);
9614 /* A good place to do this, although this was probably not intended
9615 for this kind of use. We need to dump the literal pool before
9616 references are made to a null symbol pointer. */
9618 void
9619 arm_cleanup ()
9621 if (current_poolP == NULL)
9622 return;
9624 /* Put it at the end of text section. */
9625 subseg_set (text_section, 0);
9626 s_ltorg (0);
9627 listing_prev_line ();
9630 void
9631 arm_start_line_hook ()
9633 last_label_seen = NULL;
9636 void
9637 arm_frob_label (sym)
9638 symbolS * sym;
9640 last_label_seen = sym;
9642 ARM_SET_THUMB (sym, thumb_mode);
9644 #if defined OBJ_COFF || defined OBJ_ELF
9645 ARM_SET_INTERWORK (sym, support_interwork);
9646 #endif
9648 /* Note - do not allow local symbols (.Lxxx) to be labeled
9649 as Thumb functions. This is because these labels, whilst
9650 they exist inside Thumb code, are not the entry points for
9651 possible ARM->Thumb calls. Also, these labels can be used
9652 as part of a computed goto or switch statement. eg gcc
9653 can generate code that looks like this:
9655 ldr r2, [pc, .Laaa]
9656 lsl r3, r3, #2
9657 ldr r2, [r3, r2]
9658 mov pc, r2
9660 .Lbbb: .word .Lxxx
9661 .Lccc: .word .Lyyy
9662 ..etc...
9663 .Laaa: .word Lbbb
9665 The first instruction loads the address of the jump table.
9666 The second instruction converts a table index into a byte offset.
9667 The third instruction gets the jump address out of the table.
9668 The fourth instruction performs the jump.
9670 If the address stored at .Laaa is that of a symbol which has the
9671 Thumb_Func bit set, then the linker will arrange for this address
9672 to have the bottom bit set, which in turn would mean that the
9673 address computation performed by the third instruction would end
9674 up with the bottom bit set. Since the ARM is capable of unaligned
9675 word loads, the instruction would then load the incorrect address
9676 out of the jump table, and chaos would ensue. */
9677 if (label_is_thumb_function_name
9678 && (S_GET_NAME (sym)[0] != '.' || S_GET_NAME (sym)[1] != 'L')
9679 && (bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
9681 /* When the address of a Thumb function is taken the bottom
9682 bit of that address should be set. This will allow
9683 interworking between Arm and Thumb functions to work
9684 correctly. */
9686 THUMB_SET_FUNC (sym, 1);
9688 label_is_thumb_function_name = false;
9692 /* Adjust the symbol table. This marks Thumb symbols as distinct from
9693 ARM ones. */
9695 void
9696 arm_adjust_symtab ()
9698 #ifdef OBJ_COFF
9699 symbolS * sym;
9701 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
9703 if (ARM_IS_THUMB (sym))
9705 if (THUMB_IS_FUNC (sym))
9707 /* Mark the symbol as a Thumb function. */
9708 if ( S_GET_STORAGE_CLASS (sym) == C_STAT
9709 || S_GET_STORAGE_CLASS (sym) == C_LABEL) /* This can happen! */
9710 S_SET_STORAGE_CLASS (sym, C_THUMBSTATFUNC);
9712 else if (S_GET_STORAGE_CLASS (sym) == C_EXT)
9713 S_SET_STORAGE_CLASS (sym, C_THUMBEXTFUNC);
9714 else
9715 as_bad (_("%s: unexpected function type: %d"),
9716 S_GET_NAME (sym), S_GET_STORAGE_CLASS (sym));
9718 else switch (S_GET_STORAGE_CLASS (sym))
9720 case C_EXT:
9721 S_SET_STORAGE_CLASS (sym, C_THUMBEXT);
9722 break;
9723 case C_STAT:
9724 S_SET_STORAGE_CLASS (sym, C_THUMBSTAT);
9725 break;
9726 case C_LABEL:
9727 S_SET_STORAGE_CLASS (sym, C_THUMBLABEL);
9728 break;
9729 default:
9730 /* Do nothing. */
9731 break;
9735 if (ARM_IS_INTERWORK (sym))
9736 coffsymbol (symbol_get_bfdsym (sym))->native->u.syment.n_flags = 0xFF;
9738 #endif
9739 #ifdef OBJ_ELF
9740 symbolS * sym;
9741 char bind;
9743 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
9745 if (ARM_IS_THUMB (sym))
9747 elf_symbol_type * elf_sym;
9749 elf_sym = elf_symbol (symbol_get_bfdsym (sym));
9750 bind = ELF_ST_BIND (elf_sym);
9752 /* If it's a .thumb_func, declare it as so,
9753 otherwise tag label as .code 16. */
9754 if (THUMB_IS_FUNC (sym))
9755 elf_sym->internal_elf_sym.st_info =
9756 ELF_ST_INFO (bind, STT_ARM_TFUNC);
9757 else
9758 elf_sym->internal_elf_sym.st_info =
9759 ELF_ST_INFO (bind, STT_ARM_16BIT);
9762 #endif
9766 arm_data_in_code ()
9768 if (thumb_mode && ! strncmp (input_line_pointer + 1, "data:", 5))
9770 *input_line_pointer = '/';
9771 input_line_pointer += 5;
9772 *input_line_pointer = 0;
9773 return 1;
9776 return 0;
9779 char *
9780 arm_canonicalize_symbol_name (name)
9781 char * name;
9783 int len;
9785 if (thumb_mode && (len = strlen (name)) > 5
9786 && streq (name + len - 5, "/data"))
9787 *(name + len - 5) = 0;
9789 return name;
9792 boolean
9793 arm_validate_fix (fixP)
9794 fixS * fixP;
9796 /* If the destination of the branch is a defined symbol which does not have
9797 the THUMB_FUNC attribute, then we must be calling a function which has
9798 the (interfacearm) attribute. We look for the Thumb entry point to that
9799 function and change the branch to refer to that function instead. */
9800 if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23
9801 && fixP->fx_addsy != NULL
9802 && S_IS_DEFINED (fixP->fx_addsy)
9803 && ! THUMB_IS_FUNC (fixP->fx_addsy))
9805 fixP->fx_addsy = find_real_start (fixP->fx_addsy);
9806 return true;
9809 return false;
9812 #ifdef OBJ_COFF
9813 /* This is a little hack to help the gas/arm/adrl.s test. It prevents
9814 local labels from being added to the output symbol table when they
9815 are used with the ADRL pseudo op. The ADRL relocation should always
9816 be resolved before the binbary is emitted, so it is safe to say that
9817 it is adjustable. */
9819 boolean
9820 arm_fix_adjustable (fixP)
9821 fixS * fixP;
9823 if (fixP->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE)
9824 return 1;
9825 return 0;
9827 #endif
9828 #ifdef OBJ_ELF
9829 /* Relocations against Thumb function names must be left unadjusted,
9830 so that the linker can use this information to correctly set the
9831 bottom bit of their addresses. The MIPS version of this function
9832 also prevents relocations that are mips-16 specific, but I do not
9833 know why it does this.
9835 FIXME:
9836 There is one other problem that ought to be addressed here, but
9837 which currently is not: Taking the address of a label (rather
9838 than a function) and then later jumping to that address. Such
9839 addresses also ought to have their bottom bit set (assuming that
9840 they reside in Thumb code), but at the moment they will not. */
9842 boolean
9843 arm_fix_adjustable (fixP)
9844 fixS * fixP;
9846 if (fixP->fx_addsy == NULL)
9847 return 1;
9849 /* Prevent all adjustments to global symbols. */
9850 if (S_IS_EXTERN (fixP->fx_addsy))
9851 return 0;
9853 if (S_IS_WEAK (fixP->fx_addsy))
9854 return 0;
9856 if (THUMB_IS_FUNC (fixP->fx_addsy)
9857 && fixP->fx_subsy == NULL)
9858 return 0;
9860 /* We need the symbol name for the VTABLE entries. */
9861 if ( fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
9862 || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
9863 return 0;
9865 return 1;
9868 const char *
9869 elf32_arm_target_format ()
9871 if (target_big_endian)
9873 if (target_oabi)
9874 return "elf32-bigarm-oabi";
9875 else
9876 return "elf32-bigarm";
9878 else
9880 if (target_oabi)
9881 return "elf32-littlearm-oabi";
9882 else
9883 return "elf32-littlearm";
9887 void
9888 armelf_frob_symbol (symp, puntp)
9889 symbolS * symp;
9890 int * puntp;
9892 elf_frob_symbol (symp, puntp);
9896 arm_force_relocation (fixp)
9897 struct fix * fixp;
9899 if ( fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT
9900 || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY
9901 || fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH
9902 || fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BLX
9903 || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX
9904 || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23)
9905 return 1;
9907 return 0;
9910 static bfd_reloc_code_real_type
9911 arm_parse_reloc ()
9913 char id [16];
9914 char * ip;
9915 unsigned int i;
9916 static struct
9918 char * str;
9919 int len;
9920 bfd_reloc_code_real_type reloc;
9922 reloc_map[] =
9924 #define MAP(str,reloc) { str, sizeof (str) - 1, reloc }
9925 MAP ("(got)", BFD_RELOC_ARM_GOT32),
9926 MAP ("(gotoff)", BFD_RELOC_ARM_GOTOFF),
9927 /* ScottB: Jan 30, 1998 - Added support for parsing "var(PLT)"
9928 branch instructions generated by GCC for PLT relocs. */
9929 MAP ("(plt)", BFD_RELOC_ARM_PLT32),
9930 { NULL, 0, BFD_RELOC_UNUSED }
9931 #undef MAP
9934 for (i = 0, ip = input_line_pointer;
9935 i < sizeof (id) && (ISALNUM (*ip) || ISPUNCT (*ip));
9936 i++, ip++)
9937 id[i] = TOLOWER (*ip);
9939 for (i = 0; reloc_map[i].str; i++)
9940 if (strncmp (id, reloc_map[i].str, reloc_map[i].len) == 0)
9941 break;
9943 input_line_pointer += reloc_map[i].len;
9945 return reloc_map[i].reloc;
9948 static void
9949 s_arm_elf_cons (nbytes)
9950 int nbytes;
9952 expressionS exp;
9954 #ifdef md_flush_pending_output
9955 md_flush_pending_output ();
9956 #endif
9958 if (is_it_end_of_statement ())
9960 demand_empty_rest_of_line ();
9961 return;
9964 #ifdef md_cons_align
9965 md_cons_align (nbytes);
9966 #endif
9970 bfd_reloc_code_real_type reloc;
9972 expression (& exp);
9974 if (exp.X_op == O_symbol
9975 && * input_line_pointer == '('
9976 && (reloc = arm_parse_reloc ()) != BFD_RELOC_UNUSED)
9978 reloc_howto_type *howto = bfd_reloc_type_lookup (stdoutput, reloc);
9979 int size = bfd_get_reloc_size (howto);
9981 if (size > nbytes)
9982 as_bad ("%s relocations do not fit in %d bytes",
9983 howto->name, nbytes);
9984 else
9986 register char *p = frag_more ((int) nbytes);
9987 int offset = nbytes - size;
9989 fix_new_exp (frag_now, p - frag_now->fr_literal + offset, size,
9990 &exp, 0, reloc);
9993 else
9994 emit_expr (&exp, (unsigned int) nbytes);
9996 while (*input_line_pointer++ == ',');
9998 /* Put terminator back into stream. */
9999 input_line_pointer --;
10000 demand_empty_rest_of_line ();
10003 #endif /* OBJ_ELF */
10005 /* This is called from HANDLE_ALIGN in write.c. Fill in the contents
10006 of an rs_align_code fragment. */
10008 void
10009 arm_handle_align (fragP)
10010 fragS *fragP;
10012 static char const arm_noop[4] = { 0x00, 0x00, 0xa0, 0xe1 };
10013 static char const thumb_noop[2] = { 0xc0, 0x46 };
10014 static char const arm_bigend_noop[4] = { 0xe1, 0xa0, 0x00, 0x00 };
10015 static char const thumb_bigend_noop[2] = { 0x46, 0xc0 };
10017 int bytes, fix, noop_size;
10018 char * p;
10019 const char * noop;
10021 if (fragP->fr_type != rs_align_code)
10022 return;
10024 bytes = fragP->fr_next->fr_address - fragP->fr_address - fragP->fr_fix;
10025 p = fragP->fr_literal + fragP->fr_fix;
10026 fix = 0;
10028 if (bytes > MAX_MEM_FOR_RS_ALIGN_CODE)
10029 bytes &= MAX_MEM_FOR_RS_ALIGN_CODE;
10031 if (fragP->tc_frag_data)
10033 if (target_big_endian)
10034 noop = thumb_bigend_noop;
10035 else
10036 noop = thumb_noop;
10037 noop_size = sizeof (thumb_noop);
10039 else
10041 if (target_big_endian)
10042 noop = arm_bigend_noop;
10043 else
10044 noop = arm_noop;
10045 noop_size = sizeof (arm_noop);
10048 if (bytes & (noop_size - 1))
10050 fix = bytes & (noop_size - 1);
10051 memset (p, 0, fix);
10052 p += fix;
10053 bytes -= fix;
10056 while (bytes >= noop_size)
10058 memcpy (p, noop, noop_size);
10059 p += noop_size;
10060 bytes -= noop_size;
10061 fix += noop_size;
10064 fragP->fr_fix += fix;
10065 fragP->fr_var = noop_size;
10068 /* Called from md_do_align. Used to create an alignment
10069 frag in a code section. */
10071 void
10072 arm_frag_align_code (n, max)
10073 int n;
10074 int max;
10076 char * p;
10078 /* We assume that there will never be a requirment
10079 to support alignments greater than 32 bytes. */
10080 if (max > MAX_MEM_FOR_RS_ALIGN_CODE)
10081 as_fatal (_("alignments greater than 32 bytes not supported in .text sections."));
10083 p = frag_var (rs_align_code,
10084 MAX_MEM_FOR_RS_ALIGN_CODE,
10086 (relax_substateT) max,
10087 (symbolS *) NULL,
10088 (offsetT) n,
10089 (char *) NULL);
10090 *p = 0;
10094 /* Perform target specific initialisation of a frag. */
10096 void
10097 arm_init_frag (fragP)
10098 fragS *fragP;
10100 /* Record whether this frag is in an ARM or a THUMB area. */
10101 fragP->tc_frag_data = thumb_mode;